test: restructure into unit / integration / spec layers + shared harness

Reorganize the flat 49-file test/ into three layers (jpm test recurses, so all
are still discovered):
- test/unit/        white-box component tests (reader, evaluator, types,
                    persistent-map, lazy-seq, macro, interop, compiler)
- test/integration/ cross-cutting + regression batteries (conformance, jank,
                    sci-bootstrap/runtime, features, systematic-coverage, api,
                    core, namespaces, ported clojure suites) and
   .../ports/       ported clojure/cljs test batches pending consolidation
- test/spec/        the behavioral contract (built out in following commits)
- test/support/harness.janet  shared defspec table runner (cases compared via
                    Jolt's own =, with a :throws sentinel) + expect= helpers

Files moved with git mv (history preserved) and import paths fixed for depth.
jpm test green. README Test section updated.

Next: build out test/spec/ to cover the public API area-by-area, mining the
integration batteries and filling gaps.
This commit is contained in:
Yogthos 2026-06-05 00:00:16 -04:00
parent 1898308926
commit 16428179fa
52 changed files with 185 additions and 86 deletions

View file

@ -0,0 +1,38 @@
(use ../../src/jolt/api)
(use ../../src/jolt/types)
(print "1: init creates context...")
(let [ctx (init)]
(assert (ctx? ctx) "init returns context")
(let [ns (ctx-find-ns ctx "clojure.core")]
(assert (ns? ns) "clojure.core namespace exists")
(assert (ns-find ns "nil?") "nil? is interned")
(assert (ns-find ns "+") "+ is interned")))
(print " passed")
(print "2: eval-string basics...")
(let [ctx (init)]
(assert (= 42 (eval-string ctx "42")) "eval integer")
(assert (= true (eval-string ctx "true")) "eval bool")
(assert (= 3 (eval-string ctx "(+ 1 2)")) "eval list"))
(print " passed")
(print "3: eval-string with core fns...")
(let [ctx (init)]
(assert (= true (eval-string ctx "(nil? nil)")) "nil?")
(assert (deep= [2 3 4] (normalize-pvecs (eval-string ctx "(map inc [1 2 3])"))) "map+inc")
(assert (= 6 (eval-string ctx "(reduce + [1 2 3])")) "reduce"))
(print " passed")
(print "4: eval-string with def...")
(let [ctx (init)]
(eval-string ctx "(def x 42)")
(assert (= 42 (eval-string ctx "x")) "def then resolve"))
(print " passed")
(print "5: eval-string* with bindings...")
(let [ctx (init)]
(assert (= 99 (eval-string* ctx "y" @{"y" 99})) "bound variable"))
(print " passed")
(print "\nAll API tests passed!")

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

@ -0,0 +1,154 @@
# Ported from clojure/test_clojure/atoms.clj + systematic atom tests
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported Atom Tests")
# --- atom creation ---
(print "test atom creation...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?")
(assert (= false (ct-eval ctx "(atom? nil)")) "atom? nil")
(assert (= false (ct-eval ctx "(atom? 42)")) "atom? number")
(assert (= false (ct-eval ctx "(atom? \"x\")")) "atom? string")
(assert (= 42 (ct-eval ctx "(deref (atom 42))")) "deref atom")
(assert (= 99 (ct-eval ctx "(let [a (atom 99)] @a)")) "@ deref macro"))
(print " ok")
# --- deref on non-atoms ---
(print "test deref...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(deref 1)")) "deref non-atom passes through")
(assert (= "x" (ct-eval ctx "(deref \"x\")")) "deref string passes through")
(assert (= nil (ct-eval ctx "(deref nil)")) "deref nil"))
(print " ok")
# --- reset! ---
(print "test reset!...")
(let [ctx (init)]
(assert (= :b (ct-eval ctx "(let [a (atom :a)] (reset! a :b))")) "reset! returns new")
(assert (= 42 (ct-eval ctx "(let [a (atom 0)] (reset! a 42) @a)")) "reset! updates value")
(assert (= true (ct-eval ctx "(= [1 1] (let [a (atom 0)] [(reset! a 1) @a]))")) "reset! returns new, value changed"))
(print " ok")
# --- swap! ---
(print "test swap!...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(let [a (atom 0)] (swap! a inc))")) "swap! inc returns new")
(assert (= 2 (ct-eval ctx "(let [a (atom 0)] (swap! a + 2))")) "swap! + 2")
(assert (= 3 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2) @a)")) "swap! + 1 2")
(assert (= 6 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2 3) @a)")) "swap! + 1 2 3")
(assert (= 10 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2 3 4) @a)")) "swap! + 1 2 3 4"))
(print " ok")
# --- swap-vals! (returns [old new]) ---
(print "test swap-vals!...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= [0 1] (let [a (atom 0)] (swap-vals! a inc)))")) "swap-vals! inc")
(assert (= true (ct-eval ctx
"(= [1 2] (let [a (atom 1)] (swap-vals! a inc)))")) "swap-vals! inc from 1")
(assert (= 2 (ct-eval ctx
"(let [a (atom 1)] (swap-vals! a inc) @a)")) "swap-vals! updates value"))
(print " ok")
# --- swap-vals! with extra args ---
(print "test swap-vals! arities...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= [0 1] (let [a (atom 0)] (swap-vals! a + 1)))")) "swap-vals! + 1")
(assert (= true (ct-eval ctx
"(= [1 3] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1)))")) "swap-vals! + 1 1")
(assert (= true (ct-eval ctx
"(= [3 6] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1) (swap-vals! a + 1 1 1)))")) "swap-vals! + 1 1 1")
(assert (= true (ct-eval ctx
"(= [6 10] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1) (swap-vals! a + 1 1 1) (swap-vals! a + 1 1 1 1)))")) "swap-vals! + 1 1 1 1"))
(print " ok")
# --- reset-vals! (returns [old new]) ---
(print "test reset-vals!...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= [0 :b] (let [a (atom 0)] (reset-vals! a :b)))")) "reset-vals! returns old new")
(assert (= true (ct-eval ctx
"(= [:b 42] (let [a (atom 0)] (reset-vals! a :b) (reset-vals! a 42)))")) "reset-vals! chain")
(assert (= 42 (ct-eval ctx
"(let [a (atom 0)] (reset-vals! a :b) (reset-vals! a 42) @a)")) "reset-vals! updates value"))
(print " ok")
# --- compare-and-set! ---
(print "test compare-and-set!...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(let [a (atom 0)] (compare-and-set! a 0 1))")) "CAS true match")
(assert (= true (ct-eval ctx
"(= [true 1] (let [a (atom 0)] [(compare-and-set! a 0 1) @a]))")) "CAS true + value changed")
(assert (= true (ct-eval ctx
"(= [false 0] (let [a (atom 0)] [(compare-and-set! a 1 2) @a]))")) "CAS false no match")
(assert (= true (ct-eval ctx
"(= [false 1] (let [a (atom 0)] (compare-and-set! a 0 1) [(compare-and-set! a 0 2) @a]))")) "CAS false after change"))
(print " ok")
# --- validator ---
(print "test validator...")
(let [ctx (init)]
(assert (= 42 (ct-eval ctx
"(let [a (atom 0 :validator pos?)] (reset! a 42) @a)")) "validator passes")
(assert (= true (ct-eval ctx
"(= false (try (let [a (atom 0 :validator pos?)] (reset! a -1) true) (catch Exception e false)))")) "validator blocks invalid reset!")
(assert (= true (ct-eval ctx
"(= false (try (let [a (atom 0 :validator pos?)] (swap! a (fn [x] -1)) true) (catch Exception e false)))")) "validator blocks invalid swap!")
(assert (= nil (ct-eval ctx "(set-validator! (atom 0) pos?)")) "set-validator! returns nil")
(assert (= nil (ct-eval ctx "(get-validator (atom 0))")) "get-validator nil default")
(assert (= true (ct-eval ctx
"(= even? (do (def a (atom 0)) (set-validator! a even?) (get-validator a)))")) "get-validator returns set fn"))
(print " ok")
# --- watches ---
(print "test watches...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(empty? (:watches (atom 0)))")) "atom starts with empty watches")
(assert (= true (ct-eval ctx
"(= [0 42] (let [a (atom 0)
w (atom nil)]
(add-watch a :my-key (fn [k ref old new] (reset! w [old new])))
(swap! a + 42)
@w))")) "add-watch triggers on swap!")
(assert (= true (ct-eval ctx
"(= :unchanged (let [a (atom 0)
w (atom :unchanged)]
(add-watch a :x (fn [_ _ _ _] (reset! w :fired)))
(remove-watch a :x)
(swap! a inc)
@w))")) "remove-watch stops notification")
(assert (= true (ct-eval ctx
"(= 2 (let [a (atom 0)]
(add-watch a :foo (fn [_ _ _ _] nil))
(add-watch a :bar (fn [_ _ _ _] nil))
(count (:watches a))))")) "multiple watches")
(assert (= true (ct-eval ctx
"(= 0 (let [a (atom 0)]
(add-watch a :foo (fn [_ _ _ _] nil))
(remove-watch a :foo)
(count (:watches a))))")) "remove-watch clears count")
(assert (= true (ct-eval ctx
"(= 2 (let [a (atom 0)
fired (atom [])]
(add-watch a :w1 (fn [_ _ o n] (swap! fired conj [:w1 o n])))
(add-watch a :w2 (fn [_ _ o n] (swap! fired conj [:w2 o n])))
(reset! a 99)
(count @fired)))")) "multiple watches both fire"))
(print " ok")
# --- metadata on atoms ---
(print "test atom metadata...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(meta (atom 0))")) "atom meta nil by default")
(assert (= true (ct-eval ctx
"(= {:foo \"bar\"} (meta (atom 0 :meta {:foo \"bar\"})))")) "atom with :meta")
(assert (= true (ct-eval ctx
"(= {:validated true} (meta (atom 0 :validator pos? :meta {:validated true})))")) "atom with validator and meta"))
(print " ok")
(print "\nAll Ported Atom tests passed!")

View file

@ -0,0 +1,151 @@
# Ported from clojure/test_clojure/control.clj
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported Control Tests")
# --- test-do ---
(print "test-do...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(do)")) "do empty -> nil")
(assert (= 1 (ct-eval ctx "(do 1)")) "do returns last")
(assert (= 2 (ct-eval ctx "(do 1 2)")) "do returns last")
(assert (= 5 (ct-eval ctx "(do 1 2 3 4 5)")) "do returns last"))
(print " ok")
# --- test-loop ---
(print "test-loop...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(loop [] 1)")) "loop body")
(assert (= 3 (ct-eval ctx "(loop [a 1] (if (< a 3) (recur (inc a)) a))")) "loop recur")
(assert (= true (ct-eval ctx
"(= [6 4 2] (loop [a () b [1 2 3]]
(if (seq b)
(recur (conj a (* 2 (first b))) (next b))
a)))")) "loop accum list")
(assert (= true (ct-eval ctx
"(= [2 4 6] (loop [a [] b [1 2 3]]
(if (seq b)
(recur (conj a (* 2 (first b))) (next b))
a)))")) "loop accum vector"))
(print " ok")
# --- test-when ---
(print "test-when...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(when true 1)")) "when true")
(assert (= nil (ct-eval ctx "(when true)")) "when true no body")
(assert (= nil (ct-eval ctx "(when false)")) "when false")
(assert (= nil (ct-eval ctx "(when false 1)")) "when false with body"))
(print " ok")
# --- test-when-not ---
(print "test-when-not...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(when-not false 1)")) "when-not false")
(assert (= nil (ct-eval ctx "(when-not true)")) "when-not true no body")
(assert (= nil (ct-eval ctx "(when-not false)")) "when-not false no body")
(assert (= nil (ct-eval ctx "(when-not true 1)")) "when-not true with body"))
(print " ok")
# --- test-if-not ---
(print "test-if-not...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(if-not false 1)")) "if-not false")
(assert (= 1 (ct-eval ctx "(if-not false 1 2)")) "if-not false with else")
(assert (= nil (ct-eval ctx "(if-not true 1)")) "if-not true")
(assert (= 2 (ct-eval ctx "(if-not true 1 2)")) "if-not true with else"))
(print " ok")
# --- test-when-let ---
(print "test-when-let...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(when-let [a 1] a)")) "when-let simple")
(assert (= 2 (ct-eval ctx "(when-let [[a b] '(1 2)] b)")) "when-let destructure")
(assert (= nil (ct-eval ctx "(when-let [a false] 1)")) "when-let false"))
(print " ok")
# --- test-if-let ---
(print "test-if-let...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(if-let [a 1] a)")) "if-let simple")
(assert (= 2 (ct-eval ctx "(if-let [[a b] '(1 2)] b)")) "if-let destructure")
(assert (= nil (ct-eval ctx "(if-let [a false] 1)")) "if-let false")
(assert (= 1 (ct-eval ctx "(if-let [a false] a 1)")) "if-let false with else"))
(print " ok")
# --- test-if-some ---
(print "test-if-some...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(if-some [a 1] a)")) "if-some simple")
(assert (= false (ct-eval ctx "(if-some [a false] a)")) "if-some false is some")
(assert (= nil (ct-eval ctx "(if-some [a nil] 1)")) "if-some nil")
(assert (= 3 (ct-eval ctx "(if-some [[a b] [1 2]] (+ a b))")) "if-some destructure"))
(print " ok")
# --- test-when-some ---
(print "test-when-some...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(when-some [a 1] a)")) "when-some simple")
(assert (= 2 (ct-eval ctx "(when-some [[a b] [1 2]] b)")) "when-some destructure")
(assert (= false (ct-eval ctx "(when-some [a false] a)")) "when-some false is some")
(assert (= nil (ct-eval ctx "(when-some [a nil] 1)")) "when-some nil"))
(print " ok")
# --- test-cond ---
(print "test-cond...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(cond)")) "cond empty -> nil")
(assert (= nil (ct-eval ctx "(cond nil true)")) "cond nil -> nil")
(assert (= nil (ct-eval ctx "(cond false true)")) "cond false -> nil")
(assert (= 1 (ct-eval ctx "(cond true 1)")) "cond true -> 1")
(assert (= 3 (ct-eval ctx "(cond nil 1 false 2 true 3 true 4)")) "cond third branch")
(assert (= :b (ct-eval ctx "(cond false :a true :b)")) "cond skips false")
(assert (= :a (ct-eval ctx "(cond true :a true :b)")) "cond takes first true"))
(print " ok")
# --- test-condp ---
(print "test-condp...")
(let [ctx (init)]
(assert (= :pass (ct-eval ctx "(condp = 1 1 :pass 2 :fail)")) "condp match first")
(assert (= :pass (ct-eval ctx "(condp = 1 2 :fail 1 :pass)")) "condp match second")
(assert (= :pass (ct-eval ctx "(condp = 1 2 :fail :pass)")) "condp default"))
(print " ok")
# --- test-dotimes ---
(print "test-dotimes...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(dotimes [n 1] n)")) "dotimes returns nil")
(assert (= 3 (ct-eval ctx
"(let [a (atom 0)]
(dotimes [n 3] (swap! a inc))
@a)")) "dotimes 3 iterations")
(assert (= [0 1 2] (ct-eval ctx
"(let [a (atom [])]
(dotimes [n 3] (swap! a conj n))
@a)")) "dotimes with index"))
(print " ok")
# --- test-while ---
(print "test-while...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(while nil 1)")) "while nil returns nil")
(assert (= true (ct-eval ctx
"(= [0 nil]
(let [a (atom 3)
w (while (pos? @a) (swap! a dec))]
[@a w]))")) "while dec to 0"))
(print " ok")
# --- test-case ---
(print "test-case...")
(let [ctx (init)]
(assert (= :number (ct-eval ctx "(case 1 1 :number :default)")) "case match 1")
(assert (= :string (ct-eval ctx "(case \"foo\" \"foo\" :string :default)")) "case match string")
(assert (= :kw (ct-eval ctx "(case :zap :zap :kw :default)")) "case match keyword")
(assert (= :symbol (ct-eval ctx "(case 'pow pow :symbol :default)")) "case match symbol")
(assert (= :default (ct-eval ctx "(case 99 1 :number :default)")) "case default")
(assert (= :matched (ct-eval ctx "(case 2 (2 3 4) :matched :default)")) "case one-of-many"))
(print " ok")
(print "\nAll Ported Control tests passed!")

View file

@ -0,0 +1,35 @@
# Ported from clojure/test_clojure/for.clj
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported For Tests")
# --- When ---
(print "test-for :when...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= (for [x (range 10) :when (odd? x)] x)
(quote (1 3 5 7 9)))")) "for :when odd?")
(assert (= true (ct-eval ctx
"(= (for [x (range 4) y (range 4) :when (odd? y)] [x y])
(quote ([0 1] [0 3] [1 1] [1 3] [2 1] [2 3] [3 1] [3 3])))")) "for nested :when"))
(print " ok")
# --- Let ---
(print "test-for :let...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= (for [x (range 3) y (range 3) :let [z (+ x y)] :when (odd? z)] [x y z])
(quote ([0 1 1] [1 0 1] [1 2 3] [2 1 3])))")) "for :let :when"))
(print " ok")
# --- Nesting ---
(print "test-for nesting...")
(let [ctx (init)]
(assert (= true (ct-eval ctx
"(= (for [x (quote (a b)) y (interpose x (quote (1 2))) z (list x y)] [x y z])
(quote ([a 1 a] [a 1 1] [a a a] [a a a] [a 2 a] [a 2 2]
[b 1 b] [b 1 1] [b b b] [b b b] [b 2 b] [b 2 2])))")) "for nested interpose"))
(print " ok")
(print "\nAll Ported For tests passed!")

View file

@ -0,0 +1,127 @@
# Ported from clojure/test_clojure/logic.clj
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported Logic Tests (from clojure/test-clojure/logic.clj)")
# --- test-if ---
(print "test-if: true/false/nil...")
(let [ctx (init)]
(assert (= :t (ct-eval ctx "(if true :t)")) "if true")
(assert (= :t (ct-eval ctx "(if true :t :f)")) "if true with else")
(assert (= nil (ct-eval ctx "(if false :t)")) "if false no else")
(assert (= :f (ct-eval ctx "(if false :t :f)")) "if false with else")
(assert (= nil (ct-eval ctx "(if nil :t)")) "if nil no else")
(assert (= :f (ct-eval ctx "(if nil :t :f)")) "if nil with else"))
(print " ok")
(print "test-if: zero/empty is true...")
(let [ctx (init)]
(assert (= :t (ct-eval ctx "(if 0 :t :f)")) "0 is true")
(assert (= :t (ct-eval ctx "(if 0.0 :t :f)")) "0.0 is true")
(assert (= :t (ct-eval ctx "(if \"\" :t :f)")) "empty string is true")
(assert (= :t (ct-eval ctx "(if () :t :f)")) "empty list is true")
(assert (= :t (ct-eval ctx "(if [] :t :f)")) "empty vector is true")
(assert (= :t (ct-eval ctx "(if {} :t :f)")) "empty map is true")
(assert (= :t (ct-eval ctx "(if #{} :t :f)")) "empty set is true"))
(print " ok")
(print "test-if: anything except nil/false is true...")
(let [ctx (init)]
(assert (= :t (ct-eval ctx "(if 42 :t :f)")) "42 is true")
(assert (= :t (ct-eval ctx "(if 1.2 :t :f)")) "1.2 is true")
(assert (= :t (ct-eval ctx "(if \"abc\" :t :f)")) "string is true")
(assert (= :t (ct-eval ctx "(if 'abc :t :f)")) "symbol is true")
(assert (= :t (ct-eval ctx "(if :kw :t :f)")) "keyword is true")
(assert (= :t (ct-eval ctx "(if '(1 2) :t :f)")) "list is true")
(assert (= :t (ct-eval ctx "(if [1 2] :t :f)")) "vector is true")
(assert (= :t (ct-eval ctx "(if {:a 1 :b 2} :t :f)")) "map is true")
(assert (= :t (ct-eval ctx "(if #{1 2} :t :f)")) "set is true"))
(print " ok")
# --- test-nil-punning ---
(print "test-nil-punning...")
(let [ctx (init)]
(assert (= :yes (ct-eval ctx "(if (first []) :no :yes)")) "first [] nil")
(assert (= :yes (ct-eval ctx "(if (next [1]) :no :yes)")) "next [1] nil")
(assert (= :no (ct-eval ctx "(if (rest [1]) :no :yes)")) "rest [1] non-nil")
(assert (= :yes (ct-eval ctx "(if (seq nil) :no :yes)")) "seq nil")
(assert (= :yes (ct-eval ctx "(if (seq []) :no :yes)")) "seq [] nil")
(assert (= :no (ct-eval ctx "(if (lazy-seq nil) :no :yes)")) "lazy-seq nil non-nil")
(assert (= :no (ct-eval ctx "(if (lazy-seq []) :no :yes)")) "lazy-seq [] non-nil")
(assert (= :no (ct-eval ctx "(if (filter (fn [x] (> x 10)) [1 2 3]) :no :yes)")) "filter non-match non-nil")
(assert (= :no (ct-eval ctx "(if (map identity []) :no :yes)")) "map empty non-nil")
(assert (= :no (ct-eval ctx "(if (apply concat []) :no :yes)")) "apply concat [] non-nil")
(assert (= :no (ct-eval ctx "(if (concat) :no :yes)")) "concat empty non-nil")
(assert (= :no (ct-eval ctx "(if (concat []) :no :yes)")) "concat [] non-nil")
(assert (= :no (ct-eval ctx "(if (reverse nil) :no :yes)")) "reverse nil non-nil")
(assert (= :no (ct-eval ctx "(if (reverse []) :no :yes)")) "reverse [] non-nil")
(assert (= :no (ct-eval ctx "(if (sort nil) :no :yes)")) "sort nil non-nil")
(assert (= :no (ct-eval ctx "(if (sort []) :no :yes)")) "sort [] non-nil"))
(print " ok")
# --- test-and ---
(print "test-and...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(and)")) "and empty")
(assert (= true (ct-eval ctx "(and true)")) "and true")
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
(assert (= false (ct-eval ctx "(and false)")) "and false")
(assert (= nil (ct-eval ctx "(and true nil)")) "and true nil")
(assert (= false (ct-eval ctx "(and true false)")) "and true false")
(assert (= "abc" (ct-eval ctx "(and 1 true :kw 'abc \"abc\")")) "and chain last")
(assert (= nil (ct-eval ctx "(and 1 true :kw nil 'abc \"abc\")")) "and chain nil")
(assert (= false (ct-eval ctx "(and 1 true :kw 'abc \"abc\" false)")) "and chain false"))
(print " ok")
# --- test-or ---
(print "test-or...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(or)")) "or empty")
(assert (= true (ct-eval ctx "(or true)")) "or true")
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
(assert (= false (ct-eval ctx "(or false)")) "or false")
(assert (= true (ct-eval ctx "(or nil false true)")) "or nil false true")
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or picks first truthy")
(assert (= "abc" (ct-eval ctx "(or nil false \"abc\" :kw)")) "or picks string")
(assert (= nil (ct-eval ctx "(or false nil)")) "or false nil -> nil")
(assert (= false (ct-eval ctx "(or nil false)")) "or nil false -> false")
(assert (= false (ct-eval ctx "(or nil nil nil false)")) "or chain to false")
(assert (= true (ct-eval ctx "(or nil true false)")) "or nil true false"))
(print " ok")
# --- test-not ---
(print "test-not...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
(assert (= true (ct-eval ctx "(not false)")) "not false")
(assert (= false (ct-eval ctx "(not true)")) "not true")
(assert (= false (ct-eval ctx "(not 0)")) "not 0")
(assert (= false (ct-eval ctx "(not 0.0)")) "not 0.0")
(assert (= false (ct-eval ctx "(not 42)")) "not 42")
(assert (= false (ct-eval ctx "(not 1.2)")) "not 1.2")
(assert (= false (ct-eval ctx "(not \"\")")) "not empty string")
(assert (= false (ct-eval ctx "(not \"abc\")")) "not string")
(assert (= false (ct-eval ctx "(not 'abc)")) "not symbol")
(assert (= false (ct-eval ctx "(not :kw)")) "not keyword")
(assert (= false (ct-eval ctx "(not ())")) "not empty list")
(assert (= false (ct-eval ctx "(not '(1 2))")) "not list")
(assert (= false (ct-eval ctx "(not []))")) "not empty vector")
(assert (= false (ct-eval ctx "(not [1 2])")) "not vector")
(assert (= false (ct-eval ctx "(not {})")) "not empty map")
(assert (= false (ct-eval ctx "(not {:a 1 :b 2})")) "not map")
(assert (= false (ct-eval ctx "(not #{})")) "not empty set")
(assert (= false (ct-eval ctx "(not #{1 2})")) "not set"))
(print " ok")
# --- test-some? ---
(print "test-some?...")
(let [ctx (init)]
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
(assert (= true (ct-eval ctx "(some? \"abc\")")) "some? string")
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec"))
(print " ok")
(print "\nAll Ported Logic tests passed!")

View file

@ -0,0 +1,63 @@
# Ported from clojure/test_clojure/macros.clj
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported Macros Tests")
# --- -> and ->> threading ---
(print "test -> and ->>...")
(let [ctx (init)]
(ct-eval ctx "(defmacro c [arg] (if (= 'b (first arg)) :foo :bar))")
(ct-eval ctx "(def a 2)")
(ct-eval ctx "(def b identity)")
(assert (= :foo (ct-eval ctx "(-> a b c)")) "-> threading")
(assert (= :foo (ct-eval ctx "(->> a b c)")) "->> threading"))
(print " ok")
# --- some-> ---
(print "test some->...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(some-> nil)")) "some-> nil")
(assert (= 0 (ct-eval ctx "(some-> 0)")) "some-> 0")
(assert (= -1 (ct-eval ctx "(some-> 1 (- 2))")) "some-> with form")
(ct-eval ctx "(defn const-nil [_] nil)")
(assert (= nil (ct-eval ctx "(some-> 1 const-nil (- 2))")) "some-> stop at nil"))
(print " ok")
# --- some->> ---
(print "test some->>...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(some->> nil)")) "some->> nil")
(assert (= 0 (ct-eval ctx "(some->> 0)")) "some->> 0")
(assert (= 1 (ct-eval ctx "(some->> 1 (- 2))")) "some->> with form")
(ct-eval ctx "(defn const-nil2 [_] nil)")
(assert (= nil (ct-eval ctx "(some->> 1 const-nil2 (- 2))")) "some->> stop at nil"))
(print " ok")
# --- cond-> ---
(print "test cond->...")
(let [ctx (init)]
(assert (= 0 (ct-eval ctx "(cond-> 0)")) "cond-> single")
(assert (= -1 (ct-eval ctx "(cond-> 0 true inc true (- 2))")) "cond-> with tests")
(assert (= 0 (ct-eval ctx "(cond-> 0 false inc)")) "cond-> false test")
(assert (= -1 (ct-eval ctx "(cond-> 1 true (- 2) false inc)")) "cond-> mix"))
(print " ok")
# --- cond->> ---
(print "test cond->>...")
(let [ctx (init)]
(assert (= 0 (ct-eval ctx "(cond->> 0)")) "cond->> single")
(assert (= 1 (ct-eval ctx "(cond->> 0 true inc true (- 2))")) "cond->> with tests")
(assert (= 0 (ct-eval ctx "(cond->> 0 false inc)")) "cond->> false test")
(assert (= 1 (ct-eval ctx "(cond->> 1 true (- 2) false inc)")) "cond->> mix"))
(print " ok")
# --- as-> ---
(print "test as->...")
(let [ctx (init)]
(assert (= 0 (ct-eval ctx "(as-> 0 x)")) "as-> single")
(assert (= 1 (ct-eval ctx "(as-> 0 x (inc x))")) "as-> one form")
(assert (= 2 (ct-eval ctx "(as-> [0 1] x (map inc x) (reverse x) (first x))")) "as-> chain"))
(print " ok")
(print "\nAll Ported Macros tests passed!")

View file

@ -0,0 +1,325 @@
# Clojure conformance harness (phase 1: extracted assertion pairs).
#
# Each case is [name expected-clj actual-clj]. The harness evaluates the
# single Clojure program (= <expected> <actual>) inside a fresh jolt ctx
# and asserts it returns boolean true. Comparison therefore uses jolt's OWN
# `=`, which implements Clojure sequential/collection equality -- so results
# reflect real Clojure semantics rather than Janet-level identity.
#
# `actual` may be a multi-form body; wrap such cases in (do ...).
#
# Source of truth: ~/src/clojure/test/clojure/test_clojure/*.clj
# These pairs are hand-extracted from those files (and canonical idioms)
# until a minimal clojure.test lets us load the real files directly.
(use ../../src/jolt/api)
(def cases
[
### ---- CRITICAL: lazy sequences ----
["self-ref lazy-cat fib"
"(quote (0 1 1 2 3 5 8 13 21 34))"
"(do (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))) (take 10 fib-seq))"]
["self-ref lazy-seq ones"
"(quote (1 1 1 1 1))"
"(do (def ones (lazy-seq (cons 1 ones))) (take 5 ones))"]
["self-ref lazy-seq nats"
"(quote (0 1 2 3 4))"
"(do (def nats (lazy-cat [0] (map inc nats))) (take 5 nats))"]
### ---- CRITICAL: multi-collection map ----
["map two colls" "(quote (11 22 33))" "(map + [1 2 3] [10 20 30])"]
["map three colls" "(quote (12 24 36))" "(map + [1 2 3] [10 20 30] [1 2 3])"]
["map uneven (shortest)" "(quote ([1 :a] [2 :b]))" "(map vector [1 2 3] [:a :b])"]
["map over range+vec" "(quote (1 3 5))" "(map + (range 3) [1 2 3])"]
["map fn list arg" "(quote (2 3 4))" "(map inc (list 1 2 3))"]
### ---- CRITICAL: iterate / infinite seqs ----
["iterate" "(quote (0 1 2 3 4))" "(take 5 (iterate inc 0))"]
["iterate double" "(quote (1 2 4 8 16))" "(take 5 (iterate (fn [x] (* 2 x)) 1))"]
["range over inf map" "(quote (1 2 3))" "(take 3 (map inc (range)))"]
["count of take" "100" "(count (take 100 (range)))"]
["last of take" "5" "(last (take 5 (iterate inc 1)))"]
### ---- CRITICAL: collections as IFn ----
["vector as fn" ":b" "([:a :b :c] 1)"]
["map as fn" "1" "({:a 1} :a)"]
["map as fn miss" "nil" "({:a 1} :z)"]
["map as fn default" "99" "({:a 1} :z 99)"]
["set as fn" "2" "(#{1 2 3} 2)"]
["set as fn miss" "nil" "(#{1 2 3} 9)"]
["keyword as fn" "1" "(:a {:a 1})"]
["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]
### ---- CRITICAL: vec / into over lazy + maps ----
["vec of map-result" "[2 3 4]" "(vec (map inc [1 2 3]))"]
["vec of range" "[0 1 2 3 4]" "(vec (range 5))"]
["into vec" "[1 2 3 4 5 6]" "(into [1 2 3] [4 5 6])"]
["into vec from lazy" "[2 3 4]" "(into [] (map inc [1 2 3]))"]
["into map pairs" "{:a 1 :b 2}" "(into {} [[:a 1] [:b 2]])"]
["into map onto map" "{:a 1 :b 2 :c 3}" "(into {:a 1} [[:b 2] [:c 3]])"]
["into list" "(quote (3 2 1))" "(into (list) [1 2 3])"]
### ---- HIGH: destructuring ----
["destr nested seq" "[1 2 3]" "(let [[a [b c]] [1 [2 3]]] [a b c])"]
["destr rest+as" "[1 (quote (2 3)) [1 2 3]]" "(let [[a & r :as all] [1 2 3]] [a r all])"]
["destr map :keys" "[1 2]" "(let [{:keys [a b]} {:a 1 :b 2}] [a b])"]
["destr map :or" "[1 99]" "(let [{:keys [a b] :or {b 99}} {:a 1}] [a b])"]
["destr map :strs" "[1 2]" "(let [{:strs [a b]} {\"a\" 1 \"b\" 2}] [a b])"]
["destr map :as" "[1 {:a 1}]" "(let [{:keys [a] :as m} {:a 1}] [a m])"]
["destr nested map" "5" "(let [{{:keys [x]} :pos} {:pos {:x 5}}] x)"]
["destr fn-param seq" "7" "((fn [[a b]] (+ a b)) [3 4])"]
["destr fn-param map" "3" "((fn [{:keys [a b]}] (+ a b)) {:a 1 :b 2})"]
["destr let map key" "1" "(let [{a :a} {:a 1}] a)"]
### ---- HIGH: update / assoc-in on map literals ----
["update inc" "{:a 2}" "(update {:a 1} :a inc)"]
["update extra args" "{:a 111}" "(update {:a 1} :a + 10 100)"]
["update-in" "{:a {:b 2}}" "(update-in {:a {:b 1}} [:a :b] inc)"]
["assoc-in" "{:a {:b 1 :c 2}}" "(assoc-in {:a {:b 1}} [:a :c] 2)"]
["assoc-in create" "{:a {:b 1}}" "(assoc-in {} [:a :b] 1)"]
["update-in fnil" "{:a {:b 1}}" "(update-in {} [:a :b] (fnil inc 0))"]
["get-in" "1" "(get-in {:a {:b {:c 1}}} [:a :b :c])"]
### ---- HIGH: str semantics ----
["str nil empty" "\"\"" "(str nil)"]
["str concat nil" "\"a1\"" "(str \"a\" 1 nil)"]
["str keyword" "\":b\"" "(str :b)"]
["str symbol" "\"foo\"" "(str (quote foo))"]
["str mixed" "\"a:b1\"" "(str \"a\" :b 1)"]
["str seq" "\"[1 2 3]\"" "(str [1 2 3])"]
### ---- HIGH: dispatch ----
["multimethod" "9" "(do (defmulti area :shape) (defmethod area :sq [s] (* (:s s) (:s s))) (area {:shape :sq :s 3}))"]
["multimethod default" ":def" "(do (defmulti f identity) (defmethod f :default [x] :def) (f 99))"]
["protocol on record" "16" "(do (defprotocol Sh (ar [s])) (defrecord Sq [side] Sh (ar [_] (* side side))) (ar (->Sq 4)))"]
["reify dispatch" "42" "(do (defprotocol P (m [_])) (m (reify P (m [_] 42))))"]
### ---- HIGH: aliased namespace calls ----
["require :as alias" "\"1,2,3\"" "(do (require (quote [clojure.string :as s])) (s/join \",\" [1 2 3]))"]
### ---- MED: missing core fns ----
["peek vec" "3" "(peek [1 2 3])"]
["peek list" "1" "(peek (list 1 2 3))"]
["pop vec" "[1 2]" "(pop [1 2 3])"]
["pop list" "(quote (2 3))" "(pop (list 1 2 3))"]
["subvec" "[2 3]" "(subvec [1 2 3 4 5] 1 3)"]
["subvec to-end" "[3 4 5]" "(subvec [1 2 3 4 5] 2)"]
["reduce-kv" "{:a 2 :b 3}" "(reduce-kv (fn [m k v] (assoc m k (inc v))) {} {:a 1 :b 2})"]
### ---- iterating maps yields entries ----
["map over map" "true" "(= #{1 2} (set (map val {:a 1 :b 2})))"]
["map keys over map" "true" "(= #{:a :b} (set (map key {:a 1 :b 2})))"]
["first of map" "true" "(let [e (first {:a 1})] (and (= (key e) :a) (= (val e) 1)))"]
["vec of map" "[[:a 1]]" "(vec {:a 1})"]
["reduce over map" "6" "(reduce (fn [a [k v]] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
["into transform map" "{:a 2 :b 3}" "(into {} (map (fn [[k v]] [k (inc v)]) {:a 1 :b 2}))"]
["filter over map" "true" "(= [[:b 2]] (filterv (fn [[k v]] (> v 1)) {:a 1 :b 2}))"]
["doall realizes" "(quote (2 3 4))" "(doall (map inc [1 2 3]))"]
["tree-seq" "(quote (1 2 3))" "(map (fn [x] x) (filter (complement coll?) (tree-seq coll? seq [1 [2 [3]]])))"]
["key/val" "true" "(let [e [:k 9]] (and (= :k (key e)) (= 9 (val e))))"]
["nat-int?" "true" "(and (nat-int? 0) (nat-int? 5) (not (nat-int? -1)))"]
["list* prepend" "(quote (1 2 3 4))" "(list* 1 2 [3 4])"]
["cycle" "(quote (1 2 3 1 2 3 1))" "(take 7 (cycle [1 2 3]))"]
["partition-all" "(quote ((1 2) (3 4) (5)))" "(partition-all 2 [1 2 3 4 5])"]
["reductions" "(quote (1 3 6 10))" "(reductions + [1 2 3 4])"]
["reductions init" "(quote (0 1 3 6))" "(reductions + 0 [1 2 3])"]
["dedupe" "(quote (1 2 3 1))" "(dedupe [1 1 2 3 3 1])"]
["keep-indexed" "(quote (:b :d))" "(keep-indexed (fn [i x] (if (odd? i) x)) [:a :b :c :d])"]
["map-indexed" "(quote ([0 :a] [1 :b]))" "(map-indexed (fn [i x] [i x]) [:a :b])"]
["trampoline" ":done" "(do (defn a [n] (if (zero? n) :done (fn [] (a (dec n))))) (trampoline a 5))"]
["format" "\"1-x\"" "(format \"%d-%s\" 1 \"x\")"]
["read-string" "(quote (+ 1 2))" "(read-string \"(+ 1 2)\")"]
["letfn mutual" "true" "(letfn [(ev? [n] (if (= n 0) true (od? (dec n)))) (od? [n] (if (= n 0) false (ev? (dec n))))] (ev? 10))"]
["doseq side" "[1 2 3]" "(do (def a (atom [])) (doseq [x [1 2 3]] (swap! a conj x)) @a)"]
["doseq nested" "4" "(do (def c (atom 0)) (doseq [x [1 2] y [10 20]] (swap! c inc)) @c)"]
### ---- MED: lazy filter / take-while over infinite seqs ----
["lazy filter inf" "(quote (1 3 5 7 9))" "(take 5 (filter odd? (range)))"]
["lazy take-while inf" "(quote (0 1 2 3 4))" "(take-while (fn [x] (< x 5)) (range))"]
["lazy remove inf" "(quote (0 2 4 6 8))" "(take 5 (remove odd? (range)))"]
["filter finite" "(quote (2 4))" "(filter even? [1 2 3 4 5])"]
### ==== atoms (full support) ====
["swap! args" "7" "(do (def a (atom 1)) (swap! a + 2 4) @a)"]
["reset! ret" "9" "(do (def a (atom 1)) (reset! a 9))"]
["compare-and-set!" "true" "(do (def a (atom 1)) (compare-and-set! a 1 2))"]
["compare-and-set! no" "false" "(do (def a (atom 1)) (compare-and-set! a 5 2))"]
["swap-vals!" "[1 2]" "(do (def a (atom 1)) (swap-vals! a inc))"]
["reset-vals!" "[1 9]" "(do (def a (atom 1)) (reset-vals! a 9))"]
["atom map swap" "{:a 1 :b 2}" "(do (def a (atom {:a 1})) (swap! a assoc :b 2) @a)"]
["add-watch" "[:k 1 2]" "(do (def lg (atom nil)) (def a (atom 1)) (add-watch a :k (fn [k r o n] (reset! lg [k o n]))) (swap! a inc) @lg)"]
["atom validator" "5" "(do (def a (atom 1 :validator pos?)) (reset! a 5) @a)"]
["instance? Atom" "true" "(instance? clojure.lang.Atom (atom 1))"]
### ==== volatiles / delays ====
["volatile" "2" "(do (def v (volatile! 1)) (vreset! v 2) @v)"]
["vswap!" "2" "(do (def v (volatile! 1)) (vswap! v inc) @v)"]
["volatile?" "true" "(volatile? (volatile! 1))"]
["delay force" "3" "(force (delay (+ 1 2)))"]
["delay deref once" "1" "(do (def c (atom 0)) (def d (delay (swap! c inc))) @d @d @c)"]
["realized? delay" "true" "(do (def d (delay 1)) @d (realized? d))"]
["realized? not" "false" "(realized? (delay 1))"]
### ==== numbers / math ====
["quot neg" "-2" "(quot -7 3)"]
["rem neg" "-1" "(rem -7 3)"]
["mod neg" "2" "(mod -7 3)"]
["bit ops" "[4 14 10]" "[(bit-and 12 6) (bit-or 12 6) (bit-xor 12 6)]"]
["bit-shift" "[8 2]" "[(bit-shift-left 1 3) (bit-shift-right 8 2)]"]
["Math/sqrt" "3.0" "(Math/sqrt 9)"]
["Math/pow" "8.0" "(Math/pow 2 3)"]
["min-key" "1" "(min-key abs 1 -2 3)"]
["max-key" "-4" "(max-key abs 1 -2 -4 3)"]
### ==== strings (clojure.string) ====
["str/trim" "\"hi\"" "(do (require (quote [clojure.string :as s])) (s/trim \" hi \"))"]
["str/split regex" "[\"a\" \"b\" \"c\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,b,c\" #\",\"))"]
["str/split ws" "[\"a\" \"b\" \"c\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a b c\" #\"\\s+\"))"]
["str/replace" "\"hexxo\"" "(do (require (quote [clojure.string :as s])) (s/replace \"hello\" \"ll\" \"xx\"))"]
["str/replace regex" "\"ab\"" "(do (require (quote [clojure.string :as s])) (s/replace \"a1b2\" #\"[0-9]\" \"\"))"]
["str/includes?" "true" "(do (require (quote [clojure.string :as s])) (s/includes? \"hello\" \"ell\"))"]
["str/reverse" "\"cba\"" "(do (require (quote [clojure.string :as s])) (s/reverse \"abc\"))"]
["subs" "\"ell\"" "(subs \"hello\" 1 4)"]
### ==== regex ====
["re-find" "\"123\"" "(re-find #\"[0-9]+\" \"abc123def\")"]
["re-matches" "\"abc\"" "(re-matches #\"a.c\" \"abc\")"]
["re-matches no" "nil" "(re-matches #\"a.c\" \"abcd\")"]
["re-seq" "(quote (\"12\" \"34\"))" "(re-seq #\"[0-9]+\" \"a12b34\")"]
### ==== sequences ====
["split-at" "[[1 2] [3 4 5]]" "(split-at 2 [1 2 3 4 5])"]
["split-with" "[[1 2] [3 4 1]]" "(split-with (fn [x] (< x 3)) [1 2 3 4 1])"]
["interpose" "(quote (1 0 2 0 3))" "(interpose 0 [1 2 3])"]
["partition step" "(quote ((1 2) (3 4)))" "(partition 2 2 [1 2 3 4 5])"]
["not-every?" "true" "(not-every? pos? [1 -2 3])"]
["not-any?" "true" "(not-any? neg? [1 2 3])"]
["take-nth" "(quote (0 2 4))" "(take-nth 2 [0 1 2 3 4])"]
["butlast" "(quote (1 2))" "(butlast [1 2 3])"]
["filterv" "[2 4]" "(filterv even? [1 2 3 4])"]
["mapv" "[2 3 4]" "(mapv inc [1 2 3])"]
["reduced early" "3" "(reduce (fn [a x] (if (> a 2) (reduced a) (+ a x))) 0 [1 2 3 4 5])"]
["sort cmp" "[3 2 1]" "(sort > [1 3 2])"]
["frequencies" "{1 2 2 1}" "(frequencies [1 1 2])"]
["empty" "[]" "(empty [1 2 3])"]
["not-empty" "nil" "(not-empty [])"]
["rseq" "(quote (3 2 1))" "(rseq [1 2 3])"]
["replace map" "[:a :b :a]" "(replace {1 :a 2 :b} [1 2 1])"]
### ==== data structures ====
["sorted-map seq" "(quote ([:a 1] [:b 2] [:c 3]))" "(seq (sorted-map :c 3 :a 1 :b 2))"]
["sorted-set seq" "(quote (1 2 3))" "(seq (sorted-set 3 1 2))"]
["assoc vector" "[1 9 3]" "(assoc [1 2 3] 1 9)"]
["update vector" "[1 3 3]" "(update [1 2 3] 1 inc)"]
["coll? set" "true" "(coll? #{1 2})"]
["find entry" "[:a 1]" "(find {:a 1} :a)"]
["conj map entry" "{:a 1 :b 2}" "(conj {:a 1} [:b 2])"]
["conj list prepend" "(quote (0 1 2))" "(conj (list 1 2) 0)"]
### ==== keywords / symbols ====
["keyword ns" ":a/b" "(keyword \"a\" \"b\")"]
["name ns-kw" "\"b\"" "(name :a/b)"]
["namespace" "\"a\"" "(namespace :a/b)"]
["namespace none" "nil" "(namespace :a)"]
### ==== metadata / vars ====
["vary-meta" "{:x 2}" "(meta (vary-meta (with-meta [1] {:x 1}) update :x inc))"]
["defonce no-redef" "1" "(do (defonce dv1 1) (defonce dv1 2) dv1)"]
["binding dynamic" "10" "(do (def ^:dynamic *x* 1) (binding [*x* 10] *x*))"]
### ==== try / catch ====
["try catch" ":caught" "(try (throw (ex-info \"e\" {})) (catch :default e :caught))"]
["ex-data" "{:a 1}" "(try (throw (ex-info \"m\" {:a 1})) (catch :default e (ex-data e)))"]
["ex-message" "\"m\"" "(try (throw (ex-info \"m\" {})) (catch :default e (ex-message e)))"]
### ==== macros ====
["macroexpand-1" "true" "(do (defmacro mm [x] (list (quote inc) x)) (= (quote (inc 5)) (macroexpand-1 (quote (mm 5)))))"]
["doto" "{:a 1}" "(deref (doto (atom {}) (swap! assoc :a 1)))"]
### ==== printing ====
["pr-str vec" "\"[1 2 3]\"" "(pr-str [1 2 3])"]
["prn-str" "\"1\\n\"" "(prn-str 1)"]
### ==== characters ====
["char?" "true" "(char? \\a)"]
["char not string" "false" "(= \\a \"a\")"]
["char eq" "true" "(= \\a \\a)"]
["int of char" "97" "(int \\a)"]
["char of int" "true" "(= \\A (char 65))"]
["str of chars" "\"abc\"" "(str \\a \\b \\c)"]
["seq of string" "(quote (\\a \\b))" "(seq \"ab\")"]
["first of string" "\\h" "(first \"hello\")"]
["nth of string" "\\e" "(nth \"hello\" 1)"]
["char newline" "10" "(int \\newline)"]
["char space" "32" "(int \\space)"]
["char unicode" "65" "(int \\u0041)"]
["pr-str char" "\"\\\\a\"" "(pr-str \\a)"]
["chars in vec" "[\\a \\b]" "[\\a \\b]"]
["apply str chars" "\"hi\"" "(apply str [\\h \\i])"]
### ==== transducers ====
["transduce map" "9" "(transduce (map inc) + 0 [1 2 3])"]
["transduce comp" "12" "(transduce (comp (map inc) (filter even?)) + 0 [1 2 3 4 5])"]
["transduce conj" "[2 3 4]" "(transduce (map inc) conj [] [1 2 3])"]
["into xform" "[2 3 4]" "(into [] (map inc) [1 2 3])"]
["into comp xform" "[1 9 25]" "(into [] (comp (filter odd?) (map (fn [x] (* x x)))) [1 2 3 4 5])"]
["into take xform" "[0 1 2]" "(into [] (take 3) (range 100))"]
["sequence xform" "(quote (2 3 4))" "(sequence (map inc) [1 2 3])"]
["transduce no-init" "6" "(transduce (map inc) + [0 1 2])"]
["transduce drop" "[3 4 5]" "(into [] (drop 2) [1 2 3 4 5])"]
["transduce remove" "[1 3 5]" "(into [] (remove even?) [1 2 3 4 5])"]
["transduce take-while" "[1 2]" "(into [] (take-while (fn [x] (< x 3))) [1 2 3 4 1])"]
["transduce map-indexed" "[[0 :a] [1 :b]]" "(into [] (map-indexed (fn [i x] [i x])) [:a :b])"]
### ==== regex (capturing groups, backtracking, flags, lookahead) ====
["re-find groups" "[\"12-34\" \"12\" \"34\"]" "(re-find #\"(\\d+)-(\\d+)\" \"x12-34y\")"]
["re-find no-groups" "\"123\"" "(re-find #\"\\d+\" \"ab123\")"]
["re-matches groups" "[\"1.2\" \"1\" \"2\"]" "(re-matches #\"(\\d+)\\.(\\d+)\" \"1.2\")"]
["re-matches no" "nil" "(re-matches #\"a.c\" \"abcd\")"]
["re-seq" "[\"foo\" \"bar\"]" "(re-seq #\"\\w+\" \"foo bar\")"]
["greedy backtrack" "\"xxfoo\"" "(re-find #\".*foo\" \"xxfoo\")"]
["greedy thru group" "[\"a,b,c\" \"a,b\" \"c\"]" "(re-find #\"(.*),(.*)\" \"a,b,c\")"]
["lazy quantifier" "[\"<a>\" \"a\"]" "(re-find #\"<(.+?)>\" \"<a><b>\")"]
["flag case-insens" "\"CAT\"" "(re-find #\"(?i)cat\" \"a CAT\")"]
["lookahead" "\"foo\"" "(re-find #\"foo(?=bar)\" \"foobar\")"]
["neg-lookahead" "\"foo\"" "(re-find #\"foo(?!bar)\" \"foobaz\")"]
["word-boundary" "\"word\"" "(re-find #\"\\bword\\b\" \"a word!\")"]
["word-boundary no" "nil" "(re-find #\"\\bword\\b\" \"swordfish\")"]
["optional group" "[\"1.2.3\" \"1\" \"2\" \"3\" nil]" "(re-find #\"(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-z]+))?\" \"1.2.3\")"]
["alternation" "\"dog\"" "(re-find #\"cat|dog\" \"a dog cat\")"]
["str/replace $1" "\"he[ll]o\"" "(do (require (quote [clojure.string :as s])) (s/replace \"hello\" #\"(l+)\" \"[$1]\"))"]
["str/replace regex" "\"X-X\"" "(do (require (quote [clojure.string :as s])) (s/replace \"a-b\" #\"[a-z]\" \"X\"))"]
### ==== map literals evaluate their values ====
["map literal expr" "{:a 3}" "{:a (+ 1 2)}"]
["map literal var" "{:k 5}" "(let [x 5] {:k x})"]
["map literal nested" "{:a {:b 2}}" "(let [y 2] {:a {:b y}})"]
["map literal keyfn" "{:x 1}" "(let [k :x] {k 1})"]
["map literal in fn" "6" "(do (defn mk [a b] {:sum (+ a b)}) (:sum (mk 2 4)))"]
])
(var pass 0)
(def fails @[])
(each [name expected actual] cases
(def ctx (init))
(def prog (string "(= " expected " " actual ")"))
(def res (protect (eval-string ctx prog)))
(cond
(not= (res 0) true)
(array/push fails [name "ERROR" (string (res 1))])
(= (res 1) true)
(++ pass)
# not equal: re-eval actual alone to show what we got
(let [got (protect (eval-string (init) actual))]
(array/push fails [name "MISMATCH"
(string "want=" expected
" got=" (if (= (got 0) true) (string/format "%q" (got 1)) (string "ERR:" (got 1))))]))))
(printf "\n=== CONFORMANCE: %d/%d passed ===" pass (length cases))
(unless (empty? fails)
(print "\n--- Failures ---")
(each [name kind detail] fails
(printf "[%s] %s: %s" kind name detail)))
(print)
(when (pos? (length fails)) (os/exit 1))

View file

@ -0,0 +1,122 @@
(use ../../src/jolt/types)
(use ../../src/jolt/pv)
(use ../../src/jolt/plist)
(use ../../src/jolt/reader)
(use ../../src/jolt/evaluator)
(use ../../src/jolt/core)
# Normalize jolt collection results to Janet tuples so Janet-level deep=/= can
# compare against tuple literals regardless of the (pvec/plist) representation.
(defn norm [x]
(cond
(pvec? x) (tuple ;(map norm (pv->array x)))
(plist? x) (tuple ;(map norm (pl->array x)))
(tuple? x) (tuple ;(map norm x))
(array? x) (tuple ;(map norm x))
x))
# Helper: create a fresh bootstrapped context
(defn make-boot-ctx []
(let [ctx (make-ctx)]
(init-core! ctx)
ctx))
# Helper: parse + eval
(defn eval-str [ctx s]
(let [form (parse-string s)]
(norm (eval-form ctx @{} form))))
(print "1: predicates...")
(let [ctx (make-boot-ctx)]
(assert (= true (eval-str ctx "(nil? nil)")) "nil?")
(assert (= false (eval-str ctx "(nil? 1)")) "nil? false")
(assert (= true (eval-str ctx "(string? \"hello\")")) "string?")
(assert (= true (eval-str ctx "(number? 42)")) "number?")
(assert (= true (eval-str ctx "(fn? inc)")) "fn?")
(assert (= true (eval-str ctx "(keyword? :foo)")) "keyword?")
(assert (= false (eval-str ctx "(keyword? 1)")) "keyword? false")
(assert (= true (eval-str ctx "(zero? 0)")) "zero?")
(assert (= true (eval-str ctx "(pos? 1)")) "pos?")
(assert (= true (eval-str ctx "(neg? -1)")) "neg?")
(assert (= true (eval-str ctx "(even? 2)")) "even?")
(assert (= true (eval-str ctx "(odd? 1)")) "odd?")
(assert (= true (eval-str ctx "(empty? [])")) "empty? vector")
(assert (= false (eval-str ctx "(empty? [1])")) "empty? non-empty"))
(print " passed")
(print "2: math...")
(let [ctx (make-boot-ctx)]
(assert (= 0 (eval-str ctx "(+)")) "+ 0 args")
(assert (= 5 (eval-str ctx "(+ 2 3)")) "+ 2 args")
(assert (= 10 (eval-str ctx "(+ 1 2 3 4)")) "+ varargs")
(assert (= -5 (eval-str ctx "(- 5)")) "- unary")
(assert (= 2 (eval-str ctx "(- 5 3)")) "- binary")
(assert (= 6 (eval-str ctx "(* 2 3)")) "*")
(assert (= 1 (eval-str ctx "(*)")) "* 0 args")
(assert (= 42 (eval-str ctx "(inc 41)")) "inc")
(assert (= 40 (eval-str ctx "(dec 41)")) "dec")
(assert (= 4 (eval-str ctx "(max 1 4 2)")) "max"))
(print " passed")
(print "3: comparison...")
(let [ctx (make-boot-ctx)]
(assert (= true (eval-str ctx "(= 1 1)")) "= same")
(assert (= false (eval-str ctx "(= 1 2)")) "= diff")
(assert (= true (eval-str ctx "(= 1 1 1)")) "= multi same")
(assert (= false (eval-str ctx "(= 1 2 1)")) "= multi diff")
(assert (= true (eval-str ctx "(not= 1 2)")) "not="))
(print " passed")
(print "4: collections...")
(let [ctx (make-boot-ctx)]
(assert (= 3 (eval-str ctx "(count [1 2 3])")) "count vector")
(assert (= 1 (eval-str ctx "(first [1 2 3])")) "first")
(assert (deep= [2 3] (eval-str ctx "(rest [1 2 3])")) "rest")
(assert (= nil (eval-str ctx "(next [1])")) "next singleton")
(assert (deep= [1 2 3] (eval-str ctx "(conj [1 2] 3)")) "conj vector")
(assert (= 1 (eval-str ctx "(get {:a 1} :a)")) "get map")
(assert (= 2 (eval-str ctx "(get [1 2 3] 1)")) "get vector")
(assert (= :default (eval-str ctx "(get {:a 1} :b :default)")) "get default")
(assert (deep= {:a 1 :c 3} (eval-str ctx "(assoc {:a 1} :c 3)")) "assoc")
(assert (deep= {:a 1} (eval-str ctx "(dissoc {:a 1 :b 2} :b)")) "dissoc"))
(print " passed")
(print "5: seq ops...")
(let [ctx (make-boot-ctx)]
(assert (deep= [2 3 4] (eval-str ctx "(map inc [1 2 3])")) "map")
(assert (deep= [2 4] (eval-str ctx "(filter even? [1 2 3 4])")) "filter")
(assert (= 6 (eval-str ctx "(reduce + [1 2 3])")) "reduce")
(assert (= 10 (eval-str ctx "(reduce + 4 [1 2 3])")) "reduce with val")
(assert (deep= [1 2] (eval-str ctx "(take 2 [1 2 3 4])")) "take")
(assert (deep= [3 4] (eval-str ctx "(drop 2 [1 2 3 4])")) "drop")
(assert (deep= [1 2] (eval-str ctx "(take-while (fn* [x] (<= x 2)) [1 2 3 4])")) "take-while"))
(print " passed")
(print "6: range...")
(let [ctx (make-boot-ctx)]
(assert (deep= [0 1 2 3 4] (eval-str ctx "(range 5)")) "range end")
(assert (deep= [2 3 4] (eval-str ctx "(range 2 5)")) "range start end"))
(print " passed")
(print "7: higher-order...")
(let [ctx (make-boot-ctx)]
(assert (= 42 (eval-str ctx "(identity 42)")) "identity")
(assert (= 42 (eval-str ctx "(let* [f (constantly 42)] (f))")) "constantly")
(assert (= 3 (eval-str ctx "(let* [f (comp inc inc)] (f 1))")) "comp")
(assert (deep= [2 0] (eval-str ctx "(let* [f (juxt inc dec)] (f 1))")) "juxt"))
(print " passed")
(print "8: str...")
(let [ctx (make-boot-ctx)]
(assert (= "hello" (eval-str ctx "(str \"hello\")")) "str")
(assert (= "hello42" (eval-str ctx "(str \"hello\" 42)")) "str concat"))
(print " passed")
(print "9: atom...")
(let [ctx (make-boot-ctx)]
(assert (= 1 (eval-str ctx "(let* [a (atom 1)] (deref a))")) "atom + deref")
(assert (= 42 (eval-str ctx "(let* [a (atom 1)] (reset! a 42) (deref a))")) "reset!")
(assert (= 2 (eval-str ctx "(let* [a (atom 1)] (swap! a inc) (deref a))")) "swap!"))
(print " passed")
(print "\nAll core tests passed!")

View file

@ -0,0 +1,153 @@
# Regression tests mirroring clojure-features.clj, plus expanded coverage of
# related features. Each case asserts (= expected actual) evaluated inside Jolt
# (so comparisons use Jolt's own Clojure-semantics =). Run via `jpm test`.
(use ../../src/jolt/api)
(var pass 0)
(def fails @[])
(defn check [label expected actual]
# evaluate (= expected actual) in a fresh ctx; expects boolean true
(def ctx (init))
(def res (protect (eval-string ctx (string "(= " expected " " actual ")"))))
(cond
(not= (res 0) true)
(array/push fails [label "ERROR" (string (res 1))])
(= (res 1) true)
(++ pass)
(let [got (protect (eval-string (init) actual))]
(array/push fails [label "NEQ"
(string "want=" expected " got="
(if (= (got 0) true) (string/format "%q" (got 1)) (string "ERR:" (got 1))))]))))
(def cases
[
### 1. Destructuring
["destr seq" "[10 20 30]" "(let [[a b c] [10 20 30]] [a b c])"]
["destr map :or" "[\"Alice\" 30 \"Unknown\"]"
"(let [{:keys [name age city] :or {city \"Unknown\"}} {:name \"Alice\" :age 30}] [name age city])"]
["destr nested map" "[1.0 2.5]" "(let [{[x y] :coords} {:coords [1.0 2.5]}] [x y])"]
["destr :as" "[1 [1 2 3]]" "(let [[a :as all] [1 2 3]] [a all])"]
["destr & rest" "[1 (quote (2 3))]" "(let [[a & r] [1 2 3]] [a r])"]
["destr :strs" "[1 2]" "(let [{:strs [a b]} {\"a\" 1 \"b\" 2}] [a b])"]
["destr fn-param" "7" "((fn [{:keys [a b]}] (+ a b)) {:a 3 :b 4})"]
### 2. Atoms
["atom swap! inc" "1" "(do (def a (atom 0)) (swap! a inc) @a)"]
["atom reset!" "100" "(do (def a (atom 0)) (reset! a 100) @a)"]
["atom CAS ok" "true" "(do (def a (atom 5)) (compare-and-set! a 5 10))"]
["atom CAS no" "false" "(do (def a (atom 5)) (compare-and-set! a 9 10))"]
["atom thread-first swap!" "213" "(do (def a (atom 100)) (swap! a #(-> % (* 2) (+ 3))) (swap! a #(-> % (* 1) (+ 10))) @a)"]
["atom swap! args" "10" "(do (def a (atom 1)) (swap! a + 2 3 4) @a)"]
["atom swap-vals!" "[1 2]" "(do (def a (atom 1)) (swap-vals! a inc))"]
["atom watch" "[1 2]" "(do (def lg (atom nil)) (def a (atom 1)) (add-watch a :k (fn [k r o n] (reset! lg [o n]))) (swap! a inc) @lg)"]
["atom validator" "5" "(do (def a (atom 1 :validator pos?)) (reset! a 5) @a)"]
### 3. Lazy sequences
["lazy filter inf" "(quote (0 2 4 6 8 10 12 14 16 18))" "(take 10 (filter even? (iterate inc 0)))"]
["lazy take-while sq" "(quote (0 1 4 9 16 25 36 49))" "(take-while #(< % 50) (map #(* % %) (range)))"]
["lazy cycle" "(quote (:a :b :c :a :b :c :a :b :c :a))" "(take 10 (cycle [:a :b :c]))"]
["lazy-seq cons self" "(quote (1 2 4 8 16 32 64 128))"
"(do (defn my-it [f x] (lazy-seq (cons x (my-it f (f x))))) (take 8 (my-it #(* 2 %) 1)))"]
["lazy self-ref fib" "(quote (0 1 1 2 3 5 8 13 21 34))"
"(do (def fib (lazy-cat [0 1] (map + (rest fib) fib))) (take 10 fib))"]
["repeatedly" "(quote (1 1 1))" "(repeatedly 3 (fn [] 1))"]
["range step" "(quote (0 2 4 6 8))" "(range 0 10 2)"]
### 4. Transducers
["xf comp into" "[1 3 5 7 9]" "(into [] (comp (map inc) (filter odd?)) (range 10))"]
["xf sequence" "(quote (1 3 5 7 9))" "(sequence (comp (map inc) (filter odd?)) (range 10))"]
["xf transduce" "25" "(transduce (comp (map inc) (filter odd?)) + 0 (range 10))"]
["xf take" "[0 1 2]" "(into [] (take 3) (range 100))"]
["xf remove" "[1 3 5]" "(into [] (remove even?) [1 2 3 4 5])"]
### 5. Protocols & Records
["record area circle" "78" "(do (defprotocol Sh (ar [t])) (defrecord Ci [r] Sh (ar [_] (int (* 3.14159 r r)))) (int (ar (->Ci 5))))"]
["record field" "5" "(do (defrecord Ci [r]) (:r (->Ci 5)))"]
["record map->" "3" "(do (defrecord P [x y]) (:x (map->P {:x 3 :y 4})))"]
["protocol 2 methods" "[16 \"sq\"]" "(do (defprotocol Sh (ar [t]) (nm [t])) (defrecord Sq [s] Sh (ar [_] (* s s)) (nm [_] \"sq\")) (let [x (->Sq 4)] [(ar x) (nm x)]))"]
["extend-protocol" "6" "(do (defprotocol G (g [x])) (extend-protocol G java.lang.Long (g [x] (inc x))) (g 5))"]
["reify" "42" "(do (defprotocol P (m [_])) (m (reify P (m [_] 42))))"]
["record equality" "true" "(do (defrecord R [a]) (= (->R 1) (->R 1)))"]
### 6. Multimethods
["mm dispatch circle" "\"round\"" "(do (defmulti st :kind) (defmethod st :circle [_] \"round\") (defmethod st :default [_] \"unknown\") (st {:kind :circle}))"]
["mm default" "\"unknown\"" "(do (defmulti st :kind) (defmethod st :circle [_] \"round\") (defmethod st :default [_] \"unknown\") (st {:kind :triangle}))"]
["mm multi-arity" "[1 3]" "(do (defmulti f (fn [& a] (first a))) (defmethod f :x ([_ y] y) ([_ y z] (+ y z))) [(f :x 1) (f :x 1 2)])"]
### 7. Macros
["macro log-call" "6" "(do (defmacro lc [e] `(let [r# ~e] r#)) (lc (* 2 3)))"]
["macro quote arg" "(quote (* 2 3))" "(do (defmacro qa [e] `(quote ~e)) (qa (* 2 3)))"]
["macroexpand-1" "true" "(do (defmacro mm [x] (list 'inc x)) (= '(inc 5) (macroexpand-1 '(mm 5))))"]
["gensym distinct" "false" "(= (gensym) (gensym))"]
["syntax-quote splice" "[1 2 3]" "(let [xs [1 2 3]] `[~@xs])"]
["syntax-quote unquote" "(quote (+ 1 5))" "(let [x 5] `(+ 1 ~x))"]
### 8. Recursion
["recursion fact" "120" "(do (defn fact [n] (if (<= n 1) 1 (* n (fact (dec n))))) (fact 5))"]
["recursion loop" "120" "(loop [i 5 acc 1] (if (zero? i) acc (recur (dec i) (* acc i))))"]
["mutual recursion" "true" "(letfn [(ev? [n] (if (zero? n) true (od? (dec n)))) (od? [n] (if (zero? n) false (ev? (dec n))))] (ev? 6))"]
["trampoline" ":done" "(do (defn a [n] (if (zero? n) :done (fn [] (a (dec n))))) (trampoline a 8))"]
### 9. Higher-order functions
["partial" "15" "((partial + 5) 10)"]
["comp" "8" "((comp #(* 2 %) inc) 3)"]
["juxt" "[5 6 4]" "((juxt identity inc dec) 5)"]
["every-pred" "true" "((every-pred pos? even?) 2 4 6)"]
["some-fn" "true" "((some-fn even? neg?) 3 4)"]
["fnil" "1" "((fnil inc 0) nil)"]
["complement" "true" "((complement nil?) 1)"]
### 10. Threading macros
["->> pipeline" "75" "(->> (range 20) (filter odd?) (map #(* % 3)) (take 5) (reduce +))"]
["-> sqrt long" "15" "(-> 25 Math/sqrt long (+ 10))"]
["some->" "2" "(some-> {:a {:b 1}} :a :b inc)"]
["some-> nil" "nil" "(some-> {:a nil} :a :b)"]
["cond->" "4" "(cond-> 1 true inc false (* 100) true (* 2))"]
["as->" "20" "(as-> 1 x (inc x) (* x 10))"]
### 11. Exception handling
["ex catch" "\"caught\"" "(try (throw (ex-info \"x\" {})) (catch :default e \"caught\"))"]
["ex-message" "\"broke\"" "(try (throw (ex-info \"broke\" {:code 42})) (catch :default e (ex-message e)))"]
["ex-data" "{:code 42}" "(try (throw (ex-info \"broke\" {:code 42})) (catch :default e (ex-data e)))"]
["try finally" "[:body :fin]" "(do (def lg (atom [])) (try (swap! lg conj :body) (finally (swap! lg conj :fin))) @lg)"]
### 12. For comprehension
["for nested :when" "(quote ([0 1] [0 2] [1 0] [1 2] [2 0] [2 1]))"
"(for [x (range 3) y (range 3) :when (not= x y)] [x y])"]
["for :let" "(quote (1 4 9))" "(for [x [1 2 3] :let [sq (* x x)]] sq)"]
["for :while" "(quote (0 1 2))" "(for [x (range 10) :while (< x 3)] x)"]
### 13b. Persistent lists — O(1) conj-prepend, immutable, value semantics
["list conj prepends" "(quote (0 1 2 3))" "(conj (list 1 2 3) 0)"]
["list conj multi" "(quote (:c :b :a))" "(conj (quote ()) :a :b :c)"]
["list immutable" "true" "(let [l (list 1 2 3) l2 (conj l 9)] (and (= l (quote (1 2 3))) (= l2 (quote (9 1 2 3)))))"]
["list? after conj" "true" "(list? (conj (list 1 2) 0))"]
["list = vector elts" "true" "(= (quote (1 2 3)) [1 2 3])"]
["reduce conj list" "(quote (2 1 0))" "(reduce conj (list) (range 3))"]
["cons onto list" "(quote (0 1 2 3))" "(cons 0 (list 1 2 3))"]
### 14. Janet interop
["interop method" "\"v=41\"" "(. {:value 41 :describe (fn [self] (str \"v=\" (:value self)))} describe)"]
["interop field" "41" "(.-value {:value 41})"]
# vectors are persistent vectors (Janet tables); lists are Janet arrays
["interop janet-type" ":array" "(do (require '[jolt.interop :as j]) (j/janet-type (list 1 2 3)))"]
])
(each [label expected actual] cases (check label expected actual))
(printf "\n=== features-test: %d/%d passed ===" pass (length cases))
(unless (empty? fails)
(print "--- Failures ---")
(each [label kind detail] fails (printf "[%s] %s: %s" kind label detail)))
(when (pos? (length fails))
(error (string (length fails) " feature regression(s)")))
(print "All feature tests passed!")
# Smoke test: the demo file itself loads and runs end-to-end without error.
(when (os/stat "clojure-features.clj")
(print "\n--- running clojure-features.clj (smoke test) ---")
(def res (protect (load-string (init) (slurp "clojure-features.clj"))))
(unless (= (res 0) true)
(error (string "clojure-features.clj failed to run: " (res 1))))
(print "--- clojure-features.clj ran cleanly ---"))

View file

@ -0,0 +1,54 @@
# jank conformance: runs the Clojure-language pass-tests from a local jank
# checkout (https://github.com/jank-lang/jank, MPL-2.0) against Jolt and asserts
# the number that pass stays at/above a baseline. This does NOT vendor jank's
# sources (license differs) — it references ~/src/jank if present and SKIPS
# cleanly when absent, so it is a local/dev regression aid.
#
# Each jank pass-test is an assertion script ending in `:success`. We load it in
# a fresh context and count it as passing when it returns :success.
(use ../../src/jolt/api)
(def jank-dir (string (os/getenv "HOME") "/src/jank/compiler+runtime/test/jank"))
# Baseline: the number of pass-tests Jolt currently handles. Raise this as Jolt
# gains features so regressions (a previously-passing test breaking) are caught.
(def baseline 120)
# Tests that loop forever under Jolt's eager evaluation (skipped to avoid hangs;
# tracked as known gaps — variadic-recur arity selection and var-quote calls).
(def skip-patterns ["/cpp/" "var-quote" "fn/recur/pass-variadic-position"])
(defn- skip? [path]
(var s false)
(each p skip-patterns (when (string/find p path) (set s true)))
s)
(defn- walk [dir acc]
(each e (os/dir dir)
(def p (string dir "/" e))
(case ((os/stat p) :mode)
:directory (walk p acc)
:file (when (and (string/has-suffix? ".jank" p)
(string/find "/pass-" p)
(not (skip? p)))
(array/push acc p))))
acc)
(if (not (os/stat jank-dir))
(print "jank-conformance: ~/src/jank not present — skipped")
(do
(def files (sort (walk jank-dir @[])))
(var pass 0)
(def fails @[])
(each f files
# A pass-test passes when no assertion throws (assert now errors on failure).
(def res (protect (load-string (init) (slurp f))))
(if (= (res 0) true)
(++ pass)
(array/push fails (string/slice f (+ 1 (length jank-dir))))))
(printf "jank-conformance: %d/%d pass-tests pass (baseline %d)" pass (length files) baseline)
(when (< pass baseline)
(print "--- regressions (now failing, were within baseline) ---")
(each rel fails (print " " rel))
(error (string "jank conformance dropped to " pass " (baseline " baseline ")")))
(printf "jank conformance OK (%d known gaps)" (length fails))))

View file

@ -0,0 +1,100 @@
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Ported Logic Tests (from clojure/test-clojure/logic.clj)")
(print "1: test-if true/false/nil...")
(let [ctx (init)]
(assert (= :t (ct-eval ctx "(if true :t)")) "if true")
(assert (= :t (ct-eval ctx "(if true :t :f)")) "if true with else")
(assert (= nil (ct-eval ctx "(if false :t)")) "if false no else")
(assert (= :f (ct-eval ctx "(if false :t :f)")) "if false with else")
(assert (= nil (ct-eval ctx "(if nil :t)")) "if nil no else")
(assert (= :f (ct-eval ctx "(if nil :t :f)")) "if nil with else"))
(print " ok")
(print "2: test-if zero/empty is true...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= :t (if 0 :t :f))")) "0 is true")
(assert (= true (ct-eval ctx "(= :t (if 0.0 :t :f))")) "0.0 is true")
(assert (= true (ct-eval ctx "(= :t (if \"\" :t :f))")) "empty string is true")
(assert (= true (ct-eval ctx "(= :t (if () :t :f))")) "empty list is true")
(assert (= true (ct-eval ctx "(= :t (if [] :t :f))")) "empty vector is true")
(assert (= true (ct-eval ctx "(= :t (if {} :t :f))")) "empty map is true")
(assert (= true (ct-eval ctx "(= :t (if #{} :t :f))")) "empty set is true"))
(print " ok")
(print "3: test-if anything except nil/false is true...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= :t (if 42 :t :f))")) "42 is true")
(assert (= true (ct-eval ctx "(= :t (if 1.5 :t :f))")) "float is true")
(assert (= true (ct-eval ctx "(= :t (if \"abc\" :t :f))")) "string is true")
(assert (= true (ct-eval ctx "(= :t (if 'abc :t :f))")) "symbol is true")
(assert (= true (ct-eval ctx "(= :t (if :kw :t :f))")) "keyword is true")
(assert (= true (ct-eval ctx "(= :t (if '(1 2) :t :f))")) "list is true")
(assert (= true (ct-eval ctx "(= :t (if [1 2] :t :f))")) "vector is true")
(assert (= true (ct-eval ctx "(= :t (if {:a 1 :b 2} :t :f))")) "map is true")
(assert (= true (ct-eval ctx "(= :t (if #{1 2} :t :f))")) "set is true"))
(print " ok")
(print "4: test-nil-punning...")
(let [ctx (init)]
(assert (= :yes (ct-eval ctx "(if (first []) :no :yes)")) "first [] nil")
(assert (= :yes (ct-eval ctx "(if (next [1]) :no :yes)")) "next [1] nil")
(assert (= :no (ct-eval ctx "(if (rest [1]) :no :yes)")) "rest [1] non-nil")
(assert (= :yes (ct-eval ctx "(if (seq nil) :no :yes)")) "seq nil")
(assert (= :yes (ct-eval ctx "(if (seq []) :no :yes)")) "seq [] nil")
(assert (= :no (ct-eval ctx "(if (lazy-seq nil) :no :yes)")) "lazy-seq nil non-nil")
(assert (= :no (ct-eval ctx "(if (lazy-seq []) :no :yes)")) "lazy-seq [] non-nil"))
(print " ok")
(print "5: test-and...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(and)")) "and empty")
(assert (= true (ct-eval ctx "(and true)")) "and true")
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
(assert (= false (ct-eval ctx "(and false)")) "and false")
(assert (ct-eval ctx "(= \"abc\" (and 1 true :kw 'abc \"abc\"))") "and chain last")
(assert (= nil (ct-eval ctx "(and 1 true nil 'abc \"abc\")")) "and chain nil")
(assert (= false (ct-eval ctx "(and 1 true 'abc \"abc\" false)")) "and chain false"))
(print " ok")
(print "6: test-or...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(or)")) "or empty")
(assert (= true (ct-eval ctx "(or true)")) "or true")
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
(assert (= false (ct-eval ctx "(or false)")) "or false")
(assert (= true (ct-eval ctx "(or nil false true)")) "or nil false true")
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or picks first truthy")
(assert (ct-eval ctx "(= \"abc\" (or nil false \"abc\" :kw))") "or picks string")
(assert (= nil (ct-eval ctx "(or false nil)")) "or false nil -> nil")
(assert (= false (ct-eval ctx "(or nil false)")) "or nil false -> false")
(assert (= false (ct-eval ctx "(or nil nil nil false)")) "or chain to false")
(assert (= true (ct-eval ctx "(or nil true false)")) "or nil true false"))
(print " ok")
(print "7: test-not...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
(assert (= true (ct-eval ctx "(not false)")) "not false")
(assert (= false (ct-eval ctx "(not true)")) "not true")
(assert (= false (ct-eval ctx "(not 0)")) "not 0")
(assert (= false (ct-eval ctx "(not 42)")) "not 42")
(assert (= false (ct-eval ctx "(not \"\")")) "not empty string")
(assert (= false (ct-eval ctx "(not \"abc\")")) "not string")
(assert (= false (ct-eval ctx "(not ())")) "not empty list")
(assert (= false (ct-eval ctx "(not [])")) "not empty vector")
(assert (= false (ct-eval ctx "(not {})")) "not empty map")
(assert (= false (ct-eval ctx "(not #{})")) "not empty set"))
(print " ok")
(print "8: test-some?...")
(let [ctx (init)]
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
(assert (= true (ct-eval ctx "(some? \"abc\")")) "some? string")
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec"))
(print " ok")
(print "\nAll Ported Logic tests passed!")

View file

@ -0,0 +1,92 @@
(use ../../src/jolt/reader)
(use ../../src/jolt/types)
(use ../../src/jolt/evaluator)
# Helper: parse and eval in a fresh ctx
(defn eval-str [s]
(let [ctx (make-ctx)
form (parse-string s)]
(eval-form ctx @{} form)))
(print "1: in-ns...")
(let [ctx (make-ctx)]
(def form (parse-string "(in-ns my.app)"))
(eval-form ctx @{} form)
(assert (= "my.app" (ctx-current-ns ctx)) "in-ns switches namespace"))
(print " passed")
(print "2: def in different namespace...")
(let [ctx (make-ctx)]
(eval-form ctx @{} (parse-string "(in-ns my.app)"))
(eval-form ctx @{} (parse-string "(def x 42)"))
(let [ns (ctx-find-ns ctx "my.app")
v (ns-find ns "x")]
(assert (= 42 (var-get v)) "def works in new namespace")))
(print " passed")
(print "3: ns form...")
(let [ctx (make-ctx)]
(eval-form ctx @{} (parse-string "(ns my.lib)"))
(assert (= "my.lib" (ctx-current-ns ctx)) "ns sets current namespace"))
(print " passed")
(print "4: ns with require...")
(let [ctx (make-ctx)]
# Set up a namespace with some vars
(let [other-ns (ctx-find-ns ctx "other.lib")]
(ns-intern other-ns "f" (fn [x] (inc x))))
# Now ns with require
(eval-form ctx @{} (parse-string "(ns my.app (:require [other.lib :as o]))"))
# current-ns should be my.app
(assert (= "my.app" (ctx-current-ns ctx)) "ns with require sets current namespace")
# Alias should be registered
(let [ns (ctx-find-ns ctx "my.app")
aliased (ns-import-lookup ns "o")]
(assert (= "other.lib" aliased) "alias o -> other.lib registered")))
(print " passed")
(print "5: require form (standalone)...")
(let [ctx (make-ctx)]
(eval-form ctx @{} (parse-string "(require '[other.lib :as o])"))
(let [ns (ctx-find-ns ctx "user")
aliased (ns-import-lookup ns "o")]
(assert (= "other.lib" aliased) "standalone require registers alias")))
(print " passed")
(print "6: qualified symbol via alias...")
(let [ctx (make-ctx)]
# Set up target ns
(let [target (ctx-find-ns ctx "other.lib")]
(ns-intern target "f" (fn [x] (inc x))))
# Register alias
(let [ns (ctx-find-ns ctx "user")]
(ns-import ns "o" "other.lib"))
# Resolve o/f and call it
(let [form (parse-string "(o/f 41)")
result (eval-form ctx @{} form)]
(assert (= 42 result) "qualified call via alias works")))
(print " passed")
(print "7: require then use alias...")
(let [ctx (make-ctx)]
# Set up target ns
(let [target (ctx-find-ns ctx "math.lib")]
(ns-intern target "add" (fn [a b] (+ a b))))
# require + use
(eval-form ctx @{} (parse-string "(require '[math.lib :as m])"))
(let [result (eval-form ctx @{} (parse-string "(m/add 1 2)"))]
(assert (= 3 result) "require + alias + call chain works")))
(print " passed")
(print "8: ns form requires multiple...")
(let [ctx (make-ctx)]
(let [ns1 (ctx-find-ns ctx "a.lib")]
(ns-intern ns1 "f" (fn [x] (inc x))))
(let [ns2 (ctx-find-ns ctx "b.lib")]
(ns-intern ns2 "g" (fn [x] (dec x))))
(eval-form ctx @{} (parse-string "(ns user (:require [a.lib :as a] [b.lib :as b]))"))
(assert (= 43 (eval-form ctx @{} (parse-string "(a/f 42)"))) "alias a works")
(assert (= 41 (eval-form ctx @{} (parse-string "(b/g 42)"))) "alias b works"))
(print " passed")
(print "\nAll namespace tests passed!")

View file

@ -0,0 +1,42 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "CLJS Collections Ported Tests")
(print "1: dissoc...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {:a :b} (dissoc {:a :b :c :d} :c))")) "dissoc")
(assert (= true (ct-eval ctx "(= {} (dissoc {1 2 3 4} 1 3))")) "dissoc multi"))
(print " ok")
(print "2: assoc...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {1 2 3 4} (assoc {} 1 2 3 4))")) "assoc multi")
(assert (= true (ct-eval ctx "(= {1 2} (assoc {} 1 2))")) "assoc single"))
(print " ok")
(print "3: set operations...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? (set []))")) "set empty")
(assert (= true (ct-eval ctx "(= #{\"foo\"} (set [\"foo\"]))")) "set from vec")
(assert (= true (ct-eval ctx "(= #{1 2 3} #{1 3 2})")) "set order")
(assert (= true (ct-eval ctx "(= #{1 2 3} (disj #{1 2 3}))")) "disj none")
(assert (= true (ct-eval ctx "(= #{1 2} (disj #{1 2 3} 3))")) "disj one")
(assert (= true (ct-eval ctx "(= #{1} (disj #{1 2 3} 2 3))")) "disj multi")
(assert (= true (ct-eval ctx "(= 4 (get #{1 2 3 4} 4))")) "get set")
(assert (= true (ct-eval ctx "(contains? #{1 2 3 4} 4)")) "contains? set"))
(print " ok")
(print "4: vector nth...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= :a (nth [:a :b :c :d] 0))")) "nth")
(assert (= true (ct-eval ctx "(= :c (nth [:a :b :c :d] 2 0.1))")) "nth float"))
(print " ok")
(print "5: range...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 0 (count (range 10 0 1)))")) "range empty")
(assert (= true (ct-eval ctx "(= 4 (count (range 0 10 3)))")) "range count")
(assert (= true (ct-eval ctx "(= 1 (count (range 0 1 1)))")) "range single"))
(print " ok")
(print "\nAll CLJS Collections Ported tests passed!")

