application/octet-stream
•
3.79 KB
•
133 lines
[def ctx [current-closure]]
[def display/error [let*
[defun wrap [i text]
[cond [[eq? i 0] [ansi-red text]]
[[eq? i 1] [string text]]
[[eq? i 2] [ansi-yellow [str/write text]]]
[#t text]
]
]
[defun iter [error i]
[if error
[cons [wrap i [car error]]
[iter [cdr error] [++ i]]]
[cons "" #nil]]
]
[λ [error]
"Display ERROR in a nice, human readable way"
[display [join [iter error 0] "\r\n"]]
]
]]
[defun repl/exception-handler [error]
[display/error error]
]
[def repl/history #nil]
[defun repl/prompt []
"> "
]
[def repl/wasm [let*
[λ [line]
"Evaluate LINE in the wasm context"
[try repl/exception-handler
[def raw [read line]]
[def expr [cons 'do raw]]
[def cexpr [cons [compile expr]]]
[apply ctx cexpr]
]
]
]]
[defun repl/readline [ctx]
[def line [readline [repl/prompt]]]
[when [nil? line]
[display "Bye!\r\n"]
[exit 0]
]
[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"
]]
]
[defun repl []
[readline/history/load [readline/history/path]]
[while #t
[try repl/exception-handler
[repl/readline ctx]
]
[readline/history/save [readline/history/path]]
]
]
[defun repl/print-help []
[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"]]
]
[defun repl/run-forked* [expr]
[def command [cat repl/executable-name " -x \"" [str/write expr] "\""]]
[popen command]
]
[defmacro repl/run-forked [expr]
`[repl/run-forked* ~[list 'quote expr]]
]
[def repl/executable-name "nujel"]
[def repl/parse-args [let*
[def eval-next #f]
[def run-repl #t]
[defun parse-option [option]
[cond [[eq? option "x"] [set! eval-next #t]
[set! run-repl #f]]
[[eq? option "h"] [repl/print-help]
[set! run-repl #f]]
]
]
[defun parse-options [options]
[for-each parse-option [split options ""]]
]
[defun parse-arg [arg]
[cond [eval-next [apply root-closure [cons [compile [cons 'do [read arg]]]]]
[set! eval-next #f]]
[[eq? [char-at arg 0] #\-] [parse-options [substr arg 1]]]
[#t [file/eval arg]
[set! run-repl #f]]
]
]
[defun parse-args [args]
[if args
[do [parse-arg [car args]]
[parse-args [cdr args]]]
run-repl]
]
parse-args
]]
[defun repl/init [...args]
[set! repl/executable-name [car ...args]]
[when [repl/parse-args [cdr ...args]] [repl]]
]