AstGen: implement struct init with ResultLoc.ty
This commit is contained in:
@@ -823,7 +823,31 @@ pub fn structInitExpr(
|
||||
.none, .none_or_ref => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}),
|
||||
.ref => unreachable, // struct literal not valid as l-value
|
||||
.ty => |ty_inst| {
|
||||
return mod.failNode(scope, node, "TODO implement structInitExpr ty", .{});
|
||||
const fields_list = try gpa.alloc(zir.Inst.StructInit.Item, struct_init.ast.fields.len);
|
||||
defer gpa.free(fields_list);
|
||||
|
||||
for (struct_init.ast.fields) |field_init, i| {
|
||||
const name_token = tree.firstToken(field_init) - 2;
|
||||
const str_index = try gz.identAsString(name_token);
|
||||
|
||||
const field_ty_inst = try gz.addPlNode(.field_type, field_init, zir.Inst.FieldType{
|
||||
.container_type = ty_inst,
|
||||
.name_start = str_index,
|
||||
});
|
||||
fields_list[i] = .{
|
||||
.field_type = astgen.refToIndex(field_ty_inst).?,
|
||||
.init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init),
|
||||
};
|
||||
}
|
||||
const init_inst = try gz.addPlNode(.struct_init, node, zir.Inst.StructInit{
|
||||
.fields_len = @intCast(u32, fields_list.len),
|
||||
});
|
||||
try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
|
||||
fields_list.len * @typeInfo(zir.Inst.StructInit.Item).Struct.fields.len);
|
||||
for (fields_list) |field| {
|
||||
_ = gz.astgen.addExtraAssumeCapacity(field);
|
||||
}
|
||||
return rvalue(gz, scope, rl, init_inst, node);
|
||||
},
|
||||
.ptr => |ptr_inst| {
|
||||
const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len);
|
||||
@@ -1321,6 +1345,8 @@ fn blockExprStmts(
|
||||
.switch_capture_else,
|
||||
.switch_capture_else_ref,
|
||||
.struct_init_empty,
|
||||
.struct_init,
|
||||
.field_type,
|
||||
.struct_decl,
|
||||
.struct_decl_packed,
|
||||
.struct_decl_extern,
|
||||
|
||||
14
src/Sema.zig
14
src/Sema.zig
@@ -264,6 +264,8 @@ pub fn analyzeBody(
|
||||
.typeof_peer => try sema.zirTypeofPeer(block, inst),
|
||||
.xor => try sema.zirBitwise(block, inst, .xor),
|
||||
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
|
||||
.struct_init => try sema.zirStructInit(block, inst),
|
||||
.field_type => try sema.zirFieldType(block, inst),
|
||||
|
||||
.struct_decl => try sema.zirStructDecl(block, inst, .Auto),
|
||||
.struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
|
||||
@@ -4493,6 +4495,18 @@ fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
|
||||
});
|
||||
}
|
||||
|
||||
fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInit", .{});
|
||||
}
|
||||
|
||||
fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldType", .{});
|
||||
}
|
||||
|
||||
fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
|
||||
if (sema.func == null) {
|
||||
return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{});
|
||||
|
||||
29
src/zir.zig
29
src/zir.zig
@@ -674,6 +674,13 @@ pub const Inst = struct {
|
||||
/// A struct literal with a specified type, with no fields.
|
||||
/// Uses the `un_node` field.
|
||||
struct_init_empty,
|
||||
/// Given a struct, union, enum, or opaque and a field name, returns the field type.
|
||||
/// Uses the `pl_node` field. Payload is `FieldType`.
|
||||
field_type,
|
||||
/// Finalizes a typed struct initialization, performs validation, and returns the
|
||||
/// struct value.
|
||||
/// Uses the `pl_node` field. Payload is `StructInit`.
|
||||
struct_init,
|
||||
/// Converts an integer into an enum value.
|
||||
/// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand.
|
||||
int_to_enum,
|
||||
@@ -839,6 +846,8 @@ pub const Inst = struct {
|
||||
.switch_block_ref_under_multi,
|
||||
.validate_struct_init_ptr,
|
||||
.struct_init_empty,
|
||||
.struct_init,
|
||||
.field_type,
|
||||
.int_to_enum,
|
||||
.enum_to_int,
|
||||
=> false,
|
||||
@@ -1551,6 +1560,24 @@ pub const Inst = struct {
|
||||
return @bitCast(f128, int_bits);
|
||||
}
|
||||
};
|
||||
|
||||
/// Trailing is an item per field.
|
||||
pub const StructInit = struct {
|
||||
fields_len: u32,
|
||||
|
||||
pub const Item = struct {
|
||||
/// The `field_type` ZIR instruction for this field init.
|
||||
field_type: Index,
|
||||
/// The field init expression to be used as the field value.
|
||||
init: Ref,
|
||||
};
|
||||
};
|
||||
|
||||
pub const FieldType = struct {
|
||||
container_type: Ref,
|
||||
/// Offset into `string_bytes`, null terminated.
|
||||
name_start: u32,
|
||||
};
|
||||
};
|
||||
|
||||
pub const SpecialProng = enum { none, @"else", under };
|
||||
@@ -1665,6 +1692,8 @@ const Writer = struct {
|
||||
.union_decl,
|
||||
.enum_decl,
|
||||
.enum_decl_nonexhaustive,
|
||||
.struct_init,
|
||||
.field_type,
|
||||
=> try self.writePlNode(stream, inst),
|
||||
|
||||
.add,
|
||||
|
||||
Reference in New Issue
Block a user