View file

@ -0,0 +1,90 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "CLJS Core Ported Tests")
(print "1: metadata on maps...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {:foo \"bar\"} (meta (with-meta {:a 1} {:foo \"bar\"})))")) "with-meta on map"))
(print " ok")
(print "2: atoms...")
(let [ctx (init)]
(ct-eval ctx "(def a (atom 0))")
(assert (= true (ct-eval ctx "(= 0 (deref a))")) "deref")
(assert (= true (ct-eval ctx "(= 1 (swap! a inc))")) "swap! inc")
(ct-eval ctx "(def b (atom 0))")
(assert (= true (ct-eval ctx "(= 1 (swap! b + 1))")) "swap! + 1")
(assert (= true (ct-eval ctx "(= 4 (swap! b + 1 2))")) "swap! + 1 2")
(assert (= true (ct-eval ctx "(= 10 (swap! b + 1 2 3))")) "swap! + 1 2 3")
(assert (= true (ct-eval ctx "(= 20 (swap! b + 1 2 3 4))")) "swap! + 1 2 3 4")
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?")
(assert (= true (ct-eval ctx "(nil? (meta (atom 0)))")) "atom meta nil"))
(print " ok")
(print "3: contains?...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(contains? {:a 1 :b 2} :a)")) "contains? map key")
(assert (= true (ct-eval ctx "(not (contains? {:a 1 :b 2} :z))")) "contains? missing")
(assert (= true (ct-eval ctx "(contains? [5 6 7] 1)")) "contains? vector index")
(assert (= true (ct-eval ctx "(contains? [5 6 7] 2)")) "contains? vector index 2")
(assert (= true (ct-eval ctx "(not (contains? [5 6 7] 3))")) "contains? vector oob")
(assert (= true (ct-eval ctx "(not (contains? nil 42))")) "contains? nil"))
(print " ok")
(print "4: get-in...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 (get-in {:foo 1 :bar 2} [:foo]))")) "get-in flat")
(assert (= true (ct-eval ctx "(= 2 (get-in {:foo {:bar 2}} [:foo :bar]))")) "get-in nested"))
(print " ok")
(print "5: multimethods...")
(let [ctx (init)]
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
(assert (= true (ct-eval ctx "(= \"hello\" (greet {:lang :en}))")) "dispatch :en")
(assert (= true (ct-eval ctx "(= \"bonjour\" (greet {:lang :fr}))")) "dispatch :fr"))
(print " ok")
(print "6: sequential equality...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= (list 3 2 1) [3 2 1])")) "list = vector")
(assert (= true (ct-eval ctx "(= () (rest nil))")) "rest nil")
(assert (= true (ct-eval ctx "(= () (rest [1]))")) "rest [1]")
(assert (= true (ct-eval ctx "(= () (rest ()))")) "rest empty"))
(print " ok")
(print "7: seq operations...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(nil? (seq []))")) "seq empty vec"))
(print " ok")
(print "8: empty and empty?...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(empty? nil)")) "empty? nil")
(assert (= true (ct-eval ctx "(empty? ())")) "empty? ()")
(assert (= true (ct-eval ctx "(empty? [])")) "empty? []")
(assert (= true (ct-eval ctx "(empty? {})")) "empty? {}")
(assert (= true (ct-eval ctx "(empty? #{})")) "empty? #{}")
(assert (= true (ct-eval ctx "(empty? \"\")")) "empty? empty string")
(assert (= true (ct-eval ctx "(not (empty? [1 2]))")) "empty? non-empty")
(assert (= true (ct-eval ctx "(not (empty? {:a 1}))")) "empty? non-empty map"))
(print " ok")
(print "9: distinct...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 0 (count (distinct ())))")) "distinct empty")
(assert (= true (ct-eval ctx "(= 1 (count (distinct '(1))))")) "distinct single")
(assert (= true (ct-eval ctx "(= 3 (count (distinct '(1 2 3 1 1 1))))")) "distinct multi count")
(assert (= true (ct-eval ctx "(= 1 (count (distinct [42 42])))")) "distinct nums count"))
(print " ok")
(print "10: some and some?...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(some? 1)")) "some? 1")
(assert (= true (ct-eval ctx "(not (some? nil))")) "some? nil")
(assert (= true (ct-eval ctx "(some even? [1 2 3])")) "some even?")
(assert (= true (ct-eval ctx "(nil? (some even? [1 3 5]))")) "some even? nil"))
(print " ok")
(print "\nAll CLJS Core Ported tests passed!")

View file

@ -0,0 +1,110 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 1 ===")
(print "1: core math...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
(assert (= 0 (ct-eval ctx "(+)")) "+ zero")
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
(print " passed")
(print "2: predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
(assert (= false (ct-eval ctx "(not true)")) "not")
(assert (= true (ct-eval ctx "(not false)")) "not false")
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
(print " passed")
(print "3: comparison...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
(assert (= false (ct-eval ctx "(= 1 2)")) "= false")
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= three")
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= false")
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
(print " passed")
(print "4: vectors...")
(let [ctx (init)]
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count"))
(print " passed")
(print "5: maps...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
(assert (= {:a 1 :b 2} (ct-eval ctx "(assoc {:a 1} :b 2)")) "assoc")
(assert (= {:b 2} (ct-eval ctx "(dissoc {:a 1 :b 2} :a)")) "dissoc")
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count")
(assert (= 2 (ct-eval ctx "(count (keys {:a 1 :b 2}))")) "keys count"))
(print " passed")
(print "6: sets...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj")
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj")
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
(print " passed")
(print "7: seq operations...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
(assert (= 2 (ct-eval ctx "(count (filter odd? [1 2 3 4]))")) "filter")
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
(assert (= [3 2 1] (ct-eval ctx "(reverse [1 2 3])")) "reverse")
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
(print " passed")
(print "8: printing...")
(let [ctx (init)]
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
(assert (= "ab" (ct-eval ctx "(str \"a\" \"b\")")) "str two")
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
(assert (= "" (ct-eval ctx "(str nil)")) "str nil -> empty string (Clojure semantics)")
(assert (= "a" (ct-eval ctx "(name :a)")) "name"))
(print " passed")
(print "9: apply...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
(print " passed")
(print "10: equality across types...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order-independent"))
(print " passed")
(print "11: higher-order fns...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
(print " passed")
(print "\nAll CLJS Ported Part 1 tests passed!")

View file

@ -0,0 +1,25 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 10 ===")
(print "43: when/when-not...")
(let [ctx (init)]
(assert (= 42 (ct-eval ctx "(when true 42)")) "when true")
(assert (= nil (ct-eval ctx "(when false 42)")) "when false")
(assert (= 42 (ct-eval ctx "(when-not false 42)")) "when-not false"))
(print " ok")
(print "44: if-let/when-let...")
(let [ctx (init)]
(assert (= 2 (ct-eval ctx "(if-let [x 1] (inc x) 0)")) "if-let true")
(assert (= 0 (ct-eval ctx "(if-let [x nil] (inc x) 0)")) "if-let nil")
(assert (= 2 (ct-eval ctx "(when-let [x 1] (inc x))")) "when-let"))
(print " ok")
(print "45: doto...")
(let [ctx (init)]
(ct-eval ctx "(def x (atom []))")
(assert (= nil (ct-eval ctx "(doto nil)")) "doto nil returns nil"))
(print " ok")
(print "\nAll CLJS Ported Part 10 tests passed!\n")

View file

@ -0,0 +1,77 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 1 ===")
(print "1: core math...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
(assert (= 0 (ct-eval ctx "(+)")) "+ zero")
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
(print " passed")
(print "2: predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
(assert (= false (ct-eval ctx "(not true)")) "not")
(assert (= true (ct-eval ctx "(not false)")) "not false")
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
(print " passed")
(print "3: comparison...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
(assert (= false (ct-eval ctx "(= 1 2)")) "= false")
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= three")
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= false")
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
(print " passed")
(print "4: vectors...")
(let [ctx (init)]
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count"))
(print " passed")
(print "5: maps...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
(assert (= {:a 1 :b 2} (ct-eval ctx "(assoc {:a 1} :b 2)")) "assoc")
(assert (= {:b 2} (ct-eval ctx "(dissoc {:a 1 :b 2} :a)")) "dissoc")
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count")
(assert (= 2 (ct-eval ctx "(count (keys {:a 1 :b 2}))")) "keys count"))
(print " passed")
(print "6: sets...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj count")
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj count")
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
(print " passed")
(print "\nAll CLJS Ported Part 1a tests passed!")

View file

@ -0,0 +1,37 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 1b ===")
(print "7: seq operations...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
(assert (= [1 3] (ct-eval ctx "(filter odd? [1 2 3 4])")) "filter")
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
(assert (= [3 2 1] (ct-eval ctx "(reverse [1 2 3])")) "reverse")
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
(print " passed")
(print "8: printing...")
(let [ctx (init)]
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
(assert (= "ab" (ct-eval ctx "(str \"a\" \"b\")")) "str two")
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
(assert (= "a" (ct-eval ctx "(name :a)")) "name"))
(print " passed")
(print "9: apply...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
(print " passed")
(print "10: equality...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order"))
(print " passed")
(print "11: higher-order fns...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
(print " passed")
(print "\nAll CLJS Ported Part 1b tests passed!")

View file

@ -0,0 +1,77 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 2 ===")
(print "12: atoms...")
(let [ctx (init)]
(assert (= 0 (ct-eval ctx "(deref (atom 0))")) "deref")
(assert (= 1 (ct-eval ctx "(let [a (atom 0)] (swap! a inc) (deref a))")) "swap!")
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?"))
(print " ok")
(print "13: special forms...")
(let [ctx (init)]
(assert (= 30 (ct-eval ctx "(let [x 10 y 20] (+ x y))")) "let")
(assert (= :a (ct-eval ctx "(if true :a :b)")) "if true")
(assert (= :b (ct-eval ctx "(if false :a :b)")) "if false")
(assert (= 2 (ct-eval ctx "(do 1 2)")) "do")
(assert (= 3 (ct-eval ctx "(loop [x 0] (if (< x 3) (recur (inc x)) x))")) "loop")
(assert (= "caught" (ct-eval ctx "(try (throw 42) (catch Exception e \"caught\"))")) "try catch"))
(print " ok")
(print "14: macros...")
(let [ctx (init)]
(ct-eval ctx "(defn add [a b] (+ a b))")
(assert (= 7 (ct-eval ctx "(add 3 4)")) "defn")
(assert (= 42 (ct-eval ctx "(when true 42)")) "when")
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and")
(assert (= 1 (ct-eval ctx "(or 1 2 3)")) "or")
(assert (= 49 (ct-eval ctx "((fn [x] (* x x)) 7)")) "fn"))
(print " ok")
(print "15: constructors...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(count (vector 1 2 3))")) "vector count")
(assert (= 2 (ct-eval ctx "(count (hash-map :a 1 :b 2))")) "hash-map count")
(assert (= 3 (ct-eval ctx "(count (hash-set 1 2 3))")) "hash-set count")
(assert (= 3 (ct-eval ctx "(count (zipmap [:a :b :c] [1 2 3]))")) "zipmap count"))
(print " ok")
(print "16: printing...")
(let [ctx (init)]
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
(assert (= "a" (ct-eval ctx "(name :a)")) "name")
(assert (= ":hello" (ct-eval ctx "(pr-str :hello)")) "pr-str keyword"))
(print " ok")
(print "17: apply...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
(print " ok")
(print "18: equality...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order-independent")
(assert (= false (ct-eval ctx "(= {:a 1} {:a 2})")) "map different values")
(assert (= 1 (ct-eval ctx "(:a (with-meta {:a 1} {:c 3}))")) "with-meta preserves value")
(assert (= 3 (ct-eval ctx "(:c (with-meta {:a 1} {:c 3}))")) "with-meta preserves meta via get"))
(print " ok")
(print "19: higher-order...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
(print " ok")
(print "20: seq edge cases...")
(let [ctx (init)]
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
(assert (= nil (ct-eval ctx "(seq nil)")) "seq nil")
(assert (= nil (ct-eval ctx "(first nil)")) "first nil")
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first vector"))
(print " ok")
(print "21: atoms extended...")
(let [ctx (init)]
(ct-eval ctx "(def a (atom 10))")
(assert (= 10 (ct-eval ctx "(deref a)")) "deref")
(ct-eval ctx "(reset! a 42)")
(assert (= 42 (ct-eval ctx "(deref a)")) "reset!")
(ct-eval ctx "(swap! a inc)")
(assert (= 43 (ct-eval ctx "(deref a)")) "swap! inc")
(assert (= 43 (ct-eval ctx "@a")) "@ deref macro"))
(print " ok")
(print "\nAll CLJS Ported Part 2 tests passed!")

View file

@ -0,0 +1,32 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 3 ===")
(print "16: destructuring...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure rest")
(assert (= 3 (ct-eval ctx "(let [[_ _ z] [1 2 3]] z)")) "seq destructure last"))
(print " passed")
(print "17: set operations...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "set count")
(assert (= true (ct-eval ctx "(contains? #{1 2} 1)")) "contains? set")
(assert (= 1 (ct-eval ctx "(get #{1 2 3} 1)")) "get set"))
(print " passed")
(print "18: reader literals...")
(let [ctx (init)]
(assert (= [1 2 3] (ct-eval ctx "[1 2 3]")) "vector literal")
(assert (= {:a 1} (ct-eval ctx "{:a 1}")) "map literal")
(assert (= true (ct-eval ctx "true")) "true literal")
(assert (= nil (ct-eval ctx "nil")) "nil literal")
(assert (= 42 (ct-eval ctx "42")) "number literal"))
(print " passed")
(print "19: syntax-quote...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= '(1 2 3) '(1 2 3))")) "sq basic list"))
(print " passed")
(print "20: walk...")
(print " skipped (clojure.walk needs IFn protocol)")
(print "\nAll CLJS Ported Part 3 tests passed!")

View file

@ -0,0 +1,22 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 3b ===")
(print "21: clojure.string...")
(let [ctx (init)]
(load-string ctx (slurp "src/jolt/clojure/string.clj"))
(assert (= true (ct-eval ctx "(blank? nil)")) "blank? nil")
(assert (= true (ct-eval ctx "(blank? \" \")")) "blank? spaces")
(assert (= "Abc" (ct-eval ctx "(capitalize \"abc\")")) "capitalize")
(assert (= "hello" (ct-eval ctx "(lower-case \"HELLO\")")) "lower-case")
(assert (= "hello" (ct-eval ctx "(trim \" hello \")")) "trim"))
(print " passed")
(print "22: clojure.set...")
(let [ctx (init)]
(load-string ctx (slurp "src/jolt/clojure/set.clj"))
(assert (= 3 (ct-eval ctx "(count (union #{1 2} #{2 3}))")) "union")
(assert (= 1 (ct-eval ctx "(count (intersection #{1 2} #{2 3}))")) "intersection")
(assert (= 1 (ct-eval ctx "(count (difference #{1 2} #{2 3}))")) "difference"))
(print " passed")
(print "\nAll CLJS Ported Part 3 tests passed!")
(print "\nAll CLJS Ported Part 3b tests passed!")

View file

@ -0,0 +1,48 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 4 ===")
(print "23: deftype/defrecord...")
(let [ctx (init)]
(ct-eval ctx "(deftype Point [x y])")
(assert (= true (ct-eval ctx "(instance? Point (Point. 3 4))")) "instance? true")
(assert (= 3 (ct-eval ctx "(. (Point. 3 4) x)")) ".field access")
(ct-eval ctx "(defrecord Person [name age])")
(assert (= true (ct-eval ctx "(map? (Person. \"A\" 30))")) "record is map?")
(assert (= "Alice" (ct-eval ctx "(:name (Person. \"Alice\" 30))")) "record keyword access"))
(print " ok")
(print "24: multimethods...")
(let [ctx (init)]
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
(assert (= "hello" (ct-eval ctx "(greet {:lang :en})")) "dispatch :en")
(assert (= "bonjour" (ct-eval ctx "(greet {:lang :fr})")) "dispatch :fr"))
(print " ok")
(print "25: protocols...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Greet (g [this]))")
(ct-eval ctx "(deftype Dog [name])")
(ct-eval ctx "(extend-type Dog Greet (g [this] (str \"woof \" (.-name this))))")
(assert (= "woof Rex" (ct-eval ctx "(g (Dog. \"Rex\"))")) "extend-type"))
(print " ok")
(print "26: var system...")
(let [ctx (init)]
(ct-eval ctx "(def xv 42)")
(assert (= true (ct-eval ctx "(var? (var xv))")) "var?")
(assert (= 42 (ct-eval ctx "(var-get (var xv))")) "var-get")
(ct-eval ctx "(var-set (var xv) 99)")
(assert (= 99 (ct-eval ctx "(var-get (var xv))")) "var-set"))
(print " ok")
(print "27: range/into/concat...")
(let [ctx (init)]
(assert (= 5 (ct-eval ctx "(count (range 5))")) "range count")
(assert (= [0 1 2 3 4] (ct-eval ctx "(into [] (range 5))")) "range into vec")
(assert (= 4 (ct-eval ctx "(count (concat [1 2] [3 4]))")) "concat count"))
(print " ok")
(print "\nAll CLJS Ported Part 4 tests passed!")

View file

@ -0,0 +1,22 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 5 ===")
(print "22: destructuring...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure rest"))
(print " ok")
(print "23: metadata...")
(let [ctx (init)]
(ct-eval ctx "(def ^:dynamic *dyn* 42)")
(assert (= true (ct-eval ctx "(var-dynamic? (var *dyn*))")) "dynamic metadata")
(assert (= 1 (ct-eval ctx "(:a (with-meta {:a 1} {:c 3}))")) "with-meta preserves"))
(print " ok")
(print "24: function composition...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "((complement odd?) 2)")) "complement")
(assert (= 5 (ct-eval ctx "((constantly 5) :anything)")) "constantly")
(assert (= true (ct-eval ctx "((every-pred number? even?) 4)")) "every-pred")
(assert (= ":hello" (ct-eval ctx "(pr-str :hello)")) "pr-str keyword"))
(print " ok")
(print "\nAll CLJS Ported Part 5 tests passed!")

View file

@ -0,0 +1,30 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 6 ===")
(print "28: anon fn #()...")
(let [ctx (init)]
(assert (= 6 (ct-eval ctx "(#(+ % 5) 1)")) "#() %")
(assert (= 0 (ct-eval ctx "(#(do 0))")) "#() do body"))
(print " ok")
(print "29: symbol operations...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(symbol? 'foo)")) "symbol?")
(assert (= "foo" (ct-eval ctx "(name 'foo)")) "name symbol")
(assert (= "bar" (ct-eval ctx "(name :bar)")) "name keyword"))
(print " ok")
(print "30: keyword operations...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= :foo (ct-eval ctx "(keyword \"foo\")")) "keyword string"))
(print " ok")
(print "31: list operations...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(count (list 3 2 1))")) "list count")
(assert (= 1 (ct-eval ctx "(first '(1 2 3))")) "first list"))
(print " ok")
(print "\nAll CLJS Ported Part 6 tests passed!\n")

View file

@ -0,0 +1,20 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 7 ===")
(print "32: seq destructuring...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure skip")
(assert (= 3 (ct-eval ctx "(let [[_ _ z] [1 2 3]] z)")) "seq destructure end"))
(print " ok")
(print "33: & rest args...")
(let [ctx (init)]
(ct-eval ctx "(defn sum [& xs] (apply + xs))")
(assert (= 6 (ct-eval ctx "(sum 1 2 3)")) "& rest sum")
(ct-eval ctx "(defn first-two [a b & rest] (count rest))")
(assert (= 2 (ct-eval ctx "(first-two 1 2 3 4)")) "& rest after fixed"))
(print " ok")
(print "\nAll CLJS Ported Part 7 tests passed!\n")

View file

@ -0,0 +1,35 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 8 ===")
(print "35: range and repeat...")
(let [ctx (init)]
(assert (= 5 (ct-eval ctx "(count (range 5))")) "range")
(assert (= 4 (ct-eval ctx "(count (repeat 4 :x))")) "repeat")
(assert (= 3 (ct-eval ctx "(count (repeatedly 3 (constantly :y)))")) "repeatedly"))
(print " ok")
(print "36: concat and into...")
(let [ctx (init)]
(assert (= 4 (ct-eval ctx "(count (concat [1 2] [3 4]))")) "concat")
(assert (= 4 (ct-eval ctx "(count (into [] (range 4)))")) "into"))
(print " ok")
(print "37: take-while/drop-while...")
(let [ctx (init)]
(assert (= 2 (ct-eval ctx "(count (take-while even? [2 4 3 5]))")) "take-while")
(assert (= 2 (ct-eval ctx "(count (drop-while even? [2 4 3 5]))")) "drop-while"))
(print " ok")
(print "38: partition...")
(let [ctx (init)]
(assert (= 2 (ct-eval ctx "(count (partition 2 [1 2 3 4]))")) "partition 2"))
(print " ok")
(print "39: sorting...")
(let [ctx (init)]
(assert (= [1 2 3] (ct-eval ctx "(sort [3 1 2])")) "sort")
(assert (= [1 2 3] (ct-eval ctx "(distinct [1 2 1 3 2])")) "distinct"))
(print " ok")
(print "\nAll CLJS Ported Part 8 tests passed!\n")

View file

@ -0,0 +1,18 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "=== CLJS Ported Part 9 ===")
(print "40: seq predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(empty? [])")) "empty? true")
(assert (= false (ct-eval ctx "(empty? [1])")) "empty? false")
(assert (= true (ct-eval ctx "(every? pos? [1 2 3])")) "every? pos"))
(print " ok")
(print "41: complement...")
(let [ctx (init)]
(assert (= false (ct-eval ctx "((complement pos?) 1)")) "complement pos")
(assert (= true (ct-eval ctx "((complement pos?) -1)")) "complement neg"))
(print " ok")
(print "\nAll CLJS Ported Part 9 tests passed!\n")

View file

@ -0,0 +1,131 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "CLJS Ported Tests")
(print "1: math...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
(print " ok")
(print "2: predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
(assert (= false (ct-eval ctx "(not true)")) "not")
(assert (= true (ct-eval ctx "(not false)")) "not false")
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
(print " ok")
(print "3: comparison...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
(print " ok")
(print "4: vectors...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= :a (nth [:a :b :c :d] 0))")) "nth")
(assert (= true (ct-eval ctx "(= 4 (count (conj [1 2 3] 4)))")) "conj count")
(assert (= true (ct-eval ctx "(= 1 (first [1 2 3]))")) "first")
(assert (= true (ct-eval ctx "(= 2 (count (rest [1 2 3])))")) "rest count")
(assert (= true (ct-eval ctx "(= 3 (count [1 2 3]))")) "count"))
(print " ok")
(print "5: maps...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 (get {:a 1} :a))")) "get")
(assert (= true (ct-eval ctx "(nil? (get {:a 1} :z))")) "get missing")
(assert (= true (ct-eval ctx "(= :d (get {:a 1} :z :d))")) "get default")
(assert (= true (ct-eval ctx "(= 2 (count (assoc {:a 1} :b 2)))")) "assoc count")
(assert (= true (ct-eval ctx "(= 1 (count (dissoc {:a 1 :b 2} :a)))")) "dissoc count")
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
(assert (= true (ct-eval ctx "(= 3 (count {:a 1 :b 2 :c 3}))")) "count")
(assert (= true (ct-eval ctx "(= 2 (count (keys {:a 1 :b 2})))")) "keys"))
(print " ok")
(print "6: sets...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
(assert (= true (ct-eval ctx "(= 4 (count (conj #{1 2 3} 4)))")) "conj count")
(assert (= true (ct-eval ctx "(= 2 (count (disj #{1 2 3} 3)))")) "disj count")
(assert (= true (ct-eval ctx "(= 3 (count #{1 2 3}))")) "count")
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order"))
(print " ok")
(print "7: seq ops...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(nil? (seq []))")) "seq empty")
(assert (= true (ct-eval ctx "(= 3 (count (map inc [1 2 3])))")) "map count")
(assert (= true (ct-eval ctx "(= 2 (count (filter odd? [1 2 3 4])))")) "filter count")
(assert (= true (ct-eval ctx "(= 6 (reduce + [1 2 3]))")) "reduce")
(assert (= true (ct-eval ctx "(= 3 (count (take 3 [1 2 3 4 5])))")) "take count")
(assert (= true (ct-eval ctx "(= 2 (count (drop 3 [1 2 3 4 5])))")) "drop count")
(assert (= true (ct-eval ctx "(= 3 (count (reverse [1 2 3])))")) "reverse count")
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
(print " ok")
(print "8: atoms...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 0 (deref (atom 0)))")) "deref")
(assert (= true (ct-eval ctx "(= 1 (let [a (atom 0)] (swap! a inc) (deref a)))")) "swap!")
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?"))
(print " ok")
(print "9: special forms...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 30 (let [x 10 y 20] (+ x y)))")) "let")
(assert (= true (ct-eval ctx "(= :a (if true :a :b))")) "if true")
(assert (= true (ct-eval ctx "(= :b (if false :a :b))")) "if false")
(assert (= true (ct-eval ctx "(= 2 (do 1 2))")) "do")
(assert (= true (ct-eval ctx "(= 3 (loop [x 0] (if (< x 3) (recur (inc x)) x)))")) "loop")
(assert (= true (ct-eval ctx "(= :caught (try (throw 42) (catch Exception e :caught)))")) "try"))
(print " ok")
(print "10: macros...")
(let [ctx (init)]
(ct-eval ctx "(defn add [a b] (+ a b))")
(assert (= true (ct-eval ctx "(= 7 (add 3 4))")) "defn")
(assert (= true (ct-eval ctx "(= 42 (when true 42))")) "when")
(assert (= true (ct-eval ctx "(= 3 (and 1 2 3))")) "and")
(assert (= true (ct-eval ctx "(= 1 (or 1 2 3))")) "or")
(assert (= true (ct-eval ctx "(= 49 ((fn [x] (* x x)) 7))")) "fn"))
(print " ok")
(print "11: higher-order...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 3 ((comp inc inc) 1))")) "comp")
(assert (= true (ct-eval ctx "(= 3 ((partial + 1 2)))")) "partial")
(assert (= true (ct-eval ctx "(= 5 ((constantly 5) :anything))")) "constantly")
(assert (= true (ct-eval ctx "(= 3 (identity 3))")) "identity"))
(print " ok")
(print "12: constructors...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 3 (count (vector 1 2 3)))")) "vector count")
(assert (= true (ct-eval ctx "(= 2 (count (hash-map :a 1 :b 2)))")) "hash-map count")
(assert (= true (ct-eval ctx "(= 3 (count (hash-set 1 2 3)))")) "hash-set count")
(assert (= true (ct-eval ctx "(= 3 (count (zipmap [:a :b :c] [1 2 3])))")) "zipmap count"))
(print " ok")
(print "\nAll CLJS Ported Tests passed!")

View file

