- PEG-based Clojure reader (symbols, keywords, numbers, strings, lists, vectors, maps, sets, quote forms, reader macros, metadata) - Tree-walking evaluator (quote, do, if, def, fn*, let*, loop*/recur, syntax-quote/unquote/unquote-splicing, macro system, ns/require/in-ns) - 95+ clojure.core functions (predicates, math, collections, seq ops, higher-order, atoms, I/O) - Public API (init, eval-string, eval-string*) - REPL (jolt/main.janet) - 7 test suites, all green - MIT license
73 lines
2.2 KiB
Text
73 lines
2.2 KiB
Text
(use ../src/jolt/evaluator)
|
|
(use ../src/jolt/types)
|
|
(use ../src/jolt/reader)
|
|
|
|
# Helper: create a Jolt symbol
|
|
(defn sym [name]
|
|
(let [slash (string/find "/" name)]
|
|
(if slash
|
|
{:jolt/type :symbol :ns (string/slice name 0 slash)
|
|
:name (string/slice name (+ slash 1))}
|
|
{:jolt/type :symbol :ns nil :name name})))
|
|
|
|
# Helper: parse and eval
|
|
(defn eval-str [s]
|
|
(let [ctx (make-ctx)
|
|
form (parse-string s)]
|
|
(eval-form ctx @{} form)))
|
|
|
|
(print "1: literals...")
|
|
(assert (= 42 (eval-str "42")) "integer")
|
|
(assert (= "hello" (eval-str "\"hello\"")) "string")
|
|
(assert (= true (eval-str "true")) "true")
|
|
(assert (= false (eval-str "false")) "false")
|
|
(assert (= nil (eval-str "nil")) "nil")
|
|
(print " passed")
|
|
|
|
(print "2: quote...")
|
|
(assert (deep= (sym "x") (eval-str "'x")) "quote returns symbol")
|
|
(assert (deep= @[1 2 3] (eval-str "'(1 2 3)")) "quote list")
|
|
(print " passed")
|
|
|
|
(print "3: do...")
|
|
(assert (= 2 (eval-str "(do 1 2)")) "do returns last")
|
|
(print " passed")
|
|
|
|
(print "4: if...")
|
|
(assert (= 1 (eval-str "(if true 1 2)")) "if true")
|
|
(assert (= 2 (eval-str "(if false 1 2)")) "if false")
|
|
(assert (= :b (eval-str "(if nil :a :b)")) "if nil = false")
|
|
(assert (= nil (eval-str "(if false 1)")) "if with no else")
|
|
(print " passed")
|
|
|
|
(print "5: def...")
|
|
(assert (= 42 (eval-str "(do (def x 42) x)")) "def in do")
|
|
(print " passed")
|
|
|
|
(print "6: fn*...")
|
|
(let [f (eval-str "(fn* [x] (inc x))")]
|
|
(assert (function? f) "fn* returns function")
|
|
(assert (= 42 (f 41)) "fn* fn works"))
|
|
# nested function
|
|
(let [f (eval-str "(fn* [x] (inc (inc x)))")]
|
|
(assert (= 43 (f 41)) "nested inc"))
|
|
(print " passed")
|
|
|
|
(print "7: let*...")
|
|
(assert (= 2 (eval-str "(let* [x 1 y 2] y)")) "let* binds")
|
|
(assert (= 3 (eval-str "(let* [x 1] (inc (inc x)))")) "let* with expr")
|
|
(print " passed")
|
|
|
|
(print "8: loop*/recur...")
|
|
(assert (= 5 (eval-str "(loop* [x 0] (if (< x 5) (recur (inc x)) x))"))
|
|
"loop counts up")
|
|
(assert (= 10 (eval-str "(loop* [i 0 acc 0] (if (< i 5) (recur (inc i) (+ acc i)) acc))"))
|
|
"loop with multiple bindings")
|
|
(print " passed")
|
|
|
|
(print "9: recur in fn*...")
|
|
(let [countdown (eval-str "(fn* [n] (if (< n 1) 0 (recur (dec n))))")]
|
|
(assert (= 0 (countdown 5)) "recur in fn"))
|
|
(print " passed")
|
|
|
|
(print "\nAll evaluator tests passed!")
|