green(reify): declare/define floor — reify is sx; E :: reify(...) comptime-evaluated
First slice of the re-architecture. The compiler gains two comptime
type-construction builtins — declare() (mint an empty/undefined nominal
slot) and define(handle, info) (decode a TypeInfo VALUE + complete the
slot) — executed by the interpreter against a new `mint` TypeTable handle
(setMintTable). reify becomes PLAIN sx in meta.sx:
reify :: (info) -> Type { h := declare(); define(h, info); return h; }
`E :: f(...)` where f is a non-generic Type-returning fn (reify, and later
make_enum) is now comptime-evaluated via evalComptimeTypeNamed: wrap the
call in a throwaway comptime fn, run it through the interp with the mint
table enabled so declare/define mint the type, read back the type_tag, and
rename the anonymous slot to the binding name. The compiler has ZERO reify
knowledge at the decl site — the old `E :: reify` hook is deleted.
examples/0614 (inline reify) now runs on this floor. Full suite green (673).
INTERMEDIATE: reifyType + findReturnReifyCall still serve the type-fn path
(0615/0617) and will be deleted in the next slice (type-fn body
comptime-eval), after which the compiler has no reify code at all.
This commit is contained in:
@@ -384,6 +384,49 @@ pub fn lowerInsertExprValue(self: *Lowering, expr: *const Node) Ref {
|
||||
return last_val;
|
||||
}
|
||||
|
||||
/// Evaluate a Type-returning expression at compile time → its `TypeId`.
|
||||
/// The driver of the REIFY floor: `expr` (e.g. `reify(.enum(...))`, a type-fn
|
||||
/// call) is wrapped in a throwaway comptime fn and run through the interpreter
|
||||
/// with the type-MINT table enabled, so `declare`/`define` builtins reached
|
||||
/// inside it mutate the real type table. The result value is a `.type_tag`.
|
||||
/// When `name` is given, the minted (anonymous) type is renamed to it so
|
||||
/// `type_name` / diagnostics read the binding's name. Returns null (caller
|
||||
/// poisons) if evaluation didn't yield a Type.
|
||||
pub fn evalComptimeTypeNamed(self: *Lowering, expr: *const Node, name: ?[]const u8) ?TypeId {
|
||||
const func_id = self.createComptimeFunction("__ctype", expr, .any);
|
||||
|
||||
var interp = interp_mod.Interpreter.init(self.module, self.alloc);
|
||||
defer interp.deinit();
|
||||
if (self.diagnostics) |d| if (d.import_sources) |sm| interp.setSourceMap(sm);
|
||||
interp.setMintTable(&self.module.types);
|
||||
|
||||
const result = interp.call(func_id, &.{}) catch return null;
|
||||
const tid = result.asTypeId() orelse return null;
|
||||
if (name) |nm| self.renameReifiedType(tid, nm);
|
||||
return tid;
|
||||
}
|
||||
|
||||
/// Rename a freshly-minted (anonymous `__reified_N`) nominal type to its
|
||||
/// binding's name, re-keying `intern_map` so `findByName(name)` resolves it.
|
||||
/// A no-op for a non-nominal / already-named-as-requested type.
|
||||
pub fn renameReifiedType(self: *Lowering, tid: TypeId, name: []const u8) void {
|
||||
const tbl = &self.module.types;
|
||||
const new_name_id = tbl.internString(name);
|
||||
var info = tbl.get(tid);
|
||||
switch (info) {
|
||||
.tagged_union => |*u| {
|
||||
if (u.name == new_name_id) return;
|
||||
u.name = new_name_id;
|
||||
},
|
||||
.@"enum" => |*e| {
|
||||
if (e.name == new_name_id) return;
|
||||
e.name = new_name_id;
|
||||
},
|
||||
else => return,
|
||||
}
|
||||
tbl.replaceKeyedInfo(tid, info);
|
||||
}
|
||||
|
||||
/// Evaluate an expression at compile time, returning its string value.
|
||||
/// Returns null if evaluation fails.
|
||||
pub fn evalComptimeString(self: *Lowering, expr: *const Node) ?[:0]const u8 {
|
||||
|
||||
Reference in New Issue
Block a user