astgen: fix structInitExpr rvalue, RL handling, sentinel coercion, and empty init
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
224
astgen.c
224
astgen.c
@@ -4044,8 +4044,72 @@ static uint32_t callExpr(
|
|||||||
return call_index + ZIR_REF_START_INDEX;
|
return call_index + ZIR_REF_START_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// structInitExprAnon (AstGen.zig:1865-1893).
|
||||||
|
// Anonymous struct init using struct_init_anon instruction.
|
||||||
|
static uint32_t structInitExprAnon(GenZir* gz, Scope* scope, uint32_t node,
|
||||||
|
const uint32_t* fields, uint32_t fields_len) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
const Ast* tree = ag->tree;
|
||||||
|
|
||||||
|
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
||||||
|
uint32_t payload_index = ag->extra_len;
|
||||||
|
ag->extra[ag->extra_len++] = node; // abs_node
|
||||||
|
ag->extra[ag->extra_len++] = ag->source_line; // abs_line
|
||||||
|
ag->extra[ag->extra_len++] = fields_len;
|
||||||
|
uint32_t items_start = ag->extra_len;
|
||||||
|
ag->extra_len += fields_len * 2;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < fields_len; i++) {
|
||||||
|
uint32_t field_init = fields[i];
|
||||||
|
uint32_t name_token = firstToken(tree, field_init) - 2;
|
||||||
|
uint32_t str_index = identAsString(ag, name_token);
|
||||||
|
uint32_t init_ref = expr(gz, scope, field_init);
|
||||||
|
ag->extra[items_start + i * 2] = str_index;
|
||||||
|
ag->extra[items_start + i * 2 + 1] = init_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addPlNodePayloadIndex(
|
||||||
|
gz, ZIR_INST_STRUCT_INIT_ANON, node, payload_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// structInitExprTyped (AstGen.zig:1896-1931).
|
||||||
|
// Typed struct init using struct_init or struct_init_ref instruction.
|
||||||
|
static uint32_t structInitExprTyped(GenZir* gz, Scope* scope, uint32_t node,
|
||||||
|
const uint32_t* fields, uint32_t fields_len, uint32_t ty_inst,
|
||||||
|
bool is_ref) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
const Ast* tree = ag->tree;
|
||||||
|
|
||||||
|
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
||||||
|
uint32_t payload_index = ag->extra_len;
|
||||||
|
ag->extra[ag->extra_len++] = node; // abs_node
|
||||||
|
ag->extra[ag->extra_len++] = ag->source_line; // abs_line
|
||||||
|
ag->extra[ag->extra_len++] = fields_len;
|
||||||
|
uint32_t items_start = ag->extra_len;
|
||||||
|
ag->extra_len += fields_len * 2;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < fields_len; i++) {
|
||||||
|
uint32_t field_init = fields[i];
|
||||||
|
uint32_t name_token = firstToken(tree, field_init) - 2;
|
||||||
|
uint32_t str_index = identAsString(ag, name_token);
|
||||||
|
uint32_t field_ty_inst = addPlNodeBin(gz,
|
||||||
|
ZIR_INST_STRUCT_INIT_FIELD_TYPE, field_init, ty_inst, str_index);
|
||||||
|
ResultLoc elem_rl = { .tag = RL_COERCED_TY,
|
||||||
|
.data = field_ty_inst,
|
||||||
|
.src_node = 0,
|
||||||
|
.ctx = RI_CTX_NONE };
|
||||||
|
uint32_t init_ref = exprRl(gz, scope, elem_rl, field_init);
|
||||||
|
ag->extra[items_start + i * 2]
|
||||||
|
= field_ty_inst - ZIR_REF_START_INDEX; // .toIndex()
|
||||||
|
ag->extra[items_start + i * 2 + 1] = init_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZirInstTag init_tag
|
||||||
|
= is_ref ? ZIR_INST_STRUCT_INIT_REF : ZIR_INST_STRUCT_INIT;
|
||||||
|
return addPlNodePayloadIndex(gz, init_tag, node, payload_index);
|
||||||
|
}
|
||||||
|
|
||||||
// --- structInitExpr (AstGen.zig:1674) ---
|
// --- structInitExpr (AstGen.zig:1674) ---
|
||||||
// Simplified: handles .{} (empty tuple), .{.a = b} (anon init).
|
|
||||||
static uint32_t structInitExpr(
|
static uint32_t structInitExpr(
|
||||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||||
AstGenCtx* ag = gz->astgen;
|
AstGenCtx* ag = gz->astgen;
|
||||||
@@ -4118,7 +4182,15 @@ static uint32_t structInitExpr(
|
|||||||
if (rl.tag == RL_DISCARD) {
|
if (rl.tag == RL_DISCARD) {
|
||||||
return ZIR_REF_VOID_VALUE;
|
return ZIR_REF_VOID_VALUE;
|
||||||
}
|
}
|
||||||
return ZIR_REF_EMPTY_TUPLE;
|
if (rl.tag == RL_PTR) {
|
||||||
|
// AstGen.zig:1691-1696.
|
||||||
|
uint32_t ty_inst = rlResultType(gz, rl, node);
|
||||||
|
uint32_t val = addUnNode(
|
||||||
|
gz, ZIR_INST_STRUCT_INIT_EMPTY_RESULT, ty_inst, node);
|
||||||
|
return rvalue(gz, rl, val, node);
|
||||||
|
}
|
||||||
|
// RL_NONE, RL_REF, RL_INFERRED_PTR (AstGen.zig:1697-1699).
|
||||||
|
return rvalue(gz, rl, ZIR_REF_EMPTY_TUPLE, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-register all field names to match upstream string ordering.
|
// Pre-register all field names to match upstream string ordering.
|
||||||
@@ -4130,8 +4202,46 @@ static uint32_t structInitExpr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type_expr_node == 0 && fields_len > 0) {
|
if (type_expr_node == 0 && fields_len > 0) {
|
||||||
// structInitExprPtr for RL_PTR (AstGen.zig:1843-1846, 1934-1964).
|
// Anonymous struct init with fields (AstGen.zig:1821-1861).
|
||||||
if (rl.tag == RL_PTR) {
|
switch (rl.tag) {
|
||||||
|
case RL_NONE:
|
||||||
|
// structInitExprAnon (AstGen.zig:1822, 1865-1893).
|
||||||
|
return structInitExprAnon(gz, scope, node, fields, fields_len);
|
||||||
|
case RL_DISCARD: {
|
||||||
|
// Even if discarding we must perform side-effects
|
||||||
|
// (AstGen.zig:1823-1828).
|
||||||
|
for (uint32_t i = 0; i < fields_len; i++)
|
||||||
|
exprRl(gz, scope, RL_DISCARD_VAL, fields[i]);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
case RL_REF: {
|
||||||
|
// structInitExprAnon + ref (AstGen.zig:1830-1833).
|
||||||
|
uint32_t result
|
||||||
|
= structInitExprAnon(gz, scope, node, fields, fields_len);
|
||||||
|
return addUnTok(gz, ZIR_INST_REF, result, firstToken(tree, node));
|
||||||
|
}
|
||||||
|
case RL_REF_COERCED_TY: {
|
||||||
|
// Get elem type, validate, structInitExprTyped(is_ref=true)
|
||||||
|
// (AstGen.zig:1834-1837).
|
||||||
|
uint32_t result_ty_inst
|
||||||
|
= addUnNode(gz, ZIR_INST_ELEM_TYPE, rl.data, node);
|
||||||
|
addUnNode(gz, ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY,
|
||||||
|
result_ty_inst, node);
|
||||||
|
return structInitExprTyped(
|
||||||
|
gz, scope, node, fields, fields_len, result_ty_inst, true);
|
||||||
|
}
|
||||||
|
case RL_TY:
|
||||||
|
case RL_COERCED_TY: {
|
||||||
|
// validate_struct_init_result_ty +
|
||||||
|
// structInitExprTyped(is_ref=false) (AstGen.zig:1839-1841).
|
||||||
|
uint32_t ty_inst = rl.data;
|
||||||
|
addUnNode(
|
||||||
|
gz, ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY, ty_inst, node);
|
||||||
|
return structInitExprTyped(
|
||||||
|
gz, scope, node, fields, fields_len, ty_inst, false);
|
||||||
|
}
|
||||||
|
case RL_PTR: {
|
||||||
|
// structInitExprPtr (AstGen.zig:1843-1846, 1934-1964).
|
||||||
uint32_t struct_ptr_inst
|
uint32_t struct_ptr_inst
|
||||||
= addUnNode(gz, ZIR_INST_OPT_EU_BASE_PTR_INIT, rl.data, node);
|
= addUnNode(gz, ZIR_INST_OPT_EU_BASE_PTR_INIT, rl.data, node);
|
||||||
// Block payload: body_len = fields_len.
|
// Block payload: body_len = fields_len.
|
||||||
@@ -4155,68 +4265,22 @@ static uint32_t structInitExpr(
|
|||||||
ResultLoc ptr_rl = { .tag = RL_PTR,
|
ResultLoc ptr_rl = { .tag = RL_PTR,
|
||||||
.data = field_ptr,
|
.data = field_ptr,
|
||||||
.src_node = 0,
|
.src_node = 0,
|
||||||
.ctx = rl.ctx };
|
.ctx = RI_CTX_NONE };
|
||||||
exprRl(gz, scope, ptr_rl, field_init);
|
exprRl(gz, scope, ptr_rl, field_init);
|
||||||
}
|
}
|
||||||
addPlNodePayloadIndex(
|
addPlNodePayloadIndex(
|
||||||
gz, ZIR_INST_VALIDATE_PTR_STRUCT_INIT, node, payload_index);
|
gz, ZIR_INST_VALIDATE_PTR_STRUCT_INIT, node, payload_index);
|
||||||
return ZIR_REF_VOID_VALUE;
|
return ZIR_REF_VOID_VALUE;
|
||||||
}
|
}
|
||||||
// Anonymous struct init with RL type (AstGen.zig:1706-1731).
|
case RL_INFERRED_PTR: {
|
||||||
if (rl.tag == RL_TY || rl.tag == RL_COERCED_TY) {
|
// Standard anon init + rvalue store (AstGen.zig:1847-1852).
|
||||||
uint32_t ty_inst = rl.data;
|
uint32_t struct_inst
|
||||||
// validate_struct_init_result_ty (AstGen.zig:1840).
|
= structInitExprAnon(gz, scope, node, fields, fields_len);
|
||||||
addUnNode(
|
return rvalue(gz, rl, struct_inst, node);
|
||||||
gz, ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY, ty_inst, node);
|
|
||||||
// structInitExprTyped (AstGen.zig:1896-1931).
|
|
||||||
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
|
||||||
uint32_t payload_index = ag->extra_len;
|
|
||||||
ag->extra[ag->extra_len++] = node;
|
|
||||||
ag->extra[ag->extra_len++] = ag->source_line;
|
|
||||||
ag->extra[ag->extra_len++] = fields_len;
|
|
||||||
uint32_t items_start = ag->extra_len;
|
|
||||||
ag->extra_len += fields_len * 2;
|
|
||||||
for (uint32_t i = 0; i < fields_len; i++) {
|
|
||||||
uint32_t field_init = fields[i];
|
|
||||||
uint32_t name_token = firstToken(tree, field_init) - 2;
|
|
||||||
uint32_t str_index = identAsString(ag, name_token);
|
|
||||||
uint32_t field_ty_inst
|
|
||||||
= addPlNodeBin(gz, ZIR_INST_STRUCT_INIT_FIELD_TYPE,
|
|
||||||
field_init, ty_inst, str_index);
|
|
||||||
ResultLoc elem_rl = {
|
|
||||||
.tag = RL_COERCED_TY, .data = field_ty_inst, .src_node = 0
|
|
||||||
};
|
|
||||||
uint32_t init_ref = exprRl(gz, scope, elem_rl, field_init);
|
|
||||||
ag->extra[items_start + i * 2]
|
|
||||||
= field_ty_inst - ZIR_REF_START_INDEX;
|
|
||||||
ag->extra[items_start + i * 2 + 1] = init_ref;
|
|
||||||
}
|
|
||||||
return addPlNodePayloadIndex(
|
|
||||||
gz, ZIR_INST_STRUCT_INIT, node, payload_index);
|
|
||||||
}
|
}
|
||||||
// Anonymous struct init without RL type (AstGen.zig:1864).
|
|
||||||
// StructInitAnon payload: abs_node, abs_line, fields_len.
|
|
||||||
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
|
||||||
uint32_t payload_index = ag->extra_len;
|
|
||||||
ag->extra[ag->extra_len++] = node; // abs_node
|
|
||||||
ag->extra[ag->extra_len++] = ag->source_line; // abs_line
|
|
||||||
ag->extra[ag->extra_len++] = fields_len;
|
|
||||||
// Reserve space for field entries.
|
|
||||||
uint32_t items_start = ag->extra_len;
|
|
||||||
ag->extra_len += fields_len * 2;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < fields_len; i++) {
|
|
||||||
uint32_t field_init = fields[i];
|
|
||||||
// field name is 2 tokens before the field init's first token.
|
|
||||||
uint32_t name_token = firstToken(tree, field_init) - 2;
|
|
||||||
uint32_t str_index = identAsString(ag, name_token);
|
|
||||||
uint32_t init_ref = expr(gz, scope, field_init);
|
|
||||||
ag->extra[items_start + i * 2] = str_index;
|
|
||||||
ag->extra[items_start + i * 2 + 1] = init_ref;
|
|
||||||
}
|
}
|
||||||
|
SET_ERROR(ag);
|
||||||
return addPlNodePayloadIndex(
|
return ZIR_REF_VOID_VALUE;
|
||||||
gz, ZIR_INST_STRUCT_INIT_ANON, node, payload_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typed init: evaluate type, emit struct_init_empty or struct_init.
|
// Typed init: evaluate type, emit struct_init_empty or struct_init.
|
||||||
@@ -4246,7 +4310,7 @@ static uint32_t structInitExpr(
|
|||||||
uint32_t elem_type_node
|
uint32_t elem_type_node
|
||||||
= tree->extra_data.arr[type_nd.rhs + 1];
|
= tree->extra_data.arr[type_nd.rhs + 1];
|
||||||
uint32_t elem_type = typeExpr(gz, scope, elem_type_node);
|
uint32_t elem_type = typeExpr(gz, scope, elem_type_node);
|
||||||
ResultLoc sent_rl = { .tag = RL_COERCED_TY,
|
ResultLoc sent_rl = { .tag = RL_TY,
|
||||||
.data = elem_type,
|
.data = elem_type,
|
||||||
.src_node = 0,
|
.src_node = 0,
|
||||||
.ctx = RI_CTX_NONE };
|
.ctx = RI_CTX_NONE };
|
||||||
@@ -4270,41 +4334,15 @@ static uint32_t structInitExpr(
|
|||||||
if (type_expr_node != 0 && fields_len > 0) {
|
if (type_expr_node != 0 && fields_len > 0) {
|
||||||
uint32_t ty_inst = typeExpr(gz, scope, type_expr_node);
|
uint32_t ty_inst = typeExpr(gz, scope, type_expr_node);
|
||||||
addUnNode(gz, ZIR_INST_VALIDATE_STRUCT_INIT_TY, ty_inst, node);
|
addUnNode(gz, ZIR_INST_VALIDATE_STRUCT_INIT_TY, ty_inst, node);
|
||||||
|
// Upstream: .ref => structInitExprTyped(is_ref=true)
|
||||||
// structInitExprTyped (AstGen.zig:1896-1931).
|
// else => rvalue(structInitExprTyped(is_ref=false))
|
||||||
// StructInit payload: abs_node, abs_line, fields_len.
|
if (rl.tag == RL_REF) {
|
||||||
ensureExtraCapacity(ag, 3 + fields_len * 2);
|
return structInitExprTyped(
|
||||||
uint32_t payload_index = ag->extra_len;
|
gz, scope, node, fields, fields_len, ty_inst, true);
|
||||||
ag->extra[ag->extra_len++] = node; // abs_node
|
|
||||||
ag->extra[ag->extra_len++] = ag->source_line; // abs_line
|
|
||||||
ag->extra[ag->extra_len++] = fields_len;
|
|
||||||
// Reserve space for field items (field_type + init each).
|
|
||||||
uint32_t items_start = ag->extra_len;
|
|
||||||
ag->extra_len += fields_len * 2;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < fields_len; i++) {
|
|
||||||
uint32_t field_init = fields[i];
|
|
||||||
uint32_t name_token = firstToken(tree, field_init) - 2;
|
|
||||||
uint32_t str_index = identAsString(ag, name_token);
|
|
||||||
// struct_init_field_type (AstGen.zig:1918-1921).
|
|
||||||
uint32_t field_ty_inst
|
|
||||||
= addPlNodeBin(gz, ZIR_INST_STRUCT_INIT_FIELD_TYPE, field_init,
|
|
||||||
ty_inst, str_index);
|
|
||||||
// Evaluate init with coerced_ty (AstGen.zig:1924).
|
|
||||||
ResultLoc elem_rl = { .tag = RL_COERCED_TY,
|
|
||||||
.data = field_ty_inst,
|
|
||||||
.src_node = 0,
|
|
||||||
.ctx = rl.ctx };
|
|
||||||
uint32_t init_ref = exprRl(gz, scope, elem_rl, field_init);
|
|
||||||
ag->extra[items_start + i * 2]
|
|
||||||
= field_ty_inst - ZIR_REF_START_INDEX; // .toIndex()
|
|
||||||
ag->extra[items_start + i * 2 + 1] = init_ref;
|
|
||||||
}
|
}
|
||||||
|
uint32_t struct_inst = structInitExprTyped(
|
||||||
bool is_ref = (RL_IS_REF(rl));
|
gz, scope, node, fields, fields_len, ty_inst, false);
|
||||||
ZirInstTag init_tag
|
return rvalue(gz, rl, struct_inst, node);
|
||||||
= is_ref ? ZIR_INST_STRUCT_INIT_REF : ZIR_INST_STRUCT_INIT;
|
|
||||||
return addPlNodePayloadIndex(gz, init_tag, node, payload_index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_ERROR(ag);
|
SET_ERROR(ag);
|
||||||
|
|||||||
Reference in New Issue
Block a user