4.6 KiB
4.6 KiB
CHECKPOINT-METATYPE — comptime type metaprogramming (declare / define)
Companion to PLAN-METATYPE.md. Update after every step (one step at a time, per the cadence rule).
Last completed step
Self-reference — recursive enums via declare("Name") + *Name. The
declare/define floor now supports self-referential types.
declare(name) -> Typemints an empty (undefined) nominal slot NAMEDname;define(handle, info) -> Typedecodes theTypeInfovalue (variant names + payload Type-tags), fills the slot byte-identical to a source enum, and returns the handle (one-shot form chains:T :: define(declare("T"), info)). Interp executes both against amintTypeTable handle;defineEnum+decodeVariantElementsininterp.zig.- Self-reference:
evalComptimeType'spreregisterForwardTypesscans the comptime expression (and a called ctor fn's body) fordeclare("Name")calls and, before the body lowers, registers each as an empty forward nominal type AND binds it as a type alias. The alias is essential — aName :: ctor()decl makesNamea const_decl author, so a*Nameself-reference resolves through the forward-ALIAS path (type_aliases_by_source), which a barefindByNameregistration alone does NOT satisfy (it returns a pending empty-struct stub). The interp'sdeclarereturns that same slot;definefills it. - A
::binding or type-fn body calling aType-returning fn is comptime-evaluated (evalComptimeType) — no constructor-name knowledge.decl.zigtrigger =fnReturnsTypeValue; type-fn trigger =returnExprMintsType. - Nominal identity rides the type-fn instantiation cache (
renameNominalType). - The type NAME is on
declare(name)(compile-time string), notEnumInfo.
Examples green: 0614 (one-shot), 0615 (type-fn identity), 0617 (channel
results), 0618 (recursive *List: construct, match through pointer, recursive
traversal); field_type reflection 0616. Full suite green (674 examples).
Current state
modules/std/meta.sx:EnumVariant/EnumInfo{ name, variants }/TypeInfodata types;declare/define/type_info/field_type#builtins;RecvResult($T)/TryResult($T)sx constructors overdefine(declare(), …).- Compiler primitives only:
declare/define(construction),field_type(reflection). No constructor-name knowledge anywhere in the compiler — every named constructor is sx.declare(name)carries the type name (compile-time string) for forward-type registration. type_infostill bails loudly (call.zig:tryLowerReflectionCall) — pending.
Decision (kept)
Meta lives in modules/std/meta.sx, not the prelude. Declaring its data types
in the always-loaded prelude interns them into every module's type table and
shifts every .ir snapshot. On-demand import keeps the prelude clean.
Next step
Pick any (independent):
make_enum(variants: []EnumVariant)sx helper over a COMPUTED (non-literal) variant list — exercises the interpreter decoding a value-arg slice indefine(vs. the literal.[ … ]the current examples use).type_info($T) -> TypeInfo— reflect a type INTO a value (inverse ofdefine's decode); widenTypeInfopast`enum+ construct a[]EnumVariantvalue in the interp. Bails loudly today incall.zig:tryLowerReflectionCall. Its own focused effort.- Validation + loud diagnostics — duplicate variant names, by-VALUE
self-reference (
payload = Listnot*List→ infinite size), adeclare()neverdefine()d (hard error), use-before-define.
Known issues
None.
Log
- Self-reference done.
declare(name)+preregisterForwardTypes(forward type + alias before body lowers) →*Nameresolves; recursive*Listenum constructs, matches through the pointer, and traverses recursively.0618locks it.declaregained itsnamearg;EnumInfo.namedropped. Suite green (674). - declare/define floor established. The comptime type-construction surface is
two primitives (
declare/define); all named constructors are sx. A::binding or type-fn body that calls aType-returning fn is comptime-evaluated (the builtins mint the type) — no syntactic constructor recognition in the compiler. Examples 0614 (one-shot) / 0615 (type-fn identity) / 0617 (channel results) on the floor;field_typereflection (0616) unchanged. - Stream carved (earlier). Selected as the first async-first foundation: gates
channel result types (
RecvResult($T)) andrace's synthesized union, fully validated, self-contained, testable in isolation (06xxcomptime).