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:
parent
1898308926
commit
16428179fa
52 changed files with 185 additions and 86 deletions
129
test/unit/macro-test.janet
Normal file
129
test/unit/macro-test.janet
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
(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!")
|
||||
Loading…
Add table
Add a link
Reference in a new issue