Loading these libs via require worked (load-ns-source interprets, macros
expand lazily) but the same code inlined by uberscript routes through
eval-toplevel and compiled, surfacing four gaps:
- a ^{:map} metadata def name reads as (def (with-meta name m) v); the
analyzer died extracting the name (config.core's defonce env). It now
throws uncompilable so the interpreter, which handles it, takes over.
- declare was a no-op, so a compiled forward reference to a declared
name that collides with a janet root binding bound to the host fn
(selmer.parser's (declare parse) compiled to janet's 1-arg parse).
declare now expands to no-init defs, the interpreter interns them,
and the analyzer routes no-init def to the interpreter.
- class? was missing (selmer.util's exception macro calls it at
expansion time). Always false, like ratio? — no Class objects here.
- require of an unlocatable namespace silently left an empty ns behind,
deferring the failure to an unresolved symbol far from the cause. It
now throws like Clojure's FileNotFoundException. Namespaces entered
in-session count as loaded (Clojure puts them in *loaded-libs*), and
the SCI bootstrap opts out via :lenient-require? since its
clj-targeted requires can't all exist on this host.
122 lines
4.2 KiB
Text
122 lines
4.2 KiB
Text
(use ../../src/jolt/evaluator)
|
|
(use ../../src/jolt/types)
|
|
(use ../../src/jolt/reader)
|
|
(use ../../src/jolt/api)
|
|
(use ../../src/jolt/reader)
|
|
# SCI is a clj/cljs-targeted library: its .cljc sources select implementation
|
|
# via #?(:clj ...) and have no :jolt branches — load it under clj-compat
|
|
# features (spec 02-reader S18: feature sets are a property of the loading
|
|
# context; the portable default is #{:jolt :default}).
|
|
(reader-features-set! ["jolt" "clj" "default"])
|
|
|
|
(def ctx (init-cached))
|
|
# Best-effort loading: SCI's clj-targeted requires (borkdude.graal.locking,
|
|
# clojure.tools.reader.*) don't exist on this host; a strict require would fail
|
|
# whole ns forms and cascade. See maybe-require-ns.
|
|
(put (ctx :env) :lenient-require? true)
|
|
|
|
(printf "Loading SCI stubs...\n")
|
|
(defn load-stubs [ctx filepath]
|
|
(var s (slurp filepath))
|
|
(var count 0)
|
|
(while (> (length (string/trim s)) 0)
|
|
(def [form rest] (parse-next s))
|
|
(set s rest)
|
|
(++ count)
|
|
(when (not (nil? form))
|
|
(eval-form ctx @{} form)))
|
|
(printf " Loaded %d stub forms\n" count))
|
|
|
|
(load-stubs ctx "src/jolt/clojure/sci/lang_stubs.clj")
|
|
(load-stubs ctx "src/jolt/clojure/sci/io_stubs.clj")
|
|
(load-stubs ctx "src/jolt/clojure/sci/host_stubs.clj")
|
|
|
|
# namespaces.cljc copies vars out of Jolt's own clojure.string/set/walk/edn, so
|
|
# make sure those are loaded before it runs.
|
|
(each lib ["clojure.string" "clojure.set" "clojure.walk" "clojure.edn"]
|
|
(protect (eval-form ctx @{} (first (parse-next (string "(require '[" lib "])"))))))
|
|
|
|
(defn load-file [ctx path]
|
|
(var s (slurp path))
|
|
(var count 0)
|
|
(var ok 0)
|
|
(var fail 0)
|
|
(var failures @[])
|
|
(while (> (length (string/trim s)) 0)
|
|
(def [form rest] (parse-next s))
|
|
(set s rest)
|
|
(++ count)
|
|
(if (not (nil? form))
|
|
(do
|
|
(printf "eval form %d..." count)
|
|
(flush)
|
|
(if (try
|
|
(do (eval-form ctx @{} form) true)
|
|
([err fib]
|
|
(printf " FAIL: %q\n" err)
|
|
(when (os/getenv "SCI_TRACE") (debug/stacktrace fib ""))
|
|
(array/push failures {:form-number count :error (string err) :form (string form)})
|
|
false))
|
|
(do
|
|
(printf " OK\n")
|
|
(++ ok))
|
|
(++ fail)))))
|
|
{:ok ok :fail fail :total count :failures failures})
|
|
|
|
(def sci-base "vendor/sci/src/sci")
|
|
|
|
(def load-order @[
|
|
["impl/macros.cljc" nil]
|
|
["impl/protocols.cljc" nil]
|
|
["impl/types.cljc" nil]
|
|
["impl/unrestrict.cljc" nil]
|
|
["impl/vars.cljc" nil]
|
|
["lang.cljc" nil]
|
|
["impl/utils.cljc" nil]
|
|
["ctx_store.cljc" nil]
|
|
["impl/deftype.cljc" nil]
|
|
["impl/records.cljc" nil]
|
|
["impl/core_protocols.cljc" nil]
|
|
["impl/hierarchies.cljc" nil]
|
|
# pure-Clojure macro/expander modules (loadable from SCI's real source)
|
|
["impl/destructure.cljc" nil]
|
|
["impl/doseq_macro.cljc" nil]
|
|
["impl/for_macro.cljc" nil]
|
|
["impl/fns.cljc" nil]
|
|
["impl/multimethods.cljc" nil]
|
|
["impl/namespaces.cljc" nil]
|
|
["core.cljc" nil]
|
|
])
|
|
|
|
(var total-ok 0)
|
|
(var total-fail 0)
|
|
(var all-failures @[])
|
|
|
|
(each [file expected-ns] load-order
|
|
(def path (string sci-base "/" file))
|
|
(printf "\n=== Loading %s ===\n" file)
|
|
(def result (load-file ctx path))
|
|
(printf " Result: %d ok, %d fail, %d total\n" (result :ok) (result :fail) (result :total))
|
|
(+= total-ok (result :ok))
|
|
(+= total-fail (result :fail))
|
|
(each f (result :failures)
|
|
(array/push all-failures {:file file :form-number (f :form-number) :error (f :error) :form (f :form)})))
|
|
|
|
(printf "\n==============================\n")
|
|
(printf "TOTAL: %d ok, %d fail, %d total\n" total-ok total-fail (+ total-ok total-fail))
|
|
(printf "==============================\n")
|
|
|
|
(printf "\ncurrent ns: %s\n" (ctx-current-ns ctx))
|
|
(printf "sci.core exists: %q\n" (not (nil? (ctx-find-ns ctx "sci.core"))))
|
|
(printf "total namespaces: %d\n" (length (keys ((ctx :env) :namespaces))))
|
|
|
|
(when (> (length all-failures) 0)
|
|
(printf "\n=== FAILURES ===\n")
|
|
(each f all-failures
|
|
(printf "[%s:%d] %s\n" (f :file) (f :form-number) (f :error))
|
|
(printf " form: %s\n" (f :form))))
|
|
|
|
# Regression guard: every form in the loaded SCI modules must evaluate cleanly.
|
|
(assert (= 0 total-fail)
|
|
(string total-fail " SCI form(s) failed to load (see FAILURES above)"))
|
|
(print "\nAll SCI bootstrap forms loaded successfully.")
|