@ -0,0 +1,59 @@
(use ../../../src/jolt/api)
(use ../../../src/jolt/reader)
(use ../../../src/jolt/evaluator)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(defn load-clj [ctx filepath]
(def source (slurp filepath))
(var remaining source)
(while (> (length (string/trim remaining)) 0)
(def fr (parse-next remaining))
(def form (fr 0))
(set remaining (fr 1))
(when (not (nil? form))
(eval-form ctx @{} form))))
(print "40: clojure.string...")
(let [ctx (init)]
(load-clj ctx "src/jolt/clojure/string.clj")
(assert (= true (ct-eval ctx "(blank? nil)")) "blank? nil")
(assert (= true (ct-eval ctx "(blank? \" \")")) "blank? whitespace")
(assert (= false (ct-eval ctx "(blank? \"a\")")) "blank? non-empty")
(assert (= "Abc" (ct-eval ctx "(capitalize \"abc\")")) "capitalize")
(assert (= "hello" (ct-eval ctx "(lower-case \"HELLO\")")) "lower-case")
(assert (= "HELLO" (ct-eval ctx "(upper-case \"hello\")")) "upper-case")
(assert (= true (ct-eval ctx "(includes? \"hello\" \"ell\")")) "includes? true")
(assert (= "foo" (ct-eval ctx "(trim \"foo\")")) "trim")
(assert (= true (ct-eval ctx "(starts-with? \"hello\" \"he\")")) "starts-with? true")
(assert (= true (ct-eval ctx "(ends-with? \"hello\" \"lo\")")) "ends-with? true"))
(print " passed")
(print "41: clojure.set...")
(let [ctx (init)]
(load-clj ctx "src/jolt/clojure/set.clj")
(assert (= 3 (ct-eval ctx "(count (union #{1 2} #{2 3}))")) "union")
(assert (= 1 (ct-eval ctx "(count (intersection #{1 2} #{2 3}))")) "intersection")
(assert (= 1 (ct-eval ctx "(count (difference #{1 2} #{2 3}))")) "difference")
(assert (= true (ct-eval ctx "(subset? #{1} #{1 2 3})")) "subset? true")
(assert (= true (ct-eval ctx "(superset? #{1 2 3} #{1})")) "superset? true"))
(print " passed")
(print "42: clojure.walk/zip — modules loadable")
(let [ctx (init)] (load-clj ctx "src/jolt/clojure/walk.clj") (print " walk: loaded"))
(let [ctx (init)] (load-clj ctx "src/jolt/clojure/zip.clj") (print " zip: loaded"))
(print " passed")
(print "43: stdlib summary")
(print " clojure.string — 19 functions")
(print " clojure.set — 10 functions")
(print " clojure.walk — 7 functions")
(print " clojure.zip — zipper data structure")
(print " clojure.edn — EDN reader/writer stubs")
(print " clojure.java-io — file I/O wrappers")
(print " jolt.interop — Janet interop")
(print " jolt.shell — shell command execution")
(print " jolt.http — HTTP client")
(print " passed")
(print "All Phase 10 tests passed!")

View file

@ -0,0 +1,50 @@
# Phase 12: Protocol System Tests
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "35: defprotocol...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Greet (greet [this]))")
(let [p (ct-eval ctx "Greet")]
(assert (not (nil? p)) "protocol var exists")
(assert (= :jolt/protocol (get p :jolt/type)) "protocol type tag")
(assert (get (get p :methods) :greet) "protocol has greet method"))
(assert (or (function? (ct-eval ctx "greet")) (cfunction? (ct-eval ctx "greet"))) "method fn exists"))
(print " passed")
(print "36: extend-type...")
(let [ctx (init)]
(ct-eval ctx "(deftype Person [name])")
(ct-eval ctx "(defprotocol Namable (get-name [this]))")
(ct-eval ctx "(extend-type Person Namable (get-name [this] (.-name this)))")
(assert (= "Alice" (ct-eval ctx "(get-name (Person. \"Alice\"))")) "extend-type works"))
(print " passed")
(print "37: extend-protocol...")
(let [ctx (init)]
(ct-eval ctx "(deftype Dog [breed])")
(ct-eval ctx "(deftype Cat [color])")
(ct-eval ctx "(defprotocol Animal (speak [this]))")
(ct-eval ctx "(extend-protocol Animal
Dog (speak [this] (str \"woof from \" (.-breed this)))
Cat (speak [this] (str \"meow from \" (.-color this))))")
(assert (= "woof from poodle" (ct-eval ctx "(speak (Dog. \"poodle\"))")) "dog speak")
(assert (= "meow from black" (ct-eval ctx "(speak (Cat. \"black\"))")) "cat speak"))
(print " passed")
(print "38: satisfies?...")
(let [ctx (init)]
(ct-eval ctx "(deftype Point [x y])")
(ct-eval ctx "(defprotocol Locatable (location [this]))")
(ct-eval ctx "(extend-type Point Locatable (location [this] [(.-x this) (.-y this)]))")
(assert (= true (ct-eval ctx "(satisfies? Locatable (Point. 3 4))")) "satisfies? true")
(assert (= false (ct-eval ctx "(satisfies? Locatable {:x 1})")) "satisfies? false"))
(print " passed")
(print "39: reify...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Stringable (to-str [this]))")
(assert (= "works" (ct-eval ctx "(to-str (reify Stringable (to-str [this] \"works\")))")) "reify single method"))
(print " passed")
(print "\nAll Phase 12 tests passed!")

View file

@ -0,0 +1,44 @@
(use ../../../src/jolt/api)
(use ../../../src/jolt/evaluator)
(use ../../../src/jolt/reader)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(defn load-clj [ctx filepath]
(var s (slurp filepath))
(while (> (length (string/trim s)) 0)
(def [form rest] (parse-next s))
(set s rest)
(when (not (nil? form))
(eval-form ctx @{} form))))
(print "=== Phase 13: Protocol Completion ===")
(print "28: reify dispatch...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Greeter (say-hello [this]))")
(ct-eval ctx "(def r (reify Greeter (say-hello [this] \"hello reify\")))")
(assert (= "hello reify" (ct-eval ctx "(say-hello r)")) "reify dispatch"))
(print " ok")
(print "29: #() anon-fn reader...")
(let [ctx (init)]
(assert (= 2 (ct-eval ctx "(#(inc %) 1)")) "anon fn %")
(assert (= 3 (ct-eval ctx "(#(+ %1 %2) 1 2)")) "anon fn %1 %2")
(assert (= [1 2 3] (ct-eval ctx "(map #(inc %) [0 1 2])")) "anon fn map"))
(print " ok")
(print "30: extend-type full dispatch...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Greet (g [this]))")
(ct-eval ctx "(deftype Dog [name])")
(ct-eval ctx "(extend-type Dog Greet (g [this] (str \"woof \" (.-name this))))")
(assert (= "woof Rex" (ct-eval ctx "(g (Dog. \"Rex\"))")) "extend-type dog"))
(print " ok")
(print "31: clojure.walk loading...")
(let [ctx (init)]
(load-clj ctx "src/jolt/clojure/walk.clj")
(assert (function? (ct-eval ctx "keywordize-keys")) "keywordize-keys is fn"))
(print " ok")
(print "\nAll Phase 13 tests passed!")

View file

@ -0,0 +1,74 @@
# Phase 5: Multimethods + Hierarchy Tests
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
# 22. Hierarchy
(print "22: hierarchy...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(map? (make-hierarchy))")) "make-hierarchy returns map")
# 2-arity derive/isa? just returns nil/false (no global hierarchy)
(ct-eval ctx "(derive ::square ::shape)")
(assert (= false (ct-eval ctx "(isa? ::square ::shape)")) "isa? 2-arity always false"))
(print " passed")
# 23. Multimethods — basic dispatch
(print "23: basic multimethod dispatch...")
(let [ctx (init)]
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
(assert (= "hello" (ct-eval ctx "(greet {:lang :en})")) "dispatch :en")
(assert (= "bonjour" (ct-eval ctx "(greet {:lang :fr})")) "dispatch :fr")
(assert (ct-eval ctx "(try (greet {:lang :es}) (catch Exception e true))") "missing dispatch errors"))
(print " passed")
# 24. Multimethods — :default dispatch
(print "24: :default dispatch...")
(let [ctx (init)]
(ct-eval ctx "(defmulti classify :type :default :unknown)")
(ct-eval ctx "(defmethod classify :a [_] :alpha)")
# :default :unknown renames the catch-all dispatch key; a method must be
# registered under it (Clojure semantics).
(ct-eval ctx "(defmethod classify :unknown [_] :unknown)")
(assert (= :alpha (ct-eval ctx "(classify {:type :a})")) "known dispatch")
(assert (= :unknown (ct-eval ctx "(classify {:type :z})")) "default fallback"))
(print " passed")
# 25. Multimethods — hierarchy dispatch
(print "25: hierarchy dispatch...")
(let [ctx (init)]
(ct-eval ctx "(def h (make-hierarchy))")
(ct-eval ctx "(def h (derive h ::dog ::mammal))")
(ct-eval ctx "(def h (derive h ::mammal ::animal))")
(ct-eval ctx "(defmulti animal-sound (fn [x] x) :default :unknown :hierarchy h)")
(ct-eval ctx "(defmethod animal-sound ::animal [_] \"rawr\")")
(ct-eval ctx "(defmethod animal-sound ::dog [_] \"woof\")")
# catch-all method registered under the renamed default key :unknown
(ct-eval ctx "(defmethod animal-sound :unknown [_] :unknown)")
(assert (= "woof" (ct-eval ctx "(animal-sound ::dog)")) "direct dispatch")
(assert (= "rawr" (ct-eval ctx "(animal-sound ::mammal)")) "hierarchy fallback")
(assert (= :unknown (ct-eval ctx "(animal-sound ::rock)")) "default fallback"))
(print " passed")
# 26. remove-method
(print "26: remove-method...")
(let [ctx (init)]
(ct-eval ctx "(defmulti rmtest :k)")
(ct-eval ctx "(defmethod rmtest :a [_] 1)")
(ct-eval ctx "(defmethod rmtest :b [_] 2)")
(assert (= 1 (ct-eval ctx "(rmtest {:k :a})")) "before remove")
(ct-eval ctx "(remove-method (var rmtest) :a)")
(assert (ct-eval ctx "(try (rmtest {:k :a}) (catch Exception e true))") "removed method errors"))
(print " passed")
# 27. remove-all-methods
(print "27: remove-all-methods...")
(let [ctx (init)]
(ct-eval ctx "(defmulti alltest :k)")
(ct-eval ctx "(defmethod alltest :a [_] 1)")
(ct-eval ctx "(defmethod alltest :b [_] 2)")
(ct-eval ctx "(remove-all-methods (var alltest))")
(assert (ct-eval ctx "(try (alltest {:k :a}) (catch Exception e true))") "all methods removed errors"))
(print " passed")
(print "\nAll Phase 5 tests passed!")

View file

@ -0,0 +1,82 @@
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Phase 6: comprehensive compile-mode tests...")
(let [ctx (init {:compile? true})]
(print " collections...")
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
(assert (= true (ct-eval ctx "(vector? [1 2])")) "vector?")
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
(assert (= 1 (ct-eval ctx "(get {:a 1 :b 2} :a)")) "get map")
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count map")
(assert (= [1 2 3] (ct-eval ctx "(into [1] [2 3])")) "into")
(print " core math...")
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min")
(print " predicates...")
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?")
(assert (= false (ct-eval ctx "(not true)")) "not")
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
(assert (= true (ct-eval ctx "(>= 2 2)")) ">=")
(print " seq operations...")
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
(assert (= [2 4] (ct-eval ctx "(filter even? [1 2 3 4])")) "filter")
(assert (= [1 3] (ct-eval ctx "(remove even? [1 2 3 4])")) "remove")
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
(print " special forms...")
(assert (= 30 (ct-eval ctx "(let [x 10 y 20] (+ x y))")) "let")
(assert (= :a (ct-eval ctx "(if true :a :b)")) "if true")
(assert (= :b (ct-eval ctx "(if false :a :b)")) "if false")
(assert (= 3 (ct-eval ctx "(loop [x 0] (if (< x 3) (recur (inc x)) x))")) "loop")
(assert (= "caught" (ct-eval ctx "(try (throw 42) (catch Exception e \"caught\"))")) "try")
(assert (= 42 (ct-eval ctx "'42")) "quote literal")
(print " macros...")
(ct-eval ctx "(defn add [a b] (+ a b))")
(assert (= 7 (ct-eval ctx "(add 3 4)")) "defn")
(assert (= 42 (ct-eval ctx "(when true 42)")) "when true")
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and")
(assert (= 1 (ct-eval ctx "(or 1 2 3)")) "or")
(assert (= 49 (ct-eval ctx "((fn [x] (* x x)) 7)")) "fn macro")
(assert (= 2 (ct-eval ctx "(if-let [x 1] (inc x) 0)")) "if-let")
(print " complex...")
(assert (= 6 (ct-eval ctx "(let [f (fn [n] (loop [i 0 acc 0] (if (< i n) (recur (inc i) (+ acc i)) acc)))] (f 4))")) "nested")
(assert (= 15 (ct-eval ctx "(reduce + (map inc [0 1 2 3 4]))")) "reduce+map"))
(print "\nAll Phase 6 tests passed!")

View file

@ -0,0 +1,36 @@
# Phase 6: Reader Extensions Tests
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "28: #inst tagged literal...")
(let [ctx (init)]
(let [val (ct-eval ctx "#inst \"2024-01-15\"")]
(assert (= "2024-01-15" val) "#inst string"))
(let [val (ct-eval ctx "#inst \"2024-01-15T10:30:00Z\"")]
(assert (= "2024-01-15T10:30:00Z" val) "#inst timestamp")))
(print " passed")
(print "29: #uuid tagged literal...")
(let [ctx (init)]
(let [val (ct-eval ctx "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")]
(assert (= "550e8400-e29b-41d4-a716-446655440000" val) "#uuid string")))
(print " passed")
(print "30: #? reader conditionals...")
(let [ctx (init)]
(assert (= :yes (ct-eval ctx "#?(:clj :yes :cljs :no)")) "#? selects :clj")
(assert (= :yes (ct-eval ctx "#?(:cljs :no :default :yes)")) "#? :default fallback")
(assert (= nil (ct-eval ctx "#?(:cljs :no)")) "#? nil on no match"))
(print " passed")
(print "31: #?@ splicing...")
(let [ctx (init)]
(assert (= [1 2 3] (ct-eval ctx "[#?@(:clj [1 2 3] :cljs [4 5 6])]"))
"#?@ splices :clj")
(assert (= [99] (ct-eval ctx "[#?@(:cljs [1] :default [99])]"))
"#?@ :default fallback")
(assert (= [] (ct-eval ctx "[#?@(:cljs [1 2])]"))
"#?@ nothing on no match"))
(print " passed")
(print "\nAll Phase 6 tests passed!")

View file

@ -0,0 +1,25 @@
# Phase 7: LazySeq + PersistentHashSet completion
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "32: lazy-seq...")
(let [ctx (init)]
(let [ls (ct-eval ctx "(lazy-seq (cons 1 (lazy-seq (cons 2 nil))))")]
(assert (not (nil? ls)) "lazy-seq returns non-nil")
(assert (= 1 (ct-eval ctx "(first (lazy-seq (cons 1 nil)))")) "first of lazy"))
(assert (= true (ct-eval ctx "(= [1 2 3] (seq (lazy-seq [1 2 3])))")) "seq forces lazy")
(eval-string ctx "(def counter (atom 0))")
(def val (ct-eval ctx "(let [ls (lazy-seq (do (swap! counter inc) [1 2 3]))] (seq ls) (seq ls) @counter)"))
(assert (= 1 val) "realized once"))
(print " passed")
(print "33: PersistentHashSet...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set? true")
(assert (= false (ct-eval ctx "(set? [1 2 3])")) "set? false")
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj add")
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj")
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
(print "\nAll Phase 7 tests passed!")

View file

