feat: SCI bootstrap loads completely (422/422) — fix with-meta + select-keys

The last two keystone forms in namespaces.cljc now load, so the entire SCI
source in the harness's load order evaluates with ZERO failures (was 420/2).

Two real bugs fixed to get there:
- with-meta crashed on non-collections: (with-meta a-fn {...}) did (keys fn) ->
  'expected iterable, got function'. SCI marks core fns private this way. Now
  returns functions/scalars unchanged (Jolt can't attach meta to a raw fn).
- select-keys ignored a vector key-list: (each k ks) iterated the pvec's table
  instead of its elements, so (select-keys m [:a]) returned {}. Now realizes ks.

Plus: add clojure.set/join (the only missing clojure.set fn), assert 0 failures
in test-load-sci so it's a real regression guard, drop debug instrumentation.

Jolt now fully loads SCI's reader-independent implementation: every pure-Clojure
module, the entire clojure.core aggregation map, and the clojure.* namespace
wiring. conformance 218/218, features 78/78, jank 120.
This commit is contained in:
Yogthos 2026-06-04 23:35:19 -04:00
parent 4eead1ac0f
commit bf754693b5
3 changed files with 50 additions and 11 deletions

View file

@ -40,6 +40,33 @@
[xrel ks]
(reduce (fn [m x] (let [ik (select-keys x ks)] (assoc m ik (conj (get m ik #{}) x)))) {} xrel))
(defn join
"When passed 2 rels, returns the rel corresponding to the natural join.
When passed an additional keymap, joins on the corresponding keys."
([xrel yrel]
(if (and (seq xrel) (seq yrel))
(let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel))))
[r s] (if (<= (count xrel) (count yrel)) [xrel yrel] [yrel xrel])
idx (index r ks)]
(reduce (fn [ret x]
(let [found (idx (select-keys x ks))]
(if found
(reduce (fn [acc y] (conj acc (merge y x))) ret found)
ret)))
#{} s))
#{}))
([xrel yrel km]
(let [[r s k] (if (<= (count xrel) (count yrel))
[xrel yrel (map-invert km)]
[yrel xrel km])
idx (index r (vals k))]
(reduce (fn [ret x]
(let [found (idx (rename-keys (select-keys x (keys k)) k))]
(if found
(reduce (fn [acc y] (conj acc (merge y x))) ret found)
ret)))
#{} s))))
(defn subset?
[set1 set2]
(and (<= (count set1) (count set2))

View file

@ -494,7 +494,7 @@
(defn core-select-keys [m ks]
(var result @{})
(each k ks
(each k (realize-for-iteration ks)
(let [v (core-get m k)]
(if (not (nil? v)) (put result k v))))
(if (struct? m) (table/to-struct result) result))
@ -2237,15 +2237,21 @@
(put prefs dispatch-val-a dispatch-val-b) mm-var))
(defn core-with-meta [obj meta]
(var new-obj @{})
(each k (keys obj)
(put new-obj k (get obj k)))
# table/setproto requires a table, convert struct meta to table
(var meta-tab @{})
(each k (keys meta) (put meta-tab k (get meta k)))
(table/setproto new-obj meta-tab)
(put new-obj :jolt/meta meta)
new-obj)
# Functions and scalars can't carry metadata in Jolt's model — return as-is
# rather than crashing (Clojure attaches meta only to IObj values).
(if (or (function? obj) (cfunction? obj) (number? obj) (boolean? obj)
(nil? obj) (string? obj) (keyword? obj) (buffer? obj))
obj
(do
(var new-obj @{})
(each k (keys obj)
(put new-obj k (get obj k)))
# table/setproto requires a table, convert struct meta to table
(var meta-tab @{})
(each k (keys meta) (put meta-tab k (get meta k)))
(table/setproto new-obj meta-tab)
(put new-obj :jolt/meta meta)
new-obj)))
(defn core-var-dynamic? [v]
(var-dynamic? v))