mirror of
https://github.com/kanaka/mal.git
synced 2024-09-11 13:55:55 +03:00
Print a stack trace for uncaught exceptions in self-hosting
An uncaught exception in the self-hosting implementation causes the interpreter to display the EVALed ast for each EVAL level until the exception, something similare to a stack trace. This does not cost much and may help a lot debugging the self-hosting step. On the other hand, remove try* from step0 where it serves no useful purpose. Because of indentation level, this diff is better viewed with the git -b command line option.
This commit is contained in:
parent
931971e047
commit
4807c1b65f
@ -18,10 +18,7 @@
|
||||
(if line
|
||||
(do
|
||||
(if (not (= "" line))
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(println (rep line)))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,3 +1,7 @@
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -23,15 +27,20 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast) )
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(if (empty? ast)
|
||||
ast
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))
|
||||
;; apply list
|
||||
(if (empty? ast)
|
||||
ast
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -39,7 +48,7 @@
|
||||
;; repl
|
||||
(def! repl-env {"+" +
|
||||
"-" -
|
||||
"*" *
|
||||
"*" *
|
||||
"/" /})
|
||||
(def! rep (fn* [strng]
|
||||
(PRINT (EVAL (READ strng) repl-env))))
|
||||
@ -52,7 +61,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,5 +1,9 @@
|
||||
(load-file "../mal/env.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -30,25 +34,30 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -71,7 +80,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -31,38 +35,43 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -86,7 +95,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -31,38 +35,43 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -89,7 +98,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -49,47 +53,52 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -116,7 +125,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -57,55 +61,60 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -133,7 +142,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -57,64 +61,71 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
|
||||
(= 'try* a0)
|
||||
(if (< (count ast) 3)
|
||||
(EVAL (nth ast 1) env)
|
||||
(try*
|
||||
(= 'try* a0)
|
||||
(if (< (count ast) 3)
|
||||
(EVAL (nth ast 1) env)
|
||||
(catch* exc
|
||||
(let* [a2 (nth ast 2)]
|
||||
(EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc]))))))
|
||||
(try*
|
||||
(EVAL (nth ast 1) env)
|
||||
(catch* exc
|
||||
(do
|
||||
(reset! trace "")
|
||||
(let* [a2 (nth ast 2)]
|
||||
(EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc])))))))
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -142,7 +153,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
@ -1,6 +1,10 @@
|
||||
(load-file "../mal/env.mal")
|
||||
(load-file "../mal/core.mal")
|
||||
|
||||
;; EVAL extends this stack trace when propagating exceptions. If the
|
||||
;; exception reaches the REPL loop, the full trace is printed.
|
||||
(def! trace (atom ""))
|
||||
|
||||
;; read
|
||||
(def! READ read-string)
|
||||
|
||||
@ -57,64 +61,71 @@
|
||||
|
||||
(def! EVAL (fn* [ast env]
|
||||
;; (do (prn "EVAL" ast "/" (keys @env)) )
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
(try*
|
||||
(let* [ast (MACROEXPAND ast env)]
|
||||
(if (not (list? ast))
|
||||
(eval-ast ast env)
|
||||
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
;; apply list
|
||||
(let* [a0 (first ast)]
|
||||
(cond
|
||||
(empty? ast)
|
||||
ast
|
||||
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
(= 'def! a0)
|
||||
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
|
||||
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
(= 'let* a0)
|
||||
(LET (new-env env) (nth ast 1) (nth ast 2))
|
||||
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
(= 'quote a0)
|
||||
(nth ast 1)
|
||||
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
(= 'quasiquoteexpand a0)
|
||||
(QUASIQUOTE (nth ast 1))
|
||||
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
(= 'quasiquote a0)
|
||||
(EVAL (QUASIQUOTE (nth ast 1)) env)
|
||||
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
(= 'defmacro! a0)
|
||||
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
|
||||
(EVAL (nth ast 2) env)))
|
||||
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
(= 'macroexpand a0)
|
||||
(MACROEXPAND (nth ast 1) env)
|
||||
|
||||
(= 'try* a0)
|
||||
(if (< (count ast) 3)
|
||||
(EVAL (nth ast 1) env)
|
||||
(try*
|
||||
(= 'try* a0)
|
||||
(if (< (count ast) 3)
|
||||
(EVAL (nth ast 1) env)
|
||||
(catch* exc
|
||||
(let* [a2 (nth ast 2)]
|
||||
(EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc]))))))
|
||||
(try*
|
||||
(EVAL (nth ast 1) env)
|
||||
(catch* exc
|
||||
(do
|
||||
(reset! trace "")
|
||||
(let* [a2 (nth ast 2)]
|
||||
(EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc])))))))
|
||||
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
(= 'do a0)
|
||||
(let* [el (eval-ast (rest ast) env)]
|
||||
(nth el (- (count el) 1)))
|
||||
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
(= 'if a0)
|
||||
(if (EVAL (nth ast 1) env)
|
||||
(EVAL (nth ast 2) env)
|
||||
(if (> (count ast) 3)
|
||||
(EVAL (nth ast 3) env)))
|
||||
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
(= 'fn* a0)
|
||||
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
|
||||
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))))
|
||||
"else"
|
||||
(let* [el (eval-ast ast env)]
|
||||
(apply (first el) (rest el)))))))
|
||||
|
||||
(catch* exc
|
||||
(do
|
||||
(swap! trace str "\n in mal EVAL: " ast)
|
||||
(throw exc))))))
|
||||
|
||||
;; print
|
||||
(def! PRINT pr-str)
|
||||
@ -143,7 +154,9 @@
|
||||
(try*
|
||||
(println (rep line))
|
||||
(catch* exc
|
||||
(println "Uncaught exception:" exc))))
|
||||
(do
|
||||
(println "Uncaught exception:" exc @trace)
|
||||
(reset! trace "")))))
|
||||
(repl-loop (readline "mal-user> "))))))
|
||||
|
||||
;; main
|
||||
|
Loading…
Reference in New Issue
Block a user