diff --git a/astgen.c b/astgen.c index 5e7378f152..937570b0fa 100644 --- a/astgen.c +++ b/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(