refactor(ir): add CallPlan + CallResolver.plan(c); resultType delegates (A3.2 convergence step 2)
Introduce CallPlan — the single classification record for a call: kind (14 variants), return_type, a Target union (builtin/func/named/protocol_method/ foreign_method/constructed/none), variant tag, and the prepends_receiver / prepends_ctx / expands_defaults properties the selected dispatch implies. Move call recognition into CallResolver.plan(c) (branch order preserved exactly) and reimplement resultType(c) as plan(c).return_type — the typing consumer converges onto the plan first. lowerCall is untouched; routing it through plan(c) is sub-step 3. 10 plan-object tests assert kind/target/variant + receiver/ctx/default properties for every pinned call form: builtin/reflection, lazy + resolved direct fn (incl. default-arg expansion + __sx_ctx prepend), closure / default-conv vs C-conv fn-pointer, protocol dispatch, struct/UFCS #compiler method, foreign instance vs static, qualified + dot-shorthand enum construction, namespace fn, and the unresolved fallthrough. Widen for the new collaborator only: resolveVariantIndex -> pub (plan resolves the variant tag); Scope/Binding + init/deinit/put -> pub (so unit tests can stand up a lexical scope for closure/fn-ptr callees without a full lowering). zig build, zig build test, and tests/run_examples.sh (357/0) all green; no behavior change.
This commit is contained in:
@@ -48,19 +48,23 @@ fn isExportedEntryName(name: []const u8) bool {
|
||||
|
||||
// ── Scope ───────────────────────────────────────────────────────────────
|
||||
|
||||
const Binding = struct {
|
||||
pub const Binding = struct {
|
||||
ref: Ref,
|
||||
ty: TypeId,
|
||||
is_alloca: bool, // true if ref is a pointer that needs load
|
||||
is_ref_capture: bool = false, // `for xs: (*x)` — `ref` is `*elem`; auto-deref in value positions
|
||||
};
|
||||
|
||||
const Scope = struct {
|
||||
// `init` / `deinit` / `put` are pub so collaborator unit tests (e.g.
|
||||
// calls.test.zig) can stand up a lexical scope and exercise the
|
||||
// scope-dependent call forms (closure / fn-pointer callees) without
|
||||
// driving a full function lowering.
|
||||
pub const Scope = struct {
|
||||
map: std.StringHashMap(Binding),
|
||||
fn_names: std.StringHashMap([]const u8), // bare name → mangled name for local functions
|
||||
parent: ?*Scope,
|
||||
|
||||
fn init(alloc: Allocator, parent: ?*Scope) Scope {
|
||||
pub fn init(alloc: Allocator, parent: ?*Scope) Scope {
|
||||
return .{
|
||||
.map = std.StringHashMap(Binding).init(alloc),
|
||||
.fn_names = std.StringHashMap([]const u8).init(alloc),
|
||||
@@ -68,12 +72,12 @@ const Scope = struct {
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *Scope) void {
|
||||
pub fn deinit(self: *Scope) void {
|
||||
self.map.deinit();
|
||||
self.fn_names.deinit();
|
||||
}
|
||||
|
||||
fn put(self: *Scope, name: []const u8, binding: Binding) void {
|
||||
pub fn put(self: *Scope, name: []const u8, binding: Binding) void {
|
||||
self.map.put(name, binding) catch unreachable;
|
||||
}
|
||||
|
||||
@@ -5617,7 +5621,7 @@ pub const Lowering = struct {
|
||||
}
|
||||
|
||||
/// Resolve a variant name to its tag index within an enum or union type.
|
||||
fn resolveVariantIndex(self: *Lowering, ty: TypeId, variant_name: []const u8) u32 {
|
||||
pub fn resolveVariantIndex(self: *Lowering, ty: TypeId, variant_name: []const u8) u32 {
|
||||
if (ty.isBuiltin()) return 0;
|
||||
const info = self.module.types.get(ty);
|
||||
const name_id = self.module.types.internString(variant_name);
|
||||
|
||||
Reference in New Issue
Block a user