reader: feature set #{:jolt :default}, clause-order matching (RFC 0002)
jolt no longer satisfies :clj in reader conditionals. The shortcut was a measured net liability: :clj branches carry JVM interop and JVM-specific test expectations jolt fails, and they shadowed :default branches jolt passes. A/B over the suite: clj,default = 4967 assertions / 4324 pass / 119 errors; jolt,default = 5069 / 4470 / 81 (+146 pass, -38 errors, +8 clean files). Baselines raised to 4470/86. Matching is now by CLAUSE order like Clojure — the first clause whose key is in the feature set wins (#?(:default 5 :clj 6) is 5 everywhere); the old code scanned for :clj first, then :default, regardless of position. Foreign clj-targeted libraries are a property of the LOADING CONTEXT, not the platform: reader-features-set! opts a load into a compatibility set, and the SCI bootstrap/runtime tests load SCI under ["jolt" "clj" "default"] (its .cljc selects implementations via :clj with no :jolt branches). JOLT_FEATURES remains the process-wide override. RFC 0002 records the decision with the measured data; spec 02-reader S18 is now normative (clause order, documented feature set, per-context override). Reader tests updated to the portable set + an opt-in round-trip.
This commit is contained in:
parent
2224e40afc
commit
fdfd086df6
8 changed files with 164 additions and 33 deletions
|
|
@ -387,6 +387,34 @@
|
|||
(array/push arg-names rest-sym))
|
||||
[@[(sym "fn*") (tuple ;arg-names) replaced] new-pos]))
|
||||
|
||||
# The reader-conditional feature set (spec 02-reader S18): jolt is its own
|
||||
# dialect, so the portable convention applies — the dialect key plus :default.
|
||||
# Matching is by CLAUSE order (the first clause whose key is in the feature
|
||||
# set wins), exactly like Clojure — NOT key-priority. JOLT_FEATURES overrides
|
||||
# (comma-separated, e.g. "jolt,clj,default") for compat experiments and A/B
|
||||
# measurement; :default is always honored.
|
||||
# Mutable so a loading context can opt a clj-targeted foreign library into
|
||||
# :clj compatibility (e.g. SCI) — see reader-features-set!. jolt itself and
|
||||
# the conformance surface read under the portable set.
|
||||
(var reader-features nil)
|
||||
|
||||
(defn reader-features-set!
|
||||
"Replace the active reader-conditional feature set (a list of keyword-name
|
||||
strings or keywords). :default is always honored. Returns the previous set
|
||||
so callers can restore."
|
||||
[names]
|
||||
(def prev reader-features)
|
||||
(def t @{})
|
||||
(each n names (put t (if (keyword? n) n (keyword n)) true))
|
||||
(put t :default true)
|
||||
(set reader-features t)
|
||||
prev)
|
||||
|
||||
(reader-features-set!
|
||||
(let [env (os/getenv "JOLT_FEATURES")]
|
||||
(if env (filter |(> (length $) 0) (string/split "," env))
|
||||
["jolt" "default"])))
|
||||
|
||||
(defn read-reader-conditional [s pos]
|
||||
# pos is at #, next char is ? or ?@
|
||||
(def splice? (and (< (+ pos 2) (length s)) (= (s (+ pos 2)) 64))) # @ = 64
|
||||
|
|
@ -394,23 +422,16 @@
|
|||
(let [[form new-pos] (read-form s form-start)]
|
||||
(if (array? form)
|
||||
(do
|
||||
# First clause (in clause order) whose feature key is in the set.
|
||||
# `matched` is tracked separately: a matched clause may be nil.
|
||||
(var result nil)
|
||||
(var matched false)
|
||||
(var i 0)
|
||||
(while (< i (length form))
|
||||
(if (= (in form i) :clj)
|
||||
(do
|
||||
(set result (in form (+ i 1)))
|
||||
(set i (length form)))
|
||||
(++ i)))
|
||||
# Fallback to :default if :clj not matched
|
||||
(when (nil? result)
|
||||
(set i 0)
|
||||
(while (< i (length form))
|
||||
(if (= (in form i) :default)
|
||||
(do
|
||||
(set result (in form (+ i 1)))
|
||||
(set i (length form)))
|
||||
(++ i))))
|
||||
(while (and (not matched) (< i (length form)))
|
||||
(when (get reader-features (in form i))
|
||||
(set result (in form (+ i 1)))
|
||||
(set matched true))
|
||||
(+= i 2))
|
||||
(if splice?
|
||||
# #?@ splicing: resolve :clj branch, wrap for splice
|
||||
(let [items (if (nil? result)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue