green(reify): RecvResult/TryResult channel result types over reify

REIFY Phase 3.1. Add RecvResult($T) and TryResult($T) to meta.sx as
type-fns over reify (value-or-closed; value-or-empty-or-closed). They
need NO new compiler machinery — reify-of-a-literal in a type-fn body is
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). Suite green (673 examples, 447 unit).

make_enum(variants) (3.2) and type_info (2.2) remain — both blocked on a
generalized reify reader (reifyType currently AST-walks a literal
TypeInfo). Plan/checkpoint updated.
This commit is contained in:
agra
2026-06-16 19:15:26 +03:00
parent 6627f7348b
commit 9306ad570d
6 changed files with 71 additions and 4 deletions

View File

@@ -4,7 +4,19 @@ Companion to [PLAN-REIFY.md](PLAN-REIFY.md). Update after every step (one step a
time, per the cadence rule). time, per the cadence rule).
## Last completed step ## 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 implemented over the type table (`fieldTypeOf` in `lower/generic.zig`, re-exported
on `Lowering`): struct field / tagged-union + `union` variant payload (`.void` for on `Lowering`): struct field / tagged-union + `union` variant payload (`.void` for
a tagless variant) / tuple element / array + vector element; OOB and memberless 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.) "modules/std/meta.sx"`. (User-directed.)
## Next step ## 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 *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) `meta.sx` `TypeInfo` data model beyond `` `enum `` (struct / tuple variants); (b)
build the value at comptime — a `[]EnumVariant`-style slice of structs holding build the value at comptime — a `[]EnumVariant`-style slice of structs holding
@@ -113,6 +139,10 @@ in PLAN-REIFY Phase 4.
None yet. None yet.
## Log ## 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 - **2.1 (green) — `field_type` done.** `fieldTypeOf` over the type table
(struct/tagged-union/union/tuple/array/vector; OOB+memberless = loud poison); (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` folds at lower time, composes in `type_eq`/`type_name`; `0616` green. `type_info`

View File

@@ -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.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` | | 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 | | 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) ### Phase 4 — reference-based self-reference (explicit declare → define)
> **API decision (user-directed):** an explicit **`declare()` / `define(h, info)`** > **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) 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 - [~] Phase 2 — `field_type` DONE (`examples/0616` green); `type_info` (reflect → a
`TypeInfo` value) PENDING as step 2.2 `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 2 — `type_info` + `field_type`
- [ ] Phase 3 — `make_enum` + `RecvResult`/`TryResult` - [ ] Phase 3 — `make_enum` + `RecvResult`/`TryResult`
- [ ] Phase 4 — reference self-reference - [ ] Phase 4 — reference self-reference

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,4 @@
recv value 42
recv closed
try value 7
try empty

View File

@@ -36,3 +36,29 @@ TypeInfo :: enum {
reify :: (info: TypeInfo) -> Type #builtin; reify :: (info: TypeInfo) -> Type #builtin;
type_info :: ($T: Type) -> TypeInfo #builtin; type_info :: ($T: Type) -> TypeInfo #builtin;
field_type :: ($T: Type, idx: i64) -> Type #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 },
] }));
}