authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2025-02-24 18:55:45+01:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2025-03-07 22:22:01+01:00
logca6fb30e992fd86ee41a6510ef731e86f5de77c9
tree72fc291a37d62fb3eee341ae1203c559968c0856
parent6dcd8f4f75098c716ed617a388c96238c70aff17
signaturebadge-check Signed by SSH key SHA256:HYC3SjXQcAt6uwv9pu/6OoVQ2rUH8rb5zKiUHSe9uxk

std.zig.Ast: improve type safety

This commits adds the following distinct integer types to std.zig.Ast: - OptionalTokenIndex - TokenOffset - OptionalTokenOffset - Node.OptionalIndex - Node.Offset - Node.OptionalOffset The `Node.Index` type has also been converted to a distinct type while `TokenIndex` remains unchanged. `Ast.Node.Data` has also been changed to a (untagged) union to provide safety checks.

25 files changed, 4559 insertions(+), 5056 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 = 0,
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+144-207
......@@ -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| {
......@@ -239,46 +230,27 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
239230 },
240231
241232 .@"errdefer" => {
242 const expr = datas[node].rhs;
233 const expr = ast.nodeData(node).opt_token_and_node[1];
243234 return walkExpression(w, expr);
244235 },
245236
246 .@"defer" => {
247 const expr = datas[node].rhs;
248 return walkExpression(w, expr);
249 },
250 .@"comptime", .@"nosuspend" => {
251 const block = datas[node].lhs;
252 return walkExpression(w, block);
253 },
254
255 .@"suspend" => {
256 const body = datas[node].lhs;
257 return walkExpression(w, body);
258 },
259
260 .@"catch" => {
261 try walkExpression(w, datas[node].lhs); // target
262 try walkExpression(w, datas[node].rhs); // fallback
237 .@"defer",
238 .@"comptime",
239 .@"nosuspend",
240 .@"suspend",
241 => {
242 return walkExpression(w, ast.nodeData(node).node);
263243 },
264244
265245 .field_access => {
266 const field_access = datas[node];
267 try walkExpression(w, field_access.lhs);
246 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
268247 },
269248
270 .error_union,
271 .switch_range,
272 => {
273 const infix = datas[node];
274 try walkExpression(w, infix.lhs);
275 return walkExpression(w, infix.rhs);
276 },
277249 .for_range => {
278 const infix = datas[node];
279 try walkExpression(w, infix.lhs);
280 if (infix.rhs != 0) {
281 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);
282254 }
283255 },
284256
......@@ -328,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
328300 .sub,
329301 .sub_wrap,
330302 .sub_sat,
303 .@"catch",
304 .error_union,
305 .switch_range,
331306 .@"orelse",
307 .array_access,
332308 => {
333 const infix = datas[node];
334 try walkExpression(w, infix.lhs);
335 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);
336312 },
337313
338314 .assign_destructure => {
339315 const full = ast.assignDestructure(node);
340316 for (full.ast.variables) |variable_node| {
341 switch (node_tags[variable_node]) {
317 switch (ast.nodeTag(variable_node)) {
342318 .global_var_decl,
343319 .local_var_decl,
344320 .simple_var_decl,
......@@ -357,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
357333 .negation_wrap,
358334 .optional_type,
359335 .address_of,
360 => {
361 return walkExpression(w, datas[node].lhs);
362 },
363
364336 .@"try",
365337 .@"resume",
366338 .@"await",
339 .deref,
367340 => {
368 return walkExpression(w, datas[node].lhs);
341 return walkExpression(w, ast.nodeData(node).node);
369342 },
370343
371344 .array_type,
......@@ -417,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
417390 return walkCall(w, ast.fullCall(&buf, node).?);
418391 },
419392
420 .array_access => {
421 const suffix = datas[node];
422 try walkExpression(w, suffix.lhs);
423 try walkExpression(w, suffix.rhs);
424 },
425
426393 .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?),
427394
428 .deref => {
429 try walkExpression(w, datas[node].lhs);
430 },
431
432395 .unwrap_optional => {
433 try walkExpression(w, datas[node].lhs);
396 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
434397 },
435398
436399 .@"break" => {
437 const label_token = datas[node].lhs;
438 const target = datas[node].rhs;
439 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) {
440402 // no expressions
441 } else if (label_token == 0 and target != 0) {
442 try walkExpression(w, target);
443 } else if (label_token != 0 and target == 0) {
444 try walkIdentifier(w, label_token);
445 } else if (label_token != 0 and target != 0) {
446 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().?);
447409 }
448410 },
449411
450412 .@"continue" => {
451 const label = datas[node].lhs;
452 if (label != 0) {
453 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);
454416 }
455417 },
456418
457419 .@"return" => {
458 if (datas[node].lhs != 0) {
459 try walkExpression(w, datas[node].lhs);
420 if (ast.nodeData(node).opt_node.unwrap()) |lhs| {
421 try walkExpression(w, lhs);
460422 }
461423 },
462424
463425 .grouped_expression => {
464 try walkExpression(w, datas[node].lhs);
426 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
465427 },
466428
467429 .container_decl,
......@@ -482,13 +444,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
482444 },
483445
484446 .error_set_decl => {
485 const error_token = main_tokens[node];
447 const error_token = ast.nodeMainToken(node);
486448 const lbrace = error_token + 1;
487 const rbrace = datas[node].rhs;
449 const rbrace = ast.nodeData(node).token;
488450
489451 var i = lbrace + 1;
490452 while (i < rbrace) : (i += 1) {
491 switch (token_tags[i]) {
453 switch (ast.tokenTag(i)) {
492454 .doc_comment => unreachable, // TODO
493455 .identifier => try walkIdentifier(w, i),
494456 .comma => {},
......@@ -517,20 +479,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
517479 },
518480
519481 .anyframe_type => {
520 if (datas[node].rhs != 0) {
521 return walkExpression(w, datas[node].rhs);
522 }
482 _, const child_type = ast.nodeData(node).token_and_node;
483 return walkExpression(w, child_type);
523484 },
524485
525486 .@"switch",
526487 .switch_comma,
527488 => {
528 const condition = datas[node].lhs;
529 const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange);
530 const cases = ast.extra_data[extra.start..extra.end];
531
532 try walkExpression(w, condition); // condition expression
533 try walkExpressions(w, cases);
489 const full = ast.fullSwitch(node).?;
490 try walkExpression(w, full.ast.condition); // condition expression
491 try walkExpressions(w, full.ast.cases);
534492 },
535493
536494 .switch_case_one,
......@@ -557,7 +515,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
557515 => return walkAsm(w, ast.fullAsm(node).?),
558516
559517 .enum_literal => {
560 return walkIdentifier(w, main_tokens[node]); // name
518 return walkIdentifier(w, ast.nodeMainToken(node)); // name
561519 },
562520
563521 .fn_decl => unreachable,
......@@ -579,66 +537,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
579537fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {
580538 _ = decl_node;
581539
582 if (var_decl.ast.type_node != 0) {
583 try walkExpression(w, var_decl.ast.type_node);
540 if (var_decl.ast.type_node.unwrap()) |type_node| {
541 try walkExpression(w, type_node);
584542 }
585543
586 if (var_decl.ast.align_node != 0) {
587 try walkExpression(w, var_decl.ast.align_node);
544 if (var_decl.ast.align_node.unwrap()) |align_node| {
545 try walkExpression(w, align_node);
588546 }
589547
590 if (var_decl.ast.addrspace_node != 0) {
591 try walkExpression(w, var_decl.ast.addrspace_node);
548 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
549 try walkExpression(w, addrspace_node);
592550 }
593551
594 if (var_decl.ast.section_node != 0) {
595 try walkExpression(w, var_decl.ast.section_node);
552 if (var_decl.ast.section_node.unwrap()) |section_node| {
553 try walkExpression(w, section_node);
596554 }
597555
598 if (var_decl.ast.init_node != 0) {
599 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
600 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
556 if (var_decl.ast.init_node.unwrap()) |init_node| {
557 if (!isUndefinedIdent(w.ast, init_node)) {
558 try w.transformations.append(.{ .replace_with_undef = init_node });
601559 }
602 try walkExpression(w, var_decl.ast.init_node);
560 try walkExpression(w, init_node);
603561 }
604562}
605563
606564fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
607565 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
608566
609 if (var_decl.ast.type_node != 0) {
610 try walkExpression(w, var_decl.ast.type_node);
567 if (var_decl.ast.type_node.unwrap()) |type_node| {
568 try walkExpression(w, type_node);
611569 }
612570
613 if (var_decl.ast.align_node != 0) {
614 try walkExpression(w, var_decl.ast.align_node);
571 if (var_decl.ast.align_node.unwrap()) |align_node| {
572 try walkExpression(w, align_node);
615573 }
616574
617 if (var_decl.ast.addrspace_node != 0) {
618 try walkExpression(w, var_decl.ast.addrspace_node);
575 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
576 try walkExpression(w, addrspace_node);
619577 }
620578
621 if (var_decl.ast.section_node != 0) {
622 try walkExpression(w, var_decl.ast.section_node);
579 if (var_decl.ast.section_node.unwrap()) |section_node| {
580 try walkExpression(w, section_node);
623581 }
624582
625 if (var_decl.ast.init_node != 0) {
626 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {
627 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });
583 if (var_decl.ast.init_node.unwrap()) |init_node| {
584 if (!isUndefinedIdent(w.ast, init_node)) {
585 try w.transformations.append(.{ .replace_with_undef = init_node });
628586 }
629 try walkExpression(w, var_decl.ast.init_node);
587 try walkExpression(w, init_node);
630588 }
631589}
632590
633591fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {
634 if (field.ast.type_expr != 0) {
635 try walkExpression(w, field.ast.type_expr); // type
592 if (field.ast.type_expr.unwrap()) |type_expr| {
593 try walkExpression(w, type_expr); // type
636594 }
637 if (field.ast.align_expr != 0) {
638 try walkExpression(w, field.ast.align_expr); // alignment
595 if (field.ast.align_expr.unwrap()) |align_expr| {
596 try walkExpression(w, align_expr); // alignment
639597 }
640 if (field.ast.value_expr != 0) {
641 try walkExpression(w, field.ast.value_expr); // value
598 if (field.ast.value_expr.unwrap()) |value_expr| {
599 try walkExpression(w, value_expr); // value
642600 }
643601}
644602
......@@ -649,18 +607,17 @@ fn walkBlock(
649607) Error!void {
650608 _ = block_node;
651609 const ast = w.ast;
652 const node_tags = ast.nodes.items(.tag);
653610
654611 for (statements) |stmt| {
655 switch (node_tags[stmt]) {
612 switch (ast.nodeTag(stmt)) {
656613 .global_var_decl,
657614 .local_var_decl,
658615 .simple_var_decl,
659616 .aligned_var_decl,
660617 => {
661618 const var_decl = ast.fullVarDecl(stmt).?;
662 if (var_decl.ast.init_node != 0 and
663 isUndefinedIdent(w.ast, var_decl.ast.init_node))
619 if (var_decl.ast.init_node != .none and
620 isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?))
664621 {
665622 try w.transformations.append(.{ .delete_var_decl = .{
666623 .var_decl_node = stmt,
......@@ -691,15 +648,15 @@ fn walkBlock(
691648
692649fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {
693650 try walkExpression(w, array_type.ast.elem_count);
694 if (array_type.ast.sentinel != 0) {
695 try walkExpression(w, array_type.ast.sentinel);
651 if (array_type.ast.sentinel.unwrap()) |sentinel| {
652 try walkExpression(w, sentinel);
696653 }
697654 return walkExpression(w, array_type.ast.elem_type);
698655}
699656
700657fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {
701 if (array_init.ast.type_expr != 0) {
702 try walkExpression(w, array_init.ast.type_expr); // T
658 if (array_init.ast.type_expr.unwrap()) |type_expr| {
659 try walkExpression(w, type_expr); // T
703660 }
704661 for (array_init.ast.elements) |elem_init| {
705662 try walkExpression(w, elem_init);
......@@ -712,8 +669,8 @@ fn walkStructInit(
712669 struct_init: Ast.full.StructInit,
713670) Error!void {
714671 _ = struct_node;
715 if (struct_init.ast.type_expr != 0) {
716 try walkExpression(w, struct_init.ast.type_expr); // T
672 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
673 try walkExpression(w, type_expr); // T
717674 }
718675 for (struct_init.ast.fields) |field_init| {
719676 try walkExpression(w, field_init);
......@@ -733,18 +690,17 @@ fn walkSlice(
733690 _ = slice_node;
734691 try walkExpression(w, slice.ast.sliced);
735692 try walkExpression(w, slice.ast.start);
736 if (slice.ast.end != 0) {
737 try walkExpression(w, slice.ast.end);
693 if (slice.ast.end.unwrap()) |end| {
694 try walkExpression(w, end);
738695 }
739 if (slice.ast.sentinel != 0) {
740 try walkExpression(w, slice.ast.sentinel);
696 if (slice.ast.sentinel.unwrap()) |sentinel| {
697 try walkExpression(w, sentinel);
741698 }
742699}
743700
744701fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {
745702 const ast = w.ast;
746 const token_tags = ast.tokens.items(.tag);
747 assert(token_tags[name_ident] == .identifier);
703 assert(ast.tokenTag(name_ident) == .identifier);
748704 const name_bytes = ast.tokenSlice(name_ident);
749705 _ = w.unreferenced_globals.swapRemove(name_bytes);
750706}
......@@ -760,8 +716,8 @@ fn walkContainerDecl(
760716 container_decl: Ast.full.ContainerDecl,
761717) Error!void {
762718 _ = container_decl_node;
763 if (container_decl.ast.arg != 0) {
764 try walkExpression(w, container_decl.ast.arg);
719 if (container_decl.ast.arg.unwrap()) |arg| {
720 try walkExpression(w, arg);
765721 }
766722 try walkMembers(w, container_decl.ast.members);
767723}
......@@ -772,14 +728,13 @@ fn walkBuiltinCall(
772728 params: []const Ast.Node.Index,
773729) Error!void {
774730 const ast = w.ast;
775 const main_tokens = ast.nodes.items(.main_token);
776 const builtin_token = main_tokens[call_node];
731 const builtin_token = ast.nodeMainToken(call_node);
777732 const builtin_name = ast.tokenSlice(builtin_token);
778733 const info = BuiltinFn.list.get(builtin_name).?;
779734 switch (info.tag) {
780735 .import => {
781736 const operand_node = params[0];
782 const str_lit_token = main_tokens[operand_node];
737 const str_lit_token = ast.nodeMainToken(operand_node);
783738 const token_bytes = ast.tokenSlice(str_lit_token);
784739 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {
785740 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch
......@@ -808,29 +763,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {
808763 {
809764 var it = fn_proto.iterate(ast);
810765 while (it.next()) |param| {
811 if (param.type_expr != 0) {
812 try walkExpression(w, param.type_expr);
766 if (param.type_expr) |type_expr| {
767 try walkExpression(w, type_expr);
813768 }
814769 }
815770 }
816771
817 if (fn_proto.ast.align_expr != 0) {
818 try walkExpression(w, fn_proto.ast.align_expr);
772 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
773 try walkExpression(w, align_expr);
819774 }
820775
821 if (fn_proto.ast.addrspace_expr != 0) {
822 try walkExpression(w, fn_proto.ast.addrspace_expr);
776 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
777 try walkExpression(w, addrspace_expr);
823778 }
824779
825 if (fn_proto.ast.section_expr != 0) {
826 try walkExpression(w, fn_proto.ast.section_expr);
780 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
781 try walkExpression(w, section_expr);
827782 }
828783
829 if (fn_proto.ast.callconv_expr != 0) {
830 try walkExpression(w, fn_proto.ast.callconv_expr);
784 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
785 try walkExpression(w, callconv_expr);
831786 }
832787
833 try walkExpression(w, fn_proto.ast.return_type);
788 const return_type = fn_proto.ast.return_type.unwrap().?;
789 try walkExpression(w, return_type);
834790}
835791
836792fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {
......@@ -847,16 +803,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {
847803}
848804
849805fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {
850 assert(while_node.ast.cond_expr != 0);
851 assert(while_node.ast.then_expr != 0);
852
853806 // Perform these transformations in this priority order:
854807 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
855808 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
856809 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
857810 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
858811 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and
859 (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr)))
812 (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?)))
860813 {
861814 try w.transformations.ensureUnusedCapacity(1);
862815 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });
......@@ -873,45 +826,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E
873826 try w.transformations.ensureUnusedCapacity(1);
874827 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
875828 .to_replace = node_index,
876 .replacement = while_node.ast.else_expr,
829 .replacement = while_node.ast.else_expr.unwrap().?,
877830 } });
878831 }
879832
880833 try walkExpression(w, while_node.ast.cond_expr); // condition
881834
882 if (while_node.ast.cont_expr != 0) {
883 try walkExpression(w, while_node.ast.cont_expr);
835 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
836 try walkExpression(w, cont_expr);
884837 }
885838
886 if (while_node.ast.then_expr != 0) {
887 try walkExpression(w, while_node.ast.then_expr);
888 }
889 if (while_node.ast.else_expr != 0) {
890 try walkExpression(w, while_node.ast.else_expr);
839 try walkExpression(w, while_node.ast.then_expr);
840
841 if (while_node.ast.else_expr.unwrap()) |else_expr| {
842 try walkExpression(w, else_expr);
891843 }
892844}
893845
894846fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {
895847 try walkParamList(w, for_node.ast.inputs);
896 if (for_node.ast.then_expr != 0) {
897 try walkExpression(w, for_node.ast.then_expr);
898 }
899 if (for_node.ast.else_expr != 0) {
900 try walkExpression(w, for_node.ast.else_expr);
848 try walkExpression(w, for_node.ast.then_expr);
849 if (for_node.ast.else_expr.unwrap()) |else_expr| {
850 try walkExpression(w, else_expr);
901851 }
902852}
903853
904854fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {
905 assert(if_node.ast.cond_expr != 0);
906 assert(if_node.ast.then_expr != 0);
907
908855 // Perform these transformations in this priority order:
909856 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
910857 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
911858 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
912859 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
913860 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and
914 (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr)))
861 (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?)))
915862 {
916863 try w.transformations.ensureUnusedCapacity(1);
917864 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });
......@@ -928,17 +875,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void
928875 try w.transformations.ensureUnusedCapacity(1);
929876 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
930877 .to_replace = node_index,
931 .replacement = if_node.ast.else_expr,
878 .replacement = if_node.ast.else_expr.unwrap().?,
932879 } });
933880 }
934881
935882 try walkExpression(w, if_node.ast.cond_expr); // condition
936
937 if (if_node.ast.then_expr != 0) {
938 try walkExpression(w, if_node.ast.then_expr);
939 }
940 if (if_node.ast.else_expr != 0) {
941 try walkExpression(w, if_node.ast.else_expr);
883 try walkExpression(w, if_node.ast.then_expr);
884 if (if_node.ast.else_expr.unwrap()) |else_expr| {
885 try walkExpression(w, else_expr);
942886 }
943887}
944888
......@@ -958,9 +902,8 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {
958902/// Check if it is already gutted (i.e. its body replaced with `@trap()`).
959903fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {
960904 // skip over discards
961 const node_tags = ast.nodes.items(.tag);
962905 var statements_buf: [2]Ast.Node.Index = undefined;
963 const statements = switch (node_tags[body_node]) {
906 const statements = switch (ast.nodeTag(body_node)) {
964907 .block_two,
965908 .block_two_semicolon,
966909 .block,
......@@ -988,10 +931,7 @@ const StmtCategory = enum {
988931};
989932
990933fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
991 const node_tags = ast.nodes.items(.tag);
992 const datas = ast.nodes.items(.data);
993 const main_tokens = ast.nodes.items(.main_token);
994 switch (node_tags[stmt]) {
934 switch (ast.nodeTag(stmt)) {
995935 .builtin_call_two,
996936 .builtin_call_two_comma,
997937 .builtin_call,
......@@ -999,12 +939,12 @@ fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
999939 => {
1000940 var buf: [2]Ast.Node.Index = undefined;
1001941 const params = ast.builtinCallParams(&buf, stmt).?;
1002 return categorizeBuiltinCall(ast, main_tokens[stmt], params);
942 return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params);
1003943 },
1004944 .assign => {
1005 const infix = datas[stmt];
1006 if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) {
1007 const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]);
945 const lhs, const rhs = ast.nodeData(stmt).node_and_node;
946 if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) {
947 const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs));
1008948 if (std.mem.eql(u8, name_bytes, "undefined")) {
1009949 return .discard_undefined;
1010950 } else {
......@@ -1046,11 +986,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {
1046986}
1047987
1048988fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {
1049 const node_tags = ast.nodes.items(.tag);
1050 const main_tokens = ast.nodes.items(.main_token);
1051 switch (node_tags[node]) {
989 switch (ast.nodeTag(node)) {
1052990 .identifier => {
1053 const token_index = main_tokens[node];
991 const token_index = ast.nodeMainToken(node);
1054992 const name_bytes = ast.tokenSlice(token_index);
1055993 return std.mem.eql(u8, name_bytes, string);
1056994 },
......@@ -1059,11 +997,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo
1059997}
1060998
1061999fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {
1062 const node_tags = ast.nodes.items(.tag);
1063 const node_data = ast.nodes.items(.data);
1064 switch (node_tags[node]) {
1000 switch (ast.nodeTag(node)) {
10651001 .block_two => {
1066 return node_data[node].lhs == 0 and node_data[node].rhs == 0;
1002 const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node;
1003 return opt_lhs == .none and opt_rhs == .none;
10671004 },
10681005 else => return false,
10691006 }
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+71-94
......@@ -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)) {
......@@ -259,9 +253,9 @@ pub const File = struct {
259253 .@"if",
260254 => {
261255 const if_full = ast.fullIf(node).?;
262 if (if_full.ast.else_expr != 0) {
256 if (if_full.ast.else_expr.unwrap()) |else_expr| {
263257 const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr);
264 const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr);
258 const else_cat = categorize_expr_deep(file_index, else_expr);
265259 if (then_cat == .type_type and else_cat == .type_type) {
266260 return .type_type;
267261 } else if (then_cat == .error_set and else_cat == .error_set) {
......@@ -320,11 +314,10 @@ pub const File = struct {
320314 params: []const Ast.Node.Index,
321315 ) Category {
322316 const ast = file_index.get_ast();
323 const main_tokens = ast.nodes.items(.main_token);
324 const builtin_token = main_tokens[node];
317 const builtin_token = ast.nodeMainToken(node);
325318 const builtin_name = ast.tokenSlice(builtin_token);
326319 if (std.mem.eql(u8, builtin_name, "@import")) {
327 const str_lit_token = main_tokens[params[0]];
320 const str_lit_token = ast.nodeMainToken(params[0]);
328321 const str_bytes = ast.tokenSlice(str_lit_token);
329322 const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM");
330323 defer gpa.free(file_path);
......@@ -357,14 +350,12 @@ pub const File = struct {
357350
358351 fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category {
359352 const ast = file_index.get_ast();
360 const node_datas = ast.nodes.items(.data);
361 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
362 const case_nodes = ast.extra_data[extra.start..extra.end];
353 const full = ast.fullSwitch(node).?;
363354 var all_type_type = true;
364355 var all_error_set = true;
365356 var any_type = false;
366 if (case_nodes.len == 0) return .{ .global_const = node };
367 for (case_nodes) |case_node| {
357 if (full.ast.cases.len == 0) return .{ .global_const = node };
358 for (full.ast.cases) |case_node| {
368359 const case = ast.fullSwitchCase(case_node).?;
369360 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {
370361 .type_type => {
......@@ -410,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {
410401 const scope = try gpa.create(Scope);
411402 scope.* = .{ .tag = .top };
412403
413 const decl_index = try file_index.add_decl(0, .none);
414 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());
415406
416407 const file = file_index.get();
417408 shrinkToFit(&file.ident_decls);
......@@ -505,13 +496,12 @@ pub const Scope = struct {
505496 }
506497
507498 pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index {
508 const main_tokens = ast.nodes.items(.main_token);
509499 var it: *Scope = start_scope;
510500 while (true) switch (it.tag) {
511501 .top => break,
512502 .local => {
513503 const local: *Local = @alignCast(@fieldParentPtr("base", it));
514 const name_token = main_tokens[local.var_node] + 1;
504 const name_token = ast.nodeMainToken(local.var_node) + 1;
515505 const ident_name = ast.tokenSlice(name_token);
516506 if (std.mem.eql(u8, ident_name, name)) {
517507 return local.var_node;
......@@ -538,8 +528,6 @@ fn struct_decl(
538528 container_decl: Ast.full.ContainerDecl,
539529) Oom!void {
540530 const ast = w.file.get_ast();
541 const node_tags = ast.nodes.items(.tag);
542 const node_datas = ast.nodes.items(.data);
543531
544532 const namespace = try gpa.create(Scope.Namespace);
545533 namespace.* = .{
......@@ -549,7 +537,7 @@ fn struct_decl(
549537 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);
550538 try w.scanDecls(namespace, container_decl.ast.members);
551539
552 for (container_decl.ast.members) |member| switch (node_tags[member]) {
540 for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) {
553541 .container_field_init,
554542 .container_field_align,
555543 .container_field,
......@@ -569,7 +557,7 @@ fn struct_decl(
569557 try w.file.get().doctests.put(gpa, member, doctest_node);
570558 }
571559 const decl_index = try w.file.add_decl(member, parent_decl);
572 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;
573561 try w.fn_decl(&namespace.base, decl_index, body, full);
574562 },
575563
......@@ -584,9 +572,9 @@ fn struct_decl(
584572
585573 .@"comptime",
586574 .@"usingnamespace",
587 => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs),
575 => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
588576
589 .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]),
590578
591579 else => unreachable,
592580 };
......@@ -633,13 +621,13 @@ fn fn_decl(
633621 w: *Walk,
634622 scope: *Scope,
635623 parent_decl: Decl.Index,
636 body: Ast.Node.Index,
624 body: Ast.Node.OptionalIndex,
637625 full: Ast.full.FnProto,
638626) Oom!void {
639627 for (full.ast.params) |param| {
640628 try expr(w, scope, parent_decl, param);
641629 }
642 try expr(w, scope, parent_decl, full.ast.return_type);
630 try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?);
643631 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);
644632 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);
645633 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);
......@@ -647,17 +635,13 @@ fn fn_decl(
647635 try maybe_expr(w, scope, parent_decl, body);
648636}
649637
650fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
651 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);
652640}
653641
654642fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
655 assert(node != 0);
656643 const ast = w.file.get_ast();
657 const node_tags = ast.nodes.items(.tag);
658 const node_datas = ast.nodes.items(.data);
659 const main_tokens = ast.nodes.items(.main_token);
660 switch (node_tags[node]) {
644 switch (ast.nodeTag(node)) {
661645 .root => unreachable, // Top-level declaration.
662646 .@"usingnamespace" => unreachable, // Top-level declaration.
663647 .test_decl => unreachable, // Top-level declaration.
......@@ -738,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
738722 .array_access,
739723 .switch_range,
740724 => {
741 try expr(w, scope, parent_decl, node_datas[node].lhs);
742 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);
743728 },
744729
745730 .assign_destructure => {
......@@ -752,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
752737 .bit_not,
753738 .negation,
754739 .negation_wrap,
755 .@"return",
756740 .deref,
757741 .address_of,
758742 .optional_type,
759 .unwrap_optional,
760 .grouped_expression,
761743 .@"comptime",
762744 .@"nosuspend",
763745 .@"suspend",
764746 .@"await",
765747 .@"resume",
766748 .@"try",
767 => 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),
768754
769 .anyframe_type,
770 .@"break",
771 => 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]),
772757
773758 .identifier => {
774 const ident_token = main_tokens[node];
759 const ident_token = ast.nodeMainToken(node);
775760 const ident_name = ast.tokenSlice(ident_token);
776761 if (scope.lookup(ast, ident_name)) |var_node| {
777762 try w.file.get().ident_decls.put(gpa, ident_token, var_node);
778763 }
779764 },
780765 .field_access => {
781 const object_node = node_datas[node].lhs;
782 const dot_token = main_tokens[node];
783 const field_ident = dot_token + 1;
766 const object_node, const field_ident = ast.nodeData(node).node_and_token;
784767 try w.file.get().token_parents.put(gpa, field_ident, node);
785768 // This will populate the left-most field object if it is an
786769 // identifier, allowing rendering code to piece together the link.
......@@ -857,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
857840 .for_simple, .@"for" => {
858841 const full = ast.fullFor(node).?;
859842 for (full.ast.inputs) |input| {
860 if (node_tags[input] == .for_range) {
861 try expr(w, scope, parent_decl, node_datas[input].lhs);
862 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);
863847 } else {
864848 try expr(w, scope, parent_decl, input);
865849 }
......@@ -914,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
914898 },
915899
916900 .array_type_sentinel => {
917 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
918 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);
919904 try expr(w, scope, parent_decl, extra.elem_type);
920905 try expr(w, scope, parent_decl, extra.sentinel);
921906 },
922907 .@"switch", .switch_comma => {
923 const operand_node = node_datas[node].lhs;
924 try expr(w, scope, parent_decl, operand_node);
925 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
926 const case_nodes = ast.extra_data[extra.start..extra.end];
927 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| {
928911 const case = ast.fullSwitchCase(case_node).?;
929912 for (case.ast.values) |value_node| {
930913 try expr(w, scope, parent_decl, value_node);
......@@ -973,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
973956 .fn_proto,
974957 => {
975958 var buf: [1]Ast.Node.Index = undefined;
976 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).?);
977960 },
978961 }
979962}
......@@ -993,8 +976,7 @@ fn builtin_call(
993976 params: []const Ast.Node.Index,
994977) Oom!void {
995978 const ast = w.file.get_ast();
996 const main_tokens = ast.nodes.items(.main_token);
997 const builtin_token = main_tokens[node];
979 const builtin_token = ast.nodeMainToken(node);
998980 const builtin_name = ast.tokenSlice(builtin_token);
999981 if (std.mem.eql(u8, builtin_name, "@This")) {
1000982 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());
......@@ -1012,13 +994,11 @@ fn block(
1012994 statements: []const Ast.Node.Index,
1013995) Oom!void {
1014996 const ast = w.file.get_ast();
1015 const node_tags = ast.nodes.items(.tag);
1016 const node_datas = ast.nodes.items(.data);
1017997
1018998 var scope = parent_scope;
1019999
10201000 for (statements) |node| {
1021 switch (node_tags[node]) {
1001 switch (ast.nodeTag(node)) {
10221002 .global_var_decl,
10231003 .local_var_decl,
10241004 .simple_var_decl,
......@@ -1039,11 +1019,10 @@ fn block(
10391019 log.debug("walk assign_destructure not implemented yet", .{});
10401020 },
10411021
1042 .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]),
10431023
1044 .@"defer",
1045 .@"errdefer",
1046 => 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]),
10471026
10481027 else => try expr(w, scope, parent_decl, node),
10491028 }
......@@ -1059,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W
10591038
10601039fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void {
10611040 const ast = w.file.get_ast();
1062 const node_tags = ast.nodes.items(.tag);
1063 const main_tokens = ast.nodes.items(.main_token);
1064 const token_tags = ast.tokens.items(.tag);
1065 const node_datas = ast.nodes.items(.data);
10661041
10671042 for (members) |member_node| {
1068 const name_token = switch (node_tags[member_node]) {
1043 const name_token = switch (ast.nodeTag(member_node)) {
10691044 .global_var_decl,
10701045 .local_var_decl,
10711046 .simple_var_decl,
10721047 .aligned_var_decl,
1073 => main_tokens[member_node] + 1,
1048 => ast.nodeMainToken(member_node) + 1,
10741049
10751050 .fn_proto_simple,
10761051 .fn_proto_multi,
......@@ -1078,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In
10781053 .fn_proto,
10791054 .fn_decl,
10801055 => blk: {
1081 const ident = main_tokens[member_node] + 1;
1082 if (token_tags[ident] != .identifier) continue;
1056 const ident = ast.nodeMainToken(member_node) + 1;
1057 if (ast.tokenTag(ident) != .identifier) continue;
10831058 break :blk ident;
10841059 },
10851060
10861061 .test_decl => {
1087 const ident_token = node_datas[member_node].lhs;
1088 const is_doctest = token_tags[ident_token] == .identifier;
1089 if (is_doctest) {
1090 const token_bytes = ast.tokenSlice(ident_token);
1091 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 }
10921069 }
10931070 continue;
10941071 },
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+965-844
......@@ -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,14 +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_tags = tree.tokens.items(.tag);
804889 var n = node;
805 var end_offset: TokenIndex = 0;
806 while (true) switch (tags[n]) {
807 .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),
808893
809894 .@"usingnamespace",
810895 .bool_not,
......@@ -819,11 +904,8 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
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,44 +954,53 @@ 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,
883 .fn_proto_one,
884 .fn_proto,
885961 .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,
886972 .ptr_type_aligned,
887973 .ptr_type_sentinel,
974 => n = tree.nodeData(n).opt_node_and_node[1],
975
976 .assign_destructure,
888977 .ptr_type,
889978 .ptr_type_bit_range,
890 .array_type,
891 .switch_case_one,
892 .switch_case_inline_one,
893979 .switch_case,
894980 .switch_case_inline,
895 .switch_range,
896 => n = datas[n].rhs,
981 => n = tree.nodeData(n).extra_and_node[1],
897982
898 .for_range => if (datas[n].rhs != 0) {
899 n = datas[n].rhs;
900 } else {
901 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 };
902993 },
903994
904995 .field_access,
905996 .unwrap_optional,
906 .grouped_expression,
907 .multiline_string_literal,
908 .error_set_decl,
909997 .asm_simple,
910 .asm_output,
911 .asm_input,
912 .error_value,
913 => return datas[n].rhs + end_offset,
998 => return tree.nodeData(n).node_and_token[1] + end_offset,
999 .error_set_decl => return tree.nodeData(n).token + end_offset,
1000 .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset,
1001 .multiline_string_literal => return tree.nodeData(n).token_and_token[1] + end_offset,
1002 .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset,
1003 .error_value => return tree.nodeData(n).opt_token_and_opt_token[1].unwrap().? + end_offset,
9141004
9151005 .anyframe_literal,
9161006 .char_literal,
......@@ -920,80 +1010,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
9201010 .deref,
9211011 .enum_literal,
9221012 .string_literal,
923 => return main_tokens[n] + end_offset,
1013 => return tree.nodeMainToken(n) + end_offset,
9241014
925 .@"return" => if (datas[n].lhs != 0) {
926 n = datas[n].lhs;
927 } else {
928 return main_tokens[n] + end_offset;
1015 .@"return" => {
1016 n = tree.nodeData(n).opt_node.unwrap() orelse {
1017 return tree.nodeMainToken(n) + end_offset;
1018 };
9291019 },
9301020
9311021 .call, .async_call => {
1022 _, const extra_index = tree.nodeData(n).node_and_extra;
1023 const params = tree.extraData(extra_index, Node.SubRange);
1024 assert(params.start != params.end);
9321025 end_offset += 1; // for the rparen
933 const params = tree.extraData(datas[n].rhs, Node.SubRange);
934 assert(params.end - params.start > 0);
935 n = tree.extra_data[params.end - 1]; // last parameter
1026 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
9361027 },
9371028 .tagged_union_enum_tag => {
938 const members = tree.extraData(datas[n].rhs, Node.SubRange);
939 if (members.end - members.start == 0) {
1029 const arg, const extra_index = tree.nodeData(n).node_and_extra;
1030 const members = tree.extraData(extra_index, Node.SubRange);
1031 if (members.start == members.end) {
9401032 end_offset += 4; // for the rparen + rparen + lbrace + rbrace
941 n = datas[n].lhs;
1033 n = arg;
9421034 } else {
9431035 end_offset += 1; // for the rbrace
944 n = tree.extra_data[members.end - 1]; // last parameter
1036 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9451037 }
9461038 },
9471039 .call_comma,
9481040 .async_call_comma,
9491041 .tagged_union_enum_tag_trailing,
9501042 => {
1043 _, const extra_index = tree.nodeData(n).node_and_extra;
1044 const params = tree.extraData(extra_index, Node.SubRange);
1045 assert(params.start != params.end);
9511046 end_offset += 2; // for the comma/semicolon + rparen/rbrace
952 const params = tree.extraData(datas[n].rhs, Node.SubRange);
953 assert(params.end > params.start);
954 n = tree.extra_data[params.end - 1]; // last parameter
1047 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
9551048 },
9561049 .@"switch" => {
957 const cases = tree.extraData(datas[n].rhs, Node.SubRange);
958 if (cases.end - cases.start == 0) {
1050 const condition, const extra_index = tree.nodeData(n).node_and_extra;
1051 const cases = tree.extraData(extra_index, Node.SubRange);
1052 if (cases.start == cases.end) {
9591053 end_offset += 3; // rparen, lbrace, rbrace
960 n = datas[n].lhs; // condition expression
1054 n = condition;
9611055 } else {
9621056 end_offset += 1; // for the rbrace
963 n = tree.extra_data[cases.end - 1]; // last case
1057 n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case
9641058 }
9651059 },
9661060 .container_decl_arg => {
967 const members = tree.extraData(datas[n].rhs, Node.SubRange);
968 if (members.end - members.start == 0) {
1061 const arg, const extra_index = tree.nodeData(n).node_and_extra;
1062 const members = tree.extraData(extra_index, Node.SubRange);
1063 if (members.end == members.start) {
9691064 end_offset += 3; // for the rparen + lbrace + rbrace
970 n = datas[n].lhs;
1065 n = arg;
9711066 } else {
9721067 end_offset += 1; // for the rbrace
973 n = tree.extra_data[members.end - 1]; // last parameter
1068 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9741069 }
9751070 },
9761071 .@"asm" => {
977 const extra = tree.extraData(datas[n].rhs, Node.Asm);
1072 _, const extra_index = tree.nodeData(n).node_and_extra;
1073 const extra = tree.extraData(extra_index, Node.Asm);
9781074 return extra.rparen + end_offset;
9791075 },
9801076 .array_init,
9811077 .struct_init,
9821078 => {
983 const elements = tree.extraData(datas[n].rhs, Node.SubRange);
984 assert(elements.end - elements.start > 0);
1079 _, const extra_index = tree.nodeData(n).node_and_extra;
1080 const elements = tree.extraData(extra_index, Node.SubRange);
1081 assert(elements.start != elements.end);
9851082 end_offset += 1; // for the rbrace
986 n = tree.extra_data[elements.end - 1]; // last element
1083 n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element
9871084 },
9881085 .array_init_comma,
9891086 .struct_init_comma,
9901087 .container_decl_arg_trailing,
9911088 .switch_comma,
9921089 => {
993 const members = tree.extraData(datas[n].rhs, Node.SubRange);
994 assert(members.end - members.start > 0);
1090 _, const extra_index = tree.nodeData(n).node_and_extra;
1091 const members = tree.extraData(extra_index, Node.SubRange);
1092 assert(members.start != members.end);
9951093 end_offset += 2; // for the comma + rbrace
996 n = tree.extra_data[members.end - 1]; // last parameter
1094 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
9971095 },
9981096 .array_init_dot,
9991097 .struct_init_dot,
......@@ -1002,9 +1100,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10021100 .tagged_union,
10031101 .builtin_call,
10041102 => {
1005 assert(datas[n].rhs - datas[n].lhs > 0);
1103 const range = tree.nodeData(n).extra_range;
1104 assert(range.start != range.end);
10061105 end_offset += 1; // for the rbrace
1007 n = tree.extra_data[datas[n].rhs - 1]; // last statement
1106 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement
10081107 },
10091108 .array_init_dot_comma,
10101109 .struct_init_dot_comma,
......@@ -1013,20 +1112,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10131112 .tagged_union_trailing,
10141113 .builtin_call_comma,
10151114 => {
1016 assert(datas[n].rhs - datas[n].lhs > 0);
1115 const range = tree.nodeData(n).extra_range;
1116 assert(range.start != range.end);
10171117 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1018 n = tree.extra_data[datas[n].rhs - 1]; // last member
1118 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
10191119 },
10201120 .call_one,
10211121 .async_call_one,
1022 .array_access,
10231122 => {
1024 end_offset += 1; // for the rparen/rbracket
1025 if (datas[n].rhs == 0) {
1026 return main_tokens[n] + end_offset;
1027 }
1028 n = datas[n].rhs;
1123 _, const first_param = tree.nodeData(n).node_and_opt_node;
1124 end_offset += 1; // for the rparen
1125 n = first_param.unwrap() orelse {
1126 return tree.nodeMainToken(n) + end_offset;
1127 };
10291128 },
1129
10301130 .array_init_dot_two,
10311131 .block_two,
10321132 .builtin_call_two,
......@@ -1034,14 +1134,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10341134 .container_decl_two,
10351135 .tagged_union_two,
10361136 => {
1037 if (datas[n].rhs != 0) {
1137 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1138 if (opt_rhs.unwrap()) |rhs| {
10381139 end_offset += 1; // for the rparen/rbrace
1039 n = datas[n].rhs;
1040 } else if (datas[n].lhs != 0) {
1140 n = rhs;
1141 } else if (opt_lhs.unwrap()) |lhs| {
10411142 end_offset += 1; // for the rparen/rbrace
1042 n = datas[n].lhs;
1143 n = lhs;
10431144 } else {
1044 switch (tags[n]) {
1145 switch (tree.nodeTag(n)) {
10451146 .array_init_dot_two,
10461147 .block_two,
10471148 .struct_init_dot_two,
......@@ -1049,17 +1150,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10491150 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace
10501151 .container_decl_two => {
10511152 var i: u32 = 2; // lbrace + rbrace
1052 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;
1153 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
10531154 end_offset += i;
10541155 },
10551156 .tagged_union_two => {
10561157 var i: u32 = 5; // (enum) {}
1057 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;
1158 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
10581159 end_offset += i;
10591160 },
10601161 else => unreachable,
10611162 }
1062 return main_tokens[n] + end_offset;
1163 return tree.nodeMainToken(n) + end_offset;
10631164 }
10641165 },
10651166 .array_init_dot_two_comma,
......@@ -1069,341 +1170,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
10691170 .container_decl_two_trailing,
10701171 .tagged_union_two_trailing,
10711172 => {
1173 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
10721174 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1073 if (datas[n].rhs != 0) {
1074 n = datas[n].rhs;
1075 } else if (datas[n].lhs != 0) {
1076 n = datas[n].lhs;
1175 if (opt_rhs.unwrap()) |rhs| {
1176 n = rhs;
1177 } else if (opt_lhs.unwrap()) |lhs| {
1178 n = lhs;
10771179 } else {
10781180 unreachable;
10791181 }
10801182 },
10811183 .simple_var_decl => {
1082 if (datas[n].rhs != 0) {
1083 n = datas[n].rhs;
1084 } else if (datas[n].lhs != 0) {
1085 n = datas[n].lhs;
1184 const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node;
1185 if (init_node.unwrap()) |rhs| {
1186 n = rhs;
1187 } else if (type_node.unwrap()) |lhs| {
1188 n = lhs;
10861189 } else {
10871190 end_offset += 1; // from mut token to name
1088 return main_tokens[n] + end_offset;
1191 return tree.nodeMainToken(n) + end_offset;
10891192 }
10901193 },
10911194 .aligned_var_decl => {
1092 if (datas[n].rhs != 0) {
1093 n = datas[n].rhs;
1094 } else if (datas[n].lhs != 0) {
1095 end_offset += 1; // for the rparen
1096 n = datas[n].lhs;
1195 const align_node, const init_node = tree.nodeData(n).node_and_opt_node;
1196 if (init_node.unwrap()) |rhs| {
1197 n = rhs;
10971198 } else {
1098 end_offset += 1; // from mut token to name
1099 return main_tokens[n] + end_offset;
1199 end_offset += 1; // for the rparen
1200 n = align_node;
11001201 }
11011202 },
11021203 .global_var_decl => {
1103 if (datas[n].rhs != 0) {
1104 n = datas[n].rhs;
1204 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1205 if (init_node.unwrap()) |rhs| {
1206 n = rhs;
11051207 } else {
1106 const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl);
1107 if (extra.section_node != 0) {
1208 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1209 if (extra.section_node.unwrap()) |section_node| {
11081210 end_offset += 1; // for the rparen
1109 n = extra.section_node;
1110 } else if (extra.align_node != 0) {
1211 n = section_node;
1212 } else if (extra.align_node.unwrap()) |align_node| {
11111213 end_offset += 1; // for the rparen
1112 n = extra.align_node;
1113 } else if (extra.type_node != 0) {
1114 n = extra.type_node;
1214 n = align_node;
1215 } else if (extra.type_node.unwrap()) |type_node| {
1216 n = type_node;
11151217 } else {
11161218 end_offset += 1; // from mut token to name
1117 return main_tokens[n] + end_offset;
1219 return tree.nodeMainToken(n) + end_offset;
11181220 }
11191221 }
11201222 },
11211223 .local_var_decl => {
1122 if (datas[n].rhs != 0) {
1123 n = datas[n].rhs;
1224 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1225 if (init_node.unwrap()) |rhs| {
1226 n = rhs;
11241227 } else {
1125 const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl);
1126 assert(extra.align_node != 0);
1228 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
11271229 end_offset += 1; // for the rparen
11281230 n = extra.align_node;
11291231 }
11301232 },
11311233 .container_field_init => {
1132 if (datas[n].rhs != 0) {
1133 n = datas[n].rhs;
1134 } else {
1135 assert(datas[n].lhs != 0);
1136 n = datas[n].lhs;
1137 }
1234 const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node;
1235 n = value_expr.unwrap() orelse type_expr;
11381236 },
1139 .container_field_align => {
1140 assert(datas[n].rhs != 0);
1141 end_offset += 1; // for the rparen
1142 n = datas[n].rhs;
1237
1238 .array_access,
1239 .array_init_one,
1240 .container_field_align,
1241 => {
1242 _, const rhs = tree.nodeData(n).node_and_node;
1243 end_offset += 1; // for the rbracket/rbrace/rparen
1244 n = rhs;
11431245 },
11441246 .container_field => {
1145 const extra = tree.extraData(datas[n].rhs, Node.ContainerField);
1146 assert(extra.value_expr != 0);
1247 _, const extra_index = tree.nodeData(n).node_and_extra;
1248 const extra = tree.extraData(extra_index, Node.ContainerField);
11471249 n = extra.value_expr;
11481250 },
11491251
1150 .array_init_one,
1151 .struct_init_one,
1152 => {
1252 .struct_init_one => {
1253 _, const first_field = tree.nodeData(n).node_and_opt_node;
11531254 end_offset += 1; // rbrace
1154 if (datas[n].rhs == 0) {
1155 return main_tokens[n] + end_offset;
1156 } else {
1157 n = datas[n].rhs;
1158 }
1255 n = first_field.unwrap() orelse {
1256 return tree.nodeMainToken(n) + end_offset;
1257 };
1258 },
1259 .slice_open => {
1260 _, const start_node = tree.nodeData(n).node_and_node;
1261 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1262 n = start_node;
1263 },
1264 .array_init_one_comma => {
1265 _, const first_element = tree.nodeData(n).node_and_node;
1266 end_offset += 2; // comma + rbrace
1267 n = first_element;
11591268 },
1160 .slice_open,
11611269 .call_one_comma,
11621270 .async_call_one_comma,
1163 .array_init_one_comma,
11641271 .struct_init_one_comma,
11651272 => {
1273 _, const first_field = tree.nodeData(n).node_and_opt_node;
11661274 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1167 n = datas[n].rhs;
1168 assert(n != 0);
1275 n = first_field.unwrap().?;
11691276 },
11701277 .slice => {
1171 const extra = tree.extraData(datas[n].rhs, Node.Slice);
1172 assert(extra.end != 0); // should have used slice_open
1278 _, const extra_index = tree.nodeData(n).node_and_extra;
1279 const extra = tree.extraData(extra_index, Node.Slice);
11731280 end_offset += 1; // rbracket
11741281 n = extra.end;
11751282 },
11761283 .slice_sentinel => {
1177 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);
1178 assert(extra.sentinel != 0); // should have used slice
1284 _, const extra_index = tree.nodeData(n).node_and_extra;
1285 const extra = tree.extraData(extra_index, Node.SliceSentinel);
11791286 end_offset += 1; // rbracket
11801287 n = extra.sentinel;
11811288 },
11821289
11831290 .@"continue", .@"break" => {
1184 if (datas[n].rhs != 0) {
1185 n = datas[n].rhs;
1186 } else if (datas[n].lhs != 0) {
1187 return datas[n].lhs + end_offset;
1291 const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node;
1292 if (opt_rhs.unwrap()) |rhs| {
1293 n = rhs;
1294 } else if (opt_label.unwrap()) |lhs| {
1295 return lhs + end_offset;
11881296 } else {
1189 return main_tokens[n] + end_offset;
1297 return tree.nodeMainToken(n) + end_offset;
11901298 }
11911299 },
11921300 .while_cont => {
1193 const extra = tree.extraData(datas[n].rhs, Node.WhileCont);
1194 assert(extra.then_expr != 0);
1301 _, const extra_index = tree.nodeData(n).node_and_extra;
1302 const extra = tree.extraData(extra_index, Node.WhileCont);
11951303 n = extra.then_expr;
11961304 },
11971305 .@"while" => {
1198 const extra = tree.extraData(datas[n].rhs, Node.While);
1199 assert(extra.else_expr != 0);
1306 _, const extra_index = tree.nodeData(n).node_and_extra;
1307 const extra = tree.extraData(extra_index, Node.While);
12001308 n = extra.else_expr;
12011309 },
12021310 .@"if" => {
1203 const extra = tree.extraData(datas[n].rhs, Node.If);
1204 assert(extra.else_expr != 0);
1311 _, const extra_index = tree.nodeData(n).node_and_extra;
1312 const extra = tree.extraData(extra_index, Node.If);
12051313 n = extra.else_expr;
12061314 },
12071315 .@"for" => {
1208 const extra = @as(Node.For, @bitCast(datas[n].rhs));
1209 n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)];
1316 const extra_index, const extra = tree.nodeData(n).@"for";
1317 const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else);
1318 n = @enumFromInt(tree.extra_data[index]);
12101319 },
12111320 .array_type_sentinel => {
1212 const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel);
1321 _, const extra_index = tree.nodeData(n).node_and_extra;
1322 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
12131323 n = extra.elem_type;
12141324 },
12151325 };
12161326}
12171327
12181328pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {
1219 const token_starts = tree.tokens.items(.start);
1220 const source = tree.source[token_starts[token1]..token_starts[token2]];
1329 const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)];
12211330 return mem.indexOfScalar(u8, source, '\n') == null;
12221331}
12231332
12241333pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {
1225 const token_starts = tree.tokens.items(.start);
12261334 const first_token = tree.firstToken(node);
12271335 const last_token = tree.lastToken(node);
1228 const start = token_starts[first_token];
1229 const end = token_starts[last_token] + tree.tokenSlice(last_token).len;
1336 const start = tree.tokenStart(first_token);
1337 const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len;
12301338 return tree.source[start..end];
12311339}
12321340
12331341pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1234 assert(tree.nodes.items(.tag)[node] == .global_var_decl);
1235 const data = tree.nodes.items(.data)[node];
1236 const extra = tree.extraData(data.lhs, Node.GlobalVarDecl);
1342 assert(tree.nodeTag(node) == .global_var_decl);
1343 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1344 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
12371345 return tree.fullVarDeclComponents(.{
12381346 .type_node = extra.type_node,
12391347 .align_node = extra.align_node,
12401348 .addrspace_node = extra.addrspace_node,
12411349 .section_node = extra.section_node,
1242 .init_node = data.rhs,
1243 .mut_token = tree.nodes.items(.main_token)[node],
1350 .init_node = init_node,
1351 .mut_token = tree.nodeMainToken(node),
12441352 });
12451353}
12461354
12471355pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1248 assert(tree.nodes.items(.tag)[node] == .local_var_decl);
1249 const data = tree.nodes.items(.data)[node];
1250 const extra = tree.extraData(data.lhs, Node.LocalVarDecl);
1356 assert(tree.nodeTag(node) == .local_var_decl);
1357 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1358 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
12511359 return tree.fullVarDeclComponents(.{
1252 .type_node = extra.type_node,
1253 .align_node = extra.align_node,
1254 .addrspace_node = 0,
1255 .section_node = 0,
1256 .init_node = data.rhs,
1257 .mut_token = tree.nodes.items(.main_token)[node],
1360 .type_node = extra.type_node.toOptional(),
1361 .align_node = extra.align_node.toOptional(),
1362 .addrspace_node = .none,
1363 .section_node = .none,
1364 .init_node = init_node,
1365 .mut_token = tree.nodeMainToken(node),
12581366 });
12591367}
12601368
12611369pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1262 assert(tree.nodes.items(.tag)[node] == .simple_var_decl);
1263 const data = tree.nodes.items(.data)[node];
1370 assert(tree.nodeTag(node) == .simple_var_decl);
1371 const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node;
12641372 return tree.fullVarDeclComponents(.{
1265 .type_node = data.lhs,
1266 .align_node = 0,
1267 .addrspace_node = 0,
1268 .section_node = 0,
1269 .init_node = data.rhs,
1270 .mut_token = tree.nodes.items(.main_token)[node],
1373 .type_node = type_node,
1374 .align_node = .none,
1375 .addrspace_node = .none,
1376 .section_node = .none,
1377 .init_node = init_node,
1378 .mut_token = tree.nodeMainToken(node),
12711379 });
12721380}
12731381
12741382pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1275 assert(tree.nodes.items(.tag)[node] == .aligned_var_decl);
1276 const data = tree.nodes.items(.data)[node];
1383 assert(tree.nodeTag(node) == .aligned_var_decl);
1384 const align_node, const init_node = tree.nodeData(node).node_and_opt_node;
12771385 return tree.fullVarDeclComponents(.{
1278 .type_node = 0,
1279 .align_node = data.lhs,
1280 .addrspace_node = 0,
1281 .section_node = 0,
1282 .init_node = data.rhs,
1283 .mut_token = tree.nodes.items(.main_token)[node],
1386 .type_node = .none,
1387 .align_node = align_node.toOptional(),
1388 .addrspace_node = .none,
1389 .section_node = .none,
1390 .init_node = init_node,
1391 .mut_token = tree.nodeMainToken(node),
12841392 });
12851393}
12861394
12871395pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {
1288 const data = tree.nodes.items(.data)[node];
1289 const variable_count = tree.extra_data[data.lhs];
1396 const extra_index, const value_expr = tree.nodeData(node).extra_and_node;
1397 const variable_count = tree.extra_data[@intFromEnum(extra_index)];
12901398 return tree.fullAssignDestructureComponents(.{
1291 .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count],
1292 .equal_token = tree.nodes.items(.main_token)[node],
1293 .value_expr = data.rhs,
1399 .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index),
1400 .equal_token = tree.nodeMainToken(node),
1401 .value_expr = value_expr,
12941402 });
12951403}
12961404
12971405pub fn ifSimple(tree: Ast, node: Node.Index) full.If {
1298 assert(tree.nodes.items(.tag)[node] == .if_simple);
1299 const data = tree.nodes.items(.data)[node];
1406 assert(tree.nodeTag(node) == .if_simple);
1407 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
13001408 return tree.fullIfComponents(.{
1301 .cond_expr = data.lhs,
1302 .then_expr = data.rhs,
1303 .else_expr = 0,
1304 .if_token = tree.nodes.items(.main_token)[node],
1409 .cond_expr = cond_expr,
1410 .then_expr = then_expr,
1411 .else_expr = .none,
1412 .if_token = tree.nodeMainToken(node),
13051413 });
13061414}
13071415
13081416pub fn ifFull(tree: Ast, node: Node.Index) full.If {
1309 assert(tree.nodes.items(.tag)[node] == .@"if");
1310 const data = tree.nodes.items(.data)[node];
1311 const extra = tree.extraData(data.rhs, Node.If);
1417 assert(tree.nodeTag(node) == .@"if");
1418 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1419 const extra = tree.extraData(extra_index, Node.If);
13121420 return tree.fullIfComponents(.{
1313 .cond_expr = data.lhs,
1421 .cond_expr = cond_expr,
13141422 .then_expr = extra.then_expr,
1315 .else_expr = extra.else_expr,
1316 .if_token = tree.nodes.items(.main_token)[node],
1423 .else_expr = extra.else_expr.toOptional(),
1424 .if_token = tree.nodeMainToken(node),
13171425 });
13181426}
13191427
13201428pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {
1321 assert(tree.nodes.items(.tag)[node] == .container_field);
1322 const data = tree.nodes.items(.data)[node];
1323 const extra = tree.extraData(data.rhs, Node.ContainerField);
1324 const main_token = tree.nodes.items(.main_token)[node];
1429 assert(tree.nodeTag(node) == .container_field);
1430 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1431 const extra = tree.extraData(extra_index, Node.ContainerField);
1432 const main_token = tree.nodeMainToken(node);
13251433 return tree.fullContainerFieldComponents(.{
13261434 .main_token = main_token,
1327 .type_expr = data.lhs,
1328 .align_expr = extra.align_expr,
1329 .value_expr = extra.value_expr,
1330 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1331 tree.tokens.items(.tag)[main_token + 1] != .colon,
1435 .type_expr = type_expr.toOptional(),
1436 .align_expr = extra.align_expr.toOptional(),
1437 .value_expr = extra.value_expr.toOptional(),
1438 .tuple_like = tree.tokenTag(main_token) != .identifier or
1439 tree.tokenTag(main_token + 1) != .colon,
13321440 });
13331441}
13341442
13351443pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {
1336 assert(tree.nodes.items(.tag)[node] == .container_field_init);
1337 const data = tree.nodes.items(.data)[node];
1338 const main_token = tree.nodes.items(.main_token)[node];
1444 assert(tree.nodeTag(node) == .container_field_init);
1445 const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node;
1446 const main_token = tree.nodeMainToken(node);
13391447 return tree.fullContainerFieldComponents(.{
13401448 .main_token = main_token,
1341 .type_expr = data.lhs,
1342 .align_expr = 0,
1343 .value_expr = data.rhs,
1344 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1345 tree.tokens.items(.tag)[main_token + 1] != .colon,
1449 .type_expr = type_expr.toOptional(),
1450 .align_expr = .none,
1451 .value_expr = value_expr,
1452 .tuple_like = tree.tokenTag(main_token) != .identifier or
1453 tree.tokenTag(main_token + 1) != .colon,
13461454 });
13471455}
13481456
13491457pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {
1350 assert(tree.nodes.items(.tag)[node] == .container_field_align);
1351 const data = tree.nodes.items(.data)[node];
1352 const main_token = tree.nodes.items(.main_token)[node];
1458 assert(tree.nodeTag(node) == .container_field_align);
1459 const type_expr, const align_expr = tree.nodeData(node).node_and_node;
1460 const main_token = tree.nodeMainToken(node);
13531461 return tree.fullContainerFieldComponents(.{
13541462 .main_token = main_token,
1355 .type_expr = data.lhs,
1356 .align_expr = data.rhs,
1357 .value_expr = 0,
1358 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or
1359 tree.tokens.items(.tag)[main_token + 1] != .colon,
1463 .type_expr = type_expr.toOptional(),
1464 .align_expr = align_expr.toOptional(),
1465 .value_expr = .none,
1466 .tuple_like = tree.tokenTag(main_token) != .identifier or
1467 tree.tokenTag(main_token + 1) != .colon,
13601468 });
13611469}
13621470
13631471pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1364 assert(tree.nodes.items(.tag)[node] == .fn_proto_simple);
1365 const data = tree.nodes.items(.data)[node];
1366 buffer[0] = data.lhs;
1367 const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1];
1472 assert(tree.nodeTag(node) == .fn_proto_simple);
1473 const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node;
1474 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
13681475 return tree.fullFnProtoComponents(.{
13691476 .proto_node = node,
1370 .fn_token = tree.nodes.items(.main_token)[node],
1371 .return_type = data.rhs,
1477 .fn_token = tree.nodeMainToken(node),
1478 .return_type = return_type,
13721479 .params = params,
1373 .align_expr = 0,
1374 .addrspace_expr = 0,
1375 .section_expr = 0,
1376 .callconv_expr = 0,
1480 .align_expr = .none,
1481 .addrspace_expr = .none,
1482 .section_expr = .none,
1483 .callconv_expr = .none,
13771484 });
13781485}
13791486
13801487pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {
1381 assert(tree.nodes.items(.tag)[node] == .fn_proto_multi);
1382 const data = tree.nodes.items(.data)[node];
1383 const params_range = tree.extraData(data.lhs, Node.SubRange);
1384 const params = tree.extra_data[params_range.start..params_range.end];
1488 assert(tree.nodeTag(node) == .fn_proto_multi);
1489 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1490 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
13851491 return tree.fullFnProtoComponents(.{
13861492 .proto_node = node,
1387 .fn_token = tree.nodes.items(.main_token)[node],
1388 .return_type = data.rhs,
1493 .fn_token = tree.nodeMainToken(node),
1494 .return_type = return_type,
13891495 .params = params,
1390 .align_expr = 0,
1391 .addrspace_expr = 0,
1392 .section_expr = 0,
1393 .callconv_expr = 0,
1496 .align_expr = .none,
1497 .addrspace_expr = .none,
1498 .section_expr = .none,
1499 .callconv_expr = .none,
13941500 });
13951501}
13961502
13971503pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1398 assert(tree.nodes.items(.tag)[node] == .fn_proto_one);
1399 const data = tree.nodes.items(.data)[node];
1400 const extra = tree.extraData(data.lhs, Node.FnProtoOne);
1401 buffer[0] = extra.param;
1402 const params = if (extra.param == 0) buffer[0..0] else buffer[0..1];
1504 assert(tree.nodeTag(node) == .fn_proto_one);
1505 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1506 const extra = tree.extraData(extra_index, Node.FnProtoOne);
1507 const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param});
14031508 return tree.fullFnProtoComponents(.{
14041509 .proto_node = node,
1405 .fn_token = tree.nodes.items(.main_token)[node],
1406 .return_type = data.rhs,
1510 .fn_token = tree.nodeMainToken(node),
1511 .return_type = return_type,
14071512 .params = params,
14081513 .align_expr = extra.align_expr,
14091514 .addrspace_expr = extra.addrspace_expr,
......@@ -1413,14 +1518,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr
14131518}
14141519
14151520pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1416 assert(tree.nodes.items(.tag)[node] == .fn_proto);
1417 const data = tree.nodes.items(.data)[node];
1418 const extra = tree.extraData(data.lhs, Node.FnProto);
1419 const params = tree.extra_data[extra.params_start..extra.params_end];
1521 assert(tree.nodeTag(node) == .fn_proto);
1522 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1523 const extra = tree.extraData(extra_index, Node.FnProto);
1524 const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index);
14201525 return tree.fullFnProtoComponents(.{
14211526 .proto_node = node,
1422 .fn_token = tree.nodes.items(.main_token)[node],
1423 .return_type = data.rhs,
1527 .fn_token = tree.nodeMainToken(node),
1528 .return_type = return_type,
14241529 .params = params,
14251530 .align_expr = extra.align_expr,
14261531 .addrspace_expr = extra.addrspace_expr,
......@@ -1430,300 +1535,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
14301535}
14311536
14321537pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {
1433 assert(tree.nodes.items(.tag)[node] == .struct_init_one or
1434 tree.nodes.items(.tag)[node] == .struct_init_one_comma);
1435 const data = tree.nodes.items(.data)[node];
1436 buffer[0] = data.rhs;
1437 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1538 assert(tree.nodeTag(node) == .struct_init_one or
1539 tree.nodeTag(node) == .struct_init_one_comma);
1540 const type_expr, const first_field = tree.nodeData(node).node_and_opt_node;
1541 const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field});
14381542 return .{
14391543 .ast = .{
1440 .lbrace = tree.nodes.items(.main_token)[node],
1544 .lbrace = tree.nodeMainToken(node),
14411545 .fields = fields,
1442 .type_expr = data.lhs,
1546 .type_expr = type_expr.toOptional(),
14431547 },
14441548 };
14451549}
14461550
14471551pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {
1448 assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or
1449 tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma);
1450 const data = tree.nodes.items(.data)[node];
1451 buffer.* = .{ data.lhs, data.rhs };
1452 const fields = if (data.rhs != 0)
1453 buffer[0..2]
1454 else if (data.lhs != 0)
1455 buffer[0..1]
1456 else
1457 buffer[0..0];
1552 assert(tree.nodeTag(node) == .struct_init_dot_two or
1553 tree.nodeTag(node) == .struct_init_dot_two_comma);
1554 const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
14581555 return .{
14591556 .ast = .{
1460 .lbrace = tree.nodes.items(.main_token)[node],
1557 .lbrace = tree.nodeMainToken(node),
14611558 .fields = fields,
1462 .type_expr = 0,
1559 .type_expr = .none,
14631560 },
14641561 };
14651562}
14661563
14671564pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {
1468 assert(tree.nodes.items(.tag)[node] == .struct_init_dot or
1469 tree.nodes.items(.tag)[node] == .struct_init_dot_comma);
1470 const data = tree.nodes.items(.data)[node];
1565 assert(tree.nodeTag(node) == .struct_init_dot or
1566 tree.nodeTag(node) == .struct_init_dot_comma);
1567 const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
14711568 return .{
14721569 .ast = .{
1473 .lbrace = tree.nodes.items(.main_token)[node],
1474 .fields = tree.extra_data[data.lhs..data.rhs],
1475 .type_expr = 0,
1570 .lbrace = tree.nodeMainToken(node),
1571 .fields = fields,
1572 .type_expr = .none,
14761573 },
14771574 };
14781575}
14791576
14801577pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {
1481 assert(tree.nodes.items(.tag)[node] == .struct_init or
1482 tree.nodes.items(.tag)[node] == .struct_init_comma);
1483 const data = tree.nodes.items(.data)[node];
1484 const fields_range = tree.extraData(data.rhs, Node.SubRange);
1578 assert(tree.nodeTag(node) == .struct_init or
1579 tree.nodeTag(node) == .struct_init_comma);
1580 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1581 const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
14851582 return .{
14861583 .ast = .{
1487 .lbrace = tree.nodes.items(.main_token)[node],
1488 .fields = tree.extra_data[fields_range.start..fields_range.end],
1489 .type_expr = data.lhs,
1584 .lbrace = tree.nodeMainToken(node),
1585 .fields = fields,
1586 .type_expr = type_expr.toOptional(),
14901587 },
14911588 };
14921589}
14931590
14941591pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
1495 assert(tree.nodes.items(.tag)[node] == .array_init_one or
1496 tree.nodes.items(.tag)[node] == .array_init_one_comma);
1497 const data = tree.nodes.items(.data)[node];
1498 buffer[0] = data.rhs;
1499 const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1592 assert(tree.nodeTag(node) == .array_init_one or
1593 tree.nodeTag(node) == .array_init_one_comma);
1594 const type_expr, buffer[0] = tree.nodeData(node).node_and_node;
15001595 return .{
15011596 .ast = .{
1502 .lbrace = tree.nodes.items(.main_token)[node],
1503 .elements = elements,
1504 .type_expr = data.lhs,
1597 .lbrace = tree.nodeMainToken(node),
1598 .elements = buffer[0..1],
1599 .type_expr = type_expr.toOptional(),
15051600 },
15061601 };
15071602}
15081603
15091604pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {
1510 assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or
1511 tree.nodes.items(.tag)[node] == .array_init_dot_two_comma);
1512 const data = tree.nodes.items(.data)[node];
1513 buffer.* = .{ data.lhs, data.rhs };
1514 const elements = if (data.rhs != 0)
1515 buffer[0..2]
1516 else if (data.lhs != 0)
1517 buffer[0..1]
1518 else
1519 buffer[0..0];
1605 assert(tree.nodeTag(node) == .array_init_dot_two or
1606 tree.nodeTag(node) == .array_init_dot_two_comma);
1607 const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
15201608 return .{
15211609 .ast = .{
1522 .lbrace = tree.nodes.items(.main_token)[node],
1610 .lbrace = tree.nodeMainToken(node),
15231611 .elements = elements,
1524 .type_expr = 0,
1612 .type_expr = .none,
15251613 },
15261614 };
15271615}
15281616
15291617pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {
1530 assert(tree.nodes.items(.tag)[node] == .array_init_dot or
1531 tree.nodes.items(.tag)[node] == .array_init_dot_comma);
1532 const data = tree.nodes.items(.data)[node];
1618 assert(tree.nodeTag(node) == .array_init_dot or
1619 tree.nodeTag(node) == .array_init_dot_comma);
1620 const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
15331621 return .{
15341622 .ast = .{
1535 .lbrace = tree.nodes.items(.main_token)[node],
1536 .elements = tree.extra_data[data.lhs..data.rhs],
1537 .type_expr = 0,
1623 .lbrace = tree.nodeMainToken(node),
1624 .elements = elements,
1625 .type_expr = .none,
15381626 },
15391627 };
15401628}
15411629
15421630pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {
1543 assert(tree.nodes.items(.tag)[node] == .array_init or
1544 tree.nodes.items(.tag)[node] == .array_init_comma);
1545 const data = tree.nodes.items(.data)[node];
1546 const elem_range = tree.extraData(data.rhs, Node.SubRange);
1631 assert(tree.nodeTag(node) == .array_init or
1632 tree.nodeTag(node) == .array_init_comma);
1633 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1634 const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
15471635 return .{
15481636 .ast = .{
1549 .lbrace = tree.nodes.items(.main_token)[node],
1550 .elements = tree.extra_data[elem_range.start..elem_range.end],
1551 .type_expr = data.lhs,
1637 .lbrace = tree.nodeMainToken(node),
1638 .elements = elements,
1639 .type_expr = type_expr.toOptional(),
15521640 },
15531641 };
15541642}
15551643
15561644pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {
1557 assert(tree.nodes.items(.tag)[node] == .array_type);
1558 const data = tree.nodes.items(.data)[node];
1645 assert(tree.nodeTag(node) == .array_type);
1646 const elem_count, const elem_type = tree.nodeData(node).node_and_node;
15591647 return .{
15601648 .ast = .{
1561 .lbracket = tree.nodes.items(.main_token)[node],
1562 .elem_count = data.lhs,
1563 .sentinel = 0,
1564 .elem_type = data.rhs,
1649 .lbracket = tree.nodeMainToken(node),
1650 .elem_count = elem_count,
1651 .sentinel = .none,
1652 .elem_type = elem_type,
15651653 },
15661654 };
15671655}
15681656
15691657pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {
1570 assert(tree.nodes.items(.tag)[node] == .array_type_sentinel);
1571 const data = tree.nodes.items(.data)[node];
1572 const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel);
1573 assert(extra.sentinel != 0);
1658 assert(tree.nodeTag(node) == .array_type_sentinel);
1659 const elem_count, const extra_index = tree.nodeData(node).node_and_extra;
1660 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
15741661 return .{
15751662 .ast = .{
1576 .lbracket = tree.nodes.items(.main_token)[node],
1577 .elem_count = data.lhs,
1578 .sentinel = extra.sentinel,
1663 .lbracket = tree.nodeMainToken(node),
1664 .elem_count = elem_count,
1665 .sentinel = extra.sentinel.toOptional(),
15791666 .elem_type = extra.elem_type,
15801667 },
15811668 };
15821669}
15831670
15841671pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {
1585 assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned);
1586 const data = tree.nodes.items(.data)[node];
1672 assert(tree.nodeTag(node) == .ptr_type_aligned);
1673 const align_node, const child_type = tree.nodeData(node).opt_node_and_node;
15871674 return tree.fullPtrTypeComponents(.{
1588 .main_token = tree.nodes.items(.main_token)[node],
1589 .align_node = data.lhs,
1590 .addrspace_node = 0,
1591 .sentinel = 0,
1592 .bit_range_start = 0,
1593 .bit_range_end = 0,
1594 .child_type = data.rhs,
1675 .main_token = tree.nodeMainToken(node),
1676 .align_node = align_node,
1677 .addrspace_node = .none,
1678 .sentinel = .none,
1679 .bit_range_start = .none,
1680 .bit_range_end = .none,
1681 .child_type = child_type,
15951682 });
15961683}
15971684
15981685pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {
1599 assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel);
1600 const data = tree.nodes.items(.data)[node];
1686 assert(tree.nodeTag(node) == .ptr_type_sentinel);
1687 const sentinel, const child_type = tree.nodeData(node).opt_node_and_node;
16011688 return tree.fullPtrTypeComponents(.{
1602 .main_token = tree.nodes.items(.main_token)[node],
1603 .align_node = 0,
1604 .addrspace_node = 0,
1605 .sentinel = data.lhs,
1606 .bit_range_start = 0,
1607 .bit_range_end = 0,
1608 .child_type = data.rhs,
1689 .main_token = tree.nodeMainToken(node),
1690 .align_node = .none,
1691 .addrspace_node = .none,
1692 .sentinel = sentinel,
1693 .bit_range_start = .none,
1694 .bit_range_end = .none,
1695 .child_type = child_type,
16091696 });
16101697}
16111698
16121699pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {
1613 assert(tree.nodes.items(.tag)[node] == .ptr_type);
1614 const data = tree.nodes.items(.data)[node];
1615 const extra = tree.extraData(data.lhs, Node.PtrType);
1700 assert(tree.nodeTag(node) == .ptr_type);
1701 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1702 const extra = tree.extraData(extra_index, Node.PtrType);
16161703 return tree.fullPtrTypeComponents(.{
1617 .main_token = tree.nodes.items(.main_token)[node],
1704 .main_token = tree.nodeMainToken(node),
16181705 .align_node = extra.align_node,
16191706 .addrspace_node = extra.addrspace_node,
16201707 .sentinel = extra.sentinel,
1621 .bit_range_start = 0,
1622 .bit_range_end = 0,
1623 .child_type = data.rhs,
1708 .bit_range_start = .none,
1709 .bit_range_end = .none,
1710 .child_type = child_type,
16241711 });
16251712}
16261713
16271714pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {
1628 assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range);
1629 const data = tree.nodes.items(.data)[node];
1630 const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange);
1715 assert(tree.nodeTag(node) == .ptr_type_bit_range);
1716 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1717 const extra = tree.extraData(extra_index, Node.PtrTypeBitRange);
16311718 return tree.fullPtrTypeComponents(.{
1632 .main_token = tree.nodes.items(.main_token)[node],
1633 .align_node = extra.align_node,
1719 .main_token = tree.nodeMainToken(node),
1720 .align_node = extra.align_node.toOptional(),
16341721 .addrspace_node = extra.addrspace_node,
16351722 .sentinel = extra.sentinel,
1636 .bit_range_start = extra.bit_range_start,
1637 .bit_range_end = extra.bit_range_end,
1638 .child_type = data.rhs,
1723 .bit_range_start = extra.bit_range_start.toOptional(),
1724 .bit_range_end = extra.bit_range_end.toOptional(),
1725 .child_type = child_type,
16391726 });
16401727}
16411728
16421729pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {
1643 assert(tree.nodes.items(.tag)[node] == .slice_open);
1644 const data = tree.nodes.items(.data)[node];
1730 assert(tree.nodeTag(node) == .slice_open);
1731 const sliced, const start = tree.nodeData(node).node_and_node;
16451732 return .{
16461733 .ast = .{
1647 .sliced = data.lhs,
1648 .lbracket = tree.nodes.items(.main_token)[node],
1649 .start = data.rhs,
1650 .end = 0,
1651 .sentinel = 0,
1734 .sliced = sliced,
1735 .lbracket = tree.nodeMainToken(node),
1736 .start = start,
1737 .end = .none,
1738 .sentinel = .none,
16521739 },
16531740 };
16541741}
16551742
16561743pub fn slice(tree: Ast, node: Node.Index) full.Slice {
1657 assert(tree.nodes.items(.tag)[node] == .slice);
1658 const data = tree.nodes.items(.data)[node];
1659 const extra = tree.extraData(data.rhs, Node.Slice);
1744 assert(tree.nodeTag(node) == .slice);
1745 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1746 const extra = tree.extraData(extra_index, Node.Slice);
16601747 return .{
16611748 .ast = .{
1662 .sliced = data.lhs,
1663 .lbracket = tree.nodes.items(.main_token)[node],
1749 .sliced = sliced,
1750 .lbracket = tree.nodeMainToken(node),
16641751 .start = extra.start,
1665 .end = extra.end,
1666 .sentinel = 0,
1752 .end = extra.end.toOptional(),
1753 .sentinel = .none,
16671754 },
16681755 };
16691756}
16701757
16711758pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {
1672 assert(tree.nodes.items(.tag)[node] == .slice_sentinel);
1673 const data = tree.nodes.items(.data)[node];
1674 const extra = tree.extraData(data.rhs, Node.SliceSentinel);
1759 assert(tree.nodeTag(node) == .slice_sentinel);
1760 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1761 const extra = tree.extraData(extra_index, Node.SliceSentinel);
16751762 return .{
16761763 .ast = .{
1677 .sliced = data.lhs,
1678 .lbracket = tree.nodes.items(.main_token)[node],
1764 .sliced = sliced,
1765 .lbracket = tree.nodeMainToken(node),
16791766 .start = extra.start,
16801767 .end = extra.end,
1681 .sentinel = extra.sentinel,
1768 .sentinel = extra.sentinel.toOptional(),
16821769 },
16831770 };
16841771}
16851772
16861773pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1687 assert(tree.nodes.items(.tag)[node] == .container_decl_two or
1688 tree.nodes.items(.tag)[node] == .container_decl_two_trailing);
1689 const data = tree.nodes.items(.data)[node];
1690 buffer.* = .{ data.lhs, data.rhs };
1691 const members = if (data.rhs != 0)
1692 buffer[0..2]
1693 else if (data.lhs != 0)
1694 buffer[0..1]
1695 else
1696 buffer[0..0];
1774 assert(tree.nodeTag(node) == .container_decl_two or
1775 tree.nodeTag(node) == .container_decl_two_trailing);
1776 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
16971777 return tree.fullContainerDeclComponents(.{
1698 .main_token = tree.nodes.items(.main_token)[node],
1778 .main_token = tree.nodeMainToken(node),
16991779 .enum_token = null,
17001780 .members = members,
1701 .arg = 0,
1781 .arg = .none,
17021782 });
17031783}
17041784
17051785pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {
1706 assert(tree.nodes.items(.tag)[node] == .container_decl or
1707 tree.nodes.items(.tag)[node] == .container_decl_trailing);
1708 const data = tree.nodes.items(.data)[node];
1786 assert(tree.nodeTag(node) == .container_decl or
1787 tree.nodeTag(node) == .container_decl_trailing);
1788 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
17091789 return tree.fullContainerDeclComponents(.{
1710 .main_token = tree.nodes.items(.main_token)[node],
1790 .main_token = tree.nodeMainToken(node),
17111791 .enum_token = null,
1712 .members = tree.extra_data[data.lhs..data.rhs],
1713 .arg = 0,
1792 .members = members,
1793 .arg = .none,
17141794 });
17151795}
17161796
17171797pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {
1718 assert(tree.nodes.items(.tag)[node] == .container_decl_arg or
1719 tree.nodes.items(.tag)[node] == .container_decl_arg_trailing);
1720 const data = tree.nodes.items(.data)[node];
1721 const members_range = tree.extraData(data.rhs, Node.SubRange);
1798 assert(tree.nodeTag(node) == .container_decl_arg or
1799 tree.nodeTag(node) == .container_decl_arg_trailing);
1800 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1801 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
17221802 return tree.fullContainerDeclComponents(.{
1723 .main_token = tree.nodes.items(.main_token)[node],
1803 .main_token = tree.nodeMainToken(node),
17241804 .enum_token = null,
1725 .members = tree.extra_data[members_range.start..members_range.end],
1726 .arg = data.lhs,
1805 .members = members,
1806 .arg = arg.toOptional(),
17271807 });
17281808}
17291809
......@@ -1731,175 +1811,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {
17311811 return .{
17321812 .layout_token = null,
17331813 .ast = .{
1734 .main_token = undefined,
1814 .main_token = 0,
17351815 .enum_token = null,
17361816 .members = tree.rootDecls(),
1737 .arg = 0,
1817 .arg = .none,
17381818 },
17391819 };
17401820}
17411821
17421822pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1743 assert(tree.nodes.items(.tag)[node] == .tagged_union_two or
1744 tree.nodes.items(.tag)[node] == .tagged_union_two_trailing);
1745 const data = tree.nodes.items(.data)[node];
1746 buffer.* = .{ data.lhs, data.rhs };
1747 const members = if (data.rhs != 0)
1748 buffer[0..2]
1749 else if (data.lhs != 0)
1750 buffer[0..1]
1751 else
1752 buffer[0..0];
1753 const main_token = tree.nodes.items(.main_token)[node];
1823 assert(tree.nodeTag(node) == .tagged_union_two or
1824 tree.nodeTag(node) == .tagged_union_two_trailing);
1825 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1826 const main_token = tree.nodeMainToken(node);
17541827 return tree.fullContainerDeclComponents(.{
17551828 .main_token = main_token,
17561829 .enum_token = main_token + 2, // union lparen enum
17571830 .members = members,
1758 .arg = 0,
1831 .arg = .none,
17591832 });
17601833}
17611834
17621835pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {
1763 assert(tree.nodes.items(.tag)[node] == .tagged_union or
1764 tree.nodes.items(.tag)[node] == .tagged_union_trailing);
1765 const data = tree.nodes.items(.data)[node];
1766 const main_token = tree.nodes.items(.main_token)[node];
1836 assert(tree.nodeTag(node) == .tagged_union or
1837 tree.nodeTag(node) == .tagged_union_trailing);
1838 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1839 const main_token = tree.nodeMainToken(node);
17671840 return tree.fullContainerDeclComponents(.{
17681841 .main_token = main_token,
17691842 .enum_token = main_token + 2, // union lparen enum
1770 .members = tree.extra_data[data.lhs..data.rhs],
1771 .arg = 0,
1843 .members = members,
1844 .arg = .none,
17721845 });
17731846}
17741847
17751848pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {
1776 assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or
1777 tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing);
1778 const data = tree.nodes.items(.data)[node];
1779 const members_range = tree.extraData(data.rhs, Node.SubRange);
1780 const main_token = tree.nodes.items(.main_token)[node];
1849 assert(tree.nodeTag(node) == .tagged_union_enum_tag or
1850 tree.nodeTag(node) == .tagged_union_enum_tag_trailing);
1851 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1852 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1853 const main_token = tree.nodeMainToken(node);
17811854 return tree.fullContainerDeclComponents(.{
17821855 .main_token = main_token,
17831856 .enum_token = main_token + 2, // union lparen enum
1784 .members = tree.extra_data[members_range.start..members_range.end],
1785 .arg = data.lhs,
1857 .members = members,
1858 .arg = arg.toOptional(),
17861859 });
17871860}
17881861
17891862pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {
1790 const data = &tree.nodes.items(.data)[node];
1791 const main_token = tree.nodes.items(.main_token)[node];
1792 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) {
1863 const main_token = tree.nodeMainToken(node);
1864 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) {
17931865 .identifier => .{ main_token + 2, main_token },
17941866 .keyword_switch => .{ main_token, null },
17951867 else => unreachable,
17961868 };
1797 const extra = tree.extraData(data.rhs, Ast.Node.SubRange);
1869 const condition, const extra_index = tree.nodeData(node).node_and_extra;
1870 const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index);
17981871 return .{
17991872 .ast = .{
18001873 .switch_token = switch_token,
1801 .condition = data.lhs,
1802 .cases = tree.extra_data[extra.start..extra.end],
1874 .condition = condition,
1875 .cases = cases,
18031876 },
18041877 .label_token = label_token,
18051878 };
18061879}
18071880
18081881pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
1809 const data = &tree.nodes.items(.data)[node];
1810 const values: *[1]Node.Index = &data.lhs;
1882 const first_value, const target_expr = tree.nodeData(node).opt_node_and_node;
18111883 return tree.fullSwitchCaseComponents(.{
1812 .values = if (data.lhs == 0) values[0..0] else values[0..1],
1813 .arrow_token = tree.nodes.items(.main_token)[node],
1814 .target_expr = data.rhs,
1884 .values = if (first_value == .none)
1885 &.{}
1886 else
1887 // Ensure that the returned slice points into the existing memory of the Ast
1888 (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1],
1889 .arrow_token = tree.nodeMainToken(node),
1890 .target_expr = target_expr,
18151891 }, node);
18161892}
18171893
18181894pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
1819 const data = tree.nodes.items(.data)[node];
1820 const extra = tree.extraData(data.lhs, Node.SubRange);
1895 const extra_index, const target_expr = tree.nodeData(node).extra_and_node;
1896 const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
18211897 return tree.fullSwitchCaseComponents(.{
1822 .values = tree.extra_data[extra.start..extra.end],
1823 .arrow_token = tree.nodes.items(.main_token)[node],
1824 .target_expr = data.rhs,
1898 .values = values,
1899 .arrow_token = tree.nodeMainToken(node),
1900 .target_expr = target_expr,
18251901 }, node);
18261902}
18271903
18281904pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {
1829 const data = tree.nodes.items(.data)[node];
1905 const template, const rparen = tree.nodeData(node).node_and_token;
18301906 return tree.fullAsmComponents(.{
1831 .asm_token = tree.nodes.items(.main_token)[node],
1832 .template = data.lhs,
1907 .asm_token = tree.nodeMainToken(node),
1908 .template = template,
18331909 .items = &.{},
1834 .rparen = data.rhs,
1910 .rparen = rparen,
18351911 });
18361912}
18371913
18381914pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {
1839 const data = tree.nodes.items(.data)[node];
1840 const extra = tree.extraData(data.rhs, Node.Asm);
1915 const template, const extra_index = tree.nodeData(node).node_and_extra;
1916 const extra = tree.extraData(extra_index, Node.Asm);
1917 const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index);
18411918 return tree.fullAsmComponents(.{
1842 .asm_token = tree.nodes.items(.main_token)[node],
1843 .template = data.lhs,
1844 .items = tree.extra_data[extra.items_start..extra.items_end],
1919 .asm_token = tree.nodeMainToken(node),
1920 .template = template,
1921 .items = items,
18451922 .rparen = extra.rparen,
18461923 });
18471924}
18481925
18491926pub fn whileSimple(tree: Ast, node: Node.Index) full.While {
1850 const data = tree.nodes.items(.data)[node];
1927 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
18511928 return tree.fullWhileComponents(.{
1852 .while_token = tree.nodes.items(.main_token)[node],
1853 .cond_expr = data.lhs,
1854 .cont_expr = 0,
1855 .then_expr = data.rhs,
1856 .else_expr = 0,
1929 .while_token = tree.nodeMainToken(node),
1930 .cond_expr = cond_expr,
1931 .cont_expr = .none,
1932 .then_expr = then_expr,
1933 .else_expr = .none,
18571934 });
18581935}
18591936
18601937pub fn whileCont(tree: Ast, node: Node.Index) full.While {
1861 const data = tree.nodes.items(.data)[node];
1862 const extra = tree.extraData(data.rhs, Node.WhileCont);
1938 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1939 const extra = tree.extraData(extra_index, Node.WhileCont);
18631940 return tree.fullWhileComponents(.{
1864 .while_token = tree.nodes.items(.main_token)[node],
1865 .cond_expr = data.lhs,
1866 .cont_expr = extra.cont_expr,
1941 .while_token = tree.nodeMainToken(node),
1942 .cond_expr = cond_expr,
1943 .cont_expr = extra.cont_expr.toOptional(),
18671944 .then_expr = extra.then_expr,
1868 .else_expr = 0,
1945 .else_expr = .none,
18691946 });
18701947}
18711948
18721949pub fn whileFull(tree: Ast, node: Node.Index) full.While {
1873 const data = tree.nodes.items(.data)[node];
1874 const extra = tree.extraData(data.rhs, Node.While);
1950 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1951 const extra = tree.extraData(extra_index, Node.While);
18751952 return tree.fullWhileComponents(.{
1876 .while_token = tree.nodes.items(.main_token)[node],
1877 .cond_expr = data.lhs,
1953 .while_token = tree.nodeMainToken(node),
1954 .cond_expr = cond_expr,
18781955 .cont_expr = extra.cont_expr,
18791956 .then_expr = extra.then_expr,
1880 .else_expr = extra.else_expr,
1957 .else_expr = extra.else_expr.toOptional(),
18811958 });
18821959}
18831960
18841961pub fn forSimple(tree: Ast, node: Node.Index) full.For {
1885 const data = &tree.nodes.items(.data)[node];
1886 const inputs: *[1]Node.Index = &data.lhs;
1962 const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node;
18871963 return tree.fullForComponents(.{
1888 .for_token = tree.nodes.items(.main_token)[node],
1889 .inputs = inputs[0..1],
1890 .then_expr = data.rhs,
1891 .else_expr = 0,
1964 .for_token = tree.nodeMainToken(node),
1965 .inputs = (&data[0])[0..1],
1966 .then_expr = data[1],
1967 .else_expr = .none,
18921968 });
18931969}
18941970
18951971pub fn forFull(tree: Ast, node: Node.Index) full.For {
1896 const data = tree.nodes.items(.data)[node];
1897 const extra = @as(Node.For, @bitCast(data.rhs));
1898 const inputs = tree.extra_data[data.lhs..][0..extra.inputs];
1899 const then_expr = tree.extra_data[data.lhs + extra.inputs];
1900 const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0;
1972 const extra_index, const extra = tree.nodeData(node).@"for";
1973 const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index);
1974 const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]);
1975 const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none;
19011976 return tree.fullForComponents(.{
1902 .for_token = tree.nodes.items(.main_token)[node],
1977 .for_token = tree.nodeMainToken(node),
19031978 .inputs = inputs,
19041979 .then_expr = then_expr,
19051980 .else_expr = else_expr,
......@@ -1907,28 +1982,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
19071982}
19081983
19091984pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
1910 const data = tree.nodes.items(.data)[node];
1911 buffer.* = .{data.rhs};
1912 const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0];
1985 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
1986 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
19131987 return tree.fullCallComponents(.{
1914 .lparen = tree.nodes.items(.main_token)[node],
1915 .fn_expr = data.lhs,
1988 .lparen = tree.nodeMainToken(node),
1989 .fn_expr = fn_expr,
19161990 .params = params,
19171991 });
19181992}
19191993
19201994pub fn callFull(tree: Ast, node: Node.Index) full.Call {
1921 const data = tree.nodes.items(.data)[node];
1922 const extra = tree.extraData(data.rhs, Node.SubRange);
1995 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
1996 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
19231997 return tree.fullCallComponents(.{
1924 .lparen = tree.nodes.items(.main_token)[node],
1925 .fn_expr = data.lhs,
1926 .params = tree.extra_data[extra.start..extra.end],
1998 .lparen = tree.nodeMainToken(node),
1999 .fn_expr = fn_expr,
2000 .params = params,
19272001 });
19282002}
19292003
19302004fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
1931 const token_tags = tree.tokens.items(.tag);
19322005 var result: full.VarDecl = .{
19332006 .ast = info,
19342007 .visib_token = null,
......@@ -1940,7 +2013,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
19402013 var i = info.mut_token;
19412014 while (i > 0) {
19422015 i -= 1;
1943 switch (token_tags[i]) {
2016 switch (tree.tokenTag(i)) {
19442017 .keyword_extern, .keyword_export => result.extern_export_token = i,
19452018 .keyword_comptime => result.comptime_token = i,
19462019 .keyword_pub => result.visib_token = i,
......@@ -1953,14 +2026,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
19532026}
19542027
19552028fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {
1956 const token_tags = tree.tokens.items(.tag);
1957 const node_tags = tree.nodes.items(.tag);
19582029 var result: full.AssignDestructure = .{
19592030 .comptime_token = null,
19602031 .ast = info,
19612032 };
19622033 const first_variable_token = tree.firstToken(info.variables[0]);
1963 const maybe_comptime_token = switch (node_tags[info.variables[0]]) {
2034 const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) {
19642035 .global_var_decl,
19652036 .local_var_decl,
19662037 .aligned_var_decl,
......@@ -1968,14 +2039,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo
19682039 => first_variable_token,
19692040 else => first_variable_token - 1,
19702041 };
1971 if (token_tags[maybe_comptime_token] == .keyword_comptime) {
2042 if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) {
19722043 result.comptime_token = maybe_comptime_token;
19732044 }
19742045 return result;
19752046}
19762047
19772048fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
1978 const token_tags = tree.tokens.items(.tag);
19792049 var result: full.If = .{
19802050 .ast = info,
19812051 .payload_token = null,
......@@ -1985,14 +2055,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
19852055 // if (cond_expr) |x|
19862056 // ^ ^
19872057 const payload_pipe = tree.lastToken(info.cond_expr) + 2;
1988 if (token_tags[payload_pipe] == .pipe) {
2058 if (tree.tokenTag(payload_pipe) == .pipe) {
19892059 result.payload_token = payload_pipe + 1;
19902060 }
1991 if (info.else_expr != 0) {
2061 if (info.else_expr != .none) {
19922062 // then_expr else |x|
19932063 // ^ ^
19942064 result.else_token = tree.lastToken(info.then_expr) + 1;
1995 if (token_tags[result.else_token + 1] == .pipe) {
2065 if (tree.tokenTag(result.else_token + 1) == .pipe) {
19962066 result.error_token = result.else_token + 2;
19972067 }
19982068 }
......@@ -2000,12 +2070,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
20002070}
20012071
20022072fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {
2003 const token_tags = tree.tokens.items(.tag);
20042073 var result: full.ContainerField = .{
20052074 .ast = info,
20062075 .comptime_token = null,
20072076 };
2008 if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {
2077 if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) {
20092078 // comptime type = init,
20102079 // ^ ^
20112080 // comptime name: type = init,
......@@ -2016,7 +2085,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)
20162085}
20172086
20182087fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {
2019 const token_tags = tree.tokens.items(.tag);
20202088 var result: full.FnProto = .{
20212089 .ast = info,
20222090 .visib_token = null,
......@@ -2028,7 +2096,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
20282096 var i = info.fn_token;
20292097 while (i > 0) {
20302098 i -= 1;
2031 switch (token_tags[i]) {
2099 switch (tree.tokenTag(i)) {
20322100 .keyword_extern,
20332101 .keyword_export,
20342102 .keyword_inline,
......@@ -2040,25 +2108,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
20402108 }
20412109 }
20422110 const after_fn_token = info.fn_token + 1;
2043 if (token_tags[after_fn_token] == .identifier) {
2111 if (tree.tokenTag(after_fn_token) == .identifier) {
20442112 result.name_token = after_fn_token;
20452113 result.lparen = after_fn_token + 1;
20462114 } else {
20472115 result.lparen = after_fn_token;
20482116 }
2049 assert(token_tags[result.lparen] == .l_paren);
2117 assert(tree.tokenTag(result.lparen) == .l_paren);
20502118
20512119 return result;
20522120}
20532121
20542122fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {
2055 const token_tags = tree.tokens.items(.tag);
2056 const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) {
2123 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {
20572124 .asterisk,
20582125 .asterisk_asterisk,
20592126 => .one,
2060 .l_bracket => switch (token_tags[info.main_token + 1]) {
2061 .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many,
2127 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {
2128 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,
20622129 else => .slice,
20632130 },
20642131 else => unreachable,
......@@ -2074,23 +2141,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
20742141 // here while looking for modifiers as that could result in false
20752142 // positives. Therefore, start after a sentinel if there is one and
20762143 // skip over any align node and bit range nodes.
2077 var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) {
2144 var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) {
20782145 .many, .c => info.main_token + 1,
20792146 else => info.main_token,
20802147 };
20812148 const end = tree.firstToken(info.child_type);
20822149 while (i < end) : (i += 1) {
2083 switch (token_tags[i]) {
2150 switch (tree.tokenTag(i)) {
20842151 .keyword_allowzero => result.allowzero_token = i,
20852152 .keyword_const => result.const_token = i,
20862153 .keyword_volatile => result.volatile_token = i,
20872154 .keyword_align => {
2088 assert(info.align_node != 0);
2089 if (info.bit_range_end != 0) {
2090 assert(info.bit_range_start != 0);
2091 i = tree.lastToken(info.bit_range_end) + 1;
2155 const align_node = info.align_node.unwrap().?;
2156 if (info.bit_range_end.unwrap()) |bit_range_end| {
2157 assert(info.bit_range_start != .none);
2158 i = tree.lastToken(bit_range_end) + 1;
20922159 } else {
2093 i = tree.lastToken(info.align_node) + 1;
2160 i = tree.lastToken(align_node) + 1;
20942161 }
20952162 },
20962163 else => {},
......@@ -2100,30 +2167,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
21002167}
21012168
21022169fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {
2103 const token_tags = tree.tokens.items(.tag);
21042170 var result: full.ContainerDecl = .{
21052171 .ast = info,
21062172 .layout_token = null,
21072173 };
21082174
2109 if (info.main_token == 0) return result;
2175 if (info.main_token == 0) return result; // .root
2176 const previous_token = info.main_token - 1;
21102177
2111 switch (token_tags[info.main_token - 1]) {
2112 .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1,
2178 switch (tree.tokenTag(previous_token)) {
2179 .keyword_extern, .keyword_packed => result.layout_token = previous_token,
21132180 else => {},
21142181 }
21152182 return result;
21162183}
21172184
21182185fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2119 const token_tags = tree.tokens.items(.tag);
21202186 const tok_i = info.switch_token -| 1;
21212187 var result: full.Switch = .{
21222188 .ast = info,
21232189 .label_token = null,
21242190 };
2125 if (token_tags[tok_i] == .colon and
2126 token_tags[tok_i -| 1] == .identifier)
2191 if (tree.tokenTag(tok_i) == .colon and
2192 tree.tokenTag(tok_i -| 1) == .identifier)
21272193 {
21282194 result.label_token = tok_i - 1;
21292195 }
......@@ -2131,26 +2197,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
21312197}
21322198
21332199fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
2134 const token_tags = tree.tokens.items(.tag);
2135 const node_tags = tree.nodes.items(.tag);
21362200 var result: full.SwitchCase = .{
21372201 .ast = info,
21382202 .payload_token = null,
21392203 .inline_token = null,
21402204 };
2141 if (token_tags[info.arrow_token + 1] == .pipe) {
2205 if (tree.tokenTag(info.arrow_token + 1) == .pipe) {
21422206 result.payload_token = info.arrow_token + 2;
21432207 }
2144 switch (node_tags[node]) {
2145 .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node),
2146 else => {},
2147 }
2208 result.inline_token = switch (tree.nodeTag(node)) {
2209 .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0)
2210 info.arrow_token - 2
2211 else
2212 tree.firstToken(result.ast.values[0]) - 1,
2213 else => null,
2214 };
21482215 return result;
21492216}
21502217
21512218fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2152 const token_tags = tree.tokens.items(.tag);
2153 const node_tags = tree.nodes.items(.tag);
21542219 var result: full.Asm = .{
21552220 .ast = info,
21562221 .volatile_token = null,
......@@ -2158,11 +2223,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
21582223 .outputs = &.{},
21592224 .first_clobber = null,
21602225 };
2161 if (token_tags[info.asm_token + 1] == .keyword_volatile) {
2226 if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) {
21622227 result.volatile_token = info.asm_token + 1;
21632228 }
21642229 const outputs_end: usize = for (info.items, 0..) |item, i| {
2165 switch (node_tags[item]) {
2230 switch (tree.nodeTag(item)) {
21662231 .asm_output => continue,
21672232 else => break i,
21682233 }
......@@ -2174,10 +2239,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
21742239 if (info.items.len == 0) {
21752240 // asm ("foo" ::: "a", "b");
21762241 const template_token = tree.lastToken(info.template);
2177 if (token_tags[template_token + 1] == .colon and
2178 token_tags[template_token + 2] == .colon and
2179 token_tags[template_token + 3] == .colon and
2180 token_tags[template_token + 4] == .string_literal)
2242 if (tree.tokenTag(template_token + 1) == .colon and
2243 tree.tokenTag(template_token + 2) == .colon and
2244 tree.tokenTag(template_token + 3) == .colon and
2245 tree.tokenTag(template_token + 4) == .string_literal)
21812246 {
21822247 result.first_clobber = template_token + 4;
21832248 }
......@@ -2187,9 +2252,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
21872252 const rparen = tree.lastToken(last_input);
21882253 var i = rparen + 1;
21892254 // Allow a (useless) comma right after the closing parenthesis.
2190 if (token_tags[i] == .comma) i += 1;
2191 if (token_tags[i] == .colon and
2192 token_tags[i + 1] == .string_literal)
2255 if (tree.tokenTag(i) == .comma) i = i + 1;
2256 if (tree.tokenTag(i) == .colon and
2257 tree.tokenTag(i + 1) == .string_literal)
21932258 {
21942259 result.first_clobber = i + 1;
21952260 }
......@@ -2199,10 +2264,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
21992264 const rparen = tree.lastToken(last_output);
22002265 var i = rparen + 1;
22012266 // Allow a (useless) comma right after the closing parenthesis.
2202 if (token_tags[i] == .comma) i += 1;
2203 if (token_tags[i] == .colon and
2204 token_tags[i + 1] == .colon and
2205 token_tags[i + 2] == .string_literal)
2267 if (tree.tokenTag(i) == .comma) i = i + 1;
2268 if (tree.tokenTag(i) == .colon and
2269 tree.tokenTag(i + 1) == .colon and
2270 tree.tokenTag(i + 2) == .string_literal)
22062271 {
22072272 result.first_clobber = i + 2;
22082273 }
......@@ -2212,7 +2277,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
22122277}
22132278
22142279fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2215 const token_tags = tree.tokens.items(.tag);
22162280 var result: full.While = .{
22172281 .ast = info,
22182282 .inline_token = null,
......@@ -2221,25 +2285,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
22212285 .else_token = undefined,
22222286 .error_token = null,
22232287 };
2224 var tok_i = info.while_token -| 1;
2225 if (token_tags[tok_i] == .keyword_inline) {
2226 result.inline_token = tok_i;
2227 tok_i -|= 1;
2288 var tok_i = info.while_token;
2289 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2290 result.inline_token = tok_i - 1;
2291 tok_i = tok_i - 1;
22282292 }
2229 if (token_tags[tok_i] == .colon and
2230 token_tags[tok_i -| 1] == .identifier)
2231 {
2232 result.label_token = tok_i - 1;
2293 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2294 result.label_token = tok_i - 2;
22332295 }
22342296 const last_cond_token = tree.lastToken(info.cond_expr);
2235 if (token_tags[last_cond_token + 2] == .pipe) {
2297 if (tree.tokenTag(last_cond_token + 2) == .pipe) {
22362298 result.payload_token = last_cond_token + 3;
22372299 }
2238 if (info.else_expr != 0) {
2300 if (info.else_expr != .none) {
22392301 // then_expr else |x|
22402302 // ^ ^
22412303 result.else_token = tree.lastToken(info.then_expr) + 1;
2242 if (token_tags[result.else_token + 1] == .pipe) {
2304 if (tree.tokenTag(result.else_token + 1) == .pipe) {
22432305 result.error_token = result.else_token + 2;
22442306 }
22452307 }
......@@ -2247,7 +2309,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
22472309}
22482310
22492311fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2250 const token_tags = tree.tokens.items(.tag);
22512312 var result: full.For = .{
22522313 .ast = info,
22532314 .inline_token = null,
......@@ -2255,39 +2316,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
22552316 .payload_token = undefined,
22562317 .else_token = undefined,
22572318 };
2258 var tok_i = info.for_token -| 1;
2259 if (token_tags[tok_i] == .keyword_inline) {
2260 result.inline_token = tok_i;
2261 tok_i -|= 1;
2319 var tok_i = info.for_token;
2320 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2321 result.inline_token = tok_i - 1;
2322 tok_i = tok_i - 1;
22622323 }
2263 if (token_tags[tok_i] == .colon and
2264 token_tags[tok_i -| 1] == .identifier)
2265 {
2266 result.label_token = tok_i - 1;
2324 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2325 result.label_token = tok_i - 2;
22672326 }
22682327 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);
2269 result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma);
2270 if (info.else_expr != 0) {
2328 result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma);
2329 if (info.else_expr != .none) {
22712330 result.else_token = tree.lastToken(info.then_expr) + 1;
22722331 }
22732332 return result;
22742333}
22752334
22762335fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
2277 const token_tags = tree.tokens.items(.tag);
22782336 var result: full.Call = .{
22792337 .ast = info,
22802338 .async_token = null,
22812339 };
22822340 const first_token = tree.firstToken(info.fn_expr);
2283 if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) {
2341 if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
22842342 result.async_token = first_token - 1;
22852343 }
22862344 return result;
22872345}
22882346
22892347pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2290 return switch (tree.nodes.items(.tag)[node]) {
2348 return switch (tree.nodeTag(node)) {
22912349 .global_var_decl => tree.globalVarDecl(node),
22922350 .local_var_decl => tree.localVarDecl(node),
22932351 .aligned_var_decl => tree.alignedVarDecl(node),
......@@ -2297,7 +2355,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
22972355}
22982356
22992357pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2300 return switch (tree.nodes.items(.tag)[node]) {
2358 return switch (tree.nodeTag(node)) {
23012359 .if_simple => tree.ifSimple(node),
23022360 .@"if" => tree.ifFull(node),
23032361 else => null,
......@@ -2305,7 +2363,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
23052363}
23062364
23072365pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2308 return switch (tree.nodes.items(.tag)[node]) {
2366 return switch (tree.nodeTag(node)) {
23092367 .while_simple => tree.whileSimple(node),
23102368 .while_cont => tree.whileCont(node),
23112369 .@"while" => tree.whileFull(node),
......@@ -2314,7 +2372,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
23142372}
23152373
23162374pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2317 return switch (tree.nodes.items(.tag)[node]) {
2375 return switch (tree.nodeTag(node)) {
23182376 .for_simple => tree.forSimple(node),
23192377 .@"for" => tree.forFull(node),
23202378 else => null,
......@@ -2322,7 +2380,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
23222380}
23232381
23242382pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2325 return switch (tree.nodes.items(.tag)[node]) {
2383 return switch (tree.nodeTag(node)) {
23262384 .container_field_init => tree.containerFieldInit(node),
23272385 .container_field_align => tree.containerFieldAlign(node),
23282386 .container_field => tree.containerField(node),
......@@ -2331,18 +2389,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
23312389}
23322390
23332391pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {
2334 return switch (tree.nodes.items(.tag)[node]) {
2392 return switch (tree.nodeTag(node)) {
23352393 .fn_proto => tree.fnProto(node),
23362394 .fn_proto_multi => tree.fnProtoMulti(node),
23372395 .fn_proto_one => tree.fnProtoOne(buffer, node),
23382396 .fn_proto_simple => tree.fnProtoSimple(buffer, node),
2339 .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs),
2397 .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]),
23402398 else => null,
23412399 };
23422400}
23432401
23442402pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {
2345 return switch (tree.nodes.items(.tag)[node]) {
2403 return switch (tree.nodeTag(node)) {
23462404 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),
23472405 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),
23482406 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),
......@@ -2352,7 +2410,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?
23522410}
23532411
23542412pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {
2355 return switch (tree.nodes.items(.tag)[node]) {
2413 return switch (tree.nodeTag(node)) {
23562414 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),
23572415 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),
23582416 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),
......@@ -2362,7 +2420,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.
23622420}
23632421
23642422pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2365 return switch (tree.nodes.items(.tag)[node]) {
2423 return switch (tree.nodeTag(node)) {
23662424 .array_type => tree.arrayType(node),
23672425 .array_type_sentinel => tree.arrayTypeSentinel(node),
23682426 else => null,
......@@ -2370,7 +2428,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
23702428}
23712429
23722430pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2373 return switch (tree.nodes.items(.tag)[node]) {
2431 return switch (tree.nodeTag(node)) {
23742432 .ptr_type_aligned => tree.ptrTypeAligned(node),
23752433 .ptr_type_sentinel => tree.ptrTypeSentinel(node),
23762434 .ptr_type => tree.ptrType(node),
......@@ -2380,7 +2438,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
23802438}
23812439
23822440pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2383 return switch (tree.nodes.items(.tag)[node]) {
2441 return switch (tree.nodeTag(node)) {
23842442 .slice_open => tree.sliceOpen(node),
23852443 .slice => tree.slice(node),
23862444 .slice_sentinel => tree.sliceSentinel(node),
......@@ -2389,7 +2447,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
23892447}
23902448
23912449pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {
2392 return switch (tree.nodes.items(.tag)[node]) {
2450 return switch (tree.nodeTag(node)) {
23932451 .root => tree.containerDeclRoot(),
23942452 .container_decl, .container_decl_trailing => tree.containerDecl(node),
23952453 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
......@@ -2402,14 +2460,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index
24022460}
24032461
24042462pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {
2405 return switch (tree.nodes.items(.tag)[node]) {
2463 return switch (tree.nodeTag(node)) {
24062464 .@"switch", .switch_comma => tree.switchFull(node),
24072465 else => null,
24082466 };
24092467}
24102468
24112469pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2412 return switch (tree.nodes.items(.tag)[node]) {
2470 return switch (tree.nodeTag(node)) {
24132471 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),
24142472 .switch_case, .switch_case_inline => tree.switchCase(node),
24152473 else => null,
......@@ -2417,7 +2475,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
24172475}
24182476
24192477pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2420 return switch (tree.nodes.items(.tag)[node]) {
2478 return switch (tree.nodeTag(node)) {
24212479 .asm_simple => tree.asmSimple(node),
24222480 .@"asm" => tree.asmFull(node),
24232481 else => null,
......@@ -2425,7 +2483,7 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
24252483}
24262484
24272485pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
2428 return switch (tree.nodes.items(.tag)[node]) {
2486 return switch (tree.nodeTag(node)) {
24292487 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
24302488 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
24312489 else => null,
......@@ -2433,37 +2491,17 @@ pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.C
24332491}
24342492
24352493pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2436 const data = tree.nodes.items(.data)[node];
2437 return switch (tree.nodes.items(.tag)[node]) {
2438 .builtin_call_two, .builtin_call_two_comma => {
2439 buffer.* = .{ data.lhs, data.rhs };
2440 if (data.rhs != 0) {
2441 return buffer[0..2];
2442 } else if (data.lhs != 0) {
2443 return buffer[0..1];
2444 } else {
2445 return buffer[0..0];
2446 }
2447 },
2448 .builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
2494 return switch (tree.nodeTag(node)) {
2495 .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2496 .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
24492497 else => null,
24502498 };
24512499}
24522500
24532501pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2454 const data = tree.nodes.items(.data)[node];
2455 return switch (tree.nodes.items(.tag)[node]) {
2456 .block_two, .block_two_semicolon => {
2457 buffer.* = .{ data.lhs, data.rhs };
2458 if (data.rhs != 0) {
2459 return buffer[0..2];
2460 } else if (data.lhs != 0) {
2461 return buffer[0..1];
2462 } else {
2463 return buffer[0..0];
2464 }
2465 },
2466 .block, .block_semicolon => tree.extra_data[data.lhs..data.rhs],
2502 return switch (tree.nodeTag(node)) {
2503 .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2504 .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
24672505 else => null,
24682506 };
24692507}
......@@ -2480,11 +2518,11 @@ pub const full = struct {
24802518
24812519 pub const Components = struct {
24822520 mut_token: TokenIndex,
2483 type_node: Node.Index,
2484 align_node: Node.Index,
2485 addrspace_node: Node.Index,
2486 section_node: Node.Index,
2487 init_node: Node.Index,
2521 type_node: Node.OptionalIndex,
2522 align_node: Node.OptionalIndex,
2523 addrspace_node: Node.OptionalIndex,
2524 section_node: Node.OptionalIndex,
2525 init_node: Node.OptionalIndex,
24882526 };
24892527
24902528 pub fn firstToken(var_decl: VarDecl) TokenIndex {
......@@ -2513,7 +2551,7 @@ pub const full = struct {
25132551 payload_token: ?TokenIndex,
25142552 /// Points to the identifier after the `|`.
25152553 error_token: ?TokenIndex,
2516 /// Populated only if else_expr != 0.
2554 /// Populated only if else_expr != .none.
25172555 else_token: TokenIndex,
25182556 ast: Components,
25192557
......@@ -2521,7 +2559,7 @@ pub const full = struct {
25212559 if_token: TokenIndex,
25222560 cond_expr: Node.Index,
25232561 then_expr: Node.Index,
2524 else_expr: Node.Index,
2562 else_expr: Node.OptionalIndex,
25252563 };
25262564 };
25272565
......@@ -2531,15 +2569,15 @@ pub const full = struct {
25312569 label_token: ?TokenIndex,
25322570 payload_token: ?TokenIndex,
25332571 error_token: ?TokenIndex,
2534 /// Populated only if else_expr != 0.
2572 /// Populated only if else_expr != none.
25352573 else_token: TokenIndex,
25362574
25372575 pub const Components = struct {
25382576 while_token: TokenIndex,
25392577 cond_expr: Node.Index,
2540 cont_expr: Node.Index,
2578 cont_expr: Node.OptionalIndex,
25412579 then_expr: Node.Index,
2542 else_expr: Node.Index,
2580 else_expr: Node.OptionalIndex,
25432581 };
25442582 };
25452583
......@@ -2548,14 +2586,14 @@ pub const full = struct {
25482586 inline_token: ?TokenIndex,
25492587 label_token: ?TokenIndex,
25502588 payload_token: TokenIndex,
2551 /// Populated only if else_expr != 0.
2552 else_token: TokenIndex,
2589 /// Populated only if else_expr != .none.
2590 else_token: ?TokenIndex,
25532591
25542592 pub const Components = struct {
25552593 for_token: TokenIndex,
25562594 inputs: []const Node.Index,
25572595 then_expr: Node.Index,
2558 else_expr: Node.Index,
2596 else_expr: Node.OptionalIndex,
25592597 };
25602598 };
25612599
......@@ -2565,9 +2603,10 @@ pub const full = struct {
25652603
25662604 pub const Components = struct {
25672605 main_token: TokenIndex,
2568 type_expr: Node.Index,
2569 align_expr: Node.Index,
2570 value_expr: Node.Index,
2606 /// Can only be `.none` after calling `convertToNonTupleLike`.
2607 type_expr: Node.OptionalIndex,
2608 align_expr: Node.OptionalIndex,
2609 value_expr: Node.OptionalIndex,
25712610 tuple_like: bool,
25722611 };
25732612
......@@ -2575,11 +2614,11 @@ pub const full = struct {
25752614 return cf.comptime_token orelse cf.ast.main_token;
25762615 }
25772616
2578 pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void {
2617 pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void {
25792618 if (!cf.ast.tuple_like) return;
2580 if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return;
2619 if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return;
25812620
2582 cf.ast.type_expr = 0;
2621 cf.ast.type_expr = .none;
25832622 cf.ast.tuple_like = false;
25842623 }
25852624 };
......@@ -2595,12 +2634,12 @@ pub const full = struct {
25952634 pub const Components = struct {
25962635 proto_node: Node.Index,
25972636 fn_token: TokenIndex,
2598 return_type: Node.Index,
2637 return_type: Node.OptionalIndex,
25992638 params: []const Node.Index,
2600 align_expr: Node.Index,
2601 addrspace_expr: Node.Index,
2602 section_expr: Node.Index,
2603 callconv_expr: Node.Index,
2639 align_expr: Node.OptionalIndex,
2640 addrspace_expr: Node.OptionalIndex,
2641 section_expr: Node.OptionalIndex,
2642 callconv_expr: Node.OptionalIndex,
26042643 };
26052644
26062645 pub const Param = struct {
......@@ -2608,7 +2647,7 @@ pub const full = struct {
26082647 name_token: ?TokenIndex,
26092648 comptime_noalias: ?TokenIndex,
26102649 anytype_ellipsis3: ?TokenIndex,
2611 type_expr: Node.Index,
2650 type_expr: ?Node.Index,
26122651 };
26132652
26142653 pub fn firstToken(fn_proto: FnProto) TokenIndex {
......@@ -2628,7 +2667,7 @@ pub const full = struct {
26282667 tok_flag: bool,
26292668
26302669 pub fn next(it: *Iterator) ?Param {
2631 const token_tags = it.tree.tokens.items(.tag);
2670 const tree = it.tree;
26322671 while (true) {
26332672 var first_doc_comment: ?TokenIndex = null;
26342673 var comptime_noalias: ?TokenIndex = null;
......@@ -2638,8 +2677,8 @@ pub const full = struct {
26382677 return null;
26392678 }
26402679 const param_type = it.fn_proto.ast.params[it.param_i];
2641 var tok_i = it.tree.firstToken(param_type) - 1;
2642 while (true) : (tok_i -= 1) switch (token_tags[tok_i]) {
2680 var tok_i = tree.firstToken(param_type) - 1;
2681 while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) {
26432682 .colon => continue,
26442683 .identifier => name_token = tok_i,
26452684 .doc_comment => first_doc_comment = tok_i,
......@@ -2647,9 +2686,9 @@ pub const full = struct {
26472686 else => break,
26482687 };
26492688 it.param_i += 1;
2650 it.tok_i = it.tree.lastToken(param_type) + 1;
2689 it.tok_i = tree.lastToken(param_type) + 1;
26512690 // Look for anytype and ... params afterwards.
2652 if (token_tags[it.tok_i] == .comma) {
2691 if (tree.tokenTag(it.tok_i) == .comma) {
26532692 it.tok_i += 1;
26542693 }
26552694 it.tok_flag = true;
......@@ -2661,19 +2700,19 @@ pub const full = struct {
26612700 .type_expr = param_type,
26622701 };
26632702 }
2664 if (token_tags[it.tok_i] == .comma) {
2703 if (tree.tokenTag(it.tok_i) == .comma) {
26652704 it.tok_i += 1;
26662705 }
2667 if (token_tags[it.tok_i] == .r_paren) {
2706 if (tree.tokenTag(it.tok_i) == .r_paren) {
26682707 return null;
26692708 }
2670 if (token_tags[it.tok_i] == .doc_comment) {
2709 if (tree.tokenTag(it.tok_i) == .doc_comment) {
26712710 first_doc_comment = it.tok_i;
2672 while (token_tags[it.tok_i] == .doc_comment) {
2711 while (tree.tokenTag(it.tok_i) == .doc_comment) {
26732712 it.tok_i += 1;
26742713 }
26752714 }
2676 switch (token_tags[it.tok_i]) {
2715 switch (tree.tokenTag(it.tok_i)) {
26772716 .ellipsis3 => {
26782717 it.tok_flag = false; // Next iteration should return null.
26792718 return Param{
......@@ -2681,7 +2720,7 @@ pub const full = struct {
26812720 .comptime_noalias = null,
26822721 .name_token = null,
26832722 .anytype_ellipsis3 = it.tok_i,
2684 .type_expr = 0,
2723 .type_expr = null,
26852724 };
26862725 },
26872726 .keyword_noalias, .keyword_comptime => {
......@@ -2690,20 +2729,20 @@ pub const full = struct {
26902729 },
26912730 else => {},
26922731 }
2693 if (token_tags[it.tok_i] == .identifier and
2694 token_tags[it.tok_i + 1] == .colon)
2732 if (tree.tokenTag(it.tok_i) == .identifier and
2733 tree.tokenTag(it.tok_i + 1) == .colon)
26952734 {
26962735 name_token = it.tok_i;
26972736 it.tok_i += 2;
26982737 }
2699 if (token_tags[it.tok_i] == .keyword_anytype) {
2738 if (tree.tokenTag(it.tok_i) == .keyword_anytype) {
27002739 it.tok_i += 1;
27012740 return Param{
27022741 .first_doc_comment = first_doc_comment,
27032742 .comptime_noalias = comptime_noalias,
27042743 .name_token = name_token,
27052744 .anytype_ellipsis3 = it.tok_i - 1,
2706 .type_expr = 0,
2745 .type_expr = null,
27072746 };
27082747 }
27092748 it.tok_flag = false;
......@@ -2728,7 +2767,7 @@ pub const full = struct {
27282767 pub const Components = struct {
27292768 lbrace: TokenIndex,
27302769 fields: []const Node.Index,
2731 type_expr: Node.Index,
2770 type_expr: Node.OptionalIndex,
27322771 };
27332772 };
27342773
......@@ -2738,7 +2777,7 @@ pub const full = struct {
27382777 pub const Components = struct {
27392778 lbrace: TokenIndex,
27402779 elements: []const Node.Index,
2741 type_expr: Node.Index,
2780 type_expr: Node.OptionalIndex,
27422781 };
27432782 };
27442783
......@@ -2748,7 +2787,7 @@ pub const full = struct {
27482787 pub const Components = struct {
27492788 lbracket: TokenIndex,
27502789 elem_count: Node.Index,
2751 sentinel: Node.Index,
2790 sentinel: Node.OptionalIndex,
27522791 elem_type: Node.Index,
27532792 };
27542793 };
......@@ -2762,11 +2801,11 @@ pub const full = struct {
27622801
27632802 pub const Components = struct {
27642803 main_token: TokenIndex,
2765 align_node: Node.Index,
2766 addrspace_node: Node.Index,
2767 sentinel: Node.Index,
2768 bit_range_start: Node.Index,
2769 bit_range_end: Node.Index,
2804 align_node: Node.OptionalIndex,
2805 addrspace_node: Node.OptionalIndex,
2806 sentinel: Node.OptionalIndex,
2807 bit_range_start: Node.OptionalIndex,
2808 bit_range_end: Node.OptionalIndex,
27702809 child_type: Node.Index,
27712810 };
27722811 };
......@@ -2778,8 +2817,8 @@ pub const full = struct {
27782817 sliced: Node.Index,
27792818 lbracket: TokenIndex,
27802819 start: Node.Index,
2781 end: Node.Index,
2782 sentinel: Node.Index,
2820 end: Node.OptionalIndex,
2821 sentinel: Node.OptionalIndex,
27832822 };
27842823 };
27852824
......@@ -2792,7 +2831,7 @@ pub const full = struct {
27922831 /// Populated when main_token is Keyword_union.
27932832 enum_token: ?TokenIndex,
27942833 members: []const Node.Index,
2795 arg: Node.Index,
2834 arg: Node.OptionalIndex,
27962835 };
27972836 };
27982837
......@@ -2935,16 +2974,82 @@ pub const Error = struct {
29352974 };
29362975};
29372976
2977/// Index into `extra_data`.
2978pub const ExtraIndex = enum(u32) {
2979 _,
2980};
2981
29382982pub const Node = struct {
29392983 tag: Tag,
29402984 main_token: TokenIndex,
29412985 data: Data,
29422986
2943 pub const Index = u32;
2987 /// Index into `nodes`.
2988 pub const Index = enum(u32) {
2989 root = 0,
2990 _,
2991
2992 pub fn toOptional(i: Index) OptionalIndex {
2993 const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
2994 assert(result != .none);
2995 return result;
2996 }
2997
2998 pub fn toOffset(base: Index, destination: Index) Offset {
2999 const base_i64: i64 = @intFromEnum(base);
3000 const destination_i64: i64 = @intFromEnum(destination);
3001 return @enumFromInt(destination_i64 - base_i64);
3002 }
3003 };
3004
3005 /// Index into `nodes`, or null.
3006 pub const OptionalIndex = enum(u32) {
3007 root = 0,
3008 none = std.math.maxInt(u32),
3009 _,
3010
3011 pub fn unwrap(oi: OptionalIndex) ?Index {
3012 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
3013 }
3014
3015 pub fn fromOptional(oi: ?Index) OptionalIndex {
3016 return if (oi) |i| i.toOptional() else .none;
3017 }
3018 };
3019
3020 /// A relative node index.
3021 pub const Offset = enum(i32) {
3022 zero = 0,
3023 _,
3024
3025 pub fn toOptional(o: Offset) OptionalOffset {
3026 const result: OptionalOffset = @enumFromInt(@intFromEnum(o));
3027 assert(result != .none);
3028 return result;
3029 }
3030
3031 pub fn toAbsolute(offset: Offset, base: Index) Index {
3032 return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset));
3033 }
3034 };
3035
3036 /// A relative node index, or null.
3037 pub const OptionalOffset = enum(i32) {
3038 none = std.math.maxInt(i32),
3039 _,
3040
3041 pub fn unwrap(oo: OptionalOffset) ?Offset {
3042 return if (oo == .none) null else @enumFromInt(@intFromEnum(oo));
3043 }
3044 };
29443045
29453046 comptime {
29463047 // Goal is to keep this under one byte for efficiency.
29473048 assert(@sizeOf(Tag) == 1);
3049
3050 if (!std.debug.runtime_safety) {
3051 assert(@sizeOf(Data) == 8);
3052 }
29483053 }
29493054
29503055 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of
......@@ -3435,9 +3540,26 @@ pub const Node = struct {
34353540 }
34363541 };
34373542
3438 pub const Data = struct {
3439 lhs: Index,
3440 rhs: Index,
3543 pub const Data = union {
3544 node: Index,
3545 opt_node: OptionalIndex,
3546 token: TokenIndex,
3547 node_and_node: struct { Index, Index },
3548 opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex },
3549 node_and_opt_node: struct { Index, OptionalIndex },
3550 opt_node_and_node: struct { OptionalIndex, Index },
3551 node_and_extra: struct { Index, ExtraIndex },
3552 extra_and_node: struct { ExtraIndex, Index },
3553 extra_and_opt_node: struct { ExtraIndex, OptionalIndex },
3554 node_and_token: struct { Index, TokenIndex },
3555 token_and_node: struct { TokenIndex, Index },
3556 token_and_token: struct { TokenIndex, TokenIndex },
3557 opt_node_and_token: struct { OptionalIndex, TokenIndex },
3558 opt_token_and_node: struct { OptionalTokenIndex, Index },
3559 opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex },
3560 opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex },
3561 @"for": struct { ExtraIndex, For },
3562 extra_range: SubRange,
34413563 };
34423564
34433565 pub const LocalVarDecl = struct {
......@@ -3451,24 +3573,24 @@ pub const Node = struct {
34513573 };
34523574
34533575 pub const PtrType = struct {
3454 sentinel: Index,
3455 align_node: Index,
3456 addrspace_node: Index,
3576 sentinel: OptionalIndex,
3577 align_node: OptionalIndex,
3578 addrspace_node: OptionalIndex,
34573579 };
34583580
34593581 pub const PtrTypeBitRange = struct {
3460 sentinel: Index,
3582 sentinel: OptionalIndex,
34613583 align_node: Index,
3462 addrspace_node: Index,
3584 addrspace_node: OptionalIndex,
34633585 bit_range_start: Index,
34643586 bit_range_end: Index,
34653587 };
34663588
34673589 pub const SubRange = struct {
3468 /// Index into sub_list.
3469 start: Index,
3470 /// Index into sub_list.
3471 end: Index,
3590 /// Index into extra_data.
3591 start: ExtraIndex,
3592 /// Index into extra_data.
3593 end: ExtraIndex,
34723594 };
34733595
34743596 pub const If = struct {
......@@ -3483,13 +3605,13 @@ pub const Node = struct {
34833605
34843606 pub const GlobalVarDecl = struct {
34853607 /// Populated if there is an explicit type ascription.
3486 type_node: Index,
3608 type_node: OptionalIndex,
34873609 /// Populated if align(A) is present.
3488 align_node: Index,
3610 align_node: OptionalIndex,
34893611 /// Populated if addrspace(A) is present.
3490 addrspace_node: Index,
3612 addrspace_node: OptionalIndex,
34913613 /// Populated if linksection(A) is present.
3492 section_node: Index,
3614 section_node: OptionalIndex,
34933615 };
34943616
34953617 pub const Slice = struct {
......@@ -3499,13 +3621,13 @@ pub const Node = struct {
34993621
35003622 pub const SliceSentinel = struct {
35013623 start: Index,
3502 /// May be 0 if the slice is "open"
3503 end: Index,
3624 /// May be .none if the slice is "open"
3625 end: OptionalIndex,
35043626 sentinel: Index,
35053627 };
35063628
35073629 pub const While = struct {
3508 cont_expr: Index,
3630 cont_expr: OptionalIndex,
35093631 then_expr: Index,
35103632 else_expr: Index,
35113633 };
......@@ -3522,44 +3644,44 @@ pub const Node = struct {
35223644
35233645 pub const FnProtoOne = struct {
35243646 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.
3525 param: Index,
3647 param: OptionalIndex,
35263648 /// Populated if align(A) is present.
3527 align_expr: Index,
3649 align_expr: OptionalIndex,
35283650 /// Populated if addrspace(A) is present.
3529 addrspace_expr: Index,
3651 addrspace_expr: OptionalIndex,
35303652 /// Populated if linksection(A) is present.
3531 section_expr: Index,
3653 section_expr: OptionalIndex,
35323654 /// Populated if callconv(A) is present.
3533 callconv_expr: Index,
3655 callconv_expr: OptionalIndex,
35343656 };
35353657
35363658 pub const FnProto = struct {
3537 params_start: Index,
3538 params_end: Index,
3659 params_start: ExtraIndex,
3660 params_end: ExtraIndex,
35393661 /// Populated if align(A) is present.
3540 align_expr: Index,
3662 align_expr: OptionalIndex,
35413663 /// Populated if addrspace(A) is present.
3542 addrspace_expr: Index,
3664 addrspace_expr: OptionalIndex,
35433665 /// Populated if linksection(A) is present.
3544 section_expr: Index,
3666 section_expr: OptionalIndex,
35453667 /// Populated if callconv(A) is present.
3546 callconv_expr: Index,
3668 callconv_expr: OptionalIndex,
35473669 };
35483670
35493671 pub const Asm = struct {
3550 items_start: Index,
3551 items_end: Index,
3672 items_start: ExtraIndex,
3673 items_end: ExtraIndex,
35523674 /// Needed to make lastToken() work.
35533675 rparen: TokenIndex,
35543676 };
35553677};
35563678
3557pub fn nodeToSpan(tree: *const Ast, node: u32) Span {
3679pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span {
35583680 return tokensToSpan(
35593681 tree,
35603682 tree.firstToken(node),
35613683 tree.lastToken(node),
3562 tree.nodes.items(.main_token)[node],
3684 tree.nodeMainToken(node),
35633685 );
35643686}
35653687
......@@ -3568,7 +3690,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
35683690}
35693691
35703692pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
3571 const token_starts = tree.tokens.items(.start);
35723693 var start_tok = start;
35733694 var end_tok = end;
35743695
......@@ -3582,9 +3703,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
35823703 start_tok = main;
35833704 end_tok = main;
35843705 }
3585 const start_off = token_starts[start_tok];
3586 const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
3587 return Span{ .start = start_off, .end = end_off, .main = token_starts[main] };
3706 const start_off = tree.tokenStart(start_tok);
3707 const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
3708 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
35883709}
35893710
35903711const std = @import("../std.zig");
lib/std/zig/AstGen.zig+612-743
......@@ -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
......@@ -866,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
866872 const if_full = tree.fullIf(node).?;
867873 no_switch_on_err: {
868874 const error_token = if_full.error_token orelse break :no_switch_on_err;
869 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;
870877 if (full_switch.label_token != null) break :no_switch_on_err;
871 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;
872 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;
873880 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");
874881 }
875882 return ifExpr(gz, scope, ri.br(), node, if_full);
......@@ -887,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
887894 .slice_sentinel,
888895 => {
889896 const full = tree.fullSlice(node).?;
890 if (full.ast.end != 0 and
891 node_tags[full.ast.sliced] == .slice_open and
897 if (full.ast.end != .none and
898 tree.nodeTag(full.ast.sliced) == .slice_open and
892899 nodeIsTriviallyZero(tree, full.ast.start))
893900 {
894901 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
......@@ -896,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
896903 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);
897904 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);
898905 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
899 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);
900 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;
901908 try emitDbgStmt(gz, cursor);
902909 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{
903910 .lhs = lhs,
......@@ -912,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
912919
913920 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
914921 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start);
915 const end = if (full.ast.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end) else .none;
916 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: {
917924 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);
918 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);
919926 } else .none;
920927 try emitDbgStmt(gz, cursor);
921928 if (sentinel != .none) {
......@@ -943,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
943950 },
944951
945952 .deref => {
946 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);
947954 _ = try gz.addUnNode(.validate_deref, lhs, node);
948955 switch (ri.rl) {
949956 .ref, .ref_coerced_ty => return lhs,
......@@ -958,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
958965 _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
959966 break :rl .{ .ref_coerced_ty = res_ty_inst };
960967 } else .ref;
961 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);
962969 return rvalue(gz, ri, result, node);
963970 },
964971 .optional_type => {
965 const operand = try typeExpr(gz, scope, node_datas[node].lhs);
972 const operand = try typeExpr(gz, scope, tree.nodeData(node).node);
966973 const result = try gz.addUnNode(.optional_type, operand, node);
967974 return rvalue(gz, ri, result, node);
968975 },
969976 .unwrap_optional => switch (ri.rl) {
970977 .ref, .ref_coerced_ty => {
971 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]);
972979
973980 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
974981 try emitDbgStmt(gz, cursor);
......@@ -976,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
976983 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
977984 },
978985 else => {
979 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]);
980987
981988 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
982989 try emitDbgStmt(gz, cursor);
......@@ -994,7 +1001,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
9941001 return blockExpr(gz, scope, ri, node, statements, .normal);
9951002 },
9961003 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {
997 const str_index = try astgen.identAsString(main_tokens[node]);
1004 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
9981005 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{
9991006 .lhs = res_ty,
10001007 .field_name_start = str_index,
......@@ -1004,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10041011 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us
10051012 .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node),
10061013 }
1007 } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),
1008 .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.nodeData(node).opt_token_and_opt_token[1].unwrap().?, node, .error_value),
10091016 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025
10101017 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),
10111018 .anyframe_literal => {
......@@ -1013,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10131020 return rvalue(gz, ri, result, node);
10141021 },
10151022 .anyframe_type => {
1016 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]);
10171024 const result = try gz.addUnNode(.anyframe_type, return_type, node);
10181025 return rvalue(gz, ri, result, node);
10191026 },
10201027 .@"catch" => {
1021 const catch_token = main_tokens[node];
1022 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)
10231030 catch_token + 2
10241031 else
10251032 null;
10261033 no_switch_on_err: {
10271034 const capture_token = payload_token orelse break :no_switch_on_err;
1028 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;
10291036 if (full_switch.label_token != null) break :no_switch_on_err;
1030 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;
1031 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;
10321039 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
10331040 }
10341041 switch (ri.rl) {
......@@ -1037,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10371044 scope,
10381045 ri,
10391046 node,
1040 node_datas[node].lhs,
10411047 .is_non_err_ptr,
10421048 .err_union_payload_unsafe_ptr,
10431049 .err_union_code_ptr,
1044 node_datas[node].rhs,
10451050 payload_token,
10461051 ),
10471052 else => return orelseCatchExpr(
......@@ -1049,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10491054 scope,
10501055 ri,
10511056 node,
1052 node_datas[node].lhs,
10531057 .is_non_err,
10541058 .err_union_payload_unsafe,
10551059 .err_union_code,
1056 node_datas[node].rhs,
10571060 payload_token,
10581061 ),
10591062 }
......@@ -1064,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10641067 scope,
10651068 ri,
10661069 node,
1067 node_datas[node].lhs,
10681070 .is_non_null_ptr,
10691071 .optional_payload_unsafe_ptr,
10701072 undefined,
1071 node_datas[node].rhs,
10721073 null,
10731074 ),
10741075 else => return orelseCatchExpr(
......@@ -1076,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
10761077 scope,
10771078 ri,
10781079 node,
1079 node_datas[node].lhs,
10801080 .is_non_null,
10811081 .optional_payload_unsafe,
10821082 undefined,
1083 node_datas[node].rhs,
10841083 null,
10851084 ),
10861085 },
......@@ -1110,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11101109
11111110 .@"break" => return breakExpr(gz, scope, node),
11121111 .@"continue" => return continueExpr(gz, scope, node),
1113 .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]),
11141113 .array_type => return arrayType(gz, scope, ri, node),
11151114 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
11161115 .char_literal => return charLiteral(gz, ri, node),
......@@ -1124,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11241123 .@"await" => return awaitExpr(gz, scope, ri, node),
11251124 .@"resume" => return resumeExpr(gz, scope, ri, node),
11261125
1127 .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs),
1126 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
11281127
11291128 .array_init_one,
11301129 .array_init_one_comma,
......@@ -1171,16 +1170,14 @@ fn nosuspendExpr(
11711170) InnerError!Zir.Inst.Ref {
11721171 const astgen = gz.astgen;
11731172 const tree = astgen.tree;
1174 const node_datas = tree.nodes.items(.data);
1175 const body_node = node_datas[node].lhs;
1176 assert(body_node != 0);
1177 if (gz.nosuspend_node != 0) {
1173 const body_node = tree.nodeData(node).node;
1174 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
11781175 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{
1179 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),
1176 try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}),
11801177 });
11811178 }
1182 gz.nosuspend_node = node;
1183 defer gz.nosuspend_node = 0;
1179 gz.nosuspend_node = node.toOptional();
1180 defer gz.nosuspend_node = .none;
11841181 return expr(gz, scope, ri, body_node);
11851182}
11861183
......@@ -1192,26 +1189,24 @@ fn suspendExpr(
11921189 const astgen = gz.astgen;
11931190 const gpa = astgen.gpa;
11941191 const tree = astgen.tree;
1195 const node_datas = tree.nodes.items(.data);
1196 const body_node = node_datas[node].lhs;
1192 const body_node = tree.nodeData(node).node;
11971193
1198 if (gz.nosuspend_node != 0) {
1194 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
11991195 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{
1200 try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}),
1196 try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}),
12011197 });
12021198 }
1203 if (gz.suspend_node != 0) {
1199 if (gz.suspend_node.unwrap()) |suspend_node| {
12041200 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{
1205 try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}),
1201 try astgen.errNoteNode(suspend_node, "other suspend block here", .{}),
12061202 });
12071203 }
1208 assert(body_node != 0);
12091204
12101205 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);
12111206 try gz.instructions.append(gpa, suspend_inst);
12121207
12131208 var suspend_scope = gz.makeSubBlock(scope);
1214 suspend_scope.suspend_node = node;
1209 suspend_scope.suspend_node = node.toOptional();
12151210 defer suspend_scope.unstack();
12161211
12171212 const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal);
......@@ -1231,16 +1226,15 @@ fn awaitExpr(
12311226) InnerError!Zir.Inst.Ref {
12321227 const astgen = gz.astgen;
12331228 const tree = astgen.tree;
1234 const node_datas = tree.nodes.items(.data);
1235 const rhs_node = node_datas[node].lhs;
1229 const rhs_node = tree.nodeData(node).node;
12361230
1237 if (gz.suspend_node != 0) {
1231 if (gz.suspend_node.unwrap()) |suspend_node| {
12381232 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
1239 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
1233 try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
12401234 });
12411235 }
12421236 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1243 const result = if (gz.nosuspend_node != 0)
1237 const result = if (gz.nosuspend_node != .none)
12441238 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
12451239 .node = gz.nodeIndexToRelative(node),
12461240 .operand = operand,
......@@ -1259,8 +1253,7 @@ fn resumeExpr(
12591253) InnerError!Zir.Inst.Ref {
12601254 const astgen = gz.astgen;
12611255 const tree = astgen.tree;
1262 const node_datas = tree.nodes.items(.data);
1263 const rhs_node = node_datas[node].lhs;
1256 const rhs_node = tree.nodeData(node).node;
12641257 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
12651258 const result = try gz.addUnNode(.@"resume", operand, node);
12661259 return rvalue(gz, ri, result, node);
......@@ -1275,33 +1268,33 @@ fn fnProtoExpr(
12751268) InnerError!Zir.Inst.Ref {
12761269 const astgen = gz.astgen;
12771270 const tree = astgen.tree;
1278 const token_tags = tree.tokens.items(.tag);
12791271
12801272 if (fn_proto.name_token) |some| {
12811273 return astgen.failTok(some, "function type cannot have a name", .{});
12821274 }
12831275
1284 if (fn_proto.ast.align_expr != 0) {
1285 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", .{});
12861278 }
12871279
1288 if (fn_proto.ast.addrspace_expr != 0) {
1289 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", .{});
12901282 }
12911283
1292 if (fn_proto.ast.section_expr != 0) {
1293 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", .{});
12941286 }
12951287
1296 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1297 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;
12981291 if (is_inferred_error) {
12991292 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
13001293 }
13011294
13021295 const is_extern = blk: {
13031296 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
1304 break :blk token_tags[maybe_extern_token] == .keyword_extern;
1297 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
13051298 };
13061299 assert(!is_extern);
13071300
......@@ -1318,7 +1311,6 @@ fn fnProtoExprInner(
13181311) InnerError!Zir.Inst.Ref {
13191312 const astgen = gz.astgen;
13201313 const tree = astgen.tree;
1321 const token_tags = tree.tokens.items(.tag);
13221314
13231315 var block_scope = gz.makeSubBlock(scope);
13241316 defer block_scope.unstack();
......@@ -1330,7 +1322,7 @@ fn fnProtoExprInner(
13301322 var param_type_i: usize = 0;
13311323 var it = fn_proto.iterate(tree);
13321324 while (it.next()) |param| : (param_type_i += 1) {
1333 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)) {
13341326 .keyword_noalias => is_comptime: {
13351327 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
13361328 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
......@@ -1341,7 +1333,7 @@ fn fnProtoExprInner(
13411333 } else false;
13421334
13431335 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
1344 switch (token_tags[token]) {
1336 switch (tree.tokenTag(token)) {
13451337 .keyword_anytype => break :blk true,
13461338 .ellipsis3 => break :is_var_args true,
13471339 else => unreachable,
......@@ -1364,16 +1356,14 @@ fn fnProtoExprInner(
13641356 .param_anytype;
13651357 _ = try block_scope.addStrTok(tag, param_name, name_token);
13661358 } else {
1367 const param_type_node = param.type_expr;
1368 assert(param_type_node != 0);
1359 const param_type_node = param.type_expr.?;
13691360 var param_gz = block_scope.makeSubBlock(scope);
13701361 defer param_gz.unstack();
13711362 param_gz.is_comptime = true;
13721363 const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal);
13731364 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
13741365 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
1375 const main_tokens = tree.nodes.items(.main_token);
1376 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);
13771367 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
13781368 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous
13791369 // arguments (we haven't set up scopes here).
......@@ -1384,12 +1374,12 @@ fn fnProtoExprInner(
13841374 break :is_var_args false;
13851375 };
13861376
1387 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|
13881378 try comptimeExpr(
13891379 &block_scope,
13901380 scope,
1391 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
1392 fn_proto.ast.callconv_expr,
1381 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(callconv_expr, .calling_convention) } },
1382 callconv_expr,
13931383 .@"callconv",
13941384 )
13951385 else if (implicit_ccc)
......@@ -1397,7 +1387,8 @@ fn fnProtoExprInner(
13971387 else
13981388 .none;
13991389
1400 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);
14011392
14021393 const result = try block_scope.addFunc(.{
14031394 .src_node = fn_proto.ast.proto_node,
......@@ -1437,33 +1428,32 @@ fn arrayInitExpr(
14371428) InnerError!Zir.Inst.Ref {
14381429 const astgen = gz.astgen;
14391430 const tree = astgen.tree;
1440 const node_tags = tree.nodes.items(.tag);
1441 const main_tokens = tree.nodes.items(.main_token);
14421431
14431432 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
14441433
14451434 const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: {
1446 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 };
14471436
14481437 infer: {
1449 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;
14501439 // This intentionally does not support `@"_"` syntax.
1451 if (node_tags[array_type.ast.elem_count] == .identifier and
1452 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)), "_"))
14531442 {
14541443 const len_inst = try gz.addInt(array_init.ast.elements.len);
14551444 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1456 if (array_type.ast.sentinel == 0) {
1457 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{
14581447 .lhs = len_inst,
14591448 .rhs = elem_type,
14601449 });
14611450 break :inst .{ array_type_inst, elem_type };
14621451 } else {
1463 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);
14641454 const array_type_inst = try gz.addPlNode(
14651455 .array_type_sentinel,
1466 array_init.ast.type_expr,
1456 type_expr,
14671457 Zir.Inst.ArrayTypeSentinel{
14681458 .len = len_inst,
14691459 .elem_type = elem_type,
......@@ -1474,7 +1464,7 @@ fn arrayInitExpr(
14741464 }
14751465 }
14761466 }
1477 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
1467 const array_type_inst = try typeExpr(gz, scope, type_expr);
14781468 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
14791469 .ty = array_type_inst,
14801470 .init_count = @intCast(array_init.ast.elements.len),
......@@ -1682,7 +1672,7 @@ fn structInitExpr(
16821672 const astgen = gz.astgen;
16831673 const tree = astgen.tree;
16841674
1685 if (struct_init.ast.type_expr == 0) {
1675 if (struct_init.ast.type_expr == .none) {
16861676 if (struct_init.ast.fields.len == 0) {
16871677 // Anonymous init with no fields.
16881678 switch (ri.rl) {
......@@ -1706,32 +1696,32 @@ fn structInitExpr(
17061696 }
17071697 }
17081698 } else array: {
1709 const node_tags = tree.nodes.items(.tag);
1710 const main_tokens = tree.nodes.items(.main_token);
1711 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 {
17121701 if (struct_init.ast.fields.len == 0) {
1713 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1702 const ty_inst = try typeExpr(gz, scope, type_expr);
17141703 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
17151704 return rvalue(gz, ri, result, node);
17161705 }
17171706 break :array;
17181707 };
1719 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
17201709 // This intentionally does not support `@"_"` syntax.
1721 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)), "_");
17221711 if (struct_init.ast.fields.len == 0) {
17231712 if (is_inferred_array_len) {
17241713 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1725 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {
1726 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{
17271716 .lhs = .zero_usize,
17281717 .rhs = elem_type,
17291718 });
17301719 } else blk: {
1731 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);
17321722 break :blk try gz.addPlNode(
17331723 .array_type_sentinel,
1734 struct_init.ast.type_expr,
1724 type_expr,
17351725 Zir.Inst.ArrayTypeSentinel{
17361726 .len = .zero_usize,
17371727 .elem_type = elem_type,
......@@ -1742,12 +1732,12 @@ fn structInitExpr(
17421732 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
17431733 return rvalue(gz, ri, result, node);
17441734 }
1745 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1735 const ty_inst = try typeExpr(gz, scope, type_expr);
17461736 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
17471737 return rvalue(gz, ri, result, node);
17481738 } else {
17491739 return astgen.failNode(
1750 struct_init.ast.type_expr,
1740 type_expr,
17511741 "initializing array with struct syntax",
17521742 .{},
17531743 );
......@@ -1806,9 +1796,9 @@ fn structInitExpr(
18061796 }
18071797 }
18081798
1809 if (struct_init.ast.type_expr != 0) {
1799 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
18101800 // Typed inits do not use RLS for language simplicity.
1811 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1801 const ty_inst = try typeExpr(gz, scope, type_expr);
18121802 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
18131803 switch (ri.rl) {
18141804 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),
......@@ -1997,9 +1987,7 @@ fn comptimeExpr2(
19971987 // no need to wrap it in a block. This is hard to determine in general, but we can identify a
19981988 // common subset of trivially comptime expressions to take down the size of the ZIR a bit.
19991989 const tree = gz.astgen.tree;
2000 const main_tokens = tree.nodes.items(.main_token);
2001 const node_tags = tree.nodes.items(.tag);
2002 switch (node_tags[node]) {
1990 switch (tree.nodeTag(node)) {
20031991 .identifier => {
20041992 // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has
20051993 // special handling for this case.
......@@ -2052,8 +2040,7 @@ fn comptimeExpr2(
20522040 // comptime block, because that would be silly! Note that we don't bother doing this for
20532041 // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`).
20542042 .block_two, .block_two_semicolon, .block, .block_semicolon => {
2055 const token_tags = tree.tokens.items(.tag);
2056 const lbrace = main_tokens[node];
2043 const lbrace = tree.nodeMainToken(node);
20572044 // Careful! We can't pass in the real result location here, since it may
20582045 // refer to runtime memory. A runtime-to-comptime boundary has to remove
20592046 // result location information, compute the result, and copy it to the true
......@@ -2065,11 +2052,10 @@ fn comptimeExpr2(
20652052 else
20662053 .none,
20672054 };
2068 if (token_tags[lbrace - 1] == .colon and
2069 token_tags[lbrace - 2] == .identifier)
2070 {
2055 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
20712056 var buf: [2]Ast.Node.Index = undefined;
20722057 const stmts = tree.blockStatements(&buf, node).?;
2058
20732059 // Replace result location and copy back later - see above.
20742060 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
20752061 return rvalue(gz, ri, block_ref, node);
......@@ -2117,8 +2103,7 @@ fn comptimeExprAst(
21172103 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});
21182104 }
21192105 const tree = astgen.tree;
2120 const node_datas = tree.nodes.items(.data);
2121 const body_node = node_datas[node].lhs;
2106 const body_node = tree.nodeData(node).node;
21222107 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
21232108}
21242109
......@@ -2156,9 +2141,7 @@ fn restoreErrRetIndex(
21562141fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
21572142 const astgen = parent_gz.astgen;
21582143 const tree = astgen.tree;
2159 const node_datas = tree.nodes.items(.data);
2160 const break_label = node_datas[node].lhs;
2161 const rhs = node_datas[node].rhs;
2144 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
21622145
21632146 // Look for the label in the scope.
21642147 var scope = parent_scope;
......@@ -2167,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
21672150 .gen_zir => {
21682151 const block_gz = scope.cast(GenZir).?;
21692152
2170 if (block_gz.cur_defer_node != 0) {
2153 if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| {
21712154 // We are breaking out of a `defer` block.
21722155 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
21732156 try astgen.errNoteNode(
2174 block_gz.cur_defer_node,
2157 cur_defer_node,
21752158 "defer expression here",
21762159 .{},
21772160 ),
......@@ -2179,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
21792162 }
21802163
21812164 const block_inst = blk: {
2182 if (break_label != 0) {
2165 if (opt_break_label.unwrap()) |break_label| {
21832166 if (block_gz.label) |*label| {
21842167 if (try astgen.tokenIdentEql(label.token, break_label)) {
21852168 label.used = true;
......@@ -2200,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22002183 else
22012184 .@"break";
22022185
2203 if (rhs == 0) {
2186 const rhs = opt_rhs.unwrap() orelse {
22042187 _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node);
22052188
22062189 try genDefers(parent_gz, scope, parent_scope, .normal_only);
......@@ -2211,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22112194
22122195 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
22132196 return Zir.Inst.Ref.unreachable_value;
2214 }
2197 };
22152198
22162199 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node);
22172200
......@@ -2243,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22432226 .top => unreachable,
22442227 }
22452228 }
2246 if (break_label != 0) {
2229 if (opt_break_label.unwrap()) |break_label| {
22472230 const label_name = try astgen.identifierTokenString(break_label);
22482231 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
22492232 } else {
......@@ -2254,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22542237fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
22552238 const astgen = parent_gz.astgen;
22562239 const tree = astgen.tree;
2257 const node_datas = tree.nodes.items(.data);
2258 const break_label = node_datas[node].lhs;
2259 const rhs = node_datas[node].rhs;
2240 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
22602241
2261 if (break_label == 0 and rhs != 0) {
2242 if (opt_break_label == .none and opt_rhs != .none) {
22622243 return astgen.failNode(node, "cannot continue with operand without label", .{});
22632244 }
22642245
......@@ -2269,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
22692250 .gen_zir => {
22702251 const gen_zir = scope.cast(GenZir).?;
22712252
2272 if (gen_zir.cur_defer_node != 0) {
2253 if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| {
22732254 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{
22742255 try astgen.errNoteNode(
2275 gen_zir.cur_defer_node,
2256 cur_defer_node,
22762257 "defer expression here",
22772258 .{},
22782259 ),
......@@ -2282,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
22822263 scope = gen_zir.parent;
22832264 continue;
22842265 };
2285 if (break_label != 0) blk: {
2266 if (opt_break_label.unwrap()) |break_label| blk: {
22862267 if (gen_zir.label) |*label| {
22872268 if (try astgen.tokenIdentEql(label.token, break_label)) {
22882269 const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)];
2289 if (rhs != 0) switch (maybe_switch_tag) {
2270 if (opt_rhs != .none) switch (maybe_switch_tag) {
22902271 .switch_block, .switch_block_ref => {},
22912272 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),
22922273 } else switch (maybe_switch_tag) {
......@@ -2314,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
23142295 }
23152296 }
23162297
2317 if (rhs != 0) {
2298 if (opt_rhs.unwrap()) |rhs| {
23182299 // We need to figure out the result info to use.
23192300 // The type should match
23202301 const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node);
......@@ -2353,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
23532334 .top => unreachable,
23542335 }
23552336 }
2356 if (break_label != 0) {
2337 if (opt_break_label.unwrap()) |break_label| {
23572338 const label_name = try astgen.identifierTokenString(break_label);
23582339 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
23592340 } else {
......@@ -2373,15 +2354,14 @@ fn fullBodyExpr(
23732354 block_kind: BlockKind,
23742355) InnerError!Zir.Inst.Ref {
23752356 const tree = gz.astgen.tree;
2376 const main_tokens = tree.nodes.items(.main_token);
2377 const token_tags = tree.tokens.items(.tag);
2357
23782358 var stmt_buf: [2]Ast.Node.Index = undefined;
2379 const statements = tree.blockStatements(&stmt_buf, node).?;
2359 const statements = tree.blockStatements(&stmt_buf, node) orelse
2360 return expr(gz, scope, ri, node);
23802361
2381 const lbrace = main_tokens[node];
2382 if (token_tags[lbrace - 1] == .colon and
2383 token_tags[lbrace - 2] == .identifier)
2384 {
2362 const lbrace = tree.nodeMainToken(node);
2363
2364 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
23852365 // Labeled blocks are tricky - forwarding result location information properly is non-trivial,
23862366 // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This
23872367 // case is rare, so just treat it as a normal expression and create a nested block.
......@@ -2406,13 +2386,9 @@ fn blockExpr(
24062386) InnerError!Zir.Inst.Ref {
24072387 const astgen = gz.astgen;
24082388 const tree = astgen.tree;
2409 const main_tokens = tree.nodes.items(.main_token);
2410 const token_tags = tree.tokens.items(.tag);
24112389
2412 const lbrace = main_tokens[block_node];
2413 if (token_tags[lbrace - 1] == .colon and
2414 token_tags[lbrace - 2] == .identifier)
2415 {
2390 const lbrace = tree.nodeMainToken(block_node);
2391 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
24162392 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);
24172393 }
24182394
......@@ -2489,12 +2465,10 @@ fn labeledBlockExpr(
24892465) InnerError!Zir.Inst.Ref {
24902466 const astgen = gz.astgen;
24912467 const tree = astgen.tree;
2492 const main_tokens = tree.nodes.items(.main_token);
2493 const token_tags = tree.tokens.items(.tag);
24942468
2495 const lbrace = main_tokens[block_node];
2469 const lbrace = tree.nodeMainToken(block_node);
24962470 const label_token = lbrace - 2;
2497 assert(token_tags[label_token] == .identifier);
2471 assert(tree.tokenTag(label_token) == .identifier);
24982472
24992473 try astgen.checkLabelRedefinition(parent_scope, label_token);
25002474
......@@ -2555,8 +2529,6 @@ fn labeledBlockExpr(
25552529fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void {
25562530 const astgen = gz.astgen;
25572531 const tree = astgen.tree;
2558 const node_tags = tree.nodes.items(.tag);
2559 const node_data = tree.nodes.items(.data);
25602532
25612533 if (statements.len == 0) return;
25622534
......@@ -2564,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
25642536 defer block_arena.deinit();
25652537 const block_arena_allocator = block_arena.allocator();
25662538
2567 var noreturn_src_node: Ast.Node.Index = 0;
2539 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
25682540 var scope = parent_scope;
25692541 for (statements, 0..) |statement, stmt_idx| {
2570 if (noreturn_src_node != 0) {
2542 if (noreturn_src_node.unwrap()) |src_node| {
25712543 try astgen.appendErrorNodeNotes(
25722544 statement,
25732545 "unreachable code",
25742546 .{},
25752547 &[_]u32{
25762548 try astgen.errNoteNode(
2577 noreturn_src_node,
2549 src_node,
25782550 "control flow is diverted here",
25792551 .{},
25802552 ),
......@@ -2587,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
25872559 };
25882560 var inner_node = statement;
25892561 while (true) {
2590 switch (node_tags[inner_node]) {
2562 switch (tree.nodeTag(inner_node)) {
25912563 // zig fmt: off
25922564 .global_var_decl,
25932565 .local_var_decl,
......@@ -2617,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26172589 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
26182590
26192591 .grouped_expression => {
2620 inner_node = node_data[statement].lhs;
2592 inner_node = tree.nodeData(statement).node_and_token[0];
26212593 continue;
26222594 },
26232595
......@@ -2649,15 +2621,15 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26492621 }
26502622 }
26512623
2652 if (noreturn_src_node == 0) {
2624 if (noreturn_src_node == .none) {
26532625 try genDefers(gz, parent_scope, scope, .normal_only);
26542626 }
26552627 try checkUsed(gz, parent_scope, scope);
26562628}
26572629
26582630/// Returns AST source node of the thing that is noreturn if the statement is
2659/// definitely `noreturn`. Otherwise returns 0.
2660fn 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 {
26612633 try emitDbgNode(gz, statement);
26622634 // We need to emit an error if the result is not `noreturn` or `void`, but
26632635 // we want to avoid adding the ZIR instruction if possible for performance.
......@@ -2665,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
26652637 return addEnsureResult(gz, maybe_unused_result, statement);
26662638}
26672639
2668fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index {
2669 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;
26702642 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {
26712643 // Note that this array becomes invalid after appending more items to it
26722644 // in the above while loop.
......@@ -2927,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29272899 .check_comptime_control_flow,
29282900 .switch_continue,
29292901 => {
2930 noreturn_src_node = statement;
2902 noreturn_src_node = statement.toOptional();
29312903 break :b true;
29322904 },
29332905
......@@ -2969,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
29692941 .none => unreachable,
29702942
29712943 .unreachable_value => b: {
2972 noreturn_src_node = statement;
2944 noreturn_src_node = statement.toOptional();
29732945 break :b true;
29742946 },
29752947
......@@ -3098,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
30983070 .gen_zir => scope = scope.cast(GenZir).?.parent,
30993071 .local_val => {
31003072 const s = scope.cast(Scope.LocalVal).?;
3101 if (s.used == 0 and s.discarded == 0) {
3073 if (s.used == .none and s.discarded == .none) {
31023074 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
3103 } else if (s.used != 0 and s.discarded != 0) {
3104 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3105 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", .{}),
31063078 });
31073079 }
31083080 scope = s.parent;
31093081 },
31103082 .local_ptr => {
31113083 const s = scope.cast(Scope.LocalPtr).?;
3112 if (s.used == 0 and s.discarded == 0) {
3084 if (s.used == .none and s.discarded == .none) {
31133085 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
31143086 } else {
3115 if (s.used != 0 and s.discarded != 0) {
3116 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3117 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", .{}),
31183090 });
31193091 }
31203092 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {
......@@ -3141,19 +3113,15 @@ fn deferStmt(
31413113 scope_tag: Scope.Tag,
31423114) InnerError!*Scope {
31433115 var defer_gen = gz.makeSubBlock(scope);
3144 defer_gen.cur_defer_node = node;
3145 defer_gen.any_defer_node = node;
3116 defer_gen.cur_defer_node = node.toOptional();
3117 defer_gen.any_defer_node = node.toOptional();
31463118 defer defer_gen.unstack();
31473119
31483120 const tree = gz.astgen.tree;
3149 const node_datas = tree.nodes.items(.data);
3150 const expr_node = node_datas[node].rhs;
3151
3152 const payload_token = node_datas[node].lhs;
31533121 var local_val_scope: Scope.LocalVal = undefined;
31543122 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3155 const have_err_code = scope_tag == .defer_error and payload_token != 0;
3156 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;
31573125 const ident_name = try gz.astgen.identAsString(payload_token);
31583126 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {
31593127 try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{});
......@@ -3181,6 +3149,11 @@ fn deferStmt(
31813149 try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref);
31823150 break :blk &local_val_scope.base;
31833151 };
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 };
31843157 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
31853158 try checkUsed(gz, scope, sub_scope);
31863159 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
......@@ -3215,8 +3188,6 @@ fn varDecl(
32153188 try emitDbgNode(gz, node);
32163189 const astgen = gz.astgen;
32173190 const tree = astgen.tree;
3218 const token_tags = tree.tokens.items(.tag);
3219 const main_tokens = tree.nodes.items(.main_token);
32203191
32213192 const name_token = var_decl.ast.mut_token + 1;
32223193 const ident_name_raw = tree.tokenSlice(name_token);
......@@ -3230,27 +3201,27 @@ fn varDecl(
32303201 ident_name,
32313202 name_token,
32323203 ident_name_raw,
3233 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",
32343205 );
32353206
3236 if (var_decl.ast.init_node == 0) {
3207 const init_node = var_decl.ast.init_node.unwrap() orelse {
32373208 return astgen.failNode(node, "variables must be initialized", .{});
3238 }
3209 };
32393210
3240 if (var_decl.ast.addrspace_node != 0) {
3241 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});
32423213 }
32433214
3244 if (var_decl.ast.section_node != 0) {
3245 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});
32463217 }
32473218
3248 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)
3249 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)
32503221 else
32513222 .none;
32523223
3253 switch (token_tags[var_decl.ast.mut_token]) {
3224 switch (tree.tokenTag(var_decl.ast.mut_token)) {
32543225 .keyword_const => {
32553226 if (var_decl.comptime_token) |comptime_token| {
32563227 try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
......@@ -3262,25 +3233,24 @@ fn varDecl(
32623233 // Depending on the type of AST the initialization expression is, we may need an lvalue
32633234 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
32643235 // the variable, no memory location needed.
3265 const type_node = var_decl.ast.type_node;
32663236 if (align_inst == .none and
32673237 !astgen.nodes_need_rl.contains(node))
32683238 {
3269 const result_info: ResultInfo = if (type_node != 0) .{
3239 const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{
32703240 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
32713241 .ctx = .const_init,
32723242 } else .{ .rl = .none, .ctx = .const_init };
32733243 const prev_anon_name_strategy = gz.anon_name_strategy;
32743244 gz.anon_name_strategy = .dbg_var;
3275 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);
32763246 gz.anon_name_strategy = prev_anon_name_strategy;
32773247
3278 _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node);
3248 _ = try gz.addUnNode(.validate_const, init_inst, init_node);
32793249 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
32803250
32813251 // The const init expression may have modified the error return trace, so signal
32823252 // to Sema that it should save the new index for restoring later.
3283 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
3253 if (nodeMayAppendToErrorTrace(tree, init_node))
32843254 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
32853255
32863256 const sub_scope = try block_arena.create(Scope.LocalVal);
......@@ -3296,9 +3266,9 @@ fn varDecl(
32963266 }
32973267
32983268 const is_comptime = gz.is_comptime or
3299 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";
3269 tree.nodeTag(init_node) == .@"comptime";
33003270
3301 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: {
33023272 const type_inst = try typeExpr(gz, scope, type_node);
33033273 if (align_inst == .none) {
33043274 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };
......@@ -3339,11 +3309,11 @@ fn varDecl(
33393309 const prev_anon_name_strategy = gz.anon_name_strategy;
33403310 gz.anon_name_strategy = .dbg_var;
33413311 defer gz.anon_name_strategy = prev_anon_name_strategy;
3342 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);
33433313
33443314 // The const init expression may have modified the error return trace, so signal
33453315 // to Sema that it should save the new index for restoring later.
3346 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))
3316 if (nodeMayAppendToErrorTrace(tree, init_node))
33473317 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
33483318
33493319 const const_ptr = if (resolve_inferred)
......@@ -3369,8 +3339,8 @@ fn varDecl(
33693339 if (var_decl.comptime_token != null and gz.is_comptime)
33703340 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});
33713341 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
3372 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: {
3373 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);
33743344 const alloc = alloc: {
33753345 if (align_inst == .none) {
33763346 const tag: Zir.Inst.Tag = if (is_comptime)
......@@ -3415,7 +3385,7 @@ fn varDecl(
34153385 gz,
34163386 scope,
34173387 result_info,
3418 var_decl.ast.init_node,
3388 init_node,
34193389 node,
34203390 if (var_decl.comptime_token != null) .comptime_keyword else null,
34213391 );
......@@ -3458,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
34583428 try emitDbgNode(gz, infix_node);
34593429 const astgen = gz.astgen;
34603430 const tree = astgen.tree;
3461 const node_datas = tree.nodes.items(.data);
3462 const main_tokens = tree.nodes.items(.main_token);
3463 const node_tags = tree.nodes.items(.tag);
34643431
3465 const lhs = node_datas[infix_node].lhs;
3466 const rhs = node_datas[infix_node].rhs;
3467 if (node_tags[lhs] == .identifier) {
3432 const lhs, const rhs = tree.nodeData(infix_node).node_and_node;
3433 if (tree.nodeTag(lhs) == .identifier) {
34683434 // This intentionally does not support `@"_"` syntax.
3469 const ident_name = tree.tokenSlice(main_tokens[lhs]);
3435 const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs));
34703436 if (mem.eql(u8, ident_name, "_")) {
34713437 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
34723438 return;
......@@ -3484,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
34843450 try emitDbgNode(gz, node);
34853451 const astgen = gz.astgen;
34863452 const tree = astgen.tree;
3487 const main_tokens = tree.nodes.items(.main_token);
3488 const node_tags = tree.nodes.items(.tag);
34893453
34903454 const full = tree.assignDestructure(node);
34913455 if (full.comptime_token != null and gz.is_comptime) {
......@@ -3503,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
35033467
35043468 const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len);
35053469 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3506 if (node_tags[variable_node] == .identifier) {
3470 if (tree.nodeTag(variable_node) == .identifier) {
35073471 // This intentionally does not support `@"_"` syntax.
3508 const ident_name = tree.tokenSlice(main_tokens[variable_node]);
3472 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
35093473 if (mem.eql(u8, ident_name, "_")) {
35103474 variable_rl.* = .discard;
35113475 continue;
......@@ -3542,9 +3506,6 @@ fn assignDestructureMaybeDecls(
35423506 try emitDbgNode(gz, node);
35433507 const astgen = gz.astgen;
35443508 const tree = astgen.tree;
3545 const token_tags = tree.tokens.items(.tag);
3546 const main_tokens = tree.nodes.items(.main_token);
3547 const node_tags = tree.nodes.items(.tag);
35483509
35493510 const full = tree.assignDestructure(node);
35503511 if (full.comptime_token != null and gz.is_comptime) {
......@@ -3552,7 +3513,7 @@ fn assignDestructureMaybeDecls(
35523513 }
35533514
35543515 const is_comptime = full.comptime_token != null or gz.is_comptime;
3555 const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime";
3516 const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime";
35563517
35573518 // When declaring consts via a destructure, we always use a result pointer.
35583519 // This avoids the need to create tuple types, and is also likely easier to
......@@ -3565,10 +3526,10 @@ fn assignDestructureMaybeDecls(
35653526 var any_non_const_variables = false;
35663527 var any_lvalue_expr = false;
35673528 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3568 switch (node_tags[variable_node]) {
3529 switch (tree.nodeTag(variable_node)) {
35693530 .identifier => {
35703531 // This intentionally does not support `@"_"` syntax.
3571 const ident_name = tree.tokenSlice(main_tokens[variable_node]);
3532 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
35723533 if (mem.eql(u8, ident_name, "_")) {
35733534 any_non_const_variables = true;
35743535 variable_rl.* = .discard;
......@@ -3586,14 +3547,14 @@ fn assignDestructureMaybeDecls(
35863547
35873548 // We detect shadowing in the second pass over these, while we're creating scopes.
35883549
3589 if (full_var_decl.ast.addrspace_node != 0) {
3590 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});
35913552 }
3592 if (full_var_decl.ast.section_node != 0) {
3593 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});
35943555 }
35953556
3596 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)) {
35973558 .keyword_var => false,
35983559 .keyword_const => true,
35993560 else => unreachable,
......@@ -3603,14 +3564,14 @@ fn assignDestructureMaybeDecls(
36033564 // We also mark `const`s as comptime if the RHS is definitely comptime-known.
36043565 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);
36053566
3606 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node != 0)
3607 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)
36083569 else
36093570 .none;
36103571
3611 if (full_var_decl.ast.type_node != 0) {
3572 if (full_var_decl.ast.type_node.unwrap()) |type_node| {
36123573 // Typed alloc
3613 const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node);
3574 const type_inst = try typeExpr(gz, scope, type_node);
36143575 const ptr = if (align_inst == .none) ptr: {
36153576 const tag: Zir.Inst.Tag = if (is_const)
36163577 .alloc
......@@ -3679,7 +3640,7 @@ fn assignDestructureMaybeDecls(
36793640 // evaluate the lvalues from within the possible block_comptime.
36803641 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
36813642 if (variable_rl.* != .typed_ptr) continue;
3682 switch (node_tags[variable_node]) {
3643 switch (tree.nodeTag(variable_node)) {
36833644 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue,
36843645 else => {},
36853646 }
......@@ -3708,7 +3669,7 @@ fn assignDestructureMaybeDecls(
37083669 // If there were any `const` decls, make the pointer constant.
37093670 var cur_scope = scope;
37103671 for (rl_components, full.ast.variables) |variable_rl, variable_node| {
3711 switch (node_tags[variable_node]) {
3672 switch (tree.nodeTag(variable_node)) {
37123673 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},
37133674 else => continue, // We were mutating an existing lvalue - nothing to do
37143675 }
......@@ -3718,7 +3679,7 @@ fn assignDestructureMaybeDecls(
37183679 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },
37193680 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },
37203681 };
3721 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)) {
37223683 .keyword_var => false,
37233684 .keyword_const => true,
37243685 else => unreachable,
......@@ -3769,9 +3730,9 @@ fn assignOp(
37693730 try emitDbgNode(gz, infix_node);
37703731 const astgen = gz.astgen;
37713732 const tree = astgen.tree;
3772 const node_datas = tree.nodes.items(.data);
37733733
3774 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);
37753736
37763737 const cursor = switch (op_inst_tag) {
37773738 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
......@@ -3797,7 +3758,7 @@ fn assignOp(
37973758 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type
37983759 };
37993760 // Not `coerced_ty` since `add`/etc won't coerce to this type.
3800 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);
38013762
38023763 switch (op_inst_tag) {
38033764 .add, .sub, .mul, .div, .mod_rem => {
......@@ -3824,12 +3785,12 @@ fn assignShift(
38243785 try emitDbgNode(gz, infix_node);
38253786 const astgen = gz.astgen;
38263787 const tree = astgen.tree;
3827 const node_datas = tree.nodes.items(.data);
38283788
3829 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);
38303791 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
38313792 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);
3832 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);
38333794
38343795 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
38353796 .lhs = lhs,
......@@ -3845,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
38453806 try emitDbgNode(gz, infix_node);
38463807 const astgen = gz.astgen;
38473808 const tree = astgen.tree;
3848 const node_datas = tree.nodes.items(.data);
38493809
3850 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);
38513812 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
38523813 // Saturating shift-left allows any integer type for both the LHS and RHS.
3853 const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs);
3814 const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node);
38543815
38553816 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{
38563817 .lhs = lhs,
......@@ -3885,7 +3846,7 @@ fn ptrType(
38853846 var bit_end_ref: Zir.Inst.Ref = .none;
38863847 var trailing_count: u32 = 0;
38873848
3888 if (ptr_info.ast.sentinel != 0) {
3849 if (ptr_info.ast.sentinel.unwrap()) |sentinel| {
38893850 // These attributes can appear in any order and they all come before the
38903851 // element type so we need to reset the source cursor before generating them.
38913852 gz.astgen.source_offset = source_offset;
......@@ -3896,7 +3857,7 @@ fn ptrType(
38963857 gz,
38973858 scope,
38983859 .{ .rl = .{ .ty = elem_type } },
3899 ptr_info.ast.sentinel,
3860 sentinel,
39003861 switch (ptr_info.size) {
39013862 .slice => .slice_sentinel,
39023863 else => .pointer_sentinel,
......@@ -3904,27 +3865,27 @@ fn ptrType(
39043865 );
39053866 trailing_count += 1;
39063867 }
3907 if (ptr_info.ast.addrspace_node != 0) {
3868 if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| {
39083869 gz.astgen.source_offset = source_offset;
39093870 gz.astgen.source_line = source_line;
39103871 gz.astgen.source_column = source_column;
39113872
3912 const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space);
3913 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");
39143875 trailing_count += 1;
39153876 }
3916 if (ptr_info.ast.align_node != 0) {
3877 if (ptr_info.ast.align_node.unwrap()) |align_node| {
39173878 gz.astgen.source_offset = source_offset;
39183879 gz.astgen.source_line = source_line;
39193880 gz.astgen.source_column = source_column;
39203881
3921 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");
39223883 trailing_count += 1;
39233884 }
3924 if (ptr_info.ast.bit_range_start != 0) {
3925 assert(ptr_info.ast.bit_range_end != 0);
3926 bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type);
3927 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);
39283889 trailing_count += 2;
39293890 }
39303891
......@@ -3977,18 +3938,15 @@ fn ptrType(
39773938fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
39783939 const astgen = gz.astgen;
39793940 const tree = astgen.tree;
3980 const node_datas = tree.nodes.items(.data);
3981 const node_tags = tree.nodes.items(.tag);
3982 const main_tokens = tree.nodes.items(.main_token);
39833941
3984 const len_node = node_datas[node].lhs;
3985 if (node_tags[len_node] == .identifier and
3986 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)), "_"))
39873945 {
39883946 return astgen.failNode(len_node, "unable to infer array size", .{});
39893947 }
39903948 const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);
3991 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
3949 const elem_type = try typeExpr(gz, scope, elem_type_node);
39923950
39933951 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
39943952 .lhs = len,
......@@ -4000,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
40003958fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
40013959 const astgen = gz.astgen;
40023960 const tree = astgen.tree;
4003 const node_datas = tree.nodes.items(.data);
4004 const node_tags = tree.nodes.items(.tag);
4005 const main_tokens = tree.nodes.items(.main_token);
4006 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
4007
4008 const len_node = node_datas[node].lhs;
4009 if (node_tags[len_node] == .identifier and
4010 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)), "_"))
40113967 {
40123968 return astgen.failNode(len_node, "unable to infer array size", .{});
40133969 }
......@@ -4107,11 +4063,10 @@ fn fnDecl(
41074063 scope: *Scope,
41084064 wip_members: *WipMembers,
41094065 decl_node: Ast.Node.Index,
4110 body_node: Ast.Node.Index,
4066 body_node: Ast.Node.OptionalIndex,
41114067 fn_proto: Ast.full.FnProto,
41124068) InnerError!void {
41134069 const tree = astgen.tree;
4114 const token_tags = tree.tokens.items(.tag);
41154070
41164071 const old_hasher = astgen.src_hasher;
41174072 defer astgen.src_hasher = old_hasher;
......@@ -4140,15 +4095,15 @@ fn fnDecl(
41404095 const is_pub = fn_proto.visib_token != null;
41414096 const is_export = blk: {
41424097 const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
4143 break :blk token_tags[maybe_export_token] == .keyword_export;
4098 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
41444099 };
41454100 const is_extern = blk: {
41464101 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
4147 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4102 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
41484103 };
41494104 const has_inline_keyword = blk: {
41504105 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4151 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4106 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
41524107 };
41534108 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
41544109 const lib_name_str = try astgen.strLitAsString(lib_name_token);
......@@ -4160,16 +4115,18 @@ fn fnDecl(
41604115 }
41614116 break :blk lib_name_str.index;
41624117 } else .empty;
4163 if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) {
4118 if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) {
41644119 return astgen.failNode(
4165 fn_proto.ast.callconv_expr,
4120 fn_proto.ast.callconv_expr.unwrap().?,
41664121 "explicit callconv incompatible with inline keyword",
41674122 .{},
41684123 );
41694124 }
4170 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4171 const is_inferred_error = token_tags[maybe_bang] == .bang;
4172 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) {
41734130 if (!is_extern) {
41744131 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
41754132 }
......@@ -4202,28 +4159,28 @@ fn fnDecl(
42024159 var align_gz = type_gz.makeSubBlock(scope);
42034160 defer align_gz.unstack();
42044161
4205 if (fn_proto.ast.align_expr != 0) {
4162 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
42064163 astgen.restoreSourceCursor(saved_cursor);
4207 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);
42084165 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42094166 }
42104167
42114168 var linksection_gz = align_gz.makeSubBlock(scope);
42124169 defer linksection_gz.unstack();
42134170
4214 if (fn_proto.ast.section_expr != 0) {
4171 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
42154172 astgen.restoreSourceCursor(saved_cursor);
4216 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);
42174174 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42184175 }
42194176
42204177 var addrspace_gz = linksection_gz.makeSubBlock(scope);
42214178 defer addrspace_gz.unstack();
42224179
4223 if (fn_proto.ast.addrspace_expr != 0) {
4180 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
42244181 astgen.restoreSourceCursor(saved_cursor);
4225 const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space);
4226 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);
42274184 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
42284185 }
42294186
......@@ -4233,7 +4190,7 @@ fn fnDecl(
42334190 if (!is_extern) {
42344191 // We include a function *value*, not a type.
42354192 astgen.restoreSourceCursor(saved_cursor);
4236 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);
42374194 }
42384195
42394196 // *Now* we can incorporate the full source code into the hasher.
......@@ -4272,18 +4229,19 @@ fn fnDeclInner(
42724229 fn_proto: Ast.full.FnProto,
42734230) InnerError!void {
42744231 const tree = astgen.tree;
4275 const token_tags = tree.tokens.items(.tag);
42764232
42774233 const is_noinline = blk: {
42784234 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4279 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;
4235 break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline;
42804236 };
42814237 const has_inline_keyword = blk: {
42824238 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4283 break :blk token_tags[maybe_inline_token] == .keyword_inline;
4239 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
42844240 };
4285 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
4286 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;
42874245
42884246 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
42894247 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
......@@ -4297,7 +4255,7 @@ fn fnDeclInner(
42974255 var param_type_i: usize = 0;
42984256 var it = fn_proto.iterate(tree);
42994257 while (it.next()) |param| : (param_type_i += 1) {
4300 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)) {
43014259 .keyword_noalias => is_comptime: {
43024260 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
43034261 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
......@@ -4308,7 +4266,7 @@ fn fnDeclInner(
43084266 } else false;
43094267
43104268 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
4311 switch (token_tags[token]) {
4269 switch (tree.tokenTag(token)) {
43124270 .keyword_anytype => break :blk true,
43134271 .ellipsis3 => break :is_var_args true,
43144272 else => unreachable,
......@@ -4327,30 +4285,31 @@ fn fnDeclInner(
43274285 if (param.anytype_ellipsis3) |tok| {
43284286 return astgen.failTok(tok, "missing parameter name", .{});
43294287 } else {
4288 const type_expr = param.type_expr.?;
43304289 ambiguous: {
4331 if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous;
4332 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);
43334292 const identifier_str = tree.tokenSlice(main_token);
43344293 if (isPrimitive(identifier_str)) break :ambiguous;
43354294 return astgen.failNodeNotes(
4336 param.type_expr,
4295 type_expr,
43374296 "missing parameter name or type",
43384297 .{},
43394298 &[_]u32{
43404299 try astgen.errNoteNode(
4341 param.type_expr,
4300 type_expr,
43424301 "if this is a name, annotate its type '{s}: T'",
43434302 .{identifier_str},
43444303 ),
43454304 try astgen.errNoteNode(
4346 param.type_expr,
4305 type_expr,
43474306 "if this is a type, give it a name '<name>: {s}'",
43484307 .{identifier_str},
43494308 ),
43504309 },
43514310 );
43524311 }
4353 return astgen.failNode(param.type_expr, "missing parameter name", .{});
4312 return astgen.failNode(type_expr, "missing parameter name", .{});
43544313 }
43554314 };
43564315
......@@ -4362,8 +4321,7 @@ fn fnDeclInner(
43624321 .param_anytype;
43634322 break :param try decl_gz.addStrTok(tag, param_name, name_token);
43644323 } else param: {
4365 const param_type_node = param.type_expr;
4366 assert(param_type_node != 0);
4324 const param_type_node = param.type_expr.?;
43674325 any_param_used = false; // we will check this later
43684326 var param_gz = decl_gz.makeSubBlock(scope);
43694327 defer param_gz.unstack();
......@@ -4372,8 +4330,7 @@ fn fnDeclInner(
43724330 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
43734331 const param_type_is_generic = any_param_used;
43744332
4375 const main_tokens = tree.nodes.items(.main_token);
4376 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);
43774334 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
43784335 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name);
43794336 assert(param_inst_expected == param_inst);
......@@ -4409,7 +4366,7 @@ fn fnDeclInner(
44094366 // Parameters are in scope for the return type, so we use `params_scope` here.
44104367 // The calling convention will not have parameters in scope, so we'll just use `scope`.
44114368 // See #22263 for a proposal to solve the inconsistency here.
4412 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);
44134370 if (ret_gz.instructionsSlice().len == 0) {
44144371 // In this case we will send a len=0 body which can be encoded more efficiently.
44154372 break :inst inst;
......@@ -4426,12 +4383,12 @@ fn fnDeclInner(
44264383 var cc_gz = decl_gz.makeSubBlock(scope);
44274384 defer cc_gz.unstack();
44284385 const cc_ref: Zir.Inst.Ref = blk: {
4429 if (fn_proto.ast.callconv_expr != 0) {
4386 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
44304387 const inst = try expr(
44314388 &cc_gz,
44324389 scope,
4433 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },
4434 fn_proto.ast.callconv_expr,
4390 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(callconv_expr, .calling_convention) } },
4391 callconv_expr,
44354392 );
44364393 if (cc_gz.instructionsSlice().len == 0) {
44374394 // In this case we will send a len=0 body which can be encoded more efficiently.
......@@ -4470,7 +4427,7 @@ fn fnDeclInner(
44704427 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
44714428 // the *whole* function declaration, including its body.
44724429 var proto_hasher = astgen.src_hasher;
4473 const proto_node = tree.nodes.items(.data)[decl_node].lhs;
4430 const proto_node = tree.nodeData(decl_node).node_and_node[0];
44744431 proto_hasher.update(tree.getNodeSource(proto_node));
44754432 var proto_hash: std.zig.SrcHash = undefined;
44764433 proto_hasher.final(&proto_hash);
......@@ -4540,7 +4497,6 @@ fn globalVarDecl(
45404497 var_decl: Ast.full.VarDecl,
45414498) InnerError!void {
45424499 const tree = astgen.tree;
4543 const token_tags = tree.tokens.items(.tag);
45444500
45454501 const old_hasher = astgen.src_hasher;
45464502 defer astgen.src_hasher = old_hasher;
......@@ -4548,16 +4504,16 @@ fn globalVarDecl(
45484504 astgen.src_hasher.update(tree.getNodeSource(node));
45494505 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
45504506
4551 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;
45524508 const name_token = var_decl.ast.mut_token + 1;
45534509 const is_pub = var_decl.visib_token != null;
45544510 const is_export = blk: {
45554511 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
4556 break :blk token_tags[maybe_export_token] == .keyword_export;
4512 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
45574513 };
45584514 const is_extern = blk: {
45594515 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
4560 break :blk token_tags[maybe_extern_token] == .keyword_extern;
4516 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
45614517 };
45624518 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
45634519 if (!is_mutable) {
......@@ -4583,10 +4539,10 @@ fn globalVarDecl(
45834539 const decl_inst = try gz.makeDeclaration(node);
45844540 wip_members.nextDecl(decl_inst);
45854541
4586 if (var_decl.ast.init_node != 0) {
4542 if (var_decl.ast.init_node.unwrap()) |init_node| {
45874543 if (is_extern) {
45884544 return astgen.failNode(
4589 var_decl.ast.init_node,
4545 init_node,
45904546 "extern variables have no initializers",
45914547 .{},
45924548 );
......@@ -4597,7 +4553,7 @@ fn globalVarDecl(
45974553 }
45984554 }
45994555
4600 if (is_extern and var_decl.ast.type_node == 0) {
4556 if (is_extern and var_decl.ast.type_node == .none) {
46014557 return astgen.failNode(node, "unable to infer variable type", .{});
46024558 }
46034559
......@@ -4614,45 +4570,45 @@ fn globalVarDecl(
46144570 };
46154571 defer type_gz.unstack();
46164572
4617 if (var_decl.ast.type_node != 0) {
4618 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);
46194575 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
46204576 }
46214577
46224578 var align_gz = type_gz.makeSubBlock(scope);
46234579 defer align_gz.unstack();
46244580
4625 if (var_decl.ast.align_node != 0) {
4626 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);
46274583 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
46284584 }
46294585
46304586 var linksection_gz = type_gz.makeSubBlock(scope);
46314587 defer linksection_gz.unstack();
46324588
4633 if (var_decl.ast.section_node != 0) {
4634 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);
46354591 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
46364592 }
46374593
46384594 var addrspace_gz = type_gz.makeSubBlock(scope);
46394595 defer addrspace_gz.unstack();
46404596
4641 if (var_decl.ast.addrspace_node != 0) {
4642 const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space);
4643 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);
46444600 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
46454601 }
46464602
46474603 var init_gz = type_gz.makeSubBlock(scope);
46484604 defer init_gz.unstack();
46494605
4650 if (var_decl.ast.init_node != 0) {
4606 if (var_decl.ast.init_node.unwrap()) |init_node| {
46514607 init_gz.anon_name_strategy = .parent;
4652 const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{
4608 const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{
46534609 .rl = .{ .coerced_ty = decl_inst.toRef() },
46544610 } else .{ .rl = .none };
4655 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);
46564612 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
46574613 }
46584614
......@@ -4686,8 +4642,7 @@ fn comptimeDecl(
46864642 node: Ast.Node.Index,
46874643) InnerError!void {
46884644 const tree = astgen.tree;
4689 const node_datas = tree.nodes.items(.data);
4690 const body_node = node_datas[node].lhs;
4645 const body_node = tree.nodeData(node).node;
46914646
46924647 const old_hasher = astgen.src_hasher;
46934648 defer astgen.src_hasher = old_hasher;
......@@ -4750,7 +4705,6 @@ fn usingnamespaceDecl(
47504705 node: Ast.Node.Index,
47514706) InnerError!void {
47524707 const tree = astgen.tree;
4753 const node_datas = tree.nodes.items(.data);
47544708
47554709 const old_hasher = astgen.src_hasher;
47564710 defer astgen.src_hasher = old_hasher;
......@@ -4758,13 +4712,9 @@ fn usingnamespaceDecl(
47584712 astgen.src_hasher.update(tree.getNodeSource(node));
47594713 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
47604714
4761 const type_expr = node_datas[node].lhs;
4762 const is_pub = blk: {
4763 const main_tokens = tree.nodes.items(.main_token);
4764 const token_tags = tree.tokens.items(.tag);
4765 const main_token = main_tokens[node];
4766 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
4767 };
4715 const type_expr = tree.nodeData(node).node;
4716 const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub});
4717
47684718 // Up top so the ZIR instruction index marks the start range of this
47694719 // top-level declaration.
47704720 const decl_inst = try gz.makeDeclaration(node);
......@@ -4818,8 +4768,7 @@ fn testDecl(
48184768 node: Ast.Node.Index,
48194769) InnerError!void {
48204770 const tree = astgen.tree;
4821 const node_datas = tree.nodes.items(.data);
4822 const body_node = node_datas[node].rhs;
4771 _, const body_node = tree.nodeData(node).opt_token_and_node;
48234772
48244773 const old_hasher = astgen.src_hasher;
48254774 defer astgen.src_hasher = old_hasher;
......@@ -4851,12 +4800,10 @@ fn testDecl(
48514800
48524801 const decl_column = astgen.source_column;
48534802
4854 const main_tokens = tree.nodes.items(.main_token);
4855 const token_tags = tree.tokens.items(.tag);
4856 const test_token = main_tokens[node];
4803 const test_token = tree.nodeMainToken(node);
48574804
48584805 const test_name_token = test_token + 1;
4859 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {
4806 const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) {
48604807 else => .empty,
48614808 .string_literal => name: {
48624809 const name = try astgen.strLitAsString(test_name_token);
......@@ -4888,7 +4835,7 @@ fn testDecl(
48884835 .local_val => {
48894836 const local_val = s.cast(Scope.LocalVal).?;
48904837 if (local_val.name == name_str_index) {
4891 local_val.used = test_name_token;
4838 local_val.used = .fromToken(test_name_token);
48924839 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
48934840 @tagName(local_val.id_cat),
48944841 }, &[_]u32{
......@@ -4902,7 +4849,7 @@ fn testDecl(
49024849 .local_ptr => {
49034850 const local_ptr = s.cast(Scope.LocalPtr).?;
49044851 if (local_ptr.name == name_str_index) {
4905 local_ptr.used = test_name_token;
4852 local_ptr.used = .fromToken(test_name_token);
49064853 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
49074854 @tagName(local_ptr.id_cat),
49084855 }, &[_]u32{
......@@ -5013,7 +4960,7 @@ fn testDecl(
50134960 .src_line = decl_block.decl_line,
50144961 .src_column = decl_column,
50154962
5016 .kind = switch (token_tags[test_name_token]) {
4963 .kind = switch (tree.tokenTag(test_name_token)) {
50174964 .string_literal => .@"test",
50184965 .identifier => .decltest,
50194966 else => .unnamed_test,
......@@ -5037,7 +4984,7 @@ fn structDeclInner(
50374984 node: Ast.Node.Index,
50384985 container_decl: Ast.full.ContainerDecl,
50394986 layout: std.builtin.Type.ContainerLayout,
5040 backing_int_node: Ast.Node.Index,
4987 backing_int_node: Ast.Node.OptionalIndex,
50414988) InnerError!Zir.Inst.Ref {
50424989 const astgen = gz.astgen;
50434990 const gpa = astgen.gpa;
......@@ -5049,7 +4996,7 @@ fn structDeclInner(
50494996 if (container_field.ast.tuple_like) break member_node;
50504997 } else break :is_tuple;
50514998
5052 if (node == 0) {
4999 if (node == .root) {
50535000 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});
50545001 } else {
50555002 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
......@@ -5058,7 +5005,7 @@ fn structDeclInner(
50585005
50595006 const decl_inst = try gz.reserveInstructionIndex();
50605007
5061 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) {
50625009 try gz.setStruct(decl_inst, .{
50635010 .src_node = node,
50645011 .layout = layout,
......@@ -5105,11 +5052,11 @@ fn structDeclInner(
51055052
51065053 var backing_int_body_len: usize = 0;
51075054 const backing_int_ref: Zir.Inst.Ref = blk: {
5108 if (backing_int_node != 0) {
5055 if (backing_int_node.unwrap()) |arg| {
51095056 if (layout != .@"packed") {
5110 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", .{});
51115058 } else {
5112 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);
51135060 if (!block_scope.isEmpty()) {
51145061 if (!block_scope.endsWithNoReturn()) {
51155062 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);
......@@ -5154,8 +5101,8 @@ fn structDeclInner(
51545101 defer astgen.src_hasher = old_hasher;
51555102 astgen.src_hasher = std.zig.SrcHasher.init(.{});
51565103 astgen.src_hasher.update(@tagName(layout));
5157 if (backing_int_node != 0) {
5158 astgen.src_hasher.update(tree.getNodeSource(backing_int_node));
5104 if (backing_int_node.unwrap()) |arg| {
5105 astgen.src_hasher.update(tree.getNodeSource(arg));
51595106 }
51605107
51615108 var known_non_opv = false;
......@@ -5172,18 +5119,18 @@ fn structDeclInner(
51725119 astgen.src_hasher.update(tree.getNodeSource(member_node));
51735120
51745121 const field_name = try astgen.identAsString(member.ast.main_token);
5175 member.convertToNonTupleLike(astgen.tree.nodes);
5122 member.convertToNonTupleLike(astgen.tree);
51765123 assert(!member.ast.tuple_like);
51775124 wip_members.appendToField(@intFromEnum(field_name));
51785125
5179 if (member.ast.type_expr == 0) {
5126 const type_expr = member.ast.type_expr.unwrap() orelse {
51805127 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5181 }
5128 };
51825129
5183 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);
51845131 const have_type_body = !block_scope.isEmpty();
5185 const have_align = member.ast.align_expr != 0;
5186 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;
51875134 const is_comptime = member.comptime_token != null;
51885135
51895136 if (is_comptime) {
......@@ -5193,9 +5140,9 @@ fn structDeclInner(
51935140 }
51945141 } else {
51955142 known_non_opv = known_non_opv or
5196 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);
5143 nodeImpliesMoreThanOnePossibleValue(tree, type_expr);
51975144 known_comptime_only = known_comptime_only or
5198 nodeImpliesComptimeOnly(tree, member.ast.type_expr);
5145 nodeImpliesComptimeOnly(tree, type_expr);
51995146 }
52005147 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body });
52015148
......@@ -5213,12 +5160,12 @@ fn structDeclInner(
52135160 wip_members.appendToField(@intFromEnum(field_type));
52145161 }
52155162
5216 if (have_align) {
5163 if (member.ast.align_expr.unwrap()) |align_expr| {
52175164 if (layout == .@"packed") {
5218 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", .{});
52195166 }
52205167 any_aligned_fields = true;
5221 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);
52225169 if (!block_scope.endsWithNoReturn()) {
52235170 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
52245171 }
......@@ -5230,14 +5177,14 @@ fn structDeclInner(
52305177 block_scope.instructions.items.len = block_scope.instructions_top;
52315178 }
52325179
5233 if (have_value) {
5180 if (member.ast.value_expr.unwrap()) |value_expr| {
52345181 any_default_inits = true;
52355182
52365183 // The decl_inst is used as here so that we can easily reconstruct a mapping
52375184 // between it and the field type when the fields inits are analyzed.
52385185 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } };
52395186
5240 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);
52415188 if (!block_scope.endsWithNoReturn()) {
52425189 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
52435190 }
......@@ -5300,21 +5247,19 @@ fn tupleDecl(
53005247 node: Ast.Node.Index,
53015248 container_decl: Ast.full.ContainerDecl,
53025249 layout: std.builtin.Type.ContainerLayout,
5303 backing_int_node: Ast.Node.Index,
5250 backing_int_node: Ast.Node.OptionalIndex,
53045251) InnerError!Zir.Inst.Ref {
53055252 const astgen = gz.astgen;
53065253 const gpa = astgen.gpa;
53075254 const tree = astgen.tree;
53085255
5309 const node_tags = tree.nodes.items(.tag);
5310
53115256 switch (layout) {
53125257 .auto => {},
53135258 .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}),
53145259 }
53155260
5316 if (backing_int_node != 0) {
5317 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", .{});
53185263 }
53195264
53205265 // We will use the scratch buffer, starting here, for the field data:
......@@ -5329,7 +5274,7 @@ fn tupleDecl(
53295274
53305275 for (container_decl.ast.members) |member_node| {
53315276 const field = tree.fullContainerField(member_node) orelse {
5332 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)) {
53335278 .container_field_init,
53345279 .container_field_align,
53355280 .container_field,
......@@ -5348,23 +5293,23 @@ fn tupleDecl(
53485293 return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});
53495294 }
53505295
5351 if (field.ast.align_expr != 0) {
5296 if (field.ast.align_expr != .none) {
53525297 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
53535298 }
53545299
5355 if (field.ast.value_expr != 0 and field.comptime_token == null) {
5300 if (field.ast.value_expr != .none and field.comptime_token == null) {
53565301 return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});
53575302 }
53585303
5359 if (field.ast.value_expr == 0 and field.comptime_token != null) {
5304 if (field.ast.value_expr == .none and field.comptime_token != null) {
53605305 return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});
53615306 }
53625307
5363 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().?);
53645309 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
53655310
5366 if (field.ast.value_expr != 0) {
5367 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);
53685313 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
53695314 } else {
53705315 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
......@@ -5399,7 +5344,7 @@ fn unionDeclInner(
53995344 node: Ast.Node.Index,
54005345 members: []const Ast.Node.Index,
54015346 layout: std.builtin.Type.ContainerLayout,
5402 arg_node: Ast.Node.Index,
5347 opt_arg_node: Ast.Node.OptionalIndex,
54035348 auto_enum_tok: ?Ast.TokenIndex,
54045349) InnerError!Zir.Inst.Ref {
54055350 const decl_inst = try gz.reserveInstructionIndex();
......@@ -5434,15 +5379,15 @@ fn unionDeclInner(
54345379 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");
54355380 const field_count: u32 = @intCast(members.len - decl_count);
54365381
5437 if (layout != .auto and (auto_enum_tok != null or arg_node != 0)) {
5438 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| {
54395384 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});
54405385 } else {
54415386 return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)});
54425387 }
54435388 }
54445389
5445 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
5390 const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node|
54465391 try typeExpr(&block_scope, &namespace.base, arg_node)
54475392 else
54485393 .none;
......@@ -5458,7 +5403,7 @@ fn unionDeclInner(
54585403 astgen.src_hasher = std.zig.SrcHasher.init(.{});
54595404 astgen.src_hasher.update(@tagName(layout));
54605405 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});
5461 if (arg_node != 0) {
5406 if (opt_arg_node.unwrap()) |arg_node| {
54625407 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
54635408 }
54645409
......@@ -5468,7 +5413,7 @@ fn unionDeclInner(
54685413 .field => |field| field,
54695414 };
54705415 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));
5471 member.convertToNonTupleLike(astgen.tree.nodes);
5416 member.convertToNonTupleLike(astgen.tree);
54725417 if (member.ast.tuple_like) {
54735418 return astgen.failTok(member.ast.main_token, "union field missing name", .{});
54745419 }
......@@ -5479,24 +5424,24 @@ fn unionDeclInner(
54795424 const field_name = try astgen.identAsString(member.ast.main_token);
54805425 wip_members.appendToField(@intFromEnum(field_name));
54815426
5482 const have_type = member.ast.type_expr != 0;
5483 const have_align = member.ast.align_expr != 0;
5484 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;
54855430 const unused = false;
54865431 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
54875432
5488 if (have_type) {
5489 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);
54905435 wip_members.appendToField(@intFromEnum(field_type));
54915436 } else if (arg_inst == .none and auto_enum_tok == null) {
54925437 return astgen.failNode(member_node, "union field missing type", .{});
54935438 }
5494 if (have_align) {
5495 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);
54965441 wip_members.appendToField(@intFromEnum(align_inst));
54975442 any_aligned_fields = true;
54985443 }
5499 if (have_value) {
5444 if (member.ast.value_expr.unwrap()) |value_expr| {
55005445 if (arg_inst == .none) {
55015446 return astgen.failNodeNotes(
55025447 node,
......@@ -5504,7 +5449,7 @@ fn unionDeclInner(
55045449 .{},
55055450 &[_]u32{
55065451 try astgen.errNoteNode(
5507 member.ast.value_expr,
5452 value_expr,
55085453 "tag value specified here",
55095454 .{},
55105455 ),
......@@ -5518,14 +5463,14 @@ fn unionDeclInner(
55185463 .{},
55195464 &[_]u32{
55205465 try astgen.errNoteNode(
5521 member.ast.value_expr,
5466 value_expr,
55225467 "tag value specified here",
55235468 .{},
55245469 ),
55255470 },
55265471 );
55275472 }
5528 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);
55295474 wip_members.appendToField(@intFromEnum(tag_value));
55305475 }
55315476 }
......@@ -5577,7 +5522,6 @@ fn containerDecl(
55775522 const astgen = gz.astgen;
55785523 const gpa = astgen.gpa;
55795524 const tree = astgen.tree;
5580 const token_tags = tree.tokens.items(.tag);
55815525
55825526 const prev_fn_block = astgen.fn_block;
55835527 astgen.fn_block = null;
......@@ -5586,9 +5530,9 @@ fn containerDecl(
55865530 // We must not create any types until Sema. Here the goal is only to generate
55875531 // ZIR for all the field types, alignments, and default value expressions.
55885532
5589 switch (token_tags[container_decl.ast.main_token]) {
5533 switch (tree.tokenTag(container_decl.ast.main_token)) {
55905534 .keyword_struct => {
5591 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)) {
55925536 .keyword_packed => .@"packed",
55935537 .keyword_extern => .@"extern",
55945538 else => unreachable,
......@@ -5598,7 +5542,7 @@ fn containerDecl(
55985542 return rvalue(gz, ri, result, node);
55995543 },
56005544 .keyword_union => {
5601 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)) {
56025546 .keyword_packed => .@"packed",
56035547 .keyword_extern => .@"extern",
56045548 else => unreachable,
......@@ -5616,23 +5560,23 @@ fn containerDecl(
56165560 var values: usize = 0;
56175561 var total_fields: usize = 0;
56185562 var decls: usize = 0;
5619 var nonexhaustive_node: Ast.Node.Index = 0;
5563 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
56205564 var nonfinal_nonexhaustive = false;
56215565 for (container_decl.ast.members) |member_node| {
56225566 var member = tree.fullContainerField(member_node) orelse {
56235567 decls += 1;
56245568 continue;
56255569 };
5626 member.convertToNonTupleLike(astgen.tree.nodes);
5570 member.convertToNonTupleLike(astgen.tree);
56275571 if (member.ast.tuple_like) {
56285572 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
56295573 }
56305574 if (member.comptime_token) |comptime_token| {
56315575 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
56325576 }
5633 if (member.ast.type_expr != 0) {
5577 if (member.ast.type_expr.unwrap()) |type_expr| {
56345578 return astgen.failNodeNotes(
5635 member.ast.type_expr,
5579 type_expr,
56365580 "enum fields do not have types",
56375581 .{},
56385582 &[_]u32{
......@@ -5644,13 +5588,13 @@ fn containerDecl(
56445588 },
56455589 );
56465590 }
5647 if (member.ast.align_expr != 0) {
5648 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", .{});
56495593 }
56505594
56515595 const name_token = member.ast.main_token;
56525596 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
5653 if (nonexhaustive_node != 0) {
5597 if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| {
56545598 return astgen.failNodeNotes(
56555599 member_node,
56565600 "redundant non-exhaustive enum mark",
......@@ -5664,40 +5608,41 @@ fn containerDecl(
56645608 },
56655609 );
56665610 }
5667 nonexhaustive_node = member_node;
5668 if (member.ast.value_expr != 0) {
5669 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", .{});
56705614 }
56715615 continue;
5672 } else if (nonexhaustive_node != 0) {
5616 } else if (opt_nonexhaustive_node != .none) {
56735617 nonfinal_nonexhaustive = true;
56745618 }
56755619 total_fields += 1;
5676 if (member.ast.value_expr != 0) {
5677 if (container_decl.ast.arg == 0) {
5678 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", .{});
56795623 }
56805624 values += 1;
56815625 }
56825626 }
56835627 if (nonfinal_nonexhaustive) {
5684 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", .{});
56855629 }
56865630 break :blk .{
56875631 .total_fields = total_fields,
56885632 .values = values,
56895633 .decls = decls,
5690 .nonexhaustive_node = nonexhaustive_node,
5634 .nonexhaustive_node = opt_nonexhaustive_node,
56915635 };
56925636 };
5693 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().?;
56945639 return astgen.failNodeNotes(
56955640 node,
56965641 "non-exhaustive enum missing integer tag type",
56975642 .{},
56985643 &[_]u32{
56995644 try astgen.errNoteNode(
5700 counts.nonexhaustive_node,
5645 nonexhaustive_node,
57015646 "marked non-exhaustive here",
57025647 .{},
57035648 ),
......@@ -5706,7 +5651,7 @@ fn containerDecl(
57065651 }
57075652 // In this case we must generate ZIR code for the tag values, similar to
57085653 // how structs are handled above.
5709 const nonexhaustive = counts.nonexhaustive_node != 0;
5654 const nonexhaustive = counts.nonexhaustive_node != .none;
57105655
57115656 const decl_inst = try gz.reserveInstructionIndex();
57125657
......@@ -5736,8 +5681,8 @@ fn containerDecl(
57365681 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
57375682 namespace.base.tag = .namespace;
57385683
5739 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
5740 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)
57415686 else
57425687 .none;
57435688
......@@ -5749,31 +5694,31 @@ fn containerDecl(
57495694 const old_hasher = astgen.src_hasher;
57505695 defer astgen.src_hasher = old_hasher;
57515696 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5752 if (container_decl.ast.arg != 0) {
5753 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));
57545699 }
57555700 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});
57565701
57575702 for (container_decl.ast.members) |member_node| {
5758 if (member_node == counts.nonexhaustive_node)
5703 if (member_node.toOptional() == counts.nonexhaustive_node)
57595704 continue;
57605705 astgen.src_hasher.update(tree.getNodeSource(member_node));
57615706 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
57625707 .decl => continue,
57635708 .field => |field| field,
57645709 };
5765 member.convertToNonTupleLike(astgen.tree.nodes);
5710 member.convertToNonTupleLike(astgen.tree);
57665711 assert(member.comptime_token == null);
5767 assert(member.ast.type_expr == 0);
5768 assert(member.ast.align_expr == 0);
5712 assert(member.ast.type_expr == .none);
5713 assert(member.ast.align_expr == .none);
57695714
57705715 const field_name = try astgen.identAsString(member.ast.main_token);
57715716 wip_members.appendToField(@intFromEnum(field_name));
57725717
5773 const have_value = member.ast.value_expr != 0;
5718 const have_value = member.ast.value_expr != .none;
57745719 wip_members.nextField(bits_per_field, .{have_value});
57755720
5776 if (have_value) {
5721 if (member.ast.value_expr.unwrap()) |value_expr| {
57775722 if (arg_inst == .none) {
57785723 return astgen.failNodeNotes(
57795724 node,
......@@ -5781,14 +5726,14 @@ fn containerDecl(
57815726 .{},
57825727 &[_]u32{
57835728 try astgen.errNoteNode(
5784 member.ast.value_expr,
5729 value_expr,
57855730 "tag value specified here",
57865731 .{},
57875732 ),
57885733 },
57895734 );
57905735 }
5791 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);
57925737 wip_members.appendToField(@intFromEnum(tag_value_inst));
57935738 }
57945739 }
......@@ -5828,7 +5773,7 @@ fn containerDecl(
58285773 return rvalue(gz, ri, decl_inst.toRef(), node);
58295774 },
58305775 .keyword_opaque => {
5831 assert(container_decl.ast.arg == 0);
5776 assert(container_decl.ast.arg == .none);
58325777
58335778 const decl_inst = try gz.reserveInstructionIndex();
58345779
......@@ -5899,9 +5844,7 @@ fn containerMember(
58995844) InnerError!ContainerMemberResult {
59005845 const astgen = gz.astgen;
59015846 const tree = astgen.tree;
5902 const node_tags = tree.nodes.items(.tag);
5903 const node_datas = tree.nodes.items(.data);
5904 switch (node_tags[member_node]) {
5847 switch (tree.nodeTag(member_node)) {
59055848 .container_field_init,
59065849 .container_field_align,
59075850 .container_field,
......@@ -5915,7 +5858,11 @@ fn containerMember(
59155858 => {
59165859 var buf: [1]Ast.Node.Index = undefined;
59175860 const full = tree.fullFnProto(&buf, member_node).?;
5918 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;
59195866
59205867 const prev_decl_index = wip_members.decl_index;
59215868 astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) {
......@@ -5986,12 +5933,7 @@ fn containerMember(
59865933 .@"usingnamespace",
59875934 .empty,
59885935 member_node,
5989 is_pub: {
5990 const main_tokens = tree.nodes.items(.main_token);
5991 const token_tags = tree.tokens.items(.tag);
5992 const main_token = main_tokens[member_node];
5993 break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub;
5994 },
5936 tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}),
59955937 );
59965938 },
59975939 };
......@@ -6025,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
60255967 const astgen = gz.astgen;
60265968 const gpa = astgen.gpa;
60275969 const tree = astgen.tree;
6028 const main_tokens = tree.nodes.items(.main_token);
6029 const token_tags = tree.tokens.items(.tag);
60305970
60315971 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len);
60325972 var fields_len: usize = 0;
......@@ -6034,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
60345974 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;
60355975 defer idents.deinit(gpa);
60365976
6037 const error_token = main_tokens[node];
5977 const error_token = tree.nodeMainToken(node);
60385978 var tok_i = error_token + 2;
60395979 while (true) : (tok_i += 1) {
6040 switch (token_tags[tok_i]) {
5980 switch (tree.tokenTag(tok_i)) {
60415981 .doc_comment, .comma => {},
60425982 .identifier => {
60435983 const str_index = try astgen.identAsString(tok_i);
......@@ -6089,10 +6029,10 @@ fn tryExpr(
60896029 return astgen.failNode(node, "'try' outside function scope", .{});
60906030 };
60916031
6092 if (parent_gz.any_defer_node != 0) {
6032 if (parent_gz.any_defer_node.unwrap()) |any_defer_node| {
60936033 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{
60946034 try astgen.errNoteNode(
6095 parent_gz.any_defer_node,
6035 any_defer_node,
60966036 "defer expression here",
60976037 .{},
60986038 ),
......@@ -6155,16 +6095,16 @@ fn orelseCatchExpr(
61556095 scope: *Scope,
61566096 ri: ResultInfo,
61576097 node: Ast.Node.Index,
6158 lhs: Ast.Node.Index,
61596098 cond_op: Zir.Inst.Tag,
61606099 unwrap_op: Zir.Inst.Tag,
61616100 unwrap_code_op: Zir.Inst.Tag,
6162 rhs: Ast.Node.Index,
61636101 payload_token: ?Ast.TokenIndex,
61646102) InnerError!Zir.Inst.Ref {
61656103 const astgen = parent_gz.astgen;
61666104 const tree = astgen.tree;
61676105
6106 const lhs, const rhs = tree.nodeData(node).node_and_node;
6107
61686108 const need_rl = astgen.nodes_need_rl.contains(node);
61696109 const block_ri: ResultInfo = if (need_rl) ri else .{
61706110 .rl = switch (ri.rl) {
......@@ -6297,12 +6237,8 @@ fn addFieldAccess(
62976237) InnerError!Zir.Inst.Ref {
62986238 const astgen = gz.astgen;
62996239 const tree = astgen.tree;
6300 const main_tokens = tree.nodes.items(.main_token);
6301 const node_datas = tree.nodes.items(.data);
63026240
6303 const object_node = node_datas[node].lhs;
6304 const dot_token = main_tokens[node];
6305 const field_ident = dot_token + 1;
6241 const object_node, const field_ident = tree.nodeData(node).node_and_token;
63066242 const str_index = try astgen.identAsString(field_ident);
63076243 const lhs = try expr(gz, scope, lhs_ri, object_node);
63086244
......@@ -6322,24 +6258,25 @@ fn arrayAccess(
63226258 node: Ast.Node.Index,
63236259) InnerError!Zir.Inst.Ref {
63246260 const tree = gz.astgen.tree;
6325 const node_datas = tree.nodes.items(.data);
63266261 switch (ri.rl) {
63276262 .ref, .ref_coerced_ty => {
6328 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
6263 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6264 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node);
63296265
63306266 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63316267
6332 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6268 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
63336269 try emitDbgStmt(gz, cursor);
63346270
63356271 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
63366272 },
63376273 else => {
6338 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
6274 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6275 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
63396276
63406277 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63416278
6342 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
6279 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
63436280 try emitDbgStmt(gz, cursor);
63446281
63456282 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
......@@ -6356,22 +6293,22 @@ fn simpleBinOp(
63566293) InnerError!Zir.Inst.Ref {
63576294 const astgen = gz.astgen;
63586295 const tree = astgen.tree;
6359 const node_datas = tree.nodes.items(.data);
6296
6297 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
63606298
63616299 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
6362 const node_tags = tree.nodes.items(.tag);
63636300 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
6364 if (node_tags[node_datas[node].lhs] == .string_literal or
6365 node_tags[node_datas[node].rhs] == .string_literal)
6301 if (tree.nodeTag(lhs_node) == .string_literal or
6302 tree.nodeTag(rhs_node) == .string_literal)
63666303 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
63676304 }
63686305
6369 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
6306 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node);
63706307 const cursor = switch (op_inst_tag) {
63716308 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
63726309 else => undefined,
63736310 };
6374 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
6311 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node);
63756312
63766313 switch (op_inst_tag) {
63776314 .add, .sub, .mul, .div, .mod_rem => {
......@@ -6405,16 +6342,16 @@ fn boolBinOp(
64056342) InnerError!Zir.Inst.Ref {
64066343 const astgen = gz.astgen;
64076344 const tree = astgen.tree;
6408 const node_datas = tree.nodes.items(.data);
64096345
6410 const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs);
6346 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6347 const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node);
64116348 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;
64126349
64136350 var rhs_scope = gz.makeSubBlock(scope);
64146351 defer rhs_scope.unstack();
6415 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint);
6352 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint);
64166353 if (!gz.refIsNoReturn(rhs)) {
6417 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);
6354 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node);
64186355 }
64196356 try rhs_scope.setBoolBrBody(bool_br, lhs);
64206357
......@@ -6431,7 +6368,6 @@ fn ifExpr(
64316368) InnerError!Zir.Inst.Ref {
64326369 const astgen = parent_gz.astgen;
64336370 const tree = astgen.tree;
6434 const token_tags = tree.tokens.items(.tag);
64356371
64366372 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
64376373
......@@ -6454,7 +6390,7 @@ fn ifExpr(
64546390 defer block_scope.unstack();
64556391
64566392 const payload_is_ref = if (if_full.payload_token) |payload_token|
6457 token_tags[payload_token] == .asterisk
6393 tree.tokenTag(payload_token) == .asterisk
64586394 else
64596395 false;
64606396
......@@ -6532,7 +6468,7 @@ fn ifExpr(
65326468 break :s &then_scope.base;
65336469 }
65346470 } else if (if_full.payload_token) |payload_token| {
6535 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
6471 const ident_token = payload_token + @intFromBool(payload_is_ref);
65366472 const tag: Zir.Inst.Tag = if (payload_is_ref)
65376473 .optional_payload_unsafe_ptr
65386474 else
......@@ -6574,8 +6510,7 @@ fn ifExpr(
65746510 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))
65756511 _ = try else_scope.addSaveErrRetIndex(.always);
65766512
6577 const else_node = if_full.ast.else_expr;
6578 if (else_node != 0) {
6513 if (if_full.ast.else_expr.unwrap()) |else_node| {
65796514 const sub_scope = s: {
65806515 if (if_full.error_token) |error_token| {
65816516 const tag: Zir.Inst.Tag = if (payload_is_ref)
......@@ -6663,8 +6598,6 @@ fn whileExpr(
66636598) InnerError!Zir.Inst.Ref {
66646599 const astgen = parent_gz.astgen;
66656600 const tree = astgen.tree;
6666 const token_tags = tree.tokens.items(.tag);
6667 const token_starts = tree.tokens.items(.start);
66686601
66696602 const need_rl = astgen.nodes_need_rl.contains(node);
66706603 const block_ri: ResultInfo = if (need_rl) ri else .{
......@@ -6701,7 +6634,7 @@ fn whileExpr(
67016634 defer cond_scope.unstack();
67026635
67036636 const payload_is_ref = if (while_full.payload_token) |payload_token|
6704 token_tags[payload_token] == .asterisk
6637 tree.tokenTag(payload_token) == .asterisk
67056638 else
67066639 false;
67076640
......@@ -6787,7 +6720,6 @@ fn whileExpr(
67876720 break :s &then_scope.base;
67886721 }
67896722 } else if (while_full.payload_token) |payload_token| {
6790 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
67916723 const tag: Zir.Inst.Tag = if (payload_is_ref)
67926724 .optional_payload_unsafe_ptr
67936725 else
......@@ -6795,6 +6727,7 @@ fn whileExpr(
67956727 // will add this instruction to then_scope.instructions below
67966728 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);
67976729 opt_payload_inst = payload_inst.toOptional();
6730 const ident_token = payload_token + @intFromBool(payload_is_ref);
67986731 const ident_name = try astgen.identAsString(ident_token);
67996732 const ident_bytes = tree.tokenSlice(ident_token);
68006733 if (mem.eql(u8, "_", ident_bytes)) {
......@@ -6849,8 +6782,8 @@ fn whileExpr(
68496782 // are no jumps to it. This happens when the last statement of a while body is noreturn
68506783 // and there are no `continue` statements.
68516784 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6852 if (while_full.ast.cont_expr != 0) {
6853 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);
6785 if (while_full.ast.cont_expr.unwrap()) |cont_expr| {
6786 _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr);
68546787 }
68556788
68566789 continue_scope.instructions_top = continue_scope.instructions.items.len;
......@@ -6862,7 +6795,7 @@ fn whileExpr(
68626795 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
68636796 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
68646797 if (!continue_scope.endsWithNoReturn()) {
6865 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
6798 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
68666799 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
68676800 _ = try parent_gz.add(.{
68686801 .tag = .extended,
......@@ -6880,8 +6813,7 @@ fn whileExpr(
68806813 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
68816814 defer else_scope.unstack();
68826815
6883 const else_node = while_full.ast.else_expr;
6884 if (else_node != 0) {
6816 if (while_full.ast.else_expr.unwrap()) |else_node| {
68856817 const sub_scope = s: {
68866818 if (while_full.error_token) |error_token| {
68876819 const tag: Zir.Inst.Tag = if (payload_is_ref)
......@@ -6979,10 +6911,6 @@ fn forExpr(
69796911 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});
69806912 }
69816913 const tree = astgen.tree;
6982 const token_tags = tree.tokens.items(.tag);
6983 const token_starts = tree.tokens.items(.start);
6984 const node_tags = tree.nodes.items(.tag);
6985 const node_data = tree.nodes.items(.data);
69866914 const gpa = astgen.gpa;
69876915
69886916 // For counters, this is the start value; for indexables, this is the base
......@@ -7012,7 +6940,7 @@ fn forExpr(
70126940 {
70136941 var capture_token = for_full.payload_token;
70146942 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {
7015 const capture_is_ref = token_tags[capture_token] == .asterisk;
6943 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
70166944 const ident_tok = capture_token + @intFromBool(capture_is_ref);
70176945 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");
70186946
......@@ -7023,16 +6951,15 @@ fn forExpr(
70236951 capture_token = ident_tok + 2;
70246952
70256953 try emitDbgNode(parent_gz, input);
7026 if (node_tags[input] == .for_range) {
6954 if (tree.nodeTag(input) == .for_range) {
70276955 if (capture_is_ref) {
70286956 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
70296957 }
7030 const start_node = node_data[input].lhs;
6958 const start_node, const end_node = tree.nodeData(input).node_and_opt_node;
70316959 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);
70326960
7033 const end_node = node_data[input].rhs;
7034 const end_val = if (end_node != 0)
7035 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs)
6961 const end_val = if (end_node.unwrap()) |end|
6962 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end)
70366963 else
70376964 .none;
70386965
......@@ -7125,7 +7052,7 @@ fn forExpr(
71257052 var capture_token = for_full.payload_token;
71267053 var capture_sub_scope: *Scope = &then_scope.base;
71277054 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {
7128 const capture_is_ref = token_tags[capture_token] == .asterisk;
7055 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
71297056 const ident_tok = capture_token + @intFromBool(capture_is_ref);
71307057 const capture_name = tree.tokenSlice(ident_tok);
71317058 // Skip over the comma, and on to the next capture (or the ending pipe character).
......@@ -7137,7 +7064,7 @@ fn forExpr(
71377064 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
71387065
71397066 const capture_inst = inst: {
7140 const is_counter = node_tags[input] == .for_range;
7067 const is_counter = tree.nodeTag(input) == .for_range;
71417068
71427069 if (indexable_ref == .none) {
71437070 // Special case: the main index can be used directly.
......@@ -7184,7 +7111,7 @@ fn forExpr(
71847111
71857112 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
71867113
7187 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
7114 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
71887115 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
71897116 _ = try parent_gz.add(.{
71907117 .tag = .extended,
......@@ -7201,8 +7128,7 @@ fn forExpr(
72017128 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
72027129 defer else_scope.unstack();
72037130
7204 const else_node = for_full.ast.else_expr;
7205 if (else_node != 0) {
7131 if (for_full.ast.else_expr.unwrap()) |else_node| {
72067132 const sub_scope = &else_scope.base;
72077133 // Remove the continue block and break block so that `continue` and `break`
72087134 // control flow apply to outer loops; not this one.
......@@ -7270,10 +7196,6 @@ fn switchExprErrUnion(
72707196 const astgen = parent_gz.astgen;
72717197 const gpa = astgen.gpa;
72727198 const tree = astgen.tree;
7273 const node_datas = tree.nodes.items(.data);
7274 const node_tags = tree.nodes.items(.tag);
7275 const main_tokens = tree.nodes.items(.main_token);
7276 const token_tags = tree.tokens.items(.tag);
72777199
72787200 const if_full = switch (node_ty) {
72797201 .@"catch" => undefined,
......@@ -7282,23 +7204,19 @@ fn switchExprErrUnion(
72827204
72837205 const switch_node, const operand_node, const error_payload = switch (node_ty) {
72847206 .@"catch" => .{
7285 node_datas[catch_or_if_node].rhs,
7286 node_datas[catch_or_if_node].lhs,
7287 main_tokens[catch_or_if_node] + 2,
7207 tree.nodeData(catch_or_if_node).node_and_node[1],
7208 tree.nodeData(catch_or_if_node).node_and_node[0],
7209 tree.nodeMainToken(catch_or_if_node) + 2,
72887210 },
72897211 .@"if" => .{
7290 if_full.ast.else_expr,
7212 if_full.ast.else_expr.unwrap().?,
72917213 if_full.ast.cond_expr,
72927214 if_full.error_token.?,
72937215 },
72947216 };
7295 assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma);
7217 const switch_full = tree.fullSwitch(switch_node).?;
72967218
72977219 const do_err_trace = astgen.fn_block != null;
7298
7299 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
7300 const case_nodes = tree.extra_data[extra.start..extra.end];
7301
73027220 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);
73037221 const block_ri: ResultInfo = if (need_rl) ri else .{
73047222 .rl = switch (ri.rl) {
......@@ -7310,7 +7228,7 @@ fn switchExprErrUnion(
73107228 };
73117229
73127230 const payload_is_ref = switch (node_ty) {
7313 .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk,
7231 .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk,
73147232 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,
73157233 };
73167234
......@@ -7322,9 +7240,9 @@ fn switchExprErrUnion(
73227240 var multi_cases_len: u32 = 0;
73237241 var inline_cases_len: u32 = 0;
73247242 var has_else = false;
7325 var else_node: Ast.Node.Index = 0;
7243 var else_node: Ast.Node.OptionalIndex = .none;
73267244 var else_src: ?Ast.TokenIndex = null;
7327 for (case_nodes) |case_node| {
7245 for (switch_full.ast.cases) |case_node| {
73287246 const case = tree.fullSwitchCase(case_node).?;
73297247
73307248 if (case.ast.values.len == 0) {
......@@ -7344,12 +7262,12 @@ fn switchExprErrUnion(
73447262 );
73457263 }
73467264 has_else = true;
7347 else_node = case_node;
7265 else_node = case_node.toOptional();
73487266 else_src = case_src;
73497267 continue;
73507268 } else if (case.ast.values.len == 1 and
7351 node_tags[case.ast.values[0]] == .identifier and
7352 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
7269 tree.nodeTag(case.ast.values[0]) == .identifier and
7270 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
73537271 {
73547272 const case_src = case.ast.arrow_token - 1;
73557273 return astgen.failTokNotes(
......@@ -7367,11 +7285,11 @@ fn switchExprErrUnion(
73677285 }
73687286
73697287 for (case.ast.values) |val| {
7370 if (node_tags[val] == .string_literal)
7288 if (tree.nodeTag(val) == .string_literal)
73717289 return astgen.failNode(val, "cannot switch on strings", .{});
73727290 }
73737291
7374 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
7292 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
73757293 scalar_cases_len += 1;
73767294 } else {
73777295 multi_cases_len += 1;
......@@ -7564,11 +7482,11 @@ fn switchExprErrUnion(
75647482 var multi_case_index: u32 = 0;
75657483 var scalar_case_index: u32 = 0;
75667484 var any_uses_err_capture = false;
7567 for (case_nodes) |case_node| {
7485 for (switch_full.ast.cases) |case_node| {
75687486 const case = tree.fullSwitchCase(case_node).?;
75697487
75707488 const is_multi_case = case.ast.values.len > 1 or
7571 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
7489 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
75727490
75737491 var dbg_var_name: Zir.NullTerminatedString = .empty;
75747492 var dbg_var_inst: Zir.Inst.Ref = undefined;
......@@ -7586,7 +7504,7 @@ fn switchExprErrUnion(
75867504 };
75877505
75887506 const capture_token = case.payload_token orelse break :blk &err_scope.base;
7589 if (token_tags[capture_token] != .identifier) {
7507 if (tree.tokenTag(capture_token) != .identifier) {
75907508 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});
75917509 }
75927510
......@@ -7622,7 +7540,7 @@ fn switchExprErrUnion(
76227540 // items
76237541 var items_len: u32 = 0;
76247542 for (case.ast.values) |item_node| {
7625 if (node_tags[item_node] == .switch_range) continue;
7543 if (tree.nodeTag(item_node) == .switch_range) continue;
76267544 items_len += 1;
76277545
76287546 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
......@@ -7632,11 +7550,12 @@ fn switchExprErrUnion(
76327550 // ranges
76337551 var ranges_len: u32 = 0;
76347552 for (case.ast.values) |range| {
7635 if (node_tags[range] != .switch_range) continue;
7553 if (tree.nodeTag(range) != .switch_range) continue;
76367554 ranges_len += 1;
76377555
7638 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
7639 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
7556 const first_node, const last_node = tree.nodeData(range).node_and_node;
7557 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
7558 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
76407559 try payloads.appendSlice(gpa, &[_]u32{
76417560 @intFromEnum(first), @intFromEnum(last),
76427561 });
......@@ -7645,7 +7564,7 @@ fn switchExprErrUnion(
76457564 payloads.items[header_index] = items_len;
76467565 payloads.items[header_index + 1] = ranges_len;
76477566 break :blk header_index + 2;
7648 } else if (case_node == else_node) blk: {
7567 } else if (case_node.toOptional() == else_node) blk: {
76497568 payloads.items[case_table_start + 1] = header_index;
76507569 try payloads.resize(gpa, header_index + 1); // body_len
76517570 break :blk header_index;
......@@ -7675,7 +7594,7 @@ fn switchExprErrUnion(
76757594 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);
76767595 // check capture_scope, not err_scope to avoid false positive unused error capture
76777596 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
7678 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;
7597 const uses_err = err_scope.used != .none or err_scope.discarded != .none;
76797598 if (uses_err) {
76807599 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());
76817600 any_uses_err_capture = true;
......@@ -7775,10 +7694,6 @@ fn switchExpr(
77757694 const astgen = parent_gz.astgen;
77767695 const gpa = astgen.gpa;
77777696 const tree = astgen.tree;
7778 const node_datas = tree.nodes.items(.data);
7779 const node_tags = tree.nodes.items(.tag);
7780 const main_tokens = tree.nodes.items(.main_token);
7781 const token_tags = tree.tokens.items(.tag);
77827697 const operand_node = switch_full.ast.condition;
77837698 const case_nodes = switch_full.ast.cases;
77847699
......@@ -7810,17 +7725,17 @@ fn switchExpr(
78107725 var multi_cases_len: u32 = 0;
78117726 var inline_cases_len: u32 = 0;
78127727 var special_prong: Zir.SpecialProng = .none;
7813 var special_node: Ast.Node.Index = 0;
7728 var special_node: Ast.Node.OptionalIndex = .none;
78147729 var else_src: ?Ast.TokenIndex = null;
78157730 var underscore_src: ?Ast.TokenIndex = null;
78167731 for (case_nodes) |case_node| {
78177732 const case = tree.fullSwitchCase(case_node).?;
78187733 if (case.payload_token) |payload_token| {
7819 const ident = if (token_tags[payload_token] == .asterisk) blk: {
7734 const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: {
78207735 any_payload_is_ref = true;
78217736 break :blk payload_token + 1;
78227737 } else payload_token;
7823 if (token_tags[ident + 1] == .comma) {
7738 if (tree.tokenTag(ident + 1) == .comma) {
78247739 any_has_tag_capture = true;
78257740 }
78267741
......@@ -7868,13 +7783,13 @@ fn switchExpr(
78687783 },
78697784 );
78707785 }
7871 special_node = case_node;
7786 special_node = case_node.toOptional();
78727787 special_prong = .@"else";
78737788 else_src = case_src;
78747789 continue;
78757790 } else if (case.ast.values.len == 1 and
7876 node_tags[case.ast.values[0]] == .identifier and
7877 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))
7791 tree.nodeTag(case.ast.values[0]) == .identifier and
7792 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
78787793 {
78797794 const case_src = case.ast.arrow_token - 1;
78807795 if (underscore_src) |src| {
......@@ -7912,18 +7827,18 @@ fn switchExpr(
79127827 if (case.inline_token != null) {
79137828 return astgen.failTok(case_src, "cannot inline '_' prong", .{});
79147829 }
7915 special_node = case_node;
7830 special_node = case_node.toOptional();
79167831 special_prong = .under;
79177832 underscore_src = case_src;
79187833 continue;
79197834 }
79207835
79217836 for (case.ast.values) |val| {
7922 if (node_tags[val] == .string_literal)
7837 if (tree.nodeTag(val) == .string_literal)
79237838 return astgen.failNode(val, "cannot switch on strings", .{});
79247839 }
79257840
7926 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
7841 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
79277842 scalar_cases_len += 1;
79287843 } else {
79297844 multi_cases_len += 1;
......@@ -8012,7 +7927,7 @@ fn switchExpr(
80127927 const case = tree.fullSwitchCase(case_node).?;
80137928
80147929 const is_multi_case = case.ast.values.len > 1 or
8015 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);
7930 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
80167931
80177932 var dbg_var_name: Zir.NullTerminatedString = .empty;
80187933 var dbg_var_inst: Zir.Inst.Ref = undefined;
......@@ -8026,18 +7941,15 @@ fn switchExpr(
80267941
80277942 const sub_scope = blk: {
80287943 const payload_token = case.payload_token orelse break :blk &case_scope.base;
8029 const ident = if (token_tags[payload_token] == .asterisk)
8030 payload_token + 1
8031 else
8032 payload_token;
7944 const capture_is_ref = tree.tokenTag(payload_token) == .asterisk;
7945 const ident = payload_token + @intFromBool(capture_is_ref);
80337946
8034 const is_ptr = ident != payload_token;
8035 capture = if (is_ptr) .by_ref else .by_val;
7947 capture = if (capture_is_ref) .by_ref else .by_val;
80367948
80377949 const ident_slice = tree.tokenSlice(ident);
80387950 var payload_sub_scope: *Scope = undefined;
80397951 if (mem.eql(u8, ident_slice, "_")) {
8040 if (is_ptr) {
7952 if (capture_is_ref) {
80417953 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
80427954 }
80437955 payload_sub_scope = &case_scope.base;
......@@ -8057,7 +7969,7 @@ fn switchExpr(
80577969 payload_sub_scope = &capture_val_scope.base;
80587970 }
80597971
8060 const tag_token = if (token_tags[ident + 1] == .comma)
7972 const tag_token = if (tree.tokenTag(ident + 1) == .comma)
80617973 ident + 2
80627974 else
80637975 break :blk payload_sub_scope;
......@@ -8095,7 +8007,7 @@ fn switchExpr(
80958007 // items
80968008 var items_len: u32 = 0;
80978009 for (case.ast.values) |item_node| {
8098 if (node_tags[item_node] == .switch_range) continue;
8010 if (tree.nodeTag(item_node) == .switch_range) continue;
80998011 items_len += 1;
81008012
81018013 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
......@@ -8105,11 +8017,12 @@ fn switchExpr(
81058017 // ranges
81068018 var ranges_len: u32 = 0;
81078019 for (case.ast.values) |range| {
8108 if (node_tags[range] != .switch_range) continue;
8020 if (tree.nodeTag(range) != .switch_range) continue;
81098021 ranges_len += 1;
81108022
8111 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
8112 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
8023 const first_node, const last_node = tree.nodeData(range).node_and_node;
8024 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
8025 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
81138026 try payloads.appendSlice(gpa, &[_]u32{
81148027 @intFromEnum(first), @intFromEnum(last),
81158028 });
......@@ -8118,7 +8031,7 @@ fn switchExpr(
81188031 payloads.items[header_index] = items_len;
81198032 payloads.items[header_index + 1] = ranges_len;
81208033 break :blk header_index + 2;
8121 } else if (case_node == special_node) blk: {
8034 } else if (case_node.toOptional() == special_node) blk: {
81228035 payloads.items[case_table_start] = header_index;
81238036 try payloads.resize(gpa, header_index + 1); // body_len
81248037 break :blk header_index;
......@@ -8231,17 +8144,15 @@ fn switchExpr(
82318144fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
82328145 const astgen = gz.astgen;
82338146 const tree = astgen.tree;
8234 const node_datas = tree.nodes.items(.data);
8235 const node_tags = tree.nodes.items(.tag);
82368147
82378148 if (astgen.fn_block == null) {
82388149 return astgen.failNode(node, "'return' outside function scope", .{});
82398150 }
82408151
8241 if (gz.any_defer_node != 0) {
8152 if (gz.any_defer_node.unwrap()) |any_defer_node| {
82428153 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{
82438154 try astgen.errNoteNode(
8244 gz.any_defer_node,
8155 any_defer_node,
82458156 "defer expression here",
82468157 .{},
82478158 ),
......@@ -8259,8 +8170,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
82598170
82608171 const defer_outer = &astgen.fn_block.?.base;
82618172
8262 const operand_node = node_datas[node].lhs;
8263 if (operand_node == 0) {
8173 const operand_node = tree.nodeData(node).opt_node.unwrap() orelse {
82648174 // Returning a void value; skip error defers.
82658175 try genDefers(gz, defer_outer, scope, .normal_only);
82668176
......@@ -8269,12 +8179,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
82698179
82708180 _ = try gz.addUnNode(.ret_node, .void_value, node);
82718181 return Zir.Inst.Ref.unreachable_value;
8272 }
8182 };
82738183
8274 if (node_tags[operand_node] == .error_value) {
8184 if (tree.nodeTag(operand_node) == .error_value) {
82758185 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic
82768186 // for detecting whether to add something to the function's inferred error set.
8277 const ident_token = node_datas[operand_node].rhs;
8187 const ident_token = tree.nodeData(operand_node).opt_token_and_opt_token[1].unwrap().?;
82788188 const err_name_str_index = try astgen.identAsString(ident_token);
82798189 const defer_counts = countDefers(defer_outer, scope);
82808190 if (!defer_counts.need_err_code) {
......@@ -8405,9 +8315,8 @@ fn identifier(
84058315) InnerError!Zir.Inst.Ref {
84068316 const astgen = gz.astgen;
84078317 const tree = astgen.tree;
8408 const main_tokens = tree.nodes.items(.main_token);
84098318
8410 const ident_token = main_tokens[ident];
8319 const ident_token = tree.nodeMainToken(ident);
84118320 const ident_name_raw = tree.tokenSlice(ident_token);
84128321 if (mem.eql(u8, ident_name_raw, "_")) {
84138322 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
......@@ -8509,9 +8418,9 @@ fn localVarRef(
85098418 // Locals cannot shadow anything, so we do not need to look for ambiguous
85108419 // references in this case.
85118420 if (ri.rl == .discard and ri.ctx == .assignment) {
8512 local_val.discarded = ident_token;
8421 local_val.discarded = .fromToken(ident_token);
85138422 } else {
8514 local_val.used = ident_token;
8423 local_val.used = .fromToken(ident_token);
85158424 }
85168425
85178426 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
......@@ -8533,9 +8442,9 @@ fn localVarRef(
85338442 const local_ptr = s.cast(Scope.LocalPtr).?;
85348443 if (local_ptr.name == name_str_index) {
85358444 if (ri.rl == .discard and ri.ctx == .assignment) {
8536 local_ptr.discarded = ident_token;
8445 local_ptr.discarded = .fromToken(ident_token);
85378446 } else {
8538 local_ptr.used = ident_token;
8447 local_ptr.used = .fromToken(ident_token);
85398448 }
85408449
85418450 // Can't close over a runtime variable
......@@ -8748,8 +8657,7 @@ fn stringLiteral(
87488657) InnerError!Zir.Inst.Ref {
87498658 const astgen = gz.astgen;
87508659 const tree = astgen.tree;
8751 const main_tokens = tree.nodes.items(.main_token);
8752 const str_lit_token = main_tokens[node];
8660 const str_lit_token = tree.nodeMainToken(node);
87538661 const str = try astgen.strLitAsString(str_lit_token);
87548662 const result = try gz.add(.{
87558663 .tag = .str,
......@@ -8781,8 +8689,7 @@ fn multilineStringLiteral(
87818689fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
87828690 const astgen = gz.astgen;
87838691 const tree = astgen.tree;
8784 const main_tokens = tree.nodes.items(.main_token);
8785 const main_token = main_tokens[node];
8692 const main_token = tree.nodeMainToken(node);
87868693 const slice = tree.tokenSlice(main_token);
87878694
87888695 switch (std.zig.parseCharLiteral(slice)) {
......@@ -8799,8 +8706,7 @@ const Sign = enum { negative, positive };
87998706fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
88008707 const astgen = gz.astgen;
88018708 const tree = astgen.tree;
8802 const main_tokens = tree.nodes.items(.main_token);
8803 const num_token = main_tokens[node];
8709 const num_token = tree.nodeMainToken(node);
88048710 const bytes = tree.tokenSlice(num_token);
88058711
88068712 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
......@@ -8918,16 +8824,12 @@ fn asmExpr(
89188824) InnerError!Zir.Inst.Ref {
89198825 const astgen = gz.astgen;
89208826 const tree = astgen.tree;
8921 const main_tokens = tree.nodes.items(.main_token);
8922 const node_datas = tree.nodes.items(.data);
8923 const node_tags = tree.nodes.items(.tag);
8924 const token_tags = tree.tokens.items(.tag);
89258827
89268828 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };
8927 const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) {
8829 const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) {
89288830 .string_literal => .{
89298831 .tag = .@"asm",
8930 .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index,
8832 .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index,
89318833 },
89328834 .multiline_string_literal => .{
89338835 .tag = .@"asm",
......@@ -8962,17 +8864,17 @@ fn asmExpr(
89628864 var output_type_bits: u32 = 0;
89638865
89648866 for (full.outputs, 0..) |output_node, i| {
8965 const symbolic_name = main_tokens[output_node];
8867 const symbolic_name = tree.nodeMainToken(output_node);
89668868 const name = try astgen.identAsString(symbolic_name);
89678869 const constraint_token = symbolic_name + 2;
89688870 const constraint = (try astgen.strLitAsString(constraint_token)).index;
8969 const has_arrow = token_tags[symbolic_name + 4] == .arrow;
8871 const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow;
89708872 if (has_arrow) {
89718873 if (output_type_bits != 0) {
89728874 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});
89738875 }
89748876 output_type_bits |= @as(u32, 1) << @intCast(i);
8975 const out_type_node = node_datas[output_node].lhs;
8877 const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?;
89768878 const out_type_inst = try typeExpr(gz, scope, out_type_node);
89778879 outputs[i] = .{
89788880 .name = name,
......@@ -8999,11 +8901,11 @@ fn asmExpr(
89998901 const inputs = inputs_buffer[0..full.inputs.len];
90008902
90018903 for (full.inputs, 0..) |input_node, i| {
9002 const symbolic_name = main_tokens[input_node];
8904 const symbolic_name = tree.nodeMainToken(input_node);
90038905 const name = try astgen.identAsString(symbolic_name);
90048906 const constraint_token = symbolic_name + 2;
90058907 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9006 const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs);
8908 const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]);
90078909 inputs[i] = .{
90088910 .name = name,
90098911 .constraint = constraint,
......@@ -9024,10 +8926,10 @@ fn asmExpr(
90248926 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);
90258927 clobber_i += 1;
90268928 tok_i += 1;
9027 switch (token_tags[tok_i]) {
8929 switch (tree.tokenTag(tok_i)) {
90288930 .r_paren => break :clobbers,
90298931 .comma => {
9030 if (token_tags[tok_i + 1] == .r_paren) {
8932 if (tree.tokenTag(tok_i + 1) == .r_paren) {
90318933 break :clobbers;
90328934 } else {
90338935 continue;
......@@ -9119,9 +9021,6 @@ fn ptrCast(
91199021) InnerError!Zir.Inst.Ref {
91209022 const astgen = gz.astgen;
91219023 const tree = astgen.tree;
9122 const main_tokens = tree.nodes.items(.main_token);
9123 const node_datas = tree.nodes.items(.data);
9124 const node_tags = tree.nodes.items(.tag);
91259024
91269025 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
91279026 var flags: Zir.Inst.FullPtrCastFlags = .{};
......@@ -9130,11 +9029,11 @@ fn ptrCast(
91309029 // to handle `builtin_call_two`.
91319030 var node = root_node;
91329031 while (true) {
9133 switch (node_tags[node]) {
9032 switch (tree.nodeTag(node)) {
91349033 .builtin_call_two, .builtin_call_two_comma => {},
91359034 .grouped_expression => {
91369035 // Handle the chaining even with redundant parentheses
9137 node = node_datas[node].lhs;
9036 node = tree.nodeData(node).node_and_token[0];
91389037 continue;
91399038 },
91409039 else => break,
......@@ -9144,7 +9043,9 @@ fn ptrCast(
91449043 const args = tree.builtinCallParams(&buf, node).?;
91459044 std.debug.assert(args.len <= 2);
91469045
9147 const builtin_token = main_tokens[node];
9046 if (args.len == 0) break; // 0 args
9047
9048 const builtin_token = tree.nodeMainToken(node);
91489049 const builtin_name = tree.tokenSlice(builtin_token);
91499050 const info = BuiltinFn.list.get(builtin_name) orelse break;
91509051 if (args.len == 1) {
......@@ -9344,9 +9245,8 @@ fn builtinCall(
93449245) InnerError!Zir.Inst.Ref {
93459246 const astgen = gz.astgen;
93469247 const tree = astgen.tree;
9347 const main_tokens = tree.nodes.items(.main_token);
93489248
9349 const builtin_token = main_tokens[node];
9249 const builtin_token = tree.nodeMainToken(node);
93509250 const builtin_name = tree.tokenSlice(builtin_token);
93519251
93529252 // We handle the different builtins manually because they have different semantics depending
......@@ -9387,14 +9287,13 @@ fn builtinCall(
93879287 return rvalue(gz, ri, .void_value, node);
93889288 },
93899289 .import => {
9390 const node_tags = tree.nodes.items(.tag);
93919290 const operand_node = params[0];
93929291
9393 if (node_tags[operand_node] != .string_literal) {
9292 if (tree.nodeTag(operand_node) != .string_literal) {
93949293 // Spec reference: https://github.com/ziglang/zig/issues/2206
93959294 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
93969295 }
9397 const str_lit_token = main_tokens[operand_node];
9296 const str_lit_token = tree.nodeMainToken(operand_node);
93989297 const str = try astgen.strLitAsString(str_lit_token);
93999298 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];
94009299 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
......@@ -9505,8 +9404,7 @@ fn builtinCall(
95059404 std.mem.asBytes(&astgen.source_column),
95069405 );
95079406
9508 const token_starts = tree.tokens.items(.start);
9509 const node_start = token_starts[tree.firstToken(node)];
9407 const node_start = tree.tokenStart(tree.firstToken(node));
95109408 astgen.advanceSourceCursor(node_start);
95119409 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{
95129410 .node = gz.nodeIndexToRelative(node),
......@@ -9786,7 +9684,7 @@ fn builtinCall(
97869684 .callee = callee,
97879685 .args = args,
97889686 .flags = .{
9789 .is_nosuspend = gz.nosuspend_node != 0,
9687 .is_nosuspend = gz.nosuspend_node != .none,
97909688 .ensure_result_used = false,
97919689 },
97929690 });
......@@ -10011,13 +9909,11 @@ fn negation(
100119909) InnerError!Zir.Inst.Ref {
100129910 const astgen = gz.astgen;
100139911 const tree = astgen.tree;
10014 const node_tags = tree.nodes.items(.tag);
10015 const node_datas = tree.nodes.items(.data);
100169912
100179913 // Check for float literal as the sub-expression because we want to preserve
100189914 // its negativity rather than having it go through comptime subtraction.
10019 const operand_node = node_datas[node].lhs;
10020 if (node_tags[operand_node] == .number_literal) {
9915 const operand_node = tree.nodeData(node).node;
9916 if (tree.nodeTag(operand_node) == .number_literal) {
100219917 return numberLiteral(gz, ri, operand_node, node, .negative);
100229918 }
100239919
......@@ -10133,7 +10029,7 @@ fn shiftOp(
1013310029) InnerError!Zir.Inst.Ref {
1013410030 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
1013510031
10136 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {
10032 const cursor = switch (gz.astgen.tree.nodeTag(node)) {
1013710033 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
1013810034 else => undefined,
1013910035 };
......@@ -10141,7 +10037,7 @@ fn shiftOp(
1014110037 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
1014210038 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
1014310039
10144 switch (gz.astgen.tree.nodes.items(.tag)[node]) {
10040 switch (gz.astgen.tree.nodeTag(node)) {
1014510041 .shl, .shr => try emitDbgStmt(gz, cursor),
1014610042 else => undefined,
1014710043 }
......@@ -10217,14 +10113,14 @@ fn callExpr(
1021710113 if (call.async_token != null) {
1021810114 break :blk .async_kw;
1021910115 }
10220 if (gz.nosuspend_node != 0) {
10116 if (gz.nosuspend_node != .none) {
1022110117 break :blk .no_async;
1022210118 }
1022310119 break :blk .auto;
1022410120 };
1022510121
1022610122 {
10227 astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]);
10123 astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen));
1022810124 const line = astgen.source_line - gz.decl_line;
1022910125 const column = astgen.source_column;
1023010126 // Sema expects a dbg_stmt immediately before call,
......@@ -10235,7 +10131,6 @@ fn callExpr(
1023510131 .direct => |obj| assert(obj != .none),
1023610132 .field => |field| assert(field.obj_ptr != .none),
1023710133 }
10238 assert(node != 0);
1023910134
1024010135 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
1024110136 const call_inst = call_index.toRef();
......@@ -10346,14 +10241,10 @@ fn calleeExpr(
1034610241 const astgen = gz.astgen;
1034710242 const tree = astgen.tree;
1034810243
10349 const tag = tree.nodes.items(.tag)[node];
10244 const tag = tree.nodeTag(node);
1035010245 switch (tag) {
1035110246 .field_access => {
10352 const main_tokens = tree.nodes.items(.main_token);
10353 const node_datas = tree.nodes.items(.data);
10354 const object_node = node_datas[node].lhs;
10355 const dot_token = main_tokens[node];
10356 const field_ident = dot_token + 1;
10247 const object_node, const field_ident = tree.nodeData(node).node_and_token;
1035710248 const str_index = try astgen.identAsString(field_ident);
1035810249 // Capture the object by reference so we can promote it to an
1035910250 // address in Sema if needed.
......@@ -10378,7 +10269,7 @@ fn calleeExpr(
1037810269 // Decl literal call syntax, e.g.
1037910270 // `const foo: T = .init();`
1038010271 // Look up `init` in `T`, but don't try and coerce it.
10381 const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]);
10272 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
1038210273 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{
1038310274 .lhs = res_ty,
1038410275 .field_name_start = str_index,
......@@ -10450,12 +10341,9 @@ comptime {
1045010341}
1045110342
1045210343fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10453 const node_tags = tree.nodes.items(.tag);
10454 const main_tokens = tree.nodes.items(.main_token);
10455
10456 switch (node_tags[node]) {
10344 switch (tree.nodeTag(node)) {
1045710345 .number_literal => {
10458 const ident = main_tokens[node];
10346 const ident = tree.nodeMainToken(node);
1045910347 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {
1046010348 .int => |number| switch (number) {
1046110349 0 => true,
......@@ -10469,12 +10357,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
1046910357}
1047010358
1047110359fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {
10472 const node_tags = tree.nodes.items(.tag);
10473 const node_datas = tree.nodes.items(.data);
10474
1047510360 var node = start_node;
1047610361 while (true) {
10477 switch (node_tags[node]) {
10362 switch (tree.nodeTag(node)) {
1047810363 // These don't have the opportunity to call any runtime functions.
1047910364 .error_value,
1048010365 .identifier,
......@@ -10482,11 +10367,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
1048210367 => return false,
1048310368
1048410369 // Forward the question to the LHS sub-expression.
10485 .grouped_expression,
1048610370 .@"try",
1048710371 .@"nosuspend",
10372 => node = tree.nodeData(node).node,
10373 .grouped_expression,
1048810374 .unwrap_optional,
10489 => node = node_datas[node].lhs,
10375 => node = tree.nodeData(node).node_and_token[0],
1049010376
1049110377 // Anything that does not eval to an error is guaranteed to pop any
1049210378 // additions to the error trace, so it effectively does not append.
......@@ -10496,14 +10382,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
1049610382}
1049710383
1049810384fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
10499 const node_tags = tree.nodes.items(.tag);
10500 const node_datas = tree.nodes.items(.data);
10501 const main_tokens = tree.nodes.items(.main_token);
10502 const token_tags = tree.tokens.items(.tag);
10503
1050410385 var node = start_node;
1050510386 while (true) {
10506 switch (node_tags[node]) {
10387 switch (tree.nodeTag(node)) {
1050710388 .root,
1050810389 .@"usingnamespace",
1050910390 .test_decl,
......@@ -10666,13 +10547,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1066610547 => return .never,
1066710548
1066810549 // Forward the question to the LHS sub-expression.
10669 .grouped_expression,
1067010550 .@"try",
1067110551 .@"await",
1067210552 .@"comptime",
1067310553 .@"nosuspend",
10554 => node = tree.nodeData(node).node,
10555 .grouped_expression,
1067410556 .unwrap_optional,
10675 => node = node_datas[node].lhs,
10557 => node = tree.nodeData(node).node_and_token[0],
1067610558
1067710559 // LHS sub-expression may still be an error under the outer optional or error union
1067810560 .@"catch",
......@@ -10684,8 +10566,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1068410566 .block,
1068510567 .block_semicolon,
1068610568 => {
10687 const lbrace = main_tokens[node];
10688 if (token_tags[lbrace - 1] == .colon) {
10569 const lbrace = tree.nodeMainToken(node);
10570 if (tree.tokenTag(lbrace - 1) == .colon) {
1068910571 // Labeled blocks may need a memory location to forward
1069010572 // to their break statements.
1069110573 return .maybe;
......@@ -10699,7 +10581,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1069910581 .builtin_call_two,
1070010582 .builtin_call_two_comma,
1070110583 => {
10702 const builtin_token = main_tokens[node];
10584 const builtin_token = tree.nodeMainToken(node);
1070310585 const builtin_name = tree.tokenSlice(builtin_token);
1070410586 // If the builtin is an invalid name, we don't cause an error here; instead
1070510587 // let it pass, and the error will be "invalid builtin function" later.
......@@ -10713,12 +10595,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
1071310595/// Returns `true` if it is known the type expression has more than one possible value;
1071410596/// `false` otherwise.
1071510597fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
10716 const node_tags = tree.nodes.items(.tag);
10717 const node_datas = tree.nodes.items(.data);
10718
1071910598 var node = start_node;
1072010599 while (true) {
10721 switch (node_tags[node]) {
10600 switch (tree.nodeTag(node)) {
1072210601 .root,
1072310602 .@"usingnamespace",
1072410603 .test_decl,
......@@ -10881,13 +10760,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1088110760 => return false,
1088210761
1088310762 // Forward the question to the LHS sub-expression.
10884 .grouped_expression,
1088510763 .@"try",
1088610764 .@"await",
1088710765 .@"comptime",
1088810766 .@"nosuspend",
10767 => node = tree.nodeData(node).node,
10768 .grouped_expression,
1088910769 .unwrap_optional,
10890 => node = node_datas[node].lhs,
10770 => node = tree.nodeData(node).node_and_token[0],
1089110771
1089210772 .ptr_type_aligned,
1089310773 .ptr_type_sentinel,
......@@ -10899,8 +10779,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1089910779 => return true,
1090010780
1090110781 .identifier => {
10902 const main_tokens = tree.nodes.items(.main_token);
10903 const ident_bytes = tree.tokenSlice(main_tokens[node]);
10782 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
1090410783 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
1090510784 .anyerror_type,
1090610785 .anyframe_type,
......@@ -10960,12 +10839,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
1096010839/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
1096110840/// `false` otherwise.
1096210841fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
10963 const node_tags = tree.nodes.items(.tag);
10964 const node_datas = tree.nodes.items(.data);
10965
1096610842 var node = start_node;
1096710843 while (true) {
10968 switch (node_tags[node]) {
10844 switch (tree.nodeTag(node)) {
1096910845 .root,
1097010846 .@"usingnamespace",
1097110847 .test_decl,
......@@ -11137,17 +11013,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1113711013 => return true,
1113811014
1113911015 // Forward the question to the LHS sub-expression.
11140 .grouped_expression,
1114111016 .@"try",
1114211017 .@"await",
1114311018 .@"comptime",
1114411019 .@"nosuspend",
11020 => node = tree.nodeData(node).node,
11021 .grouped_expression,
1114511022 .unwrap_optional,
11146 => node = node_datas[node].lhs,
11023 => node = tree.nodeData(node).node_and_token[0],
1114711024
1114811025 .identifier => {
11149 const main_tokens = tree.nodes.items(.main_token);
11150 const ident_bytes = tree.tokenSlice(main_tokens[node]);
11026 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
1115111027 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
1115211028 .anyerror_type,
1115311029 .anyframe_type,
......@@ -11206,8 +11082,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1120611082
1120711083/// Returns `true` if the node uses `gz.anon_name_strategy`.
1120811084fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11209 const node_tags = tree.nodes.items(.tag);
11210 switch (node_tags[node]) {
11085 switch (tree.nodeTag(node)) {
1121111086 .container_decl,
1121211087 .container_decl_trailing,
1121311088 .container_decl_two,
......@@ -11222,7 +11097,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
1122211097 .tagged_union_enum_tag_trailing,
1122311098 => return true,
1122411099 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {
11225 const builtin_token = tree.nodes.items(.main_token)[node];
11100 const builtin_token = tree.nodeMainToken(node);
1122611101 const builtin_name = tree.tokenSlice(builtin_token);
1122711102 return std.mem.eql(u8, builtin_name, "@Type");
1122811103 },
......@@ -11455,8 +11330,7 @@ fn rvalueInner(
1145511330/// See also `appendIdentStr` and `parseStrLit`.
1145611331fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {
1145711332 const tree = astgen.tree;
11458 const token_tags = tree.tokens.items(.tag);
11459 assert(token_tags[token] == .identifier);
11333 assert(tree.tokenTag(token) == .identifier);
1146011334 const ident_name = tree.tokenSlice(token);
1146111335 if (!mem.startsWith(u8, ident_name, "@")) {
1146211336 return ident_name;
......@@ -11482,8 +11356,7 @@ fn appendIdentStr(
1148211356 buf: *ArrayListUnmanaged(u8),
1148311357) InnerError!void {
1148411358 const tree = astgen.tree;
11485 const token_tags = tree.tokens.items(.tag);
11486 assert(token_tags[token] == .identifier);
11359 assert(tree.tokenTag(token) == .identifier);
1148711360 const ident_name = tree.tokenSlice(token);
1148811361 if (!mem.startsWith(u8, ident_name, "@")) {
1148911362 return buf.appendSlice(astgen.gpa, ident_name);
......@@ -11572,8 +11445,8 @@ fn appendErrorNodeNotes(
1157211445 } else 0;
1157311446 try astgen.compile_errors.append(astgen.gpa, .{
1157411447 .msg = msg,
11575 .node = node,
11576 .token = 0,
11448 .node = node.toOptional(),
11449 .token = .none,
1157711450 .byte_offset = 0,
1157811451 .notes = notes_index,
1157911452 });
......@@ -11664,8 +11537,8 @@ fn appendErrorTokNotesOff(
1166411537 } else 0;
1166511538 try astgen.compile_errors.append(gpa, .{
1166611539 .msg = msg,
11667 .node = 0,
11668 .token = token,
11540 .node = .none,
11541 .token = .fromToken(token),
1166911542 .byte_offset = byte_offset,
1167011543 .notes = notes_index,
1167111544 });
......@@ -11693,8 +11566,8 @@ fn errNoteTokOff(
1169311566 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1169411567 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1169511568 .msg = msg,
11696 .node = 0,
11697 .token = token,
11569 .node = .none,
11570 .token = .fromToken(token),
1169811571 .byte_offset = byte_offset,
1169911572 .notes = 0,
1170011573 });
......@@ -11712,8 +11585,8 @@ fn errNoteNode(
1171211585 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
1171311586 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
1171411587 .msg = msg,
11715 .node = node,
11716 .token = 0,
11588 .node = node.toOptional(),
11589 .token = .none,
1171711590 .byte_offset = 0,
1171811591 .notes = 0,
1171911592 });
......@@ -11779,10 +11652,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1177911652
1178011653fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
1178111654 const tree = astgen.tree;
11782 const node_datas = tree.nodes.items(.data);
1178311655
11784 const start = node_datas[node].lhs;
11785 const end = node_datas[node].rhs;
11656 const start, const end = tree.nodeData(node).token_and_token;
1178611657
1178711658 const gpa = astgen.gpa;
1178811659 const string_bytes = &astgen.string_bytes;
......@@ -11877,11 +11748,11 @@ const Scope = struct {
1187711748 /// Source location of the corresponding variable declaration.
1187811749 token_src: Ast.TokenIndex,
1187911750 /// Track the first identifier where it is referenced.
11880 /// 0 means never referenced.
11881 used: Ast.TokenIndex = 0,
11751 /// .none means never referenced.
11752 used: Ast.OptionalTokenIndex = .none,
1188211753 /// Track the identifier where it is discarded, like this `_ = foo;`.
11883 /// 0 means never discarded.
11884 discarded: Ast.TokenIndex = 0,
11754 /// .none means never discarded.
11755 discarded: Ast.OptionalTokenIndex = .none,
1188511756 is_used_or_discarded: ?*bool = null,
1188611757 /// String table index.
1188711758 name: Zir.NullTerminatedString,
......@@ -11901,11 +11772,11 @@ const Scope = struct {
1190111772 /// Source location of the corresponding variable declaration.
1190211773 token_src: Ast.TokenIndex,
1190311774 /// Track the first identifier where it is referenced.
11904 /// 0 means never referenced.
11905 used: Ast.TokenIndex = 0,
11775 /// .none means never referenced.
11776 used: Ast.OptionalTokenIndex = .none,
1190611777 /// Track the identifier where it is discarded, like this `_ = foo;`.
11907 /// 0 means never discarded.
11908 discarded: Ast.TokenIndex = 0,
11778 /// .none means never discarded.
11779 discarded: Ast.OptionalTokenIndex = .none,
1190911780 /// Whether this value is used as an lvalue after initialization.
1191011781 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.
1191111782 used_as_lvalue: bool = false,
......@@ -12000,12 +11871,12 @@ const GenZir = struct {
1200011871 break_result_info: AstGen.ResultInfo = undefined,
1200111872 continue_result_info: AstGen.ResultInfo = undefined,
1200211873
12003 suspend_node: Ast.Node.Index = 0,
12004 nosuspend_node: Ast.Node.Index = 0,
11874 suspend_node: Ast.Node.OptionalIndex = .none,
11875 nosuspend_node: Ast.Node.OptionalIndex = .none,
1200511876 /// Set if this GenZir is a defer.
12006 cur_defer_node: Ast.Node.Index = 0,
11877 cur_defer_node: Ast.Node.OptionalIndex = .none,
1200711878 // Set if this GenZir is a defer or it is inside a defer.
12008 any_defer_node: Ast.Node.Index = 0,
11879 any_defer_node: Ast.Node.OptionalIndex = .none,
1200911880
1201011881 const unstacked_top = std.math.maxInt(usize);
1201111882 /// Call unstack before adding any new instructions to containing GenZir.
......@@ -12086,12 +11957,12 @@ const GenZir = struct {
1208611957 return false;
1208711958 }
1208811959
12089 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 {
12090 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index));
11960 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset {
11961 return gz.decl_node_index.toOffset(node_index);
1209111962 }
1209211963
12093 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 {
12094 return token - gz.srcToken();
11964 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset {
11965 return .init(gz.srcToken(), token);
1209511966 }
1209611967
1209711968 fn srcToken(gz: GenZir) Ast.TokenIndex {
......@@ -12244,7 +12115,7 @@ const GenZir = struct {
1224412115 proto_hash: std.zig.SrcHash,
1224512116 },
1224612117 ) !Zir.Inst.Ref {
12247 assert(args.src_node != 0);
12118 assert(args.src_node != .root);
1224812119 const astgen = gz.astgen;
1224912120 const gpa = astgen.gpa;
1225012121 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
......@@ -12276,13 +12147,13 @@ const GenZir = struct {
1227612147 var src_locs_and_hash_buffer: [7]u32 = undefined;
1227712148 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {
1227812149 const tree = astgen.tree;
12279 const node_tags = tree.nodes.items(.tag);
12280 const node_datas = tree.nodes.items(.data);
12281 const token_starts = tree.tokens.items(.start);
1228212150 const fn_decl = args.src_node;
12283 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
12284 const block = node_datas[fn_decl].rhs;
12285 const rbrace_start = token_starts[tree.lastToken(block)];
12151 const block = switch (tree.nodeTag(fn_decl)) {
12152 .fn_decl => tree.nodeData(fn_decl).node_and_node[1],
12153 .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1],
12154 else => unreachable,
12155 };
12156 const rbrace_start = tree.tokenStart(tree.lastToken(block));
1228612157 astgen.advanceSourceCursor(rbrace_start);
1228712158 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);
1228812159 const rbrace_column: u32 = @intCast(astgen.source_column);
......@@ -12689,7 +12560,7 @@ const GenZir = struct {
1268912560 .data = .{ .extended = .{
1269012561 .opcode = opcode,
1269112562 .small = small,
12692 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),
12563 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
1269312564 } },
1269412565 });
1269512566 gz.instructions.appendAssumeCapacity(new_index);
......@@ -12878,9 +12749,9 @@ const GenZir = struct {
1287812749 .operand = operand,
1287912750 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{
1288012751 .operand_src_node = if (operand_src_node) |src_node|
12881 gz.nodeIndexToRelative(src_node)
12752 gz.nodeIndexToRelative(src_node).toOptional()
1288212753 else
12883 Zir.Inst.Break.no_src_node,
12754 .none,
1288412755 .block_inst = block_inst,
1288512756 }),
1288612757 } },
......@@ -12969,7 +12840,7 @@ const GenZir = struct {
1296912840 .data = .{ .extended = .{
1297012841 .opcode = opcode,
1297112842 .small = undefined,
12972 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),
12843 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
1297312844 } },
1297412845 });
1297512846 }
......@@ -13149,8 +13020,8 @@ const GenZir = struct {
1314913020 const astgen = gz.astgen;
1315013021 const gpa = astgen.gpa;
1315113022
13152 // Node 0 is valid for the root `struct_decl` of a file!
13153 assert(args.src_node != 0 or gz.parent.tag == .top);
13023 // Node .root is valid for the root `struct_decl` of a file!
13024 assert(args.src_node != .root or gz.parent.tag == .top);
1315413025
1315513026 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1315613027
......@@ -13210,7 +13081,7 @@ const GenZir = struct {
1321013081 const astgen = gz.astgen;
1321113082 const gpa = astgen.gpa;
1321213083
13213 assert(args.src_node != 0);
13084 assert(args.src_node != .root);
1321413085
1321513086 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1321613087
......@@ -13272,7 +13143,7 @@ const GenZir = struct {
1327213143 const astgen = gz.astgen;
1327313144 const gpa = astgen.gpa;
1327413145
13275 assert(args.src_node != 0);
13146 assert(args.src_node != .root);
1327613147
1327713148 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1327813149
......@@ -13327,7 +13198,7 @@ const GenZir = struct {
1332713198 const astgen = gz.astgen;
1332813199 const gpa = astgen.gpa;
1332913200
13330 assert(args.src_node != 0);
13201 assert(args.src_node != .root);
1333113202
1333213203 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);
1333313204 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
......@@ -13521,9 +13392,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
1352113392 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1352213393
1352313394 const tree = gz.astgen.tree;
13524 const token_starts = tree.tokens.items(.start);
13525 const main_tokens = tree.nodes.items(.main_token);
13526 const node_start = token_starts[main_tokens[node]];
13395 const node_start = tree.tokenStart(tree.nodeMainToken(node));
1352713396 gz.astgen.advanceSourceCursor(node_start);
1352813397
1352913398 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
......@@ -13532,8 +13401,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
1353213401/// Advances the source cursor to the beginning of `node`.
1353313402fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
1353413403 const tree = astgen.tree;
13535 const token_starts = tree.tokens.items(.start);
13536 const node_start = token_starts[tree.firstToken(node)];
13404 const node_start = tree.tokenStart(tree.firstToken(node));
1353713405 astgen.advanceSourceCursor(node_start);
1353813406}
1353913407
......@@ -13588,9 +13456,6 @@ fn scanContainer(
1358813456) !u32 {
1358913457 const gpa = astgen.gpa;
1359013458 const tree = astgen.tree;
13591 const node_tags = tree.nodes.items(.tag);
13592 const main_tokens = tree.nodes.items(.main_token);
13593 const token_tags = tree.tokens.items(.tag);
1359413459
1359513460 var any_invalid_declarations = false;
1359613461
......@@ -13620,7 +13485,7 @@ fn scanContainer(
1362013485 var decl_count: u32 = 0;
1362113486 for (members) |member_node| {
1362213487 const Kind = enum { decl, field };
13623 const kind: Kind, const name_token = switch (node_tags[member_node]) {
13488 const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) {
1362413489 .container_field_init,
1362513490 .container_field_align,
1362613491 .container_field,
......@@ -13628,7 +13493,7 @@ fn scanContainer(
1362813493 var full = tree.fullContainerField(member_node).?;
1362913494 switch (container_kind) {
1363013495 .@"struct", .@"opaque" => {},
13631 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes),
13496 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree),
1363213497 }
1363313498 if (full.ast.tuple_like) continue;
1363413499 break :blk .{ .field, full.ast.main_token };
......@@ -13640,7 +13505,7 @@ fn scanContainer(
1364013505 .aligned_var_decl,
1364113506 => blk: {
1364213507 decl_count += 1;
13643 break :blk .{ .decl, main_tokens[member_node] + 1 };
13508 break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 };
1364413509 },
1364513510
1364613511 .fn_proto_simple,
......@@ -13650,8 +13515,8 @@ fn scanContainer(
1365013515 .fn_decl,
1365113516 => blk: {
1365213517 decl_count += 1;
13653 const ident = main_tokens[member_node] + 1;
13654 if (token_tags[ident] != .identifier) {
13518 const ident = tree.nodeMainToken(member_node) + 1;
13519 if (tree.tokenTag(ident) != .identifier) {
1365513520 try astgen.appendErrorNode(member_node, "missing function name", .{});
1365613521 any_invalid_declarations = true;
1365713522 continue;
......@@ -13668,12 +13533,12 @@ fn scanContainer(
1366813533 decl_count += 1;
1366913534 // We don't want shadowing detection here, and test names work a bit differently, so
1367013535 // we must do the redeclaration detection ourselves.
13671 const test_name_token = main_tokens[member_node] + 1;
13536 const test_name_token = tree.nodeMainToken(member_node) + 1;
1367213537 const new_ent: NameEntry = .{
1367313538 .tok = test_name_token,
1367413539 .next = null,
1367513540 };
13676 switch (token_tags[test_name_token]) {
13541 switch (tree.tokenTag(test_name_token)) {
1367713542 else => {}, // unnamed test
1367813543 .string_literal => {
1367913544 const name = try astgen.strLitAsString(test_name_token);
......@@ -14275,3 +14140,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !
1427514140 }
1427614141 return refs.items;
1427714142}
14143
14144test {
14145 _ = &generate;
14146}
lib/std/zig/AstRlAnnotate.zig+159-142
......@@ -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
......@@ -338,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
338347 for (full.ast.params) |param_node| {
339348 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
340349 }
341 return switch (node_tags[node]) {
350 return switch (tree.nodeTag(node)) {
342351 .call_one,
343352 .call_one_comma,
344353 .call,
......@@ -354,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
354363 },
355364
356365 .@"return" => {
357 if (node_datas[node].lhs != 0) {
358 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);
359368 if (ret_val_consumes_rl) {
360369 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
361370 }
......@@ -364,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
364373 },
365374
366375 .field_access => {
367 _ = 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);
368378 return false;
369379 },
370380
......@@ -376,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
376386 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
377387 }
378388
379 if (full.ast.else_expr == 0) {
380 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
381 return false;
382 } else {
389 if (full.ast.else_expr.unwrap()) |else_expr| {
383390 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);
384 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);
385392 const uses_rl = then_uses_rl or else_uses_rl;
386393 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
387394 return uses_rl;
395 } else {
396 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
397 return false;
388398 }
389399 },
390400
......@@ -405,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
405415 .ri = ri,
406416 .consumes_res_ptr = false,
407417 };
408 if (full.ast.cont_expr != 0) {
409 _ = 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);
410420 }
411421 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
412 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
413 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);
414424 } else false;
415425 if (new_block.consumes_res_ptr or else_consumes_rl) {
416426 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
......@@ -426,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
426436 break :label try astrl.identString(label_token);
427437 } else null;
428438 for (full.ast.inputs) |input| {
429 if (node_tags[input] == .for_range) {
430 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);
431 if (node_datas[input].rhs != 0) {
432 _ = 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);
433444 }
434445 } else {
435446 _ = try astrl.expr(input, block, ResultInfo.none);
......@@ -443,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
443454 .consumes_res_ptr = false,
444455 };
445456 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
446 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {
447 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);
448459 } else false;
449460 if (new_block.consumes_res_ptr or else_consumes_rl) {
450461 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
......@@ -455,45 +466,49 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
455466 },
456467
457468 .slice_open => {
458 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
459 _ = 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);
460472 return false;
461473 },
462474 .slice => {
463 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
464 _ = 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);
465478 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
466479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
467480 return false;
468481 },
469482 .slice_sentinel => {
470 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
471 _ = 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);
472486 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
473 if (extra.end != 0) {
474 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
487 if (extra.end.unwrap()) |end| {
488 _ = try astrl.expr(end, block, ResultInfo.type_only);
475489 }
476490 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
477491 return false;
478492 },
479493 .deref => {
480 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
494 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
481495 return false;
482496 },
483497 .address_of => {
484 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
498 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
485499 return false;
486500 },
487501 .optional_type => {
488 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
502 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
489503 return false;
490504 },
491 .grouped_expression,
492505 .@"try",
493506 .@"await",
494507 .@"nosuspend",
508 => return astrl.expr(tree.nodeData(node).node, block, ri),
509 .grouped_expression,
495510 .unwrap_optional,
496 => return astrl.expr(node_datas[node].lhs, block, ri),
511 => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri),
497512
498513 .block_two,
499514 .block_two_semicolon,
......@@ -505,12 +520,14 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
505520 return astrl.blockExpr(block, ri, node, statements);
506521 },
507522 .anyframe_type => {
508 _ = 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);
509525 return false;
510526 },
511527 .@"catch", .@"orelse" => {
512 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
513 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);
514531 if (rhs_consumes_rl) {
515532 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
516533 }
......@@ -524,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
524541 => {
525542 const full = tree.fullPtrType(node).?;
526543 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
527 if (full.ast.sentinel != 0) {
528 _ = 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);
529546 }
530 if (full.ast.addrspace_node != 0) {
531 _ = 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);
532549 }
533 if (full.ast.align_node != 0) {
534 _ = 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);
535552 }
536 if (full.ast.bit_range_start != 0) {
537 assert(full.ast.bit_range_end != 0);
538 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);
539 _ = 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);
540557 }
541558 return false;
542559 },
......@@ -560,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
560577 },
561578
562579 .@"break" => {
563 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 {
564582 // Breaks with void are not interesting
565583 return false;
566 }
584 };
567585
568586 var opt_cur_block = block;
569 if (node_datas[node].lhs == 0) {
570 // No label - we're breaking from a loop.
587 if (opt_label.unwrap()) |label_token| {
588 const break_label = try astrl.identString(label_token);
571589 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
572 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;
573592 }
574593 } else {
575 const break_label = try astrl.identString(node_datas[node].lhs);
594 // No label - we're breaking from a loop.
576595 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
577 const block_label = cur_block.label orelse continue;
578 if (std.mem.eql(u8, block_label, break_label)) break;
596 if (cur_block.is_loop) break;
579597 }
580598 }
581599
582600 if (opt_cur_block) |target_block| {
583 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);
584602 if (consumes_break_rl) target_block.consumes_res_ptr = true;
585603 } else {
586604 // No corresponding scope to break from - AstGen will emit an error.
587 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);
605 _ = try astrl.expr(rhs, block, ResultInfo.none);
588606 }
589607
590608 return false;
591609 },
592610
593611 .array_type => {
594 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);
595 _ = 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);
596615 return false;
597616 },
598617 .array_type_sentinel => {
599 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);
600 _ = 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);
601621 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
602622 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
603623 return false;
604624 },
605625 .array_access => {
606 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
607 _ = 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);
608629 return false;
609630 },
610631 .@"comptime" => {
611632 // AstGen will emit an error if the scope is already comptime, so we can assume it is
612633 // not. This means the result location is not forwarded.
613 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
634 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
614635 return false;
615636 },
616637 .@"switch", .switch_comma => {
617 const operand_node = node_datas[node].lhs;
618 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange);
619 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);
620640
621641 _ = try astrl.expr(operand_node, block, ResultInfo.none);
622642
......@@ -624,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
624644 for (case_nodes) |case_node| {
625645 const case = tree.fullSwitchCase(case_node).?;
626646 for (case.ast.values) |item_node| {
627 if (node_tags[item_node] == .switch_range) {
628 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);
629 _ = 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);
630651 } else {
631652 _ = try astrl.expr(item_node, block, ResultInfo.none);
632653 }
......@@ -641,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
641662 return any_prong_consumed_rl;
642663 },
643664 .@"suspend" => {
644 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
665 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
645666 return false;
646667 },
647668 .@"resume" => {
648 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);
669 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
649670 return false;
650671 },
651672
......@@ -661,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
661682 var buf: [2]Ast.Node.Index = undefined;
662683 const full = tree.fullArrayInit(&buf, node).?;
663684
664 if (full.ast.type_expr != 0) {
685 if (full.ast.type_expr.unwrap()) |type_expr| {
665686 // Explicitly typed init does not participate in RLS
666 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
687 _ = try astrl.expr(type_expr, block, ResultInfo.none);
667688 for (full.ast.elements) |elem_init| {
668689 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
669690 }
......@@ -698,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
698719 var buf: [2]Ast.Node.Index = undefined;
699720 const full = tree.fullStructInit(&buf, node).?;
700721
701 if (full.ast.type_expr != 0) {
722 if (full.ast.type_expr.unwrap()) |type_expr| {
702723 // Explicitly typed init does not participate in RLS
703 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);
724 _ = try astrl.expr(type_expr, block, ResultInfo.none);
704725 for (full.ast.fields) |field_init| {
705726 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
706727 }
......@@ -728,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
728749 .fn_proto_one,
729750 .fn_proto,
730751 .fn_decl,
731 => {
752 => |tag| {
732753 var buf: [1]Ast.Node.Index = undefined;
733754 const full = tree.fullFnProto(&buf, node).?;
734 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;
735756 {
736757 var it = full.iterate(tree);
737758 while (it.next()) |param| {
738759 if (param.anytype_ellipsis3 == null) {
739 _ = 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);
740762 }
741763 }
742764 }
743 if (full.ast.align_expr != 0) {
744 _ = 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);
745767 }
746 if (full.ast.addrspace_expr != 0) {
747 _ = 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);
748770 }
749 if (full.ast.section_expr != 0) {
750 _ = 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);
751773 }
752 if (full.ast.callconv_expr != 0) {
753 _ = 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);
754776 }
755 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);
756 if (body_node != 0) {
757 _ = 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);
758781 }
759782 return false;
760783 },
......@@ -763,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
763786
764787fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
765788 const tree = astrl.tree;
766 const token_tags = tree.tokens.items(.tag);
767 assert(token_tags[token] == .identifier);
789 assert(tree.tokenTag(token) == .identifier);
768790 const ident_name = tree.tokenSlice(token);
769791 if (!std.mem.startsWith(u8, ident_name, "@")) {
770792 return ident_name;
......@@ -777,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
777799
778800fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {
779801 const tree = astrl.tree;
780 const token_tags = tree.tokens.items(.tag);
781 const main_tokens = tree.nodes.items(.main_token);
782802
783 const lbrace = main_tokens[node];
784 if (token_tags[lbrace - 1] == .colon and
785 token_tags[lbrace - 2] == .identifier)
786 {
803 const lbrace = tree.nodeMainToken(node);
804 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
787805 // Labeled block
788806 var new_block: Block = .{
789807 .parent = parent_block,
......@@ -812,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
812830 _ = ri; // Currently, no builtin consumes its result location.
813831
814832 const tree = astrl.tree;
815 const main_tokens = tree.nodes.items(.main_token);
816 const builtin_token = main_tokens[node];
833 const builtin_token = tree.nodeMainToken(node);
817834 const builtin_name = tree.tokenSlice(builtin_token);
818835 const info = BuiltinFn.list.get(builtin_name) orelse return false;
819836 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+1070-1327
......@@ -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,
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 } },
453474 .trailing = trailing,
454 },
455 1 => return Members{
456 .len = 1,
457 .lhs = items[0],
458 .rhs = 0,
459 .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(.{
2423 if (params.len <= 1) {
2424 return try p.addNode(.{
25292425 .tag = if (comma) .async_call_one_comma else .async_call_one,
25302426 .main_token = lparen,
2531 .data = .{
2532 .lhs = res,
2533 .rhs = 0,
2534 },
2535 }),
2536 1 => return p.addNode(.{
2537 .tag = if (comma) .async_call_one_comma else .async_call_one,
2538 .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,153 +2530,126 @@ 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(.{
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 => return try p.addNode(.{
27952651 .tag = .enum_literal,
2796 .data = .{
2797 .lhs = p.nextToken(), // dot
2798 .rhs = undefined,
2799 },
2652 .data = .{ .token = p.nextToken() }, // dot
28002653 .main_token = p.nextToken(), // identifier
28012654 }),
28022655 .l_brace => {
......@@ -2808,11 +2661,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28082661
28092662 const scratch_top = p.scratch.items.len;
28102663 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2811 const field_init = try p.parseFieldInit();
2812 if (field_init != 0) {
2664 const opt_field_init = try p.parseFieldInit();
2665 if (opt_field_init) |field_init| {
28132666 try p.scratch.append(p.gpa, field_init);
28142667 while (true) {
2815 switch (p.token_tags[p.tok_i]) {
2668 switch (p.tokenTag(p.tok_i)) {
28162669 .comma => p.tok_i += 1,
28172670 .r_brace => {
28182671 p.tok_i += 1;
......@@ -2826,37 +2679,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28262679 const next = try p.expectFieldInit();
28272680 try p.scratch.append(p.gpa, next);
28282681 }
2829 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2682 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
28302683 const inits = p.scratch.items[scratch_top..];
2831 switch (inits.len) {
2832 0 => unreachable,
2833 1 => return p.addNode(.{
2684 std.debug.assert(inits.len != 0);
2685 if (inits.len <= 2) {
2686 return try p.addNode(.{
28342687 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
28352688 .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,
2689 .data = .{ .opt_node_and_opt_node = .{
2690 if (inits.len >= 1) .fromOptional(inits[0]) else .none,
2691 if (inits.len >= 2) .fromOptional(inits[1]) else .none,
2692 } },
2693 });
2694 } else {
2695 return try p.addNode(.{
2696 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
28432697 .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 },
2698 .data = .{ .extra_range = try p.listToSpan(inits) },
2699 });
28602700 }
28612701 }
28622702
......@@ -2864,7 +2704,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28642704 if (p.eatToken(.r_brace)) |_| break;
28652705 const elem_init = try p.expectExpr();
28662706 try p.scratch.append(p.gpa, elem_init);
2867 switch (p.token_tags[p.tok_i]) {
2707 switch (p.tokenTag(p.tok_i)) {
28682708 .comma => p.tok_i += 1,
28692709 .r_brace => {
28702710 p.tok_i += 1;
......@@ -2875,49 +2715,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28752715 else => try p.warn(.expected_comma_after_initializer),
28762716 }
28772717 }
2878 const comma = (p.token_tags[p.tok_i - 2] == .comma);
2718 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
28792719 const inits = p.scratch.items[scratch_top..];
2880 switch (inits.len) {
2881 0 => return p.addNode(.{
2882 .tag = .struct_init_dot_two,
2883 .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,
2720 if (inits.len <= 2) {
2721 return try p.addNode(.{
2722 .tag = if (inits.len == 0)
2723 .struct_init_dot_two
2724 else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
28912725 .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,
2726 .data = .{ .opt_node_and_opt_node = .{
2727 if (inits.len >= 1) inits[0].toOptional() else .none,
2728 if (inits.len >= 2) inits[1].toOptional() else .none,
2729 } },
2730 });
2731 } else {
2732 return try p.addNode(.{
2733 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
28992734 .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 },
2735 .data = .{ .extra_range = try p.listToSpan(inits) },
2736 });
29162737 }
29172738 },
2918 else => return null_node,
2739 else => return null,
29192740 },
2920 .keyword_error => switch (p.token_tags[p.tok_i + 1]) {
2741 .keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
29212742 .l_brace => {
29222743 const error_token = p.tok_i;
29232744 p.tok_i += 2;
......@@ -2925,7 +2746,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29252746 if (p.eatToken(.r_brace)) |_| break;
29262747 _ = try p.eatDocComments();
29272748 _ = try p.expectToken(.identifier);
2928 switch (p.token_tags[p.tok_i]) {
2749 switch (p.tokenTag(p.tok_i)) {
29292750 .comma => p.tok_i += 1,
29302751 .r_brace => {
29312752 p.tok_i += 1;
......@@ -2936,13 +2757,10 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29362757 else => try p.warn(.expected_comma_after_field),
29372758 }
29382759 }
2939 return p.addNode(.{
2760 return try p.addNode(.{
29402761 .tag = .error_set_decl,
29412762 .main_token = error_token,
2942 .data = .{
2943 .lhs = undefined,
2944 .rhs = p.tok_i - 1, // rbrace
2945 },
2763 .data = .{ .token = p.tok_i - 1 }, // rbrace
29462764 });
29472765 },
29482766 else => {
......@@ -2951,41 +2769,37 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
29512769 if (period == null) try p.warnExpected(.period);
29522770 const identifier = p.eatToken(.identifier);
29532771 if (identifier == null) try p.warnExpected(.identifier);
2954 return p.addNode(.{
2772 return try p.addNode(.{
29552773 .tag = .error_value,
29562774 .main_token = main_token,
2957 .data = .{
2958 .lhs = period orelse 0,
2959 .rhs = identifier orelse 0,
2960 },
2775 .data = .{ .opt_token_and_opt_token = .{
2776 .fromOptional(period),
2777 .fromOptional(identifier),
2778 } },
29612779 });
29622780 },
29632781 },
2964 .l_paren => return p.addNode(.{
2782 .l_paren => return try p.addNode(.{
29652783 .tag = .grouped_expression,
29662784 .main_token = p.nextToken(),
2967 .data = .{
2968 .lhs = try p.expectExpr(),
2969 .rhs = try p.expectToken(.r_paren),
2970 },
2785 .data = .{ .node_and_token = .{
2786 try p.expectExpr(),
2787 try p.expectToken(.r_paren),
2788 } },
29712789 }),
2972 else => return null_node,
2790 else => return null,
29732791 }
29742792}
29752793
29762794fn 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;
2795 return try p.parsePrimaryTypeExpr() orelse return p.fail(.expected_primary_type_expr);
29822796}
29832797
29842798/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
29852799///
29862800/// 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;
2801fn parseWhileTypeExpr(p: *Parse) !?Node.Index {
2802 const while_token = p.eatToken(.keyword_while) orelse return null;
29892803 _ = try p.expectToken(.l_paren);
29902804 const condition = try p.expectExpr();
29912805 _ = try p.expectToken(.r_paren);
......@@ -2994,54 +2808,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {
29942808
29952809 const then_expr = try p.expectTypeExpr();
29962810 _ = p.eatToken(.keyword_else) orelse {
2997 if (cont_expr == 0) {
2998 return p.addNode(.{
2811 if (cont_expr == null) {
2812 return try p.addNode(.{
29992813 .tag = .while_simple,
30002814 .main_token = while_token,
3001 .data = .{
3002 .lhs = condition,
3003 .rhs = then_expr,
3004 },
2815 .data = .{ .node_and_node = .{
2816 condition,
2817 then_expr,
2818 } },
30052819 });
30062820 } else {
3007 return p.addNode(.{
2821 return try p.addNode(.{
30082822 .tag = .while_cont,
30092823 .main_token = while_token,
3010 .data = .{
3011 .lhs = condition,
3012 .rhs = try p.addExtra(Node.WhileCont{
3013 .cont_expr = cont_expr,
2824 .data = .{ .node_and_extra = .{
2825 condition, try p.addExtra(Node.WhileCont{
2826 .cont_expr = cont_expr.?,
30142827 .then_expr = then_expr,
30152828 }),
3016 },
2829 } },
30172830 });
30182831 }
30192832 };
30202833 _ = try p.parsePayload();
30212834 const else_expr = try p.expectTypeExpr();
3022 return p.addNode(.{
2835 return try p.addNode(.{
30232836 .tag = .@"while",
30242837 .main_token = while_token,
3025 .data = .{
3026 .lhs = condition,
3027 .rhs = try p.addExtra(Node.While{
3028 .cont_expr = cont_expr,
2838 .data = .{ .node_and_extra = .{
2839 condition, try p.addExtra(Node.While{
2840 .cont_expr = .fromOptional(cont_expr),
30292841 .then_expr = then_expr,
30302842 .else_expr = else_expr,
30312843 }),
3032 },
2844 } },
30332845 });
30342846}
30352847
30362848/// 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);
2849fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index {
2850 const switch_token = p.eatToken(.keyword_switch) orelse return null;
2851 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
30402852}
30412853
30422854fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {
30432855 const switch_token = p.assertToken(.keyword_switch);
3044 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
2856 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
30452857}
30462858
30472859fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
......@@ -3050,19 +2862,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
30502862 _ = try p.expectToken(.r_paren);
30512863 _ = try p.expectToken(.l_brace);
30522864 const cases = try p.parseSwitchProngList();
3053 const trailing_comma = p.token_tags[p.tok_i - 1] == .comma;
2865 const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma;
30542866 _ = try p.expectToken(.r_brace);
30552867
30562868 return p.addNode(.{
30572869 .tag = if (trailing_comma) .switch_comma else .@"switch",
30582870 .main_token = main_token,
3059 .data = .{
3060 .lhs = expr_node,
3061 .rhs = try p.addExtra(Node.SubRange{
2871 .data = .{ .node_and_extra = .{
2872 expr_node,
2873 try p.addExtra(Node.SubRange{
30622874 .start = cases.start,
30632875 .end = cases.end,
30642876 }),
3065 },
2877 } },
30662878 });
30672879}
30682880
......@@ -3089,10 +2901,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
30892901 return p.addNode(.{
30902902 .tag = .asm_simple,
30912903 .main_token = asm_token,
3092 .data = .{
3093 .lhs = template,
3094 .rhs = rparen,
3095 },
2904 .data = .{ .node_and_token = .{
2905 template,
2906 rparen,
2907 } },
30962908 });
30972909 }
30982910
......@@ -3102,10 +2914,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31022914 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31032915
31042916 while (true) {
3105 const output_item = try p.parseAsmOutputItem();
3106 if (output_item == 0) break;
2917 const output_item = try p.parseAsmOutputItem() orelse break;
31072918 try p.scratch.append(p.gpa, output_item);
3108 switch (p.token_tags[p.tok_i]) {
2919 switch (p.tokenTag(p.tok_i)) {
31092920 .comma => p.tok_i += 1,
31102921 // All possible delimiters.
31112922 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3115,10 +2926,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31152926 }
31162927 if (p.eatToken(.colon)) |_| {
31172928 while (true) {
3118 const input_item = try p.parseAsmInputItem();
3119 if (input_item == 0) break;
2929 const input_item = try p.parseAsmInputItem() orelse break;
31202930 try p.scratch.append(p.gpa, input_item);
3121 switch (p.token_tags[p.tok_i]) {
2931 switch (p.tokenTag(p.tok_i)) {
31222932 .comma => p.tok_i += 1,
31232933 // All possible delimiters.
31242934 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3128,7 +2938,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31282938 }
31292939 if (p.eatToken(.colon)) |_| {
31302940 while (p.eatToken(.string_literal)) |_| {
3131 switch (p.token_tags[p.tok_i]) {
2941 switch (p.tokenTag(p.tok_i)) {
31322942 .comma => p.tok_i += 1,
31332943 .colon, .r_paren, .r_brace, .r_bracket => break,
31342944 // Likely just a missing comma; give error but continue parsing.
......@@ -3142,121 +2952,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
31422952 return p.addNode(.{
31432953 .tag = .@"asm",
31442954 .main_token = asm_token,
3145 .data = .{
3146 .lhs = template,
3147 .rhs = try p.addExtra(Node.Asm{
2955 .data = .{ .node_and_extra = .{
2956 template,
2957 try p.addExtra(Node.Asm{
31482958 .items_start = span.start,
31492959 .items_end = span.end,
31502960 .rparen = rparen,
31512961 }),
3152 },
2962 } },
31532963 });
31542964}
31552965
31562966/// 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;
2967fn parseAsmOutputItem(p: *Parse) !?Node.Index {
2968 _ = p.eatToken(.l_bracket) orelse return null;
31592969 const identifier = try p.expectToken(.identifier);
31602970 _ = try p.expectToken(.r_bracket);
31612971 _ = try p.expectToken(.string_literal);
31622972 _ = try p.expectToken(.l_paren);
3163 const type_expr: Node.Index = blk: {
2973 const type_expr: Node.OptionalIndex = blk: {
31642974 if (p.eatToken(.arrow)) |_| {
3165 break :blk try p.expectTypeExpr();
2975 break :blk .fromOptional(try p.expectTypeExpr());
31662976 } else {
31672977 _ = try p.expectToken(.identifier);
3168 break :blk null_node;
2978 break :blk .none;
31692979 }
31702980 };
31712981 const rparen = try p.expectToken(.r_paren);
3172 return p.addNode(.{
2982 return try p.addNode(.{
31732983 .tag = .asm_output,
31742984 .main_token = identifier,
3175 .data = .{
3176 .lhs = type_expr,
3177 .rhs = rparen,
3178 },
2985 .data = .{ .opt_node_and_token = .{
2986 type_expr,
2987 rparen,
2988 } },
31792989 });
31802990}
31812991
31822992/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
3183fn parseAsmInputItem(p: *Parse) !Node.Index {
3184 _ = p.eatToken(.l_bracket) orelse return null_node;
2993fn parseAsmInputItem(p: *Parse) !?Node.Index {
2994 _ = p.eatToken(.l_bracket) orelse return null;
31852995 const identifier = try p.expectToken(.identifier);
31862996 _ = try p.expectToken(.r_bracket);
31872997 _ = try p.expectToken(.string_literal);
31882998 _ = try p.expectToken(.l_paren);
31892999 const expr = try p.expectExpr();
31903000 const rparen = try p.expectToken(.r_paren);
3191 return p.addNode(.{
3001 return try p.addNode(.{
31923002 .tag = .asm_input,
31933003 .main_token = identifier,
3194 .data = .{
3195 .lhs = expr,
3196 .rhs = rparen,
3197 },
3004 .data = .{ .node_and_token = .{
3005 expr,
3006 rparen,
3007 } },
31983008 });
31993009}
32003010
32013011/// BreakLabel <- COLON IDENTIFIER
3202fn parseBreakLabel(p: *Parse) !TokenIndex {
3203 _ = p.eatToken(.colon) orelse return null_node;
3204 return p.expectToken(.identifier);
3012fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex {
3013 _ = p.eatToken(.colon) orelse return .none;
3014 const next_token = try p.expectToken(.identifier);
3015 return .fromToken(next_token);
32053016}
32063017
32073018/// 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;
3019fn parseBlockLabel(p: *Parse) ?TokenIndex {
3020 return p.eatTokens(&.{ .identifier, .colon });
32173021}
32183022
32193023/// 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;
3024fn parseFieldInit(p: *Parse) !?Node.Index {
3025 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3026 return try p.expectExpr();
32293027 }
3028 return null;
32303029}
32313030
32323031fn 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();
3032 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3033 return try p.expectExpr();
3034 }
3035 return p.fail(.expected_initializer);
32403036}
32413037
32423038/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
3243fn parseWhileContinueExpr(p: *Parse) !Node.Index {
3039fn parseWhileContinueExpr(p: *Parse) !?Node.Index {
32443040 _ = p.eatToken(.colon) orelse {
3245 if (p.token_tags[p.tok_i] == .l_paren and
3041 if (p.tokenTag(p.tok_i) == .l_paren and
32463042 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
32473043 return p.fail(.expected_continue_expr);
3248 return null_node;
3044 return null;
32493045 };
32503046 _ = try p.expectToken(.l_paren);
3251 const node = try p.parseAssignExpr();
3252 if (node == 0) return p.fail(.expected_expr_or_assignment);
3047 const node = try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
32533048 _ = try p.expectToken(.r_paren);
32543049 return node;
32553050}
32563051
32573052/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
3258fn parseLinkSection(p: *Parse) !Node.Index {
3259 _ = p.eatToken(.keyword_linksection) orelse return null_node;
3053fn parseLinkSection(p: *Parse) !?Node.Index {
3054 _ = p.eatToken(.keyword_linksection) orelse return null;
32603055 _ = try p.expectToken(.l_paren);
32613056 const expr_node = try p.expectExpr();
32623057 _ = try p.expectToken(.r_paren);
......@@ -3264,8 +3059,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {
32643059}
32653060
32663061/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
3267fn parseCallconv(p: *Parse) !Node.Index {
3268 _ = p.eatToken(.keyword_callconv) orelse return null_node;
3062fn parseCallconv(p: *Parse) !?Node.Index {
3063 _ = p.eatToken(.keyword_callconv) orelse return null;
32693064 _ = try p.expectToken(.l_paren);
32703065 const expr_node = try p.expectExpr();
32713066 _ = try p.expectToken(.r_paren);
......@@ -3273,8 +3068,8 @@ fn parseCallconv(p: *Parse) !Node.Index {
32733068}
32743069
32753070/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
3276fn parseAddrSpace(p: *Parse) !Node.Index {
3277 _ = p.eatToken(.keyword_addrspace) orelse return null_node;
3071fn parseAddrSpace(p: *Parse) !?Node.Index {
3072 _ = p.eatToken(.keyword_addrspace) orelse return null;
32783073 _ = try p.expectToken(.l_paren);
32793074 const expr_node = try p.expectExpr();
32803075 _ = try p.expectToken(.r_paren);
......@@ -3292,59 +3087,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {
32923087/// ParamType
32933088/// <- KEYWORD_anytype
32943089/// / TypeExpr
3295fn expectParamDecl(p: *Parse) !Node.Index {
3090fn expectParamDecl(p: *Parse) !?Node.Index {
32963091 _ = try p.eatDocComments();
3297 switch (p.token_tags[p.tok_i]) {
3092 switch (p.tokenTag(p.tok_i)) {
32983093 .keyword_noalias, .keyword_comptime => p.tok_i += 1,
32993094 .ellipsis3 => {
33003095 p.tok_i += 1;
3301 return null_node;
3096 return null;
33023097 },
33033098 else => {},
33043099 }
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(),
3100 _ = p.eatTokens(&.{ .identifier, .colon });
3101 if (p.eatToken(.keyword_anytype)) |_| {
3102 return null;
3103 } else {
3104 return try p.expectTypeExpr();
33163105 }
33173106}
33183107
33193108/// Payload <- PIPE IDENTIFIER PIPE
3320fn parsePayload(p: *Parse) !TokenIndex {
3321 _ = p.eatToken(.pipe) orelse return null_node;
3109fn parsePayload(p: *Parse) Error!OptionalTokenIndex {
3110 _ = p.eatToken(.pipe) orelse return .none;
33223111 const identifier = try p.expectToken(.identifier);
33233112 _ = try p.expectToken(.pipe);
3324 return identifier;
3113 return .fromToken(identifier);
33253114}
33263115
33273116/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
3328fn parsePtrPayload(p: *Parse) !TokenIndex {
3329 _ = p.eatToken(.pipe) orelse return null_node;
3117fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex {
3118 _ = p.eatToken(.pipe) orelse return .none;
33303119 _ = p.eatToken(.asterisk);
33313120 const identifier = try p.expectToken(.identifier);
33323121 _ = try p.expectToken(.pipe);
3333 return identifier;
3122 return .fromToken(identifier);
33343123}
33353124
33363125/// Returns the first identifier token, if any.
33373126///
33383127/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
3339fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
3340 _ = p.eatToken(.pipe) orelse return null_node;
3128fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex {
3129 _ = p.eatToken(.pipe) orelse return .none;
33413130 _ = p.eatToken(.asterisk);
33423131 const identifier = try p.expectToken(.identifier);
33433132 if (p.eatToken(.comma) != null) {
33443133 _ = try p.expectToken(.identifier);
33453134 }
33463135 _ = try p.expectToken(.pipe);
3347 return identifier;
3136 return .fromToken(identifier);
33483137}
33493138
33503139/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
......@@ -3352,7 +3141,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
33523141/// SwitchCase
33533142/// <- SwitchItem (COMMA SwitchItem)* COMMA?
33543143/// / KEYWORD_else
3355fn parseSwitchProng(p: *Parse) !Node.Index {
3144fn parseSwitchProng(p: *Parse) !?Node.Index {
33563145 const scratch_top = p.scratch.items.len;
33573146 defer p.scratch.shrinkRetainingCapacity(scratch_top);
33583147
......@@ -3360,97 +3149,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {
33603149
33613150 if (p.eatToken(.keyword_else) == null) {
33623151 while (true) {
3363 const item = try p.parseSwitchItem();
3364 if (item == 0) break;
3152 const item = try p.parseSwitchItem() orelse break;
33653153 try p.scratch.append(p.gpa, item);
33663154 if (p.eatToken(.comma) == null) break;
33673155 }
33683156 if (scratch_top == p.scratch.items.len) {
33693157 if (is_inline) p.tok_i -= 1;
3370 return null_node;
3158 return null;
33713159 }
33723160 }
33733161 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
33743162 _ = try p.parsePtrIndexPayload();
33753163
33763164 const items = p.scratch.items[scratch_top..];
3377 switch (items.len) {
3378 0 => return p.addNode(.{
3165 if (items.len <= 1) {
3166 return try p.addNode(.{
33793167 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
33803168 .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(.{
3169 .data = .{ .opt_node_and_node = .{
3170 if (items.len >= 1) items[0].toOptional() else .none,
3171 try p.expectSingleAssignExpr(),
3172 } },
3173 });
3174 } else {
3175 return try p.addNode(.{
33953176 .tag = if (is_inline) .switch_case_inline else .switch_case,
33963177 .main_token = arrow_token,
3397 .data = .{
3398 .lhs = try p.addExtra(try p.listToSpan(items)),
3399 .rhs = try p.expectSingleAssignExpr(),
3400 },
3401 }),
3178 .data = .{ .extra_and_node = .{
3179 try p.addExtra(try p.listToSpan(items)),
3180 try p.expectSingleAssignExpr(),
3181 } },
3182 });
34023183 }
34033184}
34043185
34053186/// SwitchItem <- Expr (DOT3 Expr)?
3406fn parseSwitchItem(p: *Parse) !Node.Index {
3407 const expr = try p.parseExpr();
3408 if (expr == 0) return null_node;
3187fn parseSwitchItem(p: *Parse) !?Node.Index {
3188 const expr = try p.parseExpr() orelse return null;
34093189
34103190 if (p.eatToken(.ellipsis3)) |token| {
3411 return p.addNode(.{
3191 return try p.addNode(.{
34123192 .tag = .switch_range,
34133193 .main_token = token,
3414 .data = .{
3415 .lhs = expr,
3416 .rhs = try p.expectExpr(),
3417 },
3194 .data = .{ .node_and_node = .{
3195 expr,
3196 try p.expectExpr(),
3197 } },
34183198 });
34193199 }
34203200 return expr;
34213201}
34223202
3203/// The following invariant will hold:
3204/// - `(bit_range_start == .none) == (bit_range_end == .none)`
3205/// - `bit_range_start != .none` implies `align_node != .none`
3206/// - `bit_range_end != .none` implies `align_node != .none`
34233207const PtrModifiers = struct {
3424 align_node: Node.Index,
3425 addrspace_node: Node.Index,
3426 bit_range_start: Node.Index,
3427 bit_range_end: Node.Index,
3208 align_node: Node.OptionalIndex,
3209 addrspace_node: Node.OptionalIndex,
3210 bit_range_start: Node.OptionalIndex,
3211 bit_range_end: Node.OptionalIndex,
34283212};
34293213
34303214fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34313215 var result: PtrModifiers = .{
3432 .align_node = 0,
3433 .addrspace_node = 0,
3434 .bit_range_start = 0,
3435 .bit_range_end = 0,
3216 .align_node = .none,
3217 .addrspace_node = .none,
3218 .bit_range_start = .none,
3219 .bit_range_end = .none,
34363220 };
34373221 var saw_const = false;
34383222 var saw_volatile = false;
34393223 var saw_allowzero = false;
34403224 while (true) {
3441 switch (p.token_tags[p.tok_i]) {
3225 switch (p.tokenTag(p.tok_i)) {
34423226 .keyword_align => {
3443 if (result.align_node != 0) {
3227 if (result.align_node != .none) {
34443228 try p.warn(.extra_align_qualifier);
34453229 }
34463230 p.tok_i += 1;
34473231 _ = try p.expectToken(.l_paren);
3448 result.align_node = try p.expectExpr();
3232 result.align_node = (try p.expectExpr()).toOptional();
34493233
34503234 if (p.eatToken(.colon)) |_| {
3451 result.bit_range_start = try p.expectExpr();
3235 result.bit_range_start = (try p.expectExpr()).toOptional();
34523236 _ = try p.expectToken(.colon);
3453 result.bit_range_end = try p.expectExpr();
3237 result.bit_range_end = (try p.expectExpr()).toOptional();
34543238 }
34553239
34563240 _ = try p.expectToken(.r_paren);
......@@ -3477,10 +3261,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34773261 saw_allowzero = true;
34783262 },
34793263 .keyword_addrspace => {
3480 if (result.addrspace_node != 0) {
3264 if (result.addrspace_node != .none) {
34813265 try p.warn(.extra_addrspace_qualifier);
34823266 }
3483 result.addrspace_node = try p.parseAddrSpace();
3267 result.addrspace_node = .fromOptional(try p.parseAddrSpace());
34843268 },
34853269 else => return result,
34863270 }
......@@ -3492,110 +3276,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
34923276/// / DOT IDENTIFIER
34933277/// / DOTASTERISK
34943278/// / DOTQUESTIONMARK
3495fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
3496 switch (p.token_tags[p.tok_i]) {
3279fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
3280 switch (p.tokenTag(p.tok_i)) {
34973281 .l_bracket => {
34983282 const lbracket = p.nextToken();
34993283 const index_expr = try p.expectExpr();
35003284
35013285 if (p.eatToken(.ellipsis2)) |_| {
3502 const end_expr = try p.parseExpr();
3286 const opt_end_expr = try p.parseExpr();
35033287 if (p.eatToken(.colon)) |_| {
35043288 const sentinel = try p.expectExpr();
35053289 _ = try p.expectToken(.r_bracket);
3506 return p.addNode(.{
3290 return try p.addNode(.{
35073291 .tag = .slice_sentinel,
35083292 .main_token = lbracket,
3509 .data = .{
3510 .lhs = lhs,
3511 .rhs = try p.addExtra(Node.SliceSentinel{
3293 .data = .{ .node_and_extra = .{
3294 lhs, try p.addExtra(Node.SliceSentinel{
35123295 .start = index_expr,
3513 .end = end_expr,
3296 .end = .fromOptional(opt_end_expr),
35143297 .sentinel = sentinel,
35153298 }),
3516 },
3299 } },
35173300 });
35183301 }
35193302 _ = try p.expectToken(.r_bracket);
3520 if (end_expr == 0) {
3521 return p.addNode(.{
3303 const end_expr = opt_end_expr orelse {
3304 return try p.addNode(.{
35223305 .tag = .slice_open,
35233306 .main_token = lbracket,
3524 .data = .{
3525 .lhs = lhs,
3526 .rhs = index_expr,
3527 },
3307 .data = .{ .node_and_node = .{
3308 lhs,
3309 index_expr,
3310 } },
35283311 });
3529 }
3530 return p.addNode(.{
3312 };
3313 return try p.addNode(.{
35313314 .tag = .slice,
35323315 .main_token = lbracket,
3533 .data = .{
3534 .lhs = lhs,
3535 .rhs = try p.addExtra(Node.Slice{
3316 .data = .{ .node_and_extra = .{
3317 lhs, try p.addExtra(Node.Slice{
35363318 .start = index_expr,
35373319 .end = end_expr,
35383320 }),
3539 },
3321 } },
35403322 });
35413323 }
35423324 _ = try p.expectToken(.r_bracket);
3543 return p.addNode(.{
3325 return try p.addNode(.{
35443326 .tag = .array_access,
35453327 .main_token = lbracket,
3546 .data = .{
3547 .lhs = lhs,
3548 .rhs = index_expr,
3549 },
3328 .data = .{ .node_and_node = .{
3329 lhs,
3330 index_expr,
3331 } },
35503332 });
35513333 },
3552 .period_asterisk => return p.addNode(.{
3334 .period_asterisk => return try p.addNode(.{
35533335 .tag = .deref,
35543336 .main_token = p.nextToken(),
3555 .data = .{
3556 .lhs = lhs,
3557 .rhs = undefined,
3558 },
3337 .data = .{ .node = lhs },
35593338 }),
35603339 .invalid_periodasterisks => {
35613340 try p.warn(.asterisk_after_ptr_deref);
3562 return p.addNode(.{
3341 return try p.addNode(.{
35633342 .tag = .deref,
35643343 .main_token = p.nextToken(),
3565 .data = .{
3566 .lhs = lhs,
3567 .rhs = undefined,
3568 },
3344 .data = .{ .node = lhs },
35693345 });
35703346 },
3571 .period => switch (p.token_tags[p.tok_i + 1]) {
3572 .identifier => return p.addNode(.{
3347 .period => switch (p.tokenTag(p.tok_i + 1)) {
3348 .identifier => return try p.addNode(.{
35733349 .tag = .field_access,
35743350 .main_token = p.nextToken(),
3575 .data = .{
3576 .lhs = lhs,
3577 .rhs = p.nextToken(),
3578 },
3351 .data = .{ .node_and_token = .{
3352 lhs,
3353 p.nextToken(),
3354 } },
35793355 }),
3580 .question_mark => return p.addNode(.{
3356 .question_mark => return try p.addNode(.{
35813357 .tag = .unwrap_optional,
35823358 .main_token = p.nextToken(),
3583 .data = .{
3584 .lhs = lhs,
3585 .rhs = p.nextToken(),
3586 },
3359 .data = .{ .node_and_token = .{
3360 lhs,
3361 p.nextToken(),
3362 } },
35873363 }),
35883364 .l_brace => {
35893365 // this a misplaced `.{`, handle the error somewhere else
3590 return null_node;
3366 return null;
35913367 },
35923368 else => {
35933369 p.tok_i += 1;
35943370 try p.warn(.expected_suffix_op);
3595 return null_node;
3371 return null;
35963372 },
35973373 },
3598 else => return null_node,
3374 else => return null,
35993375 }
36003376}
36013377
......@@ -3608,17 +3384,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
36083384/// / KEYWORD_opaque
36093385/// / KEYWORD_enum (LPAREN Expr RPAREN)?
36103386/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
3611fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3387fn parseContainerDeclAuto(p: *Parse) !?Node.Index {
36123388 const main_token = p.nextToken();
3613 const arg_expr = switch (p.token_tags[main_token]) {
3614 .keyword_opaque => null_node,
3389 const arg_expr = switch (p.tokenTag(main_token)) {
3390 .keyword_opaque => null,
36153391 .keyword_struct, .keyword_enum => blk: {
36163392 if (p.eatToken(.l_paren)) |_| {
36173393 const expr = try p.expectExpr();
36183394 _ = try p.expectToken(.r_paren);
36193395 break :blk expr;
36203396 } else {
3621 break :blk null_node;
3397 break :blk null;
36223398 }
36233399 },
36243400 .keyword_union => blk: {
......@@ -3633,16 +3409,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36333409 const members = try p.parseContainerMembers();
36343410 const members_span = try members.toSpan(p);
36353411 _ = try p.expectToken(.r_brace);
3636 return p.addNode(.{
3412 return try p.addNode(.{
36373413 .tag = switch (members.trailing) {
36383414 true => .tagged_union_enum_tag_trailing,
36393415 false => .tagged_union_enum_tag,
36403416 },
36413417 .main_token = main_token,
3642 .data = .{
3643 .lhs = enum_tag_expr,
3644 .rhs = try p.addExtra(members_span),
3645 },
3418 .data = .{ .node_and_extra = .{
3419 enum_tag_expr,
3420 try p.addExtra(members_span),
3421 } },
36463422 });
36473423 } else {
36483424 _ = try p.expectToken(.r_paren);
......@@ -3651,29 +3427,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36513427 const members = try p.parseContainerMembers();
36523428 _ = try p.expectToken(.r_brace);
36533429 if (members.len <= 2) {
3654 return p.addNode(.{
3430 return try p.addNode(.{
36553431 .tag = switch (members.trailing) {
36563432 true => .tagged_union_two_trailing,
36573433 false => .tagged_union_two,
36583434 },
36593435 .main_token = main_token,
3660 .data = .{
3661 .lhs = members.lhs,
3662 .rhs = members.rhs,
3663 },
3436 .data = members.data,
36643437 });
36653438 } else {
36663439 const span = try members.toSpan(p);
3667 return p.addNode(.{
3440 return try p.addNode(.{
36683441 .tag = switch (members.trailing) {
36693442 true => .tagged_union_trailing,
36703443 false => .tagged_union,
36713444 },
36723445 .main_token = main_token,
3673 .data = .{
3674 .lhs = span.start,
3675 .rhs = span.end,
3676 },
3446 .data = .{ .extra_range = span },
36773447 });
36783448 }
36793449 }
......@@ -3683,7 +3453,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36833453 break :blk expr;
36843454 }
36853455 } else {
3686 break :blk null_node;
3456 break :blk null;
36873457 }
36883458 },
36893459 else => {
......@@ -3694,48 +3464,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
36943464 _ = try p.expectToken(.l_brace);
36953465 const members = try p.parseContainerMembers();
36963466 _ = try p.expectToken(.r_brace);
3697 if (arg_expr == 0) {
3467 if (arg_expr == null) {
36983468 if (members.len <= 2) {
3699 return p.addNode(.{
3469 return try p.addNode(.{
37003470 .tag = switch (members.trailing) {
37013471 true => .container_decl_two_trailing,
37023472 false => .container_decl_two,
37033473 },
37043474 .main_token = main_token,
3705 .data = .{
3706 .lhs = members.lhs,
3707 .rhs = members.rhs,
3708 },
3475 .data = members.data,
37093476 });
37103477 } else {
37113478 const span = try members.toSpan(p);
3712 return p.addNode(.{
3479 return try p.addNode(.{
37133480 .tag = switch (members.trailing) {
37143481 true => .container_decl_trailing,
37153482 false => .container_decl,
37163483 },
37173484 .main_token = main_token,
3718 .data = .{
3719 .lhs = span.start,
3720 .rhs = span.end,
3721 },
3485 .data = .{ .extra_range = span },
37223486 });
37233487 }
37243488 } else {
37253489 const span = try members.toSpan(p);
3726 return p.addNode(.{
3490 return try p.addNode(.{
37273491 .tag = switch (members.trailing) {
37283492 true => .container_decl_arg_trailing,
37293493 false => .container_decl_arg,
37303494 },
37313495 .main_token = main_token,
3732 .data = .{
3733 .lhs = arg_expr,
3734 .rhs = try p.addExtra(Node.SubRange{
3496 .data = .{ .node_and_extra = .{
3497 arg_expr.?,
3498 try p.addExtra(Node.SubRange{
37353499 .start = span.start,
37363500 .end = span.end,
37373501 }),
3738 },
3502 } },
37393503 });
37403504 }
37413505}
......@@ -3744,24 +3508,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
37443508/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.
37453509fn parseCStyleContainer(p: *Parse) Error!bool {
37463510 const main_token = p.tok_i;
3747 switch (p.token_tags[p.tok_i]) {
3511 switch (p.tokenTag(p.tok_i)) {
37483512 .keyword_enum, .keyword_union, .keyword_struct => {},
37493513 else => return false,
37503514 }
37513515 const identifier = p.tok_i + 1;
3752 if (p.token_tags[identifier] != .identifier) return false;
3516 if (p.tokenTag(identifier) != .identifier) return false;
37533517 p.tok_i += 2;
37543518
37553519 try p.warnMsg(.{
37563520 .tag = .c_style_container,
37573521 .token = identifier,
3758 .extra = .{ .expected_tag = p.token_tags[main_token] },
3522 .extra = .{ .expected_tag = p.tokenTag(main_token) },
37593523 });
37603524 try p.warnMsg(.{
37613525 .tag = .zig_style_container,
37623526 .is_note = true,
37633527 .token = identifier,
3764 .extra = .{ .expected_tag = p.token_tags[main_token] },
3528 .extra = .{ .expected_tag = p.tokenTag(main_token) },
37653529 });
37663530
37673531 _ = try p.expectToken(.l_brace);
......@@ -3774,8 +3538,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {
37743538/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.
37753539///
37763540/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
3777fn parseByteAlign(p: *Parse) !Node.Index {
3778 _ = p.eatToken(.keyword_align) orelse return null_node;
3541fn parseByteAlign(p: *Parse) !?Node.Index {
3542 _ = p.eatToken(.keyword_align) orelse return null;
37793543 _ = try p.expectToken(.l_paren);
37803544 const expr = try p.expectExpr();
37813545 _ = try p.expectToken(.r_paren);
......@@ -3788,12 +3552,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {
37883552 defer p.scratch.shrinkRetainingCapacity(scratch_top);
37893553
37903554 while (true) {
3791 const item = try parseSwitchProng(p);
3792 if (item == 0) break;
3555 const item = try parseSwitchProng(p) orelse break;
37933556
37943557 try p.scratch.append(p.gpa, item);
37953558
3796 switch (p.token_tags[p.tok_i]) {
3559 switch (p.tokenTag(p.tok_i)) {
37973560 .comma => p.tok_i += 1,
37983561 // All possible delimiters.
37993562 .colon, .r_paren, .r_brace, .r_bracket => break,
......@@ -3813,13 +3576,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
38133576 while (true) {
38143577 if (p.eatToken(.r_paren)) |_| break;
38153578 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
3816 const param = try p.expectParamDecl();
3817 if (param != 0) {
3579 const opt_param = try p.expectParamDecl();
3580 if (opt_param) |param| {
38183581 try p.scratch.append(p.gpa, param);
3819 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
3582 } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) {
38203583 if (varargs == .none) varargs = .seen;
38213584 }
3822 switch (p.token_tags[p.tok_i]) {
3585 switch (p.tokenTag(p.tok_i)) {
38233586 .comma => p.tok_i += 1,
38243587 .r_paren => {
38253588 p.tok_i += 1;
......@@ -3835,9 +3598,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
38353598 }
38363599 const params = p.scratch.items[scratch_top..];
38373600 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) },
3601 0 => .{ .zero_or_one = .none },
3602 1 => .{ .zero_or_one = params[0].toOptional() },
3603 else => .{ .multi = try p.listToSpan(params) },
38413604 };
38423605}
38433606
......@@ -3852,10 +3615,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38523615 return p.addNode(.{
38533616 .tag = .identifier,
38543617 .main_token = builtin_token,
3855 .data = .{
3856 .lhs = undefined,
3857 .rhs = undefined,
3858 },
3618 .data = undefined,
38593619 });
38603620 };
38613621 const scratch_top = p.scratch.items.len;
......@@ -3864,7 +3624,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38643624 if (p.eatToken(.r_paren)) |_| break;
38653625 const param = try p.expectExpr();
38663626 try p.scratch.append(p.gpa, param);
3867 switch (p.token_tags[p.tok_i]) {
3627 switch (p.tokenTag(p.tok_i)) {
38683628 .comma => p.tok_i += 1,
38693629 .r_paren => {
38703630 p.tok_i += 1;
......@@ -3874,88 +3634,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
38743634 else => try p.warn(.expected_comma_after_arg),
38753635 }
38763636 }
3877 const comma = (p.token_tags[p.tok_i - 2] == .comma);
3637 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
38783638 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(.{
3639 if (params.len <= 2) {
3640 return p.addNode(.{
38893641 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
38903642 .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,
3643 .data = .{ .opt_node_and_opt_node = .{
3644 if (params.len >= 1) .fromOptional(params[0]) else .none,
3645 if (params.len >= 2) .fromOptional(params[1]) else .none,
3646 } },
3647 });
3648 } else {
3649 const span = try p.listToSpan(params);
3650 return p.addNode(.{
3651 .tag = if (comma) .builtin_call_comma else .builtin_call,
38983652 .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 },
3653 .data = .{ .extra_range = span },
3654 });
39153655 }
39163656}
39173657
39183658/// 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;
3659fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index {
3660 const if_token = p.eatToken(.keyword_if) orelse return null;
39213661 _ = try p.expectToken(.l_paren);
39223662 const condition = try p.expectExpr();
39233663 _ = try p.expectToken(.r_paren);
39243664 _ = try p.parsePtrPayload();
39253665
39263666 const then_expr = try bodyParseFn(p);
3927 assert(then_expr != 0);
39283667
3929 _ = p.eatToken(.keyword_else) orelse return p.addNode(.{
3668 _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{
39303669 .tag = .if_simple,
39313670 .main_token = if_token,
3932 .data = .{
3933 .lhs = condition,
3934 .rhs = then_expr,
3935 },
3671 .data = .{ .node_and_node = .{
3672 condition,
3673 then_expr,
3674 } },
39363675 });
39373676 _ = try p.parsePayload();
39383677 const else_expr = try bodyParseFn(p);
3939 assert(else_expr != 0);
39403678
3941 return p.addNode(.{
3679 return try p.addNode(.{
39423680 .tag = .@"if",
39433681 .main_token = if_token,
3944 .data = .{
3945 .lhs = condition,
3946 .rhs = try p.addExtra(Node.If{
3682 .data = .{ .node_and_extra = .{
3683 condition,
3684 try p.addExtra(Node.If{
39473685 .then_expr = then_expr,
39483686 .else_expr = else_expr,
39493687 }),
3950 },
3688 } },
39513689 });
39523690}
39533691
39543692/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
39553693///
39563694/// 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;
3695fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index {
3696 const for_token = p.eatToken(.keyword_for) orelse return null;
39593697
39603698 const scratch_top = p.scratch.items.len;
39613699 defer p.scratch.shrinkRetainingCapacity(scratch_top);
......@@ -3969,27 +3707,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N
39693707 try p.scratch.append(p.gpa, else_expr);
39703708 has_else = true;
39713709 } else if (inputs == 1) {
3972 return p.addNode(.{
3710 return try p.addNode(.{
39733711 .tag = .for_simple,
39743712 .main_token = for_token,
3975 .data = .{
3976 .lhs = p.scratch.items[scratch_top],
3977 .rhs = then_expr,
3978 },
3713 .data = .{ .node_and_node = .{
3714 p.scratch.items[scratch_top],
3715 then_expr,
3716 } },
39793717 });
39803718 } else {
39813719 try p.scratch.append(p.gpa, then_expr);
39823720 }
3983 return p.addNode(.{
3721 return try p.addNode(.{
39843722 .tag = .@"for",
39853723 .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 },
3724 .data = .{ .@"for" = .{
3725 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3726 .{ .inputs = @intCast(inputs), .has_else = has_else },
3727 } },
39933728 });
39943729}
39953730
......@@ -4011,21 +3746,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
40113746}
40123747
40133748fn 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;
3749 return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null;
40153750}
40163751
40173752fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {
4018 return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null;
3753 return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null;
3754}
3755
3756fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex {
3757 const available_tags = p.tokens.items(.tag)[p.tok_i..];
3758 if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null;
3759 const result = p.tok_i;
3760 p.tok_i += @intCast(tags.len);
3761 return result;
40193762}
40203763
40213764fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {
40223765 const token = p.nextToken();
4023 assert(p.token_tags[token] == tag);
3766 assert(p.tokenTag(token) == tag);
40243767 return token;
40253768}
40263769
40273770fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4028 if (p.token_tags[p.tok_i] != tag) {
3771 if (p.tokenTag(p.tok_i) != tag) {
40293772 return p.failMsg(.{
40303773 .tag = .expected_token,
40313774 .token = p.tok_i,
......@@ -4036,7 +3779,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
40363779}
40373780
40383781fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {
4039 if (p.token_tags[p.tok_i] == .semicolon) {
3782 if (p.tokenTag(p.tok_i) == .semicolon) {
40403783 _ = p.nextToken();
40413784 return;
40423785 }
......@@ -4050,8 +3793,6 @@ fn nextToken(p: *Parse) TokenIndex {
40503793 return result;
40513794}
40523795
4053const null_node: Node.Index = 0;
4054
40553796const Parse = @This();
40563797const std = @import("../std.zig");
40573798const assert = std.debug.assert;
......@@ -4060,6 +3801,8 @@ const Ast = std.zig.Ast;
40603801const Node = Ast.Node;
40613802const AstError = Ast.Error;
40623803const TokenIndex = Ast.TokenIndex;
3804const OptionalTokenIndex = Ast.OptionalTokenIndex;
3805const ExtraIndex = Ast.ExtraIndex;
40633806const Token = std.zig.Token;
40643807
40653808test {
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+43-55
......@@ -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,8 +248,8 @@ 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
258255 .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}),
......@@ -262,12 +259,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
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+459-487
......@@ -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,23 +142,20 @@ fn renderMember(
141142) Error!void {
142143 const tree = r.tree;
143144 const ais = r.ais;
144 const token_tags = tree.tokens.items(.tag);
145 const main_tokens = tree.nodes.items(.main_token);
146 const datas = tree.nodes.items(.data);
147145 if (r.fixups.omit_nodes.contains(decl)) return;
148146 try renderDocComments(r, tree.firstToken(decl));
149 switch (tree.nodes.items(.tag)[decl]) {
147 switch (tree.nodeTag(decl)) {
150148 .fn_decl => {
151149 // Some examples:
152150 // pub extern "foo" fn ...
153151 // export fn ...
154 const fn_proto = datas[decl].lhs;
155 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);
156154 // Go back to the first token we should render here.
157155 var i = fn_token;
158156 while (i > 0) {
159157 i -= 1;
160 switch (token_tags[i]) {
158 switch (tree.tokenTag(i)) {
161159 .keyword_extern,
162160 .keyword_export,
163161 .keyword_pub,
......@@ -172,31 +170,34 @@ fn renderMember(
172170 },
173171 }
174172 }
173
175174 while (i < fn_token) : (i += 1) {
176175 try renderToken(r, i, .space);
177176 }
178 switch (tree.nodes.items(.tag)[fn_proto]) {
177 switch (tree.nodeTag(fn_proto)) {
179178 .fn_proto_one, .fn_proto => {
180 const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one)
181 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
182182 else
183 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;
183 tree.fnProto(fn_proto).ast.callconv_expr;
184
184185 // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE
185 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {
186 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) {
187 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 }
188191 }
189192 }
190193 },
191194 .fn_proto_simple, .fn_proto_multi => {},
192195 else => unreachable,
193196 }
194 assert(datas[decl].rhs != 0);
195197 try renderExpression(r, fn_proto, .space);
196 const body_node = datas[decl].rhs;
197198 if (r.fixups.gut_functions.contains(decl)) {
198199 try ais.pushIndent(.normal);
199 const lbrace = tree.nodes.items(.main_token)[body_node];
200 const lbrace = tree.nodeMainToken(body_node);
200201 try renderToken(r, lbrace, .newline);
201202 try discardAllParams(r, fn_proto);
202203 try ais.writer().writeAll("@trap();");
......@@ -205,7 +206,7 @@ fn renderMember(
205206 try renderToken(r, tree.lastToken(body_node), space); // rbrace
206207 } else if (r.fixups.unused_var_decls.count() != 0) {
207208 try ais.pushIndent(.normal);
208 const lbrace = tree.nodes.items(.main_token)[body_node];
209 const lbrace = tree.nodeMainToken(body_node);
209210 try renderToken(r, lbrace, .newline);
210211
211212 var fn_proto_buf: [1]Ast.Node.Index = undefined;
......@@ -213,7 +214,7 @@ fn renderMember(
213214 var it = full_fn_proto.iterate(&tree);
214215 while (it.next()) |param| {
215216 const name_ident = param.name_token.?;
216 assert(token_tags[name_ident] == .identifier);
217 assert(tree.tokenTag(name_ident) == .identifier);
217218 if (r.fixups.unused_var_decls.contains(name_ident)) {
218219 const w = ais.writer();
219220 try w.writeAll("_ = ");
......@@ -235,11 +236,11 @@ fn renderMember(
235236 => {
236237 // Extern function prototypes are parsed as these tags.
237238 // Go back to the first token we should render here.
238 const fn_token = main_tokens[decl];
239 const fn_token = tree.nodeMainToken(decl);
239240 var i = fn_token;
240241 while (i > 0) {
241242 i -= 1;
242 switch (token_tags[i]) {
243 switch (tree.tokenTag(i)) {
243244 .keyword_extern,
244245 .keyword_export,
245246 .keyword_pub,
......@@ -262,9 +263,9 @@ fn renderMember(
262263 },
263264
264265 .@"usingnamespace" => {
265 const main_token = main_tokens[decl];
266 const expr = datas[decl].lhs;
267 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})) {
268269 try renderToken(r, main_token - 1, .space); // pub
269270 }
270271 try renderToken(r, main_token, .space); // usingnamespace
......@@ -283,15 +284,17 @@ fn renderMember(
283284 },
284285
285286 .test_decl => {
286 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;
287289 try renderToken(r, test_token, .space);
288 const test_name_tag = token_tags[test_token + 1];
289 switch (test_name_tag) {
290 .string_literal => try renderToken(r, test_token + 1, .space),
291 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),
292 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 }
293296 }
294 try renderExpression(r, datas[decl].rhs, space);
297 try renderExpression(r, block_node, space);
295298 },
296299
297300 .container_field_init,
......@@ -319,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa
319322fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
320323 const tree = r.tree;
321324 const ais = r.ais;
322 const token_tags = tree.tokens.items(.tag);
323 const main_tokens = tree.nodes.items(.main_token);
324 const node_tags = tree.nodes.items(.tag);
325 const datas = tree.nodes.items(.data);
326325 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
327326 try ais.writer().writeAll(replacement);
328327 try renderOnlySpace(r, space);
......@@ -330,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
330329 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
331330 return renderExpression(r, replacement, space);
332331 }
333 switch (node_tags[node]) {
332 switch (tree.nodeTag(node)) {
334333 .identifier => {
335 const token_index = main_tokens[node];
334 const token_index = tree.nodeMainToken(node);
336335 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);
337336 },
338337
......@@ -341,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
341340 .unreachable_literal,
342341 .anyframe_literal,
343342 .string_literal,
344 => return renderToken(r, main_tokens[node], space),
343 => return renderToken(r, tree.nodeMainToken(node), space),
345344
346345 .multiline_string_literal => {
347346 try ais.maybeInsertNewline();
348347
349 var i = datas[node].lhs;
350 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);
351355
352356 // dedent the next thing that comes after a multiline string literal
353357 if (!ais.indentStackEmpty() and
354 token_tags[i] != .colon and
355 ((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
356360 ais.lastSpaceModeIndent() < ais.currentIndent()))
357361 {
358362 ais.popIndent();
......@@ -361,16 +365,17 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
361365
362366 switch (space) {
363367 .none, .space, .newline, .skip => {},
364 .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon),
365 .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma),
366 .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),
367371 }
368372 },
369373
370374 .error_value => {
371 try renderToken(r, main_tokens[node], .none);
372 try renderToken(r, main_tokens[node] + 1, .none);
373 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);
374379 },
375380
376381 .block_two,
......@@ -384,12 +389,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
384389 },
385390
386391 .@"errdefer" => {
387 const defer_token = main_tokens[node];
388 const payload_token = datas[node].lhs;
389 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;
390394
391395 try renderToken(r, defer_token, .space);
392 if (payload_token != 0) {
396 if (maybe_payload_token.unwrap()) |payload_token| {
393397 try renderToken(r, payload_token - 1, .none); // |
394398 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
395399 try renderToken(r, payload_token + 1, .space); // |
......@@ -397,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
397401 return renderExpression(r, expr, space);
398402 },
399403
400 .@"defer" => {
401 const defer_token = main_tokens[node];
402 const expr = datas[node].rhs;
403 try renderToken(r, defer_token, .space);
404 return renderExpression(r, expr, space);
405 },
406 .@"comptime", .@"nosuspend" => {
407 const comptime_token = main_tokens[node];
408 const block = datas[node].lhs;
409 try renderToken(r, comptime_token, .space);
410 return renderExpression(r, block, space);
411 },
412
413 .@"suspend" => {
414 const suspend_token = main_tokens[node];
415 const body = datas[node].lhs;
416 try renderToken(r, suspend_token, .space);
417 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);
418413 },
419414
420415 .@"catch" => {
421 const main_token = main_tokens[node];
422 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);
423419
424420 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
425421 const after_op_space = if (same_line) Space.space else Space.newline;
426422
427 try renderExpression(r, datas[node].lhs, .space); // target
423 try renderExpression(r, lhs, .space); // target
428424
429425 try ais.pushIndent(.normal);
430 if (token_tags[fallback_first - 1] == .pipe) {
426 if (tree.tokenTag(fallback_first - 1) == .pipe) {
431427 try renderToken(r, main_token, .space); // catch keyword
432428 try renderToken(r, main_token + 1, .none); // pipe
433429 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
434430 try renderToken(r, main_token + 3, after_op_space); // pipe
435431 } else {
436 assert(token_tags[fallback_first - 1] == .keyword_catch);
432 assert(tree.tokenTag(fallback_first - 1) == .keyword_catch);
437433 try renderToken(r, main_token, after_op_space); // catch keyword
438434 }
439 try renderExpression(r, datas[node].rhs, space); // fallback
435 try renderExpression(r, rhs, space); // fallback
440436 ais.popIndent();
441437 },
442438
443439 .field_access => {
444 const main_token = main_tokens[node];
445 const field_access = datas[node];
440 const lhs, const name_token = tree.nodeData(node).node_and_token;
441 const dot_token = name_token - 1;
446442
447443 try ais.pushIndent(.field_access);
448 try renderExpression(r, field_access.lhs, .none);
444 try renderExpression(r, lhs, .none);
449445
450446 // Allow a line break between the lhs and the dot if the lhs and rhs
451447 // are on different lines.
452 const lhs_last_token = tree.lastToken(field_access.lhs);
453 const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1);
454 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();
455451
456 try renderToken(r, main_token, .none); // .
452 try renderToken(r, dot_token, .none);
457453
458 try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field
454 try renderIdentifier(r, name_token, space, .eagerly_unquote); // field
459455 ais.popIndent();
460456 },
461457
462458 .error_union,
463459 .switch_range,
464460 => {
465 const infix = datas[node];
466 try renderExpression(r, infix.lhs, .none);
467 try renderToken(r, main_tokens[node], .none);
468 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);
469465 },
470466 .for_range => {
471 const infix = datas[node];
472 try renderExpression(r, infix.lhs, .none);
473 if (infix.rhs != 0) {
474 try renderToken(r, main_tokens[node], .none);
475 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);
476472 } else {
477 return renderToken(r, main_tokens[node], space);
473 return renderToken(r, tree.nodeMainToken(node), space);
478474 }
479475 },
480476
......@@ -497,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
497493 .assign_mul_wrap,
498494 .assign_mul_sat,
499495 => {
500 const infix = datas[node];
501 try renderExpression(r, infix.lhs, .space);
502 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);
503499 try ais.pushIndent(.after_equals);
504500 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
505501 try renderToken(r, op_token, .space);
506502 } else {
507503 try renderToken(r, op_token, .newline);
508504 }
509 try renderExpression(r, infix.rhs, space);
505 try renderExpression(r, rhs, space);
510506 ais.popIndent();
511507 },
512508
......@@ -540,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
540536 .sub_sat,
541537 .@"orelse",
542538 => {
543 const infix = datas[node];
544 try renderExpression(r, infix.lhs, .space);
545 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);
546542 try ais.pushIndent(.binop);
547543 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
548544 try renderToken(r, op_token, .space);
549545 } else {
550546 try renderToken(r, op_token, .newline);
551547 }
552 try renderExpression(r, infix.rhs, space);
548 try renderExpression(r, rhs, space);
553549 ais.popIndent();
554550 },
555551
......@@ -561,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
561557
562558 for (full.ast.variables, 0..) |variable_node, i| {
563559 const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space;
564 switch (node_tags[variable_node]) {
560 switch (tree.nodeTag(variable_node)) {
565561 .global_var_decl,
566562 .local_var_decl,
567563 .simple_var_decl,
......@@ -589,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
589585 .optional_type,
590586 .address_of,
591587 => {
592 try renderToken(r, main_tokens[node], .none);
593 return renderExpression(r, datas[node].lhs, space);
588 try renderToken(r, tree.nodeMainToken(node), .none);
589 return renderExpression(r, tree.nodeData(node).node, space);
594590 },
595591
596592 .@"try",
597593 .@"resume",
598594 .@"await",
599595 => {
600 try renderToken(r, main_tokens[node], .space);
601 return renderExpression(r, datas[node].lhs, space);
596 try renderToken(r, tree.nodeMainToken(node), .space);
597 return renderExpression(r, tree.nodeData(node).node, space);
602598 },
603599
604600 .array_type,
......@@ -651,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
651647 },
652648
653649 .array_access => {
654 const suffix = datas[node];
655 const lbracket = tree.firstToken(suffix.rhs) - 1;
656 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;
657653 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
658654 const inner_space = if (one_line) Space.none else Space.newline;
659 try renderExpression(r, suffix.lhs, .none);
655 try renderExpression(r, lhs, .none);
660656 try ais.pushIndent(.normal);
661657 try renderToken(r, lbracket, inner_space); // [
662 try renderExpression(r, suffix.rhs, inner_space);
658 try renderExpression(r, rhs, inner_space);
663659 ais.popIndent();
664660 return renderToken(r, rbracket, space); // ]
665661 },
666662
667 .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),
668667
669668 .deref => {
670 try renderExpression(r, datas[node].lhs, .none);
671 return renderToken(r, main_tokens[node], space);
669 try renderExpression(r, tree.nodeData(node).node, .none);
670 return renderToken(r, tree.nodeMainToken(node), space);
672671 },
673672
674673 .unwrap_optional => {
675 try renderExpression(r, datas[node].lhs, .none);
676 try renderToken(r, main_tokens[node], .none);
677 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);
678679 },
679680
680681 .@"break", .@"continue" => {
681 const main_token = main_tokens[node];
682 const label_token = datas[node].lhs;
683 const target = datas[node].rhs;
684 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) {
685685 try renderToken(r, main_token, space); // break/continue
686 } 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().?;
687688 try renderToken(r, main_token, .space); // break/continue
688689 try renderExpression(r, target, space);
689 } 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().?;
690692 try renderToken(r, main_token, .space); // break/continue
691693 try renderToken(r, label_token - 1, .none); // :
692694 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
693 } 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().?;
694698 try renderToken(r, main_token, .space); // break/continue
695699 try renderToken(r, label_token - 1, .none); // :
696700 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
697701 try renderExpression(r, target, space);
698 }
702 } else unreachable;
699703 },
700704
701705 .@"return" => {
702 if (datas[node].lhs != 0) {
703 try renderToken(r, main_tokens[node], .space);
704 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);
705709 } else {
706 try renderToken(r, main_tokens[node], space);
710 try renderToken(r, tree.nodeMainToken(node), space);
707711 }
708712 },
709713
710714 .grouped_expression => {
715 const expr, const rparen = tree.nodeData(node).node_and_token;
711716 try ais.pushIndent(.normal);
712 try renderToken(r, main_tokens[node], .none); // lparen
713 try renderExpression(r, datas[node].lhs, .none);
717 try renderToken(r, tree.nodeMainToken(node), .none); // lparen
718 try renderExpression(r, expr, .none);
714719 ais.popIndent();
715 return renderToken(r, datas[node].rhs, space); // rparen
720 return renderToken(r, rparen, space);
716721 },
717722
718723 .container_decl,
......@@ -733,9 +738,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
733738 },
734739
735740 .error_set_decl => {
736 const error_token = main_tokens[node];
741 const error_token = tree.nodeMainToken(node);
737742 const lbrace = error_token + 1;
738 const rbrace = datas[node].rhs;
743 const rbrace = tree.nodeData(node).token;
739744
740745 try renderToken(r, error_token, .none);
741746
......@@ -743,20 +748,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
743748 // There is nothing between the braces so render condensed: `error{}`
744749 try renderToken(r, lbrace, .none);
745750 return renderToken(r, rbrace, space);
746 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {
751 } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) {
747752 // There is exactly one member and no trailing comma or
748753 // comments, so render without surrounding spaces: `error{Foo}`
749754 try renderToken(r, lbrace, .none);
750755 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
751756 return renderToken(r, rbrace, space);
752 } else if (token_tags[rbrace - 1] == .comma) {
757 } else if (tree.tokenTag(rbrace - 1) == .comma) {
753758 // There is a trailing comma so render each member on a new line.
754759 try ais.pushIndent(.normal);
755760 try renderToken(r, lbrace, .newline);
756761 var i = lbrace + 1;
757762 while (i < rbrace) : (i += 1) {
758763 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
759 switch (token_tags[i]) {
764 switch (tree.tokenTag(i)) {
760765 .doc_comment => try renderToken(r, i, .newline),
761766 .identifier => {
762767 try ais.pushSpace(.comma);
......@@ -774,7 +779,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
774779 try renderToken(r, lbrace, .space);
775780 var i = lbrace + 1;
776781 while (i < rbrace) : (i += 1) {
777 switch (token_tags[i]) {
782 switch (tree.tokenTag(i)) {
778783 .doc_comment => unreachable, // TODO
779784 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),
780785 .comma => {},
......@@ -792,7 +797,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
792797 => {
793798 var buf: [2]Ast.Node.Index = undefined;
794799 const params = tree.builtinCallParams(&buf, node).?;
795 return renderBuiltinCall(r, main_tokens[node], params, space);
800 return renderBuiltinCall(r, tree.nodeMainToken(node), params, space);
796801 },
797802
798803 .fn_proto_simple,
......@@ -805,14 +810,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
805810 },
806811
807812 .anyframe_type => {
808 const main_token = main_tokens[node];
809 if (datas[node].rhs != 0) {
810 try renderToken(r, main_token, .none); // anyframe
811 try renderToken(r, main_token + 1, .none); // ->
812 return renderExpression(r, datas[node].rhs, space);
813 } else {
814 return renderToken(r, main_token, space); // anyframe
815 }
813 const main_token = tree.nodeMainToken(node);
814 try renderToken(r, main_token, .none); // anyframe
815 try renderToken(r, main_token + 1, .none); // ->
816 return renderExpression(r, tree.nodeData(node).token_and_node[1], space);
816817 },
817818
818819 .@"switch",
......@@ -869,8 +870,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
869870 => return renderAsm(r, tree.fullAsm(node).?, space),
870871
871872 .enum_literal => {
872 try renderToken(r, main_tokens[node] - 1, .none); // .
873 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name
873 try renderToken(r, tree.nodeMainToken(node) - 1, .none); // .
874 return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name
874875 },
875876
876877 .fn_decl => unreachable,
......@@ -912,9 +913,9 @@ fn renderArrayType(
912913 try ais.pushIndent(.normal);
913914 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
914915 try renderExpression(r, array_type.ast.elem_count, inner_space);
915 if (array_type.ast.sentinel != 0) {
916 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon
917 try renderExpression(r, array_type.ast.sentinel, inner_space);
916 if (array_type.ast.sentinel.unwrap()) |sentinel| {
917 try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon
918 try renderExpression(r, sentinel, inner_space);
918919 }
919920 ais.popIndent();
920921 try renderToken(r, rbracket, .none); // rbracket
......@@ -923,6 +924,7 @@ fn renderArrayType(
923924
924925fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
925926 const tree = r.tree;
927 const main_token = ptr_type.ast.main_token;
926928 switch (ptr_type.size) {
927929 .one => {
928930 // Since ** tokens exist and the same token is shared by two
......@@ -930,41 +932,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
930932 // in such a relationship. If so, skip rendering anything for
931933 // this pointer type and rely on the child to render our asterisk
932934 // as well when it renders the ** token.
933 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and
934 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])
935 if (tree.tokenTag(main_token) == .asterisk_asterisk and
936 main_token == tree.nodeMainToken(ptr_type.ast.child_type))
935937 {
936938 return renderExpression(r, ptr_type.ast.child_type, space);
937939 }
938 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk
940 try renderToken(r, main_token, .none); // asterisk
939941 },
940942 .many => {
941 if (ptr_type.ast.sentinel == 0) {
942 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
943 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
944 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket
943 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
944 try renderToken(r, main_token, .none); // lbracket
945 try renderToken(r, main_token + 1, .none); // asterisk
946 try renderToken(r, main_token + 2, .none); // colon
947 try renderExpression(r, sentinel, .none);
948 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
945949 } else {
946 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
947 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
948 try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon
949 try renderExpression(r, ptr_type.ast.sentinel, .none);
950 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
950 try renderToken(r, main_token, .none); // lbracket
951 try renderToken(r, main_token + 1, .none); // asterisk
952 try renderToken(r, main_token + 2, .none); // rbracket
951953 }
952954 },
953955 .c => {
954 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
955 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk
956 try renderToken(r, ptr_type.ast.main_token + 2, .none); // c
957 try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket
956 try renderToken(r, main_token, .none); // lbracket
957 try renderToken(r, main_token + 1, .none); // asterisk
958 try renderToken(r, main_token + 2, .none); // c
959 try renderToken(r, main_token + 3, .none); // rbracket
958960 },
959961 .slice => {
960 if (ptr_type.ast.sentinel == 0) {
961 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
962 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket
962 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
963 try renderToken(r, main_token, .none); // lbracket
964 try renderToken(r, main_token + 1, .none); // colon
965 try renderExpression(r, sentinel, .none);
966 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
963967 } else {
964 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket
965 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon
966 try renderExpression(r, ptr_type.ast.sentinel, .none);
967 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
968 try renderToken(r, main_token, .none); // lbracket
969 try renderToken(r, main_token + 1, .none); // rbracket
968970 }
969971 },
970972 }
......@@ -973,29 +975,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
973975 try renderToken(r, allowzero_token, .space);
974976 }
975977
976 if (ptr_type.ast.align_node != 0) {
977 const align_first = tree.firstToken(ptr_type.ast.align_node);
978 if (ptr_type.ast.align_node.unwrap()) |align_node| {
979 const align_first = tree.firstToken(align_node);
978980 try renderToken(r, align_first - 2, .none); // align
979981 try renderToken(r, align_first - 1, .none); // lparen
980 try renderExpression(r, ptr_type.ast.align_node, .none);
981 if (ptr_type.ast.bit_range_start != 0) {
982 assert(ptr_type.ast.bit_range_end != 0);
983 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon
984 try renderExpression(r, ptr_type.ast.bit_range_start, .none);
985 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon
986 try renderExpression(r, ptr_type.ast.bit_range_end, .none);
987 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen
982 try renderExpression(r, align_node, .none);
983 if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| {
984 const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?;
985 try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon
986 try renderExpression(r, bit_range_start, .none);
987 try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon
988 try renderExpression(r, bit_range_end, .none);
989 try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen
988990 } else {
989 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen
991 try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen
990992 }
991993 }
992994
993 if (ptr_type.ast.addrspace_node != 0) {
994 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);
995 if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| {
996 const addrspace_first = tree.firstToken(addrspace_node);
995997 try renderToken(r, addrspace_first - 2, .none); // addrspace
996998 try renderToken(r, addrspace_first - 1, .none); // lparen
997 try renderExpression(r, ptr_type.ast.addrspace_node, .none);
998 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen
999 try renderExpression(r, addrspace_node, .none);
1000 try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen
9991001 }
10001002
10011003 if (ptr_type.const_token) |const_token| {
......@@ -1016,13 +1018,12 @@ fn renderSlice(
10161018 space: Space,
10171019) Error!void {
10181020 const tree = r.tree;
1019 const node_tags = tree.nodes.items(.tag);
1020 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
1021 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
1021 const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
1022 if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
10221023 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
1023 const after_dots_space = if (slice.ast.end != 0)
1024 const after_dots_space = if (slice.ast.end != .none)
10241025 after_start_space
1025 else if (slice.ast.sentinel != 0) Space.space else Space.none;
1026 else if (slice.ast.sentinel != .none) Space.space else Space.none;
10261027
10271028 try renderExpression(r, slice.ast.sliced, .none);
10281029 try renderToken(r, slice.ast.lbracket, .none); // lbracket
......@@ -1031,14 +1032,14 @@ fn renderSlice(
10311032 try renderExpression(r, slice.ast.start, after_start_space);
10321033 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
10331034
1034 if (slice.ast.end != 0) {
1035 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;
1036 try renderExpression(r, slice.ast.end, after_end_space);
1035 if (slice.ast.end.unwrap()) |end| {
1036 const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none;
1037 try renderExpression(r, end, after_end_space);
10371038 }
10381039
1039 if (slice.ast.sentinel != 0) {
1040 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon
1041 try renderExpression(r, slice.ast.sentinel, .none);
1040 if (slice.ast.sentinel.unwrap()) |sentinel| {
1041 try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon
1042 try renderExpression(r, sentinel, .none);
10421043 }
10431044
10441045 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
......@@ -1050,12 +1051,8 @@ fn renderAsmOutput(
10501051 space: Space,
10511052) Error!void {
10521053 const tree = r.tree;
1053 const token_tags = tree.tokens.items(.tag);
1054 const node_tags = tree.nodes.items(.tag);
1055 const main_tokens = tree.nodes.items(.main_token);
1056 const datas = tree.nodes.items(.data);
1057 assert(node_tags[asm_output] == .asm_output);
1058 const symbolic_name = main_tokens[asm_output];
1054 assert(tree.nodeTag(asm_output) == .asm_output);
1055 const symbolic_name = tree.nodeMainToken(asm_output);
10591056
10601057 try renderToken(r, symbolic_name - 1, .none); // lbracket
10611058 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
......@@ -1063,10 +1060,11 @@ fn renderAsmOutput(
10631060 try renderToken(r, symbolic_name + 2, .space); // "constraint"
10641061 try renderToken(r, symbolic_name + 3, .none); // lparen
10651062
1066 if (token_tags[symbolic_name + 4] == .arrow) {
1063 if (tree.tokenTag(symbolic_name + 4) == .arrow) {
1064 const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token;
10671065 try renderToken(r, symbolic_name + 4, .space); // ->
1068 try renderExpression(r, datas[asm_output].lhs, Space.none);
1069 return renderToken(r, datas[asm_output].rhs, space); // rparen
1066 try renderExpression(r, type_expr.unwrap().?, Space.none);
1067 return renderToken(r, rparen, space);
10701068 } else {
10711069 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
10721070 return renderToken(r, symbolic_name + 5, space); // rparen
......@@ -1079,19 +1077,17 @@ fn renderAsmInput(
10791077 space: Space,
10801078) Error!void {
10811079 const tree = r.tree;
1082 const node_tags = tree.nodes.items(.tag);
1083 const main_tokens = tree.nodes.items(.main_token);
1084 const datas = tree.nodes.items(.data);
1085 assert(node_tags[asm_input] == .asm_input);
1086 const symbolic_name = main_tokens[asm_input];
1080 assert(tree.nodeTag(asm_input) == .asm_input);
1081 const symbolic_name = tree.nodeMainToken(asm_input);
1082 const expr, const rparen = tree.nodeData(asm_input).node_and_token;
10871083
10881084 try renderToken(r, symbolic_name - 1, .none); // lbracket
10891085 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
10901086 try renderToken(r, symbolic_name + 1, .space); // rbracket
10911087 try renderToken(r, symbolic_name + 2, .space); // "constraint"
10921088 try renderToken(r, symbolic_name + 3, .none); // lparen
1093 try renderExpression(r, datas[asm_input].lhs, Space.none);
1094 return renderToken(r, datas[asm_input].rhs, space); // rparen
1089 try renderExpression(r, expr, Space.none);
1090 return renderToken(r, rparen, space);
10951091}
10961092
10971093fn renderVarDecl(
......@@ -1147,15 +1143,15 @@ fn renderVarDeclWithoutFixups(
11471143
11481144 try renderToken(r, var_decl.ast.mut_token, .space); // var
11491145
1150 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or
1151 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
1152 var_decl.ast.init_node != 0)
1146 if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or
1147 var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1148 var_decl.ast.init_node != .none)
11531149 {
1154 const name_space = if (var_decl.ast.type_node == 0 and
1155 (var_decl.ast.align_node != 0 or
1156 var_decl.ast.addrspace_node != 0 or
1157 var_decl.ast.section_node != 0 or
1158 var_decl.ast.init_node != 0))
1150 const name_space = if (var_decl.ast.type_node == .none and
1151 (var_decl.ast.align_node != .none or
1152 var_decl.ast.addrspace_node != .none or
1153 var_decl.ast.section_node != .none or
1154 var_decl.ast.init_node != .none))
11591155 Space.space
11601156 else
11611157 Space.none;
......@@ -1165,26 +1161,26 @@ fn renderVarDeclWithoutFixups(
11651161 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
11661162 }
11671163
1168 if (var_decl.ast.type_node != 0) {
1164 if (var_decl.ast.type_node.unwrap()) |type_node| {
11691165 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
1170 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or
1171 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)
1166 if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or
1167 var_decl.ast.section_node != .none or var_decl.ast.init_node != .none)
11721168 {
1173 try renderExpression(r, var_decl.ast.type_node, .space);
1169 try renderExpression(r, type_node, .space);
11741170 } else {
1175 return renderExpression(r, var_decl.ast.type_node, space);
1171 return renderExpression(r, type_node, space);
11761172 }
11771173 }
11781174
1179 if (var_decl.ast.align_node != 0) {
1180 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;
1175 if (var_decl.ast.align_node.unwrap()) |align_node| {
1176 const lparen = tree.firstToken(align_node) - 1;
11811177 const align_kw = lparen - 1;
1182 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;
1178 const rparen = tree.lastToken(align_node) + 1;
11831179 try renderToken(r, align_kw, Space.none); // align
11841180 try renderToken(r, lparen, Space.none); // (
1185 try renderExpression(r, var_decl.ast.align_node, Space.none);
1186 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or
1187 var_decl.ast.init_node != 0)
1181 try renderExpression(r, align_node, Space.none);
1182 if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1183 var_decl.ast.init_node != .none)
11881184 {
11891185 try renderToken(r, rparen, .space); // )
11901186 } else {
......@@ -1192,14 +1188,14 @@ fn renderVarDeclWithoutFixups(
11921188 }
11931189 }
11941190
1195 if (var_decl.ast.addrspace_node != 0) {
1196 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;
1191 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
1192 const lparen = tree.firstToken(addrspace_node) - 1;
11971193 const addrspace_kw = lparen - 1;
1198 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;
1194 const rparen = tree.lastToken(addrspace_node) + 1;
11991195 try renderToken(r, addrspace_kw, Space.none); // addrspace
12001196 try renderToken(r, lparen, Space.none); // (
1201 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);
1202 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {
1197 try renderExpression(r, addrspace_node, Space.none);
1198 if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) {
12031199 try renderToken(r, rparen, .space); // )
12041200 } else {
12051201 try renderToken(r, rparen, .none); // )
......@@ -1207,27 +1203,27 @@ fn renderVarDeclWithoutFixups(
12071203 }
12081204 }
12091205
1210 if (var_decl.ast.section_node != 0) {
1211 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;
1206 if (var_decl.ast.section_node.unwrap()) |section_node| {
1207 const lparen = tree.firstToken(section_node) - 1;
12121208 const section_kw = lparen - 1;
1213 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;
1209 const rparen = tree.lastToken(section_node) + 1;
12141210 try renderToken(r, section_kw, Space.none); // linksection
12151211 try renderToken(r, lparen, Space.none); // (
1216 try renderExpression(r, var_decl.ast.section_node, Space.none);
1217 if (var_decl.ast.init_node != 0) {
1212 try renderExpression(r, section_node, Space.none);
1213 if (var_decl.ast.init_node != .none) {
12181214 try renderToken(r, rparen, .space); // )
12191215 } else {
12201216 return renderToken(r, rparen, space); // )
12211217 }
12221218 }
12231219
1224 assert(var_decl.ast.init_node != 0);
1220 const init_node = var_decl.ast.init_node.unwrap().?;
12251221
1226 const eq_token = tree.firstToken(var_decl.ast.init_node) - 1;
1222 const eq_token = tree.firstToken(init_node) - 1;
12271223 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
12281224 try ais.pushIndent(.after_equals);
12291225 try renderToken(r, eq_token, eq_space); // =
1230 try renderExpression(r, var_decl.ast.init_node, space); // ;
1226 try renderExpression(r, init_node, space); // ;
12311227 ais.popIndent();
12321228}
12331229
......@@ -1236,7 +1232,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
12361232 .ast = .{
12371233 .while_token = if_node.ast.if_token,
12381234 .cond_expr = if_node.ast.cond_expr,
1239 .cont_expr = 0,
1235 .cont_expr = .none,
12401236 .then_expr = if_node.ast.then_expr,
12411237 .else_expr = if_node.ast.else_expr,
12421238 },
......@@ -1252,7 +1248,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
12521248/// respective values set to null.
12531249fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
12541250 const tree = r.tree;
1255 const token_tags = tree.tokens.items(.tag);
12561251
12571252 if (while_node.label_token) |label| {
12581253 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
......@@ -1273,7 +1268,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
12731268 try renderToken(r, last_prefix_token, .space);
12741269 try renderToken(r, payload_token - 1, .none); // |
12751270 const ident = blk: {
1276 if (token_tags[payload_token] == .asterisk) {
1271 if (tree.tokenTag(payload_token) == .asterisk) {
12771272 try renderToken(r, payload_token, .none); // *
12781273 break :blk payload_token + 1;
12791274 } else {
......@@ -1282,7 +1277,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
12821277 };
12831278 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
12841279 const pipe = blk: {
1285 if (token_tags[ident + 1] == .comma) {
1280 if (tree.tokenTag(ident + 1) == .comma) {
12861281 try renderToken(r, ident + 1, .space); // ,
12871282 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
12881283 break :blk ident + 3;
......@@ -1293,13 +1288,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
12931288 last_prefix_token = pipe;
12941289 }
12951290
1296 if (while_node.ast.cont_expr != 0) {
1291 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
12971292 try renderToken(r, last_prefix_token, .space);
1298 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1293 const lparen = tree.firstToken(cont_expr) - 1;
12991294 try renderToken(r, lparen - 1, .space); // :
13001295 try renderToken(r, lparen, .none); // lparen
1301 try renderExpression(r, while_node.ast.cont_expr, .none);
1302 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen
1296 try renderExpression(r, cont_expr, .none);
1297 last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen
13031298 }
13041299
13051300 try renderThenElse(
......@@ -1317,15 +1312,14 @@ fn renderThenElse(
13171312 r: *Render,
13181313 last_prefix_token: Ast.TokenIndex,
13191314 then_expr: Ast.Node.Index,
1320 else_token: Ast.TokenIndex,
1315 else_token: ?Ast.TokenIndex,
13211316 maybe_error_token: ?Ast.TokenIndex,
1322 else_expr: Ast.Node.Index,
1317 opt_else_expr: Ast.Node.OptionalIndex,
13231318 space: Space,
13241319) Error!void {
13251320 const tree = r.tree;
13261321 const ais = r.ais;
1327 const node_tags = tree.nodes.items(.tag);
1328 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
1322 const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
13291323 const indent_then_expr = !then_expr_is_block and
13301324 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
13311325
......@@ -1341,7 +1335,7 @@ fn renderThenElse(
13411335 try renderToken(r, last_prefix_token, .space);
13421336 }
13431337
1344 if (else_expr != 0) {
1338 if (opt_else_expr.unwrap()) |else_expr| {
13451339 if (indent_then_expr) {
13461340 try renderExpression(r, then_expr, .newline);
13471341 } else {
......@@ -1350,18 +1344,18 @@ fn renderThenElse(
13501344
13511345 if (indent_then_expr) ais.popIndent();
13521346
1353 var last_else_token = else_token;
1347 var last_else_token = else_token.?;
13541348
13551349 if (maybe_error_token) |error_token| {
1356 try renderToken(r, else_token, .space); // else
1350 try renderToken(r, last_else_token, .space); // else
13571351 try renderToken(r, error_token - 1, .none); // |
13581352 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
13591353 last_else_token = error_token + 1; // |
13601354 }
13611355
13621356 const indent_else_expr = indent_then_expr and
1363 !nodeIsBlock(node_tags[else_expr]) and
1364 !nodeIsIfForWhileSwitch(node_tags[else_expr]);
1357 !nodeIsBlock(tree.nodeTag(else_expr)) and
1358 !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr));
13651359 if (indent_else_expr) {
13661360 try ais.pushIndent(.normal);
13671361 try renderToken(r, last_else_token, .newline);
......@@ -1398,21 +1392,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
13981392
13991393 var cur = for_node.payload_token;
14001394 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
1401 if (token_tags[pipe - 1] == .comma) {
1395 if (tree.tokenTag(@intCast(pipe - 1)) == .comma) {
14021396 try ais.pushIndent(.normal);
14031397 try renderToken(r, cur - 1, .newline); // |
14041398 while (true) {
1405 if (token_tags[cur] == .asterisk) {
1399 if (tree.tokenTag(cur) == .asterisk) {
14061400 try renderToken(r, cur, .none); // *
14071401 cur += 1;
14081402 }
14091403 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
14101404 cur += 1;
1411 if (token_tags[cur] == .comma) {
1405 if (tree.tokenTag(cur) == .comma) {
14121406 try renderToken(r, cur, .newline); // ,
14131407 cur += 1;
14141408 }
1415 if (token_tags[cur] == .pipe) {
1409 if (tree.tokenTag(cur) == .pipe) {
14161410 break;
14171411 }
14181412 }
......@@ -1420,17 +1414,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
14201414 } else {
14211415 try renderToken(r, cur - 1, .none); // |
14221416 while (true) {
1423 if (token_tags[cur] == .asterisk) {
1417 if (tree.tokenTag(cur) == .asterisk) {
14241418 try renderToken(r, cur, .none); // *
14251419 cur += 1;
14261420 }
14271421 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
14281422 cur += 1;
1429 if (token_tags[cur] == .comma) {
1423 if (tree.tokenTag(cur) == .comma) {
14301424 try renderToken(r, cur, .space); // ,
14311425 cur += 1;
14321426 }
1433 if (token_tags[cur] == .pipe) {
1427 if (tree.tokenTag(cur) == .pipe) {
14341428 break;
14351429 }
14361430 }
......@@ -1456,7 +1450,7 @@ fn renderContainerField(
14561450 const tree = r.tree;
14571451 const ais = r.ais;
14581452 var field = field_param;
1459 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);
1453 if (container != .tuple) field.convertToNonTupleLike(&tree);
14601454 const quote: QuoteBehavior = switch (container) {
14611455 .@"enum" => .eagerly_unquote_except_underscore,
14621456 .tuple, .other => .eagerly_unquote,
......@@ -1465,67 +1459,74 @@ fn renderContainerField(
14651459 if (field.comptime_token) |t| {
14661460 try renderToken(r, t, .space); // comptime
14671461 }
1468 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {
1469 if (field.ast.align_expr != 0) {
1462 if (field.ast.type_expr == .none and field.ast.value_expr == .none) {
1463 if (field.ast.align_expr.unwrap()) |align_expr| {
14701464 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1471 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1465 const lparen_token = tree.firstToken(align_expr) - 1;
14721466 const align_kw = lparen_token - 1;
1473 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1467 const rparen_token = tree.lastToken(align_expr) + 1;
14741468 try renderToken(r, align_kw, .none); // align
14751469 try renderToken(r, lparen_token, .none); // (
1476 try renderExpression(r, field.ast.align_expr, .none); // alignment
1470 try renderExpression(r, align_expr, .none); // alignment
14771471 return renderToken(r, rparen_token, .space); // )
14781472 }
14791473 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
14801474 }
1481 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {
1475 if (field.ast.type_expr != .none and field.ast.value_expr == .none) {
1476 const type_expr = field.ast.type_expr.unwrap().?;
14821477 if (!field.ast.tuple_like) {
14831478 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
14841479 try renderToken(r, field.ast.main_token + 1, .space); // :
14851480 }
14861481
1487 if (field.ast.align_expr != 0) {
1488 try renderExpression(r, field.ast.type_expr, .space); // type
1489 const align_token = tree.firstToken(field.ast.align_expr) - 2;
1482 if (field.ast.align_expr.unwrap()) |align_expr| {
1483 try renderExpression(r, type_expr, .space); // type
1484 const align_token = tree.firstToken(align_expr) - 2;
14901485 try renderToken(r, align_token, .none); // align
14911486 try renderToken(r, align_token + 1, .none); // (
1492 try renderExpression(r, field.ast.align_expr, .none); // alignment
1493 const rparen = tree.lastToken(field.ast.align_expr) + 1;
1487 try renderExpression(r, align_expr, .none); // alignment
1488 const rparen = tree.lastToken(align_expr) + 1;
14941489 return renderTokenComma(r, rparen, space); // )
14951490 } else {
1496 return renderExpressionComma(r, field.ast.type_expr, space); // type
1491 return renderExpressionComma(r, type_expr, space); // type
14971492 }
14981493 }
1499 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
1494 if (field.ast.type_expr == .none and field.ast.value_expr != .none) {
1495 const value_expr = field.ast.value_expr.unwrap().?;
1496
15001497 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1501 if (field.ast.align_expr != 0) {
1502 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1498 if (field.ast.align_expr.unwrap()) |align_expr| {
1499 const lparen_token = tree.firstToken(align_expr) - 1;
15031500 const align_kw = lparen_token - 1;
1504 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1501 const rparen_token = tree.lastToken(align_expr) + 1;
15051502 try renderToken(r, align_kw, .none); // align
15061503 try renderToken(r, lparen_token, .none); // (
1507 try renderExpression(r, field.ast.align_expr, .none); // alignment
1504 try renderExpression(r, align_expr, .none); // alignment
15081505 try renderToken(r, rparen_token, .space); // )
15091506 }
15101507 try renderToken(r, field.ast.main_token + 1, .space); // =
1511 return renderExpressionComma(r, field.ast.value_expr, space); // value
1508 return renderExpressionComma(r, value_expr, space); // value
15121509 }
15131510 if (!field.ast.tuple_like) {
15141511 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
15151512 try renderToken(r, field.ast.main_token + 1, .space); // :
15161513 }
1517 try renderExpression(r, field.ast.type_expr, .space); // type
15181514
1519 if (field.ast.align_expr != 0) {
1520 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
1515 const type_expr = field.ast.type_expr.unwrap().?;
1516 const value_expr = field.ast.value_expr.unwrap().?;
1517
1518 try renderExpression(r, type_expr, .space); // type
1519
1520 if (field.ast.align_expr.unwrap()) |align_expr| {
1521 const lparen_token = tree.firstToken(align_expr) - 1;
15211522 const align_kw = lparen_token - 1;
1522 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
1523 const rparen_token = tree.lastToken(align_expr) + 1;
15231524 try renderToken(r, align_kw, .none); // align
15241525 try renderToken(r, lparen_token, .none); // (
1525 try renderExpression(r, field.ast.align_expr, .none); // alignment
1526 try renderExpression(r, align_expr, .none); // alignment
15261527 try renderToken(r, rparen_token, .space); // )
15271528 }
1528 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
1529 const eq_token = tree.firstToken(value_expr) - 1;
15291530 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
15301531
15311532 try ais.pushIndent(.after_equals);
......@@ -1533,19 +1534,18 @@ fn renderContainerField(
15331534
15341535 if (eq_space == .space) {
15351536 ais.popIndent();
1536 try renderExpressionComma(r, field.ast.value_expr, space); // value
1537 try renderExpressionComma(r, value_expr, space); // value
15371538 return;
15381539 }
15391540
1540 const token_tags = tree.tokens.items(.tag);
1541 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
1541 const maybe_comma = tree.lastToken(value_expr) + 1;
15421542
1543 if (token_tags[maybe_comma] == .comma) {
1544 try renderExpression(r, field.ast.value_expr, .none); // value
1543 if (tree.tokenTag(maybe_comma) == .comma) {
1544 try renderExpression(r, value_expr, .none); // value
15451545 ais.popIndent();
15461546 try renderToken(r, maybe_comma, .newline);
15471547 } else {
1548 try renderExpression(r, field.ast.value_expr, space); // value
1548 try renderExpression(r, value_expr, space); // value
15491549 ais.popIndent();
15501550 }
15511551}
......@@ -1558,8 +1558,6 @@ fn renderBuiltinCall(
15581558) Error!void {
15591559 const tree = r.tree;
15601560 const ais = r.ais;
1561 const token_tags = tree.tokens.items(.tag);
1562 const main_tokens = tree.nodes.items(.main_token);
15631561
15641562 try renderToken(r, builtin_token, .none); // @name
15651563
......@@ -1572,8 +1570,8 @@ fn renderBuiltinCall(
15721570 const slice = tree.tokenSlice(builtin_token);
15731571 if (mem.eql(u8, slice, "@import")) f: {
15741572 const param = params[0];
1575 const str_lit_token = main_tokens[param];
1576 assert(token_tags[str_lit_token] == .string_literal);
1573 const str_lit_token = tree.nodeMainToken(param);
1574 assert(tree.tokenTag(str_lit_token) == .string_literal);
15771575 const token_bytes = tree.tokenSlice(str_lit_token);
15781576 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {
15791577 error.OutOfMemory => return error.OutOfMemory,
......@@ -1592,13 +1590,13 @@ fn renderBuiltinCall(
15921590 const last_param = params[params.len - 1];
15931591 const after_last_param_token = tree.lastToken(last_param) + 1;
15941592
1595 if (token_tags[after_last_param_token] != .comma) {
1593 if (tree.tokenTag(after_last_param_token) != .comma) {
15961594 // Render all on one line, no trailing comma.
15971595 try renderToken(r, builtin_token + 1, .none); // (
15981596
15991597 for (params, 0..) |param_node, i| {
16001598 const first_param_token = tree.firstToken(param_node);
1601 if (token_tags[first_param_token] == .multiline_string_literal_line or
1599 if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or
16021600 hasSameLineComment(tree, first_param_token - 1))
16031601 {
16041602 try ais.pushIndent(.normal);
......@@ -1633,11 +1631,9 @@ fn renderBuiltinCall(
16331631fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
16341632 const tree = r.tree;
16351633 const ais = r.ais;
1636 const token_tags = tree.tokens.items(.tag);
1637 const token_starts = tree.tokens.items(.start);
16381634
16391635 const after_fn_token = fn_proto.ast.fn_token + 1;
1640 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {
1636 const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: {
16411637 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
16421638 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
16431639 break :blk after_fn_token + 1;
......@@ -1645,41 +1641,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
16451641 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
16461642 break :blk fn_proto.ast.fn_token + 1;
16471643 };
1648 assert(token_tags[lparen] == .l_paren);
1644 assert(tree.tokenTag(lparen) == .l_paren);
16491645
1650 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
1646 const return_type = fn_proto.ast.return_type.unwrap().?;
1647 const maybe_bang = tree.firstToken(return_type) - 1;
16511648 const rparen = blk: {
16521649 // These may appear in any order, so we have to check the token_starts array
16531650 // to find out which is first.
1654 var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang;
1655 var smallest_start = token_starts[maybe_bang];
1656 if (fn_proto.ast.align_expr != 0) {
1657 const tok = tree.firstToken(fn_proto.ast.align_expr) - 3;
1658 const start = token_starts[tok];
1651 var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang;
1652 var smallest_start = tree.tokenStart(maybe_bang);
1653 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1654 const tok = tree.firstToken(align_expr) - 3;
1655 const start = tree.tokenStart(tok);
16591656 if (start < smallest_start) {
16601657 rparen = tok;
16611658 smallest_start = start;
16621659 }
16631660 }
1664 if (fn_proto.ast.addrspace_expr != 0) {
1665 const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3;
1666 const start = token_starts[tok];
1661 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1662 const tok = tree.firstToken(addrspace_expr) - 3;
1663 const start = tree.tokenStart(tok);
16671664 if (start < smallest_start) {
16681665 rparen = tok;
16691666 smallest_start = start;
16701667 }
16711668 }
1672 if (fn_proto.ast.section_expr != 0) {
1673 const tok = tree.firstToken(fn_proto.ast.section_expr) - 3;
1674 const start = token_starts[tok];
1669 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1670 const tok = tree.firstToken(section_expr) - 3;
1671 const start = tree.tokenStart(tok);
16751672 if (start < smallest_start) {
16761673 rparen = tok;
16771674 smallest_start = start;
16781675 }
16791676 }
1680 if (fn_proto.ast.callconv_expr != 0) {
1681 const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3;
1682 const start = token_starts[tok];
1677 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1678 const tok = tree.firstToken(callconv_expr) - 3;
1679 const start = tree.tokenStart(tok);
16831680 if (start < smallest_start) {
16841681 rparen = tok;
16851682 smallest_start = start;
......@@ -1687,11 +1684,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
16871684 }
16881685 break :blk rparen;
16891686 };
1690 assert(token_tags[rparen] == .r_paren);
1687 assert(tree.tokenTag(rparen) == .r_paren);
16911688
16921689 // The params list is a sparse set that does *not* include anytype or ... parameters.
16931690
1694 const trailing_comma = token_tags[rparen - 1] == .comma;
1691 const trailing_comma = tree.tokenTag(rparen - 1) == .comma;
16951692 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
16961693 // Render all on one line, no trailing comma.
16971694 try renderToken(r, lparen, .none); // (
......@@ -1700,7 +1697,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17001697 var last_param_token = lparen;
17011698 while (true) {
17021699 last_param_token += 1;
1703 switch (token_tags[last_param_token]) {
1700 switch (tree.tokenTag(last_param_token)) {
17041701 .doc_comment => {
17051702 try renderToken(r, last_param_token, .newline);
17061703 continue;
......@@ -1725,15 +1722,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17251722 },
17261723 else => {}, // Parameter type without a name.
17271724 }
1728 if (token_tags[last_param_token] == .identifier and
1729 token_tags[last_param_token + 1] == .colon)
1725 if (tree.tokenTag(last_param_token) == .identifier and
1726 tree.tokenTag(last_param_token + 1) == .colon)
17301727 {
17311728 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1732 last_param_token += 1;
1729 last_param_token = last_param_token + 1;
17331730 try renderToken(r, last_param_token, .space); // :
17341731 last_param_token += 1;
17351732 }
1736 if (token_tags[last_param_token] == .keyword_anytype) {
1733 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
17371734 try renderToken(r, last_param_token, .none); // anytype
17381735 continue;
17391736 }
......@@ -1751,7 +1748,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17511748 var last_param_token = lparen;
17521749 while (true) {
17531750 last_param_token += 1;
1754 switch (token_tags[last_param_token]) {
1751 switch (tree.tokenTag(last_param_token)) {
17551752 .doc_comment => {
17561753 try renderToken(r, last_param_token, .newline);
17571754 continue;
......@@ -1767,24 +1764,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17671764 .identifier => {},
17681765 .keyword_anytype => {
17691766 try renderToken(r, last_param_token, .comma); // anytype
1770 if (token_tags[last_param_token + 1] == .comma)
1767 if (tree.tokenTag(last_param_token + 1) == .comma)
17711768 last_param_token += 1;
17721769 continue;
17731770 },
17741771 .r_paren => break,
17751772 else => {}, // Parameter type without a name.
17761773 }
1777 if (token_tags[last_param_token] == .identifier and
1778 token_tags[last_param_token + 1] == .colon)
1774 if (tree.tokenTag(last_param_token) == .identifier and
1775 tree.tokenTag(last_param_token + 1) == .colon)
17791776 {
17801777 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
17811778 last_param_token += 1;
17821779 try renderToken(r, last_param_token, .space); // :
17831780 last_param_token += 1;
17841781 }
1785 if (token_tags[last_param_token] == .keyword_anytype) {
1782 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
17861783 try renderToken(r, last_param_token, .comma); // anytype
1787 if (token_tags[last_param_token + 1] == .comma)
1784 if (tree.tokenTag(last_param_token + 1) == .comma)
17881785 last_param_token += 1;
17891786 continue;
17901787 }
......@@ -1794,60 +1791,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
17941791 try renderExpression(r, param, .comma);
17951792 ais.popSpace();
17961793 last_param_token = tree.lastToken(param);
1797 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;
1794 if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1;
17981795 }
17991796 ais.popIndent();
18001797 }
18011798
18021799 try renderToken(r, rparen, .space); // )
18031800
1804 if (fn_proto.ast.align_expr != 0) {
1805 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;
1806 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;
1801 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1802 const align_lparen = tree.firstToken(align_expr) - 1;
1803 const align_rparen = tree.lastToken(align_expr) + 1;
18071804
18081805 try renderToken(r, align_lparen - 1, .none); // align
18091806 try renderToken(r, align_lparen, .none); // (
1810 try renderExpression(r, fn_proto.ast.align_expr, .none);
1807 try renderExpression(r, align_expr, .none);
18111808 try renderToken(r, align_rparen, .space); // )
18121809 }
18131810
1814 if (fn_proto.ast.addrspace_expr != 0) {
1815 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;
1816 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;
1811 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1812 const align_lparen = tree.firstToken(addrspace_expr) - 1;
1813 const align_rparen = tree.lastToken(addrspace_expr) + 1;
18171814
18181815 try renderToken(r, align_lparen - 1, .none); // addrspace
18191816 try renderToken(r, align_lparen, .none); // (
1820 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);
1817 try renderExpression(r, addrspace_expr, .none);
18211818 try renderToken(r, align_rparen, .space); // )
18221819 }
18231820
1824 if (fn_proto.ast.section_expr != 0) {
1825 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;
1826 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;
1821 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1822 const section_lparen = tree.firstToken(section_expr) - 1;
1823 const section_rparen = tree.lastToken(section_expr) + 1;
18271824
18281825 try renderToken(r, section_lparen - 1, .none); // section
18291826 try renderToken(r, section_lparen, .none); // (
1830 try renderExpression(r, fn_proto.ast.section_expr, .none);
1827 try renderExpression(r, section_expr, .none);
18311828 try renderToken(r, section_rparen, .space); // )
18321829 }
18331830
1834 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1835 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));
1836 const is_declaration = fn_proto.name_token != null;
1837 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {
1838 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;
1839 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;
1831 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1832 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1833 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)));
1834 const is_declaration = fn_proto.name_token != null;
1835 if (!(is_declaration and is_callconv_inline)) {
1836 const callconv_lparen = tree.firstToken(callconv_expr) - 1;
1837 const callconv_rparen = tree.lastToken(callconv_expr) + 1;
18401838
1841 try renderToken(r, callconv_lparen - 1, .none); // callconv
1842 try renderToken(r, callconv_lparen, .none); // (
1843 try renderExpression(r, fn_proto.ast.callconv_expr, .none);
1844 try renderToken(r, callconv_rparen, .space); // )
1839 try renderToken(r, callconv_lparen - 1, .none); // callconv
1840 try renderToken(r, callconv_lparen, .none); // (
1841 try renderExpression(r, callconv_expr, .none);
1842 try renderToken(r, callconv_rparen, .space); // )
1843 }
18451844 }
18461845
1847 if (token_tags[maybe_bang] == .bang) {
1846 if (tree.tokenTag(maybe_bang) == .bang) {
18481847 try renderToken(r, maybe_bang, .none); // !
18491848 }
1850 return renderExpression(r, fn_proto.ast.return_type, space);
1849 return renderExpression(r, return_type, space);
18511850}
18521851
18531852fn renderSwitchCase(
......@@ -1857,9 +1856,7 @@ fn renderSwitchCase(
18571856) Error!void {
18581857 const ais = r.ais;
18591858 const tree = r.tree;
1860 const node_tags = tree.nodes.items(.tag);
1861 const token_tags = tree.tokens.items(.tag);
1862 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
1859 const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
18631860 const has_comment_before_arrow = blk: {
18641861 if (switch_case.ast.values.len == 0) break :blk false;
18651862 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);
......@@ -1886,7 +1883,7 @@ fn renderSwitchCase(
18861883 }
18871884
18881885 // Render the arrow and everything after it
1889 const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal)
1886 const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal)
18901887 // Newline gets inserted when rendering the target expr.
18911888 Space.none
18921889 else
......@@ -1896,12 +1893,12 @@ fn renderSwitchCase(
18961893
18971894 if (switch_case.payload_token) |payload_token| {
18981895 try renderToken(r, payload_token - 1, .none); // pipe
1899 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);
1900 if (token_tags[payload_token] == .asterisk) {
1896 const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk);
1897 if (tree.tokenTag(payload_token) == .asterisk) {
19011898 try renderToken(r, payload_token, .none); // asterisk
19021899 }
19031900 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1904 if (token_tags[ident + 1] == .comma) {
1901 if (tree.tokenTag(ident + 1) == .comma) {
19051902 try renderToken(r, ident + 1, .space); // ,
19061903 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
19071904 try renderToken(r, ident + 3, pre_target_space); // pipe
......@@ -1921,12 +1918,9 @@ fn renderBlock(
19211918) Error!void {
19221919 const tree = r.tree;
19231920 const ais = r.ais;
1924 const token_tags = tree.tokens.items(.tag);
1925 const lbrace = tree.nodes.items(.main_token)[block_node];
1921 const lbrace = tree.nodeMainToken(block_node);
19261922
1927 if (token_tags[lbrace - 1] == .colon and
1928 token_tags[lbrace - 2] == .identifier)
1929 {
1923 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
19301924 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
19311925 try renderToken(r, lbrace - 1, .space); // :
19321926 }
......@@ -1948,13 +1942,12 @@ fn finishRenderBlock(
19481942 space: Space,
19491943) Error!void {
19501944 const tree = r.tree;
1951 const node_tags = tree.nodes.items(.tag);
19521945 const ais = r.ais;
19531946 for (statements, 0..) |stmt, i| {
19541947 if (i != 0) try renderExtraNewline(r, stmt);
19551948 if (r.fixups.omit_nodes.contains(stmt)) continue;
19561949 try ais.pushSpace(.semicolon);
1957 switch (node_tags[stmt]) {
1950 switch (tree.nodeTag(stmt)) {
19581951 .global_var_decl,
19591952 .local_var_decl,
19601953 .simple_var_decl,
......@@ -1978,12 +1971,13 @@ fn renderStructInit(
19781971) Error!void {
19791972 const tree = r.tree;
19801973 const ais = r.ais;
1981 const token_tags = tree.tokens.items(.tag);
1982 if (struct_init.ast.type_expr == 0) {
1983 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
1974
1975 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
1976 try renderExpression(r, type_expr, .none); // T
19841977 } else {
1985 try renderExpression(r, struct_init.ast.type_expr, .none); // T
1978 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
19861979 }
1980
19871981 if (struct_init.ast.fields.len == 0) {
19881982 try ais.pushIndent(.normal);
19891983 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
......@@ -1992,7 +1986,7 @@ fn renderStructInit(
19921986 }
19931987
19941988 const rbrace = tree.lastToken(struct_node);
1995 const trailing_comma = token_tags[rbrace - 1] == .comma;
1989 const trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
19961990 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
19971991 // Render one field init per line.
19981992 try ais.pushIndent(.normal);
......@@ -2002,9 +1996,8 @@ fn renderStructInit(
20021996 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
20031997 // Don't output a space after the = if expression is a multiline string,
20041998 // since then it will start on the next line.
2005 const nodes = tree.nodes.items(.tag);
20061999 const field_node = struct_init.ast.fields[0];
2007 const expr = nodes[field_node];
2000 const expr = tree.nodeTag(field_node);
20082001 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
20092002 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
20102003
......@@ -2017,7 +2010,7 @@ fn renderStructInit(
20172010 try renderExtraNewlineToken(r, init_token - 3);
20182011 try renderToken(r, init_token - 3, .none); // .
20192012 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
2020 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;
2013 space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
20212014 try renderToken(r, init_token - 1, space_after_equal); // =
20222015
20232016 try ais.pushSpace(.comma);
......@@ -2050,12 +2043,11 @@ fn renderArrayInit(
20502043 const tree = r.tree;
20512044 const ais = r.ais;
20522045 const gpa = r.gpa;
2053 const token_tags = tree.tokens.items(.tag);
20542046
2055 if (array_init.ast.type_expr == 0) {
2056 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
2047 if (array_init.ast.type_expr.unwrap()) |type_expr| {
2048 try renderExpression(r, type_expr, .none); // T
20572049 } else {
2058 try renderExpression(r, array_init.ast.type_expr, .none); // T
2050 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
20592051 }
20602052
20612053 if (array_init.ast.elements.len == 0) {
......@@ -2067,14 +2059,14 @@ fn renderArrayInit(
20672059
20682060 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
20692061 const last_elem_token = tree.lastToken(last_elem);
2070 const trailing_comma = token_tags[last_elem_token + 1] == .comma;
2062 const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma;
20712063 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;
2072 assert(token_tags[rbrace] == .r_brace);
2064 assert(tree.tokenTag(rbrace) == .r_brace);
20732065
20742066 if (array_init.ast.elements.len == 1) {
20752067 const only_elem = array_init.ast.elements[0];
20762068 const first_token = tree.firstToken(only_elem);
2077 if (token_tags[first_token] != .multiline_string_literal_line and
2069 if (tree.tokenTag(first_token) != .multiline_string_literal_line and
20782070 !anythingBetween(tree, last_elem_token, rbrace))
20792071 {
20802072 try renderToken(r, array_init.ast.lbrace, .none);
......@@ -2137,7 +2129,7 @@ fn renderArrayInit(
21372129 }
21382130
21392131 const maybe_comma = expr_last_token + 1;
2140 if (token_tags[maybe_comma] == .comma) {
2132 if (tree.tokenTag(maybe_comma) == .comma) {
21412133 if (hasSameLineComment(tree, maybe_comma))
21422134 break :sec_end i - this_line_size + 1;
21432135 }
......@@ -2277,13 +2269,12 @@ fn renderContainerDecl(
22772269) Error!void {
22782270 const tree = r.tree;
22792271 const ais = r.ais;
2280 const token_tags = tree.tokens.items(.tag);
22812272
22822273 if (container_decl.layout_token) |layout_token| {
22832274 try renderToken(r, layout_token, .space);
22842275 }
22852276
2286 const container: Container = switch (token_tags[container_decl.ast.main_token]) {
2277 const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) {
22872278 .keyword_enum => .@"enum",
22882279 .keyword_struct => for (container_decl.ast.members) |member| {
22892280 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
......@@ -2296,10 +2287,10 @@ fn renderContainerDecl(
22962287 try renderToken(r, container_decl.ast.main_token, .none); // union
22972288 try renderToken(r, enum_token - 1, .none); // lparen
22982289 try renderToken(r, enum_token, .none); // enum
2299 if (container_decl.ast.arg != 0) {
2290 if (container_decl.ast.arg.unwrap()) |arg| {
23002291 try renderToken(r, enum_token + 1, .none); // lparen
2301 try renderExpression(r, container_decl.ast.arg, .none);
2302 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2292 try renderExpression(r, arg, .none);
2293 const rparen = tree.lastToken(arg) + 1;
23032294 try renderToken(r, rparen, .none); // rparen
23042295 try renderToken(r, rparen + 1, .space); // rparen
23052296 lbrace = rparen + 2;
......@@ -2307,11 +2298,11 @@ fn renderContainerDecl(
23072298 try renderToken(r, enum_token + 1, .space); // rparen
23082299 lbrace = enum_token + 2;
23092300 }
2310 } else if (container_decl.ast.arg != 0) {
2301 } else if (container_decl.ast.arg.unwrap()) |arg| {
23112302 try renderToken(r, container_decl.ast.main_token, .none); // union
23122303 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2313 try renderExpression(r, container_decl.ast.arg, .none);
2314 const rparen = tree.lastToken(container_decl.ast.arg) + 1;
2304 try renderExpression(r, arg, .none);
2305 const rparen = tree.lastToken(arg) + 1;
23152306 try renderToken(r, rparen, .space); // rparen
23162307 lbrace = rparen + 1;
23172308 } else {
......@@ -2320,9 +2311,10 @@ fn renderContainerDecl(
23202311 }
23212312
23222313 const rbrace = tree.lastToken(container_decl_node);
2314
23232315 if (container_decl.ast.members.len == 0) {
23242316 try ais.pushIndent(.normal);
2325 if (token_tags[lbrace + 1] == .container_doc_comment) {
2317 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
23262318 try renderToken(r, lbrace, .newline); // lbrace
23272319 try renderContainerDocComments(r, lbrace + 1);
23282320 } else {
......@@ -2332,7 +2324,7 @@ fn renderContainerDecl(
23322324 return renderToken(r, rbrace, space); // rbrace
23332325 }
23342326
2335 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;
2327 const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
23362328 if (!src_has_trailing_comma) one_line: {
23372329 // We print all the members in-line unless one of the following conditions are true:
23382330
......@@ -2342,10 +2334,10 @@ fn renderContainerDecl(
23422334 }
23432335
23442336 // 2. The container has a container comment.
2345 if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line;
2337 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line;
23462338
23472339 // 3. A member of the container has a doc comment.
2348 for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| {
2340 for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| {
23492341 if (tag == .doc_comment) break :one_line;
23502342 }
23512343
......@@ -2365,12 +2357,12 @@ fn renderContainerDecl(
23652357 // One member per line.
23662358 try ais.pushIndent(.normal);
23672359 try renderToken(r, lbrace, .newline); // lbrace
2368 if (token_tags[lbrace + 1] == .container_doc_comment) {
2360 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
23692361 try renderContainerDocComments(r, lbrace + 1);
23702362 }
23712363 for (container_decl.ast.members, 0..) |member, i| {
23722364 if (i != 0) try renderExtraNewline(r, member);
2373 switch (tree.nodes.items(.tag)[member]) {
2365 switch (tree.nodeTag(member)) {
23742366 // For container fields, ensure a trailing comma is added if necessary.
23752367 .container_field_init,
23762368 .container_field_align,
......@@ -2396,7 +2388,6 @@ fn renderAsm(
23962388) Error!void {
23972389 const tree = r.tree;
23982390 const ais = r.ais;
2399 const token_tags = tree.tokens.items(.tag);
24002391
24012392 try renderToken(r, asm_node.ast.asm_token, .space); // asm
24022393
......@@ -2422,13 +2413,13 @@ fn renderAsm(
24222413 while (true) : (tok_i += 1) {
24232414 try renderToken(r, tok_i, .none);
24242415 tok_i += 1;
2425 switch (token_tags[tok_i]) {
2416 switch (tree.tokenTag(tok_i)) {
24262417 .r_paren => {
24272418 ais.popIndent();
24282419 return renderToken(r, tok_i, space);
24292420 },
24302421 .comma => {
2431 if (token_tags[tok_i + 1] == .r_paren) {
2422 if (tree.tokenTag(tok_i + 1) == .r_paren) {
24322423 ais.popIndent();
24332424 return renderToken(r, tok_i + 1, space);
24342425 } else {
......@@ -2480,7 +2471,7 @@ fn renderAsm(
24802471 ais.popSpace();
24812472 const comma_or_colon = tree.lastToken(asm_output) + 1;
24822473 ais.popIndent();
2483 break :colon2 switch (token_tags[comma_or_colon]) {
2474 break :colon2 switch (tree.tokenTag(comma_or_colon)) {
24842475 .comma => comma_or_colon + 1,
24852476 else => comma_or_colon,
24862477 };
......@@ -2516,7 +2507,7 @@ fn renderAsm(
25162507 ais.popSpace();
25172508 const comma_or_colon = tree.lastToken(asm_input) + 1;
25182509 ais.popIndent();
2519 break :colon3 switch (token_tags[comma_or_colon]) {
2510 break :colon3 switch (tree.tokenTag(comma_or_colon)) {
25202511 .comma => comma_or_colon + 1,
25212512 else => comma_or_colon,
25222513 };
......@@ -2529,7 +2520,7 @@ fn renderAsm(
25292520 const first_clobber = asm_node.first_clobber.?;
25302521 var tok_i = first_clobber;
25312522 while (true) {
2532 switch (token_tags[tok_i + 1]) {
2523 switch (tree.tokenTag(tok_i + 1)) {
25332524 .r_paren => {
25342525 ais.setIndentDelta(indent_delta);
25352526 try renderToken(r, tok_i, .newline);
......@@ -2537,7 +2528,7 @@ fn renderAsm(
25372528 return renderToken(r, tok_i + 1, space);
25382529 },
25392530 .comma => {
2540 switch (token_tags[tok_i + 2]) {
2531 switch (tree.tokenTag(tok_i + 2)) {
25412532 .r_paren => {
25422533 ais.setIndentDelta(indent_delta);
25432534 try renderToken(r, tok_i, .newline);
......@@ -2576,7 +2567,6 @@ fn renderParamList(
25762567) Error!void {
25772568 const tree = r.tree;
25782569 const ais = r.ais;
2579 const token_tags = tree.tokens.items(.tag);
25802570
25812571 if (params.len == 0) {
25822572 try ais.pushIndent(.normal);
......@@ -2587,7 +2577,7 @@ fn renderParamList(
25872577
25882578 const last_param = params[params.len - 1];
25892579 const after_last_param_tok = tree.lastToken(last_param) + 1;
2590 if (token_tags[after_last_param_tok] == .comma) {
2580 if (tree.tokenTag(after_last_param_tok) == .comma) {
25912581 try ais.pushIndent(.normal);
25922582 try renderToken(r, lparen, .newline); // (
25932583 for (params, 0..) |param_node, i| {
......@@ -2616,7 +2606,7 @@ fn renderParamList(
26162606 if (i + 1 < params.len) {
26172607 const comma = tree.lastToken(param_node) + 1;
26182608 const next_multiline_string =
2619 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;
2609 tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line;
26202610 const comma_space: Space = if (next_multiline_string) .none else .space;
26212611 try renderToken(r, comma, comma_space);
26222612 }
......@@ -2629,9 +2619,8 @@ fn renderParamList(
26292619/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26302620fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
26312621 const tree = r.tree;
2632 const token_tags = tree.tokens.items(.tag);
26332622 const maybe_comma = tree.lastToken(node) + 1;
2634 if (token_tags[maybe_comma] == .comma and space != .comma) {
2623 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26352624 try renderExpression(r, node, .none);
26362625 return renderToken(r, maybe_comma, space);
26372626 } else {
......@@ -2643,9 +2632,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v
26432632/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26442633fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
26452634 const tree = r.tree;
2646 const token_tags = tree.tokens.items(.tag);
26472635 const maybe_comma = token + 1;
2648 if (token_tags[maybe_comma] == .comma and space != .comma) {
2636 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26492637 try renderToken(r, token, .none);
26502638 return renderToken(r, maybe_comma, space);
26512639 } else {
......@@ -2657,9 +2645,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void
26572645/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
26582646fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
26592647 const tree = r.tree;
2660 const token_tags = tree.tokens.items(.tag);
26612648 const maybe_comma = token + 1;
2662 if (token_tags[maybe_comma] == .comma and space != .comma) {
2649 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
26632650 try renderIdentifier(r, token, .none, quote);
26642651 return renderToken(r, maybe_comma, space);
26652652 } else {
......@@ -2709,37 +2696,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
27092696fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
27102697 const tree = r.tree;
27112698 const ais = r.ais;
2712 const token_tags = tree.tokens.items(.tag);
2713 const token_starts = tree.tokens.items(.start);
27142699
2715 const token_start = token_starts[token_index];
2700 const next_token_tag = tree.tokenTag(token_index + 1);
27162701
27172702 if (space == .skip) return;
27182703
2719 if (space == .comma and token_tags[token_index + 1] != .comma) {
2704 if (space == .comma and next_token_tag != .comma) {
27202705 try ais.writer().writeByte(',');
27212706 }
27222707 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
27232708 defer ais.disableSpaceMode();
2724 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);
2709 const comment = try renderComments(
2710 r,
2711 tree.tokenStart(token_index) + lexeme_len,
2712 tree.tokenStart(token_index + 1),
2713 );
27252714 switch (space) {
27262715 .none => {},
27272716 .space => if (!comment) try ais.writer().writeByte(' '),
27282717 .newline => if (!comment) try ais.insertNewline(),
27292718
2730 .comma => if (token_tags[token_index + 1] == .comma) {
2719 .comma => if (next_token_tag == .comma) {
27312720 try renderToken(r, token_index + 1, .newline);
27322721 } else if (!comment) {
27332722 try ais.insertNewline();
27342723 },
27352724
2736 .comma_space => if (token_tags[token_index + 1] == .comma) {
2725 .comma_space => if (next_token_tag == .comma) {
27372726 try renderToken(r, token_index + 1, .space);
27382727 } else if (!comment) {
27392728 try ais.writer().writeByte(' ');
27402729 },
27412730
2742 .semicolon => if (token_tags[token_index + 1] == .semicolon) {
2731 .semicolon => if (next_token_tag == .semicolon) {
27432732 try renderToken(r, token_index + 1, .newline);
27442733 } else if (!comment) {
27452734 try ais.insertNewline();
......@@ -2770,8 +2759,7 @@ const QuoteBehavior = enum {
27702759
27712760fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
27722761 const tree = r.tree;
2773 const token_tags = tree.tokens.items(.tag);
2774 assert(token_tags[token_index] == .identifier);
2762 assert(tree.tokenTag(token_index) == .identifier);
27752763 const lexeme = tokenSliceForRender(tree, token_index);
27762764
27772765 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
......@@ -2880,8 +2868,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote
28802868fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
28812869 const tree = r.tree;
28822870 const ais = r.ais;
2883 const token_tags = tree.tokens.items(.tag);
2884 assert(token_tags[token_index] == .identifier);
2871 assert(tree.tokenTag(token_index) == .identifier);
28852872 const lexeme = tokenSliceForRender(tree, token_index);
28862873 assert(lexeme.len >= 3 and lexeme[0] == '@');
28872874
......@@ -2934,12 +2921,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
29342921/// fn_proto should be wrapped and have a trailing comma inserted even if
29352922/// there is none in the source.
29362923fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2937 const token_starts = tree.tokens.items(.start);
2938
2939 var i = start_token;
2940 while (i < end_token) : (i += 1) {
2941 const start = token_starts[i] + tree.tokenSlice(i).len;
2942 const end = token_starts[i + 1];
2924 for (start_token..end_token) |i| {
2925 const token: Ast.TokenIndex = @intCast(i);
2926 const start = tree.tokenStart(token) + tree.tokenSlice(token).len;
2927 const end = tree.tokenStart(token + 1);
29432928 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;
29442929 }
29452930
......@@ -2949,16 +2934,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)
29492934/// Returns true if there exists a multiline string literal between the start
29502935/// of token `start_token` and the start of token `end_token`.
29512936fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2952 const token_tags = tree.tokens.items(.tag);
2953
2954 for (token_tags[start_token..end_token]) |tag| {
2955 switch (tag) {
2956 .multiline_string_literal_line => return true,
2957 else => continue,
2958 }
2959 }
2960
2961 return false;
2937 return std.mem.indexOfScalar(
2938 Token.Tag,
2939 tree.tokens.items(.tag)[start_token..end_token],
2940 .multiline_string_literal_line,
2941 ) != null;
29622942}
29632943
29642944/// Assumes that start is the first byte past the previous token and
......@@ -3034,18 +3014,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
30343014fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
30353015 const tree = r.tree;
30363016 const ais = r.ais;
3037 const token_starts = tree.tokens.items(.start);
3038 const token_start = token_starts[token_index];
3017 const token_start = tree.tokenStart(token_index);
30393018 if (token_start == 0) return;
30403019 const prev_token_end = if (token_index == 0)
30413020 0
30423021 else
3043 token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len;
3022 tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len;
30443023
30453024 // If there is a immediately preceding comment or doc_comment,
30463025 // skip it because required extra newline has already been rendered.
30473026 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;
3048 if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return;
3027 if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return;
30493028
30503029 // Iterate backwards to the end of the previous token, stopping if a
30513030 // non-whitespace character is encountered or two newlines have been found.
......@@ -3063,10 +3042,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
30633042fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
30643043 const tree = r.tree;
30653044 // Search backwards for the first doc comment.
3066 const token_tags = tree.tokens.items(.tag);
30673045 if (end_token == 0) return;
30683046 var tok = end_token - 1;
3069 while (token_tags[tok] == .doc_comment) {
3047 while (tree.tokenTag(tok) == .doc_comment) {
30703048 if (tok == 0) break;
30713049 tok -= 1;
30723050 } else {
......@@ -3076,7 +3054,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
30763054 if (first_tok == end_token) return;
30773055
30783056 if (first_tok != 0) {
3079 const prev_token_tag = token_tags[first_tok - 1];
3057 const prev_token_tag = tree.tokenTag(first_tok - 1);
30803058
30813059 // Prevent accidental use of `renderDocComments` for a function argument doc comment
30823060 assert(prev_token_tag != .l_paren);
......@@ -3086,7 +3064,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
30863064 }
30873065 }
30883066
3089 while (token_tags[tok] == .doc_comment) : (tok += 1) {
3067 while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) {
30903068 try renderToken(r, tok, .newline);
30913069 }
30923070}
......@@ -3094,15 +3072,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
30943072/// start_token is first container doc comment token.
30953073fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
30963074 const tree = r.tree;
3097 const token_tags = tree.tokens.items(.tag);
30983075 var tok = start_token;
3099 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {
3076 while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
31003077 try renderToken(r, tok, .newline);
31013078 }
31023079 // Render extra newline if there is one between final container doc comment and
31033080 // the next token. If the next token is a doc comment, that code path
31043081 // will have its own logic to insert a newline.
3105 if (token_tags[tok] != .doc_comment) {
3082 if (tree.tokenTag(tok) != .doc_comment) {
31063083 try renderExtraNewlineToken(r, tok);
31073084 }
31083085}
......@@ -3112,11 +3089,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31123089 const ais = r.ais;
31133090 var buf: [1]Ast.Node.Index = undefined;
31143091 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;
3115 const token_tags = tree.tokens.items(.tag);
31163092 var it = fn_proto.iterate(tree);
31173093 while (it.next()) |param| {
31183094 const name_ident = param.name_token.?;
3119 assert(token_tags[name_ident] == .identifier);
3095 assert(tree.tokenTag(name_ident) == .identifier);
31203096 const w = ais.writer();
31213097 try w.writeAll("_ = ");
31223098 try w.writeAll(tokenSliceForRender(r.tree, name_ident));
......@@ -3126,7 +3102,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31263102
31273103fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
31283104 var ret = tree.tokenSlice(token_index);
3129 switch (tree.tokens.items(.tag)[token_index]) {
3105 switch (tree.tokenTag(token_index)) {
31303106 .container_doc_comment, .doc_comment => {
31313107 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);
31323108 },
......@@ -3136,8 +3112,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
31363112}
31373113
31383114fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3139 const token_starts = tree.tokens.items(.start);
3140 const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]];
3115 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
31413116 for (between_source) |byte| switch (byte) {
31423117 '\n' => return false,
31433118 '/' => return true,
......@@ -3150,8 +3125,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
31503125/// start_token and end_token.
31513126fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
31523127 if (start_token + 1 != end_token) return true;
3153 const token_starts = tree.tokens.items(.start);
3154 const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]];
3128 const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)];
31553129 for (between_source) |byte| switch (byte) {
31563130 '/' => return true,
31573131 else => continue,
......@@ -3245,12 +3219,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {
32453219
32463220// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.
32473221fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {
3248 const token_tags = tree.tokens.items(.tag);
3249
32503222 const first_token = tree.firstToken(exprs[0]);
32513223 if (tree.tokensOnSameLine(first_token, rtoken)) {
32523224 const maybe_comma = rtoken - 1;
3253 if (token_tags[maybe_comma] == .comma)
3225 if (tree.tokenTag(maybe_comma) == .comma)
32543226 return 1;
32553227 return exprs.len; // no newlines
32563228 }
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]),
......@@ -2322,7 +2322,7 @@ const TestFetchBuilder = struct {
23222322 .arena = std.heap.ArenaAllocator.init(allocator),
23232323 .location = .{ .path_or_url = path_or_url },
23242324 .location_tok = 0,
2325 .hash_tok = 0,
2325 .hash_tok = .none,
23262326 .name_tok = 0,
23272327 .lazy_status = .eager,
23282328 .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);
......@@ -17867,7 +17886,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1786717886 const ip = &zcu.intern_pool;
1786817887 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);
1786917888
17870 const src_node: i32 = @bitCast(extended.operand);
17889 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
1787117890 const src = block.nodeOffset(src_node);
1787217891
1787317892 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
......@@ -17891,8 +17910,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1789117910 });
1789217911 break :name null;
1789317912 };
17894 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));
17895 const token = tree.nodes.items(.main_token)[node];
17913 const node = src_node.toAbsolute(src_base_node);
17914 const token = tree.nodeMainToken(node);
1789617915 break :name tree.tokenSlice(token);
1789717916 };
1789817917
......@@ -17919,8 +17938,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1791917938 });
1792017939 break :name null;
1792117940 };
17922 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));
17923 const token = tree.nodes.items(.main_token)[node];
17941 const node = src_node.toAbsolute(src_base_node);
17942 const token = tree.nodeMainToken(node);
1792417943 break :name tree.tokenSlice(token);
1792517944 };
1792617945
......@@ -17930,7 +17949,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1793017949 try sema.errMsg(src, "variable not accessible from inner function", .{});
1793117950 errdefer msg.destroy(sema.gpa);
1793217951
17933 try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{});
17952 try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{});
1793417953
1793517954 // TODO add "declared here" note
1793617955 break :msg msg;
......@@ -17962,7 +17981,8 @@ fn zirFrameAddress(
1796217981 block: *Block,
1796317982 extended: Zir.Inst.Extended.InstData,
1796417983) CompileError!Air.Inst.Ref {
17965 const src = block.nodeOffset(@bitCast(extended.operand));
17984 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17985 const src = block.nodeOffset(src_node);
1796617986 try sema.requireRuntimeBlock(block, src, null);
1796717987 return try block.addNoOp(.frame_addr);
1796817988}
......@@ -18059,7 +18079,7 @@ fn zirBuiltinSrc(
1805918079 } });
1806018080 };
1806118081
18062 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation);
18082 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation);
1806318083 const fields = .{
1806418084 // module: [:0]const u8,
1806518085 module_name_val,
......@@ -19528,7 +19548,7 @@ fn zirCondbr(
1952819548fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1952919549 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1953019550 const src = parent_block.nodeOffset(inst_data.src_node);
19531 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
19551 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
1953219552 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1953319553 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
1953419554 const err_union = try sema.resolveInst(extra.data.operand);
......@@ -19587,7 +19607,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1958719607fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1958819608 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1958919609 const src = parent_block.nodeOffset(inst_data.src_node);
19590 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
19610 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
1959119611 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1959219612 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
1959319613 const operand = try sema.resolveInst(extra.data.operand);
......@@ -19790,7 +19810,7 @@ fn zirRetImplicit(
1979019810 }
1979119811
1979219812 const operand = try sema.resolveInst(inst_data.operand);
19793 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 });
19813 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
1979419814 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
1979519815 if (base_tag == .noreturn) {
1979619816 const msg = msg: {
......@@ -21277,7 +21297,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
2127721297 const pt = sema.pt;
2127821298 const zcu = pt.zcu;
2127921299 const ip = &zcu.intern_pool;
21280 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);
21300 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
2128121301 try stack_trace_ty.resolveFields(pt);
2128221302 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
2128321303 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
......@@ -21299,7 +21319,8 @@ fn zirFrame(
2129921319 block: *Block,
2130021320 extended: Zir.Inst.Extended.InstData,
2130121321) CompileError!Air.Inst.Ref {
21302 const src = block.nodeOffset(@bitCast(extended.operand));
21322 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
21323 const src = block.nodeOffset(src_node);
2130321324 return sema.failWithUseOfAsync(block, src);
2130421325}
2130521326
......@@ -21553,13 +21574,13 @@ fn zirReify(
2155321574 const tracked_inst = try block.trackZir(inst);
2155421575 const src: LazySrcLoc = .{
2155521576 .base_node_inst = tracked_inst,
21556 .offset = LazySrcLoc.Offset.nodeOffset(0),
21577 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
2155721578 };
2155821579 const operand_src: LazySrcLoc = .{
2155921580 .base_node_inst = tracked_inst,
2156021581 .offset = .{
2156121582 .node_offset_builtin_call_arg = .{
21562 .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
21583 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
2156321584 .arg_index = 0,
2156421585 },
2156521586 },
......@@ -22867,7 +22888,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2286722888}
2286822889
2286922890fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22870 const src = block.nodeOffset(@bitCast(extended.operand));
22891 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
22892 const src = block.nodeOffset(src_node);
2287122893
2287222894 const va_list_ty = try sema.getBuiltinType(src, .VaList);
2287322895 try sema.requireRuntimeBlock(block, src, null);
......@@ -24272,12 +24294,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2427224294fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {
2427324295 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
2427424296 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
24275 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });
24276 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });
24297 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
24298 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1);
2427724299 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2427824300
24279 const ty = try sema.resolveType(block, lhs_src, extra.lhs);
24280 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name });
24301 const ty = try sema.resolveType(block, ty_src, extra.lhs);
24302 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name });
2428124303
2428224304 const pt = sema.pt;
2428324305 const zcu = pt.zcu;
......@@ -24285,15 +24307,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2428524307 try ty.resolveLayout(pt);
2428624308 switch (ty.zigTypeTag(zcu)) {
2428724309 .@"struct" => {},
24288 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
24310 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
2428924311 }
2429024312
2429124313 const field_index = if (ty.isTuple(zcu)) blk: {
2429224314 if (field_name.eqlSlice("len", ip)) {
2429324315 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
2429424316 }
24295 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
24296 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
24317 break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src);
24318 } else try sema.structFieldIndex(block, ty, field_name, field_name_src);
2429724319
2429824320 if (ty.structFieldIsComptime(field_index, zcu)) {
2429924321 return sema.fail(block, src, "no offset available for comptime field", .{});
......@@ -25077,7 +25099,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2507725099fn analyzeShuffle(
2507825100 sema: *Sema,
2507925101 block: *Block,
25080 src_node: i32,
25102 src_node: std.zig.Ast.Node.Offset,
2508125103 elem_ty: Type,
2508225104 a_arg: Air.Inst.Ref,
2508325105 b_arg: Air.Inst.Ref,
......@@ -27004,7 +27026,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2700427026 const gpa = zcu.gpa;
2700527027 const ip = &zcu.intern_pool;
2700627028
27007 const src = block.nodeOffset(@bitCast(extended.operand));
27029 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
27030 const src = block.nodeOffset(src_node);
2700827031 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2700927032
2701027033 const ty = switch (value) {
......@@ -29479,7 +29502,7 @@ const CoerceOpts = struct {
2947929502 return .{
2948029503 .base_node_inst = func_inst,
2948129504 .offset = .{ .fn_proto_param_type = .{
29482 .fn_proto_node_offset = 0,
29505 .fn_proto_node_offset = .zero,
2948329506 .param_index = info.param_i,
2948429507 } },
2948529508 };
......@@ -30084,7 +30107,7 @@ fn coerceExtra(
3008430107
3008530108 const ret_ty_src: LazySrcLoc = .{
3008630109 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30087 .offset = .{ .node_offset_fn_type_ret_ty = 0 },
30110 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
3008830111 };
3008930112 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});
3009030113 break :msg msg;
......@@ -30124,7 +30147,7 @@ fn coerceExtra(
3012430147 {
3012530148 const ret_ty_src: LazySrcLoc = .{
3012630149 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30127 .offset = .{ .node_offset_fn_type_ret_ty = 0 },
30150 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
3012830151 };
3012930152 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {
3013030153 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
......@@ -32325,7 +32348,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
3232532348 if (zcu.analysis_in_progress.contains(anal_unit)) {
3232632349 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
3232732350 .base_node_inst = nav.analysis.?.zir_index,
32328 .offset = LazySrcLoc.Offset.nodeOffset(0),
32351 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
3232932352 }, "dependency loop detected", .{}));
3233032353 }
3233132354
......@@ -33942,7 +33965,7 @@ const PeerTypeCandidateSrc = union(enum) {
3394233965 /// index i in this slice
3394333966 override: []const ?LazySrcLoc,
3394433967 /// resolvePeerTypes originates from a @TypeOf(...) call
33945 typeof_builtin_call_node_offset: i32,
33968 typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset,
3394633969
3394733970 pub fn resolve(
3394833971 self: PeerTypeCandidateSrc,
......@@ -35545,7 +35568,7 @@ fn backingIntType(
3554535568
3554635569 const backing_int_src: LazySrcLoc = .{
3554735570 .base_node_inst = struct_type.zir_index,
35548 .offset = .{ .node_offset_container_tag = 0 },
35571 .offset = .{ .node_offset_container_tag = .zero },
3554935572 };
3555035573 block.comptime_reason = .{ .reason = .{
3555135574 .src = backing_int_src,
......@@ -35566,7 +35589,7 @@ fn backingIntType(
3556635589 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
3556735590 } else {
3556835591 if (fields_bit_sum > std.math.maxInt(u16)) {
35569 return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
35592 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
3557035593 }
3557135594 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
3557235595 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
......@@ -36167,7 +36190,7 @@ fn structFields(
3616736190 .comptime_reason = .{ .reason = .{
3616836191 .src = .{
3616936192 .base_node_inst = struct_type.zir_index,
36170 .offset = .nodeOffset(0),
36193 .offset = .nodeOffset(.zero),
3617136194 },
3617236195 .r = .{ .simple = .struct_fields },
3617336196 } },
......@@ -36508,7 +36531,7 @@ fn unionFields(
3650836531
3650936532 const src: LazySrcLoc = .{
3651036533 .base_node_inst = union_type.zir_index,
36511 .offset = .nodeOffset(0),
36534 .offset = .nodeOffset(.zero),
3651236535 };
3651336536
3651436537 var block_scope: Block = .{
......@@ -36537,7 +36560,7 @@ fn unionFields(
3653736560 if (tag_type_ref != .none) {
3653836561 const tag_ty_src: LazySrcLoc = .{
3653936562 .base_node_inst = union_type.zir_index,
36540 .offset = .{ .node_offset_container_tag = 0 },
36563 .offset = .{ .node_offset_container_tag = .zero },
3654136564 };
3654236565 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
3654336566 if (small.auto_enum_tag) {
......@@ -38512,7 +38535,7 @@ pub fn resolveDeclaredEnum(
3851238535 const zcu = pt.zcu;
3851338536 const gpa = zcu.gpa;
3851438537
38515 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };
38538 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3851638539
3851738540 var arena: std.heap.ArenaAllocator = .init(gpa);
3851838541 defer arena.deinit();
......@@ -38599,7 +38622,7 @@ fn resolveDeclaredEnumInner(
3859938622
3860038623 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3860138624
38602 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };
38625 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } };
3860338626
3860438627 const int_tag_ty = ty: {
3860538628 if (body.len != 0) {
......@@ -38752,9 +38775,9 @@ pub fn resolveNavPtrModifiers(
3875238775 const gpa = zcu.gpa;
3875338776 const ip = &zcu.intern_pool;
3875438777
38755 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
38756 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
38757 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
38778 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
38779 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
38780 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3875838781
3875938782 const alignment: InternPool.Alignment = a: {
3876038783 const align_body = zir_decl.align_body orelse break :a .none;
......@@ -38827,7 +38850,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3882738850
3882838851 const src: LazySrcLoc = .{
3882938852 .base_node_inst = ip.getNav(nav).srcInst(ip),
38830 .offset = .nodeOffset(0),
38853 .offset = .nodeOffset(.zero),
3883138854 };
3883238855
3883338856 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+278-295
......@@ -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,
......@@ -1031,10 +1031,6 @@ pub const SrcLoc = struct {
10311031 return tree.firstToken(src_loc.base_node);
10321032 }
10331033
1034 pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
1035 return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node)));
1036 }
1037
10381034 pub const Span = Ast.Span;
10391035
10401036 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
......@@ -1046,7 +1042,7 @@ pub const SrcLoc = struct {
10461042
10471043 .token_abs => |tok_index| {
10481044 const tree = try src_loc.file_scope.getTree(gpa);
1049 const start = tree.tokens.items(.start)[tok_index];
1045 const start = tree.tokenStart(tok_index);
10501046 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10511047 return Span{ .start = start, .end = end, .main = start };
10521048 },
......@@ -1057,133 +1053,137 @@ pub const SrcLoc = struct {
10571053 .byte_offset => |byte_off| {
10581054 const tree = try src_loc.file_scope.getTree(gpa);
10591055 const tok_index = src_loc.baseSrcToken();
1060 const start = tree.tokens.items(.start)[tok_index] + byte_off;
1056 const start = tree.tokenStart(tok_index) + byte_off;
10611057 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10621058 return Span{ .start = start, .end = end, .main = start };
10631059 },
10641060 .token_offset => |tok_off| {
10651061 const tree = try src_loc.file_scope.getTree(gpa);
1066 const tok_index = src_loc.baseSrcToken() + tok_off;
1067 const start = tree.tokens.items(.start)[tok_index];
1062 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());
1063 const start = tree.tokenStart(tok_index);
10681064 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
10691065 return Span{ .start = start, .end = end, .main = start };
10701066 },
10711067 .node_offset => |traced_off| {
10721068 const node_off = traced_off.x;
10731069 const tree = try src_loc.file_scope.getTree(gpa);
1074 const node = src_loc.relativeToNodeIndex(node_off);
1070 const node = node_off.toAbsolute(src_loc.base_node);
10751071 return tree.nodeToSpan(node);
10761072 },
10771073 .node_offset_main_token => |node_off| {
10781074 const tree = try src_loc.file_scope.getTree(gpa);
1079 const node = src_loc.relativeToNodeIndex(node_off);
1080 const main_token = tree.nodes.items(.main_token)[node];
1075 const node = node_off.toAbsolute(src_loc.base_node);
1076 const main_token = tree.nodeMainToken(node);
10811077 return tree.tokensToSpan(main_token, main_token, main_token);
10821078 },
10831079 .node_offset_bin_op => |node_off| {
10841080 const tree = try src_loc.file_scope.getTree(gpa);
1085 const node = src_loc.relativeToNodeIndex(node_off);
1081 const node = node_off.toAbsolute(src_loc.base_node);
10861082 return tree.nodeToSpan(node);
10871083 },
10881084 .node_offset_initializer => |node_off| {
10891085 const tree = try src_loc.file_scope.getTree(gpa);
1090 const node = src_loc.relativeToNodeIndex(node_off);
1086 const node = node_off.toAbsolute(src_loc.base_node);
10911087 return tree.tokensToSpan(
10921088 tree.firstToken(node) - 3,
10931089 tree.lastToken(node),
1094 tree.nodes.items(.main_token)[node] - 2,
1090 tree.nodeMainToken(node) - 2,
10951091 );
10961092 },
10971093 .node_offset_var_decl_ty => |node_off| {
10981094 const tree = try src_loc.file_scope.getTree(gpa);
1099 const node = src_loc.relativeToNodeIndex(node_off);
1100 const node_tags = tree.nodes.items(.tag);
1101 const full = switch (node_tags[node]) {
1095 const node = node_off.toAbsolute(src_loc.base_node);
1096 const full = switch (tree.nodeTag(node)) {
11021097 .global_var_decl,
11031098 .local_var_decl,
11041099 .simple_var_decl,
11051100 .aligned_var_decl,
11061101 => tree.fullVarDecl(node).?,
11071102 .@"usingnamespace" => {
1108 const node_data = tree.nodes.items(.data);
1109 return tree.nodeToSpan(node_data[node].lhs);
1103 return tree.nodeToSpan(tree.nodeData(node).node);
11101104 },
11111105 else => unreachable,
11121106 };
1113 if (full.ast.type_node != 0) {
1114 return tree.nodeToSpan(full.ast.type_node);
1107 if (full.ast.type_node.unwrap()) |type_node| {
1108 return tree.nodeToSpan(type_node);
11151109 }
11161110 const tok_index = full.ast.mut_token + 1; // the name token
1117 const start = tree.tokens.items(.start)[tok_index];
1111 const start = tree.tokenStart(tok_index);
11181112 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
11191113 return Span{ .start = start, .end = end, .main = start };
11201114 },
11211115 .node_offset_var_decl_align => |node_off| {
11221116 const tree = try src_loc.file_scope.getTree(gpa);
1123 const node = src_loc.relativeToNodeIndex(node_off);
1117 const node = node_off.toAbsolute(src_loc.base_node);
11241118 var buf: [1]Ast.Node.Index = undefined;
11251119 const align_node = if (tree.fullVarDecl(node)) |v|
1126 v.ast.align_node
1120 v.ast.align_node.unwrap().?
11271121 else if (tree.fullFnProto(&buf, node)) |f|
1128 f.ast.align_expr
1122 f.ast.align_expr.unwrap().?
11291123 else
11301124 unreachable;
11311125 return tree.nodeToSpan(align_node);
11321126 },
11331127 .node_offset_var_decl_section => |node_off| {
11341128 const tree = try src_loc.file_scope.getTree(gpa);
1135 const node = src_loc.relativeToNodeIndex(node_off);
1129 const node = node_off.toAbsolute(src_loc.base_node);
11361130 var buf: [1]Ast.Node.Index = undefined;
11371131 const section_node = if (tree.fullVarDecl(node)) |v|
1138 v.ast.section_node
1132 v.ast.section_node.unwrap().?
11391133 else if (tree.fullFnProto(&buf, node)) |f|
1140 f.ast.section_expr
1134 f.ast.section_expr.unwrap().?
11411135 else
11421136 unreachable;
11431137 return tree.nodeToSpan(section_node);
11441138 },
11451139 .node_offset_var_decl_addrspace => |node_off| {
11461140 const tree = try src_loc.file_scope.getTree(gpa);
1147 const node = src_loc.relativeToNodeIndex(node_off);
1141 const node = node_off.toAbsolute(src_loc.base_node);
11481142 var buf: [1]Ast.Node.Index = undefined;
11491143 const addrspace_node = if (tree.fullVarDecl(node)) |v|
1150 v.ast.addrspace_node
1144 v.ast.addrspace_node.unwrap().?
11511145 else if (tree.fullFnProto(&buf, node)) |f|
1152 f.ast.addrspace_expr
1146 f.ast.addrspace_expr.unwrap().?
11531147 else
11541148 unreachable;
11551149 return tree.nodeToSpan(addrspace_node);
11561150 },
11571151 .node_offset_var_decl_init => |node_off| {
11581152 const tree = try src_loc.file_scope.getTree(gpa);
1159 const node = src_loc.relativeToNodeIndex(node_off);
1160 const full = tree.fullVarDecl(node).?;
1161 return tree.nodeToSpan(full.ast.init_node);
1153 const node = node_off.toAbsolute(src_loc.base_node);
1154 const init_node = switch (tree.nodeTag(node)) {
1155 .global_var_decl,
1156 .local_var_decl,
1157 .aligned_var_decl,
1158 .simple_var_decl,
1159 => tree.fullVarDecl(node).?.ast.init_node.unwrap().?,
1160 .assign_destructure => tree.assignDestructure(node).ast.value_expr,
1161 else => unreachable,
1162 };
1163 return tree.nodeToSpan(init_node);
11621164 },
11631165 .node_offset_builtin_call_arg => |builtin_arg| {
11641166 const tree = try src_loc.file_scope.getTree(gpa);
1165 const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node);
1167 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);
11661168 var buf: [2]Ast.Node.Index = undefined;
11671169 const params = tree.builtinCallParams(&buf, node).?;
11681170 return tree.nodeToSpan(params[builtin_arg.arg_index]);
11691171 },
11701172 .node_offset_ptrcast_operand => |node_off| {
11711173 const tree = try src_loc.file_scope.getTree(gpa);
1172 const main_tokens = tree.nodes.items(.main_token);
1173 const node_datas = tree.nodes.items(.data);
1174 const node_tags = tree.nodes.items(.tag);
11751174
1176 var node = src_loc.relativeToNodeIndex(node_off);
1175 var node = node_off.toAbsolute(src_loc.base_node);
11771176 while (true) {
1178 switch (node_tags[node]) {
1177 switch (tree.nodeTag(node)) {
11791178 .builtin_call_two, .builtin_call_two_comma => {},
11801179 else => break,
11811180 }
11821181
1183 if (node_datas[node].lhs == 0) break; // 0 args
1184 if (node_datas[node].rhs != 0) break; // 2 args
1182 const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node;
1183 if (first_arg == .none) break; // 0 args
1184 if (second_arg != .none) break; // 2 args
11851185
1186 const builtin_token = main_tokens[node];
1186 const builtin_token = tree.nodeMainToken(node);
11871187 const builtin_name = tree.tokenSlice(builtin_token);
11881188 const info = BuiltinFn.list.get(builtin_name) orelse break;
11891189
......@@ -1197,16 +1197,15 @@ pub const SrcLoc = struct {
11971197 => {},
11981198 }
11991199
1200 node = node_datas[node].lhs;
1200 node = first_arg.unwrap().?;
12011201 }
12021202
12031203 return tree.nodeToSpan(node);
12041204 },
12051205 .node_offset_array_access_index => |node_off| {
12061206 const tree = try src_loc.file_scope.getTree(gpa);
1207 const node_datas = tree.nodes.items(.data);
1208 const node = src_loc.relativeToNodeIndex(node_off);
1209 return tree.nodeToSpan(node_datas[node].rhs);
1207 const node = node_off.toAbsolute(src_loc.base_node);
1208 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
12101209 },
12111210 .node_offset_slice_ptr,
12121211 .node_offset_slice_start,
......@@ -1214,32 +1213,30 @@ pub const SrcLoc = struct {
12141213 .node_offset_slice_sentinel,
12151214 => |node_off| {
12161215 const tree = try src_loc.file_scope.getTree(gpa);
1217 const node = src_loc.relativeToNodeIndex(node_off);
1216 const node = node_off.toAbsolute(src_loc.base_node);
12181217 const full = tree.fullSlice(node).?;
12191218 const part_node = switch (src_loc.lazy) {
12201219 .node_offset_slice_ptr => full.ast.sliced,
12211220 .node_offset_slice_start => full.ast.start,
1222 .node_offset_slice_end => full.ast.end,
1223 .node_offset_slice_sentinel => full.ast.sentinel,
1221 .node_offset_slice_end => full.ast.end.unwrap().?,
1222 .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?,
12241223 else => unreachable,
12251224 };
12261225 return tree.nodeToSpan(part_node);
12271226 },
12281227 .node_offset_call_func => |node_off| {
12291228 const tree = try src_loc.file_scope.getTree(gpa);
1230 const node = src_loc.relativeToNodeIndex(node_off);
1229 const node = node_off.toAbsolute(src_loc.base_node);
12311230 var buf: [1]Ast.Node.Index = undefined;
12321231 const full = tree.fullCall(&buf, node).?;
12331232 return tree.nodeToSpan(full.ast.fn_expr);
12341233 },
12351234 .node_offset_field_name => |node_off| {
12361235 const tree = try src_loc.file_scope.getTree(gpa);
1237 const node_datas = tree.nodes.items(.data);
1238 const node_tags = tree.nodes.items(.tag);
1239 const node = src_loc.relativeToNodeIndex(node_off);
1236 const node = node_off.toAbsolute(src_loc.base_node);
12401237 var buf: [1]Ast.Node.Index = undefined;
1241 const tok_index = switch (node_tags[node]) {
1242 .field_access => node_datas[node].rhs,
1238 const tok_index = switch (tree.nodeTag(node)) {
1239 .field_access => tree.nodeData(node).node_and_token[1],
12431240 .call_one,
12441241 .call_one_comma,
12451242 .async_call_one,
......@@ -1254,43 +1251,41 @@ pub const SrcLoc = struct {
12541251 },
12551252 else => tree.firstToken(node) - 2,
12561253 };
1257 const start = tree.tokens.items(.start)[tok_index];
1254 const start = tree.tokenStart(tok_index);
12581255 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
12591256 return Span{ .start = start, .end = end, .main = start };
12601257 },
12611258 .node_offset_field_name_init => |node_off| {
12621259 const tree = try src_loc.file_scope.getTree(gpa);
1263 const node = src_loc.relativeToNodeIndex(node_off);
1260 const node = node_off.toAbsolute(src_loc.base_node);
12641261 const tok_index = tree.firstToken(node) - 2;
1265 const start = tree.tokens.items(.start)[tok_index];
1262 const start = tree.tokenStart(tok_index);
12661263 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
12671264 return Span{ .start = start, .end = end, .main = start };
12681265 },
12691266 .node_offset_deref_ptr => |node_off| {
12701267 const tree = try src_loc.file_scope.getTree(gpa);
1271 const node = src_loc.relativeToNodeIndex(node_off);
1268 const node = node_off.toAbsolute(src_loc.base_node);
12721269 return tree.nodeToSpan(node);
12731270 },
12741271 .node_offset_asm_source => |node_off| {
12751272 const tree = try src_loc.file_scope.getTree(gpa);
1276 const node = src_loc.relativeToNodeIndex(node_off);
1273 const node = node_off.toAbsolute(src_loc.base_node);
12771274 const full = tree.fullAsm(node).?;
12781275 return tree.nodeToSpan(full.ast.template);
12791276 },
12801277 .node_offset_asm_ret_ty => |node_off| {
12811278 const tree = try src_loc.file_scope.getTree(gpa);
1282 const node = src_loc.relativeToNodeIndex(node_off);
1279 const node = node_off.toAbsolute(src_loc.base_node);
12831280 const full = tree.fullAsm(node).?;
12841281 const asm_output = full.outputs[0];
1285 const node_datas = tree.nodes.items(.data);
1286 return tree.nodeToSpan(node_datas[asm_output].lhs);
1282 return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?);
12871283 },
12881284
12891285 .node_offset_if_cond => |node_off| {
12901286 const tree = try src_loc.file_scope.getTree(gpa);
1291 const node = src_loc.relativeToNodeIndex(node_off);
1292 const node_tags = tree.nodes.items(.tag);
1293 const src_node = switch (node_tags[node]) {
1287 const node = node_off.toAbsolute(src_loc.base_node);
1288 const src_node = switch (tree.nodeTag(node)) {
12941289 .if_simple,
12951290 .@"if",
12961291 => tree.fullIf(node).?.ast.cond_expr,
......@@ -1317,20 +1312,19 @@ pub const SrcLoc = struct {
13171312 },
13181313 .for_input => |for_input| {
13191314 const tree = try src_loc.file_scope.getTree(gpa);
1320 const node = src_loc.relativeToNodeIndex(for_input.for_node_offset);
1315 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
13211316 const for_full = tree.fullFor(node).?;
13221317 const src_node = for_full.ast.inputs[for_input.input_index];
13231318 return tree.nodeToSpan(src_node);
13241319 },
13251320 .for_capture_from_input => |node_off| {
13261321 const tree = try src_loc.file_scope.getTree(gpa);
1327 const token_tags = tree.tokens.items(.tag);
1328 const input_node = src_loc.relativeToNodeIndex(node_off);
1322 const input_node = node_off.toAbsolute(src_loc.base_node);
13291323 // We have to actually linear scan the whole AST to find the for loop
13301324 // that contains this input.
13311325 const node_tags = tree.nodes.items(.tag);
13321326 for (node_tags, 0..) |node_tag, node_usize| {
1333 const node = @as(Ast.Node.Index, @intCast(node_usize));
1327 const node: Ast.Node.Index = @enumFromInt(node_usize);
13341328 switch (node_tag) {
13351329 .for_simple, .@"for" => {
13361330 const for_full = tree.fullFor(node).?;
......@@ -1339,7 +1333,7 @@ pub const SrcLoc = struct {
13391333 var count = input_index;
13401334 var tok = for_full.payload_token;
13411335 while (true) {
1342 switch (token_tags[tok]) {
1336 switch (tree.tokenTag(tok)) {
13431337 .comma => {
13441338 count -= 1;
13451339 tok += 1;
......@@ -1366,13 +1360,12 @@ pub const SrcLoc = struct {
13661360 },
13671361 .call_arg => |call_arg| {
13681362 const tree = try src_loc.file_scope.getTree(gpa);
1369 const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset);
1363 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);
13701364 var buf: [2]Ast.Node.Index = undefined;
13711365 const call_full = tree.fullCall(buf[0..1], node) orelse {
1372 const node_tags = tree.nodes.items(.tag);
1373 assert(node_tags[node] == .builtin_call);
1374 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];
1375 switch (node_tags[call_args_node]) {
1366 assert(tree.nodeTag(node) == .builtin_call);
1367 const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]);
1368 switch (tree.nodeTag(call_args_node)) {
13761369 .array_init_one,
13771370 .array_init_one_comma,
13781371 .array_init_dot_two,
......@@ -1404,7 +1397,7 @@ pub const SrcLoc = struct {
14041397 },
14051398 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
14061399 const tree = try src_loc.file_scope.getTree(gpa);
1407 const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
1400 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);
14081401 var buf: [1]Ast.Node.Index = undefined;
14091402 const full = tree.fullFnProto(&buf, node).?;
14101403 var it = full.iterate(tree);
......@@ -1416,14 +1409,14 @@ pub const SrcLoc = struct {
14161409 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {
14171410 return tree.tokenToSpan(tok);
14181411 } else {
1419 return tree.nodeToSpan(param.type_expr);
1412 return tree.nodeToSpan(param.type_expr.?);
14201413 },
14211414 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {
14221415 const first = param.comptime_noalias orelse param.name_token orelse tok;
14231416 return tree.tokensToSpan(first, tok, first);
14241417 } else {
1425 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr);
1426 return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first);
1418 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?);
1419 return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first);
14271420 },
14281421 else => unreachable,
14291422 }
......@@ -1432,28 +1425,24 @@ pub const SrcLoc = struct {
14321425 },
14331426 .node_offset_bin_lhs => |node_off| {
14341427 const tree = try src_loc.file_scope.getTree(gpa);
1435 const node = src_loc.relativeToNodeIndex(node_off);
1436 const node_datas = tree.nodes.items(.data);
1437 return tree.nodeToSpan(node_datas[node].lhs);
1428 const node = node_off.toAbsolute(src_loc.base_node);
1429 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
14381430 },
14391431 .node_offset_bin_rhs => |node_off| {
14401432 const tree = try src_loc.file_scope.getTree(gpa);
1441 const node = src_loc.relativeToNodeIndex(node_off);
1442 const node_datas = tree.nodes.items(.data);
1443 return tree.nodeToSpan(node_datas[node].rhs);
1433 const node = node_off.toAbsolute(src_loc.base_node);
1434 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
14441435 },
14451436 .array_cat_lhs, .array_cat_rhs => |cat| {
14461437 const tree = try src_loc.file_scope.getTree(gpa);
1447 const node = src_loc.relativeToNodeIndex(cat.array_cat_offset);
1448 const node_datas = tree.nodes.items(.data);
1438 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);
14491439 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1450 node_datas[node].lhs
1440 tree.nodeData(node).node_and_node[0]
14511441 else
1452 node_datas[node].rhs;
1442 tree.nodeData(node).node_and_node[1];
14531443
1454 const node_tags = tree.nodes.items(.tag);
14551444 var buf: [2]Ast.Node.Index = undefined;
1456 switch (node_tags[arr_node]) {
1445 switch (tree.nodeTag(arr_node)) {
14571446 .array_init_one,
14581447 .array_init_one_comma,
14591448 .array_init_dot_two,
......@@ -1470,27 +1459,30 @@ pub const SrcLoc = struct {
14701459 }
14711460 },
14721461
1462 .node_offset_try_operand => |node_off| {
1463 const tree = try src_loc.file_scope.getTree(gpa);
1464 const node = node_off.toAbsolute(src_loc.base_node);
1465 return tree.nodeToSpan(tree.nodeData(node).node);
1466 },
1467
14731468 .node_offset_switch_operand => |node_off| {
14741469 const tree = try src_loc.file_scope.getTree(gpa);
1475 const node = src_loc.relativeToNodeIndex(node_off);
1476 const node_datas = tree.nodes.items(.data);
1477 return tree.nodeToSpan(node_datas[node].lhs);
1470 const node = node_off.toAbsolute(src_loc.base_node);
1471 const condition, _ = tree.nodeData(node).node_and_extra;
1472 return tree.nodeToSpan(condition);
14781473 },
14791474
14801475 .node_offset_switch_special_prong => |node_off| {
14811476 const tree = try src_loc.file_scope.getTree(gpa);
1482 const switch_node = src_loc.relativeToNodeIndex(node_off);
1483 const node_datas = tree.nodes.items(.data);
1484 const node_tags = tree.nodes.items(.tag);
1485 const main_tokens = tree.nodes.items(.main_token);
1486 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1487 const case_nodes = tree.extra_data[extra.start..extra.end];
1477 const switch_node = node_off.toAbsolute(src_loc.base_node);
1478 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1479 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
14881480 for (case_nodes) |case_node| {
14891481 const case = tree.fullSwitchCase(case_node).?;
14901482 const is_special = (case.ast.values.len == 0) or
14911483 (case.ast.values.len == 1 and
1492 node_tags[case.ast.values[0]] == .identifier and
1493 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
1484 tree.nodeTag(case.ast.values[0]) == .identifier and
1485 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
14941486 if (!is_special) continue;
14951487
14961488 return tree.nodeToSpan(case_node);
......@@ -1499,22 +1491,19 @@ pub const SrcLoc = struct {
14991491
15001492 .node_offset_switch_range => |node_off| {
15011493 const tree = try src_loc.file_scope.getTree(gpa);
1502 const switch_node = src_loc.relativeToNodeIndex(node_off);
1503 const node_datas = tree.nodes.items(.data);
1504 const node_tags = tree.nodes.items(.tag);
1505 const main_tokens = tree.nodes.items(.main_token);
1506 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1507 const case_nodes = tree.extra_data[extra.start..extra.end];
1494 const switch_node = node_off.toAbsolute(src_loc.base_node);
1495 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1496 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
15081497 for (case_nodes) |case_node| {
15091498 const case = tree.fullSwitchCase(case_node).?;
15101499 const is_special = (case.ast.values.len == 0) or
15111500 (case.ast.values.len == 1 and
1512 node_tags[case.ast.values[0]] == .identifier and
1513 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
1501 tree.nodeTag(case.ast.values[0]) == .identifier and
1502 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
15141503 if (is_special) continue;
15151504
15161505 for (case.ast.values) |item_node| {
1517 if (node_tags[item_node] == .switch_range) {
1506 if (tree.nodeTag(item_node) == .switch_range) {
15181507 return tree.nodeToSpan(item_node);
15191508 }
15201509 }
......@@ -1522,47 +1511,46 @@ pub const SrcLoc = struct {
15221511 },
15231512 .node_offset_fn_type_align => |node_off| {
15241513 const tree = try src_loc.file_scope.getTree(gpa);
1525 const node = src_loc.relativeToNodeIndex(node_off);
1514 const node = node_off.toAbsolute(src_loc.base_node);
15261515 var buf: [1]Ast.Node.Index = undefined;
15271516 const full = tree.fullFnProto(&buf, node).?;
1528 return tree.nodeToSpan(full.ast.align_expr);
1517 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
15291518 },
15301519 .node_offset_fn_type_addrspace => |node_off| {
15311520 const tree = try src_loc.file_scope.getTree(gpa);
1532 const node = src_loc.relativeToNodeIndex(node_off);
1521 const node = node_off.toAbsolute(src_loc.base_node);
15331522 var buf: [1]Ast.Node.Index = undefined;
15341523 const full = tree.fullFnProto(&buf, node).?;
1535 return tree.nodeToSpan(full.ast.addrspace_expr);
1524 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
15361525 },
15371526 .node_offset_fn_type_section => |node_off| {
15381527 const tree = try src_loc.file_scope.getTree(gpa);
1539 const node = src_loc.relativeToNodeIndex(node_off);
1528 const node = node_off.toAbsolute(src_loc.base_node);
15401529 var buf: [1]Ast.Node.Index = undefined;
15411530 const full = tree.fullFnProto(&buf, node).?;
1542 return tree.nodeToSpan(full.ast.section_expr);
1531 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
15431532 },
15441533 .node_offset_fn_type_cc => |node_off| {
15451534 const tree = try src_loc.file_scope.getTree(gpa);
1546 const node = src_loc.relativeToNodeIndex(node_off);
1535 const node = node_off.toAbsolute(src_loc.base_node);
15471536 var buf: [1]Ast.Node.Index = undefined;
15481537 const full = tree.fullFnProto(&buf, node).?;
1549 return tree.nodeToSpan(full.ast.callconv_expr);
1538 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);
15501539 },
15511540
15521541 .node_offset_fn_type_ret_ty => |node_off| {
15531542 const tree = try src_loc.file_scope.getTree(gpa);
1554 const node = src_loc.relativeToNodeIndex(node_off);
1543 const node = node_off.toAbsolute(src_loc.base_node);
15551544 var buf: [1]Ast.Node.Index = undefined;
15561545 const full = tree.fullFnProto(&buf, node).?;
1557 return tree.nodeToSpan(full.ast.return_type);
1546 return tree.nodeToSpan(full.ast.return_type.unwrap().?);
15581547 },
15591548 .node_offset_param => |node_off| {
15601549 const tree = try src_loc.file_scope.getTree(gpa);
1561 const token_tags = tree.tokens.items(.tag);
1562 const node = src_loc.relativeToNodeIndex(node_off);
1550 const node = node_off.toAbsolute(src_loc.base_node);
15631551
15641552 var first_tok = tree.firstToken(node);
1565 while (true) switch (token_tags[first_tok - 1]) {
1553 while (true) switch (tree.tokenTag(first_tok - 1)) {
15661554 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
15671555 else => break,
15681556 };
......@@ -1574,12 +1562,11 @@ pub const SrcLoc = struct {
15741562 },
15751563 .token_offset_param => |token_off| {
15761564 const tree = try src_loc.file_scope.getTree(gpa);
1577 const token_tags = tree.tokens.items(.tag);
1578 const main_token = tree.nodes.items(.main_token)[src_loc.base_node];
1579 const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token))));
1565 const main_token = tree.nodeMainToken(src_loc.base_node);
1566 const tok_index = token_off.toAbsolute(main_token);
15801567
15811568 var first_tok = tok_index;
1582 while (true) switch (token_tags[first_tok - 1]) {
1569 while (true) switch (tree.tokenTag(first_tok - 1)) {
15831570 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
15841571 else => break,
15851572 };
......@@ -1592,109 +1579,108 @@ pub const SrcLoc = struct {
15921579
15931580 .node_offset_anyframe_type => |node_off| {
15941581 const tree = try src_loc.file_scope.getTree(gpa);
1595 const node_datas = tree.nodes.items(.data);
1596 const parent_node = src_loc.relativeToNodeIndex(node_off);
1597 return tree.nodeToSpan(node_datas[parent_node].rhs);
1582 const parent_node = node_off.toAbsolute(src_loc.base_node);
1583 _, const child_type = tree.nodeData(parent_node).token_and_node;
1584 return tree.nodeToSpan(child_type);
15981585 },
15991586
16001587 .node_offset_lib_name => |node_off| {
16011588 const tree = try src_loc.file_scope.getTree(gpa);
1602 const parent_node = src_loc.relativeToNodeIndex(node_off);
1589 const parent_node = node_off.toAbsolute(src_loc.base_node);
16031590 var buf: [1]Ast.Node.Index = undefined;
16041591 const full = tree.fullFnProto(&buf, parent_node).?;
16051592 const tok_index = full.lib_name.?;
1606 const start = tree.tokens.items(.start)[tok_index];
1593 const start = tree.tokenStart(tok_index);
16071594 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
16081595 return Span{ .start = start, .end = end, .main = start };
16091596 },
16101597
16111598 .node_offset_array_type_len => |node_off| {
16121599 const tree = try src_loc.file_scope.getTree(gpa);
1613 const parent_node = src_loc.relativeToNodeIndex(node_off);
1600 const parent_node = node_off.toAbsolute(src_loc.base_node);
16141601
16151602 const full = tree.fullArrayType(parent_node).?;
16161603 return tree.nodeToSpan(full.ast.elem_count);
16171604 },
16181605 .node_offset_array_type_sentinel => |node_off| {
16191606 const tree = try src_loc.file_scope.getTree(gpa);
1620 const parent_node = src_loc.relativeToNodeIndex(node_off);
1607 const parent_node = node_off.toAbsolute(src_loc.base_node);
16211608
16221609 const full = tree.fullArrayType(parent_node).?;
1623 return tree.nodeToSpan(full.ast.sentinel);
1610 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
16241611 },
16251612 .node_offset_array_type_elem => |node_off| {
16261613 const tree = try src_loc.file_scope.getTree(gpa);
1627 const parent_node = src_loc.relativeToNodeIndex(node_off);
1614 const parent_node = node_off.toAbsolute(src_loc.base_node);
16281615
16291616 const full = tree.fullArrayType(parent_node).?;
16301617 return tree.nodeToSpan(full.ast.elem_type);
16311618 },
16321619 .node_offset_un_op => |node_off| {
16331620 const tree = try src_loc.file_scope.getTree(gpa);
1634 const node_datas = tree.nodes.items(.data);
1635 const node = src_loc.relativeToNodeIndex(node_off);
1636
1637 return tree.nodeToSpan(node_datas[node].lhs);
1621 const node = node_off.toAbsolute(src_loc.base_node);
1622 return tree.nodeToSpan(tree.nodeData(node).node);
16381623 },
16391624 .node_offset_ptr_elem => |node_off| {
16401625 const tree = try src_loc.file_scope.getTree(gpa);
1641 const parent_node = src_loc.relativeToNodeIndex(node_off);
1626 const parent_node = node_off.toAbsolute(src_loc.base_node);
16421627
16431628 const full = tree.fullPtrType(parent_node).?;
16441629 return tree.nodeToSpan(full.ast.child_type);
16451630 },
16461631 .node_offset_ptr_sentinel => |node_off| {
16471632 const tree = try src_loc.file_scope.getTree(gpa);
1648 const parent_node = src_loc.relativeToNodeIndex(node_off);
1633 const parent_node = node_off.toAbsolute(src_loc.base_node);
16491634
16501635 const full = tree.fullPtrType(parent_node).?;
1651 return tree.nodeToSpan(full.ast.sentinel);
1636 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
16521637 },
16531638 .node_offset_ptr_align => |node_off| {
16541639 const tree = try src_loc.file_scope.getTree(gpa);
1655 const parent_node = src_loc.relativeToNodeIndex(node_off);
1640 const parent_node = node_off.toAbsolute(src_loc.base_node);
16561641
16571642 const full = tree.fullPtrType(parent_node).?;
1658 return tree.nodeToSpan(full.ast.align_node);
1643 return tree.nodeToSpan(full.ast.align_node.unwrap().?);
16591644 },
16601645 .node_offset_ptr_addrspace => |node_off| {
16611646 const tree = try src_loc.file_scope.getTree(gpa);
1662 const parent_node = src_loc.relativeToNodeIndex(node_off);
1647 const parent_node = node_off.toAbsolute(src_loc.base_node);
16631648
16641649 const full = tree.fullPtrType(parent_node).?;
1665 return tree.nodeToSpan(full.ast.addrspace_node);
1650 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);
16661651 },
16671652 .node_offset_ptr_bitoffset => |node_off| {
16681653 const tree = try src_loc.file_scope.getTree(gpa);
1669 const parent_node = src_loc.relativeToNodeIndex(node_off);
1654 const parent_node = node_off.toAbsolute(src_loc.base_node);
16701655
16711656 const full = tree.fullPtrType(parent_node).?;
1672 return tree.nodeToSpan(full.ast.bit_range_start);
1657 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);
16731658 },
16741659 .node_offset_ptr_hostsize => |node_off| {
16751660 const tree = try src_loc.file_scope.getTree(gpa);
1676 const parent_node = src_loc.relativeToNodeIndex(node_off);
1661 const parent_node = node_off.toAbsolute(src_loc.base_node);
16771662
16781663 const full = tree.fullPtrType(parent_node).?;
1679 return tree.nodeToSpan(full.ast.bit_range_end);
1664 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);
16801665 },
16811666 .node_offset_container_tag => |node_off| {
16821667 const tree = try src_loc.file_scope.getTree(gpa);
1683 const node_tags = tree.nodes.items(.tag);
1684 const parent_node = src_loc.relativeToNodeIndex(node_off);
1668 const parent_node = node_off.toAbsolute(src_loc.base_node);
16851669
1686 switch (node_tags[parent_node]) {
1670 switch (tree.nodeTag(parent_node)) {
16871671 .container_decl_arg, .container_decl_arg_trailing => {
16881672 const full = tree.containerDeclArg(parent_node);
1689 return tree.nodeToSpan(full.ast.arg);
1673 const arg_node = full.ast.arg.unwrap().?;
1674 return tree.nodeToSpan(arg_node);
16901675 },
16911676 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
16921677 const full = tree.taggedUnionEnumTag(parent_node);
1678 const arg_node = full.ast.arg.unwrap().?;
16931679
16941680 return tree.tokensToSpan(
1695 tree.firstToken(full.ast.arg) - 2,
1696 tree.lastToken(full.ast.arg) + 1,
1697 tree.nodes.items(.main_token)[full.ast.arg],
1681 tree.firstToken(arg_node) - 2,
1682 tree.lastToken(arg_node) + 1,
1683 tree.nodeMainToken(arg_node),
16981684 );
16991685 },
17001686 else => unreachable,
......@@ -1702,60 +1688,55 @@ pub const SrcLoc = struct {
17021688 },
17031689 .node_offset_field_default => |node_off| {
17041690 const tree = try src_loc.file_scope.getTree(gpa);
1705 const node_tags = tree.nodes.items(.tag);
1706 const parent_node = src_loc.relativeToNodeIndex(node_off);
1691 const parent_node = node_off.toAbsolute(src_loc.base_node);
17071692
1708 const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {
1693 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {
17091694 .container_field => tree.containerField(parent_node),
17101695 .container_field_init => tree.containerFieldInit(parent_node),
17111696 else => unreachable,
17121697 };
1713 return tree.nodeToSpan(full.ast.value_expr);
1698 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);
17141699 },
17151700 .node_offset_init_ty => |node_off| {
17161701 const tree = try src_loc.file_scope.getTree(gpa);
1717 const parent_node = src_loc.relativeToNodeIndex(node_off);
1702 const parent_node = node_off.toAbsolute(src_loc.base_node);
17181703
17191704 var buf: [2]Ast.Node.Index = undefined;
17201705 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|
1721 array_init.ast.type_expr
1706 array_init.ast.type_expr.unwrap().?
17221707 else
1723 tree.fullStructInit(&buf, parent_node).?.ast.type_expr;
1708 tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?;
17241709 return tree.nodeToSpan(type_expr);
17251710 },
17261711 .node_offset_store_ptr => |node_off| {
17271712 const tree = try src_loc.file_scope.getTree(gpa);
1728 const node_tags = tree.nodes.items(.tag);
1729 const node_datas = tree.nodes.items(.data);
1730 const node = src_loc.relativeToNodeIndex(node_off);
1713 const node = node_off.toAbsolute(src_loc.base_node);
17311714
1732 switch (node_tags[node]) {
1715 switch (tree.nodeTag(node)) {
17331716 .assign => {
1734 return tree.nodeToSpan(node_datas[node].lhs);
1717 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
17351718 },
17361719 else => return tree.nodeToSpan(node),
17371720 }
17381721 },
17391722 .node_offset_store_operand => |node_off| {
17401723 const tree = try src_loc.file_scope.getTree(gpa);
1741 const node_tags = tree.nodes.items(.tag);
1742 const node_datas = tree.nodes.items(.data);
1743 const node = src_loc.relativeToNodeIndex(node_off);
1724 const node = node_off.toAbsolute(src_loc.base_node);
17441725
1745 switch (node_tags[node]) {
1726 switch (tree.nodeTag(node)) {
17461727 .assign => {
1747 return tree.nodeToSpan(node_datas[node].rhs);
1728 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
17481729 },
17491730 else => return tree.nodeToSpan(node),
17501731 }
17511732 },
17521733 .node_offset_return_operand => |node_off| {
17531734 const tree = try src_loc.file_scope.getTree(gpa);
1754 const node = src_loc.relativeToNodeIndex(node_off);
1755 const node_tags = tree.nodes.items(.tag);
1756 const node_datas = tree.nodes.items(.data);
1757 if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) {
1758 return tree.nodeToSpan(node_datas[node].lhs);
1735 const node = node_off.toAbsolute(src_loc.base_node);
1736 if (tree.nodeTag(node) == .@"return") {
1737 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
1738 return tree.nodeToSpan(lhs);
1739 }
17591740 }
17601741 return tree.nodeToSpan(node);
17611742 },
......@@ -1765,7 +1746,7 @@ pub const SrcLoc = struct {
17651746 .container_field_align,
17661747 => |field_idx| {
17671748 const tree = try src_loc.file_scope.getTree(gpa);
1768 const node = src_loc.relativeToNodeIndex(0);
1749 const node = src_loc.base_node;
17691750 var buf: [2]Ast.Node.Index = undefined;
17701751 const container_decl = tree.fullContainerDecl(&buf, node) orelse
17711752 return tree.nodeToSpan(node);
......@@ -1778,36 +1759,36 @@ pub const SrcLoc = struct {
17781759 continue;
17791760 }
17801761 const field_component_node = switch (src_loc.lazy) {
1781 .container_field_name => 0,
1762 .container_field_name => .none,
17821763 .container_field_value => field.ast.value_expr,
17831764 .container_field_type => field.ast.type_expr,
17841765 .container_field_align => field.ast.align_expr,
17851766 else => unreachable,
17861767 };
1787 if (field_component_node == 0) {
1788 return tree.tokenToSpan(field.ast.main_token);
1768 if (field_component_node.unwrap()) |component_node| {
1769 return tree.nodeToSpan(component_node);
17891770 } else {
1790 return tree.nodeToSpan(field_component_node);
1771 return tree.tokenToSpan(field.ast.main_token);
17911772 }
17921773 } else unreachable;
17931774 },
17941775 .tuple_field_type, .tuple_field_init => |field_info| {
17951776 const tree = try src_loc.file_scope.getTree(gpa);
1796 const node = src_loc.relativeToNodeIndex(0);
1777 const node = src_loc.base_node;
17971778 var buf: [2]Ast.Node.Index = undefined;
17981779 const container_decl = tree.fullContainerDecl(&buf, node) orelse
17991780 return tree.nodeToSpan(node);
18001781
18011782 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;
18021783 return tree.nodeToSpan(switch (src_loc.lazy) {
1803 .tuple_field_type => field.ast.type_expr,
1804 .tuple_field_init => field.ast.value_expr,
1784 .tuple_field_type => field.ast.type_expr.unwrap().?,
1785 .tuple_field_init => field.ast.value_expr.unwrap().?,
18051786 else => unreachable,
18061787 });
18071788 },
18081789 .init_elem => |init_elem| {
18091790 const tree = try src_loc.file_scope.getTree(gpa);
1810 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);
1791 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);
18111792 var buf: [2]Ast.Node.Index = undefined;
18121793 if (tree.fullArrayInit(&buf, init_node)) |full| {
18131794 const elem_node = full.ast.elements[init_elem.elem_index];
......@@ -1817,7 +1798,7 @@ pub const SrcLoc = struct {
18171798 return tree.tokensToSpan(
18181799 tree.firstToken(field_node) - 3,
18191800 tree.lastToken(field_node),
1820 tree.nodes.items(.main_token)[field_node] - 2,
1801 tree.nodeMainToken(field_node) - 2,
18211802 );
18221803 } else unreachable;
18231804 },
......@@ -1846,7 +1827,7 @@ pub const SrcLoc = struct {
18461827 else => unreachable,
18471828 };
18481829 const tree = try src_loc.file_scope.getTree(gpa);
1849 const node = src_loc.relativeToNodeIndex(builtin_call_node);
1830 const node = builtin_call_node.toAbsolute(src_loc.base_node);
18501831 var builtin_buf: [2]Ast.Node.Index = undefined;
18511832 const args = tree.builtinCallParams(&builtin_buf, node).?;
18521833 const arg_node = args[1];
......@@ -1861,7 +1842,7 @@ pub const SrcLoc = struct {
18611842 return tree.tokensToSpan(
18621843 name_token - 1,
18631844 tree.lastToken(field_node),
1864 tree.nodes.items(.main_token)[field_node] - 2,
1845 tree.nodeMainToken(field_node) - 2,
18651846 );
18661847 }
18671848 }
......@@ -1885,12 +1866,9 @@ pub const SrcLoc = struct {
18851866 };
18861867
18871868 const tree = try src_loc.file_scope.getTree(gpa);
1888 const node_datas = tree.nodes.items(.data);
1889 const node_tags = tree.nodes.items(.tag);
1890 const main_tokens = tree.nodes.items(.main_token);
1891 const switch_node = src_loc.relativeToNodeIndex(switch_node_offset);
1892 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1893 const case_nodes = tree.extra_data[extra.start..extra.end];
1869 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);
1870 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1871 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
18941872
18951873 var multi_i: u32 = 0;
18961874 var scalar_i: u32 = 0;
......@@ -1898,8 +1876,8 @@ pub const SrcLoc = struct {
18981876 const case = tree.fullSwitchCase(case_node).?;
18991877 const is_special = special: {
19001878 if (case.ast.values.len == 0) break :special true;
1901 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {
1902 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");
1879 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) {
1880 break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_");
19031881 }
19041882 break :special false;
19051883 };
......@@ -1911,7 +1889,7 @@ pub const SrcLoc = struct {
19111889 }
19121890
19131891 const is_multi = case.ast.values.len != 1 or
1914 node_tags[case.ast.values[0]] == .switch_range;
1892 tree.nodeTag(case.ast.values[0]) == .switch_range;
19151893
19161894 switch (want_case_idx.kind) {
19171895 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,
......@@ -1931,18 +1909,17 @@ pub const SrcLoc = struct {
19311909 .switch_case_item_range_last,
19321910 => |x| x.item_idx,
19331911 .switch_capture, .switch_tag_capture => {
1934 const token_tags = tree.tokens.items(.tag);
19351912 const start = switch (src_loc.lazy) {
19361913 .switch_capture => case.payload_token.?,
19371914 .switch_tag_capture => tok: {
19381915 var tok = case.payload_token.?;
1939 if (token_tags[tok] == .asterisk) tok += 1;
1940 tok += 2; // skip over comma
1916 if (tree.tokenTag(tok) == .asterisk) tok += 1;
1917 tok = tok + 2; // skip over comma
19411918 break :tok tok;
19421919 },
19431920 else => unreachable,
19441921 };
1945 const end = switch (token_tags[start]) {
1922 const end = switch (tree.tokenTag(start)) {
19461923 .asterisk => start + 1,
19471924 else => start,
19481925 };
......@@ -1955,7 +1932,7 @@ pub const SrcLoc = struct {
19551932 .single => {
19561933 var item_i: u32 = 0;
19571934 for (case.ast.values) |item_node| {
1958 if (node_tags[item_node] == .switch_range) continue;
1935 if (tree.nodeTag(item_node) == .switch_range) continue;
19591936 if (item_i != want_item.index) {
19601937 item_i += 1;
19611938 continue;
......@@ -1966,15 +1943,16 @@ pub const SrcLoc = struct {
19661943 .range => {
19671944 var range_i: u32 = 0;
19681945 for (case.ast.values) |item_node| {
1969 if (node_tags[item_node] != .switch_range) continue;
1946 if (tree.nodeTag(item_node) != .switch_range) continue;
19701947 if (range_i != want_item.index) {
19711948 range_i += 1;
19721949 continue;
19731950 }
1951 const first, const last = tree.nodeData(item_node).node_and_node;
19741952 return switch (src_loc.lazy) {
19751953 .switch_case_item => tree.nodeToSpan(item_node),
1976 .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs),
1977 .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs),
1954 .switch_case_item_range_first => tree.nodeToSpan(first),
1955 .switch_case_item_range_last => tree.nodeToSpan(last),
19781956 else => unreachable,
19791957 };
19801958 } else unreachable;
......@@ -1997,7 +1975,7 @@ pub const SrcLoc = struct {
19971975 var param_it = full.iterate(tree);
19981976 for (0..param_idx) |_| assert(param_it.next() != null);
19991977 const param = param_it.next().?;
2000 return tree.nodeToSpan(param.type_expr);
1978 return tree.nodeToSpan(param.type_expr.?);
20011979 },
20021980 }
20031981 }
......@@ -2028,212 +2006,217 @@ pub const LazySrcLoc = struct {
20282006 byte_abs: u32,
20292007 /// The source location points to a token within a source file,
20302008 /// offset from 0. The source file is determined contextually.
2031 token_abs: u32,
2009 token_abs: Ast.TokenIndex,
20322010 /// The source location points to an AST node within a source file,
20332011 /// offset from 0. The source file is determined contextually.
2034 node_abs: u32,
2012 node_abs: Ast.Node.Index,
20352013 /// The source location points to a byte offset within a source file,
20362014 /// offset from the byte offset of the base node within the file.
20372015 byte_offset: u32,
20382016 /// This data is the offset into the token list from the base node's first token.
2039 token_offset: u32,
2017 token_offset: Ast.TokenOffset,
20402018 /// The source location points to an AST node, which is this value offset
20412019 /// from its containing base node AST index.
20422020 node_offset: TracedOffset,
20432021 /// The source location points to the main token of an AST node, found
20442022 /// by taking this AST node index offset from the containing base node.
2045 node_offset_main_token: i32,
2023 node_offset_main_token: Ast.Node.Offset,
20462024 /// The source location points to the beginning of a struct initializer.
2047 node_offset_initializer: i32,
2025 node_offset_initializer: Ast.Node.Offset,
20482026 /// The source location points to a variable declaration type expression,
20492027 /// found by taking this AST node index offset from the containing
20502028 /// base node, which points to a variable declaration AST node. Next, navigate
20512029 /// to the type expression.
2052 node_offset_var_decl_ty: i32,
2030 node_offset_var_decl_ty: Ast.Node.Offset,
20532031 /// The source location points to the alignment expression of a var decl.
2054 node_offset_var_decl_align: i32,
2032 node_offset_var_decl_align: Ast.Node.Offset,
20552033 /// The source location points to the linksection expression of a var decl.
2056 node_offset_var_decl_section: i32,
2034 node_offset_var_decl_section: Ast.Node.Offset,
20572035 /// The source location points to the addrspace expression of a var decl.
2058 node_offset_var_decl_addrspace: i32,
2036 node_offset_var_decl_addrspace: Ast.Node.Offset,
20592037 /// The source location points to the initializer of a var decl.
2060 node_offset_var_decl_init: i32,
2038 node_offset_var_decl_init: Ast.Node.Offset,
20612039 /// The source location points to the given argument of a builtin function call.
20622040 /// `builtin_call_node` points to the builtin call.
20632041 /// `arg_index` is the index of the argument which hte source location refers to.
20642042 node_offset_builtin_call_arg: struct {
2065 builtin_call_node: i32,
2043 builtin_call_node: Ast.Node.Offset,
20662044 arg_index: u32,
20672045 },
20682046 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls
20692047 /// to pointer cast builtins (taking the first argument of the most nested).
2070 node_offset_ptrcast_operand: i32,
2048 node_offset_ptrcast_operand: Ast.Node.Offset,
20712049 /// The source location points to the index expression of an array access
20722050 /// expression, found by taking this AST node index offset from the containing
20732051 /// base node, which points to an array access AST node. Next, navigate
20742052 /// to the index expression.
2075 node_offset_array_access_index: i32,
2053 node_offset_array_access_index: Ast.Node.Offset,
20762054 /// The source location points to the LHS of a slice expression
20772055 /// expression, found by taking this AST node index offset from the containing
20782056 /// base node, which points to a slice AST node. Next, navigate
20792057 /// to the sentinel expression.
2080 node_offset_slice_ptr: i32,
2058 node_offset_slice_ptr: Ast.Node.Offset,
20812059 /// The source location points to start expression of a slice expression
20822060 /// expression, found by taking this AST node index offset from the containing
20832061 /// base node, which points to a slice AST node. Next, navigate
20842062 /// to the sentinel expression.
2085 node_offset_slice_start: i32,
2063 node_offset_slice_start: Ast.Node.Offset,
20862064 /// The source location points to the end expression of a slice
20872065 /// expression, found by taking this AST node index offset from the containing
20882066 /// base node, which points to a slice AST node. Next, navigate
20892067 /// to the sentinel expression.
2090 node_offset_slice_end: i32,
2068 node_offset_slice_end: Ast.Node.Offset,
20912069 /// The source location points to the sentinel expression of a slice
20922070 /// expression, found by taking this AST node index offset from the containing
20932071 /// base node, which points to a slice AST node. Next, navigate
20942072 /// to the sentinel expression.
2095 node_offset_slice_sentinel: i32,
2073 node_offset_slice_sentinel: Ast.Node.Offset,
20962074 /// The source location points to the callee expression of a function
20972075 /// call expression, found by taking this AST node index offset from the containing
20982076 /// base node, which points to a function call AST node. Next, navigate
20992077 /// to the callee expression.
2100 node_offset_call_func: i32,
2078 node_offset_call_func: Ast.Node.Offset,
21012079 /// The payload is offset from the containing base node.
21022080 /// The source location points to the field name of:
21032081 /// * a field access expression (`a.b`), or
21042082 /// * the callee of a method call (`a.b()`)
2105 node_offset_field_name: i32,
2083 node_offset_field_name: Ast.Node.Offset,
21062084 /// The payload is offset from the containing base node.
21072085 /// The source location points to the field name of the operand ("b" node)
21082086 /// of a field initialization expression (`.a = b`)
2109 node_offset_field_name_init: i32,
2087 node_offset_field_name_init: Ast.Node.Offset,
21102088 /// The source location points to the pointer of a pointer deref expression,
21112089 /// found by taking this AST node index offset from the containing
21122090 /// base node, which points to a pointer deref AST node. Next, navigate
21132091 /// to the pointer expression.
2114 node_offset_deref_ptr: i32,
2092 node_offset_deref_ptr: Ast.Node.Offset,
21152093 /// The source location points to the assembly source code of an inline assembly
21162094 /// expression, found by taking this AST node index offset from the containing
21172095 /// base node, which points to inline assembly AST node. Next, navigate
21182096 /// to the asm template source code.
2119 node_offset_asm_source: i32,
2097 node_offset_asm_source: Ast.Node.Offset,
21202098 /// The source location points to the return type of an inline assembly
21212099 /// expression, found by taking this AST node index offset from the containing
21222100 /// base node, which points to inline assembly AST node. Next, navigate
21232101 /// to the return type expression.
2124 node_offset_asm_ret_ty: i32,
2102 node_offset_asm_ret_ty: Ast.Node.Offset,
21252103 /// The source location points to the condition expression of an if
21262104 /// expression, found by taking this AST node index offset from the containing
21272105 /// base node, which points to an if expression AST node. Next, navigate
21282106 /// to the condition expression.
2129 node_offset_if_cond: i32,
2107 node_offset_if_cond: Ast.Node.Offset,
21302108 /// The source location points to a binary expression, such as `a + b`, found
21312109 /// by taking this AST node index offset from the containing base node.
2132 node_offset_bin_op: i32,
2110 node_offset_bin_op: Ast.Node.Offset,
21332111 /// The source location points to the LHS of a binary expression, found
21342112 /// by taking this AST node index offset from the containing base node,
21352113 /// which points to a binary expression AST node. Next, navigate to the LHS.
2136 node_offset_bin_lhs: i32,
2114 node_offset_bin_lhs: Ast.Node.Offset,
21372115 /// The source location points to the RHS of a binary expression, found
21382116 /// by taking this AST node index offset from the containing base node,
21392117 /// which points to a binary expression AST node. Next, navigate to the RHS.
2140 node_offset_bin_rhs: i32,
2118 node_offset_bin_rhs: Ast.Node.Offset,
2119 /// The source location points to the operand of a try expression, found
2120 /// by taking this AST node index offset from the containing base node,
2121 /// which points to a try expression AST node. Next, navigate to the
2122 /// operand expression.
2123 node_offset_try_operand: Ast.Node.Offset,
21412124 /// The source location points to the operand of a switch expression, found
21422125 /// by taking this AST node index offset from the containing base node,
21432126 /// which points to a switch expression AST node. Next, navigate to the operand.
2144 node_offset_switch_operand: i32,
2127 node_offset_switch_operand: Ast.Node.Offset,
21452128 /// The source location points to the else/`_` prong of a switch expression, found
21462129 /// by taking this AST node index offset from the containing base node,
21472130 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.
2148 node_offset_switch_special_prong: i32,
2131 node_offset_switch_special_prong: Ast.Node.Offset,
21492132 /// The source location points to all the ranges of a switch expression, found
21502133 /// by taking this AST node index offset from the containing base node,
21512134 /// which points to a switch expression AST node. Next, navigate to any of the
21522135 /// range nodes. The error applies to all of them.
2153 node_offset_switch_range: i32,
2136 node_offset_switch_range: Ast.Node.Offset,
21542137 /// The source location points to the align expr of a function type
21552138 /// expression, found by taking this AST node index offset from the containing
21562139 /// base node, which points to a function type AST node. Next, navigate to
21572140 /// the calling convention node.
2158 node_offset_fn_type_align: i32,
2141 node_offset_fn_type_align: Ast.Node.Offset,
21592142 /// The source location points to the addrspace expr of a function type
21602143 /// expression, found by taking this AST node index offset from the containing
21612144 /// base node, which points to a function type AST node. Next, navigate to
21622145 /// the calling convention node.
2163 node_offset_fn_type_addrspace: i32,
2146 node_offset_fn_type_addrspace: Ast.Node.Offset,
21642147 /// The source location points to the linksection expr of a function type
21652148 /// expression, found by taking this AST node index offset from the containing
21662149 /// base node, which points to a function type AST node. Next, navigate to
21672150 /// the calling convention node.
2168 node_offset_fn_type_section: i32,
2151 node_offset_fn_type_section: Ast.Node.Offset,
21692152 /// The source location points to the calling convention of a function type
21702153 /// expression, found by taking this AST node index offset from the containing
21712154 /// base node, which points to a function type AST node. Next, navigate to
21722155 /// the calling convention node.
2173 node_offset_fn_type_cc: i32,
2156 node_offset_fn_type_cc: Ast.Node.Offset,
21742157 /// The source location points to the return type of a function type
21752158 /// expression, found by taking this AST node index offset from the containing
21762159 /// base node, which points to a function type AST node. Next, navigate to
21772160 /// the return type node.
2178 node_offset_fn_type_ret_ty: i32,
2179 node_offset_param: i32,
2180 token_offset_param: i32,
2161 node_offset_fn_type_ret_ty: Ast.Node.Offset,
2162 node_offset_param: Ast.Node.Offset,
2163 token_offset_param: Ast.TokenOffset,
21812164 /// The source location points to the type expression of an `anyframe->T`
21822165 /// expression, found by taking this AST node index offset from the containing
21832166 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate
21842167 /// to the type expression.
2185 node_offset_anyframe_type: i32,
2168 node_offset_anyframe_type: Ast.Node.Offset,
21862169 /// The source location points to the string literal of `extern "foo"`, found
21872170 /// by taking this AST node index offset from the containing
21882171 /// base node, which points to a function prototype or variable declaration
21892172 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
2190 node_offset_lib_name: i32,
2173 node_offset_lib_name: Ast.Node.Offset,
21912174 /// The source location points to the len expression of an `[N:S]T`
21922175 /// expression, found by taking this AST node index offset from the containing
21932176 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
21942177 /// to the len expression.
2195 node_offset_array_type_len: i32,
2178 node_offset_array_type_len: Ast.Node.Offset,
21962179 /// The source location points to the sentinel expression of an `[N:S]T`
21972180 /// expression, found by taking this AST node index offset from the containing
21982181 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
21992182 /// to the sentinel expression.
2200 node_offset_array_type_sentinel: i32,
2183 node_offset_array_type_sentinel: Ast.Node.Offset,
22012184 /// The source location points to the elem expression of an `[N:S]T`
22022185 /// expression, found by taking this AST node index offset from the containing
22032186 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
22042187 /// to the elem expression.
2205 node_offset_array_type_elem: i32,
2188 node_offset_array_type_elem: Ast.Node.Offset,
22062189 /// The source location points to the operand of an unary expression.
2207 node_offset_un_op: i32,
2190 node_offset_un_op: Ast.Node.Offset,
22082191 /// The source location points to the elem type of a pointer.
2209 node_offset_ptr_elem: i32,
2192 node_offset_ptr_elem: Ast.Node.Offset,
22102193 /// The source location points to the sentinel of a pointer.
2211 node_offset_ptr_sentinel: i32,
2194 node_offset_ptr_sentinel: Ast.Node.Offset,
22122195 /// The source location points to the align expr of a pointer.
2213 node_offset_ptr_align: i32,
2196 node_offset_ptr_align: Ast.Node.Offset,
22142197 /// The source location points to the addrspace expr of a pointer.
2215 node_offset_ptr_addrspace: i32,
2198 node_offset_ptr_addrspace: Ast.Node.Offset,
22162199 /// The source location points to the bit-offset of a pointer.
2217 node_offset_ptr_bitoffset: i32,
2200 node_offset_ptr_bitoffset: Ast.Node.Offset,
22182201 /// The source location points to the host size of a pointer.
2219 node_offset_ptr_hostsize: i32,
2202 node_offset_ptr_hostsize: Ast.Node.Offset,
22202203 /// The source location points to the tag type of an union or an enum.
2221 node_offset_container_tag: i32,
2204 node_offset_container_tag: Ast.Node.Offset,
22222205 /// The source location points to the default value of a field.
2223 node_offset_field_default: i32,
2206 node_offset_field_default: Ast.Node.Offset,
22242207 /// The source location points to the type of an array or struct initializer.
2225 node_offset_init_ty: i32,
2208 node_offset_init_ty: Ast.Node.Offset,
22262209 /// The source location points to the LHS of an assignment.
2227 node_offset_store_ptr: i32,
2210 node_offset_store_ptr: Ast.Node.Offset,
22282211 /// The source location points to the RHS of an assignment.
2229 node_offset_store_operand: i32,
2212 node_offset_store_operand: Ast.Node.Offset,
22302213 /// The source location points to the operand of a `return` statement, or
22312214 /// the `return` itself if there is no explicit operand.
2232 node_offset_return_operand: i32,
2215 node_offset_return_operand: Ast.Node.Offset,
22332216 /// The source location points to a for loop input.
22342217 for_input: struct {
22352218 /// Points to the for loop AST node.
2236 for_node_offset: i32,
2219 for_node_offset: Ast.Node.Offset,
22372220 /// Picks one of the inputs from the condition.
22382221 input_index: u32,
22392222 },
......@@ -2241,11 +2224,11 @@ pub const LazySrcLoc = struct {
22412224 /// by taking this AST node index offset from the containing
22422225 /// base node, which points to one of the input nodes of a for loop.
22432226 /// Next, navigate to the corresponding capture.
2244 for_capture_from_input: i32,
2227 for_capture_from_input: Ast.Node.Offset,
22452228 /// The source location points to the argument node of a function call.
22462229 call_arg: struct {
22472230 /// Points to the function call AST node.
2248 call_node_offset: i32,
2231 call_node_offset: Ast.Node.Offset,
22492232 /// The index of the argument the source location points to.
22502233 arg_index: u32,
22512234 },
......@@ -2272,25 +2255,25 @@ pub const LazySrcLoc = struct {
22722255 /// array initialization expression.
22732256 init_elem: struct {
22742257 /// Points to the AST node of the initialization expression.
2275 init_node_offset: i32,
2258 init_node_offset: Ast.Node.Offset,
22762259 /// The index of the field/element the source location points to.
22772260 elem_index: u32,
22782261 },
22792262 // The following source locations are like `init_elem`, but refer to a
22802263 // field with a specific name. If such a field is not given, the entire
22812264 // initialization expression is used instead.
2282 // The `i32` points to the AST node of a builtin call, whose *second*
2265 // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second*
22832266 // argument is the init expression.
2284 init_field_name: i32,
2285 init_field_linkage: i32,
2286 init_field_section: i32,
2287 init_field_visibility: i32,
2288 init_field_rw: i32,
2289 init_field_locality: i32,
2290 init_field_cache: i32,
2291 init_field_library: i32,
2292 init_field_thread_local: i32,
2293 init_field_dll_import: i32,
2267 init_field_name: Ast.Node.Offset,
2268 init_field_linkage: Ast.Node.Offset,
2269 init_field_section: Ast.Node.Offset,
2270 init_field_visibility: Ast.Node.Offset,
2271 init_field_rw: Ast.Node.Offset,
2272 init_field_locality: Ast.Node.Offset,
2273 init_field_cache: Ast.Node.Offset,
2274 init_field_library: Ast.Node.Offset,
2275 init_field_thread_local: Ast.Node.Offset,
2276 init_field_dll_import: Ast.Node.Offset,
22942277 /// The source location points to the value of an item in a specific
22952278 /// case of a `switch`.
22962279 switch_case_item: SwitchItem,
......@@ -2315,14 +2298,14 @@ pub const LazySrcLoc = struct {
23152298
23162299 pub const FnProtoParam = struct {
23172300 /// The offset of the function prototype AST node.
2318 fn_proto_node_offset: i32,
2301 fn_proto_node_offset: Ast.Node.Offset,
23192302 /// The index of the parameter the source location points to.
23202303 param_index: u32,
23212304 };
23222305
23232306 pub const SwitchItem = struct {
23242307 /// The offset of the switch AST node.
2325 switch_node_offset: i32,
2308 switch_node_offset: Ast.Node.Offset,
23262309 /// The index of the case to point to within this switch.
23272310 case_idx: SwitchCaseIndex,
23282311 /// The index of the item to point to within this case.
......@@ -2331,7 +2314,7 @@ pub const LazySrcLoc = struct {
23312314
23322315 pub const SwitchCapture = struct {
23332316 /// The offset of the switch AST node.
2334 switch_node_offset: i32,
2317 switch_node_offset: Ast.Node.Offset,
23352318 /// The index of the case whose capture to point to.
23362319 case_idx: SwitchCaseIndex,
23372320 };
......@@ -2353,34 +2336,34 @@ pub const LazySrcLoc = struct {
23532336
23542337 pub const ArrayCat = struct {
23552338 /// Points to the array concat AST node.
2356 array_cat_offset: i32,
2339 array_cat_offset: Ast.Node.Offset,
23572340 /// The index of the element the source location points to.
23582341 elem_index: u32,
23592342 };
23602343
23612344 pub const TupleField = struct {
23622345 /// Points to the AST node of the tuple type decaration.
2363 tuple_decl_node_offset: i32,
2346 tuple_decl_node_offset: Ast.Node.Offset,
23642347 /// The index of the tuple field the source location points to.
23652348 elem_index: u32,
23662349 };
23672350
23682351 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23692352
2370 noinline fn nodeOffsetDebug(node_offset: i32) Offset {
2353 noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset {
23712354 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
23722355 result.node_offset.trace.addAddr(@returnAddress(), "init");
23732356 return result;
23742357 }
23752358
2376 fn nodeOffsetRelease(node_offset: i32) Offset {
2359 fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset {
23772360 return .{ .node_offset = .{ .x = node_offset } };
23782361 }
23792362
23802363 /// This wraps a simple integer in debug builds so that later on we can find out
23812364 /// where in semantic analysis the value got set.
23822365 pub const TracedOffset = struct {
2383 x: i32,
2366 x: Ast.Node.Offset,
23842367 trace: std.debug.Trace = std.debug.Trace.init,
23852368
23862369 const want_tracing = false;
......@@ -2405,7 +2388,7 @@ pub const LazySrcLoc = struct {
24052388
24062389 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,
24072390 // which may not exist e.g. in the case of errors in ZON files.
2408 if (zir_inst == .main_struct_inst) return .{ file, 0 };
2391 if (zir_inst == .main_struct_inst) return .{ file, .root };
24092392
24102393 // Otherwise, make sure ZIR is loaded.
24112394 const zir = file.zir.?;
......@@ -2438,7 +2421,7 @@ pub const LazySrcLoc = struct {
24382421 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {
24392422 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{
24402423 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),
2441 0,
2424 .root,
24422425 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
24432426 return .{
24442427 .file_scope = file,
......@@ -4007,7 +3990,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {
40073990 const ip = &zcu.intern_pool;
40083991 return .{
40093992 .base_node_inst = ip.getNav(nav_index).srcInst(ip),
4010 .offset = LazySrcLoc.Offset.nodeOffset(0),
3993 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
40113994 };
40123995}
40133996
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+10-8
......@@ -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,8 +7284,8 @@ 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 if (dep.hash_node != 0) {
7286 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);
72877289 } else {
72887290 // https://github.com/ziglang/zig/issues/21690
72897291 }
......@@ -7292,9 +7294,9 @@ fn cmdFetch(
72927294 const deps = manifest.dependencies.values();
72937295 const last_dep_node = deps[deps.len - 1].node;
72947296 try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text);
7295 } else if (manifest.dependencies_node != 0) {
7297 } else if (manifest.dependencies_node.unwrap()) |dependencies_node| {
72967298 // Add fixup for replacing the entire dependencies struct.
7297 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);
72987300 } else {
72997301 // Add fixup for adding dependencies struct.
73007302 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);