Commit graph

7 commits

Author SHA1 Message Date
Yogthos
497970029d self-host: make it the only compile path; drop the bootstrap as a selectable path
eval-toplevel now routes every compiled form through backend/compile-and-eval
(analyzer -> IR -> Janet back end). The bootstrap compiler (compile-ast) stays
only to bootstrap jolt.ir/jolt.analyzer in backend/compile-load. Dropped the
:selfhost? flag and JOLT_SELFHOST env plumbing — self-host is the default.

Three correctness fixes the full-suite-under-self-host sweep exposed:
- analyzer/back end: recur into a variadic arity now compiles. The arity fn
  gets an ordinary positional rest param (the collected seq), with a dispatch
  wrapper, so (recur fixed... rest-seq) is a clean self-call like Clojure --
  instead of punting to the interpreter, which hangs on this (jolt-4df).
- host_iface: interop heads (.foo/.-field/Foo.) and ns-management forms
  (all-ns, create-ns, resolve, ...) now mark uncompilable so they fall back
  instead of compiling to a bad call.
- back end: named-fn self-reference ((fn self [n] ... (self ...))) binds the
  fn name via a var.

Full unit+integration suite green; clojure-test-suite battery holds 3913.
2026-06-06 11:34:02 -04:00
Yogthos
3afd1c6142 self-host: analyzer compiles to fast bytecode (fib(30) 0.52s)
The self-hosted compiler now genuinely compiles to native Janet bytecode rather
than falling back to the interpreter:
- bootstrap fixes that let it compile the analyzer: (def x) with no init, and an
  empty (do) (declare expands to one) no longer error;
- analyzer reordered so only the mutually-recursive  is forward declared
  (a deeply-nested forward ref to analyze-fn/analyze-try miscompiled to nil);
- back end emits native Janet ops for hot primitives (+,-,*,<,>,<=,>=,inc,dec)
  on clojure.core refs, like the bootstrap's core-renames.

Result: self-hosted fib(30) runs in 0.52s (was ~50s interpreted). Full
clojure-test-suite via JOLT_SELFHOST runs compiled at 3869 pass (some compiled-
vs-interpreted divergences remain to chase toward full parity — jolt-4xc).
Default suite green; conformance 218/218; jank-conformance up to 135.
2026-06-06 10:25:05 -04:00
Yogthos
06d5f51d4a 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.
2026-06-06 09:59:28 -04:00
Yogthos
f9df794475 self-host: compile loop/recur, recur-in-fn, and try
Analyzer threads an env (locals + recur target) instead of a bare locals set, and
compiles loop*/recur, recur directly in a fixed-arity fn (each arity's name is its
recur target -> self-call), and try/catch/finally (-> Janet try + defer). recur
into a variadic arity isn't a recur target, so it falls back to the interpreter
rather than miscompiling the rest seq. Still 218/218 conformance via the pipeline,
now with these forms compiling natively instead of interpreting.
2026-06-06 06:26:22 -04:00
Yogthos
5624e99eb6 self-host: analyzer reaches full conformance parity via hybrid fallback
The Clojure analyzer + Janet back end now pass all 218 conformance cases (vs the
interpreter) through the self-hosted pipeline:
- host contract gains special? (the full special-form/uncompilable set), so the
  analyzer falls back for forms it doesn't compile instead of miscompiling them
  as calls;
- qualified symbol refs that don't resolve to a var (janet/…, Math/…, host
  interop) and tagged literals (#"regex", #inst) and set literals throw
  uncompilable -> interpreter;
- the back end's compile-and-eval is now hybrid: only the compile step is
  guarded, runtime errors propagate.

Still interpreter-routed (coverage to grow next): loop/recur, recur in fn, try,
sets, destructuring.
2026-06-06 06:19:45 -04:00
Yogthos
849449aada self-host: working portable analyzer -> IR -> Janet back end pipeline
The Clojure-in-Clojure front end now compiles and runs a real subset end to end:
arithmetic, if/do/let, vector/map literals, def + name-based global refs, fn,
defn (via macroexpand), recursion through the var cell, multi-arity, variadic,
and higher-order calls. Proven by test/integration/self-host-test.janet.

Pieces:
- jolt-core/jolt/analyzer.clj — PORTABLE Clojure analyzer: reader form -> IR,
  depending only on the host contract (jolt.host), never on Janet.
- src/jolt/host_iface.janet — Janet impl of the jolt.host contract (form
  introspection + resolve/macro/current-ns), installed into each ctx.
- src/jolt/backend.janet — Janet back end: IR -> Janet form -> eval; resolves
  name-based :var nodes to cells and reuses runtime helpers.

Host Janet code lives in src/jolt/ (not a host/janet/ dir): Janet resolves
relative imports per file, so cross-dir ../../src/jolt/* imports load second
instances of compiler/types/core and corrupt state. The portability boundary is
the jolt.host namespace contract + jolt-core/, not the directory.

Notes: gensym in the back end must not be Janet's (shadowed by Jolt's via use);
a jolt bug — (into #{} coll) doesn't add elements — was worked around with reduce
conj in the analyzer (filed separately).
2026-06-06 06:11:42 -04:00
Yogthos
b1ac427bdd self-host: scaffold portable jolt-core + host/core architecture
Adds doc/self-hosting-architecture.md: the portability design (portable front
end + host back end + host runtime, seam = a minimal host protocol + the IR),
grounded in the CLJS/Clojure-in-Clojure prior art. Decisions locked: minimal host
protocol as the seam; physical split with a jolt-core/ source root.

Adds jolt-core/ as a portable Clojure source root (dev path + embedded into the
binary alongside the rest of the stdlib) and jolt-core/jolt/ir.clj — host-neutral
IR node constructors (vars referenced by name, no host values embedded). Verified
it loads and runs under both interpreter and compiler.
2026-06-06 05:44:12 -04:00