fix(ir): route every comptime-int through the shared evaluator (0083)
Attempts 1–4 fixed the array-dimension paths but the same length-0 fabrication class survived on every other site that resolves a compile-time integer. Unify them all on the single shared `program_index.evalConstIntExpr` so they cannot diverge: - All three Vector lane resolvers (resolveTypeCallWithBindings, resolveParameterizedWithBindings, resolveArrayLiteralType) and both generic value-param binders (instantiateGenericStruct, instantiateTypeFunction) hand-rolled an `else => 0` switch. A module-const lane `Vector(N, f32)` fabricated a 0-lane `<0 x float>` (LLVM "huge alignment" abort); a value-param `Vec(N, f32)` fabricated a 0 binding / wrong mangled name. They now fold through the shared evaluator and emit a clean diagnostic + `.unresolved` on a non-const operand (resolveVectorLane / resolveValueParamArg) — never 0. - evalComptimeInt (inline-for bounds) delegated to the shared evaluator, so `inline for 0..M` / `0..(M+1)` fold like array dims. The `<pack>.len` leaf moved into the shared folder via a new `ctx.lookupPackLen`. - The unknown-type semantic checker no longer walks a value-param position (`Vector(N, …)` / `Vec(N, …)`) as a type name (was reporting "unknown type 'N'"). - The parameterized-type-arg parser and the function-body lookahead (hasFnBodyAfterArrow) accept a const-EXPRESSION in a value position, so `Vector(M + 1, f32)` and `[M + 1]T` parse as a return type too (the latter a pre-existing array-dim sibling that the same heuristic broke). Regressions: examples/1501 (named-const + const-expr lane, direct + alias, 3/4-lane reads), 1502 (runtime lane clean-halts, exit 1, no LLVM crash), 0207 (Vec(N)/Vec(M+1) == Vec(3) instantiation), 0610 (inline-for const bounds). Shared-evaluator unit test extended with the pack-len arm. zig build && zig build test && bash tests/run_examples.sh: 395 passed, 0 failed.
This commit is contained in:
@@ -106,6 +106,11 @@ const DimCtx = struct {
|
||||
if (std.mem.eql(u8, name, "N")) return 6;
|
||||
return null;
|
||||
}
|
||||
// `xs` stands in for a pack of arity 3; every other name has no pack length.
|
||||
pub fn lookupPackLen(_: DimCtx, name: []const u8) ?i64 {
|
||||
if (std.mem.eql(u8, name, "xs")) return 3;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
fn nLit(v: i64) ast.Node {
|
||||
@@ -120,6 +125,9 @@ fn nBin(op: ast.BinaryOp.Op, l: *ast.Node, r: *ast.Node) ast.Node {
|
||||
fn nNeg(operand: *ast.Node) ast.Node {
|
||||
return .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .unary_op = .{ .op = .negate, .operand = operand } } };
|
||||
}
|
||||
fn nField(obj: *ast.Node, field: []const u8) ast.Node {
|
||||
return .{ .span = .{ .start = 0, .end = 0 }, .data = .{ .field_access = .{ .object = obj, .field = field } } };
|
||||
}
|
||||
|
||||
test "evalConstIntExpr folds constant-expression array dimensions, halts on non-const" {
|
||||
const eval = pi.evalConstIntExpr;
|
||||
@@ -157,6 +165,19 @@ test "evalConstIntExpr folds constant-expression array dimensions, halts on non-
|
||||
var neg = nNeg(&m);
|
||||
try std.testing.expectEqual(@as(?i64, -4), eval(&neg, ctx));
|
||||
|
||||
// `<pack>.len` leaf resolves via `ctx.lookupPackLen` and folds in an
|
||||
// expression (`xs.len` → 3, `xs.len - 1` → 2). A `.len` on a non-pack name
|
||||
// and a non-`len` field are not compile-time integer leaves → null.
|
||||
var xs = nIdent("xs");
|
||||
var xslen = nField(&xs, "len");
|
||||
var xslen_m1 = nBin(.sub, &xslen, &one);
|
||||
try std.testing.expectEqual(@as(?i64, 3), eval(&xslen, ctx));
|
||||
try std.testing.expectEqual(@as(?i64, 2), eval(&xslen_m1, ctx));
|
||||
var zlen = nField(&z, "len");
|
||||
var xscap = nField(&xs, "cap");
|
||||
try std.testing.expect(eval(&zlen, ctx) == null);
|
||||
try std.testing.expect(eval(&xscap, ctx) == null);
|
||||
|
||||
// Genuinely non-const operand, division by zero, a non-arithmetic operator,
|
||||
// and overflow all yield null → the caller's clean compile-halt (no panic,
|
||||
// no fabricated length).
|
||||
|
||||
Reference in New Issue
Block a user