Login
7 branches 0 tags
Benjamin Vincent Schulenburg Some refactoring f6e9655 4 years ago 225 Commits
nujel / binlib / repl.nuj
[defun 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]
       ]
]

[defun display/error/iter [error i]
       [if error
           [cons [display/error/wrap i [car error]]
                 [display/error/iter [cdr error] [+ 1 i]]]
           [cons "" #nil]]
]

[defun display/error [error]
                "Display ERROR in a nice, human readable way"
                [display [join [display/error/iter error 0] "\r\n"]]
]

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

[def repl/history #nil]


[defun repl/prompt []
           "> "
]

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

[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 root-closure]
               ]
               [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/eval-next #f]
[def repl/parse-args/run-repl #t]

[defun repl/parse-option [option]
       [cond [[eq? option "x"]
              [set! repl/parse-args/eval-next #t]
              [set! repl/parse-args/run-repl #f]]
             [[eq? option "h"]
              [repl/print-help]
              [set! repl/parse-args/run-repl #f]]
       ]
]

[defun repl/parse-options [options]
       [for-each repl/parse-option [split options ""]]
]

[defun repl/parse-arg [arg]
       [cond [repl/parse-args/eval-next [apply root-closure [cons [compile [cons 'do [read arg]]]]]
                        [set! repl/eval-next #f]]
             [[eq? [char-at arg 0] #\-] [repl/parse-options [substr arg 1]]]
             [#t [file/eval arg]
                 [set! repl/parse-args/run-repl #f]]
       ]
]

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

[defun repl/init/wasm [args]
       [println [cat [ansi-rainbow "Nujel"] " wasm/REPL ready for input"]]
]

[defun repl/init/bin [args]
       [set! repl/executable-name [car args]]
       [when [repl/parse-args [cdr args]] [repl]]
]

[defun repl/init [...args]
       [if [eq? ARCH "wasm"]
           [repl/init/wasm ...args]
           [repl/init/bin ...args]]
]