diff --git a/astgen.c b/astgen.c index 9c5b0ce4c4..aaaf1d045c 100644 --- a/astgen.c +++ b/astgen.c @@ -172,6 +172,7 @@ typedef enum { RL_COERCED_TY, // Coerce to specific type, result is the coercion. RL_PTR, // Store result to typed pointer. data=alloc inst, src_node=node. RL_INFERRED_PTR, // Store result to inferred pointer. data=alloc inst. + RL_REF_COERCED_TY, // Ref with pointer type. data=ptr_ty_inst. } ResultLocTag; typedef struct { @@ -185,6 +186,8 @@ typedef struct { #define RL_REF_VAL ((ResultLoc) { .tag = RL_REF, .data = 0, .src_node = 0 }) #define RL_DISCARD_VAL \ ((ResultLoc) { .tag = RL_DISCARD, .data = 0, .src_node = 0 }) +#define RL_IS_REF(rl) \ + ((rl).tag == RL_REF || (rl).tag == RL_REF_COERCED_TY) // --- Scope types (AstGen.zig:11621-11768) --- @@ -1515,7 +1518,8 @@ static uint32_t rvalue( // ensure_result_non_error (AstGen.zig:11071-11074). addUnNode(gz, ZIR_INST_ENSURE_RESULT_NON_ERROR, result, node); return ZIR_REF_VOID_VALUE; - case RL_REF: { + case RL_REF: + case RL_REF_COERCED_TY: { AstGenCtx* ag = gz->astgen; uint32_t src_token = firstToken(ag->tree, node); // If result is not an instruction index (e.g. a well-known ref), @@ -2315,7 +2319,7 @@ static uint32_t identifierExpr( case SCOPE_LOCAL_PTR: { ScopeLocalPtr* lp = (ScopeLocalPtr*)s; if (lp->name == name_str) { - if (rl.tag == RL_REF) + if (RL_IS_REF(rl)) return lp->ptr; return addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node); } @@ -2349,7 +2353,7 @@ decl_table: for (uint32_t i = 0; i < ag->decl_table_len; i++) { if (ag->decl_names[i] == name_str) { ZirInstTag itag - = (rl.tag == RL_REF) ? ZIR_INST_DECL_REF : ZIR_INST_DECL_VAL; + = (RL_IS_REF(rl)) ? ZIR_INST_DECL_REF : ZIR_INST_DECL_VAL; ZirInstData data; data.str_tok.start = name_str; data.str_tok.src_tok = tokenIndexToRelative(gz, ident_token); @@ -2379,7 +2383,7 @@ static uint32_t fieldAccessExpr( // Evaluate the LHS object expression (AstGen.zig:6181). // For .ref rl, LHS is also evaluated with .ref (AstGen.zig:6161). - ResultLoc lhs_rl = (rl.tag == RL_REF) ? RL_REF_VAL : RL_NONE_VAL; + ResultLoc lhs_rl = (RL_IS_REF(rl)) ? RL_REF_VAL : RL_NONE_VAL; uint32_t lhs = exprRl(gz, scope, lhs_rl, object_node); // Emit dbg_stmt for the dot token (AstGen.zig:6183-6184). @@ -2398,13 +2402,13 @@ static uint32_t fieldAccessExpr( // .ref → field_ptr, else → field_val (AstGen.zig:6160-6164). ZirInstTag ftag - = (rl.tag == RL_REF) ? ZIR_INST_FIELD_PTR : ZIR_INST_FIELD_VAL; + = (RL_IS_REF(rl)) ? ZIR_INST_FIELD_PTR : ZIR_INST_FIELD_VAL; ZirInstData data; data.pl_node.src_node = (int32_t)node - (int32_t)gz->decl_node_index; data.pl_node.payload_index = payload_index; uint32_t access = addInstruction(gz, ftag, data); // For ref, return directly; otherwise apply rvalue (AstGen.zig:6161-6164). - if (rl.tag == RL_REF) + if (RL_IS_REF(rl)) return access; return rvalue(gz, rl, access, node); } @@ -2561,7 +2565,7 @@ static uint32_t arrayInitExpr( gz, ZIR_INST_ARRAY_TYPE, type_expr_node, len_inst, elem_type); // arrayInitExprTyped (AstGen.zig:1598-1642). - bool is_ref = (rl.tag == RL_REF); + bool is_ref = (RL_IS_REF(rl)); uint32_t operands_len = elem_count + 1; ensureExtraCapacity(ag, 1 + operands_len); uint32_t payload_index = ag->extra_len; @@ -3028,6 +3032,10 @@ static uint32_t structInitExpr( if (type_expr_node == 0 && fields_len == 0) { // .{} — depends on result location (AstGen.zig:1687-1698). + if (rl.tag == RL_REF_COERCED_TY) { + return addUnNode(gz, ZIR_INST_STRUCT_INIT_EMPTY_REF_RESULT, + rl.data, node); + } if (rl.tag == RL_TY || rl.tag == RL_COERCED_TY) { return addUnNode( gz, ZIR_INST_STRUCT_INIT_EMPTY_RESULT, rl.data, node); @@ -3135,7 +3143,7 @@ static uint32_t structInitExpr( ag->extra[items_start + i * 2 + 1] = init_ref; } - bool is_ref = (rl.tag == RL_REF); + bool is_ref = (RL_IS_REF(rl)); ZirInstTag init_tag = is_ref ? ZIR_INST_STRUCT_INIT_REF : ZIR_INST_STRUCT_INIT; return addPlNodePayloadIndex(gz, init_tag, node, payload_index); @@ -3277,7 +3285,10 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { if (res_ty != 0) { addUnTok(gz, ZIR_INST_VALIDATE_REF_TY, res_ty, firstToken(ag->tree, node)); - operand_rl = RL_REF_VAL; // simplified: skip ref_coerced_ty + // Pass ref_coerced_ty so init expressions can use the type + // (AstGen.zig:958). + operand_rl = (ResultLoc) { .tag = RL_REF_COERCED_TY, + .data = res_ty, .src_node = 0 }; } else { operand_rl = RL_REF_VAL; } @@ -3453,7 +3464,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { case AST_NODE_DEREF: { uint32_t lhs = expr(gz, scope, nd.lhs); addUnNode(gz, ZIR_INST_VALIDATE_DEREF, lhs, node); - if (rl.tag == RL_REF) + if (RL_IS_REF(rl)) return lhs; return rvalue(gz, rl, addUnNode(gz, ZIR_INST_LOAD, lhs, node), node); } @@ -3487,7 +3498,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { } // arrayAccess (AstGen.zig:6192-6221). case AST_NODE_ARRAY_ACCESS: { - if (rl.tag == RL_REF) { + if (RL_IS_REF(rl)) { uint32_t lhs = exprRl(gz, scope, RL_REF_VAL, nd.lhs); advanceSourceCursorToMainToken(ag, node); uint32_t rhs = expr(gz, scope, nd.rhs); @@ -4141,6 +4152,37 @@ static uint32_t arrayInitDotExpr( gz, ZIR_INST_ARRAY_INIT_ANON, node, payload_index); return rvalue(gz, rl, result, node); } + case RL_REF_COERCED_TY: { + // validate_array_init_ref_ty + arrayInitExprTyped + // (AstGen.zig:1527-1532). + uint32_t ptr_ty_inst = rl.data; + ensureExtraCapacity(ag, 2); + uint32_t val_payload = ag->extra_len; + ag->extra[ag->extra_len++] = ptr_ty_inst; + ag->extra[ag->extra_len++] = elem_count; + uint32_t dest_arr_ty_inst = addPlNodePayloadIndex( + gz, ZIR_INST_VALIDATE_ARRAY_INIT_REF_TY, node, val_payload); + + // arrayInitExprTyped with elem_ty=none, is_ref=true. + uint32_t operands_len = elem_count + 1; + ensureExtraCapacity(ag, 1 + operands_len); + uint32_t ai_payload = ag->extra_len; + ag->extra[ag->extra_len++] = operands_len; + ag->extra[ag->extra_len++] = dest_arr_ty_inst; + uint32_t extra_start2 = ag->extra_len; + ag->extra_len += elem_count; + for (uint32_t i = 0; i < elem_count; i++) { + uint32_t elem_ty = addPlNodeBin(gz, + ZIR_INST_ARRAY_INIT_ELEM_TYPE, elements[i], + dest_arr_ty_inst, i); + ResultLoc elem_rl = { .tag = RL_COERCED_TY, .data = elem_ty, + .src_node = 0 }; + uint32_t elem_ref = exprRl(gz, scope, elem_rl, elements[i]); + ag->extra[extra_start2 + i] = elem_ref; + } + return addPlNodePayloadIndex( + gz, ZIR_INST_ARRAY_INIT_REF, node, ai_payload); + } case RL_PTR: // TODO: arrayInitExprPtr (AstGen.zig:1541-1543). // For now, fall through to anon + rvalue. diff --git a/astgen_test.zig b/astgen_test.zig index e95175d42e..0f185d8b42 100644 --- a/astgen_test.zig +++ b/astgen_test.zig @@ -994,7 +994,6 @@ test "astgen: corpus test_all.zig" { // } test "astgen: corpus tokenizer_test.zig" { - if (true) return error.SkipZigTest; // TODO: 428 inst diff from ref_coerced_ty RL const gpa = std.testing.allocator; try corpusCheck(gpa, "tokenizer_test.zig", @embedFile("tokenizer_test.zig")); }