docs(design): execution-model roadmap + reify implementation stream
Add the async-first execution-model roadmap (comptime JIT spine, colorblind fibers/Io, atomics, hot-reload) with all seven decisions resolved and three-way reviewed, and carve the first stream: comptime type_info/reify (PLAN-REIFY + checkpoint) — the codebase-validated foundation for channel result types and race's synthesized tagged union.
This commit is contained in:
32
current/CHECKPOINT-REIFY.md
Normal file
32
current/CHECKPOINT-REIFY.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# CHECKPOINT-REIFY — comptime `type_info` / `reify` (async-first foundation, step 3)
|
||||
|
||||
Companion to [PLAN-REIFY.md](PLAN-REIFY.md). Update after every step (one step at a
|
||||
time, per the cadence rule).
|
||||
|
||||
## Last completed step
|
||||
**None — stream just carved.** Design validated (3 codebase reviewers; all five reify
|
||||
contracts confirmed feasible). No code written yet.
|
||||
|
||||
## Current state
|
||||
- The plan + the five locked contracts exist in `PLAN-REIFY.md`; design-of-record is
|
||||
`design/execution-evolution-roadmap.md` §7 step 3 + §8.1.
|
||||
- **Nothing built.** `reify`/`type_info`/`field_type` do not exist in the compiler.
|
||||
- Confirmed against the source (anchors in the plan): type minting via
|
||||
`intern`/`internNominal` is programmatic and AST-free; type-fns memoize by mangled
|
||||
name; enum codegen is fully type-table-driven (zero AST coupling); recursive
|
||||
forward-declaration (reserve→complete) already exists for source types.
|
||||
|
||||
## Next step
|
||||
**Phase 0.0 (lock):** add `TypeInfo`/`EnumInfo`/`EnumVariant` data types + bodyless
|
||||
`#builtin` decls for `reify`/`type_info`/`field_type` to `library/modules/std/core.sx`
|
||||
(parsed, unimplemented → loud bail), with a unit test that the decls parse. Then 0.1
|
||||
(xfail: `examples/06xx-comptime-reify-enum.sx`) → 0.2 (green: implement `reify(.enum_)`).
|
||||
|
||||
## Known issues
|
||||
None yet.
|
||||
|
||||
## Log
|
||||
- **Stream carved.** Selected as the first async-first foundation: `reify` gates both
|
||||
channel result types (`RecvResult($T)`) and `race`'s synthesized union, is fully
|
||||
validated (3 reviewers), and is a self-contained compiler/type-system feature
|
||||
testable in isolation (`06xx` comptime). Generic-enum syntax dropped in its favor.
|
||||
125
current/PLAN-REIFY.md
Normal file
125
current/PLAN-REIFY.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# PLAN-REIFY — comptime type reflection + construction (`type_info` / `reify`)
|
||||
|
||||
## Goal
|
||||
|
||||
Add the two comptime metaprogramming builtins — **`type_info($T) -> TypeInfo`**
|
||||
(reflect a type → data) and **`reify(info: TypeInfo) -> Type`** (construct a *new
|
||||
nominal type* from data) — plus the sx-lib helpers (`make_enum`, `field_type`,
|
||||
`RecvResult`/`TryResult`) built over them. This is **step 3 of the async-first
|
||||
sequence** ([../design/execution-evolution-roadmap.md](../design/execution-evolution-roadmap.md)
|
||||
§7); it gates channel result types (`RecvResult($T)`) and `race`'s synthesized
|
||||
tagged-union, and **replaces** a would-be `enum($T)` generic-enum language feature.
|
||||
|
||||
> Rationale + the five validated contracts: design doc §7 step 3 + §8.1. The approach
|
||||
> was grounded by three codebase reviewers — it is a **small extension reusing existing
|
||||
> machinery**, not net-new architecture.
|
||||
|
||||
## Locked design (the five reify contracts — all codebase-validated)
|
||||
|
||||
1. **Nominal identity via type-fn memoization.** `RecvResult(i64)` is one `TypeId`
|
||||
because type-fns dedup by mangled `(fn,args)` name (`generic.zig:1620-1629`) +
|
||||
reify `findByName`. NOT structural dedup — enums are nominal (`types.zig:1110`).
|
||||
2. **Functional through codegen.** A reify'd enum has **no backing AST decl**, and
|
||||
every enum stage is type-table-driven (layout, construct, match+exhaustiveness,
|
||||
`toLLVMType`, `type_name`/format) — so it flows through **unmodified**.
|
||||
3. **Validate loudly** at the `intern`/`internNominal` choke point (`types.zig:411-439`).
|
||||
4. **Comptime-only, JIT-free** — a type-table op in the interpreter; no S1 dependency.
|
||||
5. **Reference-based self-reference** (`*Self`/`[]Self`) via reserve-placeholder→
|
||||
complete (`nominal.zig:86/108/120`, `types.zig:442`); **by-value recursion rejected**.
|
||||
|
||||
Surface follows the **`#builtin`** pattern of the existing reflection builtins
|
||||
(`type_of`/`field_count`/`field_name` in `library/modules/std/core.sx`,
|
||||
`specs.md:2594-2600`) — NOT the BuildOptions compiler-hook registry.
|
||||
|
||||
## Key code anchors (verified by review)
|
||||
|
||||
- Type minting: `TypeTable.intern` / `internNominal` — `src/ir/types.zig:411-439`.
|
||||
- Type-fn instantiation + mangled-name cache — `src/ir/lower/generic.zig:1575-1689`
|
||||
(cache check `:1620-1629`; register inline-struct result `:1663-1689`).
|
||||
- Forward-declare reserve (recursive types) — `src/ir/lower/nominal.zig:86/108/120`;
|
||||
complete a forward-declared type — `src/ir/types.zig:442`.
|
||||
- Enum codegen (all type-table-driven, the reify target shape): size `types.zig:633-636`;
|
||||
`resolveVariantIndex` `lower/expr.zig:1159-1177`; match `lower/control_flow.zig:748-945`;
|
||||
`toLLVMType` `backend/llvm/types.zig:111-154`; `type_name` `types.zig:846-882`.
|
||||
- Existing reflection builtins to mirror — `core.sx` (`#builtin`) + their interp/lower
|
||||
handlers (`src/ir/interp.zig` `type_name`/reflection at ~`:1911`).
|
||||
- Match form — `specs.md:408-424`.
|
||||
|
||||
## Cadence (IMPASSIBLE)
|
||||
|
||||
No commit may both add a test AND make it pass (xfail-then-green, or a behavior-lock).
|
||||
`zig build && zig build test` after every step. Never regenerate snapshots while red.
|
||||
Examples: `06xx` (comptime, deterministic), `11xx` (diagnostics for loud failures).
|
||||
|
||||
---
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 0 — `reify` of a flat enum (the core)
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 0.0 | lock | `TypeInfo`/`EnumInfo`/`EnumVariant` lib types in `core.sx` (data only); `reify`/`type_info`/`field_type` as bodyless `#builtin` decls (parsed, unimplemented → loud bail). Unit: decls parse. | `library/modules/std/core.sx`, `src/ir/interp.zig` |
|
||||
| 0.1 | xfail | `examples/06xx-comptime-reify-enum.sx` — `reify(.enum_(.{variants=[.{name="value",payload=i64},.{name="closed",payload=void}]}))`, construct `.value(3)`, match it. Red (reify unimplemented). | `examples/06xx-*` |
|
||||
| 0.2 | green | implement `reify(.enum_)` → build `EnumInfo`/`TaggedUnionInfo` `TypeInfo`, `internNominal(info, fresh_nominal_id)`, return `TypeId`. Example green; construct + match work unmodified (Contract 2). | `src/ir/interp.zig`, (`src/ir/types.zig` if a helper is wanted) |
|
||||
|
||||
### Phase 1 — type-fn → reify identity
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 1.0 | xfail | `examples/06xx-comptime-reify-typefn-identity.sx` — `R :: ($T)->Type { reify(...) }`; assert `R(i64)` from two sites is ONE type (assignable/matchable across sites). Red if reify-result not registered by mangled name. | `examples/06xx-*` |
|
||||
| 1.1 | green | register a reify-returning type-fn's result under the instantiation mangled name (mirror the inline-struct path `generic.zig:1663-1689`). Identity holds (Contract 1). | `src/ir/lower/generic.zig` |
|
||||
|
||||
### Phase 2 — `type_info` (reflect) + `field_type`
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 2.0 | xfail | reflect a struct/tuple → read variant/field names + **types** (`field_type($T,i)`). Red. | `examples/06xx-*` |
|
||||
| 2.1 | green | implement `type_info`/`field_type` over the type table (reuse the `field_count`/`field_name` reflection path). | `src/ir/interp.zig` |
|
||||
|
||||
### Phase 3 — `make_enum` + `RecvResult`/`TryResult` (sx lib)
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 3.0 | lock | `make_enum(variants) -> Type` (sx lib over `reify`); `RecvResult($T)`/`TryResult($T)` as type-fns. Behavior-lock: `RecvResult(i64)` constructs + matches. | `library/modules/std/*` |
|
||||
|
||||
### Phase 4 — reference-based self-reference
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 4.0 | xfail | recursive enum via `*Self` (tree/list): `reify_rec((self)=> .enum_(... payload = ptr_to(self) ...))`. Red. | `examples/06xx-*` |
|
||||
| 4.1 | green | `reify_rec` reserve-placeholder→complete (reuse `nominal.zig:86`/`types.zig:442` recursive path). | `src/ir/interp.zig`, `src/ir/types.zig` |
|
||||
|
||||
### Phase 5 — validation + loud diagnostics
|
||||
| Step | Commit | What | Files |
|
||||
|---|---|---|---|
|
||||
| 5.0 | xfail | `examples/11xx-diagnostics-reify-*` — dup variant names, non-integer backing, **by-value self-reference** ("infinite size; use `*Self`"). Pin the messages. | `examples/11xx-*` |
|
||||
| 5.1 | green | validate `TypeInfo` at the `intern`/`internNominal` choke point; emit diagnostics, never a broken type (Contract 3). | `src/ir/interp.zig` / `src/ir/types.zig` |
|
||||
|
||||
> `RaceResult` (tuple→tagged-union synthesis) is **not** in this stream — it lands with
|
||||
> `race` (async cluster), but it consumes exactly the `type_info`+`field_type`+`reify`
|
||||
> primitives built here.
|
||||
|
||||
## Risks / watch
|
||||
|
||||
- **Mangled-name plumbing (Phase 1)** is the one real unknown — confirm the type-fn
|
||||
path registers a *reify-returned* result (not just inline `struct {…}` literals).
|
||||
Fallback: have `reify` itself name the type by the instantiation key + `findByName`.
|
||||
- **Self-ref completion (Phase 4)** must reuse the existing recursive-type
|
||||
reserve→complete path; do not invent a new mutate-after-intern mechanism.
|
||||
- Keep `reify` **comptime-only**: a `reify` reached at runtime is a hard error.
|
||||
|
||||
## Status
|
||||
|
||||
- [ ] Phase 0 — `reify` flat enum
|
||||
- [ ] Phase 1 — type-fn identity
|
||||
- [ ] Phase 2 — `type_info` + `field_type`
|
||||
- [ ] Phase 3 — `make_enum` + `RecvResult`/`TryResult`
|
||||
- [ ] Phase 4 — reference self-reference
|
||||
- [ ] Phase 5 — validation + diagnostics
|
||||
|
||||
## Kickoff prompt (paste into a fresh session)
|
||||
|
||||
> Work the REIFY stream per `current/PLAN-REIFY.md` (+ checkpoint
|
||||
> `current/CHECKPOINT-REIFY.md`). Read the plan header (goal, five locked contracts,
|
||||
> key anchors) first; rationale is in `design/execution-evolution-roadmap.md` §7 step 3
|
||||
> + §8.1. **This session = Phase 0 only** (`TypeInfo` lib types + `reify` of a flat
|
||||
> enum: construct + match). Cadence (IMPASSIBLE): no commit both adds a test and makes
|
||||
> it pass — lock, then xfail→green. `zig build && zig build test` after every step. If
|
||||
> you hit an unrelated compiler bug, follow the CLAUDE.md IMPASSIBLE RULE (file an
|
||||
> issue, stop). Stop at the end of Phase 0; update the checkpoint.
|
||||
Reference in New Issue
Block a user