feat: map literals evaluate their values (fixes critical latent bug); expand SCI bootstrap to 14 files (ctx_store/deftype/records/core_protocols/hierarchies + sci.impl.io stub), 390/392 forms; fix multi-arity defmethod (builds fn*) and variadic macrofy; SCI test loaders tolerant of the 2 redundant clojure.core registration maps

This commit is contained in:
Yogthos 2026-06-04 17:28:44 -04:00
parent 7d490843e5
commit 1b37e56df4
8 changed files with 74 additions and 24 deletions

View file

@ -0,0 +1,36 @@
; Minimal sci.impl.io stub for the Jolt bootstrap.
; SCI's real io.cljc needs JVM/CLJS-only features (System/getenv, *print-meta*,
; thread-local *out* binding). Jolt has native I/O, so we provide just the names
; that sci.impl.namespaces references when building the clojure.core binding map,
; backed by Jolt's native equivalents. (Only references symbols Jolt defines.)
(ns sci.impl.io)
(def out (atom nil))
(def in (atom nil))
(def err (atom nil))
(def newline (fn newline [] (clojure.core/pr "\n") nil))
(def flush (fn flush [] nil))
(def pr clojure.core/pr)
(def prn clojure.core/prn)
(def print clojure.core/print)
(def println clojure.core/println)
(def pr-str clojure.core/pr-str)
(def prn-str clojure.core/prn-str)
(def print-str clojure.core/str)
(def println-str clojure.core/println-str)
(def printf (fn printf [fmt & args] (clojure.core/print (apply clojure.core/format fmt args)) nil))
(def print-simple (fn print-simple [o w] (clojure.core/pr o) nil))
(def read-line (fn read-line [] nil))
(def with-out-str (fn with-out-str [& body] ""))
(def with-in-str (fn with-in-str [s & body] nil))
(def print-dup-var (atom false))
(def print-meta (atom false))
(def print-readably (atom true))
(def print-length (atom nil))
(def print-level (atom nil))
(def print-namespace-maps (atom false))
(def print-newline (atom true))
(def flush-on-newline (atom true))
(def print-fn (atom nil))
(def print-err-fn (atom nil))
(def file (atom nil))

View file

@ -2100,7 +2100,7 @@
# copy-var stubs for sci.impl.copy-vars (used by sci.impl.namespaces)
(defn core-copy-core-var [sym] nil)
(defn core-copy-var [sym & args] nil)
(defn core-macrofy [sym fn] fn)
(defn core-macrofy [sym fn & more] fn)
(defn core-new-var [sym & args] nil)
(defn core-avoid-method-too-large [& args] @{})

View file

@ -998,13 +998,12 @@
(var-get v))
"defmethod" (let [mm-sym (in form 1)
dispatch-val (eval-form ctx bindings (in form 2))
arg-vec (in form 3)
body (tuple/slice form 4)
# Extract names, handling metadata-wrapped symbols
extract-name (fn [arg]
(let [arg (unwrap-meta-name arg)]
(arg :name)))
arg-names (tuple/slice (map extract-name arg-vec))
# (defmethod mm dispatch [args] body...) — single-arity, or
# (defmethod mm dispatch ([args] body)...) — multi-arity.
# Build a fn* form and evaluate it (reuses arity dispatch
# and destructuring).
impl (eval-form ctx bindings
@[{:jolt/type :symbol :ns nil :name "fn*"} ;(tuple/slice form 3)])
mm-var (resolve-var ctx bindings mm-sym)
# Auto-create multimethod if it doesn't exist
mm-var (if mm-var mm-var
@ -1013,18 +1012,7 @@
(def v (ns-intern ns (mm-sym :name) dummy-fn))
(put v :jolt/methods @{})
v))
methods (get mm-var :jolt/methods)
impl (fn [& args]
(var new-bindings @{})
(table/setproto new-bindings bindings)
(var i 0)
(each a arg-names
(bind-put new-bindings a (args i))
(++ i))
(var result nil)
(each bf body
(set result (eval-form ctx new-bindings bf)))
result)]
methods (get mm-var :jolt/methods)]
(put methods dispatch-val impl)
mm-var)
"prefer-method" (let [mm-arg (in form 1)
@ -1182,7 +1170,12 @@
(error (string "No reader function for tag " tag))))
(if (get form :jolt/type)
(error (string "Unexpected tagged form: " (form :jolt/type)))
form)))))
# plain map literal: evaluate keys and values
(let [kvs @[]]
(each k (keys form)
(array/push kvs (eval-form ctx bindings k))
(array/push kvs (eval-form ctx bindings (get form k))))
(struct ;kvs)))))))
(array? form)
(if (= 0 (length form))
@[]