The source loader sets the current ns and registers :as aliases per file. The
build flattened every app namespace into one image with no such markers, so all
app forms ran under the last-set ns ("user"). Two breakages followed, both only
in a built binary:
- defmulti/defmethod resolve their target var through chez-current-ns, so they
registered the multifn under "user" while compiled var-derefs used the baked
ns — the multifn the app saw was uninitialized ("not a fn nil" on dispatch).
- a quoted alias-qualified symbol (a (defmethod ig/foo …) on an aliased multifn)
resolves its ns through chez-resolve-alias, but the stripped (ns …) form left
the alias table empty, so it landed in ns "ig".
bld-ns-prelude now emits (set-chez-ns! ns) plus chez-register-alias! for each
ns's :as aliases before that ns's forms, in both the normal and tree-shake emit
paths. The build-app fixture gains a :default multimethod and an aliased cross-ns
defmethod so buildsmoke covers both across all build modes.
5.9 KiB
Module map
Where things live and what to read before changing them. Start here to answer "where does feature X live?" and "what else do I need to touch?"
Areas
| Area | Directory | Responsibility | Re-mint? |
|---|---|---|---|
| Chez runtime | host/chez/*.ss |
The substrate: value model, persistent collections, seqs, vars/namespaces, host interop, native clojure.core shims, regex, FFI, IO, the reader. Composed by rt.ss. |
only reader.ss |
| Compiler | jolt-core/jolt/*.clj |
analyzer → IR → backend, the optimization passes, the CLI, the deps resolver, nREPL. Baked into the seed. | yes |
clojure.core overlay |
jolt-core/clojure/core/NN-*.clj |
Portable clojure.core in dependency-ordered tiers (00-syntax … 50-io); the NN prefix is the load order. |
yes |
| Stdlib | stdlib/clojure/*.clj |
Lazily-loaded portable namespaces (string/set/walk/edn/pprint/zip/test/data). | no |
| Build & tooling | host/chez/build.ss, emit-image.ss, compile-eval.ss, loader.ss, cli.ss, bootstrap.ss |
AOT binary build, cross-compile, runtime eval/load, CLI spine, seed mint. | no (except via reader.ss) |
| Tests & gate | test/chez/, test/conformance/, host/chez/run-*.ss, Makefile |
Corpus (JVM oracle), unit, per-feature tests. Every make target has a comment. |
no |
The reader is in host/chez/reader.ss (Scheme, a seed source) — not in
jolt-core/jolt/ with the rest of the compiler. Re-mint applies to it.
rt.ss is the runtime's load-order manifest: it (load …)s every shim in
dependency order with a per-file comment. Read it to see how the runtime is
composed and where a given .ss fits.
host/chez/*.ss by family
- Value model:
values.ss(nil/numbers/keywords/symbols),collections.ss(persistent vec + HAMT map/set),seq.ss+lazy-bridge.ss(seqs, lazy-seqs),transients.ss,records.ss+records-interop.ss. - Native
clojure.coreshims:natives-*.ss(array/coll/format/meta/misc/num/ queue/reader/seq/str/transduce), pluspredicates.ss,converters.ss,printing.ss. - Vars / namespaces / dynamics:
vars.ss,ns.ss,dyn-binding.ss(the thread-local binding stack),dynamic-var-defaults.ss(a few*…*constant defaults),atoms.ss,multimethods.ss. - Host interop:
host-class.ss(class tokens + method dispatch),host-static.ss(interop registry core) +host-static-methods.ss(Class/memberstatics) +host-static-classes.ss(instantiable object classes),host-table.ss,host-contract.ss(thejolt.hostseam the compiler resolves against),dot-forms.ss,records-interop.ss. - Scalars / misc:
regex.ss(vendored irregex),math.ss,inst-time.ss,bigdec.ss,syntax-quote.ss. - IO / system / concurrency / FFI:
io.ss,png.ss,concurrency.ss,async.ss,ffi.ss. - Compiler entry on Chez:
reader.ss,compile-eval.ss,emit-image.ss,loader.ss,cli.ss,build.ss,bootstrap.ss.
Where is a clojure.core fn implemented?
Two homes, with a defined precedence:
- Native shim — a
(def-var! "clojure.core" "name" …)in ahost/chez/*.ss(hot/representation-coupled fns:first,get,=, the predicates). - Overlay — a
defnin ajolt-core/clojure/core/NN-*.cljtier (most ofclojure.core, in portable Clojure). post-prelude.ssre-asserts a handful of natives after the overlay loads, so the native version wins (the overlay's value-reading versions are wrong for Chez-native chars/atoms/etc.). Each entry there says why.
grep 'def-var! "clojure.core" "frequencies"' host/chez and
grep -rn 'defn frequencies' jolt-core/clojure/core to find a given fn. See
seed-overlay-registry.md for the shadowing mechanism.
Cross-cutting features — touch points
A feature's core lives in one file; these are the other files you must keep in sync when changing it.
- Tree-shaking / DCE (
--tree-shake):emit-image.ss(thedce-*helpers + record producers) andbuild.ss(bld-shake-allreachability + the manifest splice inbld-emit-runtime); the flag inmain.clj; validated byhost/chez/tree-shake-smoke.sh(make shakesmoke) andbuild-smoke.sh. See tools-deps.md. - Direct-linking (
--direct-link):backend_scheme.clj(direct-link?,emit-top-form, thejv$<fqn>bindings);build.ssturns it on;main.cljthe flag;test/chez/directlink-test.ss. - Numeric fl/fx** (
^double/^longhints):jolt-core/jolt/passes/numeric.clj(the hint-directed pass + loop-counter +:coerce);backend_scheme.clj(dbl-ops/lng-opsop strings,emit-numeric, entry/return coercion);analyzer.clj(nhint-of,:nhints,with-ret-nhint);host-contract.ss(:num-reton resolve);rt.ss(jolt->fx);test/chez/numeric-test.ss. - IR inlining (under
--opt):passes/inline.clj(splice) +passes.clj(stash) +host-contract.ss(inline-ir/stash-inline!);test/chez/inline-test.ss. - Multimethods:
host/chez/multimethods.ss(dispatch) + the overlaydefmulti/defmethodmacros +host-contract.sslate-bind. - AOT namespace context (
jolt build):build.ss(bld-ns-prelude) emits(set-chez-ns! ns)+chez-register-alias!per app namespace (both the normal and tree-shake emit paths), matching the loader's per-file ns context;test/chez/build-app(make buildsmoke). - Deps resolution:
jolt-core/jolt/deps.clj(the only file) +main.clj(applies the roots) +loader.ss(therequirepath).
Conventions you must preserve
See CLAUDE.md → "Conventions & Patterns" for the load-bearing rules: the
re-mint trigger, the tier macro-ordering rule, the get-on-your-own-wrapper trap,
:jolt/type-as-a-key parsing, the var-deref calling convention (the compiler is
reached from the .ss runtime by string lookup, so a public defn with no
in-Clojure callers can still be live), and the writing style.