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.
129 lines
5.1 KiB
Text
129 lines
5.1 KiB
Text
(use ../../src/jolt/reader)
|
|
(use ../../src/jolt/types)
|
|
(use ../../src/jolt/evaluator)
|
|
|
|
# Helper: create a Jolt symbol
|
|
(defn sym [name]
|
|
(let [slash (string/find "/" name)]
|
|
(if slash
|
|
{:jolt/type :symbol :ns (string/slice name 0 slash)
|
|
:name (string/slice name (+ slash 1))}
|
|
{:jolt/type :symbol :ns nil :name name})))
|
|
|
|
# Helper: parse and eval
|
|
(defn eval-str [s]
|
|
(let [ctx (make-ctx)
|
|
form (parse-string s)]
|
|
(eval-form ctx @{} form)))
|
|
|
|
# ============================================================
|
|
# 1. syntax-quote — literals pass through
|
|
# ============================================================
|
|
(print "1: syntax-quote literals...")
|
|
(assert (= 42 (eval-str "`42")) "syntax-quote number")
|
|
(assert (= "hello" (eval-str "`\"hello\"")) "syntax-quote string")
|
|
(assert (= :foo (eval-str "`:foo")) "syntax-quote keyword")
|
|
(assert (= nil (eval-str "`nil")) "syntax-quote nil")
|
|
(assert (= true (eval-str "`true")) "syntax-quote true")
|
|
(assert (= false (eval-str "`false")) "syntax-quote false")
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 2. syntax-quote — qualify symbols
|
|
# ============================================================
|
|
(print "2: syntax-quote qualifies symbols...")
|
|
# In the 'user namespace, `x → user/x
|
|
(let [form (eval-str "`x")]
|
|
(assert (deep= {:jolt/type :symbol :ns "user" :name "x"} form)
|
|
"qualifies bare symbol to current ns"))
|
|
|
|
# Already qualified symbols stay as-is
|
|
(let [form (eval-str "`foo/bar")]
|
|
(assert (deep= {:jolt/type :symbol :ns "foo" :name "bar"} form)
|
|
"qualified symbol unchanged"))
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 3. syntax-quote — lists: qualify symbols, literal items as-is
|
|
# ============================================================
|
|
(print "3: syntax-quote lists...")
|
|
# `(+ 1 2) → (user/+ 1 2) — but 1 and 2 are numbers, stay as-is
|
|
(let [form (eval-str "`(+ 1 2)")]
|
|
(assert (array? form) "syntax-quote list is array")
|
|
(assert (= 3 (length form)) "has 3 elements")
|
|
(assert (deep= {:jolt/type :symbol :ns "user" :name "+"} (in form 0))
|
|
"operator qualified")
|
|
(assert (= 1 (in form 1)) "number stays")
|
|
(assert (= 2 (in form 2)) "number stays"))
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 4. unquote inside syntax-quote
|
|
# ============================================================
|
|
(print "4: unquote...")
|
|
# `~x inside (let* [x 10] ...) → 10
|
|
(let [form (eval-str "(let* [x 10] `~x)")]
|
|
(assert (= 10 form) "unquote evaluates"))
|
|
# `(~x) produces a list containing x
|
|
(let [form2 (eval-str "(let* [x 10] `(~x))")]
|
|
(assert (deep= @[10] form2) "unquote in list"))
|
|
|
|
# `(+ ~x ~y) with x=1 y=2 → (+ 1 2)
|
|
(let [form (eval-str "(let* [x 1 y 2] `(+ ~x ~y))")]
|
|
(assert (array? form) "result is list")
|
|
(assert (= 1 (in form 1)) "first unquoted value")
|
|
(assert (= 2 (in form 2)) "second unquoted value"))
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 5. unquote-splicing inside syntax-quote
|
|
# ============================================================
|
|
(print "5: unquote-splicing...")
|
|
# `[1 2 ~@xs] with xs = (3 4) → [1 2 3 4]
|
|
(let [form (eval-str "(let* [xs '(3 4)] `[1 2 ~@xs])")]
|
|
(assert (tuple? form) "result is vector")
|
|
(assert (= 4 (length form)) "spliced items merged")
|
|
(assert (deep= [1 2 3 4] form) "correct items"))
|
|
|
|
# `(1 ~@xs) with xs = (2 3) → (1 2 3)
|
|
(let [form (eval-str "(let* [xs '(2 3)] `(1 ~@xs))")]
|
|
(assert (array? form) "result is list")
|
|
(assert (= 3 (length form)) "spliced into list")
|
|
(assert (deep= @[1 2 3] form) "correct items"))
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 6. Macro function application
|
|
# ============================================================
|
|
(print "6: macro application...")
|
|
|
|
# Define a simple macro: (my-when test body) → (if test body nil)
|
|
(def ctx (make-ctx))
|
|
(def macro-fn-form (parse-string "(fn* [test body] (if test body nil))"))
|
|
(def macro-fn (eval-form ctx @{} macro-fn-form))
|
|
# intern it in user namespace with string key
|
|
(let [ns (ctx-find-ns ctx "user")]
|
|
(ns-intern ns "my-when" macro-fn)
|
|
(put (ns-find ns "my-when") :macro true))
|
|
|
|
# (my-when true 42) should expand to (if true 42 nil), evaluating to 42
|
|
(let [form (parse-string "(my-when true 42)")]
|
|
(assert (= 42 (eval-form ctx @{} form)) "macro application returns correct value"))
|
|
|
|
# (my-when false 99) should expand to (if false 99 nil), evaluating to nil
|
|
(let [form (parse-string "(my-when false 99)")]
|
|
(assert (= nil (eval-form ctx @{} form)) "macro returns nil when false"))
|
|
(print " passed")
|
|
|
|
# ============================================================
|
|
# 7. Nested syntax-quote
|
|
# ============================================================
|
|
(print "7: nested syntax-quote...")
|
|
# ``x → (syntax-quote user/x)
|
|
(let [form (eval-str "``x")]
|
|
(assert (array? form) "nested syntax-quote produces list")
|
|
(assert (deep= {:jolt/type :symbol :ns nil :name "syntax-quote"} (in form 0))
|
|
"outer is syntax-quote"))
|
|
(print " passed")
|
|
|
|
(print "\nAll macro tests passed!")
|