How the crates in the Nikaia workspace stack up. The separation they implement is ADR-003: the language and the machinery that compiles it are two programs, and the interface between them is Rust source text.
graph TD
A[User source .nika] -->|Input| B(Crate: nikaia)
subgraph Frontend
B -->|Parses| C{AST}
C -->|Lowers| D[Rust source text]
end
D -->|Written out| E[Generated .rs]
E -->|Invokes| F[System rustc]
F -->|Produces| G[Binary executable]
H(Crate: orchestrator) -.->|cache, manifest, cargo| B
I(Crate: nikaia-std) -.->|linked into| G
crates/nikaiaclap; nikaia build, nikaia run,
nikaia lower-std, and nikaia lower, interpret and explain for
a single file.winnow-grammar (and winnow) parse .nika sources into
a Nikaia-specific AST — over bytes, not over Rust tokens
(ADR-001 D2).src/ast.sync, provenance, statement ordering —
src/check, src/contracts.src/emit turns the AST into Rust source text, in one
pass, and writes a SourceMap beside it. It is the only code generator
in the toolchain (ADR-004 D1).rustc --error-format=json read back and reported
against the .nika line that caused it
(ADR-300).orchestrator, winnow-grammar.crates/orchestratorcache: the build-cache key, the content-addressed store and
nikaia.lock (ADR-021).project: nikaia.toml rendered to a Cargo.toml, cargo driven
over it, and RUSTC_WORKSPACE_WRAPPER injected so that a .nika file
on a rustc command line is lowered and a crate from crates.io is not
(ADR-002 D1).LanguageFrontend: the trait a frontend implements — source text in,
Rust source text out, and nothing else crossing the line.crates/nikaia-stdfs, io, text,
list, html, the CLI surface..rs
committed beside the .nika and regenerated by nikaia lower-std
(ADR-002 D4). A project reaches it through
a sysroot, not through a registry.let x = 5ast::Stmt::Let { name: "x", value: LitInt(5), … }let x = 5; inside the generated fn main, plus the source
map entry that points that line back at the .nika one.