From e5d1d0de39f59ce0f86ed95265207666b8eff62a Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 16 Jun 2026 20:08:17 +0300 Subject: [PATCH] plan(reify): re-architect onto declare/define as the only compiler primitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User-directed redirection. The compiler should expose ONLY declare() and define(handle, info) as comptime type-table primitives; reify / make_enum / RecvResult / TryResult all become plain sx in meta.sx (reify == { h := declare(); define(h, info); return h; }). The AST-walking reifyType and every syntactic reify recognition (decl.zig E :: reify hook, generic.zig findReturnReifyCall routing) are to be DELETED, replaced by generic comptime evaluation of a Type-returning expression. PLAN-REIFY gains a RE-ARCHITECTURE section: the irreducible compiler floor (declare = empty nominal slot; define = decode a TypeInfo VALUE + fill via updatePreservingKey; comptime-eval a Type-returning ::-RHS/type-fn body), the resolved naming/identity story (declare mints anonymous, the binding site names it; identity via the existing instantiation cache), and an F1-F5 phase table that re-greens 0614/0615/0617 on the floor. No code change in this commit — the in-session Phase 3.2 attempt (make_enum + eval-decode reader) was reverted (reset to 9306ad5) so the floor is built first. Checkpoint records the revert + sets next step = F1. --- current/CHECKPOINT-REIFY.md | 47 +++++++++++++++++++++------------ current/PLAN-REIFY.md | 52 ++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/current/CHECKPOINT-REIFY.md b/current/CHECKPOINT-REIFY.md index 11bf39fb..a94b4612 100644 --- a/current/CHECKPOINT-REIFY.md +++ b/current/CHECKPOINT-REIFY.md @@ -12,9 +12,9 @@ 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). +**Phase 3.1 is the last GREEN step.** Phase 3.2 was attempted + reverted; the stream +now pivots to the `declare`/`define` RE-ARCHITECTURE (see the section below + the +F1–F5 table in PLAN-REIFY). **`type_info` NOT done** (old Phase 2.2, orthogonal). ### (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 @@ -90,20 +90,35 @@ type table and shifts every `.ir` snapshot (broke 37 examples in a trial). An on-demand import keeps the prelude clean; reify users `#import "modules/std/meta.sx"`. (User-directed.) -## Next step -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`. +## RE-ARCHITECTURE in progress (user-directed, 2026-06-16) +**`declare`/`define` are to be the ONLY compiler primitives; `reify` / `make_enum` / +`RecvResult` / `TryResult` move to sx in `meta.sx`.** `reify` becomes literally +`{ h := declare(); define(h, info); return h; }`. The AST-walking `reifyType` and all +syntactic `reify` recognition (`decl.zig` `E :: reify` hook, `generic.zig` +`findReturnReifyCall`) get DELETED, replaced by generic comptime evaluation of a +Type-returning expression. Full F1–F5 phase table + the resolved naming/identity +design is in **PLAN-REIFY.md → "RE-ARCHITECTURE"**. -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. +**A Phase 3.2 attempt (make_enum + an eval-decode reader, `reifyEnumFromVariantsValue` ++ `reifyValueFn`) was implemented this session, then REVERTED** (`git reset --hard +9306ad5`) per this decision — the reader grew the compiler instead of shrinking it. +The eval-decode *decode logic* is salvage for `define` (see commit 4d6c463 in reflog +if needed); the *syntactic routing* is discarded. + +## Next step +**F1 — `declare()`/`define()` primitives + a directly-minted RECURSIVE enum.** +- `declare() -> Type`: intern an empty forward nominal slot (`reserveShadowEnumSlot` + shape, `nominal.zig:98`), anonymous, return a first-class `Type`. +- `define(handle, info)`: decode the `TypeInfo` *value* (reuse the reverted decode: + interp `Value` → names + payload `Type`-tags → `tagged_union` matching + `buildEnumInfo`), fill via `updatePreservingKey`. +- `X :: declare()` decl hook + scan-time `define(...)` side-effect (must complete + before codegen needs the layout — same scan-time window the old `reifyType` used). +- Example: `List :: declare(); define(List, .enum(.{ … payload = *List … }))` — + cons/nil list, construct + match. Self-ref works because the handle predates the body. +Then F2 (reify→sx + general comptime-Type-decl eval, delete `reifyType`), F3 (type-fn +body eval, delete `findReturnReifyCall`, re-green 0615/0617), F4 (make_enum in sx), +F5 (validation). `type_info` (old 2.2) stays orthogonal/pending. ### (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 diff --git a/current/PLAN-REIFY.md b/current/PLAN-REIFY.md index 7f800442..dce9f3e6 100644 --- a/current/PLAN-REIFY.md +++ b/current/PLAN-REIFY.md @@ -55,7 +55,57 @@ Examples: `06xx` (comptime, deterministic), `11xx` (diagnostics for loud failure --- -## Phases +## RE-ARCHITECTURE (user-directed, 2026-06-16) — `declare`/`define` are the ONLY compiler primitives + +**Decision:** the compiler must expose **only** the two comptime type-table +primitives `declare()` and `define(handle, info)`. **`reify`, `make_enum`, +`RecvResult`, `TryResult` all become plain sx** in `meta.sx` — `reify` is literally +`{ h := declare(); define(h, info); return h; }`. The AST-walking `reifyType` and +every *syntactic* recognition of `reify` (`decl.zig`'s `E :: reify(...)` hook, +`generic.zig`'s `findReturnReifyCall` type-fn routing) are **deleted** — replaced by +generic **comptime evaluation of a Type-returning expression**. + +This supersedes the old builtin-`reify` approach of Phases 0/1/3 below (which are +GREEN today but compiler-coupled). Phase 3.2 (`make_enum` + the eval-decode reader) +was implemented then **reverted** (commit reset to 9306ad5) to rebuild on this floor. + +### The irreducible compiler floor (cannot be sx — mints `TypeId`s / evaluates types) +1. **`declare() -> Type`** — intern a fresh EMPTY forward nominal slot (unique + `nominal_id`, anonymous name), return it as a first-class `Type` value. Reuses the + `reserveShadowEnumSlot` shape (`nominal.zig:98`). +2. **`define(handle: Type, info: TypeInfo)`** — decode the `TypeInfo` **value** (the + reverted `reifyEnumFromVariantsValue` decode logic moves here: interp `Value` → + names + payload `Type`-tags → `tagged_union` byte-identical to `buildEnumInfo`), + fill the slot via `updatePreservingKey` (`types.zig:442`). Loud on bad input. +3. **Comptime-evaluate a Type-returning `::` RHS / type-fn body** through the + interpreter to a `type_tag`, then bind / rename / identity-cache. This is the new + general capability that REPLACES the `reify`-name pattern-matching. + +### Naming + identity (resolved) +- `declare()` mints ANONYMOUS; the **binding site** names it: a direct `X :: ` + renames the handle to `X`; a type-fn instantiation renames to the mangled name. +- **Identity (Contract 1)** still rides the existing `instantiateTypeFunction` + mangled-name cache — `RecvResult(i64)` memoizes, body (hence `declare`) runs once. + +### Floor phases (REPLACES old Phases 0/1/3; re-greens 0614/0615/0617) +| Step | Commit | What | Files | +|---|---|---|---| +| F1.0 | xfail | `examples/06xx` mints a **recursive** enum directly: `List :: declare();` + `define(List, .enum(.{ variants = .[ … payload = *List … ] }))`; construct + match a cons/nil list. Red (declare/define undefined). | `examples/06xx-*` | +| F1.1 | green | `declare`/`define` as comptime builtins + the `X :: declare()` decl hook + scan-time `define(...)` side-effect + the value-decode (from the reverted 3.2). Self-ref works because the handle predates the body. | `src/ir/lower/{decl,nominal}.zig`, `src/ir/interp.zig`, `meta.sx` | +| F2.0 | xfail | Reimplement `reify` in `meta.sx` as `declare`+`define`+return; switch `E :: reify(...)` to the **general comptime-Type-expr** decl path; delete the `E :: reify` AST special-case + `reifyType` literal walk. Red until the general path lands. | `meta.sx`, `src/ir/lower/decl.zig` | +| F2.1 | green | General comptime evaluation of a Type-returning `::` RHS (run interp → `type_tag` → rename/bind). `examples/0614` green again with ZERO `reify` knowledge in the compiler. | `src/ir/lower/decl.zig`, `src/ir/interp.zig` | +| F3.0 | xfail | Delete `findReturnReifyCall` routing; make `instantiateTypeFunction` run a Type-returning body through the interp generally. Red for 0615/0617 until it lands. | `src/ir/lower/generic.zig` | +| F3.1 | green | General type-fn body comptime-eval + rename to mangled name + identity cache. `examples/0615` (cross-site identity) + `0617` (RecvResult/TryResult) green on the floor. | `src/ir/lower/generic.zig` | +| F4 | xfail→green | `make_enum(variants)` in `meta.sx` — now TRIVIAL (reify is sx, type-fns eval generally). New `examples/06xx` (inline + computed variants). | `meta.sx`, `examples/06xx-*` | +| F5 | xfail→green | Validation + loud diagnostics: dup variant names, by-VALUE self-ref (`payload = List` not `*List` → "infinite size"), a `declare()` never `define()`d (hard error at end of comptime). | `src/ir/interp.zig` / `src/ir/types.zig`, `examples/11xx-*` | + +> `type_info($T) -> TypeInfo` (old Phase 2.2 — reflect a type INTO a value) is +> orthogonal to this floor and still pending; it CONSTRUCTS a `TypeInfo` value +> (inverse of `define`'s decode). Round-trips through the floor once it lands. + +--- + +## (SUPERSEDED by the re-architecture above) Original builtin-`reify` phases ### Phase 0 — `reify` of a flat enum (the core) | Step | Commit | What | Files |