refactor(ir): add ResolveEnv + TypeResolver shell; own primitives + compounds (A2.1)
Architecture phase A2.1 -- behavior-preserving. Introduce src/ir/type_resolver.zig as the canonical AST-type-node -> TypeId resolver (Principle 1), starting with: - ResolveEnv: the explicit resolution-context shape (Principle 2) -- type/pack/ comptime bindings + target_type. Defined now; consumed as A2.2/A2.3 move the cases that need it. - TypeResolver.resolvePrimitive(name): the builtin keyword table, MOVED here from type_bridge.resolveTypePrimitive (now a re-export -> single source; its 7 callers are unaffected; no import cycle). - TypeResolver.resolveCompound(node, inner): the structural compound types *T / [*]T / []T / ?T / [N]T. Element types recurse via inner.resolveInner (an anytype callback) so generic structs / bindings in element position keep their full stateful resolution. Lowering.resolveTypeWithBindings duplicated the 5 simple compounds across its bindings and no-bindings blocks (10 arms). Both are replaced with a single self.typeResolver().resolveCompound(node, self) delegation; adds Lowering.resolveInner (recursion hook) + typeResolver() (by-value view). Deliberately deferred: tuples, closures, and function types stay on the existing pack-aware helpers (resolveClosure/Tuple/FunctionTypeWithBindings); A2.3 owns their pack-projection logic. Tests: src/ir/type_resolver.test.zig (resolvePrimitive keyword/null cases; resolveCompound for all 5 + null for non-compound; ResolveEnv defaults), wired into the ir.zig barrel. No new fallback path; no duplicate truth. Gate green: zig build, zig build test, bash tests/run_examples.sh (350 passed, 0 failed). lower.zig 19393 -> 19372.
This commit is contained in:
@@ -19,6 +19,7 @@ const TemplateParam = program_index_mod.TemplateParam;
|
||||
const ProtocolDeclInfo = program_index_mod.ProtocolDeclInfo;
|
||||
const ProtocolMethodInfo = program_index_mod.ProtocolMethodInfo;
|
||||
const ModuleConstInfo = program_index_mod.ModuleConstInfo;
|
||||
const TypeResolver = @import("type_resolver.zig").TypeResolver;
|
||||
|
||||
const TypeId = types.TypeId;
|
||||
const StringId = types.StringId;
|
||||
@@ -12730,6 +12731,24 @@ pub const Lowering = struct {
|
||||
return self.resolveTypeWithBindings(type_ann);
|
||||
}
|
||||
|
||||
/// Construct a `TypeResolver` view over the current lowering state (borrows
|
||||
/// only; cheap by-value, reflects current `diagnostics` / `program_index`).
|
||||
fn typeResolver(self: *Lowering) TypeResolver {
|
||||
return .{
|
||||
.alloc = self.alloc,
|
||||
.types = &self.module.types,
|
||||
.diagnostics = self.diagnostics,
|
||||
.index = &self.program_index,
|
||||
};
|
||||
}
|
||||
|
||||
/// Inner-type recursion hook for `TypeResolver.resolveCompound`: resolves a
|
||||
/// child type node through the full stateful resolver, so generic structs /
|
||||
/// bindings / aliases in element position keep their resolution.
|
||||
pub fn resolveInner(self: *Lowering, node: *const Node) TypeId {
|
||||
return self.resolveTypeWithBindings(node);
|
||||
}
|
||||
|
||||
/// Resolve a type node, checking type_bindings first for generic type params.
|
||||
fn resolveTypeWithBindings(self: *Lowering, node: *const Node) TypeId {
|
||||
// Pack-index in a type position: `$<pack>[<lit>]` resolves to the
|
||||
@@ -12774,6 +12793,11 @@ pub const Lowering = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Structural compound types (`*T`, `[*]T`, `[]T`, `?T`, `[N]T`) are
|
||||
// owned by TypeResolver (A2.1). Element types recurse through the full
|
||||
// stateful resolver (`resolveInner` → here) so generic structs /
|
||||
// bindings in element position keep their resolution.
|
||||
if (self.typeResolver().resolveCompound(node, self)) |t| return t;
|
||||
if (self.type_bindings) |tb| {
|
||||
switch (node.data) {
|
||||
.type_expr => |te| {
|
||||
@@ -12786,31 +12810,6 @@ pub const Lowering = struct {
|
||||
.identifier => |id| {
|
||||
if (tb.get(id.name)) |ty| return ty;
|
||||
},
|
||||
// Compound types: resolve inner types with bindings
|
||||
.slice_type_expr => |st| {
|
||||
const elem = self.resolveTypeWithBindings(st.element_type);
|
||||
return self.module.types.sliceOf(elem);
|
||||
},
|
||||
.pointer_type_expr => |pt| {
|
||||
const pointee = self.resolveTypeWithBindings(pt.pointee_type);
|
||||
return self.module.types.ptrTo(pointee);
|
||||
},
|
||||
.many_pointer_type_expr => |mp| {
|
||||
const elem = self.resolveTypeWithBindings(mp.element_type);
|
||||
return self.module.types.manyPtrTo(elem);
|
||||
},
|
||||
.optional_type_expr => |ot| {
|
||||
const child = self.resolveTypeWithBindings(ot.inner_type);
|
||||
return self.module.types.optionalOf(child);
|
||||
},
|
||||
.array_type_expr => |at| {
|
||||
const elem = self.resolveTypeWithBindings(at.element_type);
|
||||
const len: u32 = blk: {
|
||||
if (at.length.data == .int_literal) break :blk @intCast(at.length.data.int_literal.value);
|
||||
break :blk 0;
|
||||
};
|
||||
return self.module.types.arrayOf(elem, len);
|
||||
},
|
||||
.parameterized_type_expr => |pt| {
|
||||
return self.resolveParameterizedWithBindings(&pt);
|
||||
},
|
||||
@@ -12834,30 +12833,10 @@ pub const Lowering = struct {
|
||||
if (node.data == .call) {
|
||||
return self.resolveTypeCallWithBindings(&node.data.call);
|
||||
}
|
||||
// Handle compound types that may contain generic structs (e.g., *List(ViewChild))
|
||||
// These need the lowerer's resolveType to properly instantiate generics.
|
||||
// Pointers / slices / many-pointers / optionals / arrays are owned by
|
||||
// TypeResolver (handled above). The pack-aware tuple / closure /
|
||||
// function shapes resolve here — A2.3 owns their pack projection logic.
|
||||
switch (node.data) {
|
||||
.pointer_type_expr => |pt| {
|
||||
const pointee = self.resolveTypeWithBindings(pt.pointee_type);
|
||||
return self.module.types.ptrTo(pointee);
|
||||
},
|
||||
.slice_type_expr => |st| {
|
||||
const elem = self.resolveTypeWithBindings(st.element_type);
|
||||
return self.module.types.sliceOf(elem);
|
||||
},
|
||||
.many_pointer_type_expr => |mp| {
|
||||
const elem = self.resolveTypeWithBindings(mp.element_type);
|
||||
return self.module.types.manyPtrTo(elem);
|
||||
},
|
||||
.optional_type_expr => |ot| {
|
||||
const child = self.resolveTypeWithBindings(ot.inner_type);
|
||||
return self.module.types.optionalOf(child);
|
||||
},
|
||||
.array_type_expr => |at| {
|
||||
const elem = self.resolveTypeWithBindings(at.element_type);
|
||||
const len: u32 = if (at.length.data == .int_literal) @intCast(at.length.data.int_literal.value) else 0;
|
||||
return self.module.types.arrayOf(elem, len);
|
||||
},
|
||||
.closure_type_expr => |ct| {
|
||||
return self.resolveClosureTypeWithBindings(&ct);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user