Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/design/architecture.md

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:

BoundaryOwner
normalized source and coordinatesnocter-source
lexical and syntactic structurenocter-syntax
package source discoverynocter-discovery
closed compilation inputnocter-compile-input
immutable declaration modelnocter-declarations
syntax-to-declaration loweringnocter-declaration-lowering
typed semantics and ownershipnocter-checking
target validation and executable closurenocter-target-program
concrete semantic control flownocter-mir
target-independent machine operations and ABInocter-machine
ARM64 selection and encodingnocter-arm64
Mach-O image constructionnocter-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:

ResponsibilityOwner
immutable disk/open-document viewnocter-filesystem
accepted editor source revisionsnocter-workspace-revision
revisioned dependency evaluation and reusenocter-computation
semantic identity to source projectionnocter-source-index
phase-neutral diagnosticsnocter-diagnostics
compiler session compositionnocter-session
bundled standard declaration profilenocter-standard-profile
protocol-independent semantic queriesnocter-analysis
workspace revisions, topology, and compilation demandnocter-workspace-analysis
LSP lifecycle and result projectionnocter-language-server
protocol data model and codecnocter-lsp
CLI command planningnocter-command
native backend orchestrationnocter-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-contract and projected through nocter-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:

ResponsibilityOwner
syntax-owned target-gate decisionsnocter-target-selection
compile-time expression evaluationnocter-constant-evaluation
source-only formatting and inspectionnocter-source-tooling
deterministic JSON and byte-stream hashingnocter-json and nocter-hash
physical file and regular-tree content identitynocter-content-integrity
outer process boundarynocter-cli
shared test fixture constructionnocter-test-support
whole-pipeline conformance testsnocter-conformance

Package and Installation Boundary

Package interpretation and package-state mutation are separate:

ResponsibilityOwner
package declarations, roots, exact selections, and resolved graphsnocter-package
exact-package cache representation and content verificationnocter-package-cache
root dependency-source transitions and exact-package cache publicationnocter-package-state
authenticated Git/archive acquisitionnocter-package-acquisition
installed toolchain validationnocter-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/.