Specification-First Compiler Architecture
This document owns the compiler-wide pipeline, dependency direction, and contracts that cross crate boundaries. It does not define Nocter language behavior and does not describe a crate's private module structure. Public language, platform, and tooling behavior belongs to the language specification; standard-library behavior belongs to its checked source and colocated documentation; crate-local design belongs to the relevant colocated README.md.
Program Pipeline
SourceProgram
-> SyntaxProgram
-> DiscoverySnapshot / CompileUnitInput
-> DeclarationProgram
-> AcceptedDeclarationProgram
-> CheckedProgram
-> TargetProgram
-> ExecutableProgram
-> MirProgram
-> MachineProgram
-> Arm64Program
-> MachOImage
Each arrow is a one-way lowering boundary. The producer decides and validates its own facts once. The consumer receives identities and closed decisions through the producer's public contract; it cannot recover a decision by reading source text, traversing an earlier representation, rendering a name, or depending on insertion order.
The primary owners are:
| Boundary | Owner |
|---|---|
| normalized source and coordinates | nocter-source |
| lexical and syntactic structure | nocter-syntax |
| package source discovery | nocter-discovery |
| closed compilation input | nocter-compile-input |
| immutable declaration model | nocter-declarations |
| syntax-to-declaration lowering | nocter-declaration-lowering |
| typed semantics and ownership | nocter-checking |
| target validation and executable closure | nocter-target-program |
| concrete semantic control flow | nocter-mir |
| target-independent machine operations and ABI | nocter-machine |
| ARM64 selection and encoding | nocter-arm64 |
| Mach-O image construction | nocter-macho |
The checked-program, target/executable/MIR, and machine/native documents define only the contracts spanning adjacent owners. The crate READMEs own internal responsibility splits and invariants.
Side Authorities
Some responsibilities accompany the main lowering pipeline without becoming semantic stages:
filesystem overlay ---------> package/discovery/session input
source projection <---------- lowering and checking identities
diagnostics <---------------- source-backed failures from every stage
analysis queries <----------- semantic evidence + source projection
workspace analysis ---------> immutable editor generations
language server ------------> protocol projection only
command/native session -----> pipeline orchestration and artifact publication
Their owners are:
| Responsibility | Owner |
|---|---|
| immutable disk/open-document view | nocter-filesystem |
| accepted editor source revisions | nocter-workspace-revision |
| revisioned dependency evaluation and reuse | nocter-computation |
| semantic identity to source projection | nocter-source-index |
| phase-neutral diagnostics | nocter-diagnostics |
| compiler session composition | nocter-session |
| bundled standard declaration profile | nocter-standard-profile |
| protocol-independent semantic queries | nocter-analysis |
| workspace revisions, topology, and compilation demand | nocter-workspace-analysis |
| LSP lifecycle and result projection | nocter-language-server |
| protocol data model and codec | nocter-lsp |
| CLI command planning | nocter-command |
| native backend orchestration | nocter-native-session |
A side authority cannot become a second semantic pipeline. In particular, source projection may locate an already selected identity but cannot decide type equality, lookup, dispatch, ownership, reachability, ABI, or code generation. Protocol code cannot inspect compiler storage to recreate a query, and orchestration code cannot implement a stage's validation rule.
Identity and Authority Rules
- Semantic identity domains are syntax-independent and owned by
nocter-model. - Public language vocabulary and closed language constants are owned by
nocter-language. - Runtime primitive and representation identities are owned by
nocter-runtime-contract. - Toolchain-selected declarations and standard roles are owned by
nocter-toolchain-contractand projected throughnocter-frontend-bindings. - The physical source locators for the compiler-bundled standard package are owned once by
nocter-standard-profile; production and physical-source tests cannot reconstruct that catalog. - Persistent semantic storage is an implementation facility owned by
nocter-persistent; only the semantic owner may expose domain-specific transactions. - A raw ID has meaning only with the immutable program or authority that owns its generation.
- Accepted products are complete values. A rejected product exposes only explicit recovery evidence justified by its source diagnostic.
- A builder is the sole mutation path for its product. Freezing validates every cross-identity edge.
Supporting boundary crates remain deliberately narrow:
| Responsibility | Owner |
|---|---|
| syntax-owned target-gate decisions | nocter-target-selection |
| compile-time expression evaluation | nocter-constant-evaluation |
| source-only formatting and inspection | nocter-source-tooling |
| deterministic JSON and byte-stream hashing | nocter-json and nocter-hash |
| physical file and regular-tree content identity | nocter-content-integrity |
| outer process boundary | nocter-cli |
| shared test fixture construction | nocter-test-support |
| whole-pipeline conformance tests | nocter-conformance |
Package and Installation Boundary
Package interpretation and package-state mutation are separate:
| Responsibility | Owner |
|---|---|
| package declarations, roots, exact selections, and resolved graphs | nocter-package |
| exact-package cache representation and content verification | nocter-package-cache |
| root dependency-source transitions and exact-package cache publication | nocter-package-state |
| authenticated Git/archive acquisition | nocter-package-acquisition |
| installed toolchain validation | nocter-installation |
Resolution consumes an immutable filesystem view. Acquisition and package-state publication cannot run through an editor overlay. Root dependency-source commit is failure-atomic; each dependency's source-specific commit or sha256 field is its sole selection authority. Validated exact packages publish independently into an append-only cache, so a cache entry may remain after a later root-source rejection without changing the selected graph. Acquisition seals each staged tree with one deterministic content manifest. Publication and later resolution use the same verification contract, so a changed cache tree cannot retain its exact identity. An interrupted acquisition cannot expose a partial exact package, and an interrupted installation cannot expose a partial toolchain. Package display names never replace canonical package identities. Workspace topology freezes a revision-local package-root catalog; package loading and discovery extend that catalog without reopening a root already selected from the same overlay.
Physical content identity is a shared mechanism, not a package or installation authority. nocter-content-integrity defines one deterministic regular-tree projection. Package-cache sealing, installation validation, and release assembly select their roots and exclusions, then consume that projection. An installed manifest binds the compiler file and complete standard-library tree. The installation layer validates those bytes without parsing Nocter source; package resolution remains the sole owner of the standard package declaration and checks its declared name and version against the installation-selected release.
Editor Generation Boundary
One accepted document event is admitted by nocter-workspace-revision and produces one immutable workspace revision. Workspace analysis freezes topology and compilation demand for that revision, then produces one analysis snapshot per selected scope. A changed or closed document may invalidate active demand but cannot silently become demand.
One compiler session produces one semantic-evidence value. Successful and recovered evidence are exclusive variants, not independent optional fields. Analysis joins that evidence with a validated source projection once and exposes typed query results. Features depend on the capability they need, not a phase ordinal. Set-valued queries state whether coverage is complete; mutations require a validated complete candidate before publication.
The semantic presentation boundary owns compiler-to-editor rendering rules. The incremental computation boundary owns the revision-pinned dependency graph, invalidation, and reuse contract. Computation may reuse an owning stage's immutable product but cannot change its semantic authority or editor presentation contract.
Dependency Enforcement
development/compiler/Cargo.toml is the sole workspace-membership authority. Crate manifests own exact dependency edges. Executable architecture tests validate reviewed production dependencies, while compiler-resolved Clippy restrictions prevent prohibited types or construction methods from crossing owner boundaries through aliases or re-exports.
The production graph must obey these rules:
- source and syntax do not depend on semantic stages;
- semantic model does not depend on source or syntax;
- checking cannot depend on target, MIR, machine, native encoding, analysis, or protocol crates;
- target and MIR cannot inspect syntax or repeat name/type/dispatch selection;
- machine and native emitters cannot inspect semantic declaration or checking storage;
- language-server code cannot depend directly on compiler semantic storage;
- test support and conformance may compose production contracts but cannot supply production behavior.
The architecture review rejects compatibility imports, reverse semantic lookup from presentation, parallel registries for the same identity, source-order tie-breaking, feature-local recovery joins, and wrappers whose only purpose is to bypass an owner contract.
Documentation Boundary
This document changes only when a pipeline edge, cross-crate authority, or dependency rule changes. A crate-internal refactor changes that crate's README. A public language, platform, or tooling change changes spec/; a public standard-library change changes its owning index.nct or colocated README. A temporary implementation plan changes a milestone. Review findings and remediation evidence belong in development/history/reviews/; release qualification belongs in development/history/release-audits/.