comptime VM: Phase 3 — field-level reflection readers
Three more read-only compiler-API readers on the TypeId-handle shape, each backed
by a new TypeTable query that both the legacy handler and the VM call (no drift):
type_nominal_name(t: TypeId) -> StringId (nominalName; loud-bail for unnamed types)
type_field_name(t: TypeId, idx: i64) -> StringId (memberName)
type_field_type(t: TypeId, idx: i64) -> TypeId (memberType)
All loud-bail on out-of-range idx / no-member — no silent default. First multi-arg
compiler fns (callCompilerFn now reads arg 1 = idx); added Vm.argHandle/argTypeId
range-checked arg readers and moved find_type/type_field_count onto them. Names use
the type_* family to avoid colliding with the std metatype builtins (field_name /
type_name in core.sx); the new TypeTable.nominalName is distinct from the existing
typeName(id) display-string renderer.
Example 0629 reflects Pair { lo: Point; hi: Point } — each field name + the nominal
name of a field's type, #run-folded, VM-HANDLED natively. VM unit test added.
Parity 690/690 (gate OFF and -Dcomptime-flat).
This commit is contained in:
@@ -49,6 +49,9 @@ pub const bound_fns = [_]BoundFn{
|
||||
.{ .sx_name = "text_of", .handler = handleTextOf },
|
||||
.{ .sx_name = "find_type", .handler = handleFindType },
|
||||
.{ .sx_name = "type_field_count", .handler = handleTypeFieldCount },
|
||||
.{ .sx_name = "type_nominal_name", .handler = handleTypeNominalName },
|
||||
.{ .sx_name = "type_field_name", .handler = handleTypeFieldName },
|
||||
.{ .sx_name = "type_field_type", .handler = handleTypeFieldType },
|
||||
};
|
||||
|
||||
/// Look up a compiler function by its sx name. Returns null when the name is not
|
||||
@@ -111,3 +114,40 @@ fn handleTypeFieldCount(interp: *Interpreter, args: []const Value) InterpError!V
|
||||
const count = interp.module.types.memberCount(tid) orelse return error.TypeError;
|
||||
return Value{ .int = count };
|
||||
}
|
||||
|
||||
/// Read an integer `Value` arg as a `u32` handle (StringId / TypeId). Errors on a
|
||||
/// non-int or out-of-u32-range value — never a silent clamp.
|
||||
fn handleArg(args: []const Value, i: usize) InterpError!u32 {
|
||||
if (args[i] != .int) return error.TypeError;
|
||||
if (args[i].int < 0 or args[i].int > std.math.maxInt(u32)) return error.TypeError;
|
||||
return @intCast(args[i].int);
|
||||
}
|
||||
|
||||
/// `type_nominal_name(t: TypeId) -> StringId` — the nominal name handle of a named
|
||||
/// type (struct/enum/union/…). Loud error for an unnamed type (no silent default).
|
||||
fn handleTypeNominalName(interp: *Interpreter, args: []const Value) InterpError!Value {
|
||||
if (args.len != 1) return error.TypeError;
|
||||
const tid: types.TypeId = @enumFromInt(try handleArg(args, 0));
|
||||
const sid = interp.module.types.nominalName(tid) orelse return error.TypeError;
|
||||
return Value{ .int = @intFromEnum(sid) };
|
||||
}
|
||||
|
||||
/// `type_field_name(t: TypeId, idx: i64) -> StringId` — name handle of member `idx`
|
||||
/// (struct/union/tagged-union field, enum variant, named-tuple element). Loud
|
||||
/// error for an out-of-range idx or a type with no named members.
|
||||
fn handleTypeFieldName(interp: *Interpreter, args: []const Value) InterpError!Value {
|
||||
if (args.len != 2 or args[1] != .int) return error.TypeError;
|
||||
const tid: types.TypeId = @enumFromInt(try handleArg(args, 0));
|
||||
const sid = interp.module.types.memberName(tid, args[1].int) orelse return error.TypeError;
|
||||
return Value{ .int = @intFromEnum(sid) };
|
||||
}
|
||||
|
||||
/// `type_field_type(t: TypeId, idx: i64) -> TypeId` — type handle of member `idx`
|
||||
/// (struct/union/tagged-union field, tuple/array/vector element). Loud error for
|
||||
/// an out-of-range idx or a type with no member types (e.g. a payloadless enum).
|
||||
fn handleTypeFieldType(interp: *Interpreter, args: []const Value) InterpError!Value {
|
||||
if (args.len != 2 or args[1] != .int) return error.TypeError;
|
||||
const tid: types.TypeId = @enumFromInt(try handleArg(args, 0));
|
||||
const mty = interp.module.types.memberType(tid, args[1].int) orelse return error.TypeError;
|
||||
return Value{ .int = mty.index() };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user