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
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:
directlowerableruntime-requiredunsupportedunknown
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.