Issue #793: A modular compiler: what to split so a step rebuilds less and two builders can run

Open and answer this issue on GitHub.

decision · opened 2026-10-24 · updated 2026-10-24 · 0 comments

How it came up

The owner asked (2026-10-24) whether the compiler can be modularised, perhaps with dynamic linking, so that prebuilt parts stay while others change, and so that builders can later run in parallel. The architect checked the code and wrote the decision basis: docs/modular-compiler.md.

What was found

Recommendation (for the owner to confirm)

Do: one module per .nika (#667 step 4), one generated file per .nika, one integration-test binary; then stage 2 with a worktree and CARGO_TARGET_DIR per builder, on disjoint files. Not: a crate split of crates/nikaia, dylib, cdylib plugins. Later: a nikaia-tools crate, nextest/sccache in CI.

To build

  1. #667 step 4: lower-std writes each .nika’s body as mod <file>_body { use super::*; ... } plus pub use <file>_body::*; (private items lower pub(super)). Test: the sysroot test; the count of changed .o bytes in target/fast/incremental/nikaia_std-*/s-* after a one-line .nika change, before and after (method in the doc). Keep only if it falls.
  2. One generated file per .nika (tools/lowered/<file>.rs, include!d by step 1’s modules); CI’s freshness check and scripts/self_hosting.py follow. Test: the sysroot test, scripts/self_hosting.py unchanged share.
  3. One integration-test binary (crates/nikaia/tests/it/main.rs, one module per former file, common once); CLAUDE.md and .claude/agents/builder.md: --test a becomes --test it a::. Test: the same number of tests pass as before (count from cargo test -- --list); bytes in target/fast after --no-run, before and after.
  4. docs/architect.md: stage 2 conditions (worktree + own CARGO_TARGET_DIR, disjoint .nika files and adapters, one builder at a time on emit/mod.rs, check/mod.rs, project.rs).

Step 1 is ready (it is #667’s); steps 2-4 wait for the owner’s yes to the direction.

Back to Open Issues