green(reify): type-fn over reify memoizes by mangled name (identity)

REIFY Phase 1.1 (Phase 1 complete). instantiateTypeFunction detects a
type-fn body that returns reify(...) (findReturnReifyCall) and routes it
to reifyType under the instantiation's name — mangled for inline use,
the alias name for `Foo :: Box(i64)` — with the type-arg bindings active
so reify payloads (`payload = T`) resolve against the instantiation args.
Placed before the general case, whose resolveTypeWithBindings would
route the reify call to the inline-position loud bail.

Registering under the mangled name lets the top-of-instantiation cache
return the SAME TypeId on a second instantiation, so Box(i64) resolved
at two independent sites is ONE type (Contract 1). examples/0615 green
(build()->consume() cross-site + `b : Box(i64) = .none`). Suite green
(671 examples, 447 unit).
This commit is contained in:
agra
2026-06-16 18:54:11 +03:00
parent e4d24476a9
commit 18a4f9dd54
7 changed files with 222 additions and 10 deletions

View File

@@ -4,7 +4,20 @@ Companion to [PLAN-REIFY.md](PLAN-REIFY.md). Update after every step (one step a
time, per the cadence rule).
## Last completed step
**Phase 0.2 (green) — Phase 0 COMPLETE.** Implemented `reify(.enum(...))`:
**Phase 1 (type-fn → reify identity) — COMPLETE.** A type-fn body that returns
`reify(...)` now mints the enum under the instantiation's name:
`instantiateTypeFunction` (`lower/generic.zig`) detects a reify-returning body
(`findReturnReifyCall`) and routes it to `reifyType(<mangled-or-alias name>,
reify_call)` with the type-arg bindings active (so `payload = T` resolves to the
bound arg) — placed BEFORE the general case, which would otherwise route the
reify call to the inline-position loud bail. Registering under the mangled name
lets the fn's top-of-instantiation cache return the SAME `TypeId` on the second
instantiation → `Box(i64)` at two independent sites is ONE type (**Contract 1**).
`examples/0615` green (`build()``consume()` cross-site, plus `b : Box(i64) =
.none`); full suite green (671 examples, 447 unit). Cadence: 1.0 xfail (empty
marker, RED) → 1.1 green (this commit).
### (prior) Phase 0.2 (green) — Phase 0 COMPLETE. Implemented `reify(.enum(...))`:
`Lowering.reifyType` (in `lower/nominal.zig`) reads the flat-enum `TypeInfo`
literal off the AST, synthesizes an `ast.EnumDecl`, and feeds it through the
SAME `type_bridge.buildEnumInfo` path source enums use → the minted type is
@@ -52,14 +65,16 @@ on-demand import keeps the prelude clean; reify users `#import
"modules/std/meta.sx"`. (User-directed.)
## Next step
**Phase 1 (type-fn → reify identity).** `R :: ($T) -> Type { reify(...) }`; assert
`R(i64)` from two sites is ONE type (assignable / matchable across sites). xfail →
green by registering a reify-returning type-fn's result under the instantiation
mangled name (mirror `generic.zig:1663-1689`). NOTE: Phase 0's `reifyType` is hooked
only at the `E :: reify(...)` const-decl site (`decl.zig`) and reads a LITERAL
`TypeInfo` off the AST; Phase 1 must route a reify call returned from a type-fn body
(and likely generalize the literal-AST reader, or evaluate via the interpreter, for
non-literal `TypeInfo`).
**Phase 2 (`type_info` + `field_type`).** Reflect a struct/tuple read variant /
field names + **types** (`field_type($T, i) -> Type`, `type_info($T) -> TypeInfo`).
xfail → green by implementing both over the type table (reuse the
`field_count`/`field_name` reflection path; both currently bail loudly —
`type_info` in `call.zig:tryLowerReflectionCall`, `field_type` in
`generic.zig:resolveTypeCallWithBindings`). NOTE: `reifyType` still reads a LITERAL
`TypeInfo` off the AST (works for the inline-literal and type-fn-over-literal cases
Phases 01 use); a `type_info`-derived (computed, non-literal) `TypeInfo` fed back
into `reify` would need the reader generalized (or interp evaluation) — call that out
when Phase 2 enables round-tripping.
SELF-REFERENCE = Phase 4, API DECIDED (user-directed): explicit **`declare()` →
`define(h, info)`** (the declaration-vs-definition split; NOT a `reify_rec((self)=>…)`
@@ -77,6 +92,11 @@ in PLAN-REIFY Phase 4.
None yet.
## Log
- **1.1 (green) — Phase 1 done.** Type-fn body `return reify(...)` routes through
`reifyType` under the instantiation name (`findReturnReifyCall` +
mangled-name registration); `Box(i64)` at two sites = one type (Contract 1);
`0615` green.
- **1.0 (xfail).** `0615` + empty `.exit` marker → RED (reify bailed in type-fn body).
- **0.2 (green) — Phase 0 done.** `reifyType` mints a flat enum from a literal
`TypeInfo` via the shared `buildEnumInfo` path; `0614` green; Contract 2 confirmed
(reify'd enum == source enum, same construct/match). Payload-less variant idiom in