feat(metatype): implement type_info($T) reflection (enum round-trip)

type_info reflects an enum / tagged-union INTO a TypeInfo value — the
inverse of define's decode — so define(declare(n), type_info(T)) mints
a byte-identical copy with NO literal variant list.

- inst.zig: new BuiltinId.type_info (comptime-only, like declare/define).
- lower/call.zig: replace the 'not yet implemented' bail. Resolve $T at
  lower time, reject non-enum/non-tagged-union loudly with a good span,
  emit callBuiltin(.type_info, [const_type], TypeInfo).
- interp.zig: reflectTypeInfo builds the exact nested-aggregate Value
  defineEnum decodes — variant {name,payload}, slice {data,len}, EnumInfo
  {variants}, TypeInfo {tag0, EnumInfo}. tagged_union reflects field.ty
  (tagless already void); payloadless `enum` reflects void per variant.
- emit: unchanged — type_info is always comptime-evaluated, the existing
  comptime-only else arm (shared with declare/define) never fires.

0619 turns green: a source enum (circle:f64 / rect:i64 / empty) reflected
and reconstructed, constructs and matches like the original.
This commit is contained in:
agra
2026-06-16 22:52:53 +03:00
parent 3805a051cc
commit 1ffda415c2
6 changed files with 92 additions and 26 deletions

View File

@@ -461,6 +461,12 @@ pub const BuiltinId = enum(u16) {
// it) and complete the slot.
declare,
define,
// The comptime reflection INVERSE of `define`: read a type's variants
// (name + payload type) out of the type table and CONSTRUCT the same
// `.enum(EnumInfo{ variants })` value `define` decodes. Comptime-only
// (the interp builds the Value aggregate); emit bails (Type is
// comptime-only). `type_info($T)` round-trips through `define`.
type_info,
};
pub const CompilerCall = struct {