astgen: blockExpr rvalue, local_ptr rvalue, array_mult
- blockExpr: call rvalue on void result for unlabeled blocks, matching
upstream AstGen.zig:2431. This was causing a missing STORE_NODE when
empty blocks like {} were used as struct field values with pointer RL.
- identifierExpr: call rvalueNoCoercePreRef after LOAD in local_ptr case,
matching upstream AstGen.zig:8453-8454.
- Implement AST_NODE_ARRAY_MULT (** operator) with ArrayMul payload,
matching upstream AstGen.zig:774-785.
- Enable parser_test.zig and astgen_test.zig corpus tests.
- Enable combined corpus test (all 5 files pass).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2480,6 +2480,7 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node);
|
|||||||
#define COMPTIME_REASON_ADDRSPACE 51
|
#define COMPTIME_REASON_ADDRSPACE 51
|
||||||
#define COMPTIME_REASON_FIELD_NAME 42
|
#define COMPTIME_REASON_FIELD_NAME 42
|
||||||
#define COMPTIME_REASON_COMPTIME_KEYWORD 53
|
#define COMPTIME_REASON_COMPTIME_KEYWORD 53
|
||||||
|
#define COMPTIME_REASON_ARRAY_MUL_FACTOR 22
|
||||||
#define COMPTIME_REASON_SWITCH_ITEM 56
|
#define COMPTIME_REASON_SWITCH_ITEM 56
|
||||||
#define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57
|
#define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57
|
||||||
|
|
||||||
@@ -3100,7 +3101,8 @@ static uint32_t identifierExpr(
|
|||||||
if (lp->name == name_str) {
|
if (lp->name == name_str) {
|
||||||
if (RL_IS_REF(rl))
|
if (RL_IS_REF(rl))
|
||||||
return lp->ptr;
|
return lp->ptr;
|
||||||
return addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node);
|
uint32_t val = addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node);
|
||||||
|
return rvalueNoCoercePreRef(gz, rl, val, node);
|
||||||
}
|
}
|
||||||
s = lp->parent;
|
s = lp->parent;
|
||||||
continue;
|
continue;
|
||||||
@@ -4590,6 +4592,20 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
|||||||
case AST_NODE_ARRAY_CAT:
|
case AST_NODE_ARRAY_CAT:
|
||||||
return rvalue(
|
return rvalue(
|
||||||
gz, rl, simpleBinOp(gz, scope, node, ZIR_INST_ARRAY_CAT), node);
|
gz, rl, simpleBinOp(gz, scope, node, ZIR_INST_ARRAY_CAT), node);
|
||||||
|
// array_mult (AstGen.zig:774-785): ** binary operator.
|
||||||
|
case AST_NODE_ARRAY_MULT: {
|
||||||
|
uint32_t res_ty = rlResultType(gz, rl, node);
|
||||||
|
uint32_t lhs = exprRl(gz, scope, RL_NONE_VAL, nd.lhs);
|
||||||
|
ResultLoc rhs_rl = { .tag = RL_COERCED_TY,
|
||||||
|
.data = ZIR_REF_USIZE_TYPE,
|
||||||
|
.src_node = 0,
|
||||||
|
.ctx = 0 };
|
||||||
|
uint32_t rhs = comptimeExpr(
|
||||||
|
gz, scope, rhs_rl, nd.rhs, COMPTIME_REASON_ARRAY_MUL_FACTOR);
|
||||||
|
uint32_t result = addPlNodeTriple(gz, ZIR_INST_ARRAY_MUL, node,
|
||||||
|
res_ty != 0 ? res_ty : ZIR_REF_NONE, lhs, rhs);
|
||||||
|
return rvalue(gz, rl, result, node);
|
||||||
|
}
|
||||||
// grouped_expression (AstGen.zig:1100): passthrough.
|
// grouped_expression (AstGen.zig:1100): passthrough.
|
||||||
case AST_NODE_GROUPED_EXPRESSION:
|
case AST_NODE_GROUPED_EXPRESSION:
|
||||||
return exprRl(gz, scope, rl, ag->tree->nodes.datas[node].lhs);
|
return exprRl(gz, scope, rl, ag->tree->nodes.datas[node].lhs);
|
||||||
@@ -5386,7 +5402,6 @@ static uint32_t expr(GenZir* gz, Scope* scope, uint32_t node) {
|
|||||||
|
|
||||||
static uint32_t blockExprExpr(
|
static uint32_t blockExprExpr(
|
||||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||||
(void)rl;
|
|
||||||
AstGenCtx* ag = gz->astgen;
|
AstGenCtx* ag = gz->astgen;
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
AstNodeTag tag = tree->nodes.tags[node];
|
AstNodeTag tag = tree->nodes.tags[node];
|
||||||
@@ -5459,7 +5474,8 @@ static uint32_t blockExprExpr(
|
|||||||
GenZir sub_gz = makeSubBlock(gz, scope);
|
GenZir sub_gz = makeSubBlock(gz, scope);
|
||||||
blockExprStmts(&sub_gz, &sub_gz.base, statements, stmt_count);
|
blockExprStmts(&sub_gz, &sub_gz.base, statements, stmt_count);
|
||||||
}
|
}
|
||||||
return ZIR_REF_VOID_VALUE;
|
// AstGen.zig:2431
|
||||||
|
return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Labeled block (AstGen.zig:2466-2536).
|
// Labeled block (AstGen.zig:2466-2536).
|
||||||
|
|||||||
@@ -256,6 +256,32 @@ fn expectEqualZir(gpa: Allocator, ref: Zir, got: c.Zir) !void {
|
|||||||
@as(i32, @intCast(got_counts[t])) - @as(i32, @intCast(ref_counts[t])),
|
@as(i32, @intCast(got_counts[t])) - @as(i32, @intCast(ref_counts[t])),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Find first tag divergence.
|
||||||
|
const min_len = @min(ref_len, got.inst_len);
|
||||||
|
for (0..min_len) |i| {
|
||||||
|
const ref_tag: u8 = @intFromEnum(ref_tags[i]);
|
||||||
|
const got_tag: u8 = @intCast(got.inst_tags[i]);
|
||||||
|
if (ref_tag != got_tag) {
|
||||||
|
std.debug.print("first divergence at [{d}]: ref_tag={d} got_tag={d}\n", .{ i, ref_tag, got_tag });
|
||||||
|
// Show ref instruction data for this position.
|
||||||
|
const rd = ref_datas[i];
|
||||||
|
std.debug.print(" ref pl_node: src_node={d} payload={d}\n", .{
|
||||||
|
rd.pl_node.src_node, rd.pl_node.payload_index,
|
||||||
|
});
|
||||||
|
// Scan for nearest declaration.
|
||||||
|
var j: usize = i;
|
||||||
|
while (j > 0) {
|
||||||
|
j -= 1;
|
||||||
|
if (ref_tags[j] == .declaration) {
|
||||||
|
std.debug.print(" nearest decl at [{d}]: src_node={d}\n", .{
|
||||||
|
j, ref_datas[j].declaration.src_node,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return error.TestExpectedEqual;
|
return error.TestExpectedEqual;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,9 +843,6 @@ test "astgen: corpus tokenizer_test.zig" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "astgen: corpus parser_test.zig" {
|
test "astgen: corpus parser_test.zig" {
|
||||||
// TODO: 10+ extra data mismatches (ref=48 got=32, bit 4 = propagate_error_trace)
|
|
||||||
// in call instruction flags — ctx propagation differs from upstream.
|
|
||||||
if (true) return error.SkipZigTest;
|
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
try corpusCheck(gpa, @embedFile("parser_test.zig"));
|
try corpusCheck(gpa, @embedFile("parser_test.zig"));
|
||||||
}
|
}
|
||||||
@@ -857,7 +880,7 @@ test "astgen: struct init typed" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "astgen: corpus" {
|
test "astgen: corpus" {
|
||||||
if (true) return error.SkipZigTest; // TODO: parser_test.zig fails
|
// All individual corpus tests now pass.
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
|
|
||||||
var any_fail = false;
|
var any_fail = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user