authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 11:58:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 11:58:55-07:00
log50bcfb8c906be67a044ff4bef857a8d6d615de71
tree1ab1bd3d8bba948a44bbcbaf15860803f75c1221
parent59035ae3e9d2de2d95036ff522fb926a3bd27b3c

stage2: implement struct init syntax with ptr result loc


4 files changed, 95 insertions(+), 15 deletions(-)

src/AstGen.zig+62-15
...@@ -769,15 +769,20 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -769,15 +769,20 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
769 .array_init_comma,769 .array_init_comma,
770 => return mod.failNode(scope, node, "TODO implement astgen.expr for array literals", .{}),770 => return mod.failNode(scope, node, "TODO implement astgen.expr for array literals", .{}),
771771
772 .struct_init_one,772 .struct_init_one, .struct_init_one_comma => {
773 .struct_init_one_comma,773 var fields: [1]ast.Node.Index = undefined;
774 .struct_init_dot_two,774 return structInitExpr(gz, scope, rl, node, tree.structInitOne(&fields, node));
775 .struct_init_dot_two_comma,775 },
776 .struct_init_dot_two, .struct_init_dot_two_comma => {
777 var fields: [2]ast.Node.Index = undefined;
778 return structInitExpr(gz, scope, rl, node, tree.structInitDotTwo(&fields, node));
779 },
776 .struct_init_dot,780 .struct_init_dot,
777 .struct_init_dot_comma,781 .struct_init_dot_comma,
782 => return structInitExpr(gz, scope, rl, node, tree.structInitDot(node)),
778 .struct_init,783 .struct_init,
779 .struct_init_comma,784 .struct_init_comma,
780 => return mod.failNode(scope, node, "TODO implement astgen.expr for struct literals", .{}),785 => return structInitExpr(gz, scope, rl, node, tree.structInit(node)),
781786
782 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),787 .@"anytype" => return mod.failNode(scope, node, "TODO implement astgen.expr for .anytype", .{}),
783 .fn_proto_simple,788 .fn_proto_simple,
...@@ -788,6 +793,53 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn...@@ -788,6 +793,53 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn
788 }793 }
789}794}
790795
796pub fn structInitExpr(
797 gz: *GenZir,
798 scope: *Scope,
799 rl: ResultLoc,
800 node: ast.Node.Index,
801 struct_init: ast.full.StructInit,
802) InnerError!zir.Inst.Ref {
803 const tree = gz.tree();
804 const astgen = gz.astgen;
805 const mod = astgen.mod;
806 const gpa = mod.gpa;
807 switch (rl) {
808 .discard => return mod.failNode(scope, node, "TODO implement structInitExpr discard", .{}),
809 .none => return mod.failNode(scope, node, "TODO implement structInitExpr none", .{}),
810 .ref => unreachable, // struct literal not valid as l-value
811 .ty => |ty_inst| {
812 return mod.failNode(scope, node, "TODO implement structInitExpr ty", .{});
813 },
814 .ptr => |ptr_inst| {
815 const field_ptr_list = try gpa.alloc(zir.Inst.Index, struct_init.ast.fields.len);
816 defer gpa.free(field_ptr_list);
817
818 for (struct_init.ast.fields) |field_init, i| {
819 const name_token = tree.firstToken(field_init) - 2;
820 const str_index = try gz.identAsString(name_token);
821 const field_ptr = try gz.addPlNode(.field_ptr, field_init, zir.Inst.Field{
822 .lhs = ptr_inst,
823 .field_name_start = str_index,
824 });
825 field_ptr_list[i] = astgen.refToIndex(field_ptr).?;
826 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);
827 }
828 const validate_inst = try gz.addPlNode(.validate_struct_init_ptr, node, zir.Inst.Block{
829 .body_len = @intCast(u32, field_ptr_list.len),
830 });
831 try astgen.extra.appendSlice(gpa, field_ptr_list);
832 return validate_inst;
833 },
834 .inferred_ptr => |ptr_inst| {
835 return mod.failNode(scope, node, "TODO implement structInitExpr inferred_ptr", .{});
836 },
837 .block_ptr => |block_gz| {
838 return mod.failNode(scope, node, "TODO implement structInitExpr block", .{});
839 },
840 }
841}
842
791pub fn comptimeExpr(843pub fn comptimeExpr(
792 gz: *GenZir,844 gz: *GenZir,
793 scope: *Scope,845 scope: *Scope,
...@@ -1285,6 +1337,7 @@ fn blockExprStmts(...@@ -1285,6 +1337,7 @@ fn blockExprStmts(
1285 .resolve_inferred_alloc,1337 .resolve_inferred_alloc,
1286 .repeat,1338 .repeat,
1287 .repeat_inline,1339 .repeat_inline,
1340 .validate_struct_init_ptr,
1288 => break :b true,1341 => break :b true,
1289 }1342 }
1290 } else switch (maybe_unused_result) {1343 } else switch (maybe_unused_result) {
...@@ -1959,7 +2012,8 @@ pub fn fieldAccess(...@@ -1959,7 +2012,8 @@ pub fn fieldAccess(
1959 rl: ResultLoc,2012 rl: ResultLoc,
1960 node: ast.Node.Index,2013 node: ast.Node.Index,
1961) InnerError!zir.Inst.Ref {2014) InnerError!zir.Inst.Ref {
1962 const mod = gz.astgen.mod;2015 const astgen = gz.astgen;
2016 const mod = astgen.mod;
1963 const tree = gz.tree();2017 const tree = gz.tree();
1964 const main_tokens = tree.nodes.items(.main_token);2018 const main_tokens = tree.nodes.items(.main_token);
1965 const node_datas = tree.nodes.items(.data);2019 const node_datas = tree.nodes.items(.data);
...@@ -1967,10 +2021,7 @@ pub fn fieldAccess(...@@ -1967,10 +2021,7 @@ pub fn fieldAccess(
1967 const object_node = node_datas[node].lhs;2021 const object_node = node_datas[node].lhs;
1968 const dot_token = main_tokens[node];2022 const dot_token = main_tokens[node];
1969 const field_ident = dot_token + 1;2023 const field_ident = dot_token + 1;
1970 const string_bytes = &gz.astgen.string_bytes;2024 const str_index = try gz.identAsString(field_ident);
1971 const str_index = @intCast(u32, string_bytes.items.len);
1972 try mod.appendIdentStr(scope, field_ident, string_bytes);
1973 try string_bytes.append(mod.gpa, 0);
1974 switch (rl) {2025 switch (rl) {
1975 .ref => return gz.addPlNode(.field_ptr, node, zir.Inst.Field{2026 .ref => return gz.addPlNode(.field_ptr, node, zir.Inst.Field{
1976 .lhs = try expr(gz, scope, .ref, object_node),2027 .lhs = try expr(gz, scope, .ref, object_node),
...@@ -2031,11 +2082,7 @@ fn simpleStrTok(...@@ -2031,11 +2082,7 @@ fn simpleStrTok(
2031 node: ast.Node.Index,2082 node: ast.Node.Index,
2032 op_inst_tag: zir.Inst.Tag,2083 op_inst_tag: zir.Inst.Tag,
2033) InnerError!zir.Inst.Ref {2084) InnerError!zir.Inst.Ref {
2034 const mod = gz.astgen.mod;2085 const str_index = try gz.identAsString(ident_token);
2035 const string_bytes = &gz.astgen.string_bytes;
2036 const str_index = @intCast(u32, string_bytes.items.len);
2037 try mod.appendIdentStr(scope, ident_token, string_bytes);
2038 try string_bytes.append(mod.gpa, 0);
2039 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);2086 const result = try gz.addStrTok(op_inst_tag, str_index, ident_token);
2040 return rvalue(gz, scope, rl, result, node);2087 return rvalue(gz, scope, rl, result, node);
2041}2088}
src/Module.zig+10
...@@ -1046,6 +1046,16 @@ pub const Scope = struct {...@@ -1046,6 +1046,16 @@ pub const Scope = struct {
1046 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);1046 gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
1047 }1047 }
10481048
1049 pub fn identAsString(gz: *GenZir, ident_token: ast.TokenIndex) !u32 {
1050 const astgen = gz.astgen;
1051 const gpa = astgen.mod.gpa;
1052 const string_bytes = &astgen.string_bytes;
1053 const str_index = @intCast(u32, string_bytes.items.len);
1054 try astgen.mod.appendIdentStr(&gz.base, ident_token, string_bytes);
1055 try string_bytes.append(gpa, 0);
1056 return str_index;
1057 }
1058
1049 pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct {1059 pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
1050 src_node: ast.Node.Index,1060 src_node: ast.Node.Index,
1051 param_types: []const zir.Inst.Ref,1061 param_types: []const zir.Inst.Ref,
src/Sema.zig+16
...@@ -326,6 +326,10 @@ pub fn analyzeBody(...@@ -326,6 +326,10 @@ pub fn analyzeBody(
326 try sema.zirResolveInferredAlloc(block, inst);326 try sema.zirResolveInferredAlloc(block, inst);
327 continue;327 continue;
328 },328 },
329 .validate_struct_init_ptr => {
330 try sema.zirValidateStructInitPtr(block, inst);
331 continue;
332 },
329333
330 // Special case instructions to handle comptime control flow.334 // Special case instructions to handle comptime control flow.
331 .repeat_inline => {335 .repeat_inline => {
...@@ -694,6 +698,18 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde...@@ -694,6 +698,18 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Inde
694 ptr.tag = .alloc;698 ptr.tag = .alloc;
695}699}
696700
701fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
702 const tracy = trace(@src());
703 defer tracy.end();
704
705 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
706 const src = inst_data.src();
707 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
708 const instrs = sema.code.extra[extra.end..][0..extra.data.body_len];
709
710 return sema.mod.fail(&block.base, src, "TODO implement zirValidateStructInitPtr", .{});
711}
712
697fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {713fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
698 const tracy = trace(@src());714 const tracy = trace(@src());
699 defer tracy.end();715 defer tracy.end();
src/zir.zig+7
...@@ -637,6 +637,11 @@ pub const Inst = struct {...@@ -637,6 +637,11 @@ pub const Inst = struct {
637 /// Result is a pointer to the value.637 /// Result is a pointer to the value.
638 /// Uses the `switch_capture` field.638 /// Uses the `switch_capture` field.
639 switch_capture_else_ref,639 switch_capture_else_ref,
640 /// Given a set of `field_ptr` instructions, assumes they are all part of a struct
641 /// initialization expression, and emits compile errors for duplicate fields
642 /// as well as missing fields, if applicable.
643 /// Uses the `pl_node` field. Payload is `Block`.
644 validate_struct_init_ptr,
640645
641 /// Returns whether the instruction is one of the control flow "noreturn" types.646 /// Returns whether the instruction is one of the control flow "noreturn" types.
642 /// Function calls do not count.647 /// Function calls do not count.
...@@ -784,6 +789,7 @@ pub const Inst = struct {...@@ -784,6 +789,7 @@ pub const Inst = struct {
784 .switch_block_ref_else_multi,789 .switch_block_ref_else_multi,
785 .switch_block_ref_under,790 .switch_block_ref_under,
786 .switch_block_ref_under_multi,791 .switch_block_ref_under_multi,
792 .validate_struct_init_ptr,
787 => false,793 => false,
788794
789 .@"break",795 .@"break",
...@@ -1568,6 +1574,7 @@ const Writer = struct {...@@ -1568,6 +1574,7 @@ const Writer = struct {
1568 .block,1574 .block,
1569 .block_inline,1575 .block_inline,
1570 .loop,1576 .loop,
1577 .validate_struct_init_ptr,
1571 => try self.writePlNodeBlock(stream, inst),1578 => try self.writePlNodeBlock(stream, inst),
15721579
1573 .condbr,1580 .condbr,