Login
7 branches 0 tags
Ben (Win10) Fixed testsuite 98a33ec 3 years ago 582 Commits
nujel / binlib / repl.nuj
; Nujel - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
; This project uses the MIT license, a copy should be included under /LICENSE

[def repl/executable-name "nujel"]
[def repl/parse-args/bytecode-eval-next #f]
[def repl/parse-args/eval-next #f]
[def repl/parse-args/run-repl #t]
[def repl/options @[]]
[def repl/option-map @[]]

[defn repl/exception-handler [error]
        [display/error error]]

[def repl/history #nil]


[defn repl/prompt []
           "> "]

[defn repl/wasm [line]
       "Evaluate LINE in the wasm context"
       [try repl/exception-handler
            [def raw [read line]]
            [def cexpr [list [compile [cons 'do raw]]]]
            [apply root-closure cexpr]]]

[defn repl/readline [ctx]
        [def line [readline [repl/prompt]]]
        [when [nil? line]
              [display "Bye!\r\n"]
              [exit 0]]
        [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]]
        [println [cat [if [nil? result]
                          ""
                          [str/write result]]]]]

[defn repl []
        [while #t
               [try repl/exception-handler
                    [repl/readline root-closure]]]]

[defn repl/print-help []
       [println [cat [ansi-rainbow "Nujel"] " - A Lisp dialect for games.\n"]]
       [println [cat [ansi-green "Usage:"] " nujel [options] [command_string | file]"]]
       [println [cat "\nLow-level options - for work on the runtime itself"]]
       [println [cat "  " [ansi-yellow "n"] " - do not load the standard library"]]
       [println [cat "  " [ansi-yellow "v"] " - be verbose"]]
       [println [cat "  " [ansi-yellow "r"] " - eval following file without compilation/expansion"]]
       [println [cat "\nHigh-level options - for working with/on Nujel code"]]
       [println [cat "  " [ansi-blue "b"] " - eval following file using the bytecode interpreter"]]
       [println [cat "  " [ansi-blue "x"] " - Run the expression following this argument directly"]]
       [println [cat "  " [ansi-blue "h"] " - Print this help screen"]]
       [println [cat "\nLong options - for working with/on Nujel code"]]
       [println [cat "  " [ansi-blue "no-color"] " - Disable ANSI color"]]
       [println [cat "  " [ansi-blue "color   "] " - Enable ANSI color"]]]

[defn 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]]]

[tree/set! repl/option-map 'b
           [fn [option]
               [set! repl/parse-args/bytecode-eval-next #t]
               [set! repl/parse-args/run-repl #f]]]
[tree/set! repl/option-map 'h
           [fn [option]
               [repl/print-help]
               [set! repl/parse-args/run-repl #f]]]
[tree/set! repl/option-map 'no-color
           [fn [option]
               [set! ansi/disabled ""]]]
[tree/set! repl/option-map 'color
           [fn [option]
               [set! ansi/disabled #f]]]
[tree/set! repl/option-map 'x
           [fn [option]
               [set! repl/parse-args/eval-next #t]
               [set! repl/parse-args/run-repl #f]]]
[tree/set! repl/option-map :default
           [fn [option]
               [tree/set! repl/options option #t]]]

[defn repl/parse-option [option]
       [[or [ref repl/option-map option]
            [ref repl/option-map :default]] option]]

[defn repl/parse-options [options]
       [if [== [char-at options 0] #\-]
           [repl/parse-option [string->keyword [cut options 1]]]
           [for-each [map [split options ""] str->sym] repl/parse-option]]]

[defn repl/parse-arg [arg]
       [cond [repl/parse-args/bytecode-eval-next [try display/error
                                                      [file/eval/bytecode arg]]
                                                 [set! repl/parse-args/bytecode-eval-next #f]]
             [repl/parse-args/eval-next [try display/error
                                             [apply root-closure [cons [compile [cons 'do [read arg]]]]]]
                                        [set! repl/parse-args/eval-next #f]]
             [[== [char-at arg 0] #\-] [repl/parse-options [string/cut arg 1]]]
             [#t [try display/error
                      [file/eval arg]]
                 [set! repl/parse-args/run-repl #f]]]]

[defn repl/parse-args [args]
       [if args
           [do [repl/parse-arg [car args]]
               [repl/parse-args [cdr args]]]
           repl/parse-args/run-repl]]

[defn repl/init/wasm [args]
       [println [cat [ansi-rainbow "Nujel"] " heißt euch willkommen!"]]]

[defn repl/init/bin [args]
       [try repl/exception-handler
            [set! repl/executable-name [car args]]
            [when [repl/parse-args [cdr args]] [repl]]]]

[defn repl/init args
       [if [== System/Architecture 'wasm]
           [repl/init/wasm args]
           [repl/init/bin args]]]