comptime VM: switch_br + type_name (pure reflection ops); guard unresolved type reads
Port two pure (side-effect-free) comptime ops toward the no-fallback gate:
- switch_br: multi-way branch on an i64 discriminant (enum/error tag, or a
.type_value whose word is its TypeId index) — mirrors the legacy
asInt-orelse-asTypeId switch.
- type_name(x): a Type value (.type_value word) or Any box ({tag,value}; tag ==
type_value means the boxed Type's id is in the value slot) -> table.typeName.
Guards an .unresolved TypeId (bail, not "<unresolved>") to surface a bad
slice/pack read instead of emitting garbage (see issue 0143).
These are correct in isolation (0520-0524 run green under strict mode) but flip
nothing yet because their examples also print via `out`, which can only land at
the end state: under the legacy fallback a print-then-bail double-prints (no
re-run rewind), so `out` is deferred until the fallback is removed. 699/0 both
default gates.
This commit is contained in:
@@ -859,6 +859,17 @@ pub const Vm = struct {
|
||||
if (frame.get(b.cond.index()) != 0) return .{ .jump = .{ .target = b.then_target, .args = b.then_args } };
|
||||
return .{ .jump = .{ .target = b.else_target, .args = b.else_args } };
|
||||
},
|
||||
// Multi-way branch on an integer discriminant: an enum/error tag, or a
|
||||
// type-category match where the operand is a `.type_value` whose word IS
|
||||
// its `TypeId` index (so the same i64 compare covers both, mirroring the
|
||||
// legacy `switch_br`'s `asInt orelse asTypeId().index()`).
|
||||
.switch_br => |sb| {
|
||||
const operand: i64 = @bitCast(frame.get(sb.operand.index()));
|
||||
for (sb.cases) |case| {
|
||||
if (operand == case.value) return .{ .jump = .{ .target = case.target, .args = case.args } };
|
||||
}
|
||||
return .{ .jump = .{ .target = sb.default, .args = sb.default_args } };
|
||||
},
|
||||
.ret => |u| return .{ .ret = frame.get(u.operand.index()) },
|
||||
.ret_void => return .ret_void,
|
||||
|
||||
@@ -1470,6 +1481,33 @@ pub const Vm = struct {
|
||||
return self.failMsg("comptime define: TypeInfo payload is not a single-slice info struct");
|
||||
return try self.defineFromInfo(table, handle, @intCast(tag), payload_ty, info_addr + tag_size);
|
||||
},
|
||||
// type_name(x) → the type's name as a string. The arg is a Type value
|
||||
// (`.type_value` word = a TypeId) or an Any box (`{tag@0, value@8}` whose
|
||||
// tag IS the boxed value's type, unless tag == type_value: then the boxed
|
||||
// Type's id is in the value slot). Mirrors the legacy `reflectTypeId`.
|
||||
.type_name => {
|
||||
const table = try self.requireTable();
|
||||
if (bi.args.len < 1) return self.failMsg("comptime type_name: missing argument");
|
||||
const aty = try self.refTy(ref_types, bi.args[0]);
|
||||
const w = frame.get(bi.args[0].index());
|
||||
const tid: TypeId = blk: {
|
||||
if (aty == .type_value) break :blk TypeId.fromIndex(@intCast(w));
|
||||
if (aty == .any) {
|
||||
const tag = try self.machine.readWord(w, 8);
|
||||
if (tag == @as(u64, TypeId.type_value.index()))
|
||||
break :blk TypeId.fromIndex(@intCast(try self.machine.readWord(w + 8, 8)));
|
||||
break :blk TypeId.fromIndex(@intCast(tag));
|
||||
}
|
||||
return self.failMsg("comptime type_name: arg is not a Type value or an Any box");
|
||||
};
|
||||
// An `.unresolved` TypeId means the read produced a bad type (e.g. a
|
||||
// mis-strided `[]Type` slice over an Any-boxed pack — see issue 0143):
|
||||
// the VM can't faithfully name it, so BAIL rather than emit
|
||||
// "<unresolved>". (The legacy reads Values, not bytes, so it gets the
|
||||
// real type; the fallback then handles this correctly.)
|
||||
if (tid == .unresolved) return self.failMsg("comptime type_name: unresolved type (bad slice/pack read — see issue 0143)");
|
||||
return try self.makeStringValue(table, table.typeName(tid));
|
||||
},
|
||||
// type_info($T) → reflect a type INTO a TypeInfo VALUE (the inverse of
|
||||
// define's decode). The arg folded to a `const_type` (a `.type_value`
|
||||
// word = the source TypeId); build the value in flat memory.
|
||||
|
||||
Reference in New Issue
Block a user