Speak in meaning. Think beyond syntax. Built beyond language.

Architecture

Canonical identity

The architectural invariant is:

SemanticProgram = Universal Semantic AST = canonical IR

There are not two permanent intermediate representations. Historical statement/expression trees may still appear as migration or compatibility views, but they must not become a second source of semantic truth.

Compiler layers

flowchart TB S[Source text] --> F[Language frontend] F --> U[SemanticProgram / Universal AST] U --> V[Validation & semantic contracts] U --> R[Semantic runtime] U --> E[Source emitters] U --> N[Native backend] N --> I[Machine IR] I --> X[x86-64 selector] X --> C[COFF object writer] C --> P[PE image / executable]

Universal semantic payload

The canonical representation carries more than a syntax tree. Depending on the node and frontend evidence it can include:

  • stable node IDs and scopes;
  • structured types and type origin;
  • semantic facets;
  • source spans;
  • effects;
  • symbol/binding evidence;
  • evaluation ordering;
  • call and dispatch information;
  • syntax/control/data/type/effect relations;
  • extensions and contracts.

A backend is responsible for preserving the semantics it claims to support. Unknown data is not permission to guess.

Capability model

Backend behavior is intended to be explicit. A semantic feature can be classified as:

  • direct
  • lowerable
  • runtime-required
  • unsupported
  • unknown

Unsupported or unknown demand should be rejected rather than emitted incorrectly.

Compatibility views

Legacy views can still be reconstructed for compatibility, but the data flow should remain one-way:

Canonical UAST
    ↓
Derived compatibility view

A mutation to a compatibility view must not overwrite the canonical UAST.

Why this matters for selfhosting

A selfhosting compiler exercises the architecture more aggressively than ordinary transpilation. The compiler itself uses structures, maps, control flow, selectors, indexing, module metadata, native machine descriptions and object emission. Every semantic hole becomes visible during bootstrap.

That is why the object-debug pipeline is useful: it exposes precisely which compiler units have enough native semantic coverage and which still hit a fail-closed boundary.