Reader attaches collection metadata to data, not a with-meta form

The reader lowered ^meta on a vector/map/set literal to a runtime
(with-meta form meta) list, so read-string/edn of data with metadata
returned the form and lost the metadata. Attach it to the value instead,
as Clojure does; the analyzer re-emits (with-meta coll meta) for a
meta-carrying collection literal in code, so a literal still carries its
metadata at runtime and ^Type/^long arglist hints (consumed by
analyze-arity directly) are unaffected.

Also: pr honors *print-meta*, and clojure.walk/clojure.edn re-attach
metadata to the collections they rebuild (matches Clojure; a
metadata-driven config lib like aero relies on it).
This commit is contained in:
Yogthos 2026-06-24 12:04:36 -04:00
parent 091d2c4b62
commit 473d1002b7
8 changed files with 763 additions and 716 deletions

View file

@ -67,12 +67,31 @@
(if (jolt-nil? s) (reverse acc)
(loop (jolt-seq (seq-more s)) (cons (jolt-pr-readable (seq-first s)) acc))))) ")"))
(else (jolt-pr-str x))))
(define (jolt-pr-readable x)
(define (jolt-pr-readable-dispatch x)
(let loop ((as jolt-pr-readable-arms))
(cond ((null? as) (jolt-pr-readable-base x))
(((caar as) x) ((cdar as) x))
(else (loop (cdr as))))))
;; *print-meta* support. The var is def'd after this file loads, so capture its
;; cell lazily; jolt-var-get (patched by dyn-binding.ss) honors a `binding`.
(define pr-meta-cell #f)
(define (pr-print-meta?)
(unless pr-meta-cell (set! pr-meta-cell (jolt-var "clojure.core" "*print-meta*")))
(jolt-truthy? (jolt-var-get pr-meta-cell)))
;; The metadata to print before x, or jolt-nil. A var prints as #'ns/name (its
;; {:ns :name} is derived, not user metadata) and a procedure is opaque — skip both.
(define (pr-user-meta x)
(if (or (var-cell? x) (procedure? x)) jolt-nil (jolt-meta x)))
(define (jolt-pr-readable x)
(if (pr-print-meta?)
(let ((m (pr-user-meta x)))
(if (jolt-nil? m)
(jolt-pr-readable-dispatch x)
(string-append "^" (jolt-pr-readable-dispatch m) " " (jolt-pr-readable-dispatch x))))
(jolt-pr-readable-dispatch x)))
;; __pr-str1: render ONE value readably (the overlay's pr-str joins these).
(define (jolt-pr-str1 x) (jolt-pr-readable x))