Auto-resolve ::keywords; honor clojure.edn reader opts

The reader dropped the namespace on ::kw (read ::foo as :foo), so auto-resolved
keywords never matched their qualified form — code that round-trips them (spec
keys, aero's :aero.core/* expansion keys) silently broke. Resolve ::name against
the current ns and ::alias/name through the alias table, as Clojure does. The
runtime loader reads form-by-form with the ns set after the ns form; the
cross-compile reads all forms up front, so ei-emit-ns*/ei-emit-ns-records set the
ns before reading.

clojure.edn/read over a reader discarded its opts map — :readers/:default/:eof
were ignored, so a custom :default never saw the tag. Route the reader arity
through read-string so opts apply, and pass the tag to :default as a symbol (not
the internal :#name keyword), matching Clojure.

Seed re-minted (the ::halt transducer key in clojure.core now reads as
:clojure.core/halt). Corpus gains ::-keyword rows; the unit case that asserted the
old ns-dropping behavior now asserts the qualified result.
This commit is contained in:
Yogthos 2026-06-24 09:13:14 -04:00
parent 53b1c79d99
commit 6d56982abe
7 changed files with 31 additions and 12 deletions

View file

@ -451,11 +451,19 @@
;; --- keyword ----------------------------------------------------------------
(define (rdr-read-keyword s i end) ; i points just past the leading ':'
;; ::kw auto-resolves; drop the ns, so skip a second ':'
(let ((i (if (and (< i end) (char=? (string-ref s i) #\:)) (+ i 1) i)))
(let-values (((tok j) (rdr-read-token s i end)))
(let-values (((ns name) (rdr-sym-parts tok)))
(values (keyword ns name) j)))))
;; ::kw is auto-resolved against the current ns: ::name -> current-ns/name,
;; ::alias/name -> the alias's target ns / name (Clojure's reader semantics).
(let ((auto? (and (< i end) (char=? (string-ref s i) #\:))))
(let ((i (if auto? (+ i 1) i)))
(let-values (((tok j) (rdr-read-token s i end)))
(let-values (((ns name) (rdr-sym-parts tok)))
(if auto?
(let* ((cur (chez-current-ns))
(rns (if (string? ns)
(let ((a (chez-resolve-alias cur ns))) (if a a ns))
cur)))
(values (keyword rns name) j))
(values (keyword ns name) j)))))))
;; --- the main dispatch ------------------------------------------------------
;; Returns (values form j). form is rdr-eof at end-of-input or at an unconsumed