bootstrap: SCI core deps loading with 284/304 forms passing

reader: #?@ empty splice fix (nil→@[]), #? nil→:jolt/skip, map reader handles #_/#?@ in K/V
evaluator: unwrap-meta-name helper, deftype interns ->Name too, dot-suffix fix
core: comment/prefer-method stubs, *unchecked-math*/*clojure-version* dynamic vars
This commit is contained in:
Yogthos 2026-06-01 23:24:13 -04:00
parent cdcf569506
commit b20536d1e3
31 changed files with 1348 additions and 65 deletions

28
test/bootstrap-test.janet Normal file
View file

@ -0,0 +1,28 @@
(use ../src/jolt/evaluator)
(use ../src/jolt/types)
(use ../src/jolt/reader)
(use ../src/jolt/api)
(def ctx (init))
(def source (slurp "/Users/yogthos/src/sci/src/sci/impl/macros.cljc"))
(var s source)
(var count 0)
(while (> (length (string/trim s)) 0)
(def [form rest] (parse-next s))
(set s rest)
(++ count)
(if (not (nil? form))
(do
(printf "eval form %d..." count)
(flush)
(eval-form ctx @{} form)
(printf " OK\n"))))
(printf "\n%d forms processed\n" count)
(printf "ns: %s\n" (ctx-current-ns ctx))
(let [ns (ctx-find-ns ctx "sci.impl.macros")]
(printf "sci.impl.macros bindings:\n")
(loop [[name v] :pairs (ns :mappings)]
(printf " %s: macro=%q\n" name (v :macro))))

View file

@ -1,6 +1,7 @@
(use ../src/jolt/evaluator)
(use ../src/jolt/types)
(use ../src/jolt/reader)
(use ../src/jolt/api)
# Helper: create a Jolt symbol
(defn sym [name]
@ -70,4 +71,81 @@
(assert (= 0 (countdown 5)) "recur in fn"))
(print " passed")
(print "10: throw/try/catch/finally...")
# throw + catch
(let [result (eval-str "(try (throw \"boom\") (catch Exception e \"caught\"))")]
(assert (= "caught" result) "catch catches throw"))
# try with finally — body returns, finally runs
(let [result (eval-str "(try 1 (finally 2))")]
(assert (= 1 result) "try returns body even with finally"))
# try/catch/finally — catch returns, finally runs
(let [result (eval-str "(try (throw \"err\") (catch Exception e \"handled\") (finally :cleanup))")]
(assert (= "handled" result) "catch + finally returns catch value"))
(print " passed")
(print "11: set!...")
# set! on a var
(assert (= 99 (eval-str "(do (def x 1) (set! x 99) x)")) "set! on var")
# set! re-evaluates
(assert (= 3 (eval-str "(do (def a 1) (def b 2) (set! a (+ a b)) a)")) "set! with expression")
(print " passed")
(print "12: var...")
# (var x) returns the var itself, not its value
(let [v (eval-str "(do (def x 42) (var x))")]
(assert (var? v) "(var x) returns a var")
(assert (= 42 (var-get v)) "var holds value"))
(print " passed")
(print "13: locking...")
# locking is a no-op in single-threaded Janet — just executes body
(assert (= 42 (eval-str "(locking :lock 42)")) "locking returns body result")
(print " passed")
(print "14: instance?...")
# instance? checks type
(assert (= true (eval-str "(instance? Number 42)")) "instance? Number matches number")
(assert (= false (eval-str "(instance? Number \"hello\")")) "instance? Number doesn't match string")
(print " passed")
(print "15: defmulti/defmethod...")
(let [ctx (make-ctx)]
(eval-form ctx @{} (parse-string "(defmulti my-dispatch (fn* [x] (x :type)))"))
(eval-form ctx @{} (parse-string "(defmethod my-dispatch :foo [_] :got-foo)"))
(eval-form ctx @{} (parse-string "(defmethod my-dispatch :bar [_] :got-bar)"))
(assert (= :got-foo (eval-form ctx @{} (parse-string "(my-dispatch {:type :foo})"))) "defmethod :foo dispatches")
(assert (= :got-bar (eval-form ctx @{} (parse-string "(my-dispatch {:type :bar})"))) "defmethod :bar dispatches"))
(print " passed")
(print "16: deftype...")
(let [ctx (make-ctx)
_ (eval-form ctx @{} (parse-string "(deftype Point [x y])"))
_ (eval-form ctx @{} (parse-string "(def p (Point. 10 20))"))
p-val (eval-form ctx @{} (parse-string "p"))
x-val (eval-form ctx @{} (parse-string "(p :x)"))
y-val (eval-form ctx @{} (parse-string "(p :y)"))
result [x-val y-val]]
(printf " p-val: %q" p-val)
(printf " x-val: %q, y-val: %q" x-val y-val)
(printf " result: %q" result)
(assert (deep= [10 20] result) "deftype creates tagged instances with fields"))
(print " passed")
(print "17: defmacro...")
# define a macro using defmacro special form
# init loads clojure.core so `list` is available
(let [ctx (init)
_ (eval-form ctx @{} (parse-string "(defmacro my-when [test body] (list 'if test body nil))"))
result (eval-form ctx @{} (parse-string "(my-when true 2)"))]
(assert (= 2 result) "defmacro defines callable macro"))
# verify the var is marked :macro
(let [ctx (make-ctx)
_ (eval-form ctx @{} (parse-string "(defmacro m [x] (list 'quote x))"))
v (resolve-var ctx @{} (parse-string "m"))]
(assert v "macro var exists")
(assert (v :macro) "macro var has :macro true"))
(print " passed")
(print "\nAll evaluator tests passed!")

View file

@ -115,10 +115,18 @@
(let [[form2 _] (parse-next rest-str)]
(assert (deep= [3 4] form2) "second form is vector")))
# Reader conditional (basic #? support)
(let [form (parse-string "#?(:clj 1 :cljs 2)")]
(assert (struct? form) "reader conditional")
(assert (= :jolt/reader-conditional (form :jolt/type)) "correct type"))
# Reader conditional — resolves :clj branch at read time
(assert (= 1 (parse-string "#?(:clj 1 :cljs 2)"))
"#?(:clj) picks :clj branch")
(assert (= nil (parse-string "#?(:cljs 999)"))
"#?(:cljs) returns nil on CLJ")
(assert (= 42 (parse-string "#?(:clj 42)"))
"#?(:clj) with single branch")
(assert (deep= (sym "clj-only") (parse-string "#?(:clj clj-only :cljs cljs-only)"))
"#?(:clj) picks :clj symbol")
# Nested inside a list — :clj branch is evaluated at read time
(assert (deep= @[(sym "+") 1 3] (parse-string "(+ 1 #?(:clj 3 :cljs 4))"))
"#? inside list picks :clj")
# Characters
(let [form (parse-string "\\newline")]