refactor(ir): extract CallResolver for call result typing (A3.2 relocation)
Move call-result-type discovery out of Lowering into a new src/ir/calls.zig (CallResolver): the A3.1 Lowering.inferCallType body moves verbatim into CallResolver.resultType. inferExprType's `.call` arm now delegates via callResolver(); Lowering.inferCallType is gone. CallResolver is a *Lowering facade (Principle 5, like ExprTyper/PackResolver): call typing reads live lexical-scope / target-type state and the function / foreign-class / protocol resolver helpers, so it borrows *Lowering. Transform was `self.` -> `self.l.` plus the file-local static `resolveBuiltin(` -> `Lowering.resolveBuiltin(`. Widened to pub only what the facade actually consumes: resolveTypeArg, inferGenericReturnType, resolveFuncByName, getProtocolInfo, resolveForeignMethodReturnType, the static resolveBuiltin, and Scope.lookupFn. resolveTypeArg widening is genuinely required here — the `cast` builtin's result type calls it. calls.test.zig adds focused tests (builtin/reflection classification, unknown callee -> unresolved) for the scope-free paths. Barrel-wired in ir.zig. This is the relocation half of PLAN-ARCH A3.2; call LOWERING (lowerCall) still owns its own dispatch, and the CallPlan convergence (one plan shared by typing and lowering, deleting the duplicated qualified/bare/lazy logic) remains. Behavior-preserving. Gate: zig build, zig build test (incl. new CallResolver tests), bash tests/run_examples.sh -> 356/0. lower.zig 18598 -> 18413.
This commit is contained in:
46
src/ir/calls.test.zig
Normal file
46
src/ir/calls.test.zig
Normal file
@@ -0,0 +1,46 @@
|
||||
// Tests for calls.zig — focused on the call-result-typing paths CallResolver
|
||||
// owns that need no lexical scope / fn registration: builtin and reflection
|
||||
// builtin classification, and the unresolved fallthrough. Reached via the
|
||||
// public `Lowering.inferExprType` delegation.
|
||||
|
||||
const std = @import("std");
|
||||
const ast = @import("../ast.zig");
|
||||
const Node = ast.Node;
|
||||
|
||||
const ir_mod = @import("ir.zig");
|
||||
const TypeId = ir_mod.TypeId;
|
||||
const Lowering = ir_mod.Lowering;
|
||||
|
||||
fn node(data: ast.Node.Data) Node {
|
||||
return .{ .span = .{ .start = 0, .end = 0 }, .data = data };
|
||||
}
|
||||
|
||||
test "calls: builtin and reflection result types, unknown fallthrough" {
|
||||
const alloc = std.testing.allocator;
|
||||
var module = ir_mod.Module.init(alloc);
|
||||
defer module.deinit();
|
||||
var l = Lowering.init(&module);
|
||||
|
||||
// One shared throwaway argument — the classified builtins below type by
|
||||
// callee name and don't inspect it.
|
||||
var arg = node(.{ .int_literal = .{ .value = 1 } });
|
||||
var args = [_]*Node{&arg};
|
||||
|
||||
const cases = [_]struct { name: []const u8, want: TypeId }{
|
||||
.{ .name = "size_of", .want = .s64 },
|
||||
.{ .name = "align_of", .want = .s64 },
|
||||
.{ .name = "type_name", .want = .string },
|
||||
.{ .name = "field_count", .want = .s64 },
|
||||
.{ .name = "is_flags", .want = .bool },
|
||||
.{ .name = "type_of", .want = .any },
|
||||
// Unknown bare callee with no builtin / declared fn / scope binding
|
||||
// types as unresolved, not a fabricated guess.
|
||||
.{ .name = "definitely_not_a_fn", .want = .unresolved },
|
||||
};
|
||||
|
||||
for (cases) |tc| {
|
||||
var callee = node(.{ .identifier = .{ .name = tc.name } });
|
||||
var call = node(.{ .call = .{ .callee = &callee, .args = &args } });
|
||||
try std.testing.expectEqual(tc.want, l.inferExprType(&call));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user