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:
parent
091d2c4b62
commit
473d1002b7
8 changed files with 763 additions and 716 deletions
|
|
@ -8,12 +8,15 @@
|
|||
;; The reader yields set literals as a FORM ({:jolt/type :jolt/set :value [...]})
|
||||
;; rather than a constructed set, so build the actual values, recursing into
|
||||
;; maps/vectors/lists. (Lists stay lists — EDN never evaluates them as code.)
|
||||
;; Re-attach the source value's metadata to each rebuilt collection — read-string
|
||||
;; preserves reader metadata (^:ref […]) but this rebuild would otherwise drop it,
|
||||
;; which a metadata-driven config lib (aero/integrant) relies on.
|
||||
(defn- edn->value [opts x]
|
||||
(cond
|
||||
;; Reader FORMS are detected by :jolt/type tag, never by map? — strict map?
|
||||
;; (correctly) excludes tagged structs, so the old (and (map? x) ...) guard
|
||||
;; would skip them.
|
||||
(= :jolt/set (get x :jolt/type)) (set (map (fn [v] (edn->value opts v)) (get x :value)))
|
||||
(= :jolt/set (get x :jolt/type)) (with-meta (set (map (fn [v] (edn->value opts v)) (get x :value))) (meta x))
|
||||
;; Tagged elements: a reader from the :readers opt wins, then the built-in
|
||||
;; data readers (#uuid/#inst + registered); an unknown tag falls to the
|
||||
;; :default opt fn (called with tag and value, as in Clojure) or throws.
|
||||
|
|
@ -31,9 +34,9 @@
|
|||
(get opts :default) ((get opts :default) tag-sym v)
|
||||
:else (__read-tagged tag v)))
|
||||
(map? x)
|
||||
(into {} (map (fn [e] [(edn->value opts (key e)) (edn->value opts (val e))]) x))
|
||||
(vector? x) (mapv (fn [v] (edn->value opts v)) x)
|
||||
(seq? x) (map (fn [v] (edn->value opts v)) x)
|
||||
(with-meta (into {} (map (fn [e] [(edn->value opts (key e)) (edn->value opts (val e))]) x)) (meta x))
|
||||
(vector? x) (with-meta (mapv (fn [v] (edn->value opts v)) x) (meta x))
|
||||
(seq? x) (with-meta (map (fn [v] (edn->value opts v)) x) (meta x))
|
||||
:else x))
|
||||
|
||||
;; Private helper, NOT named read-string: an unqualified (read-string …) call
|
||||
|
|
|
|||
|
|
@ -5,19 +5,21 @@
|
|||
[inner outer form]
|
||||
(cond
|
||||
; vectors/maps first so seq? can't swallow them (a vector is not seq? on
|
||||
; jolt, but keep the concrete branches authoritative)
|
||||
(vector? form) (outer (vec (map inner form)))
|
||||
; jolt, but keep the concrete branches authoritative). Re-attach the form's
|
||||
; metadata to the rebuilt collection, as Clojure does — a metadata-driven walk
|
||||
; (aero/spec) needs ^:ref and friends to survive the rebuild.
|
||||
(vector? form) (outer (with-meta (vec (map inner form)) (meta form)))
|
||||
; a record is also map?, but (empty record) yields a plain map — rebuild by
|
||||
; conj-ing the walked entries back onto the original so the record TYPE
|
||||
; survives. Type-dispatched walks depend on it (e.g. integrant resolves
|
||||
; #ig/ref by detecting its Ref record while postwalking the config).
|
||||
(record? form) (outer (reduce (fn [r x] (conj r (inner x))) form form))
|
||||
(map? form) (outer (into (empty form) (map inner form)))
|
||||
(map? form) (outer (with-meta (into (empty form) (map inner form)) (meta form)))
|
||||
; lists rebuild as lists, other seqs (incl. macro/template output: cons/
|
||||
; concat/lazy-seq) walk too — without this, postwalk-replace silently no-op'd
|
||||
; a quoted list, breaking clojure.template/apply-template
|
||||
(list? form) (outer (apply list (map inner form)))
|
||||
(seq? form) (outer (map inner form))
|
||||
(list? form) (outer (with-meta (apply list (map inner form)) (meta form)))
|
||||
(seq? form) (outer (with-meta (map inner form) (meta form)))
|
||||
:else (outer form)))
|
||||
|
||||
(defn postwalk
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue