* test: adapt jank's form/reader tests into spec suites; fix case no-match
Vendoring jank's behavior (not the project): we base our own copies on the
jank test corpus to close coverage gaps, but maintain them ourselves since
jank may diverge. Two new spec batteries (jank-isms translated to Jolt:
letfn* -> letfn, jank catch types -> :default; platform-specific bigdec/
biginteger/ratio/uuid/##Inf/unicode cases omitted):
- test/spec/forms-spec.janet (52): case, fn (arity/variadic/closure/recur/
named), let, letfn, loop, try, if/do/def/call — incl :throws regression
cases (no-match, bad params, nil call).
- test/spec/reader-forms-spec.janet (22): #() (% %N %&), #' var-quote,
^metadata, syntax-quote (gensym/unquote/splice).
Fix surfaced by adaptation: case with no matching clause and no default now
throws 'No matching clause' (Clojure semantics) instead of returning nil
(00-syntax). Gate green incl full jpm build+test.
Other gaps the adaptation surfaced are filed (tests adjusted to jolt's
current behavior + a comment, not silently dropped):
jolt-vdo case duplicate test constants not rejected
jolt-w2v loop bindings not sequential (later init can't see earlier)
jolt-6x1 #() %& miscomputes arity with a higher positional (%2 …)
jolt-xl0 ^meta not attached to collection literals ({}/[]/#{})
jolt-265 syntax-quote doesn't fully-qualify core syms to clojure.core/
jolt-edb syntax-quote ~/~@ not processed inside set literals
* core: fix 5 Clojure-conformance gaps surfaced by jank tests
All from adapting jank's form/reader tests; each fix verified in interpret +
compile modes and the spec tests now assert the correct behavior.
- jolt-vdo: case now rejects duplicate test constants at expansion (Clojure
compile error), via bootstrap-safe duplicate detection (00-syntax; analyzer.clj
uses case during its own build, so seed-only fns).
- jolt-w2v: loop bindings are now sequential like let — a later init can
reference an earlier binding. Fixed the interpreter loop* (accumulating scope)
and the back end emit-loop (bind initial inits in a sequential Janet let before
entering the recur target).
- jolt-6x1: #() reader computes the fixed arity from the MAX positional (%2 ->
[p1 p2 & rest]); % and %1 unify; unused lower slots get placeholder params.
- jolt-xl0: ^meta on collection literals ({}/[]/#{}) now attaches — read-meta
passes the NORMALIZED metadata map to with-meta (was the raw meta-form).
- jolt-edb: syntax-quote processes ~/~@ inside set literals (new __sqset builder
in core + set branches in syntax-quote* and syntax-quote-lower).
Deferred: jolt-265 (fully-qualify core syms to clojure.core/ in syntax-quote) —
it passes conformance but breaks the standalone uberscript (the ns macro emits
unqualified require/in-ns, which then qualify and break bundled require/alias).
Reverted to bare (functionally resolves); re-opened with the finding.
Gate green incl full jpm build + jpm test: conformance 269x3, suite >=4034/67,
fixpoint, self-host, sci 422/0, uberscript, all unit + spec (forms 55, reader 31).
---------
Co-authored-by: Yogthos <yogthos@gmail.com>
50 lines
2.6 KiB
Text
50 lines
2.6 KiB
Text
# Specification: reader forms + syntax-quote + metadata.
|
|
#
|
|
# Adapted from the jank test corpus (test/jank/{syntax-quote,metadata,reader-macro,
|
|
# call}); we keep our own copies since jank may diverge. Syntax-quoted symbols are
|
|
# qualified to clojure.core (matching jank/Clojure). Platform-specific reader forms
|
|
# (#uuid, #inst, ##Inf/##NaN, bigdecimal/biginteger/ratio) are omitted.
|
|
(use ../support/harness)
|
|
|
|
(defspec "reader / anonymous fn #()"
|
|
["no args" "3" "(#(+ 1 2))"]
|
|
["one arg %" "6" "(#(* % 2) 3)"]
|
|
["positional %1 %2" "[1 2]" "(#(do [%1 %2]) 1 2)"]
|
|
["rest %&" "[1 2 3]" "(#(do %&) 1 2 3)"]
|
|
["fixed + rest" "[2 3]" "(#(do % %&) 1 2 3)"]
|
|
["%2 + rest" "[3]" "(#(do %2 %&) 1 2 3)"]
|
|
["%2 only (placeholder p1)" "20" "(#(* %2 2) 1 10)"]
|
|
["% and %1 same" "10" "(#(+ % %1) 5)"])
|
|
|
|
(defspec "reader / var-quote #'"
|
|
["var-quote = var" "true" "(= (var str) #'str)"]
|
|
["is a var" "true" "(var? #'str)"]
|
|
["deref var-quote" "5" "(do (def w 5) (deref #'w))"])
|
|
|
|
(defspec "reader / metadata ^"
|
|
["meta on map" "true" "(:foo (meta ^:foo {}))"]
|
|
["meta on vector" "true" "(:foo (meta ^:foo [1 2]))"]
|
|
["meta on set" "true" "(:foo (meta ^:foo #{}))"]
|
|
["meta map form" "1" "(:a (meta ^{:a 1} {}))"]
|
|
["meta on quoted sym" "true" "(:foo (meta (quote ^:foo bar)))"]
|
|
["with-meta map" "true" "(:k (meta (with-meta {} {:k true})))"]
|
|
["with-meta vector" "true" "(:k (meta (with-meta [] {:k true})))"]
|
|
["non-metadatable num" "nil" "(meta 100)"]
|
|
["non-metadatable str" "nil" "(meta \"\")"]
|
|
["non-metadatable bool" "nil" "(meta true)"])
|
|
|
|
(defspec "reader / syntax-quote"
|
|
["plain literal" "[1 2 3]" "`[1 2 3]"]
|
|
["gensym distinct" "true" "(not= `meow# `meow#)"]
|
|
["gensym stable" "true" "(let [s `[meow# meow#]] (= (first s) (second s)))"]
|
|
["qualifies unresolved" "(quote user/foo)" "`foo"]
|
|
["unquote value" "[1 2 3]" "(let [a [1 2 3]] `~a)"]
|
|
# functional: the syntax-quoted call evaluates correctly. (jolt-265: core syms are
|
|
# left bare rather than qualified to clojure.core/ — full qualification breaks the
|
|
# standalone uberscript's ns macro, so it's deferred; they still resolve at eval.)
|
|
["unquote call evals" "6" "(let [a 5] (eval `(+ ~a 1)))"]
|
|
["splice call evals" "6" "(let [a [1 2 3]] (eval `(+ ~@a)))"]
|
|
["splice in vector" "[1 2 3 0 1 2 3]" "(let [b [0] a [1 2 3] e []] `[~@e ~@a ~@b ~@a ~@e])"]
|
|
# jolt-edb (fixed): ~/~@ inside set literals.
|
|
["splice in set" "#{0 1 2 3}" "(let [b [0] a [1 2 3] e []] `#{~@e ~@a ~@b})"]
|
|
["unquote in set" "#{5 9}" "(let [x 5] `#{~x 9})"])
|