From bcd752717e44e537f8a3f7822baf39c4c292c4db Mon Sep 17 00:00:00 2001 From: Yogthos Date: Tue, 23 Jun 2026 22:52:20 -0400 Subject: [PATCH] Remove REFACTOR_PLAN.md (now tracked in beads epic jolt-g7t1) --- REFACTOR_PLAN.md | 117 ----------------------------------------------- 1 file changed, 117 deletions(-) delete mode 100644 REFACTOR_PLAN.md diff --git a/REFACTOR_PLAN.md b/REFACTOR_PLAN.md deleted file mode 100644 index 6c0c50f..0000000 --- a/REFACTOR_PLAN.md +++ /dev/null @@ -1,117 +0,0 @@ -# Architecture refactor plan - -Working doc for the `spike/arch-refactor` branch. Goal: make the codebase easier -to understand and safely modify — optimized for both human and LLM maintainers. -Derived from a four-part review (compiler core, Chez runtime, build/tooling, -top-level organization) plus call-graph analysis of the compiler. - -The codebase is in better shape than its 58-file runtime suggests: `rt.ss` is a -real load-order map, the `passes/` split is clean, filename prefixes encode tier -order, and the Makefile self-documents the gate. The work below targets the few -genuine liabilities. - -## The re-mint constraint shapes risk - -- **Seed sources** (`jolt-core/jolt/*.clj`, `jolt-core/clojure/core/*.clj`, - `host/chez/reader.ss`): a change needs `make remint` + the byte-fixpoint - `make selfhost`. Behaviour-preserving refactors are *verified* by selfhost, but - every touch costs a re-mint. Higher risk, batch them. -- **Runtime `.ss` + runtime-loaded `.clj`** (`build.ss`, `emit-image.ss`, - `main.clj`, the dispatcher shims, …): no re-mint; verified by `make test` + - `make shakesmoke`. Lower risk. -- **Docs / renames of non-seed files**: zero behaviour risk. - -## Tier 0 — navigability (zero risk, highest LLM value, do first) - -1. **`docs/MODULES.md` — the repo map.** One table: area → directory → key files → - re-mint? Plus a per-feature "touch points" list for cross-cutting features - (tree-shaking, direct-linking, numeric fl/fx, multimethods, the deps resolver). - Collapses the current 3–4-source lookup ("where does X live?") into one read. -2. **`docs/rfc/README.md`** — index the 7 RFCs (number, title, status), mirroring - `docs/spec/README.md`. -3. **Document the shipped-but-undocumented compiler features**: IR inlining and - fl*/fx* numeric lowering (the `passes/` pipeline). A short "compilation passes" - doc or an RFC, referenced from RFC 0007. -4. **CLAUDE.md — one "Invariants you must preserve" block**: the `var-deref` - calling convention (the compiler is reached from `.ss` by string lookup), the - `def-var!` native-binding pattern, and the seed dual-home shadowing rule (today - only in `seed-overlay-registry.md`). -5. **First-line purpose comment on every `.ss`** (audit the laggards) and note the - reader's surprising location (`host/chez/reader.ss`, Scheme, re-mint applies). - -## Tier 1 — runtime structure (no re-mint; verify with `make test` + shakesmoke) - -6. **Registry pattern for the core dispatchers — the biggest runtime win.** - `jolt-pr-str`, `jolt-pr-readable`, `jolt=2`, `jolt-get`, `jolt-class`, - `jolt-hash` are extended by `set!`-capture-and-rebind across ~8 files (e.g. - `jolt-pr-str` is wrapped 9× in 8 files). The registry pattern already exists in - tree (`register-str-render!`, `register-instance-check-arm!`) and is strictly - better: type-disjoint arms gathered in one walker, load-order-independent, - greppable. Add `register-pr-arm!` / `register-eq-arm!` / `register-get-arm!` / - `register-hash-arm!` / `register-class-arm!`; convert the ~35 `set!` sites to - one-line registrations. Eliminates "read 8 files to understand one dispatcher." -7. **Extract a `host/chez/dce.ss` module for tree-shaking.** The DCE logic is split - across `emit-image.ss` (the `dce-*` helpers + record producer) and `build.ss` - (`bld-shake-all` + the manifest splice). Pull every `dce-*` def + `bld-shake-all` - (→ `dce-shake`) into `dce.ss`; give the record a named accessor API - (`dce-rec-keep?`/`-fqn`/`-refs`/`-str`) instead of `(vector-ref r 0..3)`; split - `bld-shake-all`'s five jobs (root-seed, edge-build, BFS, bail-detect, partition) - into named steps. This is recently-added code and the loosest contract in the - build. -8. **Tag the runtime manifest.** `bld-emit-runtime` decides "splice shaken core" / - "drop compiler" by substring-matching `(load "…seed/prelude.ss")` strings. - Replace the manifest with tagged entries (`(prelude)`/`(image)`/`(compile-eval)`/ - `(load path)`) and dispatch on the tag — removes a silent-failure coupling. -9. **`build-binary` options map.** It takes 8 positional args ending in two bare - booleans (`direct-link?` `tree-shake?`); a swap compiles and misbehaves silently. - Pass one options map from `main.clj`; new flags become additive. -10. **`dynamic-wind` the compiler-global set/reset** in `build-binary` so - `set-optimize!`/`set-direct-link!` always revert (today they leak on a build - error; harmless for the CLI, a trap for any in-process caller). -11. **Re-split `host-static-{,statics,objects}.ss`** on a real axis — static - methods/fields vs host object classes — instead of the current "grew too big" - chain (one file is 502 lines, the largest non-seed runtime file). Move the - System-property/env plumbing out to `io.ss` / a `host-system.ss`. -12. **Consolidate the seq/transducer/parity natives** and dissolve - `natives-parity.ss` (a literal leftovers file). One `natives-transduce.ss` for - `td-*`/`into-xform`/`transduce`/`sequence`/`cat`; relocate parity's hash / - macroexpand / reader-conditional pieces to their real homes. -13. **Smaller renames/moves:** `dynamic-vars.ss` (5 constants) vs `dyn-binding.ss` - (the binding stack) — rename the former; pull the `format` engine out of - `natives-misc.ss` into `natives-format.ss`. - -## Tier 2 — compiler core (seed sources; re-mint + selfhost + corpus) - -14. **Split the success-type checker out of `types.clj`** (716 lines = inference + - checker + driver). Move the checker (`check-*`, the error-domain predicates) to - `jolt.passes.types.check`. Highest reduction in edit blast-radius in the - compiler — inference and checker stop being able to break each other. -15. **Decompose `infer`'s `:invoke` arm** (≈120 lines, 8 hand-coded call patterns) - into named `infer-` helpers (as `numeric.clj`'s `an-invoke` already - does), and add `ty`/`nd` accessors for the positional `[type node]` tuple - (a transposition is currently silent and type-correct). -16. **Single-source the const-keyword-lookup recognizer.** It's implemented three - times divergently (`inline.clj`, `types.clj` ×2 arms, `backend_scheme.clj`). - Lift one predicate into `jolt.passes.fold` (the shared-predicate home) for the - two analysis copies; the backend's value-emission copy can stay. -17. **Co-locate the numeric op tables.** `backend_scheme.clj` (`dbl-ops`/`lng-ops`, - the Scheme strings) and `numeric.clj` (`dbl-spec`/`lng-spec`, specializable - names) must agree or `emit-numeric` splices a `nil` op string. Cross-link or - share the name→op table. -18. **Collapse `local-escapes?`'s mechanical recursion** (≈12 of its arms are just - "does any child escape" = `reduce-ir-children`); keep only the binder/lookup - arms explicit. Removes ~50 lines and a new-op soundness hazard. Fold - `recur-kinds`/`recur-arg-lists` (numeric) into one `recur-tails`. -19. **Touch-when-nearby:** drop the dead `form-char?` refer in `analyzer.clj:21`; - standardize on `(get node :k)` in the pass files; promote a few inline-comment - soundness arguments to function docstrings (`an-invoke` `:wild`, `dbl/lng-spec`). - -## Sequencing - -Tier 0 lands immediately (docs only). Tier 1 is the bulk of the maintainability win -and carries no re-mint — do 6 (registry) and 7–10 (DCE module + build hygiene) -first; they target the code most likely to be edited and most recently grown. -Tier 2 batches into one or two re-mints once Tier 1 is stable, each verified by -`make selfhost` + `make corpus`. - -Every code change in Tiers 1–2 is behaviour-preserving and gated; no feature work.