comptime VM: flip Type to .type_value; migrate the .any refs that mean a Type value

type_resolver "Type" -> .type_value; const_type result + emitConstType now a
bare 8-byte i64 handle (not a 16-byte Any box). Migrated every .any ref meaning
"a Type value", leaving real boxed-Any refs:

- "Any holds a Type" meta-marker tag .any -> .type_value at all 4 consumers
  (reflectArgTypeId, reflectTypeId, the comptime type_tag-as-struct path,
  resolveTypeCategoryTags "type").
- reflection-builtin return types (type_of/declare/define) -> .type_value;
  runtime type_of(any) reads the tag as a .type_value (no re-box).
- expr_typer: a bare type-name expr is .type_value (backtick is_raw exempt).
- reflectionArgIsType accepts .type_value OR .any (a reflection arg can be a
  bare Type or a boxed Any).
- comptime switch_br accepts a .type_tag discriminant (type-category match).
- a bare function name in a Type slot -> const_type(its function type), not a
  func-ref (fixes a JIT crash); old string-box kept only for genuine Any params.
- field-not-found diagnostic + formatTypeName render .type_value as "Type".

Fixed 3 unit tests asserting the old .any behavior. 697/0 both gates (gate ON
bails cleanly to legacy since the VM doesn't model Type values yet) + 494 unit
tests. 24 snapshots regenerated (22 .ir const_type shape; 2 .stderr Any->Type).
This commit is contained in:
agra
2026-06-18 13:54:56 +03:00
parent 6844fb90e7
commit 94f60c51c0
37 changed files with 48941 additions and 48226 deletions

View File

@@ -130,23 +130,15 @@ pub const Ops = struct {
}
pub fn emitConstType(self: Ops, tid: TypeId) void {
// Type values are Any-shaped pairs:
// { tag = .any.index() (the meta-marker),
// value = tid.index() }
// Lets storage in Any slots, struct fields,
// `Type`-typed vars, and slice elements all round-
// trip through the standard Any infrastructure.
// `case type:` in `any_to_string` matches on
// tag == `.any.index()`. Runtime `type_name(t)`
// extracts the value field and indexes into the
// type-name lookup table.
const any_ty = self.e.getAnyStructType();
const tag = c.LLVMConstInt(self.e.cached_i64, TypeId.any.index(), 0);
// A Type value is an 8-byte handle: a bare i64 carrying `tid.index()`
// (the `.type_value` builtin TypeId), distinct from the 16-byte boxed
// `.any`. Flowing a Type into an `Any` slot boxes it via the standard
// box-any coercion (`{ tag = .any.index(), value = tid }`); `case type:`
// in `any_to_string` then matches tag == `.any.index()`, and runtime
// `type_name(t)` reads the TypeId through `reflectArgTypeId` (`.bare`
// when the arg is `.type_value`, `.boxed` when it is an Any).
const val = c.LLVMConstInt(self.e.cached_i64, tid.index(), 0);
var result = c.LLVMGetUndef(any_ty);
result = c.LLVMBuildInsertValue(self.e.builder, result, tag, 0, "ct.tag");
result = c.LLVMBuildInsertValue(self.e.builder, result, val, 1, "ct.val");
self.e.mapRef(result);
self.e.mapRef(val);
}
// ── Arithmetic ─────────────────────────────────────────
@@ -1341,11 +1333,11 @@ pub const Ops = struct {
/// Resolve the `TypeId` (as a runtime `i64`) that a dynamic
/// `type_name` / `type_is_unsigned` must operate on. A reflection
/// builtin reads an `Any`'s runtime TYPE-TAG, never its raw payload:
/// - `.bare`: a `Type` value already lowered to a bare i64 `TypeId`
/// index (an unboxed direct call site) → the value itself.
/// - `.bare`: a `Type` value (a `.type_value` arg) — a bare i64 `TypeId`
/// index (e.g. `type_of(x)` directly) → the value itself.
/// - `.boxed`: an `Any` aggregate `{ tag, value }`. When the tag is
/// `.any`, the box carries a *Type value* (the `{ .any, tid }` shape
/// `const_type` / `type_of` produce) → the TypeId is the payload.
/// `.type_value`, the box carries a *Type value* (a `Type` boxed into an
/// `Any`, `{ .type_value, tid }`) → the TypeId is the payload.
/// Otherwise the box carries a *runtime value* whose type IS the tag
/// → use the tag as the TypeId. This is what makes `type_name(av)`
/// for `av : Any = 6` report `i64` (the held value's type), while
@@ -1360,8 +1352,8 @@ pub const Ops = struct {
.boxed => blk: {
const tag = c.LLVMBuildExtractValue(self.e.builder, arg_val, 0, "refl.tag");
const payload = c.LLVMBuildExtractValue(self.e.builder, arg_val, 1, "refl.val");
const any_tag = c.LLVMConstInt(self.e.cached_i64, @intCast(TypeId.any.index()), 0);
const holds_type = c.LLVMBuildICmp(self.e.builder, c.LLVMIntEQ, tag, any_tag, "refl.istype");
const type_tag = c.LLVMConstInt(self.e.cached_i64, @intCast(TypeId.type_value.index()), 0);
const holds_type = c.LLVMBuildICmp(self.e.builder, c.LLVMIntEQ, tag, type_tag, "refl.istype");
break :blk c.LLVMBuildSelect(self.e.builder, holds_type, payload, tag, "refl.tid");
},
};