comptime VM: Phase 3 — register_type write side + payloadless-enum fixes
The mutating compiler-API, minting types LAZILY at lowering time (single pass,
the existing runComptimeTypeFunc path — so the write side is legacy-only; the
VM isn't wired at lowering time, and the read-side readers stay dual-path):
declare_type(name) -> Type forward nominal handle (≈ declare)
pointer_to(t) -> Type build *T references
register_type(handle, kind, members) ONE kind-branching fill (≈ unified define)
register_type branches on kind IN THE COMPILER (subsuming define's per-kind
dispatch); codes match type_kind: 1 struct, 2 actual .@"enum", 3 tagged_union,
4 tuple. Members are {name: string, ty: Type}. A non-generic `-> Type` builder is
now flagged is_comptime (decl.zig) so its dead body permits the welded calls.
Graph support: forward declare_type handles + pointer_to express a mutually-
recursive A<->B graph (*A, *B, B-by-value) before bodies are filled. register_type
is idempotent — re-filling a nominal slot (a minting module reached via two import
edges) re-mints identically rather than erroring (nominalIdent reads identity from
any nominal kind).
Fixes (issue 0142):
- A fully payloadless comptime-minted enum was minted as an all-void tagged_union,
whose IR size disagrees with its LLVM size -> verifySizes panic. Now mints a real
.@"enum" (register_type kind 2 AND the metatype defineEnum).
- Bare `EnumType.variant` qualified construction of a payloadless variant wasn't
supported (failed for hand-written enums too — the type name lowered to a Type
value). Added in lowerFieldAccess via isPayloadlessVariant; payload-carrying
variants keep their call form.
Examples: 0631 (graph + actual enum + reflection), 0632 (make_enum all-void),
0633/0634/0635 (namespaced / bare / multi-edge import of a minted type), 0187
(qualified variant construction). Unit tests added.
Parity 697/697 (gate OFF and -Dcomptime-flat).
This commit is contained in:
@@ -325,6 +325,26 @@ when reached (sentinels or accessor fns; see the design doc Risks).
|
||||
`List` growth; orthogonal, see `current/CHECKPOINT-METATYPE.md`.)
|
||||
|
||||
## Log
|
||||
- **Phase 3 P3.3 (VM plan) — WRITE side: declare_type + pointer_to + ONE kind-branching register_type (2026-06-18).**
|
||||
The mutating compiler-API: `declare_type(name) -> Type` (forward handle), `pointer_to(t) -> Type`
|
||||
(build `*T`), and `register_type(handle, kind, members: []Member) -> Type` which branches on
|
||||
`kind` IN THE COMPILER (subsuming define's per-kind dispatch). Take/return real `Type` values
|
||||
(matching meta.sx declare/define). **Timing (per user): mint LAZILY at lowering time, single
|
||||
pass** (the existing `runComptimeTypeFunc`), so the write side is **legacy-only** (`compiler_lib`
|
||||
handlers) — the VM isn't wired at lowering time, no VM mirror needed; readers stay dual-path.
|
||||
A non-generic `-> Type` builder is now flagged `is_comptime` (decl.zig) so its dead body permits
|
||||
the welded calls. **Graph:** forward handles + `pointer_to` express mutually-recursive A↔B (`*A`,
|
||||
`*B`, B-by-value); `register_type` is **idempotent** (re-fill a nominal slot reached via two
|
||||
import edges — `nominalIdent`). `kind` codes match `type_kind` (1 struct · 2 actual `.@"enum"` ·
|
||||
3 tagged_union · 4 tuple). **Fixed two bugs (issue 0142):** (a) a fully payloadless minted enum
|
||||
was an all-void tagged_union → verifySizes panic; now a real `.@"enum"` (register_type kind 2 AND
|
||||
metatype `defineEnum`); (b) bare `EnumType.variant` payloadless qualified construction wasn't
|
||||
supported (failed for hand-written enums too) — added in `lowerFieldAccess` (`isPayloadlessVariant`).
|
||||
Examples 0631 (graph + actual enum + reflection), 0632 (make_enum all-void), 0633/0634/0635
|
||||
(namespaced / bare / multi-edge import of a minted type), 0187 (qualified variant construction).
|
||||
**Parity 697/697** (gate ON and OFF); unit tests added. **Next (P3.4):** re-express
|
||||
declare/define/type_info as sx over the compiler-API + delete the bespoke interp arms (needs the
|
||||
VM hardened for lowering-time IR, or the metatype migrated onto the legacy compiler-API calls).
|
||||
- **Phase 3 P3.2b (VM plan) — kind + enum-value readers: `type_kind` + `type_field_value`; READ side complete (2026-06-18).**
|
||||
The last two read-only readers the metatype's `type_info(T)` needs (added to
|
||||
`compiler_lib.bound_fns` AND `Vm.callCompilerFn`, each backed by a `TypeTable` query both
|
||||
|
||||
@@ -302,18 +302,36 @@ host through it:
|
||||
- **READ side now complete:** `find_type` + `type_kind` + `type_field_count` +
|
||||
`type_field_name` + `type_field_type` + `type_nominal_name` + `type_field_value` cover
|
||||
everything `reflectTypeInfo` reads.
|
||||
- **Next (P3.3) — ONE `register_type(info)` write fn (revised direction, 2026-06-18):** per
|
||||
the user, the mutating side is NOT per-kind (`register_struct`/`register_enum`/…) but a
|
||||
SINGLE function that takes a type-info value and **branches on the kind in the compiler**,
|
||||
minting the right `TypeInfo`. This subsumes `define`'s `defineStruct`/`defineEnum`/
|
||||
`defineTuple` dispatch into one host-side switch. Open design points to resolve when
|
||||
reached: the flat-memory shape of the `info` argument the sx side passes (a tagged
|
||||
`{ kind, payload }` over the readers' handle types), the mutable-table / host-ABI-vs-
|
||||
target-ABI boundary, and pointer-escape/lifetime (escaping field arrays copied into
|
||||
compiler-owned memory at the boundary). Re-expressing `declare`/`define`/`type_info` as sx
|
||||
(the metatype, which runs at LOWERING time) still needs the VM hardened against malformed
|
||||
lowering-time IR first — keep that on the legacy path until then (see the resume note in
|
||||
CHECKPOINT-COMPILER-API.md).
|
||||
- **(P3.3) WRITE side — `declare_type` + `pointer_to` + ONE kind-branching `register_type` (DONE).**
|
||||
The mutating side is a SINGLE `register_type(handle, kind, members)` that branches on `kind`
|
||||
IN THE COMPILER (subsuming `define`'s `defineStruct`/`defineEnum`/`defineTuple`), plus
|
||||
`declare_type(name) -> Type` (forward handle) and `pointer_to(t) -> Type` (build `*T`
|
||||
references). They take/return real `Type` values (matching meta.sx's declare/define).
|
||||
- **Timing decision (per the user):** mint LAZILY at LOWERING time (single pass, NOT a
|
||||
pre-emit phase, NOT two-pass) — the existing `runComptimeTypeFunc` path. So the write
|
||||
side is **legacy-only** (`compiler_lib` handlers); the VM isn't wired at lowering time, so
|
||||
no VM mirror is needed (the read-side readers stay dual-path for emit-time reflection). A
|
||||
non-generic `-> Type` builder is now flagged `is_comptime` (`decl.zig`) so its dead body
|
||||
permits the welded calls (the comptime-only gate).
|
||||
- **Graph support:** forward `declare_type` handles + `pointer_to` express a
|
||||
mutually-recursive A↔B graph (`*A`, `*B`, B-by-value) before bodies are filled.
|
||||
`register_type` is **idempotent** — re-filling a nominal slot (same module reached via two
|
||||
import edges) re-mints identically instead of erroring (`nominalIdent` reads identity from
|
||||
any nominal kind). `kind` codes match `type_kind`: 1 struct · 2 enum (actual `.@"enum"`) ·
|
||||
3 tagged_union · 4 tuple.
|
||||
- **Two bugs fixed en route** (issue 0142): (a) a fully payloadless comptime-minted enum
|
||||
was minted as an all-void `tagged_union` → `verifySizes` panic; now mints a real
|
||||
`.@"enum"` (both `register_type` kind 2 AND the metatype `defineEnum`). (b) bare
|
||||
`EnumType.variant` qualified construction of a payloadless variant wasn't supported (failed
|
||||
for hand-written enums too) — added in `lowerFieldAccess` (`isPayloadlessVariant`).
|
||||
- Examples: `0631` (graph + actual-enum + reflection), `0632` (make_enum all-void),
|
||||
`0633`/`0634`/`0635` (namespaced / bare / multi-edge import of a minted type), `0187`
|
||||
(qualified variant construction). Parity 697/697 (gate ON and OFF); unit tests added.
|
||||
- **Next (P3.4):** re-express `declare`/`define`/`type_info` as sx over the read+write
|
||||
compiler-API and DELETE the bespoke interp arms — needs the VM hardened against malformed
|
||||
lowering-time IR first (the metatype runs at lowering time), so either harden + wire the VM
|
||||
there, or migrate the metatype onto the legacy compiler-API calls first. Decide when reached.
|
||||
Phase 2 (bytecode) is the orthogonal speed work.
|
||||
|
||||
### Phase 3 — Compiler-API on flat memory (resume the stream — no weld)
|
||||
With native-byte comptime values, re-home the compiler-API:
|
||||
|
||||
Reference in New Issue
Block a user