application/octet-stream
•
5.88 KB
•
145 lines
[do [def help [λ* help
[i]
"Describe 10 functions at offset 1"
[do [def off [* [int i] 10]]
[for-each [λ* #nil
[l]
""
[println [cat l " " [describe l]]]] [map cat [symbol-table off 10]]]
[println [cat "Help page " [int i] " of " [/ [symbol-count] 10]]]
#t]]]
[def file/compile [λ* file/compile
[path no-write environment]
"Compile a Nujel source file into optimized object code"
[do [def source [read [file/read path]]]
[def object-code [compile/forms [cons 'do source] environment]]
[if no-write
#nil
[file/write [cat [path/without-extension path] ".no"] [str/write object-code]]]
object-code]]]
[def file/eval [λ* file/eval
[path]
"Evaluate a Nujel source file in the current context"
[do [def source [cons 'do [read [file/read path]]]]
[apply root-closure [cons [compile [cons 'do source]]]]]]]
[def eval/forked [λ* eval/forked
[nujel-binary raw-expr]
"Evaluate @EXPR in a separate process running NUJEL-BINARY"
[do [def expr [cat "[print [str/write " [str/write raw-expr]]]
[def tmp-path [file/temp expr]]
[def command [cat nujel-binary " " tmp-path]]
[def res [popen command]]
[file/remove tmp-path]
[cons [car res] [cdr res]]]]]
[def test-context "Nujel Bootstrap"]][do [def display/error/wrap [λ* display/error/wrap
[i text]
""
[cond [[eq? i 0] [ansi-red text]]
[[eq? i 1] [string text]]
[[eq? i 2] [ansi-yellow [str/write text]]]
[[eq? i 3] [describe/closure text]]
[#t text]]]]
[def display/error/iter [λ* display/error/iter
[error i]
""
[if error
[cons [display/error/wrap i [car error]] [display/error/iter [cdr error] [+ 1 i]]]
[cons "" #nil]]]]
[def display/error [λ* display/error
[error]
"Display ERROR in a nice, human readable way"
[display [join [display/error/iter error 0] "\r\n"]]]]
[def repl/exception-handler [λ* repl/exception-handler
[error]
""
[display/error error]]]
[def repl/history #nil]
[def repl/prompt [λ* repl/prompt
[]
"> "
"> "]]
[def repl/wasm [λ* repl/wasm
[line]
"Evaluate LINE in the wasm context"
[try repl/exception-handler [do [def raw [read line]]
[def expr [cons 'do raw]]
[def cexpr [cons [compile expr]]]
[apply root-closure cexpr]]]]]
[def repl/readline [λ* repl/readline
[ctx]
""
[do [def line [readline [repl/prompt]]]
[if [nil? line]
[do [display "Bye!\r\n"]
[exit 0]]
#nil]
[readline/history/add line]
[def raw [read line]]
[def expr [cons 'do raw]]
[def cexpr [cons [compile expr]]]
[def result [apply ctx cexpr]]
[set! repl/history [cons line repl/history]]
[display [cat [if [nil? result]
""
[str/write result]] "\n"]]]]]
[def repl [λ* repl
[]
""
[do [readline/history/load [readline/history/path]]
[while #t [do [try repl/exception-handler [repl/readline root-closure]]
[readline/history/save [readline/history/path]]]]]]]
[def repl/print-help [λ* repl/print-help
[]
""
[do [println [cat [ansi-rainbow "Nujel"] " - A Lisp dialect for games.\n"]]
[println [cat [ansi-green "Usage:"] " nujel [options] [command_string | file]\n"]]
[println [cat [ansi-blue "n"] " - do not load any stdlib"]]
[println [cat [ansi-blue "v"] " - be verbose"]]
[println [cat [ansi-blue "r"] " - eval following file without compilation/expansion"]]
[println [cat [ansi-blue "x"] " - Run the expression following this argument directly"]]]]]
[def repl/run-forked* [λ* repl/run-forked*
[expr]
""
[do [def command [cat repl/executable-name " -x \"" [str/write expr] "\""]]
[popen command]]]]
[def repl/run-forked [μ* repl/run-forked [expr] "" [cons 'repl/run-forked* [cons [list 'quote expr] #nil]]]]
[def repl/executable-name "nujel"]
[def repl/parse-args/eval-next #f]
[def repl/parse-args/run-repl #t]
[def repl/parse-option [λ* repl/parse-option
[option]
""
[cond [[eq? option "x"] [do [set! repl/parse-args/eval-next #t]
[set! repl/parse-args/run-repl #f]]]
[[eq? option "h"] [do [repl/print-help]
[set! repl/parse-args/run-repl #f]]]]]]
[def repl/parse-options [λ* repl/parse-options
[options]
""
[for-each repl/parse-option [split options ""]]]]
[def repl/parse-arg [λ* repl/parse-arg
[arg]
""
[cond [repl/parse-args/eval-next [do [apply root-closure [cons [compile [cons 'do [read arg]]]]]
[set! repl/eval-next #f]]]
[[eq? [char-at arg 0] 45] [repl/parse-options [substr arg 1]]]
[#t [do [file/eval arg]
[set! repl/parse-args/run-repl #f]]]]]]
[def repl/parse-args [λ* repl/parse-args
[args]
""
[if args
[do [repl/parse-arg [car args]]
[repl/parse-args [cdr args]]]
repl/parse-args/run-repl]]]
[def repl/init [λ* repl/init
[...args]
""
[do [set! repl/executable-name [car ...args]]
[if [repl/parse-args [cdr ...args]]
[repl]
#nil]]]]][if [eq? OS "Emscripten"]
#nil
[do [test/add* '[0 . ""] '[do [repl/run-forked 1]]]
[test/add* '[123 . ""] '[do [repl/run-forked [exit 123]]]]
[test/add* '[0 . "123"] '[do [repl/run-forked [display 123]]]]]]