ns: accept vector reference clauses; add Compiler/specials

Two general fixes shaken out by clojure/tools.macro.

- The ns macro now accepts a vector reference clause [:require …] / [:use …],
  not just the list form (:require …). Clojure dispatches on (first clause) and
  accepts both; jolt silently dropped vector clauses, so a ns written with them
  loaded with nothing required/used (tools.macro's test ns uses [:use …]).
- clojure.lang.Compiler/specials is now a static whose keys are the special-form
  symbols (matching Clojure 1.2/1.3). Macroexpansion tooling reads
  (keys Compiler/specials) to know which heads not to expand.

tools.macro itself isn't fully passing yet — its mexpand-all works, but the
macrolet/symbol-macrolet tests need letfn to macroexpand to letfn* (jolt models
letfn as a special form, not a macro over letfn*), so it stays off the list.

make test green (+1 corpus row, 0 new divergences), shakesmoke byte-identical.
One re-mint (the ns macro).
This commit is contained in:
Yogthos 2026-06-27 17:08:50 -04:00
parent 1ba79aa223
commit 192ef66e7e
4 changed files with 17 additions and 3 deletions

View file

@ -34,7 +34,18 @@
;; forms, so this is rarely hit). Updated per top-level form, like *current-source*.
(define compiler-line-cell (jolt-atom-new 0))
(define compiler-column-cell (jolt-atom-new 0))
(let ((members (list (cons "LINE" compiler-line-cell) (cons "COLUMN" compiler-column-cell))))
;; clojure.lang.Compiler/specials — the JVM's special-form table (sym -> parser).
;; tools.macro reads (keys Compiler/specials) to know which heads NOT to expand.
;; Only the keys matter here; values are #t. The set matches Clojure 1.2/1.3.
(define compiler-specials
(let ((unq '("def" "loop*" "recur" "if" "case*" "let*" "letfn*" "do" "fn*"
"quote" "var" "." "set!" "try" "monitor-enter" "monitor-exit"
"throw" "new" "&" "catch" "finally" "reify*" "deftype*")))
(fold-left (lambda (m s) (jolt-assoc1 m (jolt-symbol #f s) #t))
(jolt-assoc1 (jolt-hash-map) (jolt-symbol "clojure.core" "import*") #t)
unq)))
(let ((members (list (cons "LINE" compiler-line-cell) (cons "COLUMN" compiler-column-cell)
(cons "specials" compiler-specials))))
(register-class-statics! "Compiler" members)
(register-class-statics! "clojure.lang.Compiler" members))

View file

@ -32,7 +32,7 @@
(mark-macro! "clojure.core" "cond"))
(guard (e (#t #f))
(def-var! "clojure.core" "ns"
(lambda (nm . clauses) (let fnrec5012 ((nm nm) (clauses (list->cseq clauses))) (let* ((nm (if (jolt-truthy? (let* ((and__25__auto (jolt-invoke (var-deref "clojure.core" "seq?") nm))) (if (jolt-truthy? and__25__auto) (jolt= (jolt-symbol #f "with-meta") (jolt-first nm)) and__25__auto))) (jolt-invoke (var-deref "clojure.core" "second") nm) nm)) (calls (let* ((_a$5042 (lambda (acc clause) (let fnrec5013 ((acc acc) (clause clause)) (if (jolt-truthy? (jolt-invoke (var-deref "clojure.core" "seq?") clause)) (let* ((head (jolt-first clause)) (args (jolt-rest clause))) (if (jolt= head (keyword #f "require")) (jolt-conj acc (let* ((_a$5018 (var-deref "clojure.core" "__sqcat")) (_a$5019 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "require"))) (_a$5020 (jolt-map (lambda (s) (let fnrec5014 ((s s)) (let* ((_a$5015 (var-deref "clojure.core" "__sqcat")) (_a$5016 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5017 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5015 _a$5016 _a$5017)))) args))) (jolt-invoke _a$5018 _a$5019 _a$5020))) (if (jolt= head (keyword #f "use")) (jolt-conj acc (let* ((_a$5025 (var-deref "clojure.core" "__sqcat")) (_a$5026 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "use"))) (_a$5027 (jolt-map (lambda (s) (let fnrec5021 ((s s)) (let* ((_a$5022 (var-deref "clojure.core" "__sqcat")) (_a$5023 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5024 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5022 _a$5023 _a$5024)))) args))) (jolt-invoke _a$5025 _a$5026 _a$5027))) (if (jolt= head (keyword #f "import")) (jolt-conj acc (let* ((_a$5032 (var-deref "clojure.core" "__sqcat")) (_a$5033 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "import"))) (_a$5034 (jolt-map (lambda (s) (let fnrec5028 ((s s)) (let* ((_a$5029 (var-deref "clojure.core" "__sqcat")) (_a$5030 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5031 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5029 _a$5030 _a$5031)))) args))) (jolt-invoke _a$5032 _a$5033 _a$5034))) (if (jolt= head (keyword #f "refer-clojure")) (jolt-conj acc (let* ((_a$5039 (var-deref "clojure.core" "__sqcat")) (_a$5040 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "refer-clojure"))) (_a$5041 (jolt-map (lambda (s) (let fnrec5035 ((s s)) (let* ((_a$5036 (var-deref "clojure.core" "__sqcat")) (_a$5037 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5038 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5036 _a$5037 _a$5038)))) args))) (jolt-invoke _a$5039 _a$5040 _a$5041))) (if (jolt-truthy? (keyword #f "else")) acc jolt-nil)))))) acc)))) (_a$5043 (jolt-vector)) (_a$5044 clauses)) (jolt-reduce _a$5042 _a$5043 _a$5044)))) (let* ((_a$5051 (var-deref "clojure.core" "__sqcat")) (_a$5052 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "do"))) (_a$5053 (jolt-invoke (var-deref "clojure.core" "__sq1") (let* ((_a$5048 (var-deref "clojure.core" "__sqcat")) (_a$5049 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "in-ns"))) (_a$5050 (jolt-invoke (var-deref "clojure.core" "__sq1") (let* ((_a$5045 (var-deref "clojure.core" "__sqcat")) (_a$5046 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5047 (jolt-invoke (var-deref "clojure.core" "__sq1") nm))) (jolt-invoke _a$5045 _a$5046 _a$5047))))) (jolt-invoke _a$5048 _a$5049 _a$5050)))) (_a$5054 calls)) (jolt-invoke _a$5051 _a$5052 _a$5053 _a$5054))))))
(lambda (nm . clauses) (let fnrec5012 ((nm nm) (clauses (list->cseq clauses))) (let* ((nm (if (jolt-truthy? (let* ((and__25__auto (jolt-invoke (var-deref "clojure.core" "seq?") nm))) (if (jolt-truthy? and__25__auto) (jolt= (jolt-symbol #f "with-meta") (jolt-first nm)) and__25__auto))) (jolt-invoke (var-deref "clojure.core" "second") nm) nm)) (calls (let* ((_a$5042 (lambda (acc clause) (let fnrec5013 ((acc acc) (clause clause)) (if (jolt-truthy? (let* ((or__26__auto (jolt-invoke (var-deref "clojure.core" "seq?") clause))) (if (jolt-truthy? or__26__auto) or__26__auto (jolt-invoke (var-deref "clojure.core" "vector?") clause)))) (let* ((head (jolt-first clause)) (args (jolt-rest clause))) (if (jolt= head (keyword #f "require")) (jolt-conj acc (let* ((_a$5018 (var-deref "clojure.core" "__sqcat")) (_a$5019 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "require"))) (_a$5020 (jolt-map (lambda (s) (let fnrec5014 ((s s)) (let* ((_a$5015 (var-deref "clojure.core" "__sqcat")) (_a$5016 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5017 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5015 _a$5016 _a$5017)))) args))) (jolt-invoke _a$5018 _a$5019 _a$5020))) (if (jolt= head (keyword #f "use")) (jolt-conj acc (let* ((_a$5025 (var-deref "clojure.core" "__sqcat")) (_a$5026 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "use"))) (_a$5027 (jolt-map (lambda (s) (let fnrec5021 ((s s)) (let* ((_a$5022 (var-deref "clojure.core" "__sqcat")) (_a$5023 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5024 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5022 _a$5023 _a$5024)))) args))) (jolt-invoke _a$5025 _a$5026 _a$5027))) (if (jolt= head (keyword #f "import")) (jolt-conj acc (let* ((_a$5032 (var-deref "clojure.core" "__sqcat")) (_a$5033 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "import"))) (_a$5034 (jolt-map (lambda (s) (let fnrec5028 ((s s)) (let* ((_a$5029 (var-deref "clojure.core" "__sqcat")) (_a$5030 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5031 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5029 _a$5030 _a$5031)))) args))) (jolt-invoke _a$5032 _a$5033 _a$5034))) (if (jolt= head (keyword #f "refer-clojure")) (jolt-conj acc (let* ((_a$5039 (var-deref "clojure.core" "__sqcat")) (_a$5040 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "refer-clojure"))) (_a$5041 (jolt-map (lambda (s) (let fnrec5035 ((s s)) (let* ((_a$5036 (var-deref "clojure.core" "__sqcat")) (_a$5037 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5038 (jolt-invoke (var-deref "clojure.core" "__sq1") s))) (jolt-invoke _a$5036 _a$5037 _a$5038)))) args))) (jolt-invoke _a$5039 _a$5040 _a$5041))) (if (jolt-truthy? (keyword #f "else")) acc jolt-nil)))))) acc)))) (_a$5043 (jolt-vector)) (_a$5044 clauses)) (jolt-reduce _a$5042 _a$5043 _a$5044)))) (let* ((_a$5051 (var-deref "clojure.core" "__sqcat")) (_a$5052 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "do"))) (_a$5053 (jolt-invoke (var-deref "clojure.core" "__sq1") (let* ((_a$5048 (var-deref "clojure.core" "__sqcat")) (_a$5049 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol "clojure.core" "in-ns"))) (_a$5050 (jolt-invoke (var-deref "clojure.core" "__sq1") (let* ((_a$5045 (var-deref "clojure.core" "__sqcat")) (_a$5046 (jolt-invoke (var-deref "clojure.core" "__sq1") (jolt-symbol #f "quote"))) (_a$5047 (jolt-invoke (var-deref "clojure.core" "__sq1") nm))) (jolt-invoke _a$5045 _a$5046 _a$5047))))) (jolt-invoke _a$5048 _a$5049 _a$5050)))) (_a$5054 calls)) (jolt-invoke _a$5051 _a$5052 _a$5053 _a$5054))))))
(mark-macro! "clojure.core" "ns"))
(guard (e (#t #f))
(def-var! "clojure.core" "->"

View file

@ -117,7 +117,9 @@
(let [nm (if (and (seq? nm) (= 'with-meta (first nm))) (second nm) nm)
calls (reduce
(fn [acc clause]
(if (seq? clause)
;; a reference clause may be a list (:require …) or a vector
;; [:require …]; Clojure accepts both, dispatching on (first clause).
(if (or (seq? clause) (vector? clause))
(let [head (first clause) args (rest clause)]
(cond
(= head :require) (conj acc `(require ~@(map (fn [s] `(quote ~s)) args)))

View file

@ -3378,4 +3378,5 @@
{:suite "numbers / unsigned-bit-shift-right is logical over 64 bits" :label "shift of a negative shifts in zeros" :expected "[9223372036854775807 4611686018427387902]" :actual "[(unsigned-bit-shift-right -1 1) (unsigned-bit-shift-right -8 2)]"}
{:suite "numbers / ^long is 64-bit" :label "^long comparison on a full-width long" :expected "false" :actual "((fn* ([^long a ^long b] (< a b))) 9223372036854775807 1)"}
{:suite "numbers / ^long is 64-bit" :label "^long quot on a full-width long" :expected "3074457345618258602" :actual "((fn* ([^long a] (quot a 3))) 9223372036854775807)"}
{:suite "host-interop / Compiler" :label "Compiler/specials keys include the special forms" :expected "true" :actual "(every? (set (keys clojure.lang.Compiler/specials)) (quote [if do let* fn* quote def loop* recur try letfn* var]))"}
]