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(...@@ -4386,6 +4386,7 @@ fn structDeclInner(
4386 .backing_int_body_len = 0,4386 .backing_int_body_len = 0,
4387 .known_non_opv = false,4387 .known_non_opv = false,
4388 .known_comptime_only = false,4388 .known_comptime_only = false,
4389 .is_tuple = false,
4389 });4390 });
4390 return indexToRef(decl_inst);4391 return indexToRef(decl_inst);
4391 }4392 }
...@@ -4467,22 +4468,59 @@ fn structDeclInner(...@@ -4467,22 +4468,59 @@ fn structDeclInner(
4467 // No defer needed here because it is handled by `wip_members.deinit()` above.4468 // No defer needed here because it is handled by `wip_members.deinit()` above.
4468 const bodies_start = astgen.scratch.items.len;4469 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
4470 var known_non_opv = false;4495 var known_non_opv = false;
4471 var known_comptime_only = false;4496 var known_comptime_only = false;
4472 for (container_decl.ast.members) |member_node| {4497 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)) {
4474 .decl => continue,4499 .decl => continue,
4475 .field => |field| field,4500 .field => |field| field,
4476 };4501 };
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);4513 if (!is_tuple) {
4479 wip_members.appendToField(field_name);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
4481 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());4519 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
4482 wip_members.appendToField(doc_comment_index);4520 wip_members.appendToField(doc_comment_index);
44834521
4484 if (member.ast.type_expr == 0) {4522 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", .{});
4486 }4524 }
44874525
4488 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);4526 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
...@@ -4562,6 +4600,7 @@ fn structDeclInner(...@@ -4562,6 +4600,7 @@ fn structDeclInner(
4562 .backing_int_body_len = @intCast(u32, backing_int_body_len),4600 .backing_int_body_len = @intCast(u32, backing_int_body_len),
4563 .known_non_opv = known_non_opv,4601 .known_non_opv = known_non_opv,
4564 .known_comptime_only = known_comptime_only,4602 .known_comptime_only = known_comptime_only,
4603 .is_tuple = is_tuple,
4565 });4604 });
45664605
4567 wip_members.finishBits(bits_per_field);4606 wip_members.finishBits(bits_per_field);
...@@ -4640,15 +4679,25 @@ fn unionDeclInner(...@@ -4640,15 +4679,25 @@ fn unionDeclInner(
4640 defer wip_members.deinit();4679 defer wip_members.deinit();
46414680
4642 for (members) |member_node| {4681 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)) {
4644 .decl => continue,4683 .decl => continue,
4645 .field => |field| field,4684 .field => |field| field,
4646 };4685 };
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 }
4647 if (member.comptime_token) |comptime_token| {4696 if (member.comptime_token) |comptime_token| {
4648 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});4697 return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
4649 }4698 }
46504699
4651 const field_name = try astgen.identAsString(member.ast.name_token);4700 const field_name = try astgen.identAsString(member.ast.main_token);
4652 wip_members.appendToField(field_name);4701 wip_members.appendToField(field_name);
46534702
4654 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());4703 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
...@@ -4787,7 +4836,7 @@ fn containerDecl(...@@ -4787,7 +4836,7 @@ fn containerDecl(
4787 var nonexhaustive_node: Ast.Node.Index = 0;4836 var nonexhaustive_node: Ast.Node.Index = 0;
4788 var nonfinal_nonexhaustive = false;4837 var nonfinal_nonexhaustive = false;
4789 for (container_decl.ast.members) |member_node| {4838 for (container_decl.ast.members) |member_node| {
4790 const member = switch (node_tags[member_node]) {4839 var member = switch (node_tags[member_node]) {
4791 .container_field_init => tree.containerFieldInit(member_node),4840 .container_field_init => tree.containerFieldInit(member_node),
4792 .container_field_align => tree.containerFieldAlign(member_node),4841 .container_field_align => tree.containerFieldAlign(member_node),
4793 .container_field => tree.containerField(member_node),4842 .container_field => tree.containerField(member_node),
...@@ -4796,6 +4845,16 @@ fn containerDecl(...@@ -4796,6 +4845,16 @@ fn containerDecl(
4796 continue;4845 continue;
4797 },4846 },
4798 };4847 };
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 }
4799 if (member.comptime_token) |comptime_token| {4858 if (member.comptime_token) |comptime_token| {
4800 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});4859 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
4801 }4860 }
...@@ -4816,7 +4875,7 @@ fn containerDecl(...@@ -4816,7 +4875,7 @@ fn containerDecl(
4816 // Alignment expressions in enums are caught by the parser.4875 // Alignment expressions in enums are caught by the parser.
4817 assert(member.ast.align_expr == 0);4876 assert(member.ast.align_expr == 0);
48184877
4819 const name_token = member.ast.name_token;4878 const name_token = member.ast.main_token;
4820 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {4879 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
4821 if (nonexhaustive_node != 0) {4880 if (nonexhaustive_node != 0) {
4822 return astgen.failNodeNotes(4881 return astgen.failNodeNotes(
...@@ -4915,15 +4974,23 @@ fn containerDecl(...@@ -4915,15 +4974,23 @@ fn containerDecl(
4915 for (container_decl.ast.members) |member_node| {4974 for (container_decl.ast.members) |member_node| {
4916 if (member_node == counts.nonexhaustive_node)4975 if (member_node == counts.nonexhaustive_node)
4917 continue;4976 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)) {
4919 .decl => continue,4978 .decl => continue,
4920 .field => |field| field,4979 .field => |field| field,
4921 };4980 };
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 }
4922 assert(member.comptime_token == null);4989 assert(member.comptime_token == null);
4923 assert(member.ast.type_expr == 0);4990 assert(member.ast.type_expr == 0);
4924 assert(member.ast.align_expr == 0);4991 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);
4927 wip_members.appendToField(field_name);4994 wip_members.appendToField(field_name);
49284995
4929 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());4996 const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
...@@ -11786,6 +11853,7 @@ const GenZir = struct {...@@ -11786,6 +11853,7 @@ const GenZir = struct {
11786 layout: std.builtin.Type.ContainerLayout,11853 layout: std.builtin.Type.ContainerLayout,
11787 known_non_opv: bool,11854 known_non_opv: bool,
11788 known_comptime_only: bool,11855 known_comptime_only: bool,
11856 is_tuple: bool,
11789 }) !void {11857 }) !void {
11790 const astgen = gz.astgen;11858 const astgen = gz.astgen;
11791 const gpa = astgen.gpa;11859 const gpa = astgen.gpa;
...@@ -11820,6 +11888,7 @@ const GenZir = struct {...@@ -11820,6 +11888,7 @@ const GenZir = struct {
11820 .has_backing_int = args.backing_int_ref != .none,11888 .has_backing_int = args.backing_int_ref != .none,
11821 .known_non_opv = args.known_non_opv,11889 .known_non_opv = args.known_non_opv,
11822 .known_comptime_only = args.known_comptime_only,11890 .known_comptime_only = args.known_comptime_only,
11891 .is_tuple = args.is_tuple,
11823 .name_strategy = gz.anon_name_strategy,11892 .name_strategy = gz.anon_name_strategy,
11824 .layout = args.layout,11893 .layout = args.layout,
11825 }),11894 }),
src/Module.zig+1-1
...@@ -6138,7 +6138,7 @@ fn queryFieldSrc(...@@ -6138,7 +6138,7 @@ fn queryFieldSrc(
6138 .name => .{6138 .name => .{
6139 .file_scope = file_scope,6139 .file_scope = file_scope,
6140 .parent_decl_node = 0,6140 .parent_decl_node = 0,
6141 .lazy = .{ .token_abs = field.ast.name_token },6141 .lazy = .{ .token_abs = field.ast.main_token },
6142 },6142 },
6143 .type => .{6143 .type => .{
6144 .file_scope = file_scope,6144 .file_scope = file_scope,
src/Zir.zig+3-2
...@@ -3166,7 +3166,7 @@ pub const Inst = struct {...@@ -3166,7 +3166,7 @@ pub const Inst = struct {
3166 /// 0b0X00: whether corresponding field is comptime3166 /// 0b0X00: whether corresponding field is comptime
3167 /// 0bX000: whether corresponding field has a type expression3167 /// 0bX000: whether corresponding field has a type expression
3168 /// 9. fields: { // for every fields_len3168 /// 9. fields: { // for every fields_len
3169 /// field_name: u32,3169 /// field_name: u32, // if !is_tuple
3170 /// doc_comment: u32, // 0 if no doc comment3170 /// doc_comment: u32, // 0 if no doc comment
3171 /// field_type: Ref, // if corresponding bit is not set. none means anytype.3171 /// field_type: Ref, // if corresponding bit is not set. none means anytype.
3172 /// field_type_body_len: u32, // if corresponding bit is set3172 /// field_type_body_len: u32, // if corresponding bit is set
...@@ -3186,9 +3186,10 @@ pub const Inst = struct {...@@ -3186,9 +3186,10 @@ pub const Inst = struct {
3186 has_backing_int: bool,3186 has_backing_int: bool,
3187 known_non_opv: bool,3187 known_non_opv: bool,
3188 known_comptime_only: bool,3188 known_comptime_only: bool,
3189 is_tuple: bool,
3189 name_strategy: NameStrategy,3190 name_strategy: NameStrategy,
3190 layout: std.builtin.Type.ContainerLayout,3191 layout: std.builtin.Type.ContainerLayout,
3191 _: u6 = undefined,3192 _: u5 = undefined,
3192 };3193 };
3193 };3194 };
31943195
src/print_zir.zig+13-6
...@@ -1262,6 +1262,7 @@ const Writer = struct {...@@ -1262,6 +1262,7 @@ const Writer = struct {
12621262
1263 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);1263 try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
1264 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);1264 try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
1265 try self.writeFlag(stream, "tuple, ", small.is_tuple);
12651266
1266 try stream.print("{s}, ", .{@tagName(small.name_strategy)});1267 try stream.print("{s}, ", .{@tagName(small.name_strategy)});
12671268
...@@ -1335,8 +1336,11 @@ const Writer = struct {...@@ -1335,8 +1336,11 @@ const Writer = struct {
1335 const has_type_body = @truncate(u1, cur_bit_bag) != 0;1336 const has_type_body = @truncate(u1, cur_bit_bag) != 0;
1336 cur_bit_bag >>= 1;1337 cur_bit_bag >>= 1;
13371338
1338 const field_name = self.code.extra[extra_index];1339 var field_name: u32 = 0;
1339 extra_index += 1;1340 if (!small.is_tuple) {
1341 field_name = self.code.extra[extra_index];
1342 extra_index += 1;
1343 }
1340 const doc_comment_index = self.code.extra[extra_index];1344 const doc_comment_index = self.code.extra[extra_index];
1341 extra_index += 1;1345 extra_index += 1;
13421346
...@@ -1370,13 +1374,16 @@ const Writer = struct {...@@ -1370,13 +1374,16 @@ const Writer = struct {
1370 try stream.writeAll("{\n");1374 try stream.writeAll("{\n");
1371 self.indent += 2;1375 self.indent += 2;
13721376
1373 for (fields) |field| {1377 for (fields) |field, i| {
1374 const field_name = self.code.nullTerminatedString(field.name);
1375
1376 try self.writeDocComment(stream, field.doc_comment_index);1378 try self.writeDocComment(stream, field.doc_comment_index);
1377 try stream.writeByteNTimes(' ', self.indent);1379 try stream.writeByteNTimes(' ', self.indent);
1378 try self.writeFlag(stream, "comptime ", field.is_comptime);1380 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 }
1380 if (field.field_type != .none) {1387 if (field.field_type != .none) {
1381 try self.writeInstRef(stream, field.field_type);1388 try self.writeInstRef(stream, field.field_type);
1382 }1389 }