@ -0,0 +1,44 @@
# Phase 8: Protocol System Tests
(use ../../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "35: defprotocol...")
(let [ctx (init)]
(ct-eval ctx "(defprotocol Greet (greet [this]))")
(let [p (ct-eval ctx "Greet")]
(assert (not (nil? p)) "protocol var exists")
(assert (= :jolt/protocol (get p :jolt/type)) "protocol type tag")
(assert (get (get p :methods) :greet) "protocol has greet method"))
(assert (or (function? (ct-eval ctx "greet")) (cfunction? (ct-eval ctx "greet"))) "method fn exists"))
(print " passed")
(print "36: extend-type...")
(let [ctx (init)]
(ct-eval ctx "(deftype Person [name])")
(ct-eval ctx "(defprotocol Namable (get-name [this]))")
(ct-eval ctx "(extend-type Person Namable (get-name [this] (.-name this)))")
(assert (= "Alice" (ct-eval ctx "(get-name (Person. \"Alice\"))")) "extend-type works"))
(print " passed")
(print "37: extend-protocol...")
(let [ctx (init)]
(ct-eval ctx "(deftype Dog [breed])")
(ct-eval ctx "(deftype Cat [color])")
(ct-eval ctx "(defprotocol Animal (speak [this]))")
(ct-eval ctx "(extend-protocol Animal
Dog (speak [this] (str \"woof from \" (.-breed this)))
Cat (speak [this] (str \"meow from \" (.-color this))))")
(assert (= "woof from poodle" (ct-eval ctx "(speak (Dog. \"poodle\"))")) "dog speak")
(assert (= "meow from black" (ct-eval ctx "(speak (Cat. \"black\"))")) "cat speak"))
(print " passed")
(print "38: satisfies?...")
(let [ctx (init)]
(ct-eval ctx "(deftype Point [x y])")
(ct-eval ctx "(defprotocol Locatable (location [this]))")
(ct-eval ctx "(extend-type Point Locatable (location [this] [(.-x this) (.-y this)]))")
(assert (= true (ct-eval ctx "(satisfies? Locatable (Point. 3 4))")) "satisfies? true")
(assert (= false (ct-eval ctx "(satisfies? Locatable {:x 1})")) "satisfies? false"))
(print " passed")
(print "\nAll Phase 8 tests passed!")

View file

@ -0,0 +1,112 @@
(use ../../src/jolt/evaluator)
(use ../../src/jolt/types)
(use ../../src/jolt/reader)
(use ../../src/jolt/api)
(def ctx (init))
(printf "Loading SCI stubs...\n")
(defn load-stubs [ctx filepath]
(var s (slurp filepath))
(var count 0)
(while (> (length (string/trim s)) 0)
(def [form rest] (parse-next s))
(set s rest)
(++ count)
(when (not (nil? form))
(eval-form ctx @{} form)))
(printf " Loaded %d stub forms\n" count))
(load-stubs ctx "src/jolt/clojure/sci/lang_stubs.clj")
(load-stubs ctx "src/jolt/clojure/sci/io_stubs.clj")
(load-stubs ctx "src/jolt/clojure/sci/host_stubs.clj")
# namespaces.cljc copies vars out of Jolt's own clojure.string/set/walk/edn, so
# make sure those are loaded before it runs.
(each lib ["clojure.string" "clojure.set" "clojure.walk" "clojure.edn"]
(protect (eval-form ctx @{} (first (parse-next (string "(require '[" lib "])"))))))
(defn load-file [ctx path]
(var s (slurp path))
(var count 0)
(var ok 0)
(var fail 0)
(var failures @[])
(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)
(if (try
(do (eval-form ctx @{} form) true)
([err fib]
(printf " FAIL: %q\n" err)
(when (os/getenv "SCI_TRACE") (debug/stacktrace fib ""))
(array/push failures {:form-number count :error (string err) :form (string form)})
false))
(do
(printf " OK\n")
(++ ok))
(++ fail)))))
{:ok ok :fail fail :total count :failures failures})
(def sci-base "vendor/sci/src/sci")
(def load-order @[
["impl/macros.cljc" nil]
["impl/protocols.cljc" nil]
["impl/types.cljc" nil]
["impl/unrestrict.cljc" nil]
["impl/vars.cljc" nil]
["lang.cljc" nil]
["impl/utils.cljc" nil]
["ctx_store.cljc" nil]
["impl/deftype.cljc" nil]
["impl/records.cljc" nil]
["impl/core_protocols.cljc" nil]
["impl/hierarchies.cljc" nil]
# pure-Clojure macro/expander modules (loadable from SCI's real source)
["impl/destructure.cljc" nil]
["impl/doseq_macro.cljc" nil]
["impl/for_macro.cljc" nil]
["impl/fns.cljc" nil]
["impl/multimethods.cljc" nil]
["impl/namespaces.cljc" nil]
["core.cljc" nil]
])
(var total-ok 0)
(var total-fail 0)
(var all-failures @[])
(each [file expected-ns] load-order
(def path (string sci-base "/" file))
(printf "\n=== Loading %s ===\n" file)
(def result (load-file ctx path))
(printf " Result: %d ok, %d fail, %d total\n" (result :ok) (result :fail) (result :total))
(+= total-ok (result :ok))
(+= total-fail (result :fail))
(each f (result :failures)
(array/push all-failures {:file file :form-number (f :form-number) :error (f :error) :form (f :form)})))
(printf "\n==============================\n")
(printf "TOTAL: %d ok, %d fail, %d total\n" total-ok total-fail (+ total-ok total-fail))
(printf "==============================\n")
(printf "\ncurrent ns: %s\n" (ctx-current-ns ctx))
(printf "sci.core exists: %q\n" (not (nil? (ctx-find-ns ctx "sci.core"))))
(printf "total namespaces: %d\n" (length (keys ((ctx :env) :namespaces))))
(when (> (length all-failures) 0)
(printf "\n=== FAILURES ===\n")
(each f all-failures
(printf "[%s:%d] %s\n" (f :file) (f :form-number) (f :error))
(printf " form: %s\n" (f :form))))
# Regression guard: every form in the loaded SCI modules must evaluate cleanly.
(assert (= 0 total-fail)
(string total-fail " SCI form(s) failed to load (see FAILURES above)"))
(print "\nAll SCI bootstrap forms loaded successfully.")

View file

@ -0,0 +1,95 @@
(use ../../src/jolt/evaluator)
(use ../../src/jolt/types)
(use ../../src/jolt/reader)
(use ../../src/jolt/api)
(defn- load-stubs [ctx filepath]
(var s (slurp filepath))
(while (> (length (string/trim s)) 0)
(def [form rest] (parse-next s))
(set s rest)
(when (not (nil? form))
(protect (eval-form ctx @{} form)))))
(defn- load-file [ctx path]
(var s (slurp path))
(while (> (length (string/trim s)) 0)
(def [form rest] (parse-next s))
(set s rest)
(when (not (nil? form))
# Tolerant: SCI's clojure.core registration maps reference the full
# clojure.core surface (redundant for Jolt's native core); skip forms
# that don't resolve rather than aborting the bootstrap.
(protect (eval-form ctx @{} form)))))
# Run from project root so paths resolve
(def root (if (has-value? (dyn :syspath) 0) (first (dyn :syspath)) "."))
(def ctx (init))
(load-stubs ctx (string root "/src/jolt/clojure/sci/lang_stubs.clj"))
(load-stubs ctx (string root "/src/jolt/clojure/sci/io_stubs.clj"))
(def sci-base (string root "/vendor/sci/src/sci"))
(each file ["impl/macros.cljc" "impl/protocols.cljc" "impl/types.cljc"
"impl/unrestrict.cljc" "impl/vars.cljc" "lang.cljc"
"impl/utils.cljc" "ctx_store.cljc" "impl/deftype.cljc"
"impl/records.cljc" "impl/core_protocols.cljc" "impl/hierarchies.cljc"
"impl/namespaces.cljc" "core.cljc"]
(load-file ctx (string sci-base "/" file)))
# ── Verify sci.lang NS and Type ─────────────────────────────────
(assert (not (nil? (ctx-find-ns ctx "sci.lang")))
"sci.lang namespace exists")
(assert (not (nil? (ctx-find-ns ctx "sci.core")))
"sci.core namespace exists")
# sci.lang has Type constructor
(def sci-lang (ctx-find-ns ctx "sci.lang"))
(def type-var (ns-find sci-lang "Type"))
(assert (not (nil? type-var)) "sci.lang/Type var exists")
(def ->Type (ns-find sci-lang "->Type"))
(assert (not (nil? ->Type)) "sci.lang/->Type constructor exists")
# Instantiate a Type and check field access
(def type-inst ((var-get type-var) {:sci.impl/type-name "user.Foo"}))
(assert (table? type-inst) "Type instance is a table")
(assert (not (nil? (get type-inst :jolt/deftype))) "Type instance has deftype tag")
(assert (= "user.Foo" (get (get type-inst :data) :sci.impl/type-name)) "Type field access via data")
# ── Verify sci.lang/Var ─────────────────────────────────────────
(def var-ctor-var (ns-find sci-lang "Var"))
(assert (not (nil? var-ctor-var)) "sci.lang/Var constructor exists")
(def test-var ((var-get var-ctor-var) 42 'my-var nil nil nil nil nil))
(assert (table? test-var) "Var instance is a table")
(assert (= 42 (get test-var :root)) "Var deref")
# var? check — SCI Var is not a Jolt var but is a table with proper fields
(assert (not (nil? test-var)) "Var instance is not nil")
# ── Verify sci.impl.types/IBox protocol ─────────────────────────
(def types-ns (ctx-find-ns ctx "sci.impl.types"))
(def vars-ns (ctx-find-ns ctx "sci.impl.vars"))
(assert (not (nil? types-ns)) "sci.impl.types namespace exists")
(assert (not (nil? vars-ns)) "sci.impl.vars namespace exists")
(def ibox-getVal (ns-find types-ns "getVal"))
(def ibox-setVal (ns-find types-ns "setVal"))
(assert (not (nil? ibox-getVal)) "sci.impl.types/getVal exists")
(assert (not (nil? ibox-setVal)) "sci.impl.types/setVal exists")
# Test IBox setVal/getVal exist but skip dispatch (SCI protocol machinery not fully booted)
(assert (function? (var-get ibox-setVal)) "sci.impl.types/setVal is callable")
(assert (function? (var-get ibox-getVal)) "sci.impl.types/getVal is callable")
# ── Verify sci.impl.vars/IVar protocol methods exist ─────────────
(def ivar-toSymbol (ns-find vars-ns "toSymbol"))
(def ivar-hasRoot (ns-find vars-ns "hasRoot"))
(assert (not (nil? ivar-toSymbol)) "sci.impl.vars/toSymbol exists")
(assert (not (nil? ivar-hasRoot)) "sci.impl.vars/hasRoot exists")
# ── Verify SCI eval function exists ─────────────────────────────
(def sci-core (ctx-find-ns ctx "sci.core"))
(assert (not (nil? sci-core)) "sci.core namespace exists")
(printf "\nAll SCI runtime tests passed!\n")

View file

@ -0,0 +1,212 @@
# Systematic coverage tests for Clojure language features
(use ../../src/jolt/api)
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
(print "Systematic Coverage Tests")
# --- Type Predicates ---
(print "1: type predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(integer? 0)")) "integer? 0")
(assert (= true (ct-eval ctx "(integer? 1)")) "integer? 1")
(assert (= true (ct-eval ctx "(integer? -5)")) "integer? negative")
(assert (= false (ct-eval ctx "(integer? 1.5)")) "integer? float")
(assert (= false (ct-eval ctx "(integer? nil)")) "integer? nil")
(assert (= false (ct-eval ctx "(integer? \"abc\")")) "integer? string")
(assert (= true (ct-eval ctx "(boolean? true)")) "boolean? true")
(assert (= true (ct-eval ctx "(boolean? false)")) "boolean? false")
(assert (= false (ct-eval ctx "(boolean? 1)")) "boolean? falsy")
(assert (= false (ct-eval ctx "(boolean? nil)")) "boolean? nil")
(assert (= true (ct-eval ctx "(nil? nil)")) "nil? nil")
(assert (= false (ct-eval ctx "(nil? false)")) "nil? false")
(assert (= false (ct-eval ctx "(nil? 0)")) "nil? 0")
(assert (= false (ct-eval ctx "(nil? [])")) "nil? empty vec")
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec")
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
(assert (= false (ct-eval ctx "(string? 42)")) "string? false")
(assert (= true (ct-eval ctx "(string? \"\")")) "string? empty")
(assert (= true (ct-eval ctx "(number? 42)")) "number? int")
(assert (= true (ct-eval ctx "(number? 3.14)")) "number? float")
(assert (= false (ct-eval ctx "(number? \"42\")")) "number? string")
(assert (= true (ct-eval ctx "(fn? inc)")) "fn? builtin")
(assert (= false (ct-eval ctx "(fn? 42)")) "fn? false")
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
(assert (= false (ct-eval ctx "(keyword? \"foo\")")) "keyword? false")
(assert (= true (ct-eval ctx "(symbol? 'abc)")) "symbol?")
(assert (= false (ct-eval ctx "(symbol? :abc)")) "symbol? false")
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
(assert (= false (ct-eval ctx "(map? [1 2])")) "map? false")
(assert (= true (ct-eval ctx "(set? #{1 2})")) "set?")
(assert (= false (ct-eval ctx "(set? [1 2])")) "set? false")
(assert (= true (ct-eval ctx "(seq? '(1 2))")) "seq? list")
(assert (= true (ct-eval ctx "(seq? [1 2])")) "seq? vector")
(assert (= true (ct-eval ctx "(coll? [1 2])")) "coll? vec")
(assert (= true (ct-eval ctx "(coll? '(1 2))")) "coll? list")
(assert (= true (ct-eval ctx "(coll? {})")) "coll? map")
(assert (= true (ct-eval ctx "(true? true)")) "true? true")
(assert (= false (ct-eval ctx "(true? 1)")) "true? 1")
(assert (= true (ct-eval ctx "(false? false)")) "false? false")
(assert (= false (ct-eval ctx "(false? nil)")) "false? nil")
(assert (= true (ct-eval ctx "(identical? 42 42)")) "identical? same value"))
(print " ok")
# --- Number Predicates ---
(print "2: number predicates...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(zero? 0)")) "zero? 0")
(assert (= false (ct-eval ctx "(zero? 1)")) "zero? 1")
(assert (= false (ct-eval ctx "(zero? nil)")) "zero? nil")
(assert (= true (ct-eval ctx "(pos? 1)")) "pos?")
(assert (= false (ct-eval ctx "(pos? 0)")) "pos? 0")
(assert (= false (ct-eval ctx "(pos? -1)")) "pos? -1")
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
(assert (= false (ct-eval ctx "(neg? 0)")) "neg? 0")
(assert (= false (ct-eval ctx "(neg? 1)")) "neg? 1")
(assert (= true (ct-eval ctx "(even? 0)")) "even? 0")
(assert (= true (ct-eval ctx "(even? 2)")) "even? 2")
(assert (= false (ct-eval ctx "(even? 1)")) "even? 1")
(assert (= true (ct-eval ctx "(odd? 1)")) "odd? 1")
(assert (= true (ct-eval ctx "(odd? 3)")) "odd? 3")
(assert (= false (ct-eval ctx "(odd? 2)")) "odd? 2"))
(print " ok")
# --- Math ---
(print "3: math operations...")
(let [ctx (init)]
(assert (= 0 (ct-eval ctx "(+)")) "+ 0 args")
(assert (= 5 (ct-eval ctx "(+ 2 3)")) "+ 2 args")
(assert (= 10 (ct-eval ctx "(+ 1 2 3 4)")) "+ varargs")
(assert (= -5 (ct-eval ctx "(- 5)")) "- unary")
(assert (= 2 (ct-eval ctx "(- 5 3)")) "- binary")
(assert (= 1 (ct-eval ctx "(*)")) "* 0 args")
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
(assert (= 0.5 (ct-eval ctx "(/ 2)")) "/ unary reciprocal")
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/ binary")
(assert (= 2 (ct-eval ctx "(quot 5 2)")) "quot")
(assert (= 1 (ct-eval ctx "(rem 5 2)")) "rem")
(assert (= 1 (ct-eval ctx "(mod 5 2)")) "mod")
(assert (= 43 (ct-eval ctx "(inc 42)")) "inc")
(assert (= 41 (ct-eval ctx "(dec 42)")) "dec")
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min")
(assert (= 5 (ct-eval ctx "(abs -5)")) "abs negative")
(assert (= 5 (ct-eval ctx "(abs 5)")) "abs positive")
(assert (= 0 (ct-eval ctx "(abs 0)")) "abs 0")
(assert (= 3.14 (ct-eval ctx "(abs -3.14)")) "abs float")
(assert (= true (ct-eval ctx "(< (rand) 1)")) "rand < 1")
(assert (= true (ct-eval ctx "(number? (rand-int 10))")) "rand-int type"))
(print " ok")
# --- Comparison ---
(print "4: comparison...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= 1 1)")) "= same")
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= multi same")
(assert (= false (ct-eval ctx "(= 1 2)")) "= different")
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= different")
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= same")
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
(assert (= false (ct-eval ctx "(< 2 1)")) "< false")
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
(print " ok")
# --- Boolean logic ---
(print "5: boolean logic...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(and)")) "and empty")
(assert (= true (ct-eval ctx "(and true)")) "and true")
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
(assert (= false (ct-eval ctx "(and false)")) "and false")
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and last")
(assert (= nil (ct-eval ctx "(and 1 nil 3)")) "and short-circuit")
(assert (= nil (ct-eval ctx "(or)")) "or empty")
(assert (= true (ct-eval ctx "(or true)")) "or true")
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
(assert (= false (ct-eval ctx "(or false)")) "or false")
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or first truthy")
(assert (= false (ct-eval ctx "(or nil false)")) "or all falsy")
(assert (= false (ct-eval ctx "(not true)")) "not true")
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
(assert (= true (ct-eval ctx "(not false)")) "not false"))
(print " ok")
# --- Collections ---
(print "6: collections...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(empty? nil)")) "empty? nil")
(assert (= true (ct-eval ctx "(empty? [])")) "empty? []")
(assert (= true (ct-eval ctx "(empty? ())")) "empty? ()")
(assert (= true (ct-eval ctx "(empty? {})")) "empty? {}")
(assert (= true (ct-eval ctx "(empty? #{})")) "empty? #{}")
(assert (= true (ct-eval ctx "(empty? \"\")")) "empty? empty string")
(assert (= false (ct-eval ctx "(empty? [1])")) "empty? non-empty")
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every? true")
(assert (= false (ct-eval ctx "(every? even? [2 3 4])")) "every? false")
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count vector")
(assert (= 2 (ct-eval ctx "(count {:a 1 :b 2})")) "count map")
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count set")
(assert (= 3 (ct-eval ctx "(count \"abc\")")) "count string"))
(print " ok")
# --- Sequence Operations ---
(print "7: sequence operations...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
(assert (= nil (ct-eval ctx "(first [])")) "first empty")
(assert (= nil (ct-eval ctx "(first nil)")) "first nil")
(assert (= :a (ct-eval ctx "(nth [:a :b :c] 0)")) "nth 0")
(assert (= :c (ct-eval ctx "(nth [:a :b :c] 2)")) "nth 2")
(assert (= :d (ct-eval ctx "(nth [:a :b :c] 3 :d)")) "nth default")
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty -> nil")
(assert (= nil (ct-eval ctx "(seq nil)")) "seq nil -> nil")
(assert (= true (ct-eval ctx "(= [2 3 4] (map inc [1 2 3]))")) "map")
(assert (= true (ct-eval ctx "(= [2 4] (filter even? [1 2 3 4]))")) "filter")
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
(assert (= 10 (ct-eval ctx "(reduce + 4 [1 2 3])")) "reduce init")
(assert (= true (ct-eval ctx "(= [1 2] (take 2 [1 2 3 4]))")) "take")
(assert (= true (ct-eval ctx "(= [3 4] (drop 2 [1 2 3 4]))")) "drop")
(assert (= true (ct-eval ctx "(= [3 2 1] (reverse [1 2 3]))")) "reverse")
(assert (= true (ct-eval ctx "(= 3 (count (distinct [1 1 2 2 3 3])))")) "distinct"))
(print " ok")
# --- Collections: conj, assoc, dissoc, get ---
(print "8: collection mutation...")
(let [ctx (init)]
(assert (= true (ct-eval ctx "(= [1 2 3] (conj [1 2] 3))")) "conj vector")
(assert (= true (ct-eval ctx "(= (quote (0 1 2)) (conj (quote (1 2)) 0))")) "conj list prepend")
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} (assoc {:a 1} :b 2))")) "assoc")
(assert (= true (ct-eval ctx "(= {:a 1} (dissoc {:a 1 :b 2} :b))")) "dissoc")
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains? map")
(assert (= false (ct-eval ctx "(contains? {:a 1} :z)")) "contains? missing")
(assert (= true (ct-eval ctx "(contains? [5 6 7] 1)")) "contains? vector")
(assert (= false (ct-eval ctx "(contains? [5 6 7] 3)")) "contains? vector oob"))
(print " ok")
# --- Higher-order functions ---
(print "9: higher-order functions...")
(let [ctx (init)]
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
(assert (= 42 (ct-eval ctx "(identity 42)")) "identity")
(assert (= 99 (ct-eval ctx "((constantly 99) :anything)")) "constantly")
(assert (= true (ct-eval ctx "(= 10 ((partial + 3 7)))")) "partial")
(assert (= true (ct-eval ctx "((every-pred even? pos?) 4)")) "every-pred true")
(assert (= false (ct-eval ctx "((every-pred even? pos?) -4)")) "every-pred false")
(assert (= false (ct-eval ctx "((complement even?) 2)")) "complement"))
(print " ok")
# --- Destructuring ---
(print "10: destructuring...")
(let [ctx (init)]
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure first")
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure second"))
(print " ok")
(print "\nAll Systematic Coverage tests passed!")