astgen: fix arrayInitExpr sentinel, discard RL, and non-inferred typed init
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
163
astgen.c
163
astgen.c
@@ -3209,7 +3209,11 @@ static uint32_t arrayTypeExpr(GenZir* gz, Scope* scope, uint32_t node) {
|
||||
}
|
||||
|
||||
// --- arrayInitExpr (AstGen.zig:1431) ---
|
||||
// Simplified: handles typed array init with inferred [_] length.
|
||||
// Handles typed array init: [_]T{...}, [_:s]T{...}, and [N]T{...}.
|
||||
|
||||
static uint32_t arrayInitExprTyped(GenZir* gz, Scope* scope, uint32_t node,
|
||||
const uint32_t* elements, uint32_t elem_count, uint32_t ty_inst,
|
||||
uint32_t elem_ty, bool is_ref);
|
||||
|
||||
static uint32_t arrayInitExpr(
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
@@ -3258,56 +3262,134 @@ static uint32_t arrayInitExpr(
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
|
||||
// Check if the type is [_]T (inferred length) (AstGen.zig:1446-1474).
|
||||
if (tree->nodes.tags[type_expr_node] == AST_NODE_ARRAY_TYPE) {
|
||||
// Determine array_ty and elem_ty (AstGen.zig:1443-1482).
|
||||
uint32_t array_ty = ZIR_REF_NONE;
|
||||
uint32_t elem_ty = ZIR_REF_NONE;
|
||||
|
||||
// Check if the type is [_]T or [_:s]T (inferred length)
|
||||
// (AstGen.zig:1446-1474, fullArrayType handles both array_type and
|
||||
// array_type_sentinel).
|
||||
AstNodeTag type_tag = tree->nodes.tags[type_expr_node];
|
||||
if (type_tag == AST_NODE_ARRAY_TYPE
|
||||
|| type_tag == AST_NODE_ARRAY_TYPE_SENTINEL) {
|
||||
AstData type_nd = tree->nodes.datas[type_expr_node];
|
||||
uint32_t elem_count_node = type_nd.lhs;
|
||||
uint32_t elem_type_node = type_nd.rhs;
|
||||
|
||||
// Check if elem_count is `_` identifier.
|
||||
// This intentionally does not support `@"_"` syntax.
|
||||
if (tree->nodes.tags[elem_count_node] == AST_NODE_IDENTIFIER
|
||||
&& isUnderscoreIdent(tree, elem_count_node)) {
|
||||
// Inferred length: addInt(elem_count) (AstGen.zig:1452).
|
||||
uint32_t len_inst = addInt(gz, elem_count);
|
||||
uint32_t elem_type = typeExpr(gz, scope, elem_type_node);
|
||||
uint32_t array_type_inst = addPlNodeBin(
|
||||
gz, ZIR_INST_ARRAY_TYPE, type_expr_node, len_inst, elem_type);
|
||||
|
||||
// arrayInitExprTyped (AstGen.zig:1484-1513, 1598-1642).
|
||||
// Only RL_REF produces array_init_ref; all other RLs use
|
||||
// array_init + rvalue (AstGen.zig:1507-1511).
|
||||
bool is_ref = (rl.tag == RL_REF);
|
||||
uint32_t operands_len = elem_count + 1;
|
||||
ensureExtraCapacity(ag, 1 + operands_len);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = operands_len;
|
||||
ag->extra[ag->extra_len++] = array_type_inst;
|
||||
uint32_t extra_start = ag->extra_len;
|
||||
ag->extra_len += elem_count;
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
// Use elem_type as coercion target for each element.
|
||||
ResultLoc elem_rl = {
|
||||
.tag = RL_COERCED_TY, .data = elem_type, .src_node = 0
|
||||
};
|
||||
uint32_t elem_ref = exprRl(gz, scope, elem_rl, elements[i]);
|
||||
ag->extra[extra_start + i] = elem_ref;
|
||||
if (type_tag == AST_NODE_ARRAY_TYPE) {
|
||||
// [_]T: elem_type_node is rhs (AstGen.zig:1454-1459).
|
||||
uint32_t elem_type_node = type_nd.rhs;
|
||||
elem_ty = typeExpr(gz, scope, elem_type_node);
|
||||
array_ty = addPlNodeBin(gz, ZIR_INST_ARRAY_TYPE,
|
||||
type_expr_node, len_inst, elem_ty);
|
||||
} else {
|
||||
// [_:s]T: sentinel and elem_type from extra data
|
||||
// (AstGen.zig:1460-1473).
|
||||
uint32_t sentinel_node = tree->extra_data.arr[type_nd.rhs];
|
||||
uint32_t elem_type_node
|
||||
= tree->extra_data.arr[type_nd.rhs + 1];
|
||||
elem_ty = typeExpr(gz, scope, elem_type_node);
|
||||
ResultLoc sent_rl = { .tag = RL_TY,
|
||||
.data = elem_ty,
|
||||
.src_node = 0,
|
||||
.ctx = RI_CTX_NONE };
|
||||
uint32_t sentinel = comptimeExpr(gz, scope, sent_rl,
|
||||
sentinel_node, COMPTIME_REASON_ARRAY_SENTINEL);
|
||||
array_ty = addPlNodeTriple(gz, ZIR_INST_ARRAY_TYPE_SENTINEL,
|
||||
type_expr_node, len_inst, elem_ty, sentinel);
|
||||
}
|
||||
ZirInstTag init_tag
|
||||
= is_ref ? ZIR_INST_ARRAY_INIT_REF : ZIR_INST_ARRAY_INIT;
|
||||
ZirInstData idata;
|
||||
idata.pl_node.src_node
|
||||
= (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
idata.pl_node.payload_index = payload_index;
|
||||
uint32_t result = addInstruction(gz, init_tag, idata);
|
||||
if (is_ref)
|
||||
return result;
|
||||
return rvalue(gz, rl, result, node);
|
||||
goto typed_init;
|
||||
}
|
||||
}
|
||||
|
||||
// Non-inferred length: evaluate type normally.
|
||||
SET_ERROR(ag);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
// Non-inferred length: evaluate type normally (AstGen.zig:1476-1481).
|
||||
array_ty = typeExpr(gz, scope, type_expr_node);
|
||||
// validate_array_init_ty: ArrayInit{ty, init_count}
|
||||
addPlNodeBin(
|
||||
gz, ZIR_INST_VALIDATE_ARRAY_INIT_TY, node, array_ty, elem_count);
|
||||
elem_ty = ZIR_REF_NONE;
|
||||
|
||||
typed_init:
|
||||
// Typed inits do not use RLS for language simplicity
|
||||
// (AstGen.zig:1484-1513).
|
||||
if (rl.tag == RL_DISCARD) {
|
||||
// discard RL: evaluate elements but don't emit array_init
|
||||
// (AstGen.zig:1487-1506).
|
||||
if (elem_ty != ZIR_REF_NONE) {
|
||||
ResultLoc elem_rl
|
||||
= { .tag = RL_TY, .data = elem_ty, .src_node = 0 };
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
exprRl(gz, scope, elem_rl, elements[i]);
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
uint32_t this_elem_ty
|
||||
= addBin(gz, ZIR_INST_ARRAY_INIT_ELEM_TYPE, array_ty, i);
|
||||
ResultLoc elem_rl
|
||||
= { .tag = RL_TY, .data = this_elem_ty, .src_node = 0 };
|
||||
exprRl(gz, scope, elem_rl, elements[i]);
|
||||
}
|
||||
}
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
|
||||
if (rl.tag == RL_REF) {
|
||||
// ref RL: arrayInitExprTyped with is_ref=true
|
||||
// (AstGen.zig:1507).
|
||||
return arrayInitExprTyped(
|
||||
gz, scope, node, elements, elem_count, array_ty, elem_ty, true);
|
||||
}
|
||||
|
||||
// All other RLs: arrayInitExprTyped + rvalue (AstGen.zig:1508-1511).
|
||||
uint32_t array_inst = arrayInitExprTyped(
|
||||
gz, scope, node, elements, elem_count, array_ty, elem_ty, false);
|
||||
return rvalue(gz, rl, array_inst, node);
|
||||
}
|
||||
|
||||
// arrayInitExprTyped (AstGen.zig:1598-1642).
|
||||
// Emits array_init or array_init_ref instruction.
|
||||
static uint32_t arrayInitExprTyped(GenZir* gz, Scope* scope, uint32_t node,
|
||||
const uint32_t* elements, uint32_t elem_count, uint32_t ty_inst,
|
||||
uint32_t elem_ty, bool is_ref) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
uint32_t operands_len = elem_count + 1; // +1 for type
|
||||
ensureExtraCapacity(ag, 1 + operands_len);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = operands_len;
|
||||
ag->extra[ag->extra_len++] = ty_inst;
|
||||
uint32_t extra_start = ag->extra_len;
|
||||
ag->extra_len += elem_count;
|
||||
|
||||
if (elem_ty != ZIR_REF_NONE) {
|
||||
// Known elem type: use coerced_ty RL (AstGen.zig:1617-1623).
|
||||
ResultLoc elem_rl
|
||||
= { .tag = RL_COERCED_TY, .data = elem_ty, .src_node = 0 };
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
uint32_t elem_ref = exprRl(gz, scope, elem_rl, elements[i]);
|
||||
ag->extra[extra_start + i] = elem_ref;
|
||||
}
|
||||
} else {
|
||||
// Unknown elem type: use array_init_elem_type per element
|
||||
// (AstGen.zig:1625-1637).
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
uint32_t this_elem_ty
|
||||
= addBin(gz, ZIR_INST_ARRAY_INIT_ELEM_TYPE, ty_inst, i);
|
||||
ResultLoc elem_rl = {
|
||||
.tag = RL_COERCED_TY, .data = this_elem_ty, .src_node = 0
|
||||
};
|
||||
uint32_t elem_ref = exprRl(gz, scope, elem_rl, elements[i]);
|
||||
ag->extra[extra_start + i] = elem_ref;
|
||||
}
|
||||
}
|
||||
|
||||
ZirInstTag init_tag
|
||||
= is_ref ? ZIR_INST_ARRAY_INIT_REF : ZIR_INST_ARRAY_INIT;
|
||||
return addPlNodePayloadIndex(gz, init_tag, node, payload_index);
|
||||
}
|
||||
|
||||
// --- simpleBinOp (AstGen.zig:2204) ---
|
||||
@@ -5195,10 +5277,11 @@ static uint32_t arrayInitDotExpr(
|
||||
ag->extra[items_start + i]
|
||||
= elem_ptr_inst - ZIR_REF_START_INDEX; // .toIndex()
|
||||
// Evaluate element with ptr RL (AstGen.zig:1668).
|
||||
// Upstream creates fresh ResultInfo with default ctx (.none).
|
||||
ResultLoc ptr_rl = { .tag = RL_PTR,
|
||||
.data = elem_ptr_inst,
|
||||
.src_node = 0,
|
||||
.ctx = rl.ctx };
|
||||
.ctx = RI_CTX_NONE };
|
||||
exprRl(gz, scope, ptr_rl, elements[i]);
|
||||
}
|
||||
addPlNodePayloadIndex(
|
||||
|
||||
Reference in New Issue
Block a user