authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-03-12 02:22:41+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-03-12 02:22:41+00:00
logd0911786c95dfa7a63ec348bb4a9870da12f62e4
treec2ee731b2fcb53504dbade8077084bf935197c06
parenta0401cf3e4aed014abc1189890f4c1c756a12737
parent4129f7ff5a03cb3cd85a3ad5e3360098ab8ed796
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #22397 from Techatrix/type-safe-ast

improve type safety of std.zig.Ast

26 files changed, 5404 insertions(+), 5704 deletions(-)

lib/compiler/aro_translate_c/ast.zig+383-440
......@@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
775775 ctx.nodes.appendAssumeCapacity(.{
776776 .tag = .root,
777777 .main_token = 0,
778 .data = .{
779 .lhs = undefined,
780 .rhs = undefined,
781 },
778 .data = undefined,
782779 });
783780
784781 const root_members = blk: {
......@@ -793,10 +790,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
793790 break :blk try ctx.listToSpan(result.items);
794791 };
795792
796 ctx.nodes.items(.data)[0] = .{
797 .lhs = root_members.start,
798 .rhs = root_members.end,
799 };
793 ctx.nodes.items(.data)[0] = .{ .extra_range = root_members };
800794
801795 try ctx.tokens.append(gpa, .{
802796 .tag = .eof,
......@@ -814,15 +808,18 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
814808}
815809
816810const NodeIndex = std.zig.Ast.Node.Index;
811const NodeOptionalIndex = std.zig.Ast.Node.OptionalIndex;
817812const NodeSubRange = std.zig.Ast.Node.SubRange;
818813const TokenIndex = std.zig.Ast.TokenIndex;
814const TokenOptionalIndex = std.zig.Ast.OptionalTokenIndex;
819815const TokenTag = std.zig.Token.Tag;
816const ExtraIndex = std.zig.Ast.ExtraIndex;
820817
821818const Context = struct {
822819 gpa: Allocator,
823820 buf: std.ArrayList(u8),
824821 nodes: std.zig.Ast.NodeList = .{},
825 extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .empty,
822 extra_data: std.ArrayListUnmanaged(u32) = .empty,
826823 tokens: std.zig.Ast.TokenList = .{},
827824
828825 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
......@@ -834,7 +831,7 @@ const Context = struct {
834831 .start = @as(u32, @intCast(start_index)),
835832 });
836833
837 return @as(u32, @intCast(c.tokens.len - 1));
834 return @intCast(c.tokens.len - 1);
838835 }
839836
840837 fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {
......@@ -848,26 +845,33 @@ const Context = struct {
848845 }
849846
850847 fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {
851 try c.extra_data.appendSlice(c.gpa, list);
848 try c.extra_data.appendSlice(c.gpa, @ptrCast(list));
852849 return NodeSubRange{
853 .start = @as(NodeIndex, @intCast(c.extra_data.items.len - list.len)),
854 .end = @as(NodeIndex, @intCast(c.extra_data.items.len)),
850 .start = @enumFromInt(c.extra_data.items.len - list.len),
851 .end = @enumFromInt(c.extra_data.items.len),
855852 };
856853 }
857854
858855 fn addNode(c: *Context, elem: std.zig.Ast.Node) Allocator.Error!NodeIndex {
859 const result = @as(NodeIndex, @intCast(c.nodes.len));
856 const result: NodeIndex = @enumFromInt(c.nodes.len);
860857 try c.nodes.append(c.gpa, elem);
861858 return result;
862859 }
863860
864 fn addExtra(c: *Context, extra: anytype) Allocator.Error!NodeIndex {
861 fn addExtra(c: *Context, extra: anytype) Allocator.Error!std.zig.Ast.ExtraIndex {
865862 const fields = std.meta.fields(@TypeOf(extra));
866863 try c.extra_data.ensureUnusedCapacity(c.gpa, fields.len);
867 const result = @as(u32, @intCast(c.extra_data.items.len));
864 const result: ExtraIndex = @enumFromInt(c.extra_data.items.len);
868865 inline for (fields) |field| {
869 comptime std.debug.assert(field.type == NodeIndex);
870 c.extra_data.appendAssumeCapacity(@field(extra, field.name));
866 switch (field.type) {
867 NodeIndex,
868 NodeOptionalIndex,
869 TokenIndex,
870 TokenOptionalIndex,
871 ExtraIndex,
872 => c.extra_data.appendAssumeCapacity(@intFromEnum(@field(extra, field.name))),
873 else => @compileError("unexpected field type"),
874 }
871875 }
872876 return result;
873877 }
......@@ -894,7 +898,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
894898 try c.buf.append('\n');
895899 try c.buf.appendSlice(payload);
896900 try c.buf.append('\n');
897 return @as(NodeIndex, 0); // error: integer value 0 cannot be coerced to type 'std.mem.Allocator.Error!u32'
901 return @enumFromInt(0);
898902 },
899903 .helpers_cast => {
900904 const payload = node.castTag(.helpers_cast).?.data;
......@@ -991,26 +995,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
991995 .@"continue" => return c.addNode(.{
992996 .tag = .@"continue",
993997 .main_token = try c.addToken(.keyword_continue, "continue"),
994 .data = .{
995 .lhs = 0,
996 .rhs = undefined,
997 },
998 .data = .{ .opt_token_and_opt_node = .{ .none, .none } },
998999 }),
9991000 .return_void => return c.addNode(.{
10001001 .tag = .@"return",
10011002 .main_token = try c.addToken(.keyword_return, "return"),
1002 .data = .{
1003 .lhs = 0,
1004 .rhs = undefined,
1005 },
1003 .data = .{ .opt_node = .none },
10061004 }),
10071005 .@"break" => return c.addNode(.{
10081006 .tag = .@"break",
10091007 .main_token = try c.addToken(.keyword_break, "break"),
1010 .data = .{
1011 .lhs = 0,
1012 .rhs = 0,
1013 },
1008 .data = .{ .opt_token_and_opt_node = .{ .none, .none } },
10141009 }),
10151010 .break_val => {
10161011 const payload = node.castTag(.break_val).?.data;
......@@ -1018,14 +1013,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10181013 const break_label = if (payload.label) |some| blk: {
10191014 _ = try c.addToken(.colon, ":");
10201015 break :blk try c.addIdentifier(some);
1021 } else 0;
1016 } else null;
10221017 return c.addNode(.{
10231018 .tag = .@"break",
10241019 .main_token = tok,
1025 .data = .{
1026 .lhs = break_label,
1027 .rhs = try renderNode(c, payload.val),
1028 },
1020 .data = .{ .opt_token_and_opt_node = .{
1021 .fromOptional(break_label),
1022 (try renderNode(c, payload.val)).toOptional(),
1023 } },
10291024 });
10301025 },
10311026 .@"return" => {
......@@ -1033,10 +1028,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10331028 return c.addNode(.{
10341029 .tag = .@"return",
10351030 .main_token = try c.addToken(.keyword_return, "return"),
1036 .data = .{
1037 .lhs = try renderNode(c, payload),
1038 .rhs = undefined,
1039 },
1031 .data = .{ .opt_node = (try renderNode(c, payload)).toOptional() },
10401032 });
10411033 },
10421034 .@"comptime" => {
......@@ -1044,10 +1036,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10441036 return c.addNode(.{
10451037 .tag = .@"comptime",
10461038 .main_token = try c.addToken(.keyword_comptime, "comptime"),
1047 .data = .{
1048 .lhs = try renderNode(c, payload),
1049 .rhs = undefined,
1050 },
1039 .data = .{ .node = try renderNode(c, payload) },
10511040 });
10521041 },
10531042 .@"defer" => {
......@@ -1055,10 +1044,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10551044 return c.addNode(.{
10561045 .tag = .@"defer",
10571046 .main_token = try c.addToken(.keyword_defer, "defer"),
1058 .data = .{
1059 .lhs = undefined,
1060 .rhs = try renderNode(c, payload),
1061 },
1047 .data = .{ .node = try renderNode(c, payload) },
10621048 });
10631049 },
10641050 .asm_simple => {
......@@ -1068,10 +1054,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10681054 return c.addNode(.{
10691055 .tag = .asm_simple,
10701056 .main_token = asm_token,
1071 .data = .{
1072 .lhs = try renderNode(c, payload),
1073 .rhs = try c.addToken(.r_paren, ")"),
1074 },
1057 .data = .{ .node_and_token = .{
1058 try renderNode(c, payload),
1059 try c.addToken(.r_paren, ")"),
1060 } },
10751061 });
10761062 },
10771063 .type => {
......@@ -1104,10 +1090,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
11041090 return c.addNode(.{
11051091 .tag = .address_of,
11061092 .main_token = tok,
1107 .data = .{
1108 .lhs = arg,
1109 .rhs = undefined,
1110 },
1093 .data = .{ .node = arg },
11111094 });
11121095 },
11131096 .float_literal => {
......@@ -1191,13 +1174,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
11911174 return c.addNode(.{
11921175 .tag = .slice,
11931176 .main_token = l_bracket,
1194 .data = .{
1195 .lhs = string,
1196 .rhs = try c.addExtra(std.zig.Ast.Node.Slice{
1177 .data = .{ .node_and_extra = .{
1178 string,
1179 try c.addExtra(std.zig.Ast.Node.Slice{
11971180 .start = start,
11981181 .end = end,
11991182 }),
1200 },
1183 } },
12011184 });
12021185 },
12031186 .fail_decl => {
......@@ -1220,20 +1203,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12201203 const compile_error = try c.addNode(.{
12211204 .tag = .builtin_call_two,
12221205 .main_token = compile_error_tok,
1223 .data = .{
1224 .lhs = err_msg,
1225 .rhs = 0,
1226 },
1206 .data = .{ .opt_node_and_opt_node = .{ err_msg.toOptional(), .none } },
12271207 });
12281208 _ = try c.addToken(.semicolon, ";");
12291209
12301210 return c.addNode(.{
12311211 .tag = .simple_var_decl,
12321212 .main_token = const_tok,
1233 .data = .{
1234 .lhs = 0,
1235 .rhs = compile_error,
1236 },
1213 .data = .{ .opt_node_and_opt_node = .{
1214 .none,
1215 compile_error.toOptional(),
1216 } },
12371217 });
12381218 },
12391219 .pub_var_simple, .var_simple => {
......@@ -1249,10 +1229,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12491229 return c.addNode(.{
12501230 .tag = .simple_var_decl,
12511231 .main_token = const_tok,
1252 .data = .{
1253 .lhs = 0,
1254 .rhs = init,
1255 },
1232 .data = .{ .opt_node_and_opt_node = .{
1233 .none,
1234 init.toOptional(),
1235 } },
12561236 });
12571237 },
12581238 .static_local_var => {
......@@ -1268,10 +1248,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12681248 const container_def = try c.addNode(.{
12691249 .tag = .container_decl_two_trailing,
12701250 .main_token = kind_tok,
1271 .data = .{
1272 .lhs = try renderNode(c, payload.init),
1273 .rhs = 0,
1274 },
1251 .data = .{ .opt_node_and_opt_node = .{
1252 (try renderNode(c, payload.init)).toOptional(),
1253 .none,
1254 } },
12751255 });
12761256 _ = try c.addToken(.r_brace, "}");
12771257 _ = try c.addToken(.semicolon, ";");
......@@ -1279,10 +1259,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12791259 return c.addNode(.{
12801260 .tag = .simple_var_decl,
12811261 .main_token = const_tok,
1282 .data = .{
1283 .lhs = 0,
1284 .rhs = container_def,
1285 },
1262 .data = .{ .opt_node_and_opt_node = .{
1263 .none,
1264 container_def.toOptional(),
1265 } },
12861266 });
12871267 },
12881268 .extern_local_var => {
......@@ -1298,10 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
12981278 const container_def = try c.addNode(.{
12991279 .tag = .container_decl_two_trailing,
13001280 .main_token = kind_tok,
1301 .data = .{
1302 .lhs = try renderNode(c, payload.init),
1303 .rhs = 0,
1304 },
1281 .data = .{ .opt_node_and_opt_node = .{
1282 (try renderNode(c, payload.init)).toOptional(),
1283 .none,
1284 } },
13051285 });
13061286 _ = try c.addToken(.r_brace, "}");
13071287 _ = try c.addToken(.semicolon, ";");
......@@ -1309,10 +1289,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13091289 return c.addNode(.{
13101290 .tag = .simple_var_decl,
13111291 .main_token = const_tok,
1312 .data = .{
1313 .lhs = 0,
1314 .rhs = container_def,
1315 },
1292 .data = .{ .opt_node_and_opt_node = .{
1293 .none,
1294 container_def.toOptional(),
1295 } },
13161296 });
13171297 },
13181298 .mut_str => {
......@@ -1324,10 +1304,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13241304
13251305 const deref = try c.addNode(.{
13261306 .tag = .deref,
1327 .data = .{
1328 .lhs = try renderNodeGrouped(c, payload.init),
1329 .rhs = undefined,
1330 },
1307 .data = .{ .node = try renderNodeGrouped(c, payload.init) },
13311308 .main_token = try c.addToken(.period_asterisk, ".*"),
13321309 });
13331310 _ = try c.addToken(.semicolon, ";");
......@@ -1335,7 +1312,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13351312 return c.addNode(.{
13361313 .tag = .simple_var_decl,
13371314 .main_token = var_tok,
1338 .data = .{ .lhs = 0, .rhs = deref },
1315 .data = .{ .opt_node_and_opt_node = .{
1316 .none,
1317 deref.toOptional(),
1318 } },
13391319 });
13401320 },
13411321 .var_decl => return renderVar(c, node),
......@@ -1359,10 +1339,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13591339 return c.addNode(.{
13601340 .tag = .simple_var_decl,
13611341 .main_token = mut_tok,
1362 .data = .{
1363 .lhs = 0,
1364 .rhs = init,
1365 },
1342 .data = .{ .opt_node_and_opt_node = .{
1343 .none,
1344 init.toOptional(),
1345 } },
13661346 });
13671347 },
13681348 .int_cast => {
......@@ -1505,10 +1485,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
15051485 return c.addNode(.{
15061486 .tag = .address_of,
15071487 .main_token = ampersand,
1508 .data = .{
1509 .lhs = base,
1510 .rhs = undefined,
1511 },
1488 .data = .{ .node = base },
15121489 });
15131490 },
15141491 .deref => {
......@@ -1518,10 +1495,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
15181495 return c.addNode(.{
15191496 .tag = .deref,
15201497 .main_token = deref_tok,
1521 .data = .{
1522 .lhs = operand,
1523 .rhs = undefined,
1524 },
1498 .data = .{ .node = operand },
15251499 });
15261500 },
15271501 .unwrap => {
......@@ -1532,10 +1506,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
15321506 return c.addNode(.{
15331507 .tag = .unwrap_optional,
15341508 .main_token = period,
1535 .data = .{
1536 .lhs = operand,
1537 .rhs = question_mark,
1538 },
1509 .data = .{ .node_and_token = .{
1510 operand,
1511 question_mark,
1512 } },
15391513 });
15401514 },
15411515 .c_pointer, .single_pointer => {
......@@ -1557,10 +1531,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
15571531 return c.addNode(.{
15581532 .tag = .ptr_type_aligned,
15591533 .main_token = main_token,
1560 .data = .{
1561 .lhs = 0,
1562 .rhs = elem_type,
1563 },
1534 .data = .{ .opt_node_and_node = .{
1535 .none,
1536 elem_type,
1537 } },
15641538 });
15651539 },
15661540 .add => return renderBinOpGrouped(c, node, .add, .plus, "+"),
......@@ -1606,10 +1580,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
16061580 return c.addNode(.{
16071581 .tag = .block_two,
16081582 .main_token = l_brace,
1609 .data = .{
1610 .lhs = 0,
1611 .rhs = 0,
1612 },
1583 .data = .{ .opt_node_and_opt_node = .{
1584 .none,
1585 .none,
1586 } },
16131587 });
16141588 },
16151589 .block_single => {
......@@ -1623,10 +1597,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
16231597 return c.addNode(.{
16241598 .tag = .block_two_semicolon,
16251599 .main_token = l_brace,
1626 .data = .{
1627 .lhs = stmt,
1628 .rhs = 0,
1629 },
1600 .data = .{ .opt_node_and_opt_node = .{
1601 stmt.toOptional(),
1602 .none,
1603 } },
16301604 });
16311605 },
16321606 .block => {
......@@ -1641,7 +1615,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
16411615 defer stmts.deinit();
16421616 for (payload.stmts) |stmt| {
16431617 const res = try renderNode(c, stmt);
1644 if (res == 0) continue;
1618 if (@intFromEnum(res) == 0) continue;
16451619 try addSemicolonIfNeeded(c, stmt);
16461620 try stmts.append(res);
16471621 }
......@@ -1652,17 +1626,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
16521626 return c.addNode(.{
16531627 .tag = if (semicolon) .block_semicolon else .block,
16541628 .main_token = l_brace,
1655 .data = .{
1656 .lhs = span.start,
1657 .rhs = span.end,
1658 },
1629 .data = .{ .extra_range = span },
16591630 });
16601631 },
16611632 .func => return renderFunc(c, node),
16621633 .pub_inline_fn => return renderMacroFunc(c, node),
16631634 .discard => {
16641635 const payload = node.castTag(.discard).?.data;
1665 if (payload.should_skip) return @as(NodeIndex, 0);
1636 if (payload.should_skip) return @enumFromInt(0);
16661637
16671638 const lhs = try c.addNode(.{
16681639 .tag = .identifier,
......@@ -1680,19 +1651,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
16801651 return c.addNode(.{
16811652 .tag = .assign,
16821653 .main_token = main_token,
1683 .data = .{
1684 .lhs = lhs,
1685 .rhs = try renderNode(c, addr_of),
1686 },
1654 .data = .{ .node_and_node = .{
1655 lhs,
1656 try renderNode(c, addr_of),
1657 } },
16871658 });
16881659 } else {
16891660 return c.addNode(.{
16901661 .tag = .assign,
16911662 .main_token = main_token,
1692 .data = .{
1693 .lhs = lhs,
1694 .rhs = try renderNode(c, payload.value),
1695 },
1663 .data = .{ .node_and_node = .{
1664 lhs,
1665 try renderNode(c, payload.value),
1666 } },
16961667 });
16971668 }
16981669 },
......@@ -1709,29 +1680,29 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
17091680 const res = try renderNode(c, some);
17101681 _ = try c.addToken(.r_paren, ")");
17111682 break :blk res;
1712 } else 0;
1683 } else null;
17131684 const body = try renderNode(c, payload.body);
17141685
1715 if (cont_expr == 0) {
1686 if (cont_expr == null) {
17161687 return c.addNode(.{
17171688 .tag = .while_simple,
17181689 .main_token = while_tok,
1719 .data = .{
1720 .lhs = cond,
1721 .rhs = body,
1722 },
1690 .data = .{ .node_and_node = .{
1691 cond,
1692 body,
1693 } },
17231694 });
17241695 } else {
17251696 return c.addNode(.{
17261697 .tag = .while_cont,
17271698 .main_token = while_tok,
1728 .data = .{
1729 .lhs = cond,
1730 .rhs = try c.addExtra(std.zig.Ast.Node.WhileCont{
1731 .cont_expr = cont_expr,
1699 .data = .{ .node_and_extra = .{
1700 cond,
1701 try c.addExtra(std.zig.Ast.Node.WhileCont{
1702 .cont_expr = cont_expr.?,
17321703 .then_expr = body,
17331704 }),
1734 },
1705 } },
17351706 });
17361707 }
17371708 },
......@@ -1750,10 +1721,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
17501721 return c.addNode(.{
17511722 .tag = .while_simple,
17521723 .main_token = while_tok,
1753 .data = .{
1754 .lhs = cond,
1755 .rhs = body,
1756 },
1724 .data = .{ .node_and_node = .{
1725 cond,
1726 body,
1727 } },
17571728 });
17581729 },
17591730 .@"if" => {
......@@ -1767,10 +1738,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
17671738 const else_node = payload.@"else" orelse return c.addNode(.{
17681739 .tag = .if_simple,
17691740 .main_token = if_tok,
1770 .data = .{
1771 .lhs = cond,
1772 .rhs = then_expr,
1773 },
1741 .data = .{ .node_and_node = .{
1742 cond,
1743 then_expr,
1744 } },
17741745 });
17751746 _ = try c.addToken(.keyword_else, "else");
17761747 const else_expr = try renderNode(c, else_node);
......@@ -1778,13 +1749,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
17781749 return c.addNode(.{
17791750 .tag = .@"if",
17801751 .main_token = if_tok,
1781 .data = .{
1782 .lhs = cond,
1783 .rhs = try c.addExtra(std.zig.Ast.Node.If{
1752 .data = .{ .node_and_extra = .{
1753 cond,
1754 try c.addExtra(std.zig.Ast.Node.If{
17841755 .then_expr = then_expr,
17851756 .else_expr = else_expr,
17861757 }),
1787 },
1758 } },
17881759 });
17891760 },
17901761 .if_not_break => {
......@@ -1794,28 +1765,25 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
17941765 const cond = try c.addNode(.{
17951766 .tag = .bool_not,
17961767 .main_token = try c.addToken(.bang, "!"),
1797 .data = .{
1798 .lhs = try renderNodeGrouped(c, payload),
1799 .rhs = undefined,
1800 },
1768 .data = .{ .node = try renderNodeGrouped(c, payload) },
18011769 });
18021770 _ = try c.addToken(.r_paren, ")");
18031771 const then_expr = try c.addNode(.{
18041772 .tag = .@"break",
18051773 .main_token = try c.addToken(.keyword_break, "break"),
1806 .data = .{
1807 .lhs = 0,
1808 .rhs = 0,
1809 },
1774 .data = .{ .opt_token_and_opt_node = .{
1775 .none,
1776 .none,
1777 } },
18101778 });
18111779
18121780 return c.addNode(.{
18131781 .tag = .if_simple,
18141782 .main_token = if_tok,
1815 .data = .{
1816 .lhs = cond,
1817 .rhs = then_expr,
1818 },
1783 .data = .{ .node_and_node = .{
1784 cond,
1785 then_expr,
1786 } },
18191787 });
18201788 },
18211789 .@"switch" => {
......@@ -1837,13 +1805,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18371805 return c.addNode(.{
18381806 .tag = .switch_comma,
18391807 .main_token = switch_tok,
1840 .data = .{
1841 .lhs = cond,
1842 .rhs = try c.addExtra(NodeSubRange{
1808 .data = .{ .node_and_extra = .{
1809 cond, try c.addExtra(NodeSubRange{
18431810 .start = span.start,
18441811 .end = span.end,
18451812 }),
1846 },
1813 } },
18471814 });
18481815 },
18491816 .switch_else => {
......@@ -1852,43 +1819,42 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18521819 return c.addNode(.{
18531820 .tag = .switch_case_one,
18541821 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1855 .data = .{
1856 .lhs = 0,
1857 .rhs = try renderNode(c, payload),
1858 },
1822 .data = .{ .opt_node_and_node = .{
1823 .none,
1824 try renderNode(c, payload),
1825 } },
18591826 });
18601827 },
18611828 .switch_prong => {
18621829 const payload = node.castTag(.switch_prong).?.data;
1863 var items = try c.gpa.alloc(NodeIndex, @max(payload.cases.len, 1));
1830 var items = try c.gpa.alloc(NodeIndex, payload.cases.len);
18641831 defer c.gpa.free(items);
1865 items[0] = 0;
1866 for (payload.cases, 0..) |item, i| {
1832 for (payload.cases, items, 0..) |case, *item, i| {
18671833 if (i != 0) _ = try c.addToken(.comma, ",");
1868 items[i] = try renderNode(c, item);
1834 item.* = try renderNode(c, case);
18691835 }
18701836 _ = try c.addToken(.r_brace, "}");
18711837 if (items.len < 2) {
18721838 return c.addNode(.{
18731839 .tag = .switch_case_one,
18741840 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1875 .data = .{
1876 .lhs = items[0],
1877 .rhs = try renderNode(c, payload.cond),
1878 },
1841 .data = .{ .opt_node_and_node = .{
1842 if (items.len == 0) .none else items[0].toOptional(),
1843 try renderNode(c, payload.cond),
1844 } },
18791845 });
18801846 } else {
18811847 const span = try c.listToSpan(items);
18821848 return c.addNode(.{
18831849 .tag = .switch_case,
18841850 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1885 .data = .{
1886 .lhs = try c.addExtra(NodeSubRange{
1851 .data = .{ .extra_and_node = .{
1852 try c.addExtra(NodeSubRange{
18871853 .start = span.start,
18881854 .end = span.end,
18891855 }),
1890 .rhs = try renderNode(c, payload.cond),
1891 },
1856 try renderNode(c, payload.cond),
1857 } },
18921858 });
18931859 }
18941860 },
......@@ -1900,10 +1866,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
19001866 return c.addNode(.{
19011867 .tag = .container_decl_two,
19021868 .main_token = opaque_tok,
1903 .data = .{
1904 .lhs = 0,
1905 .rhs = 0,
1906 },
1869 .data = .{ .opt_node_and_opt_node = .{
1870 .none,
1871 .none,
1872 } },
19071873 });
19081874 },
19091875 .array_access => {
......@@ -1915,10 +1881,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
19151881 return c.addNode(.{
19161882 .tag = .array_access,
19171883 .main_token = l_bracket,
1918 .data = .{
1919 .lhs = lhs,
1920 .rhs = index_expr,
1921 },
1884 .data = .{ .node_and_node = .{
1885 lhs,
1886 index_expr,
1887 } },
19221888 });
19231889 },
19241890 .array_type => {
......@@ -1940,22 +1906,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
19401906 const init = try c.addNode(.{
19411907 .tag = .array_init_one,
19421908 .main_token = l_brace,
1943 .data = .{
1944 .lhs = type_expr,
1945 .rhs = val,
1946 },
1909 .data = .{ .node_and_node = .{
1910 type_expr,
1911 val,
1912 } },
19471913 });
19481914 return c.addNode(.{
19491915 .tag = .array_cat,
19501916 .main_token = try c.addToken(.asterisk_asterisk, "**"),
1951 .data = .{
1952 .lhs = init,
1953 .rhs = try c.addNode(.{
1917 .data = .{ .node_and_node = .{
1918 init,
1919 try c.addNode(.{
19541920 .tag = .number_literal,
19551921 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.count}),
19561922 .data = undefined,
19571923 }),
1958 },
1924 } },
19591925 });
19601926 },
19611927 .empty_array => {
......@@ -1989,7 +1955,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
19891955 const type_node = if (payload.type) |enum_const_type| blk: {
19901956 _ = try c.addToken(.colon, ":");
19911957 break :blk try renderNode(c, enum_const_type);
1992 } else 0;
1958 } else null;
19931959
19941960 _ = try c.addToken(.equal, "=");
19951961
......@@ -1999,20 +1965,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
19991965 return c.addNode(.{
20001966 .tag = .simple_var_decl,
20011967 .main_token = const_tok,
2002 .data = .{
2003 .lhs = type_node,
2004 .rhs = init_node,
2005 },
1968 .data = .{ .opt_node_and_opt_node = .{
1969 .fromOptional(type_node),
1970 init_node.toOptional(),
1971 } },
20061972 });
20071973 },
20081974 .tuple => {
20091975 const payload = node.castTag(.tuple).?.data;
20101976 _ = try c.addToken(.period, ".");
20111977 const l_brace = try c.addToken(.l_brace, "{");
2012 var inits = try c.gpa.alloc(NodeIndex, @max(payload.len, 2));
1978 var inits = try c.gpa.alloc(NodeIndex, payload.len);
20131979 defer c.gpa.free(inits);
2014 inits[0] = 0;
2015 inits[1] = 0;
20161980 for (payload, 0..) |init, i| {
20171981 if (i != 0) _ = try c.addToken(.comma, ",");
20181982 inits[i] = try renderNode(c, init);
......@@ -2022,20 +1986,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20221986 return c.addNode(.{
20231987 .tag = .array_init_dot_two,
20241988 .main_token = l_brace,
2025 .data = .{
2026 .lhs = inits[0],
2027 .rhs = inits[1],
2028 },
1989 .data = .{ .opt_node_and_opt_node = .{
1990 if (inits.len < 1) .none else inits[0].toOptional(),
1991 if (inits.len < 2) .none else inits[1].toOptional(),
1992 } },
20291993 });
20301994 } else {
20311995 const span = try c.listToSpan(inits);
20321996 return c.addNode(.{
20331997 .tag = .array_init_dot,
20341998 .main_token = l_brace,
2035 .data = .{
2036 .lhs = span.start,
2037 .rhs = span.end,
2038 },
1999 .data = .{ .extra_range = span },
20392000 });
20402001 }
20412002 },
......@@ -2043,10 +2004,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20432004 const payload = node.castTag(.container_init_dot).?.data;
20442005 _ = try c.addToken(.period, ".");
20452006 const l_brace = try c.addToken(.l_brace, "{");
2046 var inits = try c.gpa.alloc(NodeIndex, @max(payload.len, 2));
2007 var inits = try c.gpa.alloc(NodeIndex, payload.len);
20472008 defer c.gpa.free(inits);
2048 inits[0] = 0;
2049 inits[1] = 0;
20502009 for (payload, 0..) |init, i| {
20512010 _ = try c.addToken(.period, ".");
20522011 _ = try c.addIdentifier(init.name);
......@@ -2060,20 +2019,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20602019 return c.addNode(.{
20612020 .tag = .struct_init_dot_two_comma,
20622021 .main_token = l_brace,
2063 .data = .{
2064 .lhs = inits[0],
2065 .rhs = inits[1],
2066 },
2022 .data = .{ .opt_node_and_opt_node = .{
2023 if (inits.len < 1) .none else inits[0].toOptional(),
2024 if (inits.len < 2) .none else inits[1].toOptional(),
2025 } },
20672026 });
20682027 } else {
20692028 const span = try c.listToSpan(inits);
20702029 return c.addNode(.{
20712030 .tag = .struct_init_dot_comma,
20722031 .main_token = l_brace,
2073 .data = .{
2074 .lhs = span.start,
2075 .rhs = span.end,
2076 },
2032 .data = .{ .extra_range = span },
20772033 });
20782034 }
20792035 },
......@@ -2082,9 +2038,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20822038 const lhs = try renderNode(c, payload.lhs);
20832039
20842040 const l_brace = try c.addToken(.l_brace, "{");
2085 var inits = try c.gpa.alloc(NodeIndex, @max(payload.inits.len, 1));
2041 var inits = try c.gpa.alloc(NodeIndex, payload.inits.len);
20862042 defer c.gpa.free(inits);
2087 inits[0] = 0;
20882043 for (payload.inits, 0..) |init, i| {
20892044 _ = try c.addToken(.period, ".");
20902045 _ = try c.addIdentifier(init.name);
......@@ -2098,31 +2053,30 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
20982053 0 => c.addNode(.{
20992054 .tag = .struct_init_one,
21002055 .main_token = l_brace,
2101 .data = .{
2102 .lhs = lhs,
2103 .rhs = 0,
2104 },
2056 .data = .{ .node_and_opt_node = .{
2057 lhs,
2058 .none,
2059 } },
21052060 }),
21062061 1 => c.addNode(.{
21072062 .tag = .struct_init_one_comma,
21082063 .main_token = l_brace,
2109 .data = .{
2110 .lhs = lhs,
2111 .rhs = inits[0],
2112 },
2064 .data = .{ .node_and_opt_node = .{
2065 lhs,
2066 inits[0].toOptional(),
2067 } },
21132068 }),
21142069 else => blk: {
21152070 const span = try c.listToSpan(inits);
21162071 break :blk c.addNode(.{
21172072 .tag = .struct_init_comma,
21182073 .main_token = l_brace,
2119 .data = .{
2120 .lhs = lhs,
2121 .rhs = try c.addExtra(NodeSubRange{
2074 .data = .{ .node_and_extra = .{
2075 lhs, try c.addExtra(NodeSubRange{
21222076 .start = span.start,
21232077 .end = span.end,
21242078 }),
2125 },
2079 } },
21262080 });
21272081 },
21282082 };
......@@ -2147,10 +2101,8 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
21472101 const num_vars = payload.variables.len;
21482102 const num_funcs = payload.functions.len;
21492103 const total_members = payload.fields.len + num_vars + num_funcs;
2150 const members = try c.gpa.alloc(NodeIndex, @max(total_members, 2));
2104 const members = try c.gpa.alloc(NodeIndex, total_members);
21512105 defer c.gpa.free(members);
2152 members[0] = 0;
2153 members[1] = 0;
21542106
21552107 for (payload.fields, 0..) |field, i| {
21562108 const name_tok = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field.name)});
......@@ -2167,37 +2119,36 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
21672119 });
21682120 _ = try c.addToken(.r_paren, ")");
21692121 break :blk align_expr;
2170 } else 0;
2122 } else null;
21712123
21722124 const value_expr = if (field.default_value) |value| blk: {
21732125 _ = try c.addToken(.equal, "=");
21742126 break :blk try renderNode(c, value);
2175 } else 0;
2127 } else null;
21762128
2177 members[i] = try c.addNode(if (align_expr == 0) .{
2129 members[i] = try c.addNode(if (align_expr == null) .{
21782130 .tag = .container_field_init,
21792131 .main_token = name_tok,
2180 .data = .{
2181 .lhs = type_expr,
2182 .rhs = value_expr,
2183 },
2184 } else if (value_expr == 0) .{
2132 .data = .{ .node_and_opt_node = .{
2133 type_expr,
2134 .fromOptional(value_expr),
2135 } },
2136 } else if (value_expr == null) .{
21852137 .tag = .container_field_align,
21862138 .main_token = name_tok,
2187 .data = .{
2188 .lhs = type_expr,
2189 .rhs = align_expr,
2190 },
2139 .data = .{ .node_and_node = .{
2140 type_expr,
2141 align_expr.?,
2142 } },
21912143 } else .{
21922144 .tag = .container_field,
21932145 .main_token = name_tok,
2194 .data = .{
2195 .lhs = type_expr,
2196 .rhs = try c.addExtra(std.zig.Ast.Node.ContainerField{
2197 .align_expr = align_expr,
2198 .value_expr = value_expr,
2146 .data = .{ .node_and_extra = .{
2147 type_expr, try c.addExtra(std.zig.Ast.Node.ContainerField{
2148 .align_expr = align_expr.?,
2149 .value_expr = value_expr.?,
21992150 }),
2200 },
2151 } },
22012152 });
22022153 _ = try c.addToken(.comma, ",");
22032154 }
......@@ -2213,29 +2164,26 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
22132164 return c.addNode(.{
22142165 .tag = .container_decl_two,
22152166 .main_token = kind_tok,
2216 .data = .{
2217 .lhs = 0,
2218 .rhs = 0,
2219 },
2167 .data = .{ .opt_node_and_opt_node = .{
2168 .none,
2169 .none,
2170 } },
22202171 });
22212172 } else if (total_members <= 2) {
22222173 return c.addNode(.{
22232174 .tag = if (num_funcs == 0) .container_decl_two_trailing else .container_decl_two,
22242175 .main_token = kind_tok,
2225 .data = .{
2226 .lhs = members[0],
2227 .rhs = members[1],
2228 },
2176 .data = .{ .opt_node_and_opt_node = .{
2177 if (members.len < 1) .none else members[0].toOptional(),
2178 if (members.len < 2) .none else members[1].toOptional(),
2179 } },
22292180 });
22302181 } else {
22312182 const span = try c.listToSpan(members);
22322183 return c.addNode(.{
22332184 .tag = if (num_funcs == 0) .container_decl_trailing else .container_decl,
22342185 .main_token = kind_tok,
2235 .data = .{
2236 .lhs = span.start,
2237 .rhs = span.end,
2238 },
2186 .data = .{ .extra_range = span },
22392187 });
22402188 }
22412189}
......@@ -2244,45 +2192,52 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
22442192 return c.addNode(.{
22452193 .tag = .field_access,
22462194 .main_token = try c.addToken(.period, "."),
2247 .data = .{
2248 .lhs = lhs,
2249 .rhs = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),
2250 },
2195 .data = .{ .node_and_token = .{
2196 lhs,
2197 try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),
2198 } },
22512199 });
22522200}
22532201
22542202fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
22552203 const l_brace = try c.addToken(.l_brace, "{");
2256 var rendered = try c.gpa.alloc(NodeIndex, @max(inits.len, 1));
2204 var rendered = try c.gpa.alloc(NodeIndex, inits.len);
22572205 defer c.gpa.free(rendered);
2258 rendered[0] = 0;
22592206 for (inits, 0..) |init, i| {
22602207 rendered[i] = try renderNode(c, init);
22612208 _ = try c.addToken(.comma, ",");
22622209 }
22632210 _ = try c.addToken(.r_brace, "}");
2264 if (inits.len < 2) {
2265 return c.addNode(.{
2266 .tag = .array_init_one_comma,
2211 switch (inits.len) {
2212 0 => return c.addNode(.{
2213 .tag = .struct_init_one,
22672214 .main_token = l_brace,
2268 .data = .{
2269 .lhs = lhs,
2270 .rhs = rendered[0],
2271 },
2272 });
2273 } else {
2274 const span = try c.listToSpan(rendered);
2275 return c.addNode(.{
2276 .tag = .array_init_comma,
2215 .data = .{ .node_and_opt_node = .{
2216 lhs,
2217 .none,
2218 } },
2219 }),
2220 1 => return c.addNode(.{
2221 .tag = .array_init_one_comma,
22772222 .main_token = l_brace,
2278 .data = .{
2279 .lhs = lhs,
2280 .rhs = try c.addExtra(NodeSubRange{
2281 .start = span.start,
2282 .end = span.end,
2283 }),
2284 },
2285 });
2223 .data = .{ .node_and_node = .{
2224 lhs,
2225 rendered[0],
2226 } },
2227 }),
2228 else => {
2229 const span = try c.listToSpan(rendered);
2230 return c.addNode(.{
2231 .tag = .array_init_comma,
2232 .main_token = l_brace,
2233 .data = .{ .node_and_extra = .{
2234 lhs, try c.addExtra(NodeSubRange{
2235 .start = span.start,
2236 .end = span.end,
2237 }),
2238 } },
2239 });
2240 },
22862241 }
22872242}
22882243
......@@ -2298,10 +2253,10 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
22982253 return c.addNode(.{
22992254 .tag = .array_type,
23002255 .main_token = l_bracket,
2301 .data = .{
2302 .lhs = len_expr,
2303 .rhs = elem_type_expr,
2304 },
2256 .data = .{ .node_and_node = .{
2257 len_expr,
2258 elem_type_expr,
2259 } },
23052260 });
23062261}
23072262
......@@ -2325,13 +2280,13 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
23252280 return c.addNode(.{
23262281 .tag = .array_type_sentinel,
23272282 .main_token = l_bracket,
2328 .data = .{
2329 .lhs = len_expr,
2330 .rhs = try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{
2283 .data = .{ .node_and_extra = .{
2284 len_expr,
2285 try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{
23312286 .sentinel = sentinel_expr,
23322287 .elem_type = elem_type_expr,
23332288 }),
2334 },
2289 } },
23352290 });
23362291}
23372292
......@@ -2482,10 +2437,10 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
24822437 => return c.addNode(.{
24832438 .tag = .grouped_expression,
24842439 .main_token = try c.addToken(.l_paren, "("),
2485 .data = .{
2486 .lhs = try renderNode(c, node),
2487 .rhs = try c.addToken(.r_paren, ")"),
2488 },
2440 .data = .{ .node_and_token = .{
2441 try renderNode(c, node),
2442 try c.addToken(.r_paren, ")"),
2443 } },
24892444 }),
24902445 .ellipsis3,
24912446 .switch_prong,
......@@ -2539,10 +2494,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T
25392494 return c.addNode(.{
25402495 .tag = tag,
25412496 .main_token = try c.addToken(tok_tag, bytes),
2542 .data = .{
2543 .lhs = try renderNodeGrouped(c, payload),
2544 .rhs = undefined,
2545 },
2497 .data = .{ .node = try renderNodeGrouped(c, payload) },
25462498 });
25472499}
25482500
......@@ -2552,10 +2504,10 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta
25522504 return c.addNode(.{
25532505 .tag = tag,
25542506 .main_token = try c.addToken(tok_tag, bytes),
2555 .data = .{
2556 .lhs = lhs,
2557 .rhs = try renderNodeGrouped(c, payload.rhs),
2558 },
2507 .data = .{ .node_and_node = .{
2508 lhs,
2509 try renderNodeGrouped(c, payload.rhs),
2510 } },
25592511 });
25602512}
25612513
......@@ -2565,10 +2517,10 @@ fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: Toke
25652517 return c.addNode(.{
25662518 .tag = tag,
25672519 .main_token = try c.addToken(tok_tag, bytes),
2568 .data = .{
2569 .lhs = lhs,
2570 .rhs = try renderNode(c, payload.rhs),
2571 },
2520 .data = .{ .node_and_node = .{
2521 lhs,
2522 try renderNode(c, payload.rhs),
2523 } },
25722524 });
25732525}
25742526
......@@ -2586,10 +2538,7 @@ fn renderStdImport(c: *Context, parts: []const []const u8) !NodeIndex {
25862538 const import_node = try c.addNode(.{
25872539 .tag = .builtin_call_two,
25882540 .main_token = import_tok,
2589 .data = .{
2590 .lhs = std_node,
2591 .rhs = 0,
2592 },
2541 .data = .{ .opt_node_and_opt_node = .{ std_node.toOptional(), .none } },
25932542 });
25942543
25952544 var access_chain = import_node;
......@@ -2605,20 +2554,14 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
26052554 0 => try c.addNode(.{
26062555 .tag = .call_one,
26072556 .main_token = lparen,
2608 .data = .{
2609 .lhs = lhs,
2610 .rhs = 0,
2611 },
2557 .data = .{ .node_and_opt_node = .{ lhs, .none } },
26122558 }),
26132559 1 => blk: {
26142560 const arg = try renderNode(c, args[0]);
26152561 break :blk try c.addNode(.{
26162562 .tag = .call_one,
26172563 .main_token = lparen,
2618 .data = .{
2619 .lhs = lhs,
2620 .rhs = arg,
2621 },
2564 .data = .{ .node_and_opt_node = .{ lhs, arg.toOptional() } },
26222565 });
26232566 },
26242567 else => blk: {
......@@ -2633,13 +2576,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
26332576 break :blk try c.addNode(.{
26342577 .tag = .call,
26352578 .main_token = lparen,
2636 .data = .{
2637 .lhs = lhs,
2638 .rhs = try c.addExtra(NodeSubRange{
2639 .start = span.start,
2640 .end = span.end,
2641 }),
2642 },
2579 .data = .{ .node_and_extra = .{
2580 lhs,
2581 try c.addExtra(NodeSubRange{ .start = span.start, .end = span.end }),
2582 } },
26432583 });
26442584 },
26452585 };
......@@ -2650,10 +2590,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
26502590fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !NodeIndex {
26512591 const builtin_tok = try c.addToken(.builtin, builtin);
26522592 _ = try c.addToken(.l_paren, "(");
2653 var arg_1: NodeIndex = 0;
2654 var arg_2: NodeIndex = 0;
2655 var arg_3: NodeIndex = 0;
2656 var arg_4: NodeIndex = 0;
2593 var arg_1: NodeIndex = undefined;
2594 var arg_2: NodeIndex = undefined;
2595 var arg_3: NodeIndex = undefined;
2596 var arg_4: NodeIndex = undefined;
26572597 switch (args.len) {
26582598 0 => {},
26592599 1 => {
......@@ -2681,10 +2621,10 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
26812621 return c.addNode(.{
26822622 .tag = .builtin_call_two,
26832623 .main_token = builtin_tok,
2684 .data = .{
2685 .lhs = arg_1,
2686 .rhs = arg_2,
2687 },
2624 .data = .{ .opt_node_and_opt_node = .{
2625 if (args.len < 1) .none else arg_1.toOptional(),
2626 if (args.len < 2) .none else arg_2.toOptional(),
2627 } },
26882628 });
26892629 } else {
26902630 std.debug.assert(args.len == 4);
......@@ -2693,10 +2633,7 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
26932633 return c.addNode(.{
26942634 .tag = .builtin_call,
26952635 .main_token = builtin_tok,
2696 .data = .{
2697 .lhs = params.start,
2698 .rhs = params.end,
2699 },
2636 .data = .{ .extra_range = params },
27002637 });
27012638 }
27022639}
......@@ -2725,7 +2662,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
27252662 });
27262663 _ = try c.addToken(.r_paren, ")");
27272664 break :blk res;
2728 } else 0;
2665 } else null;
27292666
27302667 const section_node = if (payload.linksection_string) |some| blk: {
27312668 _ = try c.addToken(.keyword_linksection, "linksection");
......@@ -2737,50 +2674,50 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
27372674 });
27382675 _ = try c.addToken(.r_paren, ")");
27392676 break :blk res;
2740 } else 0;
2677 } else null;
27412678
27422679 const init_node = if (payload.init) |some| blk: {
27432680 _ = try c.addToken(.equal, "=");
27442681 break :blk try renderNode(c, some);
2745 } else 0;
2682 } else null;
27462683 _ = try c.addToken(.semicolon, ";");
27472684
2748 if (section_node == 0) {
2749 if (align_node == 0) {
2685 if (section_node == null) {
2686 if (align_node == null) {
27502687 return c.addNode(.{
27512688 .tag = .simple_var_decl,
27522689 .main_token = mut_tok,
2753 .data = .{
2754 .lhs = type_node,
2755 .rhs = init_node,
2756 },
2690 .data = .{ .opt_node_and_opt_node = .{
2691 type_node.toOptional(),
2692 .fromOptional(init_node),
2693 } },
27572694 });
27582695 } else {
27592696 return c.addNode(.{
27602697 .tag = .local_var_decl,
27612698 .main_token = mut_tok,
2762 .data = .{
2763 .lhs = try c.addExtra(std.zig.Ast.Node.LocalVarDecl{
2699 .data = .{ .extra_and_opt_node = .{
2700 try c.addExtra(std.zig.Ast.Node.LocalVarDecl{
27642701 .type_node = type_node,
2765 .align_node = align_node,
2702 .align_node = align_node.?,
27662703 }),
2767 .rhs = init_node,
2768 },
2704 .fromOptional(init_node),
2705 } },
27692706 });
27702707 }
27712708 } else {
27722709 return c.addNode(.{
27732710 .tag = .global_var_decl,
27742711 .main_token = mut_tok,
2775 .data = .{
2776 .lhs = try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{
2777 .type_node = type_node,
2778 .align_node = align_node,
2779 .section_node = section_node,
2780 .addrspace_node = 0,
2712 .data = .{ .extra_and_opt_node = .{
2713 try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{
2714 .type_node = type_node.toOptional(),
2715 .align_node = .fromOptional(align_node),
2716 .section_node = .fromOptional(section_node),
2717 .addrspace_node = .none,
27812718 }),
2782 .rhs = init_node,
2783 },
2719 .fromOptional(init_node),
2720 } },
27842721 });
27852722 }
27862723}
......@@ -2809,7 +2746,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
28092746 });
28102747 _ = try c.addToken(.r_paren, ")");
28112748 break :blk res;
2812 } else 0;
2749 } else null;
28132750
28142751 const section_expr = if (payload.linksection_string) |some| blk: {
28152752 _ = try c.addToken(.keyword_linksection, "linksection");
......@@ -2821,7 +2758,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
28212758 });
28222759 _ = try c.addToken(.r_paren, ")");
28232760 break :blk res;
2824 } else 0;
2761 } else null;
28252762
28262763 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
28272764 _ = try c.addToken(.keyword_callconv, "callconv");
......@@ -2856,48 +2793,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
28562793 const inner_lbrace = try c.addToken(.l_brace, "{");
28572794 _ = try c.addToken(.r_brace, "}");
28582795 _ = try c.addToken(.r_brace, "}");
2796 const inner_node = try c.addNode(.{
2797 .tag = .struct_init_dot_two,
2798 .main_token = inner_lbrace,
2799 .data = .{ .opt_node_and_opt_node = .{
2800 .none,
2801 .none,
2802 } },
2803 });
28592804 break :cc_node try c.addNode(.{
28602805 .tag = .struct_init_dot_two,
28612806 .main_token = outer_lbrace,
2862 .data = .{
2863 .lhs = try c.addNode(.{
2864 .tag = .struct_init_dot_two,
2865 .main_token = inner_lbrace,
2866 .data = .{ .lhs = 0, .rhs = 0 },
2867 }),
2868 .rhs = 0,
2869 },
2807 .data = .{ .opt_node_and_opt_node = .{
2808 inner_node.toOptional(),
2809 .none,
2810 } },
28702811 });
28712812 },
28722813 };
28732814 _ = try c.addToken(.r_paren, ")");
28742815 break :blk cc_node;
2875 } else 0;
2816 } else null;
28762817
28772818 const return_type_expr = try renderNode(c, payload.return_type);
28782819
28792820 const fn_proto = try blk: {
2880 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
2821 if (align_expr == null and section_expr == null and callconv_expr == null) {
28812822 if (params.items.len < 2)
28822823 break :blk c.addNode(.{
28832824 .tag = .fn_proto_simple,
28842825 .main_token = fn_token,
2885 .data = .{
2886 .lhs = params.items[0],
2887 .rhs = return_type_expr,
2888 },
2826 .data = .{ .opt_node_and_opt_node = .{
2827 if (params.items.len == 0) .none else params.items[0].toOptional(),
2828 return_type_expr.toOptional(),
2829 } },
28892830 })
28902831 else
28912832 break :blk c.addNode(.{
28922833 .tag = .fn_proto_multi,
28932834 .main_token = fn_token,
2894 .data = .{
2895 .lhs = try c.addExtra(NodeSubRange{
2835 .data = .{ .extra_and_opt_node = .{
2836 try c.addExtra(NodeSubRange{
28962837 .start = span.start,
28972838 .end = span.end,
28982839 }),
2899 .rhs = return_type_expr,
2900 },
2840 return_type_expr.toOptional(),
2841 } },
29012842 });
29022843 }
29032844 if (params.items.len < 2)
......@@ -2905,14 +2846,16 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
29052846 .tag = .fn_proto_one,
29062847 .main_token = fn_token,
29072848 .data = .{
2908 .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{
2909 .param = params.items[0],
2910 .align_expr = align_expr,
2911 .addrspace_expr = 0, // TODO
2912 .section_expr = section_expr,
2913 .callconv_expr = callconv_expr,
2914 }),
2915 .rhs = return_type_expr,
2849 .extra_and_opt_node = .{
2850 try c.addExtra(std.zig.Ast.Node.FnProtoOne{
2851 .param = if (params.items.len == 0) .none else params.items[0].toOptional(),
2852 .align_expr = .fromOptional(align_expr),
2853 .addrspace_expr = .none, // TODO
2854 .section_expr = .fromOptional(section_expr),
2855 .callconv_expr = .fromOptional(callconv_expr),
2856 }),
2857 return_type_expr.toOptional(),
2858 },
29162859 },
29172860 })
29182861 else
......@@ -2920,15 +2863,17 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
29202863 .tag = .fn_proto,
29212864 .main_token = fn_token,
29222865 .data = .{
2923 .lhs = try c.addExtra(std.zig.Ast.Node.FnProto{
2924 .params_start = span.start,
2925 .params_end = span.end,
2926 .align_expr = align_expr,
2927 .addrspace_expr = 0, // TODO
2928 .section_expr = section_expr,
2929 .callconv_expr = callconv_expr,
2930 }),
2931 .rhs = return_type_expr,
2866 .extra_and_opt_node = .{
2867 try c.addExtra(std.zig.Ast.Node.FnProto{
2868 .params_start = span.start,
2869 .params_end = span.end,
2870 .align_expr = .fromOptional(align_expr),
2871 .addrspace_expr = .none, // TODO
2872 .section_expr = .fromOptional(section_expr),
2873 .callconv_expr = .fromOptional(callconv_expr),
2874 }),
2875 return_type_expr.toOptional(),
2876 },
29322877 },
29332878 });
29342879 };
......@@ -2943,10 +2888,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
29432888 return c.addNode(.{
29442889 .tag = .fn_decl,
29452890 .main_token = fn_token,
2946 .data = .{
2947 .lhs = fn_proto,
2948 .rhs = body,
2949 },
2891 .data = .{ .node_and_node = .{
2892 fn_proto,
2893 body,
2894 } },
29502895 });
29512896}
29522897
......@@ -2959,8 +2904,6 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
29592904
29602905 const params = try renderParams(c, payload.params, false);
29612906 defer params.deinit();
2962 var span: NodeSubRange = undefined;
2963 if (params.items.len > 1) span = try c.listToSpan(params.items);
29642907
29652908 const return_type_expr = try renderNodeGrouped(c, payload.return_type);
29662909
......@@ -2969,38 +2912,39 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
29692912 break :blk try c.addNode(.{
29702913 .tag = .fn_proto_simple,
29712914 .main_token = fn_token,
2972 .data = .{
2973 .lhs = params.items[0],
2974 .rhs = return_type_expr,
2975 },
2915 .data = .{ .opt_node_and_opt_node = .{
2916 if (params.items.len == 0) .none else params.items[0].toOptional(),
2917 return_type_expr.toOptional(),
2918 } },
29762919 });
29772920 } else {
2921 const span: NodeSubRange = try c.listToSpan(params.items);
29782922 break :blk try c.addNode(.{
29792923 .tag = .fn_proto_multi,
29802924 .main_token = fn_token,
2981 .data = .{
2982 .lhs = try c.addExtra(std.zig.Ast.Node.SubRange{
2925 .data = .{ .extra_and_opt_node = .{
2926 try c.addExtra(std.zig.Ast.Node.SubRange{
29832927 .start = span.start,
29842928 .end = span.end,
29852929 }),
2986 .rhs = return_type_expr,
2987 },
2930 return_type_expr.toOptional(),
2931 } },
29882932 });
29892933 }
29902934 };
29912935 return c.addNode(.{
29922936 .tag = .fn_decl,
29932937 .main_token = fn_token,
2994 .data = .{
2995 .lhs = fn_proto,
2996 .rhs = try renderNode(c, payload.body),
2997 },
2938 .data = .{ .node_and_node = .{
2939 fn_proto,
2940 try renderNode(c, payload.body),
2941 } },
29982942 });
29992943}
30002944
30012945fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
30022946 _ = try c.addToken(.l_paren, "(");
3003 var rendered = try std.ArrayList(NodeIndex).initCapacity(c.gpa, @max(params.len, 1));
2947 var rendered = try std.ArrayList(NodeIndex).initCapacity(c.gpa, params.len);
30042948 errdefer rendered.deinit();
30052949
30062950 for (params, 0..) |param, i| {
......@@ -3022,6 +2966,5 @@ fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.Ar
30222966 }
30232967 _ = try c.addToken(.r_paren, ")");
30242968
3025 if (rendered.items.len == 0) rendered.appendAssumeCapacity(0);
30262969 return rendered;
30272970}
lib/compiler/reduce.zig+1-1
......@@ -220,7 +220,7 @@ pub fn main() !void {
220220 mem.eql(u8, msg, "unused function parameter") or
221221 mem.eql(u8, msg, "unused capture"))
222222 {
223 const ident_token = item.data.token;
223 const ident_token = item.data.token.unwrap().?;
224224 try more_fixups.unused_var_decls.put(gpa, ident_token, {});
225225 } else {
226226 std.debug.print("found other ZIR error: '{s}'\n", .{msg});
lib/compiler/reduce/Walk.zig+160-253
......@@ -98,29 +98,26 @@ const ScanDeclsAction = enum { add, remove };
9898fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction) Error!void {
9999 const ast = w.ast;
100100 const gpa = w.gpa;
101 const node_tags = ast.nodes.items(.tag);
102 const main_tokens = ast.nodes.items(.main_token);
103 const token_tags = ast.tokens.items(.tag);
104101
105102 for (members) |member_node| {
106 const name_token = switch (node_tags[member_node]) {
103 const name_token = switch (ast.nodeTag(member_node)) {
107104 .global_var_decl,
108105 .local_var_decl,
109106 .simple_var_decl,
110107 .aligned_var_decl,
111 => main_tokens[member_node] + 1,
108 => ast.nodeMainToken(member_node) + 1,
112109
113110 .fn_proto_simple,
114111 .fn_proto_multi,
115112 .fn_proto_one,
116113 .fn_proto,
117114 .fn_decl,
118 => main_tokens[member_node] + 1,
115 => ast.nodeMainToken(member_node) + 1,
119116
120117 else => continue,
121118 };
122119
123 assert(token_tags[name_token] == .identifier);
120 assert(ast.tokenTag(name_token) == .identifier);
124121 const name_bytes = ast.tokenSlice(name_token);
125122
126123 switch (action) {
......@@ -145,12 +142,10 @@ fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction)
145142
146143fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
147144 const ast = w.ast;
148 const datas = ast.nodes.items(.data);
149 switch (ast.nodes.items(.tag)[decl]) {
145 switch (ast.nodeTag(decl)) {
150146 .fn_decl => {
151 const fn_proto = datas[decl].lhs;
147 const fn_proto, const body_node = ast.nodeData(decl).node_and_node;
152148 try walkExpression(w, fn_proto);
153 const body_node = datas[decl].rhs;
154149 if (!isFnBodyGutted(ast, body_node)) {
155150 w.replace_names.clearRetainingCapacity();
156151 try w.transformations.append(.{ .gut_function = decl });
......@@ -167,7 +162,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
167162
168163 .@"usingnamespace" => {
169164 try w.transformations.append(.{ .delete_node = decl });
170 const expr = datas[decl].lhs;
165 const expr = ast.nodeData(decl).node;
171166 try walkExpression(w, expr);
172167 },
173168
......@@ -179,7 +174,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
179174
180175 .test_decl => {
181176 try w.transformations.append(.{ .delete_node = decl });
182 try walkExpression(w, datas[decl].rhs);
177 try walkExpression(w, ast.nodeData(decl).opt_token_and_node[1]);
183178 },
184179
185180 .container_field_init,
......@@ -202,14 +197,10 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
202197
203198fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
204199 const ast = w.ast;
205 const token_tags = ast.tokens.items(.tag);
206 const main_tokens = ast.nodes.items(.main_token);
207 const node_tags = ast.nodes.items(.tag);
208 const datas = ast.nodes.items(.data);
209 switch (node_tags[node]) {
200 switch (ast.nodeTag(node)) {
210201 .identifier => {
211 const name_ident = main_tokens[node];
212 assert(token_tags[name_ident] == .identifier);
202 const name_ident = ast.nodeMainToken(node);
203 assert(ast.tokenTag(name_ident) == .identifier);
213204 const name_bytes = ast.tokenSlice(name_ident);
214205 _ = w.unreferenced_globals.swapRemove(name_bytes);
215206 if (w.replace_names.get(name_bytes)) |index| {
......@@ -230,64 +221,36 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
230221
231222 .block_two,
232223 .block_two_semicolon,
233 => {
234 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
235 if (datas[node].lhs == 0) {
236 return walkBlock(w, node, statements[0..0]);
237 } else if (datas[node].rhs == 0) {
238 return walkBlock(w, node, statements[0..1]);
239 } else {
240 return walkBlock(w, node, statements[0..2]);
241 }
242 },
243224 .block,
244225 .block_semicolon,
245226 => {
246 const statements = ast.extra_data[datas[node].lhs..datas[node].rhs];
227 var buf: [2]Ast.Node.Index = undefined;
228 const statements = ast.blockStatements(&buf, node).?;
247229 return walkBlock(w, node, statements);
248230 },
249231
250232 .@"errdefer" => {
251 const expr = datas[node].rhs;
233 const expr = ast.nodeData(node).opt_token_and_node[1];
252234 return walkExpression(w, expr);
253235 },
254236
255 .@"defer" => {
256 const expr = datas[node].rhs;
257 return walkExpression(w, expr);
258 },
259 .@"comptime", .@"nosuspend" => {
260 const block = datas[node].lhs;
261 return walkExpression(w, block);
262 },
263
264 .@"suspend" => {
265 const body = datas[node].lhs;
266 return walkExpression(w, body);
267 },
268
269 .@"catch" => {
270 try walkExpression(w, datas[node].lhs); // target
271 try walkExpression(w, datas[node].rhs); // fallback
237 .@"defer",
238 .@"comptime",
239 .@"nosuspend",
240 .@"suspend",
241 => {
242 return walkExpression(w, ast.nodeData(node).node);
272243 },
273244
274245 .field_access => {
275 const field_access = datas[node];
276 try walkExpression(w, field_access.lhs);
246 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
277247 },
278248
279 .error_union,
280 .switch_range,
281 => {
282 const infix = datas[node];
283 try walkExpression(w, infix.lhs);
284 return walkExpression(w, infix.rhs);
285 },
286249 .for_range => {
287 const infix = datas[node];
288 try walkExpression(w, infix.lhs);
289 if (infix.rhs != 0) {
290 return walkExpression(w, infix.rhs);
250 const start, const opt_end = ast.nodeData(node).node_and_opt_node;
251 try walkExpression(w, start);
252 if (opt_end.unwrap()) |end| {
253 return walkExpression(w, end);
291254 }
292255 },
293256
......@@ -337,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
337300 .sub,
338301 .sub_wrap,
339302 .sub_sat,
303 .@"catch",
304 .error_union,
305 .switch_range,
340306 .@"orelse",
307 .array_access,
341308 => {
342 const infix = datas[node];
343 try walkExpression(w, infix.lhs);
344 try walkExpression(w, infix.rhs);
309 const lhs, const rhs = ast.nodeData(node).node_and_node;
310 try walkExpression(w, lhs);
311 try walkExpression(w, rhs);
345312 },
346313
347314 .assign_destructure => {
348315 const full = ast.assignDestructure(node);
349316 for (full.ast.variables) |variable_node| {
350 switch (node_tags[variable_node]) {
317 switch (ast.nodeTag(variable_node)) {
351318 .global_var_decl,
352319 .local_var_decl,
353320 .simple_var_decl,
......@@ -366,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
366333 .negation_wrap,
367334 .optional_type,
368335 .address_of,
369 => {
370 return walkExpression(w, datas[node].lhs);
371 },
372
373336 .@"try",
374337 .@"resume",
375338 .@"await",
339 .deref,
376340 => {
377 return walkExpression(w, datas[node].lhs);
341 return walkExpression(w, ast.nodeData(node).node);
378342 },
379343
380344 .array_type,
......@@ -426,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
426390 return walkCall(w, ast.fullCall(&buf, node).?);
427391 },
428392
429 .array_access => {
430 const suffix = datas[node];
431 try walkExpression(w, suffix.lhs);
432 try walkExpression(w, suffix.rhs);
433 },
434
435393 .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?),
436394
437 .deref => {
438 try walkExpression(w, datas[node].lhs);
439 },
440
441395 .unwrap_optional => {
442 try walkExpression(w, datas[node].lhs);
396 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
443397 },
444398
445399 .@"break" => {
446 const label_token = datas[node].lhs;
447 const target = datas[node].rhs;
448 if (label_token == 0 and target == 0) {
400 const label_token, const target = ast.nodeData(node).opt_token_and_opt_node;
401 if (label_token == .none and target == .none) {
449402 // no expressions
450 } else if (label_token == 0 and target != 0) {
451 try walkExpression(w, target);
452 } else if (label_token != 0 and target == 0) {
453 try walkIdentifier(w, label_token);
454 } else if (label_token != 0 and target != 0) {
455 try walkExpression(w, target);
403 } else if (label_token == .none and target != .none) {
404 try walkExpression(w, target.unwrap().?);
405 } else if (label_token != .none and target == .none) {
406 try walkIdentifier(w, label_token.unwrap().?);
407 } else if (label_token != .none and target != .none) {
408 try walkExpression(w, target.unwrap().?);
456409 }
457410 },
458411
459412 .@"continue" => {
460 const label = datas[node].lhs;
461 if (label != 0) {
462 return walkIdentifier(w, label); // label
413 const opt_label = ast.nodeData(node).opt_token_and_opt_node[0];
414 if (opt_label.unwrap()) |label| {
415 return walkIdentifier(w, label);
463416 }
464417 },
465418
466419 .@"return" => {
467 if (datas[node].lhs != 0) {
468 try walkExpression(w, datas[node].lhs);
420 if (ast.nodeData(node).opt_node.unwrap()) |lhs| {
421 try walkExpression(w, lhs);
469422 }
470423 },
471424
472425 .grouped_expression => {
473 try walkExpression(w, datas[node].lhs);
426 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
474427 },
475428
476429 .container_decl,
......@@ -491,13 +444,11 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
491444 },
492445
493446 .error_set_decl => {
494 const error_token = main_tokens[node];
495 const lbrace = error_token + 1;
496 const rbrace = datas[node].rhs;
447 const lbrace, const rbrace = ast.nodeData(node).token_and_token;
497448
498449 var i = lbrace + 1;
499450 while (i < rbrace) : (i += 1) {
500 switch (token_tags[i]) {
451 switch (ast.tokenTag(i)) {
501452 .doc_comment => unreachable, // TODO
502453 .identifier => try walkIdentifier(w, i),
503454 .comma => {},
......@@ -506,17 +457,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
506457 }
507458 },
508459
509 .builtin_call_two, .builtin_call_two_comma => {
510 if (datas[node].lhs == 0) {
511 return walkBuiltinCall(w, node, &.{});
512 } else if (datas[node].rhs == 0) {
513 return walkBuiltinCall(w, node, &.{datas[node].lhs});
514 } else {
515 return walkBuiltinCall(w, node, &.{ datas[node].lhs, datas[node].rhs });
516 }
517 },
518 .builtin_call, .builtin_call_comma => {
519 const params = ast.extra_data[datas[node].lhs..datas[node].rhs];
460 .builtin_call_two,
461 .builtin_call_two_comma,
462 .builtin_call,
463 .builtin_call_comma,
464 => {
465 var buf: [2]Ast.Node.Index = undefined;
466 const params = ast.builtinCallParams(&buf, node).?;
520467 return walkBuiltinCall(w, node, params);
521468 },
522469
......@@ -530,20 +477,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
530477 },
531478
532479 .anyframe_type => {
533 if (datas[node].rhs != 0) {
534 return walkExpression(w, datas[node].rhs);
535 }
480 _, const child_type = ast.nodeData(node).token_and_node;
481 return walkExpression(w, child_type);
536482 },
537483
538484 .@"switch",
539485 .switch_comma,
540486 => {
541 const condition = datas[node].lhs;
542 const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange);
543 const cases = ast.extra_data[extra.start..extra.end];
544
545 try walkExpression(w, condition); // condition expression
546 try walkExpressions(w, cases);
487 const full = ast.fullSwitch(node).?;
488 try walkExpression(w, full.ast.condition); // condition expression
489 try walkExpressions(w, full.ast.cases);
547490 },
548491
549492 .switch_case_one,
......@@ -570,7 +513,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
570513 => return walkAsm(w, ast.fullAsm(node).?),
571514
572515 .enum_literal => {
573 return walkIdentifier(w, main_tokens[node]); // name
516 return walkIdentifier(w, ast.nodeMainToken(node)); // name
574517 },
575518
576519 .fn_decl => unreachable,
......@@ -592,66 +535,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
592535fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {
593536 _ = decl_node;
594537
595 if (var_decl.ast.type_node != 0) {
596 try walkExpression(w, var_decl.ast.type_node);
538 if (var_decl.ast.type_node.unwrap()) |type_node| {
539 try walkExpression(w, type_node);
597540 }
598541
599 if (var_decl.ast.align_node != 0) {
600 try walkExpression(w, var_decl.ast.align_node);
542 if (var_decl.ast.align_node.unwrap()) |align_node| {
543 try walkExpression(w, align_node);
601544 }
602545
603 if (var_decl.ast.addrspace_node != 0) {
604 try walkExpression(w, var_decl.ast.addrspace_node);
546 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
547 try walkExpression(w, addrspace_node);
605548 }
606549
607 if (var_decl.ast.section_node != 0) {
608 try walkExpression(w, var_decl.ast.section_node);
550 if (var_decl.ast.section_node.unwrap()) |section_node| {
551 try walkExpression(w, section_node);
609552 }
610553
611 if (var_decl.ast.init_node != 0) {
612 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
613 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
554 if (var_decl.ast.init_node.unwrap()) |init_node| {
555 if (!isUndefinedIdent(w.ast, init_node)) {
556 try w.transformations.append(.{ .replace_with_undef = init_node });
614557 }
615 try walkExpression(w, var_decl.ast.init_node);
558 try walkExpression(w, init_node);
616559 }
617560}
618561
619562fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
620563 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
621564
622 if (var_decl.ast.type_node != 0) {
623 try walkExpression(w, var_decl.ast.type_node);
565 if (var_decl.ast.type_node.unwrap()) |type_node| {
566 try walkExpression(w, type_node);
624567 }
625568
626 if (var_decl.ast.align_node != 0) {
627 try walkExpression(w, var_decl.ast.align_node);
569 if (var_decl.ast.align_node.unwrap()) |align_node| {
570 try walkExpression(w, align_node);
628571 }
629572
630 if (var_decl.ast.addrspace_node != 0) {
631 try walkExpression(w, var_decl.ast.addrspace_node);
573 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
574 try walkExpression(w, addrspace_node);
632575 }
633576
634 if (var_decl.ast.section_node != 0) {
635 try walkExpression(w, var_decl.ast.section_node);
577 if (var_decl.ast.section_node.unwrap()) |section_node| {
578 try walkExpression(w, section_node);
636579 }
637580
638 if (var_decl.ast.init_node != 0) {
639 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
640 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
581 if (var_decl.ast.init_node.unwrap()) |init_node| {
582 if (!isUndefinedIdent(w.ast, init_node)) {
583 try w.transformations.append(.{ .replace_with_undef = init_node });
641584 }
642 try walkExpression(w, var_decl.ast.init_node);
585 try walkExpression(w, init_node);
643586 }
644587}
645588
646589fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {
647 if (field.ast.type_expr != 0) {
648 try walkExpression(w, field.ast.type_expr); // type
590 if (field.ast.type_expr.unwrap()) |type_expr| {
591 try walkExpression(w, type_expr); // type
649592 }
650 if (field.ast.align_expr != 0) {
651 try walkExpression(w, field.ast.align_expr); // alignment
593 if (field.ast.align_expr.unwrap()) |align_expr| {
594 try walkExpression(w, align_expr); // alignment
652595 }
653 if (field.ast.value_expr != 0) {
654 try walkExpression(w, field.ast.value_expr); // value
596 if (field.ast.value_expr.unwrap()) |value_expr| {
597 try walkExpression(w, value_expr); // value
655598 }
656599}
657600
......@@ -662,18 +605,17 @@ fn walkBlock(
662605) Error!void {
663606 _ = block_node;
664607 const ast = w.ast;
665 const node_tags = ast.nodes.items(.tag);
666608
667609 for (statements) |stmt| {
668 switch (node_tags[stmt]) {
610 switch (ast.nodeTag(stmt)) {
669611 .global_var_decl,
670612 .local_var_decl,
671613 .simple_var_decl,
672614 .aligned_var_decl,
673615 => {
674616 const var_decl = ast.fullVarDecl(stmt).?;
675 if (var_decl.ast.init_node != 0 and
676 isUndefinedIdent(w.ast, var_decl.ast.init_node))
617 if (var_decl.ast.init_node != .none and
618 isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?))
677619 {
678620 try w.transformations.append(.{ .delete_var_decl = .{
679621 .var_decl_node = stmt,
......@@ -704,15 +646,15 @@ fn walkBlock(
704646
705647fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {
706648 try walkExpression(w, array_type.ast.elem_count);
707 if (array_type.ast.sentinel != 0) {
708 try walkExpression(w, array_type.ast.sentinel);
649 if (array_type.ast.sentinel.unwrap()) |sentinel| {
650 try walkExpression(w, sentinel);
709651 }
710652 return walkExpression(w, array_type.ast.elem_type);
711653}
712654
713655fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {
714 if (array_init.ast.type_expr != 0) {
715 try walkExpression(w, array_init.ast.type_expr); // T
656 if (array_init.ast.type_expr.unwrap()) |type_expr| {
657 try walkExpression(w, type_expr); // T
716658 }
717659 for (array_init.ast.elements) |elem_init| {
718660 try walkExpression(w, elem_init);
......@@ -725,8 +667,8 @@ fn walkStructInit(
725667 struct_init: Ast.full.StructInit,
726668) Error!void {
727669 _ = struct_node;
728 if (struct_init.ast.type_expr != 0) {
729 try walkExpression(w, struct_init.ast.type_expr); // T
670 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
671 try walkExpression(w, type_expr); // T
730672 }
731673 for (struct_init.ast.fields) |field_init| {
732674 try walkExpression(w, field_init);
......@@ -746,18 +688,17 @@ fn walkSlice(
746688 _ = slice_node;
747689 try walkExpression(w, slice.ast.sliced);
748690 try walkExpression(w, slice.ast.start);
749 if (slice.ast.end != 0) {
750 try walkExpression(w, slice.ast.end);
691 if (slice.ast.end.unwrap()) |end| {
692 try walkExpression(w, end);
751693 }
752 if (slice.ast.sentinel != 0) {
753 try walkExpression(w, slice.ast.sentinel);
694 if (slice.ast.sentinel.unwrap()) |sentinel| {
695 try walkExpression(w, sentinel);
754696 }
755697}
756698
757699fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {
758700 const ast = w.ast;
759 const token_tags = ast.tokens.items(.tag);
760 assert(token_tags[name_ident] == .identifier);
701 assert(ast.tokenTag(name_ident) == .identifier);
761702 const name_bytes = ast.tokenSlice(name_ident);
762703 _ = w.unreferenced_globals.swapRemove(name_bytes);
763704}
......@@ -773,8 +714,8 @@ fn walkContainerDecl(
773714 container_decl: Ast.full.ContainerDecl,
774715) Error!void {
775716 _ = container_decl_node;
776 if (container_decl.ast.arg != 0) {
777 try walkExpression(w, container_decl.ast.arg);
717 if (container_decl.ast.arg.unwrap()) |arg| {
718 try walkExpression(w, arg);
778719 }
779720 try walkMembers(w, container_decl.ast.members);
780721}
......@@ -785,14 +726,13 @@ fn walkBuiltinCall(
785726 params: []const Ast.Node.Index,
786727) Error!void {
787728 const ast = w.ast;
788 const main_tokens = ast.nodes.items(.main_token);
789 const builtin_token = main_tokens[call_node];
729 const builtin_token = ast.nodeMainToken(call_node);
790730 const builtin_name = ast.tokenSlice(builtin_token);
791731 const info = BuiltinFn.list.get(builtin_name).?;
792732 switch (info.tag) {
793733 .import => {
794734 const operand_node = params[0];
795 const str_lit_token = main_tokens[operand_node];
735 const str_lit_token = ast.nodeMainToken(operand_node);
796736 const token_bytes = ast.tokenSlice(str_lit_token);
797737 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {
798738 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch
......@@ -821,29 +761,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {
821761 {
822762 var it = fn_proto.iterate(ast);
823763 while (it.next()) |param| {
824 if (param.type_expr != 0) {
825 try walkExpression(w, param.type_expr);
764 if (param.type_expr) |type_expr| {
765 try walkExpression(w, type_expr);
826766 }
827767 }
828768 }
829769
830 if (fn_proto.ast.align_expr != 0) {
831 try walkExpression(w, fn_proto.ast.align_expr);
770 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
771 try walkExpression(w, align_expr);
832772 }
833773
834 if (fn_proto.ast.addrspace_expr != 0) {
835 try walkExpression(w, fn_proto.ast.addrspace_expr);
774 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
775 try walkExpression(w, addrspace_expr);
836776 }
837777
838 if (fn_proto.ast.section_expr != 0) {
839 try walkExpression(w, fn_proto.ast.section_expr);
778 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
779 try walkExpression(w, section_expr);
840780 }
841781
842 if (fn_proto.ast.callconv_expr != 0) {
843 try walkExpression(w, fn_proto.ast.callconv_expr);
782 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
783 try walkExpression(w, callconv_expr);
844784 }
845785
846 try walkExpression(w, fn_proto.ast.return_type);
786 const return_type = fn_proto.ast.return_type.unwrap().?;
787 try walkExpression(w, return_type);
847788}
848789
849790fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {
......@@ -860,16 +801,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {
860801}
861802
862803fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {
863 assert(while_node.ast.cond_expr != 0);
864 assert(while_node.ast.then_expr != 0);
865
866804 // Perform these transformations in this priority order:
867805 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
868806 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
869807 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
870808 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
871809 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and
872 (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr)))
810 (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?)))
873811 {
874812 try w.transformations.ensureUnusedCapacity(1);
875813 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });
......@@ -886,45 +824,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E
886824 try w.transformations.ensureUnusedCapacity(1);
887825 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
888826 .to_replace = node_index,
889 .replacement = while_node.ast.else_expr,
827 .replacement = while_node.ast.else_expr.unwrap().?,
890828 } });
891829 }
892830
893831 try walkExpression(w, while_node.ast.cond_expr); // condition
894832
895 if (while_node.ast.cont_expr != 0) {
896 try walkExpression(w, while_node.ast.cont_expr);
833 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
834 try walkExpression(w, cont_expr);
897835 }
898836
899 if (while_node.ast.then_expr != 0) {
900 try walkExpression(w, while_node.ast.then_expr);
901 }
902 if (while_node.ast.else_expr != 0) {
903 try walkExpression(w, while_node.ast.else_expr);
837 try walkExpression(w, while_node.ast.then_expr);
838
839 if (while_node.ast.else_expr.unwrap()) |else_expr| {
840 try walkExpression(w, else_expr);
904841 }
905842}
906843
907844fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {
908845 try walkParamList(w, for_node.ast.inputs);
909 if (for_node.ast.then_expr != 0) {
910 try walkExpression(w, for_node.ast.then_expr);
911 }
912 if (for_node.ast.else_expr != 0) {
913 try walkExpression(w, for_node.ast.else_expr);
846 try walkExpression(w, for_node.ast.then_expr);
847 if (for_node.ast.else_expr.unwrap()) |else_expr| {
848 try walkExpression(w, else_expr);
914849 }
915850}
916851
917852fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {
918 assert(if_node.ast.cond_expr != 0);
919 assert(if_node.ast.then_expr != 0);
920
921853 // Perform these transformations in this priority order:
922854 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
923855 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
924856 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
925857 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
926858 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and
927 (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr)))
859 (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?)))
928860 {
929861 try w.transformations.ensureUnusedCapacity(1);
930862 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });
......@@ -941,17 +873,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void
941873 try w.transformations.ensureUnusedCapacity(1);
942874 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
943875 .to_replace = node_index,
944 .replacement = if_node.ast.else_expr,
876 .replacement = if_node.ast.else_expr.unwrap().?,
945877 } });
946878 }
947879
948880 try walkExpression(w, if_node.ast.cond_expr); // condition
949
950 if (if_node.ast.then_expr != 0) {
951 try walkExpression(w, if_node.ast.then_expr);
952 }
953 if (if_node.ast.else_expr != 0) {
954 try walkExpression(w, if_node.ast.else_expr);
881 try walkExpression(w, if_node.ast.then_expr);
882 if (if_node.ast.else_expr.unwrap()) |else_expr| {
883 try walkExpression(w, else_expr);
955884 }
956885}
957886
......@@ -971,25 +900,13 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {
971900/// Check if it is already gutted (i.e. its body replaced with `@trap()`).
972901fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {
973902 // skip over discards
974 const node_tags = ast.nodes.items(.tag);
975 const datas = ast.nodes.items(.data);
976903 var statements_buf: [2]Ast.Node.Index = undefined;
977 const statements = switch (node_tags[body_node]) {
904 const statements = switch (ast.nodeTag(body_node)) {
978905 .block_two,
979906 .block_two_semicolon,
980 => blk: {
981 statements_buf[0..2].* = .{ datas[body_node].lhs, datas[body_node].rhs };
982 break :blk if (datas[body_node].lhs == 0)
983 statements_buf[0..0]
984 else if (datas[body_node].rhs == 0)
985 statements_buf[0..1]
986 else
987 statements_buf[0..2];
988 },
989
990907 .block,
991908 .block_semicolon,
992 => ast.extra_data[datas[body_node].lhs..datas[body_node].rhs],
909 => ast.blockStatements(&statements_buf, body_node).?,
993910
994911 else => return false,
995912 };
......@@ -1012,27 +929,20 @@ const StmtCategory = enum {
1012929};
1013930
1014931fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
1015 const node_tags = ast.nodes.items(.tag);
1016 const datas = ast.nodes.items(.data);
1017 const main_tokens = ast.nodes.items(.main_token);
1018 switch (node_tags[stmt]) {
1019 .builtin_call_two, .builtin_call_two_comma => {
1020 if (datas[stmt].lhs == 0) {
1021 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{});
1022 } else if (datas[stmt].rhs == 0) {
1023 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{datas[stmt].lhs});
1024 } else {
1025 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{ datas[stmt].lhs, datas[stmt].rhs });
1026 }
1027 },
1028 .builtin_call, .builtin_call_comma => {
1029 const params = ast.extra_data[datas[stmt].lhs..datas[stmt].rhs];
1030 return categorizeBuiltinCall(ast, main_tokens[stmt], params);
932 switch (ast.nodeTag(stmt)) {
933 .builtin_call_two,
934 .builtin_call_two_comma,
935 .builtin_call,
936 .builtin_call_comma,
937 => {
938 var buf: [2]Ast.Node.Index = undefined;
939 const params = ast.builtinCallParams(&buf, stmt).?;
940 return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params);
1031941 },
1032942 .assign => {
1033 const infix = datas[stmt];
1034 if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) {
1035 const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]);
943 const lhs, const rhs = ast.nodeData(stmt).node_and_node;
944 if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) {
945 const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs));
1036946 if (std.mem.eql(u8, name_bytes, "undefined")) {
1037947 return .discard_undefined;
1038948 } else {
......@@ -1074,11 +984,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {
1074984}
1075985
1076986fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {
1077 const node_tags = ast.nodes.items(.tag);
1078 const main_tokens = ast.nodes.items(.main_token);
1079 switch (node_tags[node]) {
987 switch (ast.nodeTag(node)) {
1080988 .identifier => {
1081 const token_index = main_tokens[node];
989 const token_index = ast.nodeMainToken(node);
1082990 const name_bytes = ast.tokenSlice(token_index);
1083991 return std.mem.eql(u8, name_bytes, string);
1084992 },
......@@ -1087,11 +995,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo
1087995}
1088996
1089997fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {
1090 const node_tags = ast.nodes.items(.tag);
1091 const node_data = ast.nodes.items(.data);
1092 switch (node_tags[node]) {
998 switch (ast.nodeTag(node)) {
1093999 .block_two => {
1094 return node_data[node].lhs == 0 and node_data[node].rhs == 0;
1000 const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node;
1001 return opt_lhs == .none and opt_rhs == .none;
10951002 },
10961003 else => return false,
10971004 }
lib/docs/wasm/Decl.zig+30-60
......@@ -15,8 +15,7 @@ parent: Index,
1515pub const ExtraInfo = struct {
1616 is_pub: bool,
1717 name: []const u8,
18 /// This might not be a doc_comment token in which case there are no doc comments.
19 first_doc_comment: Ast.TokenIndex,
18 first_doc_comment: Ast.OptionalTokenIndex,
2019};
2120
2221pub const Index = enum(u32) {
......@@ -34,16 +33,14 @@ pub fn is_pub(d: *const Decl) bool {
3433
3534pub fn extra_info(d: *const Decl) ExtraInfo {
3635 const ast = d.file.get_ast();
37 const token_tags = ast.tokens.items(.tag);
38 const node_tags = ast.nodes.items(.tag);
39 switch (node_tags[d.ast_node]) {
36 switch (ast.nodeTag(d.ast_node)) {
4037 .root => return .{
4138 .name = "",
4239 .is_pub = true,
43 .first_doc_comment = if (token_tags[0] == .container_doc_comment)
44 0
40 .first_doc_comment = if (ast.tokenTag(0) == .container_doc_comment)
41 .fromToken(0)
4542 else
46 token_tags.len - 1,
43 .none,
4744 },
4845
4946 .global_var_decl,
......@@ -53,7 +50,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
5350 => {
5451 const var_decl = ast.fullVarDecl(d.ast_node).?;
5552 const name_token = var_decl.ast.mut_token + 1;
56 assert(token_tags[name_token] == .identifier);
53 assert(ast.tokenTag(name_token) == .identifier);
5754 const ident_name = ast.tokenSlice(name_token);
5855 return .{
5956 .name = ident_name,
......@@ -71,7 +68,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
7168 var buf: [1]Ast.Node.Index = undefined;
7269 const fn_proto = ast.fullFnProto(&buf, d.ast_node).?;
7370 const name_token = fn_proto.name_token.?;
74 assert(token_tags[name_token] == .identifier);
71 assert(ast.tokenTag(name_token) == .identifier);
7572 const ident_name = ast.tokenSlice(name_token);
7673 return .{
7774 .name = ident_name,
......@@ -89,9 +86,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
8986
9087pub fn value_node(d: *const Decl) ?Ast.Node.Index {
9188 const ast = d.file.get_ast();
92 const node_tags = ast.nodes.items(.tag);
93 const token_tags = ast.tokens.items(.tag);
94 return switch (node_tags[d.ast_node]) {
89 return switch (ast.nodeTag(d.ast_node)) {
9590 .fn_proto,
9691 .fn_proto_multi,
9792 .fn_proto_one,
......@@ -106,8 +101,8 @@ pub fn value_node(d: *const Decl) ?Ast.Node.Index {
106101 .aligned_var_decl,
107102 => {
108103 const var_decl = ast.fullVarDecl(d.ast_node).?;
109 if (token_tags[var_decl.ast.mut_token] == .keyword_const)
110 return var_decl.ast.init_node;
104 if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_const)
105 return var_decl.ast.init_node.unwrap();
111106
112107 return null;
113108 },
......@@ -148,19 +143,12 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index {
148143pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index {
149144 if (decl.get_type_fn_return_expr()) |return_expr| {
150145 const ast = decl.file.get_ast();
151 const node_tags = ast.nodes.items(.tag);
152
153 switch (node_tags[return_expr]) {
154 .call, .call_comma, .call_one, .call_one_comma => {
155 const node_data = ast.nodes.items(.data);
156 const function = node_data[return_expr].lhs;
157 const token = ast.nodes.items(.main_token)[function];
158 const name = ast.tokenSlice(token);
159 if (decl.lookup(name)) |function_decl| {
160 return function_decl;
161 }
162 },
163 else => {},
146 var buffer: [1]Ast.Node.Index = undefined;
147 const call = ast.fullCall(&buffer, return_expr) orelse return null;
148 const token = ast.nodeMainToken(call.ast.fn_expr);
149 const name = ast.tokenSlice(token);
150 if (decl.lookup(name)) |function_decl| {
151 return function_decl;
164152 }
165153 }
166154 return null;
......@@ -171,35 +159,18 @@ pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index {
171159 switch (decl.categorize()) {
172160 .type_function => {
173161 const ast = decl.file.get_ast();
174 const node_tags = ast.nodes.items(.tag);
175 const node_data = ast.nodes.items(.data);
176 const body_node = node_data[decl.ast_node].rhs;
177 if (body_node == 0) return null;
178162
179 switch (node_tags[body_node]) {
180 .block, .block_semicolon => {
181 const statements = ast.extra_data[node_data[body_node].lhs..node_data[body_node].rhs];
182 // Look for the return statement
183 for (statements) |stmt| {
184 if (node_tags[stmt] == .@"return") {
185 return node_data[stmt].lhs;
186 }
187 }
188 return null;
189 },
190 .block_two, .block_two_semicolon => {
191 if (node_tags[node_data[body_node].lhs] == .@"return") {
192 return node_data[node_data[body_node].lhs].lhs;
193 }
194 if (node_data[body_node].rhs != 0 and
195 node_tags[node_data[body_node].rhs] == .@"return")
196 {
197 return node_data[node_data[body_node].rhs].lhs;
198 }
199 return null;
200 },
201 else => return null,
163 const body_node = ast.nodeData(decl.ast_node).node_and_node[1];
164
165 var buf: [2]Ast.Node.Index = undefined;
166 const statements = ast.blockStatements(&buf, body_node) orelse return null;
167
168 for (statements) |stmt| {
169 if (ast.nodeTag(stmt) == .@"return") {
170 return ast.nodeData(stmt).node;
171 }
202172 }
173 return null;
203174 },
204175 else => return null,
205176 }
......@@ -269,16 +240,15 @@ pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) O
269240 }
270241}
271242
272pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.TokenIndex {
273 const token_tags = ast.tokens.items(.tag);
243pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.OptionalTokenIndex {
274244 var it = token;
275245 while (it > 0) {
276246 it -= 1;
277 if (token_tags[it] != .doc_comment) {
278 return it + 1;
247 if (ast.tokenTag(it) != .doc_comment) {
248 return .fromToken(it + 1);
279249 }
280250 }
281 return it;
251 return .none;
282252}
283253
284254/// Successively looks up each component.
lib/docs/wasm/Walk.zig+92-134
......@@ -91,12 +91,10 @@ pub const File = struct {
9191
9292 pub fn categorize_decl(file_index: File.Index, node: Ast.Node.Index) Category {
9393 const ast = file_index.get_ast();
94 const node_tags = ast.nodes.items(.tag);
95 const token_tags = ast.tokens.items(.tag);
96 switch (node_tags[node]) {
94 switch (ast.nodeTag(node)) {
9795 .root => {
9896 for (ast.rootDecls()) |member| {
99 switch (node_tags[member]) {
97 switch (ast.nodeTag(member)) {
10098 .container_field_init,
10199 .container_field_align,
102100 .container_field,
......@@ -113,10 +111,12 @@ pub const File = struct {
113111 .aligned_var_decl,
114112 => {
115113 const var_decl = ast.fullVarDecl(node).?;
116 if (token_tags[var_decl.ast.mut_token] == .keyword_var)
114 if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_var)
117115 return .{ .global_variable = node };
116 const init_node = var_decl.ast.init_node.unwrap() orelse
117 return .{ .global_const = node };
118118
119 return categorize_expr(file_index, var_decl.ast.init_node);
119 return categorize_expr(file_index, init_node);
120120 },
121121
122122 .fn_proto,
......@@ -139,7 +139,7 @@ pub const File = struct {
139139 node: Ast.Node.Index,
140140 full: Ast.full.FnProto,
141141 ) Category {
142 return switch (categorize_expr(file_index, full.ast.return_type)) {
142 return switch (categorize_expr(file_index, full.ast.return_type.unwrap().?)) {
143143 .namespace, .container, .error_set, .type_type => .{ .type_function = node },
144144 else => .{ .function = node },
145145 };
......@@ -155,12 +155,8 @@ pub const File = struct {
155155 pub fn categorize_expr(file_index: File.Index, node: Ast.Node.Index) Category {
156156 const file = file_index.get();
157157 const ast = file_index.get_ast();
158 const node_tags = ast.nodes.items(.tag);
159 const node_datas = ast.nodes.items(.data);
160 const main_tokens = ast.nodes.items(.main_token);
161 const token_tags = ast.tokens.items(.tag);
162 //log.debug("categorize_expr tag {s}", .{@tagName(node_tags[node])});
163 return switch (node_tags[node]) {
158 //log.debug("categorize_expr tag {s}", .{@tagName(ast.nodeTag(node))});
159 return switch (ast.nodeTag(node)) {
164160 .container_decl,
165161 .container_decl_trailing,
166162 .container_decl_arg,
......@@ -176,11 +172,11 @@ pub const File = struct {
176172 => {
177173 var buf: [2]Ast.Node.Index = undefined;
178174 const container_decl = ast.fullContainerDecl(&buf, node).?;
179 if (token_tags[container_decl.ast.main_token] != .keyword_struct) {
175 if (ast.tokenTag(container_decl.ast.main_token) != .keyword_struct) {
180176 return .{ .container = node };
181177 }
182178 for (container_decl.ast.members) |member| {
183 switch (node_tags[member]) {
179 switch (ast.nodeTag(member)) {
184180 .container_field_init,
185181 .container_field_align,
186182 .container_field,
......@@ -196,7 +192,7 @@ pub const File = struct {
196192 => .{ .error_set = node },
197193
198194 .identifier => {
199 const name_token = ast.nodes.items(.main_token)[node];
195 const name_token = ast.nodeMainToken(node);
200196 const ident_name = ast.tokenSlice(name_token);
201197 if (std.mem.eql(u8, ident_name, "type"))
202198 return .type_type;
......@@ -217,9 +213,7 @@ pub const File = struct {
217213 },
218214
219215 .field_access => {
220 const object_node = node_datas[node].lhs;
221 const dot_token = main_tokens[node];
222 const field_ident = dot_token + 1;
216 const object_node, const field_ident = ast.nodeData(node).node_and_token;
223217 const field_name = ast.tokenSlice(field_ident);
224218
225219 switch (categorize_expr(file_index, object_node)) {
......@@ -232,20 +226,13 @@ pub const File = struct {
232226 return .{ .global_const = node };
233227 },
234228
235 .builtin_call_two, .builtin_call_two_comma => {
236 if (node_datas[node].lhs == 0) {
237 const params = [_]Ast.Node.Index{};
238 return categorize_builtin_call(file_index, node, &params);
239 } else if (node_datas[node].rhs == 0) {
240 const params = [_]Ast.Node.Index{node_datas[node].lhs};
241 return categorize_builtin_call(file_index, node, &params);
242 } else {
243 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
244 return categorize_builtin_call(file_index, node, &params);
245 }
246 },
247 .builtin_call, .builtin_call_comma => {
248 const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
229 .builtin_call_two,
230 .builtin_call_two_comma,
231 .builtin_call,
232 .builtin_call_comma,
233 => {
234 var buf: [2]Ast.Node.Index = undefined;
235 const params = ast.builtinCallParams(&buf, node).?;
249236 return categorize_builtin_call(file_index, node, params);
250237 },
251238
......@@ -266,9 +253,9 @@ pub const File = struct {
266253 .@"if",
267254 => {
268255 const if_full = ast.fullIf(node).?;
269 if (if_full.ast.else_expr != 0) {
256 if (if_full.ast.else_expr.unwrap()) |else_expr| {
270257 const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr);
271 const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr);
258 const else_cat = categorize_expr_deep(file_index, else_expr);
272259 if (then_cat == .type_type and else_cat == .type_type) {
273260 return .type_type;
274261 } else if (then_cat == .error_set and else_cat == .error_set) {
......@@ -327,11 +314,10 @@ pub const File = struct {
327314 params: []const Ast.Node.Index,
328315 ) Category {
329316 const ast = file_index.get_ast();
330 const main_tokens = ast.nodes.items(.main_token);
331 const builtin_token = main_tokens[node];
317 const builtin_token = ast.nodeMainToken(node);
332318 const builtin_name = ast.tokenSlice(builtin_token);
333319 if (std.mem.eql(u8, builtin_name, "@import")) {
334 const str_lit_token = main_tokens[params[0]];
320 const str_lit_token = ast.nodeMainToken(params[0]);
335321 const str_bytes = ast.tokenSlice(str_lit_token);
336322 const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM");
337323 defer gpa.free(file_path);
......@@ -364,14 +350,12 @@ pub const File = struct {
364350
365351 fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category {
366352 const ast = file_index.get_ast();
367 const node_datas = ast.nodes.items(.data);
368 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
369 const case_nodes = ast.extra_data[extra.start..extra.end];
353 const full = ast.fullSwitch(node).?;
370354 var all_type_type = true;
371355 var all_error_set = true;
372356 var any_type = false;
373 if (case_nodes.len == 0) return .{ .global_const = node };
374 for (case_nodes) |case_node| {
357 if (full.ast.cases.len == 0) return .{ .global_const = node };
358 for (full.ast.cases) |case_node| {
375359 const case = ast.fullSwitchCase(case_node).?;
376360 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {
377361 .type_type => {
......@@ -417,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {
417401 const scope = try gpa.create(Scope);
418402 scope.* = .{ .tag = .top };
419403
420 const decl_index = try file_index.add_decl(0, .none);
421 try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot());
404 const decl_index = try file_index.add_decl(.root, .none);
405 try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot());
422406
423407 const file = file_index.get();
424408 shrinkToFit(&file.ident_decls);
......@@ -512,13 +496,12 @@ pub const Scope = struct {
512496 }
513497
514498 pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index {
515 const main_tokens = ast.nodes.items(.main_token);
516499 var it: *Scope = start_scope;
517500 while (true) switch (it.tag) {
518501 .top => break,
519502 .local => {
520503 const local: *Local = @alignCast(@fieldParentPtr("base", it));
521 const name_token = main_tokens[local.var_node] + 1;
504 const name_token = ast.nodeMainToken(local.var_node) + 1;
522505 const ident_name = ast.tokenSlice(name_token);
523506 if (std.mem.eql(u8, ident_name, name)) {
524507 return local.var_node;
......@@ -545,8 +528,6 @@ fn struct_decl(
545528 container_decl: Ast.full.ContainerDecl,
546529) Oom!void {
547530 const ast = w.file.get_ast();
548 const node_tags = ast.nodes.items(.tag);
549 const node_datas = ast.nodes.items(.data);
550531
551532 const namespace = try gpa.create(Scope.Namespace);
552533 namespace.* = .{
......@@ -556,7 +537,7 @@ fn struct_decl(
556537 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);
557538 try w.scanDecls(namespace, container_decl.ast.members);
558539
559 for (container_decl.ast.members) |member| switch (node_tags[member]) {
540 for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) {
560541 .container_field_init,
561542 .container_field_align,
562543 .container_field,
......@@ -576,7 +557,7 @@ fn struct_decl(
576557 try w.file.get().doctests.put(gpa, member, doctest_node);
577558 }
578559 const decl_index = try w.file.add_decl(member, parent_decl);
579 const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0;
560 const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none;
580561 try w.fn_decl(&namespace.base, decl_index, body, full);
581562 },
582563
......@@ -591,9 +572,9 @@ fn struct_decl(
591572
592573 .@"comptime",
593574 .@"usingnamespace",
594 => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs),
575 => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
595576
596 .test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs),
577 .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]),
597578
598579 else => unreachable,
599580 };
......@@ -640,13 +621,13 @@ fn fn_decl(
640621 w: *Walk,
641622 scope: *Scope,
642623 parent_decl: Decl.Index,
643 body: Ast.Node.Index,
624 body: Ast.Node.OptionalIndex,
644625 full: Ast.full.FnProto,
645626) Oom!void {
646627 for (full.ast.params) |param| {
647628 try expr(w, scope, parent_decl, param);
648629 }
649 try expr(w, scope, parent_decl, full.ast.return_type);
630 try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?);
650631 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);
651632 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);
652633 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);
......@@ -654,17 +635,13 @@ fn fn_decl(
654635 try maybe_expr(w, scope, parent_decl, body);
655636}
656637
657fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
658 if (node != 0) return expr(w, scope, parent_decl, node);
638fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.OptionalIndex) Oom!void {
639 if (node.unwrap()) |n| return expr(w, scope, parent_decl, n);
659640}
660641
661642fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
662 assert(node != 0);
663643 const ast = w.file.get_ast();
664 const node_tags = ast.nodes.items(.tag);
665 const node_datas = ast.nodes.items(.data);
666 const main_tokens = ast.nodes.items(.main_token);
667 switch (node_tags[node]) {
644 switch (ast.nodeTag(node)) {
668645 .root => unreachable, // Top-level declaration.
669646 .@"usingnamespace" => unreachable, // Top-level declaration.
670647 .test_decl => unreachable, // Top-level declaration.
......@@ -745,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
745722 .array_access,
746723 .switch_range,
747724 => {
748 try expr(w, scope, parent_decl, node_datas[node].lhs);
749 try expr(w, scope, parent_decl, node_datas[node].rhs);
725 const lhs, const rhs = ast.nodeData(node).node_and_node;
726 try expr(w, scope, parent_decl, lhs);
727 try expr(w, scope, parent_decl, rhs);
750728 },
751729
752730 .assign_destructure => {
......@@ -759,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
759737 .bit_not,
760738 .negation,
761739 .negation_wrap,
762 .@"return",
763740 .deref,
764741 .address_of,
765742 .optional_type,
766 .unwrap_optional,
767 .grouped_expression,
768743 .@"comptime",
769744 .@"nosuspend",
770745 .@"suspend",
771746 .@"await",
772747 .@"resume",
773748 .@"try",
774 => try maybe_expr(w, scope, parent_decl, node_datas[node].lhs),
749 => try expr(w, scope, parent_decl, ast.nodeData(node).node),
750 .unwrap_optional,
751 .grouped_expression,
752 => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
753 .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node),
775754
776 .anyframe_type,
777 .@"break",
778 => try maybe_expr(w, scope, parent_decl, node_datas[node].rhs),
755 .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]),
756 .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]),
779757
780758 .identifier => {
781 const ident_token = main_tokens[node];
759 const ident_token = ast.nodeMainToken(node);
782760 const ident_name = ast.tokenSlice(ident_token);
783761 if (scope.lookup(ast, ident_name)) |var_node| {
784762 try w.file.get().ident_decls.put(gpa, ident_token, var_node);
785763 }
786764 },
787765 .field_access => {
788 const object_node = node_datas[node].lhs;
789 const dot_token = main_tokens[node];
790 const field_ident = dot_token + 1;
766 const object_node, const field_ident = ast.nodeData(node).node_and_token;
791767 try w.file.get().token_parents.put(gpa, field_ident, node);
792768 // This will populate the left-most field object if it is an
793769 // identifier, allowing rendering code to piece together the link.
......@@ -818,20 +794,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
818794 try expr(w, scope, parent_decl, full.ast.template);
819795 },
820796
821 .builtin_call_two, .builtin_call_two_comma => {
822 if (node_datas[node].lhs == 0) {
823 const params = [_]Ast.Node.Index{};
824 return builtin_call(w, scope, parent_decl, node, &params);
825 } else if (node_datas[node].rhs == 0) {
826 const params = [_]Ast.Node.Index{node_datas[node].lhs};
827 return builtin_call(w, scope, parent_decl, node, &params);
828 } else {
829 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
830 return builtin_call(w, scope, parent_decl, node, &params);
831 }
832 },
833 .builtin_call, .builtin_call_comma => {
834 const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
797 .builtin_call_two,
798 .builtin_call_two_comma,
799 .builtin_call,
800 .builtin_call_comma,
801 => {
802 var buf: [2]Ast.Node.Index = undefined;
803 const params = ast.builtinCallParams(&buf, node).?;
835804 return builtin_call(w, scope, parent_decl, node, params);
836805 },
837806
......@@ -871,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
871840 .for_simple, .@"for" => {
872841 const full = ast.fullFor(node).?;
873842 for (full.ast.inputs) |input| {
874 if (node_tags[input] == .for_range) {
875 try expr(w, scope, parent_decl, node_datas[input].lhs);
876 try maybe_expr(w, scope, parent_decl, node_datas[input].rhs);
843 if (ast.nodeTag(input) == .for_range) {
844 const start, const end = ast.nodeData(input).node_and_opt_node;
845 try expr(w, scope, parent_decl, start);
846 try maybe_expr(w, scope, parent_decl, end);
877847 } else {
878848 try expr(w, scope, parent_decl, input);
879849 }
......@@ -886,18 +856,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
886856 .slice_open => return slice(w, scope, parent_decl, ast.sliceOpen(node)),
887857 .slice_sentinel => return slice(w, scope, parent_decl, ast.sliceSentinel(node)),
888858
889 .block_two, .block_two_semicolon => {
890 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
891 if (node_datas[node].lhs == 0) {
892 return block(w, scope, parent_decl, statements[0..0]);
893 } else if (node_datas[node].rhs == 0) {
894 return block(w, scope, parent_decl, statements[0..1]);
895 } else {
896 return block(w, scope, parent_decl, statements[0..2]);
897 }
898 },
899 .block, .block_semicolon => {
900 const statements = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
859 .block_two,
860 .block_two_semicolon,
861 .block,
862 .block_semicolon,
863 => {
864 var buf: [2]Ast.Node.Index = undefined;
865 const statements = ast.blockStatements(&buf, node).?;
901866 return block(w, scope, parent_decl, statements);
902867 },
903868
......@@ -933,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
933898 },
934899
935900 .array_type_sentinel => {
936 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
937 try expr(w, scope, parent_decl, node_datas[node].lhs);
901 const len_expr, const extra_index = ast.nodeData(node).node_and_extra;
902 const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
903 try expr(w, scope, parent_decl, len_expr);
938904 try expr(w, scope, parent_decl, extra.elem_type);
939905 try expr(w, scope, parent_decl, extra.sentinel);
940906 },
941907 .@"switch", .switch_comma => {
942 const operand_node = node_datas[node].lhs;
943 try expr(w, scope, parent_decl, operand_node);
944 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
945 const case_nodes = ast.extra_data[extra.start..extra.end];
946 for (case_nodes) |case_node| {
908 const full = ast.fullSwitch(node).?;
909 try expr(w, scope, parent_decl, full.ast.condition);
910 for (full.ast.cases) |case_node| {
947911 const case = ast.fullSwitchCase(case_node).?;
948912 for (case.ast.values) |value_node| {
949913 try expr(w, scope, parent_decl, value_node);
......@@ -992,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
992956 .fn_proto,
993957 => {
994958 var buf: [1]Ast.Node.Index = undefined;
995 return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?);
959 return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?);
996960 },
997961 }
998962}
......@@ -1012,8 +976,7 @@ fn builtin_call(
1012976 params: []const Ast.Node.Index,
1013977) Oom!void {
1014978 const ast = w.file.get_ast();
1015 const main_tokens = ast.nodes.items(.main_token);
1016 const builtin_token = main_tokens[node];
979 const builtin_token = ast.nodeMainToken(node);
1017980 const builtin_name = ast.tokenSlice(builtin_token);
1018981 if (std.mem.eql(u8, builtin_name, "@This")) {
1019982 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());
......@@ -1031,13 +994,11 @@ fn block(
1031994 statements: []const Ast.Node.Index,
1032995) Oom!void {
1033996 const ast = w.file.get_ast();
1034 const node_tags = ast.nodes.items(.tag);
1035 const node_datas = ast.nodes.items(.data);
1036997
1037998 var scope = parent_scope;
1038999
10391000 for (statements) |node| {
1040 switch (node_tags[node]) {
1001 switch (ast.nodeTag(node)) {
10411002 .global_var_decl,
10421003 .local_var_decl,
10431004 .simple_var_decl,
......@@ -1058,11 +1019,10 @@ fn block(
10581019 log.debug("walk assign_destructure not implemented yet", .{});
10591020 },
10601021
1061 .grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs),
1022 .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
10621023
1063 .@"defer",
1064 .@"errdefer",
1065 => try expr(w, scope, parent_decl, node_datas[node].rhs),
1024 .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
1025 .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]),
10661026
10671027 else => try expr(w, scope, parent_decl, node),
10681028 }
......@@ -1078,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W
10781038
10791039fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void {
10801040 const ast = w.file.get_ast();
1081 const node_tags = ast.nodes.items(.tag);
1082 const main_tokens = ast.nodes.items(.main_token);
1083 const token_tags = ast.tokens.items(.tag);
1084 const node_datas = ast.nodes.items(.data);
10851041
10861042 for (members) |member_node| {
1087 const name_token = switch (node_tags[member_node]) {
1043 const name_token = switch (ast.nodeTag(member_node)) {
10881044 .global_var_decl,
10891045 .local_var_decl,
10901046 .simple_var_decl,
10911047 .aligned_var_decl,
1092 => main_tokens[member_node] + 1,
1048 => ast.nodeMainToken(member_node) + 1,
10931049
10941050 .fn_proto_simple,
10951051 .fn_proto_multi,
......@@ -1097,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In
10971053 .fn_proto,
10981054 .fn_decl,
10991055 => blk: {
1100 const ident = main_tokens[member_node] + 1;
1101 if (token_tags[ident] != .identifier) continue;
1056 const ident = ast.nodeMainToken(member_node) + 1;
1057 if (ast.tokenTag(ident) != .identifier) continue;
11021058 break :blk ident;
11031059 },
11041060
11051061 .test_decl => {
1106 const ident_token = node_datas[member_node].lhs;
1107 const is_doctest = token_tags[ident_token] == .identifier;
1108 if (is_doctest) {
1109 const token_bytes = ast.tokenSlice(ident_token);
1110 try namespace.doctests.put(gpa, token_bytes, member_node);
1062 const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0];
1063 if (opt_ident_token.unwrap()) |ident_token| {
1064 const is_doctest = ast.tokenTag(ident_token) == .identifier;
1065 if (is_doctest) {
1066 const token_bytes = ast.tokenSlice(ident_token);
1067 try namespace.doctests.put(gpa, token_bytes, member_node);
1068 }
11111069 }
11121070 continue;
11131071 },
lib/docs/wasm/html_render.zig+9-18
......@@ -41,14 +41,10 @@ pub fn fileSourceHtml(
4141 var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty;
4242 };
4343
44 const token_tags = ast.tokens.items(.tag);
45 const token_starts = ast.tokens.items(.start);
46 const main_tokens = ast.nodes.items(.main_token);
47
4844 const start_token = ast.firstToken(root_node);
4945 const end_token = ast.lastToken(root_node) + 1;
5046
51 var cursor: usize = token_starts[start_token];
47 var cursor: usize = ast.tokenStart(start_token);
5248
5349 var indent: usize = 0;
5450 if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {
......@@ -64,8 +60,8 @@ pub fn fileSourceHtml(
6460 var next_annotate_index: usize = 0;
6561
6662 for (
67 token_tags[start_token..end_token],
68 token_starts[start_token..end_token],
63 ast.tokens.items(.tag)[start_token..end_token],
64 ast.tokens.items(.start)[start_token..end_token],
6965 start_token..,
7066 ) |tag, start, token_index| {
7167 const between = ast.source[cursor..start];
......@@ -184,7 +180,7 @@ pub fn fileSourceHtml(
184180 .identifier => i: {
185181 if (options.fn_link != .none) {
186182 const fn_link = options.fn_link.get();
187 const fn_token = main_tokens[fn_link.ast_node];
183 const fn_token = ast.nodeMainToken(fn_link.ast_node);
188184 if (token_index == fn_token + 1) {
189185 try out.appendSlice(gpa, "<a class=\"tok-fn\" href=\"#");
190186 _ = missing_feature_url_escape;
......@@ -196,7 +192,7 @@ pub fn fileSourceHtml(
196192 }
197193 }
198194
199 if (token_index > 0 and token_tags[token_index - 1] == .keyword_fn) {
195 if (token_index > 0 and ast.tokenTag(token_index - 1) == .keyword_fn) {
200196 try out.appendSlice(gpa, "<span class=\"tok-fn\">");
201197 try appendEscaped(out, slice);
202198 try out.appendSlice(gpa, "</span>");
......@@ -358,16 +354,11 @@ fn walkFieldAccesses(
358354 node: Ast.Node.Index,
359355) Oom!void {
360356 const ast = file_index.get_ast();
361 const node_tags = ast.nodes.items(.tag);
362 assert(node_tags[node] == .field_access);
363 const node_datas = ast.nodes.items(.data);
364 const main_tokens = ast.nodes.items(.main_token);
365 const object_node = node_datas[node].lhs;
366 const dot_token = main_tokens[node];
367 const field_ident = dot_token + 1;
368 switch (node_tags[object_node]) {
357 assert(ast.nodeTag(node) == .field_access);
358 const object_node, const field_ident = ast.nodeData(node).node_and_token;
359 switch (ast.nodeTag(object_node)) {
369360 .identifier => {
370 const lhs_ident = main_tokens[object_node];
361 const lhs_ident = ast.nodeMainToken(object_node);
371362 try resolveIdentLink(file_index, out, lhs_ident);
372363 },
373364 .field_access => {
lib/docs/wasm/main.zig+34-48
......@@ -124,7 +124,9 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
124124 @memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items);
125125
126126 const ast = decl.file.get_ast();
127 try collect_docs(&g.doc_search_text, ast, info.first_doc_comment);
127 if (info.first_doc_comment.unwrap()) |first_doc_comment| {
128 try collect_docs(&g.doc_search_text, ast, first_doc_comment);
129 }
128130
129131 if (ignore_case) {
130132 ascii_lower(g.full_path_search_text_lower.items);
......@@ -227,18 +229,15 @@ const ErrorIdentifier = packed struct(u64) {
227229 fn hasDocs(ei: ErrorIdentifier) bool {
228230 const decl_index = ei.decl_index;
229231 const ast = decl_index.get().file.get_ast();
230 const token_tags = ast.tokens.items(.tag);
231232 const token_index = ei.token_index;
232233 if (token_index == 0) return false;
233 return token_tags[token_index - 1] == .doc_comment;
234 return ast.tokenTag(token_index - 1) == .doc_comment;
234235 }
235236
236237 fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void {
237238 const decl_index = ei.decl_index;
238239 const ast = decl_index.get().file.get_ast();
239240 const name = ast.tokenSlice(ei.token_index);
240 const first_doc_comment = Decl.findFirstDocComment(ast, ei.token_index);
241 const has_docs = ast.tokens.items(.tag)[first_doc_comment] == .doc_comment;
242241 const has_link = base_decl != decl_index;
243242
244243 try out.appendSlice(gpa, "<dt>");
......@@ -253,7 +252,7 @@ const ErrorIdentifier = packed struct(u64) {
253252 }
254253 try out.appendSlice(gpa, "</dt>");
255254
256 if (has_docs) {
255 if (Decl.findFirstDocComment(ast, ei.token_index).unwrap()) |first_doc_comment| {
257256 try out.appendSlice(gpa, "<dd>");
258257 try render_docs(out, decl_index, first_doc_comment, false);
259258 try out.appendSlice(gpa, "</dd>");
......@@ -319,17 +318,16 @@ fn addErrorsFromExpr(
319318) Oom!void {
320319 const decl = decl_index.get();
321320 const ast = decl.file.get_ast();
322 const node_tags = ast.nodes.items(.tag);
323 const node_datas = ast.nodes.items(.data);
324321
325322 switch (decl.file.categorize_expr(node)) {
326 .error_set => |n| switch (node_tags[n]) {
323 .error_set => |n| switch (ast.nodeTag(n)) {
327324 .error_set_decl => {
328325 try addErrorsFromNode(decl_index, out, node);
329326 },
330327 .merge_error_sets => {
331 try addErrorsFromExpr(decl_index, out, node_datas[node].lhs);
332 try addErrorsFromExpr(decl_index, out, node_datas[node].rhs);
328 const lhs, const rhs = ast.nodeData(n).node_and_node;
329 try addErrorsFromExpr(decl_index, out, lhs);
330 try addErrorsFromExpr(decl_index, out, rhs);
333331 },
334332 else => unreachable,
335333 },
......@@ -347,11 +345,9 @@ fn addErrorsFromNode(
347345) Oom!void {
348346 const decl = decl_index.get();
349347 const ast = decl.file.get_ast();
350 const main_tokens = ast.nodes.items(.main_token);
351 const token_tags = ast.tokens.items(.tag);
352 const error_token = main_tokens[node];
348 const error_token = ast.nodeMainToken(node);
353349 var tok_i = error_token + 2;
354 while (true) : (tok_i += 1) switch (token_tags[tok_i]) {
350 while (true) : (tok_i += 1) switch (ast.tokenTag(tok_i)) {
355351 .doc_comment, .comma => {},
356352 .identifier => {
357353 const name = ast.tokenSlice(tok_i);
......@@ -391,15 +387,13 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index {
391387
392388 switch (decl.categorize()) {
393389 .type_function => {
394 const node_tags = ast.nodes.items(.tag);
395
396390 // If the type function returns a reference to another type function, get the fields from there
397391 if (decl.get_type_fn_return_type_fn()) |function_decl| {
398392 return decl_fields_fallible(function_decl);
399393 }
400394 // If the type function returns a container, such as a `struct`, read that container's fields
401395 if (decl.get_type_fn_return_expr()) |return_expr| {
402 switch (node_tags[return_expr]) {
396 switch (ast.nodeTag(return_expr)) {
403397 .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => {
404398 return ast_decl_fields_fallible(ast, return_expr);
405399 },
......@@ -420,10 +414,9 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In
420414 var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;
421415 };
422416 g.result.clearRetainingCapacity();
423 const node_tags = ast.nodes.items(.tag);
424417 var buf: [2]Ast.Node.Index = undefined;
425418 const container_decl = ast.fullContainerDecl(&buf, ast_index) orelse return &.{};
426 for (container_decl.ast.members) |member_node| switch (node_tags[member_node]) {
419 for (container_decl.ast.members) |member_node| switch (ast.nodeTag(member_node)) {
427420 .container_field_init,
428421 .container_field_align,
429422 .container_field,
......@@ -478,9 +471,8 @@ fn decl_field_html_fallible(
478471 try out.appendSlice(gpa, "</code></pre>");
479472
480473 const field = ast.fullContainerField(field_node).?;
481 const first_doc_comment = Decl.findFirstDocComment(ast, field.firstToken());
482474
483 if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) {
475 if (Decl.findFirstDocComment(ast, field.firstToken()).unwrap()) |first_doc_comment| {
484476 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
485477 try render_docs(out, decl_index, first_doc_comment, false);
486478 try out.appendSlice(gpa, "</div>");
......@@ -494,14 +486,13 @@ fn decl_param_html_fallible(
494486) !void {
495487 const decl = decl_index.get();
496488 const ast = decl.file.get_ast();
497 const token_tags = ast.tokens.items(.tag);
498489 const colon = ast.firstToken(param_node) - 1;
499490 const name_token = colon - 1;
500491 const first_doc_comment = f: {
501492 var it = ast.firstToken(param_node);
502493 while (it > 0) {
503494 it -= 1;
504 switch (token_tags[it]) {
495 switch (ast.tokenTag(it)) {
505496 .doc_comment, .colon, .identifier, .keyword_comptime, .keyword_noalias => {},
506497 else => break,
507498 }
......@@ -516,7 +507,7 @@ fn decl_param_html_fallible(
516507 try fileSourceHtml(decl.file, out, param_node, .{});
517508 try out.appendSlice(gpa, "</code></pre>");
518509
519 if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) {
510 if (ast.tokenTag(first_doc_comment) == .doc_comment) {
520511 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
521512 try render_docs(out, decl_index, first_doc_comment, false);
522513 try out.appendSlice(gpa, "</div>");
......@@ -526,10 +517,8 @@ fn decl_param_html_fallible(
526517export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) String {
527518 const decl = decl_index.get();
528519 const ast = decl.file.get_ast();
529 const node_tags = ast.nodes.items(.tag);
530 const node_datas = ast.nodes.items(.data);
531 const proto_node = switch (node_tags[decl.ast_node]) {
532 .fn_decl => node_datas[decl.ast_node].lhs,
520 const proto_node = switch (ast.nodeTag(decl.ast_node)) {
521 .fn_decl => ast.nodeData(decl.ast_node).node_and_node[0],
533522
534523 .fn_proto,
535524 .fn_proto_one,
......@@ -586,17 +575,16 @@ export fn decl_parent(decl_index: Decl.Index) Decl.Index {
586575 return decl.parent;
587576}
588577
589export fn fn_error_set(decl_index: Decl.Index) Ast.Node.Index {
578export fn fn_error_set(decl_index: Decl.Index) Ast.Node.OptionalIndex {
590579 const decl = decl_index.get();
591580 const ast = decl.file.get_ast();
592581 var buf: [1]Ast.Node.Index = undefined;
593582 const full = ast.fullFnProto(&buf, decl.ast_node).?;
594 const node_tags = ast.nodes.items(.tag);
595 const node_datas = ast.nodes.items(.data);
596 return switch (node_tags[full.ast.return_type]) {
597 .error_set_decl => full.ast.return_type,
598 .error_union => node_datas[full.ast.return_type].lhs,
599 else => 0,
583 const return_type = full.ast.return_type.unwrap().?;
584 return switch (ast.nodeTag(return_type)) {
585 .error_set_decl => return_type.toOptional(),
586 .error_union => ast.nodeData(return_type).node_and_node[0].toOptional(),
587 else => .none,
600588 };
601589}
602590
......@@ -609,21 +597,19 @@ export fn decl_file_path(decl_index: Decl.Index) String {
609597export fn decl_category_name(decl_index: Decl.Index) String {
610598 const decl = decl_index.get();
611599 const ast = decl.file.get_ast();
612 const token_tags = ast.tokens.items(.tag);
613600 const name = switch (decl.categorize()) {
614601 .namespace, .container => |node| {
615 const node_tags = ast.nodes.items(.tag);
616 if (node_tags[decl.ast_node] == .root)
602 if (ast.nodeTag(decl.ast_node) == .root)
617603 return String.init("struct");
618604 string_result.clearRetainingCapacity();
619605 var buf: [2]Ast.Node.Index = undefined;
620606 const container_decl = ast.fullContainerDecl(&buf, node).?;
621607 if (container_decl.layout_token) |t| {
622 if (token_tags[t] == .keyword_extern) {
608 if (ast.tokenTag(t) == .keyword_extern) {
623609 string_result.appendSlice(gpa, "extern ") catch @panic("OOM");
624610 }
625611 }
626 const main_token_tag = token_tags[container_decl.ast.main_token];
612 const main_token_tag = ast.tokenTag(container_decl.ast.main_token);
627613 string_result.appendSlice(gpa, main_token_tag.lexeme().?) catch @panic("OOM");
628614 return String.init(string_result.items);
629615 },
......@@ -656,7 +642,9 @@ export fn decl_name(decl_index: Decl.Index) String {
656642export fn decl_docs_html(decl_index: Decl.Index, short: bool) String {
657643 const decl = decl_index.get();
658644 string_result.clearRetainingCapacity();
659 render_docs(&string_result, decl_index, decl.extra_info().first_doc_comment, short) catch @panic("OOM");
645 if (decl.extra_info().first_doc_comment.unwrap()) |first_doc_comment| {
646 render_docs(&string_result, decl_index, first_doc_comment, short) catch @panic("OOM");
647 }
660648 return String.init(string_result.items);
661649}
662650
......@@ -665,10 +653,9 @@ fn collect_docs(
665653 ast: *const Ast,
666654 first_doc_comment: Ast.TokenIndex,
667655) Oom!void {
668 const token_tags = ast.tokens.items(.tag);
669656 list.clearRetainingCapacity();
670657 var it = first_doc_comment;
671 while (true) : (it += 1) switch (token_tags[it]) {
658 while (true) : (it += 1) switch (ast.tokenTag(it)) {
672659 .doc_comment, .container_doc_comment => {
673660 // It is tempting to trim this string but think carefully about how
674661 // that will affect the markdown parser.
......@@ -687,12 +674,11 @@ fn render_docs(
687674) Oom!void {
688675 const decl = decl_index.get();
689676 const ast = decl.file.get_ast();
690 const token_tags = ast.tokens.items(.tag);
691677
692678 var parser = try markdown.Parser.init(gpa);
693679 defer parser.deinit();
694680 var it = first_doc_comment;
695 while (true) : (it += 1) switch (token_tags[it]) {
681 while (true) : (it += 1) switch (ast.tokenTag(it)) {
696682 .doc_comment, .container_doc_comment => {
697683 const line = ast.tokenSlice(it)[3..];
698684 if (short and line.len == 0) break;
......@@ -767,9 +753,9 @@ export fn decl_type_html(decl_index: Decl.Index) String {
767753 t: {
768754 // If there is an explicit type, use it.
769755 if (ast.fullVarDecl(decl.ast_node)) |var_decl| {
770 if (var_decl.ast.type_node != 0) {
756 if (var_decl.ast.type_node.unwrap()) |type_node| {
771757 string_result.appendSlice(gpa, "<code>") catch @panic("OOM");
772 fileSourceHtml(decl.file, &string_result, var_decl.ast.type_node, .{
758 fileSourceHtml(decl.file, &string_result, type_node, .{
773759 .skip_comments = true,
774760 .collapse_whitespace = true,
775761 }) catch |e| {
lib/std/zig/Ast.zig+1681-1229
......@@ -8,15 +8,12 @@
88source: [:0]const u8,
99
1010tokens: TokenList.Slice,
11/// The root AST node is assumed to be index 0. Since there can be no
12/// references to the root node, this means 0 is available to indicate null.
1311nodes: NodeList.Slice,
14extra_data: []Node.Index,
12extra_data: []u32,
1513mode: Mode = .zig,
1614
1715errors: []const Error,
1816
19pub const TokenIndex = u32;
2017pub const ByteOffset = u32;
2118
2219pub const TokenList = std.MultiArrayList(struct {
......@@ -25,6 +22,91 @@ pub const TokenList = std.MultiArrayList(struct {
2522});
2623pub const NodeList = std.MultiArrayList(Node);
2724
25/// Index into `tokens`.
26pub const TokenIndex = u32;
27
28/// Index into `tokens`, or null.
29pub const OptionalTokenIndex = enum(u32) {
30 none = std.math.maxInt(u32),
31 _,
32
33 pub fn unwrap(oti: OptionalTokenIndex) ?TokenIndex {
34 return if (oti == .none) null else @intFromEnum(oti);
35 }
36
37 pub fn fromToken(ti: TokenIndex) OptionalTokenIndex {
38 return @enumFromInt(ti);
39 }
40
41 pub fn fromOptional(oti: ?TokenIndex) OptionalTokenIndex {
42 return if (oti) |ti| @enumFromInt(ti) else .none;
43 }
44};
45
46/// A relative token index.
47pub const TokenOffset = enum(i32) {
48 zero = 0,
49 _,
50
51 pub fn init(base: TokenIndex, destination: TokenIndex) TokenOffset {
52 const base_i64: i64 = base;
53 const destination_i64: i64 = destination;
54 return @enumFromInt(destination_i64 - base_i64);
55 }
56
57 pub fn toOptional(to: TokenOffset) OptionalTokenOffset {
58 const result: OptionalTokenOffset = @enumFromInt(@intFromEnum(to));
59 assert(result != .none);
60 return result;
61 }
62
63 pub fn toAbsolute(offset: TokenOffset, base: TokenIndex) TokenIndex {
64 return @intCast(@as(i64, base) + @intFromEnum(offset));
65 }
66};
67
68/// A relative token index, or null.
69pub const OptionalTokenOffset = enum(i32) {
70 none = std.math.maxInt(i32),
71 _,
72
73 pub fn unwrap(oto: OptionalTokenOffset) ?TokenOffset {
74 return if (oto == .none) null else @enumFromInt(@intFromEnum(oto));
75 }
76};
77
78pub fn tokenTag(tree: *const Ast, token_index: TokenIndex) Token.Tag {
79 return tree.tokens.items(.tag)[token_index];
80}
81
82pub fn tokenStart(tree: *const Ast, token_index: TokenIndex) ByteOffset {
83 return tree.tokens.items(.start)[token_index];
84}
85
86pub fn nodeTag(tree: *const Ast, node: Node.Index) Node.Tag {
87 return tree.nodes.items(.tag)[@intFromEnum(node)];
88}
89
90pub fn nodeMainToken(tree: *const Ast, node: Node.Index) TokenIndex {
91 return tree.nodes.items(.main_token)[@intFromEnum(node)];
92}
93
94pub fn nodeData(tree: *const Ast, node: Node.Index) Node.Data {
95 return tree.nodes.items(.data)[@intFromEnum(node)];
96}
97
98pub fn isTokenPrecededByTags(
99 tree: *const Ast,
100 ti: TokenIndex,
101 expected_token_tags: []const Token.Tag,
102) bool {
103 return std.mem.endsWith(
104 Token.Tag,
105 tree.tokens.items(.tag)[0..ti],
106 expected_token_tags,
107 );
108}
109
28110pub const Location = struct {
29111 line: usize,
30112 column: usize,
......@@ -77,8 +159,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A
77159 var parser: Parse = .{
78160 .source = source,
79161 .gpa = gpa,
80 .token_tags = tokens.items(.tag),
81 .token_starts = tokens.items(.start),
162 .tokens = tokens.slice(),
82163 .errors = .{},
83164 .nodes = .{},
84165 .extra_data = .{},
......@@ -143,7 +224,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde
143224 .line_start = start_offset,
144225 .line_end = self.source.len,
145226 };
146 const token_start = self.tokens.items(.start)[token_index];
227 const token_start = self.tokenStart(token_index);
147228
148229 // Scan to by line until we go past the token start
149230 while (std.mem.indexOfScalarPos(u8, self.source, loc.line_start, '\n')) |i| {
......@@ -175,9 +256,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde
175256}
176257
177258pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {
178 const token_starts = tree.tokens.items(.start);
179 const token_tags = tree.tokens.items(.tag);
180 const token_tag = token_tags[token_index];
259 const token_tag = tree.tokenTag(token_index);
181260
182261 // Many tokens can be determined entirely by their tag.
183262 if (token_tag.lexeme()) |lexeme| {
......@@ -187,33 +266,54 @@ pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {
187266 // For some tokens, re-tokenization is needed to find the end.
188267 var tokenizer: std.zig.Tokenizer = .{
189268 .buffer = tree.source,
190 .index = token_starts[token_index],
269 .index = tree.tokenStart(token_index),
191270 };
192271 const token = tokenizer.next();
193272 assert(token.tag == token_tag);
194273 return tree.source[token.loc.start..token.loc.end];
195274}
196275
197pub fn extraData(tree: Ast, index: usize, comptime T: type) T {
276pub fn extraDataSlice(tree: Ast, range: Node.SubRange, comptime T: type) []const T {
277 return @ptrCast(tree.extra_data[@intFromEnum(range.start)..@intFromEnum(range.end)]);
278}
279
280pub fn extraDataSliceWithLen(tree: Ast, start: ExtraIndex, len: u32, comptime T: type) []const T {
281 return @ptrCast(tree.extra_data[@intFromEnum(start)..][0..len]);
282}
283
284pub fn extraData(tree: Ast, index: ExtraIndex, comptime T: type) T {
198285 const fields = std.meta.fields(T);
199286 var result: T = undefined;
200287 inline for (fields, 0..) |field, i| {
201 comptime assert(field.type == Node.Index);
202 @field(result, field.name) = tree.extra_data[index + i];
288 @field(result, field.name) = switch (field.type) {
289 Node.Index,
290 Node.OptionalIndex,
291 OptionalTokenIndex,
292 ExtraIndex,
293 => @enumFromInt(tree.extra_data[@intFromEnum(index) + i]),
294 TokenIndex => tree.extra_data[@intFromEnum(index) + i],
295 else => @compileError("unexpected field type: " ++ @typeName(field.type)),
296 };
203297 }
204298 return result;
205299}
206300
301fn loadOptionalNodesIntoBuffer(comptime size: usize, buffer: *[size]Node.Index, items: [size]Node.OptionalIndex) []Node.Index {
302 for (buffer, items, 0..) |*node, opt_node, i| {
303 node.* = opt_node.unwrap() orelse return buffer[0..i];
304 }
305 return buffer[0..];
306}
307
207308pub fn rootDecls(tree: Ast) []const Node.Index {
208 const nodes_data = tree.nodes.items(.data);
209 return switch (tree.mode) {
210 .zig => tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs],
211 .zon => (&nodes_data[0].lhs)[0..1],
212 };
309 switch (tree.mode) {
310 .zig => return tree.extraDataSlice(tree.nodeData(.root).extra_range, Node.Index),
311 // Ensure that the returned slice points into the existing memory of the Ast
312 .zon => return (&tree.nodes.items(.data)[@intFromEnum(Node.Index.root)].node)[0..1],
313 }
213314}
214315
215316pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
216 const token_tags = tree.tokens.items(.tag);
217317 switch (parse_error.tag) {
218318 .asterisk_after_ptr_deref => {
219319 // Note that the token will point at the `.*` but ideally the source
......@@ -228,72 +328,72 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
228328 },
229329 .expected_block => {
230330 return stream.print("expected block, found '{s}'", .{
231 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
331 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
232332 });
233333 },
234334 .expected_block_or_assignment => {
235335 return stream.print("expected block or assignment, found '{s}'", .{
236 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
336 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
237337 });
238338 },
239339 .expected_block_or_expr => {
240340 return stream.print("expected block or expression, found '{s}'", .{
241 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
341 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
242342 });
243343 },
244344 .expected_block_or_field => {
245345 return stream.print("expected block or field, found '{s}'", .{
246 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
346 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
247347 });
248348 },
249349 .expected_container_members => {
250350 return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{
251 token_tags[parse_error.token].symbol(),
351 tree.tokenTag(parse_error.token).symbol(),
252352 });
253353 },
254354 .expected_expr => {
255355 return stream.print("expected expression, found '{s}'", .{
256 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
356 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
257357 });
258358 },
259359 .expected_expr_or_assignment => {
260360 return stream.print("expected expression or assignment, found '{s}'", .{
261 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
361 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
262362 });
263363 },
264364 .expected_expr_or_var_decl => {
265365 return stream.print("expected expression or var decl, found '{s}'", .{
266 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
366 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
267367 });
268368 },
269369 .expected_fn => {
270370 return stream.print("expected function, found '{s}'", .{
271 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
371 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
272372 });
273373 },
274374 .expected_inlinable => {
275375 return stream.print("expected 'while' or 'for', found '{s}'", .{
276 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
376 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
277377 });
278378 },
279379 .expected_labelable => {
280380 return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
281 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
381 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
282382 });
283383 },
284384 .expected_param_list => {
285385 return stream.print("expected parameter list, found '{s}'", .{
286 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
386 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
287387 });
288388 },
289389 .expected_prefix_expr => {
290390 return stream.print("expected prefix expression, found '{s}'", .{
291 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
391 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
292392 });
293393 },
294394 .expected_primary_type_expr => {
295395 return stream.print("expected primary type expression, found '{s}'", .{
296 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
396 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
297397 });
298398 },
299399 .expected_pub_item => {
......@@ -301,7 +401,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
301401 },
302402 .expected_return_type => {
303403 return stream.print("expected return type expression, found '{s}'", .{
304 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
404 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
305405 });
306406 },
307407 .expected_semi_or_else => {
......@@ -312,37 +412,37 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
312412 },
313413 .expected_statement => {
314414 return stream.print("expected statement, found '{s}'", .{
315 token_tags[parse_error.token].symbol(),
415 tree.tokenTag(parse_error.token).symbol(),
316416 });
317417 },
318418 .expected_suffix_op => {
319419 return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
320 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
420 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
321421 });
322422 },
323423 .expected_type_expr => {
324424 return stream.print("expected type expression, found '{s}'", .{
325 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
425 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
326426 });
327427 },
328428 .expected_var_decl => {
329429 return stream.print("expected variable declaration, found '{s}'", .{
330 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
430 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
331431 });
332432 },
333433 .expected_var_decl_or_fn => {
334434 return stream.print("expected variable declaration or function, found '{s}'", .{
335 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
435 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
336436 });
337437 },
338438 .expected_loop_payload => {
339439 return stream.print("expected loop payload, found '{s}'", .{
340 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
440 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
341441 });
342442 },
343443 .expected_container => {
344444 return stream.print("expected a struct, enum or union, found '{s}'", .{
345 token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)].symbol(),
445 tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
346446 });
347447 },
348448 .extern_fn_body => {
......@@ -365,7 +465,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
365465 },
366466 .ptr_mod_on_array_child_type => {
367467 return stream.print("pointer modifier '{s}' not allowed on array child type", .{
368 token_tags[parse_error.token].symbol(),
468 tree.tokenTag(parse_error.token).symbol(),
369469 });
370470 },
371471 .invalid_bit_range => {
......@@ -421,7 +521,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
421521 return stream.writeAll("expected field initializer");
422522 },
423523 .mismatched_binary_op_whitespace => {
424 return stream.print("binary operator `{s}` has whitespace on one side, but not the other.", .{token_tags[parse_error.token].lexeme().?});
524 return stream.print("binary operator `{s}` has whitespace on one side, but not the other.", .{tree.tokenTag(parse_error.token).lexeme().?});
425525 },
426526 .invalid_ampersand_ampersand => {
427527 return stream.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND");
......@@ -472,7 +572,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
472572 },
473573
474574 .expected_token => {
475 const found_tag = token_tags[parse_error.token + @intFromBool(parse_error.token_is_prev)];
575 const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));
476576 const expected_symbol = parse_error.extra.expected_tag.symbol();
477577 switch (found_tag) {
478578 .invalid => return stream.print("expected '{s}', found invalid bytes", .{
......@@ -487,13 +587,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
487587}
488588
489589pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
490 const tags = tree.nodes.items(.tag);
491 const datas = tree.nodes.items(.data);
492 const main_tokens = tree.nodes.items(.main_token);
493 const token_tags = tree.tokens.items(.tag);
494 var end_offset: TokenIndex = 0;
590 var end_offset: u32 = 0;
495591 var n = node;
496 while (true) switch (tags[n]) {
592 while (true) switch (tree.nodeTag(n)) {
497593 .root => return 0,
498594
499595 .test_decl,
......@@ -537,7 +633,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
537633 .array_type,
538634 .array_type_sentinel,
539635 .error_value,
540 => return main_tokens[n] - end_offset,
636 => return tree.nodeMainToken(n) - end_offset,
541637
542638 .array_init_dot,
543639 .array_init_dot_comma,
......@@ -548,11 +644,9 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
548644 .struct_init_dot_two,
549645 .struct_init_dot_two_comma,
550646 .enum_literal,
551 => return main_tokens[n] - 1 - end_offset,
647 => return tree.nodeMainToken(n) - 1 - end_offset,
552648
553649 .@"catch",
554 .field_access,
555 .unwrap_optional,
556650 .equal_equal,
557651 .bang_equal,
558652 .less_than,
......@@ -601,33 +695,37 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
601695 .bool_and,
602696 .bool_or,
603697 .slice_open,
604 .slice,
605 .slice_sentinel,
606 .deref,
607698 .array_access,
608699 .array_init_one,
609700 .array_init_one_comma,
610 .array_init,
611 .array_init_comma,
701 .switch_range,
702 .error_union,
703 => n = tree.nodeData(n).node_and_node[0],
704
705 .for_range,
706 .call_one,
707 .call_one_comma,
612708 .struct_init_one,
613709 .struct_init_one_comma,
710 => n = tree.nodeData(n).node_and_opt_node[0],
711
712 .field_access,
713 .unwrap_optional,
714 => n = tree.nodeData(n).node_and_token[0],
715
716 .slice,
717 .slice_sentinel,
718 .array_init,
719 .array_init_comma,
614720 .struct_init,
615721 .struct_init_comma,
616 .call_one,
617 .call_one_comma,
618722 .call,
619723 .call_comma,
620 .switch_range,
621 .for_range,
622 .error_union,
623 => n = datas[n].lhs,
724 => n = tree.nodeData(n).node_and_extra[0],
624725
625 .assign_destructure => {
626 const extra_idx = datas[n].lhs;
627 const lhs_len = tree.extra_data[extra_idx];
628 assert(lhs_len > 0);
629 n = tree.extra_data[extra_idx + 1];
630 },
726 .deref => n = tree.nodeData(n).node,
727
728 .assign_destructure => n = tree.assignDestructure(n).ast.variables[0],
631729
632730 .fn_decl,
633731 .fn_proto_simple,
......@@ -635,10 +733,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
635733 .fn_proto_one,
636734 .fn_proto,
637735 => {
638 var i = main_tokens[n]; // fn token
736 var i = tree.nodeMainToken(n); // fn token
639737 while (i > 0) {
640738 i -= 1;
641 switch (token_tags[i]) {
739 switch (tree.tokenTag(i)) {
642740 .keyword_extern,
643741 .keyword_export,
644742 .keyword_pub,
......@@ -654,30 +752,33 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
654752 },
655753
656754 .@"usingnamespace" => {
657 const main_token = main_tokens[n];
658 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {
659 end_offset += 1;
660 }
755 const main_token: TokenIndex = tree.nodeMainToken(n);
756 const has_visib_token = tree.isTokenPrecededByTags(main_token, &.{.keyword_pub});
757 end_offset += @intFromBool(has_visib_token);
661758 return main_token - end_offset;
662759 },
663760
664761 .async_call_one,
665762 .async_call_one_comma,
763 => {
764 end_offset += 1; // async token
765 n = tree.nodeData(n).node_and_opt_node[0];
766 },
767
666768 .async_call,
667769 .async_call_comma,
668770 => {
669771 end_offset += 1; // async token
670 n = datas[n].lhs;
772 n = tree.nodeData(n).node_and_extra[0];
671773 },
672774
673775 .container_field_init,
674776 .container_field_align,
675777 .container_field,
676778 => {
677 const name_token = main_tokens[n];
678 if (name_token > 0 and token_tags[name_token - 1] == .keyword_comptime) {
679 end_offset += 1;
680 }
779 const name_token = tree.nodeMainToken(n);
780 const has_comptime_token = tree.isTokenPrecededByTags(name_token, &.{.keyword_comptime});
781 end_offset += @intFromBool(has_comptime_token);
681782 return name_token - end_offset;
682783 },
683784
......@@ -686,10 +787,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
686787 .simple_var_decl,
687788 .aligned_var_decl,
688789 => {
689 var i = main_tokens[n]; // mut token
790 var i = tree.nodeMainToken(n); // mut token
690791 while (i > 0) {
691792 i -= 1;
692 switch (token_tags[i]) {
793 switch (tree.tokenTag(i)) {
693794 .keyword_extern,
694795 .keyword_export,
695796 .keyword_comptime,
......@@ -710,10 +811,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
710811 .block_two_semicolon,
711812 => {
712813 // Look for a label.
713 const lbrace = main_tokens[n];
714 if (token_tags[lbrace - 1] == .colon and
715 token_tags[lbrace - 2] == .identifier)
716 {
814 const lbrace = tree.nodeMainToken(n);
815 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
717816 end_offset += 2;
718817 }
719818 return lbrace - end_offset;
......@@ -732,8 +831,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
732831 .tagged_union_enum_tag,
733832 .tagged_union_enum_tag_trailing,
734833 => {
735 const main_token = main_tokens[n];
736 switch (token_tags[main_token -| 1]) {
834 const main_token = tree.nodeMainToken(n);
835 switch (tree.tokenTag(main_token -| 1)) {
737836 .keyword_packed, .keyword_extern => end_offset += 1,
738837 else => {},
739838 }
......@@ -744,36 +843,26 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
744843 .ptr_type_sentinel,
745844 .ptr_type,
746845 .ptr_type_bit_range,
747 => return main_tokens[n] - end_offset,
846 => return tree.nodeMainToken(n) - end_offset,
748847
749 .switch_case_one => {
750 if (datas[n].lhs == 0) {
751 return main_tokens[n] - 1 - end_offset; // else token
752 } else {
753 n = datas[n].lhs;
754 }
755 },
756 .switch_case_inline_one => {
757 if (datas[n].lhs == 0) {
758 return main_tokens[n] - 2 - end_offset; // else token
848 .switch_case_one,
849 .switch_case_inline_one,
850 .switch_case,
851 .switch_case_inline,
852 => {
853 const full_switch = tree.fullSwitchCase(n).?;
854 if (full_switch.inline_token) |inline_token| {
855 return inline_token;
856 } else if (full_switch.ast.values.len == 0) {
857 return full_switch.ast.arrow_token - 1 - end_offset; // else token
759858 } else {
760 return firstToken(tree, datas[n].lhs) - 1;
859 n = full_switch.ast.values[0];
761860 }
762861 },
763 .switch_case => {
764 const extra = tree.extraData(datas[n].lhs, Node.SubRange);
765 assert(extra.end - extra.start > 0);
766 n = tree.extra_data[extra.start];
767 },
768 .switch_case_inline => {
769 const extra = tree.extraData(datas[n].lhs, Node.SubRange);
770 assert(extra.end - extra.start > 0);
771 return firstToken(tree, tree.extra_data[extra.start]) - 1;
772 },
773862
774863 .asm_output, .asm_input => {
775 assert(token_tags[main_tokens[n] - 1] == .l_bracket);
776 return main_tokens[n] - 1 - end_offset;
864 assert(tree.tokenTag(tree.nodeMainToken(n) - 1) == .l_bracket);
865 return tree.nodeMainToken(n) - 1 - end_offset;
777866 },
778867
779868 .while_simple,
......@@ -783,13 +872,13 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
783872 .@"for",
784873 => {
785874 // Look for a label and inline.
786 const main_token = main_tokens[n];
875 const main_token = tree.nodeMainToken(n);
787876 var result = main_token;
788 if (token_tags[result -| 1] == .keyword_inline) {
789 result -= 1;
877 if (tree.isTokenPrecededByTags(result, &.{.keyword_inline})) {
878 result = result - 1;
790879 }
791 if (token_tags[result -| 1] == .colon) {
792 result -|= 2;
880 if (tree.isTokenPrecededByTags(result, &.{ .identifier, .colon })) {
881 result = result - 2;
793882 }
794883 return result - end_offset;
795884 },
......@@ -797,15 +886,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
797886}
798887
799888pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
800 const tags = tree.nodes.items(.tag);
801 const datas = tree.nodes.items(.data);
802 const main_tokens = tree.nodes.items(.main_token);
803 const token_starts = tree.tokens.items(.start);
804 const token_tags = tree.tokens.items(.tag);
805889 var n = node;
806 var end_offset: TokenIndex = 0;
807 while (true) switch (tags[n]) {
808 .root => return @as(TokenIndex, @intCast(tree.tokens.len - 1)),
890 var end_offset: u32 = 0;
891 while (true) switch (tree.nodeTag(n)) {
892 .root => return @intCast(tree.tokens.len - 1),
809893
810894 .@"usingnamespace",
811895 .bool_not,
......@@ -816,14 +900,12 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
816900 .@"try",
817901 .@"await",
818902 .optional_type,
903 .@"suspend",
819904 .@"resume",
820905 .@"nosuspend",
821906 .@"comptime",
822 => n = datas[n].lhs,
907 => n = tree.nodeData(n).node,
823908
824 .test_decl,
825 .@"errdefer",
826 .@"defer",
827909 .@"catch",
828910 .equal_equal,
829911 .bang_equal,
......@@ -849,7 +931,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
849931 .assign_add_sat,
850932 .assign_sub_sat,
851933 .assign,
852 .assign_destructure,
853934 .merge_error_sets,
854935 .mul,
855936 .div,
......@@ -873,41 +954,52 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
873954 .@"orelse",
874955 .bool_and,
875956 .bool_or,
876 .anyframe_type,
877957 .error_union,
878958 .if_simple,
879959 .while_simple,
880960 .for_simple,
881 .fn_proto_simple,
882 .fn_proto_multi,
961 .fn_decl,
962 .array_type,
963 .switch_range,
964 => n = tree.nodeData(n).node_and_node[1],
965
966 .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1],
967 .@"defer" => n = tree.nodeData(n).node,
968 .anyframe_type => n = tree.nodeData(n).token_and_node[1],
969
970 .switch_case_one,
971 .switch_case_inline_one,
883972 .ptr_type_aligned,
884973 .ptr_type_sentinel,
974 => n = tree.nodeData(n).opt_node_and_node[1],
975
976 .assign_destructure,
885977 .ptr_type,
886978 .ptr_type_bit_range,
887 .array_type,
888 .switch_case_one,
889 .switch_case_inline_one,
890979 .switch_case,
891980 .switch_case_inline,
892 .switch_range,
893 => n = datas[n].rhs,
981 => n = tree.nodeData(n).extra_and_node[1],
894982
895 .for_range => if (datas[n].rhs != 0) {
896 n = datas[n].rhs;
897 } else {
898 return main_tokens[n] + end_offset;
983 .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?,
984 .fn_proto_multi,
985 .fn_proto_one,
986 .fn_proto,
987 => n = tree.nodeData(n).extra_and_opt_node[1].unwrap().?,
988
989 .for_range => {
990 n = tree.nodeData(n).node_and_opt_node[1].unwrap() orelse {
991 return tree.nodeMainToken(n) + end_offset;
992 };
899993 },
900994
901995 .field_access,
902996 .unwrap_optional,
903 .grouped_expression,
904 .multiline_string_literal,
905 .error_set_decl,
906997 .asm_simple,
907 .asm_output,
908 .asm_input,
909 .error_value,
910 => return datas[n].rhs + end_offset,
998 => return tree.nodeData(n).node_and_token[1] + end_offset,
999 .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset,
1000 .multiline_string_literal, .error_set_decl => return tree.nodeData(n).token_and_token[1] + end_offset,
1001 .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset,
1002 .error_value => return tree.nodeMainToken(n) + 2 + end_offset,
9111003
9121004 .anyframe_literal,
9131005 .char_literal,
......@@ -917,82 +1009,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
9171009 .deref,
9181010 .enum_literal,
9191011 .string_literal,
920 => return main_tokens[n] + end_offset,
1012 => return tree.nodeMainToken(n) + end_offset,
9211013
922 .@"return" => if (datas[n].lhs != 0) {
923 n = datas[n].lhs;
924 } else {
925 return main_tokens[n] + end_offset;
1014 .@"return" => {
1015 n = tree.nodeData(n).opt_node.unwrap() orelse {
1016 return tree.nodeMainToken(n) + end_offset;
1017 };
9261018 },
9271019
9281020 .call, .async_call => {
1021 _, const extra_index = tree.nodeData(n).node_and_extra;
1022 const params = tree.extraData(extra_index, Node.SubRange);
1023 assert(params.start != params.end);
9291024 end_offset += 1; // for the rparen
930 const params = tree.extraData(datas[n].rhs, Node.SubRange);
931 if (params.end - params.start == 0) {
932 return main_tokens[n] + end_offset;
933 }
934 n = tree.extra_data[params.end - 1]; // last parameter
1025 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
9351026 },
9361027 .tagged_union_enum_tag => {
937 const members = tree.extraData(datas[n].rhs, Node.SubRange);
938 if (members.end - members.start == 0) {
1028 const arg, const extra_index = tree.nodeData(n).node_and_extra;
1029 const members = tree.extraData(extra_index, Node.SubRange);
1030 if (members.start == members.end) {
9391031 end_offset += 4; // for the rparen + rparen + lbrace + rbrace
940 n = datas[n].lhs;
1032 n = arg;
9411033 } else {
9421034 end_offset += 1; // for the rbrace
943 n = tree.extra_data[members.end - 1]; // last parameter
1035 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9441036 }
9451037 },
9461038 .call_comma,
9471039 .async_call_comma,
9481040 .tagged_union_enum_tag_trailing,
9491041 => {
1042 _, const extra_index = tree.nodeData(n).node_and_extra;
1043 const params = tree.extraData(extra_index, Node.SubRange);
1044 assert(params.start != params.end);
9501045 end_offset += 2; // for the comma/semicolon + rparen/rbrace
951 const params = tree.extraData(datas[n].rhs, Node.SubRange);
952 assert(params.end > params.start);
953 n = tree.extra_data[params.end - 1]; // last parameter
1046 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
9541047 },
9551048 .@"switch" => {
956 const cases = tree.extraData(datas[n].rhs, Node.SubRange);
957 if (cases.end - cases.start == 0) {
1049 const condition, const extra_index = tree.nodeData(n).node_and_extra;
1050 const cases = tree.extraData(extra_index, Node.SubRange);
1051 if (cases.start == cases.end) {
9581052 end_offset += 3; // rparen, lbrace, rbrace
959 n = datas[n].lhs; // condition expression
1053 n = condition;
9601054 } else {
9611055 end_offset += 1; // for the rbrace
962 n = tree.extra_data[cases.end - 1]; // last case
1056 n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case
9631057 }
9641058 },
9651059 .container_decl_arg => {
966 const members = tree.extraData(datas[n].rhs, Node.SubRange);
967 if (members.end - members.start == 0) {
1060 const arg, const extra_index = tree.nodeData(n).node_and_extra;
1061 const members = tree.extraData(extra_index, Node.SubRange);
1062 if (members.end == members.start) {
9681063 end_offset += 3; // for the rparen + lbrace + rbrace
969 n = datas[n].lhs;
1064 n = arg;
9701065 } else {
9711066 end_offset += 1; // for the rbrace
972 n = tree.extra_data[members.end - 1]; // last parameter
1067 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9731068 }
9741069 },
9751070 .@"asm" => {
976 const extra = tree.extraData(datas[n].rhs, Node.Asm);
1071 _, const extra_index = tree.nodeData(n).node_and_extra;
1072 const extra = tree.extraData(extra_index, Node.Asm);
9771073 return extra.rparen + end_offset;
9781074 },
9791075 .array_init,
9801076 .struct_init,
9811077 => {
982 const elements = tree.extraData(datas[n].rhs, Node.SubRange);
983 assert(elements.end - elements.start > 0);
1078 _, const extra_index = tree.nodeData(n).node_and_extra;
1079 const elements = tree.extraData(extra_index, Node.SubRange);
1080 assert(elements.start != elements.end);
9841081 end_offset += 1; // for the rbrace
985 n = tree.extra_data[elements.end - 1]; // last element
1082 n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element
9861083 },
9871084 .array_init_comma,
9881085 .struct_init_comma,
9891086 .container_decl_arg_trailing,
9901087 .switch_comma,
9911088 => {
992 const members = tree.extraData(datas[n].rhs, Node.SubRange);
993 assert(members.end - members.start > 0);
1089 _, const extra_index = tree.nodeData(n).node_and_extra;
1090 const members = tree.extraData(extra_index, Node.SubRange);
1091 assert(members.start != members.end);
9941092 end_offset += 2; // for the comma + rbrace
995 n = tree.extra_data[members.end - 1]; // last parameter
1093 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9961094 },
9971095 .array_init_dot,
9981096 .struct_init_dot,
......@@ -1001,9 +1099,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10011099 .tagged_union,
10021100 .builtin_call,
10031101 => {
1004 assert(datas[n].rhs - datas[n].lhs > 0);
1102 const range = tree.nodeData(n).extra_range;
1103 assert(range.start != range.end);
10051104 end_offset += 1; // for the rbrace
1006 n = tree.extra_data[datas[n].rhs - 1]; // last statement
1105 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement
10071106 },
10081107 .array_init_dot_comma,
10091108 .struct_init_dot_comma,
......@@ -1012,20 +1111,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10121111 .tagged_union_trailing,
10131112 .builtin_call_comma,
10141113 => {
1015 assert(datas[n].rhs - datas[n].lhs > 0);
1114 const range = tree.nodeData(n).extra_range;
1115 assert(range.start != range.end);
10161116 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1017 n = tree.extra_data[datas[n].rhs - 1]; // last member
1117 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
10181118 },
10191119 .call_one,
10201120 .async_call_one,
1021 .array_access,
10221121 => {
1023 end_offset += 1; // for the rparen/rbracket
1024 if (datas[n].rhs == 0) {
1025 return main_tokens[n] + end_offset;
1026 }
1027 n = datas[n].rhs;
1122 _, const first_param = tree.nodeData(n).node_and_opt_node;
1123 end_offset += 1; // for the rparen
1124 n = first_param.unwrap() orelse {
1125 return tree.nodeMainToken(n) + end_offset;
1126 };
10281127 },
1128
10291129 .array_init_dot_two,
10301130 .block_two,
10311131 .builtin_call_two,
......@@ -1033,14 +1133,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10331133 .container_decl_two,
10341134 .tagged_union_two,
10351135 => {
1036 if (datas[n].rhs != 0) {
1136 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1137 if (opt_rhs.unwrap()) |rhs| {
10371138 end_offset += 1; // for the rparen/rbrace
1038 n = datas[n].rhs;
1039 } else if (datas[n].lhs != 0) {
1139 n = rhs;
1140 } else if (opt_lhs.unwrap()) |lhs| {
10401141 end_offset += 1; // for the rparen/rbrace
1041 n = datas[n].lhs;
1142 n = lhs;
10421143 } else {
1043 switch (tags[n]) {
1144 switch (tree.nodeTag(n)) {
10441145 .array_init_dot_two,
10451146 .block_two,
10461147 .struct_init_dot_two,
......@@ -1048,17 +1149,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10481149 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace
10491150 .container_decl_two => {
10501151 var i: u32 = 2; // lbrace + rbrace
1051 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;
1152 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
10521153 end_offset += i;
10531154 },
10541155 .tagged_union_two => {
10551156 var i: u32 = 5; // (enum) {}
1056 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;
1157 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
10571158 end_offset += i;
10581159 },
10591160 else => unreachable,
10601161 }
1061 return main_tokens[n] + end_offset;
1162 return tree.nodeMainToken(n) + end_offset;
10621163 }
10631164 },
10641165 .array_init_dot_two_comma,
......@@ -1068,459 +1169,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10681169 .container_decl_two_trailing,
10691170 .tagged_union_two_trailing,
10701171 => {
1172 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
10711173 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1072 if (datas[n].rhs != 0) {
1073 n = datas[n].rhs;
1074 } else if (datas[n].lhs != 0) {
1075 n = datas[n].lhs;
1174 if (opt_rhs.unwrap()) |rhs| {
1175 n = rhs;
1176 } else if (opt_lhs.unwrap()) |lhs| {
1177 n = lhs;
10761178 } else {
10771179 unreachable;
10781180 }
10791181 },
10801182 .simple_var_decl => {
1081 if (datas[n].rhs != 0) {
1082 n = datas[n].rhs;
1083 } else if (datas[n].lhs != 0) {
1084 n = datas[n].lhs;
1183 const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node;
1184 if (init_node.unwrap()) |rhs| {
1185 n = rhs;
1186 } else if (type_node.unwrap()) |lhs| {
1187 n = lhs;
10851188 } else {
10861189 end_offset += 1; // from mut token to name
1087 return main_tokens[n] + end_offset;
1190 return tree.nodeMainToken(n) + end_offset;
10881191 }
10891192 },
10901193 .aligned_var_decl => {
1091 if (datas[n].rhs != 0) {
1092 n = datas[n].rhs;
1093 } else if (datas[n].lhs != 0) {
1094 end_offset += 1; // for the rparen
1095 n = datas[n].lhs;
1194 const align_node, const init_node = tree.nodeData(n).node_and_opt_node;
1195 if (init_node.unwrap()) |rhs| {
1196 n = rhs;
10961197 } else {
1097 end_offset += 1; // from mut token to name
1098 return main_tokens[n] + end_offset;
1198 end_offset += 1; // for the rparen
1199 n = align_node;
10991200 }
11001201 },
11011202 .global_var_decl => {
1102 if (datas[n].rhs != 0) {
1103 n = datas[n].rhs;
1203 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1204 if (init_node.unwrap()) |rhs| {
1205 n = rhs;
11041206 } else {
1105 const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl);
1106 if (extra.section_node != 0) {
1207 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1208 if (extra.section_node.unwrap()) |section_node| {
11071209 end_offset += 1; // for the rparen
1108 n = extra.section_node;
1109 } else if (extra.align_node != 0) {
1210 n = section_node;
1211 } else if (extra.align_node.unwrap()) |align_node| {
11101212 end_offset += 1; // for the rparen
1111 n = extra.align_node;
1112 } else if (extra.type_node != 0) {
1113 n = extra.type_node;
1213 n = align_node;
1214 } else if (extra.type_node.unwrap()) |type_node| {
1215 n = type_node;
11141216 } else {
11151217 end_offset += 1; // from mut token to name
1116 return main_tokens[n] + end_offset;
1218 return tree.nodeMainToken(n) + end_offset;
11171219 }
11181220 }
11191221 },
11201222 .local_var_decl => {
1121 if (datas[n].rhs != 0) {
1122 n = datas[n].rhs;
1223 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1224 if (init_node.unwrap()) |rhs| {
1225 n = rhs;
11231226 } else {
1124 const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl);
1125 if (extra.align_node != 0) {
1126 end_offset += 1; // for the rparen
1127 n = extra.align_node;
1128 } else if (extra.type_node != 0) {
1129 n = extra.type_node;
1130 } else {
1131 end_offset += 1; // from mut token to name
1132 return main_tokens[n] + end_offset;
1133 }
1227 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
1228 end_offset += 1; // for the rparen
1229 n = extra.align_node;
11341230 }
11351231 },
11361232 .container_field_init => {
1137 if (datas[n].rhs != 0) {
1138 n = datas[n].rhs;
1139 } else if (datas[n].lhs != 0) {
1140 n = datas[n].lhs;
1141 } else {
1142 return main_tokens[n] + end_offset;
1143 }
1233 const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node;
1234 n = value_expr.unwrap() orelse type_expr;
11441235 },
1145 .container_field_align => {
1146 if (datas[n].rhs != 0) {
1147 end_offset += 1; // for the rparen
1148 n = datas[n].rhs;
1149 } else if (datas[n].lhs != 0) {
1150 n = datas[n].lhs;
1151 } else {
1152 return main_tokens[n] + end_offset;
1153 }
1236
1237 .array_access,
1238 .array_init_one,
1239 .container_field_align,
1240 => {
1241 _, const rhs = tree.nodeData(n).node_and_node;
1242 end_offset += 1; // for the rbracket/rbrace/rparen
1243 n = rhs;
11541244 },
11551245 .container_field => {
1156 const extra = tree.extraData(datas[n].rhs, Node.ContainerField);
1157 if (extra.value_expr != 0) {
1158 n = extra.value_expr;
1159 } else if (extra.align_expr != 0) {
1160 end_offset += 1; // for the rparen
1161 n = extra.align_expr;
1162 } else if (datas[n].lhs != 0) {
1163 n = datas[n].lhs;
1164 } else {
1165 return main_tokens[n] + end_offset;
1166 }
1246 _, const extra_index = tree.nodeData(n).node_and_extra;
1247 const extra = tree.extraData(extra_index, Node.ContainerField);
1248 n = extra.value_expr;
11671249 },
11681250
1169 .array_init_one,
1170 .struct_init_one,
1171 => {
1251 .struct_init_one => {
1252 _, const first_field = tree.nodeData(n).node_and_opt_node;
11721253 end_offset += 1; // rbrace
1173 if (datas[n].rhs == 0) {
1174 return main_tokens[n] + end_offset;
1175 } else {
1176 n = datas[n].rhs;
1177 }
1254 n = first_field.unwrap() orelse {
1255 return tree.nodeMainToken(n) + end_offset;
1256 };
1257 },
1258 .slice_open => {
1259 _, const start_node = tree.nodeData(n).node_and_node;
1260 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1261 n = start_node;
1262 },
1263 .array_init_one_comma => {
1264 _, const first_element = tree.nodeData(n).node_and_node;
1265 end_offset += 2; // comma + rbrace
1266 n = first_element;
11781267 },
1179 .slice_open,
11801268 .call_one_comma,
11811269 .async_call_one_comma,
1182 .array_init_one_comma,
11831270 .struct_init_one_comma,
11841271 => {
1272 _, const first_field = tree.nodeData(n).node_and_opt_node;
11851273 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1186 n = datas[n].rhs;
1187 assert(n != 0);
1274 n = first_field.unwrap().?;
11881275 },
11891276 .slice => {
1190 const extra = tree.extraData(datas[n].rhs, Node.Slice);
1191 assert(extra.end != 0); // should have used slice_open
1277 _, const extra_index = tree.nodeData(n).node_and_extra;
1278 const extra = tree.extraData(extra_index, Node.Slice);
11921279 end_offset += 1; // rbracket
11931280 n = extra.end;
11941281 },
11951282 .slice_sentinel => {
1196 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);
1197 assert(extra.sentinel != 0); // should have used slice
1283 _, const extra_index = tree.nodeData(n).node_and_extra;
1284 const extra = tree.extraData(extra_index, Node.SliceSentinel);
11981285 end_offset += 1; // rbracket
11991286 n = extra.sentinel;
12001287 },
12011288
12021289 .@"continue", .@"break" => {
1203 if (datas[n].rhs != 0) {
1204 n = datas[n].rhs;
1205 } else if (datas[n].lhs != 0) {
1206 return datas[n].lhs + end_offset;
1207 } else {
1208 return main_tokens[n] + end_offset;
1209 }
1210 },
1211 .fn_decl => {
1212 if (datas[n].rhs != 0) {
1213 n = datas[n].rhs;
1290 const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node;
1291 if (opt_rhs.unwrap()) |rhs| {
1292 n = rhs;
1293 } else if (opt_label.unwrap()) |lhs| {
1294 return lhs + end_offset;
12141295 } else {
1215 n = datas[n].lhs;
1296 return tree.nodeMainToken(n) + end_offset;
12161297 }
12171298 },
1218 .fn_proto_one => {
1219 const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne);
1220 // addrspace, linksection, callconv, align can appear in any order, so we
1221 // find the last one here.
1222 var max_node: Node.Index = datas[n].rhs;
1223 var max_start = token_starts[main_tokens[max_node]];
1224 var max_offset: TokenIndex = 0;
1225 if (extra.align_expr != 0) {
1226 const start = token_starts[main_tokens[extra.align_expr]];
1227 if (start > max_start) {
1228 max_node = extra.align_expr;
1229 max_start = start;
1230 max_offset = 1; // for the rparen
1231 }
1232 }
1233 if (extra.addrspace_expr != 0) {
1234 const start = token_starts[main_tokens[extra.addrspace_expr]];
1235 if (start > max_start) {
1236 max_node = extra.addrspace_expr;
1237 max_start = start;
1238 max_offset = 1; // for the rparen
1239 }
1240 }
1241 if (extra.section_expr != 0) {
1242 const start = token_starts[main_tokens[extra.section_expr]];
1243 if (start > max_start) {
1244 max_node = extra.section_expr;
1245 max_start = start;
1246 max_offset = 1; // for the rparen
1247 }
1248 }
1249 if (extra.callconv_expr != 0) {
1250 const start = token_starts[main_tokens[extra.callconv_expr]];
1251 if (start > max_start) {
1252 max_node = extra.callconv_expr;
1253 max_start = start;
1254 max_offset = 1; // for the rparen
1255 }
1256 }
1257 n = max_node;
1258 end_offset += max_offset;
1259 },
1260 .fn_proto => {
1261 const extra = tree.extraData(datas[n].lhs, Node.FnProto);
1262 // addrspace, linksection, callconv, align can appear in any order, so we
1263 // find the last one here.
1264 var max_node: Node.Index = datas[n].rhs;
1265 var max_start = token_starts[main_tokens[max_node]];
1266 var max_offset: TokenIndex = 0;
1267 if (extra.align_expr != 0) {
1268 const start = token_starts[main_tokens[extra.align_expr]];
1269 if (start > max_start) {
1270 max_node = extra.align_expr;
1271 max_start = start;
1272 max_offset = 1; // for the rparen
1273 }
1274 }
1275 if (extra.addrspace_expr != 0) {
1276 const start = token_starts[main_tokens[extra.addrspace_expr]];
1277 if (start > max_start) {
1278 max_node = extra.addrspace_expr;
1279 max_start = start;
1280 max_offset = 1; // for the rparen
1281 }
1282 }
1283 if (extra.section_expr != 0) {
1284 const start = token_starts[main_tokens[extra.section_expr]];
1285 if (start > max_start) {
1286 max_node = extra.section_expr;
1287 max_start = start;
1288 max_offset = 1; // for the rparen
1289 }
1290 }
1291 if (extra.callconv_expr != 0) {
1292 const start = token_starts[main_tokens[extra.callconv_expr]];
1293 if (start > max_start) {
1294 max_node = extra.callconv_expr;
1295 max_start = start;
1296 max_offset = 1; // for the rparen
1297 }
1298 }
1299 n = max_node;
1300 end_offset += max_offset;
1301 },
13021299 .while_cont => {
1303 const extra = tree.extraData(datas[n].rhs, Node.WhileCont);
1304 assert(extra.then_expr != 0);
1300 _, const extra_index = tree.nodeData(n).node_and_extra;
1301 const extra = tree.extraData(extra_index, Node.WhileCont);
13051302 n = extra.then_expr;
13061303 },
13071304 .@"while" => {
1308 const extra = tree.extraData(datas[n].rhs, Node.While);
1309 assert(extra.else_expr != 0);
1305 _, const extra_index = tree.nodeData(n).node_and_extra;
1306 const extra = tree.extraData(extra_index, Node.While);
13101307 n = extra.else_expr;
13111308 },
13121309 .@"if" => {
1313 const extra = tree.extraData(datas[n].rhs, Node.If);
1314 assert(extra.else_expr != 0);
1310 _, const extra_index = tree.nodeData(n).node_and_extra;
1311 const extra = tree.extraData(extra_index, Node.If);
13151312 n = extra.else_expr;
13161313 },
13171314 .@"for" => {
1318 const extra = @as(Node.For, @bitCast(datas[n].rhs));
1319 n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)];
1320 },
1321 .@"suspend" => {
1322 if (datas[n].lhs != 0) {
1323 n = datas[n].lhs;
1324 } else {
1325 return main_tokens[n] + end_offset;
1326 }
1315 const extra_index, const extra = tree.nodeData(n).@"for";
1316 const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else);
1317 n = @enumFromInt(tree.extra_data[index]);
13271318 },
13281319 .array_type_sentinel => {
1329 const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel);
1320 _, const extra_index = tree.nodeData(n).node_and_extra;
1321 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
13301322 n = extra.elem_type;
13311323 },
13321324 };
13331325}
13341326
13351327pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {
1336 const token_starts = tree.tokens.items(.start);
1337 const source = tree.source[token_starts[token1]..token_starts[token2]];
1328 const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)];
13381329 return mem.indexOfScalar(u8, source, '\n') == null;
13391330}
13401331
13411332pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {
1342 const token_starts = tree.tokens.items(.start);
13431333 const first_token = tree.firstToken(node);
13441334 const last_token = tree.lastToken(node);
1345 const start = token_starts[first_token];
1346 const end = token_starts[last_token] + tree.tokenSlice(last_token).len;
1335 const start = tree.tokenStart(first_token);
1336 const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len;
13471337 return tree.source[start..end];
13481338}
13491339
13501340pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1351 assert(tree.nodes.items(.tag)[node] == .global_var_decl);
1352 const data = tree.nodes.items(.data)[node];
1353 const extra = tree.extraData(data.lhs, Node.GlobalVarDecl);
1341 assert(tree.nodeTag(node) == .global_var_decl);
1342 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1343 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
13541344 return tree.fullVarDeclComponents(.{
13551345 .type_node = extra.type_node,
13561346 .align_node = extra.align_node,
13571347 .addrspace_node = extra.addrspace_node,
13581348 .section_node = extra.section_node,
1359 .init_node = data.rhs,
1360 .mut_token = tree.nodes.items(.main_token)[node],
1349 .init_node = init_node,
1350 .mut_token = tree.nodeMainToken(node),
13611351 });
13621352}
13631353
13641354pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1365 assert(tree.nodes.items(.tag)[node] == .local_var_decl);
1366 const data = tree.nodes.items(.data)[node];
1367 const extra = tree.extraData(data.lhs, Node.LocalVarDecl);
1355 assert(tree.nodeTag(node) == .local_var_decl);
1356 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1357 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
13681358 return tree.fullVarDeclComponents(.{
1369 .type_node = extra.type_node,
1370 .align_node = extra.align_node,
1371 .addrspace_node = 0,
1372 .section_node = 0,
1373 .init_node = data.rhs,
1374 .mut_token = tree.nodes.items(.main_token)[node],
1359 .type_node = extra.type_node.toOptional(),
1360 .align_node = extra.align_node.toOptional(),
1361 .addrspace_node = .none,
1362 .section_node = .none,
1363 .init_node = init_node,
1364 .mut_token = tree.nodeMainToken(node),
13751365 });
13761366}
13771367
13781368pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1379 assert(tree.nodes.items(.tag)[node] == .simple_var_decl);
1380 const data = tree.nodes.items(.data)[node];
1369 assert(tree.nodeTag(node) == .simple_var_decl);
1370 const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node;
13811371 return tree.fullVarDeclComponents(.{
1382 .type_node = data.lhs,
1383 .align_node = 0,
1384 .addrspace_node = 0,
1385 .section_node = 0,
1386 .init_node = data.rhs,
1387 .mut_token = tree.nodes.items(.main_token)[node],
1372 .type_node = type_node,
1373 .align_node = .none,
1374 .addrspace_node = .none,
1375 .section_node = .none,
1376 .init_node = init_node,
1377 .mut_token = tree.nodeMainToken(node),
13881378 });
13891379}
13901380
13911381pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1392 assert(tree.nodes.items(.tag)[node] == .aligned_var_decl);
1393 const data = tree.nodes.items(.data)[node];
1382 assert(tree.nodeTag(node) == .aligned_var_decl);
1383 const align_node, const init_node = tree.nodeData(node).node_and_opt_node;
13941384 return tree.fullVarDeclComponents(.{
1395 .type_node = 0,
1396 .align_node = data.lhs,
1397 .addrspace_node = 0,
1398 .section_node = 0,
1399 .init_node = data.rhs,
1400 .mut_token = tree.nodes.items(.main_token)[node],
1385 .type_node = .none,
1386 .align_node = align_node.toOptional(),
1387 .addrspace_node = .none,
1388 .section_node = .none,
1389 .init_node = init_node,
1390 .mut_token = tree.nodeMainToken(node),
14011391 });
14021392}
14031393
14041394pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {
1405 const data = tree.nodes.items(.data)[node];
1406 const variable_count = tree.extra_data[data.lhs];
1395 const extra_index, const value_expr = tree.nodeData(node).extra_and_node;
1396 const variable_count = tree.extra_data[@intFromEnum(extra_index)];
14071397 return tree.fullAssignDestructureComponents(.{
1408 .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count],
1409 .equal_token = tree.nodes.items(.main_token)[node],
1410 .value_expr = data.rhs,
1398 .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index),
1399 .equal_token = tree.nodeMainToken(node),
1400 .value_expr = value_expr,
14111401 });
14121402}
14131403
14141404pub fn ifSimple(tree: Ast, node: Node.Index) full.If {
1415 assert(tree.nodes.items(.tag)[node] == .if_simple);
1416 const data = tree.nodes.items(.data)[node];
1405 assert(tree.nodeTag(node) == .if_simple);
1406 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
14171407 return tree.fullIfComponents(.{
1418 .cond_expr = data.lhs,
1419 .then_expr = data.rhs,
1420 .else_expr = 0,
1421 .if_token = tree.nodes.items(.main_token)[node],
1408 .cond_expr = cond_expr,
1409 .then_expr = then_expr,
1410 .else_expr = .none,
1411 .if_token = tree.nodeMainToken(node),
14221412 });
14231413}
14241414
14251415pub fn ifFull(tree: Ast, node: Node.Index) full.If {
1426 assert(tree.nodes.items(.tag)[node] == .@"if");
1427 const data = tree.nodes.items(.data)[node];
1428 const extra = tree.extraData(data.rhs, Node.If);
1416 assert(tree.nodeTag(node) == .@"if");
1417 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1418 const extra = tree.extraData(extra_index, Node.If);
14291419 return tree.fullIfComponents(.{
1430 .cond_expr = data.lhs,
1420 .cond_expr = cond_expr,
14311421 .then_expr = extra.then_expr,
1432 .else_expr = extra.else_expr,
1433 .if_token = tree.nodes.items(.main_token)[node],
1422 .else_expr = extra.else_expr.toOptional(),
1423 .if_token = tree.nodeMainToken(node),
14341424 });
14351425}
14361426
14371427pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {
1438 assert(tree.nodes.items(.tag)[node] == .container_field);
1439 const data = tree.nodes.items(.data)[node];
1440 const extra = tree.extraData(data.rhs, Node.ContainerField);
1441 const main_token = tree.nodes.items(.main_token)[node];
1428 assert(tree.nodeTag(node) == .container_field);
1429 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1430 const extra = tree.extraData(extra_index, Node.ContainerField);
1431 const main_token = tree.nodeMainToken(node);
14421432 return tree.fullContainerFieldComponents(.{
14431433 .main_token = main_token,
1444 .type_expr = data.lhs,
1445 .align_expr = extra.align_expr,
1446 .value_expr = extra.value_expr,
1447 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1448 tree.tokens.items(.tag)[main_token + 1] != .colon,
1434 .type_expr = type_expr.toOptional(),
1435 .align_expr = extra.align_expr.toOptional(),
1436 .value_expr = extra.value_expr.toOptional(),
1437 .tuple_like = tree.tokenTag(main_token) != .identifier or
1438 tree.tokenTag(main_token + 1) != .colon,
14491439 });
14501440}
14511441
14521442pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {
1453 assert(tree.nodes.items(.tag)[node] == .container_field_init);
1454 const data = tree.nodes.items(.data)[node];
1455 const main_token = tree.nodes.items(.main_token)[node];
1443 assert(tree.nodeTag(node) == .container_field_init);
1444 const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node;
1445 const main_token = tree.nodeMainToken(node);
14561446 return tree.fullContainerFieldComponents(.{
14571447 .main_token = main_token,
1458 .type_expr = data.lhs,
1459 .align_expr = 0,
1460 .value_expr = data.rhs,
1461 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1462 tree.tokens.items(.tag)[main_token + 1] != .colon,
1448 .type_expr = type_expr.toOptional(),
1449 .align_expr = .none,
1450 .value_expr = value_expr,
1451 .tuple_like = tree.tokenTag(main_token) != .identifier or
1452 tree.tokenTag(main_token + 1) != .colon,
14631453 });
14641454}
14651455
14661456pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {
1467 assert(tree.nodes.items(.tag)[node] == .container_field_align);
1468 const data = tree.nodes.items(.data)[node];
1469 const main_token = tree.nodes.items(.main_token)[node];
1457 assert(tree.nodeTag(node) == .container_field_align);
1458 const type_expr, const align_expr = tree.nodeData(node).node_and_node;
1459 const main_token = tree.nodeMainToken(node);
14701460 return tree.fullContainerFieldComponents(.{
14711461 .main_token = main_token,
1472 .type_expr = data.lhs,
1473 .align_expr = data.rhs,
1474 .value_expr = 0,
1475 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1476 tree.tokens.items(.tag)[main_token + 1] != .colon,
1462 .type_expr = type_expr.toOptional(),
1463 .align_expr = align_expr.toOptional(),
1464 .value_expr = .none,
1465 .tuple_like = tree.tokenTag(main_token) != .identifier or
1466 tree.tokenTag(main_token + 1) != .colon,
14771467 });
14781468}
14791469
14801470pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1481 assert(tree.nodes.items(.tag)[node] == .fn_proto_simple);
1482 const data = tree.nodes.items(.data)[node];
1483 buffer[0] = data.lhs;
1484 const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1];
1471 assert(tree.nodeTag(node) == .fn_proto_simple);
1472 const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node;
1473 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
14851474 return tree.fullFnProtoComponents(.{
14861475 .proto_node = node,
1487 .fn_token = tree.nodes.items(.main_token)[node],
1488 .return_type = data.rhs,
1476 .fn_token = tree.nodeMainToken(node),
1477 .return_type = return_type,
14891478 .params = params,
1490 .align_expr = 0,
1491 .addrspace_expr = 0,
1492 .section_expr = 0,
1493 .callconv_expr = 0,
1479 .align_expr = .none,
1480 .addrspace_expr = .none,
1481 .section_expr = .none,
1482 .callconv_expr = .none,
14941483 });
14951484}
14961485
14971486pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {
1498 assert(tree.nodes.items(.tag)[node] == .fn_proto_multi);
1499 const data = tree.nodes.items(.data)[node];
1500 const params_range = tree.extraData(data.lhs, Node.SubRange);
1501 const params = tree.extra_data[params_range.start..params_range.end];
1487 assert(tree.nodeTag(node) == .fn_proto_multi);
1488 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1489 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
15021490 return tree.fullFnProtoComponents(.{
15031491 .proto_node = node,
1504 .fn_token = tree.nodes.items(.main_token)[node],
1505 .return_type = data.rhs,
1492 .fn_token = tree.nodeMainToken(node),
1493 .return_type = return_type,
15061494 .params = params,
1507 .align_expr = 0,
1508 .addrspace_expr = 0,
1509 .section_expr = 0,
1510 .callconv_expr = 0,
1495 .align_expr = .none,
1496 .addrspace_expr = .none,
1497 .section_expr = .none,
1498 .callconv_expr = .none,
15111499 });
15121500}
15131501
15141502pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1515 assert(tree.nodes.items(.tag)[node] == .fn_proto_one);
1516 const data = tree.nodes.items(.data)[node];
1517 const extra = tree.extraData(data.lhs, Node.FnProtoOne);
1518 buffer[0] = extra.param;
1519 const params = if (extra.param == 0) buffer[0..0] else buffer[0..1];
1503 assert(tree.nodeTag(node) == .fn_proto_one);
1504 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1505 const extra = tree.extraData(extra_index, Node.FnProtoOne);
1506 const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param});
15201507 return tree.fullFnProtoComponents(.{
15211508 .proto_node = node,
1522 .fn_token = tree.nodes.items(.main_token)[node],
1523 .return_type = data.rhs,
1509 .fn_token = tree.nodeMainToken(node),
1510 .return_type = return_type,
15241511 .params = params,
15251512 .align_expr = extra.align_expr,
15261513 .addrspace_expr = extra.addrspace_expr,
......@@ -1530,14 +1517,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr
15301517}
15311518
15321519pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1533 assert(tree.nodes.items(.tag)[node] == .fn_proto);
1534 const data = tree.nodes.items(.data)[node];
1535 const extra = tree.extraData(data.lhs, Node.FnProto);
1536 const params = tree.extra_data[extra.params_start..extra.params_end];
1520 assert(tree.nodeTag(node) == .fn_proto);
1521 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1522 const extra = tree.extraData(extra_index, Node.FnProto);
1523 const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index);
15371524 return tree.fullFnProtoComponents(.{
15381525 .proto_node = node,
1539 .fn_token = tree.nodes.items(.main_token)[node],
1540 .return_type = data.rhs,
1526 .fn_token = tree.nodeMainToken(node),
1527 .return_type = return_type,
15411528 .params = params,
15421529 .align_expr = extra.align_expr,
15431530 .addrspace_expr = extra.addrspace_expr,
......@@ -1547,300 +1534,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
15471534}
15481535
15491536pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {
1550 assert(tree.nodes.items(.tag)[node] == .struct_init_one or
1551 tree.nodes.items(.tag)[node] == .struct_init_one_comma);
1552 const data = tree.nodes.items(.data)[node];
1553 buffer[0] = data.rhs;
1554 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1537 assert(tree.nodeTag(node) == .struct_init_one or
1538 tree.nodeTag(node) == .struct_init_one_comma);
1539 const type_expr, const first_field = tree.nodeData(node).node_and_opt_node;
1540 const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field});
15551541 return .{
15561542 .ast = .{
1557 .lbrace = tree.nodes.items(.main_token)[node],
1543 .lbrace = tree.nodeMainToken(node),
15581544 .fields = fields,
1559 .type_expr = data.lhs,
1545 .type_expr = type_expr.toOptional(),
15601546 },
15611547 };
15621548}
15631549
15641550pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {
1565 assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or
1566 tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma);
1567 const data = tree.nodes.items(.data)[node];
1568 buffer.* = .{ data.lhs, data.rhs };
1569 const fields = if (data.rhs != 0)
1570 buffer[0..2]
1571 else if (data.lhs != 0)
1572 buffer[0..1]
1573 else
1574 buffer[0..0];
1551 assert(tree.nodeTag(node) == .struct_init_dot_two or
1552 tree.nodeTag(node) == .struct_init_dot_two_comma);
1553 const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
15751554 return .{
15761555 .ast = .{
1577 .lbrace = tree.nodes.items(.main_token)[node],
1556 .lbrace = tree.nodeMainToken(node),
15781557 .fields = fields,
1579 .type_expr = 0,
1558 .type_expr = .none,
15801559 },
15811560 };
15821561}
15831562
15841563pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {
1585 assert(tree.nodes.items(.tag)[node] == .struct_init_dot or
1586 tree.nodes.items(.tag)[node] == .struct_init_dot_comma);
1587 const data = tree.nodes.items(.data)[node];
1564 assert(tree.nodeTag(node) == .struct_init_dot or
1565 tree.nodeTag(node) == .struct_init_dot_comma);
1566 const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
15881567 return .{
15891568 .ast = .{
1590 .lbrace = tree.nodes.items(.main_token)[node],
1591 .fields = tree.extra_data[data.lhs..data.rhs],
1592 .type_expr = 0,
1569 .lbrace = tree.nodeMainToken(node),
1570 .fields = fields,
1571 .type_expr = .none,
15931572 },
15941573 };
15951574}
15961575
15971576pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {
1598 assert(tree.nodes.items(.tag)[node] == .struct_init or
1599 tree.nodes.items(.tag)[node] == .struct_init_comma);
1600 const data = tree.nodes.items(.data)[node];
1601 const fields_range = tree.extraData(data.rhs, Node.SubRange);
1577 assert(tree.nodeTag(node) == .struct_init or
1578 tree.nodeTag(node) == .struct_init_comma);
1579 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1580 const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
16021581 return .{
16031582 .ast = .{
1604 .lbrace = tree.nodes.items(.main_token)[node],
1605 .fields = tree.extra_data[fields_range.start..fields_range.end],
1606 .type_expr = data.lhs,
1583 .lbrace = tree.nodeMainToken(node),
1584 .fields = fields,
1585 .type_expr = type_expr.toOptional(),
16071586 },
16081587 };
16091588}
16101589
16111590pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
1612 assert(tree.nodes.items(.tag)[node] == .array_init_one or
1613 tree.nodes.items(.tag)[node] == .array_init_one_comma);
1614 const data = tree.nodes.items(.data)[node];
1615 buffer[0] = data.rhs;
1616 const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1591 assert(tree.nodeTag(node) == .array_init_one or
1592 tree.nodeTag(node) == .array_init_one_comma);
1593 const type_expr, buffer[0] = tree.nodeData(node).node_and_node;
16171594 return .{
16181595 .ast = .{
1619 .lbrace = tree.nodes.items(.main_token)[node],
1620 .elements = elements,
1621 .type_expr = data.lhs,
1596 .lbrace = tree.nodeMainToken(node),
1597 .elements = buffer[0..1],
1598 .type_expr = type_expr.toOptional(),
16221599 },
16231600 };
16241601}
16251602
16261603pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {
1627 assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or
1628 tree.nodes.items(.tag)[node] == .array_init_dot_two_comma);
1629 const data = tree.nodes.items(.data)[node];
1630 buffer.* = .{ data.lhs, data.rhs };
1631 const elements = if (data.rhs != 0)
1632 buffer[0..2]
1633 else if (data.lhs != 0)
1634 buffer[0..1]
1635 else
1636 buffer[0..0];
1604 assert(tree.nodeTag(node) == .array_init_dot_two or
1605 tree.nodeTag(node) == .array_init_dot_two_comma);
1606 const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
16371607 return .{
16381608 .ast = .{
1639 .lbrace = tree.nodes.items(.main_token)[node],
1609 .lbrace = tree.nodeMainToken(node),
16401610 .elements = elements,
1641 .type_expr = 0,
1611 .type_expr = .none,
16421612 },
16431613 };
16441614}
16451615
16461616pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {
1647 assert(tree.nodes.items(.tag)[node] == .array_init_dot or
1648 tree.nodes.items(.tag)[node] == .array_init_dot_comma);
1649 const data = tree.nodes.items(.data)[node];
1617 assert(tree.nodeTag(node) == .array_init_dot or
1618 tree.nodeTag(node) == .array_init_dot_comma);
1619 const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
16501620 return .{
16511621 .ast = .{
1652 .lbrace = tree.nodes.items(.main_token)[node],
1653 .elements = tree.extra_data[data.lhs..data.rhs],
1654 .type_expr = 0,
1622 .lbrace = tree.nodeMainToken(node),
1623 .elements = elements,
1624 .type_expr = .none,
16551625 },
16561626 };
16571627}
16581628
16591629pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {
1660 assert(tree.nodes.items(.tag)[node] == .array_init or
1661 tree.nodes.items(.tag)[node] == .array_init_comma);
1662 const data = tree.nodes.items(.data)[node];
1663 const elem_range = tree.extraData(data.rhs, Node.SubRange);
1630 assert(tree.nodeTag(node) == .array_init or
1631 tree.nodeTag(node) == .array_init_comma);
1632 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1633 const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
16641634 return .{
16651635 .ast = .{
1666 .lbrace = tree.nodes.items(.main_token)[node],
1667 .elements = tree.extra_data[elem_range.start..elem_range.end],
1668 .type_expr = data.lhs,
1636 .lbrace = tree.nodeMainToken(node),
1637 .elements = elements,
1638 .type_expr = type_expr.toOptional(),
16691639 },
16701640 };
16711641}
16721642
16731643pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {
1674 assert(tree.nodes.items(.tag)[node] == .array_type);
1675 const data = tree.nodes.items(.data)[node];
1644 assert(tree.nodeTag(node) == .array_type);
1645 const elem_count, const elem_type = tree.nodeData(node).node_and_node;
16761646 return .{
16771647 .ast = .{
1678 .lbracket = tree.nodes.items(.main_token)[node],
1679 .elem_count = data.lhs,
1680 .sentinel = 0,
1681 .elem_type = data.rhs,
1648 .lbracket = tree.nodeMainToken(node),
1649 .elem_count = elem_count,
1650 .sentinel = .none,
1651 .elem_type = elem_type,
16821652 },
16831653 };
16841654}
16851655
16861656pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {
1687 assert(tree.nodes.items(.tag)[node] == .array_type_sentinel);
1688 const data = tree.nodes.items(.data)[node];
1689 const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel);
1690 assert(extra.sentinel != 0);
1657 assert(tree.nodeTag(node) == .array_type_sentinel);
1658 const elem_count, const extra_index = tree.nodeData(node).node_and_extra;
1659 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
16911660 return .{
16921661 .ast = .{
1693 .lbracket = tree.nodes.items(.main_token)[node],
1694 .elem_count = data.lhs,
1695 .sentinel = extra.sentinel,
1662 .lbracket = tree.nodeMainToken(node),
1663 .elem_count = elem_count,
1664 .sentinel = extra.sentinel.toOptional(),
16961665 .elem_type = extra.elem_type,
16971666 },
16981667 };
16991668}
17001669
17011670pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {
1702 assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned);
1703 const data = tree.nodes.items(.data)[node];
1671 assert(tree.nodeTag(node) == .ptr_type_aligned);
1672 const align_node, const child_type = tree.nodeData(node).opt_node_and_node;
17041673 return tree.fullPtrTypeComponents(.{
1705 .main_token = tree.nodes.items(.main_token)[node],
1706 .align_node = data.lhs,
1707 .addrspace_node = 0,
1708 .sentinel = 0,
1709 .bit_range_start = 0,
1710 .bit_range_end = 0,
1711 .child_type = data.rhs,
1674 .main_token = tree.nodeMainToken(node),
1675 .align_node = align_node,
1676 .addrspace_node = .none,
1677 .sentinel = .none,
1678 .bit_range_start = .none,
1679 .bit_range_end = .none,
1680 .child_type = child_type,
17121681 });
17131682}
17141683
17151684pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {
1716 assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel);
1717 const data = tree.nodes.items(.data)[node];
1685 assert(tree.nodeTag(node) == .ptr_type_sentinel);
1686 const sentinel, const child_type = tree.nodeData(node).opt_node_and_node;
17181687 return tree.fullPtrTypeComponents(.{
1719 .main_token = tree.nodes.items(.main_token)[node],
1720 .align_node = 0,
1721 .addrspace_node = 0,
1722 .sentinel = data.lhs,
1723 .bit_range_start = 0,
1724 .bit_range_end = 0,
1725 .child_type = data.rhs,
1688 .main_token = tree.nodeMainToken(node),
1689 .align_node = .none,
1690 .addrspace_node = .none,
1691 .sentinel = sentinel,
1692 .bit_range_start = .none,
1693 .bit_range_end = .none,
1694 .child_type = child_type,
17261695 });
17271696}
17281697
17291698pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {
1730 assert(tree.nodes.items(.tag)[node] == .ptr_type);
1731 const data = tree.nodes.items(.data)[node];
1732 const extra = tree.extraData(data.lhs, Node.PtrType);
1699 assert(tree.nodeTag(node) == .ptr_type);
1700 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1701 const extra = tree.extraData(extra_index, Node.PtrType);
17331702 return tree.fullPtrTypeComponents(.{
1734 .main_token = tree.nodes.items(.main_token)[node],
1703 .main_token = tree.nodeMainToken(node),
17351704 .align_node = extra.align_node,
17361705 .addrspace_node = extra.addrspace_node,
17371706 .sentinel = extra.sentinel,
1738 .bit_range_start = 0,
1739 .bit_range_end = 0,
1740 .child_type = data.rhs,
1707 .bit_range_start = .none,
1708 .bit_range_end = .none,
1709 .child_type = child_type,
17411710 });
17421711}
17431712
17441713pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {
1745 assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range);
1746 const data = tree.nodes.items(.data)[node];
1747 const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange);
1714 assert(tree.nodeTag(node) == .ptr_type_bit_range);
1715 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1716 const extra = tree.extraData(extra_index, Node.PtrTypeBitRange);
17481717 return tree.fullPtrTypeComponents(.{
1749 .main_token = tree.nodes.items(.main_token)[node],
1750 .align_node = extra.align_node,
1718 .main_token = tree.nodeMainToken(node),
1719 .align_node = extra.align_node.toOptional(),
17511720 .addrspace_node = extra.addrspace_node,
17521721 .sentinel = extra.sentinel,
1753 .bit_range_start = extra.bit_range_start,
1754 .bit_range_end = extra.bit_range_end,
1755 .child_type = data.rhs,
1722 .bit_range_start = extra.bit_range_start.toOptional(),
1723 .bit_range_end = extra.bit_range_end.toOptional(),
1724 .child_type = child_type,
17561725 });
17571726}
17581727
17591728pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {
1760 assert(tree.nodes.items(.tag)[node] == .slice_open);
1761 const data = tree.nodes.items(.data)[node];
1729 assert(tree.nodeTag(node) == .slice_open);
1730 const sliced, const start = tree.nodeData(node).node_and_node;
17621731 return .{
17631732 .ast = .{
1764 .sliced = data.lhs,
1765 .lbracket = tree.nodes.items(.main_token)[node],
1766 .start = data.rhs,
1767 .end = 0,
1768 .sentinel = 0,
1733 .sliced = sliced,
1734 .lbracket = tree.nodeMainToken(node),
1735 .start = start,
1736 .end = .none,
1737 .sentinel = .none,
17691738 },
17701739 };
17711740}
17721741
17731742pub fn slice(tree: Ast, node: Node.Index) full.Slice {
1774 assert(tree.nodes.items(.tag)[node] == .slice);
1775 const data = tree.nodes.items(.data)[node];
1776 const extra = tree.extraData(data.rhs, Node.Slice);
1743 assert(tree.nodeTag(node) == .slice);
1744 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1745 const extra = tree.extraData(extra_index, Node.Slice);
17771746 return .{
17781747 .ast = .{
1779 .sliced = data.lhs,
1780 .lbracket = tree.nodes.items(.main_token)[node],
1748 .sliced = sliced,
1749 .lbracket = tree.nodeMainToken(node),
17811750 .start = extra.start,
1782 .end = extra.end,
1783 .sentinel = 0,
1751 .end = extra.end.toOptional(),
1752 .sentinel = .none,
17841753 },
17851754 };
17861755}
17871756
17881757pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {
1789 assert(tree.nodes.items(.tag)[node] == .slice_sentinel);
1790 const data = tree.nodes.items(.data)[node];
1791 const extra = tree.extraData(data.rhs, Node.SliceSentinel);
1758 assert(tree.nodeTag(node) == .slice_sentinel);
1759 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1760 const extra = tree.extraData(extra_index, Node.SliceSentinel);
17921761 return .{
17931762 .ast = .{
1794 .sliced = data.lhs,
1795 .lbracket = tree.nodes.items(.main_token)[node],
1763 .sliced = sliced,
1764 .lbracket = tree.nodeMainToken(node),
17961765 .start = extra.start,
17971766 .end = extra.end,
1798 .sentinel = extra.sentinel,
1767 .sentinel = extra.sentinel.toOptional(),
17991768 },
18001769 };
18011770}
18021771
18031772pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1804 assert(tree.nodes.items(.tag)[node] == .container_decl_two or
1805 tree.nodes.items(.tag)[node] == .container_decl_two_trailing);
1806 const data = tree.nodes.items(.data)[node];
1807 buffer.* = .{ data.lhs, data.rhs };
1808 const members = if (data.rhs != 0)
1809 buffer[0..2]
1810 else if (data.lhs != 0)
1811 buffer[0..1]
1812 else
1813 buffer[0..0];
1773 assert(tree.nodeTag(node) == .container_decl_two or
1774 tree.nodeTag(node) == .container_decl_two_trailing);
1775 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
18141776 return tree.fullContainerDeclComponents(.{
1815 .main_token = tree.nodes.items(.main_token)[node],
1777 .main_token = tree.nodeMainToken(node),
18161778 .enum_token = null,
18171779 .members = members,
1818 .arg = 0,
1780 .arg = .none,
18191781 });
18201782}
18211783
18221784pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {
1823 assert(tree.nodes.items(.tag)[node] == .container_decl or
1824 tree.nodes.items(.tag)[node] == .container_decl_trailing);
1825 const data = tree.nodes.items(.data)[node];
1785 assert(tree.nodeTag(node) == .container_decl or
1786 tree.nodeTag(node) == .container_decl_trailing);
1787 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
18261788 return tree.fullContainerDeclComponents(.{
1827 .main_token = tree.nodes.items(.main_token)[node],
1789 .main_token = tree.nodeMainToken(node),
18281790 .enum_token = null,
1829 .members = tree.extra_data[data.lhs..data.rhs],
1830 .arg = 0,
1791 .members = members,
1792 .arg = .none,
18311793 });
18321794}
18331795
18341796pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {
1835 assert(tree.nodes.items(.tag)[node] == .container_decl_arg or
1836 tree.nodes.items(.tag)[node] == .container_decl_arg_trailing);
1837 const data = tree.nodes.items(.data)[node];
1838 const members_range = tree.extraData(data.rhs, Node.SubRange);
1797 assert(tree.nodeTag(node) == .container_decl_arg or
1798 tree.nodeTag(node) == .container_decl_arg_trailing);
1799 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1800 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
18391801 return tree.fullContainerDeclComponents(.{
1840 .main_token = tree.nodes.items(.main_token)[node],
1802 .main_token = tree.nodeMainToken(node),
18411803 .enum_token = null,
1842 .members = tree.extra_data[members_range.start..members_range.end],
1843 .arg = data.lhs,
1804 .members = members,
1805 .arg = arg.toOptional(),
18441806 });
18451807}
18461808
......@@ -1848,175 +1810,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {
18481810 return .{
18491811 .layout_token = null,
18501812 .ast = .{
1851 .main_token = undefined,
1813 .main_token = 0,
18521814 .enum_token = null,
18531815 .members = tree.rootDecls(),
1854 .arg = 0,
1816 .arg = .none,
18551817 },
18561818 };
18571819}
18581820
18591821pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1860 assert(tree.nodes.items(.tag)[node] == .tagged_union_two or
1861 tree.nodes.items(.tag)[node] == .tagged_union_two_trailing);
1862 const data = tree.nodes.items(.data)[node];
1863 buffer.* = .{ data.lhs, data.rhs };
1864 const members = if (data.rhs != 0)
1865 buffer[0..2]
1866 else if (data.lhs != 0)
1867 buffer[0..1]
1868 else
1869 buffer[0..0];
1870 const main_token = tree.nodes.items(.main_token)[node];
1822 assert(tree.nodeTag(node) == .tagged_union_two or
1823 tree.nodeTag(node) == .tagged_union_two_trailing);
1824 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1825 const main_token = tree.nodeMainToken(node);
18711826 return tree.fullContainerDeclComponents(.{
18721827 .main_token = main_token,
18731828 .enum_token = main_token + 2, // union lparen enum
18741829 .members = members,
1875 .arg = 0,
1830 .arg = .none,
18761831 });
18771832}
18781833
18791834pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {
1880 assert(tree.nodes.items(.tag)[node] == .tagged_union or
1881 tree.nodes.items(.tag)[node] == .tagged_union_trailing);
1882 const data = tree.nodes.items(.data)[node];
1883 const main_token = tree.nodes.items(.main_token)[node];
1835 assert(tree.nodeTag(node) == .tagged_union or
1836 tree.nodeTag(node) == .tagged_union_trailing);
1837 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1838 const main_token = tree.nodeMainToken(node);
18841839 return tree.fullContainerDeclComponents(.{
18851840 .main_token = main_token,
18861841 .enum_token = main_token + 2, // union lparen enum
1887 .members = tree.extra_data[data.lhs..data.rhs],
1888 .arg = 0,
1842 .members = members,
1843 .arg = .none,
18891844 });
18901845}
18911846
18921847pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {
1893 assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or
1894 tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing);
1895 const data = tree.nodes.items(.data)[node];
1896 const members_range = tree.extraData(data.rhs, Node.SubRange);
1897 const main_token = tree.nodes.items(.main_token)[node];
1848 assert(tree.nodeTag(node) == .tagged_union_enum_tag or
1849 tree.nodeTag(node) == .tagged_union_enum_tag_trailing);
1850 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1851 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1852 const main_token = tree.nodeMainToken(node);
18981853 return tree.fullContainerDeclComponents(.{
18991854 .main_token = main_token,
19001855 .enum_token = main_token + 2, // union lparen enum
1901 .members = tree.extra_data[members_range.start..members_range.end],
1902 .arg = data.lhs,
1856 .members = members,
1857 .arg = arg.toOptional(),
19031858 });
19041859}
19051860
19061861pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {
1907 const data = &tree.nodes.items(.data)[node];
1908 const main_token = tree.nodes.items(.main_token)[node];
1909 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) {
1862 const main_token = tree.nodeMainToken(node);
1863 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) {
19101864 .identifier => .{ main_token + 2, main_token },
19111865 .keyword_switch => .{ main_token, null },
19121866 else => unreachable,
19131867 };
1914 const extra = tree.extraData(data.rhs, Ast.Node.SubRange);
1868 const condition, const extra_index = tree.nodeData(node).node_and_extra;
1869 const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index);
19151870 return .{
19161871 .ast = .{
19171872 .switch_token = switch_token,
1918 .condition = data.lhs,
1919 .cases = tree.extra_data[extra.start..extra.end],
1873 .condition = condition,
1874 .cases = cases,
19201875 },
19211876 .label_token = label_token,
19221877 };
19231878}
19241879
19251880pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
1926 const data = &tree.nodes.items(.data)[node];
1927 const values: *[1]Node.Index = &data.lhs;
1881 const first_value, const target_expr = tree.nodeData(node).opt_node_and_node;
19281882 return tree.fullSwitchCaseComponents(.{
1929 .values = if (data.lhs == 0) values[0..0] else values[0..1],
1930 .arrow_token = tree.nodes.items(.main_token)[node],
1931 .target_expr = data.rhs,
1883 .values = if (first_value == .none)
1884 &.{}
1885 else
1886 // Ensure that the returned slice points into the existing memory of the Ast
1887 (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1],
1888 .arrow_token = tree.nodeMainToken(node),
1889 .target_expr = target_expr,
19321890 }, node);
19331891}
19341892
19351893pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
1936 const data = tree.nodes.items(.data)[node];
1937 const extra = tree.extraData(data.lhs, Node.SubRange);
1894 const extra_index, const target_expr = tree.nodeData(node).extra_and_node;
1895 const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
19381896 return tree.fullSwitchCaseComponents(.{
1939 .values = tree.extra_data[extra.start..extra.end],
1940 .arrow_token = tree.nodes.items(.main_token)[node],
1941 .target_expr = data.rhs,
1897 .values = values,
1898 .arrow_token = tree.nodeMainToken(node),
1899 .target_expr = target_expr,
19421900 }, node);
19431901}
19441902
19451903pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {
1946 const data = tree.nodes.items(.data)[node];
1904 const template, const rparen = tree.nodeData(node).node_and_token;
19471905 return tree.fullAsmComponents(.{
1948 .asm_token = tree.nodes.items(.main_token)[node],
1949 .template = data.lhs,
1906 .asm_token = tree.nodeMainToken(node),
1907 .template = template,
19501908 .items = &.{},
1951 .rparen = data.rhs,
1909 .rparen = rparen,
19521910 });
19531911}
19541912
19551913pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {
1956 const data = tree.nodes.items(.data)[node];
1957 const extra = tree.extraData(data.rhs, Node.Asm);
1914 const template, const extra_index = tree.nodeData(node).node_and_extra;
1915 const extra = tree.extraData(extra_index, Node.Asm);
1916 const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index);
19581917 return tree.fullAsmComponents(.{
1959 .asm_token = tree.nodes.items(.main_token)[node],
1960 .template = data.lhs,
1961 .items = tree.extra_data[extra.items_start..extra.items_end],
1918 .asm_token = tree.nodeMainToken(node),
1919 .template = template,
1920 .items = items,
19621921 .rparen = extra.rparen,
19631922 });
19641923}
19651924
19661925pub fn whileSimple(tree: Ast, node: Node.Index) full.While {
1967 const data = tree.nodes.items(.data)[node];
1926 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
19681927 return tree.fullWhileComponents(.{
1969 .while_token = tree.nodes.items(.main_token)[node],
1970 .cond_expr = data.lhs,
1971 .cont_expr = 0,
1972 .then_expr = data.rhs,
1973 .else_expr = 0,
1928 .while_token = tree.nodeMainToken(node),
1929 .cond_expr = cond_expr,
1930 .cont_expr = .none,
1931 .then_expr = then_expr,
1932 .else_expr = .none,
19741933 });
19751934}
19761935
19771936pub fn whileCont(tree: Ast, node: Node.Index) full.While {
1978 const data = tree.nodes.items(.data)[node];
1979 const extra = tree.extraData(data.rhs, Node.WhileCont);
1937 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1938 const extra = tree.extraData(extra_index, Node.WhileCont);
19801939 return tree.fullWhileComponents(.{
1981 .while_token = tree.nodes.items(.main_token)[node],
1982 .cond_expr = data.lhs,
1983 .cont_expr = extra.cont_expr,
1940 .while_token = tree.nodeMainToken(node),
1941 .cond_expr = cond_expr,
1942 .cont_expr = extra.cont_expr.toOptional(),
19841943 .then_expr = extra.then_expr,
1985 .else_expr = 0,
1944 .else_expr = .none,
19861945 });
19871946}
19881947
19891948pub fn whileFull(tree: Ast, node: Node.Index) full.While {
1990 const data = tree.nodes.items(.data)[node];
1991 const extra = tree.extraData(data.rhs, Node.While);
1949 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1950 const extra = tree.extraData(extra_index, Node.While);
19921951 return tree.fullWhileComponents(.{
1993 .while_token = tree.nodes.items(.main_token)[node],
1994 .cond_expr = data.lhs,
1952 .while_token = tree.nodeMainToken(node),
1953 .cond_expr = cond_expr,
19951954 .cont_expr = extra.cont_expr,
19961955 .then_expr = extra.then_expr,
1997 .else_expr = extra.else_expr,
1956 .else_expr = extra.else_expr.toOptional(),
19981957 });
19991958}
20001959
20011960pub fn forSimple(tree: Ast, node: Node.Index) full.For {
2002 const data = &tree.nodes.items(.data)[node];
2003 const inputs: *[1]Node.Index = &data.lhs;
1961 const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node;
20041962 return tree.fullForComponents(.{
2005 .for_token = tree.nodes.items(.main_token)[node],
2006 .inputs = inputs[0..1],
2007 .then_expr = data.rhs,
2008 .else_expr = 0,
1963 .for_token = tree.nodeMainToken(node),
1964 .inputs = (&data[0])[0..1],
1965 .then_expr = data[1],
1966 .else_expr = .none,
20091967 });
20101968}
20111969
20121970pub fn forFull(tree: Ast, node: Node.Index) full.For {
2013 const data = tree.nodes.items(.data)[node];
2014 const extra = @as(Node.For, @bitCast(data.rhs));
2015 const inputs = tree.extra_data[data.lhs..][0..extra.inputs];
2016 const then_expr = tree.extra_data[data.lhs + extra.inputs];
2017 const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0;
1971 const extra_index, const extra = tree.nodeData(node).@"for";
1972 const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index);
1973 const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]);
1974 const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none;
20181975 return tree.fullForComponents(.{
2019 .for_token = tree.nodes.items(.main_token)[node],
1976 .for_token = tree.nodeMainToken(node),
20201977 .inputs = inputs,
20211978 .then_expr = then_expr,
20221979 .else_expr = else_expr,
......@@ -2024,28 +1981,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
20241981}
20251982
20261983pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
2027 const data = tree.nodes.items(.data)[node];
2028 buffer.* = .{data.rhs};
2029 const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0];
1984 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
1985 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
20301986 return tree.fullCallComponents(.{
2031 .lparen = tree.nodes.items(.main_token)[node],
2032 .fn_expr = data.lhs,
1987 .lparen = tree.nodeMainToken(node),
1988 .fn_expr = fn_expr,
20331989 .params = params,
20341990 });
20351991}
20361992
20371993pub fn callFull(tree: Ast, node: Node.Index) full.Call {
2038 const data = tree.nodes.items(.data)[node];
2039 const extra = tree.extraData(data.rhs, Node.SubRange);
1994 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
1995 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
20401996 return tree.fullCallComponents(.{
2041 .lparen = tree.nodes.items(.main_token)[node],
2042 .fn_expr = data.lhs,
2043 .params = tree.extra_data[extra.start..extra.end],
1997 .lparen = tree.nodeMainToken(node),
1998 .fn_expr = fn_expr,
1999 .params = params,
20442000 });
20452001}
20462002
20472003fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
2048 const token_tags = tree.tokens.items(.tag);
20492004 var result: full.VarDecl = .{
20502005 .ast = info,
20512006 .visib_token = null,
......@@ -2057,7 +2012,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
20572012 var i = info.mut_token;
20582013 while (i > 0) {
20592014 i -= 1;
2060 switch (token_tags[i]) {
2015 switch (tree.tokenTag(i)) {
20612016 .keyword_extern, .keyword_export => result.extern_export_token = i,
20622017 .keyword_comptime => result.comptime_token = i,
20632018 .keyword_pub => result.visib_token = i,
......@@ -2070,14 +2025,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
20702025}
20712026
20722027fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {
2073 const token_tags = tree.tokens.items(.tag);
2074 const node_tags = tree.nodes.items(.tag);
20752028 var result: full.AssignDestructure = .{
20762029 .comptime_token = null,
20772030 .ast = info,
20782031 };
20792032 const first_variable_token = tree.firstToken(info.variables[0]);
2080 const maybe_comptime_token = switch (node_tags[info.variables[0]]) {
2033 const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) {
20812034 .global_var_decl,
20822035 .local_var_decl,
20832036 .aligned_var_decl,
......@@ -2085,14 +2038,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo
20852038 => first_variable_token,
20862039 else => first_variable_token - 1,
20872040 };
2088 if (token_tags[maybe_comptime_token] == .keyword_comptime) {
2041 if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) {
20892042 result.comptime_token = maybe_comptime_token;
20902043 }
20912044 return result;
20922045}
20932046
20942047fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
2095 const token_tags = tree.tokens.items(.tag);
20962048 var result: full.If = .{
20972049 .ast = info,
20982050 .payload_token = null,
......@@ -2102,14 +2054,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
21022054 // if (cond_expr) |x|
21032055 // ^ ^
21042056 const payload_pipe = tree.lastToken(info.cond_expr) + 2;
2105 if (token_tags[payload_pipe] == .pipe) {
2057 if (tree.tokenTag(payload_pipe) == .pipe) {
21062058 result.payload_token = payload_pipe + 1;
21072059 }
2108 if (info.else_expr != 0) {
2060 if (info.else_expr != .none) {
21092061 // then_expr else |x|
21102062 // ^ ^
21112063 result.else_token = tree.lastToken(info.then_expr) + 1;
2112 if (token_tags[result.else_token + 1] == .pipe) {
2064 if (tree.tokenTag(result.else_token + 1) == .pipe) {
21132065 result.error_token = result.else_token + 2;
21142066 }
21152067 }
......@@ -2117,12 +2069,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
21172069}
21182070
21192071fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {
2120 const token_tags = tree.tokens.items(.tag);
21212072 var result: full.ContainerField = .{
21222073 .ast = info,
21232074 .comptime_token = null,
21242075 };
2125 if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {
2076 if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) {
21262077 // comptime type = init,
21272078 // ^ ^
21282079 // comptime name: type = init,
......@@ -2133,7 +2084,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)
21332084}
21342085
21352086fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {
2136 const token_tags = tree.tokens.items(.tag);
21372087 var result: full.FnProto = .{
21382088 .ast = info,
21392089 .visib_token = null,
......@@ -2145,7 +2095,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
21452095 var i = info.fn_token;
21462096 while (i > 0) {
21472097 i -= 1;
2148 switch (token_tags[i]) {
2098 switch (tree.tokenTag(i)) {
21492099 .keyword_extern,
21502100 .keyword_export,
21512101 .keyword_inline,
......@@ -2157,25 +2107,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
21572107 }
21582108 }
21592109 const after_fn_token = info.fn_token + 1;
2160 if (token_tags[after_fn_token] == .identifier) {
2110 if (tree.tokenTag(after_fn_token) == .identifier) {
21612111 result.name_token = after_fn_token;
21622112 result.lparen = after_fn_token + 1;
21632113 } else {
21642114 result.lparen = after_fn_token;
21652115 }
2166 assert(token_tags[result.lparen] == .l_paren);
2116 assert(tree.tokenTag(result.lparen) == .l_paren);
21672117
21682118 return result;
21692119}
21702120
21712121fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {
2172 const token_tags = tree.tokens.items(.tag);
2173 const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) {
2122 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {
21742123 .asterisk,
21752124 .asterisk_asterisk,
21762125 => .one,
2177 .l_bracket => switch (token_tags[info.main_token + 1]) {
2178 .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many,
2126 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {
2127 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,
21792128 else => .slice,
21802129 },
21812130 else => unreachable,
......@@ -2191,23 +2140,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
21912140 // here while looking for modifiers as that could result in false
21922141 // positives. Therefore, start after a sentinel if there is one and
21932142 // skip over any align node and bit range nodes.
2194 var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) {
2143 var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) {
21952144 .many, .c => info.main_token + 1,
21962145 else => info.main_token,
21972146 };
21982147 const end = tree.firstToken(info.child_type);
21992148 while (i < end) : (i += 1) {
2200 switch (token_tags[i]) {
2149 switch (tree.tokenTag(i)) {
22012150 .keyword_allowzero => result.allowzero_token = i,
22022151 .keyword_const => result.const_token = i,
22032152 .keyword_volatile => result.volatile_token = i,
22042153 .keyword_align => {
2205 assert(info.align_node != 0);
2206 if (info.bit_range_end != 0) {
2207 assert(info.bit_range_start != 0);
2208 i = tree.lastToken(info.bit_range_end) + 1;
2154 const align_node = info.align_node.unwrap().?;
2155 if (info.bit_range_end.unwrap()) |bit_range_end| {
2156 assert(info.bit_range_start != .none);
2157 i = tree.lastToken(bit_range_end) + 1;
22092158 } else {
2210 i = tree.lastToken(info.align_node) + 1;
2159 i = tree.lastToken(align_node) + 1;
22112160 }
22122161 },
22132162 else => {},
......@@ -2217,30 +2166,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
22172166}
22182167
22192168fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {
2220 const token_tags = tree.tokens.items(.tag);
22212169 var result: full.ContainerDecl = .{
22222170 .ast = info,
22232171 .layout_token = null,
22242172 };
22252173
2226 if (info.main_token == 0) return result;
2174 if (info.main_token == 0) return result; // .root
2175 const previous_token = info.main_token - 1;
22272176
2228 switch (token_tags[info.main_token - 1]) {
2229 .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1,
2177 switch (tree.tokenTag(previous_token)) {
2178 .keyword_extern, .keyword_packed => result.layout_token = previous_token,
22302179 else => {},
22312180 }
22322181 return result;
22332182}
22342183
22352184fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2236 const token_tags = tree.tokens.items(.tag);
22372185 const tok_i = info.switch_token -| 1;
22382186 var result: full.Switch = .{
22392187 .ast = info,
22402188 .label_token = null,
22412189 };
2242 if (token_tags[tok_i] == .colon and
2243 token_tags[tok_i -| 1] == .identifier)
2190 if (tree.tokenTag(tok_i) == .colon and
2191 tree.tokenTag(tok_i -| 1) == .identifier)
22442192 {
22452193 result.label_token = tok_i - 1;
22462194 }
......@@ -2248,26 +2196,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
22482196}
22492197
22502198fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
2251 const token_tags = tree.tokens.items(.tag);
2252 const node_tags = tree.nodes.items(.tag);
22532199 var result: full.SwitchCase = .{
22542200 .ast = info,
22552201 .payload_token = null,
22562202 .inline_token = null,
22572203 };
2258 if (token_tags[info.arrow_token + 1] == .pipe) {
2204 if (tree.tokenTag(info.arrow_token + 1) == .pipe) {
22592205 result.payload_token = info.arrow_token + 2;
22602206 }
2261 switch (node_tags[node]) {
2262 .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node),
2263 else => {},
2264 }
2207 result.inline_token = switch (tree.nodeTag(node)) {
2208 .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0)
2209 info.arrow_token - 2
2210 else
2211 tree.firstToken(result.ast.values[0]) - 1,
2212 else => null,
2213 };
22652214 return result;
22662215}
22672216
22682217fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2269 const token_tags = tree.tokens.items(.tag);
2270 const node_tags = tree.nodes.items(.tag);
22712218 var result: full.Asm = .{
22722219 .ast = info,
22732220 .volatile_token = null,
......@@ -2275,11 +2222,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
22752222 .outputs = &.{},
22762223 .first_clobber = null,
22772224 };
2278 if (token_tags[info.asm_token + 1] == .keyword_volatile) {
2225 if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) {
22792226 result.volatile_token = info.asm_token + 1;
22802227 }
22812228 const outputs_end: usize = for (info.items, 0..) |item, i| {
2282 switch (node_tags[item]) {
2229 switch (tree.nodeTag(item)) {
22832230 .asm_output => continue,
22842231 else => break i,
22852232 }
......@@ -2291,10 +2238,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
22912238 if (info.items.len == 0) {
22922239 // asm ("foo" ::: "a", "b");
22932240 const template_token = tree.lastToken(info.template);
2294 if (token_tags[template_token + 1] == .colon and
2295 token_tags[template_token + 2] == .colon and
2296 token_tags[template_token + 3] == .colon and
2297 token_tags[template_token + 4] == .string_literal)
2241 if (tree.tokenTag(template_token + 1) == .colon and
2242 tree.tokenTag(template_token + 2) == .colon and
2243 tree.tokenTag(template_token + 3) == .colon and
2244 tree.tokenTag(template_token + 4) == .string_literal)
22982245 {
22992246 result.first_clobber = template_token + 4;
23002247 }
......@@ -2304,9 +2251,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
23042251 const rparen = tree.lastToken(last_input);
23052252 var i = rparen + 1;
23062253 // Allow a (useless) comma right after the closing parenthesis.
2307 if (token_tags[i] == .comma) i += 1;
2308 if (token_tags[i] == .colon and
2309 token_tags[i + 1] == .string_literal)
2254 if (tree.tokenTag(i) == .comma) i = i + 1;
2255 if (tree.tokenTag(i) == .colon and
2256 tree.tokenTag(i + 1) == .string_literal)
23102257 {
23112258 result.first_clobber = i + 1;
23122259 }
......@@ -2316,10 +2263,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
23162263 const rparen = tree.lastToken(last_output);
23172264 var i = rparen + 1;
23182265 // Allow a (useless) comma right after the closing parenthesis.
2319 if (token_tags[i] == .comma) i += 1;
2320 if (token_tags[i] == .colon and
2321 token_tags[i + 1] == .colon and
2322 token_tags[i + 2] == .string_literal)
2266 if (tree.tokenTag(i) == .comma) i = i + 1;
2267 if (tree.tokenTag(i) == .colon and
2268 tree.tokenTag(i + 1) == .colon and
2269 tree.tokenTag(i + 2) == .string_literal)
23232270 {
23242271 result.first_clobber = i + 2;
23252272 }
......@@ -2329,7 +2276,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
23292276}
23302277
23312278fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2332 const token_tags = tree.tokens.items(.tag);
23332279 var result: full.While = .{
23342280 .ast = info,
23352281 .inline_token = null,
......@@ -2338,25 +2284,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
23382284 .else_token = undefined,
23392285 .error_token = null,
23402286 };
2341 var tok_i = info.while_token -| 1;
2342 if (token_tags[tok_i] == .keyword_inline) {
2343 result.inline_token = tok_i;
2344 tok_i -|= 1;
2287 var tok_i = info.while_token;
2288 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2289 result.inline_token = tok_i - 1;
2290 tok_i = tok_i - 1;
23452291 }
2346 if (token_tags[tok_i] == .colon and
2347 token_tags[tok_i -| 1] == .identifier)
2348 {
2349 result.label_token = tok_i - 1;
2292 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2293 result.label_token = tok_i - 2;
23502294 }
23512295 const last_cond_token = tree.lastToken(info.cond_expr);
2352 if (token_tags[last_cond_token + 2] == .pipe) {
2296 if (tree.tokenTag(last_cond_token + 2) == .pipe) {
23532297 result.payload_token = last_cond_token + 3;
23542298 }
2355 if (info.else_expr != 0) {
2299 if (info.else_expr != .none) {
23562300 // then_expr else |x|
23572301 // ^ ^
23582302 result.else_token = tree.lastToken(info.then_expr) + 1;
2359 if (token_tags[result.else_token + 1] == .pipe) {
2303 if (tree.tokenTag(result.else_token + 1) == .pipe) {
23602304 result.error_token = result.else_token + 2;
23612305 }
23622306 }
......@@ -2364,7 +2308,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
23642308}
23652309
23662310fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2367 const token_tags = tree.tokens.items(.tag);
23682311 var result: full.For = .{
23692312 .ast = info,
23702313 .inline_token = null,
......@@ -2372,39 +2315,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
23722315 .payload_token = undefined,
23732316 .else_token = undefined,
23742317 };
2375 var tok_i = info.for_token -| 1;
2376 if (token_tags[tok_i] == .keyword_inline) {
2377 result.inline_token = tok_i;
2378 tok_i -|= 1;
2318 var tok_i = info.for_token;
2319 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2320 result.inline_token = tok_i - 1;
2321 tok_i = tok_i - 1;
23792322 }
2380 if (token_tags[tok_i] == .colon and
2381 token_tags[tok_i -| 1] == .identifier)
2382 {
2383 result.label_token = tok_i - 1;
2323 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2324 result.label_token = tok_i - 2;
23842325 }
23852326 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);
2386 result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma);
2387 if (info.else_expr != 0) {
2327 result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma);
2328 if (info.else_expr != .none) {
23882329 result.else_token = tree.lastToken(info.then_expr) + 1;
23892330 }
23902331 return result;
23912332}
23922333
23932334fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
2394 const token_tags = tree.tokens.items(.tag);
23952335 var result: full.Call = .{
23962336 .ast = info,
23972337 .async_token = null,
23982338 };
23992339 const first_token = tree.firstToken(info.fn_expr);
2400 if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) {
2340 if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
24012341 result.async_token = first_token - 1;
24022342 }
24032343 return result;
24042344}
24052345
24062346pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2407 return switch (tree.nodes.items(.tag)[node]) {
2347 return switch (tree.nodeTag(node)) {
24082348 .global_var_decl => tree.globalVarDecl(node),
24092349 .local_var_decl => tree.localVarDecl(node),
24102350 .aligned_var_decl => tree.alignedVarDecl(node),
......@@ -2414,7 +2354,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
24142354}
24152355
24162356pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2417 return switch (tree.nodes.items(.tag)[node]) {
2357 return switch (tree.nodeTag(node)) {
24182358 .if_simple => tree.ifSimple(node),
24192359 .@"if" => tree.ifFull(node),
24202360 else => null,
......@@ -2422,7 +2362,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
24222362}
24232363
24242364pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2425 return switch (tree.nodes.items(.tag)[node]) {
2365 return switch (tree.nodeTag(node)) {
24262366 .while_simple => tree.whileSimple(node),
24272367 .while_cont => tree.whileCont(node),
24282368 .@"while" => tree.whileFull(node),
......@@ -2431,7 +2371,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
24312371}
24322372
24332373pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2434 return switch (tree.nodes.items(.tag)[node]) {
2374 return switch (tree.nodeTag(node)) {
24352375 .for_simple => tree.forSimple(node),
24362376 .@"for" => tree.forFull(node),
24372377 else => null,
......@@ -2439,7 +2379,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
24392379}
24402380
24412381pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2442 return switch (tree.nodes.items(.tag)[node]) {
2382 return switch (tree.nodeTag(node)) {
24432383 .container_field_init => tree.containerFieldInit(node),
24442384 .container_field_align => tree.containerFieldAlign(node),
24452385 .container_field => tree.containerField(node),
......@@ -2448,18 +2388,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
24482388}
24492389
24502390pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {
2451 return switch (tree.nodes.items(.tag)[node]) {
2391 return switch (tree.nodeTag(node)) {
24522392 .fn_proto => tree.fnProto(node),
24532393 .fn_proto_multi => tree.fnProtoMulti(node),
24542394 .fn_proto_one => tree.fnProtoOne(buffer, node),
24552395 .fn_proto_simple => tree.fnProtoSimple(buffer, node),
2456 .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs),
2396 .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]),
24572397 else => null,
24582398 };
24592399}
24602400
24612401pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {
2462 return switch (tree.nodes.items(.tag)[node]) {
2402 return switch (tree.nodeTag(node)) {
24632403 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),
24642404 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),
24652405 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),
......@@ -2469,7 +2409,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?
24692409}
24702410
24712411pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {
2472 return switch (tree.nodes.items(.tag)[node]) {
2412 return switch (tree.nodeTag(node)) {
24732413 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),
24742414 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),
24752415 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),
......@@ -2479,7 +2419,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.
24792419}
24802420
24812421pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2482 return switch (tree.nodes.items(.tag)[node]) {
2422 return switch (tree.nodeTag(node)) {
24832423 .array_type => tree.arrayType(node),
24842424 .array_type_sentinel => tree.arrayTypeSentinel(node),
24852425 else => null,
......@@ -2487,7 +2427,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
24872427}
24882428
24892429pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2490 return switch (tree.nodes.items(.tag)[node]) {
2430 return switch (tree.nodeTag(node)) {
24912431 .ptr_type_aligned => tree.ptrTypeAligned(node),
24922432 .ptr_type_sentinel => tree.ptrTypeSentinel(node),
24932433 .ptr_type => tree.ptrType(node),
......@@ -2497,7 +2437,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
24972437}
24982438
24992439pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2500 return switch (tree.nodes.items(.tag)[node]) {
2440 return switch (tree.nodeTag(node)) {
25012441 .slice_open => tree.sliceOpen(node),
25022442 .slice => tree.slice(node),
25032443 .slice_sentinel => tree.sliceSentinel(node),
......@@ -2506,7 +2446,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
25062446}
25072447
25082448pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {
2509 return switch (tree.nodes.items(.tag)[node]) {
2449 return switch (tree.nodeTag(node)) {
25102450 .root => tree.containerDeclRoot(),
25112451 .container_decl, .container_decl_trailing => tree.containerDecl(node),
25122452 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
......@@ -2519,14 +2459,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index
25192459}
25202460
25212461pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {
2522 return switch (tree.nodes.items(.tag)[node]) {
2462 return switch (tree.nodeTag(node)) {
25232463 .@"switch", .switch_comma => tree.switchFull(node),
25242464 else => null,
25252465 };
25262466}
25272467
25282468pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2529 return switch (tree.nodes.items(.tag)[node]) {
2469 return switch (tree.nodeTag(node)) {
25302470 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),
25312471 .switch_case, .switch_case_inline => tree.switchCase(node),
25322472 else => null,
......@@ -2534,7 +2474,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
25342474}
25352475
25362476pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2537 return switch (tree.nodes.items(.tag)[node]) {
2477 return switch (tree.nodeTag(node)) {
25382478 .asm_simple => tree.asmSimple(node),
25392479 .@"asm" => tree.asmFull(node),
25402480 else => null,
......@@ -2542,13 +2482,29 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
25422482}
25432483
25442484pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
2545 return switch (tree.nodes.items(.tag)[node]) {
2485 return switch (tree.nodeTag(node)) {
25462486 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
25472487 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
25482488 else => null,
25492489 };
25502490}
25512491
2492pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2493 return switch (tree.nodeTag(node)) {
2494 .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2495 .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2496 else => null,
2497 };
2498}
2499
2500pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2501 return switch (tree.nodeTag(node)) {
2502 .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2503 .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2504 else => null,
2505 };
2506}
2507
25522508/// Fully assembled AST node information.
25532509pub const full = struct {
25542510 pub const VarDecl = struct {
......@@ -2561,11 +2517,11 @@ pub const full = struct {
25612517
25622518 pub const Components = struct {
25632519 mut_token: TokenIndex,
2564 type_node: Node.Index,
2565 align_node: Node.Index,
2566 addrspace_node: Node.Index,
2567 section_node: Node.Index,
2568 init_node: Node.Index,
2520 type_node: Node.OptionalIndex,
2521 align_node: Node.OptionalIndex,
2522 addrspace_node: Node.OptionalIndex,
2523 section_node: Node.OptionalIndex,
2524 init_node: Node.OptionalIndex,
25692525 };
25702526
25712527 pub fn firstToken(var_decl: VarDecl) TokenIndex {
......@@ -2594,7 +2550,7 @@ pub const full = struct {
25942550 payload_token: ?TokenIndex,
25952551 /// Points to the identifier after the `|`.
25962552 error_token: ?TokenIndex,
2597 /// Populated only if else_expr != 0.
2553 /// Populated only if else_expr != .none.
25982554 else_token: TokenIndex,
25992555 ast: Components,
26002556
......@@ -2602,7 +2558,7 @@ pub const full = struct {
26022558 if_token: TokenIndex,
26032559 cond_expr: Node.Index,
26042560 then_expr: Node.Index,
2605 else_expr: Node.Index,
2561 else_expr: Node.OptionalIndex,
26062562 };
26072563 };
26082564
......@@ -2612,15 +2568,15 @@ pub const full = struct {
26122568 label_token: ?TokenIndex,
26132569 payload_token: ?TokenIndex,
26142570 error_token: ?TokenIndex,
2615 /// Populated only if else_expr != 0.
2571 /// Populated only if else_expr != none.
26162572 else_token: TokenIndex,
26172573
26182574 pub const Components = struct {
26192575 while_token: TokenIndex,
26202576 cond_expr: Node.Index,
2621 cont_expr: Node.Index,
2577 cont_expr: Node.OptionalIndex,
26222578 then_expr: Node.Index,
2623 else_expr: Node.Index,
2579 else_expr: Node.OptionalIndex,
26242580 };
26252581 };
26262582
......@@ -2629,14 +2585,14 @@ pub const full = struct {
26292585 inline_token: ?TokenIndex,
26302586 label_token: ?TokenIndex,
26312587 payload_token: TokenIndex,
2632 /// Populated only if else_expr != 0.
2633 else_token: TokenIndex,
2588 /// Populated only if else_expr != .none.
2589 else_token: ?TokenIndex,
26342590
26352591 pub const Components = struct {
26362592 for_token: TokenIndex,
26372593 inputs: []const Node.Index,
26382594 then_expr: Node.Index,
2639 else_expr: Node.Index,
2595 else_expr: Node.OptionalIndex,
26402596 };
26412597 };
26422598
......@@ -2646,9 +2602,10 @@ pub const full = struct {
26462602
26472603 pub const Components = struct {
26482604 main_token: TokenIndex,
2649 type_expr: Node.Index,
2650 align_expr: Node.Index,
2651 value_expr: Node.Index,
2605 /// Can only be `.none` after calling `convertToNonTupleLike`.
2606 type_expr: Node.OptionalIndex,
2607 align_expr: Node.OptionalIndex,
2608 value_expr: Node.OptionalIndex,
26522609 tuple_like: bool,
26532610 };
26542611
......@@ -2656,11 +2613,11 @@ pub const full = struct {
26562613 return cf.comptime_token orelse cf.ast.main_token;
26572614 }
26582615
2659 pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void {
2616 pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void {
26602617 if (!cf.ast.tuple_like) return;
2661 if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return;
2618 if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return;
26622619
2663 cf.ast.type_expr = 0;
2620 cf.ast.type_expr = .none;
26642621 cf.ast.tuple_like = false;
26652622 }
26662623 };
......@@ -2676,12 +2633,12 @@ pub const full = struct {
26762633 pub const Components = struct {
26772634 proto_node: Node.Index,
26782635 fn_token: TokenIndex,
2679 return_type: Node.Index,
2636 return_type: Node.OptionalIndex,
26802637 params: []const Node.Index,
2681 align_expr: Node.Index,
2682 addrspace_expr: Node.Index,
2683 section_expr: Node.Index,
2684 callconv_expr: Node.Index,
2638 align_expr: Node.OptionalIndex,
2639 addrspace_expr: Node.OptionalIndex,
2640 section_expr: Node.OptionalIndex,
2641 callconv_expr: Node.OptionalIndex,
26852642 };
26862643
26872644 pub const Param = struct {
......@@ -2689,7 +2646,7 @@ pub const full = struct {
26892646 name_token: ?TokenIndex,
26902647 comptime_noalias: ?TokenIndex,
26912648 anytype_ellipsis3: ?TokenIndex,
2692 type_expr: Node.Index,
2649 type_expr: ?Node.Index,
26932650 };
26942651
26952652 pub fn firstToken(fn_proto: FnProto) TokenIndex {
......@@ -2709,7 +2666,7 @@ pub const full = struct {
27092666 tok_flag: bool,
27102667
27112668 pub fn next(it: *Iterator) ?Param {
2712 const token_tags = it.tree.tokens.items(.tag);
2669 const tree = it.tree;
27132670 while (true) {
27142671 var first_doc_comment: ?TokenIndex = null;
27152672 var comptime_noalias: ?TokenIndex = null;
......@@ -2719,8 +2676,8 @@ pub const full = struct {
27192676 return null;
27202677 }
27212678 const param_type = it.fn_proto.ast.params[it.param_i];
2722 var tok_i = it.tree.firstToken(param_type) - 1;
2723 while (true) : (tok_i -= 1) switch (token_tags[tok_i]) {
2679 var tok_i = tree.firstToken(param_type) - 1;
2680 while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) {
27242681 .colon => continue,
27252682 .identifier => name_token = tok_i,
27262683 .doc_comment => first_doc_comment = tok_i,
......@@ -2728,9 +2685,9 @@ pub const full = struct {
27282685 else => break,
27292686 };
27302687 it.param_i += 1;
2731 it.tok_i = it.tree.lastToken(param_type) + 1;
2688 it.tok_i = tree.lastToken(param_type) + 1;
27322689 // Look for anytype and ... params afterwards.
2733 if (token_tags[it.tok_i] == .comma) {
2690 if (tree.tokenTag(it.tok_i) == .comma) {
27342691 it.tok_i += 1;
27352692 }
27362693 it.tok_flag = true;
......@@ -2742,19 +2699,19 @@ pub const full = struct {
27422699 .type_expr = param_type,
27432700 };
27442701 }
2745 if (token_tags[it.tok_i] == .comma) {
2702 if (tree.tokenTag(it.tok_i) == .comma) {
27462703 it.tok_i += 1;
27472704 }
2748 if (token_tags[it.tok_i] == .r_paren) {
2705 if (tree.tokenTag(it.tok_i) == .r_paren) {
27492706 return null;
27502707 }
2751 if (token_tags[it.tok_i] == .doc_comment) {
2708 if (tree.tokenTag(it.tok_i) == .doc_comment) {
27522709 first_doc_comment = it.tok_i;
2753 while (token_tags[it.tok_i] == .doc_comment) {
2710 while (tree.tokenTag(it.tok_i) == .doc_comment) {
27542711 it.tok_i += 1;
27552712 }
27562713 }
2757 switch (token_tags[it.tok_i]) {
2714 switch (tree.tokenTag(it.tok_i)) {
27582715 .ellipsis3 => {
27592716 it.tok_flag = false; // Next iteration should return null.
27602717 return Param{
......@@ -2762,7 +2719,7 @@ pub const full = struct {
27622719 .comptime_noalias = null,
27632720 .name_token = null,
27642721 .anytype_ellipsis3 = it.tok_i,
2765 .type_expr = 0,
2722 .type_expr = null,
27662723 };
27672724 },
27682725 .keyword_noalias, .keyword_comptime => {
......@@ -2771,20 +2728,20 @@ pub const full = struct {
27712728 },
27722729 else => {},
27732730 }
2774 if (token_tags[it.tok_i] == .identifier and
2775 token_tags[it.tok_i + 1] == .colon)
2731 if (tree.tokenTag(it.tok_i) == .identifier and
2732 tree.tokenTag(it.tok_i + 1) == .colon)
27762733 {
27772734 name_token = it.tok_i;
27782735 it.tok_i += 2;
27792736 }
2780 if (token_tags[it.tok_i] == .keyword_anytype) {
2737 if (tree.tokenTag(it.tok_i) == .keyword_anytype) {
27812738 it.tok_i += 1;
27822739 return Param{
27832740 .first_doc_comment = first_doc_comment,
27842741 .comptime_noalias = comptime_noalias,
27852742 .name_token = name_token,
27862743 .anytype_ellipsis3 = it.tok_i - 1,
2787 .type_expr = 0,
2744 .type_expr = null,
27882745 };
27892746 }
27902747 it.tok_flag = false;
......@@ -2809,7 +2766,7 @@ pub const full = struct {
28092766 pub const Components = struct {
28102767 lbrace: TokenIndex,
28112768 fields: []const Node.Index,
2812 type_expr: Node.Index,
2769 type_expr: Node.OptionalIndex,
28132770 };
28142771 };
28152772
......@@ -2819,7 +2776,7 @@ pub const full = struct {
28192776 pub const Components = struct {
28202777 lbrace: TokenIndex,
28212778 elements: []const Node.Index,
2822 type_expr: Node.Index,
2779 type_expr: Node.OptionalIndex,
28232780 };
28242781 };
28252782
......@@ -2829,7 +2786,7 @@ pub const full = struct {
28292786 pub const Components = struct {
28302787 lbracket: TokenIndex,
28312788 elem_count: Node.Index,
2832 sentinel: Node.Index,
2789 sentinel: Node.OptionalIndex,
28332790 elem_type: Node.Index,
28342791 };
28352792 };
......@@ -2843,11 +2800,11 @@ pub const full = struct {
28432800
28442801 pub const Components = struct {
28452802 main_token: TokenIndex,
2846 align_node: Node.Index,
2847 addrspace_node: Node.Index,
2848 sentinel: Node.Index,
2849 bit_range_start: Node.Index,
2850 bit_range_end: Node.Index,
2803 align_node: Node.OptionalIndex,
2804 addrspace_node: Node.OptionalIndex,
2805 sentinel: Node.OptionalIndex,
2806 bit_range_start: Node.OptionalIndex,
2807 bit_range_end: Node.OptionalIndex,
28512808 child_type: Node.Index,
28522809 };
28532810 };
......@@ -2859,8 +2816,8 @@ pub const full = struct {
28592816 sliced: Node.Index,
28602817 lbracket: TokenIndex,
28612818 start: Node.Index,
2862 end: Node.Index,
2863 sentinel: Node.Index,
2819 end: Node.OptionalIndex,
2820 sentinel: Node.OptionalIndex,
28642821 };
28652822 };
28662823
......@@ -2873,7 +2830,7 @@ pub const full = struct {
28732830 /// Populated when main_token is Keyword_union.
28742831 enum_token: ?TokenIndex,
28752832 members: []const Node.Index,
2876 arg: Node.Index,
2833 arg: Node.OptionalIndex,
28772834 };
28782835 };
28792836
......@@ -3016,492 +2973,971 @@ pub const Error = struct {
30162973 };
30172974};
30182975
2976/// Index into `extra_data`.
2977pub const ExtraIndex = enum(u32) {
2978 _,
2979};
2980
30192981pub const Node = struct {
30202982 tag: Tag,
30212983 main_token: TokenIndex,
30222984 data: Data,
30232985
3024 pub const Index = u32;
2986 /// Index into `nodes`.
2987 pub const Index = enum(u32) {
2988 root = 0,
2989 _,
2990
2991 pub fn toOptional(i: Index) OptionalIndex {
2992 const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
2993 assert(result != .none);
2994 return result;
2995 }
2996
2997 pub fn toOffset(base: Index, destination: Index) Offset {
2998 const base_i64: i64 = @intFromEnum(base);
2999 const destination_i64: i64 = @intFromEnum(destination);
3000 return @enumFromInt(destination_i64 - base_i64);
3001 }
3002 };
3003
3004 /// Index into `nodes`, or null.
3005 pub const OptionalIndex = enum(u32) {
3006 root = 0,
3007 none = std.math.maxInt(u32),
3008 _,
3009
3010 pub fn unwrap(oi: OptionalIndex) ?Index {
3011 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
3012 }
3013
3014 pub fn fromOptional(oi: ?Index) OptionalIndex {
3015 return if (oi) |i| i.toOptional() else .none;
3016 }
3017 };
3018
3019 /// A relative node index.
3020 pub const Offset = enum(i32) {
3021 zero = 0,
3022 _,
3023
3024 pub fn toOptional(o: Offset) OptionalOffset {
3025 const result: OptionalOffset = @enumFromInt(@intFromEnum(o));
3026 assert(result != .none);
3027 return result;
3028 }
3029
3030 pub fn toAbsolute(offset: Offset, base: Index) Index {
3031 return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset));
3032 }
3033 };
3034
3035 /// A relative node index, or null.
3036 pub const OptionalOffset = enum(i32) {
3037 none = std.math.maxInt(i32),
3038 _,
3039
3040 pub fn unwrap(oo: OptionalOffset) ?Offset {
3041 return if (oo == .none) null else @enumFromInt(@intFromEnum(oo));
3042 }
3043 };
30253044
30263045 comptime {
30273046 // Goal is to keep this under one byte for efficiency.
30283047 assert(@sizeOf(Tag) == 1);
3048
3049 if (!std.debug.runtime_safety) {
3050 assert(@sizeOf(Data) == 8);
3051 }
30293052 }
30303053
3031 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of
3032 /// Ast.lastToken()
3054 /// The FooComma/FooSemicolon variants exist to ease the implementation of
3055 /// `Ast.lastToken()`
30333056 pub const Tag = enum {
3034 /// sub_list[lhs...rhs]
3057 /// The root node which is guaranteed to be at `Node.Index.root`.
3058 /// The meaning of the `data` field depends on whether it is a `.zig` or
3059 /// `.zon` file.
3060 ///
3061 /// The `main_token` field is the first token for the source file.
30353062 root,
3036 /// `usingnamespace lhs;`. rhs unused. main_token is `usingnamespace`.
3063 /// `usingnamespace expr;`.
3064 ///
3065 /// The `data` field is a `.node` to expr.
3066 ///
3067 /// The `main_token` field is the `usingnamespace` token.
30373068 @"usingnamespace",
3038 /// lhs is test name token (must be string literal or identifier), if any.
3039 /// rhs is the body node.
3069 /// `test {}`,
3070 /// `test "name" {}`,
3071 /// `test identifier {}`.
3072 ///
3073 /// The `data` field is a `.opt_token_and_node`:
3074 /// 1. a `OptionalTokenIndex` to the test name token (must be string literal or identifier), if any.
3075 /// 2. a `Node.Index` to the block.
3076 ///
3077 /// The `main_token` field is the `test` token.
30403078 test_decl,
3041 /// lhs is the index into extra_data.
3042 /// rhs is the initialization expression, if any.
3043 /// main_token is `var` or `const`.
3079 /// The `data` field is a `.extra_and_opt_node`:
3080 /// 1. a `ExtraIndex` to `GlobalVarDecl`.
3081 /// 2. a `Node.OptionalIndex` to the initialization expression.
3082 ///
3083 /// The `main_token` field is the `var` or `const` token.
3084 ///
3085 /// The initialization expression can't be `.none` unless it is part of
3086 /// a `assign_destructure` node or a parsing error occured.
30443087 global_var_decl,
3045 /// `var a: x align(y) = rhs`
3046 /// lhs is the index into extra_data.
3047 /// main_token is `var` or `const`.
3088 /// `var a: b align(c) = d`.
3089 /// `const main_token: type_node align(align_node) = init_expr`.
3090 ///
3091 /// The `data` field is a `.extra_and_opt_node`:
3092 /// 1. a `ExtraIndex` to `LocalVarDecl`.
3093 /// 2. a `Node.OptionalIndex` to the initialization expression-
3094 ///
3095 /// The `main_token` field is the `var` or `const` token.
3096 ///
3097 /// The initialization expression can't be `.none` unless it is part of
3098 /// a `assign_destructure` node or a parsing error occured.
30483099 local_var_decl,
3049 /// `var a: lhs = rhs`. lhs and rhs may be unused.
3100 /// `var a: b = c`.
3101 /// `const name_token: type_expr = init_expr`.
30503102 /// Can be local or global.
3051 /// main_token is `var` or `const`.
3103 ///
3104 /// The `data` field is a `.opt_node_and_opt_node`:
3105 /// 1. a `Node.OptionalIndex` to the type expression, if any.
3106 /// 2. a `Node.OptionalIndex` to the initialization expression.
3107 ///
3108 /// The `main_token` field is the `var` or `const` token.
3109 ///
3110 /// The initialization expression can't be `.none` unless it is part of
3111 /// a `assign_destructure` node or a parsing error occured.
30523112 simple_var_decl,
3053 /// `var a align(lhs) = rhs`. lhs and rhs may be unused.
3113 /// `var a align(b) = c`.
3114 /// `const name_token align(align_expr) = init_expr`.
30543115 /// Can be local or global.
3055 /// main_token is `var` or `const`.
3116 ///
3117 /// The `data` field is a `.node_and_opt_node`:
3118 /// 1. a `Node.Index` to the alignment expression.
3119 /// 2. a `Node.OptionalIndex` to the initialization expression.
3120 ///
3121 /// The `main_token` field is the `var` or `const` token.
3122 ///
3123 /// The initialization expression can't be `.none` unless it is part of
3124 /// a `assign_destructure` node or a parsing error occured.
30563125 aligned_var_decl,
3057 /// lhs is the identifier token payload if any,
3058 /// rhs is the deferred expression.
3126 /// `errdefer expr`,
3127 /// `errdefer |payload| expr`.
3128 ///
3129 /// The `data` field is a `.opt_token_and_node`:
3130 /// 1. a `OptionalTokenIndex` to the payload identifier, if any.
3131 /// 2. a `Node.Index` to the deferred expression.
3132 ///
3133 /// The `main_token` field is the `errdefer` token.
30593134 @"errdefer",
3060 /// lhs is unused.
3061 /// rhs is the deferred expression.
3135 /// `defer expr`.
3136 ///
3137 /// The `data` field is a `.node` to the deferred expression.
3138 ///
3139 /// The `main_token` field is the `defer`.
30623140 @"defer",
3063 /// lhs catch rhs
3064 /// lhs catch |err| rhs
3065 /// main_token is the `catch` keyword.
3066 /// payload is determined by looking at the next token after the `catch` keyword.
3141 /// `lhs catch rhs`,
3142 /// `lhs catch |err| rhs`.
3143 ///
3144 /// The `main_token` field is the `catch` token.
3145 ///
3146 /// The error payload is determined by looking at the next token after
3147 /// the `catch` token.
30673148 @"catch",
3068 /// `lhs.a`. main_token is the dot. rhs is the identifier token index.
3149 /// `lhs.a`.
3150 ///
3151 /// The `data` field is a `.node_and_token`:
3152 /// 1. a `Node.Index` to the left side of the field access.
3153 /// 2. a `TokenIndex` to the field name identifier.
3154 ///
3155 /// The `main_token` field is the `.` token.
30693156 field_access,
3070 /// `lhs.?`. main_token is the dot. rhs is the `?` token index.
3157 /// `lhs.?`.
3158 ///
3159 /// The `data` field is a `.node_and_token`:
3160 /// 1. a `Node.Index` to the left side of the optional unwrap.
3161 /// 2. a `TokenIndex` to the `?` token.
3162 ///
3163 /// The `main_token` field is the `.` token.
30713164 unwrap_optional,
3072 /// `lhs == rhs`. main_token is op.
3165 /// `lhs == rhs`. The `main_token` field is the `==` token.
30733166 equal_equal,
3074 /// `lhs != rhs`. main_token is op.
3167 /// `lhs != rhs`. The `main_token` field is the `!=` token.
30753168 bang_equal,
3076 /// `lhs < rhs`. main_token is op.
3169 /// `lhs < rhs`. The `main_token` field is the `<` token.
30773170 less_than,
3078 /// `lhs > rhs`. main_token is op.
3171 /// `lhs > rhs`. The `main_token` field is the `>` token.
30793172 greater_than,
3080 /// `lhs <= rhs`. main_token is op.
3173 /// `lhs <= rhs`. The `main_token` field is the `<=` token.
30813174 less_or_equal,
3082 /// `lhs >= rhs`. main_token is op.
3175 /// `lhs >= rhs`. The `main_token` field is the `>=` token.
30833176 greater_or_equal,
3084 /// `lhs *= rhs`. main_token is op.
3177 /// `lhs *= rhs`. The `main_token` field is the `*=` token.
30853178 assign_mul,
3086 /// `lhs /= rhs`. main_token is op.
3179 /// `lhs /= rhs`. The `main_token` field is the `/=` token.
30873180 assign_div,
3088 /// `lhs %= rhs`. main_token is op.
3181 /// `lhs %= rhs`. The `main_token` field is the `%=` token.
30893182 assign_mod,
3090 /// `lhs += rhs`. main_token is op.
3183 /// `lhs += rhs`. The `main_token` field is the `+=` token.
30913184 assign_add,
3092 /// `lhs -= rhs`. main_token is op.
3185 /// `lhs -= rhs`. The `main_token` field is the `-=` token.
30933186 assign_sub,
3094 /// `lhs <<= rhs`. main_token is op.
3187 /// `lhs <<= rhs`. The `main_token` field is the `<<=` token.
30953188 assign_shl,
3096 /// `lhs <<|= rhs`. main_token is op.
3189 /// `lhs <<|= rhs`. The `main_token` field is the `<<|=` token.
30973190 assign_shl_sat,
3098 /// `lhs >>= rhs`. main_token is op.
3191 /// `lhs >>= rhs`. The `main_token` field is the `>>=` token.
30993192 assign_shr,
3100 /// `lhs &= rhs`. main_token is op.
3193 /// `lhs &= rhs`. The `main_token` field is the `&=` token.
31013194 assign_bit_and,
3102 /// `lhs ^= rhs`. main_token is op.
3195 /// `lhs ^= rhs`. The `main_token` field is the `^=` token.
31033196 assign_bit_xor,
3104 /// `lhs |= rhs`. main_token is op.
3197 /// `lhs |= rhs`. The `main_token` field is the `|=` token.
31053198 assign_bit_or,
3106 /// `lhs *%= rhs`. main_token is op.
3199 /// `lhs *%= rhs`. The `main_token` field is the `*%=` token.
31073200 assign_mul_wrap,
3108 /// `lhs +%= rhs`. main_token is op.
3201 /// `lhs +%= rhs`. The `main_token` field is the `+%=` token.
31093202 assign_add_wrap,
3110 /// `lhs -%= rhs`. main_token is op.
3203 /// `lhs -%= rhs`. The `main_token` field is the `-%=` token.
31113204 assign_sub_wrap,
3112 /// `lhs *|= rhs`. main_token is op.
3205 /// `lhs *|= rhs`. The `main_token` field is the `*%=` token.
31133206 assign_mul_sat,
3114 /// `lhs +|= rhs`. main_token is op.
3207 /// `lhs +|= rhs`. The `main_token` field is the `+|=` token.
31153208 assign_add_sat,
3116 /// `lhs -|= rhs`. main_token is op.
3209 /// `lhs -|= rhs`. The `main_token` field is the `-|=` token.
31173210 assign_sub_sat,
3118 /// `lhs = rhs`. main_token is op.
3211 /// `lhs = rhs`. The `main_token` field is the `=` token.
31193212 assign,
3120 /// `a, b, ... = rhs`. main_token is op. lhs is index into `extra_data`
3121 /// of an lhs elem count followed by an array of that many `Node.Index`,
3122 /// with each node having one of the following types:
3123 /// * `global_var_decl`
3124 /// * `local_var_decl`
3125 /// * `simple_var_decl`
3126 /// * `aligned_var_decl`
3127 /// * Any expression node
3128 /// The first 3 types correspond to a `var` or `const` lhs node (note
3129 /// that their `rhs` is always 0). An expression node corresponds to a
3130 /// standard assignment LHS (which must be evaluated as an lvalue).
3131 /// There may be a preceding `comptime` token, which does not create a
3132 /// corresponding `comptime` node so must be manually detected.
3213 /// `a, b, ... = rhs`.
3214 ///
3215 /// The `data` field is a `.extra_and_node`:
3216 /// 1. a `ExtraIndex`. Further explained below.
3217 /// 2. a `Node.Index` to the initialization expression.
3218 ///
3219 /// The `main_token` field is the `=` token.
3220 ///
3221 /// The `ExtraIndex` stores the following data:
3222 /// ```
3223 /// elem_count: u32,
3224 /// variables: [elem_count]Node.Index,
3225 /// ```
3226 ///
3227 /// Each node in `variables` has one of the following tags:
3228 /// - `global_var_decl`
3229 /// - `local_var_decl`
3230 /// - `simple_var_decl`
3231 /// - `aligned_var_decl`
3232 /// - Any expression node
3233 ///
3234 /// The first 4 tags correspond to a `var` or `const` lhs node (note
3235 /// that their initialization expression is always `.none`).
3236 /// An expression node corresponds to a standard assignment LHS (which
3237 /// must be evaluated as an lvalue). There may be a preceding
3238 /// `comptime` token, which does not create a corresponding `comptime`
3239 /// node so must be manually detected.
31333240 assign_destructure,
3134 /// `lhs || rhs`. main_token is the `||`.
3241 /// `lhs || rhs`. The `main_token` field is the `||` token.
31353242 merge_error_sets,
3136 /// `lhs * rhs`. main_token is the `*`.
3243 /// `lhs * rhs`. The `main_token` field is the `*` token.
31373244 mul,
3138 /// `lhs / rhs`. main_token is the `/`.
3245 /// `lhs / rhs`. The `main_token` field is the `/` token.
31393246 div,
3140 /// `lhs % rhs`. main_token is the `%`.
3247 /// `lhs % rhs`. The `main_token` field is the `%` token.
31413248 mod,
3142 /// `lhs ** rhs`. main_token is the `**`.
3249 /// `lhs ** rhs`. The `main_token` field is the `**` token.
31433250 array_mult,
3144 /// `lhs *% rhs`. main_token is the `*%`.
3251 /// `lhs *% rhs`. The `main_token` field is the `*%` token.
31453252 mul_wrap,
3146 /// `lhs *| rhs`. main_token is the `*|`.
3253 /// `lhs *| rhs`. The `main_token` field is the `*|` token.
31473254 mul_sat,
3148 /// `lhs + rhs`. main_token is the `+`.
3255 /// `lhs + rhs`. The `main_token` field is the `+` token.
31493256 add,
3150 /// `lhs - rhs`. main_token is the `-`.
3257 /// `lhs - rhs`. The `main_token` field is the `-` token.
31513258 sub,
3152 /// `lhs ++ rhs`. main_token is the `++`.
3259 /// `lhs ++ rhs`. The `main_token` field is the `++` token.
31533260 array_cat,
3154 /// `lhs +% rhs`. main_token is the `+%`.
3261 /// `lhs +% rhs`. The `main_token` field is the `+%` token.
31553262 add_wrap,
3156 /// `lhs -% rhs`. main_token is the `-%`.
3263 /// `lhs -% rhs`. The `main_token` field is the `-%` token.
31573264 sub_wrap,
3158 /// `lhs +| rhs`. main_token is the `+|`.
3265 /// `lhs +| rhs`. The `main_token` field is the `+|` token.
31593266 add_sat,
3160 /// `lhs -| rhs`. main_token is the `-|`.
3267 /// `lhs -| rhs`. The `main_token` field is the `-|` token.
31613268 sub_sat,
3162 /// `lhs << rhs`. main_token is the `<<`.
3269 /// `lhs << rhs`. The `main_token` field is the `<<` token.
31633270 shl,
3164 /// `lhs <<| rhs`. main_token is the `<<|`.
3271 /// `lhs <<| rhs`. The `main_token` field is the `<<|` token.
31653272 shl_sat,
3166 /// `lhs >> rhs`. main_token is the `>>`.
3273 /// `lhs >> rhs`. The `main_token` field is the `>>` token.
31673274 shr,
3168 /// `lhs & rhs`. main_token is the `&`.
3275 /// `lhs & rhs`. The `main_token` field is the `&` token.
31693276 bit_and,
3170 /// `lhs ^ rhs`. main_token is the `^`.
3277 /// `lhs ^ rhs`. The `main_token` field is the `^` token.
31713278 bit_xor,
3172 /// `lhs | rhs`. main_token is the `|`.
3279 /// `lhs | rhs`. The `main_token` field is the `|` token.
31733280 bit_or,
3174 /// `lhs orelse rhs`. main_token is the `orelse`.
3281 /// `lhs orelse rhs`. The `main_token` field is the `orelse` token.
31753282 @"orelse",
3176 /// `lhs and rhs`. main_token is the `and`.
3283 /// `lhs and rhs`. The `main_token` field is the `and` token.
31773284 bool_and,
3178 /// `lhs or rhs`. main_token is the `or`.
3285 /// `lhs or rhs`. The `main_token` field is the `or` token.
31793286 bool_or,
3180 /// `op lhs`. rhs unused. main_token is op.
3287 /// `!expr`. The `main_token` field is the `!` token.
31813288 bool_not,
3182 /// `op lhs`. rhs unused. main_token is op.
3289 /// `-expr`. The `main_token` field is the `-` token.
31833290 negation,
3184 /// `op lhs`. rhs unused. main_token is op.
3291 /// `~expr`. The `main_token` field is the `~` token.
31853292 bit_not,
3186 /// `op lhs`. rhs unused. main_token is op.
3293 /// `-%expr`. The `main_token` field is the `-%` token.
31873294 negation_wrap,
3188 /// `op lhs`. rhs unused. main_token is op.
3295 /// `&expr`. The `main_token` field is the `&` token.
31893296 address_of,
3190 /// `op lhs`. rhs unused. main_token is op.
3297 /// `try expr`. The `main_token` field is the `try` token.
31913298 @"try",
3192 /// `op lhs`. rhs unused. main_token is op.
3299 /// `await expr`. The `main_token` field is the `await` token.
31933300 @"await",
3194 /// `?lhs`. rhs unused. main_token is the `?`.
3301 /// `?expr`. The `main_token` field is the `?` token.
31953302 optional_type,
3196 /// `[lhs]rhs`.
3303 /// `[lhs]rhs`. The `main_token` field is the `[` token.
31973304 array_type,
3198 /// `[lhs:a]b`. `ArrayTypeSentinel[rhs]`.
3305 /// `[lhs:a]b`.
3306 ///
3307 /// The `data` field is a `.node_and_extra`:
3308 /// 1. a `Node.Index` to the length expression.
3309 /// 2. a `ExtraIndex` to `ArrayTypeSentinel`.
3310 ///
3311 /// The `main_token` field is the `[` token.
31993312 array_type_sentinel,
3200 /// `[*]align(lhs) rhs`. lhs can be omitted.
3201 /// `*align(lhs) rhs`. lhs can be omitted.
3313 /// `[*]align(lhs) rhs`,
3314 /// `*align(lhs) rhs`,
32023315 /// `[]rhs`.
3203 /// main_token is the asterisk if a single item pointer or the lbracket
3204 /// if a slice, many-item pointer, or C-pointer
3205 /// main_token might be a ** token, which is shared with a parent/child
3206 /// pointer type and may require special handling.
3316 ///
3317 /// The `data` field is a `.opt_node_and_node`:
3318 /// 1. a `Node.OptionalIndex` to the alignment expression, if any.
3319 /// 2. a `Node.Index` to the element type expression.
3320 ///
3321 /// The `main_token` is the asterisk if a single item pointer or the
3322 /// lbracket if a slice, many-item pointer, or C-pointer.
3323 /// The `main_token` might be a ** token, which is shared with a
3324 /// parent/child pointer type and may require special handling.
32073325 ptr_type_aligned,
3208 /// `[*:lhs]rhs`. lhs can be omitted.
3209 /// `*rhs`.
3326 /// `[*:lhs]rhs`,
3327 /// `*rhs`,
32103328 /// `[:lhs]rhs`.
3211 /// main_token is the asterisk if a single item pointer or the lbracket
3212 /// if a slice, many-item pointer, or C-pointer
3213 /// main_token might be a ** token, which is shared with a parent/child
3214 /// pointer type and may require special handling.
3329 ///
3330 /// The `data` field is a `.opt_node_and_node`:
3331 /// 1. a `Node.OptionalIndex` to the sentinel expression, if any.
3332 /// 2. a `Node.Index` to the element type expression.
3333 ///
3334 /// The `main_token` is the asterisk if a single item pointer or the
3335 /// lbracket if a slice, many-item pointer, or C-pointer.
3336 /// The `main_token` might be a ** token, which is shared with a
3337 /// parent/child pointer type and may require special handling.
32153338 ptr_type_sentinel,
3216 /// lhs is index into ptr_type. rhs is the element type expression.
3217 /// main_token is the asterisk if a single item pointer or the lbracket
3218 /// if a slice, many-item pointer, or C-pointer
3219 /// main_token might be a ** token, which is shared with a parent/child
3220 /// pointer type and may require special handling.
3339 /// The `data` field is a `.opt_node_and_node`:
3340 /// 1. a `ExtraIndex` to `PtrType`.
3341 /// 2. a `Node.Index` to the element type expression.
3342 ///
3343 /// The `main_token` is the asterisk if a single item pointer or the
3344 /// lbracket if a slice, many-item pointer, or C-pointer.
3345 /// The `main_token` might be a ** token, which is shared with a
3346 /// parent/child pointer type and may require special handling.
32213347 ptr_type,
3222 /// lhs is index into ptr_type_bit_range. rhs is the element type expression.
3223 /// main_token is the asterisk if a single item pointer or the lbracket
3224 /// if a slice, many-item pointer, or C-pointer
3225 /// main_token might be a ** token, which is shared with a parent/child
3226 /// pointer type and may require special handling.
3348 /// The `data` field is a `.opt_node_and_node`:
3349 /// 1. a `ExtraIndex` to `PtrTypeBitRange`.
3350 /// 2. a `Node.Index` to the element type expression.
3351 ///
3352 /// The `main_token` is the asterisk if a single item pointer or the
3353 /// lbracket if a slice, many-item pointer, or C-pointer.
3354 /// The `main_token` might be a ** token, which is shared with a
3355 /// parent/child pointer type and may require special handling.
32273356 ptr_type_bit_range,
32283357 /// `lhs[rhs..]`
3229 /// main_token is the lbracket.
3358 ///
3359 /// The `main_token` field is the `[` token.
32303360 slice_open,
3231 /// `lhs[b..c]`. rhs is index into Slice
3232 /// main_token is the lbracket.
3361 /// `sliced[start..end]`.
3362 ///
3363 /// The `data` field is a `.node_and_extra`:
3364 /// 1. a `Node.Index` to the sliced expression.
3365 /// 2. a `ExtraIndex` to `Slice`.
3366 ///
3367 /// The `main_token` field is the `[` token.
32333368 slice,
3234 /// `lhs[b..c :d]`. rhs is index into SliceSentinel. Slice end "c" can be omitted.
3235 /// main_token is the lbracket.
3369 /// `sliced[start..end :sentinel]`,
3370 /// `sliced[start.. :sentinel]`.
3371 ///
3372 /// The `data` field is a `.node_and_extra`:
3373 /// 1. a `Node.Index` to the sliced expression.
3374 /// 2. a `ExtraIndex` to `SliceSentinel`.
3375 ///
3376 /// The `main_token` field is the `[` token.
32363377 slice_sentinel,
3237 /// `lhs.*`. rhs is unused.
3378 /// `expr.*`.
3379 ///
3380 /// The `data` field is a `.node` to expr.
3381 ///
3382 /// The `main_token` field is the `*` token.
32383383 deref,
32393384 /// `lhs[rhs]`.
3385 ///
3386 /// The `main_token` field is the `[` token.
32403387 array_access,
3241 /// `lhs{rhs}`. rhs can be omitted.
3388 /// `lhs{rhs}`.
3389 ///
3390 /// The `main_token` field is the `{` token.
32423391 array_init_one,
3243 /// `lhs{rhs,}`. rhs can *not* be omitted
3392 /// Same as `array_init_one` except there is known to be a trailing
3393 /// comma before the final rbrace.
32443394 array_init_one_comma,
3245 /// `.{lhs, rhs}`. lhs and rhs can be omitted.
3395 /// `.{a}`,
3396 /// `.{a, b}`.
3397 ///
3398 /// The `data` field is a `.opt_node_and_opt_node`:
3399 /// 1. a `Node.OptionalIndex` to the first element. Never `.none`
3400 /// 2. a `Node.OptionalIndex` to the second element, if any.
3401 ///
3402 /// The `main_token` field is the `{` token.
32463403 array_init_dot_two,
3247 /// Same as `array_init_dot_two` except there is known to be a trailing comma
3248 /// before the final rbrace.
3404 /// Same as `array_init_dot_two` except there is known to be a trailing
3405 /// comma before the final rbrace.
32493406 array_init_dot_two_comma,
3250 /// `.{a, b}`. `sub_list[lhs..rhs]`.
3407 /// `.{a, b, c}`.
3408 ///
3409 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3410 /// each element.
3411 ///
3412 /// The `main_token` field is the `{` token.
32513413 array_init_dot,
3252 /// Same as `array_init_dot` except there is known to be a trailing comma
3253 /// before the final rbrace.
3414 /// Same as `array_init_dot` except there is known to be a trailing
3415 /// comma before the final rbrace.
32543416 array_init_dot_comma,
3255 /// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`.
3417 /// `a{b, c}`.
3418 ///
3419 /// The `data` field is a `.node_and_extra`:
3420 /// 1. a `Node.Index` to the type expression.
3421 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3422 /// each element.
3423 ///
3424 /// The `main_token` field is the `{` token.
32563425 array_init,
32573426 /// Same as `array_init` except there is known to be a trailing comma
32583427 /// before the final rbrace.
32593428 array_init_comma,
3260 /// `lhs{.a = rhs}`. rhs can be omitted making it empty.
3261 /// main_token is the lbrace.
3429 /// `a{.x = b}`, `a{}`.
3430 ///
3431 /// The `data` field is a `.node_and_opt_node`:
3432 /// 1. a `Node.Index` to the type expression.
3433 /// 2. a `Node.OptionalIndex` to the first field initialization, if any.
3434 ///
3435 /// The `main_token` field is the `{` token.
3436 ///
3437 /// The field name is determined by looking at the tokens preceding the
3438 /// field initialization.
32623439 struct_init_one,
3263 /// `lhs{.a = rhs,}`. rhs can *not* be omitted.
3264 /// main_token is the lbrace.
3440 /// Same as `struct_init_one` except there is known to be a trailing comma
3441 /// before the final rbrace.
32653442 struct_init_one_comma,
3266 /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted.
3267 /// main_token is the lbrace.
3268 /// No trailing comma before the rbrace.
3443 /// `.{.x = a, .y = b}`.
3444 ///
3445 /// The `data` field is a `.opt_node_and_opt_node`:
3446 /// 1. a `Node.OptionalIndex` to the first field initialization. Never `.none`
3447 /// 2. a `Node.OptionalIndex` to the second field initialization, if any.
3448 ///
3449 /// The `main_token` field is the '{' token.
3450 ///
3451 /// The field name is determined by looking at the tokens preceding the
3452 /// field initialization.
32693453 struct_init_dot_two,
3270 /// Same as `struct_init_dot_two` except there is known to be a trailing comma
3271 /// before the final rbrace.
3454 /// Same as `struct_init_dot_two` except there is known to be a trailing
3455 /// comma before the final rbrace.
32723456 struct_init_dot_two_comma,
3273 /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`.
3274 /// main_token is the lbrace.
3457 /// `.{.x = a, .y = b, .z = c}`.
3458 ///
3459 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3460 /// each field initialization.
3461 ///
3462 /// The `main_token` field is the `{` token.
3463 ///
3464 /// The field name is determined by looking at the tokens preceding the
3465 /// field initialization.
32753466 struct_init_dot,
3276 /// Same as `struct_init_dot` except there is known to be a trailing comma
3277 /// before the final rbrace.
3467 /// Same as `struct_init_dot` except there is known to be a trailing
3468 /// comma before the final rbrace.
32783469 struct_init_dot_comma,
3279 /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`.
3280 /// lhs can be omitted which means `.{.a = b, .c = d}`.
3281 /// main_token is the lbrace.
3470 /// `a{.x = b, .y = c}`.
3471 ///
3472 /// The `data` field is a `.node_and_extra`:
3473 /// 1. a `Node.Index` to the type expression.
3474 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3475 /// each field initialization.
3476 ///
3477 /// The `main_token` field is the `{` token.
3478 ///
3479 /// The field name is determined by looking at the tokens preceding the
3480 /// field initialization.
32823481 struct_init,
32833482 /// Same as `struct_init` except there is known to be a trailing comma
32843483 /// before the final rbrace.
32853484 struct_init_comma,
3286 /// `lhs(rhs)`. rhs can be omitted.
3287 /// main_token is the lparen.
3485 /// `a(b)`, `a()`.
3486 ///
3487 /// The `data` field is a `.node_and_opt_node`:
3488 /// 1. a `Node.Index` to the function expression.
3489 /// 2. a `Node.OptionalIndex` to the first argument, if any.
3490 ///
3491 /// The `main_token` field is the `(` token.
32883492 call_one,
3289 /// `lhs(rhs,)`. rhs can be omitted.
3290 /// main_token is the lparen.
3493 /// Same as `call_one` except there is known to be a trailing comma
3494 /// before the final rparen.
32913495 call_one_comma,
3292 /// `async lhs(rhs)`. rhs can be omitted.
3496 /// `async a(b)`, `async a()`.
3497 ///
3498 /// The `data` field is a `.node_and_opt_node`:
3499 /// 1. a `Node.Index` to the function expression.
3500 /// 2. a `Node.OptionalIndex` to the first argument, if any.
3501 ///
3502 /// The `main_token` field is the `(` token.
32933503 async_call_one,
3294 /// `async lhs(rhs,)`.
3504 /// Same as `async_call_one` except there is known to be a trailing
3505 /// comma before the final rparen.
32953506 async_call_one_comma,
3296 /// `lhs(a, b, c)`. `SubRange[rhs]`.
3297 /// main_token is the `(`.
3507 /// `a(b, c, d)`.
3508 ///
3509 /// The `data` field is a `.node_and_extra`:
3510 /// 1. a `Node.Index` to the function expression.
3511 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3512 /// each argument.
3513 ///
3514 /// The `main_token` field is the `(` token.
32983515 call,
3299 /// `lhs(a, b, c,)`. `SubRange[rhs]`.
3300 /// main_token is the `(`.
3516 /// Same as `call` except there is known to be a trailing comma before
3517 /// the final rparen.
33013518 call_comma,
3302 /// `async lhs(a, b, c)`. `SubRange[rhs]`.
3303 /// main_token is the `(`.
3519 /// `async a(b, c, d)`.
3520 ///
3521 /// The `data` field is a `.node_and_extra`:
3522 /// 1. a `Node.Index` to the function expression.
3523 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3524 /// each argument.
3525 ///
3526 /// The `main_token` field is the `(` token.
33043527 async_call,
3305 /// `async lhs(a, b, c,)`. `SubRange[rhs]`.
3306 /// main_token is the `(`.
3528 /// Same as `async_call` except there is known to be a trailing comma
3529 /// before the final rparen.
33073530 async_call_comma,
3308 /// `switch(lhs) {}`. `SubRange[rhs]`.
3309 /// `main_token` is the identifier of a preceding label, if any; otherwise `switch`.
3531 /// `switch(a) {}`.
3532 ///
3533 /// The `data` field is a `.node_and_extra`:
3534 /// 1. a `Node.Index` to the switch operand.
3535 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3536 /// each switch case.
3537 ///
3538 /// `The `main_token` field` is the identifier of a preceding label, if any; otherwise `switch`.
33103539 @"switch",
3311 /// Same as switch except there is known to be a trailing comma
3312 /// before the final rbrace
3540 /// Same as `switch` except there is known to be a trailing comma before
3541 /// the final rbrace.
33133542 switch_comma,
3314 /// `lhs => rhs`. If lhs is omitted it means `else`.
3315 /// main_token is the `=>`
3543 /// `a => b`,
3544 /// `else => b`.
3545 ///
3546 /// The `data` field is a `.opt_node_and_node`:
3547 /// 1. a `Node.OptionalIndex` where `.none` means `else`.
3548 /// 2. a `Node.Index` to the target expression.
3549 ///
3550 /// The `main_token` field is the `=>` token.
33163551 switch_case_one,
3317 /// Same ast `switch_case_one` but the case is inline
3552 /// Same as `switch_case_one` but the case is inline.
33183553 switch_case_inline_one,
3319 /// `a, b, c => rhs`. `SubRange[lhs]`.
3320 /// main_token is the `=>`
3554 /// `a, b, c => d`.
3555 ///
3556 /// The `data` field is a `.extra_and_node`:
3557 /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3558 /// each switch item.
3559 /// 2. a `Node.Index` to the target expression.
3560 ///
3561 /// The `main_token` field is the `=>` token.
33213562 switch_case,
3322 /// Same ast `switch_case` but the case is inline
3563 /// Same as `switch_case` but the case is inline.
33233564 switch_case_inline,
33243565 /// `lhs...rhs`.
3566 ///
3567 /// The `main_token` field is the `...` token.
33253568 switch_range,
3326 /// `while (lhs) rhs`.
3327 /// `while (lhs) |x| rhs`.
3569 /// `while (a) b`,
3570 /// `while (a) |x| b`.
33283571 while_simple,
3329 /// `while (lhs) : (a) b`. `WhileCont[rhs]`.
3330 /// `while (lhs) : (a) b`. `WhileCont[rhs]`.
3572 /// `while (a) : (b) c`,
3573 /// `while (a) |x| : (b) c`.
33313574 while_cont,
3332 /// `while (lhs) : (a) b else c`. `While[rhs]`.
3333 /// `while (lhs) |x| : (a) b else c`. `While[rhs]`.
3334 /// `while (lhs) |x| : (a) b else |y| c`. `While[rhs]`.
3335 /// The cont expression part `: (a)` may be omitted.
3575 /// `while (a) : (b) c else d`,
3576 /// `while (a) |x| : (b) c else d`,
3577 /// `while (a) |x| : (b) c else |y| d`.
3578 /// The continue expression part `: (b)` may be omitted.
33363579 @"while",
3337 /// `for (lhs) rhs`.
3580 /// `for (a) b`.
33383581 for_simple,
33393582 /// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`.
33403583 @"for",
3341 /// `lhs..rhs`. rhs can be omitted.
3584 /// `lhs..rhs`, `lhs..`.
33423585 for_range,
3343 /// `if (lhs) rhs`.
3344 /// `if (lhs) |a| rhs`.
3586 /// `if (a) b`.
3587 /// `if (b) |x| b`.
33453588 if_simple,
3346 /// `if (lhs) a else b`. `If[rhs]`.
3347 /// `if (lhs) |x| a else b`. `If[rhs]`.
3348 /// `if (lhs) |x| a else |y| b`. `If[rhs]`.
3589 /// `if (a) b else c`.
3590 /// `if (a) |x| b else c`.
3591 /// `if (a) |x| b else |y| d`.
33493592 @"if",
3350 /// `suspend lhs`. lhs can be omitted. rhs is unused.
3593 /// `suspend expr`.
3594 ///
3595 /// The `data` field is a `.node` to expr.
3596 ///
3597 /// The `main_token` field is the `suspend` token.
33513598 @"suspend",
3352 /// `resume lhs`. rhs is unused.
3599 /// `resume expr`.
3600 ///
3601 /// The `data` field is a `.node` to expr.
3602 ///
3603 /// The `main_token` field is the `resume` token.
33533604 @"resume",
3354 /// `continue :lhs rhs`
3355 /// both lhs and rhs may be omitted.
3605 /// `continue :label expr`,
3606 /// `continue expr`,
3607 /// `continue :label`,
3608 /// `continue`.
3609 ///
3610 /// The `data` field is a `.opt_token_and_opt_node`:
3611 /// 1. a `OptionalTokenIndex` to the label identifier, if any.
3612 /// 2. a `Node.OptionalIndex` to the target expression, if any.
3613 ///
3614 /// The `main_token` field is the `continue` token.
33563615 @"continue",
3357 /// `break :lhs rhs`
3358 /// both lhs and rhs may be omitted.
3616 /// `break :label expr`,
3617 /// `break expr`,
3618 /// `break :label`,
3619 /// `break`.
3620 ///
3621 /// The `data` field is a `.opt_token_and_opt_node`:
3622 /// 1. a `OptionalTokenIndex` to the label identifier, if any.
3623 /// 2. a `Node.OptionalIndex` to the target expression, if any.
3624 ///
3625 /// The `main_token` field is the `break` token.
33593626 @"break",
3360 /// `return lhs`. lhs can be omitted. rhs is unused.
3627 /// `return expr`, `return`.
3628 ///
3629 /// The `data` field is a `.opt_node` to the return value, if any.
3630 ///
3631 /// The `main_token` field is the `return` token.
33613632 @"return",
3362 /// `fn (a: lhs) rhs`. lhs can be omitted.
3363 /// anytype and ... parameters are omitted from the AST tree.
3364 /// main_token is the `fn` keyword.
3365 /// extern function declarations use this tag.
3633 /// `fn (a: type_expr) return_type`.
3634 ///
3635 /// The `data` field is a `.opt_node_and_opt_node`:
3636 /// 1. a `Node.OptionalIndex` to the first parameter type expression, if any.
3637 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3638 /// `.none` unless a parsing error occured.
3639 ///
3640 /// The `main_token` field is the `fn` token.
3641 ///
3642 /// `anytype` and `...` parameters are omitted from the AST tree.
3643 /// Extern function declarations use this tag.
33663644 fn_proto_simple,
3367 /// `fn (a: b, c: d) rhs`. `sub_range_list[lhs]`.
3368 /// anytype and ... parameters are omitted from the AST tree.
3369 /// main_token is the `fn` keyword.
3370 /// extern function declarations use this tag.
3645 /// `fn (a: b, c: d) return_type`.
3646 ///
3647 /// The `data` field is a `.extra_and_opt_node`:
3648 /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3649 /// each parameter type expression.
3650 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3651 /// `.none` unless a parsing error occured.
3652 ///
3653 /// The `main_token` field is the `fn` token.
3654 ///
3655 /// `anytype` and `...` parameters are omitted from the AST tree.
3656 /// Extern function declarations use this tag.
33713657 fn_proto_multi,
3372 /// `fn (a: b) addrspace(e) linksection(f) callconv(g) rhs`. `FnProtoOne[lhs]`.
3658 /// `fn (a: b) addrspace(e) linksection(f) callconv(g) return_type`.
33733659 /// zero or one parameters.
3374 /// anytype and ... parameters are omitted from the AST tree.
3375 /// main_token is the `fn` keyword.
3376 /// extern function declarations use this tag.
3660 ///
3661 /// The `data` field is a `.extra_and_opt_node`:
3662 /// 1. a `Node.ExtraIndex` to `FnProtoOne`.
3663 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3664 /// `.none` unless a parsing error occured.
3665 ///
3666 /// The `main_token` field is the `fn` token.
3667 ///
3668 /// `anytype` and `...` parameters are omitted from the AST tree.
3669 /// Extern function declarations use this tag.
33773670 fn_proto_one,
3378 /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) rhs`. `FnProto[lhs]`.
3379 /// anytype and ... parameters are omitted from the AST tree.
3380 /// main_token is the `fn` keyword.
3381 /// extern function declarations use this tag.
3671 /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) return_type`.
3672 ///
3673 /// The `data` field is a `.extra_and_opt_node`:
3674 /// 1. a `Node.ExtraIndex` to `FnProto`.
3675 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3676 /// `.none` unless a parsing error occured.
3677 ///
3678 /// The `main_token` field is the `fn` token.
3679 ///
3680 /// `anytype` and `...` parameters are omitted from the AST tree.
3681 /// Extern function declarations use this tag.
33823682 fn_proto,
3383 /// lhs is the fn_proto.
3384 /// rhs is the function body block.
3385 /// Note that extern function declarations use the fn_proto tags rather
3386 /// than this one.
3683 /// Extern function declarations use the fn_proto tags rather than this one.
3684 ///
3685 /// The `data` field is a `.node_and_node`:
3686 /// 1. a `Node.Index` to `fn_proto_*`.
3687 /// 2. a `Node.Index` to function body block.
3688 ///
3689 /// The `main_token` field is the `fn` token.
33873690 fn_decl,
3388 /// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index.
3691 /// `anyframe->return_type`.
3692 ///
3693 /// The `data` field is a `.token_and_node`:
3694 /// 1. a `TokenIndex` to the `->` token.
3695 /// 2. a `Node.Index` to the function frame return type expression.
3696 ///
3697 /// The `main_token` field is the `anyframe` token.
33893698 anyframe_type,
3390 /// Both lhs and rhs unused.
3699 /// The `data` field is unused.
33913700 anyframe_literal,
3392 /// Both lhs and rhs unused.
3701 /// The `data` field is unused.
33933702 char_literal,
3394 /// Both lhs and rhs unused.
3703 /// The `data` field is unused.
33953704 number_literal,
3396 /// Both lhs and rhs unused.
3705 /// The `data` field is unused.
33973706 unreachable_literal,
3398 /// Both lhs and rhs unused.
3399 /// Most identifiers will not have explicit AST nodes, however for expressions
3400 /// which could be one of many different kinds of AST nodes, there will be an
3401 /// identifier AST node for it.
3707 /// The `data` field is unused.
3708 ///
3709 /// Most identifiers will not have explicit AST nodes, however for
3710 /// expressions which could be one of many different kinds of AST nodes,
3711 /// there will be an identifier AST node for it.
34023712 identifier,
3403 /// lhs is the dot token index, rhs unused, main_token is the identifier.
3713 /// `.foo`.
3714 ///
3715 /// The `data` field is unused.
3716 ///
3717 /// The `main_token` field is the identifier.
34043718 enum_literal,
3405 /// main_token is the string literal token
3406 /// Both lhs and rhs unused.
3719 /// The `data` field is unused.
3720 ///
3721 /// The `main_token` field is the string literal token.
34073722 string_literal,
3408 /// main_token is the first token index (redundant with lhs)
3409 /// lhs is the first token index; rhs is the last token index.
3410 /// Could be a series of multiline_string_literal_line tokens, or a single
3411 /// string_literal token.
3723 /// The `data` field is a `.token_and_token`:
3724 /// 1. a `TokenIndex` to the first `.multiline_string_literal_line` token.
3725 /// 2. a `TokenIndex` to the last `.multiline_string_literal_line` token.
3726 ///
3727 /// The `main_token` field is the first token index (redundant with `data`).
34123728 multiline_string_literal,
3413 /// `(lhs)`. main_token is the `(`; rhs is the token index of the `)`.
3729 /// `(expr)`.
3730 ///
3731 /// The `data` field is a `.node_and_token`:
3732 /// 1. a `Node.Index` to the sub-expression
3733 /// 2. a `TokenIndex` to the `)` token.
3734 ///
3735 /// The `main_token` field is the `(` token.
34143736 grouped_expression,
3415 /// `@a(lhs, rhs)`. lhs and rhs may be omitted.
3416 /// main_token is the builtin token.
3737 /// `@a(b, c)`.
3738 ///
3739 /// The `data` field is a `.opt_node_and_opt_node`:
3740 /// 1. a `Node.OptionalIndex` to the first argument, if any.
3741 /// 2. a `Node.OptionalIndex` to the second argument, if any.
3742 ///
3743 /// The `main_token` field is the builtin token.
34173744 builtin_call_two,
3418 /// Same as builtin_call_two but there is known to be a trailing comma before the rparen.
3745 /// Same as `builtin_call_two` except there is known to be a trailing comma
3746 /// before the final rparen.
34193747 builtin_call_two_comma,
3420 /// `@a(b, c)`. `sub_list[lhs..rhs]`.
3421 /// main_token is the builtin token.
3748 /// `@a(b, c, d)`.
3749 ///
3750 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3751 /// each argument.
3752 ///
3753 /// The `main_token` field is the builtin token.
34223754 builtin_call,
3423 /// Same as builtin_call but there is known to be a trailing comma before the rparen.
3755 /// Same as `builtin_call` except there is known to be a trailing comma
3756 /// before the final rparen.
34243757 builtin_call_comma,
34253758 /// `error{a, b}`.
3426 /// rhs is the rbrace, lhs is unused.
3759 ///
3760 /// The `data` field is a `.token_and_token`:
3761 /// 1. a `TokenIndex` to the `{` token.
3762 /// 2. a `TokenIndex` to the `}` token.
3763 ///
3764 /// The `main_token` field is the `error`.
34273765 error_set_decl,
3428 /// `struct {}`, `union {}`, `opaque {}`, `enum {}`. `extra_data[lhs..rhs]`.
3429 /// main_token is `struct`, `union`, `opaque`, `enum` keyword.
3766 /// `struct {}`, `union {}`, `opaque {}`, `enum {}`.
3767 ///
3768 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3769 /// each container member.
3770 ///
3771 /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
34303772 container_decl,
3431 /// Same as ContainerDecl but there is known to be a trailing comma
3432 /// or semicolon before the rbrace.
3773 /// Same as `container_decl` except there is known to be a trailing
3774 /// comma before the final rbrace.
34333775 container_decl_trailing,
34343776 /// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`.
3435 /// lhs or rhs can be omitted.
3436 /// main_token is `struct`, `union`, `opaque`, `enum` keyword.
3777 ///
3778 /// The `data` field is a `.opt_node_and_opt_node`:
3779 /// 1. a `Node.OptionalIndex` to the first container member, if any.
3780 /// 2. a `Node.OptionalIndex` to the second container member, if any.
3781 ///
3782 /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
34373783 container_decl_two,
3438 /// Same as ContainerDeclTwo except there is known to be a trailing comma
3439 /// or semicolon before the rbrace.
3784 /// Same as `container_decl_two` except there is known to be a trailing
3785 /// comma before the final rbrace.
34403786 container_decl_two_trailing,
3441 /// `struct(lhs)` / `union(lhs)` / `enum(lhs)`. `SubRange[rhs]`.
3787 /// `struct(arg)`, `union(arg)`, `enum(arg)`.
3788 ///
3789 /// The `data` field is a `.node_and_extra`:
3790 /// 1. a `Node.Index` to arg.
3791 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3792 /// each container member.
3793 ///
3794 /// The `main_token` field is the `struct`, `union` or `enum` token.
34423795 container_decl_arg,
3443 /// Same as container_decl_arg but there is known to be a trailing
3444 /// comma or semicolon before the rbrace.
3796 /// Same as `container_decl_arg` except there is known to be a trailing
3797 /// comma before the final rbrace.
34453798 container_decl_arg_trailing,
3446 /// `union(enum) {}`. `sub_list[lhs..rhs]`.
3447 /// Note that tagged unions with explicitly provided enums are represented
3448 /// by `container_decl_arg`.
3799 /// `union(enum) {}`.
3800 ///
3801 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3802 /// each container member.
3803 ///
3804 /// The `main_token` field is the `union` token.
3805 ///
3806 /// A tagged union with explicitly provided enums will instead be
3807 /// represented by `container_decl_arg`.
34493808 tagged_union,
3450 /// Same as tagged_union but there is known to be a trailing comma
3451 /// or semicolon before the rbrace.
3809 /// Same as `tagged_union` except there is known to be a trailing comma
3810 /// before the final rbrace.
34523811 tagged_union_trailing,
3453 /// `union(enum) {lhs, rhs}`. lhs or rhs may be omitted.
3454 /// Note that tagged unions with explicitly provided enums are represented
3455 /// by `container_decl_arg`.
3812 /// `union(enum) {lhs, rhs}`.
3813 ///
3814 /// The `data` field is a `.opt_node_and_opt_node`:
3815 /// 1. a `Node.OptionalIndex` to the first container member, if any.
3816 /// 2. a `Node.OptionalIndex` to the second container member, if any.
3817 ///
3818 /// The `main_token` field is the `union` token.
3819 ///
3820 /// A tagged union with explicitly provided enums will instead be
3821 /// represented by `container_decl_arg`.
34563822 tagged_union_two,
3457 /// Same as tagged_union_two but there is known to be a trailing comma
3458 /// or semicolon before the rbrace.
3823 /// Same as `tagged_union_two` except there is known to be a trailing
3824 /// comma before the final rbrace.
34593825 tagged_union_two_trailing,
3460 /// `union(enum(lhs)) {}`. `SubRange[rhs]`.
3826 /// `union(enum(arg)) {}`.
3827 ///
3828 /// The `data` field is a `.node_and_extra`:
3829 /// 1. a `Node.Index` to arg.
3830 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3831 /// each container member.
3832 ///
3833 /// The `main_token` field is the `union` token.
34613834 tagged_union_enum_tag,
3462 /// Same as tagged_union_enum_tag but there is known to be a trailing comma
3463 /// or semicolon before the rbrace.
3835 /// Same as `tagged_union_enum_tag` except there is known to be a
3836 /// trailing comma before the final rbrace.
34643837 tagged_union_enum_tag_trailing,
3465 /// `a: lhs = rhs,`. lhs and rhs can be omitted.
3466 /// main_token is the field name identifier.
3467 /// lastToken() does not include the possible trailing comma.
3838 /// `a: lhs = rhs,`,
3839 /// `a: lhs,`.
3840 ///
3841 /// The `data` field is a `.node_and_opt_node`:
3842 /// 1. a `Node.Index` to the field type expression.
3843 /// 2. a `Node.OptionalIndex` to the default value expression, if any.
3844 ///
3845 /// The `main_token` field is the field name identifier.
3846 ///
3847 /// `lastToken()` does not include the possible trailing comma.
34683848 container_field_init,
3469 /// `a: lhs align(rhs),`. rhs can be omitted.
3470 /// main_token is the field name identifier.
3471 /// lastToken() does not include the possible trailing comma.
3849 /// `a: lhs align(rhs),`.
3850 ///
3851 /// The `data` field is a `.node_and_node`:
3852 /// 1. a `Node.Index` to the field type expression.
3853 /// 2. a `Node.Index` to the alignment expression.
3854 ///
3855 /// The `main_token` field is the field name identifier.
3856 ///
3857 /// `lastToken()` does not include the possible trailing comma.
34723858 container_field_align,
3473 /// `a: lhs align(c) = d,`. `container_field_list[rhs]`.
3474 /// main_token is the field name identifier.
3475 /// lastToken() does not include the possible trailing comma.
3859 /// `a: lhs align(c) = d,`.
3860 ///
3861 /// The `data` field is a `.node_and_extra`:
3862 /// 1. a `Node.Index` to the field type expression.
3863 /// 2. a `ExtraIndex` to `ContainerField`.
3864 ///
3865 /// The `main_token` field is the field name identifier.
3866 ///
3867 /// `lastToken()` does not include the possible trailing comma.
34763868 container_field,
3477 /// `comptime lhs`. rhs unused.
3869 /// `comptime expr`.
3870 ///
3871 /// The `data` field is a `.node` to expr.
3872 ///
3873 /// The `main_token` field is the `comptime` token.
34783874 @"comptime",
3479 /// `nosuspend lhs`. rhs unused.
3875 /// `nosuspend expr`.
3876 ///
3877 /// The `data` field is a `.node` to expr.
3878 ///
3879 /// The `main_token` field is the `nosuspend` token.
34803880 @"nosuspend",
3481 /// `{lhs rhs}`. rhs or lhs can be omitted.
3482 /// main_token points at the lbrace.
3881 /// `{lhs rhs}`.
3882 ///
3883 /// The `data` field is a `.opt_node_and_opt_node`:
3884 /// 1. a `Node.OptionalIndex` to the first statement, if any.
3885 /// 2. a `Node.OptionalIndex` to the second statement, if any.
3886 ///
3887 /// The `main_token` field is the `{` token.
34833888 block_two,
3484 /// Same as block_two but there is known to be a semicolon before the rbrace.
3889 /// Same as `block_two_semicolon` except there is known to be a trailing
3890 /// comma before the final rbrace.
34853891 block_two_semicolon,
3486 /// `{}`. `sub_list[lhs..rhs]`.
3487 /// main_token points at the lbrace.
3892 /// `{a b}`.
3893 ///
3894 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3895 /// each statement.
3896 ///
3897 /// The `main_token` field is the `{` token.
34883898 block,
3489 /// Same as block but there is known to be a semicolon before the rbrace.
3899 /// Same as `block` except there is known to be a trailing comma before
3900 /// the final rbrace.
34903901 block_semicolon,
3491 /// `asm(lhs)`. rhs is the token index of the rparen.
3902 /// `asm(lhs)`.
3903 ///
3904 /// rhs is a `Token.Index` to the `)` token.
3905 /// The `main_token` field is the `asm` token.
34923906 asm_simple,
3493 /// `asm(lhs, a)`. `Asm[rhs]`.
3907 /// `asm(lhs, a)`.
3908 ///
3909 /// The `data` field is a `.node_and_extra`:
3910 /// 1. a `Node.Index` to lhs.
3911 /// 2. a `ExtraIndex` to `Asm`.
3912 ///
3913 /// The `main_token` field is the `asm` token.
34943914 @"asm",
3495 /// `[a] "b" (c)`. lhs is 0, rhs is token index of the rparen.
3496 /// `[a] "b" (-> lhs)`. rhs is token index of the rparen.
3497 /// main_token is `a`.
3915 /// `[a] "b" (c)`.
3916 /// `[a] "b" (-> lhs)`.
3917 ///
3918 /// The `data` field is a `.opt_node_and_token`:
3919 /// 1. a `Node.OptionalIndex` to lhs, if any.
3920 /// 2. a `TokenIndex` to the `)` token.
3921 ///
3922 /// The `main_token` field is `a`.
34983923 asm_output,
3499 /// `[a] "b" (lhs)`. rhs is token index of the rparen.
3500 /// main_token is `a`.
3924 /// `[a] "b" (lhs)`.
3925 ///
3926 /// The `data` field is a `.node_and_token`:
3927 /// 1. a `Node.Index` to lhs.
3928 /// 2. a `TokenIndex` to the `)` token.
3929 ///
3930 /// The `main_token` field is `a`.
35013931 asm_input,
3502 /// `error.a`. lhs is token index of `.`. rhs is token index of `a`.
3932 /// `error.a`.
3933 ///
3934 /// The `data` field is unused.
3935 ///
3936 /// The `main_token` field is `error` token.
35033937 error_value,
3504 /// `lhs!rhs`. main_token is the `!`.
3938 /// `lhs!rhs`.
3939 ///
3940 /// The `main_token` field is the `!` token.
35053941 error_union,
35063942
35073943 pub fn isContainerField(tag: Tag) bool {
......@@ -3516,9 +3952,26 @@ pub const Node = struct {
35163952 }
35173953 };
35183954
3519 pub const Data = struct {
3520 lhs: Index,
3521 rhs: Index,
3955 pub const Data = union {
3956 node: Index,
3957 opt_node: OptionalIndex,
3958 token: TokenIndex,
3959 node_and_node: struct { Index, Index },
3960 opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex },
3961 node_and_opt_node: struct { Index, OptionalIndex },
3962 opt_node_and_node: struct { OptionalIndex, Index },
3963 node_and_extra: struct { Index, ExtraIndex },
3964 extra_and_node: struct { ExtraIndex, Index },
3965 extra_and_opt_node: struct { ExtraIndex, OptionalIndex },
3966 node_and_token: struct { Index, TokenIndex },
3967 token_and_node: struct { TokenIndex, Index },
3968 token_and_token: struct { TokenIndex, TokenIndex },
3969 opt_node_and_token: struct { OptionalIndex, TokenIndex },
3970 opt_token_and_node: struct { OptionalTokenIndex, Index },
3971 opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex },
3972 opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex },
3973 @"for": struct { ExtraIndex, For },
3974 extra_range: SubRange,
35223975 };
35233976
35243977 pub const LocalVarDecl = struct {
......@@ -3532,24 +3985,24 @@ pub const Node = struct {
35323985 };
35333986
35343987 pub const PtrType = struct {
3535 sentinel: Index,
3536 align_node: Index,
3537 addrspace_node: Index,
3988 sentinel: OptionalIndex,
3989 align_node: OptionalIndex,
3990 addrspace_node: OptionalIndex,
35383991 };
35393992
35403993 pub const PtrTypeBitRange = struct {
3541 sentinel: Index,
3994 sentinel: OptionalIndex,
35423995 align_node: Index,
3543 addrspace_node: Index,
3996 addrspace_node: OptionalIndex,
35443997 bit_range_start: Index,
35453998 bit_range_end: Index,
35463999 };
35474000
35484001 pub const SubRange = struct {
3549 /// Index into sub_list.
3550 start: Index,
3551 /// Index into sub_list.
3552 end: Index,
4002 /// Index into extra_data.
4003 start: ExtraIndex,
4004 /// Index into extra_data.
4005 end: ExtraIndex,
35534006 };
35544007
35554008 pub const If = struct {
......@@ -3564,13 +4017,13 @@ pub const Node = struct {
35644017
35654018 pub const GlobalVarDecl = struct {
35664019 /// Populated if there is an explicit type ascription.
3567 type_node: Index,
4020 type_node: OptionalIndex,
35684021 /// Populated if align(A) is present.
3569 align_node: Index,
4022 align_node: OptionalIndex,
35704023 /// Populated if addrspace(A) is present.
3571 addrspace_node: Index,
4024 addrspace_node: OptionalIndex,
35724025 /// Populated if linksection(A) is present.
3573 section_node: Index,
4026 section_node: OptionalIndex,
35744027 };
35754028
35764029 pub const Slice = struct {
......@@ -3580,13 +4033,13 @@ pub const Node = struct {
35804033
35814034 pub const SliceSentinel = struct {
35824035 start: Index,
3583 /// May be 0 if the slice is "open"
3584 end: Index,
4036 /// May be .none if the slice is "open"
4037 end: OptionalIndex,
35854038 sentinel: Index,
35864039 };
35874040
35884041 pub const While = struct {
3589 cont_expr: Index,
4042 cont_expr: OptionalIndex,
35904043 then_expr: Index,
35914044 else_expr: Index,
35924045 };
......@@ -3603,44 +4056,44 @@ pub const Node = struct {
36034056
36044057 pub const FnProtoOne = struct {
36054058 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.
3606 param: Index,
4059 param: OptionalIndex,
36074060 /// Populated if align(A) is present.
3608 align_expr: Index,
4061 align_expr: OptionalIndex,
36094062 /// Populated if addrspace(A) is present.
3610 addrspace_expr: Index,
4063 addrspace_expr: OptionalIndex,
36114064 /// Populated if linksection(A) is present.
3612 section_expr: Index,
4065 section_expr: OptionalIndex,
36134066 /// Populated if callconv(A) is present.
3614 callconv_expr: Index,
4067 callconv_expr: OptionalIndex,
36154068 };
36164069
36174070 pub const FnProto = struct {
3618 params_start: Index,
3619 params_end: Index,
4071 params_start: ExtraIndex,
4072 params_end: ExtraIndex,
36204073 /// Populated if align(A) is present.
3621 align_expr: Index,
4074 align_expr: OptionalIndex,
36224075 /// Populated if addrspace(A) is present.
3623 addrspace_expr: Index,
4076 addrspace_expr: OptionalIndex,
36244077 /// Populated if linksection(A) is present.
3625 section_expr: Index,
4078 section_expr: OptionalIndex,
36264079 /// Populated if callconv(A) is present.
3627 callconv_expr: Index,
4080 callconv_expr: OptionalIndex,
36284081 };
36294082
36304083 pub const Asm = struct {
3631 items_start: Index,
3632 items_end: Index,
4084 items_start: ExtraIndex,
4085 items_end: ExtraIndex,
36334086 /// Needed to make lastToken() work.
36344087 rparen: TokenIndex,
36354088 };
36364089};
36374090
3638pub fn nodeToSpan(tree: *const Ast, node: u32) Span {
4091pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span {
36394092 return tokensToSpan(
36404093 tree,
36414094 tree.firstToken(node),
36424095 tree.lastToken(node),
3643 tree.nodes.items(.main_token)[node],
4096 tree.nodeMainToken(node),
36444097 );
36454098}
36464099
......@@ -3649,7 +4102,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
36494102}
36504103
36514104pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
3652 const token_starts = tree.tokens.items(.start);
36534105 var start_tok = start;
36544106 var end_tok = end;
36554107
......@@ -3663,9 +4115,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
36634115 start_tok = main;
36644116 end_tok = main;
36654117 }
3666 const start_off = token_starts[start_tok];
3667 const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
3668 return Span{ .start = start_off, .end = end_off, .main = token_starts[main] };
4118 const start_off = tree.tokenStart(start_tok);
4119 const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
4120 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
36694121}
36704122
36714123const std = @import("../std.zig");
lib/std/zig/AstGen.zig+650-835
......@@ -99,8 +99,18 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
9999 Zir.Inst.Declaration.Name,
100100 std.zig.SimpleComptimeReason,
101101 Zir.NullTerminatedString,
102 // Ast.TokenIndex is missing because it is a u32.
103 Ast.OptionalTokenIndex,
104 Ast.Node.Index,
105 Ast.Node.OptionalIndex,
102106 => @intFromEnum(@field(extra, field.name)),
103107
108 Ast.TokenOffset,
109 Ast.OptionalTokenOffset,
110 Ast.Node.Offset,
111 Ast.Node.OptionalOffset,
112 => @bitCast(@intFromEnum(@field(extra, field.name))),
113
104114 i32,
105115 Zir.Inst.Call.Flags,
106116 Zir.Inst.BuiltinCall.Flags,
......@@ -168,7 +178,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
168178 .is_comptime = true,
169179 .parent = &top_scope.base,
170180 .anon_name_strategy = .parent,
171 .decl_node_index = 0,
181 .decl_node_index = .root,
172182 .decl_line = 0,
173183 .astgen = &astgen,
174184 .instructions = &gz_instructions,
......@@ -182,10 +192,10 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
182192 if (AstGen.structDeclInner(
183193 &gen_scope,
184194 &gen_scope.base,
185 0,
195 .root,
186196 tree.containerDeclRoot(),
187197 .auto,
188 0,
198 .none,
189199 )) |struct_decl_ref| {
190200 assert(struct_decl_ref.toIndex().? == .main_struct_inst);
191201 break :fatal false;
......@@ -430,9 +440,7 @@ fn reachableExprComptime(
430440fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
431441 const astgen = gz.astgen;
432442 const tree = astgen.tree;
433 const node_tags = tree.nodes.items(.tag);
434 const main_tokens = tree.nodes.items(.main_token);
435 switch (node_tags[node]) {
443 switch (tree.nodeTag(node)) {
436444 .root => unreachable,
437445 .@"usingnamespace" => unreachable,
438446 .test_decl => unreachable,
......@@ -600,7 +608,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
600608 .builtin_call_two,
601609 .builtin_call_two_comma,
602610 => {
603 const builtin_token = main_tokens[node];
611 const builtin_token = tree.nodeMainToken(node);
604612 const builtin_name = tree.tokenSlice(builtin_token);
605613 // If the builtin is an invalid name, we don't cause an error here; instead
606614 // let it pass, and the error will be "invalid builtin function" later.
......@@ -631,10 +639,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
631639fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
632640 const astgen = gz.astgen;
633641 const tree = astgen.tree;
634 const main_tokens = tree.nodes.items(.main_token);
635 const token_tags = tree.tokens.items(.tag);
636 const node_datas = tree.nodes.items(.data);
637 const node_tags = tree.nodes.items(.tag);
638642
639643 const prev_anon_name_strategy = gz.anon_name_strategy;
640644 defer gz.anon_name_strategy = prev_anon_name_strategy;
......@@ -642,7 +646,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
642646 gz.anon_name_strategy = .anon;
643647 }
644648
645 switch (node_tags[node]) {
649 switch (tree.nodeTag(node)) {
646650 .root => unreachable, // Top-level declaration.
647651 .@"usingnamespace" => unreachable, // Top-level declaration.
648652 .test_decl => unreachable, // Top-level declaration.
......@@ -752,8 +756,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
752756 },
753757
754758 // zig fmt: off
755 .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl),
756 .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr),
759 .shl => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shl),
760 .shr => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shr),
757761
758762 .add => return simpleBinOp(gz, scope, ri, node, .add),
759763 .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap),
......@@ -783,10 +787,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
783787 // This syntax form does not currently use the result type in the language specification.
784788 // However, the result type can be used to emit more optimal code for large multiplications by
785789 // having Sema perform a coercion before the multiplication operation.
790 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
786791 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{
787792 .res_ty = if (try ri.rl.resultType(gz, node)) |t| t else .none,
788 .lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
789 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs, .array_mul_factor),
793 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
794 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node, .array_mul_factor),
790795 });
791796 return rvalue(gz, ri, result, node);
792797 },
......@@ -797,8 +802,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
797802 .merge_error_sets => .merge_error_sets,
798803 else => unreachable,
799804 };
800 const lhs = try reachableTypeExpr(gz, scope, node_datas[node].lhs, node);
801 const rhs = try reachableTypeExpr(gz, scope, node_datas[node].rhs, node);
805 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
806 const lhs = try reachableTypeExpr(gz, scope, lhs_node, node);
807 const rhs = try reachableTypeExpr(gz, scope, rhs_node, node);
802808 const result = try gz.addPlNode(inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
803809 return rvalue(gz, ri, result, node);
804810 },
......@@ -806,11 +812,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
806812 .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),
807813 .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or),
808814
809 .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, node_datas[node].lhs, .bool_not),
810 .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not),
815 .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, tree.nodeData(node).node, .bool_not),
816 .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, tree.nodeData(node).node, .bit_not),
811817
812818 .negation => return negation(gz, scope, ri, node),
813 .negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .negate_wrap),
819 .negation_wrap => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, tree.nodeData(node).node, .negate_wrap),
814820
815821 .identifier => return identifier(gz, scope, ri, node, null),
816822
......@@ -824,20 +830,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
824830 .number_literal => return numberLiteral(gz, ri, node, node, .positive),
825831 // zig fmt: on
826832
827 .builtin_call_two, .builtin_call_two_comma => {
828 if (node_datas[node].lhs == 0) {
829 const params = [_]Ast.Node.Index{};
830 return builtinCall(gz, scope, ri, node, &params, false);
831 } else if (node_datas[node].rhs == 0) {
832 const params = [_]Ast.Node.Index{node_datas[node].lhs};
833 return builtinCall(gz, scope, ri, node, &params, false);
834 } else {
835 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
836 return builtinCall(gz, scope, ri, node, &params, false);
837 }
838 },
839 .builtin_call, .builtin_call_comma => {
840 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
833 .builtin_call_two,
834 .builtin_call_two_comma,
835 .builtin_call,
836 .builtin_call_comma,
837 => {
838 var buf: [2]Ast.Node.Index = undefined;
839 const params = tree.builtinCallParams(&buf, node).?;
841840 return builtinCall(gz, scope, ri, node, params, false);
842841 },
843842
......@@ -873,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
873872 const if_full = tree.fullIf(node).?;
874873 no_switch_on_err: {
875874 const error_token = if_full.error_token orelse break :no_switch_on_err;
876 const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err;
875 const else_node = if_full.ast.else_expr.unwrap() orelse break :no_switch_on_err;
876 const full_switch = tree.fullSwitch(else_node) orelse break :no_switch_on_err;
877877 if (full_switch.label_token != null) break :no_switch_on_err;
878 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;
879 if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err;
878 if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err;
879 if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err;
880880 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");
881881 }
882882 return ifExpr(gz, scope, ri.br(), node, if_full);
......@@ -894,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
894894 .slice_sentinel,
895895 => {
896896 const full = tree.fullSlice(node).?;
897 if (full.ast.end != 0 and
898 node_tags[full.ast.sliced] == .slice_open and
897 if (full.ast.end != .none and
898 tree.nodeTag(full.ast.sliced) == .slice_open and
899899 nodeIsTriviallyZero(tree, full.ast.start))
900900 {
901901 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
......@@ -903,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
903903 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);
904904 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);
905905 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
906 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);
907 const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none;
906 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end.unwrap().?);
907 const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| try expr(gz, scope, .{ .rl = .none }, sentinel) else .none;
908908 try emitDbgStmt(gz, cursor);
909909 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{
910910 .lhs = lhs,
......@@ -919,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
919919
920920 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
921921 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start);
922 const end = if (full.ast.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end) else .none;
923 const sentinel = if (full.ast.sentinel != 0) s: {
922 const end = if (full.ast.end.unwrap()) |end| try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, end) else .none;
923 const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| s: {
924924 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);
925 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, full.ast.sentinel);
925 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, sentinel);
926926 } else .none;
927927 try emitDbgStmt(gz, cursor);
928928 if (sentinel != .none) {
......@@ -950,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
950950 },
951951
952952 .deref => {
953 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
953 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node);
954954 _ = try gz.addUnNode(.validate_deref, lhs, node);
955955 switch (ri.rl) {
956956 .ref, .ref_coerced_ty => return lhs,
......@@ -965,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
965965 _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
966966 break :rl .{ .ref_coerced_ty = res_ty_inst };
967967 } else .ref;
968 const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs);
968 const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node);
969969 return rvalue(gz, ri, result, node);
970970 },
971971 .optional_type => {
972 const operand = try typeExpr(gz, scope, node_datas[node].lhs);
972 const operand = try typeExpr(gz, scope, tree.nodeData(node).node);
973973 const result = try gz.addUnNode(.optional_type, operand, node);
974974 return rvalue(gz, ri, result, node);
975975 },
976976 .unwrap_optional => switch (ri.rl) {
977977 .ref, .ref_coerced_ty => {
978 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
978 const lhs = try expr(gz, scope, .{ .rl = .ref }, tree.nodeData(node).node_and_token[0]);
979979
980980 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
981981 try emitDbgStmt(gz, cursor);
......@@ -983,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
983983 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
984984 },
985985 else => {
986 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
986 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]);
987987
988988 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
989989 try emitDbgStmt(gz, cursor);
......@@ -991,22 +991,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
991991 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
992992 },
993993 },
994 .block_two, .block_two_semicolon => {
995 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
996 if (node_datas[node].lhs == 0) {
997 return blockExpr(gz, scope, ri, node, statements[0..0], .normal);
998 } else if (node_datas[node].rhs == 0) {
999 return blockExpr(gz, scope, ri, node, statements[0..1], .normal);
1000 } else {
1001 return blockExpr(gz, scope, ri, node, statements[0..2], .normal);
1002 }
1003 },
1004 .block, .block_semicolon => {
1005 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
994 .block_two,
995 .block_two_semicolon,
996 .block,
997 .block_semicolon,
998 => {
999 var buf: [2]Ast.Node.Index = undefined;
1000 const statements = tree.blockStatements(&buf, node).?;
10061001 return blockExpr(gz, scope, ri, node, statements, .normal);
10071002 },
10081003 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {
1009 const str_index = try astgen.identAsString(main_tokens[node]);
1004 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
10101005 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{
10111006 .lhs = res_ty,
10121007 .field_name_start = str_index,
......@@ -1016,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10161011 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us
10171012 .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node),
10181013 }
1019 } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),
1020 .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value),
1014 } else return simpleStrTok(gz, ri, tree.nodeMainToken(node), node, .enum_literal),
1015 .error_value => return simpleStrTok(gz, ri, tree.nodeMainToken(node) + 2, node, .error_value),
10211016 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025
10221017 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),
10231018 .anyframe_literal => {
......@@ -1025,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10251020 return rvalue(gz, ri, result, node);
10261021 },
10271022 .anyframe_type => {
1028 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);
1023 const return_type = try typeExpr(gz, scope, tree.nodeData(node).token_and_node[1]);
10291024 const result = try gz.addUnNode(.anyframe_type, return_type, node);
10301025 return rvalue(gz, ri, result, node);
10311026 },
10321027 .@"catch" => {
1033 const catch_token = main_tokens[node];
1034 const payload_token: ?Ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)
1028 const catch_token = tree.nodeMainToken(node);
1029 const payload_token: ?Ast.TokenIndex = if (tree.tokenTag(catch_token + 1) == .pipe)
10351030 catch_token + 2
10361031 else
10371032 null;
10381033 no_switch_on_err: {
10391034 const capture_token = payload_token orelse break :no_switch_on_err;
1040 const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err;
1035 const full_switch = tree.fullSwitch(tree.nodeData(node).node_and_node[1]) orelse break :no_switch_on_err;
10411036 if (full_switch.label_token != null) break :no_switch_on_err;
1042 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;
1043 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err;
1037 if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err;
1038 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err;
10441039 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
10451040 }
10461041 switch (ri.rl) {
......@@ -1049,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10491044 scope,
10501045 ri,
10511046 node,
1052 node_datas[node].lhs,
10531047 .is_non_err_ptr,
10541048 .err_union_payload_unsafe_ptr,
10551049 .err_union_code_ptr,
1056 node_datas[node].rhs,
10571050 payload_token,
10581051 ),
10591052 else => return orelseCatchExpr(
......@@ -1061,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10611054 scope,
10621055 ri,
10631056 node,
1064 node_datas[node].lhs,
10651057 .is_non_err,
10661058 .err_union_payload_unsafe,
10671059 .err_union_code,
1068 node_datas[node].rhs,
10691060 payload_token,
10701061 ),
10711062 }
......@@ -1076,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10761067 scope,
10771068 ri,
10781069 node,
1079 node_datas[node].lhs,
10801070 .is_non_null_ptr,
10811071 .optional_payload_unsafe_ptr,
10821072 undefined,
1083 node_datas[node].rhs,
10841073 null,
10851074 ),
10861075 else => return orelseCatchExpr(
......@@ -1088,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10881077 scope,
10891078 ri,
10901079 node,
1091 node_datas[node].lhs,
10921080 .is_non_null,
10931081 .optional_payload_unsafe,
10941082 undefined,
1095 node_datas[node].rhs,
10961083 null,
10971084 ),
10981085 },
......@@ -1122,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11221109
11231110 .@"break" => return breakExpr(gz, scope, node),
11241111 .@"continue" => return continueExpr(gz, scope, node),
1125 .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs),
1112 .grouped_expression => return expr(gz, scope, ri, tree.nodeData(node).node_and_token[0]),
11261113 .array_type => return arrayType(gz, scope, ri, node),
11271114 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
11281115 .char_literal => return charLiteral(gz, ri, node),
......@@ -1136,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11361123 .@"await" => return awaitExpr(gz, scope, ri, node),
11371124 .@"resume" => return resumeExpr(gz, scope, ri, node),
11381125
1139 .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs),
1126 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
11401127
11411128 .array_init_one,
11421129 .array_init_one_comma,
......@@ -1183,16 +1170,14 @@ fn nosuspendExpr(
11831170) InnerError!Zir.Inst.Ref {
11841171 const astgen = gz.astgen;
11851172 const tree = astgen.tree;
1186 const node_datas = tree.nodes.items(.data);
1187 const body_node = node_datas[node].lhs;
1188 assert(body_node != 0);
1189 if (gz.nosuspend_node != 0) {
1173 const body_node = tree.nodeData(node).node;
1174 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
11901175 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{
1191 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),
1176 try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}),
11921177 });
11931178 }
1194 gz.nosuspend_node = node;
1195 defer gz.nosuspend_node = 0;
1179 gz.nosuspend_node = node.toOptional();
1180 defer gz.nosuspend_node = .none;
11961181 return expr(gz, scope, ri, body_node);
11971182}
11981183
......@@ -1204,26 +1189,24 @@ fn suspendExpr(
12041189 const astgen = gz.astgen;
12051190 const gpa = astgen.gpa;
12061191 const tree = astgen.tree;
1207 const node_datas = tree.nodes.items(.data);
1208 const body_node = node_datas[node].lhs;
1192 const body_node = tree.nodeData(node).node;
12091193
1210 if (gz.nosuspend_node != 0) {
1194 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
12111195 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{
1212 try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}),
1196 try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}),
12131197 });
12141198 }
1215 if (gz.suspend_node != 0) {
1199 if (gz.suspend_node.unwrap()) |suspend_node| {
12161200 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{
1217 try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}),
1201 try astgen.errNoteNode(suspend_node, "other suspend block here", .{}),
12181202 });
12191203 }
1220 assert(body_node != 0);
12211204
12221205 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);
12231206 try gz.instructions.append(gpa, suspend_inst);
12241207
12251208 var suspend_scope = gz.makeSubBlock(scope);
1226 suspend_scope.suspend_node = node;
1209 suspend_scope.suspend_node = node.toOptional();
12271210 defer suspend_scope.unstack();
12281211
12291212 const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal);
......@@ -1243,16 +1226,15 @@ fn awaitExpr(
12431226) InnerError!Zir.Inst.Ref {
12441227 const astgen = gz.astgen;
12451228 const tree = astgen.tree;
1246 const node_datas = tree.nodes.items(.data);
1247 const rhs_node = node_datas[node].lhs;
1229 const rhs_node = tree.nodeData(node).node;
12481230
1249 if (gz.suspend_node != 0) {
1231 if (gz.suspend_node.unwrap()) |suspend_node| {
12501232 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
1251 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
1233 try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
12521234 });
12531235 }
12541236 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1255 const result = if (gz.nosuspend_node != 0)
1237 const result = if (gz.nosuspend_node != .none)
12561238 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
12571239 .node = gz.nodeIndexToRelative(node),
12581240 .operand = operand,
......@@ -1271,8 +1253,7 @@ fn resumeExpr(
12711253) InnerError!Zir.Inst.Ref {
12721254 const astgen = gz.astgen;
12731255 const tree = astgen.tree;
1274 const node_datas = tree.nodes.items(.data);
1275 const rhs_node = node_datas[node].lhs;
1256 const rhs_node = tree.nodeData(node).node;
12761257 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
12771258 const result = try gz.addUnNode(.@"resume", operand, node);
12781259 return rvalue(gz, ri, result, node);
......@@ -1287,33 +1268,33 @@ fn fnProtoExpr(
12871268) InnerError!Zir.Inst.Ref {
12881269 const astgen = gz.astgen;
12891270 const tree = astgen.tree;
1290 const token_tags = tree.tokens.items(.tag);
12911271
12921272 if (fn_proto.name_token) |some| {
12931273 return astgen.failTok(some, "function type cannot have a name", .{});
12941274 }
12951275
1296 if (fn_proto.ast.align_expr != 0) {
1297 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});
1276 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1277 return astgen.failNode(align_expr, "function type cannot have an alignment", .{});
12981278 }
12991279
1300 if (fn_proto.ast.addrspace_expr != 0) {
1301 return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});
1280 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1281 return astgen.failNode(addrspace_expr, "function type cannot have an addrspace", .{});
13021282 }
13031283
1304 if (fn_proto.ast.section_expr != 0) {
1305 return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});
1284 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1285 return astgen.failNode(section_expr, "function type cannot have a linksection", .{});
13061286 }
13071287
1308 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1309 const is_inferred_error = token_tags[maybe_bang] == .bang;
1288 const return_type = fn_proto.ast.return_type.unwrap().?;
1289 const maybe_bang = tree.firstToken(return_type) - 1;
1290 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
13101291 if (is_inferred_error) {
13111292 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
13121293 }
13131294
13141295 const is_extern = blk: {
13151296 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
1316 break :blk token_tags[maybe_extern_token] == .keyword_extern;
1297 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
13171298 };
13181299 assert(!is_extern);
13191300
......@@ -1330,7 +1311,6 @@ fn fnProtoExprInner(
13301311) InnerError!Zir.Inst.Ref {
13311312 const astgen = gz.astgen;
13321313 const tree = astgen.tree;
1333 const token_tags = tree.tokens.items(.tag);
13341314
13351315 var block_scope = gz.makeSubBlock(scope);
13361316 defer block_scope.unstack();
......@@ -1342,7 +1322,7 @@ fn fnProtoExprInner(
13421322 var param_type_i: usize = 0;
13431323 var it = fn_proto.iterate(tree);
13441324 while (it.next()) |param| : (param_type_i += 1) {
1345 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
1325 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
13461326 .keyword_noalias => is_comptime: {
13471327 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
13481328 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
......@@ -1353,7 +1333,7 @@ fn fnProtoExprInner(
13531333 } else false;
13541334
13551335 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
1356 switch (token_tags[token]) {
1336 switch (tree.tokenTag(token)) {
13571337 .keyword_anytype => break :blk true,
13581338 .ellipsis3 => break :is_var_args true,
13591339 else => unreachable,
......@@ -1376,16 +1356,14 @@ fn fnProtoExprInner(
13761356 .param_anytype;
13771357 _ = try block_scope.addStrTok(tag, param_name, name_token);
13781358 } else {
1379 const param_type_node = param.type_expr;
1380 assert(param_type_node != 0);
1359 const param_type_node = param.type_expr.?;
13811360 var param_gz = block_scope.makeSubBlock(scope);
13821361 defer param_gz.unstack();
13831362 param_gz.is_comptime = true;
13841363 const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal);
13851364 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
13861365 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
1387 const main_tokens = tree.nodes.items(.main_token);
1388 const name_token = param.name_token orelse main_tokens[param_type_node];
1366 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
13891367 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
13901368 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous
13911369 // arguments (we haven't set up scopes here).
......@@ -1396,12 +1374,12 @@ fn fnProtoExprInner(
13961374 break :is_var_args false;
13971375 };
13981376
1399 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
1377 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr|
14001378 try comptimeExpr(
14011379 &block_scope,
14021380 scope,
1403 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
1404 fn_proto.ast.callconv_expr,
1381 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(callconv_expr, .calling_convention) } },
1382 callconv_expr,
14051383 .@"callconv",
14061384 )
14071385 else if (implicit_ccc)
......@@ -1409,7 +1387,8 @@ fn fnProtoExprInner(
14091387 else
14101388 .none;
14111389
1412 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty);
1390 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
1391 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty);
14131392
14141393 const result = try block_scope.addFunc(.{
14151394 .src_node = fn_proto.ast.proto_node,
......@@ -1449,33 +1428,32 @@ fn arrayInitExpr(
14491428) InnerError!Zir.Inst.Ref {
14501429 const astgen = gz.astgen;
14511430 const tree = astgen.tree;
1452 const node_tags = tree.nodes.items(.tag);
1453 const main_tokens = tree.nodes.items(.main_token);
14541431
14551432 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
14561433
14571434 const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: {
1458 if (array_init.ast.type_expr == 0) break :inst .{ .none, .none };
1435 const type_expr = array_init.ast.type_expr.unwrap() orelse break :inst .{ .none, .none };
14591436
14601437 infer: {
1461 const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer;
1438 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse break :infer;
14621439 // This intentionally does not support `@"_"` syntax.
1463 if (node_tags[array_type.ast.elem_count] == .identifier and
1464 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))
1440 if (tree.nodeTag(array_type.ast.elem_count) == .identifier and
1441 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_"))
14651442 {
14661443 const len_inst = try gz.addInt(array_init.ast.elements.len);
14671444 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1468 if (array_type.ast.sentinel == 0) {
1469 const array_type_inst = try gz.addPlNode(.array_type, array_init.ast.type_expr, Zir.Inst.Bin{
1445 if (array_type.ast.sentinel == .none) {
1446 const array_type_inst = try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{
14701447 .lhs = len_inst,
14711448 .rhs = elem_type,
14721449 });
14731450 break :inst .{ array_type_inst, elem_type };
14741451 } else {
1475 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
1452 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1453 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
14761454 const array_type_inst = try gz.addPlNode(
14771455 .array_type_sentinel,
1478 array_init.ast.type_expr,
1456 type_expr,
14791457 Zir.Inst.ArrayTypeSentinel{
14801458 .len = len_inst,
14811459 .elem_type = elem_type,
......@@ -1486,7 +1464,7 @@ fn arrayInitExpr(
14861464 }
14871465 }
14881466 }
1489 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1467 const array_type_inst = try typeExpr(gz, scope, type_expr);
14901468 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
14911469 .ty = array_type_inst,
14921470 .init_count = @intCast(array_init.ast.elements.len),
......@@ -1694,7 +1672,7 @@ fn structInitExpr(
16941672 const astgen = gz.astgen;
16951673 const tree = astgen.tree;
16961674
1697 if (struct_init.ast.type_expr == 0) {
1675 if (struct_init.ast.type_expr == .none) {
16981676 if (struct_init.ast.fields.len == 0) {
16991677 // Anonymous init with no fields.
17001678 switch (ri.rl) {
......@@ -1718,32 +1696,32 @@ fn structInitExpr(
17181696 }
17191697 }
17201698 } else array: {
1721 const node_tags = tree.nodes.items(.tag);
1722 const main_tokens = tree.nodes.items(.main_token);
1723 const array_type: Ast.full.ArrayType = tree.fullArrayType(struct_init.ast.type_expr) orelse {
1699 const type_expr = struct_init.ast.type_expr.unwrap().?;
1700 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse {
17241701 if (struct_init.ast.fields.len == 0) {
1725 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1702 const ty_inst = try typeExpr(gz, scope, type_expr);
17261703 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
17271704 return rvalue(gz, ri, result, node);
17281705 }
17291706 break :array;
17301707 };
1731 const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and
1708 const is_inferred_array_len = tree.nodeTag(array_type.ast.elem_count) == .identifier and
17321709 // This intentionally does not support `@"_"` syntax.
1733 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_");
1710 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_");
17341711 if (struct_init.ast.fields.len == 0) {
17351712 if (is_inferred_array_len) {
17361713 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1737 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {
1738 break :blk try gz.addPlNode(.array_type, struct_init.ast.type_expr, Zir.Inst.Bin{
1714 const array_type_inst = if (array_type.ast.sentinel == .none) blk: {
1715 break :blk try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{
17391716 .lhs = .zero_usize,
17401717 .rhs = elem_type,
17411718 });
17421719 } else blk: {
1743 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
1720 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1721 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
17441722 break :blk try gz.addPlNode(
17451723 .array_type_sentinel,
1746 struct_init.ast.type_expr,
1724 type_expr,
17471725 Zir.Inst.ArrayTypeSentinel{
17481726 .len = .zero_usize,
17491727 .elem_type = elem_type,
......@@ -1754,12 +1732,12 @@ fn structInitExpr(
17541732 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
17551733 return rvalue(gz, ri, result, node);
17561734 }
1757 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1735 const ty_inst = try typeExpr(gz, scope, type_expr);
17581736 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
17591737 return rvalue(gz, ri, result, node);
17601738 } else {
17611739 return astgen.failNode(
1762 struct_init.ast.type_expr,
1740 type_expr,
17631741 "initializing array with struct syntax",
17641742 .{},
17651743 );
......@@ -1818,9 +1796,9 @@ fn structInitExpr(
18181796 }
18191797 }
18201798
1821 if (struct_init.ast.type_expr != 0) {
1799 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
18221800 // Typed inits do not use RLS for language simplicity.
1823 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1801 const ty_inst = try typeExpr(gz, scope, type_expr);
18241802 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
18251803 switch (ri.rl) {
18261804 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),
......@@ -2009,9 +1987,7 @@ fn comptimeExpr2(
20091987 // no need to wrap it in a block. This is hard to determine in general, but we can identify a
20101988 // common subset of trivially comptime expressions to take down the size of the ZIR a bit.
20111989 const tree = gz.astgen.tree;
2012 const main_tokens = tree.nodes.items(.main_token);
2013 const node_tags = tree.nodes.items(.tag);
2014 switch (node_tags[node]) {
1990 switch (tree.nodeTag(node)) {
20151991 .identifier => {
20161992 // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has
20171993 // special handling for this case.
......@@ -2064,8 +2040,7 @@ fn comptimeExpr2(
20642040 // comptime block, because that would be silly! Note that we don't bother doing this for
20652041 // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`).
20662042 .block_two, .block_two_semicolon, .block, .block_semicolon => {
2067 const token_tags = tree.tokens.items(.tag);
2068 const lbrace = main_tokens[node];
2043 const lbrace = tree.nodeMainToken(node);
20692044 // Careful! We can't pass in the real result location here, since it may
20702045 // refer to runtime memory. A runtime-to-comptime boundary has to remove
20712046 // result location information, compute the result, and copy it to the true
......@@ -2077,31 +2052,13 @@ fn comptimeExpr2(
20772052 else
20782053 .none,
20792054 };
2080 if (token_tags[lbrace - 1] == .colon and
2081 token_tags[lbrace - 2] == .identifier)
2082 {
2083 const node_datas = tree.nodes.items(.data);
2084 switch (node_tags[node]) {
2085 .block_two, .block_two_semicolon => {
2086 const stmts: [2]Ast.Node.Index = .{ node_datas[node].lhs, node_datas[node].rhs };
2087 const stmt_slice = if (stmts[0] == 0)
2088 stmts[0..0]
2089 else if (stmts[1] == 0)
2090 stmts[0..1]
2091 else
2092 stmts[0..2];
2055 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2056 var buf: [2]Ast.Node.Index = undefined;
2057 const stmts = tree.blockStatements(&buf, node).?;
20932058
2094 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmt_slice, true, .normal);
2095 return rvalue(gz, ri, block_ref, node);
2096 },
2097 .block, .block_semicolon => {
2098 const stmts = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
2099 // Replace result location and copy back later - see above.
2100 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
2101 return rvalue(gz, ri, block_ref, node);
2102 },
2103 else => unreachable,
2104 }
2059 // Replace result location and copy back later - see above.
2060 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
2061 return rvalue(gz, ri, block_ref, node);
21052062 }
21062063 },
21072064
......@@ -2146,8 +2103,7 @@ fn comptimeExprAst(
21462103 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});
21472104 }
21482105 const tree = astgen.tree;
2149 const node_datas = tree.nodes.items(.data);
2150 const body_node = node_datas[node].lhs;
2106 const body_node = tree.nodeData(node).node;
21512107 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
21522108}
21532109
......@@ -2185,9 +2141,7 @@ fn restoreErrRetIndex(
21852141fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
21862142 const astgen = parent_gz.astgen;
21872143 const tree = astgen.tree;
2188 const node_datas = tree.nodes.items(.data);
2189 const break_label = node_datas[node].lhs;
2190 const rhs = node_datas[node].rhs;
2144 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
21912145
21922146 // Look for the label in the scope.
21932147 var scope = parent_scope;
......@@ -2196,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
21962150 .gen_zir => {
21972151 const block_gz = scope.cast(GenZir).?;
21982152
2199 if (block_gz.cur_defer_node != 0) {
2153 if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| {
22002154 // We are breaking out of a `defer` block.
22012155 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
22022156 try astgen.errNoteNode(
2203 block_gz.cur_defer_node,
2157 cur_defer_node,
22042158 "defer expression here",
22052159 .{},
22062160 ),
......@@ -2208,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22082162 }
22092163
22102164 const block_inst = blk: {
2211 if (break_label != 0) {
2165 if (opt_break_label.unwrap()) |break_label| {
22122166 if (block_gz.label) |*label| {
22132167 if (try astgen.tokenIdentEql(label.token, break_label)) {
22142168 label.used = true;
......@@ -2229,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22292183 else
22302184 .@"break";
22312185
2232 if (rhs == 0) {
2186 const rhs = opt_rhs.unwrap() orelse {
22332187 _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node);
22342188
22352189 try genDefers(parent_gz, scope, parent_scope, .normal_only);
......@@ -2240,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22402194
22412195 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
22422196 return Zir.Inst.Ref.unreachable_value;
2243 }
2197 };
22442198
22452199 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node);
22462200
......@@ -2272,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22722226 .top => unreachable,
22732227 }
22742228 }
2275 if (break_label != 0) {
2229 if (opt_break_label.unwrap()) |break_label| {
22762230 const label_name = try astgen.identifierTokenString(break_label);
22772231 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
22782232 } else {
......@@ -2283,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22832237fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
22842238 const astgen = parent_gz.astgen;
22852239 const tree = astgen.tree;
2286 const node_datas = tree.nodes.items(.data);
2287 const break_label = node_datas[node].lhs;
2288 const rhs = node_datas[node].rhs;
2240 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
22892241
2290 if (break_label == 0 and rhs != 0) {
2242 if (opt_break_label == .none and opt_rhs != .none) {
22912243 return astgen.failNode(node, "cannot continue with operand without label", .{});
22922244 }
22932245
......@@ -2298,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
22982250 .gen_zir => {
22992251 const gen_zir = scope.cast(GenZir).?;
23002252
2301 if (gen_zir.cur_defer_node != 0) {
2253 if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| {
23022254 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{
23032255 try astgen.errNoteNode(
2304 gen_zir.cur_defer_node,
2256 cur_defer_node,
23052257 "defer expression here",
23062258 .{},
23072259 ),
......@@ -2311,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
23112263 scope = gen_zir.parent;
23122264 continue;
23132265 };
2314 if (break_label != 0) blk: {
2266 if (opt_break_label.unwrap()) |break_label| blk: {
23152267 if (gen_zir.label) |*label| {
23162268 if (try astgen.tokenIdentEql(label.token, break_label)) {
23172269 const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)];
2318 if (rhs != 0) switch (maybe_switch_tag) {
2270 if (opt_rhs != .none) switch (maybe_switch_tag) {
23192271 .switch_block, .switch_block_ref => {},
23202272 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),
23212273 } else switch (maybe_switch_tag) {
......@@ -2343,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
23432295 }
23442296 }
23452297
2346 if (rhs != 0) {
2298 if (opt_rhs.unwrap()) |rhs| {
23472299 // We need to figure out the result info to use.
23482300 // The type should match
23492301 const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node);
......@@ -2382,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
23822334 .top => unreachable,
23832335 }
23842336 }
2385 if (break_label != 0) {
2337 if (opt_break_label.unwrap()) |break_label| {
23862338 const label_name = try astgen.identifierTokenString(break_label);
23872339 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
23882340 } else {
......@@ -2402,30 +2354,14 @@ fn fullBodyExpr(
24022354 block_kind: BlockKind,
24032355) InnerError!Zir.Inst.Ref {
24042356 const tree = gz.astgen.tree;
2405 const node_tags = tree.nodes.items(.tag);
2406 const node_datas = tree.nodes.items(.data);
2407 const main_tokens = tree.nodes.items(.main_token);
2408 const token_tags = tree.tokens.items(.tag);
2357
24092358 var stmt_buf: [2]Ast.Node.Index = undefined;
2410 const statements: []const Ast.Node.Index = switch (node_tags[node]) {
2411 else => return expr(gz, scope, ri, node),
2412 .block_two, .block_two_semicolon => if (node_datas[node].lhs == 0) s: {
2413 break :s &.{};
2414 } else if (node_datas[node].rhs == 0) s: {
2415 stmt_buf[0] = node_datas[node].lhs;
2416 break :s stmt_buf[0..1];
2417 } else s: {
2418 stmt_buf[0] = node_datas[node].lhs;
2419 stmt_buf[1] = node_datas[node].rhs;
2420 break :s stmt_buf[0..2];
2421 },
2422 .block, .block_semicolon => tree.extra_data[node_datas[node].lhs..node_datas[node].rhs],
2423 };
2359 const statements = tree.blockStatements(&stmt_buf, node) orelse
2360 return expr(gz, scope, ri, node);
24242361
2425 const lbrace = main_tokens[node];
2426 if (token_tags[lbrace - 1] == .colon and
2427 token_tags[lbrace - 2] == .identifier)
2428 {
2362 const lbrace = tree.nodeMainToken(node);
2363
2364 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
24292365 // Labeled blocks are tricky - forwarding result location information properly is non-trivial,
24302366 // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This
24312367 // case is rare, so just treat it as a normal expression and create a nested block.
......@@ -2450,13 +2386,9 @@ fn blockExpr(
24502386) InnerError!Zir.Inst.Ref {
24512387 const astgen = gz.astgen;
24522388 const tree = astgen.tree;
2453 const main_tokens = tree.nodes.items(.main_token);
2454 const token_tags = tree.tokens.items(.tag);
24552389
2456 const lbrace = main_tokens[block_node];
2457 if (token_tags[lbrace - 1] == .colon and
2458 token_tags[lbrace - 2] == .identifier)
2459 {
2390 const lbrace = tree.nodeMainToken(block_node);
2391 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
24602392 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);
24612393 }
24622394
......@@ -2533,12 +2465,10 @@ fn labeledBlockExpr(
25332465) InnerError!Zir.Inst.Ref {
25342466 const astgen = gz.astgen;
25352467 const tree = astgen.tree;
2536 const main_tokens = tree.nodes.items(.main_token);
2537 const token_tags = tree.tokens.items(.tag);
25382468
2539 const lbrace = main_tokens[block_node];
2469 const lbrace = tree.nodeMainToken(block_node);
25402470 const label_token = lbrace - 2;
2541 assert(token_tags[label_token] == .identifier);
2471 assert(tree.tokenTag(label_token) == .identifier);
25422472
25432473 try astgen.checkLabelRedefinition(parent_scope, label_token);
25442474
......@@ -2599,8 +2529,6 @@ fn labeledBlockExpr(
25992529fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void {
26002530 const astgen = gz.astgen;
26012531 const tree = astgen.tree;
2602 const node_tags = tree.nodes.items(.tag);
2603 const node_data = tree.nodes.items(.data);
26042532
26052533 if (statements.len == 0) return;
26062534
......@@ -2608,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26082536 defer block_arena.deinit();
26092537 const block_arena_allocator = block_arena.allocator();
26102538
2611 var noreturn_src_node: Ast.Node.Index = 0;
2539 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
26122540 var scope = parent_scope;
26132541 for (statements, 0..) |statement, stmt_idx| {
2614 if (noreturn_src_node != 0) {
2542 if (noreturn_src_node.unwrap()) |src_node| {
26152543 try astgen.appendErrorNodeNotes(
26162544 statement,
26172545 "unreachable code",
26182546 .{},
26192547 &[_]u32{
26202548 try astgen.errNoteNode(
2621 noreturn_src_node,
2549 src_node,
26222550 "control flow is diverted here",
26232551 .{},
26242552 ),
......@@ -2631,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26312559 };
26322560 var inner_node = statement;
26332561 while (true) {
2634 switch (node_tags[inner_node]) {
2562 switch (tree.nodeTag(inner_node)) {
26352563 // zig fmt: off
26362564 .global_var_decl,
26372565 .local_var_decl,
......@@ -2661,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26612589 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
26622590
26632591 .grouped_expression => {
2664 inner_node = node_data[statement].lhs;
2592 inner_node = tree.nodeData(statement).node_and_token[0];
26652593 continue;
26662594 },
26672595
......@@ -2671,47 +2599,37 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26712599
26722600 .for_simple,
26732601 .@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true),
2602 // zig fmt: on
26742603
26752604 // These cases are here to allow branch hints.
2676 .builtin_call_two, .builtin_call_two_comma => {
2677 try emitDbgNode(gz, inner_node);
2678 const ri: ResultInfo = .{ .rl = .none };
2679 const result = if (node_data[inner_node].lhs == 0) r: {
2680 break :r try builtinCall(gz, scope, ri, inner_node, &.{}, allow_branch_hint);
2681 } else if (node_data[inner_node].rhs == 0) r: {
2682 break :r try builtinCall(gz, scope, ri, inner_node, &.{node_data[inner_node].lhs}, allow_branch_hint);
2683 } else r: {
2684 break :r try builtinCall(gz, scope, ri, inner_node, &.{
2685 node_data[inner_node].lhs,
2686 node_data[inner_node].rhs,
2687 }, allow_branch_hint);
2688 };
2689 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
2690 },
2691 .builtin_call, .builtin_call_comma => {
2605 .builtin_call_two,
2606 .builtin_call_two_comma,
2607 .builtin_call,
2608 .builtin_call_comma,
2609 => {
2610 var buf: [2]Ast.Node.Index = undefined;
2611 const params = tree.builtinCallParams(&buf, inner_node).?;
2612
26922613 try emitDbgNode(gz, inner_node);
2693 const ri: ResultInfo = .{ .rl = .none };
2694 const params = tree.extra_data[node_data[inner_node].lhs..node_data[inner_node].rhs];
2695 const result = try builtinCall(gz, scope, ri, inner_node, params, allow_branch_hint);
2614 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint);
26962615 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
26972616 },
26982617
26992618 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
2700 // zig fmt: on
27012619 }
27022620 break;
27032621 }
27042622 }
27052623
2706 if (noreturn_src_node == 0) {
2624 if (noreturn_src_node == .none) {
27072625 try genDefers(gz, parent_scope, scope, .normal_only);
27082626 }
27092627 try checkUsed(gz, parent_scope, scope);
27102628}
27112629
27122630/// Returns AST source node of the thing that is noreturn if the statement is
2713/// definitely `noreturn`. Otherwise returns 0.
2714fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index {
2631/// definitely `noreturn`. Otherwise returns .none.
2632fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex {
27152633 try emitDbgNode(gz, statement);
27162634 // We need to emit an error if the result is not `noreturn` or `void`, but
27172635 // we want to avoid adding the ZIR instruction if possible for performance.
......@@ -2719,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
27192637 return addEnsureResult(gz, maybe_unused_result, statement);
27202638}
27212639
2722fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index {
2723 var noreturn_src_node: Ast.Node.Index = 0;
2640fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex {
2641 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
27242642 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {
27252643 // Note that this array becomes invalid after appending more items to it
27262644 // in the above while loop.
......@@ -2981,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29812899 .check_comptime_control_flow,
29822900 .switch_continue,
29832901 => {
2984 noreturn_src_node = statement;
2902 noreturn_src_node = statement.toOptional();
29852903 break :b true;
29862904 },
29872905
......@@ -3023,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
30232941 .none => unreachable,
30242942
30252943 .unreachable_value => b: {
3026 noreturn_src_node = statement;
2944 noreturn_src_node = statement.toOptional();
30272945 break :b true;
30282946 },
30292947
......@@ -3152,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
31523070 .gen_zir => scope = scope.cast(GenZir).?.parent,
31533071 .local_val => {
31543072 const s = scope.cast(Scope.LocalVal).?;
3155 if (s.used == 0 and s.discarded == 0) {
3073 if (s.used == .none and s.discarded == .none) {
31563074 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
3157 } else if (s.used != 0 and s.discarded != 0) {
3158 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3159 try gz.astgen.errNoteTok(s.used, "used here", .{}),
3075 } else if (s.used != .none and s.discarded != .none) {
3076 try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3077 try gz.astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
31603078 });
31613079 }
31623080 scope = s.parent;
31633081 },
31643082 .local_ptr => {
31653083 const s = scope.cast(Scope.LocalPtr).?;
3166 if (s.used == 0 and s.discarded == 0) {
3084 if (s.used == .none and s.discarded == .none) {
31673085 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
31683086 } else {
3169 if (s.used != 0 and s.discarded != 0) {
3170 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3171 try astgen.errNoteTok(s.used, "used here", .{}),
3087 if (s.used != .none and s.discarded != .none) {
3088 try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3089 try astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
31723090 });
31733091 }
31743092 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {
......@@ -3195,19 +3113,15 @@ fn deferStmt(
31953113 scope_tag: Scope.Tag,
31963114) InnerError!*Scope {
31973115 var defer_gen = gz.makeSubBlock(scope);
3198 defer_gen.cur_defer_node = node;
3199 defer_gen.any_defer_node = node;
3116 defer_gen.cur_defer_node = node.toOptional();
3117 defer_gen.any_defer_node = node.toOptional();
32003118 defer defer_gen.unstack();
32013119
32023120 const tree = gz.astgen.tree;
3203 const node_datas = tree.nodes.items(.data);
3204 const expr_node = node_datas[node].rhs;
3205
3206 const payload_token = node_datas[node].lhs;
32073121 var local_val_scope: Scope.LocalVal = undefined;
32083122 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3209 const have_err_code = scope_tag == .defer_error and payload_token != 0;
3210 const sub_scope = if (!have_err_code) &defer_gen.base else blk: {
3123 const sub_scope = if (scope_tag != .defer_error) &defer_gen.base else blk: {
3124 const payload_token = tree.nodeData(node).opt_token_and_node[0].unwrap() orelse break :blk &defer_gen.base;
32113125 const ident_name = try gz.astgen.identAsString(payload_token);
32123126 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {
32133127 try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{});
......@@ -3235,6 +3149,11 @@ fn deferStmt(
32353149 try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref);
32363150 break :blk &local_val_scope.base;
32373151 };
3152 const expr_node = switch (scope_tag) {
3153 .defer_normal => tree.nodeData(node).node,
3154 .defer_error => tree.nodeData(node).opt_token_and_node[1],
3155 else => unreachable,
3156 };
32383157 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
32393158 try checkUsed(gz, scope, sub_scope);
32403159 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
......@@ -3269,8 +3188,6 @@ fn varDecl(
32693188 try emitDbgNode(gz, node);
32703189 const astgen = gz.astgen;
32713190 const tree = astgen.tree;
3272 const token_tags = tree.tokens.items(.tag);
3273 const main_tokens = tree.nodes.items(.main_token);
32743191
32753192 const name_token = var_decl.ast.mut_token + 1;
32763193 const ident_name_raw = tree.tokenSlice(name_token);
......@@ -3284,27 +3201,27 @@ fn varDecl(
32843201 ident_name,
32853202 name_token,
32863203 ident_name_raw,
3287 if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable",
3204 if (tree.tokenTag(var_decl.ast.mut_token) == .keyword_const) .@"local constant" else .@"local variable",
32883205 );
32893206
3290 if (var_decl.ast.init_node == 0) {
3207 const init_node = var_decl.ast.init_node.unwrap() orelse {
32913208 return astgen.failNode(node, "variables must be initialized", .{});
3292 }
3209 };
32933210
3294 if (var_decl.ast.addrspace_node != 0) {
3295 return astgen.failTok(main_tokens[var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw});
3211 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3212 return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw});
32963213 }
32973214
3298 if (var_decl.ast.section_node != 0) {
3299 return astgen.failTok(main_tokens[var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw});
3215 if (var_decl.ast.section_node.unwrap()) |section_node| {
3216 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});
33003217 }
33013218
3302 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)
3303 try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node)
3219 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node|
3220 try expr(gz, scope, coerced_align_ri, align_node)
33043221 else
33053222 .none;
33063223
3307 switch (token_tags[var_decl.ast.mut_token]) {
3224 switch (tree.tokenTag(var_decl.ast.mut_token)) {
33083225 .keyword_const => {
33093226 if (var_decl.comptime_token) |comptime_token| {
33103227 try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
......@@ -3316,25 +3233,24 @@ fn varDecl(
33163233 // Depending on the type of AST the initialization expression is, we may need an lvalue
33173234 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
33183235 // the variable, no memory location needed.
3319 const type_node = var_decl.ast.type_node;
33203236 if (align_inst == .none and
33213237 !astgen.nodes_need_rl.contains(node))
33223238 {
3323 const result_info: ResultInfo = if (type_node != 0) .{
3239 const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{
33243240 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
33253241 .ctx = .const_init,
33263242 } else .{ .rl = .none, .ctx = .const_init };
33273243 const prev_anon_name_strategy = gz.anon_name_strategy;
33283244 gz.anon_name_strategy = .dbg_var;
3329 const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
3245 const init_inst = try reachableExprComptime(gz, scope, result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
33303246 gz.anon_name_strategy = prev_anon_name_strategy;
33313247
3332 _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node);
3248 _ = try gz.addUnNode(.validate_const, init_inst, init_node);
33333249 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
33343250
33353251 // The const init expression may have modified the error return trace, so signal
33363252 // to Sema that it should save the new index for restoring later.
3337 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
3253 if (nodeMayAppendToErrorTrace(tree, init_node))
33383254 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
33393255
33403256 const sub_scope = try block_arena.create(Scope.LocalVal);
......@@ -3350,9 +3266,9 @@ fn varDecl(
33503266 }
33513267
33523268 const is_comptime = gz.is_comptime or
3353 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";
3269 tree.nodeTag(init_node) == .@"comptime";
33543270
3355 const init_rl: ResultInfo.Loc = if (type_node != 0) init_rl: {
3271 const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: {
33563272 const type_inst = try typeExpr(gz, scope, type_node);
33573273 if (align_inst == .none) {
33583274 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };
......@@ -3393,11 +3309,11 @@ fn varDecl(
33933309 const prev_anon_name_strategy = gz.anon_name_strategy;
33943310 gz.anon_name_strategy = .dbg_var;
33953311 defer gz.anon_name_strategy = prev_anon_name_strategy;
3396 const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
3312 const init_inst = try reachableExprComptime(gz, scope, init_result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
33973313
33983314 // The const init expression may have modified the error return trace, so signal
33993315 // to Sema that it should save the new index for restoring later.
3400 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
3316 if (nodeMayAppendToErrorTrace(tree, init_node))
34013317 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
34023318
34033319 const const_ptr = if (resolve_inferred)
......@@ -3423,8 +3339,8 @@ fn varDecl(
34233339 if (var_decl.comptime_token != null and gz.is_comptime)
34243340 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});
34253341 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
3426 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: {
3427 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
3342 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| a: {
3343 const type_inst = try typeExpr(gz, scope, type_node);
34283344 const alloc = alloc: {
34293345 if (align_inst == .none) {
34303346 const tag: Zir.Inst.Tag = if (is_comptime)
......@@ -3469,7 +3385,7 @@ fn varDecl(
34693385 gz,
34703386 scope,
34713387 result_info,
3472 var_decl.ast.init_node,
3388 init_node,
34733389 node,
34743390 if (var_decl.comptime_token != null) .comptime_keyword else null,
34753391 );
......@@ -3512,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
35123428 try emitDbgNode(gz, infix_node);
35133429 const astgen = gz.astgen;
35143430 const tree = astgen.tree;
3515 const node_datas = tree.nodes.items(.data);
3516 const main_tokens = tree.nodes.items(.main_token);
3517 const node_tags = tree.nodes.items(.tag);
35183431
3519 const lhs = node_datas[infix_node].lhs;
3520 const rhs = node_datas[infix_node].rhs;
3521 if (node_tags[lhs] == .identifier) {
3432 const lhs, const rhs = tree.nodeData(infix_node).node_and_node;
3433 if (tree.nodeTag(lhs) == .identifier) {
35223434 // This intentionally does not support `@"_"` syntax.
3523 const ident_name = tree.tokenSlice(main_tokens[lhs]);
3435 const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs));
35243436 if (mem.eql(u8, ident_name, "_")) {
35253437 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
35263438 return;
......@@ -3538,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
35383450 try emitDbgNode(gz, node);
35393451 const astgen = gz.astgen;
35403452 const tree = astgen.tree;
3541 const main_tokens = tree.nodes.items(.main_token);
3542 const node_tags = tree.nodes.items(.tag);
35433453
35443454 const full = tree.assignDestructure(node);
35453455 if (full.comptime_token != null and gz.is_comptime) {
......@@ -3557,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
35573467
35583468 const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len);
35593469 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3560 if (node_tags[variable_node] == .identifier) {
3470 if (tree.nodeTag(variable_node) == .identifier) {
35613471 // This intentionally does not support `@"_"` syntax.
3562 const ident_name = tree.tokenSlice(main_tokens[variable_node]);
3472 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
35633473 if (mem.eql(u8, ident_name, "_")) {
35643474 variable_rl.* = .discard;
35653475 continue;
......@@ -3596,9 +3506,6 @@ fn assignDestructureMaybeDecls(
35963506 try emitDbgNode(gz, node);
35973507 const astgen = gz.astgen;
35983508 const tree = astgen.tree;
3599 const token_tags = tree.tokens.items(.tag);
3600 const main_tokens = tree.nodes.items(.main_token);
3601 const node_tags = tree.nodes.items(.tag);
36023509
36033510 const full = tree.assignDestructure(node);
36043511 if (full.comptime_token != null and gz.is_comptime) {
......@@ -3606,7 +3513,7 @@ fn assignDestructureMaybeDecls(
36063513 }
36073514
36083515 const is_comptime = full.comptime_token != null or gz.is_comptime;
3609 const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime";
3516 const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime";
36103517
36113518 // When declaring consts via a destructure, we always use a result pointer.
36123519 // This avoids the need to create tuple types, and is also likely easier to
......@@ -3619,10 +3526,10 @@ fn assignDestructureMaybeDecls(
36193526 var any_non_const_variables = false;
36203527 var any_lvalue_expr = false;
36213528 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3622 switch (node_tags[variable_node]) {
3529 switch (tree.nodeTag(variable_node)) {
36233530 .identifier => {
36243531 // This intentionally does not support `@"_"` syntax.
3625 const ident_name = tree.tokenSlice(main_tokens[variable_node]);
3532 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
36263533 if (mem.eql(u8, ident_name, "_")) {
36273534 any_non_const_variables = true;
36283535 variable_rl.* = .discard;
......@@ -3640,14 +3547,14 @@ fn assignDestructureMaybeDecls(
36403547
36413548 // We detect shadowing in the second pass over these, while we're creating scopes.
36423549
3643 if (full_var_decl.ast.addrspace_node != 0) {
3644 return astgen.failTok(main_tokens[full_var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw});
3550 if (full_var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3551 return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw});
36453552 }
3646 if (full_var_decl.ast.section_node != 0) {
3647 return astgen.failTok(main_tokens[full_var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw});
3553 if (full_var_decl.ast.section_node.unwrap()) |section_node| {
3554 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});
36483555 }
36493556
3650 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {
3557 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
36513558 .keyword_var => false,
36523559 .keyword_const => true,
36533560 else => unreachable,
......@@ -3657,14 +3564,14 @@ fn assignDestructureMaybeDecls(
36573564 // We also mark `const`s as comptime if the RHS is definitely comptime-known.
36583565 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);
36593566
3660 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node != 0)
3661 try expr(gz, scope, coerced_align_ri, full_var_decl.ast.align_node)
3567 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node|
3568 try expr(gz, scope, coerced_align_ri, align_node)
36623569 else
36633570 .none;
36643571
3665 if (full_var_decl.ast.type_node != 0) {
3572 if (full_var_decl.ast.type_node.unwrap()) |type_node| {
36663573 // Typed alloc
3667 const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node);
3574 const type_inst = try typeExpr(gz, scope, type_node);
36683575 const ptr = if (align_inst == .none) ptr: {
36693576 const tag: Zir.Inst.Tag = if (is_const)
36703577 .alloc
......@@ -3733,7 +3640,7 @@ fn assignDestructureMaybeDecls(
37333640 // evaluate the lvalues from within the possible block_comptime.
37343641 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
37353642 if (variable_rl.* != .typed_ptr) continue;
3736 switch (node_tags[variable_node]) {
3643 switch (tree.nodeTag(variable_node)) {
37373644 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue,
37383645 else => {},
37393646 }
......@@ -3762,7 +3669,7 @@ fn assignDestructureMaybeDecls(
37623669 // If there were any `const` decls, make the pointer constant.
37633670 var cur_scope = scope;
37643671 for (rl_components, full.ast.variables) |variable_rl, variable_node| {
3765 switch (node_tags[variable_node]) {
3672 switch (tree.nodeTag(variable_node)) {
37663673 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},
37673674 else => continue, // We were mutating an existing lvalue - nothing to do
37683675 }
......@@ -3772,7 +3679,7 @@ fn assignDestructureMaybeDecls(
37723679 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },
37733680 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },
37743681 };
3775 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {
3682 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
37763683 .keyword_var => false,
37773684 .keyword_const => true,
37783685 else => unreachable,
......@@ -3823,9 +3730,9 @@ fn assignOp(
38233730 try emitDbgNode(gz, infix_node);
38243731 const astgen = gz.astgen;
38253732 const tree = astgen.tree;
3826 const node_datas = tree.nodes.items(.data);
38273733
3828 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3734 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3735 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
38293736
38303737 const cursor = switch (op_inst_tag) {
38313738 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
......@@ -3851,7 +3758,7 @@ fn assignOp(
38513758 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type
38523759 };
38533760 // Not `coerced_ty` since `add`/etc won't coerce to this type.
3854 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, node_datas[infix_node].rhs);
3761 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, rhs_node);
38553762
38563763 switch (op_inst_tag) {
38573764 .add, .sub, .mul, .div, .mod_rem => {
......@@ -3878,12 +3785,12 @@ fn assignShift(
38783785 try emitDbgNode(gz, infix_node);
38793786 const astgen = gz.astgen;
38803787 const tree = astgen.tree;
3881 const node_datas = tree.nodes.items(.data);
38823788
3883 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3789 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3790 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
38843791 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
38853792 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);
3886 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs);
3793 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, rhs_node);
38873794
38883795 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
38893796 .lhs = lhs,
......@@ -3899,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
38993806 try emitDbgNode(gz, infix_node);
39003807 const astgen = gz.astgen;
39013808 const tree = astgen.tree;
3902 const node_datas = tree.nodes.items(.data);
39033809
3904 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
3810 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3811 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
39053812 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
39063813 // Saturating shift-left allows any integer type for both the LHS and RHS.
3907 const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs);
3814 const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node);
39083815
39093816 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{
39103817 .lhs = lhs,
......@@ -3939,7 +3846,7 @@ fn ptrType(
39393846 var bit_end_ref: Zir.Inst.Ref = .none;
39403847 var trailing_count: u32 = 0;
39413848
3942 if (ptr_info.ast.sentinel != 0) {
3849 if (ptr_info.ast.sentinel.unwrap()) |sentinel| {
39433850 // These attributes can appear in any order and they all come before the
39443851 // element type so we need to reset the source cursor before generating them.
39453852 gz.astgen.source_offset = source_offset;
......@@ -3950,7 +3857,7 @@ fn ptrType(
39503857 gz,
39513858 scope,
39523859 .{ .rl = .{ .ty = elem_type } },
3953 ptr_info.ast.sentinel,
3860 sentinel,
39543861 switch (ptr_info.size) {
39553862 .slice => .slice_sentinel,
39563863 else => .pointer_sentinel,
......@@ -3958,27 +3865,27 @@ fn ptrType(
39583865 );
39593866 trailing_count += 1;
39603867 }
3961 if (ptr_info.ast.addrspace_node != 0) {
3868 if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| {
39623869 gz.astgen.source_offset = source_offset;
39633870 gz.astgen.source_line = source_line;
39643871 gz.astgen.source_column = source_column;
39653872
3966 const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space);
3967 addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node, .@"addrspace");
3873 const addrspace_ty = try gz.addBuiltinValue(addrspace_node, .address_space);
3874 addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node, .@"addrspace");
39683875 trailing_count += 1;
39693876 }
3970 if (ptr_info.ast.align_node != 0) {
3877 if (ptr_info.ast.align_node.unwrap()) |align_node| {
39713878 gz.astgen.source_offset = source_offset;
39723879 gz.astgen.source_line = source_line;
39733880 gz.astgen.source_column = source_column;
39743881
3975 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align");
3882 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align");
39763883 trailing_count += 1;
39773884 }
3978 if (ptr_info.ast.bit_range_start != 0) {
3979 assert(ptr_info.ast.bit_range_end != 0);
3980 bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type);
3981 bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end, .type);
3885 if (ptr_info.ast.bit_range_start.unwrap()) |bit_range_start| {
3886 const bit_range_end = ptr_info.ast.bit_range_end.unwrap().?;
3887 bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_start, .type);
3888 bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_end, .type);
39823889 trailing_count += 2;
39833890 }
39843891
......@@ -4031,18 +3938,15 @@ fn ptrType(
40313938fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
40323939 const astgen = gz.astgen;
40333940 const tree = astgen.tree;
4034 const node_datas = tree.nodes.items(.data);
4035 const node_tags = tree.nodes.items(.tag);
4036 const main_tokens = tree.nodes.items(.main_token);
40373941
4038 const len_node = node_datas[node].lhs;
4039 if (node_tags[len_node] == .identifier and
4040 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
3942 const len_node, const elem_type_node = tree.nodeData(node).node_and_node;
3943 if (tree.nodeTag(len_node) == .identifier and
3944 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
40413945 {
40423946 return astgen.failNode(len_node, "unable to infer array size", .{});
40433947 }
40443948 const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);
4045 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
3949 const elem_type = try typeExpr(gz, scope, elem_type_node);
40463950
40473951 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
40483952 .lhs = len,
......@@ -4054,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
40543958fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
40553959 const astgen = gz.astgen;
40563960 const tree = astgen.tree;
4057 const node_datas = tree.nodes.items(.data);
4058 const node_tags = tree.nodes.items(.tag);
4059 const main_tokens = tree.nodes.items(.main_token);
4060 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
4061
4062 const len_node = node_datas[node].lhs;
4063 if (node_tags[len_node] == .identifier and
4064 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
3961
3962 const len_node, const extra_index = tree.nodeData(node).node_and_extra;
3963 const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
3964
3965 if (tree.nodeTag(len_node) == .identifier and
3966 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
40653967 {
40663968 return astgen.failNode(len_node, "unable to infer array size", .{});
40673969 }
......@@ -4161,11 +4063,10 @@ fn fnDecl(
41614063 scope: *Scope,
41624064 wip_members: *WipMembers,
41634065 decl_node: Ast.Node.Index,
4164 body_node: Ast.Node.Index,
4066 body_node: Ast.Node.OptionalIndex,
41654067 fn_proto: Ast.full.FnProto,
41664068) InnerError!void {
41674069 const tree = astgen.tree;
4168 const token_tags = tree.tokens.items(.tag);
41694070
41704071 const old_hasher = astgen.src_hasher;
41714072 defer astgen.src_hasher = old_hasher;
......@@ -4194,15 +4095,15 @@ fn fnDecl(
41944095 const is_pub = fn_proto.visib_token != null;
41954096 const is_export = blk: {
41964097 const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
4197 break :blk token_tags[maybe_export_token] == .keyword_export;
4098 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
41984099 };
41994100 const is_extern = blk: {
42004101 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
4201 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4102 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
42024103 };
42034104 const has_inline_keyword = blk: {
42044105 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4205 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4106 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
42064107 };
42074108 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
42084109 const lib_name_str = try astgen.strLitAsString(lib_name_token);
......@@ -4214,16 +4115,18 @@ fn fnDecl(
42144115 }
42154116 break :blk lib_name_str.index;
42164117 } else .empty;
4217 if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) {
4118 if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) {
42184119 return astgen.failNode(
4219 fn_proto.ast.callconv_expr,
4120 fn_proto.ast.callconv_expr.unwrap().?,
42204121 "explicit callconv incompatible with inline keyword",
42214122 .{},
42224123 );
42234124 }
4224 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4225 const is_inferred_error = token_tags[maybe_bang] == .bang;
4226 if (body_node == 0) {
4125
4126 const return_type = fn_proto.ast.return_type.unwrap().?;
4127 const maybe_bang = tree.firstToken(return_type) - 1;
4128 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
4129 if (body_node == .none) {
42274130 if (!is_extern) {
42284131 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
42294132 }
......@@ -4256,28 +4159,28 @@ fn fnDecl(
42564159 var align_gz = type_gz.makeSubBlock(scope);
42574160 defer align_gz.unstack();
42584161
4259 if (fn_proto.ast.align_expr != 0) {
4162 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
42604163 astgen.restoreSourceCursor(saved_cursor);
4261 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr);
4164 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr);
42624165 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42634166 }
42644167
42654168 var linksection_gz = align_gz.makeSubBlock(scope);
42664169 defer linksection_gz.unstack();
42674170
4268 if (fn_proto.ast.section_expr != 0) {
4171 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
42694172 astgen.restoreSourceCursor(saved_cursor);
4270 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr);
4173 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr);
42714174 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42724175 }
42734176
42744177 var addrspace_gz = linksection_gz.makeSubBlock(scope);
42754178 defer addrspace_gz.unstack();
42764179
4277 if (fn_proto.ast.addrspace_expr != 0) {
4180 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
42784181 astgen.restoreSourceCursor(saved_cursor);
4279 const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space);
4280 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr);
4182 const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_expr, .address_space);
4183 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr);
42814184 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42824185 }
42834186
......@@ -4287,7 +4190,7 @@ fn fnDecl(
42874190 if (!is_extern) {
42884191 // We include a function *value*, not a type.
42894192 astgen.restoreSourceCursor(saved_cursor);
4290 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto);
4193 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto);
42914194 }
42924195
42934196 // *Now* we can incorporate the full source code into the hasher.
......@@ -4326,18 +4229,19 @@ fn fnDeclInner(
43264229 fn_proto: Ast.full.FnProto,
43274230) InnerError!void {
43284231 const tree = astgen.tree;
4329 const token_tags = tree.tokens.items(.tag);
43304232
43314233 const is_noinline = blk: {
43324234 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4333 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
4235 break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline;
43344236 };
43354237 const has_inline_keyword = blk: {
43364238 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4337 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4239 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
43384240 };
4339 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4340 const is_inferred_error = token_tags[maybe_bang] == .bang;
4241
4242 const return_type = fn_proto.ast.return_type.unwrap().?;
4243 const maybe_bang = tree.firstToken(return_type) - 1;
4244 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
43414245
43424246 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
43434247 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
......@@ -4351,7 +4255,7 @@ fn fnDeclInner(
43514255 var param_type_i: usize = 0;
43524256 var it = fn_proto.iterate(tree);
43534257 while (it.next()) |param| : (param_type_i += 1) {
4354 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {
4258 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
43554259 .keyword_noalias => is_comptime: {
43564260 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
43574261 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
......@@ -4362,7 +4266,7 @@ fn fnDeclInner(
43624266 } else false;
43634267
43644268 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
4365 switch (token_tags[token]) {
4269 switch (tree.tokenTag(token)) {
43664270 .keyword_anytype => break :blk true,
43674271 .ellipsis3 => break :is_var_args true,
43684272 else => unreachable,
......@@ -4381,30 +4285,31 @@ fn fnDeclInner(
43814285 if (param.anytype_ellipsis3) |tok| {
43824286 return astgen.failTok(tok, "missing parameter name", .{});
43834287 } else {
4288 const type_expr = param.type_expr.?;
43844289 ambiguous: {
4385 if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous;
4386 const main_token = tree.nodes.items(.main_token)[param.type_expr];
4290 if (tree.nodeTag(type_expr) != .identifier) break :ambiguous;
4291 const main_token = tree.nodeMainToken(type_expr);
43874292 const identifier_str = tree.tokenSlice(main_token);
43884293 if (isPrimitive(identifier_str)) break :ambiguous;
43894294 return astgen.failNodeNotes(
4390 param.type_expr,
4295 type_expr,
43914296 "missing parameter name or type",
43924297 .{},
43934298 &[_]u32{
43944299 try astgen.errNoteNode(
4395 param.type_expr,
4300 type_expr,
43964301 "if this is a name, annotate its type '{s}: T'",
43974302 .{identifier_str},
43984303 ),
43994304 try astgen.errNoteNode(
4400 param.type_expr,
4305 type_expr,
44014306 "if this is a type, give it a name '<name>: {s}'",
44024307 .{identifier_str},
44034308 ),
44044309 },
44054310 );
44064311 }
4407 return astgen.failNode(param.type_expr, "missing parameter name", .{});
4312 return astgen.failNode(type_expr, "missing parameter name", .{});
44084313 }
44094314 };
44104315
......@@ -4416,8 +4321,7 @@ fn fnDeclInner(
44164321 .param_anytype;
44174322 break :param try decl_gz.addStrTok(tag, param_name, name_token);
44184323 } else param: {
4419 const param_type_node = param.type_expr;
4420 assert(param_type_node != 0);
4324 const param_type_node = param.type_expr.?;
44214325 any_param_used = false; // we will check this later
44224326 var param_gz = decl_gz.makeSubBlock(scope);
44234327 defer param_gz.unstack();
......@@ -4426,8 +4330,7 @@ fn fnDeclInner(
44264330 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
44274331 const param_type_is_generic = any_param_used;
44284332
4429 const main_tokens = tree.nodes.items(.main_token);
4430 const name_token = param.name_token orelse main_tokens[param_type_node];
4333 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
44314334 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
44324335 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name);
44334336 assert(param_inst_expected == param_inst);
......@@ -4463,7 +4366,7 @@ fn fnDeclInner(
44634366 // Parameters are in scope for the return type, so we use `params_scope` here.
44644367 // The calling convention will not have parameters in scope, so we'll just use `scope`.
44654368 // See #22263 for a proposal to solve the inconsistency here.
4466 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal);
4369 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal);
44674370 if (ret_gz.instructionsSlice().len == 0) {
44684371 // In this case we will send a len=0 body which can be encoded more efficiently.
44694372 break :inst inst;
......@@ -4480,12 +4383,12 @@ fn fnDeclInner(
44804383 var cc_gz = decl_gz.makeSubBlock(scope);
44814384 defer cc_gz.unstack();
44824385 const cc_ref: Zir.Inst.Ref = blk: {
4483 if (fn_proto.ast.callconv_expr != 0) {
4386 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
44844387 const inst = try expr(
44854388 &cc_gz,
44864389 scope,
4487 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
4488 fn_proto.ast.callconv_expr,
4390 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(callconv_expr, .calling_convention) } },
4391 callconv_expr,
44894392 );
44904393 if (cc_gz.instructionsSlice().len == 0) {
44914394 // In this case we will send a len=0 body which can be encoded more efficiently.
......@@ -4524,7 +4427,7 @@ fn fnDeclInner(
45244427 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
45254428 // the *whole* function declaration, including its body.
45264429 var proto_hasher = astgen.src_hasher;
4527 const proto_node = tree.nodes.items(.data)[decl_node].lhs;
4430 const proto_node = tree.nodeData(decl_node).node_and_node[0];
45284431 proto_hasher.update(tree.getNodeSource(proto_node));
45294432 var proto_hash: std.zig.SrcHash = undefined;
45304433 proto_hasher.final(&proto_hash);
......@@ -4594,7 +4497,6 @@ fn globalVarDecl(
45944497 var_decl: Ast.full.VarDecl,
45954498) InnerError!void {
45964499 const tree = astgen.tree;
4597 const token_tags = tree.tokens.items(.tag);
45984500
45994501 const old_hasher = astgen.src_hasher;
46004502 defer astgen.src_hasher = old_hasher;
......@@ -4602,16 +4504,16 @@ fn globalVarDecl(
46024504 astgen.src_hasher.update(tree.getNodeSource(node));
46034505 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
46044506
4605 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
4507 const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var;
46064508 const name_token = var_decl.ast.mut_token + 1;
46074509 const is_pub = var_decl.visib_token != null;
46084510 const is_export = blk: {
46094511 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
4610 break :blk token_tags[maybe_export_token] == .keyword_export;
4512 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
46114513 };
46124514 const is_extern = blk: {
46134515 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
4614 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4516 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
46154517 };
46164518 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
46174519 if (!is_mutable) {
......@@ -4637,10 +4539,10 @@ fn globalVarDecl(
46374539 const decl_inst = try gz.makeDeclaration(node);
46384540 wip_members.nextDecl(decl_inst);
46394541
4640 if (var_decl.ast.init_node != 0) {
4542 if (var_decl.ast.init_node.unwrap()) |init_node| {
46414543 if (is_extern) {
46424544 return astgen.failNode(
4643 var_decl.ast.init_node,
4545 init_node,
46444546 "extern variables have no initializers",
46454547 .{},
46464548 );
......@@ -4651,7 +4553,7 @@ fn globalVarDecl(
46514553 }
46524554 }
46534555
4654 if (is_extern and var_decl.ast.type_node == 0) {
4556 if (is_extern and var_decl.ast.type_node == .none) {
46554557 return astgen.failNode(node, "unable to infer variable type", .{});
46564558 }
46574559
......@@ -4668,45 +4570,45 @@ fn globalVarDecl(
46684570 };
46694571 defer type_gz.unstack();
46704572
4671 if (var_decl.ast.type_node != 0) {
4672 const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, var_decl.ast.type_node);
4573 if (var_decl.ast.type_node.unwrap()) |type_node| {
4574 const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, type_node);
46734575 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
46744576 }
46754577
46764578 var align_gz = type_gz.makeSubBlock(scope);
46774579 defer align_gz.unstack();
46784580
4679 if (var_decl.ast.align_node != 0) {
4680 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);
4581 if (var_decl.ast.align_node.unwrap()) |align_node| {
4582 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_node);
46814583 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
46824584 }
46834585
46844586 var linksection_gz = type_gz.makeSubBlock(scope);
46854587 defer linksection_gz.unstack();
46864588
4687 if (var_decl.ast.section_node != 0) {
4688 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);
4589 if (var_decl.ast.section_node.unwrap()) |section_node| {
4590 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node);
46894591 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
46904592 }
46914593
46924594 var addrspace_gz = type_gz.makeSubBlock(scope);
46934595 defer addrspace_gz.unstack();
46944596
4695 if (var_decl.ast.addrspace_node != 0) {
4696 const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space);
4697 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node);
4597 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
4598 const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_node, .address_space);
4599 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node);
46984600 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
46994601 }
47004602
47014603 var init_gz = type_gz.makeSubBlock(scope);
47024604 defer init_gz.unstack();
47034605
4704 if (var_decl.ast.init_node != 0) {
4606 if (var_decl.ast.init_node.unwrap()) |init_node| {
47054607 init_gz.anon_name_strategy = .parent;
4706 const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{
4608 const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{
47074609 .rl = .{ .coerced_ty = decl_inst.toRef() },
47084610 } else .{ .rl = .none };
4709 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node);
4611 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, init_node);
47104612 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
47114613 }
47124614
......@@ -4740,8 +4642,7 @@ fn comptimeDecl(
47404642 node: Ast.Node.Index,
47414643) InnerError!void {
47424644 const tree = astgen.tree;
4743 const node_datas = tree.nodes.items(.data);
4744 const body_node = node_datas[node].lhs;
4645 const body_node = tree.nodeData(node).node;
47454646
47464647 const old_hasher = astgen.src_hasher;
47474648 defer astgen.src_hasher = old_hasher;
......@@ -4804,7 +4705,6 @@ fn usingnamespaceDecl(
48044705 node: Ast.Node.Index,
48054706) InnerError!void {
48064707 const tree = astgen.tree;
4807 const node_datas = tree.nodes.items(.data);
48084708
48094709 const old_hasher = astgen.src_hasher;
48104710 defer astgen.src_hasher = old_hasher;
......@@ -4812,13 +4712,9 @@ fn usingnamespaceDecl(
48124712 astgen.src_hasher.update(tree.getNodeSource(node));
48134713 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
48144714
4815 const type_expr = node_datas[node].lhs;
4816 const is_pub = blk: {
4817 const main_tokens = tree.nodes.items(.main_token);
4818 const token_tags = tree.tokens.items(.tag);
4819 const main_token = main_tokens[node];
4820 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
4821 };
4715 const type_expr = tree.nodeData(node).node;
4716 const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub});
4717
48224718 // Up top so the ZIR instruction index marks the start range of this
48234719 // top-level declaration.
48244720 const decl_inst = try gz.makeDeclaration(node);
......@@ -4872,8 +4768,7 @@ fn testDecl(
48724768 node: Ast.Node.Index,
48734769) InnerError!void {
48744770 const tree = astgen.tree;
4875 const node_datas = tree.nodes.items(.data);
4876 const body_node = node_datas[node].rhs;
4771 _, const body_node = tree.nodeData(node).opt_token_and_node;
48774772
48784773 const old_hasher = astgen.src_hasher;
48794774 defer astgen.src_hasher = old_hasher;
......@@ -4905,12 +4800,10 @@ fn testDecl(
49054800
49064801 const decl_column = astgen.source_column;
49074802
4908 const main_tokens = tree.nodes.items(.main_token);
4909 const token_tags = tree.tokens.items(.tag);
4910 const test_token = main_tokens[node];
4803 const test_token = tree.nodeMainToken(node);
49114804
49124805 const test_name_token = test_token + 1;
4913 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {
4806 const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) {
49144807 else => .empty,
49154808 .string_literal => name: {
49164809 const name = try astgen.strLitAsString(test_name_token);
......@@ -4942,7 +4835,7 @@ fn testDecl(
49424835 .local_val => {
49434836 const local_val = s.cast(Scope.LocalVal).?;
49444837 if (local_val.name == name_str_index) {
4945 local_val.used = test_name_token;
4838 local_val.used = .fromToken(test_name_token);
49464839 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
49474840 @tagName(local_val.id_cat),
49484841 }, &[_]u32{
......@@ -4956,7 +4849,7 @@ fn testDecl(
49564849 .local_ptr => {
49574850 const local_ptr = s.cast(Scope.LocalPtr).?;
49584851 if (local_ptr.name == name_str_index) {
4959 local_ptr.used = test_name_token;
4852 local_ptr.used = .fromToken(test_name_token);
49604853 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
49614854 @tagName(local_ptr.id_cat),
49624855 }, &[_]u32{
......@@ -5067,7 +4960,7 @@ fn testDecl(
50674960 .src_line = decl_block.decl_line,
50684961 .src_column = decl_column,
50694962
5070 .kind = switch (token_tags[test_name_token]) {
4963 .kind = switch (tree.tokenTag(test_name_token)) {
50714964 .string_literal => .@"test",
50724965 .identifier => .decltest,
50734966 else => .unnamed_test,
......@@ -5091,7 +4984,7 @@ fn structDeclInner(
50914984 node: Ast.Node.Index,
50924985 container_decl: Ast.full.ContainerDecl,
50934986 layout: std.builtin.Type.ContainerLayout,
5094 backing_int_node: Ast.Node.Index,
4987 backing_int_node: Ast.Node.OptionalIndex,
50954988) InnerError!Zir.Inst.Ref {
50964989 const astgen = gz.astgen;
50974990 const gpa = astgen.gpa;
......@@ -5103,7 +4996,7 @@ fn structDeclInner(
51034996 if (container_field.ast.tuple_like) break member_node;
51044997 } else break :is_tuple;
51054998
5106 if (node == 0) {
4999 if (node == .root) {
51075000 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});
51085001 } else {
51095002 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
......@@ -5112,7 +5005,7 @@ fn structDeclInner(
51125005
51135006 const decl_inst = try gz.reserveInstructionIndex();
51145007
5115 if (container_decl.ast.members.len == 0 and backing_int_node == 0) {
5008 if (container_decl.ast.members.len == 0 and backing_int_node == .none) {
51165009 try gz.setStruct(decl_inst, .{
51175010 .src_node = node,
51185011 .layout = layout,
......@@ -5159,11 +5052,11 @@ fn structDeclInner(
51595052
51605053 var backing_int_body_len: usize = 0;
51615054 const backing_int_ref: Zir.Inst.Ref = blk: {
5162 if (backing_int_node != 0) {
5055 if (backing_int_node.unwrap()) |arg| {
51635056 if (layout != .@"packed") {
5164 return astgen.failNode(backing_int_node, "non-packed struct does not support backing integer type", .{});
5057 return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{});
51655058 } else {
5166 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node);
5059 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg);
51675060 if (!block_scope.isEmpty()) {
51685061 if (!block_scope.endsWithNoReturn()) {
51695062 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);
......@@ -5208,8 +5101,8 @@ fn structDeclInner(
52085101 defer astgen.src_hasher = old_hasher;
52095102 astgen.src_hasher = std.zig.SrcHasher.init(.{});
52105103 astgen.src_hasher.update(@tagName(layout));
5211 if (backing_int_node != 0) {
5212 astgen.src_hasher.update(tree.getNodeSource(backing_int_node));
5104 if (backing_int_node.unwrap()) |arg| {
5105 astgen.src_hasher.update(tree.getNodeSource(arg));
52135106 }
52145107
52155108 var known_non_opv = false;
......@@ -5226,18 +5119,18 @@ fn structDeclInner(
52265119 astgen.src_hasher.update(tree.getNodeSource(member_node));
52275120
52285121 const field_name = try astgen.identAsString(member.ast.main_token);
5229 member.convertToNonTupleLike(astgen.tree.nodes);
5122 member.convertToNonTupleLike(astgen.tree);
52305123 assert(!member.ast.tuple_like);
52315124 wip_members.appendToField(@intFromEnum(field_name));
52325125
5233 if (member.ast.type_expr == 0) {
5126 const type_expr = member.ast.type_expr.unwrap() orelse {
52345127 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5235 }
5128 };
52365129
5237 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
5130 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
52385131 const have_type_body = !block_scope.isEmpty();
5239 const have_align = member.ast.align_expr != 0;
5240 const have_value = member.ast.value_expr != 0;
5132 const have_align = member.ast.align_expr != .none;
5133 const have_value = member.ast.value_expr != .none;
52415134 const is_comptime = member.comptime_token != null;
52425135
52435136 if (is_comptime) {
......@@ -5247,9 +5140,9 @@ fn structDeclInner(
52475140 }
52485141 } else {
52495142 known_non_opv = known_non_opv or
5250 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);
5143 nodeImpliesMoreThanOnePossibleValue(tree, type_expr);
52515144 known_comptime_only = known_comptime_only or
5252 nodeImpliesComptimeOnly(tree, member.ast.type_expr);
5145 nodeImpliesComptimeOnly(tree, type_expr);
52535146 }
52545147 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body });
52555148
......@@ -5267,12 +5160,12 @@ fn structDeclInner(
52675160 wip_members.appendToField(@intFromEnum(field_type));
52685161 }
52695162
5270 if (have_align) {
5163 if (member.ast.align_expr.unwrap()) |align_expr| {
52715164 if (layout == .@"packed") {
5272 return astgen.failNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});
5165 return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{});
52735166 }
52745167 any_aligned_fields = true;
5275 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr);
5168 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr);
52765169 if (!block_scope.endsWithNoReturn()) {
52775170 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
52785171 }
......@@ -5284,14 +5177,14 @@ fn structDeclInner(
52845177 block_scope.instructions.items.len = block_scope.instructions_top;
52855178 }
52865179
5287 if (have_value) {
5180 if (member.ast.value_expr.unwrap()) |value_expr| {
52885181 any_default_inits = true;
52895182
52905183 // The decl_inst is used as here so that we can easily reconstruct a mapping
52915184 // between it and the field type when the fields inits are analyzed.
52925185 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } };
52935186
5294 const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr);
5187 const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr);
52955188 if (!block_scope.endsWithNoReturn()) {
52965189 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
52975190 }
......@@ -5354,21 +5247,19 @@ fn tupleDecl(
53545247 node: Ast.Node.Index,
53555248 container_decl: Ast.full.ContainerDecl,
53565249 layout: std.builtin.Type.ContainerLayout,
5357 backing_int_node: Ast.Node.Index,
5250 backing_int_node: Ast.Node.OptionalIndex,
53585251) InnerError!Zir.Inst.Ref {
53595252 const astgen = gz.astgen;
53605253 const gpa = astgen.gpa;
53615254 const tree = astgen.tree;
53625255
5363 const node_tags = tree.nodes.items(.tag);
5364
53655256 switch (layout) {
53665257 .auto => {},
53675258 .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}),
53685259 }
53695260
5370 if (backing_int_node != 0) {
5371 return astgen.failNode(backing_int_node, "tuple does not support backing integer type", .{});
5261 if (backing_int_node.unwrap()) |arg| {
5262 return astgen.failNode(arg, "tuple does not support backing integer type", .{});
53725263 }
53735264
53745265 // We will use the scratch buffer, starting here, for the field data:
......@@ -5383,7 +5274,7 @@ fn tupleDecl(
53835274
53845275 for (container_decl.ast.members) |member_node| {
53855276 const field = tree.fullContainerField(member_node) orelse {
5386 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {
5277 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) {
53875278 .container_field_init,
53885279 .container_field_align,
53895280 .container_field,
......@@ -5402,23 +5293,23 @@ fn tupleDecl(
54025293 return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});
54035294 }
54045295
5405 if (field.ast.align_expr != 0) {
5296 if (field.ast.align_expr != .none) {
54065297 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
54075298 }
54085299
5409 if (field.ast.value_expr != 0 and field.comptime_token == null) {
5300 if (field.ast.value_expr != .none and field.comptime_token == null) {
54105301 return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});
54115302 }
54125303
5413 if (field.ast.value_expr == 0 and field.comptime_token != null) {
5304 if (field.ast.value_expr == .none and field.comptime_token != null) {
54145305 return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});
54155306 }
54165307
5417 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr);
5308 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?);
54185309 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
54195310
5420 if (field.ast.value_expr != 0) {
5421 const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value);
5311 if (field.ast.value_expr.unwrap()) |value_expr| {
5312 const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, value_expr, .tuple_field_default_value);
54225313 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
54235314 } else {
54245315 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
......@@ -5453,7 +5344,7 @@ fn unionDeclInner(
54535344 node: Ast.Node.Index,
54545345 members: []const Ast.Node.Index,
54555346 layout: std.builtin.Type.ContainerLayout,
5456 arg_node: Ast.Node.Index,
5347 opt_arg_node: Ast.Node.OptionalIndex,
54575348 auto_enum_tok: ?Ast.TokenIndex,
54585349) InnerError!Zir.Inst.Ref {
54595350 const decl_inst = try gz.reserveInstructionIndex();
......@@ -5488,15 +5379,15 @@ fn unionDeclInner(
54885379 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");
54895380 const field_count: u32 = @intCast(members.len - decl_count);
54905381
5491 if (layout != .auto and (auto_enum_tok != null or arg_node != 0)) {
5492 if (arg_node != 0) {
5382 if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) {
5383 if (opt_arg_node.unwrap()) |arg_node| {
54935384 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});
54945385 } else {
54955386 return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)});
54965387 }
54975388 }
54985389
5499 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
5390 const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node|
55005391 try typeExpr(&block_scope, &namespace.base, arg_node)
55015392 else
55025393 .none;
......@@ -5512,7 +5403,7 @@ fn unionDeclInner(
55125403 astgen.src_hasher = std.zig.SrcHasher.init(.{});
55135404 astgen.src_hasher.update(@tagName(layout));
55145405 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});
5515 if (arg_node != 0) {
5406 if (opt_arg_node.unwrap()) |arg_node| {
55165407 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
55175408 }
55185409
......@@ -5522,7 +5413,7 @@ fn unionDeclInner(
55225413 .field => |field| field,
55235414 };
55245415 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));
5525 member.convertToNonTupleLike(astgen.tree.nodes);
5416 member.convertToNonTupleLike(astgen.tree);
55265417 if (member.ast.tuple_like) {
55275418 return astgen.failTok(member.ast.main_token, "union field missing name", .{});
55285419 }
......@@ -5533,24 +5424,24 @@ fn unionDeclInner(
55335424 const field_name = try astgen.identAsString(member.ast.main_token);
55345425 wip_members.appendToField(@intFromEnum(field_name));
55355426
5536 const have_type = member.ast.type_expr != 0;
5537 const have_align = member.ast.align_expr != 0;
5538 const have_value = member.ast.value_expr != 0;
5427 const have_type = member.ast.type_expr != .none;
5428 const have_align = member.ast.align_expr != .none;
5429 const have_value = member.ast.value_expr != .none;
55395430 const unused = false;
55405431 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
55415432
5542 if (have_type) {
5543 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
5433 if (member.ast.type_expr.unwrap()) |type_expr| {
5434 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
55445435 wip_members.appendToField(@intFromEnum(field_type));
55455436 } else if (arg_inst == .none and auto_enum_tok == null) {
55465437 return astgen.failNode(member_node, "union field missing type", .{});
55475438 }
5548 if (have_align) {
5549 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, member.ast.align_expr);
5439 if (member.ast.align_expr.unwrap()) |align_expr| {
5440 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr);
55505441 wip_members.appendToField(@intFromEnum(align_inst));
55515442 any_aligned_fields = true;
55525443 }
5553 if (have_value) {
5444 if (member.ast.value_expr.unwrap()) |value_expr| {
55545445 if (arg_inst == .none) {
55555446 return astgen.failNodeNotes(
55565447 node,
......@@ -5558,7 +5449,7 @@ fn unionDeclInner(
55585449 .{},
55595450 &[_]u32{
55605451 try astgen.errNoteNode(
5561 member.ast.value_expr,
5452 value_expr,
55625453 "tag value specified here",
55635454 .{},
55645455 ),
......@@ -5572,14 +5463,14 @@ fn unionDeclInner(
55725463 .{},
55735464 &[_]u32{
55745465 try astgen.errNoteNode(
5575 member.ast.value_expr,
5466 value_expr,
55765467 "tag value specified here",
55775468 .{},
55785469 ),
55795470 },
55805471 );
55815472 }
5582 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
5473 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
55835474 wip_members.appendToField(@intFromEnum(tag_value));
55845475 }
55855476 }
......@@ -5631,7 +5522,6 @@ fn containerDecl(
56315522 const astgen = gz.astgen;
56325523 const gpa = astgen.gpa;
56335524 const tree = astgen.tree;
5634 const token_tags = tree.tokens.items(.tag);
56355525
56365526 const prev_fn_block = astgen.fn_block;
56375527 astgen.fn_block = null;
......@@ -5640,9 +5530,9 @@ fn containerDecl(
56405530 // We must not create any types until Sema. Here the goal is only to generate
56415531 // ZIR for all the field types, alignments, and default value expressions.
56425532
5643 switch (token_tags[container_decl.ast.main_token]) {
5533 switch (tree.tokenTag(container_decl.ast.main_token)) {
56445534 .keyword_struct => {
5645 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
5535 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
56465536 .keyword_packed => .@"packed",
56475537 .keyword_extern => .@"extern",
56485538 else => unreachable,
......@@ -5652,7 +5542,7 @@ fn containerDecl(
56525542 return rvalue(gz, ri, result, node);
56535543 },
56545544 .keyword_union => {
5655 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
5545 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
56565546 .keyword_packed => .@"packed",
56575547 .keyword_extern => .@"extern",
56585548 else => unreachable,
......@@ -5670,23 +5560,23 @@ fn containerDecl(
56705560 var values: usize = 0;
56715561 var total_fields: usize = 0;
56725562 var decls: usize = 0;
5673 var nonexhaustive_node: Ast.Node.Index = 0;
5563 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
56745564 var nonfinal_nonexhaustive = false;
56755565 for (container_decl.ast.members) |member_node| {
56765566 var member = tree.fullContainerField(member_node) orelse {
56775567 decls += 1;
56785568 continue;
56795569 };
5680 member.convertToNonTupleLike(astgen.tree.nodes);
5570 member.convertToNonTupleLike(astgen.tree);
56815571 if (member.ast.tuple_like) {
56825572 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
56835573 }
56845574 if (member.comptime_token) |comptime_token| {
56855575 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
56865576 }
5687 if (member.ast.type_expr != 0) {
5577 if (member.ast.type_expr.unwrap()) |type_expr| {
56885578 return astgen.failNodeNotes(
5689 member.ast.type_expr,
5579 type_expr,
56905580 "enum fields do not have types",
56915581 .{},
56925582 &[_]u32{
......@@ -5698,13 +5588,13 @@ fn containerDecl(
56985588 },
56995589 );
57005590 }
5701 if (member.ast.align_expr != 0) {
5702 return astgen.failNode(member.ast.align_expr, "enum fields cannot be aligned", .{});
5591 if (member.ast.align_expr.unwrap()) |align_expr| {
5592 return astgen.failNode(align_expr, "enum fields cannot be aligned", .{});
57035593 }
57045594
57055595 const name_token = member.ast.main_token;
57065596 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
5707 if (nonexhaustive_node != 0) {
5597 if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| {
57085598 return astgen.failNodeNotes(
57095599 member_node,
57105600 "redundant non-exhaustive enum mark",
......@@ -5718,40 +5608,41 @@ fn containerDecl(
57185608 },
57195609 );
57205610 }
5721 nonexhaustive_node = member_node;
5722 if (member.ast.value_expr != 0) {
5723 return astgen.failNode(member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
5611 opt_nonexhaustive_node = member_node.toOptional();
5612 if (member.ast.value_expr.unwrap()) |value_expr| {
5613 return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
57245614 }
57255615 continue;
5726 } else if (nonexhaustive_node != 0) {
5616 } else if (opt_nonexhaustive_node != .none) {
57275617 nonfinal_nonexhaustive = true;
57285618 }
57295619 total_fields += 1;
5730 if (member.ast.value_expr != 0) {
5731 if (container_decl.ast.arg == 0) {
5732 return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});
5620 if (member.ast.value_expr.unwrap()) |value_expr| {
5621 if (container_decl.ast.arg == .none) {
5622 return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{});
57335623 }
57345624 values += 1;
57355625 }
57365626 }
57375627 if (nonfinal_nonexhaustive) {
5738 return astgen.failNode(nonexhaustive_node, "'_' field of non-exhaustive enum must be last", .{});
5628 return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{});
57395629 }
57405630 break :blk .{
57415631 .total_fields = total_fields,
57425632 .values = values,
57435633 .decls = decls,
5744 .nonexhaustive_node = nonexhaustive_node,
5634 .nonexhaustive_node = opt_nonexhaustive_node,
57455635 };
57465636 };
5747 if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) {
5637 if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) {
5638 const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?;
57485639 return astgen.failNodeNotes(
57495640 node,
57505641 "non-exhaustive enum missing integer tag type",
57515642 .{},
57525643 &[_]u32{
57535644 try astgen.errNoteNode(
5754 counts.nonexhaustive_node,
5645 nonexhaustive_node,
57555646 "marked non-exhaustive here",
57565647 .{},
57575648 ),
......@@ -5760,7 +5651,7 @@ fn containerDecl(
57605651 }
57615652 // In this case we must generate ZIR code for the tag values, similar to
57625653 // how structs are handled above.
5763 const nonexhaustive = counts.nonexhaustive_node != 0;
5654 const nonexhaustive = counts.nonexhaustive_node != .none;
57645655
57655656 const decl_inst = try gz.reserveInstructionIndex();
57665657
......@@ -5790,8 +5681,8 @@ fn containerDecl(
57905681 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
57915682 namespace.base.tag = .namespace;
57925683
5793 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
5794 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type)
5684 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg|
5685 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type)
57955686 else
57965687 .none;
57975688
......@@ -5803,31 +5694,31 @@ fn containerDecl(
58035694 const old_hasher = astgen.src_hasher;
58045695 defer astgen.src_hasher = old_hasher;
58055696 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5806 if (container_decl.ast.arg != 0) {
5807 astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg));
5697 if (container_decl.ast.arg.unwrap()) |arg| {
5698 astgen.src_hasher.update(tree.getNodeSource(arg));
58085699 }
58095700 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});
58105701
58115702 for (container_decl.ast.members) |member_node| {
5812 if (member_node == counts.nonexhaustive_node)
5703 if (member_node.toOptional() == counts.nonexhaustive_node)
58135704 continue;
58145705 astgen.src_hasher.update(tree.getNodeSource(member_node));
58155706 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
58165707 .decl => continue,
58175708 .field => |field| field,
58185709 };
5819 member.convertToNonTupleLike(astgen.tree.nodes);
5710 member.convertToNonTupleLike(astgen.tree);
58205711 assert(member.comptime_token == null);
5821 assert(member.ast.type_expr == 0);
5822 assert(member.ast.align_expr == 0);
5712 assert(member.ast.type_expr == .none);
5713 assert(member.ast.align_expr == .none);
58235714
58245715 const field_name = try astgen.identAsString(member.ast.main_token);
58255716 wip_members.appendToField(@intFromEnum(field_name));
58265717
5827 const have_value = member.ast.value_expr != 0;
5718 const have_value = member.ast.value_expr != .none;
58285719 wip_members.nextField(bits_per_field, .{have_value});
58295720
5830 if (have_value) {
5721 if (member.ast.value_expr.unwrap()) |value_expr| {
58315722 if (arg_inst == .none) {
58325723 return astgen.failNodeNotes(
58335724 node,
......@@ -5835,14 +5726,14 @@ fn containerDecl(
58355726 .{},
58365727 &[_]u32{
58375728 try astgen.errNoteNode(
5838 member.ast.value_expr,
5729 value_expr,
58395730 "tag value specified here",
58405731 .{},
58415732 ),
58425733 },
58435734 );
58445735 }
5845 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);
5736 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
58465737 wip_members.appendToField(@intFromEnum(tag_value_inst));
58475738 }
58485739 }
......@@ -5882,7 +5773,7 @@ fn containerDecl(
58825773 return rvalue(gz, ri, decl_inst.toRef(), node);
58835774 },
58845775 .keyword_opaque => {
5885 assert(container_decl.ast.arg == 0);
5776 assert(container_decl.ast.arg == .none);
58865777
58875778 const decl_inst = try gz.reserveInstructionIndex();
58885779
......@@ -5953,9 +5844,7 @@ fn containerMember(
59535844) InnerError!ContainerMemberResult {
59545845 const astgen = gz.astgen;
59555846 const tree = astgen.tree;
5956 const node_tags = tree.nodes.items(.tag);
5957 const node_datas = tree.nodes.items(.data);
5958 switch (node_tags[member_node]) {
5847 switch (tree.nodeTag(member_node)) {
59595848 .container_field_init,
59605849 .container_field_align,
59615850 .container_field,
......@@ -5969,7 +5858,11 @@ fn containerMember(
59695858 => {
59705859 var buf: [1]Ast.Node.Index = undefined;
59715860 const full = tree.fullFnProto(&buf, member_node).?;
5972 const body = if (node_tags[member_node] == .fn_decl) node_datas[member_node].rhs else 0;
5861
5862 const body: Ast.Node.OptionalIndex = if (tree.nodeTag(member_node) == .fn_decl)
5863 tree.nodeData(member_node).node_and_node[1].toOptional()
5864 else
5865 .none;
59735866
59745867 const prev_decl_index = wip_members.decl_index;
59755868 astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) {
......@@ -6040,12 +5933,7 @@ fn containerMember(
60405933 .@"usingnamespace",
60415934 .empty,
60425935 member_node,
6043 is_pub: {
6044 const main_tokens = tree.nodes.items(.main_token);
6045 const token_tags = tree.tokens.items(.tag);
6046 const main_token = main_tokens[member_node];
6047 break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub;
6048 },
5936 tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}),
60495937 );
60505938 },
60515939 };
......@@ -6079,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
60795967 const astgen = gz.astgen;
60805968 const gpa = astgen.gpa;
60815969 const tree = astgen.tree;
6082 const main_tokens = tree.nodes.items(.main_token);
6083 const token_tags = tree.tokens.items(.tag);
60845970
60855971 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len);
60865972 var fields_len: usize = 0;
......@@ -6088,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
60885974 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;
60895975 defer idents.deinit(gpa);
60905976
6091 const error_token = main_tokens[node];
6092 var tok_i = error_token + 2;
6093 while (true) : (tok_i += 1) {
6094 switch (token_tags[tok_i]) {
5977 const lbrace, const rbrace = tree.nodeData(node).token_and_token;
5978 for (lbrace + 1..rbrace) |i| {
5979 const tok_i: Ast.TokenIndex = @intCast(i);
5980 switch (tree.tokenTag(tok_i)) {
60955981 .doc_comment, .comma => {},
60965982 .identifier => {
60975983 const str_index = try astgen.identAsString(tok_i);
......@@ -6117,7 +6003,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
61176003 try astgen.extra.append(gpa, @intFromEnum(str_index));
61186004 fields_len += 1;
61196005 },
6120 .r_brace => break,
61216006 else => unreachable,
61226007 }
61236008 }
......@@ -6143,10 +6028,10 @@ fn tryExpr(
61436028 return astgen.failNode(node, "'try' outside function scope", .{});
61446029 };
61456030
6146 if (parent_gz.any_defer_node != 0) {
6031 if (parent_gz.any_defer_node.unwrap()) |any_defer_node| {
61476032 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{
61486033 try astgen.errNoteNode(
6149 parent_gz.any_defer_node,
6034 any_defer_node,
61506035 "defer expression here",
61516036 .{},
61526037 ),
......@@ -6209,16 +6094,16 @@ fn orelseCatchExpr(
62096094 scope: *Scope,
62106095 ri: ResultInfo,
62116096 node: Ast.Node.Index,
6212 lhs: Ast.Node.Index,
62136097 cond_op: Zir.Inst.Tag,
62146098 unwrap_op: Zir.Inst.Tag,
62156099 unwrap_code_op: Zir.Inst.Tag,
6216 rhs: Ast.Node.Index,
62176100 payload_token: ?Ast.TokenIndex,
62186101) InnerError!Zir.Inst.Ref {
62196102 const astgen = parent_gz.astgen;
62206103 const tree = astgen.tree;
62216104
6105 const lhs, const rhs = tree.nodeData(node).node_and_node;
6106
62226107 const need_rl = astgen.nodes_need_rl.contains(node);
62236108 const block_ri: ResultInfo = if (need_rl) ri else .{
62246109 .rl = switch (ri.rl) {
......@@ -6351,12 +6236,8 @@ fn addFieldAccess(
63516236) InnerError!Zir.Inst.Ref {
63526237 const astgen = gz.astgen;
63536238 const tree = astgen.tree;
6354 const main_tokens = tree.nodes.items(.main_token);
6355 const node_datas = tree.nodes.items(.data);
63566239
6357 const object_node = node_datas[node].lhs;
6358 const dot_token = main_tokens[node];
6359 const field_ident = dot_token + 1;
6240 const object_node, const field_ident = tree.nodeData(node).node_and_token;
63606241 const str_index = try astgen.identAsString(field_ident);
63616242 const lhs = try expr(gz, scope, lhs_ri, object_node);
63626243
......@@ -6376,24 +6257,25 @@ fn arrayAccess(
63766257 node: Ast.Node.Index,
63776258) InnerError!Zir.Inst.Ref {
63786259 const tree = gz.astgen.tree;
6379 const node_datas = tree.nodes.items(.data);
63806260 switch (ri.rl) {
63816261 .ref, .ref_coerced_ty => {
6382 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
6262 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6263 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node);
63836264
63846265 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63856266
6386 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6267 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
63876268 try emitDbgStmt(gz, cursor);
63886269
63896270 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
63906271 },
63916272 else => {
6392 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
6273 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6274 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
63936275
63946276 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63956277
6396 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6278 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
63976279 try emitDbgStmt(gz, cursor);
63986280
63996281 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
......@@ -6410,22 +6292,22 @@ fn simpleBinOp(
64106292) InnerError!Zir.Inst.Ref {
64116293 const astgen = gz.astgen;
64126294 const tree = astgen.tree;
6413 const node_datas = tree.nodes.items(.data);
6295
6296 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
64146297
64156298 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
6416 const node_tags = tree.nodes.items(.tag);
64176299 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
6418 if (node_tags[node_datas[node].lhs] == .string_literal or
6419 node_tags[node_datas[node].rhs] == .string_literal)
6300 if (tree.nodeTag(lhs_node) == .string_literal or
6301 tree.nodeTag(rhs_node) == .string_literal)
64206302 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
64216303 }
64226304
6423 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
6305 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node);
64246306 const cursor = switch (op_inst_tag) {
64256307 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
64266308 else => undefined,
64276309 };
6428 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
6310 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node);
64296311
64306312 switch (op_inst_tag) {
64316313 .add, .sub, .mul, .div, .mod_rem => {
......@@ -6459,16 +6341,16 @@ fn boolBinOp(
64596341) InnerError!Zir.Inst.Ref {
64606342 const astgen = gz.astgen;
64616343 const tree = astgen.tree;
6462 const node_datas = tree.nodes.items(.data);
64636344
6464 const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs);
6345 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6346 const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node);
64656347 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;
64666348
64676349 var rhs_scope = gz.makeSubBlock(scope);
64686350 defer rhs_scope.unstack();
6469 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint);
6351 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint);
64706352 if (!gz.refIsNoReturn(rhs)) {
6471 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
6353 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node);
64726354 }
64736355 try rhs_scope.setBoolBrBody(bool_br, lhs);
64746356
......@@ -6485,7 +6367,6 @@ fn ifExpr(
64856367) InnerError!Zir.Inst.Ref {
64866368 const astgen = parent_gz.astgen;
64876369 const tree = astgen.tree;
6488 const token_tags = tree.tokens.items(.tag);
64896370
64906371 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
64916372
......@@ -6508,7 +6389,7 @@ fn ifExpr(
65086389 defer block_scope.unstack();
65096390
65106391 const payload_is_ref = if (if_full.payload_token) |payload_token|
6511 token_tags[payload_token] == .asterisk
6392 tree.tokenTag(payload_token) == .asterisk
65126393 else
65136394 false;
65146395
......@@ -6586,7 +6467,7 @@ fn ifExpr(
65866467 break :s &then_scope.base;
65876468 }
65886469 } else if (if_full.payload_token) |payload_token| {
6589 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
6470 const ident_token = payload_token + @intFromBool(payload_is_ref);
65906471 const tag: Zir.Inst.Tag = if (payload_is_ref)
65916472 .optional_payload_unsafe_ptr
65926473 else
......@@ -6628,8 +6509,7 @@ fn ifExpr(
66286509 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))
66296510 _ = try else_scope.addSaveErrRetIndex(.always);
66306511
6631 const else_node = if_full.ast.else_expr;
6632 if (else_node != 0) {
6512 if (if_full.ast.else_expr.unwrap()) |else_node| {
66336513 const sub_scope = s: {
66346514 if (if_full.error_token) |error_token| {
66356515 const tag: Zir.Inst.Tag = if (payload_is_ref)
......@@ -6717,8 +6597,6 @@ fn whileExpr(
67176597) InnerError!Zir.Inst.Ref {
67186598 const astgen = parent_gz.astgen;
67196599 const tree = astgen.tree;
6720 const token_tags = tree.tokens.items(.tag);
6721 const token_starts = tree.tokens.items(.start);
67226600
67236601 const need_rl = astgen.nodes_need_rl.contains(node);
67246602 const block_ri: ResultInfo = if (need_rl) ri else .{
......@@ -6755,7 +6633,7 @@ fn whileExpr(
67556633 defer cond_scope.unstack();
67566634
67576635 const payload_is_ref = if (while_full.payload_token) |payload_token|
6758 token_tags[payload_token] == .asterisk
6636 tree.tokenTag(payload_token) == .asterisk
67596637 else
67606638 false;
67616639
......@@ -6841,7 +6719,6 @@ fn whileExpr(
68416719 break :s &then_scope.base;
68426720 }
68436721 } else if (while_full.payload_token) |payload_token| {
6844 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
68456722 const tag: Zir.Inst.Tag = if (payload_is_ref)
68466723 .optional_payload_unsafe_ptr
68476724 else
......@@ -6849,6 +6726,7 @@ fn whileExpr(
68496726 // will add this instruction to then_scope.instructions below
68506727 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);
68516728 opt_payload_inst = payload_inst.toOptional();
6729 const ident_token = payload_token + @intFromBool(payload_is_ref);
68526730 const ident_name = try astgen.identAsString(ident_token);
68536731 const ident_bytes = tree.tokenSlice(ident_token);
68546732 if (mem.eql(u8, "_", ident_bytes)) {
......@@ -6903,8 +6781,8 @@ fn whileExpr(
69036781 // are no jumps to it. This happens when the last statement of a while body is noreturn
69046782 // and there are no `continue` statements.
69056783 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6906 if (while_full.ast.cont_expr != 0) {
6907 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);
6784 if (while_full.ast.cont_expr.unwrap()) |cont_expr| {
6785 _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr);
69086786 }
69096787
69106788 continue_scope.instructions_top = continue_scope.instructions.items.len;
......@@ -6916,7 +6794,7 @@ fn whileExpr(
69166794 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
69176795 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
69186796 if (!continue_scope.endsWithNoReturn()) {
6919 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
6797 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
69206798 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
69216799 _ = try parent_gz.add(.{
69226800 .tag = .extended,
......@@ -6934,8 +6812,7 @@ fn whileExpr(
69346812 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
69356813 defer else_scope.unstack();
69366814
6937 const else_node = while_full.ast.else_expr;
6938 if (else_node != 0) {
6815 if (while_full.ast.else_expr.unwrap()) |else_node| {
69396816 const sub_scope = s: {
69406817 if (while_full.error_token) |error_token| {
69416818 const tag: Zir.Inst.Tag = if (payload_is_ref)
......@@ -7033,10 +6910,6 @@ fn forExpr(
70336910 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});
70346911 }
70356912 const tree = astgen.tree;
7036 const token_tags = tree.tokens.items(.tag);
7037 const token_starts = tree.tokens.items(.start);
7038 const node_tags = tree.nodes.items(.tag);
7039 const node_data = tree.nodes.items(.data);
70406913 const gpa = astgen.gpa;
70416914
70426915 // For counters, this is the start value; for indexables, this is the base
......@@ -7066,7 +6939,7 @@ fn forExpr(
70666939 {
70676940 var capture_token = for_full.payload_token;
70686941 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {
7069 const capture_is_ref = token_tags[capture_token] == .asterisk;
6942 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
70706943 const ident_tok = capture_token + @intFromBool(capture_is_ref);
70716944 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");
70726945
......@@ -7077,16 +6950,15 @@ fn forExpr(
70776950 capture_token = ident_tok + 2;
70786951
70796952 try emitDbgNode(parent_gz, input);
7080 if (node_tags[input] == .for_range) {
6953 if (tree.nodeTag(input) == .for_range) {
70816954 if (capture_is_ref) {
70826955 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
70836956 }
7084 const start_node = node_data[input].lhs;
6957 const start_node, const end_node = tree.nodeData(input).node_and_opt_node;
70856958 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);
70866959
7087 const end_node = node_data[input].rhs;
7088 const end_val = if (end_node != 0)
7089 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs)
6960 const end_val = if (end_node.unwrap()) |end|
6961 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end)
70906962 else
70916963 .none;
70926964
......@@ -7179,7 +7051,7 @@ fn forExpr(
71797051 var capture_token = for_full.payload_token;
71807052 var capture_sub_scope: *Scope = &then_scope.base;
71817053 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {
7182 const capture_is_ref = token_tags[capture_token] == .asterisk;
7054 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
71837055 const ident_tok = capture_token + @intFromBool(capture_is_ref);
71847056 const capture_name = tree.tokenSlice(ident_tok);
71857057 // Skip over the comma, and on to the next capture (or the ending pipe character).
......@@ -7191,7 +7063,7 @@ fn forExpr(
71917063 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
71927064
71937065 const capture_inst = inst: {
7194 const is_counter = node_tags[input] == .for_range;
7066 const is_counter = tree.nodeTag(input) == .for_range;
71957067
71967068 if (indexable_ref == .none) {
71977069 // Special case: the main index can be used directly.
......@@ -7238,7 +7110,7 @@ fn forExpr(
72387110
72397111 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
72407112
7241 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
7113 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
72427114 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
72437115 _ = try parent_gz.add(.{
72447116 .tag = .extended,
......@@ -7255,8 +7127,7 @@ fn forExpr(
72557127 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
72567128 defer else_scope.unstack();
72577129
7258 const else_node = for_full.ast.else_expr;
7259 if (else_node != 0) {
7130 if (for_full.ast.else_expr.unwrap()) |else_node| {
72607131 const sub_scope = &else_scope.base;
72617132 // Remove the continue block and break block so that `continue` and `break`
72627133 // control flow apply to outer loops; not this one.
......@@ -7324,10 +7195,6 @@ fn switchExprErrUnion(
73247195 const astgen = parent_gz.astgen;
73257196 const gpa = astgen.gpa;
73267197 const tree = astgen.tree;
7327 const node_datas = tree.nodes.items(.data);
7328 const node_tags = tree.nodes.items(.tag);
7329 const main_tokens = tree.nodes.items(.main_token);
7330 const token_tags = tree.tokens.items(.tag);
73317198
73327199 const if_full = switch (node_ty) {
73337200 .@"catch" => undefined,
......@@ -7336,23 +7203,19 @@ fn switchExprErrUnion(
73367203
73377204 const switch_node, const operand_node, const error_payload = switch (node_ty) {
73387205 .@"catch" => .{
7339 node_datas[catch_or_if_node].rhs,
7340 node_datas[catch_or_if_node].lhs,
7341 main_tokens[catch_or_if_node] + 2,
7206 tree.nodeData(catch_or_if_node).node_and_node[1],
7207 tree.nodeData(catch_or_if_node).node_and_node[0],
7208 tree.nodeMainToken(catch_or_if_node) + 2,
73427209 },
73437210 .@"if" => .{
7344 if_full.ast.else_expr,
7211 if_full.ast.else_expr.unwrap().?,
73457212 if_full.ast.cond_expr,
73467213 if_full.error_token.?,
73477214 },
73487215 };
7349 assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma);
7216 const switch_full = tree.fullSwitch(switch_node).?;
73507217
73517218 const do_err_trace = astgen.fn_block != null;
7352
7353 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
7354 const case_nodes = tree.extra_data[extra.start..extra.end];
7355
73567219 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);
73577220 const block_ri: ResultInfo = if (need_rl) ri else .{
73587221 .rl = switch (ri.rl) {
......@@ -7364,7 +7227,7 @@ fn switchExprErrUnion(
73647227 };
73657228
73667229 const payload_is_ref = switch (node_ty) {
7367 .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk,
7230 .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk,
73687231 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,
73697232 };
73707233
......@@ -7376,9 +7239,9 @@ fn switchExprErrUnion(
73767239 var multi_cases_len: u32 = 0;
73777240 var inline_cases_len: u32 = 0;
73787241 var has_else = false;
7379 var else_node: Ast.Node.Index = 0;
7242 var else_node: Ast.Node.OptionalIndex = .none;
73807243 var else_src: ?Ast.TokenIndex = null;
7381 for (case_nodes) |case_node| {
7244 for (switch_full.ast.cases) |case_node| {
73827245 const case = tree.fullSwitchCase(case_node).?;
73837246
73847247 if (case.ast.values.len == 0) {
......@@ -7398,12 +7261,12 @@ fn switchExprErrUnion(
73987261 );
73997262 }
74007263 has_else = true;
7401 else_node = case_node;
7264 else_node = case_node.toOptional();
74027265 else_src = case_src;
74037266 continue;
74047267 } else if (case.ast.values.len == 1 and
7405 node_tags[case.ast.values[0]] == .identifier and
7406 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
7268 tree.nodeTag(case.ast.values[0]) == .identifier and
7269 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
74077270 {
74087271 const case_src = case.ast.arrow_token - 1;
74097272 return astgen.failTokNotes(
......@@ -7421,11 +7284,11 @@ fn switchExprErrUnion(
74217284 }
74227285
74237286 for (case.ast.values) |val| {
7424 if (node_tags[val] == .string_literal)
7287 if (tree.nodeTag(val) == .string_literal)
74257288 return astgen.failNode(val, "cannot switch on strings", .{});
74267289 }
74277290
7428 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
7291 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
74297292 scalar_cases_len += 1;
74307293 } else {
74317294 multi_cases_len += 1;
......@@ -7618,11 +7481,11 @@ fn switchExprErrUnion(
76187481 var multi_case_index: u32 = 0;
76197482 var scalar_case_index: u32 = 0;
76207483 var any_uses_err_capture = false;
7621 for (case_nodes) |case_node| {
7484 for (switch_full.ast.cases) |case_node| {
76227485 const case = tree.fullSwitchCase(case_node).?;
76237486
76247487 const is_multi_case = case.ast.values.len > 1 or
7625 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
7488 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
76267489
76277490 var dbg_var_name: Zir.NullTerminatedString = .empty;
76287491 var dbg_var_inst: Zir.Inst.Ref = undefined;
......@@ -7640,7 +7503,7 @@ fn switchExprErrUnion(
76407503 };
76417504
76427505 const capture_token = case.payload_token orelse break :blk &err_scope.base;
7643 if (token_tags[capture_token] != .identifier) {
7506 if (tree.tokenTag(capture_token) != .identifier) {
76447507 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});
76457508 }
76467509
......@@ -7676,7 +7539,7 @@ fn switchExprErrUnion(
76767539 // items
76777540 var items_len: u32 = 0;
76787541 for (case.ast.values) |item_node| {
7679 if (node_tags[item_node] == .switch_range) continue;
7542 if (tree.nodeTag(item_node) == .switch_range) continue;
76807543 items_len += 1;
76817544
76827545 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
......@@ -7686,11 +7549,12 @@ fn switchExprErrUnion(
76867549 // ranges
76877550 var ranges_len: u32 = 0;
76887551 for (case.ast.values) |range| {
7689 if (node_tags[range] != .switch_range) continue;
7552 if (tree.nodeTag(range) != .switch_range) continue;
76907553 ranges_len += 1;
76917554
7692 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
7693 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
7555 const first_node, const last_node = tree.nodeData(range).node_and_node;
7556 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
7557 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
76947558 try payloads.appendSlice(gpa, &[_]u32{
76957559 @intFromEnum(first), @intFromEnum(last),
76967560 });
......@@ -7699,7 +7563,7 @@ fn switchExprErrUnion(
76997563 payloads.items[header_index] = items_len;
77007564 payloads.items[header_index + 1] = ranges_len;
77017565 break :blk header_index + 2;
7702 } else if (case_node == else_node) blk: {
7566 } else if (case_node.toOptional() == else_node) blk: {
77037567 payloads.items[case_table_start + 1] = header_index;
77047568 try payloads.resize(gpa, header_index + 1); // body_len
77057569 break :blk header_index;
......@@ -7729,7 +7593,7 @@ fn switchExprErrUnion(
77297593 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);
77307594 // check capture_scope, not err_scope to avoid false positive unused error capture
77317595 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
7732 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;
7596 const uses_err = err_scope.used != .none or err_scope.discarded != .none;
77337597 if (uses_err) {
77347598 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());
77357599 any_uses_err_capture = true;
......@@ -7829,10 +7693,6 @@ fn switchExpr(
78297693 const astgen = parent_gz.astgen;
78307694 const gpa = astgen.gpa;
78317695 const tree = astgen.tree;
7832 const node_datas = tree.nodes.items(.data);
7833 const node_tags = tree.nodes.items(.tag);
7834 const main_tokens = tree.nodes.items(.main_token);
7835 const token_tags = tree.tokens.items(.tag);
78367696 const operand_node = switch_full.ast.condition;
78377697 const case_nodes = switch_full.ast.cases;
78387698
......@@ -7864,17 +7724,17 @@ fn switchExpr(
78647724 var multi_cases_len: u32 = 0;
78657725 var inline_cases_len: u32 = 0;
78667726 var special_prong: Zir.SpecialProng = .none;
7867 var special_node: Ast.Node.Index = 0;
7727 var special_node: Ast.Node.OptionalIndex = .none;
78687728 var else_src: ?Ast.TokenIndex = null;
78697729 var underscore_src: ?Ast.TokenIndex = null;
78707730 for (case_nodes) |case_node| {
78717731 const case = tree.fullSwitchCase(case_node).?;
78727732 if (case.payload_token) |payload_token| {
7873 const ident = if (token_tags[payload_token] == .asterisk) blk: {
7733 const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: {
78747734 any_payload_is_ref = true;
78757735 break :blk payload_token + 1;
78767736 } else payload_token;
7877 if (token_tags[ident + 1] == .comma) {
7737 if (tree.tokenTag(ident + 1) == .comma) {
78787738 any_has_tag_capture = true;
78797739 }
78807740
......@@ -7922,13 +7782,13 @@ fn switchExpr(
79227782 },
79237783 );
79247784 }
7925 special_node = case_node;
7785 special_node = case_node.toOptional();
79267786 special_prong = .@"else";
79277787 else_src = case_src;
79287788 continue;
79297789 } else if (case.ast.values.len == 1 and
7930 node_tags[case.ast.values[0]] == .identifier and
7931 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
7790 tree.nodeTag(case.ast.values[0]) == .identifier and
7791 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
79327792 {
79337793 const case_src = case.ast.arrow_token - 1;
79347794 if (underscore_src) |src| {
......@@ -7966,18 +7826,18 @@ fn switchExpr(
79667826 if (case.inline_token != null) {
79677827 return astgen.failTok(case_src, "cannot inline '_' prong", .{});
79687828 }
7969 special_node = case_node;
7829 special_node = case_node.toOptional();
79707830 special_prong = .under;
79717831 underscore_src = case_src;
79727832 continue;
79737833 }
79747834
79757835 for (case.ast.values) |val| {
7976 if (node_tags[val] == .string_literal)
7836 if (tree.nodeTag(val) == .string_literal)
79777837 return astgen.failNode(val, "cannot switch on strings", .{});
79787838 }
79797839
7980 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
7840 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
79817841 scalar_cases_len += 1;
79827842 } else {
79837843 multi_cases_len += 1;
......@@ -8066,7 +7926,7 @@ fn switchExpr(
80667926 const case = tree.fullSwitchCase(case_node).?;
80677927
80687928 const is_multi_case = case.ast.values.len > 1 or
8069 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
7929 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
80707930
80717931 var dbg_var_name: Zir.NullTerminatedString = .empty;
80727932 var dbg_var_inst: Zir.Inst.Ref = undefined;
......@@ -8080,18 +7940,15 @@ fn switchExpr(
80807940
80817941 const sub_scope = blk: {
80827942 const payload_token = case.payload_token orelse break :blk &case_scope.base;
8083 const ident = if (token_tags[payload_token] == .asterisk)
8084 payload_token + 1
8085 else
8086 payload_token;
7943 const capture_is_ref = tree.tokenTag(payload_token) == .asterisk;
7944 const ident = payload_token + @intFromBool(capture_is_ref);
80877945
8088 const is_ptr = ident != payload_token;
8089 capture = if (is_ptr) .by_ref else .by_val;
7946 capture = if (capture_is_ref) .by_ref else .by_val;
80907947
80917948 const ident_slice = tree.tokenSlice(ident);
80927949 var payload_sub_scope: *Scope = undefined;
80937950 if (mem.eql(u8, ident_slice, "_")) {
8094 if (is_ptr) {
7951 if (capture_is_ref) {
80957952 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
80967953 }
80977954 payload_sub_scope = &case_scope.base;
......@@ -8111,7 +7968,7 @@ fn switchExpr(
81117968 payload_sub_scope = &capture_val_scope.base;
81127969 }
81137970
8114 const tag_token = if (token_tags[ident + 1] == .comma)
7971 const tag_token = if (tree.tokenTag(ident + 1) == .comma)
81157972 ident + 2
81167973 else
81177974 break :blk payload_sub_scope;
......@@ -8149,7 +8006,7 @@ fn switchExpr(
81498006 // items
81508007 var items_len: u32 = 0;
81518008 for (case.ast.values) |item_node| {
8152 if (node_tags[item_node] == .switch_range) continue;
8009 if (tree.nodeTag(item_node) == .switch_range) continue;
81538010 items_len += 1;
81548011
81558012 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
......@@ -8159,11 +8016,12 @@ fn switchExpr(
81598016 // ranges
81608017 var ranges_len: u32 = 0;
81618018 for (case.ast.values) |range| {
8162 if (node_tags[range] != .switch_range) continue;
8019 if (tree.nodeTag(range) != .switch_range) continue;
81638020 ranges_len += 1;
81648021
8165 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
8166 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
8022 const first_node, const last_node = tree.nodeData(range).node_and_node;
8023 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
8024 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
81678025 try payloads.appendSlice(gpa, &[_]u32{
81688026 @intFromEnum(first), @intFromEnum(last),
81698027 });
......@@ -8172,7 +8030,7 @@ fn switchExpr(
81728030 payloads.items[header_index] = items_len;
81738031 payloads.items[header_index + 1] = ranges_len;
81748032 break :blk header_index + 2;
8175 } else if (case_node == special_node) blk: {
8033 } else if (case_node.toOptional() == special_node) blk: {
81768034 payloads.items[case_table_start] = header_index;
81778035 try payloads.resize(gpa, header_index + 1); // body_len
81788036 break :blk header_index;
......@@ -8285,17 +8143,15 @@ fn switchExpr(
82858143fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
82868144 const astgen = gz.astgen;
82878145 const tree = astgen.tree;
8288 const node_datas = tree.nodes.items(.data);
8289 const node_tags = tree.nodes.items(.tag);
82908146
82918147 if (astgen.fn_block == null) {
82928148 return astgen.failNode(node, "'return' outside function scope", .{});
82938149 }
82948150
8295 if (gz.any_defer_node != 0) {
8151 if (gz.any_defer_node.unwrap()) |any_defer_node| {
82968152 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{
82978153 try astgen.errNoteNode(
8298 gz.any_defer_node,
8154 any_defer_node,
82998155 "defer expression here",
83008156 .{},
83018157 ),
......@@ -8313,8 +8169,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
83138169
83148170 const defer_outer = &astgen.fn_block.?.base;
83158171
8316 const operand_node = node_datas[node].lhs;
8317 if (operand_node == 0) {
8172 const operand_node = tree.nodeData(node).opt_node.unwrap() orelse {
83188173 // Returning a void value; skip error defers.
83198174 try genDefers(gz, defer_outer, scope, .normal_only);
83208175
......@@ -8323,12 +8178,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
83238178
83248179 _ = try gz.addUnNode(.ret_node, .void_value, node);
83258180 return Zir.Inst.Ref.unreachable_value;
8326 }
8181 };
83278182
8328 if (node_tags[operand_node] == .error_value) {
8183 if (tree.nodeTag(operand_node) == .error_value) {
83298184 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic
83308185 // for detecting whether to add something to the function's inferred error set.
8331 const ident_token = node_datas[operand_node].rhs;
8186 const ident_token = tree.nodeMainToken(operand_node) + 2;
83328187 const err_name_str_index = try astgen.identAsString(ident_token);
83338188 const defer_counts = countDefers(defer_outer, scope);
83348189 if (!defer_counts.need_err_code) {
......@@ -8459,9 +8314,8 @@ fn identifier(
84598314) InnerError!Zir.Inst.Ref {
84608315 const astgen = gz.astgen;
84618316 const tree = astgen.tree;
8462 const main_tokens = tree.nodes.items(.main_token);
84638317
8464 const ident_token = main_tokens[ident];
8318 const ident_token = tree.nodeMainToken(ident);
84658319 const ident_name_raw = tree.tokenSlice(ident_token);
84668320 if (mem.eql(u8, ident_name_raw, "_")) {
84678321 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
......@@ -8563,9 +8417,9 @@ fn localVarRef(
85638417 // Locals cannot shadow anything, so we do not need to look for ambiguous
85648418 // references in this case.
85658419 if (ri.rl == .discard and ri.ctx == .assignment) {
8566 local_val.discarded = ident_token;
8420 local_val.discarded = .fromToken(ident_token);
85678421 } else {
8568 local_val.used = ident_token;
8422 local_val.used = .fromToken(ident_token);
85698423 }
85708424
85718425 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
......@@ -8587,9 +8441,9 @@ fn localVarRef(
85878441 const local_ptr = s.cast(Scope.LocalPtr).?;
85888442 if (local_ptr.name == name_str_index) {
85898443 if (ri.rl == .discard and ri.ctx == .assignment) {
8590 local_ptr.discarded = ident_token;
8444 local_ptr.discarded = .fromToken(ident_token);
85918445 } else {
8592 local_ptr.used = ident_token;
8446 local_ptr.used = .fromToken(ident_token);
85938447 }
85948448
85958449 // Can't close over a runtime variable
......@@ -8802,8 +8656,7 @@ fn stringLiteral(
88028656) InnerError!Zir.Inst.Ref {
88038657 const astgen = gz.astgen;
88048658 const tree = astgen.tree;
8805 const main_tokens = tree.nodes.items(.main_token);
8806 const str_lit_token = main_tokens[node];
8659 const str_lit_token = tree.nodeMainToken(node);
88078660 const str = try astgen.strLitAsString(str_lit_token);
88088661 const result = try gz.add(.{
88098662 .tag = .str,
......@@ -8835,8 +8688,7 @@ fn multilineStringLiteral(
88358688fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
88368689 const astgen = gz.astgen;
88378690 const tree = astgen.tree;
8838 const main_tokens = tree.nodes.items(.main_token);
8839 const main_token = main_tokens[node];
8691 const main_token = tree.nodeMainToken(node);
88408692 const slice = tree.tokenSlice(main_token);
88418693
88428694 switch (std.zig.parseCharLiteral(slice)) {
......@@ -8853,8 +8705,7 @@ const Sign = enum { negative, positive };
88538705fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
88548706 const astgen = gz.astgen;
88558707 const tree = astgen.tree;
8856 const main_tokens = tree.nodes.items(.main_token);
8857 const num_token = main_tokens[node];
8708 const num_token = tree.nodeMainToken(node);
88588709 const bytes = tree.tokenSlice(num_token);
88598710
88608711 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
......@@ -8972,16 +8823,12 @@ fn asmExpr(
89728823) InnerError!Zir.Inst.Ref {
89738824 const astgen = gz.astgen;
89748825 const tree = astgen.tree;
8975 const main_tokens = tree.nodes.items(.main_token);
8976 const node_datas = tree.nodes.items(.data);
8977 const node_tags = tree.nodes.items(.tag);
8978 const token_tags = tree.tokens.items(.tag);
89798826
89808827 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };
8981 const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) {
8828 const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) {
89828829 .string_literal => .{
89838830 .tag = .@"asm",
8984 .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index,
8831 .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index,
89858832 },
89868833 .multiline_string_literal => .{
89878834 .tag = .@"asm",
......@@ -9016,17 +8863,17 @@ fn asmExpr(
90168863 var output_type_bits: u32 = 0;
90178864
90188865 for (full.outputs, 0..) |output_node, i| {
9019 const symbolic_name = main_tokens[output_node];
8866 const symbolic_name = tree.nodeMainToken(output_node);
90208867 const name = try astgen.identAsString(symbolic_name);
90218868 const constraint_token = symbolic_name + 2;
90228869 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9023 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
8870 const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow;
90248871 if (has_arrow) {
90258872 if (output_type_bits != 0) {
90268873 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});
90278874 }
90288875 output_type_bits |= @as(u32, 1) << @intCast(i);
9029 const out_type_node = node_datas[output_node].lhs;
8876 const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?;
90308877 const out_type_inst = try typeExpr(gz, scope, out_type_node);
90318878 outputs[i] = .{
90328879 .name = name,
......@@ -9053,11 +8900,11 @@ fn asmExpr(
90538900 const inputs = inputs_buffer[0..full.inputs.len];
90548901
90558902 for (full.inputs, 0..) |input_node, i| {
9056 const symbolic_name = main_tokens[input_node];
8903 const symbolic_name = tree.nodeMainToken(input_node);
90578904 const name = try astgen.identAsString(symbolic_name);
90588905 const constraint_token = symbolic_name + 2;
90598906 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9060 const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs);
8907 const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]);
90618908 inputs[i] = .{
90628909 .name = name,
90638910 .constraint = constraint,
......@@ -9078,10 +8925,10 @@ fn asmExpr(
90788925 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);
90798926 clobber_i += 1;
90808927 tok_i += 1;
9081 switch (token_tags[tok_i]) {
8928 switch (tree.tokenTag(tok_i)) {
90828929 .r_paren => break :clobbers,
90838930 .comma => {
9084 if (token_tags[tok_i + 1] == .r_paren) {
8931 if (tree.tokenTag(tok_i + 1) == .r_paren) {
90858932 break :clobbers;
90868933 } else {
90878934 continue;
......@@ -9173,9 +9020,6 @@ fn ptrCast(
91739020) InnerError!Zir.Inst.Ref {
91749021 const astgen = gz.astgen;
91759022 const tree = astgen.tree;
9176 const main_tokens = tree.nodes.items(.main_token);
9177 const node_datas = tree.nodes.items(.data);
9178 const node_tags = tree.nodes.items(.tag);
91799023
91809024 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
91819025 var flags: Zir.Inst.FullPtrCastFlags = .{};
......@@ -9184,23 +9028,26 @@ fn ptrCast(
91849028 // to handle `builtin_call_two`.
91859029 var node = root_node;
91869030 while (true) {
9187 switch (node_tags[node]) {
9031 switch (tree.nodeTag(node)) {
91889032 .builtin_call_two, .builtin_call_two_comma => {},
91899033 .grouped_expression => {
91909034 // Handle the chaining even with redundant parentheses
9191 node = node_datas[node].lhs;
9035 node = tree.nodeData(node).node_and_token[0];
91929036 continue;
91939037 },
91949038 else => break,
91959039 }
91969040
9197 if (node_datas[node].lhs == 0) break; // 0 args
9041 var buf: [2]Ast.Node.Index = undefined;
9042 const args = tree.builtinCallParams(&buf, node).?;
9043 std.debug.assert(args.len <= 2);
9044
9045 if (args.len == 0) break; // 0 args
91989046
9199 const builtin_token = main_tokens[node];
9047 const builtin_token = tree.nodeMainToken(node);
92009048 const builtin_name = tree.tokenSlice(builtin_token);
92019049 const info = BuiltinFn.list.get(builtin_name) orelse break;
9202 if (node_datas[node].rhs == 0) {
9203 // 1 arg
9050 if (args.len == 1) {
92049051 if (info.param_count != 1) break;
92059052
92069053 switch (info.tag) {
......@@ -9218,9 +9065,9 @@ fn ptrCast(
92189065 },
92199066 }
92209067
9221 node = node_datas[node].lhs;
9068 node = args[0];
92229069 } else {
9223 // 2 args
9070 std.debug.assert(args.len == 2);
92249071 if (info.param_count != 2) break;
92259072
92269073 switch (info.tag) {
......@@ -9231,8 +9078,8 @@ fn ptrCast(
92319078 const flags_int: FlagsInt = @bitCast(flags);
92329079 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
92339080 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
9234 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs, .field_name);
9235 const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);
9081 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, args[0], .field_name);
9082 const field_ptr = try expr(gz, scope, .{ .rl = .none }, args[1]);
92369083 try emitDbgStmt(gz, cursor);
92379084 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
92389085 .src_node = gz.nodeIndexToRelative(node),
......@@ -9397,9 +9244,8 @@ fn builtinCall(
93979244) InnerError!Zir.Inst.Ref {
93989245 const astgen = gz.astgen;
93999246 const tree = astgen.tree;
9400 const main_tokens = tree.nodes.items(.main_token);
94019247
9402 const builtin_token = main_tokens[node];
9248 const builtin_token = tree.nodeMainToken(node);
94039249 const builtin_name = tree.tokenSlice(builtin_token);
94049250
94059251 // We handle the different builtins manually because they have different semantics depending
......@@ -9440,14 +9286,13 @@ fn builtinCall(
94409286 return rvalue(gz, ri, .void_value, node);
94419287 },
94429288 .import => {
9443 const node_tags = tree.nodes.items(.tag);
94449289 const operand_node = params[0];
94459290
9446 if (node_tags[operand_node] != .string_literal) {
9291 if (tree.nodeTag(operand_node) != .string_literal) {
94479292 // Spec reference: https://github.com/ziglang/zig/issues/2206
94489293 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
94499294 }
9450 const str_lit_token = main_tokens[operand_node];
9295 const str_lit_token = tree.nodeMainToken(operand_node);
94519296 const str = try astgen.strLitAsString(str_lit_token);
94529297 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];
94539298 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
......@@ -9558,8 +9403,7 @@ fn builtinCall(
95589403 std.mem.asBytes(&astgen.source_column),
95599404 );
95609405
9561 const token_starts = tree.tokens.items(.start);
9562 const node_start = token_starts[tree.firstToken(node)];
9406 const node_start = tree.tokenStart(tree.firstToken(node));
95639407 astgen.advanceSourceCursor(node_start);
95649408 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{
95659409 .node = gz.nodeIndexToRelative(node),
......@@ -9839,7 +9683,7 @@ fn builtinCall(
98399683 .callee = callee,
98409684 .args = args,
98419685 .flags = .{
9842 .is_nosuspend = gz.nosuspend_node != 0,
9686 .is_nosuspend = gz.nosuspend_node != .none,
98439687 .ensure_result_used = false,
98449688 },
98459689 });
......@@ -10064,13 +9908,11 @@ fn negation(
100649908) InnerError!Zir.Inst.Ref {
100659909 const astgen = gz.astgen;
100669910 const tree = astgen.tree;
10067 const node_tags = tree.nodes.items(.tag);
10068 const node_datas = tree.nodes.items(.data);
100699911
100709912 // Check for float literal as the sub-expression because we want to preserve
100719913 // its negativity rather than having it go through comptime subtraction.
10072 const operand_node = node_datas[node].lhs;
10073 if (node_tags[operand_node] == .number_literal) {
9914 const operand_node = tree.nodeData(node).node;
9915 if (tree.nodeTag(operand_node) == .number_literal) {
100749916 return numberLiteral(gz, ri, operand_node, node, .negative);
100759917 }
100769918
......@@ -10186,7 +10028,7 @@ fn shiftOp(
1018610028) InnerError!Zir.Inst.Ref {
1018710029 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
1018810030
10189 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {
10031 const cursor = switch (gz.astgen.tree.nodeTag(node)) {
1019010032 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
1019110033 else => undefined,
1019210034 };
......@@ -10194,7 +10036,7 @@ fn shiftOp(
1019410036 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
1019510037 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
1019610038
10197 switch (gz.astgen.tree.nodes.items(.tag)[node]) {
10039 switch (gz.astgen.tree.nodeTag(node)) {
1019810040 .shl, .shr => try emitDbgStmt(gz, cursor),
1019910041 else => undefined,
1020010042 }
......@@ -10270,14 +10112,14 @@ fn callExpr(
1027010112 if (call.async_token != null) {
1027110113 break :blk .async_kw;
1027210114 }
10273 if (gz.nosuspend_node != 0) {
10115 if (gz.nosuspend_node != .none) {
1027410116 break :blk .no_async;
1027510117 }
1027610118 break :blk .auto;
1027710119 };
1027810120
1027910121 {
10280 astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]);
10122 astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen));
1028110123 const line = astgen.source_line - gz.decl_line;
1028210124 const column = astgen.source_column;
1028310125 // Sema expects a dbg_stmt immediately before call,
......@@ -10288,7 +10130,6 @@ fn callExpr(
1028810130 .direct => |obj| assert(obj != .none),
1028910131 .field => |field| assert(field.obj_ptr != .none),
1029010132 }
10291 assert(node != 0);
1029210133
1029310134 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
1029410135 const call_inst = call_index.toRef();
......@@ -10399,14 +10240,10 @@ fn calleeExpr(
1039910240 const astgen = gz.astgen;
1040010241 const tree = astgen.tree;
1040110242
10402 const tag = tree.nodes.items(.tag)[node];
10243 const tag = tree.nodeTag(node);
1040310244 switch (tag) {
1040410245 .field_access => {
10405 const main_tokens = tree.nodes.items(.main_token);
10406 const node_datas = tree.nodes.items(.data);
10407 const object_node = node_datas[node].lhs;
10408 const dot_token = main_tokens[node];
10409 const field_ident = dot_token + 1;
10246 const object_node, const field_ident = tree.nodeData(node).node_and_token;
1041010247 const str_index = try astgen.identAsString(field_ident);
1041110248 // Capture the object by reference so we can promote it to an
1041210249 // address in Sema if needed.
......@@ -10431,7 +10268,7 @@ fn calleeExpr(
1043110268 // Decl literal call syntax, e.g.
1043210269 // `const foo: T = .init();`
1043310270 // Look up `init` in `T`, but don't try and coerce it.
10434 const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]);
10271 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
1043510272 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{
1043610273 .lhs = res_ty,
1043710274 .field_name_start = str_index,
......@@ -10503,12 +10340,9 @@ comptime {
1050310340}
1050410341
1050510342fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10506 const node_tags = tree.nodes.items(.tag);
10507 const main_tokens = tree.nodes.items(.main_token);
10508
10509 switch (node_tags[node]) {
10343 switch (tree.nodeTag(node)) {
1051010344 .number_literal => {
10511 const ident = main_tokens[node];
10345 const ident = tree.nodeMainToken(node);
1051210346 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {
1051310347 .int => |number| switch (number) {
1051410348 0 => true,
......@@ -10522,12 +10356,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
1052210356}
1052310357
1052410358fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {
10525 const node_tags = tree.nodes.items(.tag);
10526 const node_datas = tree.nodes.items(.data);
10527
1052810359 var node = start_node;
1052910360 while (true) {
10530 switch (node_tags[node]) {
10361 switch (tree.nodeTag(node)) {
1053110362 // These don't have the opportunity to call any runtime functions.
1053210363 .error_value,
1053310364 .identifier,
......@@ -10535,11 +10366,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
1053510366 => return false,
1053610367
1053710368 // Forward the question to the LHS sub-expression.
10538 .grouped_expression,
1053910369 .@"try",
1054010370 .@"nosuspend",
10371 => node = tree.nodeData(node).node,
10372 .grouped_expression,
1054110373 .unwrap_optional,
10542 => node = node_datas[node].lhs,
10374 => node = tree.nodeData(node).node_and_token[0],
1054310375
1054410376 // Anything that does not eval to an error is guaranteed to pop any
1054510377 // additions to the error trace, so it effectively does not append.
......@@ -10549,14 +10381,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
1054910381}
1055010382
1055110383fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
10552 const node_tags = tree.nodes.items(.tag);
10553 const node_datas = tree.nodes.items(.data);
10554 const main_tokens = tree.nodes.items(.main_token);
10555 const token_tags = tree.tokens.items(.tag);
10556
1055710384 var node = start_node;
1055810385 while (true) {
10559 switch (node_tags[node]) {
10386 switch (tree.nodeTag(node)) {
1056010387 .root,
1056110388 .@"usingnamespace",
1056210389 .test_decl,
......@@ -10719,13 +10546,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1071910546 => return .never,
1072010547
1072110548 // Forward the question to the LHS sub-expression.
10722 .grouped_expression,
1072310549 .@"try",
1072410550 .@"await",
1072510551 .@"comptime",
1072610552 .@"nosuspend",
10553 => node = tree.nodeData(node).node,
10554 .grouped_expression,
1072710555 .unwrap_optional,
10728 => node = node_datas[node].lhs,
10556 => node = tree.nodeData(node).node_and_token[0],
1072910557
1073010558 // LHS sub-expression may still be an error under the outer optional or error union
1073110559 .@"catch",
......@@ -10737,8 +10565,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1073710565 .block,
1073810566 .block_semicolon,
1073910567 => {
10740 const lbrace = main_tokens[node];
10741 if (token_tags[lbrace - 1] == .colon) {
10568 const lbrace = tree.nodeMainToken(node);
10569 if (tree.tokenTag(lbrace - 1) == .colon) {
1074210570 // Labeled blocks may need a memory location to forward
1074310571 // to their break statements.
1074410572 return .maybe;
......@@ -10752,7 +10580,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1075210580 .builtin_call_two,
1075310581 .builtin_call_two_comma,
1075410582 => {
10755 const builtin_token = main_tokens[node];
10583 const builtin_token = tree.nodeMainToken(node);
1075610584 const builtin_name = tree.tokenSlice(builtin_token);
1075710585 // If the builtin is an invalid name, we don't cause an error here; instead
1075810586 // let it pass, and the error will be "invalid builtin function" later.
......@@ -10766,12 +10594,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1076610594/// Returns `true` if it is known the type expression has more than one possible value;
1076710595/// `false` otherwise.
1076810596fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
10769 const node_tags = tree.nodes.items(.tag);
10770 const node_datas = tree.nodes.items(.data);
10771
1077210597 var node = start_node;
1077310598 while (true) {
10774 switch (node_tags[node]) {
10599 switch (tree.nodeTag(node)) {
1077510600 .root,
1077610601 .@"usingnamespace",
1077710602 .test_decl,
......@@ -10934,13 +10759,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1093410759 => return false,
1093510760
1093610761 // Forward the question to the LHS sub-expression.
10937 .grouped_expression,
1093810762 .@"try",
1093910763 .@"await",
1094010764 .@"comptime",
1094110765 .@"nosuspend",
10766 => node = tree.nodeData(node).node,
10767 .grouped_expression,
1094210768 .unwrap_optional,
10943 => node = node_datas[node].lhs,
10769 => node = tree.nodeData(node).node_and_token[0],
1094410770
1094510771 .ptr_type_aligned,
1094610772 .ptr_type_sentinel,
......@@ -10952,8 +10778,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1095210778 => return true,
1095310779
1095410780 .identifier => {
10955 const main_tokens = tree.nodes.items(.main_token);
10956 const ident_bytes = tree.tokenSlice(main_tokens[node]);
10781 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
1095710782 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
1095810783 .anyerror_type,
1095910784 .anyframe_type,
......@@ -11013,12 +10838,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1101310838/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
1101410839/// `false` otherwise.
1101510840fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
11016 const node_tags = tree.nodes.items(.tag);
11017 const node_datas = tree.nodes.items(.data);
11018
1101910841 var node = start_node;
1102010842 while (true) {
11021 switch (node_tags[node]) {
10843 switch (tree.nodeTag(node)) {
1102210844 .root,
1102310845 .@"usingnamespace",
1102410846 .test_decl,
......@@ -11190,17 +11012,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1119011012 => return true,
1119111013
1119211014 // Forward the question to the LHS sub-expression.
11193 .grouped_expression,
1119411015 .@"try",
1119511016 .@"await",
1119611017 .@"comptime",
1119711018 .@"nosuspend",
11019 => node = tree.nodeData(node).node,
11020 .grouped_expression,
1119811021 .unwrap_optional,
11199 => node = node_datas[node].lhs,
11022 => node = tree.nodeData(node).node_and_token[0],
1120011023
1120111024 .identifier => {
11202 const main_tokens = tree.nodes.items(.main_token);
11203 const ident_bytes = tree.tokenSlice(main_tokens[node]);
11025 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
1120411026 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
1120511027 .anyerror_type,
1120611028 .anyframe_type,
......@@ -11259,8 +11081,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1125911081
1126011082/// Returns `true` if the node uses `gz.anon_name_strategy`.
1126111083fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11262 const node_tags = tree.nodes.items(.tag);
11263 switch (node_tags[node]) {
11084 switch (tree.nodeTag(node)) {
1126411085 .container_decl,
1126511086 .container_decl_trailing,
1126611087 .container_decl_two,
......@@ -11275,7 +11096,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
1127511096 .tagged_union_enum_tag_trailing,
1127611097 => return true,
1127711098 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {
11278 const builtin_token = tree.nodes.items(.main_token)[node];
11099 const builtin_token = tree.nodeMainToken(node);
1127911100 const builtin_name = tree.tokenSlice(builtin_token);
1128011101 return std.mem.eql(u8, builtin_name, "@Type");
1128111102 },
......@@ -11508,8 +11329,7 @@ fn rvalueInner(
1150811329/// See also `appendIdentStr` and `parseStrLit`.
1150911330fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {
1151011331 const tree = astgen.tree;
11511 const token_tags = tree.tokens.items(.tag);
11512 assert(token_tags[token] == .identifier);
11332 assert(tree.tokenTag(token) == .identifier);
1151311333 const ident_name = tree.tokenSlice(token);
1151411334 if (!mem.startsWith(u8, ident_name, "@")) {
1151511335 return ident_name;
......@@ -11535,8 +11355,7 @@ fn appendIdentStr(
1153511355 buf: *ArrayListUnmanaged(u8),
1153611356) InnerError!void {
1153711357 const tree = astgen.tree;
11538 const token_tags = tree.tokens.items(.tag);
11539 assert(token_tags[token] == .identifier);
11358 assert(tree.tokenTag(token) == .identifier);
1154011359 const ident_name = tree.tokenSlice(token);
1154111360 if (!mem.startsWith(u8, ident_name, "@")) {
1154211361 return buf.appendSlice(astgen.gpa, ident_name);
......@@ -11625,8 +11444,8 @@ fn appendErrorNodeNotes(
1162511444 } else 0;
1162611445 try astgen.compile_errors.append(astgen.gpa, .{
1162711446 .msg = msg,
11628 .node = node,
11629 .token = 0,
11447 .node = node.toOptional(),
11448 .token = .none,
1163011449 .byte_offset = 0,
1163111450 .notes = notes_index,
1163211451 });
......@@ -11717,8 +11536,8 @@ fn appendErrorTokNotesOff(
1171711536 } else 0;
1171811537 try astgen.compile_errors.append(gpa, .{
1171911538 .msg = msg,
11720 .node = 0,
11721 .token = token,
11539 .node = .none,
11540 .token = .fromToken(token),
1172211541 .byte_offset = byte_offset,
1172311542 .notes = notes_index,
1172411543 });
......@@ -11746,8 +11565,8 @@ fn errNoteTokOff(
1174611565 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1174711566 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1174811567 .msg = msg,
11749 .node = 0,
11750 .token = token,
11568 .node = .none,
11569 .token = .fromToken(token),
1175111570 .byte_offset = byte_offset,
1175211571 .notes = 0,
1175311572 });
......@@ -11765,8 +11584,8 @@ fn errNoteNode(
1176511584 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1176611585 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1176711586 .msg = msg,
11768 .node = node,
11769 .token = 0,
11587 .node = node.toOptional(),
11588 .token = .none,
1177011589 .byte_offset = 0,
1177111590 .notes = 0,
1177211591 });
......@@ -11832,10 +11651,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1183211651
1183311652fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
1183411653 const tree = astgen.tree;
11835 const node_datas = tree.nodes.items(.data);
1183611654
11837 const start = node_datas[node].lhs;
11838 const end = node_datas[node].rhs;
11655 const start, const end = tree.nodeData(node).token_and_token;
1183911656
1184011657 const gpa = astgen.gpa;
1184111658 const string_bytes = &astgen.string_bytes;
......@@ -11930,11 +11747,11 @@ const Scope = struct {
1193011747 /// Source location of the corresponding variable declaration.
1193111748 token_src: Ast.TokenIndex,
1193211749 /// Track the first identifier where it is referenced.
11933 /// 0 means never referenced.
11934 used: Ast.TokenIndex = 0,
11750 /// .none means never referenced.
11751 used: Ast.OptionalTokenIndex = .none,
1193511752 /// Track the identifier where it is discarded, like this `_ = foo;`.
11936 /// 0 means never discarded.
11937 discarded: Ast.TokenIndex = 0,
11753 /// .none means never discarded.
11754 discarded: Ast.OptionalTokenIndex = .none,
1193811755 is_used_or_discarded: ?*bool = null,
1193911756 /// String table index.
1194011757 name: Zir.NullTerminatedString,
......@@ -11954,11 +11771,11 @@ const Scope = struct {
1195411771 /// Source location of the corresponding variable declaration.
1195511772 token_src: Ast.TokenIndex,
1195611773 /// Track the first identifier where it is referenced.
11957 /// 0 means never referenced.
11958 used: Ast.TokenIndex = 0,
11774 /// .none means never referenced.
11775 used: Ast.OptionalTokenIndex = .none,
1195911776 /// Track the identifier where it is discarded, like this `_ = foo;`.
11960 /// 0 means never discarded.
11961 discarded: Ast.TokenIndex = 0,
11777 /// .none means never discarded.
11778 discarded: Ast.OptionalTokenIndex = .none,
1196211779 /// Whether this value is used as an lvalue after initialization.
1196311780 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.
1196411781 used_as_lvalue: bool = false,
......@@ -12053,12 +11870,12 @@ const GenZir = struct {
1205311870 break_result_info: AstGen.ResultInfo = undefined,
1205411871 continue_result_info: AstGen.ResultInfo = undefined,
1205511872
12056 suspend_node: Ast.Node.Index = 0,
12057 nosuspend_node: Ast.Node.Index = 0,
11873 suspend_node: Ast.Node.OptionalIndex = .none,
11874 nosuspend_node: Ast.Node.OptionalIndex = .none,
1205811875 /// Set if this GenZir is a defer.
12059 cur_defer_node: Ast.Node.Index = 0,
11876 cur_defer_node: Ast.Node.OptionalIndex = .none,
1206011877 // Set if this GenZir is a defer or it is inside a defer.
12061 any_defer_node: Ast.Node.Index = 0,
11878 any_defer_node: Ast.Node.OptionalIndex = .none,
1206211879
1206311880 const unstacked_top = std.math.maxInt(usize);
1206411881 /// Call unstack before adding any new instructions to containing GenZir.
......@@ -12139,12 +11956,12 @@ const GenZir = struct {
1213911956 return false;
1214011957 }
1214111958
12142 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 {
12143 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index));
11959 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset {
11960 return gz.decl_node_index.toOffset(node_index);
1214411961 }
1214511962
12146 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 {
12147 return token - gz.srcToken();
11963 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset {
11964 return .init(gz.srcToken(), token);
1214811965 }
1214911966
1215011967 fn srcToken(gz: GenZir) Ast.TokenIndex {
......@@ -12297,7 +12114,7 @@ const GenZir = struct {
1229712114 proto_hash: std.zig.SrcHash,
1229812115 },
1229912116 ) !Zir.Inst.Ref {
12300 assert(args.src_node != 0);
12117 assert(args.src_node != .root);
1230112118 const astgen = gz.astgen;
1230212119 const gpa = astgen.gpa;
1230312120 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
......@@ -12329,13 +12146,13 @@ const GenZir = struct {
1232912146 var src_locs_and_hash_buffer: [7]u32 = undefined;
1233012147 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {
1233112148 const tree = astgen.tree;
12332 const node_tags = tree.nodes.items(.tag);
12333 const node_datas = tree.nodes.items(.data);
12334 const token_starts = tree.tokens.items(.start);
1233512149 const fn_decl = args.src_node;
12336 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
12337 const block = node_datas[fn_decl].rhs;
12338 const rbrace_start = token_starts[tree.lastToken(block)];
12150 const block = switch (tree.nodeTag(fn_decl)) {
12151 .fn_decl => tree.nodeData(fn_decl).node_and_node[1],
12152 .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1],
12153 else => unreachable,
12154 };
12155 const rbrace_start = tree.tokenStart(tree.lastToken(block));
1233912156 astgen.advanceSourceCursor(rbrace_start);
1234012157 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);
1234112158 const rbrace_column: u32 = @intCast(astgen.source_column);
......@@ -12742,7 +12559,7 @@ const GenZir = struct {
1274212559 .data = .{ .extended = .{
1274312560 .opcode = opcode,
1274412561 .small = small,
12745 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),
12562 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
1274612563 } },
1274712564 });
1274812565 gz.instructions.appendAssumeCapacity(new_index);
......@@ -12931,9 +12748,9 @@ const GenZir = struct {
1293112748 .operand = operand,
1293212749 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{
1293312750 .operand_src_node = if (operand_src_node) |src_node|
12934 gz.nodeIndexToRelative(src_node)
12751 gz.nodeIndexToRelative(src_node).toOptional()
1293512752 else
12936 Zir.Inst.Break.no_src_node,
12753 .none,
1293712754 .block_inst = block_inst,
1293812755 }),
1293912756 } },
......@@ -13022,7 +12839,7 @@ const GenZir = struct {
1302212839 .data = .{ .extended = .{
1302312840 .opcode = opcode,
1302412841 .small = undefined,
13025 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),
12842 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
1302612843 } },
1302712844 });
1302812845 }
......@@ -13202,8 +13019,8 @@ const GenZir = struct {
1320213019 const astgen = gz.astgen;
1320313020 const gpa = astgen.gpa;
1320413021
13205 // Node 0 is valid for the root `struct_decl` of a file!
13206 assert(args.src_node != 0 or gz.parent.tag == .top);
13022 // Node .root is valid for the root `struct_decl` of a file!
13023 assert(args.src_node != .root or gz.parent.tag == .top);
1320713024
1320813025 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1320913026
......@@ -13263,7 +13080,7 @@ const GenZir = struct {
1326313080 const astgen = gz.astgen;
1326413081 const gpa = astgen.gpa;
1326513082
13266 assert(args.src_node != 0);
13083 assert(args.src_node != .root);
1326713084
1326813085 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1326913086
......@@ -13325,7 +13142,7 @@ const GenZir = struct {
1332513142 const astgen = gz.astgen;
1332613143 const gpa = astgen.gpa;
1332713144
13328 assert(args.src_node != 0);
13145 assert(args.src_node != .root);
1332913146
1333013147 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1333113148
......@@ -13380,7 +13197,7 @@ const GenZir = struct {
1338013197 const astgen = gz.astgen;
1338113198 const gpa = astgen.gpa;
1338213199
13383 assert(args.src_node != 0);
13200 assert(args.src_node != .root);
1338413201
1338513202 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);
1338613203 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
......@@ -13574,9 +13391,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
1357413391 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1357513392
1357613393 const tree = gz.astgen.tree;
13577 const token_starts = tree.tokens.items(.start);
13578 const main_tokens = tree.nodes.items(.main_token);
13579 const node_start = token_starts[main_tokens[node]];
13394 const node_start = tree.tokenStart(tree.nodeMainToken(node));
1358013395 gz.astgen.advanceSourceCursor(node_start);
1358113396
1358213397 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
......@@ -13585,8 +13400,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
1358513400/// Advances the source cursor to the beginning of `node`.
1358613401fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
1358713402 const tree = astgen.tree;
13588 const token_starts = tree.tokens.items(.start);
13589 const node_start = token_starts[tree.firstToken(node)];
13403 const node_start = tree.tokenStart(tree.firstToken(node));
1359013404 astgen.advanceSourceCursor(node_start);
1359113405}
1359213406
......@@ -13641,9 +13455,6 @@ fn scanContainer(
1364113455) !u32 {
1364213456 const gpa = astgen.gpa;
1364313457 const tree = astgen.tree;
13644 const node_tags = tree.nodes.items(.tag);
13645 const main_tokens = tree.nodes.items(.main_token);
13646 const token_tags = tree.tokens.items(.tag);
1364713458
1364813459 var any_invalid_declarations = false;
1364913460
......@@ -13673,7 +13484,7 @@ fn scanContainer(
1367313484 var decl_count: u32 = 0;
1367413485 for (members) |member_node| {
1367513486 const Kind = enum { decl, field };
13676 const kind: Kind, const name_token = switch (node_tags[member_node]) {
13487 const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) {
1367713488 .container_field_init,
1367813489 .container_field_align,
1367913490 .container_field,
......@@ -13681,7 +13492,7 @@ fn scanContainer(
1368113492 var full = tree.fullContainerField(member_node).?;
1368213493 switch (container_kind) {
1368313494 .@"struct", .@"opaque" => {},
13684 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes),
13495 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree),
1368513496 }
1368613497 if (full.ast.tuple_like) continue;
1368713498 break :blk .{ .field, full.ast.main_token };
......@@ -13693,7 +13504,7 @@ fn scanContainer(
1369313504 .aligned_var_decl,
1369413505 => blk: {
1369513506 decl_count += 1;
13696 break :blk .{ .decl, main_tokens[member_node] + 1 };
13507 break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 };
1369713508 },
1369813509
1369913510 .fn_proto_simple,
......@@ -13703,8 +13514,8 @@ fn scanContainer(
1370313514 .fn_decl,
1370413515 => blk: {
1370513516 decl_count += 1;
13706 const ident = main_tokens[member_node] + 1;
13707 if (token_tags[ident] != .identifier) {
13517 const ident = tree.nodeMainToken(member_node) + 1;
13518 if (tree.tokenTag(ident) != .identifier) {
1370813519 try astgen.appendErrorNode(member_node, "missing function name", .{});
1370913520 any_invalid_declarations = true;
1371013521 continue;
......@@ -13721,12 +13532,12 @@ fn scanContainer(
1372113532 decl_count += 1;
1372213533 // We don't want shadowing detection here, and test names work a bit differently, so
1372313534 // we must do the redeclaration detection ourselves.
13724 const test_name_token = main_tokens[member_node] + 1;
13535 const test_name_token = tree.nodeMainToken(member_node) + 1;
1372513536 const new_ent: NameEntry = .{
1372613537 .tok = test_name_token,
1372713538 .next = null,
1372813539 };
13729 switch (token_tags[test_name_token]) {
13540 switch (tree.tokenTag(test_name_token)) {
1373013541 else => {}, // unnamed test
1373113542 .string_literal => {
1373213543 const name = try astgen.strLitAsString(test_name_token);
......@@ -14328,3 +14139,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !
1432814139 }
1432914140 return refs.items;
1433014141}
14142
14143test {
14144 _ = &generate;
14145}
lib/std/zig/AstRlAnnotate.zig+173-164
......@@ -92,27 +92,26 @@ fn containerDecl(
9292 full: Ast.full.ContainerDecl,
9393) !void {
9494 const tree = astrl.tree;
95 const token_tags = tree.tokens.items(.tag);
96 switch (token_tags[full.ast.main_token]) {
95 switch (tree.tokenTag(full.ast.main_token)) {
9796 .keyword_struct => {
98 if (full.ast.arg != 0) {
99 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
97 if (full.ast.arg.unwrap()) |arg| {
98 _ = try astrl.expr(arg, block, ResultInfo.type_only);
10099 }
101100 for (full.ast.members) |member_node| {
102101 _ = try astrl.expr(member_node, block, ResultInfo.none);
103102 }
104103 },
105104 .keyword_union => {
106 if (full.ast.arg != 0) {
107 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
105 if (full.ast.arg.unwrap()) |arg| {
106 _ = try astrl.expr(arg, block, ResultInfo.type_only);
108107 }
109108 for (full.ast.members) |member_node| {
110109 _ = try astrl.expr(member_node, block, ResultInfo.none);
111110 }
112111 },
113112 .keyword_enum => {
114 if (full.ast.arg != 0) {
115 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);
113 if (full.ast.arg.unwrap()) |arg| {
114 _ = try astrl.expr(arg, block, ResultInfo.type_only);
116115 }
117116 for (full.ast.members) |member_node| {
118117 _ = try astrl.expr(member_node, block, ResultInfo.none);
......@@ -130,10 +129,7 @@ fn containerDecl(
130129/// Returns true if `rl` provides a result pointer and the expression consumes it.
131130fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool {
132131 const tree = astrl.tree;
133 const token_tags = tree.tokens.items(.tag);
134 const node_datas = tree.nodes.items(.data);
135 const node_tags = tree.nodes.items(.tag);
136 switch (node_tags[node]) {
132 switch (tree.nodeTag(node)) {
137133 .root,
138134 .switch_case_one,
139135 .switch_case_inline_one,
......@@ -145,8 +141,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
145141 .asm_input,
146142 => unreachable,
147143
148 .@"errdefer", .@"defer" => {
149 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
144 .@"errdefer" => {
145 _ = try astrl.expr(tree.nodeData(node).opt_token_and_node[1], block, ResultInfo.none);
146 return false;
147 },
148 .@"defer" => {
149 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
150150 return false;
151151 },
152152
......@@ -155,21 +155,22 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
155155 .container_field,
156156 => {
157157 const full = tree.fullContainerField(node).?;
158 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.type_only);
159 if (full.ast.align_expr != 0) {
160 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
158 const type_expr = full.ast.type_expr.unwrap().?;
159 _ = try astrl.expr(type_expr, block, ResultInfo.type_only);
160 if (full.ast.align_expr.unwrap()) |align_expr| {
161 _ = try astrl.expr(align_expr, block, ResultInfo.type_only);
161162 }
162 if (full.ast.value_expr != 0) {
163 _ = try astrl.expr(full.ast.value_expr, block, ResultInfo.type_only);
163 if (full.ast.value_expr.unwrap()) |value_expr| {
164 _ = try astrl.expr(value_expr, block, ResultInfo.type_only);
164165 }
165166 return false;
166167 },
167168 .@"usingnamespace" => {
168 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
169 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
169170 return false;
170171 },
171172 .test_decl => {
172 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
173 _ = try astrl.expr(tree.nodeData(node).opt_token_and_node[1], block, ResultInfo.none);
173174 return false;
174175 },
175176 .global_var_decl,
......@@ -178,17 +179,17 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
178179 .aligned_var_decl,
179180 => {
180181 const full = tree.fullVarDecl(node).?;
181 const init_ri = if (full.ast.type_node != 0) init_ri: {
182 _ = try astrl.expr(full.ast.type_node, block, ResultInfo.type_only);
182 const init_ri = if (full.ast.type_node.unwrap()) |type_node| init_ri: {
183 _ = try astrl.expr(type_node, block, ResultInfo.type_only);
183184 break :init_ri ResultInfo.typed_ptr;
184185 } else ResultInfo.inferred_ptr;
185 if (full.ast.init_node == 0) {
186 const init_node = full.ast.init_node.unwrap() orelse {
186187 // No init node, so we're done.
187188 return false;
188 }
189 switch (token_tags[full.ast.mut_token]) {
189 };
190 switch (tree.tokenTag(full.ast.mut_token)) {
190191 .keyword_const => {
191 const init_consumes_rl = try astrl.expr(full.ast.init_node, block, init_ri);
192 const init_consumes_rl = try astrl.expr(init_node, block, init_ri);
192193 if (init_consumes_rl) {
193194 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
194195 }
......@@ -197,7 +198,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
197198 .keyword_var => {
198199 // We'll create an alloc either way, so don't care if the
199200 // result pointer is consumed.
200 _ = try astrl.expr(full.ast.init_node, block, init_ri);
201 _ = try astrl.expr(init_node, block, init_ri);
201202 return false;
202203 },
203204 else => unreachable,
......@@ -213,8 +214,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
213214 return false;
214215 },
215216 .assign => {
216 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
217 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.typed_ptr);
217 const lhs, const rhs = tree.nodeData(node).node_and_node;
218 _ = try astrl.expr(lhs, block, ResultInfo.none);
219 _ = try astrl.expr(rhs, block, ResultInfo.typed_ptr);
218220 return false;
219221 },
220222 .assign_shl,
......@@ -235,13 +237,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
235237 .assign_mul_wrap,
236238 .assign_mul_sat,
237239 => {
238 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
239 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
240 const lhs, const rhs = tree.nodeData(node).node_and_node;
241 _ = try astrl.expr(lhs, block, ResultInfo.none);
242 _ = try astrl.expr(rhs, block, ResultInfo.none);
240243 return false;
241244 },
242245 .shl, .shr => {
243 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
244 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
246 const lhs, const rhs = tree.nodeData(node).node_and_node;
247 _ = try astrl.expr(lhs, block, ResultInfo.none);
248 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
245249 return false;
246250 },
247251 .add,
......@@ -267,33 +271,38 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
267271 .less_or_equal,
268272 .array_cat,
269273 => {
270 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
271 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
274 const lhs, const rhs = tree.nodeData(node).node_and_node;
275 _ = try astrl.expr(lhs, block, ResultInfo.none);
276 _ = try astrl.expr(rhs, block, ResultInfo.none);
272277 return false;
273278 },
279
274280 .array_mult => {
275 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
276 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
281 const lhs, const rhs = tree.nodeData(node).node_and_node;
282 _ = try astrl.expr(lhs, block, ResultInfo.none);
283 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
277284 return false;
278285 },
279286 .error_union, .merge_error_sets => {
280 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
281 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
287 const lhs, const rhs = tree.nodeData(node).node_and_node;
288 _ = try astrl.expr(lhs, block, ResultInfo.none);
289 _ = try astrl.expr(rhs, block, ResultInfo.none);
282290 return false;
283291 },
284292 .bool_and,
285293 .bool_or,
286294 => {
287 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
288 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
295 const lhs, const rhs = tree.nodeData(node).node_and_node;
296 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
297 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
289298 return false;
290299 },
291300 .bool_not => {
292 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
301 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
293302 return false;
294303 },
295304 .bit_not, .negation, .negation_wrap => {
296 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
305 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
297306 return false;
298307 },
299308
......@@ -313,17 +322,13 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
313322 .error_set_decl,
314323 => return false,
315324
316 .builtin_call_two, .builtin_call_two_comma => {
317 if (node_datas[node].lhs == 0) {
318 return astrl.builtinCall(block, ri, node, &.{});
319 } else if (node_datas[node].rhs == 0) {
320 return astrl.builtinCall(block, ri, node, &.{node_datas[node].lhs});
321 } else {
322 return astrl.builtinCall(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
323 }
324 },
325 .builtin_call, .builtin_call_comma => {
326 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
325 .builtin_call_two,
326 .builtin_call_two_comma,
327 .builtin_call,
328 .builtin_call_comma,
329 => {
330 var buf: [2]Ast.Node.Index = undefined;
331 const params = tree.builtinCallParams(&buf, node).?;
327332 return astrl.builtinCall(block, ri, node, params);
328333 },
329334
......@@ -342,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
342347 for (full.ast.params) |param_node| {
343348 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
344349 }
345 return switch (node_tags[node]) {
350 return switch (tree.nodeTag(node)) {
346351 .call_one,
347352 .call_one_comma,
348353 .call,
......@@ -358,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
358363 },
359364
360365 .@"return" => {
361 if (node_datas[node].lhs != 0) {
362 const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr);
366 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
367 const ret_val_consumes_rl = try astrl.expr(lhs, block, ResultInfo.typed_ptr);
363368 if (ret_val_consumes_rl) {
364369 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
365370 }
......@@ -368,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
368373 },
369374
370375 .field_access => {
371 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
376 const lhs, _ = tree.nodeData(node).node_and_token;
377 _ = try astrl.expr(lhs, block, ResultInfo.none);
372378 return false;
373379 },
374380
......@@ -380,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
380386 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
381387 }
382388
383 if (full.ast.else_expr == 0) {
384 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
385 return false;
386 } else {
389 if (full.ast.else_expr.unwrap()) |else_expr| {
387390 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);
388 const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri);
391 const else_uses_rl = try astrl.expr(else_expr, block, ri);
389392 const uses_rl = then_uses_rl or else_uses_rl;
390393 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
391394 return uses_rl;
395 } else {
396 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
397 return false;
392398 }
393399 },
394400
......@@ -409,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
409415 .ri = ri,
410416 .consumes_res_ptr = false,
411417 };
412 if (full.ast.cont_expr != 0) {
413 _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none);
418 if (full.ast.cont_expr.unwrap()) |cont_expr| {
419 _ = try astrl.expr(cont_expr, &new_block, ResultInfo.none);
414420 }
415421 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
416 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
417 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
422 const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: {
423 break :else_rl try astrl.expr(else_expr, block, ri);
418424 } else false;
419425 if (new_block.consumes_res_ptr or else_consumes_rl) {
420426 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
......@@ -430,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
430436 break :label try astrl.identString(label_token);
431437 } else null;
432438 for (full.ast.inputs) |input| {
433 if (node_tags[input] == .for_range) {
434 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);
435 if (node_datas[input].rhs != 0) {
436 _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only);
439 if (tree.nodeTag(input) == .for_range) {
440 const lhs, const opt_rhs = tree.nodeData(input).node_and_opt_node;
441 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
442 if (opt_rhs.unwrap()) |rhs| {
443 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
437444 }
438445 } else {
439446 _ = try astrl.expr(input, block, ResultInfo.none);
......@@ -447,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
447454 .consumes_res_ptr = false,
448455 };
449456 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
450 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
451 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);
457 const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: {
458 break :else_rl try astrl.expr(else_expr, block, ri);
452459 } else false;
453460 if (new_block.consumes_res_ptr or else_consumes_rl) {
454461 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
......@@ -459,66 +466,68 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
459466 },
460467
461468 .slice_open => {
462 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
463 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
469 const sliced, const start = tree.nodeData(node).node_and_node;
470 _ = try astrl.expr(sliced, block, ResultInfo.none);
471 _ = try astrl.expr(start, block, ResultInfo.type_only);
464472 return false;
465473 },
466474 .slice => {
467 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
468 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
475 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
476 const extra = tree.extraData(extra_index, Ast.Node.Slice);
477 _ = try astrl.expr(sliced, block, ResultInfo.none);
469478 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
470479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
471480 return false;
472481 },
473482 .slice_sentinel => {
474 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
475 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
483 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
484 const extra = tree.extraData(extra_index, Ast.Node.SliceSentinel);
485 _ = try astrl.expr(sliced, block, ResultInfo.none);
476486 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
477 if (extra.end != 0) {
478 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
487 if (extra.end.unwrap()) |end| {
488 _ = try astrl.expr(end, block, ResultInfo.type_only);
479489 }
480490 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
481491 return false;
482492 },
483493 .deref => {
484 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
494 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
485495 return false;
486496 },
487497 .address_of => {
488 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
498 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
489499 return false;
490500 },
491501 .optional_type => {
492 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
502 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
493503 return false;
494504 },
495 .grouped_expression,
496505 .@"try",
497506 .@"await",
498507 .@"nosuspend",
508 => return astrl.expr(tree.nodeData(node).node, block, ri),
509 .grouped_expression,
499510 .unwrap_optional,
500 => return astrl.expr(node_datas[node].lhs, block, ri),
511 => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri),
501512
502 .block_two, .block_two_semicolon => {
503 if (node_datas[node].lhs == 0) {
504 return astrl.blockExpr(block, ri, node, &.{});
505 } else if (node_datas[node].rhs == 0) {
506 return astrl.blockExpr(block, ri, node, &.{node_datas[node].lhs});
507 } else {
508 return astrl.blockExpr(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });
509 }
510 },
511 .block, .block_semicolon => {
512 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
513 .block_two,
514 .block_two_semicolon,
515 .block,
516 .block_semicolon,
517 => {
518 var buf: [2]Ast.Node.Index = undefined;
519 const statements = tree.blockStatements(&buf, node).?;
513520 return astrl.blockExpr(block, ri, node, statements);
514521 },
515522 .anyframe_type => {
516 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
523 _, const child_type = tree.nodeData(node).token_and_node;
524 _ = try astrl.expr(child_type, block, ResultInfo.type_only);
517525 return false;
518526 },
519527 .@"catch", .@"orelse" => {
520 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
521 const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri);
528 const lhs, const rhs = tree.nodeData(node).node_and_node;
529 _ = try astrl.expr(lhs, block, ResultInfo.none);
530 const rhs_consumes_rl = try astrl.expr(rhs, block, ri);
522531 if (rhs_consumes_rl) {
523532 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
524533 }
......@@ -532,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
532541 => {
533542 const full = tree.fullPtrType(node).?;
534543 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
535 if (full.ast.sentinel != 0) {
536 _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only);
544 if (full.ast.sentinel.unwrap()) |sentinel| {
545 _ = try astrl.expr(sentinel, block, ResultInfo.type_only);
537546 }
538 if (full.ast.addrspace_node != 0) {
539 _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only);
547 if (full.ast.addrspace_node.unwrap()) |addrspace_node| {
548 _ = try astrl.expr(addrspace_node, block, ResultInfo.type_only);
540549 }
541 if (full.ast.align_node != 0) {
542 _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only);
550 if (full.ast.align_node.unwrap()) |align_node| {
551 _ = try astrl.expr(align_node, block, ResultInfo.type_only);
543552 }
544 if (full.ast.bit_range_start != 0) {
545 assert(full.ast.bit_range_end != 0);
546 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);
547 _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only);
553 if (full.ast.bit_range_start.unwrap()) |bit_range_start| {
554 const bit_range_end = full.ast.bit_range_end.unwrap().?;
555 _ = try astrl.expr(bit_range_start, block, ResultInfo.type_only);
556 _ = try astrl.expr(bit_range_end, block, ResultInfo.type_only);
548557 }
549558 return false;
550559 },
......@@ -568,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
568577 },
569578
570579 .@"break" => {
571 if (node_datas[node].rhs == 0) {
580 const opt_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
581 const rhs = opt_rhs.unwrap() orelse {
572582 // Breaks with void are not interesting
573583 return false;
574 }
584 };
575585
576586 var opt_cur_block = block;
577 if (node_datas[node].lhs == 0) {
578 // No label - we're breaking from a loop.
587 if (opt_label.unwrap()) |label_token| {
588 const break_label = try astrl.identString(label_token);
579589 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
580 if (cur_block.is_loop) break;
590 const block_label = cur_block.label orelse continue;
591 if (std.mem.eql(u8, block_label, break_label)) break;
581592 }
582593 } else {
583 const break_label = try astrl.identString(node_datas[node].lhs);
594 // No label - we're breaking from a loop.
584595 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
585 const block_label = cur_block.label orelse continue;
586 if (std.mem.eql(u8, block_label, break_label)) break;
596 if (cur_block.is_loop) break;
587597 }
588598 }
589599
590600 if (opt_cur_block) |target_block| {
591 const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri);
601 const consumes_break_rl = try astrl.expr(rhs, block, target_block.ri);
592602 if (consumes_break_rl) target_block.consumes_res_ptr = true;
593603 } else {
594604 // No corresponding scope to break from - AstGen will emit an error.
595 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
605 _ = try astrl.expr(rhs, block, ResultInfo.none);
596606 }
597607
598608 return false;
599609 },
600610
601611 .array_type => {
602 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
603 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
612 const lhs, const rhs = tree.nodeData(node).node_and_node;
613 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
614 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
604615 return false;
605616 },
606617 .array_type_sentinel => {
607 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
608 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
618 const len_expr, const extra_index = tree.nodeData(node).node_and_extra;
619 const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
620 _ = try astrl.expr(len_expr, block, ResultInfo.type_only);
609621 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
610622 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
611623 return false;
612624 },
613625 .array_access => {
614 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
615 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);
626 const lhs, const rhs = tree.nodeData(node).node_and_node;
627 _ = try astrl.expr(lhs, block, ResultInfo.none);
628 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
616629 return false;
617630 },
618631 .@"comptime" => {
619632 // AstGen will emit an error if the scope is already comptime, so we can assume it is
620633 // not. This means the result location is not forwarded.
621 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
634 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
622635 return false;
623636 },
624637 .@"switch", .switch_comma => {
625 const operand_node = node_datas[node].lhs;
626 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange);
627 const case_nodes = tree.extra_data[extra.start..extra.end];
638 const operand_node, const extra_index = tree.nodeData(node).node_and_extra;
639 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
628640
629641 _ = try astrl.expr(operand_node, block, ResultInfo.none);
630642
......@@ -632,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
632644 for (case_nodes) |case_node| {
633645 const case = tree.fullSwitchCase(case_node).?;
634646 for (case.ast.values) |item_node| {
635 if (node_tags[item_node] == .switch_range) {
636 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);
637 _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none);
647 if (tree.nodeTag(item_node) == .switch_range) {
648 const lhs, const rhs = tree.nodeData(item_node).node_and_node;
649 _ = try astrl.expr(lhs, block, ResultInfo.none);
650 _ = try astrl.expr(rhs, block, ResultInfo.none);
638651 } else {
639652 _ = try astrl.expr(item_node, block, ResultInfo.none);
640653 }
......@@ -649,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
649662 return any_prong_consumed_rl;
650663 },
651664 .@"suspend" => {
652 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
665 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
653666 return false;
654667 },
655668 .@"resume" => {
656 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
669 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
657670 return false;
658671 },
659672
......@@ -669,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
669682 var buf: [2]Ast.Node.Index = undefined;
670683 const full = tree.fullArrayInit(&buf, node).?;
671684
672 if (full.ast.type_expr != 0) {
685 if (full.ast.type_expr.unwrap()) |type_expr| {
673686 // Explicitly typed init does not participate in RLS
674 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
687 _ = try astrl.expr(type_expr, block, ResultInfo.none);
675688 for (full.ast.elements) |elem_init| {
676689 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
677690 }
......@@ -706,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
706719 var buf: [2]Ast.Node.Index = undefined;
707720 const full = tree.fullStructInit(&buf, node).?;
708721
709 if (full.ast.type_expr != 0) {
722 if (full.ast.type_expr.unwrap()) |type_expr| {
710723 // Explicitly typed init does not participate in RLS
711 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
724 _ = try astrl.expr(type_expr, block, ResultInfo.none);
712725 for (full.ast.fields) |field_init| {
713726 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
714727 }
......@@ -736,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
736749 .fn_proto_one,
737750 .fn_proto,
738751 .fn_decl,
739 => {
752 => |tag| {
740753 var buf: [1]Ast.Node.Index = undefined;
741754 const full = tree.fullFnProto(&buf, node).?;
742 const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0;
755 const body_node = if (tag == .fn_decl) tree.nodeData(node).node_and_node[1].toOptional() else .none;
743756 {
744757 var it = full.iterate(tree);
745758 while (it.next()) |param| {
746759 if (param.anytype_ellipsis3 == null) {
747 _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only);
760 const type_expr = param.type_expr.?;
761 _ = try astrl.expr(type_expr, block, ResultInfo.type_only);
748762 }
749763 }
750764 }
751 if (full.ast.align_expr != 0) {
752 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);
765 if (full.ast.align_expr.unwrap()) |align_expr| {
766 _ = try astrl.expr(align_expr, block, ResultInfo.type_only);
753767 }
754 if (full.ast.addrspace_expr != 0) {
755 _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only);
768 if (full.ast.addrspace_expr.unwrap()) |addrspace_expr| {
769 _ = try astrl.expr(addrspace_expr, block, ResultInfo.type_only);
756770 }
757 if (full.ast.section_expr != 0) {
758 _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only);
771 if (full.ast.section_expr.unwrap()) |section_expr| {
772 _ = try astrl.expr(section_expr, block, ResultInfo.type_only);
759773 }
760 if (full.ast.callconv_expr != 0) {
761 _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only);
774 if (full.ast.callconv_expr.unwrap()) |callconv_expr| {
775 _ = try astrl.expr(callconv_expr, block, ResultInfo.type_only);
762776 }
763 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);
764 if (body_node != 0) {
765 _ = try astrl.expr(body_node, block, ResultInfo.none);
777 const return_type = full.ast.return_type.unwrap().?;
778 _ = try astrl.expr(return_type, block, ResultInfo.type_only);
779 if (body_node.unwrap()) |body| {
780 _ = try astrl.expr(body, block, ResultInfo.none);
766781 }
767782 return false;
768783 },
......@@ -771,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
771786
772787fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
773788 const tree = astrl.tree;
774 const token_tags = tree.tokens.items(.tag);
775 assert(token_tags[token] == .identifier);
789 assert(tree.tokenTag(token) == .identifier);
776790 const ident_name = tree.tokenSlice(token);
777791 if (!std.mem.startsWith(u8, ident_name, "@")) {
778792 return ident_name;
......@@ -785,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
785799
786800fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {
787801 const tree = astrl.tree;
788 const token_tags = tree.tokens.items(.tag);
789 const main_tokens = tree.nodes.items(.main_token);
790802
791 const lbrace = main_tokens[node];
792 if (token_tags[lbrace - 1] == .colon and
793 token_tags[lbrace - 2] == .identifier)
794 {
803 const lbrace = tree.nodeMainToken(node);
804 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
795805 // Labeled block
796806 var new_block: Block = .{
797807 .parent = parent_block,
......@@ -820,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
820830 _ = ri; // Currently, no builtin consumes its result location.
821831
822832 const tree = astrl.tree;
823 const main_tokens = tree.nodes.items(.main_token);
824 const builtin_token = main_tokens[node];
833 const builtin_token = tree.nodeMainToken(node);
825834 const builtin_name = tree.tokenSlice(builtin_token);
826835 const info = BuiltinFn.list.get(builtin_name) orelse return false;
827836 if (info.param_count) |expected| {
lib/std/zig/ErrorBundle.zig+28-26
......@@ -481,13 +481,13 @@ pub const Wip = struct {
481481 const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);
482482 extra_index = item.end;
483483 const err_span = blk: {
484 if (item.data.node != 0) {
485 break :blk tree.nodeToSpan(item.data.node);
486 }
487 const token_starts = tree.tokens.items(.start);
488 const start = token_starts[item.data.token] + item.data.byte_offset;
489 const end = start + @as(u32, @intCast(tree.tokenSlice(item.data.token).len)) - item.data.byte_offset;
490 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
484 if (item.data.node.unwrap()) |node| {
485 break :blk tree.nodeToSpan(node);
486 } else if (item.data.token.unwrap()) |token| {
487 const start = tree.tokenStart(token) + item.data.byte_offset;
488 const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset;
489 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
490 } else unreachable;
491491 };
492492 const err_loc = std.zig.findLineColumn(source, err_span.main);
493493
......@@ -516,13 +516,13 @@ pub const Wip = struct {
516516 const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem);
517517 const msg = zir.nullTerminatedString(note_item.data.msg);
518518 const span = blk: {
519 if (note_item.data.node != 0) {
520 break :blk tree.nodeToSpan(note_item.data.node);
521 }
522 const token_starts = tree.tokens.items(.start);
523 const start = token_starts[note_item.data.token] + note_item.data.byte_offset;
524 const end = start + @as(u32, @intCast(tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset;
525 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
519 if (note_item.data.node.unwrap()) |node| {
520 break :blk tree.nodeToSpan(node);
521 } else if (note_item.data.token.unwrap()) |token| {
522 const start = tree.tokenStart(token) + note_item.data.byte_offset;
523 const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset;
524 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
525 } else unreachable;
526526 };
527527 const loc = std.zig.findLineColumn(source, span.main);
528528
......@@ -560,13 +560,14 @@ pub const Wip = struct {
560560
561561 for (zoir.compile_errors) |err| {
562562 const err_span: std.zig.Ast.Span = span: {
563 if (err.token == std.zig.Zoir.CompileError.invalid_token) {
564 break :span tree.nodeToSpan(err.node_or_offset);
563 if (err.token.unwrap()) |token| {
564 const token_start = tree.tokenStart(token);
565 const start = token_start + err.node_or_offset;
566 const end = token_start + @as(u32, @intCast(tree.tokenSlice(token).len));
567 break :span .{ .start = start, .end = end, .main = start };
568 } else {
569 break :span tree.nodeToSpan(@enumFromInt(err.node_or_offset));
565570 }
566 const token_start = tree.tokens.items(.start)[err.token];
567 const start = token_start + err.node_or_offset;
568 const end = token_start + @as(u32, @intCast(tree.tokenSlice(err.token).len));
569 break :span .{ .start = start, .end = end, .main = start };
570571 };
571572 const err_loc = std.zig.findLineColumn(source, err_span.main);
572573
......@@ -588,13 +589,14 @@ pub const Wip = struct {
588589 for (notes_start.., err.first_note.., 0..err.note_count) |eb_note_idx, zoir_note_idx, _| {
589590 const note = zoir.error_notes[zoir_note_idx];
590591 const note_span: std.zig.Ast.Span = span: {
591 if (note.token == std.zig.Zoir.CompileError.invalid_token) {
592 break :span tree.nodeToSpan(note.node_or_offset);
592 if (note.token.unwrap()) |token| {
593 const token_start = tree.tokenStart(token);
594 const start = token_start + note.node_or_offset;
595 const end = token_start + @as(u32, @intCast(tree.tokenSlice(token).len));
596 break :span .{ .start = start, .end = end, .main = start };
597 } else {
598 break :span tree.nodeToSpan(@enumFromInt(note.node_or_offset));
593599 }
594 const token_start = tree.tokens.items(.start)[note.token];
595 const start = token_start + note.node_or_offset;
596 const end = token_start + @as(u32, @intCast(tree.tokenSlice(note.token).len));
597 break :span .{ .start = start, .end = end, .main = start };
598600 };
599601 const note_loc = std.zig.findLineColumn(source, note_span.main);
600602
lib/std/zig/Parse.zig+1076-1328
......@@ -4,52 +4,71 @@ pub const Error = error{ParseError} || Allocator.Error;
44
55gpa: Allocator,
66source: []const u8,
7token_tags: []const Token.Tag,
8token_starts: []const Ast.ByteOffset,
7tokens: Ast.TokenList.Slice,
98tok_i: TokenIndex,
109errors: std.ArrayListUnmanaged(AstError),
1110nodes: Ast.NodeList,
12extra_data: std.ArrayListUnmanaged(Node.Index),
11extra_data: std.ArrayListUnmanaged(u32),
1312scratch: std.ArrayListUnmanaged(Node.Index),
1413
14fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag {
15 return p.tokens.items(.tag)[token_index];
16}
17
18fn tokenStart(p: *const Parse, token_index: TokenIndex) Ast.ByteOffset {
19 return p.tokens.items(.start)[token_index];
20}
21
22fn nodeTag(p: *const Parse, node: Node.Index) Node.Tag {
23 return p.nodes.items(.tag)[@intFromEnum(node)];
24}
25
26fn nodeMainToken(p: *const Parse, node: Node.Index) TokenIndex {
27 return p.nodes.items(.main_token)[@intFromEnum(node)];
28}
29
30fn nodeData(p: *const Parse, node: Node.Index) Node.Data {
31 return p.nodes.items(.data)[@intFromEnum(node)];
32}
33
1534const SmallSpan = union(enum) {
16 zero_or_one: Node.Index,
35 zero_or_one: Node.OptionalIndex,
1736 multi: Node.SubRange,
1837};
1938
2039const Members = struct {
2140 len: usize,
22 lhs: Node.Index,
23 rhs: Node.Index,
41 /// Must be either `.opt_node_and_opt_node` if `len <= 2` or `.extra_range` otherwise.
42 data: Node.Data,
2443 trailing: bool,
2544
2645 fn toSpan(self: Members, p: *Parse) !Node.SubRange {
27 if (self.len <= 2) {
28 const nodes = [2]Node.Index{ self.lhs, self.rhs };
29 return p.listToSpan(nodes[0..self.len]);
30 } else {
31 return Node.SubRange{ .start = self.lhs, .end = self.rhs };
32 }
46 return switch (self.len) {
47 0 => p.listToSpan(&.{}),
48 1 => p.listToSpan(&.{self.data.opt_node_and_opt_node[0].unwrap().?}),
49 2 => p.listToSpan(&.{ self.data.opt_node_and_opt_node[0].unwrap().?, self.data.opt_node_and_opt_node[1].unwrap().? }),
50 else => self.data.extra_range,
51 };
3352 }
3453};
3554
36fn listToSpan(p: *Parse, list: []const Node.Index) !Node.SubRange {
37 try p.extra_data.appendSlice(p.gpa, list);
38 return Node.SubRange{
39 .start = @as(Node.Index, @intCast(p.extra_data.items.len - list.len)),
40 .end = @as(Node.Index, @intCast(p.extra_data.items.len)),
55fn listToSpan(p: *Parse, list: []const Node.Index) Allocator.Error!Node.SubRange {
56 try p.extra_data.appendSlice(p.gpa, @ptrCast(list));
57 return .{
58 .start = @enumFromInt(p.extra_data.items.len - list.len),
59 .end = @enumFromInt(p.extra_data.items.len),
4160 };
4261}
4362
4463fn addNode(p: *Parse, elem: Ast.Node) Allocator.Error!Node.Index {
45 const result = @as(Node.Index, @intCast(p.nodes.len));
64 const result: Node.Index = @enumFromInt(p.nodes.len);
4665 try p.nodes.append(p.gpa, elem);
4766 return result;
4867}
4968
5069fn setNode(p: *Parse, i: usize, elem: Ast.Node) Node.Index {
5170 p.nodes.set(i, elem);
52 return @as(Node.Index, @intCast(i));
71 return @enumFromInt(i);
5372}
5473
5574fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize {
......@@ -69,13 +88,22 @@ fn unreserveNode(p: *Parse, node_index: usize) void {
6988 }
7089}
7190
72fn addExtra(p: *Parse, extra: anytype) Allocator.Error!Node.Index {
91fn addExtra(p: *Parse, extra: anytype) Allocator.Error!ExtraIndex {
7392 const fields = std.meta.fields(@TypeOf(extra));
7493 try p.extra_data.ensureUnusedCapacity(p.gpa, fields.len);
75 const result = @as(u32, @intCast(p.extra_data.items.len));
94 const result: ExtraIndex = @enumFromInt(p.extra_data.items.len);
7695 inline for (fields) |field| {
77 comptime assert(field.type == Node.Index);
78 p.extra_data.appendAssumeCapacity(@field(extra, field.name));
96 const data: u32 = switch (field.type) {
97 Node.Index,
98 Node.OptionalIndex,
99 OptionalTokenIndex,
100 ExtraIndex,
101 => @intFromEnum(@field(extra, field.name)),
102 TokenIndex,
103 => @field(extra, field.name),
104 else => @compileError("unexpected field type"),
105 };
106 p.extra_data.appendAssumeCapacity(data);
79107 }
80108 return result;
81109}
......@@ -170,13 +198,10 @@ pub fn parseRoot(p: *Parse) !void {
170198 });
171199 const root_members = try p.parseContainerMembers();
172200 const root_decls = try root_members.toSpan(p);
173 if (p.token_tags[p.tok_i] != .eof) {
201 if (p.tokenTag(p.tok_i) != .eof) {
174202 try p.warnExpected(.eof);
175203 }
176 p.nodes.items(.data)[0] = .{
177 .lhs = root_decls.start,
178 .rhs = root_decls.end,
179 };
204 p.nodes.items(.data)[0] = .{ .extra_range = root_decls };
180205}
181206
182207/// Parse in ZON mode. Subset of the language.
......@@ -196,13 +221,10 @@ pub fn parseZon(p: *Parse) !void {
196221 },
197222 else => |e| return e,
198223 };
199 if (p.token_tags[p.tok_i] != .eof) {
224 if (p.tokenTag(p.tok_i) != .eof) {
200225 try p.warnExpected(.eof);
201226 }
202 p.nodes.items(.data)[0] = .{
203 .lhs = node_index,
204 .rhs = undefined,
205 };
227 p.nodes.items(.data)[0] = .{ .node = node_index };
206228}
207229
208230/// ContainerMembers <- ContainerDeclaration* (ContainerField COMMA)* (ContainerField / ContainerDeclaration*)
......@@ -235,13 +257,13 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
235257 while (true) {
236258 const doc_comment = try p.eatDocComments();
237259
238 switch (p.token_tags[p.tok_i]) {
260 switch (p.tokenTag(p.tok_i)) {
239261 .keyword_test => {
240262 if (doc_comment) |some| {
241263 try p.warnMsg(.{ .tag = .test_doc_comment, .token = some });
242264 }
243 const test_decl_node = try p.expectTestDeclRecoverable();
244 if (test_decl_node != 0) {
265 const maybe_test_decl_node = try p.expectTestDeclRecoverable();
266 if (maybe_test_decl_node) |test_decl_node| {
245267 if (field_state == .seen) {
246268 field_state = .{ .end = test_decl_node };
247269 }
......@@ -249,27 +271,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
249271 }
250272 trailing = false;
251273 },
252 .keyword_comptime => switch (p.token_tags[p.tok_i + 1]) {
274 .keyword_comptime => switch (p.tokenTag(p.tok_i + 1)) {
253275 .l_brace => {
254276 if (doc_comment) |some| {
255277 try p.warnMsg(.{ .tag = .comptime_doc_comment, .token = some });
256278 }
257279 const comptime_token = p.nextToken();
258 const block = p.parseBlock() catch |err| switch (err) {
280 const opt_block = p.parseBlock() catch |err| switch (err) {
259281 error.OutOfMemory => return error.OutOfMemory,
260282 error.ParseError => blk: {
261283 p.findNextContainerMember();
262 break :blk null_node;
284 break :blk null;
263285 },
264286 };
265 if (block != 0) {
287 if (opt_block) |block| {
266288 const comptime_node = try p.addNode(.{
267289 .tag = .@"comptime",
268290 .main_token = comptime_token,
269 .data = .{
270 .lhs = block,
271 .rhs = undefined,
272 },
291 .data = .{ .node = block },
273292 });
274293 if (field_state == .seen) {
275294 field_state = .{ .end = comptime_node };
......@@ -294,7 +313,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
294313 .end => |node| {
295314 try p.warnMsg(.{
296315 .tag = .decl_between_fields,
297 .token = p.nodes.items(.main_token)[node],
316 .token = p.nodeMainToken(node),
298317 });
299318 try p.warnMsg(.{
300319 .tag = .previous_field,
......@@ -311,7 +330,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
311330 },
312331 }
313332 try p.scratch.append(p.gpa, container_field);
314 switch (p.token_tags[p.tok_i]) {
333 switch (p.tokenTag(p.tok_i)) {
315334 .comma => {
316335 p.tok_i += 1;
317336 trailing = true;
......@@ -331,24 +350,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
331350 },
332351 .keyword_pub => {
333352 p.tok_i += 1;
334 const top_level_decl = try p.expectTopLevelDeclRecoverable();
335 if (top_level_decl != 0) {
353 const opt_top_level_decl = try p.expectTopLevelDeclRecoverable();
354 if (opt_top_level_decl) |top_level_decl| {
336355 if (field_state == .seen) {
337356 field_state = .{ .end = top_level_decl };
338357 }
339358 try p.scratch.append(p.gpa, top_level_decl);
340359 }
341 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
360 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
342361 },
343362 .keyword_usingnamespace => {
344 const node = try p.expectUsingNamespaceRecoverable();
345 if (node != 0) {
363 const opt_node = try p.expectUsingNamespaceRecoverable();
364 if (opt_node) |node| {
346365 if (field_state == .seen) {
347366 field_state = .{ .end = node };
348367 }
349368 try p.scratch.append(p.gpa, node);
350369 }
351 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
370 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
352371 },
353372 .keyword_const,
354373 .keyword_var,
......@@ -359,14 +378,14 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
359378 .keyword_noinline,
360379 .keyword_fn,
361380 => {
362 const top_level_decl = try p.expectTopLevelDeclRecoverable();
363 if (top_level_decl != 0) {
381 const opt_top_level_decl = try p.expectTopLevelDeclRecoverable();
382 if (opt_top_level_decl) |top_level_decl| {
364383 if (field_state == .seen) {
365384 field_state = .{ .end = top_level_decl };
366385 }
367386 try p.scratch.append(p.gpa, top_level_decl);
368387 }
369 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
388 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
370389 },
371390 .eof, .r_brace => {
372391 if (doc_comment) |tok| {
......@@ -399,7 +418,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
399418 .end => |node| {
400419 try p.warnMsg(.{
401420 .tag = .decl_between_fields,
402 .token = p.nodes.items(.main_token)[node],
421 .token = p.nodeMainToken(node),
403422 });
404423 try p.warnMsg(.{
405424 .tag = .previous_field,
......@@ -416,7 +435,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
416435 },
417436 }
418437 try p.scratch.append(p.gpa, container_field);
419 switch (p.token_tags[p.tok_i]) {
438 switch (p.tokenTag(p.tok_i)) {
420439 .comma => {
421440 p.tok_i += 1;
422441 trailing = true;
......@@ -431,7 +450,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
431450 // There is not allowed to be a decl after a field with no comma.
432451 // Report error but recover parser.
433452 try p.warn(.expected_comma_after_field);
434 if (p.token_tags[p.tok_i] == .semicolon and p.token_tags[identifier] == .identifier) {
453 if (p.tokenTag(p.tok_i) == .semicolon and p.tokenTag(identifier) == .identifier) {
435454 try p.warnMsg(.{
436455 .tag = .var_const_decl,
437456 .is_note = true,
......@@ -445,34 +464,21 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
445464 }
446465
447466 const items = p.scratch.items[scratch_top..];
448 switch (items.len) {
449 0 => return Members{
450 .len = 0,
451 .lhs = 0,
452 .rhs = 0,
453 .trailing = trailing,
454 },
455 1 => return Members{
456 .len = 1,
457 .lhs = items[0],
458 .rhs = 0,
467 if (items.len <= 2) {
468 return Members{
469 .len = items.len,
470 .data = .{ .opt_node_and_opt_node = .{
471 if (items.len >= 1) items[0].toOptional() else .none,
472 if (items.len >= 2) items[1].toOptional() else .none,
473 } },
459474 .trailing = trailing,
460 },
461 2 => return Members{
462 .len = 2,
463 .lhs = items[0],
464 .rhs = items[1],
475 };
476 } else {
477 return Members{
478 .len = items.len,
479 .data = .{ .extra_range = try p.listToSpan(items) },
465480 .trailing = trailing,
466 },
467 else => {
468 const span = try p.listToSpan(items);
469 return Members{
470 .len = items.len,
471 .lhs = span.start,
472 .rhs = span.end,
473 .trailing = trailing,
474 };
475 },
481 };
476482 }
477483}
478484
......@@ -481,7 +487,7 @@ fn findNextContainerMember(p: *Parse) void {
481487 var level: u32 = 0;
482488 while (true) {
483489 const tok = p.nextToken();
484 switch (p.token_tags[tok]) {
490 switch (p.tokenTag(tok)) {
485491 // Any of these can start a new top level declaration.
486492 .keyword_test,
487493 .keyword_comptime,
......@@ -502,7 +508,7 @@ fn findNextContainerMember(p: *Parse) void {
502508 }
503509 },
504510 .identifier => {
505 if (p.token_tags[tok + 1] == .comma and level == 0) {
511 if (p.tokenTag(tok + 1) == .comma and level == 0) {
506512 p.tok_i -= 1;
507513 return;
508514 }
......@@ -539,7 +545,7 @@ fn findNextStmt(p: *Parse) void {
539545 var level: u32 = 0;
540546 while (true) {
541547 const tok = p.nextToken();
542 switch (p.token_tags[tok]) {
548 switch (p.tokenTag(tok)) {
543549 .l_brace => level += 1,
544550 .r_brace => {
545551 if (level == 0) {
......@@ -563,44 +569,45 @@ fn findNextStmt(p: *Parse) void {
563569}
564570
565571/// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block
566fn expectTestDecl(p: *Parse) !Node.Index {
572fn expectTestDecl(p: *Parse) Error!Node.Index {
567573 const test_token = p.assertToken(.keyword_test);
568 const name_token = switch (p.token_tags[p.tok_i]) {
569 .string_literal, .identifier => p.nextToken(),
570 else => null,
574 const name_token: OptionalTokenIndex = switch (p.tokenTag(p.tok_i)) {
575 .string_literal, .identifier => .fromToken(p.nextToken()),
576 else => .none,
571577 };
572 const block_node = try p.parseBlock();
573 if (block_node == 0) return p.fail(.expected_block);
578 const block_node = try p.parseBlock() orelse return p.fail(.expected_block);
574579 return p.addNode(.{
575580 .tag = .test_decl,
576581 .main_token = test_token,
577 .data = .{
578 .lhs = name_token orelse 0,
579 .rhs = block_node,
580 },
582 .data = .{ .opt_token_and_node = .{
583 name_token,
584 block_node,
585 } },
581586 });
582587}
583588
584fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {
585 return p.expectTestDecl() catch |err| switch (err) {
589fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
590 if (p.expectTestDecl()) |node| {
591 return node;
592 } else |err| switch (err) {
586593 error.OutOfMemory => return error.OutOfMemory,
587594 error.ParseError => {
588595 p.findNextContainerMember();
589 return null_node;
596 return null;
590597 },
591 };
598 }
592599}
593600
594601/// Decl
595602/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)
596603/// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
597604/// / KEYWORD_usingnamespace Expr SEMICOLON
598fn expectTopLevelDecl(p: *Parse) !Node.Index {
605fn expectTopLevelDecl(p: *Parse) !?Node.Index {
599606 const extern_export_inline_token = p.nextToken();
600607 var is_extern: bool = false;
601608 var expect_fn: bool = false;
602609 var expect_var_or_fn: bool = false;
603 switch (p.token_tags[extern_export_inline_token]) {
610 switch (p.tokenTag(extern_export_inline_token)) {
604611 .keyword_extern => {
605612 _ = p.eatToken(.string_literal);
606613 is_extern = true;
......@@ -610,9 +617,9 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
610617 .keyword_inline, .keyword_noinline => expect_fn = true,
611618 else => p.tok_i -= 1,
612619 }
613 const fn_proto = try p.parseFnProto();
614 if (fn_proto != 0) {
615 switch (p.token_tags[p.tok_i]) {
620 const opt_fn_proto = try p.parseFnProto();
621 if (opt_fn_proto) |fn_proto| {
622 switch (p.tokenTag(p.tok_i)) {
616623 .semicolon => {
617624 p.tok_i += 1;
618625 return fn_proto;
......@@ -620,20 +627,19 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
620627 .l_brace => {
621628 if (is_extern) {
622629 try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token });
623 return null_node;
630 return null;
624631 }
625632 const fn_decl_index = try p.reserveNode(.fn_decl);
626633 errdefer p.unreserveNode(fn_decl_index);
627634
628635 const body_block = try p.parseBlock();
629 assert(body_block != 0);
630636 return p.setNode(fn_decl_index, .{
631637 .tag = .fn_decl,
632 .main_token = p.nodes.items(.main_token)[fn_proto],
633 .data = .{
634 .lhs = fn_proto,
635 .rhs = body_block,
636 },
638 .main_token = p.nodeMainToken(fn_proto),
639 .data = .{ .node_and_node = .{
640 fn_proto,
641 body_block.?,
642 } },
637643 });
638644 },
639645 else => {
......@@ -641,7 +647,7 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
641647 // a missing '}' we can assume this function was
642648 // supposed to end here.
643649 try p.warn(.expected_semi_or_lbrace);
644 return null_node;
650 return null;
645651 },
646652 }
647653 }
......@@ -651,28 +657,25 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
651657 }
652658
653659 const thread_local_token = p.eatToken(.keyword_threadlocal);
654 const var_decl = try p.parseGlobalVarDecl();
655 if (var_decl != 0) {
656 return var_decl;
657 }
660 if (try p.parseGlobalVarDecl()) |var_decl| return var_decl;
658661 if (thread_local_token != null) {
659662 return p.fail(.expected_var_decl);
660663 }
661664 if (expect_var_or_fn) {
662665 return p.fail(.expected_var_decl_or_fn);
663666 }
664 if (p.token_tags[p.tok_i] != .keyword_usingnamespace) {
667 if (p.tokenTag(p.tok_i) != .keyword_usingnamespace) {
665668 return p.fail(.expected_pub_item);
666669 }
667 return p.expectUsingNamespace();
670 return try p.expectUsingNamespace();
668671}
669672
670fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {
673fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
671674 return p.expectTopLevelDecl() catch |err| switch (err) {
672675 error.OutOfMemory => return error.OutOfMemory,
673676 error.ParseError => {
674677 p.findNextContainerMember();
675 return null_node;
678 return null;
676679 },
677680 };
678681}
......@@ -684,26 +687,23 @@ fn expectUsingNamespace(p: *Parse) !Node.Index {
684687 return p.addNode(.{
685688 .tag = .@"usingnamespace",
686689 .main_token = usingnamespace_token,
687 .data = .{
688 .lhs = expr,
689 .rhs = undefined,
690 },
690 .data = .{ .node = expr },
691691 });
692692}
693693
694fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {
694fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
695695 return p.expectUsingNamespace() catch |err| switch (err) {
696696 error.OutOfMemory => return error.OutOfMemory,
697697 error.ParseError => {
698698 p.findNextContainerMember();
699 return null_node;
699 return null;
700700 },
701701 };
702702}
703703
704704/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
705fn parseFnProto(p: *Parse) !Node.Index {
706 const fn_token = p.eatToken(.keyword_fn) orelse return null_node;
705fn parseFnProto(p: *Parse) !?Node.Index {
706 const fn_token = p.eatToken(.keyword_fn) orelse return null;
707707
708708 // We want the fn proto node to be before its children in the array.
709709 const fn_proto_index = try p.reserveNode(.fn_proto);
......@@ -718,33 +718,33 @@ fn parseFnProto(p: *Parse) !Node.Index {
718718 _ = p.eatToken(.bang);
719719
720720 const return_type_expr = try p.parseTypeExpr();
721 if (return_type_expr == 0) {
721 if (return_type_expr == null) {
722722 // most likely the user forgot to specify the return type.
723723 // Mark return type as invalid and try to continue.
724724 try p.warn(.expected_return_type);
725725 }
726726
727 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0 and addrspace_expr == 0) {
727 if (align_expr == null and section_expr == null and callconv_expr == null and addrspace_expr == null) {
728728 switch (params) {
729729 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
730730 .tag = .fn_proto_simple,
731731 .main_token = fn_token,
732 .data = .{
733 .lhs = param,
734 .rhs = return_type_expr,
735 },
732 .data = .{ .opt_node_and_opt_node = .{
733 param,
734 .fromOptional(return_type_expr),
735 } },
736736 }),
737737 .multi => |span| {
738738 return p.setNode(fn_proto_index, .{
739739 .tag = .fn_proto_multi,
740740 .main_token = fn_token,
741 .data = .{
742 .lhs = try p.addExtra(Node.SubRange{
741 .data = .{ .extra_and_opt_node = .{
742 try p.addExtra(Node.SubRange{
743743 .start = span.start,
744744 .end = span.end,
745745 }),
746 .rhs = return_type_expr,
747 },
746 .fromOptional(return_type_expr),
747 } },
748748 });
749749 },
750750 }
......@@ -753,109 +753,124 @@ fn parseFnProto(p: *Parse) !Node.Index {
753753 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
754754 .tag = .fn_proto_one,
755755 .main_token = fn_token,
756 .data = .{
757 .lhs = try p.addExtra(Node.FnProtoOne{
756 .data = .{ .extra_and_opt_node = .{
757 try p.addExtra(Node.FnProtoOne{
758758 .param = param,
759 .align_expr = align_expr,
760 .addrspace_expr = addrspace_expr,
761 .section_expr = section_expr,
762 .callconv_expr = callconv_expr,
759 .align_expr = .fromOptional(align_expr),
760 .addrspace_expr = .fromOptional(addrspace_expr),
761 .section_expr = .fromOptional(section_expr),
762 .callconv_expr = .fromOptional(callconv_expr),
763763 }),
764 .rhs = return_type_expr,
765 },
764 .fromOptional(return_type_expr),
765 } },
766766 }),
767767 .multi => |span| {
768768 return p.setNode(fn_proto_index, .{
769769 .tag = .fn_proto,
770770 .main_token = fn_token,
771 .data = .{
772 .lhs = try p.addExtra(Node.FnProto{
771 .data = .{ .extra_and_opt_node = .{
772 try p.addExtra(Node.FnProto{
773773 .params_start = span.start,
774774 .params_end = span.end,
775 .align_expr = align_expr,
776 .addrspace_expr = addrspace_expr,
777 .section_expr = section_expr,
778 .callconv_expr = callconv_expr,
775 .align_expr = .fromOptional(align_expr),
776 .addrspace_expr = .fromOptional(addrspace_expr),
777 .section_expr = .fromOptional(section_expr),
778 .callconv_expr = .fromOptional(callconv_expr),
779779 }),
780 .rhs = return_type_expr,
781 },
780 .fromOptional(return_type_expr),
781 } },
782782 });
783783 },
784784 }
785785}
786786
787fn setVarDeclInitExpr(p: *Parse, var_decl: Node.Index, init_expr: Node.OptionalIndex) void {
788 const init_expr_result = switch (p.nodeTag(var_decl)) {
789 .simple_var_decl => &p.nodes.items(.data)[@intFromEnum(var_decl)].opt_node_and_opt_node[1],
790 .aligned_var_decl => &p.nodes.items(.data)[@intFromEnum(var_decl)].node_and_opt_node[1],
791 .local_var_decl, .global_var_decl => &p.nodes.items(.data)[@intFromEnum(var_decl)].extra_and_opt_node[1],
792 else => unreachable,
793 };
794 init_expr_result.* = init_expr;
795}
796
787797/// VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection?
788/// Returns a `*_var_decl` node with its rhs (init expression) initialized to 0.
789fn parseVarDeclProto(p: *Parse) !Node.Index {
798/// Returns a `*_var_decl` node with its rhs (init expression) initialized to .none.
799fn parseVarDeclProto(p: *Parse) !?Node.Index {
790800 const mut_token = p.eatToken(.keyword_const) orelse
791801 p.eatToken(.keyword_var) orelse
792 return null_node;
802 return null;
793803
794804 _ = try p.expectToken(.identifier);
795 const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr();
796 const align_node = try p.parseByteAlign();
797 const addrspace_node = try p.parseAddrSpace();
798 const section_node = try p.parseLinkSection();
799
800 if (section_node == 0 and addrspace_node == 0) {
801 if (align_node == 0) {
802 return p.addNode(.{
805 const opt_type_node = if (p.eatToken(.colon) == null) null else try p.expectTypeExpr();
806 const opt_align_node = try p.parseByteAlign();
807 const opt_addrspace_node = try p.parseAddrSpace();
808 const opt_section_node = try p.parseLinkSection();
809
810 if (opt_section_node == null and opt_addrspace_node == null) {
811 const align_node = opt_align_node orelse {
812 return try p.addNode(.{
803813 .tag = .simple_var_decl,
804814 .main_token = mut_token,
805815 .data = .{
806 .lhs = type_node,
807 .rhs = 0,
816 .opt_node_and_opt_node = .{
817 .fromOptional(opt_type_node),
818 .none, // set later with `setVarDeclInitExpr
819 },
808820 },
809821 });
810 }
822 };
811823
812 if (type_node == 0) {
813 return p.addNode(.{
824 const type_node = opt_type_node orelse {
825 return try p.addNode(.{
814826 .tag = .aligned_var_decl,
815827 .main_token = mut_token,
816828 .data = .{
817 .lhs = align_node,
818 .rhs = 0,
829 .node_and_opt_node = .{
830 align_node,
831 .none, // set later with `setVarDeclInitExpr
832 },
819833 },
820834 });
821 }
835 };
822836
823 return p.addNode(.{
837 return try p.addNode(.{
824838 .tag = .local_var_decl,
825839 .main_token = mut_token,
826840 .data = .{
827 .lhs = try p.addExtra(Node.LocalVarDecl{
828 .type_node = type_node,
829 .align_node = align_node,
830 }),
831 .rhs = 0,
841 .extra_and_opt_node = .{
842 try p.addExtra(Node.LocalVarDecl{
843 .type_node = type_node,
844 .align_node = align_node,
845 }),
846 .none, // set later with `setVarDeclInitExpr
847 },
832848 },
833849 });
834850 } else {
835 return p.addNode(.{
851 return try p.addNode(.{
836852 .tag = .global_var_decl,
837853 .main_token = mut_token,
838854 .data = .{
839 .lhs = try p.addExtra(Node.GlobalVarDecl{
840 .type_node = type_node,
841 .align_node = align_node,
842 .addrspace_node = addrspace_node,
843 .section_node = section_node,
844 }),
845 .rhs = 0,
855 .extra_and_opt_node = .{
856 try p.addExtra(Node.GlobalVarDecl{
857 .type_node = .fromOptional(opt_type_node),
858 .align_node = .fromOptional(opt_align_node),
859 .addrspace_node = .fromOptional(opt_addrspace_node),
860 .section_node = .fromOptional(opt_section_node),
861 }),
862 .none, // set later with `setVarDeclInitExpr
863 },
846864 },
847865 });
848866 }
849867}
850868
851869/// GlobalVarDecl <- VarDeclProto (EQUAL Expr?) SEMICOLON
852fn parseGlobalVarDecl(p: *Parse) !Node.Index {
853 const var_decl = try p.parseVarDeclProto();
854 if (var_decl == 0) {
855 return null_node;
856 }
870fn parseGlobalVarDecl(p: *Parse) !?Node.Index {
871 const var_decl = try p.parseVarDeclProto() orelse return null;
857872
858 const init_node: Node.Index = switch (p.token_tags[p.tok_i]) {
873 const init_node: ?Node.Index = switch (p.tokenTag(p.tok_i)) {
859874 .equal_equal => blk: {
860875 try p.warn(.wrong_equal_var_decl);
861876 p.tok_i += 1;
......@@ -865,10 +880,10 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {
865880 p.tok_i += 1;
866881 break :blk try p.expectExpr();
867882 },
868 else => 0,
883 else => null,
869884 };
870885
871 p.nodes.items(.data)[var_decl].rhs = init_node;
886 p.setVarDeclInitExpr(var_decl, .fromOptional(init_node));
872887
873888 try p.expectSemicolon(.expected_semi_after_decl, false);
874889 return var_decl;
......@@ -878,40 +893,39 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {
878893fn expectContainerField(p: *Parse) !Node.Index {
879894 _ = p.eatToken(.keyword_comptime);
880895 const main_token = p.tok_i;
881 if (p.token_tags[p.tok_i] == .identifier and p.token_tags[p.tok_i + 1] == .colon) p.tok_i += 2;
896 _ = p.eatTokens(&.{ .identifier, .colon });
882897 const type_expr = try p.expectTypeExpr();
883898 const align_expr = try p.parseByteAlign();
884 const value_expr: Node.Index = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
899 const value_expr = if (p.eatToken(.equal) == null) null else try p.expectExpr();
885900
886 if (align_expr == 0) {
901 if (align_expr == null) {
887902 return p.addNode(.{
888903 .tag = .container_field_init,
889904 .main_token = main_token,
890 .data = .{
891 .lhs = type_expr,
892 .rhs = value_expr,
893 },
905 .data = .{ .node_and_opt_node = .{
906 type_expr,
907 .fromOptional(value_expr),
908 } },
894909 });
895 } else if (value_expr == 0) {
910 } else if (value_expr == null) {
896911 return p.addNode(.{
897912 .tag = .container_field_align,
898913 .main_token = main_token,
899 .data = .{
900 .lhs = type_expr,
901 .rhs = align_expr,
902 },
914 .data = .{ .node_and_node = .{
915 type_expr,
916 align_expr.?,
917 } },
903918 });
904919 } else {
905920 return p.addNode(.{
906921 .tag = .container_field,
907922 .main_token = main_token,
908 .data = .{
909 .lhs = type_expr,
910 .rhs = try p.addExtra(Node.ContainerField{
911 .align_expr = align_expr,
912 .value_expr = value_expr,
923 .data = .{ .node_and_extra = .{
924 type_expr, try p.addExtra(Node.ContainerField{
925 .align_expr = align_expr.?,
926 .value_expr = value_expr.?,
913927 }),
914 },
928 } },
915929 });
916930 }
917931}
......@@ -927,15 +941,12 @@ fn expectContainerField(p: *Parse) !Node.Index {
927941/// / VarDeclExprStatement
928942fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
929943 if (p.eatToken(.keyword_comptime)) |comptime_token| {
930 const block_expr = try p.parseBlockExpr();
931 if (block_expr != 0) {
944 const opt_block_expr = try p.parseBlockExpr();
945 if (opt_block_expr) |block_expr| {
932946 return p.addNode(.{
933947 .tag = .@"comptime",
934948 .main_token = comptime_token,
935 .data = .{
936 .lhs = block_expr,
937 .rhs = undefined,
938 },
949 .data = .{ .node = block_expr },
939950 });
940951 }
941952
......@@ -947,23 +958,17 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
947958 return p.addNode(.{
948959 .tag = .@"comptime",
949960 .main_token = comptime_token,
950 .data = .{
951 .lhs = assign,
952 .rhs = undefined,
953 },
961 .data = .{ .node = assign },
954962 });
955963 }
956964 }
957965
958 switch (p.token_tags[p.tok_i]) {
966 switch (p.tokenTag(p.tok_i)) {
959967 .keyword_nosuspend => {
960968 return p.addNode(.{
961969 .tag = .@"nosuspend",
962970 .main_token = p.nextToken(),
963 .data = .{
964 .lhs = try p.expectBlockExprStatement(),
965 .rhs = undefined,
966 },
971 .data = .{ .node = try p.expectBlockExprStatement() },
967972 });
968973 },
969974 .keyword_suspend => {
......@@ -972,27 +977,21 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
972977 return p.addNode(.{
973978 .tag = .@"suspend",
974979 .main_token = token,
975 .data = .{
976 .lhs = block_expr,
977 .rhs = undefined,
978 },
980 .data = .{ .node = block_expr },
979981 });
980982 },
981983 .keyword_defer => if (allow_defer_var) return p.addNode(.{
982984 .tag = .@"defer",
983985 .main_token = p.nextToken(),
984 .data = .{
985 .lhs = undefined,
986 .rhs = try p.expectBlockExprStatement(),
987 },
986 .data = .{ .node = try p.expectBlockExprStatement() },
988987 }),
989988 .keyword_errdefer => if (allow_defer_var) return p.addNode(.{
990989 .tag = .@"errdefer",
991990 .main_token = p.nextToken(),
992 .data = .{
993 .lhs = try p.parsePayload(),
994 .rhs = try p.expectBlockExprStatement(),
995 },
991 .data = .{ .opt_token_and_node = .{
992 try p.parsePayload(),
993 try p.expectBlockExprStatement(),
994 } },
996995 }),
997996 .keyword_if => return p.expectIfStatement(),
998997 .keyword_enum, .keyword_struct, .keyword_union => {
......@@ -1002,18 +1001,14 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
10021001 return p.addNode(.{
10031002 .tag = .identifier,
10041003 .main_token = identifier,
1005 .data = .{
1006 .lhs = undefined,
1007 .rhs = undefined,
1008 },
1004 .data = undefined,
10091005 });
10101006 }
10111007 },
10121008 else => {},
10131009 }
10141010
1015 const labeled_statement = try p.parseLabeledStatement();
1016 if (labeled_statement != 0) return labeled_statement;
1011 if (try p.parseLabeledStatement()) |labeled_statement| return labeled_statement;
10171012
10181013 if (allow_defer_var) {
10191014 return p.expectVarDeclExprStatement(null);
......@@ -1028,12 +1023,15 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
10281023/// <- BlockExpr
10291024/// / VarDeclExprStatement
10301025fn expectComptimeStatement(p: *Parse, comptime_token: TokenIndex) !Node.Index {
1031 const block_expr = try p.parseBlockExpr();
1032 if (block_expr != 0) {
1026 const maybe_block_expr = try p.parseBlockExpr();
1027 if (maybe_block_expr) |block_expr| {
10331028 return p.addNode(.{
10341029 .tag = .@"comptime",
10351030 .main_token = comptime_token,
1036 .data = .{ .lhs = block_expr, .rhs = undefined },
1031 .data = .{
1032 .lhs = .{ .node = block_expr },
1033 .rhs = undefined,
1034 },
10371035 });
10381036 }
10391037 return p.expectVarDeclExprStatement(comptime_token);
......@@ -1047,12 +1045,11 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
10471045 defer p.scratch.shrinkRetainingCapacity(scratch_top);
10481046
10491047 while (true) {
1050 const var_decl_proto = try p.parseVarDeclProto();
1051 if (var_decl_proto != 0) {
1052 try p.scratch.append(p.gpa, var_decl_proto);
1048 const opt_var_decl_proto = try p.parseVarDeclProto();
1049 if (opt_var_decl_proto) |var_decl| {
1050 try p.scratch.append(p.gpa, var_decl);
10531051 } else {
1054 const expr = try p.parseExpr();
1055 if (expr == 0) {
1052 const expr = try p.parseExpr() orelse {
10561053 if (p.scratch.items.len == scratch_top) {
10571054 // We parsed nothing
10581055 return p.fail(.expected_statement);
......@@ -1060,7 +1057,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
10601057 // We've had at least one LHS, but had a bad comma
10611058 return p.fail(.expected_expr_or_var_decl);
10621059 }
1063 }
1060 };
10641061 try p.scratch.append(p.gpa, expr);
10651062 }
10661063 _ = p.eatToken(.comma) orelse break;
......@@ -1079,7 +1076,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
10791076 return p.failExpected(.equal);
10801077 }
10811078 const lhs = p.scratch.items[scratch_top];
1082 switch (p.nodes.items(.tag)[lhs]) {
1079 switch (p.nodeTag(lhs)) {
10831080 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {
10841081 // Definitely a var decl, so allow recovering from ==
10851082 if (p.eatToken(.equal_equal)) |tok| {
......@@ -1097,10 +1094,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
10971094 return p.addNode(.{
10981095 .tag = .@"comptime",
10991096 .main_token = t,
1100 .data = .{
1101 .lhs = expr,
1102 .rhs = undefined,
1103 },
1097 .data = .{ .node = expr },
11041098 });
11051099 } else {
11061100 return expr;
......@@ -1112,9 +1106,9 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
11121106
11131107 if (lhs_count == 1) {
11141108 const lhs = p.scratch.items[scratch_top];
1115 switch (p.nodes.items(.tag)[lhs]) {
1116 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {
1117 p.nodes.items(.data)[lhs].rhs = rhs;
1109 switch (p.nodeTag(lhs)) {
1110 .simple_var_decl, .aligned_var_decl, .local_var_decl, .global_var_decl => {
1111 p.setVarDeclInitExpr(lhs, rhs.toOptional());
11181112 // Don't need to wrap in comptime
11191113 return lhs;
11201114 },
......@@ -1123,16 +1117,16 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
11231117 const expr = try p.addNode(.{
11241118 .tag = .assign,
11251119 .main_token = equal_token,
1126 .data = .{ .lhs = lhs, .rhs = rhs },
1120 .data = .{ .node_and_node = .{
1121 lhs,
1122 rhs,
1123 } },
11271124 });
11281125 if (comptime_token) |t| {
11291126 return p.addNode(.{
11301127 .tag = .@"comptime",
11311128 .main_token = t,
1132 .data = .{
1133 .lhs = expr,
1134 .rhs = undefined,
1135 },
1129 .data = .{ .node = expr },
11361130 });
11371131 } else {
11381132 return expr;
......@@ -1141,32 +1135,32 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
11411135
11421136 // An actual destructure! No need for any `comptime` wrapper here.
11431137
1144 const extra_start = p.extra_data.items.len;
1138 const extra_start: ExtraIndex = @enumFromInt(p.extra_data.items.len);
11451139 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);
11461140 p.extra_data.appendAssumeCapacity(@intCast(lhs_count));
1147 p.extra_data.appendSliceAssumeCapacity(p.scratch.items[scratch_top..]);
1141 p.extra_data.appendSliceAssumeCapacity(@ptrCast(p.scratch.items[scratch_top..]));
11481142
11491143 return p.addNode(.{
11501144 .tag = .assign_destructure,
11511145 .main_token = equal_token,
1152 .data = .{
1153 .lhs = @intCast(extra_start),
1154 .rhs = rhs,
1155 },
1146 .data = .{ .extra_and_node = .{
1147 extra_start,
1148 rhs,
1149 } },
11561150 });
11571151}
11581152
11591153/// If a parse error occurs, reports an error, but then finds the next statement
11601154/// and returns that one instead. If a parse error occurs but there is no following
11611155/// statement, returns 0.
1162fn expectStatementRecoverable(p: *Parse) Error!Node.Index {
1156fn expectStatementRecoverable(p: *Parse) Error!?Node.Index {
11631157 while (true) {
11641158 return p.expectStatement(true) catch |err| switch (err) {
11651159 error.OutOfMemory => return error.OutOfMemory,
11661160 error.ParseError => {
11671161 p.findNextStmt(); // Try to skip to the next statement.
1168 switch (p.token_tags[p.tok_i]) {
1169 .r_brace => return null_node,
1162 switch (p.tokenTag(p.tok_i)) {
1163 .r_brace => return null,
11701164 .eof => return error.ParseError,
11711165 else => continue,
11721166 }
......@@ -1190,19 +1184,18 @@ fn expectIfStatement(p: *Parse) !Node.Index {
11901184 var else_required = false;
11911185 const then_expr = blk: {
11921186 const block_expr = try p.parseBlockExpr();
1193 if (block_expr != 0) break :blk block_expr;
1194 const assign_expr = try p.parseAssignExpr();
1195 if (assign_expr == 0) {
1187 if (block_expr) |block| break :blk block;
1188 const assign_expr = try p.parseAssignExpr() orelse {
11961189 return p.fail(.expected_block_or_assignment);
1197 }
1190 };
11981191 if (p.eatToken(.semicolon)) |_| {
11991192 return p.addNode(.{
12001193 .tag = .if_simple,
12011194 .main_token = if_token,
1202 .data = .{
1203 .lhs = condition,
1204 .rhs = assign_expr,
1205 },
1195 .data = .{ .node_and_node = .{
1196 condition,
1197 assign_expr,
1198 } },
12061199 });
12071200 }
12081201 else_required = true;
......@@ -1215,10 +1208,10 @@ fn expectIfStatement(p: *Parse) !Node.Index {
12151208 return p.addNode(.{
12161209 .tag = .if_simple,
12171210 .main_token = if_token,
1218 .data = .{
1219 .lhs = condition,
1220 .rhs = then_expr,
1221 },
1211 .data = .{ .node_and_node = .{
1212 condition,
1213 then_expr,
1214 } },
12221215 });
12231216 };
12241217 _ = try p.parsePayload();
......@@ -1226,57 +1219,46 @@ fn expectIfStatement(p: *Parse) !Node.Index {
12261219 return p.addNode(.{
12271220 .tag = .@"if",
12281221 .main_token = if_token,
1229 .data = .{
1230 .lhs = condition,
1231 .rhs = try p.addExtra(Node.If{
1222 .data = .{ .node_and_extra = .{
1223 condition, try p.addExtra(Node.If{
12321224 .then_expr = then_expr,
12331225 .else_expr = else_expr,
12341226 }),
1235 },
1227 } },
12361228 });
12371229}
12381230
12391231/// LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr)
1240fn parseLabeledStatement(p: *Parse) !Node.Index {
1241 const label_token = p.parseBlockLabel();
1242 const block = try p.parseBlock();
1243 if (block != 0) return block;
1244
1245 const loop_stmt = try p.parseLoopStatement();
1246 if (loop_stmt != 0) return loop_stmt;
1247
1248 const switch_expr = try p.parseSwitchExpr(label_token != 0);
1249 if (switch_expr != 0) return switch_expr;
1250
1251 if (label_token != 0) {
1252 const after_colon = p.tok_i;
1253 const node = try p.parseTypeExpr();
1254 if (node != 0) {
1255 const a = try p.parseByteAlign();
1256 const b = try p.parseAddrSpace();
1257 const c = try p.parseLinkSection();
1258 const d = if (p.eatToken(.equal) == null) 0 else try p.expectExpr();
1259 if (a != 0 or b != 0 or c != 0 or d != 0) {
1260 return p.failMsg(.{ .tag = .expected_var_const, .token = label_token });
1261 }
1232fn parseLabeledStatement(p: *Parse) !?Node.Index {
1233 const opt_label_token = p.parseBlockLabel();
1234
1235 if (try p.parseBlock()) |block| return block;
1236 if (try p.parseLoopStatement()) |loop_stmt| return loop_stmt;
1237 if (try p.parseSwitchExpr(opt_label_token != null)) |switch_expr| return switch_expr;
1238
1239 const label_token = opt_label_token orelse return null;
1240
1241 const after_colon = p.tok_i;
1242 if (try p.parseTypeExpr()) |_| {
1243 const a = try p.parseByteAlign();
1244 const b = try p.parseAddrSpace();
1245 const c = try p.parseLinkSection();
1246 const d = if (p.eatToken(.equal) == null) null else try p.expectExpr();
1247 if (a != null or b != null or c != null or d != null) {
1248 return p.failMsg(.{ .tag = .expected_var_const, .token = label_token });
12621249 }
1263 return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
12641250 }
1265
1266 return null_node;
1251 return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
12671252}
12681253
12691254/// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
1270fn parseLoopStatement(p: *Parse) !Node.Index {
1255fn parseLoopStatement(p: *Parse) !?Node.Index {
12711256 const inline_token = p.eatToken(.keyword_inline);
12721257
1273 const for_statement = try p.parseForStatement();
1274 if (for_statement != 0) return for_statement;
1258 if (try p.parseForStatement()) |for_statement| return for_statement;
1259 if (try p.parseWhileStatement()) |while_statement| return while_statement;
12751260
1276 const while_statement = try p.parseWhileStatement();
1277 if (while_statement != 0) return while_statement;
1278
1279 if (inline_token == null) return null_node;
1261 if (inline_token == null) return null;
12801262
12811263 // If we've seen "inline", there should have been a "for" or "while"
12821264 return p.fail(.expected_inlinable);
......@@ -1285,8 +1267,8 @@ fn parseLoopStatement(p: *Parse) !Node.Index {
12851267/// ForStatement
12861268/// <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
12871269/// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
1288fn parseForStatement(p: *Parse) !Node.Index {
1289 const for_token = p.eatToken(.keyword_for) orelse return null_node;
1270fn parseForStatement(p: *Parse) !?Node.Index {
1271 const for_token = p.eatToken(.keyword_for) orelse return null;
12901272
12911273 const scratch_top = p.scratch.items.len;
12921274 defer p.scratch.shrinkRetainingCapacity(scratch_top);
......@@ -1296,11 +1278,10 @@ fn parseForStatement(p: *Parse) !Node.Index {
12961278 var seen_semicolon = false;
12971279 const then_expr = blk: {
12981280 const block_expr = try p.parseBlockExpr();
1299 if (block_expr != 0) break :blk block_expr;
1300 const assign_expr = try p.parseAssignExpr();
1301 if (assign_expr == 0) {
1281 if (block_expr) |block| break :blk block;
1282 const assign_expr = try p.parseAssignExpr() orelse {
13021283 return p.fail(.expected_block_or_assignment);
1303 }
1284 };
13041285 if (p.eatToken(.semicolon)) |_| {
13051286 seen_semicolon = true;
13061287 break :blk assign_expr;
......@@ -1316,28 +1297,25 @@ fn parseForStatement(p: *Parse) !Node.Index {
13161297 has_else = true;
13171298 } else if (inputs == 1) {
13181299 if (else_required) try p.warn(.expected_semi_or_else);
1319 return p.addNode(.{
1300 return try p.addNode(.{
13201301 .tag = .for_simple,
13211302 .main_token = for_token,
1322 .data = .{
1323 .lhs = p.scratch.items[scratch_top],
1324 .rhs = then_expr,
1325 },
1303 .data = .{ .node_and_node = .{
1304 p.scratch.items[scratch_top],
1305 then_expr,
1306 } },
13261307 });
13271308 } else {
13281309 if (else_required) try p.warn(.expected_semi_or_else);
13291310 try p.scratch.append(p.gpa, then_expr);
13301311 }
1331 return p.addNode(.{
1312 return try p.addNode(.{
13321313 .tag = .@"for",
13331314 .main_token = for_token,
1334 .data = .{
1335 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,
1336 .rhs = @as(u32, @bitCast(Node.For{
1337 .inputs = @as(u31, @intCast(inputs)),
1338 .has_else = has_else,
1339 })),
1340 },
1315 .data = .{ .@"for" = .{
1316 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
1317 .{ .inputs = @intCast(inputs), .has_else = has_else },
1318 } },
13411319 });
13421320}
13431321
......@@ -1346,8 +1324,8 @@ fn parseForStatement(p: *Parse) !Node.Index {
13461324/// WhileStatement
13471325/// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
13481326/// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
1349fn parseWhileStatement(p: *Parse) !Node.Index {
1350 const while_token = p.eatToken(.keyword_while) orelse return null_node;
1327fn parseWhileStatement(p: *Parse) !?Node.Index {
1328 const while_token = p.eatToken(.keyword_while) orelse return null;
13511329 _ = try p.expectToken(.l_paren);
13521330 const condition = try p.expectExpr();
13531331 _ = try p.expectToken(.r_paren);
......@@ -1359,32 +1337,31 @@ fn parseWhileStatement(p: *Parse) !Node.Index {
13591337 var else_required = false;
13601338 const then_expr = blk: {
13611339 const block_expr = try p.parseBlockExpr();
1362 if (block_expr != 0) break :blk block_expr;
1363 const assign_expr = try p.parseAssignExpr();
1364 if (assign_expr == 0) {
1340 if (block_expr) |block| break :blk block;
1341 const assign_expr = try p.parseAssignExpr() orelse {
13651342 return p.fail(.expected_block_or_assignment);
1366 }
1343 };
13671344 if (p.eatToken(.semicolon)) |_| {
1368 if (cont_expr == 0) {
1369 return p.addNode(.{
1345 if (cont_expr == null) {
1346 return try p.addNode(.{
13701347 .tag = .while_simple,
13711348 .main_token = while_token,
1372 .data = .{
1373 .lhs = condition,
1374 .rhs = assign_expr,
1375 },
1349 .data = .{ .node_and_node = .{
1350 condition,
1351 assign_expr,
1352 } },
13761353 });
13771354 } else {
1378 return p.addNode(.{
1355 return try p.addNode(.{
13791356 .tag = .while_cont,
13801357 .main_token = while_token,
1381 .data = .{
1382 .lhs = condition,
1383 .rhs = try p.addExtra(Node.WhileCont{
1384 .cont_expr = cont_expr,
1358 .data = .{ .node_and_extra = .{
1359 condition,
1360 try p.addExtra(Node.WhileCont{
1361 .cont_expr = cont_expr.?,
13851362 .then_expr = assign_expr,
13861363 }),
1387 },
1364 } },
13881365 });
13891366 }
13901367 }
......@@ -1395,84 +1372,77 @@ fn parseWhileStatement(p: *Parse) !Node.Index {
13951372 if (else_required) {
13961373 try p.warn(.expected_semi_or_else);
13971374 }
1398 if (cont_expr == 0) {
1399 return p.addNode(.{
1375 if (cont_expr == null) {
1376 return try p.addNode(.{
14001377 .tag = .while_simple,
14011378 .main_token = while_token,
1402 .data = .{
1403 .lhs = condition,
1404 .rhs = then_expr,
1405 },
1379 .data = .{ .node_and_node = .{
1380 condition,
1381 then_expr,
1382 } },
14061383 });
14071384 } else {
1408 return p.addNode(.{
1385 return try p.addNode(.{
14091386 .tag = .while_cont,
14101387 .main_token = while_token,
1411 .data = .{
1412 .lhs = condition,
1413 .rhs = try p.addExtra(Node.WhileCont{
1414 .cont_expr = cont_expr,
1388 .data = .{ .node_and_extra = .{
1389 condition,
1390 try p.addExtra(Node.WhileCont{
1391 .cont_expr = cont_expr.?,
14151392 .then_expr = then_expr,
14161393 }),
1417 },
1394 } },
14181395 });
14191396 }
14201397 };
14211398 _ = try p.parsePayload();
14221399 const else_expr = try p.expectStatement(false);
1423 return p.addNode(.{
1400 return try p.addNode(.{
14241401 .tag = .@"while",
14251402 .main_token = while_token,
1426 .data = .{
1427 .lhs = condition,
1428 .rhs = try p.addExtra(Node.While{
1429 .cont_expr = cont_expr,
1403 .data = .{ .node_and_extra = .{
1404 condition, try p.addExtra(Node.While{
1405 .cont_expr = .fromOptional(cont_expr),
14301406 .then_expr = then_expr,
14311407 .else_expr = else_expr,
14321408 }),
1433 },
1409 } },
14341410 });
14351411}
14361412
14371413/// BlockExprStatement
14381414/// <- BlockExpr
14391415/// / AssignExpr SEMICOLON
1440fn parseBlockExprStatement(p: *Parse) !Node.Index {
1416fn parseBlockExprStatement(p: *Parse) !?Node.Index {
14411417 const block_expr = try p.parseBlockExpr();
1442 if (block_expr != 0) {
1443 return block_expr;
1444 }
1418 if (block_expr) |expr| return expr;
14451419 const assign_expr = try p.parseAssignExpr();
1446 if (assign_expr != 0) {
1420 if (assign_expr) |expr| {
14471421 try p.expectSemicolon(.expected_semi_after_stmt, true);
1448 return assign_expr;
1422 return expr;
14491423 }
1450 return null_node;
1424 return null;
14511425}
14521426
14531427fn expectBlockExprStatement(p: *Parse) !Node.Index {
1454 const node = try p.parseBlockExprStatement();
1455 if (node == 0) {
1456 return p.fail(.expected_block_or_expr);
1457 }
1458 return node;
1428 return try p.parseBlockExprStatement() orelse return p.fail(.expected_block_or_expr);
14591429}
14601430
14611431/// BlockExpr <- BlockLabel? Block
1462fn parseBlockExpr(p: *Parse) Error!Node.Index {
1463 switch (p.token_tags[p.tok_i]) {
1432fn parseBlockExpr(p: *Parse) Error!?Node.Index {
1433 switch (p.tokenTag(p.tok_i)) {
14641434 .identifier => {
1465 if (p.token_tags[p.tok_i + 1] == .colon and
1466 p.token_tags[p.tok_i + 2] == .l_brace)
1435 if (p.tokenTag(p.tok_i + 1) == .colon and
1436 p.tokenTag(p.tok_i + 2) == .l_brace)
14671437 {
14681438 p.tok_i += 2;
14691439 return p.parseBlock();
14701440 } else {
1471 return null_node;
1441 return null;
14721442 }
14731443 },
14741444 .l_brace => return p.parseBlock(),
1475 else => return null_node,
1445 else => return null,
14761446 }
14771447}
14781448
......@@ -1497,38 +1467,36 @@ fn parseBlockExpr(p: *Parse) Error!Node.Index {
14971467/// / PLUSPERCENTEQUAL
14981468/// / MINUSPERCENTEQUAL
14991469/// / EQUAL
1500fn parseAssignExpr(p: *Parse) !Node.Index {
1501 const expr = try p.parseExpr();
1502 if (expr == 0) return null_node;
1503 return p.finishAssignExpr(expr);
1470fn parseAssignExpr(p: *Parse) !?Node.Index {
1471 const expr = try p.parseExpr() orelse return null;
1472 return try p.finishAssignExpr(expr);
15041473}
15051474
15061475/// SingleAssignExpr <- Expr (AssignOp Expr)?
1507fn parseSingleAssignExpr(p: *Parse) !Node.Index {
1508 const lhs = try p.parseExpr();
1509 if (lhs == 0) return null_node;
1510 const tag = assignOpNode(p.token_tags[p.tok_i]) orelse return lhs;
1511 return p.addNode(.{
1476fn parseSingleAssignExpr(p: *Parse) !?Node.Index {
1477 const lhs = try p.parseExpr() orelse return null;
1478 const tag = assignOpNode(p.tokenTag(p.tok_i)) orelse return lhs;
1479 return try p.addNode(.{
15121480 .tag = tag,
15131481 .main_token = p.nextToken(),
1514 .data = .{
1515 .lhs = lhs,
1516 .rhs = try p.expectExpr(),
1517 },
1482 .data = .{ .node_and_node = .{
1483 lhs,
1484 try p.expectExpr(),
1485 } },
15181486 });
15191487}
15201488
15211489fn finishAssignExpr(p: *Parse, lhs: Node.Index) !Node.Index {
1522 const tok = p.token_tags[p.tok_i];
1490 const tok = p.tokenTag(p.tok_i);
15231491 if (tok == .comma) return p.finishAssignDestructureExpr(lhs);
15241492 const tag = assignOpNode(tok) orelse return lhs;
15251493 return p.addNode(.{
15261494 .tag = tag,
15271495 .main_token = p.nextToken(),
1528 .data = .{
1529 .lhs = lhs,
1530 .rhs = try p.expectExpr(),
1531 },
1496 .data = .{ .node_and_node = .{
1497 lhs,
1498 try p.expectExpr(),
1499 } },
15321500 });
15331501}
15341502
......@@ -1574,48 +1542,35 @@ fn finishAssignDestructureExpr(p: *Parse, first_lhs: Node.Index) !Node.Index {
15741542 const lhs_count = p.scratch.items.len - scratch_top;
15751543 assert(lhs_count > 1); // we already had first_lhs, and must have at least one more lvalue
15761544
1577 const extra_start = p.extra_data.items.len;
1545 const extra_start: ExtraIndex = @enumFromInt(p.extra_data.items.len);
15781546 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);
15791547 p.extra_data.appendAssumeCapacity(@intCast(lhs_count));
1580 p.extra_data.appendSliceAssumeCapacity(p.scratch.items[scratch_top..]);
1548 p.extra_data.appendSliceAssumeCapacity(@ptrCast(p.scratch.items[scratch_top..]));
15811549
15821550 return p.addNode(.{
15831551 .tag = .assign_destructure,
15841552 .main_token = equal_token,
1585 .data = .{
1586 .lhs = @intCast(extra_start),
1587 .rhs = rhs,
1588 },
1553 .data = .{ .extra_and_node = .{
1554 extra_start,
1555 rhs,
1556 } },
15891557 });
15901558}
15911559
15921560fn expectSingleAssignExpr(p: *Parse) !Node.Index {
1593 const expr = try p.parseSingleAssignExpr();
1594 if (expr == 0) {
1595 return p.fail(.expected_expr_or_assignment);
1596 }
1597 return expr;
1561 return try p.parseSingleAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
15981562}
15991563
16001564fn expectAssignExpr(p: *Parse) !Node.Index {
1601 const expr = try p.parseAssignExpr();
1602 if (expr == 0) {
1603 return p.fail(.expected_expr_or_assignment);
1604 }
1605 return expr;
1565 return try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
16061566}
16071567
1608fn parseExpr(p: *Parse) Error!Node.Index {
1568fn parseExpr(p: *Parse) Error!?Node.Index {
16091569 return p.parseExprPrecedence(0);
16101570}
16111571
16121572fn expectExpr(p: *Parse) Error!Node.Index {
1613 const node = try p.parseExpr();
1614 if (node == 0) {
1615 return p.fail(.expected_expr);
1616 } else {
1617 return node;
1618 }
1573 return try p.parseExpr() orelse return p.fail(.expected_expr);
16191574}
16201575
16211576const Assoc = enum {
......@@ -1671,17 +1626,14 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec
16711626 .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat },
16721627});
16731628
1674fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
1629fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {
16751630 assert(min_prec >= 0);
1676 var node = try p.parsePrefixExpr();
1677 if (node == 0) {
1678 return null_node;
1679 }
1631 var node = try p.parsePrefixExpr() orelse return null;
16801632
16811633 var banned_prec: i8 = -1;
16821634
16831635 while (true) {
1684 const tok_tag = p.token_tags[p.tok_i];
1636 const tok_tag = p.tokenTag(p.tok_i);
16851637 const info = operTable[@as(usize, @intCast(@intFromEnum(tok_tag)))];
16861638 if (info.prec < min_prec) {
16871639 break;
......@@ -1695,16 +1647,15 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
16951647 if (tok_tag == .keyword_catch) {
16961648 _ = try p.parsePayload();
16971649 }
1698 const rhs = try p.parseExprPrecedence(info.prec + 1);
1699 if (rhs == 0) {
1650 const rhs = try p.parseExprPrecedence(info.prec + 1) orelse {
17001651 try p.warn(.expected_expr);
17011652 return node;
1702 }
1653 };
17031654
17041655 {
17051656 const tok_len = tok_tag.lexeme().?.len;
1706 const char_before = p.source[p.token_starts[oper_token] - 1];
1707 const char_after = p.source[p.token_starts[oper_token] + tok_len];
1657 const char_before = p.source[p.tokenStart(oper_token) - 1];
1658 const char_after = p.source[p.tokenStart(oper_token) + tok_len];
17081659 if (tok_tag == .ampersand and char_after == '&') {
17091660 // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and
17101661 // The best the parser can do is recommend changing it to 'and' or ' & &'
......@@ -1717,10 +1668,7 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
17171668 node = try p.addNode(.{
17181669 .tag = info.tag,
17191670 .main_token = oper_token,
1720 .data = .{
1721 .lhs = node,
1722 .rhs = rhs,
1723 },
1671 .data = .{ .node_and_node = .{ node, rhs } },
17241672 });
17251673
17261674 if (info.assoc == Assoc.none) {
......@@ -1741,8 +1689,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
17411689/// / AMPERSAND
17421690/// / KEYWORD_try
17431691/// / KEYWORD_await
1744fn parsePrefixExpr(p: *Parse) Error!Node.Index {
1745 const tag: Node.Tag = switch (p.token_tags[p.tok_i]) {
1692fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
1693 const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {
17461694 .bang => .bool_not,
17471695 .minus => .negation,
17481696 .tilde => .bit_not,
......@@ -1752,22 +1700,15 @@ fn parsePrefixExpr(p: *Parse) Error!Node.Index {
17521700 .keyword_await => .@"await",
17531701 else => return p.parsePrimaryExpr(),
17541702 };
1755 return p.addNode(.{
1703 return try p.addNode(.{
17561704 .tag = tag,
17571705 .main_token = p.nextToken(),
1758 .data = .{
1759 .lhs = try p.expectPrefixExpr(),
1760 .rhs = undefined,
1761 },
1706 .data = .{ .node = try p.expectPrefixExpr() },
17621707 });
17631708}
17641709
17651710fn expectPrefixExpr(p: *Parse) Error!Node.Index {
1766 const node = try p.parsePrefixExpr();
1767 if (node == 0) {
1768 return p.fail(.expected_prefix_expr);
1769 }
1770 return node;
1711 return try p.parsePrefixExpr() orelse return p.fail(.expected_prefix_expr);
17711712}
17721713
17731714/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
......@@ -1787,67 +1728,64 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index {
17871728/// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
17881729///
17891730/// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET
1790fn parseTypeExpr(p: *Parse) Error!Node.Index {
1791 switch (p.token_tags[p.tok_i]) {
1792 .question_mark => return p.addNode(.{
1731fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1732 switch (p.tokenTag(p.tok_i)) {
1733 .question_mark => return try p.addNode(.{
17931734 .tag = .optional_type,
17941735 .main_token = p.nextToken(),
1795 .data = .{
1796 .lhs = try p.expectTypeExpr(),
1797 .rhs = undefined,
1798 },
1736 .data = .{ .node = try p.expectTypeExpr() },
17991737 }),
1800 .keyword_anyframe => switch (p.token_tags[p.tok_i + 1]) {
1801 .arrow => return p.addNode(.{
1738 .keyword_anyframe => switch (p.tokenTag(p.tok_i + 1)) {
1739 .arrow => return try p.addNode(.{
18021740 .tag = .anyframe_type,
18031741 .main_token = p.nextToken(),
1804 .data = .{
1805 .lhs = p.nextToken(),
1806 .rhs = try p.expectTypeExpr(),
1807 },
1742 .data = .{ .token_and_node = .{
1743 p.nextToken(),
1744 try p.expectTypeExpr(),
1745 } },
18081746 }),
1809 else => return p.parseErrorUnionExpr(),
1747 else => return try p.parseErrorUnionExpr(),
18101748 },
18111749 .asterisk => {
18121750 const asterisk = p.nextToken();
18131751 const mods = try p.parsePtrModifiers();
18141752 const elem_type = try p.expectTypeExpr();
1815 if (mods.bit_range_start != 0) {
1816 return p.addNode(.{
1753 if (mods.bit_range_start != .none) {
1754 return try p.addNode(.{
18171755 .tag = .ptr_type_bit_range,
18181756 .main_token = asterisk,
1819 .data = .{
1820 .lhs = try p.addExtra(Node.PtrTypeBitRange{
1821 .sentinel = 0,
1822 .align_node = mods.align_node,
1757 .data = .{ .extra_and_node = .{
1758 try p.addExtra(Node.PtrTypeBitRange{
1759 .sentinel = .none,
1760 .align_node = mods.align_node.unwrap().?,
18231761 .addrspace_node = mods.addrspace_node,
1824 .bit_range_start = mods.bit_range_start,
1825 .bit_range_end = mods.bit_range_end,
1762 .bit_range_start = mods.bit_range_start.unwrap().?,
1763 .bit_range_end = mods.bit_range_end.unwrap().?,
18261764 }),
1827 .rhs = elem_type,
1828 },
1765 elem_type,
1766 } },
18291767 });
1830 } else if (mods.addrspace_node != 0) {
1831 return p.addNode(.{
1768 } else if (mods.addrspace_node != .none) {
1769 return try p.addNode(.{
18321770 .tag = .ptr_type,
18331771 .main_token = asterisk,
1834 .data = .{
1835 .lhs = try p.addExtra(Node.PtrType{
1836 .sentinel = 0,
1772 .data = .{ .extra_and_node = .{
1773 try p.addExtra(Node.PtrType{
1774 .sentinel = .none,
18371775 .align_node = mods.align_node,
18381776 .addrspace_node = mods.addrspace_node,
18391777 }),
1840 .rhs = elem_type,
1841 },
1778 elem_type,
1779 } },
18421780 });
18431781 } else {
1844 return p.addNode(.{
1782 return try p.addNode(.{
18451783 .tag = .ptr_type_aligned,
18461784 .main_token = asterisk,
1847 .data = .{
1848 .lhs = mods.align_node,
1849 .rhs = elem_type,
1850 },
1785 .data = .{ .opt_node_and_node = .{
1786 mods.align_node,
1787 elem_type,
1788 } },
18511789 });
18521790 }
18531791 },
......@@ -1856,61 +1794,61 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
18561794 const mods = try p.parsePtrModifiers();
18571795 const elem_type = try p.expectTypeExpr();
18581796 const inner: Node.Index = inner: {
1859 if (mods.bit_range_start != 0) {
1797 if (mods.bit_range_start != .none) {
18601798 break :inner try p.addNode(.{
18611799 .tag = .ptr_type_bit_range,
18621800 .main_token = asterisk,
1863 .data = .{
1864 .lhs = try p.addExtra(Node.PtrTypeBitRange{
1865 .sentinel = 0,
1866 .align_node = mods.align_node,
1801 .data = .{ .extra_and_node = .{
1802 try p.addExtra(Node.PtrTypeBitRange{
1803 .sentinel = .none,
1804 .align_node = mods.align_node.unwrap().?,
18671805 .addrspace_node = mods.addrspace_node,
1868 .bit_range_start = mods.bit_range_start,
1869 .bit_range_end = mods.bit_range_end,
1806 .bit_range_start = mods.bit_range_start.unwrap().?,
1807 .bit_range_end = mods.bit_range_end.unwrap().?,
18701808 }),
1871 .rhs = elem_type,
1872 },
1809 elem_type,
1810 } },
18731811 });
1874 } else if (mods.addrspace_node != 0) {
1812 } else if (mods.addrspace_node != .none) {
18751813 break :inner try p.addNode(.{
18761814 .tag = .ptr_type,
18771815 .main_token = asterisk,
1878 .data = .{
1879 .lhs = try p.addExtra(Node.PtrType{
1880 .sentinel = 0,
1816 .data = .{ .extra_and_node = .{
1817 try p.addExtra(Node.PtrType{
1818 .sentinel = .none,
18811819 .align_node = mods.align_node,
18821820 .addrspace_node = mods.addrspace_node,
18831821 }),
1884 .rhs = elem_type,
1885 },
1822 elem_type,
1823 } },
18861824 });
18871825 } else {
18881826 break :inner try p.addNode(.{
18891827 .tag = .ptr_type_aligned,
18901828 .main_token = asterisk,
1891 .data = .{
1892 .lhs = mods.align_node,
1893 .rhs = elem_type,
1894 },
1829 .data = .{ .opt_node_and_node = .{
1830 mods.align_node,
1831 elem_type,
1832 } },
18951833 });
18961834 }
18971835 };
1898 return p.addNode(.{
1836 return try p.addNode(.{
18991837 .tag = .ptr_type_aligned,
19001838 .main_token = asterisk,
1901 .data = .{
1902 .lhs = 0,
1903 .rhs = inner,
1904 },
1839 .data = .{ .opt_node_and_node = .{
1840 .none,
1841 inner,
1842 } },
19051843 });
19061844 },
1907 .l_bracket => switch (p.token_tags[p.tok_i + 1]) {
1845 .l_bracket => switch (p.tokenTag(p.tok_i + 1)) {
19081846 .asterisk => {
19091847 const l_bracket = p.nextToken();
19101848 _ = p.nextToken();
1911 var sentinel: Node.Index = 0;
1849 var sentinel: ?Node.Index = null;
19121850 if (p.eatToken(.identifier)) |ident| {
1913 const ident_slice = p.source[p.token_starts[ident]..p.token_starts[ident + 1]];
1851 const ident_slice = p.source[p.tokenStart(ident)..p.tokenStart(ident + 1)];
19141852 if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.whitespace), "c")) {
19151853 p.tok_i -= 1;
19161854 }
......@@ -1920,107 +1858,107 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
19201858 _ = try p.expectToken(.r_bracket);
19211859 const mods = try p.parsePtrModifiers();
19221860 const elem_type = try p.expectTypeExpr();
1923 if (mods.bit_range_start == 0) {
1924 if (sentinel == 0 and mods.addrspace_node == 0) {
1925 return p.addNode(.{
1861 if (mods.bit_range_start == .none) {
1862 if (sentinel == null and mods.addrspace_node == .none) {
1863 return try p.addNode(.{
19261864 .tag = .ptr_type_aligned,
19271865 .main_token = l_bracket,
1928 .data = .{
1929 .lhs = mods.align_node,
1930 .rhs = elem_type,
1931 },
1866 .data = .{ .opt_node_and_node = .{
1867 mods.align_node,
1868 elem_type,
1869 } },
19321870 });
1933 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {
1934 return p.addNode(.{
1871 } else if (mods.align_node == .none and mods.addrspace_node == .none) {
1872 return try p.addNode(.{
19351873 .tag = .ptr_type_sentinel,
19361874 .main_token = l_bracket,
1937 .data = .{
1938 .lhs = sentinel,
1939 .rhs = elem_type,
1940 },
1875 .data = .{ .opt_node_and_node = .{
1876 .fromOptional(sentinel),
1877 elem_type,
1878 } },
19411879 });
19421880 } else {
1943 return p.addNode(.{
1881 return try p.addNode(.{
19441882 .tag = .ptr_type,
19451883 .main_token = l_bracket,
1946 .data = .{
1947 .lhs = try p.addExtra(Node.PtrType{
1948 .sentinel = sentinel,
1884 .data = .{ .extra_and_node = .{
1885 try p.addExtra(Node.PtrType{
1886 .sentinel = .fromOptional(sentinel),
19491887 .align_node = mods.align_node,
19501888 .addrspace_node = mods.addrspace_node,
19511889 }),
1952 .rhs = elem_type,
1953 },
1890 elem_type,
1891 } },
19541892 });
19551893 }
19561894 } else {
1957 return p.addNode(.{
1895 return try p.addNode(.{
19581896 .tag = .ptr_type_bit_range,
19591897 .main_token = l_bracket,
1960 .data = .{
1961 .lhs = try p.addExtra(Node.PtrTypeBitRange{
1962 .sentinel = sentinel,
1963 .align_node = mods.align_node,
1898 .data = .{ .extra_and_node = .{
1899 try p.addExtra(Node.PtrTypeBitRange{
1900 .sentinel = .fromOptional(sentinel),
1901 .align_node = mods.align_node.unwrap().?,
19641902 .addrspace_node = mods.addrspace_node,
1965 .bit_range_start = mods.bit_range_start,
1966 .bit_range_end = mods.bit_range_end,
1903 .bit_range_start = mods.bit_range_start.unwrap().?,
1904 .bit_range_end = mods.bit_range_end.unwrap().?,
19671905 }),
1968 .rhs = elem_type,
1969 },
1906 elem_type,
1907 } },
19701908 });
19711909 }
19721910 },
19731911 else => {
19741912 const lbracket = p.nextToken();
19751913 const len_expr = try p.parseExpr();
1976 const sentinel: Node.Index = if (p.eatToken(.colon)) |_|
1914 const sentinel: ?Node.Index = if (p.eatToken(.colon)) |_|
19771915 try p.expectExpr()
19781916 else
1979 0;
1917 null;
19801918 _ = try p.expectToken(.r_bracket);
1981 if (len_expr == 0) {
1919 if (len_expr == null) {
19821920 const mods = try p.parsePtrModifiers();
19831921 const elem_type = try p.expectTypeExpr();
1984 if (mods.bit_range_start != 0) {
1922 if (mods.bit_range_start.unwrap()) |bit_range_start| {
19851923 try p.warnMsg(.{
19861924 .tag = .invalid_bit_range,
1987 .token = p.nodes.items(.main_token)[mods.bit_range_start],
1925 .token = p.nodeMainToken(bit_range_start),
19881926 });
19891927 }
1990 if (sentinel == 0 and mods.addrspace_node == 0) {
1991 return p.addNode(.{
1928 if (sentinel == null and mods.addrspace_node == .none) {
1929 return try p.addNode(.{
19921930 .tag = .ptr_type_aligned,
19931931 .main_token = lbracket,
1994 .data = .{
1995 .lhs = mods.align_node,
1996 .rhs = elem_type,
1997 },
1932 .data = .{ .opt_node_and_node = .{
1933 mods.align_node,
1934 elem_type,
1935 } },
19981936 });
1999 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {
2000 return p.addNode(.{
1937 } else if (mods.align_node == .none and mods.addrspace_node == .none) {
1938 return try p.addNode(.{
20011939 .tag = .ptr_type_sentinel,
20021940 .main_token = lbracket,
2003 .data = .{
2004 .lhs = sentinel,
2005 .rhs = elem_type,
2006 },
1941 .data = .{ .opt_node_and_node = .{
1942 .fromOptional(sentinel),
1943 elem_type,
1944 } },
20071945 });
20081946 } else {
2009 return p.addNode(.{
1947 return try p.addNode(.{
20101948 .tag = .ptr_type,
20111949 .main_token = lbracket,
2012 .data = .{
2013 .lhs = try p.addExtra(Node.PtrType{
2014 .sentinel = sentinel,
1950 .data = .{ .extra_and_node = .{
1951 try p.addExtra(Node.PtrType{
1952 .sentinel = .fromOptional(sentinel),
20151953 .align_node = mods.align_node,
20161954 .addrspace_node = mods.addrspace_node,
20171955 }),
2018 .rhs = elem_type,
2019 },
1956 elem_type,
1957 } },
20201958 });
20211959 }
20221960 } else {
2023 switch (p.token_tags[p.tok_i]) {
1961 switch (p.tokenTag(p.tok_i)) {
20241962 .keyword_align,
20251963 .keyword_const,
20261964 .keyword_volatile,
......@@ -2030,26 +1968,25 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
20301968 else => {},
20311969 }
20321970 const elem_type = try p.expectTypeExpr();
2033 if (sentinel == 0) {
2034 return p.addNode(.{
1971 if (sentinel == null) {
1972 return try p.addNode(.{
20351973 .tag = .array_type,
20361974 .main_token = lbracket,
2037 .data = .{
2038 .lhs = len_expr,
2039 .rhs = elem_type,
2040 },
1975 .data = .{ .node_and_node = .{
1976 len_expr.?,
1977 elem_type,
1978 } },
20411979 });
20421980 } else {
2043 return p.addNode(.{
1981 return try p.addNode(.{
20441982 .tag = .array_type_sentinel,
20451983 .main_token = lbracket,
2046 .data = .{
2047 .lhs = len_expr,
2048 .rhs = try p.addExtra(Node.ArrayTypeSentinel{
2049 .sentinel = sentinel,
1984 .data = .{ .node_and_extra = .{
1985 len_expr.?, try p.addExtra(Node.ArrayTypeSentinel{
1986 .sentinel = sentinel.?,
20501987 .elem_type = elem_type,
20511988 }),
2052 },
1989 } },
20531990 });
20541991 }
20551992 }
......@@ -2060,11 +1997,7 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
20601997}
20611998
20621999fn expectTypeExpr(p: *Parse) Error!Node.Index {
2063 const node = try p.parseTypeExpr();
2064 if (node == 0) {
2065 return p.fail(.expected_type_expr);
2066 }
2067 return node;
2000 return try p.parseTypeExpr() orelse return p.fail(.expected_type_expr);
20682001}
20692002
20702003/// PrimaryExpr
......@@ -2079,169 +2012,135 @@ fn expectTypeExpr(p: *Parse) Error!Node.Index {
20792012/// / BlockLabel? LoopExpr
20802013/// / Block
20812014/// / CurlySuffixExpr
2082fn parsePrimaryExpr(p: *Parse) !Node.Index {
2083 switch (p.token_tags[p.tok_i]) {
2084 .keyword_asm => return p.expectAsmExpr(),
2085 .keyword_if => return p.parseIfExpr(),
2015fn parsePrimaryExpr(p: *Parse) !?Node.Index {
2016 switch (p.tokenTag(p.tok_i)) {
2017 .keyword_asm => return try p.expectAsmExpr(),
2018 .keyword_if => return try p.parseIfExpr(),
20862019 .keyword_break => {
2087 return p.addNode(.{
2020 return try p.addNode(.{
20882021 .tag = .@"break",
20892022 .main_token = p.nextToken(),
2090 .data = .{
2091 .lhs = try p.parseBreakLabel(),
2092 .rhs = try p.parseExpr(),
2093 },
2023 .data = .{ .opt_token_and_opt_node = .{
2024 try p.parseBreakLabel(),
2025 .fromOptional(try p.parseExpr()),
2026 } },
20942027 });
20952028 },
20962029 .keyword_continue => {
2097 return p.addNode(.{
2030 return try p.addNode(.{
20982031 .tag = .@"continue",
20992032 .main_token = p.nextToken(),
2100 .data = .{
2101 .lhs = try p.parseBreakLabel(),
2102 .rhs = try p.parseExpr(),
2103 },
2033 .data = .{ .opt_token_and_opt_node = .{
2034 try p.parseBreakLabel(),
2035 .fromOptional(try p.parseExpr()),
2036 } },
21042037 });
21052038 },
21062039 .keyword_comptime => {
2107 return p.addNode(.{
2040 return try p.addNode(.{
21082041 .tag = .@"comptime",
21092042 .main_token = p.nextToken(),
2110 .data = .{
2111 .lhs = try p.expectExpr(),
2112 .rhs = undefined,
2113 },
2043 .data = .{ .node = try p.expectExpr() },
21142044 });
21152045 },
21162046 .keyword_nosuspend => {
2117 return p.addNode(.{
2047 return try p.addNode(.{
21182048 .tag = .@"nosuspend",
21192049 .main_token = p.nextToken(),
2120 .data = .{
2121 .lhs = try p.expectExpr(),
2122 .rhs = undefined,
2123 },
2050 .data = .{ .node = try p.expectExpr() },
21242051 });
21252052 },
21262053 .keyword_resume => {
2127 return p.addNode(.{
2054 return try p.addNode(.{
21282055 .tag = .@"resume",
21292056 .main_token = p.nextToken(),
2130 .data = .{
2131 .lhs = try p.expectExpr(),
2132 .rhs = undefined,
2133 },
2057 .data = .{ .node = try p.expectExpr() },
21342058 });
21352059 },
21362060 .keyword_return => {
2137 return p.addNode(.{
2061 return try p.addNode(.{
21382062 .tag = .@"return",
21392063 .main_token = p.nextToken(),
2140 .data = .{
2141 .lhs = try p.parseExpr(),
2142 .rhs = undefined,
2143 },
2064 .data = .{ .opt_node = .fromOptional(try p.parseExpr()) },
21442065 });
21452066 },
21462067 .identifier => {
2147 if (p.token_tags[p.tok_i + 1] == .colon) {
2148 switch (p.token_tags[p.tok_i + 2]) {
2068 if (p.tokenTag(p.tok_i + 1) == .colon) {
2069 switch (p.tokenTag(p.tok_i + 2)) {
21492070 .keyword_inline => {
21502071 p.tok_i += 3;
2151 switch (p.token_tags[p.tok_i]) {
2152 .keyword_for => return p.parseFor(expectExpr),
2153 .keyword_while => return p.parseWhileExpr(),
2072 switch (p.tokenTag(p.tok_i)) {
2073 .keyword_for => return try p.parseFor(expectExpr),
2074 .keyword_while => return try p.parseWhileExpr(),
21542075 else => return p.fail(.expected_inlinable),
21552076 }
21562077 },
21572078 .keyword_for => {
21582079 p.tok_i += 2;
2159 return p.parseFor(expectExpr);
2080 return try p.parseFor(expectExpr);
21602081 },
21612082 .keyword_while => {
21622083 p.tok_i += 2;
2163 return p.parseWhileExpr();
2084 return try p.parseWhileExpr();
21642085 },
21652086 .l_brace => {
21662087 p.tok_i += 2;
2167 return p.parseBlock();
2088 return try p.parseBlock();
21682089 },
2169 else => return p.parseCurlySuffixExpr(),
2090 else => return try p.parseCurlySuffixExpr(),
21702091 }
21712092 } else {
2172 return p.parseCurlySuffixExpr();
2093 return try p.parseCurlySuffixExpr();
21732094 }
21742095 },
21752096 .keyword_inline => {
21762097 p.tok_i += 1;
2177 switch (p.token_tags[p.tok_i]) {
2178 .keyword_for => return p.parseFor(expectExpr),
2179 .keyword_while => return p.parseWhileExpr(),
2098 switch (p.tokenTag(p.tok_i)) {
2099 .keyword_for => return try p.parseFor(expectExpr),
2100 .keyword_while => return try p.parseWhileExpr(),
21802101 else => return p.fail(.expected_inlinable),
21812102 }
21822103 },
2183 .keyword_for => return p.parseFor(expectExpr),
2184 .keyword_while => return p.parseWhileExpr(),
2185 .l_brace => return p.parseBlock(),
2186 else => return p.parseCurlySuffixExpr(),
2104 .keyword_for => return try p.parseFor(expectExpr),
2105 .keyword_while => return try p.parseWhileExpr(),
2106 .l_brace => return try p.parseBlock(),
2107 else => return try p.parseCurlySuffixExpr(),
21872108 }
21882109}
21892110
21902111/// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
2191fn parseIfExpr(p: *Parse) !Node.Index {
2192 return p.parseIf(expectExpr);
2112fn parseIfExpr(p: *Parse) !?Node.Index {
2113 return try p.parseIf(expectExpr);
21932114}
21942115
21952116/// Block <- LBRACE Statement* RBRACE
2196fn parseBlock(p: *Parse) !Node.Index {
2197 const lbrace = p.eatToken(.l_brace) orelse return null_node;
2117fn parseBlock(p: *Parse) !?Node.Index {
2118 const lbrace = p.eatToken(.l_brace) orelse return null;
21982119 const scratch_top = p.scratch.items.len;
21992120 defer p.scratch.shrinkRetainingCapacity(scratch_top);
22002121 while (true) {
2201 if (p.token_tags[p.tok_i] == .r_brace) break;
2202 const statement = try p.expectStatementRecoverable();
2203 if (statement == 0) break;
2122 if (p.tokenTag(p.tok_i) == .r_brace) break;
2123 const statement = try p.expectStatementRecoverable() orelse break;
22042124 try p.scratch.append(p.gpa, statement);
22052125 }
22062126 _ = try p.expectToken(.r_brace);
2207 const semicolon = (p.token_tags[p.tok_i - 2] == .semicolon);
22082127 const statements = p.scratch.items[scratch_top..];
2209 switch (statements.len) {
2210 0 => return p.addNode(.{
2211 .tag = .block_two,
2212 .main_token = lbrace,
2213 .data = .{
2214 .lhs = 0,
2215 .rhs = 0,
2216 },
2217 }),
2218 1 => return p.addNode(.{
2128 const semicolon = statements.len != 0 and (p.tokenTag(p.tok_i - 2)) == .semicolon;
2129 if (statements.len <= 2) {
2130 return try p.addNode(.{
22192131 .tag = if (semicolon) .block_two_semicolon else .block_two,
22202132 .main_token = lbrace,
2221 .data = .{
2222 .lhs = statements[0],
2223 .rhs = 0,
2224 },
2225 }),
2226 2 => return p.addNode(.{
2227 .tag = if (semicolon) .block_two_semicolon else .block_two,
2133 .data = .{ .opt_node_and_opt_node = .{
2134 if (statements.len >= 1) statements[0].toOptional() else .none,
2135 if (statements.len >= 2) statements[1].toOptional() else .none,
2136 } },
2137 });
2138 } else {
2139 return try p.addNode(.{
2140 .tag = if (semicolon) .block_semicolon else .block,
22282141 .main_token = lbrace,
2229 .data = .{
2230 .lhs = statements[0],
2231 .rhs = statements[1],
2232 },
2233 }),
2234 else => {
2235 const span = try p.listToSpan(statements);
2236 return p.addNode(.{
2237 .tag = if (semicolon) .block_semicolon else .block,
2238 .main_token = lbrace,
2239 .data = .{
2240 .lhs = span.start,
2241 .rhs = span.end,
2242 },
2243 });
2244 },
2142 .data = .{ .extra_range = try p.listToSpan(statements) },
2143 });
22452144 }
22462145}
22472146
......@@ -2260,15 +2159,15 @@ fn forPrefix(p: *Parse) Error!usize {
22602159 input = try p.addNode(.{
22612160 .tag = .for_range,
22622161 .main_token = ellipsis,
2263 .data = .{
2264 .lhs = input,
2265 .rhs = try p.parseExpr(),
2266 },
2162 .data = .{ .node_and_opt_node = .{
2163 input,
2164 .fromOptional(try p.parseExpr()),
2165 } },
22672166 });
22682167 }
22692168
22702169 try p.scratch.append(p.gpa, input);
2271 switch (p.token_tags[p.tok_i]) {
2170 switch (p.tokenTag(p.tok_i)) {
22722171 .comma => p.tok_i += 1,
22732172 .r_paren => {
22742173 p.tok_i += 1;
......@@ -2297,7 +2196,7 @@ fn forPrefix(p: *Parse) Error!usize {
22972196 try p.warnMsg(.{ .tag = .extra_for_capture, .token = identifier });
22982197 warned_excess = true;
22992198 }
2300 switch (p.token_tags[p.tok_i]) {
2199 switch (p.tokenTag(p.tok_i)) {
23012200 .comma => p.tok_i += 1,
23022201 .pipe => {
23032202 p.tok_i += 1;
......@@ -2311,7 +2210,7 @@ fn forPrefix(p: *Parse) Error!usize {
23112210
23122211 if (captures < inputs) {
23132212 const index = p.scratch.items.len - captures;
2314 const input = p.nodes.items(.main_token)[p.scratch.items[index]];
2213 const input = p.nodeMainToken(p.scratch.items[index]);
23152214 try p.warnMsg(.{ .tag = .for_input_not_captured, .token = input });
23162215 }
23172216 return inputs;
......@@ -2320,8 +2219,8 @@ fn forPrefix(p: *Parse) Error!usize {
23202219/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
23212220///
23222221/// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
2323fn parseWhileExpr(p: *Parse) !Node.Index {
2324 const while_token = p.eatToken(.keyword_while) orelse return null_node;
2222fn parseWhileExpr(p: *Parse) !?Node.Index {
2223 const while_token = p.eatToken(.keyword_while) orelse return null;
23252224 _ = try p.expectToken(.l_paren);
23262225 const condition = try p.expectExpr();
23272226 _ = try p.expectToken(.r_paren);
......@@ -2330,42 +2229,42 @@ fn parseWhileExpr(p: *Parse) !Node.Index {
23302229
23312230 const then_expr = try p.expectExpr();
23322231 _ = p.eatToken(.keyword_else) orelse {
2333 if (cont_expr == 0) {
2334 return p.addNode(.{
2232 if (cont_expr == null) {
2233 return try p.addNode(.{
23352234 .tag = .while_simple,
23362235 .main_token = while_token,
2337 .data = .{
2338 .lhs = condition,
2339 .rhs = then_expr,
2340 },
2236 .data = .{ .node_and_node = .{
2237 condition,
2238 then_expr,
2239 } },
23412240 });
23422241 } else {
2343 return p.addNode(.{
2242 return try p.addNode(.{
23442243 .tag = .while_cont,
23452244 .main_token = while_token,
2346 .data = .{
2347 .lhs = condition,
2348 .rhs = try p.addExtra(Node.WhileCont{
2349 .cont_expr = cont_expr,
2245 .data = .{ .node_and_extra = .{
2246 condition,
2247 try p.addExtra(Node.WhileCont{
2248 .cont_expr = cont_expr.?,
23502249 .then_expr = then_expr,
23512250 }),
2352 },
2251 } },
23532252 });
23542253 }
23552254 };
23562255 _ = try p.parsePayload();
23572256 const else_expr = try p.expectExpr();
2358 return p.addNode(.{
2257 return try p.addNode(.{
23592258 .tag = .@"while",
23602259 .main_token = while_token,
2361 .data = .{
2362 .lhs = condition,
2363 .rhs = try p.addExtra(Node.While{
2364 .cont_expr = cont_expr,
2260 .data = .{ .node_and_extra = .{
2261 condition,
2262 try p.addExtra(Node.While{
2263 .cont_expr = .fromOptional(cont_expr),
23652264 .then_expr = then_expr,
23662265 .else_expr = else_expr,
23672266 }),
2368 },
2267 } },
23692268 });
23702269}
23712270
......@@ -2375,9 +2274,8 @@ fn parseWhileExpr(p: *Parse) !Node.Index {
23752274/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
23762275/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
23772276/// / LBRACE RBRACE
2378fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
2379 const lhs = try p.parseTypeExpr();
2380 if (lhs == 0) return null_node;
2277fn parseCurlySuffixExpr(p: *Parse) !?Node.Index {
2278 const lhs = try p.parseTypeExpr() orelse return null;
23812279 const lbrace = p.eatToken(.l_brace) orelse return lhs;
23822280
23832281 // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne;
......@@ -2385,11 +2283,11 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
23852283
23862284 const scratch_top = p.scratch.items.len;
23872285 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2388 const field_init = try p.parseFieldInit();
2389 if (field_init != 0) {
2286 const opt_field_init = try p.parseFieldInit();
2287 if (opt_field_init) |field_init| {
23902288 try p.scratch.append(p.gpa, field_init);
23912289 while (true) {
2392 switch (p.token_tags[p.tok_i]) {
2290 switch (p.tokenTag(p.tok_i)) {
23932291 .comma => p.tok_i += 1,
23942292 .r_brace => {
23952293 p.tok_i += 1;
......@@ -2403,26 +2301,27 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
24032301 const next = try p.expectFieldInit();
24042302 try p.scratch.append(p.gpa, next);
24052303 }
2406 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2304 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
24072305 const inits = p.scratch.items[scratch_top..];
2408 switch (inits.len) {
2409 0 => unreachable,
2410 1 => return p.addNode(.{
2306 std.debug.assert(inits.len != 0);
2307 if (inits.len <= 1) {
2308 return try p.addNode(.{
24112309 .tag = if (comma) .struct_init_one_comma else .struct_init_one,
24122310 .main_token = lbrace,
2413 .data = .{
2414 .lhs = lhs,
2415 .rhs = inits[0],
2416 },
2417 }),
2418 else => return p.addNode(.{
2311 .data = .{ .node_and_opt_node = .{
2312 lhs,
2313 inits[0].toOptional(),
2314 } },
2315 });
2316 } else {
2317 return try p.addNode(.{
24192318 .tag = if (comma) .struct_init_comma else .struct_init,
24202319 .main_token = lbrace,
2421 .data = .{
2422 .lhs = lhs,
2423 .rhs = try p.addExtra(try p.listToSpan(inits)),
2424 },
2425 }),
2320 .data = .{ .node_and_extra = .{
2321 lhs,
2322 try p.addExtra(try p.listToSpan(inits)),
2323 } },
2324 });
24262325 }
24272326 }
24282327
......@@ -2430,7 +2329,7 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
24302329 if (p.eatToken(.r_brace)) |_| break;
24312330 const elem_init = try p.expectExpr();
24322331 try p.scratch.append(p.gpa, elem_init);
2433 switch (p.token_tags[p.tok_i]) {
2332 switch (p.tokenTag(p.tok_i)) {
24342333 .comma => p.tok_i += 1,
24352334 .r_brace => {
24362335 p.tok_i += 1;
......@@ -2441,48 +2340,47 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
24412340 else => try p.warn(.expected_comma_after_initializer),
24422341 }
24432342 }
2444 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2343 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
24452344 const inits = p.scratch.items[scratch_top..];
24462345 switch (inits.len) {
2447 0 => return p.addNode(.{
2346 0 => return try p.addNode(.{
24482347 .tag = .struct_init_one,
24492348 .main_token = lbrace,
2450 .data = .{
2451 .lhs = lhs,
2452 .rhs = 0,
2453 },
2349 .data = .{ .node_and_opt_node = .{
2350 lhs,
2351 .none,
2352 } },
24542353 }),
2455 1 => return p.addNode(.{
2354 1 => return try p.addNode(.{
24562355 .tag = if (comma) .array_init_one_comma else .array_init_one,
24572356 .main_token = lbrace,
2458 .data = .{
2459 .lhs = lhs,
2460 .rhs = inits[0],
2461 },
2357 .data = .{ .node_and_node = .{
2358 lhs,
2359 inits[0],
2360 } },
24622361 }),
2463 else => return p.addNode(.{
2362 else => return try p.addNode(.{
24642363 .tag = if (comma) .array_init_comma else .array_init,
24652364 .main_token = lbrace,
2466 .data = .{
2467 .lhs = lhs,
2468 .rhs = try p.addExtra(try p.listToSpan(inits)),
2469 },
2365 .data = .{ .node_and_extra = .{
2366 lhs,
2367 try p.addExtra(try p.listToSpan(inits)),
2368 } },
24702369 }),
24712370 }
24722371}
24732372
24742373/// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
2475fn parseErrorUnionExpr(p: *Parse) !Node.Index {
2476 const suffix_expr = try p.parseSuffixExpr();
2477 if (suffix_expr == 0) return null_node;
2374fn parseErrorUnionExpr(p: *Parse) !?Node.Index {
2375 const suffix_expr = try p.parseSuffixExpr() orelse return null;
24782376 const bang = p.eatToken(.bang) orelse return suffix_expr;
2479 return p.addNode(.{
2377 return try p.addNode(.{
24802378 .tag = .error_union,
24812379 .main_token = bang,
2482 .data = .{
2483 .lhs = suffix_expr,
2484 .rhs = try p.expectTypeExpr(),
2485 },
2380 .data = .{ .node_and_node = .{
2381 suffix_expr,
2382 try p.expectTypeExpr(),
2383 } },
24862384 });
24872385}
24882386
......@@ -2493,13 +2391,11 @@ fn parseErrorUnionExpr(p: *Parse) !Node.Index {
24932391/// FnCallArguments <- LPAREN ExprList RPAREN
24942392///
24952393/// ExprList <- (Expr COMMA)* Expr?
2496fn parseSuffixExpr(p: *Parse) !Node.Index {
2394fn parseSuffixExpr(p: *Parse) !?Node.Index {
24972395 if (p.eatToken(.keyword_async)) |_| {
24982396 var res = try p.expectPrimaryTypeExpr();
24992397 while (true) {
2500 const node = try p.parseSuffixOp(res);
2501 if (node == 0) break;
2502 res = node;
2398 res = try p.parseSuffixOp(res) orelse break;
25032399 }
25042400 const lparen = p.eatToken(.l_paren) orelse {
25052401 try p.warn(.expected_param_list);
......@@ -2511,7 +2407,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
25112407 if (p.eatToken(.r_paren)) |_| break;
25122408 const param = try p.expectExpr();
25132409 try p.scratch.append(p.gpa, param);
2514 switch (p.token_tags[p.tok_i]) {
2410 switch (p.tokenTag(p.tok_i)) {
25152411 .comma => p.tok_i += 1,
25162412 .r_paren => {
25172413 p.tok_i += 1;
......@@ -2522,41 +2418,33 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
25222418 else => try p.warn(.expected_comma_after_arg),
25232419 }
25242420 }
2525 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2421 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
25262422 const params = p.scratch.items[scratch_top..];
2527 switch (params.len) {
2528 0 => return p.addNode(.{
2529 .tag = if (comma) .async_call_one_comma else .async_call_one,
2530 .main_token = lparen,
2531 .data = .{
2532 .lhs = res,
2533 .rhs = 0,
2534 },
2535 }),
2536 1 => return p.addNode(.{
2423 if (params.len <= 1) {
2424 return try p.addNode(.{
25372425 .tag = if (comma) .async_call_one_comma else .async_call_one,
25382426 .main_token = lparen,
2539 .data = .{
2540 .lhs = res,
2541 .rhs = params[0],
2542 },
2543 }),
2544 else => return p.addNode(.{
2427 .data = .{ .node_and_opt_node = .{
2428 res,
2429 if (params.len >= 1) params[0].toOptional() else .none,
2430 } },
2431 });
2432 } else {
2433 return try p.addNode(.{
25452434 .tag = if (comma) .async_call_comma else .async_call,
25462435 .main_token = lparen,
2547 .data = .{
2548 .lhs = res,
2549 .rhs = try p.addExtra(try p.listToSpan(params)),
2550 },
2551 }),
2436 .data = .{ .node_and_extra = .{
2437 res,
2438 try p.addExtra(try p.listToSpan(params)),
2439 } },
2440 });
25522441 }
25532442 }
25542443
2555 var res = try p.parsePrimaryTypeExpr();
2556 if (res == 0) return res;
2444 var res = try p.parsePrimaryTypeExpr() orelse return null;
25572445 while (true) {
2558 const suffix_op = try p.parseSuffixOp(res);
2559 if (suffix_op != 0) {
2446 const opt_suffix_op = try p.parseSuffixOp(res);
2447 if (opt_suffix_op) |suffix_op| {
25602448 res = suffix_op;
25612449 continue;
25622450 }
......@@ -2567,7 +2455,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
25672455 if (p.eatToken(.r_paren)) |_| break;
25682456 const param = try p.expectExpr();
25692457 try p.scratch.append(p.gpa, param);
2570 switch (p.token_tags[p.tok_i]) {
2458 switch (p.tokenTag(p.tok_i)) {
25712459 .comma => p.tok_i += 1,
25722460 .r_paren => {
25732461 p.tok_i += 1;
......@@ -2578,32 +2466,24 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
25782466 else => try p.warn(.expected_comma_after_arg),
25792467 }
25802468 }
2581 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2469 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
25822470 const params = p.scratch.items[scratch_top..];
25832471 res = switch (params.len) {
2584 0 => try p.addNode(.{
2472 0, 1 => try p.addNode(.{
25852473 .tag = if (comma) .call_one_comma else .call_one,
25862474 .main_token = lparen,
2587 .data = .{
2588 .lhs = res,
2589 .rhs = 0,
2590 },
2591 }),
2592 1 => try p.addNode(.{
2593 .tag = if (comma) .call_one_comma else .call_one,
2594 .main_token = lparen,
2595 .data = .{
2596 .lhs = res,
2597 .rhs = params[0],
2598 },
2475 .data = .{ .node_and_opt_node = .{
2476 res,
2477 if (params.len >= 1) .fromOptional(params[0]) else .none,
2478 } },
25992479 }),
26002480 else => try p.addNode(.{
26012481 .tag = if (comma) .call_comma else .call,
26022482 .main_token = lparen,
2603 .data = .{
2604 .lhs = res,
2605 .rhs = try p.addExtra(try p.listToSpan(params)),
2606 },
2483 .data = .{ .node_and_extra = .{
2484 res,
2485 try p.addExtra(try p.listToSpan(params)),
2486 } },
26072487 }),
26082488 };
26092489 }
......@@ -2650,155 +2530,131 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
26502530/// / BlockLabel? SwitchExpr
26512531///
26522532/// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
2653fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2654 switch (p.token_tags[p.tok_i]) {
2655 .char_literal => return p.addNode(.{
2533fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index {
2534 switch (p.tokenTag(p.tok_i)) {
2535 .char_literal => return try p.addNode(.{
26562536 .tag = .char_literal,
26572537 .main_token = p.nextToken(),
2658 .data = .{
2659 .lhs = undefined,
2660 .rhs = undefined,
2661 },
2538 .data = undefined,
26622539 }),
2663 .number_literal => return p.addNode(.{
2540 .number_literal => return try p.addNode(.{
26642541 .tag = .number_literal,
26652542 .main_token = p.nextToken(),
2666 .data = .{
2667 .lhs = undefined,
2668 .rhs = undefined,
2669 },
2543 .data = undefined,
26702544 }),
2671 .keyword_unreachable => return p.addNode(.{
2545 .keyword_unreachable => return try p.addNode(.{
26722546 .tag = .unreachable_literal,
26732547 .main_token = p.nextToken(),
2674 .data = .{
2675 .lhs = undefined,
2676 .rhs = undefined,
2677 },
2548 .data = undefined,
26782549 }),
2679 .keyword_anyframe => return p.addNode(.{
2550 .keyword_anyframe => return try p.addNode(.{
26802551 .tag = .anyframe_literal,
26812552 .main_token = p.nextToken(),
2682 .data = .{
2683 .lhs = undefined,
2684 .rhs = undefined,
2685 },
2553 .data = undefined,
26862554 }),
26872555 .string_literal => {
26882556 const main_token = p.nextToken();
2689 return p.addNode(.{
2557 return try p.addNode(.{
26902558 .tag = .string_literal,
26912559 .main_token = main_token,
2692 .data = .{
2693 .lhs = undefined,
2694 .rhs = undefined,
2695 },
2560 .data = undefined,
26962561 });
26972562 },
26982563
2699 .builtin => return p.parseBuiltinCall(),
2700 .keyword_fn => return p.parseFnProto(),
2701 .keyword_if => return p.parseIf(expectTypeExpr),
2702 .keyword_switch => return p.expectSwitchExpr(false),
2564 .builtin => return try p.parseBuiltinCall(),
2565 .keyword_fn => return try p.parseFnProto(),
2566 .keyword_if => return try p.parseIf(expectTypeExpr),
2567 .keyword_switch => return try p.expectSwitchExpr(false),
27032568
27042569 .keyword_extern,
27052570 .keyword_packed,
27062571 => {
27072572 p.tok_i += 1;
2708 return p.parseContainerDeclAuto();
2573 return try p.parseContainerDeclAuto();
27092574 },
27102575
27112576 .keyword_struct,
27122577 .keyword_opaque,
27132578 .keyword_enum,
27142579 .keyword_union,
2715 => return p.parseContainerDeclAuto(),
2580 => return try p.parseContainerDeclAuto(),
27162581
2717 .keyword_comptime => return p.addNode(.{
2582 .keyword_comptime => return try p.addNode(.{
27182583 .tag = .@"comptime",
27192584 .main_token = p.nextToken(),
2720 .data = .{
2721 .lhs = try p.expectTypeExpr(),
2722 .rhs = undefined,
2723 },
2585 .data = .{ .node = try p.expectTypeExpr() },
27242586 }),
27252587 .multiline_string_literal_line => {
27262588 const first_line = p.nextToken();
2727 while (p.token_tags[p.tok_i] == .multiline_string_literal_line) {
2589 while (p.tokenTag(p.tok_i) == .multiline_string_literal_line) {
27282590 p.tok_i += 1;
27292591 }
2730 return p.addNode(.{
2592 return try p.addNode(.{
27312593 .tag = .multiline_string_literal,
27322594 .main_token = first_line,
2733 .data = .{
2734 .lhs = first_line,
2735 .rhs = p.tok_i - 1,
2736 },
2595 .data = .{ .token_and_token = .{
2596 first_line,
2597 p.tok_i - 1,
2598 } },
27372599 });
27382600 },
2739 .identifier => switch (p.token_tags[p.tok_i + 1]) {
2740 .colon => switch (p.token_tags[p.tok_i + 2]) {
2601 .identifier => switch (p.tokenTag(p.tok_i + 1)) {
2602 .colon => switch (p.tokenTag(p.tok_i + 2)) {
27412603 .keyword_inline => {
27422604 p.tok_i += 3;
2743 switch (p.token_tags[p.tok_i]) {
2744 .keyword_for => return p.parseFor(expectTypeExpr),
2745 .keyword_while => return p.parseWhileTypeExpr(),
2605 switch (p.tokenTag(p.tok_i)) {
2606 .keyword_for => return try p.parseFor(expectTypeExpr),
2607 .keyword_while => return try p.parseWhileTypeExpr(),
27462608 else => return p.fail(.expected_inlinable),
27472609 }
27482610 },
27492611 .keyword_for => {
27502612 p.tok_i += 2;
2751 return p.parseFor(expectTypeExpr);
2613 return try p.parseFor(expectTypeExpr);
27522614 },
27532615 .keyword_while => {
27542616 p.tok_i += 2;
2755 return p.parseWhileTypeExpr();
2617 return try p.parseWhileTypeExpr();
27562618 },
27572619 .keyword_switch => {
27582620 p.tok_i += 2;
2759 return p.expectSwitchExpr(true);
2621 return try p.expectSwitchExpr(true);
27602622 },
27612623 .l_brace => {
27622624 p.tok_i += 2;
2763 return p.parseBlock();
2625 return try p.parseBlock();
27642626 },
2765 else => return p.addNode(.{
2627 else => return try p.addNode(.{
27662628 .tag = .identifier,
27672629 .main_token = p.nextToken(),
2768 .data = .{
2769 .lhs = undefined,
2770 .rhs = undefined,
2771 },
2630 .data = undefined,
27722631 }),
27732632 },
2774 else => return p.addNode(.{
2633 else => return try p.addNode(.{
27752634 .tag = .identifier,
27762635 .main_token = p.nextToken(),
2777 .data = .{
2778 .lhs = undefined,
2779 .rhs = undefined,
2780 },
2636 .data = undefined,
27812637 }),
27822638 },
27832639 .keyword_inline => {
27842640 p.tok_i += 1;
2785 switch (p.token_tags[p.tok_i]) {
2786 .keyword_for => return p.parseFor(expectTypeExpr),
2787 .keyword_while => return p.parseWhileTypeExpr(),
2641 switch (p.tokenTag(p.tok_i)) {
2642 .keyword_for => return try p.parseFor(expectTypeExpr),
2643 .keyword_while => return try p.parseWhileTypeExpr(),
27882644 else => return p.fail(.expected_inlinable),
27892645 }
27902646 },
2791 .keyword_for => return p.parseFor(expectTypeExpr),
2792 .keyword_while => return p.parseWhileTypeExpr(),
2793 .period => switch (p.token_tags[p.tok_i + 1]) {
2794 .identifier => return p.addNode(.{
2795 .tag = .enum_literal,
2796 .data = .{
2797 .lhs = p.nextToken(), // dot
2798 .rhs = undefined,
2799 },
2800 .main_token = p.nextToken(), // identifier
2801 }),
2647 .keyword_for => return try p.parseFor(expectTypeExpr),
2648 .keyword_while => return try p.parseWhileTypeExpr(),
2649 .period => switch (p.tokenTag(p.tok_i + 1)) {
2650 .identifier => {
2651 p.tok_i += 1;
2652 return try p.addNode(.{
2653 .tag = .enum_literal,
2654 .main_token = p.nextToken(), // identifier
2655 .data = undefined,
2656 });
2657 },
28022658 .l_brace => {
28032659 const lbrace = p.tok_i + 1;
28042660 p.tok_i = lbrace + 1;
......@@ -2808,11 +2664,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28082664
28092665 const scratch_top = p.scratch.items.len;
28102666 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2811 const field_init = try p.parseFieldInit();
2812 if (field_init != 0) {
2667 const opt_field_init = try p.parseFieldInit();
2668 if (opt_field_init) |field_init| {
28132669 try p.scratch.append(p.gpa, field_init);
28142670 while (true) {
2815 switch (p.token_tags[p.tok_i]) {
2671 switch (p.tokenTag(p.tok_i)) {
28162672 .comma => p.tok_i += 1,
28172673 .r_brace => {
28182674 p.tok_i += 1;
......@@ -2826,37 +2682,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28262682 const next = try p.expectFieldInit();
28272683 try p.scratch.append(p.gpa, next);
28282684 }
2829 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2685 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
28302686 const inits = p.scratch.items[scratch_top..];
2831 switch (inits.len) {
2832 0 => unreachable,
2833 1 => return p.addNode(.{
2687 std.debug.assert(inits.len != 0);
2688 if (inits.len <= 2) {
2689 return try p.addNode(.{
28342690 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
28352691 .main_token = lbrace,
2836 .data = .{
2837 .lhs = inits[0],
2838 .rhs = 0,
2839 },
2840 }),
2841 2 => return p.addNode(.{
2842 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
2692 .data = .{ .opt_node_and_opt_node = .{
2693 if (inits.len >= 1) .fromOptional(inits[0]) else .none,
2694 if (inits.len >= 2) .fromOptional(inits[1]) else .none,
2695 } },
2696 });
2697 } else {
2698 return try p.addNode(.{
2699 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
28432700 .main_token = lbrace,
2844 .data = .{
2845 .lhs = inits[0],
2846 .rhs = inits[1],
2847 },
2848 }),
2849 else => {
2850 const span = try p.listToSpan(inits);
2851 return p.addNode(.{
2852 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
2853 .main_token = lbrace,
2854 .data = .{
2855 .lhs = span.start,
2856 .rhs = span.end,
2857 },
2858 });
2859 },
2701 .data = .{ .extra_range = try p.listToSpan(inits) },
2702 });
28602703 }
28612704 }
28622705
......@@ -2864,7 +2707,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28642707 if (p.eatToken(.r_brace)) |_| break;
28652708 const elem_init = try p.expectExpr();
28662709 try p.scratch.append(p.gpa, elem_init);
2867 switch (p.token_tags[p.tok_i]) {
2710 switch (p.tokenTag(p.tok_i)) {
28682711 .comma => p.tok_i += 1,
28692712 .r_brace => {
28702713 p.tok_i += 1;
......@@ -2875,49 +2718,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28752718 else => try p.warn(.expected_comma_after_initializer),
28762719 }
28772720 }
2878 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2721 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
28792722 const inits = p.scratch.items[scratch_top..];
2880 switch (inits.len) {
2881 0 => return p.addNode(.{
2882 .tag = .struct_init_dot_two,
2723 if (inits.len <= 2) {
2724 return try p.addNode(.{
2725 .tag = if (inits.len == 0)
2726 .struct_init_dot_two
2727 else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
28832728 .main_token = lbrace,
2884 .data = .{
2885 .lhs = 0,
2886 .rhs = 0,
2887 },
2888 }),
2889 1 => return p.addNode(.{
2890 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,
2891 .main_token = lbrace,
2892 .data = .{
2893 .lhs = inits[0],
2894 .rhs = 0,
2895 },
2896 }),
2897 2 => return p.addNode(.{
2898 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,
2729 .data = .{ .opt_node_and_opt_node = .{
2730 if (inits.len >= 1) inits[0].toOptional() else .none,
2731 if (inits.len >= 2) inits[1].toOptional() else .none,
2732 } },
2733 });
2734 } else {
2735 return try p.addNode(.{
2736 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
28992737 .main_token = lbrace,
2900 .data = .{
2901 .lhs = inits[0],
2902 .rhs = inits[1],
2903 },
2904 }),
2905 else => {
2906 const span = try p.listToSpan(inits);
2907 return p.addNode(.{
2908 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
2909 .main_token = lbrace,
2910 .data = .{
2911 .lhs = span.start,
2912 .rhs = span.end,
2913 },
2914 });
2915 },
2738 .data = .{ .extra_range = try p.listToSpan(inits) },
2739 });
29162740 }
29172741 },
2918 else => return null_node,
2742 else => return null,
29192743 },
2920 .keyword_error => switch (p.token_tags[p.tok_i + 1]) {
2744 .keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
29212745 .l_brace => {
29222746 const error_token = p.tok_i;
29232747 p.tok_i += 2;
......@@ -2925,7 +2749,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29252749 if (p.eatToken(.r_brace)) |_| break;
29262750 _ = try p.eatDocComments();
29272751 _ = try p.expectToken(.identifier);
2928 switch (p.token_tags[p.tok_i]) {
2752 switch (p.tokenTag(p.tok_i)) {
29292753 .comma => p.tok_i += 1,
29302754 .r_brace => {
29312755 p.tok_i += 1;
......@@ -2936,12 +2760,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29362760 else => try p.warn(.expected_comma_after_field),
29372761 }
29382762 }
2939 return p.addNode(.{
2763 return try p.addNode(.{
29402764 .tag = .error_set_decl,
29412765 .main_token = error_token,
29422766 .data = .{
2943 .lhs = undefined,
2944 .rhs = p.tok_i - 1, // rbrace
2767 .token_and_token = .{
2768 error_token + 1, // lbrace
2769 p.tok_i - 1, // rbrace
2770 },
29452771 },
29462772 });
29472773 },
......@@ -2951,41 +2777,34 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29512777 if (period == null) try p.warnExpected(.period);
29522778 const identifier = p.eatToken(.identifier);
29532779 if (identifier == null) try p.warnExpected(.identifier);
2954 return p.addNode(.{
2780 return try p.addNode(.{
29552781 .tag = .error_value,
29562782 .main_token = main_token,
2957 .data = .{
2958 .lhs = period orelse 0,
2959 .rhs = identifier orelse 0,
2960 },
2783 .data = undefined,
29612784 });
29622785 },
29632786 },
2964 .l_paren => return p.addNode(.{
2787 .l_paren => return try p.addNode(.{
29652788 .tag = .grouped_expression,
29662789 .main_token = p.nextToken(),
2967 .data = .{
2968 .lhs = try p.expectExpr(),
2969 .rhs = try p.expectToken(.r_paren),
2970 },
2790 .data = .{ .node_and_token = .{
2791 try p.expectExpr(),
2792 try p.expectToken(.r_paren),
2793 } },
29712794 }),
2972 else => return null_node,
2795 else => return null,
29732796 }
29742797}
29752798
29762799fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {
2977 const node = try p.parsePrimaryTypeExpr();
2978 if (node == 0) {
2979 return p.fail(.expected_primary_type_expr);
2980 }
2981 return node;
2800 return try p.parsePrimaryTypeExpr() orelse return p.fail(.expected_primary_type_expr);
29822801}
29832802
29842803/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
29852804///
29862805/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
2987fn parseWhileTypeExpr(p: *Parse) !Node.Index {
2988 const while_token = p.eatToken(.keyword_while) orelse return null_node;
2806fn parseWhileTypeExpr(p: *Parse) !?Node.Index {
2807 const while_token = p.eatToken(.keyword_while) orelse return null;
29892808 _ = try p.expectToken(.l_paren);
29902809 const condition = try p.expectExpr();
29912810 _ = try p.expectToken(.r_paren);
......@@ -2994,54 +2813,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {
29942813
29952814 const then_expr = try p.expectTypeExpr();
29962815 _ = p.eatToken(.keyword_else) orelse {
2997 if (cont_expr == 0) {
2998 return p.addNode(.{
2816 if (cont_expr == null) {
2817 return try p.addNode(.{
29992818 .tag = .while_simple,
30002819 .main_token = while_token,
3001 .data = .{
3002 .lhs = condition,
3003 .rhs = then_expr,
3004 },
2820 .data = .{ .node_and_node = .{
2821 condition,
2822 then_expr,
2823 } },
30052824 });
30062825 } else {
3007 return p.addNode(.{
2826 return try p.addNode(.{
30082827 .tag = .while_cont,
30092828 .main_token = while_token,
3010 .data = .{
3011 .lhs = condition,
3012 .rhs = try p.addExtra(Node.WhileCont{
3013 .cont_expr = cont_expr,
2829 .data = .{ .node_and_extra = .{
2830 condition, try p.addExtra(Node.WhileCont{
2831 .cont_expr = cont_expr.?,
30142832 .then_expr = then_expr,
30152833 }),
3016 },
2834 } },
30172835 });
30182836 }
30192837 };
30202838 _ = try p.parsePayload();
30212839 const else_expr = try p.expectTypeExpr();
3022 return p.addNode(.{
2840 return try p.addNode(.{
30232841 .tag = .@"while",
30242842 .main_token = while_token,
3025 .data = .{
3026 .lhs = condition,
3027 .rhs = try p.addExtra(Node.While{
3028 .cont_expr = cont_expr,
2843 .data = .{ .node_and_extra = .{
2844 condition, try p.addExtra(Node.While{
2845 .cont_expr = .fromOptional(cont_expr),
30292846 .then_expr = then_expr,
30302847 .else_expr = else_expr,
30312848 }),
3032 },
2849 } },
30332850 });
30342851}
30352852
30362853/// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
3037fn parseSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {
3038 const switch_token = p.eatToken(.keyword_switch) orelse return null_node;
3039 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
2854fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index {
2855 const switch_token = p.eatToken(.keyword_switch) orelse return null;
2856 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
30402857}
30412858
30422859fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {
30432860 const switch_token = p.assertToken(.keyword_switch);
3044 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
2861 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
30452862}
30462863
30472864fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
......@@ -3050,19 +2867,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
30502867 _ = try p.expectToken(.r_paren);
30512868 _ = try p.expectToken(.l_brace);
30522869 const cases = try p.parseSwitchProngList();
3053 const trailing_comma = p.token_tags[p.tok_i - 1] == .comma;
2870 const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma;
30542871 _ = try p.expectToken(.r_brace);
30552872
30562873 return p.addNode(.{
30572874 .tag = if (trailing_comma) .switch_comma else .@"switch",
30582875 .main_token = main_token,
3059 .data = .{
3060 .lhs = expr_node,
3061 .rhs = try p.addExtra(Node.SubRange{
2876 .data = .{ .node_and_extra = .{
2877 expr_node,
2878 try p.addExtra(Node.SubRange{
30622879 .start = cases.start,
30632880 .end = cases.end,
30642881 }),
3065 },
2882 } },
30662883 });
30672884}
30682885
......@@ -3089,10 +2906,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
30892906 return p.addNode(.{
30902907 .tag = .asm_simple,
30912908 .main_token = asm_token,
3092 .data = .{
3093 .lhs = template,
3094 .rhs = rparen,
3095 },
2909 .data = .{ .node_and_token = .{
2910 template,
2911 rparen,
2912 } },
30962913 });
30972914 }
30982915
......@@ -3102,10 +2919,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31022919 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31032920
31042921 while (true) {
3105 const output_item = try p.parseAsmOutputItem();
3106 if (output_item == 0) break;
2922 const output_item = try p.parseAsmOutputItem() orelse break;
31072923 try p.scratch.append(p.gpa, output_item);
3108 switch (p.token_tags[p.tok_i]) {
2924 switch (p.tokenTag(p.tok_i)) {
31092925 .comma => p.tok_i += 1,
31102926 // All possible delimiters.
31112927 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3115,10 +2931,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31152931 }
31162932 if (p.eatToken(.colon)) |_| {
31172933 while (true) {
3118 const input_item = try p.parseAsmInputItem();
3119 if (input_item == 0) break;
2934 const input_item = try p.parseAsmInputItem() orelse break;
31202935 try p.scratch.append(p.gpa, input_item);
3121 switch (p.token_tags[p.tok_i]) {
2936 switch (p.tokenTag(p.tok_i)) {
31222937 .comma => p.tok_i += 1,
31232938 // All possible delimiters.
31242939 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3128,7 +2943,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31282943 }
31292944 if (p.eatToken(.colon)) |_| {
31302945 while (p.eatToken(.string_literal)) |_| {
3131 switch (p.token_tags[p.tok_i]) {
2946 switch (p.tokenTag(p.tok_i)) {
31322947 .comma => p.tok_i += 1,
31332948 .colon, .r_paren, .r_brace, .r_bracket => break,
31342949 // Likely just a missing comma; give error but continue parsing.
......@@ -3142,121 +2957,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31422957 return p.addNode(.{
31432958 .tag = .@"asm",
31442959 .main_token = asm_token,
3145 .data = .{
3146 .lhs = template,
3147 .rhs = try p.addExtra(Node.Asm{
2960 .data = .{ .node_and_extra = .{
2961 template,
2962 try p.addExtra(Node.Asm{
31482963 .items_start = span.start,
31492964 .items_end = span.end,
31502965 .rparen = rparen,
31512966 }),
3152 },
2967 } },
31532968 });
31542969}
31552970
31562971/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
3157fn parseAsmOutputItem(p: *Parse) !Node.Index {
3158 _ = p.eatToken(.l_bracket) orelse return null_node;
2972fn parseAsmOutputItem(p: *Parse) !?Node.Index {
2973 _ = p.eatToken(.l_bracket) orelse return null;
31592974 const identifier = try p.expectToken(.identifier);
31602975 _ = try p.expectToken(.r_bracket);
31612976 _ = try p.expectToken(.string_literal);
31622977 _ = try p.expectToken(.l_paren);
3163 const type_expr: Node.Index = blk: {
2978 const type_expr: Node.OptionalIndex = blk: {
31642979 if (p.eatToken(.arrow)) |_| {
3165 break :blk try p.expectTypeExpr();
2980 break :blk .fromOptional(try p.expectTypeExpr());
31662981 } else {
31672982 _ = try p.expectToken(.identifier);
3168 break :blk null_node;
2983 break :blk .none;
31692984 }
31702985 };
31712986 const rparen = try p.expectToken(.r_paren);
3172 return p.addNode(.{
2987 return try p.addNode(.{
31732988 .tag = .asm_output,
31742989 .main_token = identifier,
3175 .data = .{
3176 .lhs = type_expr,
3177 .rhs = rparen,
3178 },
2990 .data = .{ .opt_node_and_token = .{
2991 type_expr,
2992 rparen,
2993 } },
31792994 });
31802995}
31812996
31822997/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
3183fn parseAsmInputItem(p: *Parse) !Node.Index {
3184 _ = p.eatToken(.l_bracket) orelse return null_node;
2998fn parseAsmInputItem(p: *Parse) !?Node.Index {
2999 _ = p.eatToken(.l_bracket) orelse return null;
31853000 const identifier = try p.expectToken(.identifier);
31863001 _ = try p.expectToken(.r_bracket);
31873002 _ = try p.expectToken(.string_literal);
31883003 _ = try p.expectToken(.l_paren);
31893004 const expr = try p.expectExpr();
31903005 const rparen = try p.expectToken(.r_paren);
3191 return p.addNode(.{
3006 return try p.addNode(.{
31923007 .tag = .asm_input,
31933008 .main_token = identifier,
3194 .data = .{
3195 .lhs = expr,
3196 .rhs = rparen,
3197 },
3009 .data = .{ .node_and_token = .{
3010 expr,
3011 rparen,
3012 } },
31983013 });
31993014}
32003015
32013016/// BreakLabel <- COLON IDENTIFIER
3202fn parseBreakLabel(p: *Parse) !TokenIndex {
3203 _ = p.eatToken(.colon) orelse return null_node;
3204 return p.expectToken(.identifier);
3017fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex {
3018 _ = p.eatToken(.colon) orelse return .none;
3019 const next_token = try p.expectToken(.identifier);
3020 return .fromToken(next_token);
32053021}
32063022
32073023/// BlockLabel <- IDENTIFIER COLON
3208fn parseBlockLabel(p: *Parse) TokenIndex {
3209 if (p.token_tags[p.tok_i] == .identifier and
3210 p.token_tags[p.tok_i + 1] == .colon)
3211 {
3212 const identifier = p.tok_i;
3213 p.tok_i += 2;
3214 return identifier;
3215 }
3216 return null_node;
3024fn parseBlockLabel(p: *Parse) ?TokenIndex {
3025 return p.eatTokens(&.{ .identifier, .colon });
32173026}
32183027
32193028/// FieldInit <- DOT IDENTIFIER EQUAL Expr
3220fn parseFieldInit(p: *Parse) !Node.Index {
3221 if (p.token_tags[p.tok_i + 0] == .period and
3222 p.token_tags[p.tok_i + 1] == .identifier and
3223 p.token_tags[p.tok_i + 2] == .equal)
3224 {
3225 p.tok_i += 3;
3226 return p.expectExpr();
3227 } else {
3228 return null_node;
3029fn parseFieldInit(p: *Parse) !?Node.Index {
3030 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3031 return try p.expectExpr();
32293032 }
3033 return null;
32303034}
32313035
32323036fn expectFieldInit(p: *Parse) !Node.Index {
3233 if (p.token_tags[p.tok_i] != .period or
3234 p.token_tags[p.tok_i + 1] != .identifier or
3235 p.token_tags[p.tok_i + 2] != .equal)
3236 return p.fail(.expected_initializer);
3237
3238 p.tok_i += 3;
3239 return p.expectExpr();
3037 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3038 return try p.expectExpr();
3039 }
3040 return p.fail(.expected_initializer);
32403041}
32413042
32423043/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
3243fn parseWhileContinueExpr(p: *Parse) !Node.Index {
3044fn parseWhileContinueExpr(p: *Parse) !?Node.Index {
32443045 _ = p.eatToken(.colon) orelse {
3245 if (p.token_tags[p.tok_i] == .l_paren and
3046 if (p.tokenTag(p.tok_i) == .l_paren and
32463047 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
32473048 return p.fail(.expected_continue_expr);
3248 return null_node;
3049 return null;
32493050 };
32503051 _ = try p.expectToken(.l_paren);
3251 const node = try p.parseAssignExpr();
3252 if (node == 0) return p.fail(.expected_expr_or_assignment);
3052 const node = try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
32533053 _ = try p.expectToken(.r_paren);
32543054 return node;
32553055}
32563056
32573057/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
3258fn parseLinkSection(p: *Parse) !Node.Index {
3259 _ = p.eatToken(.keyword_linksection) orelse return null_node;
3058fn parseLinkSection(p: *Parse) !?Node.Index {
3059 _ = p.eatToken(.keyword_linksection) orelse return null;
32603060 _ = try p.expectToken(.l_paren);
32613061 const expr_node = try p.expectExpr();
32623062 _ = try p.expectToken(.r_paren);
......@@ -3264,8 +3064,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {
32643064}
32653065
32663066/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
3267fn parseCallconv(p: *Parse) !Node.Index {
3268 _ = p.eatToken(.keyword_callconv) orelse return null_node;
3067fn parseCallconv(p: *Parse) !?Node.Index {
3068 _ = p.eatToken(.keyword_callconv) orelse return null;
32693069 _ = try p.expectToken(.l_paren);
32703070 const expr_node = try p.expectExpr();
32713071 _ = try p.expectToken(.r_paren);
......@@ -3273,8 +3073,8 @@ fn parseCallconv(p: *Parse) !Node.Index {
32733073}
32743074
32753075/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
3276fn parseAddrSpace(p: *Parse) !Node.Index {
3277 _ = p.eatToken(.keyword_addrspace) orelse return null_node;
3076fn parseAddrSpace(p: *Parse) !?Node.Index {
3077 _ = p.eatToken(.keyword_addrspace) orelse return null;
32783078 _ = try p.expectToken(.l_paren);
32793079 const expr_node = try p.expectExpr();
32803080 _ = try p.expectToken(.r_paren);
......@@ -3292,59 +3092,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {
32923092/// ParamType
32933093/// <- KEYWORD_anytype
32943094/// / TypeExpr
3295fn expectParamDecl(p: *Parse) !Node.Index {
3095fn expectParamDecl(p: *Parse) !?Node.Index {
32963096 _ = try p.eatDocComments();
3297 switch (p.token_tags[p.tok_i]) {
3097 switch (p.tokenTag(p.tok_i)) {
32983098 .keyword_noalias, .keyword_comptime => p.tok_i += 1,
32993099 .ellipsis3 => {
33003100 p.tok_i += 1;
3301 return null_node;
3101 return null;
33023102 },
33033103 else => {},
33043104 }
3305 if (p.token_tags[p.tok_i] == .identifier and
3306 p.token_tags[p.tok_i + 1] == .colon)
3307 {
3308 p.tok_i += 2;
3309 }
3310 switch (p.token_tags[p.tok_i]) {
3311 .keyword_anytype => {
3312 p.tok_i += 1;
3313 return null_node;
3314 },
3315 else => return p.expectTypeExpr(),
3105 _ = p.eatTokens(&.{ .identifier, .colon });
3106 if (p.eatToken(.keyword_anytype)) |_| {
3107 return null;
3108 } else {
3109 return try p.expectTypeExpr();
33163110 }
33173111}
33183112
33193113/// Payload <- PIPE IDENTIFIER PIPE
3320fn parsePayload(p: *Parse) !TokenIndex {
3321 _ = p.eatToken(.pipe) orelse return null_node;
3114fn parsePayload(p: *Parse) Error!OptionalTokenIndex {
3115 _ = p.eatToken(.pipe) orelse return .none;
33223116 const identifier = try p.expectToken(.identifier);
33233117 _ = try p.expectToken(.pipe);
3324 return identifier;
3118 return .fromToken(identifier);
33253119}
33263120
33273121/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
3328fn parsePtrPayload(p: *Parse) !TokenIndex {
3329 _ = p.eatToken(.pipe) orelse return null_node;
3122fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex {
3123 _ = p.eatToken(.pipe) orelse return .none;
33303124 _ = p.eatToken(.asterisk);
33313125 const identifier = try p.expectToken(.identifier);
33323126 _ = try p.expectToken(.pipe);
3333 return identifier;
3127 return .fromToken(identifier);
33343128}
33353129
33363130/// Returns the first identifier token, if any.
33373131///
33383132/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
3339fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
3340 _ = p.eatToken(.pipe) orelse return null_node;
3133fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex {
3134 _ = p.eatToken(.pipe) orelse return .none;
33413135 _ = p.eatToken(.asterisk);
33423136 const identifier = try p.expectToken(.identifier);
33433137 if (p.eatToken(.comma) != null) {
33443138 _ = try p.expectToken(.identifier);
33453139 }
33463140 _ = try p.expectToken(.pipe);
3347 return identifier;
3141 return .fromToken(identifier);
33483142}
33493143
33503144/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
......@@ -3352,7 +3146,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
33523146/// SwitchCase
33533147/// <- SwitchItem (COMMA SwitchItem)* COMMA?
33543148/// / KEYWORD_else
3355fn parseSwitchProng(p: *Parse) !Node.Index {
3149fn parseSwitchProng(p: *Parse) !?Node.Index {
33563150 const scratch_top = p.scratch.items.len;
33573151 defer p.scratch.shrinkRetainingCapacity(scratch_top);
33583152
......@@ -3360,97 +3154,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {
33603154
33613155 if (p.eatToken(.keyword_else) == null) {
33623156 while (true) {
3363 const item = try p.parseSwitchItem();
3364 if (item == 0) break;
3157 const item = try p.parseSwitchItem() orelse break;
33653158 try p.scratch.append(p.gpa, item);
33663159 if (p.eatToken(.comma) == null) break;
33673160 }
33683161 if (scratch_top == p.scratch.items.len) {
33693162 if (is_inline) p.tok_i -= 1;
3370 return null_node;
3163 return null;
33713164 }
33723165 }
33733166 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
33743167 _ = try p.parsePtrIndexPayload();
33753168
33763169 const items = p.scratch.items[scratch_top..];
3377 switch (items.len) {
3378 0 => return p.addNode(.{
3170 if (items.len <= 1) {
3171 return try p.addNode(.{
33793172 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
33803173 .main_token = arrow_token,
3381 .data = .{
3382 .lhs = 0,
3383 .rhs = try p.expectSingleAssignExpr(),
3384 },
3385 }),
3386 1 => return p.addNode(.{
3387 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
3388 .main_token = arrow_token,
3389 .data = .{
3390 .lhs = items[0],
3391 .rhs = try p.expectSingleAssignExpr(),
3392 },
3393 }),
3394 else => return p.addNode(.{
3174 .data = .{ .opt_node_and_node = .{
3175 if (items.len >= 1) items[0].toOptional() else .none,
3176 try p.expectSingleAssignExpr(),
3177 } },
3178 });
3179 } else {
3180 return try p.addNode(.{
33953181 .tag = if (is_inline) .switch_case_inline else .switch_case,
33963182 .main_token = arrow_token,
3397 .data = .{
3398 .lhs = try p.addExtra(try p.listToSpan(items)),
3399 .rhs = try p.expectSingleAssignExpr(),
3400 },
3401 }),
3183 .data = .{ .extra_and_node = .{
3184 try p.addExtra(try p.listToSpan(items)),
3185 try p.expectSingleAssignExpr(),
3186 } },
3187 });
34023188 }
34033189}
34043190
34053191/// SwitchItem <- Expr (DOT3 Expr)?
3406fn parseSwitchItem(p: *Parse) !Node.Index {
3407 const expr = try p.parseExpr();
3408 if (expr == 0) return null_node;
3192fn parseSwitchItem(p: *Parse) !?Node.Index {
3193 const expr = try p.parseExpr() orelse return null;
34093194
34103195 if (p.eatToken(.ellipsis3)) |token| {
3411 return p.addNode(.{
3196 return try p.addNode(.{
34123197 .tag = .switch_range,
34133198 .main_token = token,
3414 .data = .{
3415 .lhs = expr,
3416 .rhs = try p.expectExpr(),
3417 },
3199 .data = .{ .node_and_node = .{
3200 expr,
3201 try p.expectExpr(),
3202 } },
34183203 });
34193204 }
34203205 return expr;
34213206}
34223207
3208/// The following invariant will hold:
3209/// - `(bit_range_start == .none) == (bit_range_end == .none)`
3210/// - `bit_range_start != .none` implies `align_node != .none`
3211/// - `bit_range_end != .none` implies `align_node != .none`
34233212const PtrModifiers = struct {
3424 align_node: Node.Index,
3425 addrspace_node: Node.Index,
3426 bit_range_start: Node.Index,
3427 bit_range_end: Node.Index,
3213 align_node: Node.OptionalIndex,
3214 addrspace_node: Node.OptionalIndex,
3215 bit_range_start: Node.OptionalIndex,
3216 bit_range_end: Node.OptionalIndex,
34283217};
34293218
34303219fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34313220 var result: PtrModifiers = .{
3432 .align_node = 0,
3433 .addrspace_node = 0,
3434 .bit_range_start = 0,
3435 .bit_range_end = 0,
3221 .align_node = .none,
3222 .addrspace_node = .none,
3223 .bit_range_start = .none,
3224 .bit_range_end = .none,
34363225 };
34373226 var saw_const = false;
34383227 var saw_volatile = false;
34393228 var saw_allowzero = false;
34403229 while (true) {
3441 switch (p.token_tags[p.tok_i]) {
3230 switch (p.tokenTag(p.tok_i)) {
34423231 .keyword_align => {
3443 if (result.align_node != 0) {
3232 if (result.align_node != .none) {
34443233 try p.warn(.extra_align_qualifier);
34453234 }
34463235 p.tok_i += 1;
34473236 _ = try p.expectToken(.l_paren);
3448 result.align_node = try p.expectExpr();
3237 result.align_node = (try p.expectExpr()).toOptional();
34493238
34503239 if (p.eatToken(.colon)) |_| {
3451 result.bit_range_start = try p.expectExpr();
3240 result.bit_range_start = (try p.expectExpr()).toOptional();
34523241 _ = try p.expectToken(.colon);
3453 result.bit_range_end = try p.expectExpr();
3242 result.bit_range_end = (try p.expectExpr()).toOptional();
34543243 }
34553244
34563245 _ = try p.expectToken(.r_paren);
......@@ -3477,10 +3266,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34773266 saw_allowzero = true;
34783267 },
34793268 .keyword_addrspace => {
3480 if (result.addrspace_node != 0) {
3269 if (result.addrspace_node != .none) {
34813270 try p.warn(.extra_addrspace_qualifier);
34823271 }
3483 result.addrspace_node = try p.parseAddrSpace();
3272 result.addrspace_node = .fromOptional(try p.parseAddrSpace());
34843273 },
34853274 else => return result,
34863275 }
......@@ -3492,110 +3281,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34923281/// / DOT IDENTIFIER
34933282/// / DOTASTERISK
34943283/// / DOTQUESTIONMARK
3495fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
3496 switch (p.token_tags[p.tok_i]) {
3284fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
3285 switch (p.tokenTag(p.tok_i)) {
34973286 .l_bracket => {
34983287 const lbracket = p.nextToken();
34993288 const index_expr = try p.expectExpr();
35003289
35013290 if (p.eatToken(.ellipsis2)) |_| {
3502 const end_expr = try p.parseExpr();
3291 const opt_end_expr = try p.parseExpr();
35033292 if (p.eatToken(.colon)) |_| {
35043293 const sentinel = try p.expectExpr();
35053294 _ = try p.expectToken(.r_bracket);
3506 return p.addNode(.{
3295 return try p.addNode(.{
35073296 .tag = .slice_sentinel,
35083297 .main_token = lbracket,
3509 .data = .{
3510 .lhs = lhs,
3511 .rhs = try p.addExtra(Node.SliceSentinel{
3298 .data = .{ .node_and_extra = .{
3299 lhs, try p.addExtra(Node.SliceSentinel{
35123300 .start = index_expr,
3513 .end = end_expr,
3301 .end = .fromOptional(opt_end_expr),
35143302 .sentinel = sentinel,
35153303 }),
3516 },
3304 } },
35173305 });
35183306 }
35193307 _ = try p.expectToken(.r_bracket);
3520 if (end_expr == 0) {
3521 return p.addNode(.{
3308 const end_expr = opt_end_expr orelse {
3309 return try p.addNode(.{
35223310 .tag = .slice_open,
35233311 .main_token = lbracket,
3524 .data = .{
3525 .lhs = lhs,
3526 .rhs = index_expr,
3527 },
3312 .data = .{ .node_and_node = .{
3313 lhs,
3314 index_expr,
3315 } },
35283316 });
3529 }
3530 return p.addNode(.{
3317 };
3318 return try p.addNode(.{
35313319 .tag = .slice,
35323320 .main_token = lbracket,
3533 .data = .{
3534 .lhs = lhs,
3535 .rhs = try p.addExtra(Node.Slice{
3321 .data = .{ .node_and_extra = .{
3322 lhs, try p.addExtra(Node.Slice{
35363323 .start = index_expr,
35373324 .end = end_expr,
35383325 }),
3539 },
3326 } },
35403327 });
35413328 }
35423329 _ = try p.expectToken(.r_bracket);
3543 return p.addNode(.{
3330 return try p.addNode(.{
35443331 .tag = .array_access,
35453332 .main_token = lbracket,
3546 .data = .{
3547 .lhs = lhs,
3548 .rhs = index_expr,
3549 },
3333 .data = .{ .node_and_node = .{
3334 lhs,
3335 index_expr,
3336 } },
35503337 });
35513338 },
3552 .period_asterisk => return p.addNode(.{
3339 .period_asterisk => return try p.addNode(.{
35533340 .tag = .deref,
35543341 .main_token = p.nextToken(),
3555 .data = .{
3556 .lhs = lhs,
3557 .rhs = undefined,
3558 },
3342 .data = .{ .node = lhs },
35593343 }),
35603344 .invalid_periodasterisks => {
35613345 try p.warn(.asterisk_after_ptr_deref);
3562 return p.addNode(.{
3346 return try p.addNode(.{
35633347 .tag = .deref,
35643348 .main_token = p.nextToken(),
3565 .data = .{
3566 .lhs = lhs,
3567 .rhs = undefined,
3568 },
3349 .data = .{ .node = lhs },
35693350 });
35703351 },
3571 .period => switch (p.token_tags[p.tok_i + 1]) {
3572 .identifier => return p.addNode(.{
3352 .period => switch (p.tokenTag(p.tok_i + 1)) {
3353 .identifier => return try p.addNode(.{
35733354 .tag = .field_access,
35743355 .main_token = p.nextToken(),
3575 .data = .{
3576 .lhs = lhs,
3577 .rhs = p.nextToken(),
3578 },
3356 .data = .{ .node_and_token = .{
3357 lhs,
3358 p.nextToken(),
3359 } },
35793360 }),
3580 .question_mark => return p.addNode(.{
3361 .question_mark => return try p.addNode(.{
35813362 .tag = .unwrap_optional,
35823363 .main_token = p.nextToken(),
3583 .data = .{
3584 .lhs = lhs,
3585 .rhs = p.nextToken(),
3586 },
3364 .data = .{ .node_and_token = .{
3365 lhs,
3366 p.nextToken(),
3367 } },
35873368 }),
35883369 .l_brace => {
35893370 // this a misplaced `.{`, handle the error somewhere else
3590 return null_node;
3371 return null;
35913372 },
35923373 else => {
35933374 p.tok_i += 1;
35943375 try p.warn(.expected_suffix_op);
3595 return null_node;
3376 return null;
35963377 },
35973378 },
3598 else => return null_node,
3379 else => return null,
35993380 }
36003381}
36013382
......@@ -3608,17 +3389,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
36083389/// / KEYWORD_opaque
36093390/// / KEYWORD_enum (LPAREN Expr RPAREN)?
36103391/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
3611fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3392fn parseContainerDeclAuto(p: *Parse) !?Node.Index {
36123393 const main_token = p.nextToken();
3613 const arg_expr = switch (p.token_tags[main_token]) {
3614 .keyword_opaque => null_node,
3394 const arg_expr = switch (p.tokenTag(main_token)) {
3395 .keyword_opaque => null,
36153396 .keyword_struct, .keyword_enum => blk: {
36163397 if (p.eatToken(.l_paren)) |_| {
36173398 const expr = try p.expectExpr();
36183399 _ = try p.expectToken(.r_paren);
36193400 break :blk expr;
36203401 } else {
3621 break :blk null_node;
3402 break :blk null;
36223403 }
36233404 },
36243405 .keyword_union => blk: {
......@@ -3633,16 +3414,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36333414 const members = try p.parseContainerMembers();
36343415 const members_span = try members.toSpan(p);
36353416 _ = try p.expectToken(.r_brace);
3636 return p.addNode(.{
3417 return try p.addNode(.{
36373418 .tag = switch (members.trailing) {
36383419 true => .tagged_union_enum_tag_trailing,
36393420 false => .tagged_union_enum_tag,
36403421 },
36413422 .main_token = main_token,
3642 .data = .{
3643 .lhs = enum_tag_expr,
3644 .rhs = try p.addExtra(members_span),
3645 },
3423 .data = .{ .node_and_extra = .{
3424 enum_tag_expr,
3425 try p.addExtra(members_span),
3426 } },
36463427 });
36473428 } else {
36483429 _ = try p.expectToken(.r_paren);
......@@ -3651,29 +3432,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36513432 const members = try p.parseContainerMembers();
36523433 _ = try p.expectToken(.r_brace);
36533434 if (members.len <= 2) {
3654 return p.addNode(.{
3435 return try p.addNode(.{
36553436 .tag = switch (members.trailing) {
36563437 true => .tagged_union_two_trailing,
36573438 false => .tagged_union_two,
36583439 },
36593440 .main_token = main_token,
3660 .data = .{
3661 .lhs = members.lhs,
3662 .rhs = members.rhs,
3663 },
3441 .data = members.data,
36643442 });
36653443 } else {
36663444 const span = try members.toSpan(p);
3667 return p.addNode(.{
3445 return try p.addNode(.{
36683446 .tag = switch (members.trailing) {
36693447 true => .tagged_union_trailing,
36703448 false => .tagged_union,
36713449 },
36723450 .main_token = main_token,
3673 .data = .{
3674 .lhs = span.start,
3675 .rhs = span.end,
3676 },
3451 .data = .{ .extra_range = span },
36773452 });
36783453 }
36793454 }
......@@ -3683,7 +3458,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36833458 break :blk expr;
36843459 }
36853460 } else {
3686 break :blk null_node;
3461 break :blk null;
36873462 }
36883463 },
36893464 else => {
......@@ -3694,48 +3469,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36943469 _ = try p.expectToken(.l_brace);
36953470 const members = try p.parseContainerMembers();
36963471 _ = try p.expectToken(.r_brace);
3697 if (arg_expr == 0) {
3472 if (arg_expr == null) {
36983473 if (members.len <= 2) {
3699 return p.addNode(.{
3474 return try p.addNode(.{
37003475 .tag = switch (members.trailing) {
37013476 true => .container_decl_two_trailing,
37023477 false => .container_decl_two,
37033478 },
37043479 .main_token = main_token,
3705 .data = .{
3706 .lhs = members.lhs,
3707 .rhs = members.rhs,
3708 },
3480 .data = members.data,
37093481 });
37103482 } else {
37113483 const span = try members.toSpan(p);
3712 return p.addNode(.{
3484 return try p.addNode(.{
37133485 .tag = switch (members.trailing) {
37143486 true => .container_decl_trailing,
37153487 false => .container_decl,
37163488 },
37173489 .main_token = main_token,
3718 .data = .{
3719 .lhs = span.start,
3720 .rhs = span.end,
3721 },
3490 .data = .{ .extra_range = span },
37223491 });
37233492 }
37243493 } else {
37253494 const span = try members.toSpan(p);
3726 return p.addNode(.{
3495 return try p.addNode(.{
37273496 .tag = switch (members.trailing) {
37283497 true => .container_decl_arg_trailing,
37293498 false => .container_decl_arg,
37303499 },
37313500 .main_token = main_token,
3732 .data = .{
3733 .lhs = arg_expr,
3734 .rhs = try p.addExtra(Node.SubRange{
3501 .data = .{ .node_and_extra = .{
3502 arg_expr.?,
3503 try p.addExtra(Node.SubRange{
37353504 .start = span.start,
37363505 .end = span.end,
37373506 }),
3738 },
3507 } },
37393508 });
37403509 }
37413510}
......@@ -3744,24 +3513,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
37443513/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.
37453514fn parseCStyleContainer(p: *Parse) Error!bool {
37463515 const main_token = p.tok_i;
3747 switch (p.token_tags[p.tok_i]) {
3516 switch (p.tokenTag(p.tok_i)) {
37483517 .keyword_enum, .keyword_union, .keyword_struct => {},
37493518 else => return false,
37503519 }
37513520 const identifier = p.tok_i + 1;
3752 if (p.token_tags[identifier] != .identifier) return false;
3521 if (p.tokenTag(identifier) != .identifier) return false;
37533522 p.tok_i += 2;
37543523
37553524 try p.warnMsg(.{
37563525 .tag = .c_style_container,
37573526 .token = identifier,
3758 .extra = .{ .expected_tag = p.token_tags[main_token] },
3527 .extra = .{ .expected_tag = p.tokenTag(main_token) },
37593528 });
37603529 try p.warnMsg(.{
37613530 .tag = .zig_style_container,
37623531 .is_note = true,
37633532 .token = identifier,
3764 .extra = .{ .expected_tag = p.token_tags[main_token] },
3533 .extra = .{ .expected_tag = p.tokenTag(main_token) },
37653534 });
37663535
37673536 _ = try p.expectToken(.l_brace);
......@@ -3774,8 +3543,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {
37743543/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.
37753544///
37763545/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
3777fn parseByteAlign(p: *Parse) !Node.Index {
3778 _ = p.eatToken(.keyword_align) orelse return null_node;
3546fn parseByteAlign(p: *Parse) !?Node.Index {
3547 _ = p.eatToken(.keyword_align) orelse return null;
37793548 _ = try p.expectToken(.l_paren);
37803549 const expr = try p.expectExpr();
37813550 _ = try p.expectToken(.r_paren);
......@@ -3788,12 +3557,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {
37883557 defer p.scratch.shrinkRetainingCapacity(scratch_top);
37893558
37903559 while (true) {
3791 const item = try parseSwitchProng(p);
3792 if (item == 0) break;
3560 const item = try parseSwitchProng(p) orelse break;
37933561
37943562 try p.scratch.append(p.gpa, item);
37953563
3796 switch (p.token_tags[p.tok_i]) {
3564 switch (p.tokenTag(p.tok_i)) {
37973565 .comma => p.tok_i += 1,
37983566 // All possible delimiters.
37993567 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3813,13 +3581,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
38133581 while (true) {
38143582 if (p.eatToken(.r_paren)) |_| break;
38153583 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
3816 const param = try p.expectParamDecl();
3817 if (param != 0) {
3584 const opt_param = try p.expectParamDecl();
3585 if (opt_param) |param| {
38183586 try p.scratch.append(p.gpa, param);
3819 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
3587 } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) {
38203588 if (varargs == .none) varargs = .seen;
38213589 }
3822 switch (p.token_tags[p.tok_i]) {
3590 switch (p.tokenTag(p.tok_i)) {
38233591 .comma => p.tok_i += 1,
38243592 .r_paren => {
38253593 p.tok_i += 1;
......@@ -3835,9 +3603,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
38353603 }
38363604 const params = p.scratch.items[scratch_top..];
38373605 return switch (params.len) {
3838 0 => SmallSpan{ .zero_or_one = 0 },
3839 1 => SmallSpan{ .zero_or_one = params[0] },
3840 else => SmallSpan{ .multi = try p.listToSpan(params) },
3606 0 => .{ .zero_or_one = .none },
3607 1 => .{ .zero_or_one = params[0].toOptional() },
3608 else => .{ .multi = try p.listToSpan(params) },
38413609 };
38423610}
38433611
......@@ -3852,10 +3620,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38523620 return p.addNode(.{
38533621 .tag = .identifier,
38543622 .main_token = builtin_token,
3855 .data = .{
3856 .lhs = undefined,
3857 .rhs = undefined,
3858 },
3623 .data = undefined,
38593624 });
38603625 };
38613626 const scratch_top = p.scratch.items.len;
......@@ -3864,7 +3629,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38643629 if (p.eatToken(.r_paren)) |_| break;
38653630 const param = try p.expectExpr();
38663631 try p.scratch.append(p.gpa, param);
3867 switch (p.token_tags[p.tok_i]) {
3632 switch (p.tokenTag(p.tok_i)) {
38683633 .comma => p.tok_i += 1,
38693634 .r_paren => {
38703635 p.tok_i += 1;
......@@ -3874,88 +3639,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38743639 else => try p.warn(.expected_comma_after_arg),
38753640 }
38763641 }
3877 const comma = (p.token_tags[p.tok_i - 2] == .comma);
3642 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
38783643 const params = p.scratch.items[scratch_top..];
3879 switch (params.len) {
3880 0 => return p.addNode(.{
3881 .tag = .builtin_call_two,
3882 .main_token = builtin_token,
3883 .data = .{
3884 .lhs = 0,
3885 .rhs = 0,
3886 },
3887 }),
3888 1 => return p.addNode(.{
3644 if (params.len <= 2) {
3645 return p.addNode(.{
38893646 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
38903647 .main_token = builtin_token,
3891 .data = .{
3892 .lhs = params[0],
3893 .rhs = 0,
3894 },
3895 }),
3896 2 => return p.addNode(.{
3897 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
3648 .data = .{ .opt_node_and_opt_node = .{
3649 if (params.len >= 1) .fromOptional(params[0]) else .none,
3650 if (params.len >= 2) .fromOptional(params[1]) else .none,
3651 } },
3652 });
3653 } else {
3654 const span = try p.listToSpan(params);
3655 return p.addNode(.{
3656 .tag = if (comma) .builtin_call_comma else .builtin_call,
38983657 .main_token = builtin_token,
3899 .data = .{
3900 .lhs = params[0],
3901 .rhs = params[1],
3902 },
3903 }),
3904 else => {
3905 const span = try p.listToSpan(params);
3906 return p.addNode(.{
3907 .tag = if (comma) .builtin_call_comma else .builtin_call,
3908 .main_token = builtin_token,
3909 .data = .{
3910 .lhs = span.start,
3911 .rhs = span.end,
3912 },
3913 });
3914 },
3658 .data = .{ .extra_range = span },
3659 });
39153660 }
39163661}
39173662
39183663/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
3919fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {
3920 const if_token = p.eatToken(.keyword_if) orelse return null_node;
3664fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index {
3665 const if_token = p.eatToken(.keyword_if) orelse return null;
39213666 _ = try p.expectToken(.l_paren);
39223667 const condition = try p.expectExpr();
39233668 _ = try p.expectToken(.r_paren);
39243669 _ = try p.parsePtrPayload();
39253670
39263671 const then_expr = try bodyParseFn(p);
3927 assert(then_expr != 0);
39283672
3929 _ = p.eatToken(.keyword_else) orelse return p.addNode(.{
3673 _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{
39303674 .tag = .if_simple,
39313675 .main_token = if_token,
3932 .data = .{
3933 .lhs = condition,
3934 .rhs = then_expr,
3935 },
3676 .data = .{ .node_and_node = .{
3677 condition,
3678 then_expr,
3679 } },
39363680 });
39373681 _ = try p.parsePayload();
39383682 const else_expr = try bodyParseFn(p);
3939 assert(else_expr != 0);
39403683
3941 return p.addNode(.{
3684 return try p.addNode(.{
39423685 .tag = .@"if",
39433686 .main_token = if_token,
3944 .data = .{
3945 .lhs = condition,
3946 .rhs = try p.addExtra(Node.If{
3687 .data = .{ .node_and_extra = .{
3688 condition,
3689 try p.addExtra(Node.If{
39473690 .then_expr = then_expr,
39483691 .else_expr = else_expr,
39493692 }),
3950 },
3693 } },
39513694 });
39523695}
39533696
39543697/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
39553698///
39563699/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3957fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {
3958 const for_token = p.eatToken(.keyword_for) orelse return null_node;
3700fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index {
3701 const for_token = p.eatToken(.keyword_for) orelse return null;
39593702
39603703 const scratch_top = p.scratch.items.len;
39613704 defer p.scratch.shrinkRetainingCapacity(scratch_top);
......@@ -3969,27 +3712,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N
39693712 try p.scratch.append(p.gpa, else_expr);
39703713 has_else = true;
39713714 } else if (inputs == 1) {
3972 return p.addNode(.{
3715 return try p.addNode(.{
39733716 .tag = .for_simple,
39743717 .main_token = for_token,
3975 .data = .{
3976 .lhs = p.scratch.items[scratch_top],
3977 .rhs = then_expr,
3978 },
3718 .data = .{ .node_and_node = .{
3719 p.scratch.items[scratch_top],
3720 then_expr,
3721 } },
39793722 });
39803723 } else {
39813724 try p.scratch.append(p.gpa, then_expr);
39823725 }
3983 return p.addNode(.{
3726 return try p.addNode(.{
39843727 .tag = .@"for",
39853728 .main_token = for_token,
3986 .data = .{
3987 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3988 .rhs = @as(u32, @bitCast(Node.For{
3989 .inputs = @as(u31, @intCast(inputs)),
3990 .has_else = has_else,
3991 })),
3992 },
3729 .data = .{ .@"for" = .{
3730 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3731 .{ .inputs = @intCast(inputs), .has_else = has_else },
3732 } },
39933733 });
39943734}
39953735
......@@ -4011,21 +3751,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
40113751}
40123752
40133753fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool {
4014 return std.mem.indexOfScalar(u8, p.source[p.token_starts[token1]..p.token_starts[token2]], '\n') == null;
3754 return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null;
40153755}
40163756
40173757fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {
4018 return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null;
3758 return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null;
3759}
3760
3761fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex {
3762 const available_tags = p.tokens.items(.tag)[p.tok_i..];
3763 if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null;
3764 const result = p.tok_i;
3765 p.tok_i += @intCast(tags.len);
3766 return result;
40193767}
40203768
40213769fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {
40223770 const token = p.nextToken();
4023 assert(p.token_tags[token] == tag);
3771 assert(p.tokenTag(token) == tag);
40243772 return token;
40253773}
40263774
40273775fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4028 if (p.token_tags[p.tok_i] != tag) {
3776 if (p.tokenTag(p.tok_i) != tag) {
40293777 return p.failMsg(.{
40303778 .tag = .expected_token,
40313779 .token = p.tok_i,
......@@ -4036,7 +3784,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
40363784}
40373785
40383786fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {
4039 if (p.token_tags[p.tok_i] == .semicolon) {
3787 if (p.tokenTag(p.tok_i) == .semicolon) {
40403788 _ = p.nextToken();
40413789 return;
40423790 }
......@@ -4050,8 +3798,6 @@ fn nextToken(p: *Parse) TokenIndex {
40503798 return result;
40513799}
40523800
4053const null_node: Node.Index = 0;
4054
40553801const Parse = @This();
40563802const std = @import("../std.zig");
40573803const assert = std.debug.assert;
......@@ -4060,6 +3806,8 @@ const Ast = std.zig.Ast;
40603806const Node = Ast.Node;
40613807const AstError = Ast.Error;
40623808const TokenIndex = Ast.TokenIndex;
3809const OptionalTokenIndex = Ast.OptionalTokenIndex;
3810const ExtraIndex = Ast.ExtraIndex;
40633811const Token = std.zig.Token;
40643812
40653813test {
lib/std/zig/Zir.zig+52-45
......@@ -80,9 +80,18 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
8080 Inst.Declaration.Name,
8181 std.zig.SimpleComptimeReason,
8282 NullTerminatedString,
83 // Ast.TokenIndex is missing because it is a u32.
84 Ast.OptionalTokenIndex,
85 Ast.Node.Index,
86 Ast.Node.OptionalIndex,
8387 => @enumFromInt(code.extra[i]),
8488
85 i32,
89 Ast.TokenOffset,
90 Ast.OptionalTokenOffset,
91 Ast.Node.Offset,
92 Ast.Node.OptionalOffset,
93 => @enumFromInt(@as(i32, @bitCast(code.extra[i]))),
94
8695 Inst.Call.Flags,
8796 Inst.BuiltinCall.Flags,
8897 Inst.SwitchBlock.Bits,
......@@ -1904,22 +1913,22 @@ pub const Inst = struct {
19041913 /// `small` is `fields_len: u16`.
19051914 tuple_decl,
19061915 /// Implements the `@This` builtin.
1907 /// `operand` is `src_node: i32`.
1916 /// `operand` is `src_node: Ast.Node.Offset`.
19081917 this,
19091918 /// Implements the `@returnAddress` builtin.
1910 /// `operand` is `src_node: i32`.
1919 /// `operand` is `src_node: Ast.Node.Offset`.
19111920 ret_addr,
19121921 /// Implements the `@src` builtin.
19131922 /// `operand` is payload index to `LineColumn`.
19141923 builtin_src,
19151924 /// Implements the `@errorReturnTrace` builtin.
1916 /// `operand` is `src_node: i32`.
1925 /// `operand` is `src_node: Ast.Node.Offset`.
19171926 error_return_trace,
19181927 /// Implements the `@frame` builtin.
1919 /// `operand` is `src_node: i32`.
1928 /// `operand` is `src_node: Ast.Node.Offset`.
19201929 frame,
19211930 /// Implements the `@frameAddress` builtin.
1922 /// `operand` is `src_node: i32`.
1931 /// `operand` is `src_node: Ast.Node.Offset`.
19231932 frame_address,
19241933 /// Same as `alloc` from `Tag` but may contain an alignment instruction.
19251934 /// `operand` is payload index to `AllocExtended`.
......@@ -2004,9 +2013,9 @@ pub const Inst = struct {
20042013 /// `operand` is payload index to `UnNode`.
20052014 await_nosuspend,
20062015 /// Implements `@breakpoint`.
2007 /// `operand` is `src_node: i32`.
2016 /// `operand` is `src_node: Ast.Node.Offset`.
20082017 breakpoint,
2009 /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.
2018 /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: Ast.Node.Offset`.
20102019 disable_instrumentation,
20112020 /// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`.
20122021 disable_intrinsics,
......@@ -2040,7 +2049,7 @@ pub const Inst = struct {
20402049 /// `operand` is payload index to `UnNode`.
20412050 c_va_end,
20422051 /// Implement builtin `@cVaStart`.
2043 /// `operand` is `src_node: i32`.
2052 /// `operand` is `src_node: Ast.Node.Offset`.
20442053 c_va_start,
20452054 /// Implements the following builtins:
20462055 /// `@ptrCast`, `@alignCast`, `@addrSpaceCast`, `@constCast`, `@volatileCast`.
......@@ -2067,7 +2076,7 @@ pub const Inst = struct {
20672076 /// `operand` is payload index to `UnNode`.
20682077 work_group_id,
20692078 /// Implements the `@inComptime` builtin.
2070 /// `operand` is `src_node: i32`.
2079 /// `operand` is `src_node: Ast.Node.Offset`.
20712080 in_comptime,
20722081 /// Restores the error return index to its last saved state in a given
20732082 /// block. If the block is `.none`, restores to the state from the point
......@@ -2077,7 +2086,7 @@ pub const Inst = struct {
20772086 /// `small` is undefined.
20782087 restore_err_ret_index,
20792088 /// Retrieves a value from the current type declaration scope's closure.
2080 /// `operand` is `src_node: i32`.
2089 /// `operand` is `src_node: Ast.Node.Offset`.
20812090 /// `small` is closure index.
20822091 closure_get,
20832092 /// Used as a placeholder instruction which is just a dummy index for Sema to replace
......@@ -2091,7 +2100,7 @@ pub const Inst = struct {
20912100 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
20922101 field_parent_ptr,
20932102 /// Get a type or value from `std.builtin`.
2094 /// `operand` is `src_node: i32`.
2103 /// `operand` is `src_node: Ast.Node.Offset`.
20952104 /// `small` is an `Inst.BuiltinValue`.
20962105 builtin_value,
20972106 /// Provide a `@branchHint` for the current block.
......@@ -2286,28 +2295,28 @@ pub const Inst = struct {
22862295 /// Used for unary operators, with an AST node source location.
22872296 un_node: struct {
22882297 /// Offset from Decl AST node index.
2289 src_node: i32,
2298 src_node: Ast.Node.Offset,
22902299 /// The meaning of this operand depends on the corresponding `Tag`.
22912300 operand: Ref,
22922301 },
22932302 /// Used for unary operators, with a token source location.
22942303 un_tok: struct {
22952304 /// Offset from Decl AST token index.
2296 src_tok: Ast.TokenIndex,
2305 src_tok: Ast.TokenOffset,
22972306 /// The meaning of this operand depends on the corresponding `Tag`.
22982307 operand: Ref,
22992308 },
23002309 pl_node: struct {
23012310 /// Offset from Decl AST node index.
23022311 /// `Tag` determines which kind of AST node this points to.
2303 src_node: i32,
2312 src_node: Ast.Node.Offset,
23042313 /// index into extra.
23052314 /// `Tag` determines what lives there.
23062315 payload_index: u32,
23072316 },
23082317 pl_tok: struct {
23092318 /// Offset from Decl AST token index.
2310 src_tok: Ast.TokenIndex,
2319 src_tok: Ast.TokenOffset,
23112320 /// index into extra.
23122321 /// `Tag` determines what lives there.
23132322 payload_index: u32,
......@@ -2328,16 +2337,16 @@ pub const Inst = struct {
23282337 /// Offset into `string_bytes`. Null-terminated.
23292338 start: NullTerminatedString,
23302339 /// Offset from Decl AST token index.
2331 src_tok: u32,
2340 src_tok: Ast.TokenOffset,
23322341
23332342 pub fn get(self: @This(), code: Zir) [:0]const u8 {
23342343 return code.nullTerminatedString(self.start);
23352344 }
23362345 },
23372346 /// Offset from Decl AST token index.
2338 tok: Ast.TokenIndex,
2347 tok: Ast.TokenOffset,
23392348 /// Offset from Decl AST node index.
2340 node: i32,
2349 node: Ast.Node.Offset,
23412350 int: u64,
23422351 float: f64,
23432352 ptr_type: struct {
......@@ -2358,14 +2367,14 @@ pub const Inst = struct {
23582367 int_type: struct {
23592368 /// Offset from Decl AST node index.
23602369 /// `Tag` determines which kind of AST node this points to.
2361 src_node: i32,
2370 src_node: Ast.Node.Offset,
23622371 signedness: std.builtin.Signedness,
23632372 bit_count: u16,
23642373 },
23652374 @"unreachable": struct {
23662375 /// Offset from Decl AST node index.
23672376 /// `Tag` determines which kind of AST node this points to.
2368 src_node: i32,
2377 src_node: Ast.Node.Offset,
23692378 },
23702379 @"break": struct {
23712380 operand: Ref,
......@@ -2377,7 +2386,7 @@ pub const Inst = struct {
23772386 /// with an AST node source location.
23782387 inst_node: struct {
23792388 /// Offset from Decl AST node index.
2380 src_node: i32,
2389 src_node: Ast.Node.Offset,
23812390 /// The meaning of this operand depends on the corresponding `Tag`.
23822391 inst: Index,
23832392 },
......@@ -2456,9 +2465,7 @@ pub const Inst = struct {
24562465 };
24572466
24582467 pub const Break = struct {
2459 pub const no_src_node = std.math.maxInt(i32);
2460
2461 operand_src_node: i32,
2468 operand_src_node: Ast.Node.OptionalOffset,
24622469 block_inst: Index,
24632470 };
24642471
......@@ -2467,7 +2474,7 @@ pub const Inst = struct {
24672474 /// 1. Input for every inputs_len
24682475 /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len.
24692476 pub const Asm = struct {
2470 src_node: i32,
2477 src_node: Ast.Node.Offset,
24712478 // null-terminated string index
24722479 asm_source: NullTerminatedString,
24732480 /// 1 bit for each outputs_len: whether it uses `-> T` or not.
......@@ -2582,7 +2589,7 @@ pub const Inst = struct {
25822589
25832590 /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).
25842591 pub const NodeMultiOp = struct {
2585 src_node: i32,
2592 src_node: Ast.Node.Offset,
25862593 };
25872594
25882595 /// This data is stored inside extra, with trailing operands according to `body_len`.
......@@ -3033,7 +3040,7 @@ pub const Inst = struct {
30333040 /// Trailing:
30343041 /// 0. operand: Ref // for each `operands_len`
30353042 pub const TypeOfPeer = struct {
3036 src_node: i32,
3043 src_node: Ast.Node.Offset,
30373044 body_len: u32,
30383045 body_index: u32,
30393046 };
......@@ -3084,7 +3091,7 @@ pub const Inst = struct {
30843091 /// 4. host_size: Ref // if `has_bit_range` flag is set
30853092 pub const PtrType = struct {
30863093 elem_type: Ref,
3087 src_node: i32,
3094 src_node: Ast.Node.Offset,
30883095 };
30893096
30903097 pub const ArrayTypeSentinel = struct {
......@@ -3116,7 +3123,7 @@ pub const Inst = struct {
31163123 start: Ref,
31173124 len: Ref,
31183125 sentinel: Ref,
3119 start_src_node_offset: i32,
3126 start_src_node_offset: Ast.Node.Offset,
31203127 };
31213128
31223129 /// The meaning of these operands depends on the corresponding `Tag`.
......@@ -3126,13 +3133,13 @@ pub const Inst = struct {
31263133 };
31273134
31283135 pub const BinNode = struct {
3129 node: i32,
3136 node: Ast.Node.Offset,
31303137 lhs: Ref,
31313138 rhs: Ref,
31323139 };
31333140
31343141 pub const UnNode = struct {
3135 node: i32,
3142 node: Ast.Node.Offset,
31363143 operand: Ref,
31373144 };
31383145
......@@ -3186,7 +3193,7 @@ pub const Inst = struct {
31863193 pub const SwitchBlockErrUnion = struct {
31873194 operand: Ref,
31883195 bits: Bits,
3189 main_src_node_offset: i32,
3196 main_src_node_offset: Ast.Node.Offset,
31903197
31913198 pub const Bits = packed struct(u32) {
31923199 /// If true, one or more prongs have multiple items.
......@@ -3592,7 +3599,7 @@ pub const Inst = struct {
35923599 /// init: Inst.Ref, // `.none` for non-`comptime` fields
35933600 /// }
35943601 pub const TupleDecl = struct {
3595 src_node: i32, // relative
3602 src_node: Ast.Node.Offset,
35963603 };
35973604
35983605 /// Trailing:
......@@ -3666,7 +3673,7 @@ pub const Inst = struct {
36663673 };
36673674
36683675 pub const Cmpxchg = struct {
3669 node: i32,
3676 node: Ast.Node.Offset,
36703677 ptr: Ref,
36713678 expected_value: Ref,
36723679 new_value: Ref,
......@@ -3706,7 +3713,7 @@ pub const Inst = struct {
37063713 };
37073714
37083715 pub const FieldParentPtr = struct {
3709 src_node: i32,
3716 src_node: Ast.Node.Offset,
37103717 parent_ptr_type: Ref,
37113718 field_name: Ref,
37123719 field_ptr: Ref,
......@@ -3720,7 +3727,7 @@ pub const Inst = struct {
37203727 };
37213728
37223729 pub const Select = struct {
3723 node: i32,
3730 node: Ast.Node.Offset,
37243731 elem_type: Ref,
37253732 pred: Ref,
37263733 a: Ref,
......@@ -3728,7 +3735,7 @@ pub const Inst = struct {
37283735 };
37293736
37303737 pub const AsyncCall = struct {
3731 node: i32,
3738 node: Ast.Node.Offset,
37323739 frame_buffer: Ref,
37333740 result_ptr: Ref,
37343741 fn_ptr: Ref,
......@@ -3753,7 +3760,7 @@ pub const Inst = struct {
37533760 /// 0. type_inst: Ref, // if small 0b000X is set
37543761 /// 1. align_inst: Ref, // if small 0b00X0 is set
37553762 pub const AllocExtended = struct {
3756 src_node: i32,
3763 src_node: Ast.Node.Offset,
37573764
37583765 pub const Small = packed struct {
37593766 has_type: bool,
......@@ -3778,9 +3785,9 @@ pub const Inst = struct {
37783785 pub const Item = struct {
37793786 /// null terminated string index
37803787 msg: NullTerminatedString,
3781 node: Ast.Node.Index,
3782 /// If node is 0 then this will be populated.
3783 token: Ast.TokenIndex,
3788 node: Ast.Node.OptionalIndex,
3789 /// If node is .none then this will be populated.
3790 token: Ast.OptionalTokenIndex,
37843791 /// Can be used in combination with `token`.
37853792 byte_offset: u32,
37863793 /// 0 or a payload index of a `Block`, each is a payload
......@@ -3818,7 +3825,7 @@ pub const Inst = struct {
38183825 };
38193826
38203827 pub const Src = struct {
3821 node: i32,
3828 node: Ast.Node.Offset,
38223829 line: u32,
38233830 column: u32,
38243831 };
......@@ -3833,7 +3840,7 @@ pub const Inst = struct {
38333840 /// The value being destructured.
38343841 operand: Ref,
38353842 /// The `destructure_assign` node.
3836 destructure_node: i32,
3843 destructure_node: Ast.Node.Offset,
38373844 /// The expected field count.
38383845 expect_len: u32,
38393846 };
......@@ -3848,7 +3855,7 @@ pub const Inst = struct {
38483855 };
38493856
38503857 pub const RestoreErrRetIndex = struct {
3851 src_node: i32,
3858 src_node: Ast.Node.Offset,
38523859 /// If `.none`, restore the trace to its state upon function entry.
38533860 block: Ref,
38543861 /// If `.none`, restore unconditionally.
lib/std/zig/Zoir.zig+4-6
......@@ -228,8 +228,8 @@ pub const NullTerminatedString = enum(u32) {
228228
229229pub const CompileError = extern struct {
230230 msg: NullTerminatedString,
231 token: Ast.TokenIndex,
232 /// If `token == invalid_token`, this is an `Ast.Node.Index`.
231 token: Ast.OptionalTokenIndex,
232 /// If `token == .none`, this is an `Ast.Node.Index`.
233233 /// Otherwise, this is a byte offset into `token`.
234234 node_or_offset: u32,
235235
......@@ -243,14 +243,12 @@ pub const CompileError = extern struct {
243243
244244 pub const Note = extern struct {
245245 msg: NullTerminatedString,
246 token: Ast.TokenIndex,
247 /// If `token == invalid_token`, this is an `Ast.Node.Index`.
246 token: Ast.OptionalTokenIndex,
247 /// If `token == .none`, this is an `Ast.Node.Index`.
248248 /// Otherwise, this is a byte offset into `token`.
249249 node_or_offset: u32,
250250 };
251251
252 pub const invalid_token: Ast.TokenIndex = std.math.maxInt(Ast.TokenIndex);
253
254252 comptime {
255253 assert(std.meta.hasUniqueRepresentation(CompileError));
256254 assert(std.meta.hasUniqueRepresentation(Note));
lib/std/zig/ZonGen.zig+44-56
......@@ -48,7 +48,7 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi
4848 }
4949
5050 if (tree.errors.len == 0) {
51 const root_ast_node = tree.nodes.items(.data)[0].lhs;
51 const root_ast_node = tree.rootDecls()[0];
5252 try zg.nodes.append(gpa, undefined); // index 0; root node
5353 try zg.expr(root_ast_node, .root);
5454 } else {
......@@ -97,11 +97,8 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi
9797fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator.Error!void {
9898 const gpa = zg.gpa;
9999 const tree = zg.tree;
100 const node_tags = tree.nodes.items(.tag);
101 const node_datas = tree.nodes.items(.data);
102 const main_tokens = tree.nodes.items(.main_token);
103100
104 switch (node_tags[node]) {
101 switch (tree.nodeTag(node)) {
105102 .root => unreachable,
106103 .@"usingnamespace" => unreachable,
107104 .test_decl => unreachable,
......@@ -173,7 +170,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
173170 .bool_not,
174171 .bit_not,
175172 .negation_wrap,
176 => try zg.addErrorTok(main_tokens[node], "operator '{s}' is not allowed in ZON", .{tree.tokenSlice(main_tokens[node])}),
173 => try zg.addErrorTok(tree.nodeMainToken(node), "operator '{s}' is not allowed in ZON", .{tree.tokenSlice(tree.nodeMainToken(node))}),
177174
178175 .error_union,
179176 .merge_error_sets,
......@@ -251,23 +248,20 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
251248 .slice_sentinel,
252249 => try zg.addErrorNode(node, "slice operator is not allowed in ZON", .{}),
253250
254 .deref, .address_of => try zg.addErrorTok(main_tokens[node], "pointers are not available in ZON", .{}),
255 .unwrap_optional => try zg.addErrorTok(main_tokens[node], "optionals are not available in ZON", .{}),
251 .deref, .address_of => try zg.addErrorTok(tree.nodeMainToken(node), "pointers are not available in ZON", .{}),
252 .unwrap_optional => try zg.addErrorTok(tree.nodeMainToken(node), "optionals are not available in ZON", .{}),
256253 .error_value => try zg.addErrorNode(node, "errors are not available in ZON", .{}),
257254
258 .array_access => try zg.addErrorTok(node, "array indexing is not allowed in ZON", .{}),
255 .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}),
259256
260257 .block_two,
261258 .block_two_semicolon,
262259 .block,
263260 .block_semicolon,
264261 => {
265 const size = switch (node_tags[node]) {
266 .block_two, .block_two_semicolon => @intFromBool(node_datas[node].lhs != 0) + @intFromBool(node_datas[node].rhs != 0),
267 .block, .block_semicolon => node_datas[node].rhs - node_datas[node].lhs,
268 else => unreachable,
269 };
270 if (size == 0) {
262 var buffer: [2]Ast.Node.Index = undefined;
263 const statements = tree.blockStatements(&buffer, node).?;
264 if (statements.len == 0) {
271265 try zg.addErrorNodeNotes(node, "void literals are not available in ZON", .{}, &.{
272266 try zg.errNoteNode(node, "void union payloads can be represented by enum literals", .{}),
273267 });
......@@ -288,9 +282,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
288282 var buf: [2]Ast.Node.Index = undefined;
289283
290284 const type_node = if (tree.fullArrayInit(&buf, node)) |full|
291 full.ast.type_expr
285 full.ast.type_expr.unwrap().?
292286 else if (tree.fullStructInit(&buf, node)) |full|
293 full.ast.type_expr
287 full.ast.type_expr.unwrap().?
294288 else
295289 unreachable;
296290
......@@ -300,18 +294,18 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
300294 },
301295
302296 .grouped_expression => {
303 try zg.addErrorTokNotes(main_tokens[node], "expression grouping is not allowed in ZON", .{}, &.{
304 try zg.errNoteTok(main_tokens[node], "these parentheses are always redundant", .{}),
297 try zg.addErrorTokNotes(tree.nodeMainToken(node), "expression grouping is not allowed in ZON", .{}, &.{
298 try zg.errNoteTok(tree.nodeMainToken(node), "these parentheses are always redundant", .{}),
305299 });
306 return zg.expr(node_datas[node].lhs, dest_node);
300 return zg.expr(tree.nodeData(node).node_and_token[0], dest_node);
307301 },
308302
309303 .negation => {
310 const child_node = node_datas[node].lhs;
311 switch (node_tags[child_node]) {
304 const child_node = tree.nodeData(node).node;
305 switch (tree.nodeTag(child_node)) {
312306 .number_literal => return zg.numberLiteral(child_node, node, dest_node, .negative),
313307 .identifier => {
314 const child_ident = tree.tokenSlice(main_tokens[child_node]);
308 const child_ident = tree.tokenSlice(tree.nodeMainToken(child_node));
315309 if (mem.eql(u8, child_ident, "inf")) {
316310 zg.setNode(dest_node, .{
317311 .tag = .neg_inf,
......@@ -323,7 +317,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
323317 },
324318 else => {},
325319 }
326 try zg.addErrorTok(main_tokens[node], "expected number or 'inf' after '-'", .{});
320 try zg.addErrorTok(tree.nodeMainToken(node), "expected number or 'inf' after '-'", .{});
327321 },
328322 .number_literal => try zg.numberLiteral(node, node, dest_node, .positive),
329323 .char_literal => try zg.charLiteral(node, dest_node),
......@@ -331,7 +325,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
331325 .identifier => try zg.identifier(node, dest_node),
332326
333327 .enum_literal => {
334 const str_index = zg.identAsString(main_tokens[node]) catch |err| switch (err) {
328 const str_index = zg.identAsString(tree.nodeMainToken(node)) catch |err| switch (err) {
335329 error.BadString => undefined, // doesn't matter, there's an error
336330 error.OutOfMemory => |e| return e,
337331 };
......@@ -369,7 +363,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
369363 var buf: [2]Ast.Node.Index = undefined;
370364 const full = tree.fullArrayInit(&buf, node).?;
371365 assert(full.ast.elements.len != 0); // Otherwise it would be a struct init
372 assert(full.ast.type_expr == 0); // The tag was `array_init_dot_*`
366 assert(full.ast.type_expr == .none); // The tag was `array_init_dot_*`
373367
374368 const first_elem: u32 = @intCast(zg.nodes.len);
375369 try zg.nodes.resize(gpa, zg.nodes.len + full.ast.elements.len);
......@@ -398,7 +392,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
398392 => {
399393 var buf: [2]Ast.Node.Index = undefined;
400394 const full = tree.fullStructInit(&buf, node).?;
401 assert(full.ast.type_expr == 0); // The tag was `struct_init_dot_*`
395 assert(full.ast.type_expr == .none); // The tag was `struct_init_dot_*`
402396
403397 if (full.ast.fields.len == 0) {
404398 zg.setNode(dest_node, .{
......@@ -460,7 +454,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
460454
461455fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
462456 const tree = zg.tree;
463 assert(tree.tokens.items(.tag)[ident_token] == .identifier);
457 assert(tree.tokenTag(ident_token) == .identifier);
464458 const ident_name = tree.tokenSlice(ident_token);
465459 if (!mem.startsWith(u8, ident_name, "@")) {
466460 const start = zg.string_bytes.items.len;
......@@ -493,19 +487,16 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
493487
494488/// Estimates the size of a string node without parsing it.
495489pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
496 switch (tree.nodes.items(.tag)[node]) {
490 switch (tree.nodeTag(node)) {
497491 // Parsed string literals are typically around the size of the raw strings.
498492 .string_literal => {
499 const token = tree.nodes.items(.main_token)[node];
493 const token = tree.nodeMainToken(node);
500494 const raw_string = tree.tokenSlice(token);
501495 return raw_string.len;
502496 },
503497 // Multiline string literal lengths can be computed exactly.
504498 .multiline_string_literal => {
505 const first_tok, const last_tok = bounds: {
506 const node_data = tree.nodes.items(.data)[node];
507 break :bounds .{ node_data.lhs, node_data.rhs };
508 };
499 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
509500
510501 var size = tree.tokenSlice(first_tok)[2..].len;
511502 for (first_tok + 1..last_tok + 1) |tok_idx| {
......@@ -524,17 +515,14 @@ pub fn parseStrLit(
524515 node: Ast.Node.Index,
525516 writer: anytype,
526517) error{OutOfMemory}!std.zig.string_literal.Result {
527 switch (tree.nodes.items(.tag)[node]) {
518 switch (tree.nodeTag(node)) {
528519 .string_literal => {
529 const token = tree.nodes.items(.main_token)[node];
520 const token = tree.nodeMainToken(node);
530521 const raw_string = tree.tokenSlice(token);
531522 return std.zig.string_literal.parseWrite(writer, raw_string);
532523 },
533524 .multiline_string_literal => {
534 const first_tok, const last_tok = bounds: {
535 const node_data = tree.nodes.items(.data)[node];
536 break :bounds .{ node_data.lhs, node_data.rhs };
537 };
525 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
538526
539527 // First line: do not append a newline.
540528 {
......@@ -572,7 +560,7 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) !StringLiteralResult {
572560 switch (try parseStrLit(zg.tree, str_node, zg.string_bytes.writer(zg.gpa))) {
573561 .success => {},
574562 .failure => |err| {
575 const token = zg.tree.nodes.items(.main_token)[str_node];
563 const token = zg.tree.nodeMainToken(str_node);
576564 const raw_string = zg.tree.tokenSlice(token);
577565 try zg.lowerStrLitError(err, token, raw_string, 0);
578566 return error.BadString;
......@@ -620,7 +608,7 @@ fn identAsString(zg: *ZonGen, ident_token: Ast.TokenIndex) !Zoir.NullTerminatedS
620608
621609fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum { negative, positive }) !void {
622610 const tree = zg.tree;
623 const num_token = tree.nodes.items(.main_token)[num_node];
611 const num_token = tree.nodeMainToken(num_node);
624612 const num_bytes = tree.tokenSlice(num_token);
625613
626614 switch (std.zig.parseNumberLiteral(num_bytes)) {
......@@ -724,8 +712,8 @@ fn setBigIntLiteralNode(zg: *ZonGen, dest_node: Zoir.Node.Index, src_node: Ast.N
724712
725713fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {
726714 const tree = zg.tree;
727 assert(tree.nodes.items(.tag)[node] == .char_literal);
728 const main_token = tree.nodes.items(.main_token)[node];
715 assert(tree.nodeTag(node) == .char_literal);
716 const main_token = tree.nodeMainToken(node);
729717 const slice = tree.tokenSlice(main_token);
730718 switch (std.zig.parseCharLiteral(slice)) {
731719 .success => |codepoint| zg.setNode(dest_node, .{
......@@ -739,8 +727,8 @@ fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !v
739727
740728fn identifier(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {
741729 const tree = zg.tree;
742 assert(tree.nodes.items(.tag)[node] == .identifier);
743 const main_token = tree.nodes.items(.main_token)[node];
730 assert(tree.nodeTag(node) == .identifier);
731 const main_token = tree.nodeMainToken(node);
744732 const ident = tree.tokenSlice(main_token);
745733
746734 const tag: Zoir.Node.Repr.Tag = t: {
......@@ -823,8 +811,8 @@ fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, a
823811
824812 return .{
825813 .msg = @enumFromInt(message_idx),
826 .token = Zoir.CompileError.invalid_token,
827 .node_or_offset = node,
814 .token = .none,
815 .node_or_offset = @intFromEnum(node),
828816 };
829817}
830818
......@@ -836,33 +824,33 @@ fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, arg
836824
837825 return .{
838826 .msg = @enumFromInt(message_idx),
839 .token = tok,
827 .token = .fromToken(tok),
840828 .node_or_offset = 0,
841829 };
842830}
843831
844832fn addErrorNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype) Allocator.Error!void {
845 return zg.addErrorInner(Zoir.CompileError.invalid_token, node, format, args, &.{});
833 return zg.addErrorInner(.none, @intFromEnum(node), format, args, &.{});
846834}
847835fn addErrorTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype) Allocator.Error!void {
848 return zg.addErrorInner(tok, 0, format, args, &.{});
836 return zg.addErrorInner(.fromToken(tok), 0, format, args, &.{});
849837}
850838fn addErrorNodeNotes(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {
851 return zg.addErrorInner(Zoir.CompileError.invalid_token, node, format, args, notes);
839 return zg.addErrorInner(.none, @intFromEnum(node), format, args, notes);
852840}
853841fn addErrorTokNotes(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {
854 return zg.addErrorInner(tok, 0, format, args, notes);
842 return zg.addErrorInner(.fromToken(tok), 0, format, args, notes);
855843}
856844fn addErrorTokOff(zg: *ZonGen, tok: Ast.TokenIndex, offset: u32, comptime format: []const u8, args: anytype) Allocator.Error!void {
857 return zg.addErrorInner(tok, offset, format, args, &.{});
845 return zg.addErrorInner(.fromToken(tok), offset, format, args, &.{});
858846}
859847fn addErrorTokNotesOff(zg: *ZonGen, tok: Ast.TokenIndex, offset: u32, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {
860 return zg.addErrorInner(tok, offset, format, args, notes);
848 return zg.addErrorInner(.fromToken(tok), offset, format, args, notes);
861849}
862850
863851fn addErrorInner(
864852 zg: *ZonGen,
865 token: Ast.TokenIndex,
853 token: Ast.OptionalTokenIndex,
866854 node_or_offset: u32,
867855 comptime format: []const u8,
868856 args: anytype,
lib/std/zig/render.zig+469-530
......@@ -91,21 +91,22 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v
9191 };
9292
9393 // Render all the line comments at the beginning of the file.
94 const comment_end_loc = tree.tokens.items(.start)[0];
94 const comment_end_loc = tree.tokenStart(0);
9595 _ = try renderComments(&r, 0, comment_end_loc);
9696
97 if (tree.tokens.items(.tag)[0] == .container_doc_comment) {
97 if (tree.tokenTag(0) == .container_doc_comment) {
9898 try renderContainerDocComments(&r, 0);
9999 }
100100
101 if (tree.mode == .zon) {
102 try renderExpression(
103 &r,
104 tree.nodes.items(.data)[0].lhs,
105 .newline,
106 );
107 } else {
108 try renderMembers(&r, tree.rootDecls());
101 switch (tree.mode) {
102 .zig => try renderMembers(&r, tree.rootDecls()),
103 .zon => {
104 try renderExpression(
105 &r,
106 tree.rootDecls()[0],
107 .newline,
108 );
109 },
109110 }
110111
111112 if (auto_indenting_stream.disabled_offset) |disabled_offset| {
......@@ -141,24 +142,20 @@ fn renderMember(
141142) Error!void {
142143 const tree = r.tree;
143144 const ais = r.ais;
144 const node_tags = tree.nodes.items(.tag);
145 const token_tags = tree.tokens.items(.tag);
146 const main_tokens = tree.nodes.items(.main_token);
147 const datas = tree.nodes.items(.data);
148145 if (r.fixups.omit_nodes.contains(decl)) return;
149146 try renderDocComments(r, tree.firstToken(decl));
150 switch (tree.nodes.items(.tag)[decl]) {
147 switch (tree.nodeTag(decl)) {
151148 .fn_decl => {
152149 // Some examples:
153150 // pub extern "foo" fn ...
154151 // export fn ...
155 const fn_proto = datas[decl].lhs;
156 const fn_token = main_tokens[fn_proto];
152 const fn_proto, const body_node = tree.nodeData(decl).node_and_node;
153 const fn_token = tree.nodeMainToken(fn_proto);
157154 // Go back to the first token we should render here.
158155 var i = fn_token;
159156 while (i > 0) {
160157 i -= 1;
161 switch (token_tags[i]) {
158 switch (tree.tokenTag(i)) {
162159 .keyword_extern,
163160 .keyword_export,
164161 .keyword_pub,
......@@ -173,31 +170,34 @@ fn renderMember(
173170 },
174171 }
175172 }
173
176174 while (i < fn_token) : (i += 1) {
177175 try renderToken(r, i, .space);
178176 }
179 switch (tree.nodes.items(.tag)[fn_proto]) {
177 switch (tree.nodeTag(fn_proto)) {
180178 .fn_proto_one, .fn_proto => {
181 const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one)
182 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr
179 var buf: [1]Ast.Node.Index = undefined;
180 const opt_callconv_expr = if (tree.nodeTag(fn_proto) == .fn_proto_one)
181 tree.fnProtoOne(&buf, fn_proto).ast.callconv_expr
183182 else
184 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;
183 tree.fnProto(fn_proto).ast.callconv_expr;
184
185185 // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE
186 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {
187 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) {
188 try ais.writer().writeAll("inline ");
186 if (opt_callconv_expr.unwrap()) |callconv_expr| {
187 if (tree.nodeTag(callconv_expr) == .enum_literal) {
188 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
189 try ais.writer().writeAll("inline ");
190 }
189191 }
190192 }
191193 },
192194 .fn_proto_simple, .fn_proto_multi => {},
193195 else => unreachable,
194196 }
195 assert(datas[decl].rhs != 0);
196197 try renderExpression(r, fn_proto, .space);
197 const body_node = datas[decl].rhs;
198198 if (r.fixups.gut_functions.contains(decl)) {
199199 try ais.pushIndent(.normal);
200 const lbrace = tree.nodes.items(.main_token)[body_node];
200 const lbrace = tree.nodeMainToken(body_node);
201201 try renderToken(r, lbrace, .newline);
202202 try discardAllParams(r, fn_proto);
203203 try ais.writer().writeAll("@trap();");
......@@ -206,7 +206,7 @@ fn renderMember(
206206 try renderToken(r, tree.lastToken(body_node), space); // rbrace
207207 } else if (r.fixups.unused_var_decls.count() != 0) {
208208 try ais.pushIndent(.normal);
209 const lbrace = tree.nodes.items(.main_token)[body_node];
209 const lbrace = tree.nodeMainToken(body_node);
210210 try renderToken(r, lbrace, .newline);
211211
212212 var fn_proto_buf: [1]Ast.Node.Index = undefined;
......@@ -214,7 +214,7 @@ fn renderMember(
214214 var it = full_fn_proto.iterate(&tree);
215215 while (it.next()) |param| {
216216 const name_ident = param.name_token.?;
217 assert(token_tags[name_ident] == .identifier);
217 assert(tree.tokenTag(name_ident) == .identifier);
218218 if (r.fixups.unused_var_decls.contains(name_ident)) {
219219 const w = ais.writer();
220220 try w.writeAll("_ = ");
......@@ -223,25 +223,7 @@ fn renderMember(
223223 }
224224 }
225225 var statements_buf: [2]Ast.Node.Index = undefined;
226 const statements = switch (node_tags[body_node]) {
227 .block_two,
228 .block_two_semicolon,
229 => b: {
230 statements_buf = .{ datas[body_node].lhs, datas[body_node].rhs };
231 if (datas[body_node].lhs == 0) {
232 break :b statements_buf[0..0];
233 } else if (datas[body_node].rhs == 0) {
234 break :b statements_buf[0..1];
235 } else {
236 break :b statements_buf[0..2];
237 }
238 },
239 .block,
240 .block_semicolon,
241 => tree.extra_data[datas[body_node].lhs..datas[body_node].rhs],
242
243 else => unreachable,
244 };
226 const statements = tree.blockStatements(&statements_buf, body_node).?;
245227 return finishRenderBlock(r, body_node, statements, space);
246228 } else {
247229 return renderExpression(r, body_node, space);
......@@ -254,11 +236,11 @@ fn renderMember(
254236 => {
255237 // Extern function prototypes are parsed as these tags.
256238 // Go back to the first token we should render here.
257 const fn_token = main_tokens[decl];
239 const fn_token = tree.nodeMainToken(decl);
258240 var i = fn_token;
259241 while (i > 0) {
260242 i -= 1;
261 switch (token_tags[i]) {
243 switch (tree.tokenTag(i)) {
262244 .keyword_extern,
263245 .keyword_export,
264246 .keyword_pub,
......@@ -281,9 +263,9 @@ fn renderMember(
281263 },
282264
283265 .@"usingnamespace" => {
284 const main_token = main_tokens[decl];
285 const expr = datas[decl].lhs;
286 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {
266 const main_token = tree.nodeMainToken(decl);
267 const expr = tree.nodeData(decl).node;
268 if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) {
287269 try renderToken(r, main_token - 1, .space); // pub
288270 }
289271 try renderToken(r, main_token, .space); // usingnamespace
......@@ -302,15 +284,17 @@ fn renderMember(
302284 },
303285
304286 .test_decl => {
305 const test_token = main_tokens[decl];
287 const test_token = tree.nodeMainToken(decl);
288 const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node;
306289 try renderToken(r, test_token, .space);
307 const test_name_tag = token_tags[test_token + 1];
308 switch (test_name_tag) {
309 .string_literal => try renderToken(r, test_token + 1, .space),
310 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),
311 else => {},
290 if (opt_name_token.unwrap()) |name_token| {
291 switch (tree.tokenTag(name_token)) {
292 .string_literal => try renderToken(r, name_token, .space),
293 .identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing),
294 else => unreachable,
295 }
312296 }
313 try renderExpression(r, datas[decl].rhs, space);
297 try renderExpression(r, block_node, space);
314298 },
315299
316300 .container_field_init,
......@@ -338,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa
338322fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
339323 const tree = r.tree;
340324 const ais = r.ais;
341 const token_tags = tree.tokens.items(.tag);
342 const main_tokens = tree.nodes.items(.main_token);
343 const node_tags = tree.nodes.items(.tag);
344 const datas = tree.nodes.items(.data);
345325 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
346326 try ais.writer().writeAll(replacement);
347327 try renderOnlySpace(r, space);
......@@ -349,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
349329 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
350330 return renderExpression(r, replacement, space);
351331 }
352 switch (node_tags[node]) {
332 switch (tree.nodeTag(node)) {
353333 .identifier => {
354 const token_index = main_tokens[node];
334 const token_index = tree.nodeMainToken(node);
355335 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);
356336 },
357337
......@@ -360,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
360340 .unreachable_literal,
361341 .anyframe_literal,
362342 .string_literal,
363 => return renderToken(r, main_tokens[node], space),
343 => return renderToken(r, tree.nodeMainToken(node), space),
364344
365345 .multiline_string_literal => {
366346 try ais.maybeInsertNewline();
367347
368 var i = datas[node].lhs;
369 while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline);
348 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
349 for (first_tok..last_tok + 1) |i| {
350 try renderToken(r, @intCast(i), .newline);
351 }
352
353 const next_token = last_tok + 1;
354 const next_token_tag = tree.tokenTag(next_token);
370355
371356 // dedent the next thing that comes after a multiline string literal
372357 if (!ais.indentStackEmpty() and
373 token_tags[i] != .colon and
374 ((token_tags[i] != .semicolon and token_tags[i] != .comma) or
358 next_token_tag != .colon and
359 ((next_token_tag != .semicolon and next_token_tag != .comma) or
375360 ais.lastSpaceModeIndent() < ais.currentIndent()))
376361 {
377362 ais.popIndent();
......@@ -380,44 +365,35 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
380365
381366 switch (space) {
382367 .none, .space, .newline, .skip => {},
383 .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon),
384 .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma),
385 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),
368 .semicolon => if (next_token_tag == .semicolon) try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon),
369 .comma => if (next_token_tag == .comma) try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma),
370 .comma_space => if (next_token_tag == .comma) try renderToken(r, next_token, .space),
386371 }
387372 },
388373
389374 .error_value => {
390 try renderToken(r, main_tokens[node], .none);
391 try renderToken(r, main_tokens[node] + 1, .none);
392 return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote);
375 const main_token = tree.nodeMainToken(node);
376 try renderToken(r, main_token, .none);
377 try renderToken(r, main_token + 1, .none);
378 return renderIdentifier(r, main_token + 2, space, .eagerly_unquote);
393379 },
394380
395381 .block_two,
396382 .block_two_semicolon,
397 => {
398 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
399 if (datas[node].lhs == 0) {
400 return renderBlock(r, node, statements[0..0], space);
401 } else if (datas[node].rhs == 0) {
402 return renderBlock(r, node, statements[0..1], space);
403 } else {
404 return renderBlock(r, node, statements[0..2], space);
405 }
406 },
407383 .block,
408384 .block_semicolon,
409385 => {
410 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];
386 var buf: [2]Ast.Node.Index = undefined;
387 const statements = tree.blockStatements(&buf, node).?;
411388 return renderBlock(r, node, statements, space);
412389 },
413390
414391 .@"errdefer" => {
415 const defer_token = main_tokens[node];
416 const payload_token = datas[node].lhs;
417 const expr = datas[node].rhs;
392 const defer_token = tree.nodeMainToken(node);
393 const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node;
418394
419395 try renderToken(r, defer_token, .space);
420 if (payload_token != 0) {
396 if (maybe_payload_token.unwrap()) |payload_token| {
421397 try renderToken(r, payload_token - 1, .none); // |
422398 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
423399 try renderToken(r, payload_token + 1, .space); // |
......@@ -425,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
425401 return renderExpression(r, expr, space);
426402 },
427403
428 .@"defer" => {
429 const defer_token = main_tokens[node];
430 const expr = datas[node].rhs;
431 try renderToken(r, defer_token, .space);
432 return renderExpression(r, expr, space);
433 },
434 .@"comptime", .@"nosuspend" => {
435 const comptime_token = main_tokens[node];
436 const block = datas[node].lhs;
437 try renderToken(r, comptime_token, .space);
438 return renderExpression(r, block, space);
439 },
440
441 .@"suspend" => {
442 const suspend_token = main_tokens[node];
443 const body = datas[node].lhs;
444 try renderToken(r, suspend_token, .space);
445 return renderExpression(r, body, space);
404 .@"defer",
405 .@"comptime",
406 .@"nosuspend",
407 .@"suspend",
408 => {
409 const main_token = tree.nodeMainToken(node);
410 const item = tree.nodeData(node).node;
411 try renderToken(r, main_token, .space);
412 return renderExpression(r, item, space);
446413 },
447414
448415 .@"catch" => {
449 const main_token = main_tokens[node];
450 const fallback_first = tree.firstToken(datas[node].rhs);
416 const main_token = tree.nodeMainToken(node);
417 const lhs, const rhs = tree.nodeData(node).node_and_node;
418 const fallback_first = tree.firstToken(rhs);
451419
452420 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
453421 const after_op_space = if (same_line) Space.space else Space.newline;
454422
455 try renderExpression(r, datas[node].lhs, .space); // target
423 try renderExpression(r, lhs, .space); // target
456424
457425 try ais.pushIndent(.normal);
458 if (token_tags[fallback_first - 1] == .pipe) {
426 if (tree.tokenTag(fallback_first - 1) == .pipe) {
459427 try renderToken(r, main_token, .space); // catch keyword
460428 try renderToken(r, main_token + 1, .none); // pipe
461429 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
462430 try renderToken(r, main_token + 3, after_op_space); // pipe
463431 } else {
464 assert(token_tags[fallback_first - 1] == .keyword_catch);
432 assert(tree.tokenTag(fallback_first - 1) == .keyword_catch);
465433 try renderToken(r, main_token, after_op_space); // catch keyword
466434 }
467 try renderExpression(r, datas[node].rhs, space); // fallback
435 try renderExpression(r, rhs, space); // fallback
468436 ais.popIndent();
469437 },
470438
471439 .field_access => {
472 const main_token = main_tokens[node];
473 const field_access = datas[node];
440 const lhs, const name_token = tree.nodeData(node).node_and_token;
441 const dot_token = name_token - 1;
474442
475443 try ais.pushIndent(.field_access);
476 try renderExpression(r, field_access.lhs, .none);
444 try renderExpression(r, lhs, .none);
477445
478446 // Allow a line break between the lhs and the dot if the lhs and rhs
479447 // are on different lines.
480 const lhs_last_token = tree.lastToken(field_access.lhs);
481 const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1);
482 if (!same_line and !hasComment(tree, lhs_last_token, main_token)) try ais.insertNewline();
448 const lhs_last_token = tree.lastToken(lhs);
449 const same_line = tree.tokensOnSameLine(lhs_last_token, name_token);
450 if (!same_line and !hasComment(tree, lhs_last_token, dot_token)) try ais.insertNewline();
483451
484 try renderToken(r, main_token, .none); // .
452 try renderToken(r, dot_token, .none);
485453
486 try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field
454 try renderIdentifier(r, name_token, space, .eagerly_unquote); // field
487455 ais.popIndent();
488456 },
489457
490458 .error_union,
491459 .switch_range,
492460 => {
493 const infix = datas[node];
494 try renderExpression(r, infix.lhs, .none);
495 try renderToken(r, main_tokens[node], .none);
496 return renderExpression(r, infix.rhs, space);
461 const lhs, const rhs = tree.nodeData(node).node_and_node;
462 try renderExpression(r, lhs, .none);
463 try renderToken(r, tree.nodeMainToken(node), .none);
464 return renderExpression(r, rhs, space);
497465 },
498466 .for_range => {
499 const infix = datas[node];
500 try renderExpression(r, infix.lhs, .none);
501 if (infix.rhs != 0) {
502 try renderToken(r, main_tokens[node], .none);
503 return renderExpression(r, infix.rhs, space);
467 const start, const opt_end = tree.nodeData(node).node_and_opt_node;
468 try renderExpression(r, start, .none);
469 if (opt_end.unwrap()) |end| {
470 try renderToken(r, tree.nodeMainToken(node), .none);
471 return renderExpression(r, end, space);
504472 } else {
505 return renderToken(r, main_tokens[node], space);
473 return renderToken(r, tree.nodeMainToken(node), space);
506474 }
507475 },
508476
......@@ -525,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
525493 .assign_mul_wrap,
526494 .assign_mul_sat,
527495 => {
528 const infix = datas[node];
529 try renderExpression(r, infix.lhs, .space);
530 const op_token = main_tokens[node];
496 const lhs, const rhs = tree.nodeData(node).node_and_node;
497 try renderExpression(r, lhs, .space);
498 const op_token = tree.nodeMainToken(node);
531499 try ais.pushIndent(.after_equals);
532500 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
533501 try renderToken(r, op_token, .space);
534502 } else {
535503 try renderToken(r, op_token, .newline);
536504 }
537 try renderExpression(r, infix.rhs, space);
505 try renderExpression(r, rhs, space);
538506 ais.popIndent();
539507 },
540508
......@@ -568,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
568536 .sub_sat,
569537 .@"orelse",
570538 => {
571 const infix = datas[node];
572 try renderExpression(r, infix.lhs, .space);
573 const op_token = main_tokens[node];
539 const lhs, const rhs = tree.nodeData(node).node_and_node;
540 try renderExpression(r, lhs, .space);
541 const op_token = tree.nodeMainToken(node);
574542 try ais.pushIndent(.binop);
575543 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
576544 try renderToken(r, op_token, .space);
577545 } else {
578546 try renderToken(r, op_token, .newline);
579547 }
580 try renderExpression(r, infix.rhs, space);
548 try renderExpression(r, rhs, space);
581549 ais.popIndent();
582550 },
583551
......@@ -589,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
589557
590558 for (full.ast.variables, 0..) |variable_node, i| {
591559 const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space;
592 switch (node_tags[variable_node]) {
560 switch (tree.nodeTag(variable_node)) {
593561 .global_var_decl,
594562 .local_var_decl,
595563 .simple_var_decl,
......@@ -617,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
617585 .optional_type,
618586 .address_of,
619587 => {
620 try renderToken(r, main_tokens[node], .none);
621 return renderExpression(r, datas[node].lhs, space);
588 try renderToken(r, tree.nodeMainToken(node), .none);
589 return renderExpression(r, tree.nodeData(node).node, space);
622590 },
623591
624592 .@"try",
625593 .@"resume",
626594 .@"await",
627595 => {
628 try renderToken(r, main_tokens[node], .space);
629 return renderExpression(r, datas[node].lhs, space);
596 try renderToken(r, tree.nodeMainToken(node), .space);
597 return renderExpression(r, tree.nodeData(node).node, space);
630598 },
631599
632600 .array_type,
......@@ -679,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
679647 },
680648
681649 .array_access => {
682 const suffix = datas[node];
683 const lbracket = tree.firstToken(suffix.rhs) - 1;
684 const rbracket = tree.lastToken(suffix.rhs) + 1;
650 const lhs, const rhs = tree.nodeData(node).node_and_node;
651 const lbracket = tree.firstToken(rhs) - 1;
652 const rbracket = tree.lastToken(rhs) + 1;
685653 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
686654 const inner_space = if (one_line) Space.none else Space.newline;
687 try renderExpression(r, suffix.lhs, .none);
655 try renderExpression(r, lhs, .none);
688656 try ais.pushIndent(.normal);
689657 try renderToken(r, lbracket, inner_space); // [
690 try renderExpression(r, suffix.rhs, inner_space);
658 try renderExpression(r, rhs, inner_space);
691659 ais.popIndent();
692660 return renderToken(r, rbracket, space); // ]
693661 },
694662
695 .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space),
663 .slice_open,
664 .slice,
665 .slice_sentinel,
666 => return renderSlice(r, node, tree.fullSlice(node).?, space),
696667
697668 .deref => {
698 try renderExpression(r, datas[node].lhs, .none);
699 return renderToken(r, main_tokens[node], space);
669 try renderExpression(r, tree.nodeData(node).node, .none);
670 return renderToken(r, tree.nodeMainToken(node), space);
700671 },
701672
702673 .unwrap_optional => {
703 try renderExpression(r, datas[node].lhs, .none);
704 try renderToken(r, main_tokens[node], .none);
705 return renderToken(r, datas[node].rhs, space);
674 const lhs, const question_mark = tree.nodeData(node).node_and_token;
675 const dot_token = question_mark - 1;
676 try renderExpression(r, lhs, .none);
677 try renderToken(r, dot_token, .none);
678 return renderToken(r, question_mark, space);
706679 },
707680
708681 .@"break", .@"continue" => {
709 const main_token = main_tokens[node];
710 const label_token = datas[node].lhs;
711 const target = datas[node].rhs;
712 if (label_token == 0 and target == 0) {
682 const main_token = tree.nodeMainToken(node);
683 const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node;
684 if (opt_label_token == .none and opt_target == .none) {
713685 try renderToken(r, main_token, space); // break/continue
714 } else if (label_token == 0 and target != 0) {
686 } else if (opt_label_token == .none and opt_target != .none) {
687 const target = opt_target.unwrap().?;
715688 try renderToken(r, main_token, .space); // break/continue
716689 try renderExpression(r, target, space);
717 } else if (label_token != 0 and target == 0) {
690 } else if (opt_label_token != .none and opt_target == .none) {
691 const label_token = opt_label_token.unwrap().?;
718692 try renderToken(r, main_token, .space); // break/continue
719693 try renderToken(r, label_token - 1, .none); // :
720694 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
721 } else if (label_token != 0 and target != 0) {
695 } else if (opt_label_token != .none and opt_target != .none) {
696 const label_token = opt_label_token.unwrap().?;
697 const target = opt_target.unwrap().?;
722698 try renderToken(r, main_token, .space); // break/continue
723699 try renderToken(r, label_token - 1, .none); // :
724700 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
725701 try renderExpression(r, target, space);
726 }
702 } else unreachable;
727703 },
728704
729705 .@"return" => {
730 if (datas[node].lhs != 0) {
731 try renderToken(r, main_tokens[node], .space);
732 try renderExpression(r, datas[node].lhs, space);
706 if (tree.nodeData(node).opt_node.unwrap()) |expr| {
707 try renderToken(r, tree.nodeMainToken(node), .space);
708 try renderExpression(r, expr, space);
733709 } else {
734 try renderToken(r, main_tokens[node], space);
710 try renderToken(r, tree.nodeMainToken(node), space);
735711 }
736712 },
737713
738714 .grouped_expression => {
715 const expr, const rparen = tree.nodeData(node).node_and_token;
739716 try ais.pushIndent(.normal);
740 try renderToken(r, main_tokens[node], .none); // lparen
741 try renderExpression(r, datas[node].lhs, .none);
717 try renderToken(r, tree.nodeMainToken(node), .none); // lparen
718 try renderExpression(r, expr, .none);
742719 ais.popIndent();
743 return renderToken(r, datas[node].rhs, space); // rparen
720 return renderToken(r, rparen, space);
744721 },
745722
746723 .container_decl,
......@@ -761,9 +738,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
761738 },
762739
763740 .error_set_decl => {
764 const error_token = main_tokens[node];
765 const lbrace = error_token + 1;
766 const rbrace = datas[node].rhs;
741 const error_token = tree.nodeMainToken(node);
742 const lbrace, const rbrace = tree.nodeData(node).token_and_token;
767743
768744 try renderToken(r, error_token, .none);
769745
......@@ -771,20 +747,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
771747 // There is nothing between the braces so render condensed: `error{}`
772748 try renderToken(r, lbrace, .none);
773749 return renderToken(r, rbrace, space);
774 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {
750 } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) {
775751 // There is exactly one member and no trailing comma or
776752 // comments, so render without surrounding spaces: `error{Foo}`
777753 try renderToken(r, lbrace, .none);
778754 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
779755 return renderToken(r, rbrace, space);
780 } else if (token_tags[rbrace - 1] == .comma) {
756 } else if (tree.tokenTag(rbrace - 1) == .comma) {
781757 // There is a trailing comma so render each member on a new line.
782758 try ais.pushIndent(.normal);
783759 try renderToken(r, lbrace, .newline);
784760 var i = lbrace + 1;
785761 while (i < rbrace) : (i += 1) {
786762 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
787 switch (token_tags[i]) {
763 switch (tree.tokenTag(i)) {
788764 .doc_comment => try renderToken(r, i, .newline),
789765 .identifier => {
790766 try ais.pushSpace(.comma);
......@@ -802,7 +778,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
802778 try renderToken(r, lbrace, .space);
803779 var i = lbrace + 1;
804780 while (i < rbrace) : (i += 1) {
805 switch (token_tags[i]) {
781 switch (tree.tokenTag(i)) {
806782 .doc_comment => unreachable, // TODO
807783 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),
808784 .comma => {},
......@@ -813,18 +789,14 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
813789 }
814790 },
815791
816 .builtin_call_two, .builtin_call_two_comma => {
817 if (datas[node].lhs == 0) {
818 return renderBuiltinCall(r, main_tokens[node], &.{}, space);
819 } else if (datas[node].rhs == 0) {
820 return renderBuiltinCall(r, main_tokens[node], &.{datas[node].lhs}, space);
821 } else {
822 return renderBuiltinCall(r, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);
823 }
824 },
825 .builtin_call, .builtin_call_comma => {
826 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
827 return renderBuiltinCall(r, main_tokens[node], params, space);
792 .builtin_call_two,
793 .builtin_call_two_comma,
794 .builtin_call,
795 .builtin_call_comma,
796 => {
797 var buf: [2]Ast.Node.Index = undefined;
798 const params = tree.builtinCallParams(&buf, node).?;
799 return renderBuiltinCall(r, tree.nodeMainToken(node), params, space);
828800 },
829801
830802 .fn_proto_simple,
......@@ -837,14 +809,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
837809 },
838810
839811 .anyframe_type => {
840 const main_token = main_tokens[node];
841 if (datas[node].rhs != 0) {
842 try renderToken(r, main_token, .none); // anyframe
843 try renderToken(r, main_token + 1, .none); // ->
844 return renderExpression(r, datas[node].rhs, space);
845 } else {
846 return renderToken(r, main_token, space); // anyframe
847 }
812 const main_token = tree.nodeMainToken(node);
813 try renderToken(r, main_token, .none); // anyframe
814 try renderToken(r, main_token + 1, .none); // ->
815 return renderExpression(r, tree.nodeData(node).token_and_node[1], space);
848816 },
849817
850818 .@"switch",
......@@ -901,8 +869,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
901869 => return renderAsm(r, tree.fullAsm(node).?, space),
902870
903871 .enum_literal => {
904 try renderToken(r, main_tokens[node] - 1, .none); // .
905 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name
872 try renderToken(r, tree.nodeMainToken(node) - 1, .none); // .
873 return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name
906874 },
907875
908876 .fn_decl => unreachable,
......@@ -944,9 +912,9 @@ fn renderArrayType(
944912 try ais.pushIndent(.normal);
945913 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
946914 try renderExpression(r, array_type.ast.elem_count, inner_space);
947 if (array_type.ast.sentinel != 0) {
948 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
949 try renderExpression(r, array_type.ast.sentinel, inner_space);
915 if (array_type.ast.sentinel.unwrap()) |sentinel| {
916 try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon
917 try renderExpression(r, sentinel, inner_space);
950918 }
951919 ais.popIndent();
952920 try renderToken(r, rbracket, .none); // rbracket
......@@ -955,6 +923,7 @@ fn renderArrayType(
955923
956924fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
957925 const tree = r.tree;
926 const main_token = ptr_type.ast.main_token;
958927 switch (ptr_type.size) {
959928 .one => {
960929 // Since ** tokens exist and the same token is shared by two
......@@ -962,41 +931,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
962931 // in such a relationship. If so, skip rendering anything for
963932 // this pointer type and rely on the child to render our asterisk
964933 // as well when it renders the ** token.
965 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and
966 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
934 if (tree.tokenTag(main_token) == .asterisk_asterisk and
935 main_token == tree.nodeMainToken(ptr_type.ast.child_type))
967936 {
968937 return renderExpression(r, ptr_type.ast.child_type, space);
969938 }
970 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
939 try renderToken(r, main_token, .none); // asterisk
971940 },
972941 .many => {
973 if (ptr_type.ast.sentinel == 0) {
974 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
975 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
976 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket
942 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
943 try renderToken(r, main_token, .none); // lbracket
944 try renderToken(r, main_token + 1, .none); // asterisk
945 try renderToken(r, main_token + 2, .none); // colon
946 try renderExpression(r, sentinel, .none);
947 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
977948 } else {
978 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
979 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
980 try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon
981 try renderExpression(r, ptr_type.ast.sentinel, .none);
982 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
949 try renderToken(r, main_token, .none); // lbracket
950 try renderToken(r, main_token + 1, .none); // asterisk
951 try renderToken(r, main_token + 2, .none); // rbracket
983952 }
984953 },
985954 .c => {
986 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
987 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
988 try renderToken(r, ptr_type.ast.main_token + 2, .none); // c
989 try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket
955 try renderToken(r, main_token, .none); // lbracket
956 try renderToken(r, main_token + 1, .none); // asterisk
957 try renderToken(r, main_token + 2, .none); // c
958 try renderToken(r, main_token + 3, .none); // rbracket
990959 },
991960 .slice => {
992 if (ptr_type.ast.sentinel == 0) {
993 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
994 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
961 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
962 try renderToken(r, main_token, .none); // lbracket
963 try renderToken(r, main_token + 1, .none); // colon
964 try renderExpression(r, sentinel, .none);
965 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
995966 } else {
996 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
997 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
998 try renderExpression(r, ptr_type.ast.sentinel, .none);
999 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
967 try renderToken(r, main_token, .none); // lbracket
968 try renderToken(r, main_token + 1, .none); // rbracket
1000969 }
1001970 },
1002971 }
......@@ -1005,29 +974,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
1005974 try renderToken(r, allowzero_token, .space);
1006975 }
1007976
1008 if (ptr_type.ast.align_node != 0) {
1009 const align_first = tree.firstToken(ptr_type.ast.align_node);
977 if (ptr_type.ast.align_node.unwrap()) |align_node| {
978 const align_first = tree.firstToken(align_node);
1010979 try renderToken(r, align_first - 2, .none); // align
1011980 try renderToken(r, align_first - 1, .none); // lparen
1012 try renderExpression(r, ptr_type.ast.align_node, .none);
1013 if (ptr_type.ast.bit_range_start != 0) {
1014 assert(ptr_type.ast.bit_range_end != 0);
1015 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
1016 try renderExpression(r, ptr_type.ast.bit_range_start, .none);
1017 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
1018 try renderExpression(r, ptr_type.ast.bit_range_end, .none);
1019 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
981 try renderExpression(r, align_node, .none);
982 if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| {
983 const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?;
984 try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon
985 try renderExpression(r, bit_range_start, .none);
986 try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon
987 try renderExpression(r, bit_range_end, .none);
988 try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen
1020989 } else {
1021 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
990 try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen
1022991 }
1023992 }
1024993
1025 if (ptr_type.ast.addrspace_node != 0) {
1026 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);
994 if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| {
995 const addrspace_first = tree.firstToken(addrspace_node);
1027996 try renderToken(r, addrspace_first - 2, .none); // addrspace
1028997 try renderToken(r, addrspace_first - 1, .none); // lparen
1029 try renderExpression(r, ptr_type.ast.addrspace_node, .none);
1030 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen
998 try renderExpression(r, addrspace_node, .none);
999 try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen
10311000 }
10321001
10331002 if (ptr_type.const_token) |const_token| {
......@@ -1048,13 +1017,12 @@ fn renderSlice(
10481017 space: Space,
10491018) Error!void {
10501019 const tree = r.tree;
1051 const node_tags = tree.nodes.items(.tag);
1052 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
1053 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
1020 const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
1021 if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
10541022 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
1055 const after_dots_space = if (slice.ast.end != 0)
1023 const after_dots_space = if (slice.ast.end != .none)
10561024 after_start_space
1057 else if (slice.ast.sentinel != 0) Space.space else Space.none;
1025 else if (slice.ast.sentinel != .none) Space.space else Space.none;
10581026
10591027 try renderExpression(r, slice.ast.sliced, .none);
10601028 try renderToken(r, slice.ast.lbracket, .none); // lbracket
......@@ -1063,14 +1031,14 @@ fn renderSlice(
10631031 try renderExpression(r, slice.ast.start, after_start_space);
10641032 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
10651033
1066 if (slice.ast.end != 0) {
1067 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;
1068 try renderExpression(r, slice.ast.end, after_end_space);
1034 if (slice.ast.end.unwrap()) |end| {
1035 const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none;
1036 try renderExpression(r, end, after_end_space);
10691037 }
10701038
1071 if (slice.ast.sentinel != 0) {
1072 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
1073 try renderExpression(r, slice.ast.sentinel, .none);
1039 if (slice.ast.sentinel.unwrap()) |sentinel| {
1040 try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon
1041 try renderExpression(r, sentinel, .none);
10741042 }
10751043
10761044 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
......@@ -1082,12 +1050,8 @@ fn renderAsmOutput(
10821050 space: Space,
10831051) Error!void {
10841052 const tree = r.tree;
1085 const token_tags = tree.tokens.items(.tag);
1086 const node_tags = tree.nodes.items(.tag);
1087 const main_tokens = tree.nodes.items(.main_token);
1088 const datas = tree.nodes.items(.data);
1089 assert(node_tags[asm_output] == .asm_output);
1090 const symbolic_name = main_tokens[asm_output];
1053 assert(tree.nodeTag(asm_output) == .asm_output);
1054 const symbolic_name = tree.nodeMainToken(asm_output);
10911055
10921056 try renderToken(r, symbolic_name - 1, .none); // lbracket
10931057 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
......@@ -1095,10 +1059,11 @@ fn renderAsmOutput(
10951059 try renderToken(r, symbolic_name + 2, .space); // "constraint"
10961060 try renderToken(r, symbolic_name + 3, .none); // lparen
10971061
1098 if (token_tags[symbolic_name + 4] == .arrow) {
1062 if (tree.tokenTag(symbolic_name + 4) == .arrow) {
1063 const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token;
10991064 try renderToken(r, symbolic_name + 4, .space); // ->
1100 try renderExpression(r, datas[asm_output].lhs, Space.none);
1101 return renderToken(r, datas[asm_output].rhs, space); // rparen
1065 try renderExpression(r, type_expr.unwrap().?, Space.none);
1066 return renderToken(r, rparen, space);
11021067 } else {
11031068 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
11041069 return renderToken(r, symbolic_name + 5, space); // rparen
......@@ -1111,19 +1076,17 @@ fn renderAsmInput(
11111076 space: Space,
11121077) Error!void {
11131078 const tree = r.tree;
1114 const node_tags = tree.nodes.items(.tag);
1115 const main_tokens = tree.nodes.items(.main_token);
1116 const datas = tree.nodes.items(.data);
1117 assert(node_tags[asm_input] == .asm_input);
1118 const symbolic_name = main_tokens[asm_input];
1079 assert(tree.nodeTag(asm_input) == .asm_input);
1080 const symbolic_name = tree.nodeMainToken(asm_input);
1081 const expr, const rparen = tree.nodeData(asm_input).node_and_token;
11191082
11201083 try renderToken(r, symbolic_name - 1, .none); // lbracket
11211084 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
11221085 try renderToken(r, symbolic_name + 1, .space); // rbracket
11231086 try renderToken(r, symbolic_name + 2, .space); // "constraint"
11241087 try renderToken(r, symbolic_name + 3, .none); // lparen
1125 try renderExpression(r, datas[asm_input].lhs, Space.none);
1126 return renderToken(r, datas[asm_input].rhs, space); // rparen
1088 try renderExpression(r, expr, Space.none);
1089 return renderToken(r, rparen, space);
11271090}
11281091
11291092fn renderVarDecl(
......@@ -1179,15 +1142,15 @@ fn renderVarDeclWithoutFixups(
11791142
11801143 try renderToken(r, var_decl.ast.mut_token, .space); // var
11811144
1182 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or
1183 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
1184 var_decl.ast.init_node != 0)
1145 if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or
1146 var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1147 var_decl.ast.init_node != .none)
11851148 {
1186 const name_space = if (var_decl.ast.type_node == 0 and
1187 (var_decl.ast.align_node != 0 or
1188 var_decl.ast.addrspace_node != 0 or
1189 var_decl.ast.section_node != 0 or
1190 var_decl.ast.init_node != 0))
1149 const name_space = if (var_decl.ast.type_node == .none and
1150 (var_decl.ast.align_node != .none or
1151 var_decl.ast.addrspace_node != .none or
1152 var_decl.ast.section_node != .none or
1153 var_decl.ast.init_node != .none))
11911154 Space.space
11921155 else
11931156 Space.none;
......@@ -1197,26 +1160,26 @@ fn renderVarDeclWithoutFixups(
11971160 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
11981161 }
11991162
1200 if (var_decl.ast.type_node != 0) {
1163 if (var_decl.ast.type_node.unwrap()) |type_node| {
12011164 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
1202 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or
1203 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)
1165 if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or
1166 var_decl.ast.section_node != .none or var_decl.ast.init_node != .none)
12041167 {
1205 try renderExpression(r, var_decl.ast.type_node, .space);
1168 try renderExpression(r, type_node, .space);
12061169 } else {
1207 return renderExpression(r, var_decl.ast.type_node, space);
1170 return renderExpression(r, type_node, space);
12081171 }
12091172 }
12101173
1211 if (var_decl.ast.align_node != 0) {
1212 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;
1174 if (var_decl.ast.align_node.unwrap()) |align_node| {
1175 const lparen = tree.firstToken(align_node) - 1;
12131176 const align_kw = lparen - 1;
1214 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;
1177 const rparen = tree.lastToken(align_node) + 1;
12151178 try renderToken(r, align_kw, Space.none); // align
12161179 try renderToken(r, lparen, Space.none); // (
1217 try renderExpression(r, var_decl.ast.align_node, Space.none);
1218 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
1219 var_decl.ast.init_node != 0)
1180 try renderExpression(r, align_node, Space.none);
1181 if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1182 var_decl.ast.init_node != .none)
12201183 {
12211184 try renderToken(r, rparen, .space); // )
12221185 } else {
......@@ -1224,14 +1187,14 @@ fn renderVarDeclWithoutFixups(
12241187 }
12251188 }
12261189
1227 if (var_decl.ast.addrspace_node != 0) {
1228 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;
1190 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
1191 const lparen = tree.firstToken(addrspace_node) - 1;
12291192 const addrspace_kw = lparen - 1;
1230 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;
1193 const rparen = tree.lastToken(addrspace_node) + 1;
12311194 try renderToken(r, addrspace_kw, Space.none); // addrspace
12321195 try renderToken(r, lparen, Space.none); // (
1233 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);
1234 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {
1196 try renderExpression(r, addrspace_node, Space.none);
1197 if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) {
12351198 try renderToken(r, rparen, .space); // )
12361199 } else {
12371200 try renderToken(r, rparen, .none); // )
......@@ -1239,27 +1202,27 @@ fn renderVarDeclWithoutFixups(
12391202 }
12401203 }
12411204
1242 if (var_decl.ast.section_node != 0) {
1243 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;
1205 if (var_decl.ast.section_node.unwrap()) |section_node| {
1206 const lparen = tree.firstToken(section_node) - 1;
12441207 const section_kw = lparen - 1;
1245 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;
1208 const rparen = tree.lastToken(section_node) + 1;
12461209 try renderToken(r, section_kw, Space.none); // linksection
12471210 try renderToken(r, lparen, Space.none); // (
1248 try renderExpression(r, var_decl.ast.section_node, Space.none);
1249 if (var_decl.ast.init_node != 0) {
1211 try renderExpression(r, section_node, Space.none);
1212 if (var_decl.ast.init_node != .none) {
12501213 try renderToken(r, rparen, .space); // )
12511214 } else {
12521215 return renderToken(r, rparen, space); // )
12531216 }
12541217 }
12551218
1256 assert(var_decl.ast.init_node != 0);
1219 const init_node = var_decl.ast.init_node.unwrap().?;
12571220
1258 const eq_token = tree.firstToken(var_decl.ast.init_node) - 1;
1221 const eq_token = tree.firstToken(init_node) - 1;
12591222 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
12601223 try ais.pushIndent(.after_equals);
12611224 try renderToken(r, eq_token, eq_space); // =
1262 try renderExpression(r, var_decl.ast.init_node, space); // ;
1225 try renderExpression(r, init_node, space); // ;
12631226 ais.popIndent();
12641227}
12651228
......@@ -1268,7 +1231,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
12681231 .ast = .{
12691232 .while_token = if_node.ast.if_token,
12701233 .cond_expr = if_node.ast.cond_expr,
1271 .cont_expr = 0,
1234 .cont_expr = .none,
12721235 .then_expr = if_node.ast.then_expr,
12731236 .else_expr = if_node.ast.else_expr,
12741237 },
......@@ -1284,7 +1247,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
12841247/// respective values set to null.
12851248fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
12861249 const tree = r.tree;
1287 const token_tags = tree.tokens.items(.tag);
12881250
12891251 if (while_node.label_token) |label| {
12901252 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
......@@ -1305,7 +1267,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
13051267 try renderToken(r, last_prefix_token, .space);
13061268 try renderToken(r, payload_token - 1, .none); // |
13071269 const ident = blk: {
1308 if (token_tags[payload_token] == .asterisk) {
1270 if (tree.tokenTag(payload_token) == .asterisk) {
13091271 try renderToken(r, payload_token, .none); // *
13101272 break :blk payload_token + 1;
13111273 } else {
......@@ -1314,7 +1276,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
13141276 };
13151277 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
13161278 const pipe = blk: {
1317 if (token_tags[ident + 1] == .comma) {
1279 if (tree.tokenTag(ident + 1) == .comma) {
13181280 try renderToken(r, ident + 1, .space); // ,
13191281 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
13201282 break :blk ident + 3;
......@@ -1325,13 +1287,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
13251287 last_prefix_token = pipe;
13261288 }
13271289
1328 if (while_node.ast.cont_expr != 0) {
1290 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
13291291 try renderToken(r, last_prefix_token, .space);
1330 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1292 const lparen = tree.firstToken(cont_expr) - 1;
13311293 try renderToken(r, lparen - 1, .space); // :
13321294 try renderToken(r, lparen, .none); // lparen
1333 try renderExpression(r, while_node.ast.cont_expr, .none);
1334 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen
1295 try renderExpression(r, cont_expr, .none);
1296 last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen
13351297 }
13361298
13371299 try renderThenElse(
......@@ -1349,15 +1311,14 @@ fn renderThenElse(
13491311 r: *Render,
13501312 last_prefix_token: Ast.TokenIndex,
13511313 then_expr: Ast.Node.Index,
1352 else_token: Ast.TokenIndex,
1314 else_token: ?Ast.TokenIndex,
13531315 maybe_error_token: ?Ast.TokenIndex,
1354 else_expr: Ast.Node.Index,
1316 opt_else_expr: Ast.Node.OptionalIndex,
13551317 space: Space,
13561318) Error!void {
13571319 const tree = r.tree;
13581320 const ais = r.ais;
1359 const node_tags = tree.nodes.items(.tag);
1360 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
1321 const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
13611322 const indent_then_expr = !then_expr_is_block and
13621323 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
13631324
......@@ -1373,7 +1334,7 @@ fn renderThenElse(
13731334 try renderToken(r, last_prefix_token, .space);
13741335 }
13751336
1376 if (else_expr != 0) {
1337 if (opt_else_expr.unwrap()) |else_expr| {
13771338 if (indent_then_expr) {
13781339 try renderExpression(r, then_expr, .newline);
13791340 } else {
......@@ -1382,18 +1343,18 @@ fn renderThenElse(
13821343
13831344 if (indent_then_expr) ais.popIndent();
13841345
1385 var last_else_token = else_token;
1346 var last_else_token = else_token.?;
13861347
13871348 if (maybe_error_token) |error_token| {
1388 try renderToken(r, else_token, .space); // else
1349 try renderToken(r, last_else_token, .space); // else
13891350 try renderToken(r, error_token - 1, .none); // |
13901351 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
13911352 last_else_token = error_token + 1; // |
13921353 }
13931354
13941355 const indent_else_expr = indent_then_expr and
1395 !nodeIsBlock(node_tags[else_expr]) and
1396 !nodeIsIfForWhileSwitch(node_tags[else_expr]);
1356 !nodeIsBlock(tree.nodeTag(else_expr)) and
1357 !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr));
13971358 if (indent_else_expr) {
13981359 try ais.pushIndent(.normal);
13991360 try renderToken(r, last_else_token, .newline);
......@@ -1430,21 +1391,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
14301391
14311392 var cur = for_node.payload_token;
14321393 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
1433 if (token_tags[pipe - 1] == .comma) {
1394 if (tree.tokenTag(@intCast(pipe - 1)) == .comma) {
14341395 try ais.pushIndent(.normal);
14351396 try renderToken(r, cur - 1, .newline); // |
14361397 while (true) {
1437 if (token_tags[cur] == .asterisk) {
1398 if (tree.tokenTag(cur) == .asterisk) {
14381399 try renderToken(r, cur, .none); // *
14391400 cur += 1;
14401401 }
14411402 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
14421403 cur += 1;
1443 if (token_tags[cur] == .comma) {
1404 if (tree.tokenTag(cur) == .comma) {
14441405 try renderToken(r, cur, .newline); // ,
14451406 cur += 1;
14461407 }
1447 if (token_tags[cur] == .pipe) {
1408 if (tree.tokenTag(cur) == .pipe) {
14481409 break;
14491410 }
14501411 }
......@@ -1452,17 +1413,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
14521413 } else {
14531414 try renderToken(r, cur - 1, .none); // |
14541415 while (true) {
1455 if (token_tags[cur] == .asterisk) {
1416 if (tree.tokenTag(cur) == .asterisk) {
14561417 try renderToken(r, cur, .none); // *
14571418 cur += 1;
14581419 }
14591420 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
14601421 cur += 1;
1461 if (token_tags[cur] == .comma) {
1422 if (tree.tokenTag(cur) == .comma) {
14621423 try renderToken(r, cur, .space); // ,
14631424 cur += 1;
14641425 }
1465 if (token_tags[cur] == .pipe) {
1426 if (tree.tokenTag(cur) == .pipe) {
14661427 break;
14671428 }
14681429 }
......@@ -1488,7 +1449,7 @@ fn renderContainerField(
14881449 const tree = r.tree;
14891450 const ais = r.ais;
14901451 var field = field_param;
1491 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);
1452 if (container != .tuple) field.convertToNonTupleLike(&tree);
14921453 const quote: QuoteBehavior = switch (container) {
14931454 .@"enum" => .eagerly_unquote_except_underscore,
14941455 .tuple, .other => .eagerly_unquote,
......@@ -1497,67 +1458,74 @@ fn renderContainerField(
14971458 if (field.comptime_token) |t| {
14981459 try renderToken(r, t, .space); // comptime
14991460 }
1500 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {
1501 if (field.ast.align_expr != 0) {
1461 if (field.ast.type_expr == .none and field.ast.value_expr == .none) {
1462 if (field.ast.align_expr.unwrap()) |align_expr| {
15021463 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1503 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1464 const lparen_token = tree.firstToken(align_expr) - 1;
15041465 const align_kw = lparen_token - 1;
1505 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1466 const rparen_token = tree.lastToken(align_expr) + 1;
15061467 try renderToken(r, align_kw, .none); // align
15071468 try renderToken(r, lparen_token, .none); // (
1508 try renderExpression(r, field.ast.align_expr, .none); // alignment
1469 try renderExpression(r, align_expr, .none); // alignment
15091470 return renderToken(r, rparen_token, .space); // )
15101471 }
15111472 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
15121473 }
1513 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {
1474 if (field.ast.type_expr != .none and field.ast.value_expr == .none) {
1475 const type_expr = field.ast.type_expr.unwrap().?;
15141476 if (!field.ast.tuple_like) {
15151477 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
15161478 try renderToken(r, field.ast.main_token + 1, .space); // :
15171479 }
15181480
1519 if (field.ast.align_expr != 0) {
1520 try renderExpression(r, field.ast.type_expr, .space); // type
1521 const align_token = tree.firstToken(field.ast.align_expr) - 2;
1481 if (field.ast.align_expr.unwrap()) |align_expr| {
1482 try renderExpression(r, type_expr, .space); // type
1483 const align_token = tree.firstToken(align_expr) - 2;
15221484 try renderToken(r, align_token, .none); // align
15231485 try renderToken(r, align_token + 1, .none); // (
1524 try renderExpression(r, field.ast.align_expr, .none); // alignment
1525 const rparen = tree.lastToken(field.ast.align_expr) + 1;
1486 try renderExpression(r, align_expr, .none); // alignment
1487 const rparen = tree.lastToken(align_expr) + 1;
15261488 return renderTokenComma(r, rparen, space); // )
15271489 } else {
1528 return renderExpressionComma(r, field.ast.type_expr, space); // type
1490 return renderExpressionComma(r, type_expr, space); // type
15291491 }
15301492 }
1531 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
1493 if (field.ast.type_expr == .none and field.ast.value_expr != .none) {
1494 const value_expr = field.ast.value_expr.unwrap().?;
1495
15321496 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1533 if (field.ast.align_expr != 0) {
1534 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1497 if (field.ast.align_expr.unwrap()) |align_expr| {
1498 const lparen_token = tree.firstToken(align_expr) - 1;
15351499 const align_kw = lparen_token - 1;
1536 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1500 const rparen_token = tree.lastToken(align_expr) + 1;
15371501 try renderToken(r, align_kw, .none); // align
15381502 try renderToken(r, lparen_token, .none); // (
1539 try renderExpression(r, field.ast.align_expr, .none); // alignment
1503 try renderExpression(r, align_expr, .none); // alignment
15401504 try renderToken(r, rparen_token, .space); // )
15411505 }
15421506 try renderToken(r, field.ast.main_token + 1, .space); // =
1543 return renderExpressionComma(r, field.ast.value_expr, space); // value
1507 return renderExpressionComma(r, value_expr, space); // value
15441508 }
15451509 if (!field.ast.tuple_like) {
15461510 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
15471511 try renderToken(r, field.ast.main_token + 1, .space); // :
15481512 }
1549 try renderExpression(r, field.ast.type_expr, .space); // type
15501513
1551 if (field.ast.align_expr != 0) {
1552 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1514 const type_expr = field.ast.type_expr.unwrap().?;
1515 const value_expr = field.ast.value_expr.unwrap().?;
1516
1517 try renderExpression(r, type_expr, .space); // type
1518
1519 if (field.ast.align_expr.unwrap()) |align_expr| {
1520 const lparen_token = tree.firstToken(align_expr) - 1;
15531521 const align_kw = lparen_token - 1;
1554 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1522 const rparen_token = tree.lastToken(align_expr) + 1;
15551523 try renderToken(r, align_kw, .none); // align
15561524 try renderToken(r, lparen_token, .none); // (
1557 try renderExpression(r, field.ast.align_expr, .none); // alignment
1525 try renderExpression(r, align_expr, .none); // alignment
15581526 try renderToken(r, rparen_token, .space); // )
15591527 }
1560 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
1528 const eq_token = tree.firstToken(value_expr) - 1;
15611529 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
15621530
15631531 try ais.pushIndent(.after_equals);
......@@ -1565,19 +1533,18 @@ fn renderContainerField(
15651533
15661534 if (eq_space == .space) {
15671535 ais.popIndent();
1568 try renderExpressionComma(r, field.ast.value_expr, space); // value
1536 try renderExpressionComma(r, value_expr, space); // value
15691537 return;
15701538 }
15711539
1572 const token_tags = tree.tokens.items(.tag);
1573 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
1540 const maybe_comma = tree.lastToken(value_expr) + 1;
15741541
1575 if (token_tags[maybe_comma] == .comma) {
1576 try renderExpression(r, field.ast.value_expr, .none); // value
1542 if (tree.tokenTag(maybe_comma) == .comma) {
1543 try renderExpression(r, value_expr, .none); // value
15771544 ais.popIndent();
15781545 try renderToken(r, maybe_comma, .newline);
15791546 } else {
1580 try renderExpression(r, field.ast.value_expr, space); // value
1547 try renderExpression(r, value_expr, space); // value
15811548 ais.popIndent();
15821549 }
15831550}
......@@ -1590,8 +1557,6 @@ fn renderBuiltinCall(
15901557) Error!void {
15911558 const tree = r.tree;
15921559 const ais = r.ais;
1593 const token_tags = tree.tokens.items(.tag);
1594 const main_tokens = tree.nodes.items(.main_token);
15951560
15961561 try renderToken(r, builtin_token, .none); // @name
15971562
......@@ -1604,8 +1569,8 @@ fn renderBuiltinCall(
16041569 const slice = tree.tokenSlice(builtin_token);
16051570 if (mem.eql(u8, slice, "@import")) f: {
16061571 const param = params[0];
1607 const str_lit_token = main_tokens[param];
1608 assert(token_tags[str_lit_token] == .string_literal);
1572 const str_lit_token = tree.nodeMainToken(param);
1573 assert(tree.tokenTag(str_lit_token) == .string_literal);
16091574 const token_bytes = tree.tokenSlice(str_lit_token);
16101575 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {
16111576 error.OutOfMemory => return error.OutOfMemory,
......@@ -1624,13 +1589,13 @@ fn renderBuiltinCall(
16241589 const last_param = params[params.len - 1];
16251590 const after_last_param_token = tree.lastToken(last_param) + 1;
16261591
1627 if (token_tags[after_last_param_token] != .comma) {
1592 if (tree.tokenTag(after_last_param_token) != .comma) {
16281593 // Render all on one line, no trailing comma.
16291594 try renderToken(r, builtin_token + 1, .none); // (
16301595
16311596 for (params, 0..) |param_node, i| {
16321597 const first_param_token = tree.firstToken(param_node);
1633 if (token_tags[first_param_token] == .multiline_string_literal_line or
1598 if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or
16341599 hasSameLineComment(tree, first_param_token - 1))
16351600 {
16361601 try ais.pushIndent(.normal);
......@@ -1665,11 +1630,9 @@ fn renderBuiltinCall(
16651630fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
16661631 const tree = r.tree;
16671632 const ais = r.ais;
1668 const token_tags = tree.tokens.items(.tag);
1669 const token_starts = tree.tokens.items(.start);
16701633
16711634 const after_fn_token = fn_proto.ast.fn_token + 1;
1672 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {
1635 const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: {
16731636 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
16741637 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
16751638 break :blk after_fn_token + 1;
......@@ -1677,41 +1640,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
16771640 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
16781641 break :blk fn_proto.ast.fn_token + 1;
16791642 };
1680 assert(token_tags[lparen] == .l_paren);
1643 assert(tree.tokenTag(lparen) == .l_paren);
16811644
1682 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1645 const return_type = fn_proto.ast.return_type.unwrap().?;
1646 const maybe_bang = tree.firstToken(return_type) - 1;
16831647 const rparen = blk: {
16841648 // These may appear in any order, so we have to check the token_starts array
16851649 // to find out which is first.
1686 var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang;
1687 var smallest_start = token_starts[maybe_bang];
1688 if (fn_proto.ast.align_expr != 0) {
1689 const tok = tree.firstToken(fn_proto.ast.align_expr) - 3;
1690 const start = token_starts[tok];
1650 var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang;
1651 var smallest_start = tree.tokenStart(maybe_bang);
1652 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1653 const tok = tree.firstToken(align_expr) - 3;
1654 const start = tree.tokenStart(tok);
16911655 if (start < smallest_start) {
16921656 rparen = tok;
16931657 smallest_start = start;
16941658 }
16951659 }
1696 if (fn_proto.ast.addrspace_expr != 0) {
1697 const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3;
1698 const start = token_starts[tok];
1660 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1661 const tok = tree.firstToken(addrspace_expr) - 3;
1662 const start = tree.tokenStart(tok);
16991663 if (start < smallest_start) {
17001664 rparen = tok;
17011665 smallest_start = start;
17021666 }
17031667 }
1704 if (fn_proto.ast.section_expr != 0) {
1705 const tok = tree.firstToken(fn_proto.ast.section_expr) - 3;
1706 const start = token_starts[tok];
1668 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1669 const tok = tree.firstToken(section_expr) - 3;
1670 const start = tree.tokenStart(tok);
17071671 if (start < smallest_start) {
17081672 rparen = tok;
17091673 smallest_start = start;
17101674 }
17111675 }
1712 if (fn_proto.ast.callconv_expr != 0) {
1713 const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3;
1714 const start = token_starts[tok];
1676 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1677 const tok = tree.firstToken(callconv_expr) - 3;
1678 const start = tree.tokenStart(tok);
17151679 if (start < smallest_start) {
17161680 rparen = tok;
17171681 smallest_start = start;
......@@ -1719,11 +1683,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17191683 }
17201684 break :blk rparen;
17211685 };
1722 assert(token_tags[rparen] == .r_paren);
1686 assert(tree.tokenTag(rparen) == .r_paren);
17231687
17241688 // The params list is a sparse set that does *not* include anytype or ... parameters.
17251689
1726 const trailing_comma = token_tags[rparen - 1] == .comma;
1690 const trailing_comma = tree.tokenTag(rparen - 1) == .comma;
17271691 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
17281692 // Render all on one line, no trailing comma.
17291693 try renderToken(r, lparen, .none); // (
......@@ -1732,7 +1696,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17321696 var last_param_token = lparen;
17331697 while (true) {
17341698 last_param_token += 1;
1735 switch (token_tags[last_param_token]) {
1699 switch (tree.tokenTag(last_param_token)) {
17361700 .doc_comment => {
17371701 try renderToken(r, last_param_token, .newline);
17381702 continue;
......@@ -1757,15 +1721,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17571721 },
17581722 else => {}, // Parameter type without a name.
17591723 }
1760 if (token_tags[last_param_token] == .identifier and
1761 token_tags[last_param_token + 1] == .colon)
1724 if (tree.tokenTag(last_param_token) == .identifier and
1725 tree.tokenTag(last_param_token + 1) == .colon)
17621726 {
17631727 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1764 last_param_token += 1;
1728 last_param_token = last_param_token + 1;
17651729 try renderToken(r, last_param_token, .space); // :
17661730 last_param_token += 1;
17671731 }
1768 if (token_tags[last_param_token] == .keyword_anytype) {
1732 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
17691733 try renderToken(r, last_param_token, .none); // anytype
17701734 continue;
17711735 }
......@@ -1783,7 +1747,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17831747 var last_param_token = lparen;
17841748 while (true) {
17851749 last_param_token += 1;
1786 switch (token_tags[last_param_token]) {
1750 switch (tree.tokenTag(last_param_token)) {
17871751 .doc_comment => {
17881752 try renderToken(r, last_param_token, .newline);
17891753 continue;
......@@ -1799,24 +1763,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17991763 .identifier => {},
18001764 .keyword_anytype => {
18011765 try renderToken(r, last_param_token, .comma); // anytype
1802 if (token_tags[last_param_token + 1] == .comma)
1766 if (tree.tokenTag(last_param_token + 1) == .comma)
18031767 last_param_token += 1;
18041768 continue;
18051769 },
18061770 .r_paren => break,
18071771 else => {}, // Parameter type without a name.
18081772 }
1809 if (token_tags[last_param_token] == .identifier and
1810 token_tags[last_param_token + 1] == .colon)
1773 if (tree.tokenTag(last_param_token) == .identifier and
1774 tree.tokenTag(last_param_token + 1) == .colon)
18111775 {
18121776 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
18131777 last_param_token += 1;
18141778 try renderToken(r, last_param_token, .space); // :
18151779 last_param_token += 1;
18161780 }
1817 if (token_tags[last_param_token] == .keyword_anytype) {
1781 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
18181782 try renderToken(r, last_param_token, .comma); // anytype
1819 if (token_tags[last_param_token + 1] == .comma)
1783 if (tree.tokenTag(last_param_token + 1) == .comma)
18201784 last_param_token += 1;
18211785 continue;
18221786 }
......@@ -1826,60 +1790,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
18261790 try renderExpression(r, param, .comma);
18271791 ais.popSpace();
18281792 last_param_token = tree.lastToken(param);
1829 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;
1793 if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1;
18301794 }
18311795 ais.popIndent();
18321796 }
18331797
18341798 try renderToken(r, rparen, .space); // )
18351799
1836 if (fn_proto.ast.align_expr != 0) {
1837 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;
1838 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;
1800 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1801 const align_lparen = tree.firstToken(align_expr) - 1;
1802 const align_rparen = tree.lastToken(align_expr) + 1;
18391803
18401804 try renderToken(r, align_lparen - 1, .none); // align
18411805 try renderToken(r, align_lparen, .none); // (
1842 try renderExpression(r, fn_proto.ast.align_expr, .none);
1806 try renderExpression(r, align_expr, .none);
18431807 try renderToken(r, align_rparen, .space); // )
18441808 }
18451809
1846 if (fn_proto.ast.addrspace_expr != 0) {
1847 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;
1848 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;
1810 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1811 const align_lparen = tree.firstToken(addrspace_expr) - 1;
1812 const align_rparen = tree.lastToken(addrspace_expr) + 1;
18491813
18501814 try renderToken(r, align_lparen - 1, .none); // addrspace
18511815 try renderToken(r, align_lparen, .none); // (
1852 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);
1816 try renderExpression(r, addrspace_expr, .none);
18531817 try renderToken(r, align_rparen, .space); // )
18541818 }
18551819
1856 if (fn_proto.ast.section_expr != 0) {
1857 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;
1858 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;
1820 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1821 const section_lparen = tree.firstToken(section_expr) - 1;
1822 const section_rparen = tree.lastToken(section_expr) + 1;
18591823
18601824 try renderToken(r, section_lparen - 1, .none); // section
18611825 try renderToken(r, section_lparen, .none); // (
1862 try renderExpression(r, fn_proto.ast.section_expr, .none);
1826 try renderExpression(r, section_expr, .none);
18631827 try renderToken(r, section_rparen, .space); // )
18641828 }
18651829
1866 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1867 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));
1868 const is_declaration = fn_proto.name_token != null;
1869 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {
1870 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;
1871 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;
1830 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1831 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1832 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)));
1833 const is_declaration = fn_proto.name_token != null;
1834 if (!(is_declaration and is_callconv_inline)) {
1835 const callconv_lparen = tree.firstToken(callconv_expr) - 1;
1836 const callconv_rparen = tree.lastToken(callconv_expr) + 1;
18721837
1873 try renderToken(r, callconv_lparen - 1, .none); // callconv
1874 try renderToken(r, callconv_lparen, .none); // (
1875 try renderExpression(r, fn_proto.ast.callconv_expr, .none);
1876 try renderToken(r, callconv_rparen, .space); // )
1838 try renderToken(r, callconv_lparen - 1, .none); // callconv
1839 try renderToken(r, callconv_lparen, .none); // (
1840 try renderExpression(r, callconv_expr, .none);
1841 try renderToken(r, callconv_rparen, .space); // )
1842 }
18771843 }
18781844
1879 if (token_tags[maybe_bang] == .bang) {
1845 if (tree.tokenTag(maybe_bang) == .bang) {
18801846 try renderToken(r, maybe_bang, .none); // !
18811847 }
1882 return renderExpression(r, fn_proto.ast.return_type, space);
1848 return renderExpression(r, return_type, space);
18831849}
18841850
18851851fn renderSwitchCase(
......@@ -1889,9 +1855,7 @@ fn renderSwitchCase(
18891855) Error!void {
18901856 const ais = r.ais;
18911857 const tree = r.tree;
1892 const node_tags = tree.nodes.items(.tag);
1893 const token_tags = tree.tokens.items(.tag);
1894 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
1858 const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
18951859 const has_comment_before_arrow = blk: {
18961860 if (switch_case.ast.values.len == 0) break :blk false;
18971861 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);
......@@ -1918,7 +1882,7 @@ fn renderSwitchCase(
19181882 }
19191883
19201884 // Render the arrow and everything after it
1921 const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal)
1885 const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal)
19221886 // Newline gets inserted when rendering the target expr.
19231887 Space.none
19241888 else
......@@ -1928,12 +1892,12 @@ fn renderSwitchCase(
19281892
19291893 if (switch_case.payload_token) |payload_token| {
19301894 try renderToken(r, payload_token - 1, .none); // pipe
1931 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);
1932 if (token_tags[payload_token] == .asterisk) {
1895 const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk);
1896 if (tree.tokenTag(payload_token) == .asterisk) {
19331897 try renderToken(r, payload_token, .none); // asterisk
19341898 }
19351899 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1936 if (token_tags[ident + 1] == .comma) {
1900 if (tree.tokenTag(ident + 1) == .comma) {
19371901 try renderToken(r, ident + 1, .space); // ,
19381902 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
19391903 try renderToken(r, ident + 3, pre_target_space); // pipe
......@@ -1953,12 +1917,9 @@ fn renderBlock(
19531917) Error!void {
19541918 const tree = r.tree;
19551919 const ais = r.ais;
1956 const token_tags = tree.tokens.items(.tag);
1957 const lbrace = tree.nodes.items(.main_token)[block_node];
1920 const lbrace = tree.nodeMainToken(block_node);
19581921
1959 if (token_tags[lbrace - 1] == .colon and
1960 token_tags[lbrace - 2] == .identifier)
1961 {
1922 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
19621923 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
19631924 try renderToken(r, lbrace - 1, .space); // :
19641925 }
......@@ -1980,13 +1941,12 @@ fn finishRenderBlock(
19801941 space: Space,
19811942) Error!void {
19821943 const tree = r.tree;
1983 const node_tags = tree.nodes.items(.tag);
19841944 const ais = r.ais;
19851945 for (statements, 0..) |stmt, i| {
19861946 if (i != 0) try renderExtraNewline(r, stmt);
19871947 if (r.fixups.omit_nodes.contains(stmt)) continue;
19881948 try ais.pushSpace(.semicolon);
1989 switch (node_tags[stmt]) {
1949 switch (tree.nodeTag(stmt)) {
19901950 .global_var_decl,
19911951 .local_var_decl,
19921952 .simple_var_decl,
......@@ -2010,12 +1970,13 @@ fn renderStructInit(
20101970) Error!void {
20111971 const tree = r.tree;
20121972 const ais = r.ais;
2013 const token_tags = tree.tokens.items(.tag);
2014 if (struct_init.ast.type_expr == 0) {
2015 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
1973
1974 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
1975 try renderExpression(r, type_expr, .none); // T
20161976 } else {
2017 try renderExpression(r, struct_init.ast.type_expr, .none); // T
1977 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
20181978 }
1979
20191980 if (struct_init.ast.fields.len == 0) {
20201981 try ais.pushIndent(.normal);
20211982 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
......@@ -2024,7 +1985,7 @@ fn renderStructInit(
20241985 }
20251986
20261987 const rbrace = tree.lastToken(struct_node);
2027 const trailing_comma = token_tags[rbrace - 1] == .comma;
1988 const trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
20281989 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
20291990 // Render one field init per line.
20301991 try ais.pushIndent(.normal);
......@@ -2034,9 +1995,8 @@ fn renderStructInit(
20341995 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
20351996 // Don't output a space after the = if expression is a multiline string,
20361997 // since then it will start on the next line.
2037 const nodes = tree.nodes.items(.tag);
20381998 const field_node = struct_init.ast.fields[0];
2039 const expr = nodes[field_node];
1999 const expr = tree.nodeTag(field_node);
20402000 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
20412001 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
20422002
......@@ -2049,7 +2009,7 @@ fn renderStructInit(
20492009 try renderExtraNewlineToken(r, init_token - 3);
20502010 try renderToken(r, init_token - 3, .none); // .
20512011 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
2052 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;
2012 space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
20532013 try renderToken(r, init_token - 1, space_after_equal); // =
20542014
20552015 try ais.pushSpace(.comma);
......@@ -2082,12 +2042,11 @@ fn renderArrayInit(
20822042 const tree = r.tree;
20832043 const ais = r.ais;
20842044 const gpa = r.gpa;
2085 const token_tags = tree.tokens.items(.tag);
20862045
2087 if (array_init.ast.type_expr == 0) {
2088 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
2046 if (array_init.ast.type_expr.unwrap()) |type_expr| {
2047 try renderExpression(r, type_expr, .none); // T
20892048 } else {
2090 try renderExpression(r, array_init.ast.type_expr, .none); // T
2049 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
20912050 }
20922051
20932052 if (array_init.ast.elements.len == 0) {
......@@ -2099,14 +2058,14 @@ fn renderArrayInit(
20992058
21002059 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
21012060 const last_elem_token = tree.lastToken(last_elem);
2102 const trailing_comma = token_tags[last_elem_token + 1] == .comma;
2061 const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma;
21032062 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;
2104 assert(token_tags[rbrace] == .r_brace);
2063 assert(tree.tokenTag(rbrace) == .r_brace);
21052064
21062065 if (array_init.ast.elements.len == 1) {
21072066 const only_elem = array_init.ast.elements[0];
21082067 const first_token = tree.firstToken(only_elem);
2109 if (token_tags[first_token] != .multiline_string_literal_line and
2068 if (tree.tokenTag(first_token) != .multiline_string_literal_line and
21102069 !anythingBetween(tree, last_elem_token, rbrace))
21112070 {
21122071 try renderToken(r, array_init.ast.lbrace, .none);
......@@ -2169,7 +2128,7 @@ fn renderArrayInit(
21692128 }
21702129
21712130 const maybe_comma = expr_last_token + 1;
2172 if (token_tags[maybe_comma] == .comma) {
2131 if (tree.tokenTag(maybe_comma) == .comma) {
21732132 if (hasSameLineComment(tree, maybe_comma))
21742133 break :sec_end i - this_line_size + 1;
21752134 }
......@@ -2309,13 +2268,12 @@ fn renderContainerDecl(
23092268) Error!void {
23102269 const tree = r.tree;
23112270 const ais = r.ais;
2312 const token_tags = tree.tokens.items(.tag);
23132271
23142272 if (container_decl.layout_token) |layout_token| {
23152273 try renderToken(r, layout_token, .space);
23162274 }
23172275
2318 const container: Container = switch (token_tags[container_decl.ast.main_token]) {
2276 const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) {
23192277 .keyword_enum => .@"enum",
23202278 .keyword_struct => for (container_decl.ast.members) |member| {
23212279 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
......@@ -2328,10 +2286,10 @@ fn renderContainerDecl(
23282286 try renderToken(r, container_decl.ast.main_token, .none); // union
23292287 try renderToken(r, enum_token - 1, .none); // lparen
23302288 try renderToken(r, enum_token, .none); // enum
2331 if (container_decl.ast.arg != 0) {
2289 if (container_decl.ast.arg.unwrap()) |arg| {
23322290 try renderToken(r, enum_token + 1, .none); // lparen
2333 try renderExpression(r, container_decl.ast.arg, .none);
2334 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2291 try renderExpression(r, arg, .none);
2292 const rparen = tree.lastToken(arg) + 1;
23352293 try renderToken(r, rparen, .none); // rparen
23362294 try renderToken(r, rparen + 1, .space); // rparen
23372295 lbrace = rparen + 2;
......@@ -2339,11 +2297,11 @@ fn renderContainerDecl(
23392297 try renderToken(r, enum_token + 1, .space); // rparen
23402298 lbrace = enum_token + 2;
23412299 }
2342 } else if (container_decl.ast.arg != 0) {
2300 } else if (container_decl.ast.arg.unwrap()) |arg| {
23432301 try renderToken(r, container_decl.ast.main_token, .none); // union
23442302 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2345 try renderExpression(r, container_decl.ast.arg, .none);
2346 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2303 try renderExpression(r, arg, .none);
2304 const rparen = tree.lastToken(arg) + 1;
23472305 try renderToken(r, rparen, .space); // rparen
23482306 lbrace = rparen + 1;
23492307 } else {
......@@ -2352,9 +2310,10 @@ fn renderContainerDecl(
23522310 }
23532311
23542312 const rbrace = tree.lastToken(container_decl_node);
2313
23552314 if (container_decl.ast.members.len == 0) {
23562315 try ais.pushIndent(.normal);
2357 if (token_tags[lbrace + 1] == .container_doc_comment) {
2316 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
23582317 try renderToken(r, lbrace, .newline); // lbrace
23592318 try renderContainerDocComments(r, lbrace + 1);
23602319 } else {
......@@ -2364,7 +2323,7 @@ fn renderContainerDecl(
23642323 return renderToken(r, rbrace, space); // rbrace
23652324 }
23662325
2367 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;
2326 const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
23682327 if (!src_has_trailing_comma) one_line: {
23692328 // We print all the members in-line unless one of the following conditions are true:
23702329
......@@ -2374,10 +2333,10 @@ fn renderContainerDecl(
23742333 }
23752334
23762335 // 2. The container has a container comment.
2377 if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line;
2336 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line;
23782337
23792338 // 3. A member of the container has a doc comment.
2380 for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| {
2339 for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| {
23812340 if (tag == .doc_comment) break :one_line;
23822341 }
23832342
......@@ -2397,12 +2356,12 @@ fn renderContainerDecl(
23972356 // One member per line.
23982357 try ais.pushIndent(.normal);
23992358 try renderToken(r, lbrace, .newline); // lbrace
2400 if (token_tags[lbrace + 1] == .container_doc_comment) {
2359 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
24012360 try renderContainerDocComments(r, lbrace + 1);
24022361 }
24032362 for (container_decl.ast.members, 0..) |member, i| {
24042363 if (i != 0) try renderExtraNewline(r, member);
2405 switch (tree.nodes.items(.tag)[member]) {
2364 switch (tree.nodeTag(member)) {
24062365 // For container fields, ensure a trailing comma is added if necessary.
24072366 .container_field_init,
24082367 .container_field_align,
......@@ -2428,7 +2387,6 @@ fn renderAsm(
24282387) Error!void {
24292388 const tree = r.tree;
24302389 const ais = r.ais;
2431 const token_tags = tree.tokens.items(.tag);
24322390
24332391 try renderToken(r, asm_node.ast.asm_token, .space); // asm
24342392
......@@ -2454,13 +2412,13 @@ fn renderAsm(
24542412 while (true) : (tok_i += 1) {
24552413 try renderToken(r, tok_i, .none);
24562414 tok_i += 1;
2457 switch (token_tags[tok_i]) {
2415 switch (tree.tokenTag(tok_i)) {
24582416 .r_paren => {
24592417 ais.popIndent();
24602418 return renderToken(r, tok_i, space);
24612419 },
24622420 .comma => {
2463 if (token_tags[tok_i + 1] == .r_paren) {
2421 if (tree.tokenTag(tok_i + 1) == .r_paren) {
24642422 ais.popIndent();
24652423 return renderToken(r, tok_i + 1, space);
24662424 } else {
......@@ -2512,7 +2470,7 @@ fn renderAsm(
25122470 ais.popSpace();
25132471 const comma_or_colon = tree.lastToken(asm_output) + 1;
25142472 ais.popIndent();
2515 break :colon2 switch (token_tags[comma_or_colon]) {
2473 break :colon2 switch (tree.tokenTag(comma_or_colon)) {
25162474 .comma => comma_or_colon + 1,
25172475 else => comma_or_colon,
25182476 };
......@@ -2548,7 +2506,7 @@ fn renderAsm(
25482506 ais.popSpace();
25492507 const comma_or_colon = tree.lastToken(asm_input) + 1;
25502508 ais.popIndent();
2551 break :colon3 switch (token_tags[comma_or_colon]) {
2509 break :colon3 switch (tree.tokenTag(comma_or_colon)) {
25522510 .comma => comma_or_colon + 1,
25532511 else => comma_or_colon,
25542512 };
......@@ -2561,7 +2519,7 @@ fn renderAsm(
25612519 const first_clobber = asm_node.first_clobber.?;
25622520 var tok_i = first_clobber;
25632521 while (true) {
2564 switch (token_tags[tok_i + 1]) {
2522 switch (tree.tokenTag(tok_i + 1)) {
25652523 .r_paren => {
25662524 ais.setIndentDelta(indent_delta);
25672525 try renderToken(r, tok_i, .newline);
......@@ -2569,7 +2527,7 @@ fn renderAsm(
25692527 return renderToken(r, tok_i + 1, space);
25702528 },
25712529 .comma => {
2572 switch (token_tags[tok_i + 2]) {
2530 switch (tree.tokenTag(tok_i + 2)) {
25732531 .r_paren => {
25742532 ais.setIndentDelta(indent_delta);
25752533 try renderToken(r, tok_i, .newline);
......@@ -2608,7 +2566,6 @@ fn renderParamList(
26082566) Error!void {
26092567 const tree = r.tree;
26102568 const ais = r.ais;
2611 const token_tags = tree.tokens.items(.tag);
26122569
26132570 if (params.len == 0) {
26142571 try ais.pushIndent(.normal);
......@@ -2619,7 +2576,7 @@ fn renderParamList(
26192576
26202577 const last_param = params[params.len - 1];
26212578 const after_last_param_tok = tree.lastToken(last_param) + 1;
2622 if (token_tags[after_last_param_tok] == .comma) {
2579 if (tree.tokenTag(after_last_param_tok) == .comma) {
26232580 try ais.pushIndent(.normal);
26242581 try renderToken(r, lparen, .newline); // (
26252582 for (params, 0..) |param_node, i| {
......@@ -2648,7 +2605,7 @@ fn renderParamList(
26482605 if (i + 1 < params.len) {
26492606 const comma = tree.lastToken(param_node) + 1;
26502607 const next_multiline_string =
2651 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;
2608 tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line;
26522609 const comma_space: Space = if (next_multiline_string) .none else .space;
26532610 try renderToken(r, comma, comma_space);
26542611 }
......@@ -2661,9 +2618,8 @@ fn renderParamList(
26612618/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26622619fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
26632620 const tree = r.tree;
2664 const token_tags = tree.tokens.items(.tag);
26652621 const maybe_comma = tree.lastToken(node) + 1;
2666 if (token_tags[maybe_comma] == .comma and space != .comma) {
2622 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26672623 try renderExpression(r, node, .none);
26682624 return renderToken(r, maybe_comma, space);
26692625 } else {
......@@ -2675,9 +2631,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v
26752631/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26762632fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
26772633 const tree = r.tree;
2678 const token_tags = tree.tokens.items(.tag);
26792634 const maybe_comma = token + 1;
2680 if (token_tags[maybe_comma] == .comma and space != .comma) {
2635 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26812636 try renderToken(r, token, .none);
26822637 return renderToken(r, maybe_comma, space);
26832638 } else {
......@@ -2689,9 +2644,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void
26892644/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26902645fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
26912646 const tree = r.tree;
2692 const token_tags = tree.tokens.items(.tag);
26932647 const maybe_comma = token + 1;
2694 if (token_tags[maybe_comma] == .comma and space != .comma) {
2648 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26952649 try renderIdentifier(r, token, .none, quote);
26962650 return renderToken(r, maybe_comma, space);
26972651 } else {
......@@ -2741,37 +2695,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
27412695fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
27422696 const tree = r.tree;
27432697 const ais = r.ais;
2744 const token_tags = tree.tokens.items(.tag);
2745 const token_starts = tree.tokens.items(.start);
27462698
2747 const token_start = token_starts[token_index];
2699 const next_token_tag = tree.tokenTag(token_index + 1);
27482700
27492701 if (space == .skip) return;
27502702
2751 if (space == .comma and token_tags[token_index + 1] != .comma) {
2703 if (space == .comma and next_token_tag != .comma) {
27522704 try ais.writer().writeByte(',');
27532705 }
27542706 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
27552707 defer ais.disableSpaceMode();
2756 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);
2708 const comment = try renderComments(
2709 r,
2710 tree.tokenStart(token_index) + lexeme_len,
2711 tree.tokenStart(token_index + 1),
2712 );
27572713 switch (space) {
27582714 .none => {},
27592715 .space => if (!comment) try ais.writer().writeByte(' '),
27602716 .newline => if (!comment) try ais.insertNewline(),
27612717
2762 .comma => if (token_tags[token_index + 1] == .comma) {
2718 .comma => if (next_token_tag == .comma) {
27632719 try renderToken(r, token_index + 1, .newline);
27642720 } else if (!comment) {
27652721 try ais.insertNewline();
27662722 },
27672723
2768 .comma_space => if (token_tags[token_index + 1] == .comma) {
2724 .comma_space => if (next_token_tag == .comma) {
27692725 try renderToken(r, token_index + 1, .space);
27702726 } else if (!comment) {
27712727 try ais.writer().writeByte(' ');
27722728 },
27732729
2774 .semicolon => if (token_tags[token_index + 1] == .semicolon) {
2730 .semicolon => if (next_token_tag == .semicolon) {
27752731 try renderToken(r, token_index + 1, .newline);
27762732 } else if (!comment) {
27772733 try ais.insertNewline();
......@@ -2802,8 +2758,7 @@ const QuoteBehavior = enum {
28022758
28032759fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
28042760 const tree = r.tree;
2805 const token_tags = tree.tokens.items(.tag);
2806 assert(token_tags[token_index] == .identifier);
2761 assert(tree.tokenTag(token_index) == .identifier);
28072762 const lexeme = tokenSliceForRender(tree, token_index);
28082763
28092764 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
......@@ -2912,8 +2867,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote
29122867fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
29132868 const tree = r.tree;
29142869 const ais = r.ais;
2915 const token_tags = tree.tokens.items(.tag);
2916 assert(token_tags[token_index] == .identifier);
2870 assert(tree.tokenTag(token_index) == .identifier);
29172871 const lexeme = tokenSliceForRender(tree, token_index);
29182872 assert(lexeme.len >= 3 and lexeme[0] == '@');
29192873
......@@ -2966,12 +2920,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
29662920/// fn_proto should be wrapped and have a trailing comma inserted even if
29672921/// there is none in the source.
29682922fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2969 const token_starts = tree.tokens.items(.start);
2970
2971 var i = start_token;
2972 while (i < end_token) : (i += 1) {
2973 const start = token_starts[i] + tree.tokenSlice(i).len;
2974 const end = token_starts[i + 1];
2923 for (start_token..end_token) |i| {
2924 const token: Ast.TokenIndex = @intCast(i);
2925 const start = tree.tokenStart(token) + tree.tokenSlice(token).len;
2926 const end = tree.tokenStart(token + 1);
29752927 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;
29762928 }
29772929
......@@ -2981,16 +2933,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)
29812933/// Returns true if there exists a multiline string literal between the start
29822934/// of token `start_token` and the start of token `end_token`.
29832935fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2984 const token_tags = tree.tokens.items(.tag);
2985
2986 for (token_tags[start_token..end_token]) |tag| {
2987 switch (tag) {
2988 .multiline_string_literal_line => return true,
2989 else => continue,
2990 }
2991 }
2992
2993 return false;
2936 return std.mem.indexOfScalar(
2937 Token.Tag,
2938 tree.tokens.items(.tag)[start_token..end_token],
2939 .multiline_string_literal_line,
2940 ) != null;
29942941}
29952942
29962943/// Assumes that start is the first byte past the previous token and
......@@ -3066,18 +3013,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
30663013fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
30673014 const tree = r.tree;
30683015 const ais = r.ais;
3069 const token_starts = tree.tokens.items(.start);
3070 const token_start = token_starts[token_index];
3016 const token_start = tree.tokenStart(token_index);
30713017 if (token_start == 0) return;
30723018 const prev_token_end = if (token_index == 0)
30733019 0
30743020 else
3075 token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len;
3021 tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len;
30763022
30773023 // If there is a immediately preceding comment or doc_comment,
30783024 // skip it because required extra newline has already been rendered.
30793025 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;
3080 if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return;
3026 if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return;
30813027
30823028 // Iterate backwards to the end of the previous token, stopping if a
30833029 // non-whitespace character is encountered or two newlines have been found.
......@@ -3095,10 +3041,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
30953041fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
30963042 const tree = r.tree;
30973043 // Search backwards for the first doc comment.
3098 const token_tags = tree.tokens.items(.tag);
30993044 if (end_token == 0) return;
31003045 var tok = end_token - 1;
3101 while (token_tags[tok] == .doc_comment) {
3046 while (tree.tokenTag(tok) == .doc_comment) {
31023047 if (tok == 0) break;
31033048 tok -= 1;
31043049 } else {
......@@ -3108,7 +3053,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
31083053 if (first_tok == end_token) return;
31093054
31103055 if (first_tok != 0) {
3111 const prev_token_tag = token_tags[first_tok - 1];
3056 const prev_token_tag = tree.tokenTag(first_tok - 1);
31123057
31133058 // Prevent accidental use of `renderDocComments` for a function argument doc comment
31143059 assert(prev_token_tag != .l_paren);
......@@ -3118,7 +3063,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
31183063 }
31193064 }
31203065
3121 while (token_tags[tok] == .doc_comment) : (tok += 1) {
3066 while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) {
31223067 try renderToken(r, tok, .newline);
31233068 }
31243069}
......@@ -3126,15 +3071,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
31263071/// start_token is first container doc comment token.
31273072fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
31283073 const tree = r.tree;
3129 const token_tags = tree.tokens.items(.tag);
31303074 var tok = start_token;
3131 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {
3075 while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
31323076 try renderToken(r, tok, .newline);
31333077 }
31343078 // Render extra newline if there is one between final container doc comment and
31353079 // the next token. If the next token is a doc comment, that code path
31363080 // will have its own logic to insert a newline.
3137 if (token_tags[tok] != .doc_comment) {
3081 if (tree.tokenTag(tok) != .doc_comment) {
31383082 try renderExtraNewlineToken(r, tok);
31393083 }
31403084}
......@@ -3144,11 +3088,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31443088 const ais = r.ais;
31453089 var buf: [1]Ast.Node.Index = undefined;
31463090 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;
3147 const token_tags = tree.tokens.items(.tag);
31483091 var it = fn_proto.iterate(tree);
31493092 while (it.next()) |param| {
31503093 const name_ident = param.name_token.?;
3151 assert(token_tags[name_ident] == .identifier);
3094 assert(tree.tokenTag(name_ident) == .identifier);
31523095 const w = ais.writer();
31533096 try w.writeAll("_ = ");
31543097 try w.writeAll(tokenSliceForRender(r.tree, name_ident));
......@@ -3158,7 +3101,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31583101
31593102fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
31603103 var ret = tree.tokenSlice(token_index);
3161 switch (tree.tokens.items(.tag)[token_index]) {
3104 switch (tree.tokenTag(token_index)) {
31623105 .container_doc_comment, .doc_comment => {
31633106 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);
31643107 },
......@@ -3168,8 +3111,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
31683111}
31693112
31703113fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3171 const token_starts = tree.tokens.items(.start);
3172 const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]];
3114 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
31733115 for (between_source) |byte| switch (byte) {
31743116 '\n' => return false,
31753117 '/' => return true,
......@@ -3182,8 +3124,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
31823124/// start_token and end_token.
31833125fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
31843126 if (start_token + 1 != end_token) return true;
3185 const token_starts = tree.tokens.items(.start);
3186 const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]];
3127 const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)];
31873128 for (between_source) |byte| switch (byte) {
31883129 '/' => return true,
31893130 else => continue,
......@@ -3277,12 +3218,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {
32773218
32783219// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.
32793220fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {
3280 const token_tags = tree.tokens.items(.tag);
3281
32823221 const first_token = tree.firstToken(exprs[0]);
32833222 if (tree.tokensOnSameLine(first_token, rtoken)) {
32843223 const maybe_comma = rtoken - 1;
3285 if (token_tags[maybe_comma] == .comma)
3224 if (tree.tokenTag(maybe_comma) == .comma)
32863225 return 1;
32873226 return exprs.len; // no newlines
32883227 }
lib/std/zon/parse.zig+11-17
......@@ -196,16 +196,15 @@ pub const Error = union(enum) {
196196 return .{ .err = self, .status = status };
197197 }
198198
199 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.TokenIndex, node_or_offset: u32) Ast.Location {
200 if (maybe_token == Zoir.CompileError.invalid_token) {
201 const main_tokens = ast.nodes.items(.main_token);
202 const ast_node = node_or_offset;
203 const token = main_tokens[ast_node];
204 return ast.tokenLocation(0, token);
205 } else {
206 var location = ast.tokenLocation(0, maybe_token);
199 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location {
200 if (maybe_token.unwrap()) |token| {
201 var location = ast.tokenLocation(0, token);
207202 location.column += node_or_offset;
208203 return location;
204 } else {
205 const ast_node: Ast.Node.Index = @enumFromInt(node_or_offset);
206 const token = ast.nodeMainToken(ast_node);
207 return ast.tokenLocation(0, token);
209208 }
210209 }
211210};
......@@ -632,7 +631,7 @@ const Parser = struct {
632631 switch (try ZonGen.parseStrLit(self.ast, ast_node, buf.writer(self.gpa))) {
633632 .success => {},
634633 .failure => |err| {
635 const token = self.ast.nodes.items(.main_token)[ast_node];
634 const token = self.ast.nodeMainToken(ast_node);
636635 const raw_string = self.ast.tokenSlice(token);
637636 return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)});
638637 },
......@@ -1005,8 +1004,7 @@ const Parser = struct {
10051004 args: anytype,
10061005 ) error{ OutOfMemory, ParseZon } {
10071006 @branchHint(.cold);
1008 const main_tokens = self.ast.nodes.items(.main_token);
1009 const token = main_tokens[node.getAstNode(self.zoir)];
1007 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
10101008 return self.failTokenFmt(token, 0, fmt, args);
10111009 }
10121010
......@@ -1025,8 +1023,7 @@ const Parser = struct {
10251023 message: []const u8,
10261024 ) error{ParseZon} {
10271025 @branchHint(.cold);
1028 const main_tokens = self.ast.nodes.items(.main_token);
1029 const token = main_tokens[node.getAstNode(self.zoir)];
1026 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
10301027 return self.failToken(.{
10311028 .token = token,
10321029 .offset = 0,
......@@ -1059,10 +1056,7 @@ const Parser = struct {
10591056 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
10601057 const field_node = struct_init.ast.fields[f];
10611058 break :b self.ast.firstToken(field_node) - 2;
1062 } else b: {
1063 const main_tokens = self.ast.nodes.items(.main_token);
1064 break :b main_tokens[node.getAstNode(self.zoir)];
1065 };
1059 } else self.ast.nodeMainToken(node.getAstNode(self.zoir));
10661060 switch (@typeInfo(T)) {
10671061 inline .@"struct", .@"union", .@"enum" => |info| {
10681062 const note: Error.TypeCheckFailure.Note = if (info.fields.len == 0) b: {
src/Package/Fetch.zig+10-10
......@@ -30,7 +30,7 @@
3030arena: std.heap.ArenaAllocator,
3131location: Location,
3232location_tok: std.zig.Ast.TokenIndex,
33hash_tok: std.zig.Ast.TokenIndex,
33hash_tok: std.zig.Ast.OptionalTokenIndex,
3434name_tok: std.zig.Ast.TokenIndex,
3535lazy_status: LazyStatus,
3636parent_package_root: Cache.Path,
......@@ -317,8 +317,8 @@ pub fn run(f: *Fetch) RunError!void {
317317 f.location_tok,
318318 try eb.addString("expected path relative to build root; found absolute path"),
319319 );
320 if (f.hash_tok != 0) return f.fail(
321 f.hash_tok,
320 if (f.hash_tok.unwrap()) |hash_tok| return f.fail(
321 hash_tok,
322322 try eb.addString("path-based dependencies are not hashed"),
323323 );
324324 // Packages fetched by URL may not use relative paths to escape outside the
......@@ -555,17 +555,18 @@ fn runResource(
555555 // job is done.
556556
557557 if (remote_hash) |declared_hash| {
558 const hash_tok = f.hash_tok.unwrap().?;
558559 if (declared_hash.isOld()) {
559560 const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest);
560561 if (!std.mem.eql(u8, declared_hash.toSlice(), &actual_hex)) {
561 return f.fail(f.hash_tok, try eb.printString(
562 return f.fail(hash_tok, try eb.printString(
562563 "hash mismatch: manifest declares {s} but the fetched package has {s}",
563564 .{ declared_hash.toSlice(), actual_hex },
564565 ));
565566 }
566567 } else {
567568 if (!computed_package_hash.eql(&declared_hash)) {
568 return f.fail(f.hash_tok, try eb.printString(
569 return f.fail(hash_tok, try eb.printString(
569570 "hash mismatch: manifest declares {s} but the fetched package has {s}",
570571 .{ declared_hash.toSlice(), computed_package_hash.toSlice() },
571572 ));
......@@ -813,15 +814,14 @@ fn srcLoc(
813814) Allocator.Error!ErrorBundle.SourceLocationIndex {
814815 const ast = f.parent_manifest_ast orelse return .none;
815816 const eb = &f.error_bundle;
816 const token_starts = ast.tokens.items(.start);
817817 const start_loc = ast.tokenLocation(0, tok);
818818 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});
819819 const msg_off = 0;
820820 return eb.addSourceLocation(.{
821821 .src_path = src_path,
822 .span_start = token_starts[tok],
823 .span_end = @intCast(token_starts[tok] + ast.tokenSlice(tok).len),
824 .span_main = token_starts[tok] + msg_off,
822 .span_start = ast.tokenStart(tok),
823 .span_end = @intCast(ast.tokenStart(tok) + ast.tokenSlice(tok).len),
824 .span_main = ast.tokenStart(tok) + msg_off,
825825 .line = @intCast(start_loc.line),
826826 .column = @intCast(start_loc.column),
827827 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),
......@@ -2331,7 +2331,7 @@ const TestFetchBuilder = struct {
23312331 .arena = std.heap.ArenaAllocator.init(allocator),
23322332 .location = .{ .path_or_url = path_or_url },
23332333 .location_tok = 0,
2334 .hash_tok = 0,
2334 .hash_tok = .none,
23352335 .name_tok = 0,
23362336 .lazy_status = .eager,
23372337 .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } },
src/Package/Manifest.zig+42-61
......@@ -17,8 +17,8 @@ pub const Dependency = struct {
1717 location_tok: Ast.TokenIndex,
1818 location_node: Ast.Node.Index,
1919 hash: ?[]const u8,
20 hash_tok: Ast.TokenIndex,
21 hash_node: Ast.Node.Index,
20 hash_tok: Ast.OptionalTokenIndex,
21 hash_node: Ast.Node.OptionalIndex,
2222 node: Ast.Node.Index,
2323 name_tok: Ast.TokenIndex,
2424 lazy: bool,
......@@ -40,7 +40,7 @@ id: u32,
4040version: std.SemanticVersion,
4141version_node: Ast.Node.Index,
4242dependencies: std.StringArrayHashMapUnmanaged(Dependency),
43dependencies_node: Ast.Node.Index,
43dependencies_node: Ast.Node.OptionalIndex,
4444paths: std.StringArrayHashMapUnmanaged(void),
4545minimum_zig_version: ?std.SemanticVersion,
4646
......@@ -58,10 +58,7 @@ pub const ParseOptions = struct {
5858pub const Error = Allocator.Error;
5959
6060pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
61 const node_tags = ast.nodes.items(.tag);
62 const node_datas = ast.nodes.items(.data);
63 assert(node_tags[0] == .root);
64 const main_node_index = node_datas[0].lhs;
61 const main_node_index = ast.nodeData(.root).node;
6562
6663 var arena_instance = std.heap.ArenaAllocator.init(gpa);
6764 errdefer arena_instance.deinit();
......@@ -75,9 +72,9 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
7572 .name = undefined,
7673 .id = 0,
7774 .version = undefined,
78 .version_node = 0,
75 .version_node = undefined,
7976 .dependencies = .{},
80 .dependencies_node = 0,
77 .dependencies_node = .none,
8178 .paths = .{},
8279 .allow_missing_paths_field = options.allow_missing_paths_field,
8380 .allow_name_string = options.allow_name_string,
......@@ -121,8 +118,6 @@ pub fn copyErrorsIntoBundle(
121118 src_path: u32,
122119 eb: *std.zig.ErrorBundle.Wip,
123120) Allocator.Error!void {
124 const token_starts = ast.tokens.items(.start);
125
126121 for (man.errors) |msg| {
127122 const start_loc = ast.tokenLocation(0, msg.tok);
128123
......@@ -130,9 +125,9 @@ pub fn copyErrorsIntoBundle(
130125 .msg = try eb.addString(msg.msg),
131126 .src_loc = try eb.addSourceLocation(.{
132127 .src_path = src_path,
133 .span_start = token_starts[msg.tok],
134 .span_end = @intCast(token_starts[msg.tok] + ast.tokenSlice(msg.tok).len),
135 .span_main = token_starts[msg.tok] + msg.off,
128 .span_start = ast.tokenStart(msg.tok),
129 .span_end = @intCast(ast.tokenStart(msg.tok) + ast.tokenSlice(msg.tok).len),
130 .span_main = ast.tokenStart(msg.tok) + msg.off,
136131 .line = @intCast(start_loc.line),
137132 .column = @intCast(start_loc.column),
138133 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),
......@@ -153,7 +148,7 @@ const Parse = struct {
153148 version: std.SemanticVersion,
154149 version_node: Ast.Node.Index,
155150 dependencies: std.StringArrayHashMapUnmanaged(Dependency),
156 dependencies_node: Ast.Node.Index,
151 dependencies_node: Ast.Node.OptionalIndex,
157152 paths: std.StringArrayHashMapUnmanaged(void),
158153 allow_missing_paths_field: bool,
159154 allow_name_string: bool,
......@@ -164,8 +159,7 @@ const Parse = struct {
164159
165160 fn parseRoot(p: *Parse, node: Ast.Node.Index) !void {
166161 const ast = p.ast;
167 const main_tokens = ast.nodes.items(.main_token);
168 const main_token = main_tokens[node];
162 const main_token = ast.nodeMainToken(node);
169163
170164 var buf: [2]Ast.Node.Index = undefined;
171165 const struct_init = ast.fullStructInit(&buf, node) orelse {
......@@ -184,7 +178,7 @@ const Parse = struct {
184178 // things manually provides an opportunity to do any additional verification
185179 // that is desirable on a per-field basis.
186180 if (mem.eql(u8, field_name, "dependencies")) {
187 p.dependencies_node = field_init;
181 p.dependencies_node = field_init.toOptional();
188182 try parseDependencies(p, field_init);
189183 } else if (mem.eql(u8, field_name, "paths")) {
190184 have_included_paths = true;
......@@ -198,17 +192,17 @@ const Parse = struct {
198192 p.version_node = field_init;
199193 const version_text = try parseString(p, field_init);
200194 if (version_text.len > max_version_len) {
201 try appendError(p, main_tokens[field_init], "version string length {d} exceeds maximum of {d}", .{ version_text.len, max_version_len });
195 try appendError(p, ast.nodeMainToken(field_init), "version string length {d} exceeds maximum of {d}", .{ version_text.len, max_version_len });
202196 }
203197 p.version = std.SemanticVersion.parse(version_text) catch |err| v: {
204 try appendError(p, main_tokens[field_init], "unable to parse semantic version: {s}", .{@errorName(err)});
198 try appendError(p, ast.nodeMainToken(field_init), "unable to parse semantic version: {s}", .{@errorName(err)});
205199 break :v undefined;
206200 };
207201 have_version = true;
208202 } else if (mem.eql(u8, field_name, "minimum_zig_version")) {
209203 const version_text = try parseString(p, field_init);
210204 p.minimum_zig_version = std.SemanticVersion.parse(version_text) catch |err| v: {
211 try appendError(p, main_tokens[field_init], "unable to parse semantic version: {s}", .{@errorName(err)});
205 try appendError(p, ast.nodeMainToken(field_init), "unable to parse semantic version: {s}", .{@errorName(err)});
212206 break :v null;
213207 };
214208 } else {
......@@ -251,11 +245,10 @@ const Parse = struct {
251245
252246 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {
253247 const ast = p.ast;
254 const main_tokens = ast.nodes.items(.main_token);
255248
256249 var buf: [2]Ast.Node.Index = undefined;
257250 const struct_init = ast.fullStructInit(&buf, node) orelse {
258 const tok = main_tokens[node];
251 const tok = ast.nodeMainToken(node);
259252 return fail(p, tok, "expected dependencies expression to be a struct", .{});
260253 };
261254
......@@ -269,23 +262,22 @@ const Parse = struct {
269262
270263 fn parseDependency(p: *Parse, node: Ast.Node.Index) !Dependency {
271264 const ast = p.ast;
272 const main_tokens = ast.nodes.items(.main_token);
273265
274266 var buf: [2]Ast.Node.Index = undefined;
275267 const struct_init = ast.fullStructInit(&buf, node) orelse {
276 const tok = main_tokens[node];
268 const tok = ast.nodeMainToken(node);
277269 return fail(p, tok, "expected dependency expression to be a struct", .{});
278270 };
279271
280272 var dep: Dependency = .{
281273 .location = undefined,
282 .location_tok = 0,
274 .location_tok = undefined,
283275 .location_node = undefined,
284276 .hash = null,
285 .hash_tok = 0,
286 .hash_node = undefined,
277 .hash_tok = .none,
278 .hash_node = .none,
287279 .node = node,
288 .name_tok = 0,
280 .name_tok = undefined,
289281 .lazy = false,
290282 };
291283 var has_location = false;
......@@ -299,7 +291,7 @@ const Parse = struct {
299291 // that is desirable on a per-field basis.
300292 if (mem.eql(u8, field_name, "url")) {
301293 if (has_location) {
302 return fail(p, main_tokens[field_init], "dependency should specify only one of 'url' and 'path' fields.", .{});
294 return fail(p, ast.nodeMainToken(field_init), "dependency should specify only one of 'url' and 'path' fields.", .{});
303295 }
304296 dep.location = .{
305297 .url = parseString(p, field_init) catch |err| switch (err) {
......@@ -308,11 +300,11 @@ const Parse = struct {
308300 },
309301 };
310302 has_location = true;
311 dep.location_tok = main_tokens[field_init];
303 dep.location_tok = ast.nodeMainToken(field_init);
312304 dep.location_node = field_init;
313305 } else if (mem.eql(u8, field_name, "path")) {
314306 if (has_location) {
315 return fail(p, main_tokens[field_init], "dependency should specify only one of 'url' and 'path' fields.", .{});
307 return fail(p, ast.nodeMainToken(field_init), "dependency should specify only one of 'url' and 'path' fields.", .{});
316308 }
317309 dep.location = .{
318310 .path = parseString(p, field_init) catch |err| switch (err) {
......@@ -321,15 +313,15 @@ const Parse = struct {
321313 },
322314 };
323315 has_location = true;
324 dep.location_tok = main_tokens[field_init];
316 dep.location_tok = ast.nodeMainToken(field_init);
325317 dep.location_node = field_init;
326318 } else if (mem.eql(u8, field_name, "hash")) {
327319 dep.hash = parseHash(p, field_init) catch |err| switch (err) {
328320 error.ParseFailure => continue,
329321 else => |e| return e,
330322 };
331 dep.hash_tok = main_tokens[field_init];
332 dep.hash_node = field_init;
323 dep.hash_tok = .fromToken(ast.nodeMainToken(field_init));
324 dep.hash_node = field_init.toOptional();
333325 } else if (mem.eql(u8, field_name, "lazy")) {
334326 dep.lazy = parseBool(p, field_init) catch |err| switch (err) {
335327 error.ParseFailure => continue,
......@@ -342,7 +334,7 @@ const Parse = struct {
342334 }
343335
344336 if (!has_location) {
345 try appendError(p, main_tokens[node], "dependency requires location field, one of 'url' or 'path'.", .{});
337 try appendError(p, ast.nodeMainToken(node), "dependency requires location field, one of 'url' or 'path'.", .{});
346338 }
347339
348340 return dep;
......@@ -350,11 +342,10 @@ const Parse = struct {
350342
351343 fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void {
352344 const ast = p.ast;
353 const main_tokens = ast.nodes.items(.main_token);
354345
355346 var buf: [2]Ast.Node.Index = undefined;
356347 const array_init = ast.fullArrayInit(&buf, node) orelse {
357 const tok = main_tokens[node];
348 const tok = ast.nodeMainToken(node);
358349 return fail(p, tok, "expected paths expression to be a list of strings", .{});
359350 };
360351
......@@ -369,12 +360,10 @@ const Parse = struct {
369360
370361 fn parseBool(p: *Parse, node: Ast.Node.Index) !bool {
371362 const ast = p.ast;
372 const node_tags = ast.nodes.items(.tag);
373 const main_tokens = ast.nodes.items(.main_token);
374 if (node_tags[node] != .identifier) {
375 return fail(p, main_tokens[node], "expected identifier", .{});
363 if (ast.nodeTag(node) != .identifier) {
364 return fail(p, ast.nodeMainToken(node), "expected identifier", .{});
376365 }
377 const ident_token = main_tokens[node];
366 const ident_token = ast.nodeMainToken(node);
378367 const token_bytes = ast.tokenSlice(ident_token);
379368 if (mem.eql(u8, token_bytes, "true")) {
380369 return true;
......@@ -387,10 +376,8 @@ const Parse = struct {
387376
388377 fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint {
389378 const ast = p.ast;
390 const node_tags = ast.nodes.items(.tag);
391 const main_tokens = ast.nodes.items(.main_token);
392 const main_token = main_tokens[node];
393 if (node_tags[node] != .number_literal) {
379 const main_token = ast.nodeMainToken(node);
380 if (ast.nodeTag(node) != .number_literal) {
394381 return fail(p, main_token, "expected integer literal", .{});
395382 }
396383 const token_bytes = ast.tokenSlice(main_token);
......@@ -406,11 +393,9 @@ const Parse = struct {
406393
407394 fn parseName(p: *Parse, node: Ast.Node.Index) ![]const u8 {
408395 const ast = p.ast;
409 const node_tags = ast.nodes.items(.tag);
410 const main_tokens = ast.nodes.items(.main_token);
411 const main_token = main_tokens[node];
396 const main_token = ast.nodeMainToken(node);
412397
413 if (p.allow_name_string and node_tags[node] == .string_literal) {
398 if (p.allow_name_string and ast.nodeTag(node) == .string_literal) {
414399 const name = try parseString(p, node);
415400 if (!std.zig.isValidId(name))
416401 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});
......@@ -423,7 +408,7 @@ const Parse = struct {
423408 return name;
424409 }
425410
426 if (node_tags[node] != .enum_literal)
411 if (ast.nodeTag(node) != .enum_literal)
427412 return fail(p, main_token, "expected enum literal", .{});
428413
429414 const ident_name = ast.tokenSlice(main_token);
......@@ -440,12 +425,10 @@ const Parse = struct {
440425
441426 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {
442427 const ast = p.ast;
443 const node_tags = ast.nodes.items(.tag);
444 const main_tokens = ast.nodes.items(.main_token);
445 if (node_tags[node] != .string_literal) {
446 return fail(p, main_tokens[node], "expected string literal", .{});
428 if (ast.nodeTag(node) != .string_literal) {
429 return fail(p, ast.nodeMainToken(node), "expected string literal", .{});
447430 }
448 const str_lit_token = main_tokens[node];
431 const str_lit_token = ast.nodeMainToken(node);
449432 const token_bytes = ast.tokenSlice(str_lit_token);
450433 p.buf.clearRetainingCapacity();
451434 try parseStrLit(p, str_lit_token, &p.buf, token_bytes, 0);
......@@ -455,8 +438,7 @@ const Parse = struct {
455438
456439 fn parseHash(p: *Parse, node: Ast.Node.Index) ![]const u8 {
457440 const ast = p.ast;
458 const main_tokens = ast.nodes.items(.main_token);
459 const tok = main_tokens[node];
441 const tok = ast.nodeMainToken(node);
460442 const h = try parseString(p, node);
461443
462444 if (h.len > Package.Hash.max_len) {
......@@ -469,8 +451,7 @@ const Parse = struct {
469451 /// TODO: try to DRY this with AstGen.identifierTokenString
470452 fn identifierTokenString(p: *Parse, token: Ast.TokenIndex) InnerError![]const u8 {
471453 const ast = p.ast;
472 const token_tags = ast.tokens.items(.tag);
473 assert(token_tags[token] == .identifier);
454 assert(ast.tokenTag(token) == .identifier);
474455 const ident_name = ast.tokenSlice(token);
475456 if (!mem.startsWith(u8, ident_name, "@")) {
476457 return ident_name;
src/Sema.zig+110-87
......@@ -407,18 +407,18 @@ pub const Block = struct {
407407 return block.comptime_reason != null;
408408 }
409409
410 fn builtinCallArgSrc(block: *Block, builtin_call_node: i32, arg_index: u32) LazySrcLoc {
410 fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc {
411411 return block.src(.{ .node_offset_builtin_call_arg = .{
412412 .builtin_call_node = builtin_call_node,
413413 .arg_index = arg_index,
414414 } });
415415 }
416416
417 pub fn nodeOffset(block: Block, node_offset: i32) LazySrcLoc {
417 pub fn nodeOffset(block: Block, node_offset: std.zig.Ast.Node.Offset) LazySrcLoc {
418418 return block.src(LazySrcLoc.Offset.nodeOffset(node_offset));
419419 }
420420
421 fn tokenOffset(block: Block, tok_offset: u32) LazySrcLoc {
421 fn tokenOffset(block: Block, tok_offset: std.zig.Ast.TokenOffset) LazySrcLoc {
422422 return block.src(.{ .token_offset = tok_offset });
423423 }
424424
......@@ -1860,7 +1860,7 @@ fn analyzeBodyInner(
18601860 if (!block.isComptime()) break :blk try sema.zirTry(block, inst);
18611861 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
18621862 const src = block.nodeOffset(inst_data.src_node);
1863 const operand_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
1863 const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node });
18641864 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
18651865 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
18661866 const err_union = try sema.resolveInst(extra.data.operand);
......@@ -1883,7 +1883,7 @@ fn analyzeBodyInner(
18831883 if (!block.isComptime()) break :blk try sema.zirTryPtr(block, inst);
18841884 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
18851885 const src = block.nodeOffset(inst_data.src_node);
1886 const operand_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
1886 const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node });
18871887 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
18881888 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
18891889 const operand = try sema.resolveInst(extra.data.operand);
......@@ -2166,7 +2166,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
21662166 const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty));
21672167
21682168 // var st: StackTrace = undefined;
2169 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
2169 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
21702170 try stack_trace_ty.resolveFields(pt);
21712171 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
21722172
......@@ -2901,7 +2901,7 @@ fn zirStructDecl(
29012901 const tracked_inst = try block.trackZir(inst);
29022902 const src: LazySrcLoc = .{
29032903 .base_node_inst = tracked_inst,
2904 .offset = LazySrcLoc.Offset.nodeOffset(0),
2904 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
29052905 };
29062906
29072907 var extra_index = extra.end;
......@@ -3114,7 +3114,7 @@ fn zirEnumDecl(
31143114 var extra_index: usize = extra.end;
31153115
31163116 const tracked_inst = try block.trackZir(inst);
3117 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
3117 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
31183118
31193119 const tag_type_ref = if (small.has_tag_type) blk: {
31203120 const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
......@@ -3277,7 +3277,7 @@ fn zirUnionDecl(
32773277 var extra_index: usize = extra.end;
32783278
32793279 const tracked_inst = try block.trackZir(inst);
3280 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
3280 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
32813281
32823282 extra_index += @intFromBool(small.has_tag_type);
32833283 const captures_len = if (small.has_captures_len) blk: {
......@@ -3402,7 +3402,7 @@ fn zirOpaqueDecl(
34023402 var extra_index: usize = extra.end;
34033403
34043404 const tracked_inst = try block.trackZir(inst);
3405 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
3405 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
34063406
34073407 const captures_len = if (small.has_captures_len) blk: {
34083408 const captures_len = sema.code.extra[extra_index];
......@@ -3835,7 +3835,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
38353835 if (try elem_ty.comptimeOnlySema(pt)) {
38363836 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
38373837 // TODO: source location of runtime control flow
3838 const init_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
3838 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
38393839 return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)});
38403840 }
38413841
......@@ -6690,8 +6690,8 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
66906690 if (block.label) |label| {
66916691 if (label.zir_block == zir_block) {
66926692 const br_ref = try start_block.addBr(label.merges.block_inst, operand);
6693 const src_loc = if (extra.operand_src_node != Zir.Inst.Break.no_src_node)
6694 start_block.nodeOffset(extra.operand_src_node)
6693 const src_loc = if (extra.operand_src_node.unwrap()) |operand_src_node|
6694 start_block.nodeOffset(operand_src_node)
66956695 else
66966696 null;
66976697 try label.merges.src_locs.append(sema.gpa, src_loc);
......@@ -6715,8 +6715,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com
67156715
67166716 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break";
67176717 const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;
6718 assert(extra.operand_src_node != Zir.Inst.Break.no_src_node);
6719 const operand_src = start_block.nodeOffset(extra.operand_src_node);
6718 const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?);
67206719 const uncoerced_operand = try sema.resolveInst(inst_data.operand);
67216720 const switch_inst = extra.block_inst;
67226721
......@@ -7048,7 +7047,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
70487047
70497048 if (!block.ownerModule().error_tracing) return .none;
70507049
7051 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
7050 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
70527051 try stack_trace_ty.resolveFields(pt);
70537052 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
70547053 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
......@@ -7346,7 +7345,7 @@ fn checkCallArgumentCount(
73467345 if (maybe_func_inst) |func_inst| {
73477346 try sema.errNote(.{
73487347 .base_node_inst = func_inst,
7349 .offset = LazySrcLoc.Offset.nodeOffset(0),
7348 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
73507349 }, msg, "function declared here", .{});
73517350 }
73527351 break :msg msg;
......@@ -7418,7 +7417,7 @@ const CallArgsInfo = union(enum) {
74187417 /// The list of resolved (but uncoerced) arguments is known ahead of time, but
74197418 /// originated from a usage of the @call builtin at the given node offset.
74207419 call_builtin: struct {
7421 call_node_offset: i32,
7420 call_node_offset: std.zig.Ast.Node.Offset,
74227421 args: []const Air.Inst.Ref,
74237422 },
74247423
......@@ -7436,7 +7435,7 @@ const CallArgsInfo = union(enum) {
74367435 /// analyzing arguments.
74377436 call_inst: Zir.Inst.Index,
74387437 /// The node offset of `call_inst`.
7439 call_node_offset: i32,
7438 call_node_offset: std.zig.Ast.Node.Offset,
74407439 /// The number of arguments to this call, not including `bound_arg`.
74417440 num_args: u32,
74427441 /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it
......@@ -7599,7 +7598,7 @@ fn analyzeCall(
75997598 const maybe_func_inst = try sema.funcDeclSrcInst(callee);
76007599 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{
76017600 .base_node_inst = fn_decl_inst,
7602 .offset = .{ .node_offset_fn_type_ret_ty = 0 },
7601 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
76037602 } else func_src;
76047603
76057604 const func_ty_info = zcu.typeToFunc(func_ty).?;
......@@ -7613,7 +7612,7 @@ fn analyzeCall(
76137612 errdefer msg.destroy(gpa);
76147613 if (maybe_func_inst) |func_inst| try sema.errNote(.{
76157614 .base_node_inst = func_inst,
7616 .offset = .nodeOffset(0),
7615 .offset = .nodeOffset(.zero),
76177616 }, msg, "function declared here", .{});
76187617 break :msg msg;
76197618 });
......@@ -9574,7 +9573,7 @@ const Section = union(enum) {
95749573fn funcCommon(
95759574 sema: *Sema,
95769575 block: *Block,
9577 src_node_offset: i32,
9576 src_node_offset: std.zig.Ast.Node.Offset,
95789577 func_inst: Zir.Inst.Index,
95799578 cc: std.builtin.CallingConvention,
95809579 /// this might be Type.generic_poison
......@@ -9948,7 +9947,7 @@ fn finishFunc(
99489947 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
99499948 // Make sure that StackTrace's fields are resolved so that the backend can
99509949 // lower this fn type.
9951 const unresolved_stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
9950 const unresolved_stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
99529951 try unresolved_stack_trace_ty.resolveFields(pt);
99539952 }
99549953
......@@ -12599,7 +12598,7 @@ fn analyzeSwitchRuntimeBlock(
1259912598 union_originally: bool,
1260012599 maybe_union_ty: Type,
1260112600 err_set: bool,
12602 switch_node_offset: i32,
12601 switch_node_offset: std.zig.Ast.Node.Offset,
1260312602 special_prong_src: LazySrcLoc,
1260412603 seen_enum_fields: []?LazySrcLoc,
1260512604 seen_errors: SwitchErrorSet,
......@@ -13219,7 +13218,7 @@ fn resolveSwitchComptimeLoop(
1321913218 maybe_ptr_operand_ty: Type,
1322013219 cond_ty: Type,
1322113220 init_cond_val: Value,
13222 switch_node_offset: i32,
13221 switch_node_offset: std.zig.Ast.Node.Offset,
1322313222 special: SpecialProng,
1322413223 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),
1322513224 scalar_cases_len: u32,
......@@ -13255,7 +13254,7 @@ fn resolveSwitchComptimeLoop(
1325513254 const extra = sema.code.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data;
1325613255 if (extra.block_inst != spa.switch_block_inst) return error.ComptimeBreak;
1325713256 // This is a `switch_continue` targeting this block. Change the operand and start over.
13258 const src = child_block.nodeOffset(extra.operand_src_node);
13257 const src = child_block.nodeOffset(extra.operand_src_node.unwrap().?);
1325913258 const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand);
1326013259 const new_operand = try sema.coerce(child_block, maybe_ptr_operand_ty, new_operand_uncoerced, src);
1326113260
......@@ -13287,7 +13286,7 @@ fn resolveSwitchComptime(
1328713286 cond_operand: Air.Inst.Ref,
1328813287 operand_val: Value,
1328913288 operand_ty: Type,
13290 switch_node_offset: i32,
13289 switch_node_offset: std.zig.Ast.Node.Offset,
1329113290 special: SpecialProng,
1329213291 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),
1329313292 scalar_cases_len: u32,
......@@ -13837,7 +13836,7 @@ fn validateSwitchNoRange(
1383713836 block: *Block,
1383813837 ranges_len: u32,
1383913838 operand_ty: Type,
13840 src_node_offset: i32,
13839 src_node_offset: std.zig.Ast.Node.Offset,
1384113840) CompileError!void {
1384213841 if (ranges_len == 0)
1384313842 return;
......@@ -14158,14 +14157,24 @@ fn zirShl(
1415814157 const pt = sema.pt;
1415914158 const zcu = pt.zcu;
1416014159 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
14161 const src = block.nodeOffset(inst_data.src_node);
14162 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
14163 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
1416414160 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1416514161 const lhs = try sema.resolveInst(extra.lhs);
1416614162 const rhs = try sema.resolveInst(extra.rhs);
1416714163 const lhs_ty = sema.typeOf(lhs);
1416814164 const rhs_ty = sema.typeOf(rhs);
14165
14166 const src = block.nodeOffset(inst_data.src_node);
14167 const lhs_src = switch (air_tag) {
14168 .shl, .shl_sat => block.src(.{ .node_offset_bin_lhs = inst_data.src_node }),
14169 .shl_exact => block.builtinCallArgSrc(inst_data.src_node, 0),
14170 else => unreachable,
14171 };
14172 const rhs_src = switch (air_tag) {
14173 .shl, .shl_sat => block.src(.{ .node_offset_bin_rhs = inst_data.src_node }),
14174 .shl_exact => block.builtinCallArgSrc(inst_data.src_node, 1),
14175 else => unreachable,
14176 };
14177
1416914178 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1417014179
1417114180 const scalar_ty = lhs_ty.scalarType(zcu);
......@@ -14329,14 +14338,24 @@ fn zirShr(
1432914338 const pt = sema.pt;
1433014339 const zcu = pt.zcu;
1433114340 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
14332 const src = block.nodeOffset(inst_data.src_node);
14333 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
14334 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
1433514341 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1433614342 const lhs = try sema.resolveInst(extra.lhs);
1433714343 const rhs = try sema.resolveInst(extra.rhs);
1433814344 const lhs_ty = sema.typeOf(lhs);
1433914345 const rhs_ty = sema.typeOf(rhs);
14346
14347 const src = block.nodeOffset(inst_data.src_node);
14348 const lhs_src = switch (air_tag) {
14349 .shr => block.src(.{ .node_offset_bin_lhs = inst_data.src_node }),
14350 .shr_exact => block.builtinCallArgSrc(inst_data.src_node, 0),
14351 else => unreachable,
14352 };
14353 const rhs_src = switch (air_tag) {
14354 .shr => block.src(.{ .node_offset_bin_rhs = inst_data.src_node }),
14355 .shr_exact => block.builtinCallArgSrc(inst_data.src_node, 1),
14356 else => unreachable,
14357 };
14358
1434014359 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1434114360 const scalar_ty = lhs_ty.scalarType(zcu);
1434214361
......@@ -14560,7 +14579,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1456014579fn analyzeTupleCat(
1456114580 sema: *Sema,
1456214581 block: *Block,
14563 src_node: i32,
14582 src_node: std.zig.Ast.Node.Offset,
1456414583 lhs: Air.Inst.Ref,
1456514584 rhs: Air.Inst.Ref,
1456614585) CompileError!Air.Inst.Ref {
......@@ -15005,7 +15024,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
1500515024fn analyzeTupleMul(
1500615025 sema: *Sema,
1500715026 block: *Block,
15008 src_node: i32,
15027 src_node: std.zig.Ast.Node.Offset,
1500915028 operand: Air.Inst.Ref,
1501015029 factor: usize,
1501115030) CompileError!Air.Inst.Ref {
......@@ -15494,8 +15513,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1549415513 const zcu = pt.zcu;
1549515514 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1549615515 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
15497 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
15498 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
15516 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15517 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1549915518 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1550015519 const lhs = try sema.resolveInst(extra.lhs);
1550115520 const rhs = try sema.resolveInst(extra.rhs);
......@@ -15660,8 +15679,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1566015679 const zcu = pt.zcu;
1566115680 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1566215681 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
15663 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
15664 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
15682 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15683 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1566515684 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1566615685 const lhs = try sema.resolveInst(extra.lhs);
1566715686 const rhs = try sema.resolveInst(extra.rhs);
......@@ -15771,8 +15790,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1577115790 const zcu = pt.zcu;
1577215791 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1577315792 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
15774 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
15775 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
15793 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15794 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1577615795 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1577715796 const lhs = try sema.resolveInst(extra.lhs);
1577815797 const rhs = try sema.resolveInst(extra.rhs);
......@@ -16201,8 +16220,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1620116220 const zcu = pt.zcu;
1620216221 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1620316222 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
16204 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
16205 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
16223 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
16224 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1620616225 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1620716226 const lhs = try sema.resolveInst(extra.lhs);
1620816227 const rhs = try sema.resolveInst(extra.rhs);
......@@ -16297,8 +16316,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1629716316 const zcu = pt.zcu;
1629816317 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1629916318 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
16300 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
16301 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
16319 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
16320 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1630216321 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1630316322 const lhs = try sema.resolveInst(extra.lhs);
1630416323 const rhs = try sema.resolveInst(extra.rhs);
......@@ -17873,7 +17892,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1787317892 const ip = &zcu.intern_pool;
1787417893 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);
1787517894
17876 const src_node: i32 = @bitCast(extended.operand);
17895 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
1787717896 const src = block.nodeOffset(src_node);
1787817897
1787917898 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
......@@ -17897,8 +17916,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1789717916 });
1789817917 break :name null;
1789917918 };
17900 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));
17901 const token = tree.nodes.items(.main_token)[node];
17919 const node = src_node.toAbsolute(src_base_node);
17920 const token = tree.nodeMainToken(node);
1790217921 break :name tree.tokenSlice(token);
1790317922 };
1790417923
......@@ -17925,8 +17944,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1792517944 });
1792617945 break :name null;
1792717946 };
17928 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));
17929 const token = tree.nodes.items(.main_token)[node];
17947 const node = src_node.toAbsolute(src_base_node);
17948 const token = tree.nodeMainToken(node);
1793017949 break :name tree.tokenSlice(token);
1793117950 };
1793217951
......@@ -17936,7 +17955,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1793617955 try sema.errMsg(src, "variable not accessible from inner function", .{});
1793717956 errdefer msg.destroy(sema.gpa);
1793817957
17939 try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{});
17958 try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{});
1794017959
1794117960 // TODO add "declared here" note
1794217961 break :msg msg;
......@@ -17968,7 +17987,8 @@ fn zirFrameAddress(
1796817987 block: *Block,
1796917988 extended: Zir.Inst.Extended.InstData,
1797017989) CompileError!Air.Inst.Ref {
17971 const src = block.nodeOffset(@bitCast(extended.operand));
17990 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17991 const src = block.nodeOffset(src_node);
1797217992 try sema.requireRuntimeBlock(block, src, null);
1797317993 return try block.addNoOp(.frame_addr);
1797417994}
......@@ -18065,7 +18085,7 @@ fn zirBuiltinSrc(
1806518085 } });
1806618086 };
1806718087
18068 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation);
18088 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation);
1806918089 const fields = .{
1807018090 // module: [:0]const u8,
1807118091 module_name_val,
......@@ -19534,7 +19554,7 @@ fn zirCondbr(
1953419554fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1953519555 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1953619556 const src = parent_block.nodeOffset(inst_data.src_node);
19537 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
19557 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
1953819558 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1953919559 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
1954019560 const err_union = try sema.resolveInst(extra.data.operand);
......@@ -19593,7 +19613,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1959319613fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1959419614 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1959519615 const src = parent_block.nodeOffset(inst_data.src_node);
19596 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
19616 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
1959719617 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1959819618 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
1959919619 const operand = try sema.resolveInst(extra.data.operand);
......@@ -19796,7 +19816,7 @@ fn zirRetImplicit(
1979619816 }
1979719817
1979819818 const operand = try sema.resolveInst(inst_data.operand);
19799 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 });
19819 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
1980019820 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
1980119821 if (base_tag == .noreturn) {
1980219822 const msg = msg: {
......@@ -21283,7 +21303,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
2128321303 const pt = sema.pt;
2128421304 const zcu = pt.zcu;
2128521305 const ip = &zcu.intern_pool;
21286 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
21306 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
2128721307 try stack_trace_ty.resolveFields(pt);
2128821308 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
2128921309 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
......@@ -21305,7 +21325,8 @@ fn zirFrame(
2130521325 block: *Block,
2130621326 extended: Zir.Inst.Extended.InstData,
2130721327) CompileError!Air.Inst.Ref {
21308 const src = block.nodeOffset(@bitCast(extended.operand));
21328 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
21329 const src = block.nodeOffset(src_node);
2130921330 return sema.failWithUseOfAsync(block, src);
2131021331}
2131121332
......@@ -21559,13 +21580,13 @@ fn zirReify(
2155921580 const tracked_inst = try block.trackZir(inst);
2156021581 const src: LazySrcLoc = .{
2156121582 .base_node_inst = tracked_inst,
21562 .offset = LazySrcLoc.Offset.nodeOffset(0),
21583 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
2156321584 };
2156421585 const operand_src: LazySrcLoc = .{
2156521586 .base_node_inst = tracked_inst,
2156621587 .offset = .{
2156721588 .node_offset_builtin_call_arg = .{
21568 .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
21589 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
2156921590 .arg_index = 0,
2157021591 },
2157121592 },
......@@ -22873,7 +22894,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2287322894}
2287422895
2287522896fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22876 const src = block.nodeOffset(@bitCast(extended.operand));
22897 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
22898 const src = block.nodeOffset(src_node);
2287722899
2287822900 const va_list_ty = try sema.getBuiltinType(src, .VaList);
2287922901 try sema.requireRuntimeBlock(block, src, null);
......@@ -24278,12 +24300,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2427824300fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {
2427924301 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2428024302 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
24281 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
24282 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
24303 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
24304 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1);
2428324305 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2428424306
24285 const ty = try sema.resolveType(block, lhs_src, extra.lhs);
24286 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name });
24307 const ty = try sema.resolveType(block, ty_src, extra.lhs);
24308 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name });
2428724309
2428824310 const pt = sema.pt;
2428924311 const zcu = pt.zcu;
......@@ -24291,15 +24313,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2429124313 try ty.resolveLayout(pt);
2429224314 switch (ty.zigTypeTag(zcu)) {
2429324315 .@"struct" => {},
24294 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
24316 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
2429524317 }
2429624318
2429724319 const field_index = if (ty.isTuple(zcu)) blk: {
2429824320 if (field_name.eqlSlice("len", ip)) {
2429924321 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
2430024322 }
24301 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
24302 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
24323 break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src);
24324 } else try sema.structFieldIndex(block, ty, field_name, field_name_src);
2430324325
2430424326 if (ty.structFieldIsComptime(field_index, zcu)) {
2430524327 return sema.fail(block, src, "no offset available for comptime field", .{});
......@@ -25083,7 +25105,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2508325105fn analyzeShuffle(
2508425106 sema: *Sema,
2508525107 block: *Block,
25086 src_node: i32,
25108 src_node: std.zig.Ast.Node.Offset,
2508725109 elem_ty: Type,
2508825110 a_arg: Air.Inst.Ref,
2508925111 b_arg: Air.Inst.Ref,
......@@ -27010,7 +27032,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2701027032 const gpa = zcu.gpa;
2701127033 const ip = &zcu.intern_pool;
2701227034
27013 const src = block.nodeOffset(@bitCast(extended.operand));
27035 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
27036 const src = block.nodeOffset(src_node);
2701427037 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2701527038
2701627039 const ty = switch (value) {
......@@ -29485,7 +29508,7 @@ const CoerceOpts = struct {
2948529508 return .{
2948629509 .base_node_inst = func_inst,
2948729510 .offset = .{ .fn_proto_param_type = .{
29488 .fn_proto_node_offset = 0,
29511 .fn_proto_node_offset = .zero,
2948929512 .param_index = info.param_i,
2949029513 } },
2949129514 };
......@@ -30090,7 +30113,7 @@ fn coerceExtra(
3009030113
3009130114 const ret_ty_src: LazySrcLoc = .{
3009230115 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30093 .offset = .{ .node_offset_fn_type_ret_ty = 0 },
30116 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
3009430117 };
3009530118 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});
3009630119 break :msg msg;
......@@ -30130,7 +30153,7 @@ fn coerceExtra(
3013030153 {
3013130154 const ret_ty_src: LazySrcLoc = .{
3013230155 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30133 .offset = .{ .node_offset_fn_type_ret_ty = 0 },
30156 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
3013430157 };
3013530158 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {
3013630159 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
......@@ -32331,7 +32354,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
3233132354 if (zcu.analysis_in_progress.contains(anal_unit)) {
3233232355 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
3233332356 .base_node_inst = nav.analysis.?.zir_index,
32334 .offset = LazySrcLoc.Offset.nodeOffset(0),
32357 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
3233532358 }, "dependency loop detected", .{}));
3233632359 }
3233732360
......@@ -33948,7 +33971,7 @@ const PeerTypeCandidateSrc = union(enum) {
3394833971 /// index i in this slice
3394933972 override: []const ?LazySrcLoc,
3395033973 /// resolvePeerTypes originates from a @TypeOf(...) call
33951 typeof_builtin_call_node_offset: i32,
33974 typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset,
3395233975
3395333976 pub fn resolve(
3395433977 self: PeerTypeCandidateSrc,
......@@ -35551,7 +35574,7 @@ fn backingIntType(
3555135574
3555235575 const backing_int_src: LazySrcLoc = .{
3555335576 .base_node_inst = struct_type.zir_index,
35554 .offset = .{ .node_offset_container_tag = 0 },
35577 .offset = .{ .node_offset_container_tag = .zero },
3555535578 };
3555635579 block.comptime_reason = .{ .reason = .{
3555735580 .src = backing_int_src,
......@@ -35572,7 +35595,7 @@ fn backingIntType(
3557235595 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
3557335596 } else {
3557435597 if (fields_bit_sum > std.math.maxInt(u16)) {
35575 return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
35598 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
3557635599 }
3557735600 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
3557835601 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
......@@ -36173,7 +36196,7 @@ fn structFields(
3617336196 .comptime_reason = .{ .reason = .{
3617436197 .src = .{
3617536198 .base_node_inst = struct_type.zir_index,
36176 .offset = .nodeOffset(0),
36199 .offset = .nodeOffset(.zero),
3617736200 },
3617836201 .r = .{ .simple = .struct_fields },
3617936202 } },
......@@ -36514,7 +36537,7 @@ fn unionFields(
3651436537
3651536538 const src: LazySrcLoc = .{
3651636539 .base_node_inst = union_type.zir_index,
36517 .offset = .nodeOffset(0),
36540 .offset = .nodeOffset(.zero),
3651836541 };
3651936542
3652036543 var block_scope: Block = .{
......@@ -36543,7 +36566,7 @@ fn unionFields(
3654336566 if (tag_type_ref != .none) {
3654436567 const tag_ty_src: LazySrcLoc = .{
3654536568 .base_node_inst = union_type.zir_index,
36546 .offset = .{ .node_offset_container_tag = 0 },
36569 .offset = .{ .node_offset_container_tag = .zero },
3654736570 };
3654836571 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
3654936572 if (small.auto_enum_tag) {
......@@ -38523,7 +38546,7 @@ pub fn resolveDeclaredEnum(
3852338546 const zcu = pt.zcu;
3852438547 const gpa = zcu.gpa;
3852538548
38526 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
38549 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3852738550
3852838551 var arena: std.heap.ArenaAllocator = .init(gpa);
3852938552 defer arena.deinit();
......@@ -38610,7 +38633,7 @@ fn resolveDeclaredEnumInner(
3861038633
3861138634 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3861238635
38613 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
38636 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } };
3861438637
3861538638 const int_tag_ty = ty: {
3861638639 if (body.len != 0) {
......@@ -38763,9 +38786,9 @@ pub fn resolveNavPtrModifiers(
3876338786 const gpa = zcu.gpa;
3876438787 const ip = &zcu.intern_pool;
3876538788
38766 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
38767 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
38768 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
38789 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
38790 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
38791 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3876938792
3877038793 const alignment: InternPool.Alignment = a: {
3877138794 const align_body = zir_decl.align_body orelse break :a .none;
......@@ -38838,7 +38861,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3883838861
3883938862 const src: LazySrcLoc = .{
3884038863 .base_node_inst = ip.getNav(nav).srcInst(ip),
38841 .offset = .nodeOffset(0),
38864 .offset = .nodeOffset(.zero),
3884238865 };
3884338866
3884438867 const result = try sema.analyzeNavVal(block, src, nav);
src/Type.zig+1-1
......@@ -3505,7 +3505,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
35053505 },
35063506 else => return null,
35073507 },
3508 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),
3508 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero),
35093509 };
35103510}
35113511
src/Zcu.zig+284-314
......@@ -134,7 +134,7 @@ failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empt
134134/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.
135135compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
136136 base_node_inst: InternPool.TrackedInst.Index,
137 node_offset: i32,
137 node_offset: Ast.Node.Offset,
138138 pub fn src(self: @This()) LazySrcLoc {
139139 return .{
140140 .base_node_inst = self.base_node_inst,
......@@ -1034,10 +1034,6 @@ pub const SrcLoc = struct {
10341034 return tree.firstToken(src_loc.base_node);
10351035 }
10361036
1037 pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
1038 return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node)));
1039 }
1040
10411037 pub const Span = Ast.Span;
10421038
10431039 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
......@@ -1049,7 +1045,7 @@ pub const SrcLoc = struct {
10491045
10501046 .token_abs => |tok_index| {
10511047 const tree = try src_loc.file_scope.getTree(gpa);
1052 const start = tree.tokens.items(.start)[tok_index];
1048 const start = tree.tokenStart(tok_index);
10531049 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10541050 return Span{ .start = start, .end = end, .main = start };
10551051 },
......@@ -1060,142 +1056,137 @@ pub const SrcLoc = struct {
10601056 .byte_offset => |byte_off| {
10611057 const tree = try src_loc.file_scope.getTree(gpa);
10621058 const tok_index = src_loc.baseSrcToken();
1063 const start = tree.tokens.items(.start)[tok_index] + byte_off;
1059 const start = tree.tokenStart(tok_index) + byte_off;
10641060 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10651061 return Span{ .start = start, .end = end, .main = start };
10661062 },
10671063 .token_offset => |tok_off| {
10681064 const tree = try src_loc.file_scope.getTree(gpa);
1069 const tok_index = src_loc.baseSrcToken() + tok_off;
1070 const start = tree.tokens.items(.start)[tok_index];
1065 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());
1066 const start = tree.tokenStart(tok_index);
10711067 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10721068 return Span{ .start = start, .end = end, .main = start };
10731069 },
10741070 .node_offset => |traced_off| {
10751071 const node_off = traced_off.x;
10761072 const tree = try src_loc.file_scope.getTree(gpa);
1077 const node = src_loc.relativeToNodeIndex(node_off);
1073 const node = node_off.toAbsolute(src_loc.base_node);
10781074 return tree.nodeToSpan(node);
10791075 },
10801076 .node_offset_main_token => |node_off| {
10811077 const tree = try src_loc.file_scope.getTree(gpa);
1082 const node = src_loc.relativeToNodeIndex(node_off);
1083 const main_token = tree.nodes.items(.main_token)[node];
1078 const node = node_off.toAbsolute(src_loc.base_node);
1079 const main_token = tree.nodeMainToken(node);
10841080 return tree.tokensToSpan(main_token, main_token, main_token);
10851081 },
10861082 .node_offset_bin_op => |node_off| {
10871083 const tree = try src_loc.file_scope.getTree(gpa);
1088 const node = src_loc.relativeToNodeIndex(node_off);
1084 const node = node_off.toAbsolute(src_loc.base_node);
10891085 return tree.nodeToSpan(node);
10901086 },
10911087 .node_offset_initializer => |node_off| {
10921088 const tree = try src_loc.file_scope.getTree(gpa);
1093 const node = src_loc.relativeToNodeIndex(node_off);
1089 const node = node_off.toAbsolute(src_loc.base_node);
10941090 return tree.tokensToSpan(
10951091 tree.firstToken(node) - 3,
10961092 tree.lastToken(node),
1097 tree.nodes.items(.main_token)[node] - 2,
1093 tree.nodeMainToken(node) - 2,
10981094 );
10991095 },
11001096 .node_offset_var_decl_ty => |node_off| {
11011097 const tree = try src_loc.file_scope.getTree(gpa);
1102 const node = src_loc.relativeToNodeIndex(node_off);
1103 const node_tags = tree.nodes.items(.tag);
1104 const full = switch (node_tags[node]) {
1098 const node = node_off.toAbsolute(src_loc.base_node);
1099 const full = switch (tree.nodeTag(node)) {
11051100 .global_var_decl,
11061101 .local_var_decl,
11071102 .simple_var_decl,
11081103 .aligned_var_decl,
11091104 => tree.fullVarDecl(node).?,
11101105 .@"usingnamespace" => {
1111 const node_data = tree.nodes.items(.data);
1112 return tree.nodeToSpan(node_data[node].lhs);
1106 return tree.nodeToSpan(tree.nodeData(node).node);
11131107 },
11141108 else => unreachable,
11151109 };
1116 if (full.ast.type_node != 0) {
1117 return tree.nodeToSpan(full.ast.type_node);
1110 if (full.ast.type_node.unwrap()) |type_node| {
1111 return tree.nodeToSpan(type_node);
11181112 }
11191113 const tok_index = full.ast.mut_token + 1; // the name token
1120 const start = tree.tokens.items(.start)[tok_index];
1114 const start = tree.tokenStart(tok_index);
11211115 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
11221116 return Span{ .start = start, .end = end, .main = start };
11231117 },
11241118 .node_offset_var_decl_align => |node_off| {
11251119 const tree = try src_loc.file_scope.getTree(gpa);
1126 const node = src_loc.relativeToNodeIndex(node_off);
1120 const node = node_off.toAbsolute(src_loc.base_node);
11271121 var buf: [1]Ast.Node.Index = undefined;
11281122 const align_node = if (tree.fullVarDecl(node)) |v|
1129 v.ast.align_node
1123 v.ast.align_node.unwrap().?
11301124 else if (tree.fullFnProto(&buf, node)) |f|
1131 f.ast.align_expr
1125 f.ast.align_expr.unwrap().?
11321126 else
11331127 unreachable;
11341128 return tree.nodeToSpan(align_node);
11351129 },
11361130 .node_offset_var_decl_section => |node_off| {
11371131 const tree = try src_loc.file_scope.getTree(gpa);
1138 const node = src_loc.relativeToNodeIndex(node_off);
1132 const node = node_off.toAbsolute(src_loc.base_node);
11391133 var buf: [1]Ast.Node.Index = undefined;
11401134 const section_node = if (tree.fullVarDecl(node)) |v|
1141 v.ast.section_node
1135 v.ast.section_node.unwrap().?
11421136 else if (tree.fullFnProto(&buf, node)) |f|
1143 f.ast.section_expr
1137 f.ast.section_expr.unwrap().?
11441138 else
11451139 unreachable;
11461140 return tree.nodeToSpan(section_node);
11471141 },
11481142 .node_offset_var_decl_addrspace => |node_off| {
11491143 const tree = try src_loc.file_scope.getTree(gpa);
1150 const node = src_loc.relativeToNodeIndex(node_off);
1144 const node = node_off.toAbsolute(src_loc.base_node);
11511145 var buf: [1]Ast.Node.Index = undefined;
11521146 const addrspace_node = if (tree.fullVarDecl(node)) |v|
1153 v.ast.addrspace_node
1147 v.ast.addrspace_node.unwrap().?
11541148 else if (tree.fullFnProto(&buf, node)) |f|
1155 f.ast.addrspace_expr
1149 f.ast.addrspace_expr.unwrap().?
11561150 else
11571151 unreachable;
11581152 return tree.nodeToSpan(addrspace_node);
11591153 },
11601154 .node_offset_var_decl_init => |node_off| {
11611155 const tree = try src_loc.file_scope.getTree(gpa);
1162 const node = src_loc.relativeToNodeIndex(node_off);
1163 const full = tree.fullVarDecl(node).?;
1164 return tree.nodeToSpan(full.ast.init_node);
1156 const node = node_off.toAbsolute(src_loc.base_node);
1157 const init_node = switch (tree.nodeTag(node)) {
1158 .global_var_decl,
1159 .local_var_decl,
1160 .aligned_var_decl,
1161 .simple_var_decl,
1162 => tree.fullVarDecl(node).?.ast.init_node.unwrap().?,
1163 .assign_destructure => tree.assignDestructure(node).ast.value_expr,
1164 else => unreachable,
1165 };
1166 return tree.nodeToSpan(init_node);
11651167 },
11661168 .node_offset_builtin_call_arg => |builtin_arg| {
11671169 const tree = try src_loc.file_scope.getTree(gpa);
1168 const node_datas = tree.nodes.items(.data);
1169 const node_tags = tree.nodes.items(.tag);
1170 const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node);
1171 const param = switch (node_tags[node]) {
1172 .builtin_call_two, .builtin_call_two_comma => switch (builtin_arg.arg_index) {
1173 0 => node_datas[node].lhs,
1174 1 => node_datas[node].rhs,
1175 else => unreachable,
1176 },
1177 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + builtin_arg.arg_index],
1178 else => unreachable,
1179 };
1180 return tree.nodeToSpan(param);
1170 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);
1171 var buf: [2]Ast.Node.Index = undefined;
1172 const params = tree.builtinCallParams(&buf, node).?;
1173 return tree.nodeToSpan(params[builtin_arg.arg_index]);
11811174 },
11821175 .node_offset_ptrcast_operand => |node_off| {
11831176 const tree = try src_loc.file_scope.getTree(gpa);
1184 const main_tokens = tree.nodes.items(.main_token);
1185 const node_datas = tree.nodes.items(.data);
1186 const node_tags = tree.nodes.items(.tag);
11871177
1188 var node = src_loc.relativeToNodeIndex(node_off);
1178 var node = node_off.toAbsolute(src_loc.base_node);
11891179 while (true) {
1190 switch (node_tags[node]) {
1180 switch (tree.nodeTag(node)) {
11911181 .builtin_call_two, .builtin_call_two_comma => {},
11921182 else => break,
11931183 }
11941184
1195 if (node_datas[node].lhs == 0) break; // 0 args
1196 if (node_datas[node].rhs != 0) break; // 2 args
1185 const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node;
1186 if (first_arg == .none) break; // 0 args
1187 if (second_arg != .none) break; // 2 args
11971188
1198 const builtin_token = main_tokens[node];
1189 const builtin_token = tree.nodeMainToken(node);
11991190 const builtin_name = tree.tokenSlice(builtin_token);
12001191 const info = BuiltinFn.list.get(builtin_name) orelse break;
12011192
......@@ -1209,16 +1200,15 @@ pub const SrcLoc = struct {
12091200 => {},
12101201 }
12111202
1212 node = node_datas[node].lhs;
1203 node = first_arg.unwrap().?;
12131204 }
12141205
12151206 return tree.nodeToSpan(node);
12161207 },
12171208 .node_offset_array_access_index => |node_off| {
12181209 const tree = try src_loc.file_scope.getTree(gpa);
1219 const node_datas = tree.nodes.items(.data);
1220 const node = src_loc.relativeToNodeIndex(node_off);
1221 return tree.nodeToSpan(node_datas[node].rhs);
1210 const node = node_off.toAbsolute(src_loc.base_node);
1211 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
12221212 },
12231213 .node_offset_slice_ptr,
12241214 .node_offset_slice_start,
......@@ -1226,32 +1216,30 @@ pub const SrcLoc = struct {
12261216 .node_offset_slice_sentinel,
12271217 => |node_off| {
12281218 const tree = try src_loc.file_scope.getTree(gpa);
1229 const node = src_loc.relativeToNodeIndex(node_off);
1219 const node = node_off.toAbsolute(src_loc.base_node);
12301220 const full = tree.fullSlice(node).?;
12311221 const part_node = switch (src_loc.lazy) {
12321222 .node_offset_slice_ptr => full.ast.sliced,
12331223 .node_offset_slice_start => full.ast.start,
1234 .node_offset_slice_end => full.ast.end,
1235 .node_offset_slice_sentinel => full.ast.sentinel,
1224 .node_offset_slice_end => full.ast.end.unwrap().?,
1225 .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?,
12361226 else => unreachable,
12371227 };
12381228 return tree.nodeToSpan(part_node);
12391229 },
12401230 .node_offset_call_func => |node_off| {
12411231 const tree = try src_loc.file_scope.getTree(gpa);
1242 const node = src_loc.relativeToNodeIndex(node_off);
1232 const node = node_off.toAbsolute(src_loc.base_node);
12431233 var buf: [1]Ast.Node.Index = undefined;
12441234 const full = tree.fullCall(&buf, node).?;
12451235 return tree.nodeToSpan(full.ast.fn_expr);
12461236 },
12471237 .node_offset_field_name => |node_off| {
12481238 const tree = try src_loc.file_scope.getTree(gpa);
1249 const node_datas = tree.nodes.items(.data);
1250 const node_tags = tree.nodes.items(.tag);
1251 const node = src_loc.relativeToNodeIndex(node_off);
1239 const node = node_off.toAbsolute(src_loc.base_node);
12521240 var buf: [1]Ast.Node.Index = undefined;
1253 const tok_index = switch (node_tags[node]) {
1254 .field_access => node_datas[node].rhs,
1241 const tok_index = switch (tree.nodeTag(node)) {
1242 .field_access => tree.nodeData(node).node_and_token[1],
12551243 .call_one,
12561244 .call_one_comma,
12571245 .async_call_one,
......@@ -1266,43 +1254,41 @@ pub const SrcLoc = struct {
12661254 },
12671255 else => tree.firstToken(node) - 2,
12681256 };
1269 const start = tree.tokens.items(.start)[tok_index];
1257 const start = tree.tokenStart(tok_index);
12701258 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
12711259 return Span{ .start = start, .end = end, .main = start };
12721260 },
12731261 .node_offset_field_name_init => |node_off| {
12741262 const tree = try src_loc.file_scope.getTree(gpa);
1275 const node = src_loc.relativeToNodeIndex(node_off);
1263 const node = node_off.toAbsolute(src_loc.base_node);
12761264 const tok_index = tree.firstToken(node) - 2;
1277 const start = tree.tokens.items(.start)[tok_index];
1265 const start = tree.tokenStart(tok_index);
12781266 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
12791267 return Span{ .start = start, .end = end, .main = start };
12801268 },
12811269 .node_offset_deref_ptr => |node_off| {
12821270 const tree = try src_loc.file_scope.getTree(gpa);
1283 const node = src_loc.relativeToNodeIndex(node_off);
1271 const node = node_off.toAbsolute(src_loc.base_node);
12841272 return tree.nodeToSpan(node);
12851273 },
12861274 .node_offset_asm_source => |node_off| {
12871275 const tree = try src_loc.file_scope.getTree(gpa);
1288 const node = src_loc.relativeToNodeIndex(node_off);
1276 const node = node_off.toAbsolute(src_loc.base_node);
12891277 const full = tree.fullAsm(node).?;
12901278 return tree.nodeToSpan(full.ast.template);
12911279 },
12921280 .node_offset_asm_ret_ty => |node_off| {
12931281 const tree = try src_loc.file_scope.getTree(gpa);
1294 const node = src_loc.relativeToNodeIndex(node_off);
1282 const node = node_off.toAbsolute(src_loc.base_node);
12951283 const full = tree.fullAsm(node).?;
12961284 const asm_output = full.outputs[0];
1297 const node_datas = tree.nodes.items(.data);
1298 return tree.nodeToSpan(node_datas[asm_output].lhs);
1285 return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?);
12991286 },
13001287
13011288 .node_offset_if_cond => |node_off| {
13021289 const tree = try src_loc.file_scope.getTree(gpa);
1303 const node = src_loc.relativeToNodeIndex(node_off);
1304 const node_tags = tree.nodes.items(.tag);
1305 const src_node = switch (node_tags[node]) {
1290 const node = node_off.toAbsolute(src_loc.base_node);
1291 const src_node = switch (tree.nodeTag(node)) {
13061292 .if_simple,
13071293 .@"if",
13081294 => tree.fullIf(node).?.ast.cond_expr,
......@@ -1329,20 +1315,19 @@ pub const SrcLoc = struct {
13291315 },
13301316 .for_input => |for_input| {
13311317 const tree = try src_loc.file_scope.getTree(gpa);
1332 const node = src_loc.relativeToNodeIndex(for_input.for_node_offset);
1318 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
13331319 const for_full = tree.fullFor(node).?;
13341320 const src_node = for_full.ast.inputs[for_input.input_index];
13351321 return tree.nodeToSpan(src_node);
13361322 },
13371323 .for_capture_from_input => |node_off| {
13381324 const tree = try src_loc.file_scope.getTree(gpa);
1339 const token_tags = tree.tokens.items(.tag);
1340 const input_node = src_loc.relativeToNodeIndex(node_off);
1325 const input_node = node_off.toAbsolute(src_loc.base_node);
13411326 // We have to actually linear scan the whole AST to find the for loop
13421327 // that contains this input.
13431328 const node_tags = tree.nodes.items(.tag);
13441329 for (node_tags, 0..) |node_tag, node_usize| {
1345 const node = @as(Ast.Node.Index, @intCast(node_usize));
1330 const node: Ast.Node.Index = @enumFromInt(node_usize);
13461331 switch (node_tag) {
13471332 .for_simple, .@"for" => {
13481333 const for_full = tree.fullFor(node).?;
......@@ -1351,7 +1336,7 @@ pub const SrcLoc = struct {
13511336 var count = input_index;
13521337 var tok = for_full.payload_token;
13531338 while (true) {
1354 switch (token_tags[tok]) {
1339 switch (tree.tokenTag(tok)) {
13551340 .comma => {
13561341 count -= 1;
13571342 tok += 1;
......@@ -1378,13 +1363,12 @@ pub const SrcLoc = struct {
13781363 },
13791364 .call_arg => |call_arg| {
13801365 const tree = try src_loc.file_scope.getTree(gpa);
1381 const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset);
1366 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);
13821367 var buf: [2]Ast.Node.Index = undefined;
13831368 const call_full = tree.fullCall(buf[0..1], node) orelse {
1384 const node_tags = tree.nodes.items(.tag);
1385 assert(node_tags[node] == .builtin_call);
1386 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
1387 switch (node_tags[call_args_node]) {
1369 assert(tree.nodeTag(node) == .builtin_call);
1370 const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]);
1371 switch (tree.nodeTag(call_args_node)) {
13881372 .array_init_one,
13891373 .array_init_one_comma,
13901374 .array_init_dot_two,
......@@ -1416,7 +1400,7 @@ pub const SrcLoc = struct {
14161400 },
14171401 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
14181402 const tree = try src_loc.file_scope.getTree(gpa);
1419 const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
1403 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);
14201404 var buf: [1]Ast.Node.Index = undefined;
14211405 const full = tree.fullFnProto(&buf, node).?;
14221406 var it = full.iterate(tree);
......@@ -1428,14 +1412,14 @@ pub const SrcLoc = struct {
14281412 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {
14291413 return tree.tokenToSpan(tok);
14301414 } else {
1431 return tree.nodeToSpan(param.type_expr);
1415 return tree.nodeToSpan(param.type_expr.?);
14321416 },
14331417 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {
14341418 const first = param.comptime_noalias orelse param.name_token orelse tok;
14351419 return tree.tokensToSpan(first, tok, first);
14361420 } else {
1437 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr);
1438 return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first);
1421 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?);
1422 return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first);
14391423 },
14401424 else => unreachable,
14411425 }
......@@ -1444,28 +1428,24 @@ pub const SrcLoc = struct {
14441428 },
14451429 .node_offset_bin_lhs => |node_off| {
14461430 const tree = try src_loc.file_scope.getTree(gpa);
1447 const node = src_loc.relativeToNodeIndex(node_off);
1448 const node_datas = tree.nodes.items(.data);
1449 return tree.nodeToSpan(node_datas[node].lhs);
1431 const node = node_off.toAbsolute(src_loc.base_node);
1432 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
14501433 },
14511434 .node_offset_bin_rhs => |node_off| {
14521435 const tree = try src_loc.file_scope.getTree(gpa);
1453 const node = src_loc.relativeToNodeIndex(node_off);
1454 const node_datas = tree.nodes.items(.data);
1455 return tree.nodeToSpan(node_datas[node].rhs);
1436 const node = node_off.toAbsolute(src_loc.base_node);
1437 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
14561438 },
14571439 .array_cat_lhs, .array_cat_rhs => |cat| {
14581440 const tree = try src_loc.file_scope.getTree(gpa);
1459 const node = src_loc.relativeToNodeIndex(cat.array_cat_offset);
1460 const node_datas = tree.nodes.items(.data);
1441 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);
14611442 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1462 node_datas[node].lhs
1443 tree.nodeData(node).node_and_node[0]
14631444 else
1464 node_datas[node].rhs;
1445 tree.nodeData(node).node_and_node[1];
14651446
1466 const node_tags = tree.nodes.items(.tag);
14671447 var buf: [2]Ast.Node.Index = undefined;
1468 switch (node_tags[arr_node]) {
1448 switch (tree.nodeTag(arr_node)) {
14691449 .array_init_one,
14701450 .array_init_one_comma,
14711451 .array_init_dot_two,
......@@ -1482,27 +1462,30 @@ pub const SrcLoc = struct {
14821462 }
14831463 },
14841464
1465 .node_offset_try_operand => |node_off| {
1466 const tree = try src_loc.file_scope.getTree(gpa);
1467 const node = node_off.toAbsolute(src_loc.base_node);
1468 return tree.nodeToSpan(tree.nodeData(node).node);
1469 },
1470
14851471 .node_offset_switch_operand => |node_off| {
14861472 const tree = try src_loc.file_scope.getTree(gpa);
1487 const node = src_loc.relativeToNodeIndex(node_off);
1488 const node_datas = tree.nodes.items(.data);
1489 return tree.nodeToSpan(node_datas[node].lhs);
1473 const node = node_off.toAbsolute(src_loc.base_node);
1474 const condition, _ = tree.nodeData(node).node_and_extra;
1475 return tree.nodeToSpan(condition);
14901476 },
14911477
14921478 .node_offset_switch_special_prong => |node_off| {
14931479 const tree = try src_loc.file_scope.getTree(gpa);
1494 const switch_node = src_loc.relativeToNodeIndex(node_off);
1495 const node_datas = tree.nodes.items(.data);
1496 const node_tags = tree.nodes.items(.tag);
1497 const main_tokens = tree.nodes.items(.main_token);
1498 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1499 const case_nodes = tree.extra_data[extra.start..extra.end];
1480 const switch_node = node_off.toAbsolute(src_loc.base_node);
1481 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1482 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
15001483 for (case_nodes) |case_node| {
15011484 const case = tree.fullSwitchCase(case_node).?;
15021485 const is_special = (case.ast.values.len == 0) or
15031486 (case.ast.values.len == 1 and
1504 node_tags[case.ast.values[0]] == .identifier and
1505 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
1487 tree.nodeTag(case.ast.values[0]) == .identifier and
1488 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
15061489 if (!is_special) continue;
15071490
15081491 return tree.nodeToSpan(case_node);
......@@ -1511,22 +1494,19 @@ pub const SrcLoc = struct {
15111494
15121495 .node_offset_switch_range => |node_off| {
15131496 const tree = try src_loc.file_scope.getTree(gpa);
1514 const switch_node = src_loc.relativeToNodeIndex(node_off);
1515 const node_datas = tree.nodes.items(.data);
1516 const node_tags = tree.nodes.items(.tag);
1517 const main_tokens = tree.nodes.items(.main_token);
1518 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1519 const case_nodes = tree.extra_data[extra.start..extra.end];
1497 const switch_node = node_off.toAbsolute(src_loc.base_node);
1498 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1499 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
15201500 for (case_nodes) |case_node| {
15211501 const case = tree.fullSwitchCase(case_node).?;
15221502 const is_special = (case.ast.values.len == 0) or
15231503 (case.ast.values.len == 1 and
1524 node_tags[case.ast.values[0]] == .identifier and
1525 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
1504 tree.nodeTag(case.ast.values[0]) == .identifier and
1505 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
15261506 if (is_special) continue;
15271507
15281508 for (case.ast.values) |item_node| {
1529 if (node_tags[item_node] == .switch_range) {
1509 if (tree.nodeTag(item_node) == .switch_range) {
15301510 return tree.nodeToSpan(item_node);
15311511 }
15321512 }
......@@ -1534,47 +1514,46 @@ pub const SrcLoc = struct {
15341514 },
15351515 .node_offset_fn_type_align => |node_off| {
15361516 const tree = try src_loc.file_scope.getTree(gpa);
1537 const node = src_loc.relativeToNodeIndex(node_off);
1517 const node = node_off.toAbsolute(src_loc.base_node);
15381518 var buf: [1]Ast.Node.Index = undefined;
15391519 const full = tree.fullFnProto(&buf, node).?;
1540 return tree.nodeToSpan(full.ast.align_expr);
1520 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
15411521 },
15421522 .node_offset_fn_type_addrspace => |node_off| {
15431523 const tree = try src_loc.file_scope.getTree(gpa);
1544 const node = src_loc.relativeToNodeIndex(node_off);
1524 const node = node_off.toAbsolute(src_loc.base_node);
15451525 var buf: [1]Ast.Node.Index = undefined;
15461526 const full = tree.fullFnProto(&buf, node).?;
1547 return tree.nodeToSpan(full.ast.addrspace_expr);
1527 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
15481528 },
15491529 .node_offset_fn_type_section => |node_off| {
15501530 const tree = try src_loc.file_scope.getTree(gpa);
1551 const node = src_loc.relativeToNodeIndex(node_off);
1531 const node = node_off.toAbsolute(src_loc.base_node);
15521532 var buf: [1]Ast.Node.Index = undefined;
15531533 const full = tree.fullFnProto(&buf, node).?;
1554 return tree.nodeToSpan(full.ast.section_expr);
1534 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
15551535 },
15561536 .node_offset_fn_type_cc => |node_off| {
15571537 const tree = try src_loc.file_scope.getTree(gpa);
1558 const node = src_loc.relativeToNodeIndex(node_off);
1538 const node = node_off.toAbsolute(src_loc.base_node);
15591539 var buf: [1]Ast.Node.Index = undefined;
15601540 const full = tree.fullFnProto(&buf, node).?;
1561 return tree.nodeToSpan(full.ast.callconv_expr);
1541 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);
15621542 },
15631543
15641544 .node_offset_fn_type_ret_ty => |node_off| {
15651545 const tree = try src_loc.file_scope.getTree(gpa);
1566 const node = src_loc.relativeToNodeIndex(node_off);
1546 const node = node_off.toAbsolute(src_loc.base_node);
15671547 var buf: [1]Ast.Node.Index = undefined;
15681548 const full = tree.fullFnProto(&buf, node).?;
1569 return tree.nodeToSpan(full.ast.return_type);
1549 return tree.nodeToSpan(full.ast.return_type.unwrap().?);
15701550 },
15711551 .node_offset_param => |node_off| {
15721552 const tree = try src_loc.file_scope.getTree(gpa);
1573 const token_tags = tree.tokens.items(.tag);
1574 const node = src_loc.relativeToNodeIndex(node_off);
1553 const node = node_off.toAbsolute(src_loc.base_node);
15751554
15761555 var first_tok = tree.firstToken(node);
1577 while (true) switch (token_tags[first_tok - 1]) {
1556 while (true) switch (tree.tokenTag(first_tok - 1)) {
15781557 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
15791558 else => break,
15801559 };
......@@ -1586,12 +1565,11 @@ pub const SrcLoc = struct {
15861565 },
15871566 .token_offset_param => |token_off| {
15881567 const tree = try src_loc.file_scope.getTree(gpa);
1589 const token_tags = tree.tokens.items(.tag);
1590 const main_token = tree.nodes.items(.main_token)[src_loc.base_node];
1591 const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token))));
1568 const main_token = tree.nodeMainToken(src_loc.base_node);
1569 const tok_index = token_off.toAbsolute(main_token);
15921570
15931571 var first_tok = tok_index;
1594 while (true) switch (token_tags[first_tok - 1]) {
1572 while (true) switch (tree.tokenTag(first_tok - 1)) {
15951573 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
15961574 else => break,
15971575 };
......@@ -1604,109 +1582,108 @@ pub const SrcLoc = struct {
16041582
16051583 .node_offset_anyframe_type => |node_off| {
16061584 const tree = try src_loc.file_scope.getTree(gpa);
1607 const node_datas = tree.nodes.items(.data);
1608 const parent_node = src_loc.relativeToNodeIndex(node_off);
1609 return tree.nodeToSpan(node_datas[parent_node].rhs);
1585 const parent_node = node_off.toAbsolute(src_loc.base_node);
1586 _, const child_type = tree.nodeData(parent_node).token_and_node;
1587 return tree.nodeToSpan(child_type);
16101588 },
16111589
16121590 .node_offset_lib_name => |node_off| {
16131591 const tree = try src_loc.file_scope.getTree(gpa);
1614 const parent_node = src_loc.relativeToNodeIndex(node_off);
1592 const parent_node = node_off.toAbsolute(src_loc.base_node);
16151593 var buf: [1]Ast.Node.Index = undefined;
16161594 const full = tree.fullFnProto(&buf, parent_node).?;
16171595 const tok_index = full.lib_name.?;
1618 const start = tree.tokens.items(.start)[tok_index];
1596 const start = tree.tokenStart(tok_index);
16191597 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
16201598 return Span{ .start = start, .end = end, .main = start };
16211599 },
16221600
16231601 .node_offset_array_type_len => |node_off| {
16241602 const tree = try src_loc.file_scope.getTree(gpa);
1625 const parent_node = src_loc.relativeToNodeIndex(node_off);
1603 const parent_node = node_off.toAbsolute(src_loc.base_node);
16261604
16271605 const full = tree.fullArrayType(parent_node).?;
16281606 return tree.nodeToSpan(full.ast.elem_count);
16291607 },
16301608 .node_offset_array_type_sentinel => |node_off| {
16311609 const tree = try src_loc.file_scope.getTree(gpa);
1632 const parent_node = src_loc.relativeToNodeIndex(node_off);
1610 const parent_node = node_off.toAbsolute(src_loc.base_node);
16331611
16341612 const full = tree.fullArrayType(parent_node).?;
1635 return tree.nodeToSpan(full.ast.sentinel);
1613 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
16361614 },
16371615 .node_offset_array_type_elem => |node_off| {
16381616 const tree = try src_loc.file_scope.getTree(gpa);
1639 const parent_node = src_loc.relativeToNodeIndex(node_off);
1617 const parent_node = node_off.toAbsolute(src_loc.base_node);
16401618
16411619 const full = tree.fullArrayType(parent_node).?;
16421620 return tree.nodeToSpan(full.ast.elem_type);
16431621 },
16441622 .node_offset_un_op => |node_off| {
16451623 const tree = try src_loc.file_scope.getTree(gpa);
1646 const node_datas = tree.nodes.items(.data);
1647 const node = src_loc.relativeToNodeIndex(node_off);
1648
1649 return tree.nodeToSpan(node_datas[node].lhs);
1624 const node = node_off.toAbsolute(src_loc.base_node);
1625 return tree.nodeToSpan(tree.nodeData(node).node);
16501626 },
16511627 .node_offset_ptr_elem => |node_off| {
16521628 const tree = try src_loc.file_scope.getTree(gpa);
1653 const parent_node = src_loc.relativeToNodeIndex(node_off);
1629 const parent_node = node_off.toAbsolute(src_loc.base_node);
16541630
16551631 const full = tree.fullPtrType(parent_node).?;
16561632 return tree.nodeToSpan(full.ast.child_type);
16571633 },
16581634 .node_offset_ptr_sentinel => |node_off| {
16591635 const tree = try src_loc.file_scope.getTree(gpa);
1660 const parent_node = src_loc.relativeToNodeIndex(node_off);
1636 const parent_node = node_off.toAbsolute(src_loc.base_node);
16611637
16621638 const full = tree.fullPtrType(parent_node).?;
1663 return tree.nodeToSpan(full.ast.sentinel);
1639 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
16641640 },
16651641 .node_offset_ptr_align => |node_off| {
16661642 const tree = try src_loc.file_scope.getTree(gpa);
1667 const parent_node = src_loc.relativeToNodeIndex(node_off);
1643 const parent_node = node_off.toAbsolute(src_loc.base_node);
16681644
16691645 const full = tree.fullPtrType(parent_node).?;
1670 return tree.nodeToSpan(full.ast.align_node);
1646 return tree.nodeToSpan(full.ast.align_node.unwrap().?);
16711647 },
16721648 .node_offset_ptr_addrspace => |node_off| {
16731649 const tree = try src_loc.file_scope.getTree(gpa);
1674 const parent_node = src_loc.relativeToNodeIndex(node_off);
1650 const parent_node = node_off.toAbsolute(src_loc.base_node);
16751651
16761652 const full = tree.fullPtrType(parent_node).?;
1677 return tree.nodeToSpan(full.ast.addrspace_node);
1653 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);
16781654 },
16791655 .node_offset_ptr_bitoffset => |node_off| {
16801656 const tree = try src_loc.file_scope.getTree(gpa);
1681 const parent_node = src_loc.relativeToNodeIndex(node_off);
1657 const parent_node = node_off.toAbsolute(src_loc.base_node);
16821658
16831659 const full = tree.fullPtrType(parent_node).?;
1684 return tree.nodeToSpan(full.ast.bit_range_start);
1660 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);
16851661 },
16861662 .node_offset_ptr_hostsize => |node_off| {
16871663 const tree = try src_loc.file_scope.getTree(gpa);
1688 const parent_node = src_loc.relativeToNodeIndex(node_off);
1664 const parent_node = node_off.toAbsolute(src_loc.base_node);
16891665
16901666 const full = tree.fullPtrType(parent_node).?;
1691 return tree.nodeToSpan(full.ast.bit_range_end);
1667 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);
16921668 },
16931669 .node_offset_container_tag => |node_off| {
16941670 const tree = try src_loc.file_scope.getTree(gpa);
1695 const node_tags = tree.nodes.items(.tag);
1696 const parent_node = src_loc.relativeToNodeIndex(node_off);
1671 const parent_node = node_off.toAbsolute(src_loc.base_node);
16971672
1698 switch (node_tags[parent_node]) {
1673 switch (tree.nodeTag(parent_node)) {
16991674 .container_decl_arg, .container_decl_arg_trailing => {
17001675 const full = tree.containerDeclArg(parent_node);
1701 return tree.nodeToSpan(full.ast.arg);
1676 const arg_node = full.ast.arg.unwrap().?;
1677 return tree.nodeToSpan(arg_node);
17021678 },
17031679 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
17041680 const full = tree.taggedUnionEnumTag(parent_node);
1681 const arg_node = full.ast.arg.unwrap().?;
17051682
17061683 return tree.tokensToSpan(
1707 tree.firstToken(full.ast.arg) - 2,
1708 tree.lastToken(full.ast.arg) + 1,
1709 tree.nodes.items(.main_token)[full.ast.arg],
1684 tree.firstToken(arg_node) - 2,
1685 tree.lastToken(arg_node) + 1,
1686 tree.nodeMainToken(arg_node),
17101687 );
17111688 },
17121689 else => unreachable,
......@@ -1714,60 +1691,55 @@ pub const SrcLoc = struct {
17141691 },
17151692 .node_offset_field_default => |node_off| {
17161693 const tree = try src_loc.file_scope.getTree(gpa);
1717 const node_tags = tree.nodes.items(.tag);
1718 const parent_node = src_loc.relativeToNodeIndex(node_off);
1694 const parent_node = node_off.toAbsolute(src_loc.base_node);
17191695
1720 const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {
1696 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {
17211697 .container_field => tree.containerField(parent_node),
17221698 .container_field_init => tree.containerFieldInit(parent_node),
17231699 else => unreachable,
17241700 };
1725 return tree.nodeToSpan(full.ast.value_expr);
1701 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);
17261702 },
17271703 .node_offset_init_ty => |node_off| {
17281704 const tree = try src_loc.file_scope.getTree(gpa);
1729 const parent_node = src_loc.relativeToNodeIndex(node_off);
1705 const parent_node = node_off.toAbsolute(src_loc.base_node);
17301706
17311707 var buf: [2]Ast.Node.Index = undefined;
17321708 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|
1733 array_init.ast.type_expr
1709 array_init.ast.type_expr.unwrap().?
17341710 else
1735 tree.fullStructInit(&buf, parent_node).?.ast.type_expr;
1711 tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?;
17361712 return tree.nodeToSpan(type_expr);
17371713 },
17381714 .node_offset_store_ptr => |node_off| {
17391715 const tree = try src_loc.file_scope.getTree(gpa);
1740 const node_tags = tree.nodes.items(.tag);
1741 const node_datas = tree.nodes.items(.data);
1742 const node = src_loc.relativeToNodeIndex(node_off);
1716 const node = node_off.toAbsolute(src_loc.base_node);
17431717
1744 switch (node_tags[node]) {
1718 switch (tree.nodeTag(node)) {
17451719 .assign => {
1746 return tree.nodeToSpan(node_datas[node].lhs);
1720 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
17471721 },
17481722 else => return tree.nodeToSpan(node),
17491723 }
17501724 },
17511725 .node_offset_store_operand => |node_off| {
17521726 const tree = try src_loc.file_scope.getTree(gpa);
1753 const node_tags = tree.nodes.items(.tag);
1754 const node_datas = tree.nodes.items(.data);
1755 const node = src_loc.relativeToNodeIndex(node_off);
1727 const node = node_off.toAbsolute(src_loc.base_node);
17561728
1757 switch (node_tags[node]) {
1729 switch (tree.nodeTag(node)) {
17581730 .assign => {
1759 return tree.nodeToSpan(node_datas[node].rhs);
1731 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
17601732 },
17611733 else => return tree.nodeToSpan(node),
17621734 }
17631735 },
17641736 .node_offset_return_operand => |node_off| {
17651737 const tree = try src_loc.file_scope.getTree(gpa);
1766 const node = src_loc.relativeToNodeIndex(node_off);
1767 const node_tags = tree.nodes.items(.tag);
1768 const node_datas = tree.nodes.items(.data);
1769 if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) {
1770 return tree.nodeToSpan(node_datas[node].lhs);
1738 const node = node_off.toAbsolute(src_loc.base_node);
1739 if (tree.nodeTag(node) == .@"return") {
1740 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
1741 return tree.nodeToSpan(lhs);
1742 }
17711743 }
17721744 return tree.nodeToSpan(node);
17731745 },
......@@ -1777,7 +1749,7 @@ pub const SrcLoc = struct {
17771749 .container_field_align,
17781750 => |field_idx| {
17791751 const tree = try src_loc.file_scope.getTree(gpa);
1780 const node = src_loc.relativeToNodeIndex(0);
1752 const node = src_loc.base_node;
17811753 var buf: [2]Ast.Node.Index = undefined;
17821754 const container_decl = tree.fullContainerDecl(&buf, node) orelse
17831755 return tree.nodeToSpan(node);
......@@ -1790,36 +1762,36 @@ pub const SrcLoc = struct {
17901762 continue;
17911763 }
17921764 const field_component_node = switch (src_loc.lazy) {
1793 .container_field_name => 0,
1765 .container_field_name => .none,
17941766 .container_field_value => field.ast.value_expr,
17951767 .container_field_type => field.ast.type_expr,
17961768 .container_field_align => field.ast.align_expr,
17971769 else => unreachable,
17981770 };
1799 if (field_component_node == 0) {
1800 return tree.tokenToSpan(field.ast.main_token);
1771 if (field_component_node.unwrap()) |component_node| {
1772 return tree.nodeToSpan(component_node);
18011773 } else {
1802 return tree.nodeToSpan(field_component_node);
1774 return tree.tokenToSpan(field.ast.main_token);
18031775 }
18041776 } else unreachable;
18051777 },
18061778 .tuple_field_type, .tuple_field_init => |field_info| {
18071779 const tree = try src_loc.file_scope.getTree(gpa);
1808 const node = src_loc.relativeToNodeIndex(0);
1780 const node = src_loc.base_node;
18091781 var buf: [2]Ast.Node.Index = undefined;
18101782 const container_decl = tree.fullContainerDecl(&buf, node) orelse
18111783 return tree.nodeToSpan(node);
18121784
18131785 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;
18141786 return tree.nodeToSpan(switch (src_loc.lazy) {
1815 .tuple_field_type => field.ast.type_expr,
1816 .tuple_field_init => field.ast.value_expr,
1787 .tuple_field_type => field.ast.type_expr.unwrap().?,
1788 .tuple_field_init => field.ast.value_expr.unwrap().?,
18171789 else => unreachable,
18181790 });
18191791 },
18201792 .init_elem => |init_elem| {
18211793 const tree = try src_loc.file_scope.getTree(gpa);
1822 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);
1794 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);
18231795 var buf: [2]Ast.Node.Index = undefined;
18241796 if (tree.fullArrayInit(&buf, init_node)) |full| {
18251797 const elem_node = full.ast.elements[init_elem.elem_index];
......@@ -1829,7 +1801,7 @@ pub const SrcLoc = struct {
18291801 return tree.tokensToSpan(
18301802 tree.firstToken(field_node) - 3,
18311803 tree.lastToken(field_node),
1832 tree.nodes.items(.main_token)[field_node] - 2,
1804 tree.nodeMainToken(field_node) - 2,
18331805 );
18341806 } else unreachable;
18351807 },
......@@ -1858,14 +1830,10 @@ pub const SrcLoc = struct {
18581830 else => unreachable,
18591831 };
18601832 const tree = try src_loc.file_scope.getTree(gpa);
1861 const node_datas = tree.nodes.items(.data);
1862 const node_tags = tree.nodes.items(.tag);
1863 const node = src_loc.relativeToNodeIndex(builtin_call_node);
1864 const arg_node = switch (node_tags[node]) {
1865 .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs,
1866 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1],
1867 else => unreachable,
1868 };
1833 const node = builtin_call_node.toAbsolute(src_loc.base_node);
1834 var builtin_buf: [2]Ast.Node.Index = undefined;
1835 const args = tree.builtinCallParams(&builtin_buf, node).?;
1836 const arg_node = args[1];
18691837 var buf: [2]Ast.Node.Index = undefined;
18701838 const full = tree.fullStructInit(&buf, arg_node) orelse
18711839 return tree.nodeToSpan(arg_node);
......@@ -1877,7 +1845,7 @@ pub const SrcLoc = struct {
18771845 return tree.tokensToSpan(
18781846 name_token - 1,
18791847 tree.lastToken(field_node),
1880 tree.nodes.items(.main_token)[field_node] - 2,
1848 tree.nodeMainToken(field_node) - 2,
18811849 );
18821850 }
18831851 }
......@@ -1901,12 +1869,9 @@ pub const SrcLoc = struct {
19011869 };
19021870
19031871 const tree = try src_loc.file_scope.getTree(gpa);
1904 const node_datas = tree.nodes.items(.data);
1905 const node_tags = tree.nodes.items(.tag);
1906 const main_tokens = tree.nodes.items(.main_token);
1907 const switch_node = src_loc.relativeToNodeIndex(switch_node_offset);
1908 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1909 const case_nodes = tree.extra_data[extra.start..extra.end];
1872 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);
1873 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1874 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
19101875
19111876 var multi_i: u32 = 0;
19121877 var scalar_i: u32 = 0;
......@@ -1914,8 +1879,8 @@ pub const SrcLoc = struct {
19141879 const case = tree.fullSwitchCase(case_node).?;
19151880 const is_special = special: {
19161881 if (case.ast.values.len == 0) break :special true;
1917 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {
1918 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");
1882 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) {
1883 break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_");
19191884 }
19201885 break :special false;
19211886 };
......@@ -1927,7 +1892,7 @@ pub const SrcLoc = struct {
19271892 }
19281893
19291894 const is_multi = case.ast.values.len != 1 or
1930 node_tags[case.ast.values[0]] == .switch_range;
1895 tree.nodeTag(case.ast.values[0]) == .switch_range;
19311896
19321897 switch (want_case_idx.kind) {
19331898 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,
......@@ -1947,18 +1912,17 @@ pub const SrcLoc = struct {
19471912 .switch_case_item_range_last,
19481913 => |x| x.item_idx,
19491914 .switch_capture, .switch_tag_capture => {
1950 const token_tags = tree.tokens.items(.tag);
19511915 const start = switch (src_loc.lazy) {
19521916 .switch_capture => case.payload_token.?,
19531917 .switch_tag_capture => tok: {
19541918 var tok = case.payload_token.?;
1955 if (token_tags[tok] == .asterisk) tok += 1;
1956 tok += 2; // skip over comma
1919 if (tree.tokenTag(tok) == .asterisk) tok += 1;
1920 tok = tok + 2; // skip over comma
19571921 break :tok tok;
19581922 },
19591923 else => unreachable,
19601924 };
1961 const end = switch (token_tags[start]) {
1925 const end = switch (tree.tokenTag(start)) {
19621926 .asterisk => start + 1,
19631927 else => start,
19641928 };
......@@ -1971,7 +1935,7 @@ pub const SrcLoc = struct {
19711935 .single => {
19721936 var item_i: u32 = 0;
19731937 for (case.ast.values) |item_node| {
1974 if (node_tags[item_node] == .switch_range) continue;
1938 if (tree.nodeTag(item_node) == .switch_range) continue;
19751939 if (item_i != want_item.index) {
19761940 item_i += 1;
19771941 continue;
......@@ -1982,15 +1946,16 @@ pub const SrcLoc = struct {
19821946 .range => {
19831947 var range_i: u32 = 0;
19841948 for (case.ast.values) |item_node| {
1985 if (node_tags[item_node] != .switch_range) continue;
1949 if (tree.nodeTag(item_node) != .switch_range) continue;
19861950 if (range_i != want_item.index) {
19871951 range_i += 1;
19881952 continue;
19891953 }
1954 const first, const last = tree.nodeData(item_node).node_and_node;
19901955 return switch (src_loc.lazy) {
19911956 .switch_case_item => tree.nodeToSpan(item_node),
1992 .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs),
1993 .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs),
1957 .switch_case_item_range_first => tree.nodeToSpan(first),
1958 .switch_case_item_range_last => tree.nodeToSpan(last),
19941959 else => unreachable,
19951960 };
19961961 } else unreachable;
......@@ -2013,7 +1978,7 @@ pub const SrcLoc = struct {
20131978 var param_it = full.iterate(tree);
20141979 for (0..param_idx) |_| assert(param_it.next() != null);
20151980 const param = param_it.next().?;
2016 return tree.nodeToSpan(param.type_expr);
1981 return tree.nodeToSpan(param.type_expr.?);
20171982 },
20181983 }
20191984 }
......@@ -2044,212 +2009,217 @@ pub const LazySrcLoc = struct {
20442009 byte_abs: u32,
20452010 /// The source location points to a token within a source file,
20462011 /// offset from 0. The source file is determined contextually.
2047 token_abs: u32,
2012 token_abs: Ast.TokenIndex,
20482013 /// The source location points to an AST node within a source file,
20492014 /// offset from 0. The source file is determined contextually.
2050 node_abs: u32,
2015 node_abs: Ast.Node.Index,
20512016 /// The source location points to a byte offset within a source file,
20522017 /// offset from the byte offset of the base node within the file.
20532018 byte_offset: u32,
20542019 /// This data is the offset into the token list from the base node's first token.
2055 token_offset: u32,
2020 token_offset: Ast.TokenOffset,
20562021 /// The source location points to an AST node, which is this value offset
20572022 /// from its containing base node AST index.
20582023 node_offset: TracedOffset,
20592024 /// The source location points to the main token of an AST node, found
20602025 /// by taking this AST node index offset from the containing base node.
2061 node_offset_main_token: i32,
2026 node_offset_main_token: Ast.Node.Offset,
20622027 /// The source location points to the beginning of a struct initializer.
2063 node_offset_initializer: i32,
2028 node_offset_initializer: Ast.Node.Offset,
20642029 /// The source location points to a variable declaration type expression,
20652030 /// found by taking this AST node index offset from the containing
20662031 /// base node, which points to a variable declaration AST node. Next, navigate
20672032 /// to the type expression.
2068 node_offset_var_decl_ty: i32,
2033 node_offset_var_decl_ty: Ast.Node.Offset,
20692034 /// The source location points to the alignment expression of a var decl.
2070 node_offset_var_decl_align: i32,
2035 node_offset_var_decl_align: Ast.Node.Offset,
20712036 /// The source location points to the linksection expression of a var decl.
2072 node_offset_var_decl_section: i32,
2037 node_offset_var_decl_section: Ast.Node.Offset,
20732038 /// The source location points to the addrspace expression of a var decl.
2074 node_offset_var_decl_addrspace: i32,
2039 node_offset_var_decl_addrspace: Ast.Node.Offset,
20752040 /// The source location points to the initializer of a var decl.
2076 node_offset_var_decl_init: i32,
2041 node_offset_var_decl_init: Ast.Node.Offset,
20772042 /// The source location points to the given argument of a builtin function call.
20782043 /// `builtin_call_node` points to the builtin call.
20792044 /// `arg_index` is the index of the argument which hte source location refers to.
20802045 node_offset_builtin_call_arg: struct {
2081 builtin_call_node: i32,
2046 builtin_call_node: Ast.Node.Offset,
20822047 arg_index: u32,
20832048 },
20842049 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls
20852050 /// to pointer cast builtins (taking the first argument of the most nested).
2086 node_offset_ptrcast_operand: i32,
2051 node_offset_ptrcast_operand: Ast.Node.Offset,
20872052 /// The source location points to the index expression of an array access
20882053 /// expression, found by taking this AST node index offset from the containing
20892054 /// base node, which points to an array access AST node. Next, navigate
20902055 /// to the index expression.
2091 node_offset_array_access_index: i32,
2056 node_offset_array_access_index: Ast.Node.Offset,
20922057 /// The source location points to the LHS of a slice expression
20932058 /// expression, found by taking this AST node index offset from the containing
20942059 /// base node, which points to a slice AST node. Next, navigate
20952060 /// to the sentinel expression.
2096 node_offset_slice_ptr: i32,
2061 node_offset_slice_ptr: Ast.Node.Offset,
20972062 /// The source location points to start expression of a slice expression
20982063 /// expression, found by taking this AST node index offset from the containing
20992064 /// base node, which points to a slice AST node. Next, navigate
21002065 /// to the sentinel expression.
2101 node_offset_slice_start: i32,
2066 node_offset_slice_start: Ast.Node.Offset,
21022067 /// The source location points to the end expression of a slice
21032068 /// expression, found by taking this AST node index offset from the containing
21042069 /// base node, which points to a slice AST node. Next, navigate
21052070 /// to the sentinel expression.
2106 node_offset_slice_end: i32,
2071 node_offset_slice_end: Ast.Node.Offset,
21072072 /// The source location points to the sentinel expression of a slice
21082073 /// expression, found by taking this AST node index offset from the containing
21092074 /// base node, which points to a slice AST node. Next, navigate
21102075 /// to the sentinel expression.
2111 node_offset_slice_sentinel: i32,
2076 node_offset_slice_sentinel: Ast.Node.Offset,
21122077 /// The source location points to the callee expression of a function
21132078 /// call expression, found by taking this AST node index offset from the containing
21142079 /// base node, which points to a function call AST node. Next, navigate
21152080 /// to the callee expression.
2116 node_offset_call_func: i32,
2081 node_offset_call_func: Ast.Node.Offset,
21172082 /// The payload is offset from the containing base node.
21182083 /// The source location points to the field name of:
21192084 /// * a field access expression (`a.b`), or
21202085 /// * the callee of a method call (`a.b()`)
2121 node_offset_field_name: i32,
2086 node_offset_field_name: Ast.Node.Offset,
21222087 /// The payload is offset from the containing base node.
21232088 /// The source location points to the field name of the operand ("b" node)
21242089 /// of a field initialization expression (`.a = b`)
2125 node_offset_field_name_init: i32,
2090 node_offset_field_name_init: Ast.Node.Offset,
21262091 /// The source location points to the pointer of a pointer deref expression,
21272092 /// found by taking this AST node index offset from the containing
21282093 /// base node, which points to a pointer deref AST node. Next, navigate
21292094 /// to the pointer expression.
2130 node_offset_deref_ptr: i32,
2095 node_offset_deref_ptr: Ast.Node.Offset,
21312096 /// The source location points to the assembly source code of an inline assembly
21322097 /// expression, found by taking this AST node index offset from the containing
21332098 /// base node, which points to inline assembly AST node. Next, navigate
21342099 /// to the asm template source code.
2135 node_offset_asm_source: i32,
2100 node_offset_asm_source: Ast.Node.Offset,
21362101 /// The source location points to the return type of an inline assembly
21372102 /// expression, found by taking this AST node index offset from the containing
21382103 /// base node, which points to inline assembly AST node. Next, navigate
21392104 /// to the return type expression.
2140 node_offset_asm_ret_ty: i32,
2105 node_offset_asm_ret_ty: Ast.Node.Offset,
21412106 /// The source location points to the condition expression of an if
21422107 /// expression, found by taking this AST node index offset from the containing
21432108 /// base node, which points to an if expression AST node. Next, navigate
21442109 /// to the condition expression.
2145 node_offset_if_cond: i32,
2110 node_offset_if_cond: Ast.Node.Offset,
21462111 /// The source location points to a binary expression, such as `a + b`, found
21472112 /// by taking this AST node index offset from the containing base node.
2148 node_offset_bin_op: i32,
2113 node_offset_bin_op: Ast.Node.Offset,
21492114 /// The source location points to the LHS of a binary expression, found
21502115 /// by taking this AST node index offset from the containing base node,
21512116 /// which points to a binary expression AST node. Next, navigate to the LHS.
2152 node_offset_bin_lhs: i32,
2117 node_offset_bin_lhs: Ast.Node.Offset,
21532118 /// The source location points to the RHS of a binary expression, found
21542119 /// by taking this AST node index offset from the containing base node,
21552120 /// which points to a binary expression AST node. Next, navigate to the RHS.
2156 node_offset_bin_rhs: i32,
2121 node_offset_bin_rhs: Ast.Node.Offset,
2122 /// The source location points to the operand of a try expression, found
2123 /// by taking this AST node index offset from the containing base node,
2124 /// which points to a try expression AST node. Next, navigate to the
2125 /// operand expression.
2126 node_offset_try_operand: Ast.Node.Offset,
21572127 /// The source location points to the operand of a switch expression, found
21582128 /// by taking this AST node index offset from the containing base node,
21592129 /// which points to a switch expression AST node. Next, navigate to the operand.
2160 node_offset_switch_operand: i32,
2130 node_offset_switch_operand: Ast.Node.Offset,
21612131 /// The source location points to the else/`_` prong of a switch expression, found
21622132 /// by taking this AST node index offset from the containing base node,
21632133 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.
2164 node_offset_switch_special_prong: i32,
2134 node_offset_switch_special_prong: Ast.Node.Offset,
21652135 /// The source location points to all the ranges of a switch expression, found
21662136 /// by taking this AST node index offset from the containing base node,
21672137 /// which points to a switch expression AST node. Next, navigate to any of the
21682138 /// range nodes. The error applies to all of them.
2169 node_offset_switch_range: i32,
2139 node_offset_switch_range: Ast.Node.Offset,
21702140 /// The source location points to the align expr of a function type
21712141 /// expression, found by taking this AST node index offset from the containing
21722142 /// base node, which points to a function type AST node. Next, navigate to
21732143 /// the calling convention node.
2174 node_offset_fn_type_align: i32,
2144 node_offset_fn_type_align: Ast.Node.Offset,
21752145 /// The source location points to the addrspace expr of a function type
21762146 /// expression, found by taking this AST node index offset from the containing
21772147 /// base node, which points to a function type AST node. Next, navigate to
21782148 /// the calling convention node.
2179 node_offset_fn_type_addrspace: i32,
2149 node_offset_fn_type_addrspace: Ast.Node.Offset,
21802150 /// The source location points to the linksection expr of a function type
21812151 /// expression, found by taking this AST node index offset from the containing
21822152 /// base node, which points to a function type AST node. Next, navigate to
21832153 /// the calling convention node.
2184 node_offset_fn_type_section: i32,
2154 node_offset_fn_type_section: Ast.Node.Offset,
21852155 /// The source location points to the calling convention of a function type
21862156 /// expression, found by taking this AST node index offset from the containing
21872157 /// base node, which points to a function type AST node. Next, navigate to
21882158 /// the calling convention node.
2189 node_offset_fn_type_cc: i32,
2159 node_offset_fn_type_cc: Ast.Node.Offset,
21902160 /// The source location points to the return type of a function type
21912161 /// expression, found by taking this AST node index offset from the containing
21922162 /// base node, which points to a function type AST node. Next, navigate to
21932163 /// the return type node.
2194 node_offset_fn_type_ret_ty: i32,
2195 node_offset_param: i32,
2196 token_offset_param: i32,
2164 node_offset_fn_type_ret_ty: Ast.Node.Offset,
2165 node_offset_param: Ast.Node.Offset,
2166 token_offset_param: Ast.TokenOffset,
21972167 /// The source location points to the type expression of an `anyframe->T`
21982168 /// expression, found by taking this AST node index offset from the containing
21992169 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate
22002170 /// to the type expression.
2201 node_offset_anyframe_type: i32,
2171 node_offset_anyframe_type: Ast.Node.Offset,
22022172 /// The source location points to the string literal of `extern "foo"`, found
22032173 /// by taking this AST node index offset from the containing
22042174 /// base node, which points to a function prototype or variable declaration
22052175 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
2206 node_offset_lib_name: i32,
2176 node_offset_lib_name: Ast.Node.Offset,
22072177 /// The source location points to the len expression of an `[N:S]T`
22082178 /// expression, found by taking this AST node index offset from the containing
22092179 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
22102180 /// to the len expression.
2211 node_offset_array_type_len: i32,
2181 node_offset_array_type_len: Ast.Node.Offset,
22122182 /// The source location points to the sentinel expression of an `[N:S]T`
22132183 /// expression, found by taking this AST node index offset from the containing
22142184 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
22152185 /// to the sentinel expression.
2216 node_offset_array_type_sentinel: i32,
2186 node_offset_array_type_sentinel: Ast.Node.Offset,
22172187 /// The source location points to the elem expression of an `[N:S]T`
22182188 /// expression, found by taking this AST node index offset from the containing
22192189 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
22202190 /// to the elem expression.
2221 node_offset_array_type_elem: i32,
2191 node_offset_array_type_elem: Ast.Node.Offset,
22222192 /// The source location points to the operand of an unary expression.
2223 node_offset_un_op: i32,
2193 node_offset_un_op: Ast.Node.Offset,
22242194 /// The source location points to the elem type of a pointer.
2225 node_offset_ptr_elem: i32,
2195 node_offset_ptr_elem: Ast.Node.Offset,
22262196 /// The source location points to the sentinel of a pointer.
2227 node_offset_ptr_sentinel: i32,
2197 node_offset_ptr_sentinel: Ast.Node.Offset,
22282198 /// The source location points to the align expr of a pointer.
2229 node_offset_ptr_align: i32,
2199 node_offset_ptr_align: Ast.Node.Offset,
22302200 /// The source location points to the addrspace expr of a pointer.
2231 node_offset_ptr_addrspace: i32,
2201 node_offset_ptr_addrspace: Ast.Node.Offset,
22322202 /// The source location points to the bit-offset of a pointer.
2233 node_offset_ptr_bitoffset: i32,
2203 node_offset_ptr_bitoffset: Ast.Node.Offset,
22342204 /// The source location points to the host size of a pointer.
2235 node_offset_ptr_hostsize: i32,
2205 node_offset_ptr_hostsize: Ast.Node.Offset,
22362206 /// The source location points to the tag type of an union or an enum.
2237 node_offset_container_tag: i32,
2207 node_offset_container_tag: Ast.Node.Offset,
22382208 /// The source location points to the default value of a field.
2239 node_offset_field_default: i32,
2209 node_offset_field_default: Ast.Node.Offset,
22402210 /// The source location points to the type of an array or struct initializer.
2241 node_offset_init_ty: i32,
2211 node_offset_init_ty: Ast.Node.Offset,
22422212 /// The source location points to the LHS of an assignment.
2243 node_offset_store_ptr: i32,
2213 node_offset_store_ptr: Ast.Node.Offset,
22442214 /// The source location points to the RHS of an assignment.
2245 node_offset_store_operand: i32,
2215 node_offset_store_operand: Ast.Node.Offset,
22462216 /// The source location points to the operand of a `return` statement, or
22472217 /// the `return` itself if there is no explicit operand.
2248 node_offset_return_operand: i32,
2218 node_offset_return_operand: Ast.Node.Offset,
22492219 /// The source location points to a for loop input.
22502220 for_input: struct {
22512221 /// Points to the for loop AST node.
2252 for_node_offset: i32,
2222 for_node_offset: Ast.Node.Offset,
22532223 /// Picks one of the inputs from the condition.
22542224 input_index: u32,
22552225 },
......@@ -2257,11 +2227,11 @@ pub const LazySrcLoc = struct {
22572227 /// by taking this AST node index offset from the containing
22582228 /// base node, which points to one of the input nodes of a for loop.
22592229 /// Next, navigate to the corresponding capture.
2260 for_capture_from_input: i32,
2230 for_capture_from_input: Ast.Node.Offset,
22612231 /// The source location points to the argument node of a function call.
22622232 call_arg: struct {
22632233 /// Points to the function call AST node.
2264 call_node_offset: i32,
2234 call_node_offset: Ast.Node.Offset,
22652235 /// The index of the argument the source location points to.
22662236 arg_index: u32,
22672237 },
......@@ -2288,25 +2258,25 @@ pub const LazySrcLoc = struct {
22882258 /// array initialization expression.
22892259 init_elem: struct {
22902260 /// Points to the AST node of the initialization expression.
2291 init_node_offset: i32,
2261 init_node_offset: Ast.Node.Offset,
22922262 /// The index of the field/element the source location points to.
22932263 elem_index: u32,
22942264 },
22952265 // The following source locations are like `init_elem`, but refer to a
22962266 // field with a specific name. If such a field is not given, the entire
22972267 // initialization expression is used instead.
2298 // The `i32` points to the AST node of a builtin call, whose *second*
2268 // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second*
22992269 // argument is the init expression.
2300 init_field_name: i32,
2301 init_field_linkage: i32,
2302 init_field_section: i32,
2303 init_field_visibility: i32,
2304 init_field_rw: i32,
2305 init_field_locality: i32,
2306 init_field_cache: i32,
2307 init_field_library: i32,
2308 init_field_thread_local: i32,
2309 init_field_dll_import: i32,
2270 init_field_name: Ast.Node.Offset,
2271 init_field_linkage: Ast.Node.Offset,
2272 init_field_section: Ast.Node.Offset,
2273 init_field_visibility: Ast.Node.Offset,
2274 init_field_rw: Ast.Node.Offset,
2275 init_field_locality: Ast.Node.Offset,
2276 init_field_cache: Ast.Node.Offset,
2277 init_field_library: Ast.Node.Offset,
2278 init_field_thread_local: Ast.Node.Offset,
2279 init_field_dll_import: Ast.Node.Offset,
23102280 /// The source location points to the value of an item in a specific
23112281 /// case of a `switch`.
23122282 switch_case_item: SwitchItem,
......@@ -2331,14 +2301,14 @@ pub const LazySrcLoc = struct {
23312301
23322302 pub const FnProtoParam = struct {
23332303 /// The offset of the function prototype AST node.
2334 fn_proto_node_offset: i32,
2304 fn_proto_node_offset: Ast.Node.Offset,
23352305 /// The index of the parameter the source location points to.
23362306 param_index: u32,
23372307 };
23382308
23392309 pub const SwitchItem = struct {
23402310 /// The offset of the switch AST node.
2341 switch_node_offset: i32,
2311 switch_node_offset: Ast.Node.Offset,
23422312 /// The index of the case to point to within this switch.
23432313 case_idx: SwitchCaseIndex,
23442314 /// The index of the item to point to within this case.
......@@ -2347,7 +2317,7 @@ pub const LazySrcLoc = struct {
23472317
23482318 pub const SwitchCapture = struct {
23492319 /// The offset of the switch AST node.
2350 switch_node_offset: i32,
2320 switch_node_offset: Ast.Node.Offset,
23512321 /// The index of the case whose capture to point to.
23522322 case_idx: SwitchCaseIndex,
23532323 };
......@@ -2369,34 +2339,34 @@ pub const LazySrcLoc = struct {
23692339
23702340 pub const ArrayCat = struct {
23712341 /// Points to the array concat AST node.
2372 array_cat_offset: i32,
2342 array_cat_offset: Ast.Node.Offset,
23732343 /// The index of the element the source location points to.
23742344 elem_index: u32,
23752345 };
23762346
23772347 pub const TupleField = struct {
23782348 /// Points to the AST node of the tuple type decaration.
2379 tuple_decl_node_offset: i32,
2349 tuple_decl_node_offset: Ast.Node.Offset,
23802350 /// The index of the tuple field the source location points to.
23812351 elem_index: u32,
23822352 };
23832353
23842354 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23852355
2386 noinline fn nodeOffsetDebug(node_offset: i32) Offset {
2356 noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset {
23872357 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
23882358 result.node_offset.trace.addAddr(@returnAddress(), "init");
23892359 return result;
23902360 }
23912361
2392 fn nodeOffsetRelease(node_offset: i32) Offset {
2362 fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset {
23932363 return .{ .node_offset = .{ .x = node_offset } };
23942364 }
23952365
23962366 /// This wraps a simple integer in debug builds so that later on we can find out
23972367 /// where in semantic analysis the value got set.
23982368 pub const TracedOffset = struct {
2399 x: i32,
2369 x: Ast.Node.Offset,
24002370 trace: std.debug.Trace = std.debug.Trace.init,
24012371
24022372 const want_tracing = false;
......@@ -2421,7 +2391,7 @@ pub const LazySrcLoc = struct {
24212391
24222392 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,
24232393 // which may not exist e.g. in the case of errors in ZON files.
2424 if (zir_inst == .main_struct_inst) return .{ file, 0 };
2394 if (zir_inst == .main_struct_inst) return .{ file, .root };
24252395
24262396 // Otherwise, make sure ZIR is loaded.
24272397 const zir = file.zir.?;
......@@ -2454,7 +2424,7 @@ pub const LazySrcLoc = struct {
24542424 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {
24552425 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{
24562426 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),
2457 0,
2427 .root,
24582428 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
24592429 return .{
24602430 .file_scope = file,
......@@ -4023,7 +3993,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {
40233993 const ip = &zcu.intern_pool;
40243994 return .{
40253995 .base_node_inst = ip.getNav(nav_index).srcInst(ip),
4026 .offset = LazySrcLoc.Offset.nodeOffset(0),
3996 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
40273997 };
40283998}
40293999
src/Zcu/PerThread.zig+11-11
......@@ -841,7 +841,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
841841 .comptime_reason = .{ .reason = .{
842842 .src = .{
843843 .base_node_inst = comptime_unit.zir_index,
844 .offset = .{ .token_offset = 0 },
844 .offset = .{ .token_offset = .zero },
845845 },
846846 .r = .{ .simple = .comptime_keyword },
847847 } },
......@@ -1042,11 +1042,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
10421042 const zir_decl = zir.getDeclaration(inst_resolved.inst);
10431043 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
10441044
1045 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1046 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });
1047 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
1048 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
1049 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
1045 const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero });
1046 const init_src = block.src(.{ .node_offset_var_decl_init = .zero });
1047 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
1048 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
1049 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
10501050
10511051 block.comptime_reason = .{ .reason = .{
10521052 .src = init_src,
......@@ -1135,7 +1135,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
11351135 break :l zir.nullTerminatedString(zir_decl.lib_name);
11361136 } else null;
11371137 if (lib_name) |l| {
1138 const lib_name_src = block.src(.{ .node_offset_lib_name = 0 });
1138 const lib_name_src = block.src(.{ .node_offset_lib_name = .zero });
11391139 try sema.handleExternLibName(&block, lib_name_src, l);
11401140 }
11411141 break :val .fromInterned(try pt.getExtern(.{
......@@ -1233,7 +1233,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
12331233 }
12341234
12351235 if (zir_decl.linkage == .@"export") {
1236 const export_src = block.src(.{ .token_offset = @intFromBool(zir_decl.is_pub) });
1236 const export_src = block.src(.{ .token_offset = @enumFromInt(@intFromBool(zir_decl.is_pub)) });
12371237 const name_slice = zir.nullTerminatedString(zir_decl.name);
12381238 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
12391239 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);
......@@ -1414,7 +1414,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
14141414 const zir_decl = zir.getDeclaration(inst_resolved.inst);
14151415 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
14161416
1417 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
1417 const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero });
14181418
14191419 block.comptime_reason = .{ .reason = .{
14201420 .src = ty_src,
......@@ -2743,7 +2743,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27432743 if (sema.fn_ret_ty_ies) |ies| {
27442744 sema.resolveInferredErrorSetPtr(&inner_block, .{
27452745 .base_node_inst = inner_block.src_base_inst,
2746 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),
2746 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero),
27472747 }, ies) catch |err| switch (err) {
27482748 error.ComptimeReturn => unreachable,
27492749 error.ComptimeBreak => unreachable,
......@@ -2762,7 +2762,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
27622762 // result in circular dependency errors.
27632763 // TODO: this can go away once we fix backends having to resolve `StackTrace`.
27642764 // The codegen timing guarantees that the parameter types will be populated.
2765 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(0)) catch |err| switch (err) {
2765 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(.zero)) catch |err| switch (err) {
27662766 error.ComptimeReturn => unreachable,
27672767 error.ComptimeBreak => unreachable,
27682768 else => |e| return e,
src/main.zig+13-7
......@@ -5224,7 +5224,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
52245224 .arena = std.heap.ArenaAllocator.init(gpa),
52255225 .location = .{ .relative_path = build_mod.root },
52265226 .location_tok = 0,
5227 .hash_tok = 0,
5227 .hash_tok = .none,
52285228 .name_tok = 0,
52295229 .lazy_status = .eager,
52305230 .parent_package_root = build_mod.root,
......@@ -6285,8 +6285,10 @@ fn cmdAstCheck(
62856285 file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset));
62866286 const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len *
62876287 (@sizeOf(Ast.Node.Tag) +
6288 @sizeOf(Ast.Node.Data) +
6289 @sizeOf(Ast.TokenIndex));
6288 @sizeOf(Ast.TokenIndex) +
6289 // Here we don't use @sizeOf(Ast.Node.Data) because it would include
6290 // the debug safety tag but we want to measure release size.
6291 8);
62906292 const instruction_bytes = file.zir.?.instructions.len *
62916293 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
62926294 // the debug safety tag but we want to measure release size.
......@@ -7126,7 +7128,7 @@ fn cmdFetch(
71267128 .arena = std.heap.ArenaAllocator.init(gpa),
71277129 .location = .{ .path_or_url = path_or_url },
71287130 .location_tok = 0,
7129 .hash_tok = 0,
7131 .hash_tok = .none,
71307132 .name_tok = 0,
71317133 .lazy_status = .eager,
71327134 .parent_package_root = undefined,
......@@ -7282,15 +7284,19 @@ fn cmdFetch(
72827284
72837285 warn("overwriting existing dependency named '{s}'", .{name});
72847286 try fixups.replace_nodes_with_string.put(gpa, dep.location_node, location_replace);
7285 try fixups.replace_nodes_with_string.put(gpa, dep.hash_node, hash_replace);
7287 if (dep.hash_node.unwrap()) |hash_node| {
7288 try fixups.replace_nodes_with_string.put(gpa, hash_node, hash_replace);
7289 } else {
7290 // https://github.com/ziglang/zig/issues/21690
7291 }
72867292 } else if (manifest.dependencies.count() > 0) {
72877293 // Add fixup for adding another dependency.
72887294 const deps = manifest.dependencies.values();
72897295 const last_dep_node = deps[deps.len - 1].node;
72907296 try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text);
7291 } else if (manifest.dependencies_node != 0) {
7297 } else if (manifest.dependencies_node.unwrap()) |dependencies_node| {
72927298 // Add fixup for replacing the entire dependencies struct.
7293 try fixups.replace_nodes_with_string.put(gpa, manifest.dependencies_node, dependencies_init);
7299 try fixups.replace_nodes_with_string.put(gpa, dependencies_node, dependencies_init);
72947300 } else {
72957301 // Add fixup for adding dependencies struct.
72967302 try fixups.append_string_after_node.put(gpa, manifest.version_node, dependencies_text);
src/print_zir.zig+22-23
......@@ -24,7 +24,7 @@ pub fn renderAsTextToFile(
2424 .file = scope_file,
2525 .code = scope_file.zir.?,
2626 .indent = 0,
27 .parent_decl_node = 0,
27 .parent_decl_node = .root,
2828 .recurse_decls = true,
2929 .recurse_blocks = true,
3030 };
......@@ -185,10 +185,6 @@ const Writer = struct {
185185 }
186186 } = .{},
187187
188 fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index {
189 return @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node)));
190 }
191
192188 fn writeInstToStream(
193189 self: *Writer,
194190 stream: anytype,
......@@ -595,7 +591,7 @@ const Writer = struct {
595591 const prev_parent_decl_node = self.parent_decl_node;
596592 self.parent_decl_node = inst_data.node;
597593 defer self.parent_decl_node = prev_parent_decl_node;
598 try self.writeSrcNode(stream, 0);
594 try self.writeSrcNode(stream, .zero);
599595 },
600596
601597 .builtin_extern,
......@@ -631,7 +627,8 @@ const Writer = struct {
631627
632628 fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
633629 try stream.writeAll(")) ");
634 try self.writeSrcNode(stream, @bitCast(extended.operand));
630 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
631 try self.writeSrcNode(stream, src_node);
635632 }
636633
637634 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
......@@ -1579,7 +1576,7 @@ const Writer = struct {
15791576 try stream.writeByteNTimes(' ', self.indent);
15801577 try stream.writeAll("}) ");
15811578 }
1582 try self.writeSrcNode(stream, 0);
1579 try self.writeSrcNode(stream, .zero);
15831580 }
15841581
15851582 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
......@@ -1659,7 +1656,7 @@ const Writer = struct {
16591656
16601657 if (fields_len == 0) {
16611658 try stream.writeAll("}) ");
1662 try self.writeSrcNode(stream, 0);
1659 try self.writeSrcNode(stream, .zero);
16631660 return;
16641661 }
16651662 try stream.writeAll(", ");
......@@ -1730,7 +1727,7 @@ const Writer = struct {
17301727 self.indent -= 2;
17311728 try stream.writeByteNTimes(' ', self.indent);
17321729 try stream.writeAll("}) ");
1733 try self.writeSrcNode(stream, 0);
1730 try self.writeSrcNode(stream, .zero);
17341731 }
17351732
17361733 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
......@@ -1849,7 +1846,7 @@ const Writer = struct {
18491846 try stream.writeByteNTimes(' ', self.indent);
18501847 try stream.writeAll("}) ");
18511848 }
1852 try self.writeSrcNode(stream, 0);
1849 try self.writeSrcNode(stream, .zero);
18531850 }
18541851
18551852 fn writeOpaqueDecl(
......@@ -1893,7 +1890,7 @@ const Writer = struct {
18931890 try stream.writeByteNTimes(' ', self.indent);
18941891 try stream.writeAll("}) ");
18951892 }
1896 try self.writeSrcNode(stream, 0);
1893 try self.writeSrcNode(stream, .zero);
18971894 }
18981895
18991896 fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
......@@ -2539,7 +2536,7 @@ const Writer = struct {
25392536 ret_ty_body: []const Zir.Inst.Index,
25402537 ret_ty_is_generic: bool,
25412538 body: []const Zir.Inst.Index,
2542 src_node: i32,
2539 src_node: Ast.Node.Offset,
25432540 src_locs: Zir.Inst.Func.SrcLocs,
25442541 noalias_bits: u32,
25452542 ) !void {
......@@ -2647,18 +2644,20 @@ const Writer = struct {
26472644 }
26482645
26492646 try stream.writeAll(") ");
2650 try self.writeSrcNode(stream, 0);
2647 try self.writeSrcNode(stream, .zero);
26512648 }
26522649
26532650 fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
26542651 try stream.print("{d})) ", .{extended.small});
2655 try self.writeSrcNode(stream, @bitCast(extended.operand));
2652 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2653 try self.writeSrcNode(stream, src_node);
26562654 }
26572655
26582656 fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
26592657 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
26602658 try stream.print("{s})) ", .{@tagName(val)});
2661 try self.writeSrcNode(stream, @bitCast(extended.operand));
2659 const src_node: Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
2660 try self.writeSrcNode(stream, src_node);
26622661 }
26632662
26642663 fn writeInplaceArithResultTy(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
......@@ -2760,9 +2759,9 @@ const Writer = struct {
27602759 try stream.writeAll(name);
27612760 }
27622761
2763 fn writeSrcNode(self: *Writer, stream: anytype, src_node: i32) !void {
2762 fn writeSrcNode(self: *Writer, stream: anytype, src_node: Ast.Node.Offset) !void {
27642763 const tree = self.file.tree orelse return;
2765 const abs_node = self.relativeToNodeIndex(src_node);
2764 const abs_node = src_node.toAbsolute(self.parent_decl_node);
27662765 const src_span = tree.nodeToSpan(abs_node);
27672766 const start = self.line_col_cursor.find(tree.source, src_span.start);
27682767 const end = self.line_col_cursor.find(tree.source, src_span.end);
......@@ -2772,10 +2771,10 @@ const Writer = struct {
27722771 });
27732772 }
27742773
2775 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void {
2774 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void {
27762775 const tree = self.file.tree orelse return;
2777 const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok;
2778 const span_start = tree.tokens.items(.start)[abs_tok];
2776 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2777 const span_start = tree.tokenStart(abs_tok);
27792778 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
27802779 const start = self.line_col_cursor.find(tree.source, span_start);
27812780 const end = self.line_col_cursor.find(tree.source, span_end);
......@@ -2785,9 +2784,9 @@ const Writer = struct {
27852784 });
27862785 }
27872786
2788 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void {
2787 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void {
27892788 const tree = self.file.tree orelse return;
2790 const span_start = tree.tokens.items(.start)[src_tok];
2789 const span_start = tree.tokenStart(src_tok);
27912790 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
27922791 const start = self.line_col_cursor.find(tree.source, span_start);
27932792 const end = self.line_col_cursor.find(tree.source, span_end);
test/cases/translate_c/continue_from_while.c created+14
......@@ -0,0 +1,14 @@
1void foo() {
2 for (;;) {
3 continue;
4 }
5}
6
7// translate-c
8// c_frontend=clang
9//
10// pub export fn foo() void {
11// while (true) {
12// continue;
13// }
14// }