diff --git a/current/CHECKPOINT-REIFY.md b/current/CHECKPOINT-REIFY.md index e499fa07..11bf39fb 100644 --- a/current/CHECKPOINT-REIFY.md +++ b/current/CHECKPOINT-REIFY.md @@ -4,7 +4,19 @@ Companion to [PLAN-REIFY.md](PLAN-REIFY.md). Update after every step (one step a time, per the cadence rule). ## Last completed step -**Phase 2.1 (green) — `field_type` done.** `field_type($T, i) -> Type` is +**Phase 3.1 (green) — `RecvResult`/`TryResult` done.** Added `RecvResult($T)` and +`TryResult($T)` to `meta.sx` as type-fns over `reify` (a value-or-`closed`, and a +value-or-`empty`-or-`closed` enum). They needed NO new compiler machinery — they're +reify-of-a-literal in a type-fn body, i.e. exactly the Phase 1 path — so the channel +result types are pure sx library code. `examples/0617` green (both construct + +match, incl. payload-less `.closed`/`.empty`). Full suite green (673 examples). +Cadence: 3.0 xfail (undefined → RED) → 3.1 green. + +**`make_enum(variants)` NOT done** (Phase 3.2): it takes a RUNTIME `[]EnumVariant`, +so `reify(.enum(.{ variants = variants }))` is a non-literal arg — blocked on the +generalized reify reader (pairs with 2.2). **`type_info` NOT done** (Phase 2.2). + +### (prior) Phase 2.1 (green) — `field_type` done. `field_type($T, i) -> Type` is implemented over the type table (`fieldTypeOf` in `lower/generic.zig`, re-exported on `Lowering`): struct field / tagged-union + `union` variant payload (`.void` for a tagless variant) / tuple element / array + vector element; OOB and memberless @@ -79,7 +91,21 @@ on-demand import keeps the prelude clean; reify users `#import "modules/std/meta.sx"`. (User-directed.) ## Next step -**Phase 2.2 (`type_info($T) -> TypeInfo`).** Reflect a type into a `TypeInfo` +Two pending pieces, both blocked on the SAME thing — **a generalized reify reader** +(`reifyType` currently AST-walks a LITERAL `TypeInfo`; it can't read a computed / +variable `TypeInfo`). Do that generalization (interp-evaluate the `TypeInfo` value, +or a broader AST reader) and both unlock: +- **Phase 3.2 — `make_enum(variants: []EnumVariant) -> Type`** (sx lib; `variants` is + a runtime value, not a literal). +- **Phase 2.2 — `type_info($T) -> TypeInfo`** (reflect → a `TypeInfo` value; also + needs the `TypeInfo` data model widened past `` `enum `` for struct/tuple). Bails + loudly today in `call.zig:tryLowerReflectionCall`. + +Remaining after that: **Phase 4** (self-reference via `declare()`/`define()` — API +already decided), **Phase 5** (validation + loud diagnostics: dup variants, bad +backing, by-value self-ref). Both are independent of the reader generalization. + +### (superseded) earlier Next step — `type_info` value construction Reflect a type into a `TypeInfo` *value* — the inverse of reify. Two sub-pieces, both non-trivial: (a) widen the `meta.sx` `TypeInfo` data model beyond `` `enum `` (struct / tuple variants); (b) build the value at comptime — a `[]EnumVariant`-style slice of structs holding @@ -113,6 +139,10 @@ in PLAN-REIFY Phase 4. None yet. ## Log +- **3.1 (green) — `RecvResult`/`TryResult` done.** Added as type-fns over `reify` + in `meta.sx` (no new machinery — Phase 1 reify-of-literal-in-type-fn); `0617` + green. `make_enum` (3.2) pending on the generalized reify reader. +- **3.0 (xfail).** `0617` + empty marker → RED (RecvResult undefined). - **2.1 (green) — `field_type` done.** `fieldTypeOf` over the type table (struct/tagged-union/union/tuple/array/vector; OOB+memberless = loud poison); folds at lower time, composes in `type_eq`/`type_name`; `0616` green. `type_info` diff --git a/current/PLAN-REIFY.md b/current/PLAN-REIFY.md index 2bbc1a00..7f800442 100644 --- a/current/PLAN-REIFY.md +++ b/current/PLAN-REIFY.md @@ -77,10 +77,12 @@ Examples: `06xx` (comptime, deterministic), `11xx` (diagnostics for loud failure | 2.1 | green | **DONE.** `field_type($T, i) -> Type` over the type table (`fieldTypeOf` in `generic.zig`): struct field / tagged-union+union variant payload / tuple element / array+vector element; OOB + memberless → loud poison. Folds at lower time, composes in `type_eq`/`type_name`. | `src/ir/lower/generic.zig` | | 2.2 | xfail→green | **PENDING.** `type_info($T) -> TypeInfo` — reflect a type into a `TypeInfo` *value* (the inverse of reify). Needs the `TypeInfo` data model widened (struct/tuple variants beyond `` `enum ``) AND comptime construction of a `[]EnumVariant`-style value (slice of structs holding strings + `Type` tags) read from the type table. Still bails loudly in `call.zig:tryLowerReflectionCall`. Larger than 2.1 — its own step. | `library/modules/std/meta.sx`, `src/ir/interp.zig` / `call.zig` | -### Phase 3 — `make_enum` + `RecvResult`/`TryResult` (sx lib) +### Phase 3 — `RecvResult`/`TryResult` (done) + `make_enum` (pending) | 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/*` | +| 3.0 | xfail | `examples/0617` uses `RecvResult(i64)`/`TryResult(i64)` (construct + match). Red (undefined). | `examples/0617-*` | +| 3.1 | green | **DONE.** `RecvResult($T)`/`TryResult($T)` as type-fns over `reify` in `meta.sx` — needs NO new machinery (reify-of-literal in a type-fn body = Phase 1). `0617` green. | `library/modules/std/meta.sx` | +| 3.2 | pending | **`make_enum(variants: []EnumVariant) -> Type`** — sx lib over `reify` with a RUNTIME (non-literal) `variants` arg. BLOCKED on the generalized reify reader: `reifyType` currently reads a LITERAL `TypeInfo` off the AST, so `reify(.enum(.{ variants = variants }))` (variable, not a literal) can't be read yet. Pairs with Phase 2.2 (interp-evaluate the `TypeInfo` value instead of AST-walking). | `library/modules/std/meta.sx`, `src/ir/lower/nominal.zig` | ### Phase 4 — reference-based self-reference (explicit declare → define) > **API decision (user-directed):** an explicit **`declare()` / `define(h, info)`** @@ -133,6 +135,9 @@ Examples: `06xx` (comptime, deterministic), `11xx` (diagnostics for loud failure mangled name; `Box(i64)` at two sites is one type; `examples/0615` green) - [~] Phase 2 — `field_type` DONE (`examples/0616` green); `type_info` (reflect → a `TypeInfo` value) PENDING as step 2.2 +- [~] Phase 3 — `RecvResult($T)`/`TryResult($T)` DONE (`examples/0617` green, type-fns + over `reify` in `meta.sx`); `make_enum(variants)` PENDING (step 3.2 — needs the + generalized reify reader, pairs with 2.2) - [ ] Phase 2 — `type_info` + `field_type` - [ ] Phase 3 — `make_enum` + `RecvResult`/`TryResult` - [ ] Phase 4 — reference self-reference diff --git a/examples/expected/0617-comptime-reify-recvresult.exit b/examples/expected/0617-comptime-reify-recvresult.exit index e69de29b..573541ac 100644 --- a/examples/expected/0617-comptime-reify-recvresult.exit +++ b/examples/expected/0617-comptime-reify-recvresult.exit @@ -0,0 +1 @@ +0 diff --git a/examples/expected/0617-comptime-reify-recvresult.stderr b/examples/expected/0617-comptime-reify-recvresult.stderr new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/examples/expected/0617-comptime-reify-recvresult.stderr @@ -0,0 +1 @@ + diff --git a/examples/expected/0617-comptime-reify-recvresult.stdout b/examples/expected/0617-comptime-reify-recvresult.stdout new file mode 100644 index 00000000..ee8130cc --- /dev/null +++ b/examples/expected/0617-comptime-reify-recvresult.stdout @@ -0,0 +1,4 @@ +recv value 42 +recv closed +try value 7 +try empty diff --git a/library/modules/std/meta.sx b/library/modules/std/meta.sx index 76f91732..8df7e504 100644 --- a/library/modules/std/meta.sx +++ b/library/modules/std/meta.sx @@ -36,3 +36,29 @@ TypeInfo :: enum { reify :: (info: TypeInfo) -> Type #builtin; type_info :: ($T: Type) -> TypeInfo #builtin; field_type :: ($T: Type, idx: i64) -> Type #builtin; + +// --- Reify'd shapes built in sx library code (no new compiler machinery) --- +// +// The channel result types, expressed as type-fns over `reify`. They are the +// canonical demonstration that `reify` carries a full enum through codegen: +// `RecvResult(i64)` constructs and matches like any hand-written enum, and is +// one nominal type across sites (the type-fn mangled-name identity path). The +// channel library (N3) consumes these once it lands. + +// A blocking recv: a value, or the channel was closed (drained). +RecvResult :: ($T: Type) -> Type { + return reify(.enum(.{ variants = .[ + EnumVariant.{ name = "value", payload = T }, + EnumVariant.{ name = "closed", payload = void }, + ] })); +} + +// A non-blocking try-recv: a value, currently empty, or closed — three states +// a bool can't express. +TryResult :: ($T: Type) -> Type { + return reify(.enum(.{ variants = .[ + EnumVariant.{ name = "value", payload = T }, + EnumVariant.{ name = "empty", payload = void }, + EnumVariant.{ name = "closed", payload = void }, + ] })); +}