authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-22 00:23:08+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-23 12:13:39+02:00
log80575face7a3b1e0f47e413507a6fa8b1d002e57
tree312aa0ddf6dc53634f626adda28d8fbbfd82ab81
parent6fb689e97a4ec05fd97dfa05cc203e9bcb7cffa1

AstGen: implement tuple declarations


4 files changed, 96 insertions(+), 19 deletions(-)

src/AstGen.zig+79-10
......@@ -4386,6 +4386,7 @@ fn structDeclInner(
43864386 .backing_int_body_len = 0,
43874387 .known_non_opv = false,
43884388 .known_comptime_only = false,
4389 .is_tuple = false,
43894390 });
43904391 return indexToRef(decl_inst);
43914392 }
......@@ -4467,22 +4468,59 @@ fn structDeclInner(
44674468 // No defer needed here because it is handled by `wip_members.deinit()` above.
44684469 const bodies_start = astgen.scratch.items.len;
44694470
4471 var is_tuple = false;
4472 const node_tags = tree.nodes.items(.tag);
4473 for (container_decl.ast.members) |member_node| {
4474 switch (node_tags[member_node]) {
4475 .container_field_init => is_tuple = tree.containerFieldInit(member_node).ast.tuple_like,
4476 .container_field_align => is_tuple = tree.containerFieldAlign(member_node).ast.tuple_like,
4477 .container_field => is_tuple = tree.containerField(member_node).ast.tuple_like,
4478 else => continue,
4479 }
4480 if (is_tuple) break;
4481 }
4482 if (is_tuple) for (container_decl.ast.members) |member_node| {
4483 switch (node_tags[member_node]) {
4484 .container_field_init,
4485 .container_field_align,
4486 .container_field,
4487 .@"comptime",
4488 => continue,
4489 else => {
4490 return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{});
4491 },
4492 }
4493 };
4494
44704495 var known_non_opv = false;
44714496 var known_comptime_only = false;
44724497 for (container_decl.ast.members) |member_node| {
4473 const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
4498 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
44744499 .decl => continue,
44754500 .field => |field| field,
44764501 };
4502 if (member.ast.tuple_like and !is_tuple and member.ast.type_expr != 0 and
4503 astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
4504 {
4505 const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
4506 member.ast.tuple_like = false;
4507 member.ast.main_token = ident;
4508 member.ast.type_expr = 0;
4509 } else if (is_tuple and !member.ast.tuple_like) {
4510 return astgen.failTok(member.ast.main_token, "tuple field has a name", .{});
4511 }
44774512
4478 const field_name = try astgen.identAsString(member.ast.name_token);
4479 wip_members.appendToField(field_name);
4513 if (!is_tuple) {
4514 if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "struct field missing name", .{});
4515 const field_name = try astgen.identAsString(member.ast.main_token);
4516 wip_members.appendToField(field_name);
4517 }
44804518
44814519 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
44824520 wip_members.appendToField(doc_comment_index);
44834521
44844522 if (member.ast.type_expr == 0) {
4485 return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
4523 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
44864524 }
44874525
44884526 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
......@@ -4562,6 +4600,7 @@ fn structDeclInner(
45624600 .backing_int_body_len = @intCast(u32, backing_int_body_len),
45634601 .known_non_opv = known_non_opv,
45644602 .known_comptime_only = known_comptime_only,
4603 .is_tuple = is_tuple,
45654604 });
45664605
45674606 wip_members.finishBits(bits_per_field);
......@@ -4640,15 +4679,25 @@ fn unionDeclInner(
46404679 defer wip_members.deinit();
46414680
46424681 for (members) |member_node| {
4643 const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
4682 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
46444683 .decl => continue,
46454684 .field => |field| field,
46464685 };
4686 if (member.ast.tuple_like and member.ast.type_expr != 0 and
4687 astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
4688 {
4689 const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
4690 member.ast.tuple_like = false;
4691 member.ast.main_token = ident;
4692 member.ast.type_expr = 0;
4693 } else if (member.ast.tuple_like) {
4694 return astgen.failTok(member.ast.main_token, "union field missing name", .{});
4695 }
46474696 if (member.comptime_token) |comptime_token| {
46484697 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
46494698 }
46504699
4651 const field_name = try astgen.identAsString(member.ast.name_token);
4700 const field_name = try astgen.identAsString(member.ast.main_token);
46524701 wip_members.appendToField(field_name);
46534702
46544703 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
......@@ -4787,7 +4836,7 @@ fn containerDecl(
47874836 var nonexhaustive_node: Ast.Node.Index = 0;
47884837 var nonfinal_nonexhaustive = false;
47894838 for (container_decl.ast.members) |member_node| {
4790 const member = switch (node_tags[member_node]) {
4839 var member = switch (node_tags[member_node]) {
47914840 .container_field_init => tree.containerFieldInit(member_node),
47924841 .container_field_align => tree.containerFieldAlign(member_node),
47934842 .container_field => tree.containerField(member_node),
......@@ -4796,6 +4845,16 @@ fn containerDecl(
47964845 continue;
47974846 },
47984847 };
4848 if (member.ast.tuple_like and member.ast.type_expr != 0 and
4849 astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
4850 {
4851 const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
4852 member.ast.tuple_like = false;
4853 member.ast.main_token = ident;
4854 member.ast.type_expr = 0;
4855 } else if (member.ast.tuple_like) {
4856 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
4857 }
47994858 if (member.comptime_token) |comptime_token| {
48004859 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
48014860 }
......@@ -4816,7 +4875,7 @@ fn containerDecl(
48164875 // Alignment expressions in enums are caught by the parser.
48174876 assert(member.ast.align_expr == 0);
48184877
4819 const name_token = member.ast.name_token;
4878 const name_token = member.ast.main_token;
48204879 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
48214880 if (nonexhaustive_node != 0) {
48224881 return astgen.failNodeNotes(
......@@ -4915,15 +4974,23 @@ fn containerDecl(
49154974 for (container_decl.ast.members) |member_node| {
49164975 if (member_node == counts.nonexhaustive_node)
49174976 continue;
4918 const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
4977 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
49194978 .decl => continue,
49204979 .field => |field| field,
49214980 };
4981 if (member.ast.tuple_like and member.ast.type_expr != 0 and
4982 astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
4983 {
4984 const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
4985 member.ast.tuple_like = false;
4986 member.ast.main_token = ident;
4987 member.ast.type_expr = 0;
4988 }
49224989 assert(member.comptime_token == null);
49234990 assert(member.ast.type_expr == 0);
49244991 assert(member.ast.align_expr == 0);
49254992
4926 const field_name = try astgen.identAsString(member.ast.name_token);
4993 const field_name = try astgen.identAsString(member.ast.main_token);
49274994 wip_members.appendToField(field_name);
49284995
49294996 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
......@@ -11786,6 +11853,7 @@ const GenZir = struct {
1178611853 layout: std.builtin.Type.ContainerLayout,
1178711854 known_non_opv: bool,
1178811855 known_comptime_only: bool,
11856 is_tuple: bool,
1178911857 }) !void {
1179011858 const astgen = gz.astgen;
1179111859 const gpa = astgen.gpa;
......@@ -11820,6 +11888,7 @@ const GenZir = struct {
1182011888 .has_backing_int = args.backing_int_ref != .none,
1182111889 .known_non_opv = args.known_non_opv,
1182211890 .known_comptime_only = args.known_comptime_only,
11891 .is_tuple = args.is_tuple,
1182311892 .name_strategy = gz.anon_name_strategy,
1182411893 .layout = args.layout,
1182511894 }),
src/Module.zig+1-1
......@@ -6138,7 +6138,7 @@ fn queryFieldSrc(
61386138 .name => .{
61396139 .file_scope = file_scope,
61406140 .parent_decl_node = 0,
6141 .lazy = .{ .token_abs = field.ast.name_token },
6141 .lazy = .{ .token_abs = field.ast.main_token },
61426142 },
61436143 .type => .{
61446144 .file_scope = file_scope,
src/Zir.zig+3-2
......@@ -3166,7 +3166,7 @@ pub const Inst = struct {
31663166 /// 0b0X00: whether corresponding field is comptime
31673167 /// 0bX000: whether corresponding field has a type expression
31683168 /// 9. fields: { // for every fields_len
3169 /// field_name: u32,
3169 /// field_name: u32, // if !is_tuple
31703170 /// doc_comment: u32, // 0 if no doc comment
31713171 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
31723172 /// field_type_body_len: u32, // if corresponding bit is set
......@@ -3186,9 +3186,10 @@ pub const Inst = struct {
31863186 has_backing_int: bool,
31873187 known_non_opv: bool,
31883188 known_comptime_only: bool,
3189 is_tuple: bool,
31893190 name_strategy: NameStrategy,
31903191 layout: std.builtin.Type.ContainerLayout,
3191 _: u6 = undefined,
3192 _: u5 = undefined,
31923193 };
31933194 };
31943195
src/print_zir.zig+13-6
......@@ -1262,6 +1262,7 @@ const Writer = struct {
12621262
12631263 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
12641264 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
1265 try self.writeFlag(stream, "tuple, ", small.is_tuple);
12651266
12661267 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
12671268
......@@ -1335,8 +1336,11 @@ const Writer = struct {
13351336 const has_type_body = @truncate(u1, cur_bit_bag) != 0;
13361337 cur_bit_bag >>= 1;
13371338
1338 const field_name = self.code.extra[extra_index];
1339 extra_index += 1;
1339 var field_name: u32 = 0;
1340 if (!small.is_tuple) {
1341 field_name = self.code.extra[extra_index];
1342 extra_index += 1;
1343 }
13401344 const doc_comment_index = self.code.extra[extra_index];
13411345 extra_index += 1;
13421346
......@@ -1370,13 +1374,16 @@ const Writer = struct {
13701374 try stream.writeAll("{\n");
13711375 self.indent += 2;
13721376
1373 for (fields) |field| {
1374 const field_name = self.code.nullTerminatedString(field.name);
1375
1377 for (fields) |field, i| {
13761378 try self.writeDocComment(stream, field.doc_comment_index);
13771379 try stream.writeByteNTimes(' ', self.indent);
13781380 try self.writeFlag(stream, "comptime ", field.is_comptime);
1379 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
1381 if (field.name != 0) {
1382 const field_name = self.code.nullTerminatedString(field.name);
1383 try stream.print("{}: ", .{std.zig.fmtId(field_name)});
1384 } else {
1385 try stream.print("@\"{d}\": ", .{i});
1386 }
13801387 if (field.field_type != .none) {
13811388 try self.writeInstRef(stream, field.field_type);
13821389 }