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:
parent
3c1e0214dd
commit
e859d3e8e7
7 changed files with 128 additions and 49 deletions
|
|
@ -296,6 +296,26 @@
|
|||
(if (seq? c)
|
||||
`(or ~@(map (fn [v] `(= ~g ~(mk-const v))) c))
|
||||
`(= ~g ~(mk-const c))))
|
||||
;; Collect test constants pairwise (so a trailing unpaired default is
|
||||
;; excluded), flattening list/or-group tests into individual constants.
|
||||
;; seed-only fns (reduce/conj/first/rest/drop/empty?/seq?) — analyzer.clj
|
||||
;; uses case during its own build, before some/distinct load.
|
||||
collect (fn* collect [cls acc]
|
||||
(if (or (empty? cls) (empty? (rest cls)))
|
||||
acc
|
||||
(let [t (first cls)
|
||||
acc (if (seq? t) (reduce conj acc t) (conj acc t))]
|
||||
(collect (drop 2 cls) acc))))
|
||||
;; first duplicate constant, wrapped in [x] (so a duplicate nil is detected);
|
||||
;; nil = none. Clojure rejects duplicate case constants at compile time.
|
||||
first-dup (fn* fd [items seen]
|
||||
(if (empty? items)
|
||||
nil
|
||||
(let [x (first items)]
|
||||
(if (reduce (fn [f s] (or f (= s x))) false seen)
|
||||
[x]
|
||||
(fd (rest items) (conj seen x))))))
|
||||
dup (first-dup (collect clauses []) [])
|
||||
build (fn build [cls]
|
||||
(if (empty? cls)
|
||||
;; no clause matched and no default — Clojure throws here.
|
||||
|
|
@ -303,7 +323,9 @@
|
|||
(if (empty? (rest cls))
|
||||
(first cls)
|
||||
`(if ~(mk-test (first cls)) ~(nth cls 1) ~(build (drop 2 cls))))))]
|
||||
`(let* [~g ~expr] ~(build clauses))))
|
||||
(if dup
|
||||
(throw (str "Duplicate case test constant: " (first dup)))
|
||||
`(let* [~g ~expr] ~(build clauses)))))
|
||||
|
||||
;; for: list comprehension, desugared to nested map/mapcat over the binding colls.
|
||||
;; Per binding group: :when wraps the inner form in (if test (list inner) []) so
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue