V1 Compiler Implementation Tasks¶
Working direction
Implementation task plan extracted from Scope Backlog. The scope backlog owns language-design acceptance; this page owns later compiler sequencing, modularity, and verification work.
This page tracks implementation and verification work needed after the V1 language design is accepted. It should not introduce new language semantics. If a task discovers a missing or contradictory language rule, update the owning design page and the Scope Backlog before treating the implementation behavior as settled.
V1 scope is complete. The slices below are implementation sequencing only; they do not defer accepted V1 language features.
Architecture Rules¶
Catalyst implementation should stay modular, with small phase-local modules and typed artifact boundaries inspired by Compiler Pipeline and Phase Boundaries.
- Every phase has a typed input artifact and typed output artifact.
- Later phases consume only the previous phase's public artifact.
- Debug consumers and stubs are allowed in early slices, but they must use the same artifact boundary as the real implementation.
- Backends consume
VerifiedIRrather than unverified IR. - The interpreter consumes
VerifiedIRrather than unverified IR, including in comptime mode. - Parser code must not resolve names, infer types, or query the type table.
- Sema must not emit C-specific forms or backend layout structs.
- Lowering must not recover source syntax from tokens or AST trivia.
- C backend output must not rerun semantic checks, inspect AST attributes, or call sema helpers.
- Snapshot output is part of the public implementation contract for each phase that exists in a slice.
- Stubs must be explicitly named in the slice that allows them and removed or tracked before V1 final acceptance.
Implementation Toolchain¶
The reference compiler implementation targets Zig 0.16.0.
Agent implementation tasks should assume Zig 0.16.0 for build files, standard-library APIs, test commands, CI setup, and generated examples. Do not silently update the compiler implementation to another Zig version during a slice. If a task needs a different Zig version because of a toolchain bug, missing API, or release availability issue, report the blocker in the handoff and ask for explicit approval before changing the target version.
Module Boundaries¶
The implementation should use concrete subsystem boundaries. Exact source paths may vary, but ownership should stay clear.
| Module | Ownership |
|---|---|
driver |
CLI parsing, command dispatch, input/output path handling, session construction, exit codes |
session |
immutable invocation config, phase options, shared services, selected target, safety mode, build profile |
target |
normalized target facts: pointer width, endianness, maximum object alignment, bit-precise integer support, selected C ABI family, target-selected layout facts |
source |
file loading, file IDs, source text, spans, path normalization primitives |
modules |
root module registry, module identity, namespace loading, include/module resolution policy, module manifests, import/re-export filtering, dependency diagnostics |
diagnostics |
structured diagnostics, notes, warnings, fatal errors, deterministic rendering |
hooks |
typed HookBus, deterministic hook ordering, phase-owned hook points |
lex |
source text to tokens and trivia |
parse |
tokens to AST and syntax diagnostics, using Catalyst Source Grammar as the source grammar map |
ast |
AST node storage, spans, deterministic AST dumps |
names |
scopes, namespaces, imports, visibility, symbol IDs |
types |
type table, primitive types, type constructors, layout queries |
sema |
AST to SIR, type checking, name resolution, source semantics |
sir |
semantic artifact model and deterministic dumps |
comptime |
demand interface, compiler-owned handles, intrinsic registry metadata, host-intrinsic dispatch, interpreter bridge |
lower |
SIR to IR lowering, lowering-intrinsic expansion |
ir |
IR data model, verifier, deterministic IR dumps |
interp |
verified IR interpreter |
backend_c |
C emission from verified IR only |
prelude |
seeded prelude loading and bootstrap support |
lint |
lint passes over hook points and artifacts |
tests |
snapshot harness and integration runner |
HookBus¶
Hooks are internal compiler extension points, not a public V1 plugin API.
Hook points are typed and phase-owned. A hook point declares:
- input artifact;
- allowed outputs or mutations;
- deterministic ordering;
- diagnostic authority;
- whether it may affect source semantics;
- whether it may abort the current phase or compilation.
Hooks may observe, transform, emit diagnostics, and error out only when the hook-point contract grants that authority. Hooks must not reach around the current artifact boundary. Semantic-changing hooks are compiler-owned in V1. Lints should be implemented through hooks or artifact passes when possible; if a lint needs semantic facts owned by a phase, the phase may expose those facts through a typed hook point rather than hardwiring lint policy into unrelated code.
Hook execution order is part of the hook-point contract:
- hook points run in fixed pipeline order;
- within a hook point, compiler-owned hooks run by explicit registration group: normalization, lint, then debug/check;
- within each group, hooks run by stable hook ID, not source discovery order, map iteration order, filesystem order, or module load order;
- hooks that may mutate an artifact must declare that authority in the hook-point contract and must run before observe-only hooks for the same artifact.
V1 should start with these internal hook points:
| Hook point | Artifact | Default authority |
|---|---|---|
after_parse |
AST | observe; emit syntax/style/lint diagnostics; abort only through fatal diagnostics |
after_sema |
SIR | observe; emit semantic/lint diagnostics; abort for hard semantic diagnostics |
before_verify |
IR | observe; compiler-owned normalization hooks may transform when explicitly registered; abort for lowering/verifier-prep diagnostics |
after_verify |
VerifiedIR | observe; no transform; emit backend-independent warnings/debug checks; abort only for internal consistency failures |
before_emit_c |
VerifiedIR | observe; no transform; emit backend diagnostics; abort for unsupported target/backend forms |
Slice Format¶
Each vertical slice should record:
- goal;
- accepted source subset;
- required real modules;
- required snapshots or runtime outputs;
- allowed stubs;
- forbidden shortcuts and anti-leak rules.
Each slice or sub-slice should be directly assignable to an implementation agent by ID. A request such as "implement Slice 0a from compiler/v1-implementation-tasks.md" means the agent must implement that slice's local requirements, inherit the parent slice requirements, follow this page's architecture rules, and consult the linked canonical docs before inventing behavior.
Every agent handoff should return:
- summary of behavior implemented;
- commands run;
- fixtures and snapshots added or updated;
- stubs introduced or retired;
- phase-boundary notes for any new artifact or cross-module dependency;
- design ambiguities or contradictions discovered;
- recommended next slice or sub-slice.
Early slices may stop at the latest implemented boundary or use a debug consumer. Once a slice claims executable behavior, it should pass through SIR, IR, verifier, and at least the interpreter unless the slice explicitly says otherwise.
Implementation should follow the test strategy in Testing: prefer tracer-bullet TDD, add one failing public behavior fixture at a time, and keep snapshot updates in the narrowest phase that proves the rule.
Comptime Capability Ladder¶
Comptime is a cross-cutting implementation spine, not a single isolated feature slice. Each slice that consumes comptime must name the comptime capability it relies on and the compiler-owned handles or intrinsics it adds.
The capability ladder is:
- Slice 17 establishes the demand interface, primitive comptime values, already-known primitive
Typehandles, function item values, explicit comptime parameters, ordinary function calls during demanded comptime evaluation, and the typed intrinsic registry with category/effect/context metadata. - Slice 18 adds prelude bootstrap use: primitive factory wrappers, primitive aliases, source-loaded prelude declarations,
Namespacehandles as needed formoduleandinclude, and validation roots that demand the prelude surface. - Slice 20 adds attribute-provider use: provider registration contexts, attribute target handles, target mutation APIs, provider evaluation, and provider diagnostics.
- Slices 22 and 23 add contract use: contract factory instances, operation guards, contract surface handles, conformance facts, and contract-related cache dependencies.
- Slice 24 verifies reflection use: public reflection operations over compiler-owned handles, wrong-kind diagnostics, visibility behavior, and cross-feature metadata consistency.
No slice may introduce a second comptime evaluator. If a prelude, attribute, contract, or reflection feature cannot be expressed through the shared comptime demand interface plus explicit compiler intrinsics, the slice must extend those mechanisms rather than adding a side path.
Vertical Slice Plan¶
Slice 0: Source, Tokens, and AST Skeleton¶
Goal: load one .ct file, lex it, parse a tiny function/module, and emit token and AST snapshots.
Accepted source: fn main() void { return void }.
Required real modules: driver, session, target, source, diagnostics, hooks, lex, parse, ast, tests.
Required outputs: .tokens.snap, .ast.snap, .diag.snap, and selected .stderr.snap for syntax errors.
Agent context for all Slice 0 sub-slices: consult Compiler Pipeline, Phase Boundaries, Testing, Diagnostics, and Catalyst Source Grammar. Use the grammar page as the parser map only; focused source-form pages own semantic rules when they disagree with the grammar map. Sub-slices inherit the Slice 0 accepted source, required modules, outputs, allowed stubs, and forbidden shortcuts unless a sub-slice narrows them further.
Required driver behavior: parse a minimal CLI with commands such as tokens, ast, and check; accept an input path; select output mode; construct a Session with default target/profile/safety facts; return deterministic exit codes for success and diagnostics.
Required snapshot workflow: test mode must support stable snapshot paths/names, deterministic mismatch diffs, and local snapshot update mode such as --update-snapshots.
Required diagnostic shape: structured diagnostics must exist from Slice 0 with severity, stable diagnostic code/ID, primary span, optional secondary spans, labels, notes, hints, deterministic technical output, and deterministic stderr rendering from that technical output.
Required parser recovery: syntax diagnostics must support deterministic multi-error recovery from Slice 0 onward, using Catalyst Source Grammar as the parser's source-form map. The parser should synchronize at ;, }, EOF, and top-level declaration starters such as fn, const, var, struct, enum, contract, and impl; recovery diagnostics must use SourceStore spans, notes, and hints where useful, and must not infer semantic meaning while resuming.
Required literal syntax coverage: string literal forms including byte escapes, and code point literal forms are tokenized and represented in AST snapshots, but typed string/text literal values are not semantically accepted until the standard text surface owns their representation.
Required expression parser coverage: precedence and associativity snapshots must prove AST grouping for accepted operator tokens and call/member/index forms as they become syntactically available. Slice 0 owns parser grouping; later slices own semantic meaning.
Sub-slices:
- 0a: driver, session, target, and source-store scaffold. Build the minimal command surface, immutable session config, default target/profile/safety facts, single-root
.ctfile loading, file IDs, source text storage, and span primitives. Required outputs may be limited to harness smoke output and deterministic command exit behavior. Allowed stubs: commands may stop before lexing/parsing, but command names, input path handling, and session construction should already be real. - 0b: diagnostics model and deterministic rendering. Add structured diagnostics with severity, stable code/ID, primary span, optional secondary spans, labels, notes, hints, deterministic technical output, and deterministic non-color stderr rendering from
SourceStorespans. Required outputs:.diag.snapand selected.stderr.snapfor source-loading or deliberately injected scaffold diagnostics. Allowed stubs: no parser diagnostics yet. - 0c: snapshot harness and fixture metadata. Add stable fixture discovery, stable snapshot paths/names, deterministic mismatch diffs, and local update mode such as
--update-snapshots. Required outputs: at least one passing fixture and one failing diagnostic fixture. Allowed stubs: phase outputs not implemented yet may be rejected by harness diagnostics rather than silently skipped. - 0d: HookBus scaffold. Add typed hook-point registration for Slice 0 artifacts with built-in no-op hooks only, deterministic registration order, and no public plugin API. Required outputs may be limited to unit coverage or a small scaffold snapshot if the implementation exposes hook-order debugging early. Allowed stubs: hooks may not transform artifacts or affect source semantics.
- 0e: lexer and token snapshots. Tokenize the accepted source subset plus comments/trivia, identifiers, keywords, separators, delimiters, operators needed by the grammar map, and literal token forms including string spelling, byte escape spelling, and code point spelling. Required outputs:
.tokens.snapand.diag.snapfor lexical errors. Forbidden shortcuts: lexing does not resolve names, assign types, or classify identifiers beyond the reserved-word filter. - 0f: AST model and deterministic AST dump. Add AST node storage, source spans, syntax-only names as written, metadata/trivia attachment needed by early snapshots, and a deterministic AST dump format. Required outputs: scaffold
.ast.snapfixtures once parser nodes exist. Forbidden shortcuts: AST nodes do not store semantic IDs, resolved symbols, inferred types, or backend facts. - 0g: minimal parser for the tiny accepted program. Parse
fn main() void { return void }, top-level item lists, function declarations, parameter lists, return type syntax, blocks, return expressions, primitive literal expressions, and the separators needed by that source. Required outputs:.ast.snap,.diag.snap, and selected.stderr.snap. Allowed stubs: unsupported grammar forms may produce deterministic syntax diagnostics. - 0h: parser recovery and multi-error syntax diagnostics. Add deterministic recovery at
;,}, EOF, and top-level declaration starters such asfn,const,var,struct,enum,contract, andimpl. Required outputs: focused.diag.snapand selected.stderr.snapfixtures proving multiple syntax errors in one file. Forbidden shortcuts: recovery diagnostics useSourceStorespans and do not infer semantic meaning while resuming. - 0i: parser coverage hardening for literals and expression grouping. Add AST representation and parser snapshots for string literal syntax including byte escapes, code point literal syntax, precedence and associativity grouping for accepted operator tokens, and call/member/index postfix forms as they become syntactically available. Required outputs: focused
.ast.snapfixtures. Boundary: this sub-slice proves parser grouping only; typed literal values, operator meaning, indexing semantics, and call resolution remain later slices.
Allowed stubs: sema, lowering, IR, interpreter, and C backend may be absent; source loading may handle only one root file; HookBus may have only built-in no-op hooks.
Forbidden shortcuts: parser does not type-check; AST does not store semantic IDs; diagnostics use SourceStore spans instead of ad hoc raw byte offsets.
Slice 1: Primitive Sema and SIR Snapshots¶
Goal: resolve local/top-level names and type-check primitive declarations and expressions into SIR.
Accepted source: top-level constants, local constants, primitive annotations, returns, and primitive arithmetic such as return answer + 1.
Required real modules: names, types, sema, sir, plus previous slice modules.
Required outputs: .sir.snap, .diag.snap, and selected .stderr.snap for name/type errors.
Required semantics: primitive type identities, integer literals as comptime_int, annotation-driven literal coercion where the target type is explicit, primitive arithmetic result typing, block and return typing, local scopes, and top-level const lookup.
Required reference coverage: within-file top-level forward references for accepted primitive const/function cases, plus deterministic cycle diagnostics for invalid recursive const evaluation or declaration dependencies.
Allowed bootstrap: primitive type identities may be seeded directly by types before prelude loading exists. This is not a public alias mechanism. When prelude bootstrap lands, aliases such as i32 and u32 must be loaded from prelude source and resolve to the same canonical Type IDs.
Allowed stubs: no comptime execution except literal evaluation; no modules/imports/include; no structs, methods, pointers, arrays, or slices; no IR/lowering/interpreter/C backend.
Forbidden shortcuts: SIR contains resolved symbol/type IDs, not raw name strings as semantic references; sema does not emit IR-shaped control flow; type table is owned by types, not parser or AST.
Slice 2: Inference and Expected-Type Semantics¶
Goal: make core inference behavior explicit before lowering/backend slices depend on typed SIR.
Required semantics: local binding type inference, inference-context plumbing for later function result inference, inference-driven contextual literal resolution, numeric coercion and inference diagnostics, range endpoint fallback inference, expected-type shorthand for leading-dot members, inference failure diagnostics, and ambiguity diagnostics.
Boundary: Slice 2 does not complete ordinary function return inference or expression-bodied => function inference. Slice 3 owns inferred function signatures, block/final-expression completion, and arrow-body parsing/checking.
Allowed stubs: no generic inference, contract inference, comptime parameter inference, overload inference, broad reflection, or module/prelude-driven inference.
Forbidden shortcuts: inference is sema-owned and produces typed SIR; lowering never guesses types; expected-type shorthand resolves through sema/type context, not parser name lookup.
Slice 3: Function Surface Completion¶
Goal: cover accepted V1 function source forms before lowering depends on function assumptions.
Required features: explicit and inferred return types, expression-bodied => functions, final-expression completion, main entry-point rules, parameter binding patterns, default parameter values, trailing argument omission, function item values in comptime positions, runtime function pointers for concrete signatures, function type expressions, and an internal default calling-convention field in function type identity.
Sub-slices:
- 3a: function body shape, block expressions, return expressions, explicit discard expressions, and return inference. Parse expression-bodied
=>function bodies, parse real block expressions using the shared block syntax, keep block-bodied functions as the existing syntax shape, movereturninto expression AST/SIR as anever-typed expression whose payload contributes to function return inference, add explicit discard expressions_ = exprwithvoidcompletion, add SIR statement completion types, infer omitted return types from statement completion in the accepted primitive subset, model local declaration completion asvoid, and snapshot explicit/inferred return consistency diagnostics. - 3b:
mainentry-point rules. Validate acceptedmainsignatures against the currently implemented type universe, emit deterministic diagnostics for invalidmainreturn types, and keep driver/runtime behavior deferred until executable slices exist. - 3c: default parameters and trailing omission. Preserve default parameter metadata, enforce that only trailing positional parameters may be omitted, type-check default values in declaration scope, and materialize omitted arguments for SIR call checking once calls are semantically supported.
- 3d: function type identity, function item values, and runtime function pointers. Add function type expressions, compile-time-known function item values, compatible function-item-to-pointer coercions, runtime function pointer types for concrete signatures, and the internal default calling-convention field in function type identity. When direct function calls become semantically checked here, add call fixtures for Slice 3c default-argument behavior: full arguments, trailing omission of defaulted parameters, too few required arguments, and the positional-call rule that only the trailing defaulted suffix may be omitted.
- 3e: parameter binding patterns. Add parameter binding-pattern syntax and diagnostics, with
_binding support first. Keep struct/array destructuring behind a deferred diagnostic for now, and replace that diagnostic with real binding expansion in the aggregate/array slices once those type facts exist.
Allowed stubs: no closures, anonymous functions, overloads, named arguments, comptime parameter inference, source @callconv parsing/storage, C ABI import/export, or full C ABI validation.
Forbidden shortcuts: parser preserves source shape, sema owns signature inference; function items are not runtime values unless converted to accepted function pointer forms; lowering receives a resolved callable target, not raw call syntax.
Slice 4: Tiny IR and Debug Dump¶
Goal: lower Slice 3 SIR into a tiny structured IR, verify it, and dump it deterministically.
Accepted source: primitive functions returning primitive values, direct primitive arithmetic, simple locals, and direct internal calls between accepted primitive functions.
Required real modules: lower, ir, verifier, debug IR dump, plus previous slice modules.
Required outputs: .ir.snap, .diag.snap, and selected .stderr.snap for lowering/verifier errors.
Required IR: modules, functions, parameters, locals/constants, direct internal calls between accepted primitive functions, primitive integer checked add for the accepted subset, stable trap kind, and return.
Boundary: Slice 4 lowers sema-successful runtime forms in its accepted subset unless explicitly deferred. Runtime IR lowering requires concrete runtime primitive types; comptime_int values must already be coerced to concrete runtime types before this path. Runtime IR excludes comptime fn units; comptime execution through IR remains owned by Slice 17. Slice 4 does not lower indirect function-pointer calls yet.
IR shape: use IR-local type and value identities, real blocks and terminators even for single-block functions, direct calls by IR FunctionId, typed runtime constants, module-level target and safety-mode facts, and optional source-derived debug names/spans as provenance only. Public .ir.snap output is verified IR only; lowering or verifier failures produce diagnostics instead of dumping malformed IR. Lower demanded top-level constants only when they are present in SIR; lowering must not ask sema or AST to demand more constants.
Allowed stubs: interpreter and C backend absent; verifier may check only IDs, type consistency, terminators, and return type.
Forbidden shortcuts: debug dump consumes IR or verified IR only and is not treated as a backend; IR contains no AST IDs, source names as semantic references, unresolved symbols, or contract facts; optional source-derived debug names are provenance only and are not identity, lookup, verifier, ABI, or linkage facts; lowering does not call C backend helpers.
Slice 5: HookBus and Trivial Lints¶
Goal: make hooks real by running deterministic built-in hooks over useful AST, SIR, IR, and VerifiedIR artifacts.
Accepted source: Slice 4 source plus simple comments, identifiers, unused declarations, redundant semicolons, and extra whitespace needed by lint fixtures.
Required real modules: hooks, lint, diagnostics, plus previous slice modules.
Required outputs: .diag.snap and selected .stderr.snap for warnings/lints, plus a hook-order snapshot that proves the HookBus ordering policy is stable.
Required diagnostic coverage: first real warning/lint snapshots must exercise the structured diagnostic payload shape, warning versus lint classification, hook diagnostic authority, labels, notes, and hints.
Required hook points: after_parse(AST), after_sema(SIR), before_verify(IR), after_verify(VerifiedIR), and before_emit_c(VerifiedIR) may be stubbed until C emission exists.
Required trivial lints: at least two simple lints over real artifacts, such as naming-convention warnings over AST/SIR, unused local or unused top-level const warnings over SIR, redundant semicolon/trivia warnings over AST/trivia, or debug-only IR shape warnings over IR.
Allowed stubs: hooks may be compiler-owned only; no public plugin API; no semantic-changing hooks except explicitly registered compiler-owned before_verify normalization; no lint configuration, suppression, autofix, or project policy.
Forbidden shortcuts: lints do not run by being hardcoded into parser/sema branches unless the phase exposes a typed hook point; hooks do not access global compiler internals outside the hook contract; lint diagnostics use the shared diagnostics module.
Slice 6: Verified IR Interpreter for Primitive Functions¶
Goal: execute Slice 4 verified IR and compare deterministic runtime results/traps.
Accepted source: direct primitive functions and one direct internal call.
Required real modules: interp, plus previous slice modules.
Required outputs: runtime-result snapshots, deterministic checked-trap diagnostics/output, and optional test-harness output snapshots for demo programs that need observable runtime text before std.io exists.
Required interpreter behavior: function entry, direct internal call frames, primitive constants, local values, checked integer add, return, and stable trap kinds.
Allowed stubs: no memory model beyond value locals; no comptime mode; no C backend. A compiler-owned test/demo output hook may exist only in the harness and must not be exposed as Catalyst source syntax, prelude API, std.io, or a Compiler.print intrinsic.
Forbidden shortcuts: interpreter consumes verified IR only; interpreter does not evaluate AST/SIR; trap behavior is based on IR checks/traps, not rediscovered source rules; test/demo output does not become a public language-visible I/O surface.
Slice 7: C Backend for Primitive Direct Calls¶
Goal: emit deterministic C from Slice 6 verified IR for primitive functions and direct calls.
Required real modules: backend_c, plus previous slice modules.
Required outputs: .c.snap.
Required C backend behavior: deterministic function order, primitive integer type mapping for standard widths, direct calls, return values, and checked add lowering for the small accepted subset.
Allowed stubs: no C ABI import/export; no non-standard integer widths unless target reports bit-precise integer support; no structs/pointers/arrays/slices; no debug info or optimization.
Forbidden shortcuts: backend consumes verified IR only; backend does not inspect SIR types, AST names, attributes, or source spans except IR-provided diagnostic span refs.
Slice 7b: C Toolchain Integration Smoke¶
Goal: compile generated C for the Slice 7 subset into an executable and run small end-to-end source-to-binary smoke tests when a supported local C toolchain is available.
Required behavior: discover or configure a C compiler, invoke it with deterministic output paths, pass target/session facts needed by the backend driver, run the produced executable for primitive direct-call fixtures, compare stdout/exit-code snapshots, and emit deterministic skip diagnostics when no supported C toolchain is available.
Allowed stubs: no full linker model, cross-compilation, package build graph, installed-library discovery, debug info, optimization control, C ABI import/export, or non-default target matrix.
Forbidden shortcuts: toolchain integration consumes generated C and backend/session facts; it does not inspect AST/SIR attributes or rerun semantic checks; smoke tests must be skippable without changing language validity or phase snapshots.
Slice 7c: Target Negotiation Smoke¶
Goal: prove non-default target facts flow through the existing pipeline before layout-heavy and ABI-heavy slices depend on them.
Required behavior: snapshot default and selected non-default target facts; exercise pointer width, endianness, maximum object alignment, selected C ABI family, and bit-precise integer support; prove session and target facts reach type/layout queries, IR facts, interpreter assumptions where observable, and C backend emission; emit deterministic diagnostics for unsupported target/feature combinations.
Allowed stubs: no full cross-compilation matrix, platform linker discovery, C ABI import/export, target-specific standard library selection, or target-specific optimization policy.
Forbidden shortcuts: target facts come from the target module through session, not ad hoc backend conditionals; C backend and interpreter consume normalized target facts instead of querying host platform behavior directly.
Slice 7d: Runtime Function Pointer Calls¶
Goal: lower, interpret, and C-emit indirect calls through concrete runtime function pointer values.
Required behavior: function-item-to-pointer values that were type-checked in Slice 3, local storage of concrete function pointers, indirect function-pointer call IR, verifier signature checks, interpreter call frames through function pointer values, and deterministic C emission for function pointer calls.
Allowed stubs: no C ABI callback interop, no dynamic dispatch, no closures, no bound methods, no overloads, and no comptime parameter inference.
Forbidden shortcuts: function pointer calls lower from resolved SIR callable targets into IR indirect-call facts; interpreter and C backend consume verified IR only and do not inspect SIR call expressions.
Slice 8: Structured Control Flow¶
Goal: compile and run structured blocks, if, while, break, and continue.
Required real modules: sema, lower, ir, verifier, interp, backend_c.
Required IR: branch, conditional branch, return, mutable locals/stores, comparison, checked add/sub/neg.
Allowed stubs: no for, ranges, defer, resource cleanup, arrays, or slices.
Forbidden shortcuts: conditionals and loops lower through IR control flow, not interpreter-side AST execution; C backend emits from IR blocks, not reconstructed source syntax.
Slice 9a: Enums and Case Resolution¶
Goal: support tag-only enums, enum unions where accepted, and shared case-resolution machinery before error sets depend on similar shorthand behavior.
Required features: enum { ... } type expressions, enum values, enum case identity, duplicate diagnostics, leading-dot shorthand for enum-like cases, enum unions where accepted, and enum reflection basics.
Allowed stubs: no optionals, optional binding, general pattern matching, exhaustive match, payload enums, discriminated unions, error sets, or value reflection.
Forbidden shortcuts: enum and later error expected-type shorthand uses shared owner-resolution machinery; enum reflection is produced from type facts, not parser-only syntax.
Slice 9b: Optionals and Narrowing Basics¶
Goal: support optional types, optional binding, and basic narrowing before error handling depends on related success/error flow.
Required features: ?T, null, presence coercion, orelse optional defaulting, .? forced optional unwrap with checked traps, if const optional binding, while const optional loops, optional reflection basics, and reusable narrowing machinery.
Allowed stubs: no general pattern matching, exhaustive match, payload enums, discriminated unions, error narrowing, or value reflection.
Forbidden shortcuts: optional binding narrows in sema/SIR, not interpreter source execution; narrowing facts are represented in typed artifacts rather than rediscovered by later phases.
Slice 10: Structs, Fields, Pointers, and Catalyst Layout¶
Goal: type-check, lower, interpret, and C-emit concrete structs, field access, simple methods, address-of, dereference, and pointer mutability.
Required real modules: types layout support, aggregate sema, field access lowering, IR memory ops, interpreter local/field memory model, C struct emission.
Required outputs: SIR, IR, C, runtime, and deterministic layout snapshots or layout sections.
Required reference coverage: mutually recursive aggregate declarations where accepted, pointer-mediated recursive structs, and deterministic diagnostics for invalid by-value recursive layouts.
Allowed stubs: only .catalyst layout; no arrays/slices; no heap allocation; no resource ownership beyond ordinary locals.
Forbidden shortcuts: layout is computed by types/layout, not by C backend; C backend consumes finalized layout facts from IR; interpreter uses the same layout facts where observable.
Slice 11: Fixed Arrays and Checked Indexing¶
Goal: support [N]T, array literals, array indexing, mutable element assignment, and checked bounds.
Required modules: array type model, array literal/index sema, array_index_addr, load/store, explicit bounds checks, interpreter array storage, C array emission.
Required checks: index type checking, comptime-known length, and bounds-check trap in Checked mode.
Allowed stubs: no slices, range expressions, for over arrays, array-to-slice coercion, or generic arrays beyond concrete [N]T.
Forbidden shortcuts: bounds checks are explicit IR checks; C backend does not rederive array length from AST; interpreter and C backend consume the same IR indexing facts.
Slice 12: Slices, Ranges, and Slicing¶
Goal: support slice descriptors, array-to-slice views, range values, slicing, and slice indexing.
Required modules: range typing, range fallback inference, slice descriptors, slicing sema/lowering, slice range checks, interpreter descriptor behavior, C descriptor emission.
Required outputs: SIR, IR, runtime, and C snapshots for indexing, slicing, and range failures.
Allowed stubs: no for; no iterator contracts; no dynamic iteration; no hidden allocation.
Forbidden shortcuts: omitted-bound slicing is sema-owned; range and slice checks are explicit IR checks; backends consume descriptor facts from IR.
Slice 13: Basic Non-Contract for¶
Goal: support for over ranges, arrays, and slices using staged built-in lowering only.
Required modules: loop-source sema for built-in range/array/slice sources, loop lowering, interpreter/C backend loop execution.
Allowed stubs: no iterator contracts, Iterable, iter, iter_dyn, hidden allocation, or resource-owning iterator cleanup beyond simple loop locals.
Reconciliation rule: by the iterator-contract slice, this staged lowering must either be replaced by the canonical loop-source selection path or become the built-in fast path behind the same canonical source-selection result. No later feature may depend on a second independent for implementation.
Forbidden shortcuts: built-in for lowering is clearly marked as the staged non-contract subset and later reconciled with iterator-loop source selection.
Slice 14: Error Returns, try, and catch¶
Goal: support closed error sets, T!E, T!, try, catch, and inferred error sets for non-resource values.
Sub-slices:
- 14a: closed error sets and explicit
T!E, with success returns and qualified error returns. - 14b:
catchfallback forms, includingcatch fallback,catch { ... }, andcatch as err { ... }. - 14c:
trypropagation for compatible errors. - 14d: inferred
T!, including errors fromtry, returned errors, fallible tail expressions, and recursive inference diagnostics.
Required modules: error-set types, fallible SIR facts, IR result operations, interpreter result values, C result lowering.
Allowed stubs: no resource cleanup during error propagation; no errors across C ABI; no rich error reflection; no allocation-backed fallible APIs.
Forbidden shortcuts: try/catch lower through explicit result/error IR operations; catch binding uses accepted catch as err { ... } grammar; C backend does not encode errors as ad hoc magic returns outside IR result lowering.
Slice 15: defer Without Resources¶
Goal: support defer lowering for ordinary calls and early exits.
Required modules: defer sema, cleanup-edge lowering, IR control flow for generated defer calls, interpreter/C execution.
Allowed stubs: no resource ownership, move-state diagnostics, heap allocation, or dynamic dispatch.
Forbidden shortcuts: defer lowering is explicit before backend consumption; C backend does not recover defer semantics from source.
Slice 16: Move State and Cleanup Skeleton¶
Goal: support move-state analysis, cleanup-state analysis, generated cleanup edges, live overwrite diagnostics, double cleanup diagnostics, and cleanup interactions with return, try, and defer before real resource metadata exists.
Required regression coverage: try, catch, return, and defer must be re-tested with cleanup-state and the synthetic cleanup marker so Slice 14 error lowering cannot silently bypass generated cleanup edges.
Allowed scaffolding: a compiler-owned test-only cleanup marker or synthetic resource kind may be used to exercise cleanup mechanics. This marker cannot leak into language semantics and must be retired or replaced by finalized @resource metadata before V1 final acceptance.
Allowed stubs: no heap allocation, Box, dynamic dispatch disposal, real @resource, or contract-based resource requirements.
Forbidden shortcuts: cleanup is represented in SIR/lowering, not injected by C backend; move-state diagnostics are sema-owned; generated cleanup lowers to ordinary IR calls/branches.
Slice 17: Basic Comptime Substrate¶
Goal: represent comptime-known values and evaluate simple top-level constants and demanded function calls without modules, prelude bootstrap, attributes, or contracts.
Sub-slices:
- comptime value representation for primitive values and already-known primitive
Typehandles; - comptime-only function item values;
- lazy top-level const evaluation in one file with dependency tracking and cycle diagnostics;
- forced
comptime exprandcomptime { ... }over already-supported executable expressions; comptime fnand explicit comptime parameters;- demanded comptime calls to ordinary
fndeclarations when the call path and inputs are comptime-available; - audit and route Slice 1-16 comptime-adjacent behavior, including
comptime_intliteral storage/coercion, function item values, default-argument comptime facts, and expected-type shorthand dependencies, through the shared demand interface or explicitly document why a behavior remains sema-only; - typed compiler intrinsic registry with stable IDs,
comptime_hostversuslowering_expansioncategories, effect/dependency classes, context requirements, result storage categories, and compiler-owned provenance; - simple diagnostic intrinsics such as
Compiler.note,Compiler.warn, andCompiler.err; - intrinsic registry snapshots covering seeded
Compilerdeclarations, public signatures, categories, effects, context requirements, and provenance summaries.
Allowed stubs: no module/include loading, prelude source bootstrap, attributes, contract factories, reflection enumeration, or incremental cross-run cache.
Forbidden shortcuts: executable comptime code uses SIR -> IR -> verifier -> interpreter; compiler-owned handles are opaque values; host intrinsics use explicit handlers with narrow authority objects; lowering intrinsics expand to ordinary IR; no generic compiler intrinsic call survives into verified backend IR.
Slice 18: Minimal Namespace Loading and Prelude Bootstrap¶
Goal: build the module-loader core once, then load prelude through that same path with a compiler-provided root namespace.
Sub-slices:
- module-loader core: namespace identity, loaded source unit identity, declaration table, public/private declaration filtering, deterministic load diagnostics;
- compiler-provided roots, including
preludeand a futurestdroot stub; - prelude source load, starting with one file;
- implicit prelude import into user roots through the same internal import mechanism as later user imports;
- primitive factories and aliases through prelude source functions over public compiler intrinsics such as primitive type construction and top-error-set construction;
Namespacehandles as needed for prelude-definedmoduleandincludewrappers;- prelude validation roots that demand and snapshot-check primitive factories, primitive aliases,
Error,module,include, and range helpers as those declarations become active.
Allowed stubs: no full std, no user-facing import syntax, no third-party modules, no contracts/Allocator/Box unless inert declarations are needed.
Forbidden shortcuts: prelude may be compiler-known as a root namespace, but it must not be injected by manually copying declarations into user scopes outside the normal import/resolution machinery.
Slice 19: User Modules, Imports, and Include¶
Goal: support user-facing module/include mechanics using the same namespace loader/import core as prelude.
Sub-slices:
- declaration-scope
include("./file.ct")with relative path resolution, stable source identity, and deterministic duplicate/cycle diagnostics; module("std")and named root modules, withstdallowed to be a tiny stub module first;- explicit import forms accepted by V1;
- minimal
module.toml, loose-file synthesized module context, namespace destructuring imports, re-export behavior, import conflicts, root escape checks, manifest dependency diagnostics, cross-file forward references and cycles, and multi-file snapshots.
Allowed stubs: tiny placeholder std; no package manager, manifest evolution, incremental cache, or broad source-text reflection.
Forbidden shortcuts: user module lookup uses the same loader/import core as prelude; include/module do not bypass sema with textual concatenation.
Slice 20: Attribute Syntax, Registration, and Provider Metadata¶
Goal: parse attributes, register provider functions, resolve provider calls, evaluate simple providers at comptime, validate targets, and write normalized declaration metadata.
Sub-slices:
- attribute provider registration through
Compiler.register_attribute_provider(provider, spec); - provider registry entries for identity, target kinds, repetition/conflict policy, ordering, and duplicate/invalid registration diagnostics;
- attribute syntax and AST/SIR storage;
- provider lookup and target validation;
- comptime provider evaluation through ordinary comptime functions, compiler-owned target handles, and explicit target mutation APIs;
- first concrete metadata providers such as
@deprecated,@align, and@repr(.catalyst).
Allowed stubs: no broad attribute target expansion, expression/local attributes, user-generated declarations, arbitrary semantic rewrites, @resource, or C ABI providers unless the relevant later slice is active.
Forbidden shortcuts: attributes do not patch AST directly; providers mutate only through explicit compiler target APIs; IR receives only finalized backend-facing metadata, not raw attributes.
Slice 21: @resource Integration¶
Goal: replace cleanup scaffolding with real resource metadata from attributes.
Sub-slices:
@resourceprovider target validation and normalized resource metadata;- dispose operation shape validation;
- copyability metadata;
- resource reflection/provider APIs;
- cleanup obligations and generated cleanup IR driven by finalized resource metadata.
Required regression coverage: repeat the Slice 16 try, catch, return, and defer cleanup tests after @resource metadata replaces the synthetic cleanup marker.
Allowed stubs: no heap allocation, Box, dynamic dispatch disposal, or contract-based resource requirements.
Forbidden shortcuts: resource metadata comes from finalized attributes, not type-name checks or synthetic test markers; generated cleanup lowers to ordinary IR calls/branches.
Slice 22: Static Semantic Contracts¶
Goal: support contract definitions, explicit impls, visible conformance lookup, operation checking, and static contract dispatch.
Sub-slices:
contract { ... }and generic contract factory functions;- demanded comptime contract factory instances with explicit comptime arguments and dependency recording;
- required operations;
impl Type as Contract { ... };- operation signature compatibility, inherent-member fill, coherence, and visibility;
- static operation lookup, qualified contract calls, and direct-call lowering;
- anonymous static
*impl Cparameters in function parameter position only.
Allowed stubs: no dyn, default methods, operation guards, contract dependencies/intersections, or ContractSurface.current().
Forbidden shortcuts: conformance is explicit only, never structural; static dispatch resolves in sema; IR contains direct calls, not semantic contract references.
Slice 23: Contract Surface Completion¶
Goal: complete accepted static contract surface semantics before allocation and dynamic dispatch depend on them.
Required features: default methods, operation guards evaluated as demanded comptime instances, ContractSurface.current().is_static() through compiler-owned contract surface handles, contract dependencies, intersections, constrained local annotation diagnostics, anonymous impl pointer rejection outside function parameter position, conformance reflection, and deterministic diagnostics for guarded/invalid operation surfaces.
Allowed stubs: no borrowed or owned dynamic dispatch yet.
Forbidden shortcuts: operation guards evaluate through comptime machinery; default-method wrappers and dependency facts are represented before lowering.
Slice 24: Reflection Surface Pass¶
Goal: verify public reflection names, metadata shapes, wrong-kind errors, visibility behavior, and cross-feature consistency after the main producers of reflection facts exist.
Required coverage: public reflection operations over compiler-owned comptime handles, primitive Type classifiers, Type.Predicate fact propagation, optional/enum/function/attribute/layout/source reflection, structural satisfaction reflection, conformance reflection, dyn-safety metadata names where available, public metadata names, visibility behavior, and deterministic wrong-kind diagnostics.
Feature slices still own their local reflection facts. This pass verifies that the public reflection surface is coherent across features.
Allowed stubs: no runtime value reflection, namespace enumeration, Type.Expr, Type.Value, or broad source-text access.
Slice 25: Allocator Contract and Concrete Box(T)¶
Goal: support the Allocator contract, std.mem.FixedBufferAllocator, concrete allocation/deallocation, placement initialization, and Box(T) ownership for concrete sized T.
Sub-slices:
Allocatorcontract andAllocError;std.mem.FixedBufferAllocator, initially with a compiler-owned smoke-test fixture allowed;- placement initialization, typed pointer formation, alignment/layout validation, and failure cleanup;
Box(T)create/destroy and move-only ownership.
Allowed scaffolding: the compiler-owned FixedBufferAllocator smoke-test fixture must be retired once std.mem.FixedBufferAllocator is source-backed, or explicitly tracked as remaining scaffolding before V1 final acceptance. It must not become hidden compiler magic for allocation semantics.
Allowed stubs: no *dyn Allocator, Box(dyn C), dynamic dispose descriptors, free-list/reset APIs, or broad allocator catalog.
Forbidden shortcuts: allocation calls go through static Allocator dispatch; Box is prelude/source-level abstraction, not a backend primitive; C backend does not special-case Box semantics.
Slice 26: Borrowed Dynamic Dispatch¶
Goal: support dyn-safety, borrowed *dyn C / *const dyn C, descriptors, vtables, dynamic calls, and borrowed upcasts.
Sub-slices:
- dynamic surface computation and dyn-safety;
- descriptor/vtable constants;
- forming borrowed dyn pointers from concrete references;
- dynamic call lowering;
- dependency upcasts and intersections for borrowed dyn.
Allowed stubs: no owned Box(dyn C), dynamic disposal descriptors, or *dyn Allocator unless needed by a borrowed dyn smoke test.
Forbidden shortcuts: dyn calls use descriptor metadata, not source contract lookup in backend.
Slice 27: Owned Dynamic Dispatch with Box(dyn C)¶
Goal: support Box(dyn C), box_dyn, into_dyn, private disposal state, dynamic dispose descriptors, and owned upcasts.
Required features: *dyn Allocator where needed, erased allocation authority, dynamic dispose metadata, Box(dyn C) private layout, and cleanup integration.
Allowed stubs: no dynamic iteration yet.
Forbidden shortcuts: owned dyn disposal uses descriptor/dispose metadata, not type-name checks; Box(dyn C) public layout remains private.
Slice 28: Dynamic Iteration and Boxed Iterator Forwarding¶
Goal: support explicit iter_dyn / iter_dyn_mut, boxed dynamic iterators, and loop use of borrowed/boxed dynamic iterators.
Sub-slices:
Iterator,Iterable, andMutableIterablecontract families;- boxed iterator forwarding for
Box(dyn Iterator(Item)); - explicit
iter_dyn(alloc)/iter_dyn_mut(alloc); - allocation failure cleanup for dynamic iterator construction;
- loop over
*dyn Iterator(Item)andBox(dyn Iterator(Item)); - reconciliation of staged built-in
forwith canonical iterator-loop source selection.
Allowed stubs: no owned iter_dyn_owned, hidden allocation in plain for, or broad std iterator helpers.
Forbidden shortcuts: plain for item in xs does not secretly call iter_dyn; dynamic iteration allocation boundary remains explicit.
Slice 29: Scalar C ABI Interop¶
Goal: support accepted V1 scalar C ABI import/export/callconv/link-name metadata and deterministic diagnostics for unsupported ABI forms.
Sub-slices:
- evaluate and validate ABI attributes such as
@extern(.c),@export(.c),@callconv(.c), and@link_nameafter generic attribute parsing/storage has already run; - bodyless C-like import rejection;
- ABI-safe type validation for accepted primitive scalar and pointer forms;
- function-pointer ABI positions;
- internal symbol naming;
- error-return and compound-type rejection diagnostics;
- SIR/IR ABI metadata for call convention, linkage, external symbol, and import/export facts;
- C backend extern/export emission and duplicate-link-name diagnostics.
Allowed stubs: no compound C ABI, C struct layout, error-return ABI, varargs, or callbacks beyond accepted function pointer forms.
Forbidden shortcuts: C backend consumes resolved IR ABI facts only; providers validate before backend emission; backend does not inspect raw source attributes.
Slice 30: Diagnostics and Lint Boundary Pass¶
Goal: audit diagnostic categories, lint boundaries, warning behavior, and hook diagnostic authority before final integration.
Required coverage: cross-feature diagnostic consistency, warning versus lint versus hard-error boundaries, comptime Compiler.note / warn / err, lint catalog smoke tests, explicit deferral of lint configuration/suppression/autofix, hook diagnostic authority audit, and source spans across modules/includes/prelude.
Forbidden shortcuts: lint findings do not define source validity; warnings and hard errors remain phase-owned; comptime diagnostics use the same diagnostics module and deterministic rendering path.
Slice 31: V1 Integration Matrix and Hardening¶
Goal: prove accepted V1 features compose through the modular pipeline.
Named example targets:
primitive_arithmetic_and_range_inference.ct;modules_include_and_prelude.ct;structs_arrays_slices_ranges_for.ct;errors_try_catch_and_cleanup.ct;resource_defer_and_early_exit.ct;static_contract_dispatch.ct;allocator_fixed_buffer_and_box.ct;borrowed_dyn_dispatch.ct;boxed_dyn_dispatch.ct;dynamic_iterator_boxed_forwarding.ct;scalar_c_import_export_smoke.ct.
Required outputs: token/AST snapshots where syntax is relevant, SIR snapshots for semantic-heavy cases, IR snapshots for lowering-heavy cases, structured diagnostic snapshots, selected rendered stderr snapshots, interpreter runtime snapshots, C output snapshots, and selected compile-and-run C smoke tests.
Required architecture checks: backend consumes verified IR only; hooks have deterministic order and explicit authority; no phase reaches around artifact boundaries; earlier stubs are removed or explicitly tracked as post-V1 gaps.
Assigned Coverage Additions¶
The slice plan above is the primary implementation sequence. The items below assign accepted V1 coverage to concrete slices so implementation work does not rely on implicit ownership. This list is about implementation coverage only; it does not reopen V1 scope.
- Slice 0 owns comments, documentation comments as trivia, newline-significant statement separation, semicolon handling, parser-contextual continuation diagnostics, expression parser precedence/associativity snapshots, and rejected deferred syntax forms. Slice 24 owns public source metadata reflection that exposes normalized source facts.
- Slice 1 owns primitive declarations, within-file top-level forward references, deterministic recursive declaration/const cycle diagnostics, shadowing diagnostics, assignment expression typing for primitive values, annotation-driven literal coercion where the target type is explicit,
true,false, base-prefixed integers, numeric suffix parsing that is accepted in V1, and rejected literal forms that do not require later feature context. - Slice 2 owns inference-driven contextual literal resolution, explicit numeric conversion diagnostics, range endpoint fallback inference, expected-type shorthand for leading-dot members, contextual aggregate-literal typing hooks, and target/safety-mode context in inference snapshots.
- Slice 3 owns expression-bodied arrow function bodies, ordinary return inference,
mainentry-point rules, parameter binding patterns, default parameter values, trailing argument omission, function item values, runtime function pointers, function type expressions, and an internal default calling-convention field in function type identity. Slice 29 owns source@callconvparsing, validation, and ABI-facing facts. - Slice 5 owns the first naming-convention and documented-convention lints, redundant semicolon/trivia lints, unused declaration lints where enough SIR exists, deterministic hook ordering snapshots, and proof that lints are not hard source validity.
- Slice 7b owns local C toolchain discovery/configuration, generated-C compilation, executable production, source-to-binary smoke snapshots, and deterministic skip diagnostics when no supported C toolchain is available.
- Slice 7c owns target negotiation smoke coverage for non-default target facts, unsupported target/feature diagnostics, and proof that normalized target facts flow through
session, type/layout queries, IR, interpreter, and C backend emission. - Slice 9a owns enum type expressions, enum values, enum unions where accepted, expected-type shorthand for enum/error-like cases, and enum reflection producers.
- Slice 9b owns optional types, optional binding,
while const, rejectedwhile var,orelse,.?forced unwrap/check traps, optional reflection producers, and reusable narrowing machinery. - Slice 10 owns aggregate recursion coverage, pointer-mediated recursive structs, invalid by-value recursive layout diagnostics, opaque pointer recovery operations such as
cast,as_type,assume_aligned, their diagnostics, and layout/alignment facts for.catalyststructs. - Slice 13 owns static built-in iterator sources for ranges, arrays, and slices,
for var, loop result typevoid, deferred value-producing loop diagnostics, and temporary hidden cleanup only for staged loop locals. Slice 28 reconciles this with canonical iterator-loop source selection. - Slice 18 owns complete prelude bootstrap for primitive factories, primitive aliases,
Namespace,module,include,Error,AllocError,Ordering, range helpers, inert core contract declarations needed before contract sema,Boxdeclarations before allocation is active,Allocatordeclarations before implementation, and V1 attribute-provider declarations before provider registration is active. - Slice 19 owns minimal
module.toml, loose-file synthesized module context, re-export behavior, namespace destructuring imports, import conflicts, module/include root escape checks, manifest dependency diagnostics, cross-file forward references and cycles, and multi-file source-span stability. - Slice 20 owns
Compiler.register_attribute_provider, provider repetition/conflict rules, provenance reflection producers, all accepted declaration attribute targets,@repr(.catalyst),@align,@deprecated, and generic parsing/storage for ABI-named attributes before scalar ABI validation. - Slice 21 owns
@resourcesemantics, resource reflection/provider APIs, and transition from the Slice 16 synthetic cleanup marker to finalized resource metadata. - Slice 22 owns core prelude contract families needed for static dispatch, including arithmetic contracts, built-in primitive conformances,
PartialEq,Eq,PartialOrd,Ord,Indexable,MutableIndexable,Sequence,MutableSequence,Disposable, and array/slice/range conformances that do not require dynamic iteration. - Slice 23 owns structural constraints such as
satisfies(...)andmutable_fields(...), structural satisfaction reflection producers, opaque static returns, contract dependencies/intersections in static contexts, constrained local annotation diagnostics, and function-type/local/field/type-alias rejection for anonymousimplpointers. - Slice 24 owns primitive
Typeclassifier predicates,Type.Predicatefact propagation, source/function/attribute/layout reflection APIs, function type reflection, conformance reflection polish, public reflection metadata names, and wrong-kind/visibility diagnostics. - Slice 25 owns the
std.memallocator surface,std.mem.FixedBufferAllocator, allocation visibility diagnostics for concreteBox(T), and failure-cleanup lowering for allocation-backed concrete ownership. - Slice 28 owns
IndexIterator,MutableIndexIterator, existing-iteratorfor, hidden iterator cleanup, dynamic iterator construction snapshots, erased allocator authority lifetime lint candidates, allocation failure cleanup, and no hidden allocation in plainfor. - Slice 29 owns scalar C ABI details: bodyless C-like import rejection, accepted scalar ABI-safe set diagnostics, internal symbol naming, function-pointer ABI positions, duplicate link-name diagnostics, and error-return/compound-type rejection diagnostics.
- Slice 0 owns compiler diagnostic payload shape, stable diagnostic codes, span labels, notes, hints, and deterministic rendering. Slice 5 owns first warning/lint classification and hook diagnostic authority coverage. Slice 30 owns cross-feature diagnostic consistency, comptime-produced warnings/errors, lint catalog smoke tests, explicit deferral of lint configuration/suppression/autofix, and realtime/allocation-visibility policy warnings that are diagnostics rather than validity rules.
- Slice 31 owns typed string/text literal value semantics through
std.text, final standard-library skeleton namespace smoke coverage forstd.Result,std.text,std.mem,std.collections,std.hash,std.fmt,std.debug,std.io,std.math,std.sort, andstd.testing, plus final IR/verifier coverage for every accepted backend-visible fact: optionals, enums, attributes, layout/alignment, cleanup, dynamic descriptors, dispose descriptors, calls, traps, ABI facts, and source-span references.
Coverage Checklists¶
These checklists make sure the vertical slices cover every accepted V1 workstream. They are not the implementation order.
Compiler Skeleton¶
Source design:
Tasks:
- Implement the compiler with phase-local data and typed IDs.
- Keep source loading, diagnostics, hooks, lexing, parsing, sema, lowering, IR, interpreter, and C backend in separate modules with typed artifact boundaries.
Syntax and Source Forms¶
Source design:
Tasks:
- Parser snapshots cover newline statement separation, semicolon handling, contextual continuation, and braces in blocks versus aggregate/call contexts.
- Literal snapshots cover accepted primitive literals, parsed string literals including byte escapes, parsed code point forms,
null,undefined, deterministic rejection of deferred literal forms, and deterministic unsupported-use diagnostics for typed string/text literals beforestd.textowns their representation. - Declaration and binding snapshots cover shadowing, assignment typing, destructuring forms, and rejected destructuring-assignment/rest forms.
Functions and Calls¶
Source design:
Tasks:
- Parser, sema, reflection, and function-pointer snapshots cover declarations, methods, parameter binding patterns, defaults, inferred returns, and C callconv function types.
- Function item values are rejected in runtime storage with deterministic diagnostics.
- Deferred anonymous functions, closures, bound methods, overloads, named arguments, and
comptimeparameter inference are rejected or parked in V2 diagnostics.
Comptime and Compile-Time Evaluation¶
Source design:
Tasks:
- Comptime value snapshots cover primitive values, opaque compiler handles, primitive
Typehandles, and deterministiccomptime_intstorage limits. - Demanded comptime snapshots cover ordinary
fncalls,comptime fncalls, function item values, explicit comptime parameters, dependency recording, and cache-key inputs for semantic instances. - Intrinsic registry snapshots cover seeded declarations, public signatures, stable IDs,
comptime_hostversuslowering_expansioncategories, effect/dependency classes, context requirements, result storage category, and compiler-owned provenance. - Comptime evaluation uses the SIR to IR to verifier to interpreter path for executable code, with explicit compiler intrinsic handlers for compiler-owned objects.
- Lowering expansion snapshots prove primitive operation intrinsics such as integer add/compare expand into ordinary IR and do not survive into backend-verified IR.
- Prelude bootstrap, type factories, contract factories, attribute providers, and reflection operations use the same comptime demand interface instead of a separate interpreter.
Errors¶
Source design:
Tasks:
- Error snapshots cover closed error sets, inferred
T!,try, all acceptedcatchforms, error expected-type shorthand, and recursive inference diagnostics. - Lowering snapshots show explicit result/error IR operations and cleanup behavior for
try,catch,return, anddefer. - Unsupported error-return ABI and rich deferred error-reflection cases have deterministic rejection tests.
Modules, Namespaces, Imports, and Package Boundaries¶
Source design:
Tasks:
- Module-loader snapshots cover root namespace identity, loose-file synthesized module context,
module.toml,module(...),include(...), imports, re-exports, destructuring imports, conflicts, root escapes, and cycles. - Prelude loading uses the same internal namespace/import path that later user modules use.
- Multi-file diagnostics retain stable source IDs, spans, and deterministic load order.
Prelude¶
Source design:
Tasks:
- Prelude bootstrap snapshots cover primitive aliases/factories,
Namespace,module,include,Error,AllocError,Ordering, range helpers,Allocator,Box, core contract declarations, and accepted V1 attribute declarations. - Prelude validation roots demand and snapshot-check the public declarations needed by later language features instead of relying on namespace visibility alone.
- Prelude declarations resolve through ordinary source/namespace mechanics after the initial seeded primitive universe.
- Inert prelude declarations used before their implementing slice have explicit stubs and deterministic unsupported-use diagnostics.
Type System and Reflection¶
Source design:
Tasks:
- Type-table snapshots cover primitive types, non-standard integer-width target diagnostics, optionals, enums, functions, structs, arrays, slices, ranges, pointers, contracts, dyn descriptors, and layout facts.
- Reflection snapshots cover public names, wrong-kind diagnostics, visibility behavior,
Type.Predicatepropagation, structural satisfaction, conformance facts, and source/function/attribute/layout metadata. - Deferred reflection surfaces such as
Type.Expr,Type.Value, namespace enumeration, and runtime value reflection have deterministic unsupported-use diagnostics.
Structs, Methods, References, Mutability, and Ownership¶
Source design:
- Structs, Methods, References, Mutability, and Ownership
- Structs and Methods
- Reference and Mutability
- Ownership
Tasks:
- Cleanup-state snapshots cover defer, early exits, live overwrite, double cleanup, hidden temporaries, loop-created iterators, and move with active defer.
-
Boxallocation and failure-cleanup lowering is represented without backend access to source-level ownership rules. -
Box(dyn C)descriptor, disposal, and upcast lowering is testable while public layout remains private.
Semantic Contracts and Dispatch¶
Source design:
Tasks:
- Parser and sema snapshots cover
contract(...) { ... }. - Parser and sema snapshots cover
impl Type as Contract { ... }. - Diagnostics cover constrained local annotations such as
*const impl Sequence(T)outside function declaration parameter position. - Diagnostics cover anonymous static
implpointer parameters outside function declaration parameter position. - Diagnostics cover coherence, visibility, contract operation method lookup, dependency upcasts, and intersection normalization.
Arrays, Slices, Ranges, and Indexing¶
Source design:
Tasks:
- Array, slice, indexing, slicing, and range diagnostics have implementation snapshots.
- Bounds-check lowering and trap behavior are represented in IR.
- Slice descriptor field reflection is covered by sema/reflection snapshots.
- Array/slice built-in contract conformances are covered by sema snapshots.
Loops and Iteration¶
Source design:
Tasks:
- Dynamic iterator construction snapshots cover
Box(dyn Iterator(Item)).create_from_dyn(I, alloc, value), erased allocator authority lifetime lint candidates, allocation failure cleanup, and no hidden allocation infor. - Loop-source diagnostics and hidden cleanup lowering cases are covered by implementation snapshots.
Attributes¶
Source design:
Tasks:
- Attribute snapshots cover provider registration, target validation, repetition/conflict rules, provider evaluation, normalized metadata mutation, provenance reflection, and unsupported target diagnostics.
-
@resource,@repr(.catalyst),@align,@deprecated, ABI-named attributes, and accepted function call-convention metadata each have an owning slice and backend-facing fact path where needed. - Providers mutate compiler-owned targets only through explicit APIs and never patch AST directly.
C ABI Interop¶
Source design:
Tasks:
- Exact diagnostics that reject unsupported export/import types are settled.
- Resolved ABI, import/export, link-name, visibility, and lowered type facts are carried into SIR and IR.
- C backend consumes only IR facts and does not inspect AST attributes or rerun semantic ABI checks.
- Duplicate exported/imported link-name behavior is covered by diagnostics snapshots.
Realtime and Allocation Visibility¶
Source design:
Tasks:
- Allocation-backed features make allocation authority explicit in SIR/IR snapshots and never hide allocation behind plain
foror ordinary static dispatch. - Realtime/effect metadata remains explicitly out of V1 semantics, with any policy guidance implemented as warnings or future-lint classification rather than source validity.
Compiler Diagnostics and Lint Boundary¶
Source design:
Tasks:
- Diagnostics snapshots cover payload shape, notes, warnings, lints, fatal errors, deterministic rendering, multi-file spans, and comptime-produced diagnostics.
- Lint snapshots prove lints are hook/artifact-driven, can warn or fail only through explicit policy, and do not define source validity.
- Lint configuration, suppression, and autofix remain explicitly deferred.
Standard Library Skeleton¶
Source design:
Tasks:
- Standard-library smoke snapshots cover the accepted namespace skeleton and minimal declarations needed by V1 examples.
-
std.mem.FixedBufferAllocatorand allocation-backed examples are staged through the allocator/Box slices, not preloaded as compiler magic. - Namespaces without V1 implementation stay as deterministic stubs or deferred diagnostics, not partially specified semantics.
SIR, IR, Lowering, and Backend Closure¶
Source design:
- Compiler Pipeline
- Phase Boundaries
- SIR, IR, and Lowering
- IR
- Interpreter Backend
- Layout Reflection
- C ABI Interop
Tasks:
- SIR can represent every V1 semantic fact without preserving source ambiguity or backend details.
- IR can represent every V1 backend fact without unresolved names, generics, semantic contracts, or source-level method calls.
- Layout finalization is routed through an internal representation-mode abstraction even though V1 accepts only
.catalystsource layout. - Lowering rules exist for functions, errors, blocks, conditionals, loops, optionals, structs, arrays, slices, ranges, pointers, calls, methods, contracts, static dispatch, dynamic dispatch,
Box, resources, attributes, and C ABI. - Lowering represents
Allocatorstatic dispatch,*dyn Allocatorcalls,Boxprivate freeing state, dynamic contract pointer/dispose descriptors, placement initialization, and cleanup without backend access to source-level contracts. - IR verifier invariants are listed and tested.
- C backend output is deterministic and inspectable for the V1 core.
- Runtime traps, bounds checks, and checked safety failures have deterministic behavior and diagnostics/output expectations.
- The backend never reaches into AST or SIR for facts that should be in IR.
V1 Test Matrix and Final Review¶
Source design:
Tasks:
- Every V1 design workstream lists the phase snapshots needed to verify it.
- Deferred V2/Far Future features that share syntax with V1 have deterministic rejection tests.
- Example programs cover a scalar C export, module/import use, arrays/slices/ranges, resource cleanup, static contract dispatch, dynamic dispatch through
Box(dyn C), and iteration. -
git diff --checkand a Markdown link/path check pass after documentation updates. - All V1 pages are accepted or explicitly marked as design-incomplete.
Implementation Discipline¶
Do not mix parser, sema, IR, and backend work unless the task is explicitly an integration milestone. Behavior changes need tests in the narrowest relevant phase and should follow the tracer-bullet TDD workflow in Testing. Snapshot output is part of the public contract, and generated output must remain deterministic.