self-host: compile the analyzer (full-suite parity, fast); fix interp multi-arity
The portable analyzer now refers the host contract + IR ctors unqualified (host form predicates renamed form-* to dodge core-renames), so the bootstrap compiles it via its plain :var path — no qualified-ref compilation needed. ensure-analyzer compile-loads jolt.ir + jolt.analyzer as native bytecode. Result: the self-hosted pipeline (portable Clojure analyzer -> IR -> Janet back end) runs the FULL clojure-test-suite at 3913 pass — parity with the interpreter baseline — and fast (no timeouts), via JOLT_SELFHOST=1. Conformance 218/218. Also fixes a real interpreter bug: multi-arity dispatch stored the variadic clause by fixed-count (colliding) and only matched exact counts, so (f a b c..) on an [a b & more] clause threw. Now the variadic clause dispatches for any count >= its fixed arity. Remaining (jolt-4xc): the compiled analyzer still errors analyzing a multi-arity fn literal (falls back to the interpreter, now correct); compiling that is the last coverage gap before flipping the self-hosted pipeline on by default.
This commit is contained in:
parent
98bf389f82
commit
06d5f51d4a
4 changed files with 134 additions and 109 deletions
|
|
@ -155,14 +155,29 @@
|
|||
|
||||
# --- pipeline wiring (the self-hosted compile path) ---
|
||||
|
||||
# Compile-load a jolt-core namespace via the bootstrap so it runs as native
|
||||
# bytecode. The analyzer uses unqualified referred names (jolt.host form-* + the
|
||||
# IR ctors), so the bootstrap's plain :var path compiles it. Stateful forms (the
|
||||
# ns/require) fall back to the interpreter. Source from the embedded stdlib map.
|
||||
(defn- compile-load [ctx ns-name]
|
||||
(def src (get (get (ctx :env) :embedded-sources @{}) ns-name))
|
||||
(when src
|
||||
(def saved (ctx-current-ns ctx))
|
||||
(ctx-set-current-ns ctx ns-name)
|
||||
(var s src)
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def parsed (r/parse-next s))
|
||||
(set s (in parsed 1))
|
||||
(def f (in parsed 0))
|
||||
(when (not (nil? f))
|
||||
(def c (protect (comp/compile-ast f ctx)))
|
||||
(if (c 0) (comp/eval-compiled (c 1) ctx) (eval-form ctx @{} f))))
|
||||
(ctx-set-current-ns ctx saved)))
|
||||
|
||||
(defn- ensure-analyzer [ctx]
|
||||
# Load jolt.analyzer (and transitively jolt.ir) once; jolt.host is pre-installed
|
||||
# by host/install! so its require is a no-op. The analyzer runs INTERPRETED:
|
||||
# compiling it via the bootstrap needs qualified-ref compilation, which
|
||||
# regresses compile mode (the clojure.test shim breaks) — tracked in jolt-4xc.
|
||||
# Correctness is unaffected (218/218 conformance); speed is the open item.
|
||||
(when (= 0 (length ((ctx-find-ns ctx "jolt.analyzer") :mappings)))
|
||||
(eval-form ctx @{} (r/parse-string "(require '[jolt.analyzer])"))))
|
||||
(compile-load ctx "jolt.ir")
|
||||
(compile-load ctx "jolt.analyzer")))
|
||||
|
||||
(defn analyze-form
|
||||
"Run the portable Clojure analyzer (jolt.analyzer/analyze) on a reader form,
|
||||
|
|
|
|||
|
|
@ -810,15 +810,20 @@
|
|||
arities @{}
|
||||
defining-ns (ctx-current-ns ctx)]
|
||||
(var self nil)
|
||||
# The (single) variadic clause is dispatched separately: it handles
|
||||
# any arg count >= its fixed count. Storing it in `arities` by
|
||||
# fixed-count would collide with a same-fixed-count fixed clause and
|
||||
# only match that exact count.
|
||||
(var variadic-fn nil)
|
||||
(var variadic-min 0)
|
||||
(each pair pairs
|
||||
(let [args-form (in pair 0)
|
||||
body (tuple/slice pair 1)
|
||||
param-info (parse-params args-form)
|
||||
fixed-pats (param-info :fixed)
|
||||
rest-pat (param-info :rest)
|
||||
n-fixed (length fixed-pats)]
|
||||
(put arities n-fixed
|
||||
(fn [& fn-args]
|
||||
n-fixed (length fixed-pats)
|
||||
f (fn [& fn-args]
|
||||
(var fn-bindings @{})
|
||||
(table/setproto fn-bindings bindings)
|
||||
(var i 0)
|
||||
|
|
@ -836,12 +841,16 @@
|
|||
(each body-form body
|
||||
(set result (eval-form ctx fn-bindings body-form)))
|
||||
(ctx-set-current-ns ctx saved-ns)
|
||||
result))))
|
||||
result)]
|
||||
(if rest-pat
|
||||
(do (set variadic-fn f) (set variadic-min n-fixed))
|
||||
(put arities n-fixed f))))
|
||||
(set self (fn [& fn-args]
|
||||
(let [n (length fn-args)
|
||||
f (get arities n)]
|
||||
(if f
|
||||
(apply f fn-args)
|
||||
(cond
|
||||
f (apply f fn-args)
|
||||
(and variadic-fn (>= n variadic-min)) (apply variadic-fn fn-args)
|
||||
(error (string "Wrong number of args (" n ") passed to fn"))))))
|
||||
self)
|
||||
# Single-arity: (fn* [args] body...)
|
||||
|
|
|
|||
|
|
@ -114,13 +114,18 @@
|
|||
# can call them. Idempotent per context.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Form predicates use `form-*` names (not list?/vector?/map?/set?/char?) so the
|
||||
# analyzer can refer them unqualified without the bootstrap's core-renames
|
||||
# intercepting them as the value-level predicates.
|
||||
(def- exports
|
||||
{"sym?" h-sym? "sym-name" h-sym-name "sym-ns" h-sym-ns
|
||||
"list?" h-list? "vector?" h-vector? "map?" h-map? "set?" h-set? "char?" h-char?
|
||||
"literal?" h-literal? "elements" h-elements "vector-items" h-vector-items
|
||||
"map-pairs" h-map-pairs "set-items" h-set-items
|
||||
"special?" h-special? "current-ns" h-current-ns "macro?" h-macro?
|
||||
"expand-1" h-expand-1 "resolve-global" h-resolve-global "intern!" h-intern!})
|
||||
{"form-sym?" h-sym? "form-sym-name" h-sym-name "form-sym-ns" h-sym-ns
|
||||
"form-list?" h-list? "form-vec?" h-vector? "form-map?" h-map?
|
||||
"form-set?" h-set? "form-char?" h-char? "form-literal?" h-literal?
|
||||
"form-elements" h-elements "form-vec-items" h-vector-items
|
||||
"form-map-pairs" h-map-pairs "form-set-items" h-set-items
|
||||
"form-special?" h-special? "compile-ns" h-current-ns "form-macro?" h-macro?
|
||||
"form-expand-1" h-expand-1 "resolve-global" h-resolve-global
|
||||
"host-intern!" h-intern!})
|
||||
|
||||
(defn install! [ctx]
|
||||
(def ns (ctx-find-ns ctx "jolt.host"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue