1
0
mirror of https://github.com/janet-lang/janet synced 2025-06-27 07:32:51 +00:00

Address #495 Add :read and :parser to run-context.

This commit is contained in:
Calvin Rose 2020-11-15 15:01:35 -06:00
parent 6e6900fa3a
commit 3ab2ae130b

View File

@ -2047,7 +2047,7 @@
"Default handler for a parse error." "Default handler for a parse error."
[p where] [p where]
(def ec (dyn :err-color)) (def ec (dyn :err-color))
(def [line col] (parser/where p)) (def [line col] (:where p))
(eprint (eprint
(if ec "\e[31m" "") (if ec "\e[31m" "")
"parse error in " "parse error in "
@ -2057,7 +2057,7 @@
", column " ", column "
(string col) (string col)
": " ": "
(parser/error p) (:error p)
(if ec "\e[0m" "")) (if ec "\e[0m" ""))
(eflush)) (eflush))
@ -2097,7 +2097,9 @@
:evaluator - callback that executes thunks. Signature is (evaluator thunk source env where)\n\t :evaluator - callback that executes thunks. Signature is (evaluator thunk source env where)\n\t
:on-status - callback when a value is evaluated - default is debug/stacktrace\n\t :on-status - callback when a value is evaluated - default is debug/stacktrace\n\t
:fiber-flags - what flags to wrap the compilation fiber with. Default is :ia.\n\t :fiber-flags - what flags to wrap the compilation fiber with. Default is :ia.\n\t
:expander - an optional function that is called on each top level form before being compiled." :expander - an optional function that is called on each top level form before being compiled.\n\t
:parser - provide a custom parser that implements the same interface as Janet's built in parser.\n\t
:read - optional function to get the next form, called like (read env source). Overrides all parsing."
[opts] [opts]
(def {:env env (def {:env env
@ -2108,6 +2110,8 @@
:fiber-flags guard :fiber-flags guard
:evaluator evaluator :evaluator evaluator
:source where :source where
:parser parser
:read read
:expander expand} opts) :expander expand} opts)
(default env (fiber/getenv (fiber/current))) (default env (fiber/getenv (fiber/current)))
(default chunks (fn [buf p] (getline "" buf env))) (default chunks (fn [buf p] (getline "" buf env)))
@ -2121,9 +2125,6 @@
# Are we done yet? # Are we done yet?
(var going true) (var going true)
# The parser object
(def p (parser/new))
# Evaluate 1 source form in a protected manner # Evaluate 1 source form in a protected manner
(defn eval1 [source] (defn eval1 [source]
(def source (if expand (expand source) source)) (def source (if expand (expand source) source))
@ -2149,6 +2150,20 @@
(def res (resume f resumeval)) (def res (resume f resumeval))
(when good (when going (set resumeval (onstatus f res)))))) (when good (when going (set resumeval (onstatus f res))))))
# Reader version
(when read
(forever
(if (in env :exit) (break))
(eval1 (read env where)))
(break (in env :exit-value env)))
# The parser object
(def p (or parser (parser/new)))
(def p-consume (p :consume))
(def p-produce (p :produce))
(def p-status (p :status))
(def p-has-more (p :has-more))
(defn parse-err (defn parse-err
"Handle parser error in the correct environment" "Handle parser error in the correct environment"
[p where] [p where]
@ -2165,26 +2180,26 @@
:cancel) :cancel)
(do (do
# A :cancel chunk represents a cancelled form in the REPL, so reset. # A :cancel chunk represents a cancelled form in the REPL, so reset.
(parser/flush p) (:flush p)
(buffer/clear buf)) (buffer/clear buf))
(do (do
(var pindex 0) (var pindex 0)
(var pstatus nil) (var pstatus nil)
(def len (length buf)) (def len (length buf))
(when (= len 0) (when (= len 0)
(parser/eof p) (:eof p)
(set going false)) (set going false))
(while (> len pindex) (while (> len pindex)
(+= pindex (parser/consume p buf pindex)) (+= pindex (p-consume p buf pindex))
(while (parser/has-more p) (while (p-has-more p)
(eval1 (parser/produce p))) (eval1 (p-produce p)))
(when (= (parser/status p) :error) (when (= (p-status p) :error)
(parse-err p where)))))) (parse-err p where))))))
# Check final parser state # Check final parser state
(while (parser/has-more p) (while (p-has-more p)
(eval1 (parser/produce p))) (eval1 (p-produce p)))
(when (= (parser/status p) :error) (when (= (p-status p) :error)
(parse-err p where)) (parse-err p where))
(in env :exit-value env)) (in env :exit-value env))
@ -2384,7 +2399,9 @@
:env env :env env
:source src :source src
:expander expander :expander expander
:evaluator evaluator}] :evaluator evaluator
:read read
:parser parser}]
(def f (if (= (type path) :core/file) (def f (if (= (type path) :core/file)
path path
(file/open path :rb))) (file/open path :rb)))
@ -2415,6 +2432,8 @@
(if exit (os/exit 1) (eflush)))) (if exit (os/exit 1) (eflush))))
:evaluator evaluator :evaluator evaluator
:expander expander :expander expander
:read read
:parser parser
:source (or src (if path-is-file "<anonymous>" spath))})) :source (or src (if path-is-file "<anonymous>" spath))}))
(if-not path-is-file (file/close f)) (if-not path-is-file (file/close f))
nenv) nenv)
@ -2671,8 +2690,9 @@
get a chunk of source code that should return nil for end of file. get a chunk of source code that should return nil for end of file.
The second parameter is a function that is called when a signal is The second parameter is a function that is called when a signal is
caught. One can provide an optional environment table to run caught. One can provide an optional environment table to run
the repl in." the repl in, as well as an optional parser or read function to pass
[&opt chunks onsignal env] to run-context."
[&opt chunks onsignal env parser read]
(default env (make-env)) (default env (make-env))
(default chunks (default chunks
(fn [buf p] (fn [buf p]
@ -2720,6 +2740,8 @@
(run-context {:env env (run-context {:env env
:chunks chunks :chunks chunks
:on-status (or onsignal (make-onsignal env 1)) :on-status (or onsignal (make-onsignal env 1))
:parser parser
:read read
:source "repl"})) :source "repl"}))
### ###