The whole-program fixpoint collects a self-recursive call's arg types into the fn's own params. When a recursive call threads a param straight through unchanged (same arg, same position — e.g. ray-cast passing `hittables` to itself), that arg's type is the param's own current type: :any until external callers determine it. And :any is absorbing, so collecting it pinned the param at :any forever — the type a caller supplied (a vector of records) was lost, and the fn's field reads stayed generic. Skip a same-position pass-through arg in the self-recursion collection (contribute the join identity). It can't add information — param i ⊇ param i is trivial — so dropping it is sound; the param is still constrained by every external caller and by any non-pass-through recursive arg. Applies to both self-recursion paths: a `defn` recursing through its var, and a named fn literal recursing via its self-local. This is why ray-cast's `ray` typed (its recursion passes a fresh ray) but `hittables` didn't (passed through). With the fix, hittables keeps its vec<Sphere> element type, so hit-all's reduce element — and hit-sphere's reads — type without any hint: ray tracer 38.4s -> 31.3s (~1.23x) with no annotations. run-wp.ss: a recursive fn threading a vec param through keeps its element type. make test / shakesmoke green, selfhost holds, 0 new divergences. |
||
|---|---|---|
| .. | ||
| image.ss | ||
| prelude.ss | ||
| README.md | ||
Chez bootstrap seed
These two files are the bootstrap compiler for jolt — the seed that makes the build self-hosting:
prelude.ss— theclojure.coreprelude (all tiers + clojure.string/walk/ template/edn/set/pprint) as Schemedef-var!forms.image.ss— the compiler image (jolt.ir+jolt.analyzer+jolt.backend-scheme) as Schemedef-var!forms.
Both are generated, not hand-written. They are checked in because a fresh
checkout must be able to build jolt-on-Chez using only Chez: host/chez/bootstrap.ss
loads this seed, then rebuilds the prelude + image from the .clj/.ss sources via
the on-Chez compiler (read → analyze → emit, all on Chez). The seed is a joint
byte-fixpoint: rebuilding from an up-to-date seed reproduces it exactly.
make selfhost (host/chez/selfcheck.sh) runs host/chez/bootstrap.ss and diffs
the rebuilt artifacts against the checked-in seed.
Re-minting
When the seed sources change (the core tiers, the compiler namespaces, the host
contract, the reader, emit-image.ss), the seed drifts and make selfhost
fails. Re-mint it by running host/chez/bootstrap.ss and writing the freshly
rebuilt prelude/image back to host/chez/seed/prelude.ss /
host/chez/seed/image.ss, then commit the refreshed files.