docs(reify): Phase 4 self-reference = explicit reserve()/complete()
User-directed API decision: replace the reify_rec((self)=>...) closure with an explicit reserve() -> Type handle + complete(handle, info) pair. reserve() returns a forward nominal Type usable freely in any later TypeInfo (*List, []List, and across types for mutual recursion the one-self closure couldn't express); reify(info) stays as the one-shot sugar. Maps onto existing reserve->complete machinery. Captured in PLAN-REIFY Phase 4 + Contract 5 + CHECKPOINT-REIFY.
This commit is contained in:
@@ -61,12 +61,16 @@ only at the `E :: reify(...)` const-decl site (`decl.zig`) and reads a LITERAL
|
|||||||
(and likely generalize the literal-AST reader, or evaluate via the interpreter, for
|
(and likely generalize the literal-AST reader, or evaluate via the interpreter, for
|
||||||
non-literal `TypeInfo`).
|
non-literal `TypeInfo`).
|
||||||
|
|
||||||
OPEN DESIGN Q (raised by user, = Phase 4): self-referencing enum via `*Self`/`[]Self`
|
SELF-REFERENCE = Phase 4, API DECIDED (user-directed): explicit **`reserve()` →
|
||||||
payloads. Current `reifyType` resolves each payload eagerly through `buildEnumInfo`,
|
`complete()`** (NOT a `reify_rec((self)=>…)` closure). `reserve()` returns a forward
|
||||||
so a `*Self` payload has no type to point at yet — Phase 4 needs the
|
nominal `Type` handle (named from the `::` LHS) usable freely in any later `TypeInfo`
|
||||||
reserve-placeholder→complete path (`nominal.zig` reserve + `types.zig:442`): intern
|
— `*List`, `[]List`, and across types for MUTUAL recursion the one-`self` closure
|
||||||
the enum's nominal slot FIRST, expose it as `Self`, then resolve payloads. By-value
|
couldn't express; `complete(handle, info)` fills the body. `reify(info)` stays as the
|
||||||
recursion stays rejected (infinite size).
|
one-shot sugar. Maps onto existing machinery: reserve = empty nominal slot
|
||||||
|
(`reserveShadowEnumSlot`-style), complete = `buildEnumInfo` + `updatePreservingKey`,
|
||||||
|
struct-stub→tagged_union re-key already handled (`internNamedTypeDecl`'s
|
||||||
|
`adoptsForwardStructStub`). Loud invariants: never-completed reserve = hard error;
|
||||||
|
by-value self-inclusion rejected (infinite size). Full write-up in PLAN-REIFY Phase 4.
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
None yet.
|
None yet.
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ tagged-union, and **replaces** a would-be `enum($T)` generic-enum language featu
|
|||||||
`toLLVMType`, `type_name`/format) — so it flows through **unmodified**.
|
`toLLVMType`, `type_name`/format) — so it flows through **unmodified**.
|
||||||
3. **Validate loudly** at the `intern`/`internNominal` choke point (`types.zig:411-439`).
|
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.
|
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→
|
5. **Reference-based self-reference** (`*Self`/`[]Self`) via an explicit
|
||||||
complete (`nominal.zig:86/108/120`, `types.zig:442`); **by-value recursion rejected**.
|
**`reserve()` → `complete()`** pair (reserve-placeholder→complete reuse of
|
||||||
|
`nominal.zig:86/108/120`, `types.zig:442`); **by-value recursion rejected**. (See
|
||||||
|
Phase 4 — the `reserve`/`complete` API supersedes the earlier `reify_rec` closure.)
|
||||||
|
|
||||||
Surface follows the **`#builtin`** pattern of the existing reflection builtins
|
Surface follows the **`#builtin`** pattern of the existing reflection builtins
|
||||||
(`type_of`/`field_count`/`field_name` in `library/modules/std/core.sx`,
|
(`type_of`/`field_count`/`field_name` in `library/modules/std/core.sx`,
|
||||||
@@ -79,11 +81,28 @@ Examples: `06xx` (comptime, deterministic), `11xx` (diagnostics for loud failure
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 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/*` |
|
| 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
|
### Phase 4 — reference-based self-reference (explicit reserve → complete)
|
||||||
|
> **API decision (user-directed):** an explicit **`reserve()` / `complete()`** pair,
|
||||||
|
> NOT a `reify_rec((self) => …)` closure. `reserve()` returns a forward-declared
|
||||||
|
> nominal `Type` HANDLE — a real `Type` value usable freely in any later `TypeInfo`
|
||||||
|
> (`*List`, `[]List`, and across types for MUTUAL recursion, which the one-`self`
|
||||||
|
> closure can't express). `complete(handle, info)` fills the body. `reify(info)` stays
|
||||||
|
> as the one-shot sugar (= reserve + complete + return) for the non-recursive case.
|
||||||
|
> No special self-ref node in `TypeInfo` — a reserved type is just a `Type`.
|
||||||
|
> ```sx
|
||||||
|
> List :: reserve(); // name from the `::` LHS
|
||||||
|
> complete(List, .enum(.{ variants = .[
|
||||||
|
> EnumVariant.{ name = "cons", payload = *List }, // reference it freely
|
||||||
|
> EnumVariant.{ name = "nil", payload = void } ] }));
|
||||||
|
> ```
|
||||||
|
> Loud invariants: (a) a `reserve()` never `complete()`d = hard error at end of
|
||||||
|
> comptime (no silent empty type); (b) by-VALUE self-inclusion (`payload = List`, not
|
||||||
|
> `*List`) rejected — infinite size, same check recursive source types get.
|
||||||
|
|
||||||
| Step | Commit | What | Files |
|
| 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.0 | xfail | `reserve()` returns a forward nominal `Type`; `complete()` fills it. Recursive enum via `*Self` (tree/list). 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` |
|
| 4.1 | green | `reserve` = intern empty nominal slot (`reserveShadowEnumSlot`-style); `complete` = `buildEnumInfo` + `updatePreservingKey`; struct-stub→tagged_union re-key already handled by `internNamedTypeDecl` (`adoptsForwardStructStub`). | `src/ir/lower/nominal.zig`, `src/ir/lower/decl.zig`, `src/ir/types.zig` |
|
||||||
|
|
||||||
### Phase 5 — validation + loud diagnostics
|
### Phase 5 — validation + loud diagnostics
|
||||||
| Step | Commit | What | Files |
|
| Step | Commit | What | Files |
|
||||||
|
|||||||
Reference in New Issue
Block a user