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).
This commit is contained in:
Yogthos 2026-06-09 21:32:51 -04:00
parent 3c1e0214dd
commit e859d3e8e7
7 changed files with 128 additions and 49 deletions

View file

@ -18,8 +18,9 @@
["nil match" ":nada" "(case nil nil :nada :default)"]
["default" ":def" "(case 99 1 :one 2 :two :def)"]
["list of consts" ":vowel" "(case \\a (\\a \\e \\i \\o \\u) :vowel :consonant)"]
["no match no default" :throws "(case 5 1 :one)"])
# gap (jolt-vdo): case allows duplicate test constants — Clojure compile-errors.
["no match no default" :throws "(case 5 1 :one)"]
["duplicate keys" :throws "(case 1 1 :one 1 :dup :default)"]
["duplicate in or-group" :throws "(case 2 (1 2) :a (2 3) :b :default)"])
(defspec "forms / fn"
["named fn nil" "nil" "((fn* foo-bar []))"]
@ -52,9 +53,8 @@
(defspec "forms / loop"
["sum" "55" "(loop* [sum 0 cnt 10] (if (= cnt 0) sum (recur (+ cnt sum) (dec cnt))))"]
["multi binding" "[4 2]" "(loop* [a 1 b 2 n 0] (if (< n 3) (recur (inc a) b (inc n)) [a b]))"])
# gap (jolt-w2v): loop bindings aren't sequential — a later init can't reference an
# earlier binding (Clojure's loop is like let). (loop* [a 1 b (+ a 1)] …) errors.
["multi binding" "[4 2]" "(loop* [a 1 b 2 n 0] (if (< n 3) (recur (inc a) b (inc n)) [a b]))"]
["init sees prior" "[1 2 3]" "(loop* [a 1 b (+ a 1) c (+ b 1)] [a b c])"])
(defspec "forms / try"
["immediate throw caught" ":caught" "(try (throw :boom) (catch :default e :caught))"]