diff --git a/src/jolt/clojure/edn.clj b/src/jolt/clojure/edn.clj index 6de5146..ea271b3 100644 --- a/src/jolt/clojure/edn.clj +++ b/src/jolt/clojure/edn.clj @@ -5,13 +5,27 @@ "Reading EDN data." (:require [clojure.string :as cstr])) +;; 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.) +(defn- edn->value [x] + (cond + (and (map? x) (= :jolt/set (get x :jolt/type))) (set (map edn->value (get x :value))) + ;; Only untagged structs are real maps; symbols/chars/tagged literals are also + ;; struct? (=> map?) but carry a :jolt/type and must pass through unchanged. + (and (map? x) (nil? (get x :jolt/type))) + (into {} (map (fn [e] [(edn->value (key e)) (edn->value (val e))]) x)) + (vector? x) (mapv edn->value x) + (seq? x) (map edn->value x) + :else x)) + ;; Private helper, NOT named read-string: an unqualified (read-string …) call ;; dispatches the core read-string SPECIAL FORM (by name, regardless of ns), so ;; the 1-arity can't delegate to the 2-arity through that name. (defn- read-edn [opts s] (if (or (nil? s) (cstr/blank? s)) (get opts :eof nil) - (clojure.core/read-string s))) + (edn->value (clojure.core/read-string s)))) (defn read-string "Reads one object from the string s. Returns the :eof option value (default diff --git a/test/integration/clojure-stdlib-suite-test.janet b/test/integration/clojure-stdlib-suite-test.janet index d50fc58..1b4417e 100644 --- a/test/integration/clojure-stdlib-suite-test.janet +++ b/test/integration/clojure-stdlib-suite-test.janet @@ -12,10 +12,10 @@ [["clojure/walk_test/walk.cljc" 34 true] ["clojure/zip_test/zip.cljc" 33 true] ["clojure/data_test/diff.cljc" 61 true] - # clojure.edn now reads via clojure.core/read-string with opts/:eof + nil/blank - # handling. The remaining 3 fails are sets (the reader yields a set FORM, not a - # constructed set) and #uuid — tracked in jolt-b7y. Guard the passing subset. - ["clojure/edn_test/read_string.cljc" 47 false]]) + # clojure.edn reads via clojure.core/read-string (opts/:eof + nil/blank) and + # constructs set/nested values. Only #uuid remains (no real uuid type) — + # jolt-b7y. Guard the passing subset. + ["clojure/edn_test/read_string.cljc" 49 false]]) (def root "test/clojure-stdlib") (def per-file-timeout 6)