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

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

improve type safety of std.zig.Ast

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

lib/compiler/aro_translate_c/ast.zig+383-440
...@@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {...@@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
775 ctx.nodes.appendAssumeCapacity(.{775 ctx.nodes.appendAssumeCapacity(.{
776 .tag = .root,776 .tag = .root,
777 .main_token = 0,777 .main_token = 0,
778 .data = .{778 .data = undefined,
779 .lhs = undefined,
780 .rhs = undefined,
781 },
782 });779 });
783780
784 const root_members = blk: {781 const root_members = blk: {
...@@ -793,10 +790,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {...@@ -793,10 +790,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
793 break :blk try ctx.listToSpan(result.items);790 break :blk try ctx.listToSpan(result.items);
794 };791 };
795792
796 ctx.nodes.items(.data)[0] = .{793 ctx.nodes.items(.data)[0] = .{ .extra_range = root_members };
797 .lhs = root_members.start,
798 .rhs = root_members.end,
799 };
800794
801 try ctx.tokens.append(gpa, .{795 try ctx.tokens.append(gpa, .{
802 .tag = .eof,796 .tag = .eof,
...@@ -814,15 +808,18 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {...@@ -814,15 +808,18 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {
814}808}
815809
816const NodeIndex = std.zig.Ast.Node.Index;810const NodeIndex = std.zig.Ast.Node.Index;
811const NodeOptionalIndex = std.zig.Ast.Node.OptionalIndex;
817const NodeSubRange = std.zig.Ast.Node.SubRange;812const NodeSubRange = std.zig.Ast.Node.SubRange;
818const TokenIndex = std.zig.Ast.TokenIndex;813const TokenIndex = std.zig.Ast.TokenIndex;
814const TokenOptionalIndex = std.zig.Ast.OptionalTokenIndex;
819const TokenTag = std.zig.Token.Tag;815const TokenTag = std.zig.Token.Tag;
816const ExtraIndex = std.zig.Ast.ExtraIndex;
820817
821const Context = struct {818const Context = struct {
822 gpa: Allocator,819 gpa: Allocator,
823 buf: std.ArrayList(u8),820 buf: std.ArrayList(u8),
824 nodes: std.zig.Ast.NodeList = .{},821 nodes: std.zig.Ast.NodeList = .{},
825 extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .empty,822 extra_data: std.ArrayListUnmanaged(u32) = .empty,
826 tokens: std.zig.Ast.TokenList = .{},823 tokens: std.zig.Ast.TokenList = .{},
827824
828 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {825 fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex {
...@@ -834,7 +831,7 @@ const Context = struct {...@@ -834,7 +831,7 @@ const Context = struct {
834 .start = @as(u32, @intCast(start_index)),831 .start = @as(u32, @intCast(start_index)),
835 });832 });
836833
837 return @as(u32, @intCast(c.tokens.len - 1));834 return @intCast(c.tokens.len - 1);
838 }835 }
839836
840 fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {837 fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex {
...@@ -848,26 +845,33 @@ const Context = struct {...@@ -848,26 +845,33 @@ const Context = struct {
848 }845 }
849846
850 fn listToSpan(c: *Context, list: []const NodeIndex) Allocator.Error!NodeSubRange {847 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));
852 return NodeSubRange{849 return NodeSubRange{
853 .start = @as(NodeIndex, @intCast(c.extra_data.items.len - list.len)),850 .start = @enumFromInt(c.extra_data.items.len - list.len),
854 .end = @as(NodeIndex, @intCast(c.extra_data.items.len)),851 .end = @enumFromInt(c.extra_data.items.len),
855 };852 };
856 }853 }
857854
858 fn addNode(c: *Context, elem: std.zig.Ast.Node) Allocator.Error!NodeIndex {855 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);
860 try c.nodes.append(c.gpa, elem);857 try c.nodes.append(c.gpa, elem);
861 return result;858 return result;
862 }859 }
863860
864 fn addExtra(c: *Context, extra: anytype) Allocator.Error!NodeIndex {861 fn addExtra(c: *Context, extra: anytype) Allocator.Error!std.zig.Ast.ExtraIndex {
865 const fields = std.meta.fields(@TypeOf(extra));862 const fields = std.meta.fields(@TypeOf(extra));
866 try c.extra_data.ensureUnusedCapacity(c.gpa, fields.len);863 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);
868 inline for (fields) |field| {865 inline for (fields) |field| {
869 comptime std.debug.assert(field.type == NodeIndex);866 switch (field.type) {
870 c.extra_data.appendAssumeCapacity(@field(extra, field.name));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 }
871 }875 }
872 return result;876 return result;
873 }877 }
...@@ -894,7 +898,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -894,7 +898,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
894 try c.buf.append('\n');898 try c.buf.append('\n');
895 try c.buf.appendSlice(payload);899 try c.buf.appendSlice(payload);
896 try c.buf.append('\n');900 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);
898 },902 },
899 .helpers_cast => {903 .helpers_cast => {
900 const payload = node.castTag(.helpers_cast).?.data;904 const payload = node.castTag(.helpers_cast).?.data;
...@@ -991,26 +995,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -991,26 +995,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
991 .@"continue" => return c.addNode(.{995 .@"continue" => return c.addNode(.{
992 .tag = .@"continue",996 .tag = .@"continue",
993 .main_token = try c.addToken(.keyword_continue, "continue"),997 .main_token = try c.addToken(.keyword_continue, "continue"),
994 .data = .{998 .data = .{ .opt_token_and_opt_node = .{ .none, .none } },
995 .lhs = 0,
996 .rhs = undefined,
997 },
998 }),999 }),
999 .return_void => return c.addNode(.{1000 .return_void => return c.addNode(.{
1000 .tag = .@"return",1001 .tag = .@"return",
1001 .main_token = try c.addToken(.keyword_return, "return"),1002 .main_token = try c.addToken(.keyword_return, "return"),
1002 .data = .{1003 .data = .{ .opt_node = .none },
1003 .lhs = 0,
1004 .rhs = undefined,
1005 },
1006 }),1004 }),
1007 .@"break" => return c.addNode(.{1005 .@"break" => return c.addNode(.{
1008 .tag = .@"break",1006 .tag = .@"break",
1009 .main_token = try c.addToken(.keyword_break, "break"),1007 .main_token = try c.addToken(.keyword_break, "break"),
1010 .data = .{1008 .data = .{ .opt_token_and_opt_node = .{ .none, .none } },
1011 .lhs = 0,
1012 .rhs = 0,
1013 },
1014 }),1009 }),
1015 .break_val => {1010 .break_val => {
1016 const payload = node.castTag(.break_val).?.data;1011 const payload = node.castTag(.break_val).?.data;
...@@ -1018,14 +1013,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1018,14 +1013,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1018 const break_label = if (payload.label) |some| blk: {1013 const break_label = if (payload.label) |some| blk: {
1019 _ = try c.addToken(.colon, ":");1014 _ = try c.addToken(.colon, ":");
1020 break :blk try c.addIdentifier(some);1015 break :blk try c.addIdentifier(some);
1021 } else 0;1016 } else null;
1022 return c.addNode(.{1017 return c.addNode(.{
1023 .tag = .@"break",1018 .tag = .@"break",
1024 .main_token = tok,1019 .main_token = tok,
1025 .data = .{1020 .data = .{ .opt_token_and_opt_node = .{
1026 .lhs = break_label,1021 .fromOptional(break_label),
1027 .rhs = try renderNode(c, payload.val),1022 (try renderNode(c, payload.val)).toOptional(),
1028 },1023 } },
1029 });1024 });
1030 },1025 },
1031 .@"return" => {1026 .@"return" => {
...@@ -1033,10 +1028,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1033,10 +1028,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1033 return c.addNode(.{1028 return c.addNode(.{
1034 .tag = .@"return",1029 .tag = .@"return",
1035 .main_token = try c.addToken(.keyword_return, "return"),1030 .main_token = try c.addToken(.keyword_return, "return"),
1036 .data = .{1031 .data = .{ .opt_node = (try renderNode(c, payload)).toOptional() },
1037 .lhs = try renderNode(c, payload),
1038 .rhs = undefined,
1039 },
1040 });1032 });
1041 },1033 },
1042 .@"comptime" => {1034 .@"comptime" => {
...@@ -1044,10 +1036,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1044,10 +1036,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1044 return c.addNode(.{1036 return c.addNode(.{
1045 .tag = .@"comptime",1037 .tag = .@"comptime",
1046 .main_token = try c.addToken(.keyword_comptime, "comptime"),1038 .main_token = try c.addToken(.keyword_comptime, "comptime"),
1047 .data = .{1039 .data = .{ .node = try renderNode(c, payload) },
1048 .lhs = try renderNode(c, payload),
1049 .rhs = undefined,
1050 },
1051 });1040 });
1052 },1041 },
1053 .@"defer" => {1042 .@"defer" => {
...@@ -1055,10 +1044,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1055,10 +1044,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1055 return c.addNode(.{1044 return c.addNode(.{
1056 .tag = .@"defer",1045 .tag = .@"defer",
1057 .main_token = try c.addToken(.keyword_defer, "defer"),1046 .main_token = try c.addToken(.keyword_defer, "defer"),
1058 .data = .{1047 .data = .{ .node = try renderNode(c, payload) },
1059 .lhs = undefined,
1060 .rhs = try renderNode(c, payload),
1061 },
1062 });1048 });
1063 },1049 },
1064 .asm_simple => {1050 .asm_simple => {
...@@ -1068,10 +1054,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1068,10 +1054,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1068 return c.addNode(.{1054 return c.addNode(.{
1069 .tag = .asm_simple,1055 .tag = .asm_simple,
1070 .main_token = asm_token,1056 .main_token = asm_token,
1071 .data = .{1057 .data = .{ .node_and_token = .{
1072 .lhs = try renderNode(c, payload),1058 try renderNode(c, payload),
1073 .rhs = try c.addToken(.r_paren, ")"),1059 try c.addToken(.r_paren, ")"),
1074 },1060 } },
1075 });1061 });
1076 },1062 },
1077 .type => {1063 .type => {
...@@ -1104,10 +1090,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1104,10 +1090,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1104 return c.addNode(.{1090 return c.addNode(.{
1105 .tag = .address_of,1091 .tag = .address_of,
1106 .main_token = tok,1092 .main_token = tok,
1107 .data = .{1093 .data = .{ .node = arg },
1108 .lhs = arg,
1109 .rhs = undefined,
1110 },
1111 });1094 });
1112 },1095 },
1113 .float_literal => {1096 .float_literal => {
...@@ -1191,13 +1174,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1191,13 +1174,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1191 return c.addNode(.{1174 return c.addNode(.{
1192 .tag = .slice,1175 .tag = .slice,
1193 .main_token = l_bracket,1176 .main_token = l_bracket,
1194 .data = .{1177 .data = .{ .node_and_extra = .{
1195 .lhs = string,1178 string,
1196 .rhs = try c.addExtra(std.zig.Ast.Node.Slice{1179 try c.addExtra(std.zig.Ast.Node.Slice{
1197 .start = start,1180 .start = start,
1198 .end = end,1181 .end = end,
1199 }),1182 }),
1200 },1183 } },
1201 });1184 });
1202 },1185 },
1203 .fail_decl => {1186 .fail_decl => {
...@@ -1220,20 +1203,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1220,20 +1203,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1220 const compile_error = try c.addNode(.{1203 const compile_error = try c.addNode(.{
1221 .tag = .builtin_call_two,1204 .tag = .builtin_call_two,
1222 .main_token = compile_error_tok,1205 .main_token = compile_error_tok,
1223 .data = .{1206 .data = .{ .opt_node_and_opt_node = .{ err_msg.toOptional(), .none } },
1224 .lhs = err_msg,
1225 .rhs = 0,
1226 },
1227 });1207 });
1228 _ = try c.addToken(.semicolon, ";");1208 _ = try c.addToken(.semicolon, ";");
12291209
1230 return c.addNode(.{1210 return c.addNode(.{
1231 .tag = .simple_var_decl,1211 .tag = .simple_var_decl,
1232 .main_token = const_tok,1212 .main_token = const_tok,
1233 .data = .{1213 .data = .{ .opt_node_and_opt_node = .{
1234 .lhs = 0,1214 .none,
1235 .rhs = compile_error,1215 compile_error.toOptional(),
1236 },1216 } },
1237 });1217 });
1238 },1218 },
1239 .pub_var_simple, .var_simple => {1219 .pub_var_simple, .var_simple => {
...@@ -1249,10 +1229,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1249,10 +1229,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1249 return c.addNode(.{1229 return c.addNode(.{
1250 .tag = .simple_var_decl,1230 .tag = .simple_var_decl,
1251 .main_token = const_tok,1231 .main_token = const_tok,
1252 .data = .{1232 .data = .{ .opt_node_and_opt_node = .{
1253 .lhs = 0,1233 .none,
1254 .rhs = init,1234 init.toOptional(),
1255 },1235 } },
1256 });1236 });
1257 },1237 },
1258 .static_local_var => {1238 .static_local_var => {
...@@ -1268,10 +1248,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1268,10 +1248,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1268 const container_def = try c.addNode(.{1248 const container_def = try c.addNode(.{
1269 .tag = .container_decl_two_trailing,1249 .tag = .container_decl_two_trailing,
1270 .main_token = kind_tok,1250 .main_token = kind_tok,
1271 .data = .{1251 .data = .{ .opt_node_and_opt_node = .{
1272 .lhs = try renderNode(c, payload.init),1252 (try renderNode(c, payload.init)).toOptional(),
1273 .rhs = 0,1253 .none,
1274 },1254 } },
1275 });1255 });
1276 _ = try c.addToken(.r_brace, "}");1256 _ = try c.addToken(.r_brace, "}");
1277 _ = try c.addToken(.semicolon, ";");1257 _ = try c.addToken(.semicolon, ";");
...@@ -1279,10 +1259,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1279,10 +1259,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1279 return c.addNode(.{1259 return c.addNode(.{
1280 .tag = .simple_var_decl,1260 .tag = .simple_var_decl,
1281 .main_token = const_tok,1261 .main_token = const_tok,
1282 .data = .{1262 .data = .{ .opt_node_and_opt_node = .{
1283 .lhs = 0,1263 .none,
1284 .rhs = container_def,1264 container_def.toOptional(),
1285 },1265 } },
1286 });1266 });
1287 },1267 },
1288 .extern_local_var => {1268 .extern_local_var => {
...@@ -1298,10 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1298,10 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1298 const container_def = try c.addNode(.{1278 const container_def = try c.addNode(.{
1299 .tag = .container_decl_two_trailing,1279 .tag = .container_decl_two_trailing,
1300 .main_token = kind_tok,1280 .main_token = kind_tok,
1301 .data = .{1281 .data = .{ .opt_node_and_opt_node = .{
1302 .lhs = try renderNode(c, payload.init),1282 (try renderNode(c, payload.init)).toOptional(),
1303 .rhs = 0,1283 .none,
1304 },1284 } },
1305 });1285 });
1306 _ = try c.addToken(.r_brace, "}");1286 _ = try c.addToken(.r_brace, "}");
1307 _ = try c.addToken(.semicolon, ";");1287 _ = try c.addToken(.semicolon, ";");
...@@ -1309,10 +1289,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1309,10 +1289,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1309 return c.addNode(.{1289 return c.addNode(.{
1310 .tag = .simple_var_decl,1290 .tag = .simple_var_decl,
1311 .main_token = const_tok,1291 .main_token = const_tok,
1312 .data = .{1292 .data = .{ .opt_node_and_opt_node = .{
1313 .lhs = 0,1293 .none,
1314 .rhs = container_def,1294 container_def.toOptional(),
1315 },1295 } },
1316 });1296 });
1317 },1297 },
1318 .mut_str => {1298 .mut_str => {
...@@ -1324,10 +1304,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1324,10 +1304,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
13241304
1325 const deref = try c.addNode(.{1305 const deref = try c.addNode(.{
1326 .tag = .deref,1306 .tag = .deref,
1327 .data = .{1307 .data = .{ .node = try renderNodeGrouped(c, payload.init) },
1328 .lhs = try renderNodeGrouped(c, payload.init),
1329 .rhs = undefined,
1330 },
1331 .main_token = try c.addToken(.period_asterisk, ".*"),1308 .main_token = try c.addToken(.period_asterisk, ".*"),
1332 });1309 });
1333 _ = try c.addToken(.semicolon, ";");1310 _ = try c.addToken(.semicolon, ";");
...@@ -1335,7 +1312,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1335,7 +1312,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1335 return c.addNode(.{1312 return c.addNode(.{
1336 .tag = .simple_var_decl,1313 .tag = .simple_var_decl,
1337 .main_token = var_tok,1314 .main_token = var_tok,
1338 .data = .{ .lhs = 0, .rhs = deref },1315 .data = .{ .opt_node_and_opt_node = .{
1316 .none,
1317 deref.toOptional(),
1318 } },
1339 });1319 });
1340 },1320 },
1341 .var_decl => return renderVar(c, node),1321 .var_decl => return renderVar(c, node),
...@@ -1359,10 +1339,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1359,10 +1339,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1359 return c.addNode(.{1339 return c.addNode(.{
1360 .tag = .simple_var_decl,1340 .tag = .simple_var_decl,
1361 .main_token = mut_tok,1341 .main_token = mut_tok,
1362 .data = .{1342 .data = .{ .opt_node_and_opt_node = .{
1363 .lhs = 0,1343 .none,
1364 .rhs = init,1344 init.toOptional(),
1365 },1345 } },
1366 });1346 });
1367 },1347 },
1368 .int_cast => {1348 .int_cast => {
...@@ -1505,10 +1485,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1505,10 +1485,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1505 return c.addNode(.{1485 return c.addNode(.{
1506 .tag = .address_of,1486 .tag = .address_of,
1507 .main_token = ampersand,1487 .main_token = ampersand,
1508 .data = .{1488 .data = .{ .node = base },
1509 .lhs = base,
1510 .rhs = undefined,
1511 },
1512 });1489 });
1513 },1490 },
1514 .deref => {1491 .deref => {
...@@ -1518,10 +1495,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1518,10 +1495,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1518 return c.addNode(.{1495 return c.addNode(.{
1519 .tag = .deref,1496 .tag = .deref,
1520 .main_token = deref_tok,1497 .main_token = deref_tok,
1521 .data = .{1498 .data = .{ .node = operand },
1522 .lhs = operand,
1523 .rhs = undefined,
1524 },
1525 });1499 });
1526 },1500 },
1527 .unwrap => {1501 .unwrap => {
...@@ -1532,10 +1506,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1532,10 +1506,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1532 return c.addNode(.{1506 return c.addNode(.{
1533 .tag = .unwrap_optional,1507 .tag = .unwrap_optional,
1534 .main_token = period,1508 .main_token = period,
1535 .data = .{1509 .data = .{ .node_and_token = .{
1536 .lhs = operand,1510 operand,
1537 .rhs = question_mark,1511 question_mark,
1538 },1512 } },
1539 });1513 });
1540 },1514 },
1541 .c_pointer, .single_pointer => {1515 .c_pointer, .single_pointer => {
...@@ -1557,10 +1531,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1557,10 +1531,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1557 return c.addNode(.{1531 return c.addNode(.{
1558 .tag = .ptr_type_aligned,1532 .tag = .ptr_type_aligned,
1559 .main_token = main_token,1533 .main_token = main_token,
1560 .data = .{1534 .data = .{ .opt_node_and_node = .{
1561 .lhs = 0,1535 .none,
1562 .rhs = elem_type,1536 elem_type,
1563 },1537 } },
1564 });1538 });
1565 },1539 },
1566 .add => return renderBinOpGrouped(c, node, .add, .plus, "+"),1540 .add => return renderBinOpGrouped(c, node, .add, .plus, "+"),
...@@ -1606,10 +1580,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1606,10 +1580,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1606 return c.addNode(.{1580 return c.addNode(.{
1607 .tag = .block_two,1581 .tag = .block_two,
1608 .main_token = l_brace,1582 .main_token = l_brace,
1609 .data = .{1583 .data = .{ .opt_node_and_opt_node = .{
1610 .lhs = 0,1584 .none,
1611 .rhs = 0,1585 .none,
1612 },1586 } },
1613 });1587 });
1614 },1588 },
1615 .block_single => {1589 .block_single => {
...@@ -1623,10 +1597,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1623,10 +1597,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1623 return c.addNode(.{1597 return c.addNode(.{
1624 .tag = .block_two_semicolon,1598 .tag = .block_two_semicolon,
1625 .main_token = l_brace,1599 .main_token = l_brace,
1626 .data = .{1600 .data = .{ .opt_node_and_opt_node = .{
1627 .lhs = stmt,1601 stmt.toOptional(),
1628 .rhs = 0,1602 .none,
1629 },1603 } },
1630 });1604 });
1631 },1605 },
1632 .block => {1606 .block => {
...@@ -1641,7 +1615,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1641,7 +1615,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1641 defer stmts.deinit();1615 defer stmts.deinit();
1642 for (payload.stmts) |stmt| {1616 for (payload.stmts) |stmt| {
1643 const res = try renderNode(c, stmt);1617 const res = try renderNode(c, stmt);
1644 if (res == 0) continue;1618 if (@intFromEnum(res) == 0) continue;
1645 try addSemicolonIfNeeded(c, stmt);1619 try addSemicolonIfNeeded(c, stmt);
1646 try stmts.append(res);1620 try stmts.append(res);
1647 }1621 }
...@@ -1652,17 +1626,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1652,17 +1626,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1652 return c.addNode(.{1626 return c.addNode(.{
1653 .tag = if (semicolon) .block_semicolon else .block,1627 .tag = if (semicolon) .block_semicolon else .block,
1654 .main_token = l_brace,1628 .main_token = l_brace,
1655 .data = .{1629 .data = .{ .extra_range = span },
1656 .lhs = span.start,
1657 .rhs = span.end,
1658 },
1659 });1630 });
1660 },1631 },
1661 .func => return renderFunc(c, node),1632 .func => return renderFunc(c, node),
1662 .pub_inline_fn => return renderMacroFunc(c, node),1633 .pub_inline_fn => return renderMacroFunc(c, node),
1663 .discard => {1634 .discard => {
1664 const payload = node.castTag(.discard).?.data;1635 const payload = node.castTag(.discard).?.data;
1665 if (payload.should_skip) return @as(NodeIndex, 0);1636 if (payload.should_skip) return @enumFromInt(0);
16661637
1667 const lhs = try c.addNode(.{1638 const lhs = try c.addNode(.{
1668 .tag = .identifier,1639 .tag = .identifier,
...@@ -1680,19 +1651,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1680,19 +1651,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1680 return c.addNode(.{1651 return c.addNode(.{
1681 .tag = .assign,1652 .tag = .assign,
1682 .main_token = main_token,1653 .main_token = main_token,
1683 .data = .{1654 .data = .{ .node_and_node = .{
1684 .lhs = lhs,1655 lhs,
1685 .rhs = try renderNode(c, addr_of),1656 try renderNode(c, addr_of),
1686 },1657 } },
1687 });1658 });
1688 } else {1659 } else {
1689 return c.addNode(.{1660 return c.addNode(.{
1690 .tag = .assign,1661 .tag = .assign,
1691 .main_token = main_token,1662 .main_token = main_token,
1692 .data = .{1663 .data = .{ .node_and_node = .{
1693 .lhs = lhs,1664 lhs,
1694 .rhs = try renderNode(c, payload.value),1665 try renderNode(c, payload.value),
1695 },1666 } },
1696 });1667 });
1697 }1668 }
1698 },1669 },
...@@ -1709,29 +1680,29 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1709,29 +1680,29 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1709 const res = try renderNode(c, some);1680 const res = try renderNode(c, some);
1710 _ = try c.addToken(.r_paren, ")");1681 _ = try c.addToken(.r_paren, ")");
1711 break :blk res;1682 break :blk res;
1712 } else 0;1683 } else null;
1713 const body = try renderNode(c, payload.body);1684 const body = try renderNode(c, payload.body);
17141685
1715 if (cont_expr == 0) {1686 if (cont_expr == null) {
1716 return c.addNode(.{1687 return c.addNode(.{
1717 .tag = .while_simple,1688 .tag = .while_simple,
1718 .main_token = while_tok,1689 .main_token = while_tok,
1719 .data = .{1690 .data = .{ .node_and_node = .{
1720 .lhs = cond,1691 cond,
1721 .rhs = body,1692 body,
1722 },1693 } },
1723 });1694 });
1724 } else {1695 } else {
1725 return c.addNode(.{1696 return c.addNode(.{
1726 .tag = .while_cont,1697 .tag = .while_cont,
1727 .main_token = while_tok,1698 .main_token = while_tok,
1728 .data = .{1699 .data = .{ .node_and_extra = .{
1729 .lhs = cond,1700 cond,
1730 .rhs = try c.addExtra(std.zig.Ast.Node.WhileCont{1701 try c.addExtra(std.zig.Ast.Node.WhileCont{
1731 .cont_expr = cont_expr,1702 .cont_expr = cont_expr.?,
1732 .then_expr = body,1703 .then_expr = body,
1733 }),1704 }),
1734 },1705 } },
1735 });1706 });
1736 }1707 }
1737 },1708 },
...@@ -1750,10 +1721,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1750,10 +1721,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1750 return c.addNode(.{1721 return c.addNode(.{
1751 .tag = .while_simple,1722 .tag = .while_simple,
1752 .main_token = while_tok,1723 .main_token = while_tok,
1753 .data = .{1724 .data = .{ .node_and_node = .{
1754 .lhs = cond,1725 cond,
1755 .rhs = body,1726 body,
1756 },1727 } },
1757 });1728 });
1758 },1729 },
1759 .@"if" => {1730 .@"if" => {
...@@ -1767,10 +1738,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1767,10 +1738,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1767 const else_node = payload.@"else" orelse return c.addNode(.{1738 const else_node = payload.@"else" orelse return c.addNode(.{
1768 .tag = .if_simple,1739 .tag = .if_simple,
1769 .main_token = if_tok,1740 .main_token = if_tok,
1770 .data = .{1741 .data = .{ .node_and_node = .{
1771 .lhs = cond,1742 cond,
1772 .rhs = then_expr,1743 then_expr,
1773 },1744 } },
1774 });1745 });
1775 _ = try c.addToken(.keyword_else, "else");1746 _ = try c.addToken(.keyword_else, "else");
1776 const else_expr = try renderNode(c, else_node);1747 const else_expr = try renderNode(c, else_node);
...@@ -1778,13 +1749,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1778,13 +1749,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1778 return c.addNode(.{1749 return c.addNode(.{
1779 .tag = .@"if",1750 .tag = .@"if",
1780 .main_token = if_tok,1751 .main_token = if_tok,
1781 .data = .{1752 .data = .{ .node_and_extra = .{
1782 .lhs = cond,1753 cond,
1783 .rhs = try c.addExtra(std.zig.Ast.Node.If{1754 try c.addExtra(std.zig.Ast.Node.If{
1784 .then_expr = then_expr,1755 .then_expr = then_expr,
1785 .else_expr = else_expr,1756 .else_expr = else_expr,
1786 }),1757 }),
1787 },1758 } },
1788 });1759 });
1789 },1760 },
1790 .if_not_break => {1761 .if_not_break => {
...@@ -1794,28 +1765,25 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1794,28 +1765,25 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1794 const cond = try c.addNode(.{1765 const cond = try c.addNode(.{
1795 .tag = .bool_not,1766 .tag = .bool_not,
1796 .main_token = try c.addToken(.bang, "!"),1767 .main_token = try c.addToken(.bang, "!"),
1797 .data = .{1768 .data = .{ .node = try renderNodeGrouped(c, payload) },
1798 .lhs = try renderNodeGrouped(c, payload),
1799 .rhs = undefined,
1800 },
1801 });1769 });
1802 _ = try c.addToken(.r_paren, ")");1770 _ = try c.addToken(.r_paren, ")");
1803 const then_expr = try c.addNode(.{1771 const then_expr = try c.addNode(.{
1804 .tag = .@"break",1772 .tag = .@"break",
1805 .main_token = try c.addToken(.keyword_break, "break"),1773 .main_token = try c.addToken(.keyword_break, "break"),
1806 .data = .{1774 .data = .{ .opt_token_and_opt_node = .{
1807 .lhs = 0,1775 .none,
1808 .rhs = 0,1776 .none,
1809 },1777 } },
1810 });1778 });
18111779
1812 return c.addNode(.{1780 return c.addNode(.{
1813 .tag = .if_simple,1781 .tag = .if_simple,
1814 .main_token = if_tok,1782 .main_token = if_tok,
1815 .data = .{1783 .data = .{ .node_and_node = .{
1816 .lhs = cond,1784 cond,
1817 .rhs = then_expr,1785 then_expr,
1818 },1786 } },
1819 });1787 });
1820 },1788 },
1821 .@"switch" => {1789 .@"switch" => {
...@@ -1837,13 +1805,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1837,13 +1805,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1837 return c.addNode(.{1805 return c.addNode(.{
1838 .tag = .switch_comma,1806 .tag = .switch_comma,
1839 .main_token = switch_tok,1807 .main_token = switch_tok,
1840 .data = .{1808 .data = .{ .node_and_extra = .{
1841 .lhs = cond,1809 cond, try c.addExtra(NodeSubRange{
1842 .rhs = try c.addExtra(NodeSubRange{
1843 .start = span.start,1810 .start = span.start,
1844 .end = span.end,1811 .end = span.end,
1845 }),1812 }),
1846 },1813 } },
1847 });1814 });
1848 },1815 },
1849 .switch_else => {1816 .switch_else => {
...@@ -1852,43 +1819,42 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1852,43 +1819,42 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1852 return c.addNode(.{1819 return c.addNode(.{
1853 .tag = .switch_case_one,1820 .tag = .switch_case_one,
1854 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),1821 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1855 .data = .{1822 .data = .{ .opt_node_and_node = .{
1856 .lhs = 0,1823 .none,
1857 .rhs = try renderNode(c, payload),1824 try renderNode(c, payload),
1858 },1825 } },
1859 });1826 });
1860 },1827 },
1861 .switch_prong => {1828 .switch_prong => {
1862 const payload = node.castTag(.switch_prong).?.data;1829 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);
1864 defer c.gpa.free(items);1831 defer c.gpa.free(items);
1865 items[0] = 0;1832 for (payload.cases, items, 0..) |case, *item, i| {
1866 for (payload.cases, 0..) |item, i| {
1867 if (i != 0) _ = try c.addToken(.comma, ",");1833 if (i != 0) _ = try c.addToken(.comma, ",");
1868 items[i] = try renderNode(c, item);1834 item.* = try renderNode(c, case);
1869 }1835 }
1870 _ = try c.addToken(.r_brace, "}");1836 _ = try c.addToken(.r_brace, "}");
1871 if (items.len < 2) {1837 if (items.len < 2) {
1872 return c.addNode(.{1838 return c.addNode(.{
1873 .tag = .switch_case_one,1839 .tag = .switch_case_one,
1874 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),1840 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1875 .data = .{1841 .data = .{ .opt_node_and_node = .{
1876 .lhs = items[0],1842 if (items.len == 0) .none else items[0].toOptional(),
1877 .rhs = try renderNode(c, payload.cond),1843 try renderNode(c, payload.cond),
1878 },1844 } },
1879 });1845 });
1880 } else {1846 } else {
1881 const span = try c.listToSpan(items);1847 const span = try c.listToSpan(items);
1882 return c.addNode(.{1848 return c.addNode(.{
1883 .tag = .switch_case,1849 .tag = .switch_case,
1884 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),1850 .main_token = try c.addToken(.equal_angle_bracket_right, "=>"),
1885 .data = .{1851 .data = .{ .extra_and_node = .{
1886 .lhs = try c.addExtra(NodeSubRange{1852 try c.addExtra(NodeSubRange{
1887 .start = span.start,1853 .start = span.start,
1888 .end = span.end,1854 .end = span.end,
1889 }),1855 }),
1890 .rhs = try renderNode(c, payload.cond),1856 try renderNode(c, payload.cond),
1891 },1857 } },
1892 });1858 });
1893 }1859 }
1894 },1860 },
...@@ -1900,10 +1866,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1900,10 +1866,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1900 return c.addNode(.{1866 return c.addNode(.{
1901 .tag = .container_decl_two,1867 .tag = .container_decl_two,
1902 .main_token = opaque_tok,1868 .main_token = opaque_tok,
1903 .data = .{1869 .data = .{ .opt_node_and_opt_node = .{
1904 .lhs = 0,1870 .none,
1905 .rhs = 0,1871 .none,
1906 },1872 } },
1907 });1873 });
1908 },1874 },
1909 .array_access => {1875 .array_access => {
...@@ -1915,10 +1881,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1915,10 +1881,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1915 return c.addNode(.{1881 return c.addNode(.{
1916 .tag = .array_access,1882 .tag = .array_access,
1917 .main_token = l_bracket,1883 .main_token = l_bracket,
1918 .data = .{1884 .data = .{ .node_and_node = .{
1919 .lhs = lhs,1885 lhs,
1920 .rhs = index_expr,1886 index_expr,
1921 },1887 } },
1922 });1888 });
1923 },1889 },
1924 .array_type => {1890 .array_type => {
...@@ -1940,22 +1906,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1940,22 +1906,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1940 const init = try c.addNode(.{1906 const init = try c.addNode(.{
1941 .tag = .array_init_one,1907 .tag = .array_init_one,
1942 .main_token = l_brace,1908 .main_token = l_brace,
1943 .data = .{1909 .data = .{ .node_and_node = .{
1944 .lhs = type_expr,1910 type_expr,
1945 .rhs = val,1911 val,
1946 },1912 } },
1947 });1913 });
1948 return c.addNode(.{1914 return c.addNode(.{
1949 .tag = .array_cat,1915 .tag = .array_cat,
1950 .main_token = try c.addToken(.asterisk_asterisk, "**"),1916 .main_token = try c.addToken(.asterisk_asterisk, "**"),
1951 .data = .{1917 .data = .{ .node_and_node = .{
1952 .lhs = init,1918 init,
1953 .rhs = try c.addNode(.{1919 try c.addNode(.{
1954 .tag = .number_literal,1920 .tag = .number_literal,
1955 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.count}),1921 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.count}),
1956 .data = undefined,1922 .data = undefined,
1957 }),1923 }),
1958 },1924 } },
1959 });1925 });
1960 },1926 },
1961 .empty_array => {1927 .empty_array => {
...@@ -1989,7 +1955,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1989,7 +1955,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1989 const type_node = if (payload.type) |enum_const_type| blk: {1955 const type_node = if (payload.type) |enum_const_type| blk: {
1990 _ = try c.addToken(.colon, ":");1956 _ = try c.addToken(.colon, ":");
1991 break :blk try renderNode(c, enum_const_type);1957 break :blk try renderNode(c, enum_const_type);
1992 } else 0;1958 } else null;
19931959
1994 _ = try c.addToken(.equal, "=");1960 _ = try c.addToken(.equal, "=");
19951961
...@@ -1999,20 +1965,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1999,20 +1965,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1999 return c.addNode(.{1965 return c.addNode(.{
2000 .tag = .simple_var_decl,1966 .tag = .simple_var_decl,
2001 .main_token = const_tok,1967 .main_token = const_tok,
2002 .data = .{1968 .data = .{ .opt_node_and_opt_node = .{
2003 .lhs = type_node,1969 .fromOptional(type_node),
2004 .rhs = init_node,1970 init_node.toOptional(),
2005 },1971 } },
2006 });1972 });
2007 },1973 },
2008 .tuple => {1974 .tuple => {
2009 const payload = node.castTag(.tuple).?.data;1975 const payload = node.castTag(.tuple).?.data;
2010 _ = try c.addToken(.period, ".");1976 _ = try c.addToken(.period, ".");
2011 const l_brace = try c.addToken(.l_brace, "{");1977 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);
2013 defer c.gpa.free(inits);1979 defer c.gpa.free(inits);
2014 inits[0] = 0;
2015 inits[1] = 0;
2016 for (payload, 0..) |init, i| {1980 for (payload, 0..) |init, i| {
2017 if (i != 0) _ = try c.addToken(.comma, ",");1981 if (i != 0) _ = try c.addToken(.comma, ",");
2018 inits[i] = try renderNode(c, init);1982 inits[i] = try renderNode(c, init);
...@@ -2022,20 +1986,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -2022,20 +1986,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
2022 return c.addNode(.{1986 return c.addNode(.{
2023 .tag = .array_init_dot_two,1987 .tag = .array_init_dot_two,
2024 .main_token = l_brace,1988 .main_token = l_brace,
2025 .data = .{1989 .data = .{ .opt_node_and_opt_node = .{
2026 .lhs = inits[0],1990 if (inits.len < 1) .none else inits[0].toOptional(),
2027 .rhs = inits[1],1991 if (inits.len < 2) .none else inits[1].toOptional(),
2028 },1992 } },
2029 });1993 });
2030 } else {1994 } else {
2031 const span = try c.listToSpan(inits);1995 const span = try c.listToSpan(inits);
2032 return c.addNode(.{1996 return c.addNode(.{
2033 .tag = .array_init_dot,1997 .tag = .array_init_dot,
2034 .main_token = l_brace,1998 .main_token = l_brace,
2035 .data = .{1999 .data = .{ .extra_range = span },
2036 .lhs = span.start,
2037 .rhs = span.end,
2038 },
2039 });2000 });
2040 }2001 }
2041 },2002 },
...@@ -2043,10 +2004,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -2043,10 +2004,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
2043 const payload = node.castTag(.container_init_dot).?.data;2004 const payload = node.castTag(.container_init_dot).?.data;
2044 _ = try c.addToken(.period, ".");2005 _ = try c.addToken(.period, ".");
2045 const l_brace = try c.addToken(.l_brace, "{");2006 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);
2047 defer c.gpa.free(inits);2008 defer c.gpa.free(inits);
2048 inits[0] = 0;
2049 inits[1] = 0;
2050 for (payload, 0..) |init, i| {2009 for (payload, 0..) |init, i| {
2051 _ = try c.addToken(.period, ".");2010 _ = try c.addToken(.period, ".");
2052 _ = try c.addIdentifier(init.name);2011 _ = try c.addIdentifier(init.name);
...@@ -2060,20 +2019,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -2060,20 +2019,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
2060 return c.addNode(.{2019 return c.addNode(.{
2061 .tag = .struct_init_dot_two_comma,2020 .tag = .struct_init_dot_two_comma,
2062 .main_token = l_brace,2021 .main_token = l_brace,
2063 .data = .{2022 .data = .{ .opt_node_and_opt_node = .{
2064 .lhs = inits[0],2023 if (inits.len < 1) .none else inits[0].toOptional(),
2065 .rhs = inits[1],2024 if (inits.len < 2) .none else inits[1].toOptional(),
2066 },2025 } },
2067 });2026 });
2068 } else {2027 } else {
2069 const span = try c.listToSpan(inits);2028 const span = try c.listToSpan(inits);
2070 return c.addNode(.{2029 return c.addNode(.{
2071 .tag = .struct_init_dot_comma,2030 .tag = .struct_init_dot_comma,
2072 .main_token = l_brace,2031 .main_token = l_brace,
2073 .data = .{2032 .data = .{ .extra_range = span },
2074 .lhs = span.start,
2075 .rhs = span.end,
2076 },
2077 });2033 });
2078 }2034 }
2079 },2035 },
...@@ -2082,9 +2038,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -2082,9 +2038,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
2082 const lhs = try renderNode(c, payload.lhs);2038 const lhs = try renderNode(c, payload.lhs);
20832039
2084 const l_brace = try c.addToken(.l_brace, "{");2040 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);
2086 defer c.gpa.free(inits);2042 defer c.gpa.free(inits);
2087 inits[0] = 0;
2088 for (payload.inits, 0..) |init, i| {2043 for (payload.inits, 0..) |init, i| {
2089 _ = try c.addToken(.period, ".");2044 _ = try c.addToken(.period, ".");
2090 _ = try c.addIdentifier(init.name);2045 _ = try c.addIdentifier(init.name);
...@@ -2098,31 +2053,30 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -2098,31 +2053,30 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
2098 0 => c.addNode(.{2053 0 => c.addNode(.{
2099 .tag = .struct_init_one,2054 .tag = .struct_init_one,
2100 .main_token = l_brace,2055 .main_token = l_brace,
2101 .data = .{2056 .data = .{ .node_and_opt_node = .{
2102 .lhs = lhs,2057 lhs,
2103 .rhs = 0,2058 .none,
2104 },2059 } },
2105 }),2060 }),
2106 1 => c.addNode(.{2061 1 => c.addNode(.{
2107 .tag = .struct_init_one_comma,2062 .tag = .struct_init_one_comma,
2108 .main_token = l_brace,2063 .main_token = l_brace,
2109 .data = .{2064 .data = .{ .node_and_opt_node = .{
2110 .lhs = lhs,2065 lhs,
2111 .rhs = inits[0],2066 inits[0].toOptional(),
2112 },2067 } },
2113 }),2068 }),
2114 else => blk: {2069 else => blk: {
2115 const span = try c.listToSpan(inits);2070 const span = try c.listToSpan(inits);
2116 break :blk c.addNode(.{2071 break :blk c.addNode(.{
2117 .tag = .struct_init_comma,2072 .tag = .struct_init_comma,
2118 .main_token = l_brace,2073 .main_token = l_brace,
2119 .data = .{2074 .data = .{ .node_and_extra = .{
2120 .lhs = lhs,2075 lhs, try c.addExtra(NodeSubRange{
2121 .rhs = try c.addExtra(NodeSubRange{
2122 .start = span.start,2076 .start = span.start,
2123 .end = span.end,2077 .end = span.end,
2124 }),2078 }),
2125 },2079 } },
2126 });2080 });
2127 },2081 },
2128 };2082 };
...@@ -2147,10 +2101,8 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {...@@ -2147,10 +2101,8 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
2147 const num_vars = payload.variables.len;2101 const num_vars = payload.variables.len;
2148 const num_funcs = payload.functions.len;2102 const num_funcs = payload.functions.len;
2149 const total_members = payload.fields.len + num_vars + num_funcs;2103 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);
2151 defer c.gpa.free(members);2105 defer c.gpa.free(members);
2152 members[0] = 0;
2153 members[1] = 0;
21542106
2155 for (payload.fields, 0..) |field, i| {2107 for (payload.fields, 0..) |field, i| {
2156 const name_tok = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field.name)});2108 const name_tok = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field.name)});
...@@ -2167,37 +2119,36 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {...@@ -2167,37 +2119,36 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
2167 });2119 });
2168 _ = try c.addToken(.r_paren, ")");2120 _ = try c.addToken(.r_paren, ")");
2169 break :blk align_expr;2121 break :blk align_expr;
2170 } else 0;2122 } else null;
21712123
2172 const value_expr = if (field.default_value) |value| blk: {2124 const value_expr = if (field.default_value) |value| blk: {
2173 _ = try c.addToken(.equal, "=");2125 _ = try c.addToken(.equal, "=");
2174 break :blk try renderNode(c, value);2126 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) .{
2178 .tag = .container_field_init,2130 .tag = .container_field_init,
2179 .main_token = name_tok,2131 .main_token = name_tok,
2180 .data = .{2132 .data = .{ .node_and_opt_node = .{
2181 .lhs = type_expr,2133 type_expr,
2182 .rhs = value_expr,2134 .fromOptional(value_expr),
2183 },2135 } },
2184 } else if (value_expr == 0) .{2136 } else if (value_expr == null) .{
2185 .tag = .container_field_align,2137 .tag = .container_field_align,
2186 .main_token = name_tok,2138 .main_token = name_tok,
2187 .data = .{2139 .data = .{ .node_and_node = .{
2188 .lhs = type_expr,2140 type_expr,
2189 .rhs = align_expr,2141 align_expr.?,
2190 },2142 } },
2191 } else .{2143 } else .{
2192 .tag = .container_field,2144 .tag = .container_field,
2193 .main_token = name_tok,2145 .main_token = name_tok,
2194 .data = .{2146 .data = .{ .node_and_extra = .{
2195 .lhs = type_expr,2147 type_expr, try c.addExtra(std.zig.Ast.Node.ContainerField{
2196 .rhs = try c.addExtra(std.zig.Ast.Node.ContainerField{2148 .align_expr = align_expr.?,
2197 .align_expr = align_expr,2149 .value_expr = value_expr.?,
2198 .value_expr = value_expr,
2199 }),2150 }),
2200 },2151 } },
2201 });2152 });
2202 _ = try c.addToken(.comma, ",");2153 _ = try c.addToken(.comma, ",");
2203 }2154 }
...@@ -2213,29 +2164,26 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {...@@ -2213,29 +2164,26 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
2213 return c.addNode(.{2164 return c.addNode(.{
2214 .tag = .container_decl_two,2165 .tag = .container_decl_two,
2215 .main_token = kind_tok,2166 .main_token = kind_tok,
2216 .data = .{2167 .data = .{ .opt_node_and_opt_node = .{
2217 .lhs = 0,2168 .none,
2218 .rhs = 0,2169 .none,
2219 },2170 } },
2220 });2171 });
2221 } else if (total_members <= 2) {2172 } else if (total_members <= 2) {
2222 return c.addNode(.{2173 return c.addNode(.{
2223 .tag = if (num_funcs == 0) .container_decl_two_trailing else .container_decl_two,2174 .tag = if (num_funcs == 0) .container_decl_two_trailing else .container_decl_two,
2224 .main_token = kind_tok,2175 .main_token = kind_tok,
2225 .data = .{2176 .data = .{ .opt_node_and_opt_node = .{
2226 .lhs = members[0],2177 if (members.len < 1) .none else members[0].toOptional(),
2227 .rhs = members[1],2178 if (members.len < 2) .none else members[1].toOptional(),
2228 },2179 } },
2229 });2180 });
2230 } else {2181 } else {
2231 const span = try c.listToSpan(members);2182 const span = try c.listToSpan(members);
2232 return c.addNode(.{2183 return c.addNode(.{
2233 .tag = if (num_funcs == 0) .container_decl_trailing else .container_decl,2184 .tag = if (num_funcs == 0) .container_decl_trailing else .container_decl,
2234 .main_token = kind_tok,2185 .main_token = kind_tok,
2235 .data = .{2186 .data = .{ .extra_range = span },
2236 .lhs = span.start,
2237 .rhs = span.end,
2238 },
2239 });2187 });
2240 }2188 }
2241}2189}
...@@ -2244,45 +2192,52 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI...@@ -2244,45 +2192,52 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI
2244 return c.addNode(.{2192 return c.addNode(.{
2245 .tag = .field_access,2193 .tag = .field_access,
2246 .main_token = try c.addToken(.period, "."),2194 .main_token = try c.addToken(.period, "."),
2247 .data = .{2195 .data = .{ .node_and_token = .{
2248 .lhs = lhs,2196 lhs,
2249 .rhs = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),2197 try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}),
2250 },2198 } },
2251 });2199 });
2252}2200}
22532201
2254fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {2202fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex {
2255 const l_brace = try c.addToken(.l_brace, "{");2203 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);
2257 defer c.gpa.free(rendered);2205 defer c.gpa.free(rendered);
2258 rendered[0] = 0;
2259 for (inits, 0..) |init, i| {2206 for (inits, 0..) |init, i| {
2260 rendered[i] = try renderNode(c, init);2207 rendered[i] = try renderNode(c, init);
2261 _ = try c.addToken(.comma, ",");2208 _ = try c.addToken(.comma, ",");
2262 }2209 }
2263 _ = try c.addToken(.r_brace, "}");2210 _ = try c.addToken(.r_brace, "}");
2264 if (inits.len < 2) {2211 switch (inits.len) {
2265 return c.addNode(.{2212 0 => return c.addNode(.{
2266 .tag = .array_init_one_comma,2213 .tag = .struct_init_one,
2267 .main_token = l_brace,2214 .main_token = l_brace,
2268 .data = .{2215 .data = .{ .node_and_opt_node = .{
2269 .lhs = lhs,2216 lhs,
2270 .rhs = rendered[0],2217 .none,
2271 },2218 } },
2272 });2219 }),
2273 } else {2220 1 => return c.addNode(.{
2274 const span = try c.listToSpan(rendered);2221 .tag = .array_init_one_comma,
2275 return c.addNode(.{
2276 .tag = .array_init_comma,
2277 .main_token = l_brace,2222 .main_token = l_brace,
2278 .data = .{2223 .data = .{ .node_and_node = .{
2279 .lhs = lhs,2224 lhs,
2280 .rhs = try c.addExtra(NodeSubRange{2225 rendered[0],
2281 .start = span.start,2226 } },
2282 .end = span.end,2227 }),
2283 }),2228 else => {
2284 },2229 const span = try c.listToSpan(rendered);
2285 });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 },
2286 }2241 }
2287}2242}
22882243
...@@ -2298,10 +2253,10 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {...@@ -2298,10 +2253,10 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
2298 return c.addNode(.{2253 return c.addNode(.{
2299 .tag = .array_type,2254 .tag = .array_type,
2300 .main_token = l_bracket,2255 .main_token = l_bracket,
2301 .data = .{2256 .data = .{ .node_and_node = .{
2302 .lhs = len_expr,2257 len_expr,
2303 .rhs = elem_type_expr,2258 elem_type_expr,
2304 },2259 } },
2305 });2260 });
2306}2261}
23072262
...@@ -2325,13 +2280,13 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn...@@ -2325,13 +2280,13 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn
2325 return c.addNode(.{2280 return c.addNode(.{
2326 .tag = .array_type_sentinel,2281 .tag = .array_type_sentinel,
2327 .main_token = l_bracket,2282 .main_token = l_bracket,
2328 .data = .{2283 .data = .{ .node_and_extra = .{
2329 .lhs = len_expr,2284 len_expr,
2330 .rhs = try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{2285 try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{
2331 .sentinel = sentinel_expr,2286 .sentinel = sentinel_expr,
2332 .elem_type = elem_type_expr,2287 .elem_type = elem_type_expr,
2333 }),2288 }),
2334 },2289 } },
2335 });2290 });
2336}2291}
23372292
...@@ -2482,10 +2437,10 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -2482,10 +2437,10 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
2482 => return c.addNode(.{2437 => return c.addNode(.{
2483 .tag = .grouped_expression,2438 .tag = .grouped_expression,
2484 .main_token = try c.addToken(.l_paren, "("),2439 .main_token = try c.addToken(.l_paren, "("),
2485 .data = .{2440 .data = .{ .node_and_token = .{
2486 .lhs = try renderNode(c, node),2441 try renderNode(c, node),
2487 .rhs = try c.addToken(.r_paren, ")"),2442 try c.addToken(.r_paren, ")"),
2488 },2443 } },
2489 }),2444 }),
2490 .ellipsis3,2445 .ellipsis3,
2491 .switch_prong,2446 .switch_prong,
...@@ -2539,10 +2494,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T...@@ -2539,10 +2494,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T
2539 return c.addNode(.{2494 return c.addNode(.{
2540 .tag = tag,2495 .tag = tag,
2541 .main_token = try c.addToken(tok_tag, bytes),2496 .main_token = try c.addToken(tok_tag, bytes),
2542 .data = .{2497 .data = .{ .node = try renderNodeGrouped(c, payload) },
2543 .lhs = try renderNodeGrouped(c, payload),
2544 .rhs = undefined,
2545 },
2546 });2498 });
2547}2499}
25482500
...@@ -2552,10 +2504,10 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta...@@ -2552,10 +2504,10 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta
2552 return c.addNode(.{2504 return c.addNode(.{
2553 .tag = tag,2505 .tag = tag,
2554 .main_token = try c.addToken(tok_tag, bytes),2506 .main_token = try c.addToken(tok_tag, bytes),
2555 .data = .{2507 .data = .{ .node_and_node = .{
2556 .lhs = lhs,2508 lhs,
2557 .rhs = try renderNodeGrouped(c, payload.rhs),2509 try renderNodeGrouped(c, payload.rhs),
2558 },2510 } },
2559 });2511 });
2560}2512}
25612513
...@@ -2565,10 +2517,10 @@ fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: Toke...@@ -2565,10 +2517,10 @@ fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: Toke
2565 return c.addNode(.{2517 return c.addNode(.{
2566 .tag = tag,2518 .tag = tag,
2567 .main_token = try c.addToken(tok_tag, bytes),2519 .main_token = try c.addToken(tok_tag, bytes),
2568 .data = .{2520 .data = .{ .node_and_node = .{
2569 .lhs = lhs,2521 lhs,
2570 .rhs = try renderNode(c, payload.rhs),2522 try renderNode(c, payload.rhs),
2571 },2523 } },
2572 });2524 });
2573}2525}
25742526
...@@ -2586,10 +2538,7 @@ fn renderStdImport(c: *Context, parts: []const []const u8) !NodeIndex {...@@ -2586,10 +2538,7 @@ fn renderStdImport(c: *Context, parts: []const []const u8) !NodeIndex {
2586 const import_node = try c.addNode(.{2538 const import_node = try c.addNode(.{
2587 .tag = .builtin_call_two,2539 .tag = .builtin_call_two,
2588 .main_token = import_tok,2540 .main_token = import_tok,
2589 .data = .{2541 .data = .{ .opt_node_and_opt_node = .{ std_node.toOptional(), .none } },
2590 .lhs = std_node,
2591 .rhs = 0,
2592 },
2593 });2542 });
25942543
2595 var access_chain = import_node;2544 var access_chain = import_node;
...@@ -2605,20 +2554,14 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {...@@ -2605,20 +2554,14 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
2605 0 => try c.addNode(.{2554 0 => try c.addNode(.{
2606 .tag = .call_one,2555 .tag = .call_one,
2607 .main_token = lparen,2556 .main_token = lparen,
2608 .data = .{2557 .data = .{ .node_and_opt_node = .{ lhs, .none } },
2609 .lhs = lhs,
2610 .rhs = 0,
2611 },
2612 }),2558 }),
2613 1 => blk: {2559 1 => blk: {
2614 const arg = try renderNode(c, args[0]);2560 const arg = try renderNode(c, args[0]);
2615 break :blk try c.addNode(.{2561 break :blk try c.addNode(.{
2616 .tag = .call_one,2562 .tag = .call_one,
2617 .main_token = lparen,2563 .main_token = lparen,
2618 .data = .{2564 .data = .{ .node_and_opt_node = .{ lhs, arg.toOptional() } },
2619 .lhs = lhs,
2620 .rhs = arg,
2621 },
2622 });2565 });
2623 },2566 },
2624 else => blk: {2567 else => blk: {
...@@ -2633,13 +2576,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {...@@ -2633,13 +2576,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
2633 break :blk try c.addNode(.{2576 break :blk try c.addNode(.{
2634 .tag = .call,2577 .tag = .call,
2635 .main_token = lparen,2578 .main_token = lparen,
2636 .data = .{2579 .data = .{ .node_and_extra = .{
2637 .lhs = lhs,2580 lhs,
2638 .rhs = try c.addExtra(NodeSubRange{2581 try c.addExtra(NodeSubRange{ .start = span.start, .end = span.end }),
2639 .start = span.start,2582 } },
2640 .end = span.end,
2641 }),
2642 },
2643 });2583 });
2644 },2584 },
2645 };2585 };
...@@ -2650,10 +2590,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {...@@ -2650,10 +2590,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex {
2650fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !NodeIndex {2590fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !NodeIndex {
2651 const builtin_tok = try c.addToken(.builtin, builtin);2591 const builtin_tok = try c.addToken(.builtin, builtin);
2652 _ = try c.addToken(.l_paren, "(");2592 _ = try c.addToken(.l_paren, "(");
2653 var arg_1: NodeIndex = 0;2593 var arg_1: NodeIndex = undefined;
2654 var arg_2: NodeIndex = 0;2594 var arg_2: NodeIndex = undefined;
2655 var arg_3: NodeIndex = 0;2595 var arg_3: NodeIndex = undefined;
2656 var arg_4: NodeIndex = 0;2596 var arg_4: NodeIndex = undefined;
2657 switch (args.len) {2597 switch (args.len) {
2658 0 => {},2598 0 => {},
2659 1 => {2599 1 => {
...@@ -2681,10 +2621,10 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node...@@ -2681,10 +2621,10 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
2681 return c.addNode(.{2621 return c.addNode(.{
2682 .tag = .builtin_call_two,2622 .tag = .builtin_call_two,
2683 .main_token = builtin_tok,2623 .main_token = builtin_tok,
2684 .data = .{2624 .data = .{ .opt_node_and_opt_node = .{
2685 .lhs = arg_1,2625 if (args.len < 1) .none else arg_1.toOptional(),
2686 .rhs = arg_2,2626 if (args.len < 2) .none else arg_2.toOptional(),
2687 },2627 } },
2688 });2628 });
2689 } else {2629 } else {
2690 std.debug.assert(args.len == 4);2630 std.debug.assert(args.len == 4);
...@@ -2693,10 +2633,7 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node...@@ -2693,10 +2633,7 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
2693 return c.addNode(.{2633 return c.addNode(.{
2694 .tag = .builtin_call,2634 .tag = .builtin_call,
2695 .main_token = builtin_tok,2635 .main_token = builtin_tok,
2696 .data = .{2636 .data = .{ .extra_range = params },
2697 .lhs = params.start,
2698 .rhs = params.end,
2699 },
2700 });2637 });
2701 }2638 }
2702}2639}
...@@ -2725,7 +2662,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {...@@ -2725,7 +2662,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
2725 });2662 });
2726 _ = try c.addToken(.r_paren, ")");2663 _ = try c.addToken(.r_paren, ")");
2727 break :blk res;2664 break :blk res;
2728 } else 0;2665 } else null;
27292666
2730 const section_node = if (payload.linksection_string) |some| blk: {2667 const section_node = if (payload.linksection_string) |some| blk: {
2731 _ = try c.addToken(.keyword_linksection, "linksection");2668 _ = try c.addToken(.keyword_linksection, "linksection");
...@@ -2737,50 +2674,50 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {...@@ -2737,50 +2674,50 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
2737 });2674 });
2738 _ = try c.addToken(.r_paren, ")");2675 _ = try c.addToken(.r_paren, ")");
2739 break :blk res;2676 break :blk res;
2740 } else 0;2677 } else null;
27412678
2742 const init_node = if (payload.init) |some| blk: {2679 const init_node = if (payload.init) |some| blk: {
2743 _ = try c.addToken(.equal, "=");2680 _ = try c.addToken(.equal, "=");
2744 break :blk try renderNode(c, some);2681 break :blk try renderNode(c, some);
2745 } else 0;2682 } else null;
2746 _ = try c.addToken(.semicolon, ";");2683 _ = try c.addToken(.semicolon, ";");
27472684
2748 if (section_node == 0) {2685 if (section_node == null) {
2749 if (align_node == 0) {2686 if (align_node == null) {
2750 return c.addNode(.{2687 return c.addNode(.{
2751 .tag = .simple_var_decl,2688 .tag = .simple_var_decl,
2752 .main_token = mut_tok,2689 .main_token = mut_tok,
2753 .data = .{2690 .data = .{ .opt_node_and_opt_node = .{
2754 .lhs = type_node,2691 type_node.toOptional(),
2755 .rhs = init_node,2692 .fromOptional(init_node),
2756 },2693 } },
2757 });2694 });
2758 } else {2695 } else {
2759 return c.addNode(.{2696 return c.addNode(.{
2760 .tag = .local_var_decl,2697 .tag = .local_var_decl,
2761 .main_token = mut_tok,2698 .main_token = mut_tok,
2762 .data = .{2699 .data = .{ .extra_and_opt_node = .{
2763 .lhs = try c.addExtra(std.zig.Ast.Node.LocalVarDecl{2700 try c.addExtra(std.zig.Ast.Node.LocalVarDecl{
2764 .type_node = type_node,2701 .type_node = type_node,
2765 .align_node = align_node,2702 .align_node = align_node.?,
2766 }),2703 }),
2767 .rhs = init_node,2704 .fromOptional(init_node),
2768 },2705 } },
2769 });2706 });
2770 }2707 }
2771 } else {2708 } else {
2772 return c.addNode(.{2709 return c.addNode(.{
2773 .tag = .global_var_decl,2710 .tag = .global_var_decl,
2774 .main_token = mut_tok,2711 .main_token = mut_tok,
2775 .data = .{2712 .data = .{ .extra_and_opt_node = .{
2776 .lhs = try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{2713 try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{
2777 .type_node = type_node,2714 .type_node = type_node.toOptional(),
2778 .align_node = align_node,2715 .align_node = .fromOptional(align_node),
2779 .section_node = section_node,2716 .section_node = .fromOptional(section_node),
2780 .addrspace_node = 0,2717 .addrspace_node = .none,
2781 }),2718 }),
2782 .rhs = init_node,2719 .fromOptional(init_node),
2783 },2720 } },
2784 });2721 });
2785 }2722 }
2786}2723}
...@@ -2809,7 +2746,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2809,7 +2746,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2809 });2746 });
2810 _ = try c.addToken(.r_paren, ")");2747 _ = try c.addToken(.r_paren, ")");
2811 break :blk res;2748 break :blk res;
2812 } else 0;2749 } else null;
28132750
2814 const section_expr = if (payload.linksection_string) |some| blk: {2751 const section_expr = if (payload.linksection_string) |some| blk: {
2815 _ = try c.addToken(.keyword_linksection, "linksection");2752 _ = try c.addToken(.keyword_linksection, "linksection");
...@@ -2821,7 +2758,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2821,7 +2758,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2821 });2758 });
2822 _ = try c.addToken(.r_paren, ")");2759 _ = try c.addToken(.r_paren, ")");
2823 break :blk res;2760 break :blk res;
2824 } else 0;2761 } else null;
28252762
2826 const callconv_expr = if (payload.explicit_callconv) |some| blk: {2763 const callconv_expr = if (payload.explicit_callconv) |some| blk: {
2827 _ = try c.addToken(.keyword_callconv, "callconv");2764 _ = try c.addToken(.keyword_callconv, "callconv");
...@@ -2856,48 +2793,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2856,48 +2793,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2856 const inner_lbrace = try c.addToken(.l_brace, "{");2793 const inner_lbrace = try c.addToken(.l_brace, "{");
2857 _ = try c.addToken(.r_brace, "}");2794 _ = try c.addToken(.r_brace, "}");
2858 _ = try c.addToken(.r_brace, "}");2795 _ = 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 });
2859 break :cc_node try c.addNode(.{2804 break :cc_node try c.addNode(.{
2860 .tag = .struct_init_dot_two,2805 .tag = .struct_init_dot_two,
2861 .main_token = outer_lbrace,2806 .main_token = outer_lbrace,
2862 .data = .{2807 .data = .{ .opt_node_and_opt_node = .{
2863 .lhs = try c.addNode(.{2808 inner_node.toOptional(),
2864 .tag = .struct_init_dot_two,2809 .none,
2865 .main_token = inner_lbrace,2810 } },
2866 .data = .{ .lhs = 0, .rhs = 0 },
2867 }),
2868 .rhs = 0,
2869 },
2870 });2811 });
2871 },2812 },
2872 };2813 };
2873 _ = try c.addToken(.r_paren, ")");2814 _ = try c.addToken(.r_paren, ")");
2874 break :blk cc_node;2815 break :blk cc_node;
2875 } else 0;2816 } else null;
28762817
2877 const return_type_expr = try renderNode(c, payload.return_type);2818 const return_type_expr = try renderNode(c, payload.return_type);
28782819
2879 const fn_proto = try blk: {2820 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) {
2881 if (params.items.len < 2)2822 if (params.items.len < 2)
2882 break :blk c.addNode(.{2823 break :blk c.addNode(.{
2883 .tag = .fn_proto_simple,2824 .tag = .fn_proto_simple,
2884 .main_token = fn_token,2825 .main_token = fn_token,
2885 .data = .{2826 .data = .{ .opt_node_and_opt_node = .{
2886 .lhs = params.items[0],2827 if (params.items.len == 0) .none else params.items[0].toOptional(),
2887 .rhs = return_type_expr,2828 return_type_expr.toOptional(),
2888 },2829 } },
2889 })2830 })
2890 else2831 else
2891 break :blk c.addNode(.{2832 break :blk c.addNode(.{
2892 .tag = .fn_proto_multi,2833 .tag = .fn_proto_multi,
2893 .main_token = fn_token,2834 .main_token = fn_token,
2894 .data = .{2835 .data = .{ .extra_and_opt_node = .{
2895 .lhs = try c.addExtra(NodeSubRange{2836 try c.addExtra(NodeSubRange{
2896 .start = span.start,2837 .start = span.start,
2897 .end = span.end,2838 .end = span.end,
2898 }),2839 }),
2899 .rhs = return_type_expr,2840 return_type_expr.toOptional(),
2900 },2841 } },
2901 });2842 });
2902 }2843 }
2903 if (params.items.len < 2)2844 if (params.items.len < 2)
...@@ -2905,14 +2846,16 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2905,14 +2846,16 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2905 .tag = .fn_proto_one,2846 .tag = .fn_proto_one,
2906 .main_token = fn_token,2847 .main_token = fn_token,
2907 .data = .{2848 .data = .{
2908 .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{2849 .extra_and_opt_node = .{
2909 .param = params.items[0],2850 try c.addExtra(std.zig.Ast.Node.FnProtoOne{
2910 .align_expr = align_expr,2851 .param = if (params.items.len == 0) .none else params.items[0].toOptional(),
2911 .addrspace_expr = 0, // TODO2852 .align_expr = .fromOptional(align_expr),
2912 .section_expr = section_expr,2853 .addrspace_expr = .none, // TODO
2913 .callconv_expr = callconv_expr,2854 .section_expr = .fromOptional(section_expr),
2914 }),2855 .callconv_expr = .fromOptional(callconv_expr),
2915 .rhs = return_type_expr,2856 }),
2857 return_type_expr.toOptional(),
2858 },
2916 },2859 },
2917 })2860 })
2918 else2861 else
...@@ -2920,15 +2863,17 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2920,15 +2863,17 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2920 .tag = .fn_proto,2863 .tag = .fn_proto,
2921 .main_token = fn_token,2864 .main_token = fn_token,
2922 .data = .{2865 .data = .{
2923 .lhs = try c.addExtra(std.zig.Ast.Node.FnProto{2866 .extra_and_opt_node = .{
2924 .params_start = span.start,2867 try c.addExtra(std.zig.Ast.Node.FnProto{
2925 .params_end = span.end,2868 .params_start = span.start,
2926 .align_expr = align_expr,2869 .params_end = span.end,
2927 .addrspace_expr = 0, // TODO2870 .align_expr = .fromOptional(align_expr),
2928 .section_expr = section_expr,2871 .addrspace_expr = .none, // TODO
2929 .callconv_expr = callconv_expr,2872 .section_expr = .fromOptional(section_expr),
2930 }),2873 .callconv_expr = .fromOptional(callconv_expr),
2931 .rhs = return_type_expr,2874 }),
2875 return_type_expr.toOptional(),
2876 },
2932 },2877 },
2933 });2878 });
2934 };2879 };
...@@ -2943,10 +2888,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2943,10 +2888,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2943 return c.addNode(.{2888 return c.addNode(.{
2944 .tag = .fn_decl,2889 .tag = .fn_decl,
2945 .main_token = fn_token,2890 .main_token = fn_token,
2946 .data = .{2891 .data = .{ .node_and_node = .{
2947 .lhs = fn_proto,2892 fn_proto,
2948 .rhs = body,2893 body,
2949 },2894 } },
2950 });2895 });
2951}2896}
29522897
...@@ -2959,8 +2904,6 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {...@@ -2959,8 +2904,6 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
29592904
2960 const params = try renderParams(c, payload.params, false);2905 const params = try renderParams(c, payload.params, false);
2961 defer params.deinit();2906 defer params.deinit();
2962 var span: NodeSubRange = undefined;
2963 if (params.items.len > 1) span = try c.listToSpan(params.items);
29642907
2965 const return_type_expr = try renderNodeGrouped(c, payload.return_type);2908 const return_type_expr = try renderNodeGrouped(c, payload.return_type);
29662909
...@@ -2969,38 +2912,39 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {...@@ -2969,38 +2912,39 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex {
2969 break :blk try c.addNode(.{2912 break :blk try c.addNode(.{
2970 .tag = .fn_proto_simple,2913 .tag = .fn_proto_simple,
2971 .main_token = fn_token,2914 .main_token = fn_token,
2972 .data = .{2915 .data = .{ .opt_node_and_opt_node = .{
2973 .lhs = params.items[0],2916 if (params.items.len == 0) .none else params.items[0].toOptional(),
2974 .rhs = return_type_expr,2917 return_type_expr.toOptional(),
2975 },2918 } },
2976 });2919 });
2977 } else {2920 } else {
2921 const span: NodeSubRange = try c.listToSpan(params.items);
2978 break :blk try c.addNode(.{2922 break :blk try c.addNode(.{
2979 .tag = .fn_proto_multi,2923 .tag = .fn_proto_multi,
2980 .main_token = fn_token,2924 .main_token = fn_token,
2981 .data = .{2925 .data = .{ .extra_and_opt_node = .{
2982 .lhs = try c.addExtra(std.zig.Ast.Node.SubRange{2926 try c.addExtra(std.zig.Ast.Node.SubRange{
2983 .start = span.start,2927 .start = span.start,
2984 .end = span.end,2928 .end = span.end,
2985 }),2929 }),
2986 .rhs = return_type_expr,2930 return_type_expr.toOptional(),
2987 },2931 } },
2988 });2932 });
2989 }2933 }
2990 };2934 };
2991 return c.addNode(.{2935 return c.addNode(.{
2992 .tag = .fn_decl,2936 .tag = .fn_decl,
2993 .main_token = fn_token,2937 .main_token = fn_token,
2994 .data = .{2938 .data = .{ .node_and_node = .{
2995 .lhs = fn_proto,2939 fn_proto,
2996 .rhs = try renderNode(c, payload.body),2940 try renderNode(c, payload.body),
2997 },2941 } },
2998 });2942 });
2999}2943}
30002944
3001fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {2945fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) {
3002 _ = try c.addToken(.l_paren, "(");2946 _ = 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);
3004 errdefer rendered.deinit();2948 errdefer rendered.deinit();
30052949
3006 for (params, 0..) |param, i| {2950 for (params, 0..) |param, i| {
...@@ -3022,6 +2966,5 @@ fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.Ar...@@ -3022,6 +2966,5 @@ fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.Ar
3022 }2966 }
3023 _ = try c.addToken(.r_paren, ")");2967 _ = try c.addToken(.r_paren, ")");
30242968
3025 if (rendered.items.len == 0) rendered.appendAssumeCapacity(0);
3026 return rendered;2969 return rendered;
3027}2970}
lib/compiler/reduce.zig+1-1
...@@ -220,7 +220,7 @@ pub fn main() !void {...@@ -220,7 +220,7 @@ pub fn main() !void {
220 mem.eql(u8, msg, "unused function parameter") or220 mem.eql(u8, msg, "unused function parameter") or
221 mem.eql(u8, msg, "unused capture"))221 mem.eql(u8, msg, "unused capture"))
222 {222 {
223 const ident_token = item.data.token;223 const ident_token = item.data.token.unwrap().?;
224 try more_fixups.unused_var_decls.put(gpa, ident_token, {});224 try more_fixups.unused_var_decls.put(gpa, ident_token, {});
225 } else {225 } else {
226 std.debug.print("found other ZIR error: '{s}'\n", .{msg});226 std.debug.print("found other ZIR error: '{s}'\n", .{msg});
lib/compiler/reduce/Walk.zig+160-253
...@@ -98,29 +98,26 @@ const ScanDeclsAction = enum { add, remove };...@@ -98,29 +98,26 @@ const ScanDeclsAction = enum { add, remove };
98fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction) Error!void {98fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction) Error!void {
99 const ast = w.ast;99 const ast = w.ast;
100 const gpa = w.gpa;100 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
105 for (members) |member_node| {102 for (members) |member_node| {
106 const name_token = switch (node_tags[member_node]) {103 const name_token = switch (ast.nodeTag(member_node)) {
107 .global_var_decl,104 .global_var_decl,
108 .local_var_decl,105 .local_var_decl,
109 .simple_var_decl,106 .simple_var_decl,
110 .aligned_var_decl,107 .aligned_var_decl,
111 => main_tokens[member_node] + 1,108 => ast.nodeMainToken(member_node) + 1,
112109
113 .fn_proto_simple,110 .fn_proto_simple,
114 .fn_proto_multi,111 .fn_proto_multi,
115 .fn_proto_one,112 .fn_proto_one,
116 .fn_proto,113 .fn_proto,
117 .fn_decl,114 .fn_decl,
118 => main_tokens[member_node] + 1,115 => ast.nodeMainToken(member_node) + 1,
119116
120 else => continue,117 else => continue,
121 };118 };
122119
123 assert(token_tags[name_token] == .identifier);120 assert(ast.tokenTag(name_token) == .identifier);
124 const name_bytes = ast.tokenSlice(name_token);121 const name_bytes = ast.tokenSlice(name_token);
125122
126 switch (action) {123 switch (action) {
...@@ -145,12 +142,10 @@ fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction)...@@ -145,12 +142,10 @@ fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction)
145142
146fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {143fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
147 const ast = w.ast;144 const ast = w.ast;
148 const datas = ast.nodes.items(.data);145 switch (ast.nodeTag(decl)) {
149 switch (ast.nodes.items(.tag)[decl]) {
150 .fn_decl => {146 .fn_decl => {
151 const fn_proto = datas[decl].lhs;147 const fn_proto, const body_node = ast.nodeData(decl).node_and_node;
152 try walkExpression(w, fn_proto);148 try walkExpression(w, fn_proto);
153 const body_node = datas[decl].rhs;
154 if (!isFnBodyGutted(ast, body_node)) {149 if (!isFnBodyGutted(ast, body_node)) {
155 w.replace_names.clearRetainingCapacity();150 w.replace_names.clearRetainingCapacity();
156 try w.transformations.append(.{ .gut_function = decl });151 try w.transformations.append(.{ .gut_function = decl });
...@@ -167,7 +162,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {...@@ -167,7 +162,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
167162
168 .@"usingnamespace" => {163 .@"usingnamespace" => {
169 try w.transformations.append(.{ .delete_node = decl });164 try w.transformations.append(.{ .delete_node = decl });
170 const expr = datas[decl].lhs;165 const expr = ast.nodeData(decl).node;
171 try walkExpression(w, expr);166 try walkExpression(w, expr);
172 },167 },
173168
...@@ -179,7 +174,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {...@@ -179,7 +174,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
179174
180 .test_decl => {175 .test_decl => {
181 try w.transformations.append(.{ .delete_node = decl });176 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]);
183 },178 },
184179
185 .container_field_init,180 .container_field_init,
...@@ -202,14 +197,10 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {...@@ -202,14 +197,10 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void {
202197
203fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {198fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
204 const ast = w.ast;199 const ast = w.ast;
205 const token_tags = ast.tokens.items(.tag);200 switch (ast.nodeTag(node)) {
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]) {
210 .identifier => {201 .identifier => {
211 const name_ident = main_tokens[node];202 const name_ident = ast.nodeMainToken(node);
212 assert(token_tags[name_ident] == .identifier);203 assert(ast.tokenTag(name_ident) == .identifier);
213 const name_bytes = ast.tokenSlice(name_ident);204 const name_bytes = ast.tokenSlice(name_ident);
214 _ = w.unreferenced_globals.swapRemove(name_bytes);205 _ = w.unreferenced_globals.swapRemove(name_bytes);
215 if (w.replace_names.get(name_bytes)) |index| {206 if (w.replace_names.get(name_bytes)) |index| {
...@@ -230,64 +221,36 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -230,64 +221,36 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
230221
231 .block_two,222 .block_two,
232 .block_two_semicolon,223 .block_two_semicolon,
233 => {
234 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
235 if (datas[node].lhs == 0) {
236 return walkBlock(w, node, statements[0..0]);
237 } else if (datas[node].rhs == 0) {
238 return walkBlock(w, node, statements[0..1]);
239 } else {
240 return walkBlock(w, node, statements[0..2]);
241 }
242 },
243 .block,224 .block,
244 .block_semicolon,225 .block_semicolon,
245 => {226 => {
246 const statements = ast.extra_data[datas[node].lhs..datas[node].rhs];227 var buf: [2]Ast.Node.Index = undefined;
228 const statements = ast.blockStatements(&buf, node).?;
247 return walkBlock(w, node, statements);229 return walkBlock(w, node, statements);
248 },230 },
249231
250 .@"errdefer" => {232 .@"errdefer" => {
251 const expr = datas[node].rhs;233 const expr = ast.nodeData(node).opt_token_and_node[1];
252 return walkExpression(w, expr);234 return walkExpression(w, expr);
253 },235 },
254236
255 .@"defer" => {237 .@"defer",
256 const expr = datas[node].rhs;238 .@"comptime",
257 return walkExpression(w, expr);239 .@"nosuspend",
258 },240 .@"suspend",
259 .@"comptime", .@"nosuspend" => {241 => {
260 const block = datas[node].lhs;242 return walkExpression(w, ast.nodeData(node).node);
261 return walkExpression(w, block);
262 },
263
264 .@"suspend" => {
265 const body = datas[node].lhs;
266 return walkExpression(w, body);
267 },
268
269 .@"catch" => {
270 try walkExpression(w, datas[node].lhs); // target
271 try walkExpression(w, datas[node].rhs); // fallback
272 },243 },
273244
274 .field_access => {245 .field_access => {
275 const field_access = datas[node];246 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
276 try walkExpression(w, field_access.lhs);
277 },247 },
278248
279 .error_union,
280 .switch_range,
281 => {
282 const infix = datas[node];
283 try walkExpression(w, infix.lhs);
284 return walkExpression(w, infix.rhs);
285 },
286 .for_range => {249 .for_range => {
287 const infix = datas[node];250 const start, const opt_end = ast.nodeData(node).node_and_opt_node;
288 try walkExpression(w, infix.lhs);251 try walkExpression(w, start);
289 if (infix.rhs != 0) {252 if (opt_end.unwrap()) |end| {
290 return walkExpression(w, infix.rhs);253 return walkExpression(w, end);
291 }254 }
292 },255 },
293256
...@@ -337,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -337,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
337 .sub,300 .sub,
338 .sub_wrap,301 .sub_wrap,
339 .sub_sat,302 .sub_sat,
303 .@"catch",
304 .error_union,
305 .switch_range,
340 .@"orelse",306 .@"orelse",
307 .array_access,
341 => {308 => {
342 const infix = datas[node];309 const lhs, const rhs = ast.nodeData(node).node_and_node;
343 try walkExpression(w, infix.lhs);310 try walkExpression(w, lhs);
344 try walkExpression(w, infix.rhs);311 try walkExpression(w, rhs);
345 },312 },
346313
347 .assign_destructure => {314 .assign_destructure => {
348 const full = ast.assignDestructure(node);315 const full = ast.assignDestructure(node);
349 for (full.ast.variables) |variable_node| {316 for (full.ast.variables) |variable_node| {
350 switch (node_tags[variable_node]) {317 switch (ast.nodeTag(variable_node)) {
351 .global_var_decl,318 .global_var_decl,
352 .local_var_decl,319 .local_var_decl,
353 .simple_var_decl,320 .simple_var_decl,
...@@ -366,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -366,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
366 .negation_wrap,333 .negation_wrap,
367 .optional_type,334 .optional_type,
368 .address_of,335 .address_of,
369 => {
370 return walkExpression(w, datas[node].lhs);
371 },
372
373 .@"try",336 .@"try",
374 .@"resume",337 .@"resume",
375 .@"await",338 .@"await",
339 .deref,
376 => {340 => {
377 return walkExpression(w, datas[node].lhs);341 return walkExpression(w, ast.nodeData(node).node);
378 },342 },
379343
380 .array_type,344 .array_type,
...@@ -426,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -426,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
426 return walkCall(w, ast.fullCall(&buf, node).?);390 return walkCall(w, ast.fullCall(&buf, node).?);
427 },391 },
428392
429 .array_access => {
430 const suffix = datas[node];
431 try walkExpression(w, suffix.lhs);
432 try walkExpression(w, suffix.rhs);
433 },
434
435 .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?),393 .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?),
436394
437 .deref => {
438 try walkExpression(w, datas[node].lhs);
439 },
440
441 .unwrap_optional => {395 .unwrap_optional => {
442 try walkExpression(w, datas[node].lhs);396 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
443 },397 },
444398
445 .@"break" => {399 .@"break" => {
446 const label_token = datas[node].lhs;400 const label_token, const target = ast.nodeData(node).opt_token_and_opt_node;
447 const target = datas[node].rhs;401 if (label_token == .none and target == .none) {
448 if (label_token == 0 and target == 0) {
449 // no expressions402 // no expressions
450 } else if (label_token == 0 and target != 0) {403 } else if (label_token == .none and target != .none) {
451 try walkExpression(w, target);404 try walkExpression(w, target.unwrap().?);
452 } else if (label_token != 0 and target == 0) {405 } else if (label_token != .none and target == .none) {
453 try walkIdentifier(w, label_token);406 try walkIdentifier(w, label_token.unwrap().?);
454 } else if (label_token != 0 and target != 0) {407 } else if (label_token != .none and target != .none) {
455 try walkExpression(w, target);408 try walkExpression(w, target.unwrap().?);
456 }409 }
457 },410 },
458411
459 .@"continue" => {412 .@"continue" => {
460 const label = datas[node].lhs;413 const opt_label = ast.nodeData(node).opt_token_and_opt_node[0];
461 if (label != 0) {414 if (opt_label.unwrap()) |label| {
462 return walkIdentifier(w, label); // label415 return walkIdentifier(w, label);
463 }416 }
464 },417 },
465418
466 .@"return" => {419 .@"return" => {
467 if (datas[node].lhs != 0) {420 if (ast.nodeData(node).opt_node.unwrap()) |lhs| {
468 try walkExpression(w, datas[node].lhs);421 try walkExpression(w, lhs);
469 }422 }
470 },423 },
471424
472 .grouped_expression => {425 .grouped_expression => {
473 try walkExpression(w, datas[node].lhs);426 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
474 },427 },
475428
476 .container_decl,429 .container_decl,
...@@ -491,13 +444,11 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -491,13 +444,11 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
491 },444 },
492445
493 .error_set_decl => {446 .error_set_decl => {
494 const error_token = main_tokens[node];447 const lbrace, const rbrace = ast.nodeData(node).token_and_token;
495 const lbrace = error_token + 1;
496 const rbrace = datas[node].rhs;
497448
498 var i = lbrace + 1;449 var i = lbrace + 1;
499 while (i < rbrace) : (i += 1) {450 while (i < rbrace) : (i += 1) {
500 switch (token_tags[i]) {451 switch (ast.tokenTag(i)) {
501 .doc_comment => unreachable, // TODO452 .doc_comment => unreachable, // TODO
502 .identifier => try walkIdentifier(w, i),453 .identifier => try walkIdentifier(w, i),
503 .comma => {},454 .comma => {},
...@@ -506,17 +457,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -506,17 +457,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
506 }457 }
507 },458 },
508459
509 .builtin_call_two, .builtin_call_two_comma => {460 .builtin_call_two,
510 if (datas[node].lhs == 0) {461 .builtin_call_two_comma,
511 return walkBuiltinCall(w, node, &.{});462 .builtin_call,
512 } else if (datas[node].rhs == 0) {463 .builtin_call_comma,
513 return walkBuiltinCall(w, node, &.{datas[node].lhs});464 => {
514 } else {465 var buf: [2]Ast.Node.Index = undefined;
515 return walkBuiltinCall(w, node, &.{ datas[node].lhs, datas[node].rhs });466 const params = ast.builtinCallParams(&buf, node).?;
516 }
517 },
518 .builtin_call, .builtin_call_comma => {
519 const params = ast.extra_data[datas[node].lhs..datas[node].rhs];
520 return walkBuiltinCall(w, node, params);467 return walkBuiltinCall(w, node, params);
521 },468 },
522469
...@@ -530,20 +477,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -530,20 +477,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
530 },477 },
531478
532 .anyframe_type => {479 .anyframe_type => {
533 if (datas[node].rhs != 0) {480 _, const child_type = ast.nodeData(node).token_and_node;
534 return walkExpression(w, datas[node].rhs);481 return walkExpression(w, child_type);
535 }
536 },482 },
537483
538 .@"switch",484 .@"switch",
539 .switch_comma,485 .switch_comma,
540 => {486 => {
541 const condition = datas[node].lhs;487 const full = ast.fullSwitch(node).?;
542 const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange);488 try walkExpression(w, full.ast.condition); // condition expression
543 const cases = ast.extra_data[extra.start..extra.end];489 try walkExpressions(w, full.ast.cases);
544
545 try walkExpression(w, condition); // condition expression
546 try walkExpressions(w, cases);
547 },490 },
548491
549 .switch_case_one,492 .switch_case_one,
...@@ -570,7 +513,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -570,7 +513,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
570 => return walkAsm(w, ast.fullAsm(node).?),513 => return walkAsm(w, ast.fullAsm(node).?),
571514
572 .enum_literal => {515 .enum_literal => {
573 return walkIdentifier(w, main_tokens[node]); // name516 return walkIdentifier(w, ast.nodeMainToken(node)); // name
574 },517 },
575518
576 .fn_decl => unreachable,519 .fn_decl => unreachable,
...@@ -592,66 +535,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -592,66 +535,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
592fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {535fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {
593 _ = decl_node;536 _ = decl_node;
594537
595 if (var_decl.ast.type_node != 0) {538 if (var_decl.ast.type_node.unwrap()) |type_node| {
596 try walkExpression(w, var_decl.ast.type_node);539 try walkExpression(w, type_node);
597 }540 }
598541
599 if (var_decl.ast.align_node != 0) {542 if (var_decl.ast.align_node.unwrap()) |align_node| {
600 try walkExpression(w, var_decl.ast.align_node);543 try walkExpression(w, align_node);
601 }544 }
602545
603 if (var_decl.ast.addrspace_node != 0) {546 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
604 try walkExpression(w, var_decl.ast.addrspace_node);547 try walkExpression(w, addrspace_node);
605 }548 }
606549
607 if (var_decl.ast.section_node != 0) {550 if (var_decl.ast.section_node.unwrap()) |section_node| {
608 try walkExpression(w, var_decl.ast.section_node);551 try walkExpression(w, section_node);
609 }552 }
610553
611 if (var_decl.ast.init_node != 0) {554 if (var_decl.ast.init_node.unwrap()) |init_node| {
612 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {555 if (!isUndefinedIdent(w.ast, init_node)) {
613 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });556 try w.transformations.append(.{ .replace_with_undef = init_node });
614 }557 }
615 try walkExpression(w, var_decl.ast.init_node);558 try walkExpression(w, init_node);
616 }559 }
617}560}
618561
619fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {562fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
620 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name563 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
621564
622 if (var_decl.ast.type_node != 0) {565 if (var_decl.ast.type_node.unwrap()) |type_node| {
623 try walkExpression(w, var_decl.ast.type_node);566 try walkExpression(w, type_node);
624 }567 }
625568
626 if (var_decl.ast.align_node != 0) {569 if (var_decl.ast.align_node.unwrap()) |align_node| {
627 try walkExpression(w, var_decl.ast.align_node);570 try walkExpression(w, align_node);
628 }571 }
629572
630 if (var_decl.ast.addrspace_node != 0) {573 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
631 try walkExpression(w, var_decl.ast.addrspace_node);574 try walkExpression(w, addrspace_node);
632 }575 }
633576
634 if (var_decl.ast.section_node != 0) {577 if (var_decl.ast.section_node.unwrap()) |section_node| {
635 try walkExpression(w, var_decl.ast.section_node);578 try walkExpression(w, section_node);
636 }579 }
637580
638 if (var_decl.ast.init_node != 0) {581 if (var_decl.ast.init_node.unwrap()) |init_node| {
639 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {582 if (!isUndefinedIdent(w.ast, init_node)) {
640 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });583 try w.transformations.append(.{ .replace_with_undef = init_node });
641 }584 }
642 try walkExpression(w, var_decl.ast.init_node);585 try walkExpression(w, init_node);
643 }586 }
644}587}
645588
646fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {589fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {
647 if (field.ast.type_expr != 0) {590 if (field.ast.type_expr.unwrap()) |type_expr| {
648 try walkExpression(w, field.ast.type_expr); // type591 try walkExpression(w, type_expr); // type
649 }592 }
650 if (field.ast.align_expr != 0) {593 if (field.ast.align_expr.unwrap()) |align_expr| {
651 try walkExpression(w, field.ast.align_expr); // alignment594 try walkExpression(w, align_expr); // alignment
652 }595 }
653 if (field.ast.value_expr != 0) {596 if (field.ast.value_expr.unwrap()) |value_expr| {
654 try walkExpression(w, field.ast.value_expr); // value597 try walkExpression(w, value_expr); // value
655 }598 }
656}599}
657600
...@@ -662,18 +605,17 @@ fn walkBlock(...@@ -662,18 +605,17 @@ fn walkBlock(
662) Error!void {605) Error!void {
663 _ = block_node;606 _ = block_node;
664 const ast = w.ast;607 const ast = w.ast;
665 const node_tags = ast.nodes.items(.tag);
666608
667 for (statements) |stmt| {609 for (statements) |stmt| {
668 switch (node_tags[stmt]) {610 switch (ast.nodeTag(stmt)) {
669 .global_var_decl,611 .global_var_decl,
670 .local_var_decl,612 .local_var_decl,
671 .simple_var_decl,613 .simple_var_decl,
672 .aligned_var_decl,614 .aligned_var_decl,
673 => {615 => {
674 const var_decl = ast.fullVarDecl(stmt).?;616 const var_decl = ast.fullVarDecl(stmt).?;
675 if (var_decl.ast.init_node != 0 and617 if (var_decl.ast.init_node != .none and
676 isUndefinedIdent(w.ast, var_decl.ast.init_node))618 isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?))
677 {619 {
678 try w.transformations.append(.{ .delete_var_decl = .{620 try w.transformations.append(.{ .delete_var_decl = .{
679 .var_decl_node = stmt,621 .var_decl_node = stmt,
...@@ -704,15 +646,15 @@ fn walkBlock(...@@ -704,15 +646,15 @@ fn walkBlock(
704646
705fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {647fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {
706 try walkExpression(w, array_type.ast.elem_count);648 try walkExpression(w, array_type.ast.elem_count);
707 if (array_type.ast.sentinel != 0) {649 if (array_type.ast.sentinel.unwrap()) |sentinel| {
708 try walkExpression(w, array_type.ast.sentinel);650 try walkExpression(w, sentinel);
709 }651 }
710 return walkExpression(w, array_type.ast.elem_type);652 return walkExpression(w, array_type.ast.elem_type);
711}653}
712654
713fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {655fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {
714 if (array_init.ast.type_expr != 0) {656 if (array_init.ast.type_expr.unwrap()) |type_expr| {
715 try walkExpression(w, array_init.ast.type_expr); // T657 try walkExpression(w, type_expr); // T
716 }658 }
717 for (array_init.ast.elements) |elem_init| {659 for (array_init.ast.elements) |elem_init| {
718 try walkExpression(w, elem_init);660 try walkExpression(w, elem_init);
...@@ -725,8 +667,8 @@ fn walkStructInit(...@@ -725,8 +667,8 @@ fn walkStructInit(
725 struct_init: Ast.full.StructInit,667 struct_init: Ast.full.StructInit,
726) Error!void {668) Error!void {
727 _ = struct_node;669 _ = struct_node;
728 if (struct_init.ast.type_expr != 0) {670 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
729 try walkExpression(w, struct_init.ast.type_expr); // T671 try walkExpression(w, type_expr); // T
730 }672 }
731 for (struct_init.ast.fields) |field_init| {673 for (struct_init.ast.fields) |field_init| {
732 try walkExpression(w, field_init);674 try walkExpression(w, field_init);
...@@ -746,18 +688,17 @@ fn walkSlice(...@@ -746,18 +688,17 @@ fn walkSlice(
746 _ = slice_node;688 _ = slice_node;
747 try walkExpression(w, slice.ast.sliced);689 try walkExpression(w, slice.ast.sliced);
748 try walkExpression(w, slice.ast.start);690 try walkExpression(w, slice.ast.start);
749 if (slice.ast.end != 0) {691 if (slice.ast.end.unwrap()) |end| {
750 try walkExpression(w, slice.ast.end);692 try walkExpression(w, end);
751 }693 }
752 if (slice.ast.sentinel != 0) {694 if (slice.ast.sentinel.unwrap()) |sentinel| {
753 try walkExpression(w, slice.ast.sentinel);695 try walkExpression(w, sentinel);
754 }696 }
755}697}
756698
757fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {699fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {
758 const ast = w.ast;700 const ast = w.ast;
759 const token_tags = ast.tokens.items(.tag);701 assert(ast.tokenTag(name_ident) == .identifier);
760 assert(token_tags[name_ident] == .identifier);
761 const name_bytes = ast.tokenSlice(name_ident);702 const name_bytes = ast.tokenSlice(name_ident);
762 _ = w.unreferenced_globals.swapRemove(name_bytes);703 _ = w.unreferenced_globals.swapRemove(name_bytes);
763}704}
...@@ -773,8 +714,8 @@ fn walkContainerDecl(...@@ -773,8 +714,8 @@ fn walkContainerDecl(
773 container_decl: Ast.full.ContainerDecl,714 container_decl: Ast.full.ContainerDecl,
774) Error!void {715) Error!void {
775 _ = container_decl_node;716 _ = container_decl_node;
776 if (container_decl.ast.arg != 0) {717 if (container_decl.ast.arg.unwrap()) |arg| {
777 try walkExpression(w, container_decl.ast.arg);718 try walkExpression(w, arg);
778 }719 }
779 try walkMembers(w, container_decl.ast.members);720 try walkMembers(w, container_decl.ast.members);
780}721}
...@@ -785,14 +726,13 @@ fn walkBuiltinCall(...@@ -785,14 +726,13 @@ fn walkBuiltinCall(
785 params: []const Ast.Node.Index,726 params: []const Ast.Node.Index,
786) Error!void {727) Error!void {
787 const ast = w.ast;728 const ast = w.ast;
788 const main_tokens = ast.nodes.items(.main_token);729 const builtin_token = ast.nodeMainToken(call_node);
789 const builtin_token = main_tokens[call_node];
790 const builtin_name = ast.tokenSlice(builtin_token);730 const builtin_name = ast.tokenSlice(builtin_token);
791 const info = BuiltinFn.list.get(builtin_name).?;731 const info = BuiltinFn.list.get(builtin_name).?;
792 switch (info.tag) {732 switch (info.tag) {
793 .import => {733 .import => {
794 const operand_node = params[0];734 const operand_node = params[0];
795 const str_lit_token = main_tokens[operand_node];735 const str_lit_token = ast.nodeMainToken(operand_node);
796 const token_bytes = ast.tokenSlice(str_lit_token);736 const token_bytes = ast.tokenSlice(str_lit_token);
797 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {737 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {
798 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch738 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch
...@@ -821,29 +761,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {...@@ -821,29 +761,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {
821 {761 {
822 var it = fn_proto.iterate(ast);762 var it = fn_proto.iterate(ast);
823 while (it.next()) |param| {763 while (it.next()) |param| {
824 if (param.type_expr != 0) {764 if (param.type_expr) |type_expr| {
825 try walkExpression(w, param.type_expr);765 try walkExpression(w, type_expr);
826 }766 }
827 }767 }
828 }768 }
829769
830 if (fn_proto.ast.align_expr != 0) {770 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
831 try walkExpression(w, fn_proto.ast.align_expr);771 try walkExpression(w, align_expr);
832 }772 }
833773
834 if (fn_proto.ast.addrspace_expr != 0) {774 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
835 try walkExpression(w, fn_proto.ast.addrspace_expr);775 try walkExpression(w, addrspace_expr);
836 }776 }
837777
838 if (fn_proto.ast.section_expr != 0) {778 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
839 try walkExpression(w, fn_proto.ast.section_expr);779 try walkExpression(w, section_expr);
840 }780 }
841781
842 if (fn_proto.ast.callconv_expr != 0) {782 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
843 try walkExpression(w, fn_proto.ast.callconv_expr);783 try walkExpression(w, callconv_expr);
844 }784 }
845785
846 try walkExpression(w, fn_proto.ast.return_type);786 const return_type = fn_proto.ast.return_type.unwrap().?;
787 try walkExpression(w, return_type);
847}788}
848789
849fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {790fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {
...@@ -860,16 +801,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {...@@ -860,16 +801,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {
860}801}
861802
862fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {803fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {
863 assert(while_node.ast.cond_expr != 0);
864 assert(while_node.ast.then_expr != 0);
865
866 // Perform these transformations in this priority order:804 // Perform these transformations in this priority order:
867 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.805 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
868 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.806 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
869 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.807 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
870 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.808 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
871 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and809 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and
872 (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr)))810 (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?)))
873 {811 {
874 try w.transformations.ensureUnusedCapacity(1);812 try w.transformations.ensureUnusedCapacity(1);
875 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });813 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });
...@@ -886,45 +824,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E...@@ -886,45 +824,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E
886 try w.transformations.ensureUnusedCapacity(1);824 try w.transformations.ensureUnusedCapacity(1);
887 w.transformations.appendAssumeCapacity(.{ .replace_node = .{825 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
888 .to_replace = node_index,826 .to_replace = node_index,
889 .replacement = while_node.ast.else_expr,827 .replacement = while_node.ast.else_expr.unwrap().?,
890 } });828 } });
891 }829 }
892830
893 try walkExpression(w, while_node.ast.cond_expr); // condition831 try walkExpression(w, while_node.ast.cond_expr); // condition
894832
895 if (while_node.ast.cont_expr != 0) {833 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
896 try walkExpression(w, while_node.ast.cont_expr);834 try walkExpression(w, cont_expr);
897 }835 }
898836
899 if (while_node.ast.then_expr != 0) {837 try walkExpression(w, while_node.ast.then_expr);
900 try walkExpression(w, while_node.ast.then_expr);838
901 }839 if (while_node.ast.else_expr.unwrap()) |else_expr| {
902 if (while_node.ast.else_expr != 0) {840 try walkExpression(w, else_expr);
903 try walkExpression(w, while_node.ast.else_expr);
904 }841 }
905}842}
906843
907fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {844fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {
908 try walkParamList(w, for_node.ast.inputs);845 try walkParamList(w, for_node.ast.inputs);
909 if (for_node.ast.then_expr != 0) {846 try walkExpression(w, for_node.ast.then_expr);
910 try walkExpression(w, for_node.ast.then_expr);847 if (for_node.ast.else_expr.unwrap()) |else_expr| {
911 }848 try walkExpression(w, else_expr);
912 if (for_node.ast.else_expr != 0) {
913 try walkExpression(w, for_node.ast.else_expr);
914 }849 }
915}850}
916851
917fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {852fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {
918 assert(if_node.ast.cond_expr != 0);
919 assert(if_node.ast.then_expr != 0);
920
921 // Perform these transformations in this priority order:853 // Perform these transformations in this priority order:
922 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.854 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
923 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.855 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
924 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.856 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
925 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.857 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
926 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and858 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and
927 (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr)))859 (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?)))
928 {860 {
929 try w.transformations.ensureUnusedCapacity(1);861 try w.transformations.ensureUnusedCapacity(1);
930 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });862 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });
...@@ -941,17 +873,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void...@@ -941,17 +873,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void
941 try w.transformations.ensureUnusedCapacity(1);873 try w.transformations.ensureUnusedCapacity(1);
942 w.transformations.appendAssumeCapacity(.{ .replace_node = .{874 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
943 .to_replace = node_index,875 .to_replace = node_index,
944 .replacement = if_node.ast.else_expr,876 .replacement = if_node.ast.else_expr.unwrap().?,
945 } });877 } });
946 }878 }
947879
948 try walkExpression(w, if_node.ast.cond_expr); // condition880 try walkExpression(w, if_node.ast.cond_expr); // condition
949881 try walkExpression(w, if_node.ast.then_expr);
950 if (if_node.ast.then_expr != 0) {882 if (if_node.ast.else_expr.unwrap()) |else_expr| {
951 try walkExpression(w, if_node.ast.then_expr);883 try walkExpression(w, else_expr);
952 }
953 if (if_node.ast.else_expr != 0) {
954 try walkExpression(w, if_node.ast.else_expr);
955 }884 }
956}885}
957886
...@@ -971,25 +900,13 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {...@@ -971,25 +900,13 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {
971/// Check if it is already gutted (i.e. its body replaced with `@trap()`).900/// Check if it is already gutted (i.e. its body replaced with `@trap()`).
972fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {901fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {
973 // skip over discards902 // skip over discards
974 const node_tags = ast.nodes.items(.tag);
975 const datas = ast.nodes.items(.data);
976 var statements_buf: [2]Ast.Node.Index = undefined;903 var statements_buf: [2]Ast.Node.Index = undefined;
977 const statements = switch (node_tags[body_node]) {904 const statements = switch (ast.nodeTag(body_node)) {
978 .block_two,905 .block_two,
979 .block_two_semicolon,906 .block_two_semicolon,
980 => blk: {
981 statements_buf[0..2].* = .{ datas[body_node].lhs, datas[body_node].rhs };
982 break :blk if (datas[body_node].lhs == 0)
983 statements_buf[0..0]
984 else if (datas[body_node].rhs == 0)
985 statements_buf[0..1]
986 else
987 statements_buf[0..2];
988 },
989
990 .block,907 .block,
991 .block_semicolon,908 .block_semicolon,
992 => ast.extra_data[datas[body_node].lhs..datas[body_node].rhs],909 => ast.blockStatements(&statements_buf, body_node).?,
993910
994 else => return false,911 else => return false,
995 };912 };
...@@ -1012,27 +929,20 @@ const StmtCategory = enum {...@@ -1012,27 +929,20 @@ const StmtCategory = enum {
1012};929};
1013930
1014fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {931fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
1015 const node_tags = ast.nodes.items(.tag);932 switch (ast.nodeTag(stmt)) {
1016 const datas = ast.nodes.items(.data);933 .builtin_call_two,
1017 const main_tokens = ast.nodes.items(.main_token);934 .builtin_call_two_comma,
1018 switch (node_tags[stmt]) {935 .builtin_call,
1019 .builtin_call_two, .builtin_call_two_comma => {936 .builtin_call_comma,
1020 if (datas[stmt].lhs == 0) {937 => {
1021 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{});938 var buf: [2]Ast.Node.Index = undefined;
1022 } else if (datas[stmt].rhs == 0) {939 const params = ast.builtinCallParams(&buf, stmt).?;
1023 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{datas[stmt].lhs});940 return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params);
1024 } else {
1025 return categorizeBuiltinCall(ast, main_tokens[stmt], &.{ datas[stmt].lhs, datas[stmt].rhs });
1026 }
1027 },
1028 .builtin_call, .builtin_call_comma => {
1029 const params = ast.extra_data[datas[stmt].lhs..datas[stmt].rhs];
1030 return categorizeBuiltinCall(ast, main_tokens[stmt], params);
1031 },941 },
1032 .assign => {942 .assign => {
1033 const infix = datas[stmt];943 const lhs, const rhs = ast.nodeData(stmt).node_and_node;
1034 if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) {944 if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) {
1035 const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]);945 const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs));
1036 if (std.mem.eql(u8, name_bytes, "undefined")) {946 if (std.mem.eql(u8, name_bytes, "undefined")) {
1037 return .discard_undefined;947 return .discard_undefined;
1038 } else {948 } else {
...@@ -1074,11 +984,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {...@@ -1074,11 +984,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {
1074}984}
1075985
1076fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {986fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {
1077 const node_tags = ast.nodes.items(.tag);987 switch (ast.nodeTag(node)) {
1078 const main_tokens = ast.nodes.items(.main_token);
1079 switch (node_tags[node]) {
1080 .identifier => {988 .identifier => {
1081 const token_index = main_tokens[node];989 const token_index = ast.nodeMainToken(node);
1082 const name_bytes = ast.tokenSlice(token_index);990 const name_bytes = ast.tokenSlice(token_index);
1083 return std.mem.eql(u8, name_bytes, string);991 return std.mem.eql(u8, name_bytes, string);
1084 },992 },
...@@ -1087,11 +995,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo...@@ -1087,11 +995,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo
1087}995}
1088996
1089fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {997fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {
1090 const node_tags = ast.nodes.items(.tag);998 switch (ast.nodeTag(node)) {
1091 const node_data = ast.nodes.items(.data);
1092 switch (node_tags[node]) {
1093 .block_two => {999 .block_two => {
1094 return node_data[node].lhs == 0 and node_data[node].rhs == 0;1000 const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node;
1001 return opt_lhs == .none and opt_rhs == .none;
1095 },1002 },
1096 else => return false,1003 else => return false,
1097 }1004 }
lib/docs/wasm/Decl.zig+30-60
...@@ -15,8 +15,7 @@ parent: Index,...@@ -15,8 +15,7 @@ parent: Index,
15pub const ExtraInfo = struct {15pub const ExtraInfo = struct {
16 is_pub: bool,16 is_pub: bool,
17 name: []const u8,17 name: []const u8,
18 /// This might not be a doc_comment token in which case there are no doc comments.18 first_doc_comment: Ast.OptionalTokenIndex,
19 first_doc_comment: Ast.TokenIndex,
20};19};
2120
22pub const Index = enum(u32) {21pub const Index = enum(u32) {
...@@ -34,16 +33,14 @@ pub fn is_pub(d: *const Decl) bool {...@@ -34,16 +33,14 @@ pub fn is_pub(d: *const Decl) bool {
3433
35pub fn extra_info(d: *const Decl) ExtraInfo {34pub fn extra_info(d: *const Decl) ExtraInfo {
36 const ast = d.file.get_ast();35 const ast = d.file.get_ast();
37 const token_tags = ast.tokens.items(.tag);36 switch (ast.nodeTag(d.ast_node)) {
38 const node_tags = ast.nodes.items(.tag);
39 switch (node_tags[d.ast_node]) {
40 .root => return .{37 .root => return .{
41 .name = "",38 .name = "",
42 .is_pub = true,39 .is_pub = true,
43 .first_doc_comment = if (token_tags[0] == .container_doc_comment)40 .first_doc_comment = if (ast.tokenTag(0) == .container_doc_comment)
44 041 .fromToken(0)
45 else42 else
46 token_tags.len - 1,43 .none,
47 },44 },
4845
49 .global_var_decl,46 .global_var_decl,
...@@ -53,7 +50,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {...@@ -53,7 +50,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
53 => {50 => {
54 const var_decl = ast.fullVarDecl(d.ast_node).?;51 const var_decl = ast.fullVarDecl(d.ast_node).?;
55 const name_token = var_decl.ast.mut_token + 1;52 const name_token = var_decl.ast.mut_token + 1;
56 assert(token_tags[name_token] == .identifier);53 assert(ast.tokenTag(name_token) == .identifier);
57 const ident_name = ast.tokenSlice(name_token);54 const ident_name = ast.tokenSlice(name_token);
58 return .{55 return .{
59 .name = ident_name,56 .name = ident_name,
...@@ -71,7 +68,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {...@@ -71,7 +68,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
71 var buf: [1]Ast.Node.Index = undefined;68 var buf: [1]Ast.Node.Index = undefined;
72 const fn_proto = ast.fullFnProto(&buf, d.ast_node).?;69 const fn_proto = ast.fullFnProto(&buf, d.ast_node).?;
73 const name_token = fn_proto.name_token.?;70 const name_token = fn_proto.name_token.?;
74 assert(token_tags[name_token] == .identifier);71 assert(ast.tokenTag(name_token) == .identifier);
75 const ident_name = ast.tokenSlice(name_token);72 const ident_name = ast.tokenSlice(name_token);
76 return .{73 return .{
77 .name = ident_name,74 .name = ident_name,
...@@ -89,9 +86,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {...@@ -89,9 +86,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo {
8986
90pub fn value_node(d: *const Decl) ?Ast.Node.Index {87pub fn value_node(d: *const Decl) ?Ast.Node.Index {
91 const ast = d.file.get_ast();88 const ast = d.file.get_ast();
92 const node_tags = ast.nodes.items(.tag);89 return switch (ast.nodeTag(d.ast_node)) {
93 const token_tags = ast.tokens.items(.tag);
94 return switch (node_tags[d.ast_node]) {
95 .fn_proto,90 .fn_proto,
96 .fn_proto_multi,91 .fn_proto_multi,
97 .fn_proto_one,92 .fn_proto_one,
...@@ -106,8 +101,8 @@ pub fn value_node(d: *const Decl) ?Ast.Node.Index {...@@ -106,8 +101,8 @@ pub fn value_node(d: *const Decl) ?Ast.Node.Index {
106 .aligned_var_decl,101 .aligned_var_decl,
107 => {102 => {
108 const var_decl = ast.fullVarDecl(d.ast_node).?;103 const var_decl = ast.fullVarDecl(d.ast_node).?;
109 if (token_tags[var_decl.ast.mut_token] == .keyword_const)104 if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_const)
110 return var_decl.ast.init_node;105 return var_decl.ast.init_node.unwrap();
111106
112 return null;107 return null;
113 },108 },
...@@ -148,19 +143,12 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index {...@@ -148,19 +143,12 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index {
148pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index {143pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index {
149 if (decl.get_type_fn_return_expr()) |return_expr| {144 if (decl.get_type_fn_return_expr()) |return_expr| {
150 const ast = decl.file.get_ast();145 const ast = decl.file.get_ast();
151 const node_tags = ast.nodes.items(.tag);146 var buffer: [1]Ast.Node.Index = undefined;
152147 const call = ast.fullCall(&buffer, return_expr) orelse return null;
153 switch (node_tags[return_expr]) {148 const token = ast.nodeMainToken(call.ast.fn_expr);
154 .call, .call_comma, .call_one, .call_one_comma => {149 const name = ast.tokenSlice(token);
155 const node_data = ast.nodes.items(.data);150 if (decl.lookup(name)) |function_decl| {
156 const function = node_data[return_expr].lhs;151 return function_decl;
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 => {},
164 }152 }
165 }153 }
166 return null;154 return null;
...@@ -171,35 +159,18 @@ pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index {...@@ -171,35 +159,18 @@ pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index {
171 switch (decl.categorize()) {159 switch (decl.categorize()) {
172 .type_function => {160 .type_function => {
173 const ast = decl.file.get_ast();161 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]) {163 const body_node = ast.nodeData(decl.ast_node).node_and_node[1];
180 .block, .block_semicolon => {164
181 const statements = ast.extra_data[node_data[body_node].lhs..node_data[body_node].rhs];165 var buf: [2]Ast.Node.Index = undefined;
182 // Look for the return statement166 const statements = ast.blockStatements(&buf, body_node) orelse return null;
183 for (statements) |stmt| {167
184 if (node_tags[stmt] == .@"return") {168 for (statements) |stmt| {
185 return node_data[stmt].lhs;169 if (ast.nodeTag(stmt) == .@"return") {
186 }170 return ast.nodeData(stmt).node;
187 }171 }
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,
202 }172 }
173 return null;
203 },174 },
204 else => return null,175 else => return null,
205 }176 }
...@@ -269,16 +240,15 @@ pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) O...@@ -269,16 +240,15 @@ pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) O
269 }240 }
270}241}
271242
272pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.TokenIndex {243pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.OptionalTokenIndex {
273 const token_tags = ast.tokens.items(.tag);
274 var it = token;244 var it = token;
275 while (it > 0) {245 while (it > 0) {
276 it -= 1;246 it -= 1;
277 if (token_tags[it] != .doc_comment) {247 if (ast.tokenTag(it) != .doc_comment) {
278 return it + 1;248 return .fromToken(it + 1);
279 }249 }
280 }250 }
281 return it;251 return .none;
282}252}
283253
284/// Successively looks up each component.254/// Successively looks up each component.
lib/docs/wasm/Walk.zig+92-134
...@@ -91,12 +91,10 @@ pub const File = struct {...@@ -91,12 +91,10 @@ pub const File = struct {
9191
92 pub fn categorize_decl(file_index: File.Index, node: Ast.Node.Index) Category {92 pub fn categorize_decl(file_index: File.Index, node: Ast.Node.Index) Category {
93 const ast = file_index.get_ast();93 const ast = file_index.get_ast();
94 const node_tags = ast.nodes.items(.tag);94 switch (ast.nodeTag(node)) {
95 const token_tags = ast.tokens.items(.tag);
96 switch (node_tags[node]) {
97 .root => {95 .root => {
98 for (ast.rootDecls()) |member| {96 for (ast.rootDecls()) |member| {
99 switch (node_tags[member]) {97 switch (ast.nodeTag(member)) {
100 .container_field_init,98 .container_field_init,
101 .container_field_align,99 .container_field_align,
102 .container_field,100 .container_field,
...@@ -113,10 +111,12 @@ pub const File = struct {...@@ -113,10 +111,12 @@ pub const File = struct {
113 .aligned_var_decl,111 .aligned_var_decl,
114 => {112 => {
115 const var_decl = ast.fullVarDecl(node).?;113 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)
117 return .{ .global_variable = node };115 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);
120 },120 },
121121
122 .fn_proto,122 .fn_proto,
...@@ -139,7 +139,7 @@ pub const File = struct {...@@ -139,7 +139,7 @@ pub const File = struct {
139 node: Ast.Node.Index,139 node: Ast.Node.Index,
140 full: Ast.full.FnProto,140 full: Ast.full.FnProto,
141 ) Category {141 ) Category {
142 return switch (categorize_expr(file_index, full.ast.return_type)) {142 return switch (categorize_expr(file_index, full.ast.return_type.unwrap().?)) {
143 .namespace, .container, .error_set, .type_type => .{ .type_function = node },143 .namespace, .container, .error_set, .type_type => .{ .type_function = node },
144 else => .{ .function = node },144 else => .{ .function = node },
145 };145 };
...@@ -155,12 +155,8 @@ pub const File = struct {...@@ -155,12 +155,8 @@ pub const File = struct {
155 pub fn categorize_expr(file_index: File.Index, node: Ast.Node.Index) Category {155 pub fn categorize_expr(file_index: File.Index, node: Ast.Node.Index) Category {
156 const file = file_index.get();156 const file = file_index.get();
157 const ast = file_index.get_ast();157 const ast = file_index.get_ast();
158 const node_tags = ast.nodes.items(.tag);158 //log.debug("categorize_expr tag {s}", .{@tagName(ast.nodeTag(node))});
159 const node_datas = ast.nodes.items(.data);159 return switch (ast.nodeTag(node)) {
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]) {
164 .container_decl,160 .container_decl,
165 .container_decl_trailing,161 .container_decl_trailing,
166 .container_decl_arg,162 .container_decl_arg,
...@@ -176,11 +172,11 @@ pub const File = struct {...@@ -176,11 +172,11 @@ pub const File = struct {
176 => {172 => {
177 var buf: [2]Ast.Node.Index = undefined;173 var buf: [2]Ast.Node.Index = undefined;
178 const container_decl = ast.fullContainerDecl(&buf, node).?;174 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) {
180 return .{ .container = node };176 return .{ .container = node };
181 }177 }
182 for (container_decl.ast.members) |member| {178 for (container_decl.ast.members) |member| {
183 switch (node_tags[member]) {179 switch (ast.nodeTag(member)) {
184 .container_field_init,180 .container_field_init,
185 .container_field_align,181 .container_field_align,
186 .container_field,182 .container_field,
...@@ -196,7 +192,7 @@ pub const File = struct {...@@ -196,7 +192,7 @@ pub const File = struct {
196 => .{ .error_set = node },192 => .{ .error_set = node },
197193
198 .identifier => {194 .identifier => {
199 const name_token = ast.nodes.items(.main_token)[node];195 const name_token = ast.nodeMainToken(node);
200 const ident_name = ast.tokenSlice(name_token);196 const ident_name = ast.tokenSlice(name_token);
201 if (std.mem.eql(u8, ident_name, "type"))197 if (std.mem.eql(u8, ident_name, "type"))
202 return .type_type;198 return .type_type;
...@@ -217,9 +213,7 @@ pub const File = struct {...@@ -217,9 +213,7 @@ pub const File = struct {
217 },213 },
218214
219 .field_access => {215 .field_access => {
220 const object_node = node_datas[node].lhs;216 const object_node, const field_ident = ast.nodeData(node).node_and_token;
221 const dot_token = main_tokens[node];
222 const field_ident = dot_token + 1;
223 const field_name = ast.tokenSlice(field_ident);217 const field_name = ast.tokenSlice(field_ident);
224218
225 switch (categorize_expr(file_index, object_node)) {219 switch (categorize_expr(file_index, object_node)) {
...@@ -232,20 +226,13 @@ pub const File = struct {...@@ -232,20 +226,13 @@ pub const File = struct {
232 return .{ .global_const = node };226 return .{ .global_const = node };
233 },227 },
234228
235 .builtin_call_two, .builtin_call_two_comma => {229 .builtin_call_two,
236 if (node_datas[node].lhs == 0) {230 .builtin_call_two_comma,
237 const params = [_]Ast.Node.Index{};231 .builtin_call,
238 return categorize_builtin_call(file_index, node, &params);232 .builtin_call_comma,
239 } else if (node_datas[node].rhs == 0) {233 => {
240 const params = [_]Ast.Node.Index{node_datas[node].lhs};234 var buf: [2]Ast.Node.Index = undefined;
241 return categorize_builtin_call(file_index, node, &params);235 const params = ast.builtinCallParams(&buf, node).?;
242 } else {
243 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
244 return categorize_builtin_call(file_index, node, &params);
245 }
246 },
247 .builtin_call, .builtin_call_comma => {
248 const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
249 return categorize_builtin_call(file_index, node, params);236 return categorize_builtin_call(file_index, node, params);
250 },237 },
251238
...@@ -266,9 +253,9 @@ pub const File = struct {...@@ -266,9 +253,9 @@ pub const File = struct {
266 .@"if",253 .@"if",
267 => {254 => {
268 const if_full = ast.fullIf(node).?;255 const if_full = ast.fullIf(node).?;
269 if (if_full.ast.else_expr != 0) {256 if (if_full.ast.else_expr.unwrap()) |else_expr| {
270 const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr);257 const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr);
271 const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr);258 const else_cat = categorize_expr_deep(file_index, else_expr);
272 if (then_cat == .type_type and else_cat == .type_type) {259 if (then_cat == .type_type and else_cat == .type_type) {
273 return .type_type;260 return .type_type;
274 } else if (then_cat == .error_set and else_cat == .error_set) {261 } else if (then_cat == .error_set and else_cat == .error_set) {
...@@ -327,11 +314,10 @@ pub const File = struct {...@@ -327,11 +314,10 @@ pub const File = struct {
327 params: []const Ast.Node.Index,314 params: []const Ast.Node.Index,
328 ) Category {315 ) Category {
329 const ast = file_index.get_ast();316 const ast = file_index.get_ast();
330 const main_tokens = ast.nodes.items(.main_token);317 const builtin_token = ast.nodeMainToken(node);
331 const builtin_token = main_tokens[node];
332 const builtin_name = ast.tokenSlice(builtin_token);318 const builtin_name = ast.tokenSlice(builtin_token);
333 if (std.mem.eql(u8, builtin_name, "@import")) {319 if (std.mem.eql(u8, builtin_name, "@import")) {
334 const str_lit_token = main_tokens[params[0]];320 const str_lit_token = ast.nodeMainToken(params[0]);
335 const str_bytes = ast.tokenSlice(str_lit_token);321 const str_bytes = ast.tokenSlice(str_lit_token);
336 const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM");322 const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM");
337 defer gpa.free(file_path);323 defer gpa.free(file_path);
...@@ -364,14 +350,12 @@ pub const File = struct {...@@ -364,14 +350,12 @@ pub const File = struct {
364350
365 fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category {351 fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category {
366 const ast = file_index.get_ast();352 const ast = file_index.get_ast();
367 const node_datas = ast.nodes.items(.data);353 const full = ast.fullSwitch(node).?;
368 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
369 const case_nodes = ast.extra_data[extra.start..extra.end];
370 var all_type_type = true;354 var all_type_type = true;
371 var all_error_set = true;355 var all_error_set = true;
372 var any_type = false;356 var any_type = false;
373 if (case_nodes.len == 0) return .{ .global_const = node };357 if (full.ast.cases.len == 0) return .{ .global_const = node };
374 for (case_nodes) |case_node| {358 for (full.ast.cases) |case_node| {
375 const case = ast.fullSwitchCase(case_node).?;359 const case = ast.fullSwitchCase(case_node).?;
376 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {360 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {
377 .type_type => {361 .type_type => {
...@@ -417,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {...@@ -417,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {
417 const scope = try gpa.create(Scope);401 const scope = try gpa.create(Scope);
418 scope.* = .{ .tag = .top };402 scope.* = .{ .tag = .top };
419403
420 const decl_index = try file_index.add_decl(0, .none);404 const decl_index = try file_index.add_decl(.root, .none);
421 try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot());405 try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot());
422406
423 const file = file_index.get();407 const file = file_index.get();
424 shrinkToFit(&file.ident_decls);408 shrinkToFit(&file.ident_decls);
...@@ -512,13 +496,12 @@ pub const Scope = struct {...@@ -512,13 +496,12 @@ pub const Scope = struct {
512 }496 }
513497
514 pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index {498 pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index {
515 const main_tokens = ast.nodes.items(.main_token);
516 var it: *Scope = start_scope;499 var it: *Scope = start_scope;
517 while (true) switch (it.tag) {500 while (true) switch (it.tag) {
518 .top => break,501 .top => break,
519 .local => {502 .local => {
520 const local: *Local = @alignCast(@fieldParentPtr("base", it));503 const local: *Local = @alignCast(@fieldParentPtr("base", it));
521 const name_token = main_tokens[local.var_node] + 1;504 const name_token = ast.nodeMainToken(local.var_node) + 1;
522 const ident_name = ast.tokenSlice(name_token);505 const ident_name = ast.tokenSlice(name_token);
523 if (std.mem.eql(u8, ident_name, name)) {506 if (std.mem.eql(u8, ident_name, name)) {
524 return local.var_node;507 return local.var_node;
...@@ -545,8 +528,6 @@ fn struct_decl(...@@ -545,8 +528,6 @@ fn struct_decl(
545 container_decl: Ast.full.ContainerDecl,528 container_decl: Ast.full.ContainerDecl,
546) Oom!void {529) Oom!void {
547 const ast = w.file.get_ast();530 const ast = w.file.get_ast();
548 const node_tags = ast.nodes.items(.tag);
549 const node_datas = ast.nodes.items(.data);
550531
551 const namespace = try gpa.create(Scope.Namespace);532 const namespace = try gpa.create(Scope.Namespace);
552 namespace.* = .{533 namespace.* = .{
...@@ -556,7 +537,7 @@ fn struct_decl(...@@ -556,7 +537,7 @@ fn struct_decl(
556 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);537 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);
557 try w.scanDecls(namespace, container_decl.ast.members);538 try w.scanDecls(namespace, container_decl.ast.members);
558539
559 for (container_decl.ast.members) |member| switch (node_tags[member]) {540 for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) {
560 .container_field_init,541 .container_field_init,
561 .container_field_align,542 .container_field_align,
562 .container_field,543 .container_field,
...@@ -576,7 +557,7 @@ fn struct_decl(...@@ -576,7 +557,7 @@ fn struct_decl(
576 try w.file.get().doctests.put(gpa, member, doctest_node);557 try w.file.get().doctests.put(gpa, member, doctest_node);
577 }558 }
578 const decl_index = try w.file.add_decl(member, parent_decl);559 const decl_index = try w.file.add_decl(member, parent_decl);
579 const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0;560 const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none;
580 try w.fn_decl(&namespace.base, decl_index, body, full);561 try w.fn_decl(&namespace.base, decl_index, body, full);
581 },562 },
582563
...@@ -591,9 +572,9 @@ fn struct_decl(...@@ -591,9 +572,9 @@ fn struct_decl(
591572
592 .@"comptime",573 .@"comptime",
593 .@"usingnamespace",574 .@"usingnamespace",
594 => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs),575 => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
595576
596 .test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs),577 .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]),
597578
598 else => unreachable,579 else => unreachable,
599 };580 };
...@@ -640,13 +621,13 @@ fn fn_decl(...@@ -640,13 +621,13 @@ fn fn_decl(
640 w: *Walk,621 w: *Walk,
641 scope: *Scope,622 scope: *Scope,
642 parent_decl: Decl.Index,623 parent_decl: Decl.Index,
643 body: Ast.Node.Index,624 body: Ast.Node.OptionalIndex,
644 full: Ast.full.FnProto,625 full: Ast.full.FnProto,
645) Oom!void {626) Oom!void {
646 for (full.ast.params) |param| {627 for (full.ast.params) |param| {
647 try expr(w, scope, parent_decl, param);628 try expr(w, scope, parent_decl, param);
648 }629 }
649 try expr(w, scope, parent_decl, full.ast.return_type);630 try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?);
650 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);631 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);
651 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);632 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);
652 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);633 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);
...@@ -654,17 +635,13 @@ fn fn_decl(...@@ -654,17 +635,13 @@ fn fn_decl(
654 try maybe_expr(w, scope, parent_decl, body);635 try maybe_expr(w, scope, parent_decl, body);
655}636}
656637
657fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {638fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.OptionalIndex) Oom!void {
658 if (node != 0) return expr(w, scope, parent_decl, node);639 if (node.unwrap()) |n| return expr(w, scope, parent_decl, n);
659}640}
660641
661fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {642fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void {
662 assert(node != 0);
663 const ast = w.file.get_ast();643 const ast = w.file.get_ast();
664 const node_tags = ast.nodes.items(.tag);644 switch (ast.nodeTag(node)) {
665 const node_datas = ast.nodes.items(.data);
666 const main_tokens = ast.nodes.items(.main_token);
667 switch (node_tags[node]) {
668 .root => unreachable, // Top-level declaration.645 .root => unreachable, // Top-level declaration.
669 .@"usingnamespace" => unreachable, // Top-level declaration.646 .@"usingnamespace" => unreachable, // Top-level declaration.
670 .test_decl => unreachable, // Top-level declaration.647 .test_decl => unreachable, // Top-level declaration.
...@@ -745,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -745,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
745 .array_access,722 .array_access,
746 .switch_range,723 .switch_range,
747 => {724 => {
748 try expr(w, scope, parent_decl, node_datas[node].lhs);725 const lhs, const rhs = ast.nodeData(node).node_and_node;
749 try expr(w, scope, parent_decl, node_datas[node].rhs);726 try expr(w, scope, parent_decl, lhs);
727 try expr(w, scope, parent_decl, rhs);
750 },728 },
751729
752 .assign_destructure => {730 .assign_destructure => {
...@@ -759,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -759,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
759 .bit_not,737 .bit_not,
760 .negation,738 .negation,
761 .negation_wrap,739 .negation_wrap,
762 .@"return",
763 .deref,740 .deref,
764 .address_of,741 .address_of,
765 .optional_type,742 .optional_type,
766 .unwrap_optional,
767 .grouped_expression,
768 .@"comptime",743 .@"comptime",
769 .@"nosuspend",744 .@"nosuspend",
770 .@"suspend",745 .@"suspend",
771 .@"await",746 .@"await",
772 .@"resume",747 .@"resume",
773 .@"try",748 .@"try",
774 => try maybe_expr(w, scope, parent_decl, node_datas[node].lhs),749 => try expr(w, scope, parent_decl, ast.nodeData(node).node),
750 .unwrap_optional,
751 .grouped_expression,
752 => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
753 .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node),
775754
776 .anyframe_type,755 .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]),
777 .@"break",756 .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]),
778 => try maybe_expr(w, scope, parent_decl, node_datas[node].rhs),
779757
780 .identifier => {758 .identifier => {
781 const ident_token = main_tokens[node];759 const ident_token = ast.nodeMainToken(node);
782 const ident_name = ast.tokenSlice(ident_token);760 const ident_name = ast.tokenSlice(ident_token);
783 if (scope.lookup(ast, ident_name)) |var_node| {761 if (scope.lookup(ast, ident_name)) |var_node| {
784 try w.file.get().ident_decls.put(gpa, ident_token, var_node);762 try w.file.get().ident_decls.put(gpa, ident_token, var_node);
785 }763 }
786 },764 },
787 .field_access => {765 .field_access => {
788 const object_node = node_datas[node].lhs;766 const object_node, const field_ident = ast.nodeData(node).node_and_token;
789 const dot_token = main_tokens[node];
790 const field_ident = dot_token + 1;
791 try w.file.get().token_parents.put(gpa, field_ident, node);767 try w.file.get().token_parents.put(gpa, field_ident, node);
792 // This will populate the left-most field object if it is an768 // This will populate the left-most field object if it is an
793 // identifier, allowing rendering code to piece together the link.769 // identifier, allowing rendering code to piece together the link.
...@@ -818,20 +794,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -818,20 +794,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
818 try expr(w, scope, parent_decl, full.ast.template);794 try expr(w, scope, parent_decl, full.ast.template);
819 },795 },
820796
821 .builtin_call_two, .builtin_call_two_comma => {797 .builtin_call_two,
822 if (node_datas[node].lhs == 0) {798 .builtin_call_two_comma,
823 const params = [_]Ast.Node.Index{};799 .builtin_call,
824 return builtin_call(w, scope, parent_decl, node, &params);800 .builtin_call_comma,
825 } else if (node_datas[node].rhs == 0) {801 => {
826 const params = [_]Ast.Node.Index{node_datas[node].lhs};802 var buf: [2]Ast.Node.Index = undefined;
827 return builtin_call(w, scope, parent_decl, node, &params);803 const params = ast.builtinCallParams(&buf, node).?;
828 } else {
829 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
830 return builtin_call(w, scope, parent_decl, node, &params);
831 }
832 },
833 .builtin_call, .builtin_call_comma => {
834 const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
835 return builtin_call(w, scope, parent_decl, node, params);804 return builtin_call(w, scope, parent_decl, node, params);
836 },805 },
837806
...@@ -871,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -871,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
871 .for_simple, .@"for" => {840 .for_simple, .@"for" => {
872 const full = ast.fullFor(node).?;841 const full = ast.fullFor(node).?;
873 for (full.ast.inputs) |input| {842 for (full.ast.inputs) |input| {
874 if (node_tags[input] == .for_range) {843 if (ast.nodeTag(input) == .for_range) {
875 try expr(w, scope, parent_decl, node_datas[input].lhs);844 const start, const end = ast.nodeData(input).node_and_opt_node;
876 try maybe_expr(w, scope, parent_decl, node_datas[input].rhs);845 try expr(w, scope, parent_decl, start);
846 try maybe_expr(w, scope, parent_decl, end);
877 } else {847 } else {
878 try expr(w, scope, parent_decl, input);848 try expr(w, scope, parent_decl, input);
879 }849 }
...@@ -886,18 +856,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -886,18 +856,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
886 .slice_open => return slice(w, scope, parent_decl, ast.sliceOpen(node)),856 .slice_open => return slice(w, scope, parent_decl, ast.sliceOpen(node)),
887 .slice_sentinel => return slice(w, scope, parent_decl, ast.sliceSentinel(node)),857 .slice_sentinel => return slice(w, scope, parent_decl, ast.sliceSentinel(node)),
888858
889 .block_two, .block_two_semicolon => {859 .block_two,
890 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };860 .block_two_semicolon,
891 if (node_datas[node].lhs == 0) {861 .block,
892 return block(w, scope, parent_decl, statements[0..0]);862 .block_semicolon,
893 } else if (node_datas[node].rhs == 0) {863 => {
894 return block(w, scope, parent_decl, statements[0..1]);864 var buf: [2]Ast.Node.Index = undefined;
895 } else {865 const statements = ast.blockStatements(&buf, node).?;
896 return block(w, scope, parent_decl, statements[0..2]);
897 }
898 },
899 .block, .block_semicolon => {
900 const statements = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs];
901 return block(w, scope, parent_decl, statements);866 return block(w, scope, parent_decl, statements);
902 },867 },
903868
...@@ -933,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -933,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
933 },898 },
934899
935 .array_type_sentinel => {900 .array_type_sentinel => {
936 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);901 const len_expr, const extra_index = ast.nodeData(node).node_and_extra;
937 try expr(w, scope, parent_decl, node_datas[node].lhs);902 const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
903 try expr(w, scope, parent_decl, len_expr);
938 try expr(w, scope, parent_decl, extra.elem_type);904 try expr(w, scope, parent_decl, extra.elem_type);
939 try expr(w, scope, parent_decl, extra.sentinel);905 try expr(w, scope, parent_decl, extra.sentinel);
940 },906 },
941 .@"switch", .switch_comma => {907 .@"switch", .switch_comma => {
942 const operand_node = node_datas[node].lhs;908 const full = ast.fullSwitch(node).?;
943 try expr(w, scope, parent_decl, operand_node);909 try expr(w, scope, parent_decl, full.ast.condition);
944 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);910 for (full.ast.cases) |case_node| {
945 const case_nodes = ast.extra_data[extra.start..extra.end];
946 for (case_nodes) |case_node| {
947 const case = ast.fullSwitchCase(case_node).?;911 const case = ast.fullSwitchCase(case_node).?;
948 for (case.ast.values) |value_node| {912 for (case.ast.values) |value_node| {
949 try expr(w, scope, parent_decl, value_node);913 try expr(w, scope, parent_decl, value_node);
...@@ -992,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -992,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
992 .fn_proto,956 .fn_proto,
993 => {957 => {
994 var buf: [1]Ast.Node.Index = undefined;958 var buf: [1]Ast.Node.Index = undefined;
995 return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?);959 return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?);
996 },960 },
997 }961 }
998}962}
...@@ -1012,8 +976,7 @@ fn builtin_call(...@@ -1012,8 +976,7 @@ fn builtin_call(
1012 params: []const Ast.Node.Index,976 params: []const Ast.Node.Index,
1013) Oom!void {977) Oom!void {
1014 const ast = w.file.get_ast();978 const ast = w.file.get_ast();
1015 const main_tokens = ast.nodes.items(.main_token);979 const builtin_token = ast.nodeMainToken(node);
1016 const builtin_token = main_tokens[node];
1017 const builtin_name = ast.tokenSlice(builtin_token);980 const builtin_name = ast.tokenSlice(builtin_token);
1018 if (std.mem.eql(u8, builtin_name, "@This")) {981 if (std.mem.eql(u8, builtin_name, "@This")) {
1019 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());982 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());
...@@ -1031,13 +994,11 @@ fn block(...@@ -1031,13 +994,11 @@ fn block(
1031 statements: []const Ast.Node.Index,994 statements: []const Ast.Node.Index,
1032) Oom!void {995) Oom!void {
1033 const ast = w.file.get_ast();996 const ast = w.file.get_ast();
1034 const node_tags = ast.nodes.items(.tag);
1035 const node_datas = ast.nodes.items(.data);
1036997
1037 var scope = parent_scope;998 var scope = parent_scope;
1038999
1039 for (statements) |node| {1000 for (statements) |node| {
1040 switch (node_tags[node]) {1001 switch (ast.nodeTag(node)) {
1041 .global_var_decl,1002 .global_var_decl,
1042 .local_var_decl,1003 .local_var_decl,
1043 .simple_var_decl,1004 .simple_var_decl,
...@@ -1058,11 +1019,10 @@ fn block(...@@ -1058,11 +1019,10 @@ fn block(
1058 log.debug("walk assign_destructure not implemented yet", .{});1019 log.debug("walk assign_destructure not implemented yet", .{});
1059 },1020 },
10601021
1061 .grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs),1022 .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
10621023
1063 .@"defer",1024 .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
1064 .@"errdefer",1025 .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]),
1065 => try expr(w, scope, parent_decl, node_datas[node].rhs),
10661026
1067 else => try expr(w, scope, parent_decl, node),1027 else => try expr(w, scope, parent_decl, node),
1068 }1028 }
...@@ -1078,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W...@@ -1078,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W
10781038
1079fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void {1039fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void {
1080 const ast = w.file.get_ast();1040 const ast = w.file.get_ast();
1081 const node_tags = ast.nodes.items(.tag);
1082 const main_tokens = ast.nodes.items(.main_token);
1083 const token_tags = ast.tokens.items(.tag);
1084 const node_datas = ast.nodes.items(.data);
10851041
1086 for (members) |member_node| {1042 for (members) |member_node| {
1087 const name_token = switch (node_tags[member_node]) {1043 const name_token = switch (ast.nodeTag(member_node)) {
1088 .global_var_decl,1044 .global_var_decl,
1089 .local_var_decl,1045 .local_var_decl,
1090 .simple_var_decl,1046 .simple_var_decl,
1091 .aligned_var_decl,1047 .aligned_var_decl,
1092 => main_tokens[member_node] + 1,1048 => ast.nodeMainToken(member_node) + 1,
10931049
1094 .fn_proto_simple,1050 .fn_proto_simple,
1095 .fn_proto_multi,1051 .fn_proto_multi,
...@@ -1097,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In...@@ -1097,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In
1097 .fn_proto,1053 .fn_proto,
1098 .fn_decl,1054 .fn_decl,
1099 => blk: {1055 => blk: {
1100 const ident = main_tokens[member_node] + 1;1056 const ident = ast.nodeMainToken(member_node) + 1;
1101 if (token_tags[ident] != .identifier) continue;1057 if (ast.tokenTag(ident) != .identifier) continue;
1102 break :blk ident;1058 break :blk ident;
1103 },1059 },
11041060
1105 .test_decl => {1061 .test_decl => {
1106 const ident_token = node_datas[member_node].lhs;1062 const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0];
1107 const is_doctest = token_tags[ident_token] == .identifier;1063 if (opt_ident_token.unwrap()) |ident_token| {
1108 if (is_doctest) {1064 const is_doctest = ast.tokenTag(ident_token) == .identifier;
1109 const token_bytes = ast.tokenSlice(ident_token);1065 if (is_doctest) {
1110 try namespace.doctests.put(gpa, token_bytes, member_node);1066 const token_bytes = ast.tokenSlice(ident_token);
1067 try namespace.doctests.put(gpa, token_bytes, member_node);
1068 }
1111 }1069 }
1112 continue;1070 continue;
1113 },1071 },
lib/docs/wasm/html_render.zig+9-18
...@@ -41,14 +41,10 @@ pub fn fileSourceHtml(...@@ -41,14 +41,10 @@ pub fn fileSourceHtml(
41 var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty;41 var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty;
42 };42 };
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
48 const start_token = ast.firstToken(root_node);44 const start_token = ast.firstToken(root_node);
49 const end_token = ast.lastToken(root_node) + 1;45 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
53 var indent: usize = 0;49 var indent: usize = 0;
54 if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {50 if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| {
...@@ -64,8 +60,8 @@ pub fn fileSourceHtml(...@@ -64,8 +60,8 @@ pub fn fileSourceHtml(
64 var next_annotate_index: usize = 0;60 var next_annotate_index: usize = 0;
6561
66 for (62 for (
67 token_tags[start_token..end_token],63 ast.tokens.items(.tag)[start_token..end_token],
68 token_starts[start_token..end_token],64 ast.tokens.items(.start)[start_token..end_token],
69 start_token..,65 start_token..,
70 ) |tag, start, token_index| {66 ) |tag, start, token_index| {
71 const between = ast.source[cursor..start];67 const between = ast.source[cursor..start];
...@@ -184,7 +180,7 @@ pub fn fileSourceHtml(...@@ -184,7 +180,7 @@ pub fn fileSourceHtml(
184 .identifier => i: {180 .identifier => i: {
185 if (options.fn_link != .none) {181 if (options.fn_link != .none) {
186 const fn_link = options.fn_link.get();182 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);
188 if (token_index == fn_token + 1) {184 if (token_index == fn_token + 1) {
189 try out.appendSlice(gpa, "<a class=\"tok-fn\" href=\"#");185 try out.appendSlice(gpa, "<a class=\"tok-fn\" href=\"#");
190 _ = missing_feature_url_escape;186 _ = missing_feature_url_escape;
...@@ -196,7 +192,7 @@ pub fn fileSourceHtml(...@@ -196,7 +192,7 @@ pub fn fileSourceHtml(
196 }192 }
197 }193 }
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) {
200 try out.appendSlice(gpa, "<span class=\"tok-fn\">");196 try out.appendSlice(gpa, "<span class=\"tok-fn\">");
201 try appendEscaped(out, slice);197 try appendEscaped(out, slice);
202 try out.appendSlice(gpa, "</span>");198 try out.appendSlice(gpa, "</span>");
...@@ -358,16 +354,11 @@ fn walkFieldAccesses(...@@ -358,16 +354,11 @@ fn walkFieldAccesses(
358 node: Ast.Node.Index,354 node: Ast.Node.Index,
359) Oom!void {355) Oom!void {
360 const ast = file_index.get_ast();356 const ast = file_index.get_ast();
361 const node_tags = ast.nodes.items(.tag);357 assert(ast.nodeTag(node) == .field_access);
362 assert(node_tags[node] == .field_access);358 const object_node, const field_ident = ast.nodeData(node).node_and_token;
363 const node_datas = ast.nodes.items(.data);359 switch (ast.nodeTag(object_node)) {
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]) {
369 .identifier => {360 .identifier => {
370 const lhs_ident = main_tokens[object_node];361 const lhs_ident = ast.nodeMainToken(object_node);
371 try resolveIdentLink(file_index, out, lhs_ident);362 try resolveIdentLink(file_index, out, lhs_ident);
372 },363 },
373 .field_access => {364 .field_access => {
lib/docs/wasm/main.zig+34-48
...@@ -124,7 +124,9 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {...@@ -124,7 +124,9 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
124 @memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items);124 @memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items);
125125
126 const ast = decl.file.get_ast();126 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
129 if (ignore_case) {131 if (ignore_case) {
130 ascii_lower(g.full_path_search_text_lower.items);132 ascii_lower(g.full_path_search_text_lower.items);
...@@ -227,18 +229,15 @@ const ErrorIdentifier = packed struct(u64) {...@@ -227,18 +229,15 @@ const ErrorIdentifier = packed struct(u64) {
227 fn hasDocs(ei: ErrorIdentifier) bool {229 fn hasDocs(ei: ErrorIdentifier) bool {
228 const decl_index = ei.decl_index;230 const decl_index = ei.decl_index;
229 const ast = decl_index.get().file.get_ast();231 const ast = decl_index.get().file.get_ast();
230 const token_tags = ast.tokens.items(.tag);
231 const token_index = ei.token_index;232 const token_index = ei.token_index;
232 if (token_index == 0) return false;233 if (token_index == 0) return false;
233 return token_tags[token_index - 1] == .doc_comment;234 return ast.tokenTag(token_index - 1) == .doc_comment;
234 }235 }
235236
236 fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void {237 fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void {
237 const decl_index = ei.decl_index;238 const decl_index = ei.decl_index;
238 const ast = decl_index.get().file.get_ast();239 const ast = decl_index.get().file.get_ast();
239 const name = ast.tokenSlice(ei.token_index);240 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;
242 const has_link = base_decl != decl_index;241 const has_link = base_decl != decl_index;
243242
244 try out.appendSlice(gpa, "<dt>");243 try out.appendSlice(gpa, "<dt>");
...@@ -253,7 +252,7 @@ const ErrorIdentifier = packed struct(u64) {...@@ -253,7 +252,7 @@ const ErrorIdentifier = packed struct(u64) {
253 }252 }
254 try out.appendSlice(gpa, "</dt>");253 try out.appendSlice(gpa, "</dt>");
255254
256 if (has_docs) {255 if (Decl.findFirstDocComment(ast, ei.token_index).unwrap()) |first_doc_comment| {
257 try out.appendSlice(gpa, "<dd>");256 try out.appendSlice(gpa, "<dd>");
258 try render_docs(out, decl_index, first_doc_comment, false);257 try render_docs(out, decl_index, first_doc_comment, false);
259 try out.appendSlice(gpa, "</dd>");258 try out.appendSlice(gpa, "</dd>");
...@@ -319,17 +318,16 @@ fn addErrorsFromExpr(...@@ -319,17 +318,16 @@ fn addErrorsFromExpr(
319) Oom!void {318) Oom!void {
320 const decl = decl_index.get();319 const decl = decl_index.get();
321 const ast = decl.file.get_ast();320 const ast = decl.file.get_ast();
322 const node_tags = ast.nodes.items(.tag);
323 const node_datas = ast.nodes.items(.data);
324321
325 switch (decl.file.categorize_expr(node)) {322 switch (decl.file.categorize_expr(node)) {
326 .error_set => |n| switch (node_tags[n]) {323 .error_set => |n| switch (ast.nodeTag(n)) {
327 .error_set_decl => {324 .error_set_decl => {
328 try addErrorsFromNode(decl_index, out, node);325 try addErrorsFromNode(decl_index, out, node);
329 },326 },
330 .merge_error_sets => {327 .merge_error_sets => {
331 try addErrorsFromExpr(decl_index, out, node_datas[node].lhs);328 const lhs, const rhs = ast.nodeData(n).node_and_node;
332 try addErrorsFromExpr(decl_index, out, node_datas[node].rhs);329 try addErrorsFromExpr(decl_index, out, lhs);
330 try addErrorsFromExpr(decl_index, out, rhs);
333 },331 },
334 else => unreachable,332 else => unreachable,
335 },333 },
...@@ -347,11 +345,9 @@ fn addErrorsFromNode(...@@ -347,11 +345,9 @@ fn addErrorsFromNode(
347) Oom!void {345) Oom!void {
348 const decl = decl_index.get();346 const decl = decl_index.get();
349 const ast = decl.file.get_ast();347 const ast = decl.file.get_ast();
350 const main_tokens = ast.nodes.items(.main_token);348 const error_token = ast.nodeMainToken(node);
351 const token_tags = ast.tokens.items(.tag);
352 const error_token = main_tokens[node];
353 var tok_i = error_token + 2;349 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)) {
355 .doc_comment, .comma => {},351 .doc_comment, .comma => {},
356 .identifier => {352 .identifier => {
357 const name = ast.tokenSlice(tok_i);353 const name = ast.tokenSlice(tok_i);
...@@ -391,15 +387,13 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index {...@@ -391,15 +387,13 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index {
391387
392 switch (decl.categorize()) {388 switch (decl.categorize()) {
393 .type_function => {389 .type_function => {
394 const node_tags = ast.nodes.items(.tag);
395
396 // If the type function returns a reference to another type function, get the fields from there390 // If the type function returns a reference to another type function, get the fields from there
397 if (decl.get_type_fn_return_type_fn()) |function_decl| {391 if (decl.get_type_fn_return_type_fn()) |function_decl| {
398 return decl_fields_fallible(function_decl);392 return decl_fields_fallible(function_decl);
399 }393 }
400 // If the type function returns a container, such as a `struct`, read that container's fields394 // If the type function returns a container, such as a `struct`, read that container's fields
401 if (decl.get_type_fn_return_expr()) |return_expr| {395 if (decl.get_type_fn_return_expr()) |return_expr| {
402 switch (node_tags[return_expr]) {396 switch (ast.nodeTag(return_expr)) {
403 .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => {397 .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => {
404 return ast_decl_fields_fallible(ast, return_expr);398 return ast_decl_fields_fallible(ast, return_expr);
405 },399 },
...@@ -420,10 +414,9 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In...@@ -420,10 +414,9 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In
420 var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;414 var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;
421 };415 };
422 g.result.clearRetainingCapacity();416 g.result.clearRetainingCapacity();
423 const node_tags = ast.nodes.items(.tag);
424 var buf: [2]Ast.Node.Index = undefined;417 var buf: [2]Ast.Node.Index = undefined;
425 const container_decl = ast.fullContainerDecl(&buf, ast_index) orelse return &.{};418 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)) {
427 .container_field_init,420 .container_field_init,
428 .container_field_align,421 .container_field_align,
429 .container_field,422 .container_field,
...@@ -478,9 +471,8 @@ fn decl_field_html_fallible(...@@ -478,9 +471,8 @@ fn decl_field_html_fallible(
478 try out.appendSlice(gpa, "</code></pre>");471 try out.appendSlice(gpa, "</code></pre>");
479472
480 const field = ast.fullContainerField(field_node).?;473 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| {
484 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");476 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
485 try render_docs(out, decl_index, first_doc_comment, false);477 try render_docs(out, decl_index, first_doc_comment, false);
486 try out.appendSlice(gpa, "</div>");478 try out.appendSlice(gpa, "</div>");
...@@ -494,14 +486,13 @@ fn decl_param_html_fallible(...@@ -494,14 +486,13 @@ fn decl_param_html_fallible(
494) !void {486) !void {
495 const decl = decl_index.get();487 const decl = decl_index.get();
496 const ast = decl.file.get_ast();488 const ast = decl.file.get_ast();
497 const token_tags = ast.tokens.items(.tag);
498 const colon = ast.firstToken(param_node) - 1;489 const colon = ast.firstToken(param_node) - 1;
499 const name_token = colon - 1;490 const name_token = colon - 1;
500 const first_doc_comment = f: {491 const first_doc_comment = f: {
501 var it = ast.firstToken(param_node);492 var it = ast.firstToken(param_node);
502 while (it > 0) {493 while (it > 0) {
503 it -= 1;494 it -= 1;
504 switch (token_tags[it]) {495 switch (ast.tokenTag(it)) {
505 .doc_comment, .colon, .identifier, .keyword_comptime, .keyword_noalias => {},496 .doc_comment, .colon, .identifier, .keyword_comptime, .keyword_noalias => {},
506 else => break,497 else => break,
507 }498 }
...@@ -516,7 +507,7 @@ fn decl_param_html_fallible(...@@ -516,7 +507,7 @@ fn decl_param_html_fallible(
516 try fileSourceHtml(decl.file, out, param_node, .{});507 try fileSourceHtml(decl.file, out, param_node, .{});
517 try out.appendSlice(gpa, "</code></pre>");508 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) {
520 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");511 try out.appendSlice(gpa, "<div class=\"fieldDocs\">");
521 try render_docs(out, decl_index, first_doc_comment, false);512 try render_docs(out, decl_index, first_doc_comment, false);
522 try out.appendSlice(gpa, "</div>");513 try out.appendSlice(gpa, "</div>");
...@@ -526,10 +517,8 @@ fn decl_param_html_fallible(...@@ -526,10 +517,8 @@ fn decl_param_html_fallible(
526export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) String {517export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) String {
527 const decl = decl_index.get();518 const decl = decl_index.get();
528 const ast = decl.file.get_ast();519 const ast = decl.file.get_ast();
529 const node_tags = ast.nodes.items(.tag);520 const proto_node = switch (ast.nodeTag(decl.ast_node)) {
530 const node_datas = ast.nodes.items(.data);521 .fn_decl => ast.nodeData(decl.ast_node).node_and_node[0],
531 const proto_node = switch (node_tags[decl.ast_node]) {
532 .fn_decl => node_datas[decl.ast_node].lhs,
533522
534 .fn_proto,523 .fn_proto,
535 .fn_proto_one,524 .fn_proto_one,
...@@ -586,17 +575,16 @@ export fn decl_parent(decl_index: Decl.Index) Decl.Index {...@@ -586,17 +575,16 @@ export fn decl_parent(decl_index: Decl.Index) Decl.Index {
586 return decl.parent;575 return decl.parent;
587}576}
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 {
590 const decl = decl_index.get();579 const decl = decl_index.get();
591 const ast = decl.file.get_ast();580 const ast = decl.file.get_ast();
592 var buf: [1]Ast.Node.Index = undefined;581 var buf: [1]Ast.Node.Index = undefined;
593 const full = ast.fullFnProto(&buf, decl.ast_node).?;582 const full = ast.fullFnProto(&buf, decl.ast_node).?;
594 const node_tags = ast.nodes.items(.tag);583 const return_type = full.ast.return_type.unwrap().?;
595 const node_datas = ast.nodes.items(.data);584 return switch (ast.nodeTag(return_type)) {
596 return switch (node_tags[full.ast.return_type]) {585 .error_set_decl => return_type.toOptional(),
597 .error_set_decl => full.ast.return_type,586 .error_union => ast.nodeData(return_type).node_and_node[0].toOptional(),
598 .error_union => node_datas[full.ast.return_type].lhs,587 else => .none,
599 else => 0,
600 };588 };
601}589}
602590
...@@ -609,21 +597,19 @@ export fn decl_file_path(decl_index: Decl.Index) String {...@@ -609,21 +597,19 @@ export fn decl_file_path(decl_index: Decl.Index) String {
609export fn decl_category_name(decl_index: Decl.Index) String {597export fn decl_category_name(decl_index: Decl.Index) String {
610 const decl = decl_index.get();598 const decl = decl_index.get();
611 const ast = decl.file.get_ast();599 const ast = decl.file.get_ast();
612 const token_tags = ast.tokens.items(.tag);
613 const name = switch (decl.categorize()) {600 const name = switch (decl.categorize()) {
614 .namespace, .container => |node| {601 .namespace, .container => |node| {
615 const node_tags = ast.nodes.items(.tag);602 if (ast.nodeTag(decl.ast_node) == .root)
616 if (node_tags[decl.ast_node] == .root)
617 return String.init("struct");603 return String.init("struct");
618 string_result.clearRetainingCapacity();604 string_result.clearRetainingCapacity();
619 var buf: [2]Ast.Node.Index = undefined;605 var buf: [2]Ast.Node.Index = undefined;
620 const container_decl = ast.fullContainerDecl(&buf, node).?;606 const container_decl = ast.fullContainerDecl(&buf, node).?;
621 if (container_decl.layout_token) |t| {607 if (container_decl.layout_token) |t| {
622 if (token_tags[t] == .keyword_extern) {608 if (ast.tokenTag(t) == .keyword_extern) {
623 string_result.appendSlice(gpa, "extern ") catch @panic("OOM");609 string_result.appendSlice(gpa, "extern ") catch @panic("OOM");
624 }610 }
625 }611 }
626 const main_token_tag = token_tags[container_decl.ast.main_token];612 const main_token_tag = ast.tokenTag(container_decl.ast.main_token);
627 string_result.appendSlice(gpa, main_token_tag.lexeme().?) catch @panic("OOM");613 string_result.appendSlice(gpa, main_token_tag.lexeme().?) catch @panic("OOM");
628 return String.init(string_result.items);614 return String.init(string_result.items);
629 },615 },
...@@ -656,7 +642,9 @@ export fn decl_name(decl_index: Decl.Index) String {...@@ -656,7 +642,9 @@ export fn decl_name(decl_index: Decl.Index) String {
656export fn decl_docs_html(decl_index: Decl.Index, short: bool) String {642export fn decl_docs_html(decl_index: Decl.Index, short: bool) String {
657 const decl = decl_index.get();643 const decl = decl_index.get();
658 string_result.clearRetainingCapacity();644 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 }
660 return String.init(string_result.items);648 return String.init(string_result.items);
661}649}
662650
...@@ -665,10 +653,9 @@ fn collect_docs(...@@ -665,10 +653,9 @@ fn collect_docs(
665 ast: *const Ast,653 ast: *const Ast,
666 first_doc_comment: Ast.TokenIndex,654 first_doc_comment: Ast.TokenIndex,
667) Oom!void {655) Oom!void {
668 const token_tags = ast.tokens.items(.tag);
669 list.clearRetainingCapacity();656 list.clearRetainingCapacity();
670 var it = first_doc_comment;657 var it = first_doc_comment;
671 while (true) : (it += 1) switch (token_tags[it]) {658 while (true) : (it += 1) switch (ast.tokenTag(it)) {
672 .doc_comment, .container_doc_comment => {659 .doc_comment, .container_doc_comment => {
673 // It is tempting to trim this string but think carefully about how660 // It is tempting to trim this string but think carefully about how
674 // that will affect the markdown parser.661 // that will affect the markdown parser.
...@@ -687,12 +674,11 @@ fn render_docs(...@@ -687,12 +674,11 @@ fn render_docs(
687) Oom!void {674) Oom!void {
688 const decl = decl_index.get();675 const decl = decl_index.get();
689 const ast = decl.file.get_ast();676 const ast = decl.file.get_ast();
690 const token_tags = ast.tokens.items(.tag);
691677
692 var parser = try markdown.Parser.init(gpa);678 var parser = try markdown.Parser.init(gpa);
693 defer parser.deinit();679 defer parser.deinit();
694 var it = first_doc_comment;680 var it = first_doc_comment;
695 while (true) : (it += 1) switch (token_tags[it]) {681 while (true) : (it += 1) switch (ast.tokenTag(it)) {
696 .doc_comment, .container_doc_comment => {682 .doc_comment, .container_doc_comment => {
697 const line = ast.tokenSlice(it)[3..];683 const line = ast.tokenSlice(it)[3..];
698 if (short and line.len == 0) break;684 if (short and line.len == 0) break;
...@@ -767,9 +753,9 @@ export fn decl_type_html(decl_index: Decl.Index) String {...@@ -767,9 +753,9 @@ export fn decl_type_html(decl_index: Decl.Index) String {
767 t: {753 t: {
768 // If there is an explicit type, use it.754 // If there is an explicit type, use it.
769 if (ast.fullVarDecl(decl.ast_node)) |var_decl| {755 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| {
771 string_result.appendSlice(gpa, "<code>") catch @panic("OOM");757 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, .{
773 .skip_comments = true,759 .skip_comments = true,
774 .collapse_whitespace = true,760 .collapse_whitespace = true,
775 }) catch |e| {761 }) catch |e| {
lib/std/zig/Ast.zig+1681-1229
...@@ -8,15 +8,12 @@...@@ -8,15 +8,12 @@
8source: [:0]const u8,8source: [:0]const u8,
99
10tokens: TokenList.Slice,10tokens: 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.
13nodes: NodeList.Slice,11nodes: NodeList.Slice,
14extra_data: []Node.Index,12extra_data: []u32,
15mode: Mode = .zig,13mode: Mode = .zig,
1614
17errors: []const Error,15errors: []const Error,
1816
19pub const TokenIndex = u32;
20pub const ByteOffset = u32;17pub const ByteOffset = u32;
2118
22pub const TokenList = std.MultiArrayList(struct {19pub const TokenList = std.MultiArrayList(struct {
...@@ -25,6 +22,91 @@ pub const TokenList = std.MultiArrayList(struct {...@@ -25,6 +22,91 @@ pub const TokenList = std.MultiArrayList(struct {
25});22});
26pub const NodeList = std.MultiArrayList(Node);23pub 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
28pub const Location = struct {110pub const Location = struct {
29 line: usize,111 line: usize,
30 column: usize,112 column: usize,
...@@ -77,8 +159,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A...@@ -77,8 +159,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A
77 var parser: Parse = .{159 var parser: Parse = .{
78 .source = source,160 .source = source,
79 .gpa = gpa,161 .gpa = gpa,
80 .token_tags = tokens.items(.tag),162 .tokens = tokens.slice(),
81 .token_starts = tokens.items(.start),
82 .errors = .{},163 .errors = .{},
83 .nodes = .{},164 .nodes = .{},
84 .extra_data = .{},165 .extra_data = .{},
...@@ -143,7 +224,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde...@@ -143,7 +224,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde
143 .line_start = start_offset,224 .line_start = start_offset,
144 .line_end = self.source.len,225 .line_end = self.source.len,
145 };226 };
146 const token_start = self.tokens.items(.start)[token_index];227 const token_start = self.tokenStart(token_index);
147228
148 // Scan to by line until we go past the token start229 // Scan to by line until we go past the token start
149 while (std.mem.indexOfScalarPos(u8, self.source, loc.line_start, '\n')) |i| {230 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...@@ -175,9 +256,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde
175}256}
176257
177pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {258pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {
178 const token_starts = tree.tokens.items(.start);259 const token_tag = tree.tokenTag(token_index);
179 const token_tags = tree.tokens.items(.tag);
180 const token_tag = token_tags[token_index];
181260
182 // Many tokens can be determined entirely by their tag.261 // Many tokens can be determined entirely by their tag.
183 if (token_tag.lexeme()) |lexeme| {262 if (token_tag.lexeme()) |lexeme| {
...@@ -187,33 +266,54 @@ pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {...@@ -187,33 +266,54 @@ pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 {
187 // For some tokens, re-tokenization is needed to find the end.266 // For some tokens, re-tokenization is needed to find the end.
188 var tokenizer: std.zig.Tokenizer = .{267 var tokenizer: std.zig.Tokenizer = .{
189 .buffer = tree.source,268 .buffer = tree.source,
190 .index = token_starts[token_index],269 .index = tree.tokenStart(token_index),
191 };270 };
192 const token = tokenizer.next();271 const token = tokenizer.next();
193 assert(token.tag == token_tag);272 assert(token.tag == token_tag);
194 return tree.source[token.loc.start..token.loc.end];273 return tree.source[token.loc.start..token.loc.end];
195}274}
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 {
198 const fields = std.meta.fields(T);285 const fields = std.meta.fields(T);
199 var result: T = undefined;286 var result: T = undefined;
200 inline for (fields, 0..) |field, i| {287 inline for (fields, 0..) |field, i| {
201 comptime assert(field.type == Node.Index);288 @field(result, field.name) = switch (field.type) {
202 @field(result, field.name) = tree.extra_data[index + i];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 };
203 }297 }
204 return result;298 return result;
205}299}
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
207pub fn rootDecls(tree: Ast) []const Node.Index {308pub fn rootDecls(tree: Ast) []const Node.Index {
208 const nodes_data = tree.nodes.items(.data);309 switch (tree.mode) {
209 return switch (tree.mode) {310 .zig => return tree.extraDataSlice(tree.nodeData(.root).extra_range, Node.Index),
210 .zig => tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs],311 // Ensure that the returned slice points into the existing memory of the Ast
211 .zon => (&nodes_data[0].lhs)[0..1],312 .zon => return (&tree.nodes.items(.data)[@intFromEnum(Node.Index.root)].node)[0..1],
212 };313 }
213}314}
214315
215pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {316pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
216 const token_tags = tree.tokens.items(.tag);
217 switch (parse_error.tag) {317 switch (parse_error.tag) {
218 .asterisk_after_ptr_deref => {318 .asterisk_after_ptr_deref => {
219 // Note that the token will point at the `.*` but ideally the source319 // 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 {...@@ -228,72 +328,72 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
228 },328 },
229 .expected_block => {329 .expected_block => {
230 return stream.print("expected block, found '{s}'", .{330 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(),
232 });332 });
233 },333 },
234 .expected_block_or_assignment => {334 .expected_block_or_assignment => {
235 return stream.print("expected block or assignment, found '{s}'", .{335 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(),
237 });337 });
238 },338 },
239 .expected_block_or_expr => {339 .expected_block_or_expr => {
240 return stream.print("expected block or expression, found '{s}'", .{340 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(),
242 });342 });
243 },343 },
244 .expected_block_or_field => {344 .expected_block_or_field => {
245 return stream.print("expected block or field, found '{s}'", .{345 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(),
247 });347 });
248 },348 },
249 .expected_container_members => {349 .expected_container_members => {
250 return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{350 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(),
252 });352 });
253 },353 },
254 .expected_expr => {354 .expected_expr => {
255 return stream.print("expected expression, found '{s}'", .{355 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(),
257 });357 });
258 },358 },
259 .expected_expr_or_assignment => {359 .expected_expr_or_assignment => {
260 return stream.print("expected expression or assignment, found '{s}'", .{360 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(),
262 });362 });
263 },363 },
264 .expected_expr_or_var_decl => {364 .expected_expr_or_var_decl => {
265 return stream.print("expected expression or var decl, found '{s}'", .{365 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(),
267 });367 });
268 },368 },
269 .expected_fn => {369 .expected_fn => {
270 return stream.print("expected function, found '{s}'", .{370 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(),
272 });372 });
273 },373 },
274 .expected_inlinable => {374 .expected_inlinable => {
275 return stream.print("expected 'while' or 'for', found '{s}'", .{375 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(),
277 });377 });
278 },378 },
279 .expected_labelable => {379 .expected_labelable => {
280 return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{380 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(),
282 });382 });
283 },383 },
284 .expected_param_list => {384 .expected_param_list => {
285 return stream.print("expected parameter list, found '{s}'", .{385 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(),
287 });387 });
288 },388 },
289 .expected_prefix_expr => {389 .expected_prefix_expr => {
290 return stream.print("expected prefix expression, found '{s}'", .{390 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(),
292 });392 });
293 },393 },
294 .expected_primary_type_expr => {394 .expected_primary_type_expr => {
295 return stream.print("expected primary type expression, found '{s}'", .{395 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(),
297 });397 });
298 },398 },
299 .expected_pub_item => {399 .expected_pub_item => {
...@@ -301,7 +401,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -301,7 +401,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
301 },401 },
302 .expected_return_type => {402 .expected_return_type => {
303 return stream.print("expected return type expression, found '{s}'", .{403 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(),
305 });405 });
306 },406 },
307 .expected_semi_or_else => {407 .expected_semi_or_else => {
...@@ -312,37 +412,37 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -312,37 +412,37 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
312 },412 },
313 .expected_statement => {413 .expected_statement => {
314 return stream.print("expected statement, found '{s}'", .{414 return stream.print("expected statement, found '{s}'", .{
315 token_tags[parse_error.token].symbol(),415 tree.tokenTag(parse_error.token).symbol(),
316 });416 });
317 },417 },
318 .expected_suffix_op => {418 .expected_suffix_op => {
319 return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{419 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(),
321 });421 });
322 },422 },
323 .expected_type_expr => {423 .expected_type_expr => {
324 return stream.print("expected type expression, found '{s}'", .{424 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(),
326 });426 });
327 },427 },
328 .expected_var_decl => {428 .expected_var_decl => {
329 return stream.print("expected variable declaration, found '{s}'", .{429 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(),
331 });431 });
332 },432 },
333 .expected_var_decl_or_fn => {433 .expected_var_decl_or_fn => {
334 return stream.print("expected variable declaration or function, found '{s}'", .{434 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(),
336 });436 });
337 },437 },
338 .expected_loop_payload => {438 .expected_loop_payload => {
339 return stream.print("expected loop payload, found '{s}'", .{439 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(),
341 });441 });
342 },442 },
343 .expected_container => {443 .expected_container => {
344 return stream.print("expected a struct, enum or union, found '{s}'", .{444 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(),
346 });446 });
347 },447 },
348 .extern_fn_body => {448 .extern_fn_body => {
...@@ -365,7 +465,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -365,7 +465,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
365 },465 },
366 .ptr_mod_on_array_child_type => {466 .ptr_mod_on_array_child_type => {
367 return stream.print("pointer modifier '{s}' not allowed on array child type", .{467 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(),
369 });469 });
370 },470 },
371 .invalid_bit_range => {471 .invalid_bit_range => {
...@@ -421,7 +521,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -421,7 +521,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
421 return stream.writeAll("expected field initializer");521 return stream.writeAll("expected field initializer");
422 },522 },
423 .mismatched_binary_op_whitespace => {523 .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().?});
425 },525 },
426 .invalid_ampersand_ampersand => {526 .invalid_ampersand_ampersand => {
427 return stream.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND");527 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 {...@@ -472,7 +572,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
472 },572 },
473573
474 .expected_token => {574 .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));
476 const expected_symbol = parse_error.extra.expected_tag.symbol();576 const expected_symbol = parse_error.extra.expected_tag.symbol();
477 switch (found_tag) {577 switch (found_tag) {
478 .invalid => return stream.print("expected '{s}', found invalid bytes", .{578 .invalid => return stream.print("expected '{s}', found invalid bytes", .{
...@@ -487,13 +587,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -487,13 +587,9 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
487}587}
488588
489pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {589pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
490 const tags = tree.nodes.items(.tag);590 var end_offset: u32 = 0;
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;
495 var n = node;591 var n = node;
496 while (true) switch (tags[n]) {592 while (true) switch (tree.nodeTag(n)) {
497 .root => return 0,593 .root => return 0,
498594
499 .test_decl,595 .test_decl,
...@@ -537,7 +633,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -537,7 +633,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
537 .array_type,633 .array_type,
538 .array_type_sentinel,634 .array_type_sentinel,
539 .error_value,635 .error_value,
540 => return main_tokens[n] - end_offset,636 => return tree.nodeMainToken(n) - end_offset,
541637
542 .array_init_dot,638 .array_init_dot,
543 .array_init_dot_comma,639 .array_init_dot_comma,
...@@ -548,11 +644,9 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -548,11 +644,9 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
548 .struct_init_dot_two,644 .struct_init_dot_two,
549 .struct_init_dot_two_comma,645 .struct_init_dot_two_comma,
550 .enum_literal,646 .enum_literal,
551 => return main_tokens[n] - 1 - end_offset,647 => return tree.nodeMainToken(n) - 1 - end_offset,
552648
553 .@"catch",649 .@"catch",
554 .field_access,
555 .unwrap_optional,
556 .equal_equal,650 .equal_equal,
557 .bang_equal,651 .bang_equal,
558 .less_than,652 .less_than,
...@@ -601,33 +695,37 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -601,33 +695,37 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
601 .bool_and,695 .bool_and,
602 .bool_or,696 .bool_or,
603 .slice_open,697 .slice_open,
604 .slice,
605 .slice_sentinel,
606 .deref,
607 .array_access,698 .array_access,
608 .array_init_one,699 .array_init_one,
609 .array_init_one_comma,700 .array_init_one_comma,
610 .array_init,701 .switch_range,
611 .array_init_comma,702 .error_union,
703 => n = tree.nodeData(n).node_and_node[0],
704
705 .for_range,
706 .call_one,
707 .call_one_comma,
612 .struct_init_one,708 .struct_init_one,
613 .struct_init_one_comma,709 .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,
614 .struct_init,720 .struct_init,
615 .struct_init_comma,721 .struct_init_comma,
616 .call_one,
617 .call_one_comma,
618 .call,722 .call,
619 .call_comma,723 .call_comma,
620 .switch_range,724 => n = tree.nodeData(n).node_and_extra[0],
621 .for_range,
622 .error_union,
623 => n = datas[n].lhs,
624725
625 .assign_destructure => {726 .deref => n = tree.nodeData(n).node,
626 const extra_idx = datas[n].lhs;727
627 const lhs_len = tree.extra_data[extra_idx];728 .assign_destructure => n = tree.assignDestructure(n).ast.variables[0],
628 assert(lhs_len > 0);
629 n = tree.extra_data[extra_idx + 1];
630 },
631729
632 .fn_decl,730 .fn_decl,
633 .fn_proto_simple,731 .fn_proto_simple,
...@@ -635,10 +733,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -635,10 +733,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
635 .fn_proto_one,733 .fn_proto_one,
636 .fn_proto,734 .fn_proto,
637 => {735 => {
638 var i = main_tokens[n]; // fn token736 var i = tree.nodeMainToken(n); // fn token
639 while (i > 0) {737 while (i > 0) {
640 i -= 1;738 i -= 1;
641 switch (token_tags[i]) {739 switch (tree.tokenTag(i)) {
642 .keyword_extern,740 .keyword_extern,
643 .keyword_export,741 .keyword_export,
644 .keyword_pub,742 .keyword_pub,
...@@ -654,30 +752,33 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -654,30 +752,33 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
654 },752 },
655753
656 .@"usingnamespace" => {754 .@"usingnamespace" => {
657 const main_token = main_tokens[n];755 const main_token: TokenIndex = tree.nodeMainToken(n);
658 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {756 const has_visib_token = tree.isTokenPrecededByTags(main_token, &.{.keyword_pub});
659 end_offset += 1;757 end_offset += @intFromBool(has_visib_token);
660 }
661 return main_token - end_offset;758 return main_token - end_offset;
662 },759 },
663760
664 .async_call_one,761 .async_call_one,
665 .async_call_one_comma,762 .async_call_one_comma,
763 => {
764 end_offset += 1; // async token
765 n = tree.nodeData(n).node_and_opt_node[0];
766 },
767
666 .async_call,768 .async_call,
667 .async_call_comma,769 .async_call_comma,
668 => {770 => {
669 end_offset += 1; // async token771 end_offset += 1; // async token
670 n = datas[n].lhs;772 n = tree.nodeData(n).node_and_extra[0];
671 },773 },
672774
673 .container_field_init,775 .container_field_init,
674 .container_field_align,776 .container_field_align,
675 .container_field,777 .container_field,
676 => {778 => {
677 const name_token = main_tokens[n];779 const name_token = tree.nodeMainToken(n);
678 if (name_token > 0 and token_tags[name_token - 1] == .keyword_comptime) {780 const has_comptime_token = tree.isTokenPrecededByTags(name_token, &.{.keyword_comptime});
679 end_offset += 1;781 end_offset += @intFromBool(has_comptime_token);
680 }
681 return name_token - end_offset;782 return name_token - end_offset;
682 },783 },
683784
...@@ -686,10 +787,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -686,10 +787,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
686 .simple_var_decl,787 .simple_var_decl,
687 .aligned_var_decl,788 .aligned_var_decl,
688 => {789 => {
689 var i = main_tokens[n]; // mut token790 var i = tree.nodeMainToken(n); // mut token
690 while (i > 0) {791 while (i > 0) {
691 i -= 1;792 i -= 1;
692 switch (token_tags[i]) {793 switch (tree.tokenTag(i)) {
693 .keyword_extern,794 .keyword_extern,
694 .keyword_export,795 .keyword_export,
695 .keyword_comptime,796 .keyword_comptime,
...@@ -710,10 +811,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -710,10 +811,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
710 .block_two_semicolon,811 .block_two_semicolon,
711 => {812 => {
712 // Look for a label.813 // Look for a label.
713 const lbrace = main_tokens[n];814 const lbrace = tree.nodeMainToken(n);
714 if (token_tags[lbrace - 1] == .colon and815 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
715 token_tags[lbrace - 2] == .identifier)
716 {
717 end_offset += 2;816 end_offset += 2;
718 }817 }
719 return lbrace - end_offset;818 return lbrace - end_offset;
...@@ -732,8 +831,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -732,8 +831,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
732 .tagged_union_enum_tag,831 .tagged_union_enum_tag,
733 .tagged_union_enum_tag_trailing,832 .tagged_union_enum_tag_trailing,
734 => {833 => {
735 const main_token = main_tokens[n];834 const main_token = tree.nodeMainToken(n);
736 switch (token_tags[main_token -| 1]) {835 switch (tree.tokenTag(main_token -| 1)) {
737 .keyword_packed, .keyword_extern => end_offset += 1,836 .keyword_packed, .keyword_extern => end_offset += 1,
738 else => {},837 else => {},
739 }838 }
...@@ -744,36 +843,26 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -744,36 +843,26 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
744 .ptr_type_sentinel,843 .ptr_type_sentinel,
745 .ptr_type,844 .ptr_type,
746 .ptr_type_bit_range,845 .ptr_type_bit_range,
747 => return main_tokens[n] - end_offset,846 => return tree.nodeMainToken(n) - end_offset,
748847
749 .switch_case_one => {848 .switch_case_one,
750 if (datas[n].lhs == 0) {849 .switch_case_inline_one,
751 return main_tokens[n] - 1 - end_offset; // else token850 .switch_case,
752 } else {851 .switch_case_inline,
753 n = datas[n].lhs;852 => {
754 }853 const full_switch = tree.fullSwitchCase(n).?;
755 },854 if (full_switch.inline_token) |inline_token| {
756 .switch_case_inline_one => {855 return inline_token;
757 if (datas[n].lhs == 0) {856 } else if (full_switch.ast.values.len == 0) {
758 return main_tokens[n] - 2 - end_offset; // else token857 return full_switch.ast.arrow_token - 1 - end_offset; // else token
759 } else {858 } else {
760 return firstToken(tree, datas[n].lhs) - 1;859 n = full_switch.ast.values[0];
761 }860 }
762 },861 },
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
774 .asm_output, .asm_input => {863 .asm_output, .asm_input => {
775 assert(token_tags[main_tokens[n] - 1] == .l_bracket);864 assert(tree.tokenTag(tree.nodeMainToken(n) - 1) == .l_bracket);
776 return main_tokens[n] - 1 - end_offset;865 return tree.nodeMainToken(n) - 1 - end_offset;
777 },866 },
778867
779 .while_simple,868 .while_simple,
...@@ -783,13 +872,13 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -783,13 +872,13 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
783 .@"for",872 .@"for",
784 => {873 => {
785 // Look for a label and inline.874 // Look for a label and inline.
786 const main_token = main_tokens[n];875 const main_token = tree.nodeMainToken(n);
787 var result = main_token;876 var result = main_token;
788 if (token_tags[result -| 1] == .keyword_inline) {877 if (tree.isTokenPrecededByTags(result, &.{.keyword_inline})) {
789 result -= 1;878 result = result - 1;
790 }879 }
791 if (token_tags[result -| 1] == .colon) {880 if (tree.isTokenPrecededByTags(result, &.{ .identifier, .colon })) {
792 result -|= 2;881 result = result - 2;
793 }882 }
794 return result - end_offset;883 return result - end_offset;
795 },884 },
...@@ -797,15 +886,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -797,15 +886,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
797}886}
798887
799pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {888pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
800 const tags = tree.nodes.items(.tag);
801 const datas = tree.nodes.items(.data);
802 const main_tokens = tree.nodes.items(.main_token);
803 const token_starts = tree.tokens.items(.start);
804 const token_tags = tree.tokens.items(.tag);
805 var n = node;889 var n = node;
806 var end_offset: TokenIndex = 0;890 var end_offset: u32 = 0;
807 while (true) switch (tags[n]) {891 while (true) switch (tree.nodeTag(n)) {
808 .root => return @as(TokenIndex, @intCast(tree.tokens.len - 1)),892 .root => return @intCast(tree.tokens.len - 1),
809893
810 .@"usingnamespace",894 .@"usingnamespace",
811 .bool_not,895 .bool_not,
...@@ -816,14 +900,12 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -816,14 +900,12 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
816 .@"try",900 .@"try",
817 .@"await",901 .@"await",
818 .optional_type,902 .optional_type,
903 .@"suspend",
819 .@"resume",904 .@"resume",
820 .@"nosuspend",905 .@"nosuspend",
821 .@"comptime",906 .@"comptime",
822 => n = datas[n].lhs,907 => n = tree.nodeData(n).node,
823908
824 .test_decl,
825 .@"errdefer",
826 .@"defer",
827 .@"catch",909 .@"catch",
828 .equal_equal,910 .equal_equal,
829 .bang_equal,911 .bang_equal,
...@@ -849,7 +931,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -849,7 +931,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
849 .assign_add_sat,931 .assign_add_sat,
850 .assign_sub_sat,932 .assign_sub_sat,
851 .assign,933 .assign,
852 .assign_destructure,
853 .merge_error_sets,934 .merge_error_sets,
854 .mul,935 .mul,
855 .div,936 .div,
...@@ -873,41 +954,52 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -873,41 +954,52 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
873 .@"orelse",954 .@"orelse",
874 .bool_and,955 .bool_and,
875 .bool_or,956 .bool_or,
876 .anyframe_type,
877 .error_union,957 .error_union,
878 .if_simple,958 .if_simple,
879 .while_simple,959 .while_simple,
880 .for_simple,960 .for_simple,
881 .fn_proto_simple,961 .fn_decl,
882 .fn_proto_multi,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,
883 .ptr_type_aligned,972 .ptr_type_aligned,
884 .ptr_type_sentinel,973 .ptr_type_sentinel,
974 => n = tree.nodeData(n).opt_node_and_node[1],
975
976 .assign_destructure,
885 .ptr_type,977 .ptr_type,
886 .ptr_type_bit_range,978 .ptr_type_bit_range,
887 .array_type,
888 .switch_case_one,
889 .switch_case_inline_one,
890 .switch_case,979 .switch_case,
891 .switch_case_inline,980 .switch_case_inline,
892 .switch_range,981 => n = tree.nodeData(n).extra_and_node[1],
893 => n = datas[n].rhs,
894982
895 .for_range => if (datas[n].rhs != 0) {983 .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?,
896 n = datas[n].rhs;984 .fn_proto_multi,
897 } else {985 .fn_proto_one,
898 return main_tokens[n] + end_offset;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 };
899 },993 },
900994
901 .field_access,995 .field_access,
902 .unwrap_optional,996 .unwrap_optional,
903 .grouped_expression,
904 .multiline_string_literal,
905 .error_set_decl,
906 .asm_simple,997 .asm_simple,
907 .asm_output,998 => return tree.nodeData(n).node_and_token[1] + end_offset,
908 .asm_input,999 .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset,
909 .error_value,1000 .multiline_string_literal, .error_set_decl => return tree.nodeData(n).token_and_token[1] + end_offset,
910 => return datas[n].rhs + end_offset,1001 .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset,
1002 .error_value => return tree.nodeMainToken(n) + 2 + end_offset,
9111003
912 .anyframe_literal,1004 .anyframe_literal,
913 .char_literal,1005 .char_literal,
...@@ -917,82 +1009,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -917,82 +1009,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
917 .deref,1009 .deref,
918 .enum_literal,1010 .enum_literal,
919 .string_literal,1011 .string_literal,
920 => return main_tokens[n] + end_offset,1012 => return tree.nodeMainToken(n) + end_offset,
9211013
922 .@"return" => if (datas[n].lhs != 0) {1014 .@"return" => {
923 n = datas[n].lhs;1015 n = tree.nodeData(n).opt_node.unwrap() orelse {
924 } else {1016 return tree.nodeMainToken(n) + end_offset;
925 return main_tokens[n] + end_offset;1017 };
926 },1018 },
9271019
928 .call, .async_call => {1020 .call, .async_call => {
1021 _, const extra_index = tree.nodeData(n).node_and_extra;
1022 const params = tree.extraData(extra_index, Node.SubRange);
1023 assert(params.start != params.end);
929 end_offset += 1; // for the rparen1024 end_offset += 1; // for the rparen
930 const params = tree.extraData(datas[n].rhs, Node.SubRange);1025 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
931 if (params.end - params.start == 0) {
932 return main_tokens[n] + end_offset;
933 }
934 n = tree.extra_data[params.end - 1]; // last parameter
935 },1026 },
936 .tagged_union_enum_tag => {1027 .tagged_union_enum_tag => {
937 const members = tree.extraData(datas[n].rhs, Node.SubRange);1028 const arg, const extra_index = tree.nodeData(n).node_and_extra;
938 if (members.end - members.start == 0) {1029 const members = tree.extraData(extra_index, Node.SubRange);
1030 if (members.start == members.end) {
939 end_offset += 4; // for the rparen + rparen + lbrace + rbrace1031 end_offset += 4; // for the rparen + rparen + lbrace + rbrace
940 n = datas[n].lhs;1032 n = arg;
941 } else {1033 } else {
942 end_offset += 1; // for the rbrace1034 end_offset += 1; // for the rbrace
943 n = tree.extra_data[members.end - 1]; // last parameter1035 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
944 }1036 }
945 },1037 },
946 .call_comma,1038 .call_comma,
947 .async_call_comma,1039 .async_call_comma,
948 .tagged_union_enum_tag_trailing,1040 .tagged_union_enum_tag_trailing,
949 => {1041 => {
1042 _, const extra_index = tree.nodeData(n).node_and_extra;
1043 const params = tree.extraData(extra_index, Node.SubRange);
1044 assert(params.start != params.end);
950 end_offset += 2; // for the comma/semicolon + rparen/rbrace1045 end_offset += 2; // for the comma/semicolon + rparen/rbrace
951 const params = tree.extraData(datas[n].rhs, Node.SubRange);1046 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
952 assert(params.end > params.start);
953 n = tree.extra_data[params.end - 1]; // last parameter
954 },1047 },
955 .@"switch" => {1048 .@"switch" => {
956 const cases = tree.extraData(datas[n].rhs, Node.SubRange);1049 const condition, const extra_index = tree.nodeData(n).node_and_extra;
957 if (cases.end - cases.start == 0) {1050 const cases = tree.extraData(extra_index, Node.SubRange);
1051 if (cases.start == cases.end) {
958 end_offset += 3; // rparen, lbrace, rbrace1052 end_offset += 3; // rparen, lbrace, rbrace
959 n = datas[n].lhs; // condition expression1053 n = condition;
960 } else {1054 } else {
961 end_offset += 1; // for the rbrace1055 end_offset += 1; // for the rbrace
962 n = tree.extra_data[cases.end - 1]; // last case1056 n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case
963 }1057 }
964 },1058 },
965 .container_decl_arg => {1059 .container_decl_arg => {
966 const members = tree.extraData(datas[n].rhs, Node.SubRange);1060 const arg, const extra_index = tree.nodeData(n).node_and_extra;
967 if (members.end - members.start == 0) {1061 const members = tree.extraData(extra_index, Node.SubRange);
1062 if (members.end == members.start) {
968 end_offset += 3; // for the rparen + lbrace + rbrace1063 end_offset += 3; // for the rparen + lbrace + rbrace
969 n = datas[n].lhs;1064 n = arg;
970 } else {1065 } else {
971 end_offset += 1; // for the rbrace1066 end_offset += 1; // for the rbrace
972 n = tree.extra_data[members.end - 1]; // last parameter1067 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
973 }1068 }
974 },1069 },
975 .@"asm" => {1070 .@"asm" => {
976 const extra = tree.extraData(datas[n].rhs, Node.Asm);1071 _, const extra_index = tree.nodeData(n).node_and_extra;
1072 const extra = tree.extraData(extra_index, Node.Asm);
977 return extra.rparen + end_offset;1073 return extra.rparen + end_offset;
978 },1074 },
979 .array_init,1075 .array_init,
980 .struct_init,1076 .struct_init,
981 => {1077 => {
982 const elements = tree.extraData(datas[n].rhs, Node.SubRange);1078 _, const extra_index = tree.nodeData(n).node_and_extra;
983 assert(elements.end - elements.start > 0);1079 const elements = tree.extraData(extra_index, Node.SubRange);
1080 assert(elements.start != elements.end);
984 end_offset += 1; // for the rbrace1081 end_offset += 1; // for the rbrace
985 n = tree.extra_data[elements.end - 1]; // last element1082 n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element
986 },1083 },
987 .array_init_comma,1084 .array_init_comma,
988 .struct_init_comma,1085 .struct_init_comma,
989 .container_decl_arg_trailing,1086 .container_decl_arg_trailing,
990 .switch_comma,1087 .switch_comma,
991 => {1088 => {
992 const members = tree.extraData(datas[n].rhs, Node.SubRange);1089 _, const extra_index = tree.nodeData(n).node_and_extra;
993 assert(members.end - members.start > 0);1090 const members = tree.extraData(extra_index, Node.SubRange);
1091 assert(members.start != members.end);
994 end_offset += 2; // for the comma + rbrace1092 end_offset += 2; // for the comma + rbrace
995 n = tree.extra_data[members.end - 1]; // last parameter1093 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
996 },1094 },
997 .array_init_dot,1095 .array_init_dot,
998 .struct_init_dot,1096 .struct_init_dot,
...@@ -1001,9 +1099,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1001,9 +1099,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1001 .tagged_union,1099 .tagged_union,
1002 .builtin_call,1100 .builtin_call,
1003 => {1101 => {
1004 assert(datas[n].rhs - datas[n].lhs > 0);1102 const range = tree.nodeData(n).extra_range;
1103 assert(range.start != range.end);
1005 end_offset += 1; // for the rbrace1104 end_offset += 1; // for the rbrace
1006 n = tree.extra_data[datas[n].rhs - 1]; // last statement1105 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement
1007 },1106 },
1008 .array_init_dot_comma,1107 .array_init_dot_comma,
1009 .struct_init_dot_comma,1108 .struct_init_dot_comma,
...@@ -1012,20 +1111,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1012,20 +1111,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1012 .tagged_union_trailing,1111 .tagged_union_trailing,
1013 .builtin_call_comma,1112 .builtin_call_comma,
1014 => {1113 => {
1015 assert(datas[n].rhs - datas[n].lhs > 0);1114 const range = tree.nodeData(n).extra_range;
1115 assert(range.start != range.end);
1016 end_offset += 2; // for the comma/semicolon + rbrace/rparen1116 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1017 n = tree.extra_data[datas[n].rhs - 1]; // last member1117 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
1018 },1118 },
1019 .call_one,1119 .call_one,
1020 .async_call_one,1120 .async_call_one,
1021 .array_access,
1022 => {1121 => {
1023 end_offset += 1; // for the rparen/rbracket1122 _, const first_param = tree.nodeData(n).node_and_opt_node;
1024 if (datas[n].rhs == 0) {1123 end_offset += 1; // for the rparen
1025 return main_tokens[n] + end_offset;1124 n = first_param.unwrap() orelse {
1026 }1125 return tree.nodeMainToken(n) + end_offset;
1027 n = datas[n].rhs;1126 };
1028 },1127 },
1128
1029 .array_init_dot_two,1129 .array_init_dot_two,
1030 .block_two,1130 .block_two,
1031 .builtin_call_two,1131 .builtin_call_two,
...@@ -1033,14 +1133,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1033,14 +1133,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1033 .container_decl_two,1133 .container_decl_two,
1034 .tagged_union_two,1134 .tagged_union_two,
1035 => {1135 => {
1036 if (datas[n].rhs != 0) {1136 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1137 if (opt_rhs.unwrap()) |rhs| {
1037 end_offset += 1; // for the rparen/rbrace1138 end_offset += 1; // for the rparen/rbrace
1038 n = datas[n].rhs;1139 n = rhs;
1039 } else if (datas[n].lhs != 0) {1140 } else if (opt_lhs.unwrap()) |lhs| {
1040 end_offset += 1; // for the rparen/rbrace1141 end_offset += 1; // for the rparen/rbrace
1041 n = datas[n].lhs;1142 n = lhs;
1042 } else {1143 } else {
1043 switch (tags[n]) {1144 switch (tree.nodeTag(n)) {
1044 .array_init_dot_two,1145 .array_init_dot_two,
1045 .block_two,1146 .block_two,
1046 .struct_init_dot_two,1147 .struct_init_dot_two,
...@@ -1048,17 +1149,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1048,17 +1149,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1048 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace1149 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace
1049 .container_decl_two => {1150 .container_decl_two => {
1050 var i: u32 = 2; // lbrace + rbrace1151 var i: u32 = 2; // lbrace + rbrace
1051 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;1152 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
1052 end_offset += i;1153 end_offset += i;
1053 },1154 },
1054 .tagged_union_two => {1155 .tagged_union_two => {
1055 var i: u32 = 5; // (enum) {}1156 var i: u32 = 5; // (enum) {}
1056 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;1157 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
1057 end_offset += i;1158 end_offset += i;
1058 },1159 },
1059 else => unreachable,1160 else => unreachable,
1060 }1161 }
1061 return main_tokens[n] + end_offset;1162 return tree.nodeMainToken(n) + end_offset;
1062 }1163 }
1063 },1164 },
1064 .array_init_dot_two_comma,1165 .array_init_dot_two_comma,
...@@ -1068,459 +1169,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1068,459 +1169,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1068 .container_decl_two_trailing,1169 .container_decl_two_trailing,
1069 .tagged_union_two_trailing,1170 .tagged_union_two_trailing,
1070 => {1171 => {
1172 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1071 end_offset += 2; // for the comma/semicolon + rbrace/rparen1173 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1072 if (datas[n].rhs != 0) {1174 if (opt_rhs.unwrap()) |rhs| {
1073 n = datas[n].rhs;1175 n = rhs;
1074 } else if (datas[n].lhs != 0) {1176 } else if (opt_lhs.unwrap()) |lhs| {
1075 n = datas[n].lhs;1177 n = lhs;
1076 } else {1178 } else {
1077 unreachable;1179 unreachable;
1078 }1180 }
1079 },1181 },
1080 .simple_var_decl => {1182 .simple_var_decl => {
1081 if (datas[n].rhs != 0) {1183 const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node;
1082 n = datas[n].rhs;1184 if (init_node.unwrap()) |rhs| {
1083 } else if (datas[n].lhs != 0) {1185 n = rhs;
1084 n = datas[n].lhs;1186 } else if (type_node.unwrap()) |lhs| {
1187 n = lhs;
1085 } else {1188 } else {
1086 end_offset += 1; // from mut token to name1189 end_offset += 1; // from mut token to name
1087 return main_tokens[n] + end_offset;1190 return tree.nodeMainToken(n) + end_offset;
1088 }1191 }
1089 },1192 },
1090 .aligned_var_decl => {1193 .aligned_var_decl => {
1091 if (datas[n].rhs != 0) {1194 const align_node, const init_node = tree.nodeData(n).node_and_opt_node;
1092 n = datas[n].rhs;1195 if (init_node.unwrap()) |rhs| {
1093 } else if (datas[n].lhs != 0) {1196 n = rhs;
1094 end_offset += 1; // for the rparen
1095 n = datas[n].lhs;
1096 } else {1197 } else {
1097 end_offset += 1; // from mut token to name1198 end_offset += 1; // for the rparen
1098 return main_tokens[n] + end_offset;1199 n = align_node;
1099 }1200 }
1100 },1201 },
1101 .global_var_decl => {1202 .global_var_decl => {
1102 if (datas[n].rhs != 0) {1203 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1103 n = datas[n].rhs;1204 if (init_node.unwrap()) |rhs| {
1205 n = rhs;
1104 } else {1206 } else {
1105 const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl);1207 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1106 if (extra.section_node != 0) {1208 if (extra.section_node.unwrap()) |section_node| {
1107 end_offset += 1; // for the rparen1209 end_offset += 1; // for the rparen
1108 n = extra.section_node;1210 n = section_node;
1109 } else if (extra.align_node != 0) {1211 } else if (extra.align_node.unwrap()) |align_node| {
1110 end_offset += 1; // for the rparen1212 end_offset += 1; // for the rparen
1111 n = extra.align_node;1213 n = align_node;
1112 } else if (extra.type_node != 0) {1214 } else if (extra.type_node.unwrap()) |type_node| {
1113 n = extra.type_node;1215 n = type_node;
1114 } else {1216 } else {
1115 end_offset += 1; // from mut token to name1217 end_offset += 1; // from mut token to name
1116 return main_tokens[n] + end_offset;1218 return tree.nodeMainToken(n) + end_offset;
1117 }1219 }
1118 }1220 }
1119 },1221 },
1120 .local_var_decl => {1222 .local_var_decl => {
1121 if (datas[n].rhs != 0) {1223 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1122 n = datas[n].rhs;1224 if (init_node.unwrap()) |rhs| {
1225 n = rhs;
1123 } else {1226 } else {
1124 const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl);1227 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
1125 if (extra.align_node != 0) {1228 end_offset += 1; // for the rparen
1126 end_offset += 1; // for the rparen1229 n = extra.align_node;
1127 n = extra.align_node;
1128 } else if (extra.type_node != 0) {
1129 n = extra.type_node;
1130 } else {
1131 end_offset += 1; // from mut token to name
1132 return main_tokens[n] + end_offset;
1133 }
1134 }1230 }
1135 },1231 },
1136 .container_field_init => {1232 .container_field_init => {
1137 if (datas[n].rhs != 0) {1233 const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node;
1138 n = datas[n].rhs;1234 n = value_expr.unwrap() orelse type_expr;
1139 } else if (datas[n].lhs != 0) {
1140 n = datas[n].lhs;
1141 } else {
1142 return main_tokens[n] + end_offset;
1143 }
1144 },1235 },
1145 .container_field_align => {1236
1146 if (datas[n].rhs != 0) {1237 .array_access,
1147 end_offset += 1; // for the rparen1238 .array_init_one,
1148 n = datas[n].rhs;1239 .container_field_align,
1149 } else if (datas[n].lhs != 0) {1240 => {
1150 n = datas[n].lhs;1241 _, const rhs = tree.nodeData(n).node_and_node;
1151 } else {1242 end_offset += 1; // for the rbracket/rbrace/rparen
1152 return main_tokens[n] + end_offset;1243 n = rhs;
1153 }
1154 },1244 },
1155 .container_field => {1245 .container_field => {
1156 const extra = tree.extraData(datas[n].rhs, Node.ContainerField);1246 _, const extra_index = tree.nodeData(n).node_and_extra;
1157 if (extra.value_expr != 0) {1247 const extra = tree.extraData(extra_index, Node.ContainerField);
1158 n = extra.value_expr;1248 n = extra.value_expr;
1159 } else if (extra.align_expr != 0) {
1160 end_offset += 1; // for the rparen
1161 n = extra.align_expr;
1162 } else if (datas[n].lhs != 0) {
1163 n = datas[n].lhs;
1164 } else {
1165 return main_tokens[n] + end_offset;
1166 }
1167 },1249 },
11681250
1169 .array_init_one,1251 .struct_init_one => {
1170 .struct_init_one,1252 _, const first_field = tree.nodeData(n).node_and_opt_node;
1171 => {
1172 end_offset += 1; // rbrace1253 end_offset += 1; // rbrace
1173 if (datas[n].rhs == 0) {1254 n = first_field.unwrap() orelse {
1174 return main_tokens[n] + end_offset;1255 return tree.nodeMainToken(n) + end_offset;
1175 } else {1256 };
1176 n = datas[n].rhs;1257 },
1177 }1258 .slice_open => {
1259 _, const start_node = tree.nodeData(n).node_and_node;
1260 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1261 n = start_node;
1262 },
1263 .array_init_one_comma => {
1264 _, const first_element = tree.nodeData(n).node_and_node;
1265 end_offset += 2; // comma + rbrace
1266 n = first_element;
1178 },1267 },
1179 .slice_open,
1180 .call_one_comma,1268 .call_one_comma,
1181 .async_call_one_comma,1269 .async_call_one_comma,
1182 .array_init_one_comma,
1183 .struct_init_one_comma,1270 .struct_init_one_comma,
1184 => {1271 => {
1272 _, const first_field = tree.nodeData(n).node_and_opt_node;
1185 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen1273 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1186 n = datas[n].rhs;1274 n = first_field.unwrap().?;
1187 assert(n != 0);
1188 },1275 },
1189 .slice => {1276 .slice => {
1190 const extra = tree.extraData(datas[n].rhs, Node.Slice);1277 _, const extra_index = tree.nodeData(n).node_and_extra;
1191 assert(extra.end != 0); // should have used slice_open1278 const extra = tree.extraData(extra_index, Node.Slice);
1192 end_offset += 1; // rbracket1279 end_offset += 1; // rbracket
1193 n = extra.end;1280 n = extra.end;
1194 },1281 },
1195 .slice_sentinel => {1282 .slice_sentinel => {
1196 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);1283 _, const extra_index = tree.nodeData(n).node_and_extra;
1197 assert(extra.sentinel != 0); // should have used slice1284 const extra = tree.extraData(extra_index, Node.SliceSentinel);
1198 end_offset += 1; // rbracket1285 end_offset += 1; // rbracket
1199 n = extra.sentinel;1286 n = extra.sentinel;
1200 },1287 },
12011288
1202 .@"continue", .@"break" => {1289 .@"continue", .@"break" => {
1203 if (datas[n].rhs != 0) {1290 const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node;
1204 n = datas[n].rhs;1291 if (opt_rhs.unwrap()) |rhs| {
1205 } else if (datas[n].lhs != 0) {1292 n = rhs;
1206 return datas[n].lhs + end_offset;1293 } else if (opt_label.unwrap()) |lhs| {
1207 } else {1294 return lhs + end_offset;
1208 return main_tokens[n] + end_offset;
1209 }
1210 },
1211 .fn_decl => {
1212 if (datas[n].rhs != 0) {
1213 n = datas[n].rhs;
1214 } else {1295 } else {
1215 n = datas[n].lhs;1296 return tree.nodeMainToken(n) + end_offset;
1216 }1297 }
1217 },1298 },
1218 .fn_proto_one => {
1219 const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne);
1220 // addrspace, linksection, callconv, align can appear in any order, so we
1221 // find the last one here.
1222 var max_node: Node.Index = datas[n].rhs;
1223 var max_start = token_starts[main_tokens[max_node]];
1224 var max_offset: TokenIndex = 0;
1225 if (extra.align_expr != 0) {
1226 const start = token_starts[main_tokens[extra.align_expr]];
1227 if (start > max_start) {
1228 max_node = extra.align_expr;
1229 max_start = start;
1230 max_offset = 1; // for the rparen
1231 }
1232 }
1233 if (extra.addrspace_expr != 0) {
1234 const start = token_starts[main_tokens[extra.addrspace_expr]];
1235 if (start > max_start) {
1236 max_node = extra.addrspace_expr;
1237 max_start = start;
1238 max_offset = 1; // for the rparen
1239 }
1240 }
1241 if (extra.section_expr != 0) {
1242 const start = token_starts[main_tokens[extra.section_expr]];
1243 if (start > max_start) {
1244 max_node = extra.section_expr;
1245 max_start = start;
1246 max_offset = 1; // for the rparen
1247 }
1248 }
1249 if (extra.callconv_expr != 0) {
1250 const start = token_starts[main_tokens[extra.callconv_expr]];
1251 if (start > max_start) {
1252 max_node = extra.callconv_expr;
1253 max_start = start;
1254 max_offset = 1; // for the rparen
1255 }
1256 }
1257 n = max_node;
1258 end_offset += max_offset;
1259 },
1260 .fn_proto => {
1261 const extra = tree.extraData(datas[n].lhs, Node.FnProto);
1262 // addrspace, linksection, callconv, align can appear in any order, so we
1263 // find the last one here.
1264 var max_node: Node.Index = datas[n].rhs;
1265 var max_start = token_starts[main_tokens[max_node]];
1266 var max_offset: TokenIndex = 0;
1267 if (extra.align_expr != 0) {
1268 const start = token_starts[main_tokens[extra.align_expr]];
1269 if (start > max_start) {
1270 max_node = extra.align_expr;
1271 max_start = start;
1272 max_offset = 1; // for the rparen
1273 }
1274 }
1275 if (extra.addrspace_expr != 0) {
1276 const start = token_starts[main_tokens[extra.addrspace_expr]];
1277 if (start > max_start) {
1278 max_node = extra.addrspace_expr;
1279 max_start = start;
1280 max_offset = 1; // for the rparen
1281 }
1282 }
1283 if (extra.section_expr != 0) {
1284 const start = token_starts[main_tokens[extra.section_expr]];
1285 if (start > max_start) {
1286 max_node = extra.section_expr;
1287 max_start = start;
1288 max_offset = 1; // for the rparen
1289 }
1290 }
1291 if (extra.callconv_expr != 0) {
1292 const start = token_starts[main_tokens[extra.callconv_expr]];
1293 if (start > max_start) {
1294 max_node = extra.callconv_expr;
1295 max_start = start;
1296 max_offset = 1; // for the rparen
1297 }
1298 }
1299 n = max_node;
1300 end_offset += max_offset;
1301 },
1302 .while_cont => {1299 .while_cont => {
1303 const extra = tree.extraData(datas[n].rhs, Node.WhileCont);1300 _, const extra_index = tree.nodeData(n).node_and_extra;
1304 assert(extra.then_expr != 0);1301 const extra = tree.extraData(extra_index, Node.WhileCont);
1305 n = extra.then_expr;1302 n = extra.then_expr;
1306 },1303 },
1307 .@"while" => {1304 .@"while" => {
1308 const extra = tree.extraData(datas[n].rhs, Node.While);1305 _, const extra_index = tree.nodeData(n).node_and_extra;
1309 assert(extra.else_expr != 0);1306 const extra = tree.extraData(extra_index, Node.While);
1310 n = extra.else_expr;1307 n = extra.else_expr;
1311 },1308 },
1312 .@"if" => {1309 .@"if" => {
1313 const extra = tree.extraData(datas[n].rhs, Node.If);1310 _, const extra_index = tree.nodeData(n).node_and_extra;
1314 assert(extra.else_expr != 0);1311 const extra = tree.extraData(extra_index, Node.If);
1315 n = extra.else_expr;1312 n = extra.else_expr;
1316 },1313 },
1317 .@"for" => {1314 .@"for" => {
1318 const extra = @as(Node.For, @bitCast(datas[n].rhs));1315 const extra_index, const extra = tree.nodeData(n).@"for";
1319 n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)];1316 const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else);
1320 },1317 n = @enumFromInt(tree.extra_data[index]);
1321 .@"suspend" => {
1322 if (datas[n].lhs != 0) {
1323 n = datas[n].lhs;
1324 } else {
1325 return main_tokens[n] + end_offset;
1326 }
1327 },1318 },
1328 .array_type_sentinel => {1319 .array_type_sentinel => {
1329 const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel);1320 _, const extra_index = tree.nodeData(n).node_and_extra;
1321 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
1330 n = extra.elem_type;1322 n = extra.elem_type;
1331 },1323 },
1332 };1324 };
1333}1325}
13341326
1335pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {1327pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {
1336 const token_starts = tree.tokens.items(.start);1328 const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)];
1337 const source = tree.source[token_starts[token1]..token_starts[token2]];
1338 return mem.indexOfScalar(u8, source, '\n') == null;1329 return mem.indexOfScalar(u8, source, '\n') == null;
1339}1330}
13401331
1341pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {1332pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {
1342 const token_starts = tree.tokens.items(.start);
1343 const first_token = tree.firstToken(node);1333 const first_token = tree.firstToken(node);
1344 const last_token = tree.lastToken(node);1334 const last_token = tree.lastToken(node);
1345 const start = token_starts[first_token];1335 const start = tree.tokenStart(first_token);
1346 const end = token_starts[last_token] + tree.tokenSlice(last_token).len;1336 const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len;
1347 return tree.source[start..end];1337 return tree.source[start..end];
1348}1338}
13491339
1350pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1340pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1351 assert(tree.nodes.items(.tag)[node] == .global_var_decl);1341 assert(tree.nodeTag(node) == .global_var_decl);
1352 const data = tree.nodes.items(.data)[node];1342 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1353 const extra = tree.extraData(data.lhs, Node.GlobalVarDecl);1343 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1354 return tree.fullVarDeclComponents(.{1344 return tree.fullVarDeclComponents(.{
1355 .type_node = extra.type_node,1345 .type_node = extra.type_node,
1356 .align_node = extra.align_node,1346 .align_node = extra.align_node,
1357 .addrspace_node = extra.addrspace_node,1347 .addrspace_node = extra.addrspace_node,
1358 .section_node = extra.section_node,1348 .section_node = extra.section_node,
1359 .init_node = data.rhs,1349 .init_node = init_node,
1360 .mut_token = tree.nodes.items(.main_token)[node],1350 .mut_token = tree.nodeMainToken(node),
1361 });1351 });
1362}1352}
13631353
1364pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1354pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1365 assert(tree.nodes.items(.tag)[node] == .local_var_decl);1355 assert(tree.nodeTag(node) == .local_var_decl);
1366 const data = tree.nodes.items(.data)[node];1356 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1367 const extra = tree.extraData(data.lhs, Node.LocalVarDecl);1357 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
1368 return tree.fullVarDeclComponents(.{1358 return tree.fullVarDeclComponents(.{
1369 .type_node = extra.type_node,1359 .type_node = extra.type_node.toOptional(),
1370 .align_node = extra.align_node,1360 .align_node = extra.align_node.toOptional(),
1371 .addrspace_node = 0,1361 .addrspace_node = .none,
1372 .section_node = 0,1362 .section_node = .none,
1373 .init_node = data.rhs,1363 .init_node = init_node,
1374 .mut_token = tree.nodes.items(.main_token)[node],1364 .mut_token = tree.nodeMainToken(node),
1375 });1365 });
1376}1366}
13771367
1378pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1368pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1379 assert(tree.nodes.items(.tag)[node] == .simple_var_decl);1369 assert(tree.nodeTag(node) == .simple_var_decl);
1380 const data = tree.nodes.items(.data)[node];1370 const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node;
1381 return tree.fullVarDeclComponents(.{1371 return tree.fullVarDeclComponents(.{
1382 .type_node = data.lhs,1372 .type_node = type_node,
1383 .align_node = 0,1373 .align_node = .none,
1384 .addrspace_node = 0,1374 .addrspace_node = .none,
1385 .section_node = 0,1375 .section_node = .none,
1386 .init_node = data.rhs,1376 .init_node = init_node,
1387 .mut_token = tree.nodes.items(.main_token)[node],1377 .mut_token = tree.nodeMainToken(node),
1388 });1378 });
1389}1379}
13901380
1391pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1381pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1392 assert(tree.nodes.items(.tag)[node] == .aligned_var_decl);1382 assert(tree.nodeTag(node) == .aligned_var_decl);
1393 const data = tree.nodes.items(.data)[node];1383 const align_node, const init_node = tree.nodeData(node).node_and_opt_node;
1394 return tree.fullVarDeclComponents(.{1384 return tree.fullVarDeclComponents(.{
1395 .type_node = 0,1385 .type_node = .none,
1396 .align_node = data.lhs,1386 .align_node = align_node.toOptional(),
1397 .addrspace_node = 0,1387 .addrspace_node = .none,
1398 .section_node = 0,1388 .section_node = .none,
1399 .init_node = data.rhs,1389 .init_node = init_node,
1400 .mut_token = tree.nodes.items(.main_token)[node],1390 .mut_token = tree.nodeMainToken(node),
1401 });1391 });
1402}1392}
14031393
1404pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {1394pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {
1405 const data = tree.nodes.items(.data)[node];1395 const extra_index, const value_expr = tree.nodeData(node).extra_and_node;
1406 const variable_count = tree.extra_data[data.lhs];1396 const variable_count = tree.extra_data[@intFromEnum(extra_index)];
1407 return tree.fullAssignDestructureComponents(.{1397 return tree.fullAssignDestructureComponents(.{
1408 .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count],1398 .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index),
1409 .equal_token = tree.nodes.items(.main_token)[node],1399 .equal_token = tree.nodeMainToken(node),
1410 .value_expr = data.rhs,1400 .value_expr = value_expr,
1411 });1401 });
1412}1402}
14131403
1414pub fn ifSimple(tree: Ast, node: Node.Index) full.If {1404pub fn ifSimple(tree: Ast, node: Node.Index) full.If {
1415 assert(tree.nodes.items(.tag)[node] == .if_simple);1405 assert(tree.nodeTag(node) == .if_simple);
1416 const data = tree.nodes.items(.data)[node];1406 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
1417 return tree.fullIfComponents(.{1407 return tree.fullIfComponents(.{
1418 .cond_expr = data.lhs,1408 .cond_expr = cond_expr,
1419 .then_expr = data.rhs,1409 .then_expr = then_expr,
1420 .else_expr = 0,1410 .else_expr = .none,
1421 .if_token = tree.nodes.items(.main_token)[node],1411 .if_token = tree.nodeMainToken(node),
1422 });1412 });
1423}1413}
14241414
1425pub fn ifFull(tree: Ast, node: Node.Index) full.If {1415pub fn ifFull(tree: Ast, node: Node.Index) full.If {
1426 assert(tree.nodes.items(.tag)[node] == .@"if");1416 assert(tree.nodeTag(node) == .@"if");
1427 const data = tree.nodes.items(.data)[node];1417 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1428 const extra = tree.extraData(data.rhs, Node.If);1418 const extra = tree.extraData(extra_index, Node.If);
1429 return tree.fullIfComponents(.{1419 return tree.fullIfComponents(.{
1430 .cond_expr = data.lhs,1420 .cond_expr = cond_expr,
1431 .then_expr = extra.then_expr,1421 .then_expr = extra.then_expr,
1432 .else_expr = extra.else_expr,1422 .else_expr = extra.else_expr.toOptional(),
1433 .if_token = tree.nodes.items(.main_token)[node],1423 .if_token = tree.nodeMainToken(node),
1434 });1424 });
1435}1425}
14361426
1437pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {1427pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {
1438 assert(tree.nodes.items(.tag)[node] == .container_field);1428 assert(tree.nodeTag(node) == .container_field);
1439 const data = tree.nodes.items(.data)[node];1429 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1440 const extra = tree.extraData(data.rhs, Node.ContainerField);1430 const extra = tree.extraData(extra_index, Node.ContainerField);
1441 const main_token = tree.nodes.items(.main_token)[node];1431 const main_token = tree.nodeMainToken(node);
1442 return tree.fullContainerFieldComponents(.{1432 return tree.fullContainerFieldComponents(.{
1443 .main_token = main_token,1433 .main_token = main_token,
1444 .type_expr = data.lhs,1434 .type_expr = type_expr.toOptional(),
1445 .align_expr = extra.align_expr,1435 .align_expr = extra.align_expr.toOptional(),
1446 .value_expr = extra.value_expr,1436 .value_expr = extra.value_expr.toOptional(),
1447 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1437 .tuple_like = tree.tokenTag(main_token) != .identifier or
1448 tree.tokens.items(.tag)[main_token + 1] != .colon,1438 tree.tokenTag(main_token + 1) != .colon,
1449 });1439 });
1450}1440}
14511441
1452pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {1442pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {
1453 assert(tree.nodes.items(.tag)[node] == .container_field_init);1443 assert(tree.nodeTag(node) == .container_field_init);
1454 const data = tree.nodes.items(.data)[node];1444 const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node;
1455 const main_token = tree.nodes.items(.main_token)[node];1445 const main_token = tree.nodeMainToken(node);
1456 return tree.fullContainerFieldComponents(.{1446 return tree.fullContainerFieldComponents(.{
1457 .main_token = main_token,1447 .main_token = main_token,
1458 .type_expr = data.lhs,1448 .type_expr = type_expr.toOptional(),
1459 .align_expr = 0,1449 .align_expr = .none,
1460 .value_expr = data.rhs,1450 .value_expr = value_expr,
1461 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1451 .tuple_like = tree.tokenTag(main_token) != .identifier or
1462 tree.tokens.items(.tag)[main_token + 1] != .colon,1452 tree.tokenTag(main_token + 1) != .colon,
1463 });1453 });
1464}1454}
14651455
1466pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {1456pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {
1467 assert(tree.nodes.items(.tag)[node] == .container_field_align);1457 assert(tree.nodeTag(node) == .container_field_align);
1468 const data = tree.nodes.items(.data)[node];1458 const type_expr, const align_expr = tree.nodeData(node).node_and_node;
1469 const main_token = tree.nodes.items(.main_token)[node];1459 const main_token = tree.nodeMainToken(node);
1470 return tree.fullContainerFieldComponents(.{1460 return tree.fullContainerFieldComponents(.{
1471 .main_token = main_token,1461 .main_token = main_token,
1472 .type_expr = data.lhs,1462 .type_expr = type_expr.toOptional(),
1473 .align_expr = data.rhs,1463 .align_expr = align_expr.toOptional(),
1474 .value_expr = 0,1464 .value_expr = .none,
1475 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1465 .tuple_like = tree.tokenTag(main_token) != .identifier or
1476 tree.tokens.items(.tag)[main_token + 1] != .colon,1466 tree.tokenTag(main_token + 1) != .colon,
1477 });1467 });
1478}1468}
14791469
1480pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {1470pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1481 assert(tree.nodes.items(.tag)[node] == .fn_proto_simple);1471 assert(tree.nodeTag(node) == .fn_proto_simple);
1482 const data = tree.nodes.items(.data)[node];1472 const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node;
1483 buffer[0] = data.lhs;1473 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
1484 const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1];
1485 return tree.fullFnProtoComponents(.{1474 return tree.fullFnProtoComponents(.{
1486 .proto_node = node,1475 .proto_node = node,
1487 .fn_token = tree.nodes.items(.main_token)[node],1476 .fn_token = tree.nodeMainToken(node),
1488 .return_type = data.rhs,1477 .return_type = return_type,
1489 .params = params,1478 .params = params,
1490 .align_expr = 0,1479 .align_expr = .none,
1491 .addrspace_expr = 0,1480 .addrspace_expr = .none,
1492 .section_expr = 0,1481 .section_expr = .none,
1493 .callconv_expr = 0,1482 .callconv_expr = .none,
1494 });1483 });
1495}1484}
14961485
1497pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {1486pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {
1498 assert(tree.nodes.items(.tag)[node] == .fn_proto_multi);1487 assert(tree.nodeTag(node) == .fn_proto_multi);
1499 const data = tree.nodes.items(.data)[node];1488 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1500 const params_range = tree.extraData(data.lhs, Node.SubRange);1489 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1501 const params = tree.extra_data[params_range.start..params_range.end];
1502 return tree.fullFnProtoComponents(.{1490 return tree.fullFnProtoComponents(.{
1503 .proto_node = node,1491 .proto_node = node,
1504 .fn_token = tree.nodes.items(.main_token)[node],1492 .fn_token = tree.nodeMainToken(node),
1505 .return_type = data.rhs,1493 .return_type = return_type,
1506 .params = params,1494 .params = params,
1507 .align_expr = 0,1495 .align_expr = .none,
1508 .addrspace_expr = 0,1496 .addrspace_expr = .none,
1509 .section_expr = 0,1497 .section_expr = .none,
1510 .callconv_expr = 0,1498 .callconv_expr = .none,
1511 });1499 });
1512}1500}
15131501
1514pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {1502pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1515 assert(tree.nodes.items(.tag)[node] == .fn_proto_one);1503 assert(tree.nodeTag(node) == .fn_proto_one);
1516 const data = tree.nodes.items(.data)[node];1504 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1517 const extra = tree.extraData(data.lhs, Node.FnProtoOne);1505 const extra = tree.extraData(extra_index, Node.FnProtoOne);
1518 buffer[0] = extra.param;1506 const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param});
1519 const params = if (extra.param == 0) buffer[0..0] else buffer[0..1];
1520 return tree.fullFnProtoComponents(.{1507 return tree.fullFnProtoComponents(.{
1521 .proto_node = node,1508 .proto_node = node,
1522 .fn_token = tree.nodes.items(.main_token)[node],1509 .fn_token = tree.nodeMainToken(node),
1523 .return_type = data.rhs,1510 .return_type = return_type,
1524 .params = params,1511 .params = params,
1525 .align_expr = extra.align_expr,1512 .align_expr = extra.align_expr,
1526 .addrspace_expr = extra.addrspace_expr,1513 .addrspace_expr = extra.addrspace_expr,
...@@ -1530,14 +1517,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr...@@ -1530,14 +1517,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr
1530}1517}
15311518
1532pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {1519pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1533 assert(tree.nodes.items(.tag)[node] == .fn_proto);1520 assert(tree.nodeTag(node) == .fn_proto);
1534 const data = tree.nodes.items(.data)[node];1521 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1535 const extra = tree.extraData(data.lhs, Node.FnProto);1522 const extra = tree.extraData(extra_index, Node.FnProto);
1536 const params = tree.extra_data[extra.params_start..extra.params_end];1523 const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index);
1537 return tree.fullFnProtoComponents(.{1524 return tree.fullFnProtoComponents(.{
1538 .proto_node = node,1525 .proto_node = node,
1539 .fn_token = tree.nodes.items(.main_token)[node],1526 .fn_token = tree.nodeMainToken(node),
1540 .return_type = data.rhs,1527 .return_type = return_type,
1541 .params = params,1528 .params = params,
1542 .align_expr = extra.align_expr,1529 .align_expr = extra.align_expr,
1543 .addrspace_expr = extra.addrspace_expr,1530 .addrspace_expr = extra.addrspace_expr,
...@@ -1547,300 +1534,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {...@@ -1547,300 +1534,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1547}1534}
15481535
1549pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {1536pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {
1550 assert(tree.nodes.items(.tag)[node] == .struct_init_one or1537 assert(tree.nodeTag(node) == .struct_init_one or
1551 tree.nodes.items(.tag)[node] == .struct_init_one_comma);1538 tree.nodeTag(node) == .struct_init_one_comma);
1552 const data = tree.nodes.items(.data)[node];1539 const type_expr, const first_field = tree.nodeData(node).node_and_opt_node;
1553 buffer[0] = data.rhs;1540 const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field});
1554 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1555 return .{1541 return .{
1556 .ast = .{1542 .ast = .{
1557 .lbrace = tree.nodes.items(.main_token)[node],1543 .lbrace = tree.nodeMainToken(node),
1558 .fields = fields,1544 .fields = fields,
1559 .type_expr = data.lhs,1545 .type_expr = type_expr.toOptional(),
1560 },1546 },
1561 };1547 };
1562}1548}
15631549
1564pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {1550pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {
1565 assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or1551 assert(tree.nodeTag(node) == .struct_init_dot_two or
1566 tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma);1552 tree.nodeTag(node) == .struct_init_dot_two_comma);
1567 const data = tree.nodes.items(.data)[node];1553 const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1568 buffer.* = .{ data.lhs, data.rhs };
1569 const fields = if (data.rhs != 0)
1570 buffer[0..2]
1571 else if (data.lhs != 0)
1572 buffer[0..1]
1573 else
1574 buffer[0..0];
1575 return .{1554 return .{
1576 .ast = .{1555 .ast = .{
1577 .lbrace = tree.nodes.items(.main_token)[node],1556 .lbrace = tree.nodeMainToken(node),
1578 .fields = fields,1557 .fields = fields,
1579 .type_expr = 0,1558 .type_expr = .none,
1580 },1559 },
1581 };1560 };
1582}1561}
15831562
1584pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {1563pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {
1585 assert(tree.nodes.items(.tag)[node] == .struct_init_dot or1564 assert(tree.nodeTag(node) == .struct_init_dot or
1586 tree.nodes.items(.tag)[node] == .struct_init_dot_comma);1565 tree.nodeTag(node) == .struct_init_dot_comma);
1587 const data = tree.nodes.items(.data)[node];1566 const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1588 return .{1567 return .{
1589 .ast = .{1568 .ast = .{
1590 .lbrace = tree.nodes.items(.main_token)[node],1569 .lbrace = tree.nodeMainToken(node),
1591 .fields = tree.extra_data[data.lhs..data.rhs],1570 .fields = fields,
1592 .type_expr = 0,1571 .type_expr = .none,
1593 },1572 },
1594 };1573 };
1595}1574}
15961575
1597pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {1576pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {
1598 assert(tree.nodes.items(.tag)[node] == .struct_init or1577 assert(tree.nodeTag(node) == .struct_init or
1599 tree.nodes.items(.tag)[node] == .struct_init_comma);1578 tree.nodeTag(node) == .struct_init_comma);
1600 const data = tree.nodes.items(.data)[node];1579 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1601 const fields_range = tree.extraData(data.rhs, Node.SubRange);1580 const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1602 return .{1581 return .{
1603 .ast = .{1582 .ast = .{
1604 .lbrace = tree.nodes.items(.main_token)[node],1583 .lbrace = tree.nodeMainToken(node),
1605 .fields = tree.extra_data[fields_range.start..fields_range.end],1584 .fields = fields,
1606 .type_expr = data.lhs,1585 .type_expr = type_expr.toOptional(),
1607 },1586 },
1608 };1587 };
1609}1588}
16101589
1611pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {1590pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
1612 assert(tree.nodes.items(.tag)[node] == .array_init_one or1591 assert(tree.nodeTag(node) == .array_init_one or
1613 tree.nodes.items(.tag)[node] == .array_init_one_comma);1592 tree.nodeTag(node) == .array_init_one_comma);
1614 const data = tree.nodes.items(.data)[node];1593 const type_expr, buffer[0] = tree.nodeData(node).node_and_node;
1615 buffer[0] = data.rhs;
1616 const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1617 return .{1594 return .{
1618 .ast = .{1595 .ast = .{
1619 .lbrace = tree.nodes.items(.main_token)[node],1596 .lbrace = tree.nodeMainToken(node),
1620 .elements = elements,1597 .elements = buffer[0..1],
1621 .type_expr = data.lhs,1598 .type_expr = type_expr.toOptional(),
1622 },1599 },
1623 };1600 };
1624}1601}
16251602
1626pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {1603pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {
1627 assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or1604 assert(tree.nodeTag(node) == .array_init_dot_two or
1628 tree.nodes.items(.tag)[node] == .array_init_dot_two_comma);1605 tree.nodeTag(node) == .array_init_dot_two_comma);
1629 const data = tree.nodes.items(.data)[node];1606 const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1630 buffer.* = .{ data.lhs, data.rhs };
1631 const elements = if (data.rhs != 0)
1632 buffer[0..2]
1633 else if (data.lhs != 0)
1634 buffer[0..1]
1635 else
1636 buffer[0..0];
1637 return .{1607 return .{
1638 .ast = .{1608 .ast = .{
1639 .lbrace = tree.nodes.items(.main_token)[node],1609 .lbrace = tree.nodeMainToken(node),
1640 .elements = elements,1610 .elements = elements,
1641 .type_expr = 0,1611 .type_expr = .none,
1642 },1612 },
1643 };1613 };
1644}1614}
16451615
1646pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {1616pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {
1647 assert(tree.nodes.items(.tag)[node] == .array_init_dot or1617 assert(tree.nodeTag(node) == .array_init_dot or
1648 tree.nodes.items(.tag)[node] == .array_init_dot_comma);1618 tree.nodeTag(node) == .array_init_dot_comma);
1649 const data = tree.nodes.items(.data)[node];1619 const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1650 return .{1620 return .{
1651 .ast = .{1621 .ast = .{
1652 .lbrace = tree.nodes.items(.main_token)[node],1622 .lbrace = tree.nodeMainToken(node),
1653 .elements = tree.extra_data[data.lhs..data.rhs],1623 .elements = elements,
1654 .type_expr = 0,1624 .type_expr = .none,
1655 },1625 },
1656 };1626 };
1657}1627}
16581628
1659pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {1629pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {
1660 assert(tree.nodes.items(.tag)[node] == .array_init or1630 assert(tree.nodeTag(node) == .array_init or
1661 tree.nodes.items(.tag)[node] == .array_init_comma);1631 tree.nodeTag(node) == .array_init_comma);
1662 const data = tree.nodes.items(.data)[node];1632 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1663 const elem_range = tree.extraData(data.rhs, Node.SubRange);1633 const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1664 return .{1634 return .{
1665 .ast = .{1635 .ast = .{
1666 .lbrace = tree.nodes.items(.main_token)[node],1636 .lbrace = tree.nodeMainToken(node),
1667 .elements = tree.extra_data[elem_range.start..elem_range.end],1637 .elements = elements,
1668 .type_expr = data.lhs,1638 .type_expr = type_expr.toOptional(),
1669 },1639 },
1670 };1640 };
1671}1641}
16721642
1673pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {1643pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {
1674 assert(tree.nodes.items(.tag)[node] == .array_type);1644 assert(tree.nodeTag(node) == .array_type);
1675 const data = tree.nodes.items(.data)[node];1645 const elem_count, const elem_type = tree.nodeData(node).node_and_node;
1676 return .{1646 return .{
1677 .ast = .{1647 .ast = .{
1678 .lbracket = tree.nodes.items(.main_token)[node],1648 .lbracket = tree.nodeMainToken(node),
1679 .elem_count = data.lhs,1649 .elem_count = elem_count,
1680 .sentinel = 0,1650 .sentinel = .none,
1681 .elem_type = data.rhs,1651 .elem_type = elem_type,
1682 },1652 },
1683 };1653 };
1684}1654}
16851655
1686pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {1656pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {
1687 assert(tree.nodes.items(.tag)[node] == .array_type_sentinel);1657 assert(tree.nodeTag(node) == .array_type_sentinel);
1688 const data = tree.nodes.items(.data)[node];1658 const elem_count, const extra_index = tree.nodeData(node).node_and_extra;
1689 const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel);1659 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
1690 assert(extra.sentinel != 0);
1691 return .{1660 return .{
1692 .ast = .{1661 .ast = .{
1693 .lbracket = tree.nodes.items(.main_token)[node],1662 .lbracket = tree.nodeMainToken(node),
1694 .elem_count = data.lhs,1663 .elem_count = elem_count,
1695 .sentinel = extra.sentinel,1664 .sentinel = extra.sentinel.toOptional(),
1696 .elem_type = extra.elem_type,1665 .elem_type = extra.elem_type,
1697 },1666 },
1698 };1667 };
1699}1668}
17001669
1701pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {1670pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {
1702 assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned);1671 assert(tree.nodeTag(node) == .ptr_type_aligned);
1703 const data = tree.nodes.items(.data)[node];1672 const align_node, const child_type = tree.nodeData(node).opt_node_and_node;
1704 return tree.fullPtrTypeComponents(.{1673 return tree.fullPtrTypeComponents(.{
1705 .main_token = tree.nodes.items(.main_token)[node],1674 .main_token = tree.nodeMainToken(node),
1706 .align_node = data.lhs,1675 .align_node = align_node,
1707 .addrspace_node = 0,1676 .addrspace_node = .none,
1708 .sentinel = 0,1677 .sentinel = .none,
1709 .bit_range_start = 0,1678 .bit_range_start = .none,
1710 .bit_range_end = 0,1679 .bit_range_end = .none,
1711 .child_type = data.rhs,1680 .child_type = child_type,
1712 });1681 });
1713}1682}
17141683
1715pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {1684pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {
1716 assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel);1685 assert(tree.nodeTag(node) == .ptr_type_sentinel);
1717 const data = tree.nodes.items(.data)[node];1686 const sentinel, const child_type = tree.nodeData(node).opt_node_and_node;
1718 return tree.fullPtrTypeComponents(.{1687 return tree.fullPtrTypeComponents(.{
1719 .main_token = tree.nodes.items(.main_token)[node],1688 .main_token = tree.nodeMainToken(node),
1720 .align_node = 0,1689 .align_node = .none,
1721 .addrspace_node = 0,1690 .addrspace_node = .none,
1722 .sentinel = data.lhs,1691 .sentinel = sentinel,
1723 .bit_range_start = 0,1692 .bit_range_start = .none,
1724 .bit_range_end = 0,1693 .bit_range_end = .none,
1725 .child_type = data.rhs,1694 .child_type = child_type,
1726 });1695 });
1727}1696}
17281697
1729pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {1698pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {
1730 assert(tree.nodes.items(.tag)[node] == .ptr_type);1699 assert(tree.nodeTag(node) == .ptr_type);
1731 const data = tree.nodes.items(.data)[node];1700 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1732 const extra = tree.extraData(data.lhs, Node.PtrType);1701 const extra = tree.extraData(extra_index, Node.PtrType);
1733 return tree.fullPtrTypeComponents(.{1702 return tree.fullPtrTypeComponents(.{
1734 .main_token = tree.nodes.items(.main_token)[node],1703 .main_token = tree.nodeMainToken(node),
1735 .align_node = extra.align_node,1704 .align_node = extra.align_node,
1736 .addrspace_node = extra.addrspace_node,1705 .addrspace_node = extra.addrspace_node,
1737 .sentinel = extra.sentinel,1706 .sentinel = extra.sentinel,
1738 .bit_range_start = 0,1707 .bit_range_start = .none,
1739 .bit_range_end = 0,1708 .bit_range_end = .none,
1740 .child_type = data.rhs,1709 .child_type = child_type,
1741 });1710 });
1742}1711}
17431712
1744pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {1713pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {
1745 assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range);1714 assert(tree.nodeTag(node) == .ptr_type_bit_range);
1746 const data = tree.nodes.items(.data)[node];1715 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1747 const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange);1716 const extra = tree.extraData(extra_index, Node.PtrTypeBitRange);
1748 return tree.fullPtrTypeComponents(.{1717 return tree.fullPtrTypeComponents(.{
1749 .main_token = tree.nodes.items(.main_token)[node],1718 .main_token = tree.nodeMainToken(node),
1750 .align_node = extra.align_node,1719 .align_node = extra.align_node.toOptional(),
1751 .addrspace_node = extra.addrspace_node,1720 .addrspace_node = extra.addrspace_node,
1752 .sentinel = extra.sentinel,1721 .sentinel = extra.sentinel,
1753 .bit_range_start = extra.bit_range_start,1722 .bit_range_start = extra.bit_range_start.toOptional(),
1754 .bit_range_end = extra.bit_range_end,1723 .bit_range_end = extra.bit_range_end.toOptional(),
1755 .child_type = data.rhs,1724 .child_type = child_type,
1756 });1725 });
1757}1726}
17581727
1759pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {1728pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {
1760 assert(tree.nodes.items(.tag)[node] == .slice_open);1729 assert(tree.nodeTag(node) == .slice_open);
1761 const data = tree.nodes.items(.data)[node];1730 const sliced, const start = tree.nodeData(node).node_and_node;
1762 return .{1731 return .{
1763 .ast = .{1732 .ast = .{
1764 .sliced = data.lhs,1733 .sliced = sliced,
1765 .lbracket = tree.nodes.items(.main_token)[node],1734 .lbracket = tree.nodeMainToken(node),
1766 .start = data.rhs,1735 .start = start,
1767 .end = 0,1736 .end = .none,
1768 .sentinel = 0,1737 .sentinel = .none,
1769 },1738 },
1770 };1739 };
1771}1740}
17721741
1773pub fn slice(tree: Ast, node: Node.Index) full.Slice {1742pub fn slice(tree: Ast, node: Node.Index) full.Slice {
1774 assert(tree.nodes.items(.tag)[node] == .slice);1743 assert(tree.nodeTag(node) == .slice);
1775 const data = tree.nodes.items(.data)[node];1744 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1776 const extra = tree.extraData(data.rhs, Node.Slice);1745 const extra = tree.extraData(extra_index, Node.Slice);
1777 return .{1746 return .{
1778 .ast = .{1747 .ast = .{
1779 .sliced = data.lhs,1748 .sliced = sliced,
1780 .lbracket = tree.nodes.items(.main_token)[node],1749 .lbracket = tree.nodeMainToken(node),
1781 .start = extra.start,1750 .start = extra.start,
1782 .end = extra.end,1751 .end = extra.end.toOptional(),
1783 .sentinel = 0,1752 .sentinel = .none,
1784 },1753 },
1785 };1754 };
1786}1755}
17871756
1788pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {1757pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {
1789 assert(tree.nodes.items(.tag)[node] == .slice_sentinel);1758 assert(tree.nodeTag(node) == .slice_sentinel);
1790 const data = tree.nodes.items(.data)[node];1759 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1791 const extra = tree.extraData(data.rhs, Node.SliceSentinel);1760 const extra = tree.extraData(extra_index, Node.SliceSentinel);
1792 return .{1761 return .{
1793 .ast = .{1762 .ast = .{
1794 .sliced = data.lhs,1763 .sliced = sliced,
1795 .lbracket = tree.nodes.items(.main_token)[node],1764 .lbracket = tree.nodeMainToken(node),
1796 .start = extra.start,1765 .start = extra.start,
1797 .end = extra.end,1766 .end = extra.end,
1798 .sentinel = extra.sentinel,1767 .sentinel = extra.sentinel.toOptional(),
1799 },1768 },
1800 };1769 };
1801}1770}
18021771
1803pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {1772pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1804 assert(tree.nodes.items(.tag)[node] == .container_decl_two or1773 assert(tree.nodeTag(node) == .container_decl_two or
1805 tree.nodes.items(.tag)[node] == .container_decl_two_trailing);1774 tree.nodeTag(node) == .container_decl_two_trailing);
1806 const data = tree.nodes.items(.data)[node];1775 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1807 buffer.* = .{ data.lhs, data.rhs };
1808 const members = if (data.rhs != 0)
1809 buffer[0..2]
1810 else if (data.lhs != 0)
1811 buffer[0..1]
1812 else
1813 buffer[0..0];
1814 return tree.fullContainerDeclComponents(.{1776 return tree.fullContainerDeclComponents(.{
1815 .main_token = tree.nodes.items(.main_token)[node],1777 .main_token = tree.nodeMainToken(node),
1816 .enum_token = null,1778 .enum_token = null,
1817 .members = members,1779 .members = members,
1818 .arg = 0,1780 .arg = .none,
1819 });1781 });
1820}1782}
18211783
1822pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {1784pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {
1823 assert(tree.nodes.items(.tag)[node] == .container_decl or1785 assert(tree.nodeTag(node) == .container_decl or
1824 tree.nodes.items(.tag)[node] == .container_decl_trailing);1786 tree.nodeTag(node) == .container_decl_trailing);
1825 const data = tree.nodes.items(.data)[node];1787 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1826 return tree.fullContainerDeclComponents(.{1788 return tree.fullContainerDeclComponents(.{
1827 .main_token = tree.nodes.items(.main_token)[node],1789 .main_token = tree.nodeMainToken(node),
1828 .enum_token = null,1790 .enum_token = null,
1829 .members = tree.extra_data[data.lhs..data.rhs],1791 .members = members,
1830 .arg = 0,1792 .arg = .none,
1831 });1793 });
1832}1794}
18331795
1834pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {1796pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {
1835 assert(tree.nodes.items(.tag)[node] == .container_decl_arg or1797 assert(tree.nodeTag(node) == .container_decl_arg or
1836 tree.nodes.items(.tag)[node] == .container_decl_arg_trailing);1798 tree.nodeTag(node) == .container_decl_arg_trailing);
1837 const data = tree.nodes.items(.data)[node];1799 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1838 const members_range = tree.extraData(data.rhs, Node.SubRange);1800 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1839 return tree.fullContainerDeclComponents(.{1801 return tree.fullContainerDeclComponents(.{
1840 .main_token = tree.nodes.items(.main_token)[node],1802 .main_token = tree.nodeMainToken(node),
1841 .enum_token = null,1803 .enum_token = null,
1842 .members = tree.extra_data[members_range.start..members_range.end],1804 .members = members,
1843 .arg = data.lhs,1805 .arg = arg.toOptional(),
1844 });1806 });
1845}1807}
18461808
...@@ -1848,175 +1810,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {...@@ -1848,175 +1810,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {
1848 return .{1810 return .{
1849 .layout_token = null,1811 .layout_token = null,
1850 .ast = .{1812 .ast = .{
1851 .main_token = undefined,1813 .main_token = 0,
1852 .enum_token = null,1814 .enum_token = null,
1853 .members = tree.rootDecls(),1815 .members = tree.rootDecls(),
1854 .arg = 0,1816 .arg = .none,
1855 },1817 },
1856 };1818 };
1857}1819}
18581820
1859pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {1821pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1860 assert(tree.nodes.items(.tag)[node] == .tagged_union_two or1822 assert(tree.nodeTag(node) == .tagged_union_two or
1861 tree.nodes.items(.tag)[node] == .tagged_union_two_trailing);1823 tree.nodeTag(node) == .tagged_union_two_trailing);
1862 const data = tree.nodes.items(.data)[node];1824 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1863 buffer.* = .{ data.lhs, data.rhs };1825 const main_token = tree.nodeMainToken(node);
1864 const members = if (data.rhs != 0)
1865 buffer[0..2]
1866 else if (data.lhs != 0)
1867 buffer[0..1]
1868 else
1869 buffer[0..0];
1870 const main_token = tree.nodes.items(.main_token)[node];
1871 return tree.fullContainerDeclComponents(.{1826 return tree.fullContainerDeclComponents(.{
1872 .main_token = main_token,1827 .main_token = main_token,
1873 .enum_token = main_token + 2, // union lparen enum1828 .enum_token = main_token + 2, // union lparen enum
1874 .members = members,1829 .members = members,
1875 .arg = 0,1830 .arg = .none,
1876 });1831 });
1877}1832}
18781833
1879pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {1834pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {
1880 assert(tree.nodes.items(.tag)[node] == .tagged_union or1835 assert(tree.nodeTag(node) == .tagged_union or
1881 tree.nodes.items(.tag)[node] == .tagged_union_trailing);1836 tree.nodeTag(node) == .tagged_union_trailing);
1882 const data = tree.nodes.items(.data)[node];1837 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1883 const main_token = tree.nodes.items(.main_token)[node];1838 const main_token = tree.nodeMainToken(node);
1884 return tree.fullContainerDeclComponents(.{1839 return tree.fullContainerDeclComponents(.{
1885 .main_token = main_token,1840 .main_token = main_token,
1886 .enum_token = main_token + 2, // union lparen enum1841 .enum_token = main_token + 2, // union lparen enum
1887 .members = tree.extra_data[data.lhs..data.rhs],1842 .members = members,
1888 .arg = 0,1843 .arg = .none,
1889 });1844 });
1890}1845}
18911846
1892pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {1847pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {
1893 assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or1848 assert(tree.nodeTag(node) == .tagged_union_enum_tag or
1894 tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing);1849 tree.nodeTag(node) == .tagged_union_enum_tag_trailing);
1895 const data = tree.nodes.items(.data)[node];1850 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1896 const members_range = tree.extraData(data.rhs, Node.SubRange);1851 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1897 const main_token = tree.nodes.items(.main_token)[node];1852 const main_token = tree.nodeMainToken(node);
1898 return tree.fullContainerDeclComponents(.{1853 return tree.fullContainerDeclComponents(.{
1899 .main_token = main_token,1854 .main_token = main_token,
1900 .enum_token = main_token + 2, // union lparen enum1855 .enum_token = main_token + 2, // union lparen enum
1901 .members = tree.extra_data[members_range.start..members_range.end],1856 .members = members,
1902 .arg = data.lhs,1857 .arg = arg.toOptional(),
1903 });1858 });
1904}1859}
19051860
1906pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {1861pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {
1907 const data = &tree.nodes.items(.data)[node];1862 const main_token = tree.nodeMainToken(node);
1908 const main_token = tree.nodes.items(.main_token)[node];1863 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) {
1909 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) {
1910 .identifier => .{ main_token + 2, main_token },1864 .identifier => .{ main_token + 2, main_token },
1911 .keyword_switch => .{ main_token, null },1865 .keyword_switch => .{ main_token, null },
1912 else => unreachable,1866 else => unreachable,
1913 };1867 };
1914 const extra = tree.extraData(data.rhs, Ast.Node.SubRange);1868 const condition, const extra_index = tree.nodeData(node).node_and_extra;
1869 const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index);
1915 return .{1870 return .{
1916 .ast = .{1871 .ast = .{
1917 .switch_token = switch_token,1872 .switch_token = switch_token,
1918 .condition = data.lhs,1873 .condition = condition,
1919 .cases = tree.extra_data[extra.start..extra.end],1874 .cases = cases,
1920 },1875 },
1921 .label_token = label_token,1876 .label_token = label_token,
1922 };1877 };
1923}1878}
19241879
1925pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {1880pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
1926 const data = &tree.nodes.items(.data)[node];1881 const first_value, const target_expr = tree.nodeData(node).opt_node_and_node;
1927 const values: *[1]Node.Index = &data.lhs;
1928 return tree.fullSwitchCaseComponents(.{1882 return tree.fullSwitchCaseComponents(.{
1929 .values = if (data.lhs == 0) values[0..0] else values[0..1],1883 .values = if (first_value == .none)
1930 .arrow_token = tree.nodes.items(.main_token)[node],1884 &.{}
1931 .target_expr = data.rhs,1885 else
1886 // Ensure that the returned slice points into the existing memory of the Ast
1887 (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1],
1888 .arrow_token = tree.nodeMainToken(node),
1889 .target_expr = target_expr,
1932 }, node);1890 }, node);
1933}1891}
19341892
1935pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {1893pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
1936 const data = tree.nodes.items(.data)[node];1894 const extra_index, const target_expr = tree.nodeData(node).extra_and_node;
1937 const extra = tree.extraData(data.lhs, Node.SubRange);1895 const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1938 return tree.fullSwitchCaseComponents(.{1896 return tree.fullSwitchCaseComponents(.{
1939 .values = tree.extra_data[extra.start..extra.end],1897 .values = values,
1940 .arrow_token = tree.nodes.items(.main_token)[node],1898 .arrow_token = tree.nodeMainToken(node),
1941 .target_expr = data.rhs,1899 .target_expr = target_expr,
1942 }, node);1900 }, node);
1943}1901}
19441902
1945pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {1903pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {
1946 const data = tree.nodes.items(.data)[node];1904 const template, const rparen = tree.nodeData(node).node_and_token;
1947 return tree.fullAsmComponents(.{1905 return tree.fullAsmComponents(.{
1948 .asm_token = tree.nodes.items(.main_token)[node],1906 .asm_token = tree.nodeMainToken(node),
1949 .template = data.lhs,1907 .template = template,
1950 .items = &.{},1908 .items = &.{},
1951 .rparen = data.rhs,1909 .rparen = rparen,
1952 });1910 });
1953}1911}
19541912
1955pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {1913pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {
1956 const data = tree.nodes.items(.data)[node];1914 const template, const extra_index = tree.nodeData(node).node_and_extra;
1957 const extra = tree.extraData(data.rhs, Node.Asm);1915 const extra = tree.extraData(extra_index, Node.Asm);
1916 const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index);
1958 return tree.fullAsmComponents(.{1917 return tree.fullAsmComponents(.{
1959 .asm_token = tree.nodes.items(.main_token)[node],1918 .asm_token = tree.nodeMainToken(node),
1960 .template = data.lhs,1919 .template = template,
1961 .items = tree.extra_data[extra.items_start..extra.items_end],1920 .items = items,
1962 .rparen = extra.rparen,1921 .rparen = extra.rparen,
1963 });1922 });
1964}1923}
19651924
1966pub fn whileSimple(tree: Ast, node: Node.Index) full.While {1925pub fn whileSimple(tree: Ast, node: Node.Index) full.While {
1967 const data = tree.nodes.items(.data)[node];1926 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
1968 return tree.fullWhileComponents(.{1927 return tree.fullWhileComponents(.{
1969 .while_token = tree.nodes.items(.main_token)[node],1928 .while_token = tree.nodeMainToken(node),
1970 .cond_expr = data.lhs,1929 .cond_expr = cond_expr,
1971 .cont_expr = 0,1930 .cont_expr = .none,
1972 .then_expr = data.rhs,1931 .then_expr = then_expr,
1973 .else_expr = 0,1932 .else_expr = .none,
1974 });1933 });
1975}1934}
19761935
1977pub fn whileCont(tree: Ast, node: Node.Index) full.While {1936pub fn whileCont(tree: Ast, node: Node.Index) full.While {
1978 const data = tree.nodes.items(.data)[node];1937 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1979 const extra = tree.extraData(data.rhs, Node.WhileCont);1938 const extra = tree.extraData(extra_index, Node.WhileCont);
1980 return tree.fullWhileComponents(.{1939 return tree.fullWhileComponents(.{
1981 .while_token = tree.nodes.items(.main_token)[node],1940 .while_token = tree.nodeMainToken(node),
1982 .cond_expr = data.lhs,1941 .cond_expr = cond_expr,
1983 .cont_expr = extra.cont_expr,1942 .cont_expr = extra.cont_expr.toOptional(),
1984 .then_expr = extra.then_expr,1943 .then_expr = extra.then_expr,
1985 .else_expr = 0,1944 .else_expr = .none,
1986 });1945 });
1987}1946}
19881947
1989pub fn whileFull(tree: Ast, node: Node.Index) full.While {1948pub fn whileFull(tree: Ast, node: Node.Index) full.While {
1990 const data = tree.nodes.items(.data)[node];1949 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1991 const extra = tree.extraData(data.rhs, Node.While);1950 const extra = tree.extraData(extra_index, Node.While);
1992 return tree.fullWhileComponents(.{1951 return tree.fullWhileComponents(.{
1993 .while_token = tree.nodes.items(.main_token)[node],1952 .while_token = tree.nodeMainToken(node),
1994 .cond_expr = data.lhs,1953 .cond_expr = cond_expr,
1995 .cont_expr = extra.cont_expr,1954 .cont_expr = extra.cont_expr,
1996 .then_expr = extra.then_expr,1955 .then_expr = extra.then_expr,
1997 .else_expr = extra.else_expr,1956 .else_expr = extra.else_expr.toOptional(),
1998 });1957 });
1999}1958}
20001959
2001pub fn forSimple(tree: Ast, node: Node.Index) full.For {1960pub fn forSimple(tree: Ast, node: Node.Index) full.For {
2002 const data = &tree.nodes.items(.data)[node];1961 const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node;
2003 const inputs: *[1]Node.Index = &data.lhs;
2004 return tree.fullForComponents(.{1962 return tree.fullForComponents(.{
2005 .for_token = tree.nodes.items(.main_token)[node],1963 .for_token = tree.nodeMainToken(node),
2006 .inputs = inputs[0..1],1964 .inputs = (&data[0])[0..1],
2007 .then_expr = data.rhs,1965 .then_expr = data[1],
2008 .else_expr = 0,1966 .else_expr = .none,
2009 });1967 });
2010}1968}
20111969
2012pub fn forFull(tree: Ast, node: Node.Index) full.For {1970pub fn forFull(tree: Ast, node: Node.Index) full.For {
2013 const data = tree.nodes.items(.data)[node];1971 const extra_index, const extra = tree.nodeData(node).@"for";
2014 const extra = @as(Node.For, @bitCast(data.rhs));1972 const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index);
2015 const inputs = tree.extra_data[data.lhs..][0..extra.inputs];1973 const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]);
2016 const then_expr = tree.extra_data[data.lhs + extra.inputs];1974 const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none;
2017 const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0;
2018 return tree.fullForComponents(.{1975 return tree.fullForComponents(.{
2019 .for_token = tree.nodes.items(.main_token)[node],1976 .for_token = tree.nodeMainToken(node),
2020 .inputs = inputs,1977 .inputs = inputs,
2021 .then_expr = then_expr,1978 .then_expr = then_expr,
2022 .else_expr = else_expr,1979 .else_expr = else_expr,
...@@ -2024,28 +1981,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {...@@ -2024,28 +1981,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
2024}1981}
20251982
2026pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {1983pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
2027 const data = tree.nodes.items(.data)[node];1984 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
2028 buffer.* = .{data.rhs};1985 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
2029 const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0];
2030 return tree.fullCallComponents(.{1986 return tree.fullCallComponents(.{
2031 .lparen = tree.nodes.items(.main_token)[node],1987 .lparen = tree.nodeMainToken(node),
2032 .fn_expr = data.lhs,1988 .fn_expr = fn_expr,
2033 .params = params,1989 .params = params,
2034 });1990 });
2035}1991}
20361992
2037pub fn callFull(tree: Ast, node: Node.Index) full.Call {1993pub fn callFull(tree: Ast, node: Node.Index) full.Call {
2038 const data = tree.nodes.items(.data)[node];1994 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
2039 const extra = tree.extraData(data.rhs, Node.SubRange);1995 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
2040 return tree.fullCallComponents(.{1996 return tree.fullCallComponents(.{
2041 .lparen = tree.nodes.items(.main_token)[node],1997 .lparen = tree.nodeMainToken(node),
2042 .fn_expr = data.lhs,1998 .fn_expr = fn_expr,
2043 .params = tree.extra_data[extra.start..extra.end],1999 .params = params,
2044 });2000 });
2045}2001}
20462002
2047fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {2003fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
2048 const token_tags = tree.tokens.items(.tag);
2049 var result: full.VarDecl = .{2004 var result: full.VarDecl = .{
2050 .ast = info,2005 .ast = info,
2051 .visib_token = null,2006 .visib_token = null,
...@@ -2057,7 +2012,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl...@@ -2057,7 +2012,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
2057 var i = info.mut_token;2012 var i = info.mut_token;
2058 while (i > 0) {2013 while (i > 0) {
2059 i -= 1;2014 i -= 1;
2060 switch (token_tags[i]) {2015 switch (tree.tokenTag(i)) {
2061 .keyword_extern, .keyword_export => result.extern_export_token = i,2016 .keyword_extern, .keyword_export => result.extern_export_token = i,
2062 .keyword_comptime => result.comptime_token = i,2017 .keyword_comptime => result.comptime_token = i,
2063 .keyword_pub => result.visib_token = i,2018 .keyword_pub => result.visib_token = i,
...@@ -2070,14 +2025,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl...@@ -2070,14 +2025,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
2070}2025}
20712026
2072fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {2027fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {
2073 const token_tags = tree.tokens.items(.tag);
2074 const node_tags = tree.nodes.items(.tag);
2075 var result: full.AssignDestructure = .{2028 var result: full.AssignDestructure = .{
2076 .comptime_token = null,2029 .comptime_token = null,
2077 .ast = info,2030 .ast = info,
2078 };2031 };
2079 const first_variable_token = tree.firstToken(info.variables[0]);2032 const first_variable_token = tree.firstToken(info.variables[0]);
2080 const maybe_comptime_token = switch (node_tags[info.variables[0]]) {2033 const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) {
2081 .global_var_decl,2034 .global_var_decl,
2082 .local_var_decl,2035 .local_var_decl,
2083 .aligned_var_decl,2036 .aligned_var_decl,
...@@ -2085,14 +2038,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo...@@ -2085,14 +2038,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo
2085 => first_variable_token,2038 => first_variable_token,
2086 else => first_variable_token - 1,2039 else => first_variable_token - 1,
2087 };2040 };
2088 if (token_tags[maybe_comptime_token] == .keyword_comptime) {2041 if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) {
2089 result.comptime_token = maybe_comptime_token;2042 result.comptime_token = maybe_comptime_token;
2090 }2043 }
2091 return result;2044 return result;
2092}2045}
20932046
2094fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {2047fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
2095 const token_tags = tree.tokens.items(.tag);
2096 var result: full.If = .{2048 var result: full.If = .{
2097 .ast = info,2049 .ast = info,
2098 .payload_token = null,2050 .payload_token = null,
...@@ -2102,14 +2054,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {...@@ -2102,14 +2054,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
2102 // if (cond_expr) |x|2054 // if (cond_expr) |x|
2103 // ^ ^2055 // ^ ^
2104 const payload_pipe = tree.lastToken(info.cond_expr) + 2;2056 const payload_pipe = tree.lastToken(info.cond_expr) + 2;
2105 if (token_tags[payload_pipe] == .pipe) {2057 if (tree.tokenTag(payload_pipe) == .pipe) {
2106 result.payload_token = payload_pipe + 1;2058 result.payload_token = payload_pipe + 1;
2107 }2059 }
2108 if (info.else_expr != 0) {2060 if (info.else_expr != .none) {
2109 // then_expr else |x|2061 // then_expr else |x|
2110 // ^ ^2062 // ^ ^
2111 result.else_token = tree.lastToken(info.then_expr) + 1;2063 result.else_token = tree.lastToken(info.then_expr) + 1;
2112 if (token_tags[result.else_token + 1] == .pipe) {2064 if (tree.tokenTag(result.else_token + 1) == .pipe) {
2113 result.error_token = result.else_token + 2;2065 result.error_token = result.else_token + 2;
2114 }2066 }
2115 }2067 }
...@@ -2117,12 +2069,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {...@@ -2117,12 +2069,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
2117}2069}
21182070
2119fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {2071fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {
2120 const token_tags = tree.tokens.items(.tag);
2121 var result: full.ContainerField = .{2072 var result: full.ContainerField = .{
2122 .ast = info,2073 .ast = info,
2123 .comptime_token = null,2074 .comptime_token = null,
2124 };2075 };
2125 if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {2076 if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) {
2126 // comptime type = init,2077 // comptime type = init,
2127 // ^ ^2078 // ^ ^
2128 // comptime name: type = init,2079 // comptime name: type = init,
...@@ -2133,7 +2084,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)...@@ -2133,7 +2084,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)
2133}2084}
21342085
2135fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {2086fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {
2136 const token_tags = tree.tokens.items(.tag);
2137 var result: full.FnProto = .{2087 var result: full.FnProto = .{
2138 .ast = info,2088 .ast = info,
2139 .visib_token = null,2089 .visib_token = null,
...@@ -2145,7 +2095,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto...@@ -2145,7 +2095,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
2145 var i = info.fn_token;2095 var i = info.fn_token;
2146 while (i > 0) {2096 while (i > 0) {
2147 i -= 1;2097 i -= 1;
2148 switch (token_tags[i]) {2098 switch (tree.tokenTag(i)) {
2149 .keyword_extern,2099 .keyword_extern,
2150 .keyword_export,2100 .keyword_export,
2151 .keyword_inline,2101 .keyword_inline,
...@@ -2157,25 +2107,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto...@@ -2157,25 +2107,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
2157 }2107 }
2158 }2108 }
2159 const after_fn_token = info.fn_token + 1;2109 const after_fn_token = info.fn_token + 1;
2160 if (token_tags[after_fn_token] == .identifier) {2110 if (tree.tokenTag(after_fn_token) == .identifier) {
2161 result.name_token = after_fn_token;2111 result.name_token = after_fn_token;
2162 result.lparen = after_fn_token + 1;2112 result.lparen = after_fn_token + 1;
2163 } else {2113 } else {
2164 result.lparen = after_fn_token;2114 result.lparen = after_fn_token;
2165 }2115 }
2166 assert(token_tags[result.lparen] == .l_paren);2116 assert(tree.tokenTag(result.lparen) == .l_paren);
21672117
2168 return result;2118 return result;
2169}2119}
21702120
2171fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {2121fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {
2172 const token_tags = tree.tokens.items(.tag);2122 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {
2173 const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) {
2174 .asterisk,2123 .asterisk,
2175 .asterisk_asterisk,2124 .asterisk_asterisk,
2176 => .one,2125 => .one,
2177 .l_bracket => switch (token_tags[info.main_token + 1]) {2126 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {
2178 .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many,2127 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,
2179 else => .slice,2128 else => .slice,
2180 },2129 },
2181 else => unreachable,2130 else => unreachable,
...@@ -2191,23 +2140,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType...@@ -2191,23 +2140,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
2191 // here while looking for modifiers as that could result in false2140 // here while looking for modifiers as that could result in false
2192 // positives. Therefore, start after a sentinel if there is one and2141 // positives. Therefore, start after a sentinel if there is one and
2193 // skip over any align node and bit range nodes.2142 // skip over any align node and bit range nodes.
2194 var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) {2143 var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) {
2195 .many, .c => info.main_token + 1,2144 .many, .c => info.main_token + 1,
2196 else => info.main_token,2145 else => info.main_token,
2197 };2146 };
2198 const end = tree.firstToken(info.child_type);2147 const end = tree.firstToken(info.child_type);
2199 while (i < end) : (i += 1) {2148 while (i < end) : (i += 1) {
2200 switch (token_tags[i]) {2149 switch (tree.tokenTag(i)) {
2201 .keyword_allowzero => result.allowzero_token = i,2150 .keyword_allowzero => result.allowzero_token = i,
2202 .keyword_const => result.const_token = i,2151 .keyword_const => result.const_token = i,
2203 .keyword_volatile => result.volatile_token = i,2152 .keyword_volatile => result.volatile_token = i,
2204 .keyword_align => {2153 .keyword_align => {
2205 assert(info.align_node != 0);2154 const align_node = info.align_node.unwrap().?;
2206 if (info.bit_range_end != 0) {2155 if (info.bit_range_end.unwrap()) |bit_range_end| {
2207 assert(info.bit_range_start != 0);2156 assert(info.bit_range_start != .none);
2208 i = tree.lastToken(info.bit_range_end) + 1;2157 i = tree.lastToken(bit_range_end) + 1;
2209 } else {2158 } else {
2210 i = tree.lastToken(info.align_node) + 1;2159 i = tree.lastToken(align_node) + 1;
2211 }2160 }
2212 },2161 },
2213 else => {},2162 else => {},
...@@ -2217,30 +2166,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType...@@ -2217,30 +2166,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
2217}2166}
22182167
2219fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {2168fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {
2220 const token_tags = tree.tokens.items(.tag);
2221 var result: full.ContainerDecl = .{2169 var result: full.ContainerDecl = .{
2222 .ast = info,2170 .ast = info,
2223 .layout_token = null,2171 .layout_token = null,
2224 };2172 };
22252173
2226 if (info.main_token == 0) return result;2174 if (info.main_token == 0) return result; // .root
2175 const previous_token = info.main_token - 1;
22272176
2228 switch (token_tags[info.main_token - 1]) {2177 switch (tree.tokenTag(previous_token)) {
2229 .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1,2178 .keyword_extern, .keyword_packed => result.layout_token = previous_token,
2230 else => {},2179 else => {},
2231 }2180 }
2232 return result;2181 return result;
2233}2182}
22342183
2235fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {2184fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2236 const token_tags = tree.tokens.items(.tag);
2237 const tok_i = info.switch_token -| 1;2185 const tok_i = info.switch_token -| 1;
2238 var result: full.Switch = .{2186 var result: full.Switch = .{
2239 .ast = info,2187 .ast = info,
2240 .label_token = null,2188 .label_token = null,
2241 };2189 };
2242 if (token_tags[tok_i] == .colon and2190 if (tree.tokenTag(tok_i) == .colon and
2243 token_tags[tok_i -| 1] == .identifier)2191 tree.tokenTag(tok_i -| 1) == .identifier)
2244 {2192 {
2245 result.label_token = tok_i - 1;2193 result.label_token = tok_i - 1;
2246 }2194 }
...@@ -2248,26 +2196,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {...@@ -2248,26 +2196,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2248}2196}
22492197
2250fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {2198fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
2251 const token_tags = tree.tokens.items(.tag);
2252 const node_tags = tree.nodes.items(.tag);
2253 var result: full.SwitchCase = .{2199 var result: full.SwitchCase = .{
2254 .ast = info,2200 .ast = info,
2255 .payload_token = null,2201 .payload_token = null,
2256 .inline_token = null,2202 .inline_token = null,
2257 };2203 };
2258 if (token_tags[info.arrow_token + 1] == .pipe) {2204 if (tree.tokenTag(info.arrow_token + 1) == .pipe) {
2259 result.payload_token = info.arrow_token + 2;2205 result.payload_token = info.arrow_token + 2;
2260 }2206 }
2261 switch (node_tags[node]) {2207 result.inline_token = switch (tree.nodeTag(node)) {
2262 .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node),2208 .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0)
2263 else => {},2209 info.arrow_token - 2
2264 }2210 else
2211 tree.firstToken(result.ast.values[0]) - 1,
2212 else => null,
2213 };
2265 return result;2214 return result;
2266}2215}
22672216
2268fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {2217fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2269 const token_tags = tree.tokens.items(.tag);
2270 const node_tags = tree.nodes.items(.tag);
2271 var result: full.Asm = .{2218 var result: full.Asm = .{
2272 .ast = info,2219 .ast = info,
2273 .volatile_token = null,2220 .volatile_token = null,
...@@ -2275,11 +2222,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2275,11 +2222,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2275 .outputs = &.{},2222 .outputs = &.{},
2276 .first_clobber = null,2223 .first_clobber = null,
2277 };2224 };
2278 if (token_tags[info.asm_token + 1] == .keyword_volatile) {2225 if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) {
2279 result.volatile_token = info.asm_token + 1;2226 result.volatile_token = info.asm_token + 1;
2280 }2227 }
2281 const outputs_end: usize = for (info.items, 0..) |item, i| {2228 const outputs_end: usize = for (info.items, 0..) |item, i| {
2282 switch (node_tags[item]) {2229 switch (tree.nodeTag(item)) {
2283 .asm_output => continue,2230 .asm_output => continue,
2284 else => break i,2231 else => break i,
2285 }2232 }
...@@ -2291,10 +2238,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2291,10 +2238,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2291 if (info.items.len == 0) {2238 if (info.items.len == 0) {
2292 // asm ("foo" ::: "a", "b");2239 // asm ("foo" ::: "a", "b");
2293 const template_token = tree.lastToken(info.template);2240 const template_token = tree.lastToken(info.template);
2294 if (token_tags[template_token + 1] == .colon and2241 if (tree.tokenTag(template_token + 1) == .colon and
2295 token_tags[template_token + 2] == .colon and2242 tree.tokenTag(template_token + 2) == .colon and
2296 token_tags[template_token + 3] == .colon and2243 tree.tokenTag(template_token + 3) == .colon and
2297 token_tags[template_token + 4] == .string_literal)2244 tree.tokenTag(template_token + 4) == .string_literal)
2298 {2245 {
2299 result.first_clobber = template_token + 4;2246 result.first_clobber = template_token + 4;
2300 }2247 }
...@@ -2304,9 +2251,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2304,9 +2251,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2304 const rparen = tree.lastToken(last_input);2251 const rparen = tree.lastToken(last_input);
2305 var i = rparen + 1;2252 var i = rparen + 1;
2306 // Allow a (useless) comma right after the closing parenthesis.2253 // Allow a (useless) comma right after the closing parenthesis.
2307 if (token_tags[i] == .comma) i += 1;2254 if (tree.tokenTag(i) == .comma) i = i + 1;
2308 if (token_tags[i] == .colon and2255 if (tree.tokenTag(i) == .colon and
2309 token_tags[i + 1] == .string_literal)2256 tree.tokenTag(i + 1) == .string_literal)
2310 {2257 {
2311 result.first_clobber = i + 1;2258 result.first_clobber = i + 1;
2312 }2259 }
...@@ -2316,10 +2263,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2316,10 +2263,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2316 const rparen = tree.lastToken(last_output);2263 const rparen = tree.lastToken(last_output);
2317 var i = rparen + 1;2264 var i = rparen + 1;
2318 // Allow a (useless) comma right after the closing parenthesis.2265 // Allow a (useless) comma right after the closing parenthesis.
2319 if (token_tags[i] == .comma) i += 1;2266 if (tree.tokenTag(i) == .comma) i = i + 1;
2320 if (token_tags[i] == .colon and2267 if (tree.tokenTag(i) == .colon and
2321 token_tags[i + 1] == .colon and2268 tree.tokenTag(i + 1) == .colon and
2322 token_tags[i + 2] == .string_literal)2269 tree.tokenTag(i + 2) == .string_literal)
2323 {2270 {
2324 result.first_clobber = i + 2;2271 result.first_clobber = i + 2;
2325 }2272 }
...@@ -2329,7 +2276,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2329,7 +2276,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2329}2276}
23302277
2331fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {2278fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2332 const token_tags = tree.tokens.items(.tag);
2333 var result: full.While = .{2279 var result: full.While = .{
2334 .ast = info,2280 .ast = info,
2335 .inline_token = null,2281 .inline_token = null,
...@@ -2338,25 +2284,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {...@@ -2338,25 +2284,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2338 .else_token = undefined,2284 .else_token = undefined,
2339 .error_token = null,2285 .error_token = null,
2340 };2286 };
2341 var tok_i = info.while_token -| 1;2287 var tok_i = info.while_token;
2342 if (token_tags[tok_i] == .keyword_inline) {2288 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2343 result.inline_token = tok_i;2289 result.inline_token = tok_i - 1;
2344 tok_i -|= 1;2290 tok_i = tok_i - 1;
2345 }2291 }
2346 if (token_tags[tok_i] == .colon and2292 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2347 token_tags[tok_i -| 1] == .identifier)2293 result.label_token = tok_i - 2;
2348 {
2349 result.label_token = tok_i - 1;
2350 }2294 }
2351 const last_cond_token = tree.lastToken(info.cond_expr);2295 const last_cond_token = tree.lastToken(info.cond_expr);
2352 if (token_tags[last_cond_token + 2] == .pipe) {2296 if (tree.tokenTag(last_cond_token + 2) == .pipe) {
2353 result.payload_token = last_cond_token + 3;2297 result.payload_token = last_cond_token + 3;
2354 }2298 }
2355 if (info.else_expr != 0) {2299 if (info.else_expr != .none) {
2356 // then_expr else |x|2300 // then_expr else |x|
2357 // ^ ^2301 // ^ ^
2358 result.else_token = tree.lastToken(info.then_expr) + 1;2302 result.else_token = tree.lastToken(info.then_expr) + 1;
2359 if (token_tags[result.else_token + 1] == .pipe) {2303 if (tree.tokenTag(result.else_token + 1) == .pipe) {
2360 result.error_token = result.else_token + 2;2304 result.error_token = result.else_token + 2;
2361 }2305 }
2362 }2306 }
...@@ -2364,7 +2308,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {...@@ -2364,7 +2308,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2364}2308}
23652309
2366fn fullForComponents(tree: Ast, info: full.For.Components) full.For {2310fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2367 const token_tags = tree.tokens.items(.tag);
2368 var result: full.For = .{2311 var result: full.For = .{
2369 .ast = info,2312 .ast = info,
2370 .inline_token = null,2313 .inline_token = null,
...@@ -2372,39 +2315,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {...@@ -2372,39 +2315,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2372 .payload_token = undefined,2315 .payload_token = undefined,
2373 .else_token = undefined,2316 .else_token = undefined,
2374 };2317 };
2375 var tok_i = info.for_token -| 1;2318 var tok_i = info.for_token;
2376 if (token_tags[tok_i] == .keyword_inline) {2319 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2377 result.inline_token = tok_i;2320 result.inline_token = tok_i - 1;
2378 tok_i -|= 1;2321 tok_i = tok_i - 1;
2379 }2322 }
2380 if (token_tags[tok_i] == .colon and2323 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2381 token_tags[tok_i -| 1] == .identifier)2324 result.label_token = tok_i - 2;
2382 {
2383 result.label_token = tok_i - 1;
2384 }2325 }
2385 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);2326 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);
2386 result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma);2327 result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma);
2387 if (info.else_expr != 0) {2328 if (info.else_expr != .none) {
2388 result.else_token = tree.lastToken(info.then_expr) + 1;2329 result.else_token = tree.lastToken(info.then_expr) + 1;
2389 }2330 }
2390 return result;2331 return result;
2391}2332}
23922333
2393fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {2334fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
2394 const token_tags = tree.tokens.items(.tag);
2395 var result: full.Call = .{2335 var result: full.Call = .{
2396 .ast = info,2336 .ast = info,
2397 .async_token = null,2337 .async_token = null,
2398 };2338 };
2399 const first_token = tree.firstToken(info.fn_expr);2339 const first_token = tree.firstToken(info.fn_expr);
2400 if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) {2340 if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
2401 result.async_token = first_token - 1;2341 result.async_token = first_token - 1;
2402 }2342 }
2403 return result;2343 return result;
2404}2344}
24052345
2406pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {2346pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2407 return switch (tree.nodes.items(.tag)[node]) {2347 return switch (tree.nodeTag(node)) {
2408 .global_var_decl => tree.globalVarDecl(node),2348 .global_var_decl => tree.globalVarDecl(node),
2409 .local_var_decl => tree.localVarDecl(node),2349 .local_var_decl => tree.localVarDecl(node),
2410 .aligned_var_decl => tree.alignedVarDecl(node),2350 .aligned_var_decl => tree.alignedVarDecl(node),
...@@ -2414,7 +2354,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {...@@ -2414,7 +2354,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2414}2354}
24152355
2416pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {2356pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2417 return switch (tree.nodes.items(.tag)[node]) {2357 return switch (tree.nodeTag(node)) {
2418 .if_simple => tree.ifSimple(node),2358 .if_simple => tree.ifSimple(node),
2419 .@"if" => tree.ifFull(node),2359 .@"if" => tree.ifFull(node),
2420 else => null,2360 else => null,
...@@ -2422,7 +2362,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {...@@ -2422,7 +2362,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2422}2362}
24232363
2424pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {2364pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2425 return switch (tree.nodes.items(.tag)[node]) {2365 return switch (tree.nodeTag(node)) {
2426 .while_simple => tree.whileSimple(node),2366 .while_simple => tree.whileSimple(node),
2427 .while_cont => tree.whileCont(node),2367 .while_cont => tree.whileCont(node),
2428 .@"while" => tree.whileFull(node),2368 .@"while" => tree.whileFull(node),
...@@ -2431,7 +2371,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {...@@ -2431,7 +2371,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2431}2371}
24322372
2433pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {2373pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2434 return switch (tree.nodes.items(.tag)[node]) {2374 return switch (tree.nodeTag(node)) {
2435 .for_simple => tree.forSimple(node),2375 .for_simple => tree.forSimple(node),
2436 .@"for" => tree.forFull(node),2376 .@"for" => tree.forFull(node),
2437 else => null,2377 else => null,
...@@ -2439,7 +2379,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {...@@ -2439,7 +2379,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2439}2379}
24402380
2441pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {2381pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2442 return switch (tree.nodes.items(.tag)[node]) {2382 return switch (tree.nodeTag(node)) {
2443 .container_field_init => tree.containerFieldInit(node),2383 .container_field_init => tree.containerFieldInit(node),
2444 .container_field_align => tree.containerFieldAlign(node),2384 .container_field_align => tree.containerFieldAlign(node),
2445 .container_field => tree.containerField(node),2385 .container_field => tree.containerField(node),
...@@ -2448,18 +2388,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {...@@ -2448,18 +2388,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2448}2388}
24492389
2450pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {2390pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {
2451 return switch (tree.nodes.items(.tag)[node]) {2391 return switch (tree.nodeTag(node)) {
2452 .fn_proto => tree.fnProto(node),2392 .fn_proto => tree.fnProto(node),
2453 .fn_proto_multi => tree.fnProtoMulti(node),2393 .fn_proto_multi => tree.fnProtoMulti(node),
2454 .fn_proto_one => tree.fnProtoOne(buffer, node),2394 .fn_proto_one => tree.fnProtoOne(buffer, node),
2455 .fn_proto_simple => tree.fnProtoSimple(buffer, node),2395 .fn_proto_simple => tree.fnProtoSimple(buffer, node),
2456 .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs),2396 .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]),
2457 else => null,2397 else => null,
2458 };2398 };
2459}2399}
24602400
2461pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {2401pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {
2462 return switch (tree.nodes.items(.tag)[node]) {2402 return switch (tree.nodeTag(node)) {
2463 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),2403 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),
2464 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),2404 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),
2465 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),2405 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),
...@@ -2469,7 +2409,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?...@@ -2469,7 +2409,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?
2469}2409}
24702410
2471pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {2411pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {
2472 return switch (tree.nodes.items(.tag)[node]) {2412 return switch (tree.nodeTag(node)) {
2473 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),2413 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),
2474 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),2414 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),
2475 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),2415 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),
...@@ -2479,7 +2419,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full....@@ -2479,7 +2419,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.
2479}2419}
24802420
2481pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {2421pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2482 return switch (tree.nodes.items(.tag)[node]) {2422 return switch (tree.nodeTag(node)) {
2483 .array_type => tree.arrayType(node),2423 .array_type => tree.arrayType(node),
2484 .array_type_sentinel => tree.arrayTypeSentinel(node),2424 .array_type_sentinel => tree.arrayTypeSentinel(node),
2485 else => null,2425 else => null,
...@@ -2487,7 +2427,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {...@@ -2487,7 +2427,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2487}2427}
24882428
2489pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {2429pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2490 return switch (tree.nodes.items(.tag)[node]) {2430 return switch (tree.nodeTag(node)) {
2491 .ptr_type_aligned => tree.ptrTypeAligned(node),2431 .ptr_type_aligned => tree.ptrTypeAligned(node),
2492 .ptr_type_sentinel => tree.ptrTypeSentinel(node),2432 .ptr_type_sentinel => tree.ptrTypeSentinel(node),
2493 .ptr_type => tree.ptrType(node),2433 .ptr_type => tree.ptrType(node),
...@@ -2497,7 +2437,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {...@@ -2497,7 +2437,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2497}2437}
24982438
2499pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {2439pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2500 return switch (tree.nodes.items(.tag)[node]) {2440 return switch (tree.nodeTag(node)) {
2501 .slice_open => tree.sliceOpen(node),2441 .slice_open => tree.sliceOpen(node),
2502 .slice => tree.slice(node),2442 .slice => tree.slice(node),
2503 .slice_sentinel => tree.sliceSentinel(node),2443 .slice_sentinel => tree.sliceSentinel(node),
...@@ -2506,7 +2446,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {...@@ -2506,7 +2446,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2506}2446}
25072447
2508pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {2448pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {
2509 return switch (tree.nodes.items(.tag)[node]) {2449 return switch (tree.nodeTag(node)) {
2510 .root => tree.containerDeclRoot(),2450 .root => tree.containerDeclRoot(),
2511 .container_decl, .container_decl_trailing => tree.containerDecl(node),2451 .container_decl, .container_decl_trailing => tree.containerDecl(node),
2512 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),2452 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
...@@ -2519,14 +2459,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index...@@ -2519,14 +2459,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index
2519}2459}
25202460
2521pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {2461pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {
2522 return switch (tree.nodes.items(.tag)[node]) {2462 return switch (tree.nodeTag(node)) {
2523 .@"switch", .switch_comma => tree.switchFull(node),2463 .@"switch", .switch_comma => tree.switchFull(node),
2524 else => null,2464 else => null,
2525 };2465 };
2526}2466}
25272467
2528pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {2468pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2529 return switch (tree.nodes.items(.tag)[node]) {2469 return switch (tree.nodeTag(node)) {
2530 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),2470 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),
2531 .switch_case, .switch_case_inline => tree.switchCase(node),2471 .switch_case, .switch_case_inline => tree.switchCase(node),
2532 else => null,2472 else => null,
...@@ -2534,7 +2474,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {...@@ -2534,7 +2474,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2534}2474}
25352475
2536pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {2476pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2537 return switch (tree.nodes.items(.tag)[node]) {2477 return switch (tree.nodeTag(node)) {
2538 .asm_simple => tree.asmSimple(node),2478 .asm_simple => tree.asmSimple(node),
2539 .@"asm" => tree.asmFull(node),2479 .@"asm" => tree.asmFull(node),
2540 else => null,2480 else => null,
...@@ -2542,13 +2482,29 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {...@@ -2542,13 +2482,29 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2542}2482}
25432483
2544pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {2484pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
2545 return switch (tree.nodes.items(.tag)[node]) {2485 return switch (tree.nodeTag(node)) {
2546 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),2486 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
2547 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),2487 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
2548 else => null,2488 else => null,
2549 };2489 };
2550}2490}
25512491
2492pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2493 return switch (tree.nodeTag(node)) {
2494 .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2495 .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2496 else => null,
2497 };
2498}
2499
2500pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2501 return switch (tree.nodeTag(node)) {
2502 .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2503 .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2504 else => null,
2505 };
2506}
2507
2552/// Fully assembled AST node information.2508/// Fully assembled AST node information.
2553pub const full = struct {2509pub const full = struct {
2554 pub const VarDecl = struct {2510 pub const VarDecl = struct {
...@@ -2561,11 +2517,11 @@ pub const full = struct {...@@ -2561,11 +2517,11 @@ pub const full = struct {
25612517
2562 pub const Components = struct {2518 pub const Components = struct {
2563 mut_token: TokenIndex,2519 mut_token: TokenIndex,
2564 type_node: Node.Index,2520 type_node: Node.OptionalIndex,
2565 align_node: Node.Index,2521 align_node: Node.OptionalIndex,
2566 addrspace_node: Node.Index,2522 addrspace_node: Node.OptionalIndex,
2567 section_node: Node.Index,2523 section_node: Node.OptionalIndex,
2568 init_node: Node.Index,2524 init_node: Node.OptionalIndex,
2569 };2525 };
25702526
2571 pub fn firstToken(var_decl: VarDecl) TokenIndex {2527 pub fn firstToken(var_decl: VarDecl) TokenIndex {
...@@ -2594,7 +2550,7 @@ pub const full = struct {...@@ -2594,7 +2550,7 @@ pub const full = struct {
2594 payload_token: ?TokenIndex,2550 payload_token: ?TokenIndex,
2595 /// Points to the identifier after the `|`.2551 /// Points to the identifier after the `|`.
2596 error_token: ?TokenIndex,2552 error_token: ?TokenIndex,
2597 /// Populated only if else_expr != 0.2553 /// Populated only if else_expr != .none.
2598 else_token: TokenIndex,2554 else_token: TokenIndex,
2599 ast: Components,2555 ast: Components,
26002556
...@@ -2602,7 +2558,7 @@ pub const full = struct {...@@ -2602,7 +2558,7 @@ pub const full = struct {
2602 if_token: TokenIndex,2558 if_token: TokenIndex,
2603 cond_expr: Node.Index,2559 cond_expr: Node.Index,
2604 then_expr: Node.Index,2560 then_expr: Node.Index,
2605 else_expr: Node.Index,2561 else_expr: Node.OptionalIndex,
2606 };2562 };
2607 };2563 };
26082564
...@@ -2612,15 +2568,15 @@ pub const full = struct {...@@ -2612,15 +2568,15 @@ pub const full = struct {
2612 label_token: ?TokenIndex,2568 label_token: ?TokenIndex,
2613 payload_token: ?TokenIndex,2569 payload_token: ?TokenIndex,
2614 error_token: ?TokenIndex,2570 error_token: ?TokenIndex,
2615 /// Populated only if else_expr != 0.2571 /// Populated only if else_expr != none.
2616 else_token: TokenIndex,2572 else_token: TokenIndex,
26172573
2618 pub const Components = struct {2574 pub const Components = struct {
2619 while_token: TokenIndex,2575 while_token: TokenIndex,
2620 cond_expr: Node.Index,2576 cond_expr: Node.Index,
2621 cont_expr: Node.Index,2577 cont_expr: Node.OptionalIndex,
2622 then_expr: Node.Index,2578 then_expr: Node.Index,
2623 else_expr: Node.Index,2579 else_expr: Node.OptionalIndex,
2624 };2580 };
2625 };2581 };
26262582
...@@ -2629,14 +2585,14 @@ pub const full = struct {...@@ -2629,14 +2585,14 @@ pub const full = struct {
2629 inline_token: ?TokenIndex,2585 inline_token: ?TokenIndex,
2630 label_token: ?TokenIndex,2586 label_token: ?TokenIndex,
2631 payload_token: TokenIndex,2587 payload_token: TokenIndex,
2632 /// Populated only if else_expr != 0.2588 /// Populated only if else_expr != .none.
2633 else_token: TokenIndex,2589 else_token: ?TokenIndex,
26342590
2635 pub const Components = struct {2591 pub const Components = struct {
2636 for_token: TokenIndex,2592 for_token: TokenIndex,
2637 inputs: []const Node.Index,2593 inputs: []const Node.Index,
2638 then_expr: Node.Index,2594 then_expr: Node.Index,
2639 else_expr: Node.Index,2595 else_expr: Node.OptionalIndex,
2640 };2596 };
2641 };2597 };
26422598
...@@ -2646,9 +2602,10 @@ pub const full = struct {...@@ -2646,9 +2602,10 @@ pub const full = struct {
26462602
2647 pub const Components = struct {2603 pub const Components = struct {
2648 main_token: TokenIndex,2604 main_token: TokenIndex,
2649 type_expr: Node.Index,2605 /// Can only be `.none` after calling `convertToNonTupleLike`.
2650 align_expr: Node.Index,2606 type_expr: Node.OptionalIndex,
2651 value_expr: Node.Index,2607 align_expr: Node.OptionalIndex,
2608 value_expr: Node.OptionalIndex,
2652 tuple_like: bool,2609 tuple_like: bool,
2653 };2610 };
26542611
...@@ -2656,11 +2613,11 @@ pub const full = struct {...@@ -2656,11 +2613,11 @@ pub const full = struct {
2656 return cf.comptime_token orelse cf.ast.main_token;2613 return cf.comptime_token orelse cf.ast.main_token;
2657 }2614 }
26582615
2659 pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void {2616 pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void {
2660 if (!cf.ast.tuple_like) return;2617 if (!cf.ast.tuple_like) return;
2661 if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return;2618 if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return;
26622619
2663 cf.ast.type_expr = 0;2620 cf.ast.type_expr = .none;
2664 cf.ast.tuple_like = false;2621 cf.ast.tuple_like = false;
2665 }2622 }
2666 };2623 };
...@@ -2676,12 +2633,12 @@ pub const full = struct {...@@ -2676,12 +2633,12 @@ pub const full = struct {
2676 pub const Components = struct {2633 pub const Components = struct {
2677 proto_node: Node.Index,2634 proto_node: Node.Index,
2678 fn_token: TokenIndex,2635 fn_token: TokenIndex,
2679 return_type: Node.Index,2636 return_type: Node.OptionalIndex,
2680 params: []const Node.Index,2637 params: []const Node.Index,
2681 align_expr: Node.Index,2638 align_expr: Node.OptionalIndex,
2682 addrspace_expr: Node.Index,2639 addrspace_expr: Node.OptionalIndex,
2683 section_expr: Node.Index,2640 section_expr: Node.OptionalIndex,
2684 callconv_expr: Node.Index,2641 callconv_expr: Node.OptionalIndex,
2685 };2642 };
26862643
2687 pub const Param = struct {2644 pub const Param = struct {
...@@ -2689,7 +2646,7 @@ pub const full = struct {...@@ -2689,7 +2646,7 @@ pub const full = struct {
2689 name_token: ?TokenIndex,2646 name_token: ?TokenIndex,
2690 comptime_noalias: ?TokenIndex,2647 comptime_noalias: ?TokenIndex,
2691 anytype_ellipsis3: ?TokenIndex,2648 anytype_ellipsis3: ?TokenIndex,
2692 type_expr: Node.Index,2649 type_expr: ?Node.Index,
2693 };2650 };
26942651
2695 pub fn firstToken(fn_proto: FnProto) TokenIndex {2652 pub fn firstToken(fn_proto: FnProto) TokenIndex {
...@@ -2709,7 +2666,7 @@ pub const full = struct {...@@ -2709,7 +2666,7 @@ pub const full = struct {
2709 tok_flag: bool,2666 tok_flag: bool,
27102667
2711 pub fn next(it: *Iterator) ?Param {2668 pub fn next(it: *Iterator) ?Param {
2712 const token_tags = it.tree.tokens.items(.tag);2669 const tree = it.tree;
2713 while (true) {2670 while (true) {
2714 var first_doc_comment: ?TokenIndex = null;2671 var first_doc_comment: ?TokenIndex = null;
2715 var comptime_noalias: ?TokenIndex = null;2672 var comptime_noalias: ?TokenIndex = null;
...@@ -2719,8 +2676,8 @@ pub const full = struct {...@@ -2719,8 +2676,8 @@ pub const full = struct {
2719 return null;2676 return null;
2720 }2677 }
2721 const param_type = it.fn_proto.ast.params[it.param_i];2678 const param_type = it.fn_proto.ast.params[it.param_i];
2722 var tok_i = it.tree.firstToken(param_type) - 1;2679 var tok_i = tree.firstToken(param_type) - 1;
2723 while (true) : (tok_i -= 1) switch (token_tags[tok_i]) {2680 while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) {
2724 .colon => continue,2681 .colon => continue,
2725 .identifier => name_token = tok_i,2682 .identifier => name_token = tok_i,
2726 .doc_comment => first_doc_comment = tok_i,2683 .doc_comment => first_doc_comment = tok_i,
...@@ -2728,9 +2685,9 @@ pub const full = struct {...@@ -2728,9 +2685,9 @@ pub const full = struct {
2728 else => break,2685 else => break,
2729 };2686 };
2730 it.param_i += 1;2687 it.param_i += 1;
2731 it.tok_i = it.tree.lastToken(param_type) + 1;2688 it.tok_i = tree.lastToken(param_type) + 1;
2732 // Look for anytype and ... params afterwards.2689 // Look for anytype and ... params afterwards.
2733 if (token_tags[it.tok_i] == .comma) {2690 if (tree.tokenTag(it.tok_i) == .comma) {
2734 it.tok_i += 1;2691 it.tok_i += 1;
2735 }2692 }
2736 it.tok_flag = true;2693 it.tok_flag = true;
...@@ -2742,19 +2699,19 @@ pub const full = struct {...@@ -2742,19 +2699,19 @@ pub const full = struct {
2742 .type_expr = param_type,2699 .type_expr = param_type,
2743 };2700 };
2744 }2701 }
2745 if (token_tags[it.tok_i] == .comma) {2702 if (tree.tokenTag(it.tok_i) == .comma) {
2746 it.tok_i += 1;2703 it.tok_i += 1;
2747 }2704 }
2748 if (token_tags[it.tok_i] == .r_paren) {2705 if (tree.tokenTag(it.tok_i) == .r_paren) {
2749 return null;2706 return null;
2750 }2707 }
2751 if (token_tags[it.tok_i] == .doc_comment) {2708 if (tree.tokenTag(it.tok_i) == .doc_comment) {
2752 first_doc_comment = it.tok_i;2709 first_doc_comment = it.tok_i;
2753 while (token_tags[it.tok_i] == .doc_comment) {2710 while (tree.tokenTag(it.tok_i) == .doc_comment) {
2754 it.tok_i += 1;2711 it.tok_i += 1;
2755 }2712 }
2756 }2713 }
2757 switch (token_tags[it.tok_i]) {2714 switch (tree.tokenTag(it.tok_i)) {
2758 .ellipsis3 => {2715 .ellipsis3 => {
2759 it.tok_flag = false; // Next iteration should return null.2716 it.tok_flag = false; // Next iteration should return null.
2760 return Param{2717 return Param{
...@@ -2762,7 +2719,7 @@ pub const full = struct {...@@ -2762,7 +2719,7 @@ pub const full = struct {
2762 .comptime_noalias = null,2719 .comptime_noalias = null,
2763 .name_token = null,2720 .name_token = null,
2764 .anytype_ellipsis3 = it.tok_i,2721 .anytype_ellipsis3 = it.tok_i,
2765 .type_expr = 0,2722 .type_expr = null,
2766 };2723 };
2767 },2724 },
2768 .keyword_noalias, .keyword_comptime => {2725 .keyword_noalias, .keyword_comptime => {
...@@ -2771,20 +2728,20 @@ pub const full = struct {...@@ -2771,20 +2728,20 @@ pub const full = struct {
2771 },2728 },
2772 else => {},2729 else => {},
2773 }2730 }
2774 if (token_tags[it.tok_i] == .identifier and2731 if (tree.tokenTag(it.tok_i) == .identifier and
2775 token_tags[it.tok_i + 1] == .colon)2732 tree.tokenTag(it.tok_i + 1) == .colon)
2776 {2733 {
2777 name_token = it.tok_i;2734 name_token = it.tok_i;
2778 it.tok_i += 2;2735 it.tok_i += 2;
2779 }2736 }
2780 if (token_tags[it.tok_i] == .keyword_anytype) {2737 if (tree.tokenTag(it.tok_i) == .keyword_anytype) {
2781 it.tok_i += 1;2738 it.tok_i += 1;
2782 return Param{2739 return Param{
2783 .first_doc_comment = first_doc_comment,2740 .first_doc_comment = first_doc_comment,
2784 .comptime_noalias = comptime_noalias,2741 .comptime_noalias = comptime_noalias,
2785 .name_token = name_token,2742 .name_token = name_token,
2786 .anytype_ellipsis3 = it.tok_i - 1,2743 .anytype_ellipsis3 = it.tok_i - 1,
2787 .type_expr = 0,2744 .type_expr = null,
2788 };2745 };
2789 }2746 }
2790 it.tok_flag = false;2747 it.tok_flag = false;
...@@ -2809,7 +2766,7 @@ pub const full = struct {...@@ -2809,7 +2766,7 @@ pub const full = struct {
2809 pub const Components = struct {2766 pub const Components = struct {
2810 lbrace: TokenIndex,2767 lbrace: TokenIndex,
2811 fields: []const Node.Index,2768 fields: []const Node.Index,
2812 type_expr: Node.Index,2769 type_expr: Node.OptionalIndex,
2813 };2770 };
2814 };2771 };
28152772
...@@ -2819,7 +2776,7 @@ pub const full = struct {...@@ -2819,7 +2776,7 @@ pub const full = struct {
2819 pub const Components = struct {2776 pub const Components = struct {
2820 lbrace: TokenIndex,2777 lbrace: TokenIndex,
2821 elements: []const Node.Index,2778 elements: []const Node.Index,
2822 type_expr: Node.Index,2779 type_expr: Node.OptionalIndex,
2823 };2780 };
2824 };2781 };
28252782
...@@ -2829,7 +2786,7 @@ pub const full = struct {...@@ -2829,7 +2786,7 @@ pub const full = struct {
2829 pub const Components = struct {2786 pub const Components = struct {
2830 lbracket: TokenIndex,2787 lbracket: TokenIndex,
2831 elem_count: Node.Index,2788 elem_count: Node.Index,
2832 sentinel: Node.Index,2789 sentinel: Node.OptionalIndex,
2833 elem_type: Node.Index,2790 elem_type: Node.Index,
2834 };2791 };
2835 };2792 };
...@@ -2843,11 +2800,11 @@ pub const full = struct {...@@ -2843,11 +2800,11 @@ pub const full = struct {
28432800
2844 pub const Components = struct {2801 pub const Components = struct {
2845 main_token: TokenIndex,2802 main_token: TokenIndex,
2846 align_node: Node.Index,2803 align_node: Node.OptionalIndex,
2847 addrspace_node: Node.Index,2804 addrspace_node: Node.OptionalIndex,
2848 sentinel: Node.Index,2805 sentinel: Node.OptionalIndex,
2849 bit_range_start: Node.Index,2806 bit_range_start: Node.OptionalIndex,
2850 bit_range_end: Node.Index,2807 bit_range_end: Node.OptionalIndex,
2851 child_type: Node.Index,2808 child_type: Node.Index,
2852 };2809 };
2853 };2810 };
...@@ -2859,8 +2816,8 @@ pub const full = struct {...@@ -2859,8 +2816,8 @@ pub const full = struct {
2859 sliced: Node.Index,2816 sliced: Node.Index,
2860 lbracket: TokenIndex,2817 lbracket: TokenIndex,
2861 start: Node.Index,2818 start: Node.Index,
2862 end: Node.Index,2819 end: Node.OptionalIndex,
2863 sentinel: Node.Index,2820 sentinel: Node.OptionalIndex,
2864 };2821 };
2865 };2822 };
28662823
...@@ -2873,7 +2830,7 @@ pub const full = struct {...@@ -2873,7 +2830,7 @@ pub const full = struct {
2873 /// Populated when main_token is Keyword_union.2830 /// Populated when main_token is Keyword_union.
2874 enum_token: ?TokenIndex,2831 enum_token: ?TokenIndex,
2875 members: []const Node.Index,2832 members: []const Node.Index,
2876 arg: Node.Index,2833 arg: Node.OptionalIndex,
2877 };2834 };
2878 };2835 };
28792836
...@@ -3016,492 +2973,971 @@ pub const Error = struct {...@@ -3016,492 +2973,971 @@ pub const Error = struct {
3016 };2973 };
3017};2974};
30182975
2976/// Index into `extra_data`.
2977pub const ExtraIndex = enum(u32) {
2978 _,
2979};
2980
3019pub const Node = struct {2981pub const Node = struct {
3020 tag: Tag,2982 tag: Tag,
3021 main_token: TokenIndex,2983 main_token: TokenIndex,
3022 data: Data,2984 data: Data,
30232985
3024 pub const Index = u32;2986 /// Index into `nodes`.
2987 pub const Index = enum(u32) {
2988 root = 0,
2989 _,
2990
2991 pub fn toOptional(i: Index) OptionalIndex {
2992 const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
2993 assert(result != .none);
2994 return result;
2995 }
2996
2997 pub fn toOffset(base: Index, destination: Index) Offset {
2998 const base_i64: i64 = @intFromEnum(base);
2999 const destination_i64: i64 = @intFromEnum(destination);
3000 return @enumFromInt(destination_i64 - base_i64);
3001 }
3002 };
3003
3004 /// Index into `nodes`, or null.
3005 pub const OptionalIndex = enum(u32) {
3006 root = 0,
3007 none = std.math.maxInt(u32),
3008 _,
3009
3010 pub fn unwrap(oi: OptionalIndex) ?Index {
3011 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
3012 }
3013
3014 pub fn fromOptional(oi: ?Index) OptionalIndex {
3015 return if (oi) |i| i.toOptional() else .none;
3016 }
3017 };
3018
3019 /// A relative node index.
3020 pub const Offset = enum(i32) {
3021 zero = 0,
3022 _,
3023
3024 pub fn toOptional(o: Offset) OptionalOffset {
3025 const result: OptionalOffset = @enumFromInt(@intFromEnum(o));
3026 assert(result != .none);
3027 return result;
3028 }
3029
3030 pub fn toAbsolute(offset: Offset, base: Index) Index {
3031 return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset));
3032 }
3033 };
3034
3035 /// A relative node index, or null.
3036 pub const OptionalOffset = enum(i32) {
3037 none = std.math.maxInt(i32),
3038 _,
3039
3040 pub fn unwrap(oo: OptionalOffset) ?Offset {
3041 return if (oo == .none) null else @enumFromInt(@intFromEnum(oo));
3042 }
3043 };
30253044
3026 comptime {3045 comptime {
3027 // Goal is to keep this under one byte for efficiency.3046 // Goal is to keep this under one byte for efficiency.
3028 assert(@sizeOf(Tag) == 1);3047 assert(@sizeOf(Tag) == 1);
3048
3049 if (!std.debug.runtime_safety) {
3050 assert(@sizeOf(Data) == 8);
3051 }
3029 }3052 }
30303053
3031 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of3054 /// The FooComma/FooSemicolon variants exist to ease the implementation of
3032 /// Ast.lastToken()3055 /// `Ast.lastToken()`
3033 pub const Tag = enum {3056 pub const Tag = enum {
3034 /// sub_list[lhs...rhs]3057 /// The root node which is guaranteed to be at `Node.Index.root`.
3058 /// The meaning of the `data` field depends on whether it is a `.zig` or
3059 /// `.zon` file.
3060 ///
3061 /// The `main_token` field is the first token for the source file.
3035 root,3062 root,
3036 /// `usingnamespace lhs;`. rhs unused. main_token is `usingnamespace`.3063 /// `usingnamespace expr;`.
3064 ///
3065 /// The `data` field is a `.node` to expr.
3066 ///
3067 /// The `main_token` field is the `usingnamespace` token.
3037 @"usingnamespace",3068 @"usingnamespace",
3038 /// lhs is test name token (must be string literal or identifier), if any.3069 /// `test {}`,
3039 /// rhs is the body node.3070 /// `test "name" {}`,
3071 /// `test identifier {}`.
3072 ///
3073 /// The `data` field is a `.opt_token_and_node`:
3074 /// 1. a `OptionalTokenIndex` to the test name token (must be string literal or identifier), if any.
3075 /// 2. a `Node.Index` to the block.
3076 ///
3077 /// The `main_token` field is the `test` token.
3040 test_decl,3078 test_decl,
3041 /// lhs is the index into extra_data.3079 /// The `data` field is a `.extra_and_opt_node`:
3042 /// rhs is the initialization expression, if any.3080 /// 1. a `ExtraIndex` to `GlobalVarDecl`.
3043 /// main_token is `var` or `const`.3081 /// 2. a `Node.OptionalIndex` to the initialization expression.
3082 ///
3083 /// The `main_token` field is the `var` or `const` token.
3084 ///
3085 /// The initialization expression can't be `.none` unless it is part of
3086 /// a `assign_destructure` node or a parsing error occured.
3044 global_var_decl,3087 global_var_decl,
3045 /// `var a: x align(y) = rhs`3088 /// `var a: b align(c) = d`.
3046 /// lhs is the index into extra_data.3089 /// `const main_token: type_node align(align_node) = init_expr`.
3047 /// main_token is `var` or `const`.3090 ///
3091 /// The `data` field is a `.extra_and_opt_node`:
3092 /// 1. a `ExtraIndex` to `LocalVarDecl`.
3093 /// 2. a `Node.OptionalIndex` to the initialization expression-
3094 ///
3095 /// The `main_token` field is the `var` or `const` token.
3096 ///
3097 /// The initialization expression can't be `.none` unless it is part of
3098 /// a `assign_destructure` node or a parsing error occured.
3048 local_var_decl,3099 local_var_decl,
3049 /// `var a: lhs = rhs`. lhs and rhs may be unused.3100 /// `var a: b = c`.
3101 /// `const name_token: type_expr = init_expr`.
3050 /// Can be local or global.3102 /// Can be local or global.
3051 /// main_token is `var` or `const`.3103 ///
3104 /// The `data` field is a `.opt_node_and_opt_node`:
3105 /// 1. a `Node.OptionalIndex` to the type expression, if any.
3106 /// 2. a `Node.OptionalIndex` to the initialization expression.
3107 ///
3108 /// The `main_token` field is the `var` or `const` token.
3109 ///
3110 /// The initialization expression can't be `.none` unless it is part of
3111 /// a `assign_destructure` node or a parsing error occured.
3052 simple_var_decl,3112 simple_var_decl,
3053 /// `var a align(lhs) = rhs`. lhs and rhs may be unused.3113 /// `var a align(b) = c`.
3114 /// `const name_token align(align_expr) = init_expr`.
3054 /// Can be local or global.3115 /// Can be local or global.
3055 /// main_token is `var` or `const`.3116 ///
3117 /// The `data` field is a `.node_and_opt_node`:
3118 /// 1. a `Node.Index` to the alignment expression.
3119 /// 2. a `Node.OptionalIndex` to the initialization expression.
3120 ///
3121 /// The `main_token` field is the `var` or `const` token.
3122 ///
3123 /// The initialization expression can't be `.none` unless it is part of
3124 /// a `assign_destructure` node or a parsing error occured.
3056 aligned_var_decl,3125 aligned_var_decl,
3057 /// lhs is the identifier token payload if any,3126 /// `errdefer expr`,
3058 /// rhs is the deferred expression.3127 /// `errdefer |payload| expr`.
3128 ///
3129 /// The `data` field is a `.opt_token_and_node`:
3130 /// 1. a `OptionalTokenIndex` to the payload identifier, if any.
3131 /// 2. a `Node.Index` to the deferred expression.
3132 ///
3133 /// The `main_token` field is the `errdefer` token.
3059 @"errdefer",3134 @"errdefer",
3060 /// lhs is unused.3135 /// `defer expr`.
3061 /// rhs is the deferred expression.3136 ///
3137 /// The `data` field is a `.node` to the deferred expression.
3138 ///
3139 /// The `main_token` field is the `defer`.
3062 @"defer",3140 @"defer",
3063 /// lhs catch rhs3141 /// `lhs catch rhs`,
3064 /// lhs catch |err| rhs3142 /// `lhs catch |err| rhs`.
3065 /// main_token is the `catch` keyword.3143 ///
3066 /// payload is determined by looking at the next token after the `catch` keyword.3144 /// The `main_token` field is the `catch` token.
3145 ///
3146 /// The error payload is determined by looking at the next token after
3147 /// the `catch` token.
3067 @"catch",3148 @"catch",
3068 /// `lhs.a`. main_token is the dot. rhs is the identifier token index.3149 /// `lhs.a`.
3150 ///
3151 /// The `data` field is a `.node_and_token`:
3152 /// 1. a `Node.Index` to the left side of the field access.
3153 /// 2. a `TokenIndex` to the field name identifier.
3154 ///
3155 /// The `main_token` field is the `.` token.
3069 field_access,3156 field_access,
3070 /// `lhs.?`. main_token is the dot. rhs is the `?` token index.3157 /// `lhs.?`.
3158 ///
3159 /// The `data` field is a `.node_and_token`:
3160 /// 1. a `Node.Index` to the left side of the optional unwrap.
3161 /// 2. a `TokenIndex` to the `?` token.
3162 ///
3163 /// The `main_token` field is the `.` token.
3071 unwrap_optional,3164 unwrap_optional,
3072 /// `lhs == rhs`. main_token is op.3165 /// `lhs == rhs`. The `main_token` field is the `==` token.
3073 equal_equal,3166 equal_equal,
3074 /// `lhs != rhs`. main_token is op.3167 /// `lhs != rhs`. The `main_token` field is the `!=` token.
3075 bang_equal,3168 bang_equal,
3076 /// `lhs < rhs`. main_token is op.3169 /// `lhs < rhs`. The `main_token` field is the `<` token.
3077 less_than,3170 less_than,
3078 /// `lhs > rhs`. main_token is op.3171 /// `lhs > rhs`. The `main_token` field is the `>` token.
3079 greater_than,3172 greater_than,
3080 /// `lhs <= rhs`. main_token is op.3173 /// `lhs <= rhs`. The `main_token` field is the `<=` token.
3081 less_or_equal,3174 less_or_equal,
3082 /// `lhs >= rhs`. main_token is op.3175 /// `lhs >= rhs`. The `main_token` field is the `>=` token.
3083 greater_or_equal,3176 greater_or_equal,
3084 /// `lhs *= rhs`. main_token is op.3177 /// `lhs *= rhs`. The `main_token` field is the `*=` token.
3085 assign_mul,3178 assign_mul,
3086 /// `lhs /= rhs`. main_token is op.3179 /// `lhs /= rhs`. The `main_token` field is the `/=` token.
3087 assign_div,3180 assign_div,
3088 /// `lhs %= rhs`. main_token is op.3181 /// `lhs %= rhs`. The `main_token` field is the `%=` token.
3089 assign_mod,3182 assign_mod,
3090 /// `lhs += rhs`. main_token is op.3183 /// `lhs += rhs`. The `main_token` field is the `+=` token.
3091 assign_add,3184 assign_add,
3092 /// `lhs -= rhs`. main_token is op.3185 /// `lhs -= rhs`. The `main_token` field is the `-=` token.
3093 assign_sub,3186 assign_sub,
3094 /// `lhs <<= rhs`. main_token is op.3187 /// `lhs <<= rhs`. The `main_token` field is the `<<=` token.
3095 assign_shl,3188 assign_shl,
3096 /// `lhs <<|= rhs`. main_token is op.3189 /// `lhs <<|= rhs`. The `main_token` field is the `<<|=` token.
3097 assign_shl_sat,3190 assign_shl_sat,
3098 /// `lhs >>= rhs`. main_token is op.3191 /// `lhs >>= rhs`. The `main_token` field is the `>>=` token.
3099 assign_shr,3192 assign_shr,
3100 /// `lhs &= rhs`. main_token is op.3193 /// `lhs &= rhs`. The `main_token` field is the `&=` token.
3101 assign_bit_and,3194 assign_bit_and,
3102 /// `lhs ^= rhs`. main_token is op.3195 /// `lhs ^= rhs`. The `main_token` field is the `^=` token.
3103 assign_bit_xor,3196 assign_bit_xor,
3104 /// `lhs |= rhs`. main_token is op.3197 /// `lhs |= rhs`. The `main_token` field is the `|=` token.
3105 assign_bit_or,3198 assign_bit_or,
3106 /// `lhs *%= rhs`. main_token is op.3199 /// `lhs *%= rhs`. The `main_token` field is the `*%=` token.
3107 assign_mul_wrap,3200 assign_mul_wrap,
3108 /// `lhs +%= rhs`. main_token is op.3201 /// `lhs +%= rhs`. The `main_token` field is the `+%=` token.
3109 assign_add_wrap,3202 assign_add_wrap,
3110 /// `lhs -%= rhs`. main_token is op.3203 /// `lhs -%= rhs`. The `main_token` field is the `-%=` token.
3111 assign_sub_wrap,3204 assign_sub_wrap,
3112 /// `lhs *|= rhs`. main_token is op.3205 /// `lhs *|= rhs`. The `main_token` field is the `*%=` token.
3113 assign_mul_sat,3206 assign_mul_sat,
3114 /// `lhs +|= rhs`. main_token is op.3207 /// `lhs +|= rhs`. The `main_token` field is the `+|=` token.
3115 assign_add_sat,3208 assign_add_sat,
3116 /// `lhs -|= rhs`. main_token is op.3209 /// `lhs -|= rhs`. The `main_token` field is the `-|=` token.
3117 assign_sub_sat,3210 assign_sub_sat,
3118 /// `lhs = rhs`. main_token is op.3211 /// `lhs = rhs`. The `main_token` field is the `=` token.
3119 assign,3212 assign,
3120 /// `a, b, ... = rhs`. main_token is op. lhs is index into `extra_data`3213 /// `a, b, ... = rhs`.
3121 /// of an lhs elem count followed by an array of that many `Node.Index`,3214 ///
3122 /// with each node having one of the following types:3215 /// The `data` field is a `.extra_and_node`:
3123 /// * `global_var_decl`3216 /// 1. a `ExtraIndex`. Further explained below.
3124 /// * `local_var_decl`3217 /// 2. a `Node.Index` to the initialization expression.
3125 /// * `simple_var_decl`3218 ///
3126 /// * `aligned_var_decl`3219 /// The `main_token` field is the `=` token.
3127 /// * Any expression node3220 ///
3128 /// The first 3 types correspond to a `var` or `const` lhs node (note3221 /// The `ExtraIndex` stores the following data:
3129 /// that their `rhs` is always 0). An expression node corresponds to a3222 /// ```
3130 /// standard assignment LHS (which must be evaluated as an lvalue).3223 /// elem_count: u32,
3131 /// There may be a preceding `comptime` token, which does not create a3224 /// variables: [elem_count]Node.Index,
3132 /// corresponding `comptime` node so must be manually detected.3225 /// ```
3226 ///
3227 /// Each node in `variables` has one of the following tags:
3228 /// - `global_var_decl`
3229 /// - `local_var_decl`
3230 /// - `simple_var_decl`
3231 /// - `aligned_var_decl`
3232 /// - Any expression node
3233 ///
3234 /// The first 4 tags correspond to a `var` or `const` lhs node (note
3235 /// that their initialization expression is always `.none`).
3236 /// An expression node corresponds to a standard assignment LHS (which
3237 /// must be evaluated as an lvalue). There may be a preceding
3238 /// `comptime` token, which does not create a corresponding `comptime`
3239 /// node so must be manually detected.
3133 assign_destructure,3240 assign_destructure,
3134 /// `lhs || rhs`. main_token is the `||`.3241 /// `lhs || rhs`. The `main_token` field is the `||` token.
3135 merge_error_sets,3242 merge_error_sets,
3136 /// `lhs * rhs`. main_token is the `*`.3243 /// `lhs * rhs`. The `main_token` field is the `*` token.
3137 mul,3244 mul,
3138 /// `lhs / rhs`. main_token is the `/`.3245 /// `lhs / rhs`. The `main_token` field is the `/` token.
3139 div,3246 div,
3140 /// `lhs % rhs`. main_token is the `%`.3247 /// `lhs % rhs`. The `main_token` field is the `%` token.
3141 mod,3248 mod,
3142 /// `lhs ** rhs`. main_token is the `**`.3249 /// `lhs ** rhs`. The `main_token` field is the `**` token.
3143 array_mult,3250 array_mult,
3144 /// `lhs *% rhs`. main_token is the `*%`.3251 /// `lhs *% rhs`. The `main_token` field is the `*%` token.
3145 mul_wrap,3252 mul_wrap,
3146 /// `lhs *| rhs`. main_token is the `*|`.3253 /// `lhs *| rhs`. The `main_token` field is the `*|` token.
3147 mul_sat,3254 mul_sat,
3148 /// `lhs + rhs`. main_token is the `+`.3255 /// `lhs + rhs`. The `main_token` field is the `+` token.
3149 add,3256 add,
3150 /// `lhs - rhs`. main_token is the `-`.3257 /// `lhs - rhs`. The `main_token` field is the `-` token.
3151 sub,3258 sub,
3152 /// `lhs ++ rhs`. main_token is the `++`.3259 /// `lhs ++ rhs`. The `main_token` field is the `++` token.
3153 array_cat,3260 array_cat,
3154 /// `lhs +% rhs`. main_token is the `+%`.3261 /// `lhs +% rhs`. The `main_token` field is the `+%` token.
3155 add_wrap,3262 add_wrap,
3156 /// `lhs -% rhs`. main_token is the `-%`.3263 /// `lhs -% rhs`. The `main_token` field is the `-%` token.
3157 sub_wrap,3264 sub_wrap,
3158 /// `lhs +| rhs`. main_token is the `+|`.3265 /// `lhs +| rhs`. The `main_token` field is the `+|` token.
3159 add_sat,3266 add_sat,
3160 /// `lhs -| rhs`. main_token is the `-|`.3267 /// `lhs -| rhs`. The `main_token` field is the `-|` token.
3161 sub_sat,3268 sub_sat,
3162 /// `lhs << rhs`. main_token is the `<<`.3269 /// `lhs << rhs`. The `main_token` field is the `<<` token.
3163 shl,3270 shl,
3164 /// `lhs <<| rhs`. main_token is the `<<|`.3271 /// `lhs <<| rhs`. The `main_token` field is the `<<|` token.
3165 shl_sat,3272 shl_sat,
3166 /// `lhs >> rhs`. main_token is the `>>`.3273 /// `lhs >> rhs`. The `main_token` field is the `>>` token.
3167 shr,3274 shr,
3168 /// `lhs & rhs`. main_token is the `&`.3275 /// `lhs & rhs`. The `main_token` field is the `&` token.
3169 bit_and,3276 bit_and,
3170 /// `lhs ^ rhs`. main_token is the `^`.3277 /// `lhs ^ rhs`. The `main_token` field is the `^` token.
3171 bit_xor,3278 bit_xor,
3172 /// `lhs | rhs`. main_token is the `|`.3279 /// `lhs | rhs`. The `main_token` field is the `|` token.
3173 bit_or,3280 bit_or,
3174 /// `lhs orelse rhs`. main_token is the `orelse`.3281 /// `lhs orelse rhs`. The `main_token` field is the `orelse` token.
3175 @"orelse",3282 @"orelse",
3176 /// `lhs and rhs`. main_token is the `and`.3283 /// `lhs and rhs`. The `main_token` field is the `and` token.
3177 bool_and,3284 bool_and,
3178 /// `lhs or rhs`. main_token is the `or`.3285 /// `lhs or rhs`. The `main_token` field is the `or` token.
3179 bool_or,3286 bool_or,
3180 /// `op lhs`. rhs unused. main_token is op.3287 /// `!expr`. The `main_token` field is the `!` token.
3181 bool_not,3288 bool_not,
3182 /// `op lhs`. rhs unused. main_token is op.3289 /// `-expr`. The `main_token` field is the `-` token.
3183 negation,3290 negation,
3184 /// `op lhs`. rhs unused. main_token is op.3291 /// `~expr`. The `main_token` field is the `~` token.
3185 bit_not,3292 bit_not,
3186 /// `op lhs`. rhs unused. main_token is op.3293 /// `-%expr`. The `main_token` field is the `-%` token.
3187 negation_wrap,3294 negation_wrap,
3188 /// `op lhs`. rhs unused. main_token is op.3295 /// `&expr`. The `main_token` field is the `&` token.
3189 address_of,3296 address_of,
3190 /// `op lhs`. rhs unused. main_token is op.3297 /// `try expr`. The `main_token` field is the `try` token.
3191 @"try",3298 @"try",
3192 /// `op lhs`. rhs unused. main_token is op.3299 /// `await expr`. The `main_token` field is the `await` token.
3193 @"await",3300 @"await",
3194 /// `?lhs`. rhs unused. main_token is the `?`.3301 /// `?expr`. The `main_token` field is the `?` token.
3195 optional_type,3302 optional_type,
3196 /// `[lhs]rhs`.3303 /// `[lhs]rhs`. The `main_token` field is the `[` token.
3197 array_type,3304 array_type,
3198 /// `[lhs:a]b`. `ArrayTypeSentinel[rhs]`.3305 /// `[lhs:a]b`.
3306 ///
3307 /// The `data` field is a `.node_and_extra`:
3308 /// 1. a `Node.Index` to the length expression.
3309 /// 2. a `ExtraIndex` to `ArrayTypeSentinel`.
3310 ///
3311 /// The `main_token` field is the `[` token.
3199 array_type_sentinel,3312 array_type_sentinel,
3200 /// `[*]align(lhs) rhs`. lhs can be omitted.3313 /// `[*]align(lhs) rhs`,
3201 /// `*align(lhs) rhs`. lhs can be omitted.3314 /// `*align(lhs) rhs`,
3202 /// `[]rhs`.3315 /// `[]rhs`.
3203 /// main_token is the asterisk if a single item pointer or the lbracket3316 ///
3204 /// if a slice, many-item pointer, or C-pointer3317 /// The `data` field is a `.opt_node_and_node`:
3205 /// main_token might be a ** token, which is shared with a parent/child3318 /// 1. a `Node.OptionalIndex` to the alignment expression, if any.
3206 /// pointer type and may require special handling.3319 /// 2. a `Node.Index` to the element type expression.
3320 ///
3321 /// The `main_token` is the asterisk if a single item pointer or the
3322 /// lbracket if a slice, many-item pointer, or C-pointer.
3323 /// The `main_token` might be a ** token, which is shared with a
3324 /// parent/child pointer type and may require special handling.
3207 ptr_type_aligned,3325 ptr_type_aligned,
3208 /// `[*:lhs]rhs`. lhs can be omitted.3326 /// `[*:lhs]rhs`,
3209 /// `*rhs`.3327 /// `*rhs`,
3210 /// `[:lhs]rhs`.3328 /// `[:lhs]rhs`.
3211 /// main_token is the asterisk if a single item pointer or the lbracket3329 ///
3212 /// if a slice, many-item pointer, or C-pointer3330 /// The `data` field is a `.opt_node_and_node`:
3213 /// main_token might be a ** token, which is shared with a parent/child3331 /// 1. a `Node.OptionalIndex` to the sentinel expression, if any.
3214 /// pointer type and may require special handling.3332 /// 2. a `Node.Index` to the element type expression.
3333 ///
3334 /// The `main_token` is the asterisk if a single item pointer or the
3335 /// lbracket if a slice, many-item pointer, or C-pointer.
3336 /// The `main_token` might be a ** token, which is shared with a
3337 /// parent/child pointer type and may require special handling.
3215 ptr_type_sentinel,3338 ptr_type_sentinel,
3216 /// lhs is index into ptr_type. rhs is the element type expression.3339 /// The `data` field is a `.opt_node_and_node`:
3217 /// main_token is the asterisk if a single item pointer or the lbracket3340 /// 1. a `ExtraIndex` to `PtrType`.
3218 /// if a slice, many-item pointer, or C-pointer3341 /// 2. a `Node.Index` to the element type expression.
3219 /// main_token might be a ** token, which is shared with a parent/child3342 ///
3220 /// pointer type and may require special handling.3343 /// The `main_token` is the asterisk if a single item pointer or the
3344 /// lbracket if a slice, many-item pointer, or C-pointer.
3345 /// The `main_token` might be a ** token, which is shared with a
3346 /// parent/child pointer type and may require special handling.
3221 ptr_type,3347 ptr_type,
3222 /// lhs is index into ptr_type_bit_range. rhs is the element type expression.3348 /// The `data` field is a `.opt_node_and_node`:
3223 /// main_token is the asterisk if a single item pointer or the lbracket3349 /// 1. a `ExtraIndex` to `PtrTypeBitRange`.
3224 /// if a slice, many-item pointer, or C-pointer3350 /// 2. a `Node.Index` to the element type expression.
3225 /// main_token might be a ** token, which is shared with a parent/child3351 ///
3226 /// pointer type and may require special handling.3352 /// The `main_token` is the asterisk if a single item pointer or the
3353 /// lbracket if a slice, many-item pointer, or C-pointer.
3354 /// The `main_token` might be a ** token, which is shared with a
3355 /// parent/child pointer type and may require special handling.
3227 ptr_type_bit_range,3356 ptr_type_bit_range,
3228 /// `lhs[rhs..]`3357 /// `lhs[rhs..]`
3229 /// main_token is the lbracket.3358 ///
3359 /// The `main_token` field is the `[` token.
3230 slice_open,3360 slice_open,
3231 /// `lhs[b..c]`. rhs is index into Slice3361 /// `sliced[start..end]`.
3232 /// main_token is the lbracket.3362 ///
3363 /// The `data` field is a `.node_and_extra`:
3364 /// 1. a `Node.Index` to the sliced expression.
3365 /// 2. a `ExtraIndex` to `Slice`.
3366 ///
3367 /// The `main_token` field is the `[` token.
3233 slice,3368 slice,
3234 /// `lhs[b..c :d]`. rhs is index into SliceSentinel. Slice end "c" can be omitted.3369 /// `sliced[start..end :sentinel]`,
3235 /// main_token is the lbracket.3370 /// `sliced[start.. :sentinel]`.
3371 ///
3372 /// The `data` field is a `.node_and_extra`:
3373 /// 1. a `Node.Index` to the sliced expression.
3374 /// 2. a `ExtraIndex` to `SliceSentinel`.
3375 ///
3376 /// The `main_token` field is the `[` token.
3236 slice_sentinel,3377 slice_sentinel,
3237 /// `lhs.*`. rhs is unused.3378 /// `expr.*`.
3379 ///
3380 /// The `data` field is a `.node` to expr.
3381 ///
3382 /// The `main_token` field is the `*` token.
3238 deref,3383 deref,
3239 /// `lhs[rhs]`.3384 /// `lhs[rhs]`.
3385 ///
3386 /// The `main_token` field is the `[` token.
3240 array_access,3387 array_access,
3241 /// `lhs{rhs}`. rhs can be omitted.3388 /// `lhs{rhs}`.
3389 ///
3390 /// The `main_token` field is the `{` token.
3242 array_init_one,3391 array_init_one,
3243 /// `lhs{rhs,}`. rhs can *not* be omitted3392 /// Same as `array_init_one` except there is known to be a trailing
3393 /// comma before the final rbrace.
3244 array_init_one_comma,3394 array_init_one_comma,
3245 /// `.{lhs, rhs}`. lhs and rhs can be omitted.3395 /// `.{a}`,
3396 /// `.{a, b}`.
3397 ///
3398 /// The `data` field is a `.opt_node_and_opt_node`:
3399 /// 1. a `Node.OptionalIndex` to the first element. Never `.none`
3400 /// 2. a `Node.OptionalIndex` to the second element, if any.
3401 ///
3402 /// The `main_token` field is the `{` token.
3246 array_init_dot_two,3403 array_init_dot_two,
3247 /// Same as `array_init_dot_two` except there is known to be a trailing comma3404 /// Same as `array_init_dot_two` except there is known to be a trailing
3248 /// before the final rbrace.3405 /// comma before the final rbrace.
3249 array_init_dot_two_comma,3406 array_init_dot_two_comma,
3250 /// `.{a, b}`. `sub_list[lhs..rhs]`.3407 /// `.{a, b, c}`.
3408 ///
3409 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3410 /// each element.
3411 ///
3412 /// The `main_token` field is the `{` token.
3251 array_init_dot,3413 array_init_dot,
3252 /// Same as `array_init_dot` except there is known to be a trailing comma3414 /// Same as `array_init_dot` except there is known to be a trailing
3253 /// before the final rbrace.3415 /// comma before the final rbrace.
3254 array_init_dot_comma,3416 array_init_dot_comma,
3255 /// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`.3417 /// `a{b, c}`.
3418 ///
3419 /// The `data` field is a `.node_and_extra`:
3420 /// 1. a `Node.Index` to the type expression.
3421 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3422 /// each element.
3423 ///
3424 /// The `main_token` field is the `{` token.
3256 array_init,3425 array_init,
3257 /// Same as `array_init` except there is known to be a trailing comma3426 /// Same as `array_init` except there is known to be a trailing comma
3258 /// before the final rbrace.3427 /// before the final rbrace.
3259 array_init_comma,3428 array_init_comma,
3260 /// `lhs{.a = rhs}`. rhs can be omitted making it empty.3429 /// `a{.x = b}`, `a{}`.
3261 /// main_token is the lbrace.3430 ///
3431 /// The `data` field is a `.node_and_opt_node`:
3432 /// 1. a `Node.Index` to the type expression.
3433 /// 2. a `Node.OptionalIndex` to the first field initialization, if any.
3434 ///
3435 /// The `main_token` field is the `{` token.
3436 ///
3437 /// The field name is determined by looking at the tokens preceding the
3438 /// field initialization.
3262 struct_init_one,3439 struct_init_one,
3263 /// `lhs{.a = rhs,}`. rhs can *not* be omitted.3440 /// Same as `struct_init_one` except there is known to be a trailing comma
3264 /// main_token is the lbrace.3441 /// before the final rbrace.
3265 struct_init_one_comma,3442 struct_init_one_comma,
3266 /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted.3443 /// `.{.x = a, .y = b}`.
3267 /// main_token is the lbrace.3444 ///
3268 /// No trailing comma before the rbrace.3445 /// The `data` field is a `.opt_node_and_opt_node`:
3446 /// 1. a `Node.OptionalIndex` to the first field initialization. Never `.none`
3447 /// 2. a `Node.OptionalIndex` to the second field initialization, if any.
3448 ///
3449 /// The `main_token` field is the '{' token.
3450 ///
3451 /// The field name is determined by looking at the tokens preceding the
3452 /// field initialization.
3269 struct_init_dot_two,3453 struct_init_dot_two,
3270 /// Same as `struct_init_dot_two` except there is known to be a trailing comma3454 /// Same as `struct_init_dot_two` except there is known to be a trailing
3271 /// before the final rbrace.3455 /// comma before the final rbrace.
3272 struct_init_dot_two_comma,3456 struct_init_dot_two_comma,
3273 /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`.3457 /// `.{.x = a, .y = b, .z = c}`.
3274 /// main_token is the lbrace.3458 ///
3459 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3460 /// each field initialization.
3461 ///
3462 /// The `main_token` field is the `{` token.
3463 ///
3464 /// The field name is determined by looking at the tokens preceding the
3465 /// field initialization.
3275 struct_init_dot,3466 struct_init_dot,
3276 /// Same as `struct_init_dot` except there is known to be a trailing comma3467 /// Same as `struct_init_dot` except there is known to be a trailing
3277 /// before the final rbrace.3468 /// comma before the final rbrace.
3278 struct_init_dot_comma,3469 struct_init_dot_comma,
3279 /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`.3470 /// `a{.x = b, .y = c}`.
3280 /// lhs can be omitted which means `.{.a = b, .c = d}`.3471 ///
3281 /// main_token is the lbrace.3472 /// The `data` field is a `.node_and_extra`:
3473 /// 1. a `Node.Index` to the type expression.
3474 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3475 /// each field initialization.
3476 ///
3477 /// The `main_token` field is the `{` token.
3478 ///
3479 /// The field name is determined by looking at the tokens preceding the
3480 /// field initialization.
3282 struct_init,3481 struct_init,
3283 /// Same as `struct_init` except there is known to be a trailing comma3482 /// Same as `struct_init` except there is known to be a trailing comma
3284 /// before the final rbrace.3483 /// before the final rbrace.
3285 struct_init_comma,3484 struct_init_comma,
3286 /// `lhs(rhs)`. rhs can be omitted.3485 /// `a(b)`, `a()`.
3287 /// main_token is the lparen.3486 ///
3487 /// The `data` field is a `.node_and_opt_node`:
3488 /// 1. a `Node.Index` to the function expression.
3489 /// 2. a `Node.OptionalIndex` to the first argument, if any.
3490 ///
3491 /// The `main_token` field is the `(` token.
3288 call_one,3492 call_one,
3289 /// `lhs(rhs,)`. rhs can be omitted.3493 /// Same as `call_one` except there is known to be a trailing comma
3290 /// main_token is the lparen.3494 /// before the final rparen.
3291 call_one_comma,3495 call_one_comma,
3292 /// `async lhs(rhs)`. rhs can be omitted.3496 /// `async a(b)`, `async a()`.
3497 ///
3498 /// The `data` field is a `.node_and_opt_node`:
3499 /// 1. a `Node.Index` to the function expression.
3500 /// 2. a `Node.OptionalIndex` to the first argument, if any.
3501 ///
3502 /// The `main_token` field is the `(` token.
3293 async_call_one,3503 async_call_one,
3294 /// `async lhs(rhs,)`.3504 /// Same as `async_call_one` except there is known to be a trailing
3505 /// comma before the final rparen.
3295 async_call_one_comma,3506 async_call_one_comma,
3296 /// `lhs(a, b, c)`. `SubRange[rhs]`.3507 /// `a(b, c, d)`.
3297 /// main_token is the `(`.3508 ///
3509 /// The `data` field is a `.node_and_extra`:
3510 /// 1. a `Node.Index` to the function expression.
3511 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3512 /// each argument.
3513 ///
3514 /// The `main_token` field is the `(` token.
3298 call,3515 call,
3299 /// `lhs(a, b, c,)`. `SubRange[rhs]`.3516 /// Same as `call` except there is known to be a trailing comma before
3300 /// main_token is the `(`.3517 /// the final rparen.
3301 call_comma,3518 call_comma,
3302 /// `async lhs(a, b, c)`. `SubRange[rhs]`.3519 /// `async a(b, c, d)`.
3303 /// main_token is the `(`.3520 ///
3521 /// The `data` field is a `.node_and_extra`:
3522 /// 1. a `Node.Index` to the function expression.
3523 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3524 /// each argument.
3525 ///
3526 /// The `main_token` field is the `(` token.
3304 async_call,3527 async_call,
3305 /// `async lhs(a, b, c,)`. `SubRange[rhs]`.3528 /// Same as `async_call` except there is known to be a trailing comma
3306 /// main_token is the `(`.3529 /// before the final rparen.
3307 async_call_comma,3530 async_call_comma,
3308 /// `switch(lhs) {}`. `SubRange[rhs]`.3531 /// `switch(a) {}`.
3309 /// `main_token` is the identifier of a preceding label, if any; otherwise `switch`.3532 ///
3533 /// The `data` field is a `.node_and_extra`:
3534 /// 1. a `Node.Index` to the switch operand.
3535 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3536 /// each switch case.
3537 ///
3538 /// `The `main_token` field` is the identifier of a preceding label, if any; otherwise `switch`.
3310 @"switch",3539 @"switch",
3311 /// Same as switch except there is known to be a trailing comma3540 /// Same as `switch` except there is known to be a trailing comma before
3312 /// before the final rbrace3541 /// the final rbrace.
3313 switch_comma,3542 switch_comma,
3314 /// `lhs => rhs`. If lhs is omitted it means `else`.3543 /// `a => b`,
3315 /// main_token is the `=>`3544 /// `else => b`.
3545 ///
3546 /// The `data` field is a `.opt_node_and_node`:
3547 /// 1. a `Node.OptionalIndex` where `.none` means `else`.
3548 /// 2. a `Node.Index` to the target expression.
3549 ///
3550 /// The `main_token` field is the `=>` token.
3316 switch_case_one,3551 switch_case_one,
3317 /// Same ast `switch_case_one` but the case is inline3552 /// Same as `switch_case_one` but the case is inline.
3318 switch_case_inline_one,3553 switch_case_inline_one,
3319 /// `a, b, c => rhs`. `SubRange[lhs]`.3554 /// `a, b, c => d`.
3320 /// main_token is the `=>`3555 ///
3556 /// The `data` field is a `.extra_and_node`:
3557 /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3558 /// each switch item.
3559 /// 2. a `Node.Index` to the target expression.
3560 ///
3561 /// The `main_token` field is the `=>` token.
3321 switch_case,3562 switch_case,
3322 /// Same ast `switch_case` but the case is inline3563 /// Same as `switch_case` but the case is inline.
3323 switch_case_inline,3564 switch_case_inline,
3324 /// `lhs...rhs`.3565 /// `lhs...rhs`.
3566 ///
3567 /// The `main_token` field is the `...` token.
3325 switch_range,3568 switch_range,
3326 /// `while (lhs) rhs`.3569 /// `while (a) b`,
3327 /// `while (lhs) |x| rhs`.3570 /// `while (a) |x| b`.
3328 while_simple,3571 while_simple,
3329 /// `while (lhs) : (a) b`. `WhileCont[rhs]`.3572 /// `while (a) : (b) c`,
3330 /// `while (lhs) : (a) b`. `WhileCont[rhs]`.3573 /// `while (a) |x| : (b) c`.
3331 while_cont,3574 while_cont,
3332 /// `while (lhs) : (a) b else c`. `While[rhs]`.3575 /// `while (a) : (b) c else d`,
3333 /// `while (lhs) |x| : (a) b else c`. `While[rhs]`.3576 /// `while (a) |x| : (b) c else d`,
3334 /// `while (lhs) |x| : (a) b else |y| c`. `While[rhs]`.3577 /// `while (a) |x| : (b) c else |y| d`.
3335 /// The cont expression part `: (a)` may be omitted.3578 /// The continue expression part `: (b)` may be omitted.
3336 @"while",3579 @"while",
3337 /// `for (lhs) rhs`.3580 /// `for (a) b`.
3338 for_simple,3581 for_simple,
3339 /// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`.3582 /// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`.
3340 @"for",3583 @"for",
3341 /// `lhs..rhs`. rhs can be omitted.3584 /// `lhs..rhs`, `lhs..`.
3342 for_range,3585 for_range,
3343 /// `if (lhs) rhs`.3586 /// `if (a) b`.
3344 /// `if (lhs) |a| rhs`.3587 /// `if (b) |x| b`.
3345 if_simple,3588 if_simple,
3346 /// `if (lhs) a else b`. `If[rhs]`.3589 /// `if (a) b else c`.
3347 /// `if (lhs) |x| a else b`. `If[rhs]`.3590 /// `if (a) |x| b else c`.
3348 /// `if (lhs) |x| a else |y| b`. `If[rhs]`.3591 /// `if (a) |x| b else |y| d`.
3349 @"if",3592 @"if",
3350 /// `suspend lhs`. lhs can be omitted. rhs is unused.3593 /// `suspend expr`.
3594 ///
3595 /// The `data` field is a `.node` to expr.
3596 ///
3597 /// The `main_token` field is the `suspend` token.
3351 @"suspend",3598 @"suspend",
3352 /// `resume lhs`. rhs is unused.3599 /// `resume expr`.
3600 ///
3601 /// The `data` field is a `.node` to expr.
3602 ///
3603 /// The `main_token` field is the `resume` token.
3353 @"resume",3604 @"resume",
3354 /// `continue :lhs rhs`3605 /// `continue :label expr`,
3355 /// both lhs and rhs may be omitted.3606 /// `continue expr`,
3607 /// `continue :label`,
3608 /// `continue`.
3609 ///
3610 /// The `data` field is a `.opt_token_and_opt_node`:
3611 /// 1. a `OptionalTokenIndex` to the label identifier, if any.
3612 /// 2. a `Node.OptionalIndex` to the target expression, if any.
3613 ///
3614 /// The `main_token` field is the `continue` token.
3356 @"continue",3615 @"continue",
3357 /// `break :lhs rhs`3616 /// `break :label expr`,
3358 /// both lhs and rhs may be omitted.3617 /// `break expr`,
3618 /// `break :label`,
3619 /// `break`.
3620 ///
3621 /// The `data` field is a `.opt_token_and_opt_node`:
3622 /// 1. a `OptionalTokenIndex` to the label identifier, if any.
3623 /// 2. a `Node.OptionalIndex` to the target expression, if any.
3624 ///
3625 /// The `main_token` field is the `break` token.
3359 @"break",3626 @"break",
3360 /// `return lhs`. lhs can be omitted. rhs is unused.3627 /// `return expr`, `return`.
3628 ///
3629 /// The `data` field is a `.opt_node` to the return value, if any.
3630 ///
3631 /// The `main_token` field is the `return` token.
3361 @"return",3632 @"return",
3362 /// `fn (a: lhs) rhs`. lhs can be omitted.3633 /// `fn (a: type_expr) return_type`.
3363 /// anytype and ... parameters are omitted from the AST tree.3634 ///
3364 /// main_token is the `fn` keyword.3635 /// The `data` field is a `.opt_node_and_opt_node`:
3365 /// extern function declarations use this tag.3636 /// 1. a `Node.OptionalIndex` to the first parameter type expression, if any.
3637 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3638 /// `.none` unless a parsing error occured.
3639 ///
3640 /// The `main_token` field is the `fn` token.
3641 ///
3642 /// `anytype` and `...` parameters are omitted from the AST tree.
3643 /// Extern function declarations use this tag.
3366 fn_proto_simple,3644 fn_proto_simple,
3367 /// `fn (a: b, c: d) rhs`. `sub_range_list[lhs]`.3645 /// `fn (a: b, c: d) return_type`.
3368 /// anytype and ... parameters are omitted from the AST tree.3646 ///
3369 /// main_token is the `fn` keyword.3647 /// The `data` field is a `.extra_and_opt_node`:
3370 /// extern function declarations use this tag.3648 /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3649 /// each parameter type expression.
3650 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3651 /// `.none` unless a parsing error occured.
3652 ///
3653 /// The `main_token` field is the `fn` token.
3654 ///
3655 /// `anytype` and `...` parameters are omitted from the AST tree.
3656 /// Extern function declarations use this tag.
3371 fn_proto_multi,3657 fn_proto_multi,
3372 /// `fn (a: b) addrspace(e) linksection(f) callconv(g) rhs`. `FnProtoOne[lhs]`.3658 /// `fn (a: b) addrspace(e) linksection(f) callconv(g) return_type`.
3373 /// zero or one parameters.3659 /// zero or one parameters.
3374 /// anytype and ... parameters are omitted from the AST tree.3660 ///
3375 /// main_token is the `fn` keyword.3661 /// The `data` field is a `.extra_and_opt_node`:
3376 /// extern function declarations use this tag.3662 /// 1. a `Node.ExtraIndex` to `FnProtoOne`.
3663 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3664 /// `.none` unless a parsing error occured.
3665 ///
3666 /// The `main_token` field is the `fn` token.
3667 ///
3668 /// `anytype` and `...` parameters are omitted from the AST tree.
3669 /// Extern function declarations use this tag.
3377 fn_proto_one,3670 fn_proto_one,
3378 /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) rhs`. `FnProto[lhs]`.3671 /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) return_type`.
3379 /// anytype and ... parameters are omitted from the AST tree.3672 ///
3380 /// main_token is the `fn` keyword.3673 /// The `data` field is a `.extra_and_opt_node`:
3381 /// extern function declarations use this tag.3674 /// 1. a `Node.ExtraIndex` to `FnProto`.
3675 /// 2. a `Node.OptionalIndex` to the return type expression. Can't be
3676 /// `.none` unless a parsing error occured.
3677 ///
3678 /// The `main_token` field is the `fn` token.
3679 ///
3680 /// `anytype` and `...` parameters are omitted from the AST tree.
3681 /// Extern function declarations use this tag.
3382 fn_proto,3682 fn_proto,
3383 /// lhs is the fn_proto.3683 /// Extern function declarations use the fn_proto tags rather than this one.
3384 /// rhs is the function body block.3684 ///
3385 /// Note that extern function declarations use the fn_proto tags rather3685 /// The `data` field is a `.node_and_node`:
3386 /// than this one.3686 /// 1. a `Node.Index` to `fn_proto_*`.
3687 /// 2. a `Node.Index` to function body block.
3688 ///
3689 /// The `main_token` field is the `fn` token.
3387 fn_decl,3690 fn_decl,
3388 /// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index.3691 /// `anyframe->return_type`.
3692 ///
3693 /// The `data` field is a `.token_and_node`:
3694 /// 1. a `TokenIndex` to the `->` token.
3695 /// 2. a `Node.Index` to the function frame return type expression.
3696 ///
3697 /// The `main_token` field is the `anyframe` token.
3389 anyframe_type,3698 anyframe_type,
3390 /// Both lhs and rhs unused.3699 /// The `data` field is unused.
3391 anyframe_literal,3700 anyframe_literal,
3392 /// Both lhs and rhs unused.3701 /// The `data` field is unused.
3393 char_literal,3702 char_literal,
3394 /// Both lhs and rhs unused.3703 /// The `data` field is unused.
3395 number_literal,3704 number_literal,
3396 /// Both lhs and rhs unused.3705 /// The `data` field is unused.
3397 unreachable_literal,3706 unreachable_literal,
3398 /// Both lhs and rhs unused.3707 /// The `data` field is unused.
3399 /// Most identifiers will not have explicit AST nodes, however for expressions3708 ///
3400 /// which could be one of many different kinds of AST nodes, there will be an3709 /// Most identifiers will not have explicit AST nodes, however for
3401 /// identifier AST node for it.3710 /// expressions which could be one of many different kinds of AST nodes,
3711 /// there will be an identifier AST node for it.
3402 identifier,3712 identifier,
3403 /// lhs is the dot token index, rhs unused, main_token is the identifier.3713 /// `.foo`.
3714 ///
3715 /// The `data` field is unused.
3716 ///
3717 /// The `main_token` field is the identifier.
3404 enum_literal,3718 enum_literal,
3405 /// main_token is the string literal token3719 /// The `data` field is unused.
3406 /// Both lhs and rhs unused.3720 ///
3721 /// The `main_token` field is the string literal token.
3407 string_literal,3722 string_literal,
3408 /// main_token is the first token index (redundant with lhs)3723 /// The `data` field is a `.token_and_token`:
3409 /// lhs is the first token index; rhs is the last token index.3724 /// 1. a `TokenIndex` to the first `.multiline_string_literal_line` token.
3410 /// Could be a series of multiline_string_literal_line tokens, or a single3725 /// 2. a `TokenIndex` to the last `.multiline_string_literal_line` token.
3411 /// string_literal token.3726 ///
3727 /// The `main_token` field is the first token index (redundant with `data`).
3412 multiline_string_literal,3728 multiline_string_literal,
3413 /// `(lhs)`. main_token is the `(`; rhs is the token index of the `)`.3729 /// `(expr)`.
3730 ///
3731 /// The `data` field is a `.node_and_token`:
3732 /// 1. a `Node.Index` to the sub-expression
3733 /// 2. a `TokenIndex` to the `)` token.
3734 ///
3735 /// The `main_token` field is the `(` token.
3414 grouped_expression,3736 grouped_expression,
3415 /// `@a(lhs, rhs)`. lhs and rhs may be omitted.3737 /// `@a(b, c)`.
3416 /// main_token is the builtin token.3738 ///
3739 /// The `data` field is a `.opt_node_and_opt_node`:
3740 /// 1. a `Node.OptionalIndex` to the first argument, if any.
3741 /// 2. a `Node.OptionalIndex` to the second argument, if any.
3742 ///
3743 /// The `main_token` field is the builtin token.
3417 builtin_call_two,3744 builtin_call_two,
3418 /// Same as builtin_call_two but there is known to be a trailing comma before the rparen.3745 /// Same as `builtin_call_two` except there is known to be a trailing comma
3746 /// before the final rparen.
3419 builtin_call_two_comma,3747 builtin_call_two_comma,
3420 /// `@a(b, c)`. `sub_list[lhs..rhs]`.3748 /// `@a(b, c, d)`.
3421 /// main_token is the builtin token.3749 ///
3750 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3751 /// each argument.
3752 ///
3753 /// The `main_token` field is the builtin token.
3422 builtin_call,3754 builtin_call,
3423 /// Same as builtin_call but there is known to be a trailing comma before the rparen.3755 /// Same as `builtin_call` except there is known to be a trailing comma
3756 /// before the final rparen.
3424 builtin_call_comma,3757 builtin_call_comma,
3425 /// `error{a, b}`.3758 /// `error{a, b}`.
3426 /// rhs is the rbrace, lhs is unused.3759 ///
3760 /// The `data` field is a `.token_and_token`:
3761 /// 1. a `TokenIndex` to the `{` token.
3762 /// 2. a `TokenIndex` to the `}` token.
3763 ///
3764 /// The `main_token` field is the `error`.
3427 error_set_decl,3765 error_set_decl,
3428 /// `struct {}`, `union {}`, `opaque {}`, `enum {}`. `extra_data[lhs..rhs]`.3766 /// `struct {}`, `union {}`, `opaque {}`, `enum {}`.
3429 /// main_token is `struct`, `union`, `opaque`, `enum` keyword.3767 ///
3768 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3769 /// each container member.
3770 ///
3771 /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
3430 container_decl,3772 container_decl,
3431 /// Same as ContainerDecl but there is known to be a trailing comma3773 /// Same as `container_decl` except there is known to be a trailing
3432 /// or semicolon before the rbrace.3774 /// comma before the final rbrace.
3433 container_decl_trailing,3775 container_decl_trailing,
3434 /// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`.3776 /// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`.
3435 /// lhs or rhs can be omitted.3777 ///
3436 /// main_token is `struct`, `union`, `opaque`, `enum` keyword.3778 /// The `data` field is a `.opt_node_and_opt_node`:
3779 /// 1. a `Node.OptionalIndex` to the first container member, if any.
3780 /// 2. a `Node.OptionalIndex` to the second container member, if any.
3781 ///
3782 /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
3437 container_decl_two,3783 container_decl_two,
3438 /// Same as ContainerDeclTwo except there is known to be a trailing comma3784 /// Same as `container_decl_two` except there is known to be a trailing
3439 /// or semicolon before the rbrace.3785 /// comma before the final rbrace.
3440 container_decl_two_trailing,3786 container_decl_two_trailing,
3441 /// `struct(lhs)` / `union(lhs)` / `enum(lhs)`. `SubRange[rhs]`.3787 /// `struct(arg)`, `union(arg)`, `enum(arg)`.
3788 ///
3789 /// The `data` field is a `.node_and_extra`:
3790 /// 1. a `Node.Index` to arg.
3791 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3792 /// each container member.
3793 ///
3794 /// The `main_token` field is the `struct`, `union` or `enum` token.
3442 container_decl_arg,3795 container_decl_arg,
3443 /// Same as container_decl_arg but there is known to be a trailing3796 /// Same as `container_decl_arg` except there is known to be a trailing
3444 /// comma or semicolon before the rbrace.3797 /// comma before the final rbrace.
3445 container_decl_arg_trailing,3798 container_decl_arg_trailing,
3446 /// `union(enum) {}`. `sub_list[lhs..rhs]`.3799 /// `union(enum) {}`.
3447 /// Note that tagged unions with explicitly provided enums are represented3800 ///
3448 /// by `container_decl_arg`.3801 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3802 /// each container member.
3803 ///
3804 /// The `main_token` field is the `union` token.
3805 ///
3806 /// A tagged union with explicitly provided enums will instead be
3807 /// represented by `container_decl_arg`.
3449 tagged_union,3808 tagged_union,
3450 /// Same as tagged_union but there is known to be a trailing comma3809 /// Same as `tagged_union` except there is known to be a trailing comma
3451 /// or semicolon before the rbrace.3810 /// before the final rbrace.
3452 tagged_union_trailing,3811 tagged_union_trailing,
3453 /// `union(enum) {lhs, rhs}`. lhs or rhs may be omitted.3812 /// `union(enum) {lhs, rhs}`.
3454 /// Note that tagged unions with explicitly provided enums are represented3813 ///
3455 /// by `container_decl_arg`.3814 /// The `data` field is a `.opt_node_and_opt_node`:
3815 /// 1. a `Node.OptionalIndex` to the first container member, if any.
3816 /// 2. a `Node.OptionalIndex` to the second container member, if any.
3817 ///
3818 /// The `main_token` field is the `union` token.
3819 ///
3820 /// A tagged union with explicitly provided enums will instead be
3821 /// represented by `container_decl_arg`.
3456 tagged_union_two,3822 tagged_union_two,
3457 /// Same as tagged_union_two but there is known to be a trailing comma3823 /// Same as `tagged_union_two` except there is known to be a trailing
3458 /// or semicolon before the rbrace.3824 /// comma before the final rbrace.
3459 tagged_union_two_trailing,3825 tagged_union_two_trailing,
3460 /// `union(enum(lhs)) {}`. `SubRange[rhs]`.3826 /// `union(enum(arg)) {}`.
3827 ///
3828 /// The `data` field is a `.node_and_extra`:
3829 /// 1. a `Node.Index` to arg.
3830 /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
3831 /// each container member.
3832 ///
3833 /// The `main_token` field is the `union` token.
3461 tagged_union_enum_tag,3834 tagged_union_enum_tag,
3462 /// Same as tagged_union_enum_tag but there is known to be a trailing comma3835 /// Same as `tagged_union_enum_tag` except there is known to be a
3463 /// or semicolon before the rbrace.3836 /// trailing comma before the final rbrace.
3464 tagged_union_enum_tag_trailing,3837 tagged_union_enum_tag_trailing,
3465 /// `a: lhs = rhs,`. lhs and rhs can be omitted.3838 /// `a: lhs = rhs,`,
3466 /// main_token is the field name identifier.3839 /// `a: lhs,`.
3467 /// lastToken() does not include the possible trailing comma.3840 ///
3841 /// The `data` field is a `.node_and_opt_node`:
3842 /// 1. a `Node.Index` to the field type expression.
3843 /// 2. a `Node.OptionalIndex` to the default value expression, if any.
3844 ///
3845 /// The `main_token` field is the field name identifier.
3846 ///
3847 /// `lastToken()` does not include the possible trailing comma.
3468 container_field_init,3848 container_field_init,
3469 /// `a: lhs align(rhs),`. rhs can be omitted.3849 /// `a: lhs align(rhs),`.
3470 /// main_token is the field name identifier.3850 ///
3471 /// lastToken() does not include the possible trailing comma.3851 /// The `data` field is a `.node_and_node`:
3852 /// 1. a `Node.Index` to the field type expression.
3853 /// 2. a `Node.Index` to the alignment expression.
3854 ///
3855 /// The `main_token` field is the field name identifier.
3856 ///
3857 /// `lastToken()` does not include the possible trailing comma.
3472 container_field_align,3858 container_field_align,
3473 /// `a: lhs align(c) = d,`. `container_field_list[rhs]`.3859 /// `a: lhs align(c) = d,`.
3474 /// main_token is the field name identifier.3860 ///
3475 /// lastToken() does not include the possible trailing comma.3861 /// The `data` field is a `.node_and_extra`:
3862 /// 1. a `Node.Index` to the field type expression.
3863 /// 2. a `ExtraIndex` to `ContainerField`.
3864 ///
3865 /// The `main_token` field is the field name identifier.
3866 ///
3867 /// `lastToken()` does not include the possible trailing comma.
3476 container_field,3868 container_field,
3477 /// `comptime lhs`. rhs unused.3869 /// `comptime expr`.
3870 ///
3871 /// The `data` field is a `.node` to expr.
3872 ///
3873 /// The `main_token` field is the `comptime` token.
3478 @"comptime",3874 @"comptime",
3479 /// `nosuspend lhs`. rhs unused.3875 /// `nosuspend expr`.
3876 ///
3877 /// The `data` field is a `.node` to expr.
3878 ///
3879 /// The `main_token` field is the `nosuspend` token.
3480 @"nosuspend",3880 @"nosuspend",
3481 /// `{lhs rhs}`. rhs or lhs can be omitted.3881 /// `{lhs rhs}`.
3482 /// main_token points at the lbrace.3882 ///
3883 /// The `data` field is a `.opt_node_and_opt_node`:
3884 /// 1. a `Node.OptionalIndex` to the first statement, if any.
3885 /// 2. a `Node.OptionalIndex` to the second statement, if any.
3886 ///
3887 /// The `main_token` field is the `{` token.
3483 block_two,3888 block_two,
3484 /// Same as block_two but there is known to be a semicolon before the rbrace.3889 /// Same as `block_two_semicolon` except there is known to be a trailing
3890 /// comma before the final rbrace.
3485 block_two_semicolon,3891 block_two_semicolon,
3486 /// `{}`. `sub_list[lhs..rhs]`.3892 /// `{a b}`.
3487 /// main_token points at the lbrace.3893 ///
3894 /// The `data` field is a `.extra_range` that stores a `Node.Index` for
3895 /// each statement.
3896 ///
3897 /// The `main_token` field is the `{` token.
3488 block,3898 block,
3489 /// Same as block but there is known to be a semicolon before the rbrace.3899 /// Same as `block` except there is known to be a trailing comma before
3900 /// the final rbrace.
3490 block_semicolon,3901 block_semicolon,
3491 /// `asm(lhs)`. rhs is the token index of the rparen.3902 /// `asm(lhs)`.
3903 ///
3904 /// rhs is a `Token.Index` to the `)` token.
3905 /// The `main_token` field is the `asm` token.
3492 asm_simple,3906 asm_simple,
3493 /// `asm(lhs, a)`. `Asm[rhs]`.3907 /// `asm(lhs, a)`.
3908 ///
3909 /// The `data` field is a `.node_and_extra`:
3910 /// 1. a `Node.Index` to lhs.
3911 /// 2. a `ExtraIndex` to `Asm`.
3912 ///
3913 /// The `main_token` field is the `asm` token.
3494 @"asm",3914 @"asm",
3495 /// `[a] "b" (c)`. lhs is 0, rhs is token index of the rparen.3915 /// `[a] "b" (c)`.
3496 /// `[a] "b" (-> lhs)`. rhs is token index of the rparen.3916 /// `[a] "b" (-> lhs)`.
3497 /// main_token is `a`.3917 ///
3918 /// The `data` field is a `.opt_node_and_token`:
3919 /// 1. a `Node.OptionalIndex` to lhs, if any.
3920 /// 2. a `TokenIndex` to the `)` token.
3921 ///
3922 /// The `main_token` field is `a`.
3498 asm_output,3923 asm_output,
3499 /// `[a] "b" (lhs)`. rhs is token index of the rparen.3924 /// `[a] "b" (lhs)`.
3500 /// main_token is `a`.3925 ///
3926 /// The `data` field is a `.node_and_token`:
3927 /// 1. a `Node.Index` to lhs.
3928 /// 2. a `TokenIndex` to the `)` token.
3929 ///
3930 /// The `main_token` field is `a`.
3501 asm_input,3931 asm_input,
3502 /// `error.a`. lhs is token index of `.`. rhs is token index of `a`.3932 /// `error.a`.
3933 ///
3934 /// The `data` field is unused.
3935 ///
3936 /// The `main_token` field is `error` token.
3503 error_value,3937 error_value,
3504 /// `lhs!rhs`. main_token is the `!`.3938 /// `lhs!rhs`.
3939 ///
3940 /// The `main_token` field is the `!` token.
3505 error_union,3941 error_union,
35063942
3507 pub fn isContainerField(tag: Tag) bool {3943 pub fn isContainerField(tag: Tag) bool {
...@@ -3516,9 +3952,26 @@ pub const Node = struct {...@@ -3516,9 +3952,26 @@ pub const Node = struct {
3516 }3952 }
3517 };3953 };
35183954
3519 pub const Data = struct {3955 pub const Data = union {
3520 lhs: Index,3956 node: Index,
3521 rhs: Index,3957 opt_node: OptionalIndex,
3958 token: TokenIndex,
3959 node_and_node: struct { Index, Index },
3960 opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex },
3961 node_and_opt_node: struct { Index, OptionalIndex },
3962 opt_node_and_node: struct { OptionalIndex, Index },
3963 node_and_extra: struct { Index, ExtraIndex },
3964 extra_and_node: struct { ExtraIndex, Index },
3965 extra_and_opt_node: struct { ExtraIndex, OptionalIndex },
3966 node_and_token: struct { Index, TokenIndex },
3967 token_and_node: struct { TokenIndex, Index },
3968 token_and_token: struct { TokenIndex, TokenIndex },
3969 opt_node_and_token: struct { OptionalIndex, TokenIndex },
3970 opt_token_and_node: struct { OptionalTokenIndex, Index },
3971 opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex },
3972 opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex },
3973 @"for": struct { ExtraIndex, For },
3974 extra_range: SubRange,
3522 };3975 };
35233976
3524 pub const LocalVarDecl = struct {3977 pub const LocalVarDecl = struct {
...@@ -3532,24 +3985,24 @@ pub const Node = struct {...@@ -3532,24 +3985,24 @@ pub const Node = struct {
3532 };3985 };
35333986
3534 pub const PtrType = struct {3987 pub const PtrType = struct {
3535 sentinel: Index,3988 sentinel: OptionalIndex,
3536 align_node: Index,3989 align_node: OptionalIndex,
3537 addrspace_node: Index,3990 addrspace_node: OptionalIndex,
3538 };3991 };
35393992
3540 pub const PtrTypeBitRange = struct {3993 pub const PtrTypeBitRange = struct {
3541 sentinel: Index,3994 sentinel: OptionalIndex,
3542 align_node: Index,3995 align_node: Index,
3543 addrspace_node: Index,3996 addrspace_node: OptionalIndex,
3544 bit_range_start: Index,3997 bit_range_start: Index,
3545 bit_range_end: Index,3998 bit_range_end: Index,
3546 };3999 };
35474000
3548 pub const SubRange = struct {4001 pub const SubRange = struct {
3549 /// Index into sub_list.4002 /// Index into extra_data.
3550 start: Index,4003 start: ExtraIndex,
3551 /// Index into sub_list.4004 /// Index into extra_data.
3552 end: Index,4005 end: ExtraIndex,
3553 };4006 };
35544007
3555 pub const If = struct {4008 pub const If = struct {
...@@ -3564,13 +4017,13 @@ pub const Node = struct {...@@ -3564,13 +4017,13 @@ pub const Node = struct {
35644017
3565 pub const GlobalVarDecl = struct {4018 pub const GlobalVarDecl = struct {
3566 /// Populated if there is an explicit type ascription.4019 /// Populated if there is an explicit type ascription.
3567 type_node: Index,4020 type_node: OptionalIndex,
3568 /// Populated if align(A) is present.4021 /// Populated if align(A) is present.
3569 align_node: Index,4022 align_node: OptionalIndex,
3570 /// Populated if addrspace(A) is present.4023 /// Populated if addrspace(A) is present.
3571 addrspace_node: Index,4024 addrspace_node: OptionalIndex,
3572 /// Populated if linksection(A) is present.4025 /// Populated if linksection(A) is present.
3573 section_node: Index,4026 section_node: OptionalIndex,
3574 };4027 };
35754028
3576 pub const Slice = struct {4029 pub const Slice = struct {
...@@ -3580,13 +4033,13 @@ pub const Node = struct {...@@ -3580,13 +4033,13 @@ pub const Node = struct {
35804033
3581 pub const SliceSentinel = struct {4034 pub const SliceSentinel = struct {
3582 start: Index,4035 start: Index,
3583 /// May be 0 if the slice is "open"4036 /// May be .none if the slice is "open"
3584 end: Index,4037 end: OptionalIndex,
3585 sentinel: Index,4038 sentinel: Index,
3586 };4039 };
35874040
3588 pub const While = struct {4041 pub const While = struct {
3589 cont_expr: Index,4042 cont_expr: OptionalIndex,
3590 then_expr: Index,4043 then_expr: Index,
3591 else_expr: Index,4044 else_expr: Index,
3592 };4045 };
...@@ -3603,44 +4056,44 @@ pub const Node = struct {...@@ -3603,44 +4056,44 @@ pub const Node = struct {
36034056
3604 pub const FnProtoOne = struct {4057 pub const FnProtoOne = struct {
3605 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.4058 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.
3606 param: Index,4059 param: OptionalIndex,
3607 /// Populated if align(A) is present.4060 /// Populated if align(A) is present.
3608 align_expr: Index,4061 align_expr: OptionalIndex,
3609 /// Populated if addrspace(A) is present.4062 /// Populated if addrspace(A) is present.
3610 addrspace_expr: Index,4063 addrspace_expr: OptionalIndex,
3611 /// Populated if linksection(A) is present.4064 /// Populated if linksection(A) is present.
3612 section_expr: Index,4065 section_expr: OptionalIndex,
3613 /// Populated if callconv(A) is present.4066 /// Populated if callconv(A) is present.
3614 callconv_expr: Index,4067 callconv_expr: OptionalIndex,
3615 };4068 };
36164069
3617 pub const FnProto = struct {4070 pub const FnProto = struct {
3618 params_start: Index,4071 params_start: ExtraIndex,
3619 params_end: Index,4072 params_end: ExtraIndex,
3620 /// Populated if align(A) is present.4073 /// Populated if align(A) is present.
3621 align_expr: Index,4074 align_expr: OptionalIndex,
3622 /// Populated if addrspace(A) is present.4075 /// Populated if addrspace(A) is present.
3623 addrspace_expr: Index,4076 addrspace_expr: OptionalIndex,
3624 /// Populated if linksection(A) is present.4077 /// Populated if linksection(A) is present.
3625 section_expr: Index,4078 section_expr: OptionalIndex,
3626 /// Populated if callconv(A) is present.4079 /// Populated if callconv(A) is present.
3627 callconv_expr: Index,4080 callconv_expr: OptionalIndex,
3628 };4081 };
36294082
3630 pub const Asm = struct {4083 pub const Asm = struct {
3631 items_start: Index,4084 items_start: ExtraIndex,
3632 items_end: Index,4085 items_end: ExtraIndex,
3633 /// Needed to make lastToken() work.4086 /// Needed to make lastToken() work.
3634 rparen: TokenIndex,4087 rparen: TokenIndex,
3635 };4088 };
3636};4089};
36374090
3638pub fn nodeToSpan(tree: *const Ast, node: u32) Span {4091pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span {
3639 return tokensToSpan(4092 return tokensToSpan(
3640 tree,4093 tree,
3641 tree.firstToken(node),4094 tree.firstToken(node),
3642 tree.lastToken(node),4095 tree.lastToken(node),
3643 tree.nodes.items(.main_token)[node],4096 tree.nodeMainToken(node),
3644 );4097 );
3645}4098}
36464099
...@@ -3649,7 +4102,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {...@@ -3649,7 +4102,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
3649}4102}
36504103
3651pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {4104pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
3652 const token_starts = tree.tokens.items(.start);
3653 var start_tok = start;4105 var start_tok = start;
3654 var end_tok = end;4106 var end_tok = end;
36554107
...@@ -3663,9 +4115,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex...@@ -3663,9 +4115,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
3663 start_tok = main;4115 start_tok = main;
3664 end_tok = main;4116 end_tok = main;
3665 }4117 }
3666 const start_off = token_starts[start_tok];4118 const start_off = tree.tokenStart(start_tok);
3667 const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len));4119 const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
3668 return Span{ .start = start_off, .end = end_off, .main = token_starts[main] };4120 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
3669}4121}
36704122
3671const std = @import("../std.zig");4123const std = @import("../std.zig");
lib/std/zig/AstGen.zig+650-835
...@@ -99,8 +99,18 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -99,8 +99,18 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
99 Zir.Inst.Declaration.Name,99 Zir.Inst.Declaration.Name,
100 std.zig.SimpleComptimeReason,100 std.zig.SimpleComptimeReason,
101 Zir.NullTerminatedString,101 Zir.NullTerminatedString,
102 // Ast.TokenIndex is missing because it is a u32.
103 Ast.OptionalTokenIndex,
104 Ast.Node.Index,
105 Ast.Node.OptionalIndex,
102 => @intFromEnum(@field(extra, field.name)),106 => @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
104 i32,114 i32,
105 Zir.Inst.Call.Flags,115 Zir.Inst.Call.Flags,
106 Zir.Inst.BuiltinCall.Flags,116 Zir.Inst.BuiltinCall.Flags,
...@@ -168,7 +178,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {...@@ -168,7 +178,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
168 .is_comptime = true,178 .is_comptime = true,
169 .parent = &top_scope.base,179 .parent = &top_scope.base,
170 .anon_name_strategy = .parent,180 .anon_name_strategy = .parent,
171 .decl_node_index = 0,181 .decl_node_index = .root,
172 .decl_line = 0,182 .decl_line = 0,
173 .astgen = &astgen,183 .astgen = &astgen,
174 .instructions = &gz_instructions,184 .instructions = &gz_instructions,
...@@ -182,10 +192,10 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {...@@ -182,10 +192,10 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir {
182 if (AstGen.structDeclInner(192 if (AstGen.structDeclInner(
183 &gen_scope,193 &gen_scope,
184 &gen_scope.base,194 &gen_scope.base,
185 0,195 .root,
186 tree.containerDeclRoot(),196 tree.containerDeclRoot(),
187 .auto,197 .auto,
188 0,198 .none,
189 )) |struct_decl_ref| {199 )) |struct_decl_ref| {
190 assert(struct_decl_ref.toIndex().? == .main_struct_inst);200 assert(struct_decl_ref.toIndex().? == .main_struct_inst);
191 break :fatal false;201 break :fatal false;
...@@ -430,9 +440,7 @@ fn reachableExprComptime(...@@ -430,9 +440,7 @@ fn reachableExprComptime(
430fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {440fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
431 const astgen = gz.astgen;441 const astgen = gz.astgen;
432 const tree = astgen.tree;442 const tree = astgen.tree;
433 const node_tags = tree.nodes.items(.tag);443 switch (tree.nodeTag(node)) {
434 const main_tokens = tree.nodes.items(.main_token);
435 switch (node_tags[node]) {
436 .root => unreachable,444 .root => unreachable,
437 .@"usingnamespace" => unreachable,445 .@"usingnamespace" => unreachable,
438 .test_decl => unreachable,446 .test_decl => unreachable,
...@@ -600,7 +608,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins...@@ -600,7 +608,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
600 .builtin_call_two,608 .builtin_call_two,
601 .builtin_call_two_comma,609 .builtin_call_two_comma,
602 => {610 => {
603 const builtin_token = main_tokens[node];611 const builtin_token = tree.nodeMainToken(node);
604 const builtin_name = tree.tokenSlice(builtin_token);612 const builtin_name = tree.tokenSlice(builtin_token);
605 // If the builtin is an invalid name, we don't cause an error here; instead613 // If the builtin is an invalid name, we don't cause an error here; instead
606 // let it pass, and the error will be "invalid builtin function" later.614 // 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...@@ -631,10 +639,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
631fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {639fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
632 const astgen = gz.astgen;640 const astgen = gz.astgen;
633 const tree = astgen.tree;641 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
639 const prev_anon_name_strategy = gz.anon_name_strategy;643 const prev_anon_name_strategy = gz.anon_name_strategy;
640 defer gz.anon_name_strategy = prev_anon_name_strategy;644 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...@@ -642,7 +646,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
642 gz.anon_name_strategy = .anon;646 gz.anon_name_strategy = .anon;
643 }647 }
644648
645 switch (node_tags[node]) {649 switch (tree.nodeTag(node)) {
646 .root => unreachable, // Top-level declaration.650 .root => unreachable, // Top-level declaration.
647 .@"usingnamespace" => unreachable, // Top-level declaration.651 .@"usingnamespace" => unreachable, // Top-level declaration.
648 .test_decl => unreachable, // Top-level declaration.652 .test_decl => unreachable, // Top-level declaration.
...@@ -752,8 +756,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -752,8 +756,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
752 },756 },
753757
754 // zig fmt: off758 // zig fmt: off
755 .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl),759 .shl => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shl),
756 .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr),760 .shr => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shr),
757761
758 .add => return simpleBinOp(gz, scope, ri, node, .add),762 .add => return simpleBinOp(gz, scope, ri, node, .add),
759 .add_wrap => return simpleBinOp(gz, scope, ri, node, .addwrap),763 .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...@@ -783,10 +787,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
783 // This syntax form does not currently use the result type in the language specification.787 // This syntax form does not currently use the result type in the language specification.
784 // However, the result type can be used to emit more optimal code for large multiplications by788 // However, the result type can be used to emit more optimal code for large multiplications by
785 // having Sema perform a coercion before the multiplication operation.789 // having Sema perform a coercion before the multiplication operation.
790 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
786 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{791 const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{
787 .res_ty = if (try ri.rl.resultType(gz, node)) |t| t else .none,792 .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),793 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
789 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs, .array_mul_factor),794 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node, .array_mul_factor),
790 });795 });
791 return rvalue(gz, ri, result, node);796 return rvalue(gz, ri, result, node);
792 },797 },
...@@ -797,8 +802,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -797,8 +802,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
797 .merge_error_sets => .merge_error_sets,802 .merge_error_sets => .merge_error_sets,
798 else => unreachable,803 else => unreachable,
799 };804 };
800 const lhs = try reachableTypeExpr(gz, scope, node_datas[node].lhs, node);805 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
801 const rhs = try reachableTypeExpr(gz, scope, node_datas[node].rhs, node);806 const lhs = try reachableTypeExpr(gz, scope, lhs_node, node);
807 const rhs = try reachableTypeExpr(gz, scope, rhs_node, node);
802 const result = try gz.addPlNode(inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });808 const result = try gz.addPlNode(inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
803 return rvalue(gz, ri, result, node);809 return rvalue(gz, ri, result, node);
804 },810 },
...@@ -806,11 +812,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -806,11 +812,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
806 .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),812 .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and),
807 .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or),813 .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),815 .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, tree.nodeData(node).node, .bool_not),
810 .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not),816 .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, tree.nodeData(node).node, .bit_not),
811817
812 .negation => return negation(gz, scope, ri, node),818 .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
815 .identifier => return identifier(gz, scope, ri, node, null),821 .identifier => return identifier(gz, scope, ri, node, null),
816822
...@@ -824,20 +830,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -824,20 +830,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
824 .number_literal => return numberLiteral(gz, ri, node, node, .positive),830 .number_literal => return numberLiteral(gz, ri, node, node, .positive),
825 // zig fmt: on831 // zig fmt: on
826832
827 .builtin_call_two, .builtin_call_two_comma => {833 .builtin_call_two,
828 if (node_datas[node].lhs == 0) {834 .builtin_call_two_comma,
829 const params = [_]Ast.Node.Index{};835 .builtin_call,
830 return builtinCall(gz, scope, ri, node, &params, false);836 .builtin_call_comma,
831 } else if (node_datas[node].rhs == 0) {837 => {
832 const params = [_]Ast.Node.Index{node_datas[node].lhs};838 var buf: [2]Ast.Node.Index = undefined;
833 return builtinCall(gz, scope, ri, node, &params, false);839 const params = tree.builtinCallParams(&buf, node).?;
834 } else {
835 const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };
836 return builtinCall(gz, scope, ri, node, &params, false);
837 }
838 },
839 .builtin_call, .builtin_call_comma => {
840 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
841 return builtinCall(gz, scope, ri, node, params, false);840 return builtinCall(gz, scope, ri, node, params, false);
842 },841 },
843842
...@@ -873,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -873,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
873 const if_full = tree.fullIf(node).?;872 const if_full = tree.fullIf(node).?;
874 no_switch_on_err: {873 no_switch_on_err: {
875 const error_token = if_full.error_token orelse break :no_switch_on_err;874 const error_token = if_full.error_token orelse break :no_switch_on_err;
876 const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err;875 const else_node = if_full.ast.else_expr.unwrap() orelse break :no_switch_on_err;
876 const full_switch = tree.fullSwitch(else_node) orelse break :no_switch_on_err;
877 if (full_switch.label_token != null) break :no_switch_on_err;877 if (full_switch.label_token != null) break :no_switch_on_err;
878 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;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(main_tokens[full_switch.ast.condition]))) 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;
880 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");880 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");
881 }881 }
882 return ifExpr(gz, scope, ri.br(), node, if_full);882 return ifExpr(gz, scope, ri.br(), node, if_full);
...@@ -894,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -894,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
894 .slice_sentinel,894 .slice_sentinel,
895 => {895 => {
896 const full = tree.fullSlice(node).?;896 const full = tree.fullSlice(node).?;
897 if (full.ast.end != 0 and897 if (full.ast.end != .none and
898 node_tags[full.ast.sliced] == .slice_open and898 tree.nodeTag(full.ast.sliced) == .slice_open and
899 nodeIsTriviallyZero(tree, full.ast.start))899 nodeIsTriviallyZero(tree, full.ast.start))
900 {900 {
901 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;901 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
...@@ -903,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -903,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
903 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);903 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);
904 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);904 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start);
905 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);905 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
906 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end);906 const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end.unwrap().?);
907 const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none;907 const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| try expr(gz, scope, .{ .rl = .none }, sentinel) else .none;
908 try emitDbgStmt(gz, cursor);908 try emitDbgStmt(gz, cursor);
909 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{909 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{
910 .lhs = lhs,910 .lhs = lhs,
...@@ -919,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -919,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
919919
920 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);920 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
921 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start);921 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start);
922 const end = if (full.ast.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end) else .none;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 != 0) s: {923 const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| s: {
924 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);924 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);
925 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, full.ast.sentinel);925 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, sentinel);
926 } else .none;926 } else .none;
927 try emitDbgStmt(gz, cursor);927 try emitDbgStmt(gz, cursor);
928 if (sentinel != .none) {928 if (sentinel != .none) {
...@@ -950,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -950,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
950 },950 },
951951
952 .deref => {952 .deref => {
953 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);953 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node);
954 _ = try gz.addUnNode(.validate_deref, lhs, node);954 _ = try gz.addUnNode(.validate_deref, lhs, node);
955 switch (ri.rl) {955 switch (ri.rl) {
956 .ref, .ref_coerced_ty => return lhs,956 .ref, .ref_coerced_ty => return lhs,
...@@ -965,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -965,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
965 _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));965 _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node));
966 break :rl .{ .ref_coerced_ty = res_ty_inst };966 break :rl .{ .ref_coerced_ty = res_ty_inst };
967 } else .ref;967 } else .ref;
968 const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs);968 const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node);
969 return rvalue(gz, ri, result, node);969 return rvalue(gz, ri, result, node);
970 },970 },
971 .optional_type => {971 .optional_type => {
972 const operand = try typeExpr(gz, scope, node_datas[node].lhs);972 const operand = try typeExpr(gz, scope, tree.nodeData(node).node);
973 const result = try gz.addUnNode(.optional_type, operand, node);973 const result = try gz.addUnNode(.optional_type, operand, node);
974 return rvalue(gz, ri, result, node);974 return rvalue(gz, ri, result, node);
975 },975 },
976 .unwrap_optional => switch (ri.rl) {976 .unwrap_optional => switch (ri.rl) {
977 .ref, .ref_coerced_ty => {977 .ref, .ref_coerced_ty => {
978 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);978 const lhs = try expr(gz, scope, .{ .rl = .ref }, tree.nodeData(node).node_and_token[0]);
979979
980 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);980 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
981 try emitDbgStmt(gz, cursor);981 try emitDbgStmt(gz, cursor);
...@@ -983,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -983,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
983 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);983 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
984 },984 },
985 else => {985 else => {
986 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);986 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]);
987987
988 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);988 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
989 try emitDbgStmt(gz, cursor);989 try emitDbgStmt(gz, cursor);
...@@ -991,22 +991,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -991,22 +991,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
991 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);991 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
992 },992 },
993 },993 },
994 .block_two, .block_two_semicolon => {994 .block_two,
995 const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs };995 .block_two_semicolon,
996 if (node_datas[node].lhs == 0) {996 .block,
997 return blockExpr(gz, scope, ri, node, statements[0..0], .normal);997 .block_semicolon,
998 } else if (node_datas[node].rhs == 0) {998 => {
999 return blockExpr(gz, scope, ri, node, statements[0..1], .normal);999 var buf: [2]Ast.Node.Index = undefined;
1000 } else {1000 const statements = tree.blockStatements(&buf, node).?;
1001 return blockExpr(gz, scope, ri, node, statements[0..2], .normal);
1002 }
1003 },
1004 .block, .block_semicolon => {
1005 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
1006 return blockExpr(gz, scope, ri, node, statements, .normal);1001 return blockExpr(gz, scope, ri, node, statements, .normal);
1007 },1002 },
1008 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {1003 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {
1009 const str_index = try astgen.identAsString(main_tokens[node]);1004 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
1010 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{1005 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{
1011 .lhs = res_ty,1006 .lhs = res_ty,
1012 .field_name_start = str_index,1007 .field_name_start = str_index,
...@@ -1016,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1016,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1016 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us1011 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us
1017 .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node),1012 .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node),
1018 }1013 }
1019 } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),1014 } else return simpleStrTok(gz, ri, tree.nodeMainToken(node), node, .enum_literal),
1020 .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value),1015 .error_value => return simpleStrTok(gz, ri, tree.nodeMainToken(node) + 2, node, .error_value),
1021 // TODO restore this when implementing https://github.com/ziglang/zig/issues/60251016 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025
1022 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),1017 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),
1023 .anyframe_literal => {1018 .anyframe_literal => {
...@@ -1025,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1025,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1025 return rvalue(gz, ri, result, node);1020 return rvalue(gz, ri, result, node);
1026 },1021 },
1027 .anyframe_type => {1022 .anyframe_type => {
1028 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);1023 const return_type = try typeExpr(gz, scope, tree.nodeData(node).token_and_node[1]);
1029 const result = try gz.addUnNode(.anyframe_type, return_type, node);1024 const result = try gz.addUnNode(.anyframe_type, return_type, node);
1030 return rvalue(gz, ri, result, node);1025 return rvalue(gz, ri, result, node);
1031 },1026 },
1032 .@"catch" => {1027 .@"catch" => {
1033 const catch_token = main_tokens[node];1028 const catch_token = tree.nodeMainToken(node);
1034 const payload_token: ?Ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe)1029 const payload_token: ?Ast.TokenIndex = if (tree.tokenTag(catch_token + 1) == .pipe)
1035 catch_token + 21030 catch_token + 2
1036 else1031 else
1037 null;1032 null;
1038 no_switch_on_err: {1033 no_switch_on_err: {
1039 const capture_token = payload_token orelse break :no_switch_on_err;1034 const capture_token = payload_token orelse break :no_switch_on_err;
1040 const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err;1035 const full_switch = tree.fullSwitch(tree.nodeData(node).node_and_node[1]) orelse break :no_switch_on_err;
1041 if (full_switch.label_token != null) break :no_switch_on_err;1036 if (full_switch.label_token != null) break :no_switch_on_err;
1042 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;1037 if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err;
1043 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err;1038 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err;
1044 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");1039 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
1045 }1040 }
1046 switch (ri.rl) {1041 switch (ri.rl) {
...@@ -1049,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1049,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1049 scope,1044 scope,
1050 ri,1045 ri,
1051 node,1046 node,
1052 node_datas[node].lhs,
1053 .is_non_err_ptr,1047 .is_non_err_ptr,
1054 .err_union_payload_unsafe_ptr,1048 .err_union_payload_unsafe_ptr,
1055 .err_union_code_ptr,1049 .err_union_code_ptr,
1056 node_datas[node].rhs,
1057 payload_token,1050 payload_token,
1058 ),1051 ),
1059 else => return orelseCatchExpr(1052 else => return orelseCatchExpr(
...@@ -1061,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1061,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1061 scope,1054 scope,
1062 ri,1055 ri,
1063 node,1056 node,
1064 node_datas[node].lhs,
1065 .is_non_err,1057 .is_non_err,
1066 .err_union_payload_unsafe,1058 .err_union_payload_unsafe,
1067 .err_union_code,1059 .err_union_code,
1068 node_datas[node].rhs,
1069 payload_token,1060 payload_token,
1070 ),1061 ),
1071 }1062 }
...@@ -1076,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1076,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1076 scope,1067 scope,
1077 ri,1068 ri,
1078 node,1069 node,
1079 node_datas[node].lhs,
1080 .is_non_null_ptr,1070 .is_non_null_ptr,
1081 .optional_payload_unsafe_ptr,1071 .optional_payload_unsafe_ptr,
1082 undefined,1072 undefined,
1083 node_datas[node].rhs,
1084 null,1073 null,
1085 ),1074 ),
1086 else => return orelseCatchExpr(1075 else => return orelseCatchExpr(
...@@ -1088,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1088,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1088 scope,1077 scope,
1089 ri,1078 ri,
1090 node,1079 node,
1091 node_datas[node].lhs,
1092 .is_non_null,1080 .is_non_null,
1093 .optional_payload_unsafe,1081 .optional_payload_unsafe,
1094 undefined,1082 undefined,
1095 node_datas[node].rhs,
1096 null,1083 null,
1097 ),1084 ),
1098 },1085 },
...@@ -1122,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1122,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11221109
1123 .@"break" => return breakExpr(gz, scope, node),1110 .@"break" => return breakExpr(gz, scope, node),
1124 .@"continue" => return continueExpr(gz, scope, node),1111 .@"continue" => return continueExpr(gz, scope, node),
1125 .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs),1112 .grouped_expression => return expr(gz, scope, ri, tree.nodeData(node).node_and_token[0]),
1126 .array_type => return arrayType(gz, scope, ri, node),1113 .array_type => return arrayType(gz, scope, ri, node),
1127 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),1114 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
1128 .char_literal => return charLiteral(gz, ri, node),1115 .char_literal => return charLiteral(gz, ri, node),
...@@ -1136,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1136,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1136 .@"await" => return awaitExpr(gz, scope, ri, node),1123 .@"await" => return awaitExpr(gz, scope, ri, node),
1137 .@"resume" => return resumeExpr(gz, scope, ri, node),1124 .@"resume" => return resumeExpr(gz, scope, ri, node),
11381125
1139 .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs),1126 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
11401127
1141 .array_init_one,1128 .array_init_one,
1142 .array_init_one_comma,1129 .array_init_one_comma,
...@@ -1183,16 +1170,14 @@ fn nosuspendExpr(...@@ -1183,16 +1170,14 @@ fn nosuspendExpr(
1183) InnerError!Zir.Inst.Ref {1170) InnerError!Zir.Inst.Ref {
1184 const astgen = gz.astgen;1171 const astgen = gz.astgen;
1185 const tree = astgen.tree;1172 const tree = astgen.tree;
1186 const node_datas = tree.nodes.items(.data);1173 const body_node = tree.nodeData(node).node;
1187 const body_node = node_datas[node].lhs;1174 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
1188 assert(body_node != 0);
1189 if (gz.nosuspend_node != 0) {
1190 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{1175 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{
1191 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),1176 try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}),
1192 });1177 });
1193 }1178 }
1194 gz.nosuspend_node = node;1179 gz.nosuspend_node = node.toOptional();
1195 defer gz.nosuspend_node = 0;1180 defer gz.nosuspend_node = .none;
1196 return expr(gz, scope, ri, body_node);1181 return expr(gz, scope, ri, body_node);
1197}1182}
11981183
...@@ -1204,26 +1189,24 @@ fn suspendExpr(...@@ -1204,26 +1189,24 @@ fn suspendExpr(
1204 const astgen = gz.astgen;1189 const astgen = gz.astgen;
1205 const gpa = astgen.gpa;1190 const gpa = astgen.gpa;
1206 const tree = astgen.tree;1191 const tree = astgen.tree;
1207 const node_datas = tree.nodes.items(.data);1192 const body_node = tree.nodeData(node).node;
1208 const body_node = node_datas[node].lhs;
12091193
1210 if (gz.nosuspend_node != 0) {1194 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
1211 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{1195 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{
1212 try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}),1196 try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}),
1213 });1197 });
1214 }1198 }
1215 if (gz.suspend_node != 0) {1199 if (gz.suspend_node.unwrap()) |suspend_node| {
1216 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{1200 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{
1217 try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}),1201 try astgen.errNoteNode(suspend_node, "other suspend block here", .{}),
1218 });1202 });
1219 }1203 }
1220 assert(body_node != 0);
12211204
1222 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);1205 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);
1223 try gz.instructions.append(gpa, suspend_inst);1206 try gz.instructions.append(gpa, suspend_inst);
12241207
1225 var suspend_scope = gz.makeSubBlock(scope);1208 var suspend_scope = gz.makeSubBlock(scope);
1226 suspend_scope.suspend_node = node;1209 suspend_scope.suspend_node = node.toOptional();
1227 defer suspend_scope.unstack();1210 defer suspend_scope.unstack();
12281211
1229 const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal);1212 const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal);
...@@ -1243,16 +1226,15 @@ fn awaitExpr(...@@ -1243,16 +1226,15 @@ fn awaitExpr(
1243) InnerError!Zir.Inst.Ref {1226) InnerError!Zir.Inst.Ref {
1244 const astgen = gz.astgen;1227 const astgen = gz.astgen;
1245 const tree = astgen.tree;1228 const tree = astgen.tree;
1246 const node_datas = tree.nodes.items(.data);1229 const rhs_node = tree.nodeData(node).node;
1247 const rhs_node = node_datas[node].lhs;
12481230
1249 if (gz.suspend_node != 0) {1231 if (gz.suspend_node.unwrap()) |suspend_node| {
1250 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{1232 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
1251 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),1233 try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
1252 });1234 });
1253 }1235 }
1254 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);1236 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1255 const result = if (gz.nosuspend_node != 0)1237 const result = if (gz.nosuspend_node != .none)
1256 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{1238 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
1257 .node = gz.nodeIndexToRelative(node),1239 .node = gz.nodeIndexToRelative(node),
1258 .operand = operand,1240 .operand = operand,
...@@ -1271,8 +1253,7 @@ fn resumeExpr(...@@ -1271,8 +1253,7 @@ fn resumeExpr(
1271) InnerError!Zir.Inst.Ref {1253) InnerError!Zir.Inst.Ref {
1272 const astgen = gz.astgen;1254 const astgen = gz.astgen;
1273 const tree = astgen.tree;1255 const tree = astgen.tree;
1274 const node_datas = tree.nodes.items(.data);1256 const rhs_node = tree.nodeData(node).node;
1275 const rhs_node = node_datas[node].lhs;
1276 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);1257 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1277 const result = try gz.addUnNode(.@"resume", operand, node);1258 const result = try gz.addUnNode(.@"resume", operand, node);
1278 return rvalue(gz, ri, result, node);1259 return rvalue(gz, ri, result, node);
...@@ -1287,33 +1268,33 @@ fn fnProtoExpr(...@@ -1287,33 +1268,33 @@ fn fnProtoExpr(
1287) InnerError!Zir.Inst.Ref {1268) InnerError!Zir.Inst.Ref {
1288 const astgen = gz.astgen;1269 const astgen = gz.astgen;
1289 const tree = astgen.tree;1270 const tree = astgen.tree;
1290 const token_tags = tree.tokens.items(.tag);
12911271
1292 if (fn_proto.name_token) |some| {1272 if (fn_proto.name_token) |some| {
1293 return astgen.failTok(some, "function type cannot have a name", .{});1273 return astgen.failTok(some, "function type cannot have a name", .{});
1294 }1274 }
12951275
1296 if (fn_proto.ast.align_expr != 0) {1276 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1297 return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{});1277 return astgen.failNode(align_expr, "function type cannot have an alignment", .{});
1298 }1278 }
12991279
1300 if (fn_proto.ast.addrspace_expr != 0) {1280 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1301 return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{});1281 return astgen.failNode(addrspace_expr, "function type cannot have an addrspace", .{});
1302 }1282 }
13031283
1304 if (fn_proto.ast.section_expr != 0) {1284 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1305 return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{});1285 return astgen.failNode(section_expr, "function type cannot have a linksection", .{});
1306 }1286 }
13071287
1308 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1288 const return_type = fn_proto.ast.return_type.unwrap().?;
1309 const is_inferred_error = token_tags[maybe_bang] == .bang;1289 const maybe_bang = tree.firstToken(return_type) - 1;
1290 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
1310 if (is_inferred_error) {1291 if (is_inferred_error) {
1311 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});1292 return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{});
1312 }1293 }
13131294
1314 const is_extern = blk: {1295 const is_extern = blk: {
1315 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;1296 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
1316 break :blk token_tags[maybe_extern_token] == .keyword_extern;1297 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
1317 };1298 };
1318 assert(!is_extern);1299 assert(!is_extern);
13191300
...@@ -1330,7 +1311,6 @@ fn fnProtoExprInner(...@@ -1330,7 +1311,6 @@ fn fnProtoExprInner(
1330) InnerError!Zir.Inst.Ref {1311) InnerError!Zir.Inst.Ref {
1331 const astgen = gz.astgen;1312 const astgen = gz.astgen;
1332 const tree = astgen.tree;1313 const tree = astgen.tree;
1333 const token_tags = tree.tokens.items(.tag);
13341314
1335 var block_scope = gz.makeSubBlock(scope);1315 var block_scope = gz.makeSubBlock(scope);
1336 defer block_scope.unstack();1316 defer block_scope.unstack();
...@@ -1342,7 +1322,7 @@ fn fnProtoExprInner(...@@ -1342,7 +1322,7 @@ fn fnProtoExprInner(
1342 var param_type_i: usize = 0;1322 var param_type_i: usize = 0;
1343 var it = fn_proto.iterate(tree);1323 var it = fn_proto.iterate(tree);
1344 while (it.next()) |param| : (param_type_i += 1) {1324 while (it.next()) |param| : (param_type_i += 1) {
1345 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {1325 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
1346 .keyword_noalias => is_comptime: {1326 .keyword_noalias => is_comptime: {
1347 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse1327 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
1348 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));1328 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
...@@ -1353,7 +1333,7 @@ fn fnProtoExprInner(...@@ -1353,7 +1333,7 @@ fn fnProtoExprInner(
1353 } else false;1333 } else false;
13541334
1355 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {1335 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
1356 switch (token_tags[token]) {1336 switch (tree.tokenTag(token)) {
1357 .keyword_anytype => break :blk true,1337 .keyword_anytype => break :blk true,
1358 .ellipsis3 => break :is_var_args true,1338 .ellipsis3 => break :is_var_args true,
1359 else => unreachable,1339 else => unreachable,
...@@ -1376,16 +1356,14 @@ fn fnProtoExprInner(...@@ -1376,16 +1356,14 @@ fn fnProtoExprInner(
1376 .param_anytype;1356 .param_anytype;
1377 _ = try block_scope.addStrTok(tag, param_name, name_token);1357 _ = try block_scope.addStrTok(tag, param_name, name_token);
1378 } else {1358 } else {
1379 const param_type_node = param.type_expr;1359 const param_type_node = param.type_expr.?;
1380 assert(param_type_node != 0);
1381 var param_gz = block_scope.makeSubBlock(scope);1360 var param_gz = block_scope.makeSubBlock(scope);
1382 defer param_gz.unstack();1361 defer param_gz.unstack();
1383 param_gz.is_comptime = true;1362 param_gz.is_comptime = true;
1384 const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal);1363 const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal);
1385 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);1364 const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1);
1386 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);1365 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
1387 const main_tokens = tree.nodes.items(.main_token);1366 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
1388 const name_token = param.name_token orelse main_tokens[param_type_node];
1389 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;1367 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
1390 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous1368 // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous
1391 // arguments (we haven't set up scopes here).1369 // arguments (we haven't set up scopes here).
...@@ -1396,12 +1374,12 @@ fn fnProtoExprInner(...@@ -1396,12 +1374,12 @@ fn fnProtoExprInner(
1396 break :is_var_args false;1374 break :is_var_args false;
1397 };1375 };
13981376
1399 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)1377 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr|
1400 try comptimeExpr(1378 try comptimeExpr(
1401 &block_scope,1379 &block_scope,
1402 scope,1380 scope,
1403 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },1381 .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(callconv_expr, .calling_convention) } },
1404 fn_proto.ast.callconv_expr,1382 callconv_expr,
1405 .@"callconv",1383 .@"callconv",
1406 )1384 )
1407 else if (implicit_ccc)1385 else if (implicit_ccc)
...@@ -1409,7 +1387,8 @@ fn fnProtoExprInner(...@@ -1409,7 +1387,8 @@ fn fnProtoExprInner(
1409 else1387 else
1410 .none;1388 .none;
14111389
1412 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty);1390 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
1391 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty);
14131392
1414 const result = try block_scope.addFunc(.{1393 const result = try block_scope.addFunc(.{
1415 .src_node = fn_proto.ast.proto_node,1394 .src_node = fn_proto.ast.proto_node,
...@@ -1449,33 +1428,32 @@ fn arrayInitExpr(...@@ -1449,33 +1428,32 @@ fn arrayInitExpr(
1449) InnerError!Zir.Inst.Ref {1428) InnerError!Zir.Inst.Ref {
1450 const astgen = gz.astgen;1429 const astgen = gz.astgen;
1451 const tree = astgen.tree;1430 const tree = astgen.tree;
1452 const node_tags = tree.nodes.items(.tag);
1453 const main_tokens = tree.nodes.items(.main_token);
14541431
1455 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.1432 assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init.
14561433
1457 const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: {1434 const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: {
1458 if (array_init.ast.type_expr == 0) break :inst .{ .none, .none };1435 const type_expr = array_init.ast.type_expr.unwrap() orelse break :inst .{ .none, .none };
14591436
1460 infer: {1437 infer: {
1461 const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer;1438 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse break :infer;
1462 // This intentionally does not support `@"_"` syntax.1439 // This intentionally does not support `@"_"` syntax.
1463 if (node_tags[array_type.ast.elem_count] == .identifier and1440 if (tree.nodeTag(array_type.ast.elem_count) == .identifier and
1464 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))1441 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_"))
1465 {1442 {
1466 const len_inst = try gz.addInt(array_init.ast.elements.len);1443 const len_inst = try gz.addInt(array_init.ast.elements.len);
1467 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);1444 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1468 if (array_type.ast.sentinel == 0) {1445 if (array_type.ast.sentinel == .none) {
1469 const array_type_inst = try gz.addPlNode(.array_type, array_init.ast.type_expr, Zir.Inst.Bin{1446 const array_type_inst = try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{
1470 .lhs = len_inst,1447 .lhs = len_inst,
1471 .rhs = elem_type,1448 .rhs = elem_type,
1472 });1449 });
1473 break :inst .{ array_type_inst, elem_type };1450 break :inst .{ array_type_inst, elem_type };
1474 } else {1451 } else {
1475 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);1452 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1453 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
1476 const array_type_inst = try gz.addPlNode(1454 const array_type_inst = try gz.addPlNode(
1477 .array_type_sentinel,1455 .array_type_sentinel,
1478 array_init.ast.type_expr,1456 type_expr,
1479 Zir.Inst.ArrayTypeSentinel{1457 Zir.Inst.ArrayTypeSentinel{
1480 .len = len_inst,1458 .len = len_inst,
1481 .elem_type = elem_type,1459 .elem_type = elem_type,
...@@ -1486,7 +1464,7 @@ fn arrayInitExpr(...@@ -1486,7 +1464,7 @@ fn arrayInitExpr(
1486 }1464 }
1487 }1465 }
1488 }1466 }
1489 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);1467 const array_type_inst = try typeExpr(gz, scope, type_expr);
1490 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{1468 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
1491 .ty = array_type_inst,1469 .ty = array_type_inst,
1492 .init_count = @intCast(array_init.ast.elements.len),1470 .init_count = @intCast(array_init.ast.elements.len),
...@@ -1694,7 +1672,7 @@ fn structInitExpr(...@@ -1694,7 +1672,7 @@ fn structInitExpr(
1694 const astgen = gz.astgen;1672 const astgen = gz.astgen;
1695 const tree = astgen.tree;1673 const tree = astgen.tree;
16961674
1697 if (struct_init.ast.type_expr == 0) {1675 if (struct_init.ast.type_expr == .none) {
1698 if (struct_init.ast.fields.len == 0) {1676 if (struct_init.ast.fields.len == 0) {
1699 // Anonymous init with no fields.1677 // Anonymous init with no fields.
1700 switch (ri.rl) {1678 switch (ri.rl) {
...@@ -1718,32 +1696,32 @@ fn structInitExpr(...@@ -1718,32 +1696,32 @@ fn structInitExpr(
1718 }1696 }
1719 }1697 }
1720 } else array: {1698 } else array: {
1721 const node_tags = tree.nodes.items(.tag);1699 const type_expr = struct_init.ast.type_expr.unwrap().?;
1722 const main_tokens = tree.nodes.items(.main_token);1700 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse {
1723 const array_type: Ast.full.ArrayType = tree.fullArrayType(struct_init.ast.type_expr) orelse {
1724 if (struct_init.ast.fields.len == 0) {1701 if (struct_init.ast.fields.len == 0) {
1725 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1702 const ty_inst = try typeExpr(gz, scope, type_expr);
1726 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1703 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1727 return rvalue(gz, ri, result, node);1704 return rvalue(gz, ri, result, node);
1728 }1705 }
1729 break :array;1706 break :array;
1730 };1707 };
1731 const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and1708 const is_inferred_array_len = tree.nodeTag(array_type.ast.elem_count) == .identifier and
1732 // This intentionally does not support `@"_"` syntax.1709 // This intentionally does not support `@"_"` syntax.
1733 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_");1710 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_");
1734 if (struct_init.ast.fields.len == 0) {1711 if (struct_init.ast.fields.len == 0) {
1735 if (is_inferred_array_len) {1712 if (is_inferred_array_len) {
1736 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);1713 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1737 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {1714 const array_type_inst = if (array_type.ast.sentinel == .none) blk: {
1738 break :blk try gz.addPlNode(.array_type, struct_init.ast.type_expr, Zir.Inst.Bin{1715 break :blk try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{
1739 .lhs = .zero_usize,1716 .lhs = .zero_usize,
1740 .rhs = elem_type,1717 .rhs = elem_type,
1741 });1718 });
1742 } else blk: {1719 } else blk: {
1743 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);1720 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1721 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
1744 break :blk try gz.addPlNode(1722 break :blk try gz.addPlNode(
1745 .array_type_sentinel,1723 .array_type_sentinel,
1746 struct_init.ast.type_expr,1724 type_expr,
1747 Zir.Inst.ArrayTypeSentinel{1725 Zir.Inst.ArrayTypeSentinel{
1748 .len = .zero_usize,1726 .len = .zero_usize,
1749 .elem_type = elem_type,1727 .elem_type = elem_type,
...@@ -1754,12 +1732,12 @@ fn structInitExpr(...@@ -1754,12 +1732,12 @@ fn structInitExpr(
1754 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);1732 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
1755 return rvalue(gz, ri, result, node);1733 return rvalue(gz, ri, result, node);
1756 }1734 }
1757 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1735 const ty_inst = try typeExpr(gz, scope, type_expr);
1758 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1736 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1759 return rvalue(gz, ri, result, node);1737 return rvalue(gz, ri, result, node);
1760 } else {1738 } else {
1761 return astgen.failNode(1739 return astgen.failNode(
1762 struct_init.ast.type_expr,1740 type_expr,
1763 "initializing array with struct syntax",1741 "initializing array with struct syntax",
1764 .{},1742 .{},
1765 );1743 );
...@@ -1818,9 +1796,9 @@ fn structInitExpr(...@@ -1818,9 +1796,9 @@ fn structInitExpr(
1818 }1796 }
1819 }1797 }
18201798
1821 if (struct_init.ast.type_expr != 0) {1799 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
1822 // Typed inits do not use RLS for language simplicity.1800 // Typed inits do not use RLS for language simplicity.
1823 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1801 const ty_inst = try typeExpr(gz, scope, type_expr);
1824 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);1802 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1825 switch (ri.rl) {1803 switch (ri.rl) {
1826 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),1804 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),
...@@ -2009,9 +1987,7 @@ fn comptimeExpr2(...@@ -2009,9 +1987,7 @@ fn comptimeExpr2(
2009 // no need to wrap it in a block. This is hard to determine in general, but we can identify a1987 // no need to wrap it in a block. This is hard to determine in general, but we can identify a
2010 // common subset of trivially comptime expressions to take down the size of the ZIR a bit.1988 // common subset of trivially comptime expressions to take down the size of the ZIR a bit.
2011 const tree = gz.astgen.tree;1989 const tree = gz.astgen.tree;
2012 const main_tokens = tree.nodes.items(.main_token);1990 switch (tree.nodeTag(node)) {
2013 const node_tags = tree.nodes.items(.tag);
2014 switch (node_tags[node]) {
2015 .identifier => {1991 .identifier => {
2016 // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has1992 // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has
2017 // special handling for this case.1993 // special handling for this case.
...@@ -2064,8 +2040,7 @@ fn comptimeExpr2(...@@ -2064,8 +2040,7 @@ fn comptimeExpr2(
2064 // comptime block, because that would be silly! Note that we don't bother doing this for2040 // comptime block, because that would be silly! Note that we don't bother doing this for
2065 // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`).2041 // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`).
2066 .block_two, .block_two_semicolon, .block, .block_semicolon => {2042 .block_two, .block_two_semicolon, .block, .block_semicolon => {
2067 const token_tags = tree.tokens.items(.tag);2043 const lbrace = tree.nodeMainToken(node);
2068 const lbrace = main_tokens[node];
2069 // Careful! We can't pass in the real result location here, since it may2044 // Careful! We can't pass in the real result location here, since it may
2070 // refer to runtime memory. A runtime-to-comptime boundary has to remove2045 // refer to runtime memory. A runtime-to-comptime boundary has to remove
2071 // result location information, compute the result, and copy it to the true2046 // result location information, compute the result, and copy it to the true
...@@ -2077,31 +2052,13 @@ fn comptimeExpr2(...@@ -2077,31 +2052,13 @@ fn comptimeExpr2(
2077 else2052 else
2078 .none,2053 .none,
2079 };2054 };
2080 if (token_tags[lbrace - 1] == .colon and2055 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2081 token_tags[lbrace - 2] == .identifier)2056 var buf: [2]Ast.Node.Index = undefined;
2082 {2057 const stmts = tree.blockStatements(&buf, node).?;
2083 const node_datas = tree.nodes.items(.data);
2084 switch (node_tags[node]) {
2085 .block_two, .block_two_semicolon => {
2086 const stmts: [2]Ast.Node.Index = .{ node_datas[node].lhs, node_datas[node].rhs };
2087 const stmt_slice = if (stmts[0] == 0)
2088 stmts[0..0]
2089 else if (stmts[1] == 0)
2090 stmts[0..1]
2091 else
2092 stmts[0..2];
20932058
2094 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmt_slice, true, .normal);2059 // Replace result location and copy back later - see above.
2095 return rvalue(gz, ri, block_ref, node);2060 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
2096 },2061 return rvalue(gz, ri, block_ref, node);
2097 .block, .block_semicolon => {
2098 const stmts = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
2099 // Replace result location and copy back later - see above.
2100 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
2101 return rvalue(gz, ri, block_ref, node);
2102 },
2103 else => unreachable,
2104 }
2105 }2062 }
2106 },2063 },
21072064
...@@ -2146,8 +2103,7 @@ fn comptimeExprAst(...@@ -2146,8 +2103,7 @@ fn comptimeExprAst(
2146 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});2103 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});
2147 }2104 }
2148 const tree = astgen.tree;2105 const tree = astgen.tree;
2149 const node_datas = tree.nodes.items(.data);2106 const body_node = tree.nodeData(node).node;
2150 const body_node = node_datas[node].lhs;
2151 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);2107 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
2152}2108}
21532109
...@@ -2185,9 +2141,7 @@ fn restoreErrRetIndex(...@@ -2185,9 +2141,7 @@ fn restoreErrRetIndex(
2185fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {2141fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
2186 const astgen = parent_gz.astgen;2142 const astgen = parent_gz.astgen;
2187 const tree = astgen.tree;2143 const tree = astgen.tree;
2188 const node_datas = tree.nodes.items(.data);2144 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
2189 const break_label = node_datas[node].lhs;
2190 const rhs = node_datas[node].rhs;
21912145
2192 // Look for the label in the scope.2146 // Look for the label in the scope.
2193 var scope = parent_scope;2147 var scope = parent_scope;
...@@ -2196,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2196,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2196 .gen_zir => {2150 .gen_zir => {
2197 const block_gz = scope.cast(GenZir).?;2151 const block_gz = scope.cast(GenZir).?;
21982152
2199 if (block_gz.cur_defer_node != 0) {2153 if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| {
2200 // We are breaking out of a `defer` block.2154 // We are breaking out of a `defer` block.
2201 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{2155 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
2202 try astgen.errNoteNode(2156 try astgen.errNoteNode(
2203 block_gz.cur_defer_node,2157 cur_defer_node,
2204 "defer expression here",2158 "defer expression here",
2205 .{},2159 .{},
2206 ),2160 ),
...@@ -2208,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2208,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2208 }2162 }
22092163
2210 const block_inst = blk: {2164 const block_inst = blk: {
2211 if (break_label != 0) {2165 if (opt_break_label.unwrap()) |break_label| {
2212 if (block_gz.label) |*label| {2166 if (block_gz.label) |*label| {
2213 if (try astgen.tokenIdentEql(label.token, break_label)) {2167 if (try astgen.tokenIdentEql(label.token, break_label)) {
2214 label.used = true;2168 label.used = true;
...@@ -2229,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2229,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2229 else2183 else
2230 .@"break";2184 .@"break";
22312185
2232 if (rhs == 0) {2186 const rhs = opt_rhs.unwrap() orelse {
2233 _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node);2187 _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node);
22342188
2235 try genDefers(parent_gz, scope, parent_scope, .normal_only);2189 try genDefers(parent_gz, scope, parent_scope, .normal_only);
...@@ -2240,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2240,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22402194
2241 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);2195 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
2242 return Zir.Inst.Ref.unreachable_value;2196 return Zir.Inst.Ref.unreachable_value;
2243 }2197 };
22442198
2245 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node);2199 const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node);
22462200
...@@ -2272,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2272,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2272 .top => unreachable,2226 .top => unreachable,
2273 }2227 }
2274 }2228 }
2275 if (break_label != 0) {2229 if (opt_break_label.unwrap()) |break_label| {
2276 const label_name = try astgen.identifierTokenString(break_label);2230 const label_name = try astgen.identifierTokenString(break_label);
2277 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});2231 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
2278 } else {2232 } else {
...@@ -2283,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2283,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2283fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {2237fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
2284 const astgen = parent_gz.astgen;2238 const astgen = parent_gz.astgen;
2285 const tree = astgen.tree;2239 const tree = astgen.tree;
2286 const node_datas = tree.nodes.items(.data);2240 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
2287 const break_label = node_datas[node].lhs;
2288 const rhs = node_datas[node].rhs;
22892241
2290 if (break_label == 0 and rhs != 0) {2242 if (opt_break_label == .none and opt_rhs != .none) {
2291 return astgen.failNode(node, "cannot continue with operand without label", .{});2243 return astgen.failNode(node, "cannot continue with operand without label", .{});
2292 }2244 }
22932245
...@@ -2298,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2298,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2298 .gen_zir => {2250 .gen_zir => {
2299 const gen_zir = scope.cast(GenZir).?;2251 const gen_zir = scope.cast(GenZir).?;
23002252
2301 if (gen_zir.cur_defer_node != 0) {2253 if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| {
2302 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{2254 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{
2303 try astgen.errNoteNode(2255 try astgen.errNoteNode(
2304 gen_zir.cur_defer_node,2256 cur_defer_node,
2305 "defer expression here",2257 "defer expression here",
2306 .{},2258 .{},
2307 ),2259 ),
...@@ -2311,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2311,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2311 scope = gen_zir.parent;2263 scope = gen_zir.parent;
2312 continue;2264 continue;
2313 };2265 };
2314 if (break_label != 0) blk: {2266 if (opt_break_label.unwrap()) |break_label| blk: {
2315 if (gen_zir.label) |*label| {2267 if (gen_zir.label) |*label| {
2316 if (try astgen.tokenIdentEql(label.token, break_label)) {2268 if (try astgen.tokenIdentEql(label.token, break_label)) {
2317 const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)];2269 const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)];
2318 if (rhs != 0) switch (maybe_switch_tag) {2270 if (opt_rhs != .none) switch (maybe_switch_tag) {
2319 .switch_block, .switch_block_ref => {},2271 .switch_block, .switch_block_ref => {},
2320 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),2272 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),
2321 } else switch (maybe_switch_tag) {2273 } else switch (maybe_switch_tag) {
...@@ -2343,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2343,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2343 }2295 }
2344 }2296 }
23452297
2346 if (rhs != 0) {2298 if (opt_rhs.unwrap()) |rhs| {
2347 // We need to figure out the result info to use.2299 // We need to figure out the result info to use.
2348 // The type should match2300 // The type should match
2349 const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node);2301 const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node);
...@@ -2382,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2382,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2382 .top => unreachable,2334 .top => unreachable,
2383 }2335 }
2384 }2336 }
2385 if (break_label != 0) {2337 if (opt_break_label.unwrap()) |break_label| {
2386 const label_name = try astgen.identifierTokenString(break_label);2338 const label_name = try astgen.identifierTokenString(break_label);
2387 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});2339 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
2388 } else {2340 } else {
...@@ -2402,30 +2354,14 @@ fn fullBodyExpr(...@@ -2402,30 +2354,14 @@ fn fullBodyExpr(
2402 block_kind: BlockKind,2354 block_kind: BlockKind,
2403) InnerError!Zir.Inst.Ref {2355) InnerError!Zir.Inst.Ref {
2404 const tree = gz.astgen.tree;2356 const tree = gz.astgen.tree;
2405 const node_tags = tree.nodes.items(.tag);2357
2406 const node_datas = tree.nodes.items(.data);
2407 const main_tokens = tree.nodes.items(.main_token);
2408 const token_tags = tree.tokens.items(.tag);
2409 var stmt_buf: [2]Ast.Node.Index = undefined;2358 var stmt_buf: [2]Ast.Node.Index = undefined;
2410 const statements: []const Ast.Node.Index = switch (node_tags[node]) {2359 const statements = tree.blockStatements(&stmt_buf, node) orelse
2411 else => return expr(gz, scope, ri, node),2360 return expr(gz, scope, ri, node);
2412 .block_two, .block_two_semicolon => if (node_datas[node].lhs == 0) s: {
2413 break :s &.{};
2414 } else if (node_datas[node].rhs == 0) s: {
2415 stmt_buf[0] = node_datas[node].lhs;
2416 break :s stmt_buf[0..1];
2417 } else s: {
2418 stmt_buf[0] = node_datas[node].lhs;
2419 stmt_buf[1] = node_datas[node].rhs;
2420 break :s stmt_buf[0..2];
2421 },
2422 .block, .block_semicolon => tree.extra_data[node_datas[node].lhs..node_datas[node].rhs],
2423 };
24242361
2425 const lbrace = main_tokens[node];2362 const lbrace = tree.nodeMainToken(node);
2426 if (token_tags[lbrace - 1] == .colon and2363
2427 token_tags[lbrace - 2] == .identifier)2364 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2428 {
2429 // Labeled blocks are tricky - forwarding result location information properly is non-trivial,2365 // Labeled blocks are tricky - forwarding result location information properly is non-trivial,
2430 // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This2366 // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This
2431 // case is rare, so just treat it as a normal expression and create a nested block.2367 // case is rare, so just treat it as a normal expression and create a nested block.
...@@ -2450,13 +2386,9 @@ fn blockExpr(...@@ -2450,13 +2386,9 @@ fn blockExpr(
2450) InnerError!Zir.Inst.Ref {2386) InnerError!Zir.Inst.Ref {
2451 const astgen = gz.astgen;2387 const astgen = gz.astgen;
2452 const tree = astgen.tree;2388 const tree = astgen.tree;
2453 const main_tokens = tree.nodes.items(.main_token);
2454 const token_tags = tree.tokens.items(.tag);
24552389
2456 const lbrace = main_tokens[block_node];2390 const lbrace = tree.nodeMainToken(block_node);
2457 if (token_tags[lbrace - 1] == .colon and2391 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2458 token_tags[lbrace - 2] == .identifier)
2459 {
2460 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);2392 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);
2461 }2393 }
24622394
...@@ -2533,12 +2465,10 @@ fn labeledBlockExpr(...@@ -2533,12 +2465,10 @@ fn labeledBlockExpr(
2533) InnerError!Zir.Inst.Ref {2465) InnerError!Zir.Inst.Ref {
2534 const astgen = gz.astgen;2466 const astgen = gz.astgen;
2535 const tree = astgen.tree;2467 const tree = astgen.tree;
2536 const main_tokens = tree.nodes.items(.main_token);
2537 const token_tags = tree.tokens.items(.tag);
25382468
2539 const lbrace = main_tokens[block_node];2469 const lbrace = tree.nodeMainToken(block_node);
2540 const label_token = lbrace - 2;2470 const label_token = lbrace - 2;
2541 assert(token_tags[label_token] == .identifier);2471 assert(tree.tokenTag(label_token) == .identifier);
25422472
2543 try astgen.checkLabelRedefinition(parent_scope, label_token);2473 try astgen.checkLabelRedefinition(parent_scope, label_token);
25442474
...@@ -2599,8 +2529,6 @@ fn labeledBlockExpr(...@@ -2599,8 +2529,6 @@ fn labeledBlockExpr(
2599fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void {2529fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void {
2600 const astgen = gz.astgen;2530 const astgen = gz.astgen;
2601 const tree = astgen.tree;2531 const tree = astgen.tree;
2602 const node_tags = tree.nodes.items(.tag);
2603 const node_data = tree.nodes.items(.data);
26042532
2605 if (statements.len == 0) return;2533 if (statements.len == 0) return;
26062534
...@@ -2608,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2608,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2608 defer block_arena.deinit();2536 defer block_arena.deinit();
2609 const block_arena_allocator = block_arena.allocator();2537 const block_arena_allocator = block_arena.allocator();
26102538
2611 var noreturn_src_node: Ast.Node.Index = 0;2539 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
2612 var scope = parent_scope;2540 var scope = parent_scope;
2613 for (statements, 0..) |statement, stmt_idx| {2541 for (statements, 0..) |statement, stmt_idx| {
2614 if (noreturn_src_node != 0) {2542 if (noreturn_src_node.unwrap()) |src_node| {
2615 try astgen.appendErrorNodeNotes(2543 try astgen.appendErrorNodeNotes(
2616 statement,2544 statement,
2617 "unreachable code",2545 "unreachable code",
2618 .{},2546 .{},
2619 &[_]u32{2547 &[_]u32{
2620 try astgen.errNoteNode(2548 try astgen.errNoteNode(
2621 noreturn_src_node,2549 src_node,
2622 "control flow is diverted here",2550 "control flow is diverted here",
2623 .{},2551 .{},
2624 ),2552 ),
...@@ -2631,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2631,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2631 };2559 };
2632 var inner_node = statement;2560 var inner_node = statement;
2633 while (true) {2561 while (true) {
2634 switch (node_tags[inner_node]) {2562 switch (tree.nodeTag(inner_node)) {
2635 // zig fmt: off2563 // zig fmt: off
2636 .global_var_decl,2564 .global_var_decl,
2637 .local_var_decl,2565 .local_var_decl,
...@@ -2661,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2661,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2661 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),2589 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
26622590
2663 .grouped_expression => {2591 .grouped_expression => {
2664 inner_node = node_data[statement].lhs;2592 inner_node = tree.nodeData(statement).node_and_token[0];
2665 continue;2593 continue;
2666 },2594 },
26672595
...@@ -2671,47 +2599,37 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2671,47 +2599,37 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26712599
2672 .for_simple,2600 .for_simple,
2673 .@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true),2601 .@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true),
2602 // zig fmt: on
26742603
2675 // These cases are here to allow branch hints.2604 // These cases are here to allow branch hints.
2676 .builtin_call_two, .builtin_call_two_comma => {2605 .builtin_call_two,
2677 try emitDbgNode(gz, inner_node);2606 .builtin_call_two_comma,
2678 const ri: ResultInfo = .{ .rl = .none };2607 .builtin_call,
2679 const result = if (node_data[inner_node].lhs == 0) r: {2608 .builtin_call_comma,
2680 break :r try builtinCall(gz, scope, ri, inner_node, &.{}, allow_branch_hint);2609 => {
2681 } else if (node_data[inner_node].rhs == 0) r: {2610 var buf: [2]Ast.Node.Index = undefined;
2682 break :r try builtinCall(gz, scope, ri, inner_node, &.{node_data[inner_node].lhs}, allow_branch_hint);2611 const params = tree.builtinCallParams(&buf, inner_node).?;
2683 } else r: {2612
2684 break :r try builtinCall(gz, scope, ri, inner_node, &.{
2685 node_data[inner_node].lhs,
2686 node_data[inner_node].rhs,
2687 }, allow_branch_hint);
2688 };
2689 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
2690 },
2691 .builtin_call, .builtin_call_comma => {
2692 try emitDbgNode(gz, inner_node);2613 try emitDbgNode(gz, inner_node);
2693 const ri: ResultInfo = .{ .rl = .none };2614 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint);
2694 const params = tree.extra_data[node_data[inner_node].lhs..node_data[inner_node].rhs];
2695 const result = try builtinCall(gz, scope, ri, inner_node, params, allow_branch_hint);
2696 noreturn_src_node = try addEnsureResult(gz, result, inner_node);2615 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
2697 },2616 },
26982617
2699 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),2618 else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
2700 // zig fmt: on
2701 }2619 }
2702 break;2620 break;
2703 }2621 }
2704 }2622 }
27052623
2706 if (noreturn_src_node == 0) {2624 if (noreturn_src_node == .none) {
2707 try genDefers(gz, parent_scope, scope, .normal_only);2625 try genDefers(gz, parent_scope, scope, .normal_only);
2708 }2626 }
2709 try checkUsed(gz, parent_scope, scope);2627 try checkUsed(gz, parent_scope, scope);
2710}2628}
27112629
2712/// Returns AST source node of the thing that is noreturn if the statement is2630/// Returns AST source node of the thing that is noreturn if the statement is
2713/// definitely `noreturn`. Otherwise returns 0.2631/// definitely `noreturn`. Otherwise returns .none.
2714fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index {2632fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex {
2715 try emitDbgNode(gz, statement);2633 try emitDbgNode(gz, statement);
2716 // We need to emit an error if the result is not `noreturn` or `void`, but2634 // We need to emit an error if the result is not `noreturn` or `void`, but
2717 // we want to avoid adding the ZIR instruction if possible for performance.2635 // we want to avoid adding the ZIR instruction if possible for performance.
...@@ -2719,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2719,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2719 return addEnsureResult(gz, maybe_unused_result, statement);2637 return addEnsureResult(gz, maybe_unused_result, statement);
2720}2638}
27212639
2722fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index {2640fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex {
2723 var noreturn_src_node: Ast.Node.Index = 0;2641 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
2724 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {2642 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {
2725 // Note that this array becomes invalid after appending more items to it2643 // Note that this array becomes invalid after appending more items to it
2726 // in the above while loop.2644 // in the above while loop.
...@@ -2981,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2981,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2981 .check_comptime_control_flow,2899 .check_comptime_control_flow,
2982 .switch_continue,2900 .switch_continue,
2983 => {2901 => {
2984 noreturn_src_node = statement;2902 noreturn_src_node = statement.toOptional();
2985 break :b true;2903 break :b true;
2986 },2904 },
29872905
...@@ -3023,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -3023,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
3023 .none => unreachable,2941 .none => unreachable,
30242942
3025 .unreachable_value => b: {2943 .unreachable_value => b: {
3026 noreturn_src_node = statement;2944 noreturn_src_node = statement.toOptional();
3027 break :b true;2945 break :b true;
3028 },2946 },
30292947
...@@ -3152,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v...@@ -3152,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
3152 .gen_zir => scope = scope.cast(GenZir).?.parent,3070 .gen_zir => scope = scope.cast(GenZir).?.parent,
3153 .local_val => {3071 .local_val => {
3154 const s = scope.cast(Scope.LocalVal).?;3072 const s = scope.cast(Scope.LocalVal).?;
3155 if (s.used == 0 and s.discarded == 0) {3073 if (s.used == .none and s.discarded == .none) {
3156 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});3074 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
3157 } else if (s.used != 0 and s.discarded != 0) {3075 } else if (s.used != .none and s.discarded != .none) {
3158 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{3076 try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3159 try gz.astgen.errNoteTok(s.used, "used here", .{}),3077 try gz.astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
3160 });3078 });
3161 }3079 }
3162 scope = s.parent;3080 scope = s.parent;
3163 },3081 },
3164 .local_ptr => {3082 .local_ptr => {
3165 const s = scope.cast(Scope.LocalPtr).?;3083 const s = scope.cast(Scope.LocalPtr).?;
3166 if (s.used == 0 and s.discarded == 0) {3084 if (s.used == .none and s.discarded == .none) {
3167 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});3085 try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
3168 } else {3086 } else {
3169 if (s.used != 0 and s.discarded != 0) {3087 if (s.used != .none and s.discarded != .none) {
3170 try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{3088 try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{
3171 try astgen.errNoteTok(s.used, "used here", .{}),3089 try astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
3172 });3090 });
3173 }3091 }
3174 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {3092 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {
...@@ -3195,19 +3113,15 @@ fn deferStmt(...@@ -3195,19 +3113,15 @@ fn deferStmt(
3195 scope_tag: Scope.Tag,3113 scope_tag: Scope.Tag,
3196) InnerError!*Scope {3114) InnerError!*Scope {
3197 var defer_gen = gz.makeSubBlock(scope);3115 var defer_gen = gz.makeSubBlock(scope);
3198 defer_gen.cur_defer_node = node;3116 defer_gen.cur_defer_node = node.toOptional();
3199 defer_gen.any_defer_node = node;3117 defer_gen.any_defer_node = node.toOptional();
3200 defer defer_gen.unstack();3118 defer defer_gen.unstack();
32013119
3202 const tree = gz.astgen.tree;3120 const tree = gz.astgen.tree;
3203 const node_datas = tree.nodes.items(.data);
3204 const expr_node = node_datas[node].rhs;
3205
3206 const payload_token = node_datas[node].lhs;
3207 var local_val_scope: Scope.LocalVal = undefined;3121 var local_val_scope: Scope.LocalVal = undefined;
3208 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;3122 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3209 const have_err_code = scope_tag == .defer_error and payload_token != 0;3123 const sub_scope = if (scope_tag != .defer_error) &defer_gen.base else blk: {
3210 const sub_scope = if (!have_err_code) &defer_gen.base else blk: {3124 const payload_token = tree.nodeData(node).opt_token_and_node[0].unwrap() orelse break :blk &defer_gen.base;
3211 const ident_name = try gz.astgen.identAsString(payload_token);3125 const ident_name = try gz.astgen.identAsString(payload_token);
3212 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {3126 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {
3213 try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{});3127 try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{});
...@@ -3235,6 +3149,11 @@ fn deferStmt(...@@ -3235,6 +3149,11 @@ fn deferStmt(
3235 try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref);3149 try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref);
3236 break :blk &local_val_scope.base;3150 break :blk &local_val_scope.base;
3237 };3151 };
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 };
3238 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);3157 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
3239 try checkUsed(gz, scope, sub_scope);3158 try checkUsed(gz, scope, sub_scope);
3240 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);3159 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
...@@ -3269,8 +3188,6 @@ fn varDecl(...@@ -3269,8 +3188,6 @@ fn varDecl(
3269 try emitDbgNode(gz, node);3188 try emitDbgNode(gz, node);
3270 const astgen = gz.astgen;3189 const astgen = gz.astgen;
3271 const tree = astgen.tree;3190 const tree = astgen.tree;
3272 const token_tags = tree.tokens.items(.tag);
3273 const main_tokens = tree.nodes.items(.main_token);
32743191
3275 const name_token = var_decl.ast.mut_token + 1;3192 const name_token = var_decl.ast.mut_token + 1;
3276 const ident_name_raw = tree.tokenSlice(name_token);3193 const ident_name_raw = tree.tokenSlice(name_token);
...@@ -3284,27 +3201,27 @@ fn varDecl(...@@ -3284,27 +3201,27 @@ fn varDecl(
3284 ident_name,3201 ident_name,
3285 name_token,3202 name_token,
3286 ident_name_raw,3203 ident_name_raw,
3287 if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable",3204 if (tree.tokenTag(var_decl.ast.mut_token) == .keyword_const) .@"local constant" else .@"local variable",
3288 );3205 );
32893206
3290 if (var_decl.ast.init_node == 0) {3207 const init_node = var_decl.ast.init_node.unwrap() orelse {
3291 return astgen.failNode(node, "variables must be initialized", .{});3208 return astgen.failNode(node, "variables must be initialized", .{});
3292 }3209 };
32933210
3294 if (var_decl.ast.addrspace_node != 0) {3211 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3295 return astgen.failTok(main_tokens[var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw});3212 return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw});
3296 }3213 }
32973214
3298 if (var_decl.ast.section_node != 0) {3215 if (var_decl.ast.section_node.unwrap()) |section_node| {
3299 return astgen.failTok(main_tokens[var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw});3216 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});
3300 }3217 }
33013218
3302 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0)3219 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node|
3303 try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node)3220 try expr(gz, scope, coerced_align_ri, align_node)
3304 else3221 else
3305 .none;3222 .none;
33063223
3307 switch (token_tags[var_decl.ast.mut_token]) {3224 switch (tree.tokenTag(var_decl.ast.mut_token)) {
3308 .keyword_const => {3225 .keyword_const => {
3309 if (var_decl.comptime_token) |comptime_token| {3226 if (var_decl.comptime_token) |comptime_token| {
3310 try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});3227 try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{});
...@@ -3316,25 +3233,24 @@ fn varDecl(...@@ -3316,25 +3233,24 @@ fn varDecl(
3316 // Depending on the type of AST the initialization expression is, we may need an lvalue3233 // Depending on the type of AST the initialization expression is, we may need an lvalue
3317 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as3234 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
3318 // the variable, no memory location needed.3235 // the variable, no memory location needed.
3319 const type_node = var_decl.ast.type_node;
3320 if (align_inst == .none and3236 if (align_inst == .none and
3321 !astgen.nodes_need_rl.contains(node))3237 !astgen.nodes_need_rl.contains(node))
3322 {3238 {
3323 const result_info: ResultInfo = if (type_node != 0) .{3239 const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{
3324 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },3240 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
3325 .ctx = .const_init,3241 .ctx = .const_init,
3326 } else .{ .rl = .none, .ctx = .const_init };3242 } else .{ .rl = .none, .ctx = .const_init };
3327 const prev_anon_name_strategy = gz.anon_name_strategy;3243 const prev_anon_name_strategy = gz.anon_name_strategy;
3328 gz.anon_name_strategy = .dbg_var;3244 gz.anon_name_strategy = .dbg_var;
3329 const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);3245 const init_inst = try reachableExprComptime(gz, scope, result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
3330 gz.anon_name_strategy = prev_anon_name_strategy;3246 gz.anon_name_strategy = prev_anon_name_strategy;
33313247
3332 _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node);3248 _ = try gz.addUnNode(.validate_const, init_inst, init_node);
3333 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);3249 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
33343250
3335 // The const init expression may have modified the error return trace, so signal3251 // The const init expression may have modified the error return trace, so signal
3336 // to Sema that it should save the new index for restoring later.3252 // to Sema that it should save the new index for restoring later.
3337 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))3253 if (nodeMayAppendToErrorTrace(tree, init_node))
3338 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });3254 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
33393255
3340 const sub_scope = try block_arena.create(Scope.LocalVal);3256 const sub_scope = try block_arena.create(Scope.LocalVal);
...@@ -3350,9 +3266,9 @@ fn varDecl(...@@ -3350,9 +3266,9 @@ fn varDecl(
3350 }3266 }
33513267
3352 const is_comptime = gz.is_comptime or3268 const is_comptime = gz.is_comptime or
3353 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";3269 tree.nodeTag(init_node) == .@"comptime";
33543270
3355 const init_rl: ResultInfo.Loc = if (type_node != 0) init_rl: {3271 const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: {
3356 const type_inst = try typeExpr(gz, scope, type_node);3272 const type_inst = try typeExpr(gz, scope, type_node);
3357 if (align_inst == .none) {3273 if (align_inst == .none) {
3358 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };3274 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };
...@@ -3393,11 +3309,11 @@ fn varDecl(...@@ -3393,11 +3309,11 @@ fn varDecl(
3393 const prev_anon_name_strategy = gz.anon_name_strategy;3309 const prev_anon_name_strategy = gz.anon_name_strategy;
3394 gz.anon_name_strategy = .dbg_var;3310 gz.anon_name_strategy = .dbg_var;
3395 defer gz.anon_name_strategy = prev_anon_name_strategy;3311 defer gz.anon_name_strategy = prev_anon_name_strategy;
3396 const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);3312 const init_inst = try reachableExprComptime(gz, scope, init_result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
33973313
3398 // The const init expression may have modified the error return trace, so signal3314 // The const init expression may have modified the error return trace, so signal
3399 // to Sema that it should save the new index for restoring later.3315 // to Sema that it should save the new index for restoring later.
3400 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))3316 if (nodeMayAppendToErrorTrace(tree, init_node))
3401 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });3317 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
34023318
3403 const const_ptr = if (resolve_inferred)3319 const const_ptr = if (resolve_inferred)
...@@ -3423,8 +3339,8 @@ fn varDecl(...@@ -3423,8 +3339,8 @@ fn varDecl(
3423 if (var_decl.comptime_token != null and gz.is_comptime)3339 if (var_decl.comptime_token != null and gz.is_comptime)
3424 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});3340 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});
3425 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;3341 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
3426 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: {3342 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| a: {
3427 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);3343 const type_inst = try typeExpr(gz, scope, type_node);
3428 const alloc = alloc: {3344 const alloc = alloc: {
3429 if (align_inst == .none) {3345 if (align_inst == .none) {
3430 const tag: Zir.Inst.Tag = if (is_comptime)3346 const tag: Zir.Inst.Tag = if (is_comptime)
...@@ -3469,7 +3385,7 @@ fn varDecl(...@@ -3469,7 +3385,7 @@ fn varDecl(
3469 gz,3385 gz,
3470 scope,3386 scope,
3471 result_info,3387 result_info,
3472 var_decl.ast.init_node,3388 init_node,
3473 node,3389 node,
3474 if (var_decl.comptime_token != null) .comptime_keyword else null,3390 if (var_decl.comptime_token != null) .comptime_keyword else null,
3475 );3391 );
...@@ -3512,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi...@@ -3512,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
3512 try emitDbgNode(gz, infix_node);3428 try emitDbgNode(gz, infix_node);
3513 const astgen = gz.astgen;3429 const astgen = gz.astgen;
3514 const tree = astgen.tree;3430 const tree = astgen.tree;
3515 const node_datas = tree.nodes.items(.data);
3516 const main_tokens = tree.nodes.items(.main_token);
3517 const node_tags = tree.nodes.items(.tag);
35183431
3519 const lhs = node_datas[infix_node].lhs;3432 const lhs, const rhs = tree.nodeData(infix_node).node_and_node;
3520 const rhs = node_datas[infix_node].rhs;3433 if (tree.nodeTag(lhs) == .identifier) {
3521 if (node_tags[lhs] == .identifier) {
3522 // This intentionally does not support `@"_"` syntax.3434 // This intentionally does not support `@"_"` syntax.
3523 const ident_name = tree.tokenSlice(main_tokens[lhs]);3435 const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs));
3524 if (mem.eql(u8, ident_name, "_")) {3436 if (mem.eql(u8, ident_name, "_")) {
3525 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);3437 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
3526 return;3438 return;
...@@ -3538,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro...@@ -3538,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
3538 try emitDbgNode(gz, node);3450 try emitDbgNode(gz, node);
3539 const astgen = gz.astgen;3451 const astgen = gz.astgen;
3540 const tree = astgen.tree;3452 const tree = astgen.tree;
3541 const main_tokens = tree.nodes.items(.main_token);
3542 const node_tags = tree.nodes.items(.tag);
35433453
3544 const full = tree.assignDestructure(node);3454 const full = tree.assignDestructure(node);
3545 if (full.comptime_token != null and gz.is_comptime) {3455 if (full.comptime_token != null and gz.is_comptime) {
...@@ -3557,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro...@@ -3557,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
35573467
3558 const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len);3468 const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len);
3559 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3469 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3560 if (node_tags[variable_node] == .identifier) {3470 if (tree.nodeTag(variable_node) == .identifier) {
3561 // This intentionally does not support `@"_"` syntax.3471 // This intentionally does not support `@"_"` syntax.
3562 const ident_name = tree.tokenSlice(main_tokens[variable_node]);3472 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
3563 if (mem.eql(u8, ident_name, "_")) {3473 if (mem.eql(u8, ident_name, "_")) {
3564 variable_rl.* = .discard;3474 variable_rl.* = .discard;
3565 continue;3475 continue;
...@@ -3596,9 +3506,6 @@ fn assignDestructureMaybeDecls(...@@ -3596,9 +3506,6 @@ fn assignDestructureMaybeDecls(
3596 try emitDbgNode(gz, node);3506 try emitDbgNode(gz, node);
3597 const astgen = gz.astgen;3507 const astgen = gz.astgen;
3598 const tree = astgen.tree;3508 const tree = astgen.tree;
3599 const token_tags = tree.tokens.items(.tag);
3600 const main_tokens = tree.nodes.items(.main_token);
3601 const node_tags = tree.nodes.items(.tag);
36023509
3603 const full = tree.assignDestructure(node);3510 const full = tree.assignDestructure(node);
3604 if (full.comptime_token != null and gz.is_comptime) {3511 if (full.comptime_token != null and gz.is_comptime) {
...@@ -3606,7 +3513,7 @@ fn assignDestructureMaybeDecls(...@@ -3606,7 +3513,7 @@ fn assignDestructureMaybeDecls(
3606 }3513 }
36073514
3608 const is_comptime = full.comptime_token != null or gz.is_comptime;3515 const is_comptime = full.comptime_token != null or gz.is_comptime;
3609 const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime";3516 const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime";
36103517
3611 // When declaring consts via a destructure, we always use a result pointer.3518 // When declaring consts via a destructure, we always use a result pointer.
3612 // This avoids the need to create tuple types, and is also likely easier to3519 // This avoids the need to create tuple types, and is also likely easier to
...@@ -3619,10 +3526,10 @@ fn assignDestructureMaybeDecls(...@@ -3619,10 +3526,10 @@ fn assignDestructureMaybeDecls(
3619 var any_non_const_variables = false;3526 var any_non_const_variables = false;
3620 var any_lvalue_expr = false;3527 var any_lvalue_expr = false;
3621 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3528 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3622 switch (node_tags[variable_node]) {3529 switch (tree.nodeTag(variable_node)) {
3623 .identifier => {3530 .identifier => {
3624 // This intentionally does not support `@"_"` syntax.3531 // This intentionally does not support `@"_"` syntax.
3625 const ident_name = tree.tokenSlice(main_tokens[variable_node]);3532 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
3626 if (mem.eql(u8, ident_name, "_")) {3533 if (mem.eql(u8, ident_name, "_")) {
3627 any_non_const_variables = true;3534 any_non_const_variables = true;
3628 variable_rl.* = .discard;3535 variable_rl.* = .discard;
...@@ -3640,14 +3547,14 @@ fn assignDestructureMaybeDecls(...@@ -3640,14 +3547,14 @@ fn assignDestructureMaybeDecls(
36403547
3641 // We detect shadowing in the second pass over these, while we're creating scopes.3548 // We detect shadowing in the second pass over these, while we're creating scopes.
36423549
3643 if (full_var_decl.ast.addrspace_node != 0) {3550 if (full_var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3644 return astgen.failTok(main_tokens[full_var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw});3551 return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw});
3645 }3552 }
3646 if (full_var_decl.ast.section_node != 0) {3553 if (full_var_decl.ast.section_node.unwrap()) |section_node| {
3647 return astgen.failTok(main_tokens[full_var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw});3554 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});
3648 }3555 }
36493556
3650 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {3557 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
3651 .keyword_var => false,3558 .keyword_var => false,
3652 .keyword_const => true,3559 .keyword_const => true,
3653 else => unreachable,3560 else => unreachable,
...@@ -3657,14 +3564,14 @@ fn assignDestructureMaybeDecls(...@@ -3657,14 +3564,14 @@ fn assignDestructureMaybeDecls(
3657 // We also mark `const`s as comptime if the RHS is definitely comptime-known.3564 // We also mark `const`s as comptime if the RHS is definitely comptime-known.
3658 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);3565 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);
36593566
3660 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node != 0)3567 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node|
3661 try expr(gz, scope, coerced_align_ri, full_var_decl.ast.align_node)3568 try expr(gz, scope, coerced_align_ri, align_node)
3662 else3569 else
3663 .none;3570 .none;
36643571
3665 if (full_var_decl.ast.type_node != 0) {3572 if (full_var_decl.ast.type_node.unwrap()) |type_node| {
3666 // Typed alloc3573 // Typed alloc
3667 const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node);3574 const type_inst = try typeExpr(gz, scope, type_node);
3668 const ptr = if (align_inst == .none) ptr: {3575 const ptr = if (align_inst == .none) ptr: {
3669 const tag: Zir.Inst.Tag = if (is_const)3576 const tag: Zir.Inst.Tag = if (is_const)
3670 .alloc3577 .alloc
...@@ -3733,7 +3640,7 @@ fn assignDestructureMaybeDecls(...@@ -3733,7 +3640,7 @@ fn assignDestructureMaybeDecls(
3733 // evaluate the lvalues from within the possible block_comptime.3640 // evaluate the lvalues from within the possible block_comptime.
3734 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3641 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3735 if (variable_rl.* != .typed_ptr) continue;3642 if (variable_rl.* != .typed_ptr) continue;
3736 switch (node_tags[variable_node]) {3643 switch (tree.nodeTag(variable_node)) {
3737 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue,3644 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue,
3738 else => {},3645 else => {},
3739 }3646 }
...@@ -3762,7 +3669,7 @@ fn assignDestructureMaybeDecls(...@@ -3762,7 +3669,7 @@ fn assignDestructureMaybeDecls(
3762 // If there were any `const` decls, make the pointer constant.3669 // If there were any `const` decls, make the pointer constant.
3763 var cur_scope = scope;3670 var cur_scope = scope;
3764 for (rl_components, full.ast.variables) |variable_rl, variable_node| {3671 for (rl_components, full.ast.variables) |variable_rl, variable_node| {
3765 switch (node_tags[variable_node]) {3672 switch (tree.nodeTag(variable_node)) {
3766 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},3673 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},
3767 else => continue, // We were mutating an existing lvalue - nothing to do3674 else => continue, // We were mutating an existing lvalue - nothing to do
3768 }3675 }
...@@ -3772,7 +3679,7 @@ fn assignDestructureMaybeDecls(...@@ -3772,7 +3679,7 @@ fn assignDestructureMaybeDecls(
3772 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },3679 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },
3773 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },3680 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },
3774 };3681 };
3775 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {3682 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
3776 .keyword_var => false,3683 .keyword_var => false,
3777 .keyword_const => true,3684 .keyword_const => true,
3778 else => unreachable,3685 else => unreachable,
...@@ -3823,9 +3730,9 @@ fn assignOp(...@@ -3823,9 +3730,9 @@ fn assignOp(
3823 try emitDbgNode(gz, infix_node);3730 try emitDbgNode(gz, infix_node);
3824 const astgen = gz.astgen;3731 const astgen = gz.astgen;
3825 const tree = astgen.tree;3732 const tree = astgen.tree;
3826 const node_datas = tree.nodes.items(.data);
38273733
3828 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3734 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3735 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
38293736
3830 const cursor = switch (op_inst_tag) {3737 const cursor = switch (op_inst_tag) {
3831 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),3738 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
...@@ -3851,7 +3758,7 @@ fn assignOp(...@@ -3851,7 +3758,7 @@ fn assignOp(
3851 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type3758 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type
3852 };3759 };
3853 // Not `coerced_ty` since `add`/etc won't coerce to this type.3760 // Not `coerced_ty` since `add`/etc won't coerce to this type.
3854 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, node_datas[infix_node].rhs);3761 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, rhs_node);
38553762
3856 switch (op_inst_tag) {3763 switch (op_inst_tag) {
3857 .add, .sub, .mul, .div, .mod_rem => {3764 .add, .sub, .mul, .div, .mod_rem => {
...@@ -3878,12 +3785,12 @@ fn assignShift(...@@ -3878,12 +3785,12 @@ fn assignShift(
3878 try emitDbgNode(gz, infix_node);3785 try emitDbgNode(gz, infix_node);
3879 const astgen = gz.astgen;3786 const astgen = gz.astgen;
3880 const tree = astgen.tree;3787 const tree = astgen.tree;
3881 const node_datas = tree.nodes.items(.data);
38823788
3883 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3789 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3790 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
3884 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3791 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3885 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);3792 const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node);
3886 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs);3793 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, rhs_node);
38873794
3888 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{3795 const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{
3889 .lhs = lhs,3796 .lhs = lhs,
...@@ -3899,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE...@@ -3899,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
3899 try emitDbgNode(gz, infix_node);3806 try emitDbgNode(gz, infix_node);
3900 const astgen = gz.astgen;3807 const astgen = gz.astgen;
3901 const tree = astgen.tree;3808 const tree = astgen.tree;
3902 const node_datas = tree.nodes.items(.data);
39033809
3904 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3810 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3811 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
3905 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3812 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3906 // Saturating shift-left allows any integer type for both the LHS and RHS.3813 // Saturating shift-left allows any integer type for both the LHS and RHS.
3907 const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs);3814 const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node);
39083815
3909 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{3816 const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{
3910 .lhs = lhs,3817 .lhs = lhs,
...@@ -3939,7 +3846,7 @@ fn ptrType(...@@ -3939,7 +3846,7 @@ fn ptrType(
3939 var bit_end_ref: Zir.Inst.Ref = .none;3846 var bit_end_ref: Zir.Inst.Ref = .none;
3940 var trailing_count: u32 = 0;3847 var trailing_count: u32 = 0;
39413848
3942 if (ptr_info.ast.sentinel != 0) {3849 if (ptr_info.ast.sentinel.unwrap()) |sentinel| {
3943 // These attributes can appear in any order and they all come before the3850 // These attributes can appear in any order and they all come before the
3944 // element type so we need to reset the source cursor before generating them.3851 // element type so we need to reset the source cursor before generating them.
3945 gz.astgen.source_offset = source_offset;3852 gz.astgen.source_offset = source_offset;
...@@ -3950,7 +3857,7 @@ fn ptrType(...@@ -3950,7 +3857,7 @@ fn ptrType(
3950 gz,3857 gz,
3951 scope,3858 scope,
3952 .{ .rl = .{ .ty = elem_type } },3859 .{ .rl = .{ .ty = elem_type } },
3953 ptr_info.ast.sentinel,3860 sentinel,
3954 switch (ptr_info.size) {3861 switch (ptr_info.size) {
3955 .slice => .slice_sentinel,3862 .slice => .slice_sentinel,
3956 else => .pointer_sentinel,3863 else => .pointer_sentinel,
...@@ -3958,27 +3865,27 @@ fn ptrType(...@@ -3958,27 +3865,27 @@ fn ptrType(
3958 );3865 );
3959 trailing_count += 1;3866 trailing_count += 1;
3960 }3867 }
3961 if (ptr_info.ast.addrspace_node != 0) {3868 if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| {
3962 gz.astgen.source_offset = source_offset;3869 gz.astgen.source_offset = source_offset;
3963 gz.astgen.source_line = source_line;3870 gz.astgen.source_line = source_line;
3964 gz.astgen.source_column = source_column;3871 gz.astgen.source_column = source_column;
39653872
3966 const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space);3873 const addrspace_ty = try gz.addBuiltinValue(addrspace_node, .address_space);
3967 addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node, .@"addrspace");3874 addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node, .@"addrspace");
3968 trailing_count += 1;3875 trailing_count += 1;
3969 }3876 }
3970 if (ptr_info.ast.align_node != 0) {3877 if (ptr_info.ast.align_node.unwrap()) |align_node| {
3971 gz.astgen.source_offset = source_offset;3878 gz.astgen.source_offset = source_offset;
3972 gz.astgen.source_line = source_line;3879 gz.astgen.source_line = source_line;
3973 gz.astgen.source_column = source_column;3880 gz.astgen.source_column = source_column;
39743881
3975 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align");3882 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align");
3976 trailing_count += 1;3883 trailing_count += 1;
3977 }3884 }
3978 if (ptr_info.ast.bit_range_start != 0) {3885 if (ptr_info.ast.bit_range_start.unwrap()) |bit_range_start| {
3979 assert(ptr_info.ast.bit_range_end != 0);3886 const bit_range_end = ptr_info.ast.bit_range_end.unwrap().?;
3980 bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type);3887 bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_start, .type);
3981 bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end, .type);3888 bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_end, .type);
3982 trailing_count += 2;3889 trailing_count += 2;
3983 }3890 }
39843891
...@@ -4031,18 +3938,15 @@ fn ptrType(...@@ -4031,18 +3938,15 @@ fn ptrType(
4031fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {3938fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
4032 const astgen = gz.astgen;3939 const astgen = gz.astgen;
4033 const tree = astgen.tree;3940 const tree = astgen.tree;
4034 const node_datas = tree.nodes.items(.data);
4035 const node_tags = tree.nodes.items(.tag);
4036 const main_tokens = tree.nodes.items(.main_token);
40373941
4038 const len_node = node_datas[node].lhs;3942 const len_node, const elem_type_node = tree.nodeData(node).node_and_node;
4039 if (node_tags[len_node] == .identifier and3943 if (tree.nodeTag(len_node) == .identifier and
4040 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))3944 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
4041 {3945 {
4042 return astgen.failNode(len_node, "unable to infer array size", .{});3946 return astgen.failNode(len_node, "unable to infer array size", .{});
4043 }3947 }
4044 const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);3948 const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);
4045 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);3949 const elem_type = try typeExpr(gz, scope, elem_type_node);
40463950
4047 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{3951 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
4048 .lhs = len,3952 .lhs = len,
...@@ -4054,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !...@@ -4054,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
4054fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {3958fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref {
4055 const astgen = gz.astgen;3959 const astgen = gz.astgen;
4056 const tree = astgen.tree;3960 const tree = astgen.tree;
4057 const node_datas = tree.nodes.items(.data);3961
4058 const node_tags = tree.nodes.items(.tag);3962 const len_node, const extra_index = tree.nodeData(node).node_and_extra;
4059 const main_tokens = tree.nodes.items(.main_token);3963 const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
4060 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);3964
40613965 if (tree.nodeTag(len_node) == .identifier and
4062 const len_node = node_datas[node].lhs;3966 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
4063 if (node_tags[len_node] == .identifier and
4064 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
4065 {3967 {
4066 return astgen.failNode(len_node, "unable to infer array size", .{});3968 return astgen.failNode(len_node, "unable to infer array size", .{});
4067 }3969 }
...@@ -4161,11 +4063,10 @@ fn fnDecl(...@@ -4161,11 +4063,10 @@ fn fnDecl(
4161 scope: *Scope,4063 scope: *Scope,
4162 wip_members: *WipMembers,4064 wip_members: *WipMembers,
4163 decl_node: Ast.Node.Index,4065 decl_node: Ast.Node.Index,
4164 body_node: Ast.Node.Index,4066 body_node: Ast.Node.OptionalIndex,
4165 fn_proto: Ast.full.FnProto,4067 fn_proto: Ast.full.FnProto,
4166) InnerError!void {4068) InnerError!void {
4167 const tree = astgen.tree;4069 const tree = astgen.tree;
4168 const token_tags = tree.tokens.items(.tag);
41694070
4170 const old_hasher = astgen.src_hasher;4071 const old_hasher = astgen.src_hasher;
4171 defer astgen.src_hasher = old_hasher;4072 defer astgen.src_hasher = old_hasher;
...@@ -4194,15 +4095,15 @@ fn fnDecl(...@@ -4194,15 +4095,15 @@ fn fnDecl(
4194 const is_pub = fn_proto.visib_token != null;4095 const is_pub = fn_proto.visib_token != null;
4195 const is_export = blk: {4096 const is_export = blk: {
4196 const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;4097 const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false;
4197 break :blk token_tags[maybe_export_token] == .keyword_export;4098 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
4198 };4099 };
4199 const is_extern = blk: {4100 const is_extern = blk: {
4200 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;4101 const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false;
4201 break :blk token_tags[maybe_extern_token] == .keyword_extern;4102 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
4202 };4103 };
4203 const has_inline_keyword = blk: {4104 const has_inline_keyword = blk: {
4204 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;4105 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4205 break :blk token_tags[maybe_inline_token] == .keyword_inline;4106 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
4206 };4107 };
4207 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {4108 const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: {
4208 const lib_name_str = try astgen.strLitAsString(lib_name_token);4109 const lib_name_str = try astgen.strLitAsString(lib_name_token);
...@@ -4214,16 +4115,18 @@ fn fnDecl(...@@ -4214,16 +4115,18 @@ fn fnDecl(
4214 }4115 }
4215 break :blk lib_name_str.index;4116 break :blk lib_name_str.index;
4216 } else .empty;4117 } else .empty;
4217 if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) {4118 if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) {
4218 return astgen.failNode(4119 return astgen.failNode(
4219 fn_proto.ast.callconv_expr,4120 fn_proto.ast.callconv_expr.unwrap().?,
4220 "explicit callconv incompatible with inline keyword",4121 "explicit callconv incompatible with inline keyword",
4221 .{},4122 .{},
4222 );4123 );
4223 }4124 }
4224 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;4125
4225 const is_inferred_error = token_tags[maybe_bang] == .bang;4126 const return_type = fn_proto.ast.return_type.unwrap().?;
4226 if (body_node == 0) {4127 const maybe_bang = tree.firstToken(return_type) - 1;
4128 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
4129 if (body_node == .none) {
4227 if (!is_extern) {4130 if (!is_extern) {
4228 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});4131 return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{});
4229 }4132 }
...@@ -4256,28 +4159,28 @@ fn fnDecl(...@@ -4256,28 +4159,28 @@ fn fnDecl(
4256 var align_gz = type_gz.makeSubBlock(scope);4159 var align_gz = type_gz.makeSubBlock(scope);
4257 defer align_gz.unstack();4160 defer align_gz.unstack();
42584161
4259 if (fn_proto.ast.align_expr != 0) {4162 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
4260 astgen.restoreSourceCursor(saved_cursor);4163 astgen.restoreSourceCursor(saved_cursor);
4261 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr);4164 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr);
4262 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4165 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4263 }4166 }
42644167
4265 var linksection_gz = align_gz.makeSubBlock(scope);4168 var linksection_gz = align_gz.makeSubBlock(scope);
4266 defer linksection_gz.unstack();4169 defer linksection_gz.unstack();
42674170
4268 if (fn_proto.ast.section_expr != 0) {4171 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
4269 astgen.restoreSourceCursor(saved_cursor);4172 astgen.restoreSourceCursor(saved_cursor);
4270 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr);4173 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr);
4271 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4174 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4272 }4175 }
42734176
4274 var addrspace_gz = linksection_gz.makeSubBlock(scope);4177 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4275 defer addrspace_gz.unstack();4178 defer addrspace_gz.unstack();
42764179
4277 if (fn_proto.ast.addrspace_expr != 0) {4180 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
4278 astgen.restoreSourceCursor(saved_cursor);4181 astgen.restoreSourceCursor(saved_cursor);
4279 const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space);4182 const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_expr, .address_space);
4280 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr);4183 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr);
4281 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4184 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4282 }4185 }
42834186
...@@ -4287,7 +4190,7 @@ fn fnDecl(...@@ -4287,7 +4190,7 @@ fn fnDecl(
4287 if (!is_extern) {4190 if (!is_extern) {
4288 // We include a function *value*, not a type.4191 // We include a function *value*, not a type.
4289 astgen.restoreSourceCursor(saved_cursor);4192 astgen.restoreSourceCursor(saved_cursor);
4290 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto);4193 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto);
4291 }4194 }
42924195
4293 // *Now* we can incorporate the full source code into the hasher.4196 // *Now* we can incorporate the full source code into the hasher.
...@@ -4326,18 +4229,19 @@ fn fnDeclInner(...@@ -4326,18 +4229,19 @@ fn fnDeclInner(
4326 fn_proto: Ast.full.FnProto,4229 fn_proto: Ast.full.FnProto,
4327) InnerError!void {4230) InnerError!void {
4328 const tree = astgen.tree;4231 const tree = astgen.tree;
4329 const token_tags = tree.tokens.items(.tag);
43304232
4331 const is_noinline = blk: {4233 const is_noinline = blk: {
4332 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;4234 const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4333 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;4235 break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline;
4334 };4236 };
4335 const has_inline_keyword = blk: {4237 const has_inline_keyword = blk: {
4336 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;4238 const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false;
4337 break :blk token_tags[maybe_inline_token] == .keyword_inline;4239 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
4338 };4240 };
4339 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;4241
4340 const is_inferred_error = token_tags[maybe_bang] == .bang;4242 const return_type = fn_proto.ast.return_type.unwrap().?;
4243 const maybe_bang = tree.firstToken(return_type) - 1;
4244 const is_inferred_error = tree.tokenTag(maybe_bang) == .bang;
43414245
4342 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.4246 // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters.
4343 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);4247 var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len);
...@@ -4351,7 +4255,7 @@ fn fnDeclInner(...@@ -4351,7 +4255,7 @@ fn fnDeclInner(
4351 var param_type_i: usize = 0;4255 var param_type_i: usize = 0;
4352 var it = fn_proto.iterate(tree);4256 var it = fn_proto.iterate(tree);
4353 while (it.next()) |param| : (param_type_i += 1) {4257 while (it.next()) |param| : (param_type_i += 1) {
4354 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {4258 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
4355 .keyword_noalias => is_comptime: {4259 .keyword_noalias => is_comptime: {
4356 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse4260 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse
4357 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));4261 return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
...@@ -4362,7 +4266,7 @@ fn fnDeclInner(...@@ -4362,7 +4266,7 @@ fn fnDeclInner(
4362 } else false;4266 } else false;
43634267
4364 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {4268 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
4365 switch (token_tags[token]) {4269 switch (tree.tokenTag(token)) {
4366 .keyword_anytype => break :blk true,4270 .keyword_anytype => break :blk true,
4367 .ellipsis3 => break :is_var_args true,4271 .ellipsis3 => break :is_var_args true,
4368 else => unreachable,4272 else => unreachable,
...@@ -4381,30 +4285,31 @@ fn fnDeclInner(...@@ -4381,30 +4285,31 @@ fn fnDeclInner(
4381 if (param.anytype_ellipsis3) |tok| {4285 if (param.anytype_ellipsis3) |tok| {
4382 return astgen.failTok(tok, "missing parameter name", .{});4286 return astgen.failTok(tok, "missing parameter name", .{});
4383 } else {4287 } else {
4288 const type_expr = param.type_expr.?;
4384 ambiguous: {4289 ambiguous: {
4385 if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous;4290 if (tree.nodeTag(type_expr) != .identifier) break :ambiguous;
4386 const main_token = tree.nodes.items(.main_token)[param.type_expr];4291 const main_token = tree.nodeMainToken(type_expr);
4387 const identifier_str = tree.tokenSlice(main_token);4292 const identifier_str = tree.tokenSlice(main_token);
4388 if (isPrimitive(identifier_str)) break :ambiguous;4293 if (isPrimitive(identifier_str)) break :ambiguous;
4389 return astgen.failNodeNotes(4294 return astgen.failNodeNotes(
4390 param.type_expr,4295 type_expr,
4391 "missing parameter name or type",4296 "missing parameter name or type",
4392 .{},4297 .{},
4393 &[_]u32{4298 &[_]u32{
4394 try astgen.errNoteNode(4299 try astgen.errNoteNode(
4395 param.type_expr,4300 type_expr,
4396 "if this is a name, annotate its type '{s}: T'",4301 "if this is a name, annotate its type '{s}: T'",
4397 .{identifier_str},4302 .{identifier_str},
4398 ),4303 ),
4399 try astgen.errNoteNode(4304 try astgen.errNoteNode(
4400 param.type_expr,4305 type_expr,
4401 "if this is a type, give it a name '<name>: {s}'",4306 "if this is a type, give it a name '<name>: {s}'",
4402 .{identifier_str},4307 .{identifier_str},
4403 ),4308 ),
4404 },4309 },
4405 );4310 );
4406 }4311 }
4407 return astgen.failNode(param.type_expr, "missing parameter name", .{});4312 return astgen.failNode(type_expr, "missing parameter name", .{});
4408 }4313 }
4409 };4314 };
44104315
...@@ -4416,8 +4321,7 @@ fn fnDeclInner(...@@ -4416,8 +4321,7 @@ fn fnDeclInner(
4416 .param_anytype;4321 .param_anytype;
4417 break :param try decl_gz.addStrTok(tag, param_name, name_token);4322 break :param try decl_gz.addStrTok(tag, param_name, name_token);
4418 } else param: {4323 } else param: {
4419 const param_type_node = param.type_expr;4324 const param_type_node = param.type_expr.?;
4420 assert(param_type_node != 0);
4421 any_param_used = false; // we will check this later4325 any_param_used = false; // we will check this later
4422 var param_gz = decl_gz.makeSubBlock(scope);4326 var param_gz = decl_gz.makeSubBlock(scope);
4423 defer param_gz.unstack();4327 defer param_gz.unstack();
...@@ -4426,8 +4330,7 @@ fn fnDeclInner(...@@ -4426,8 +4330,7 @@ fn fnDeclInner(
4426 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);4330 _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node);
4427 const param_type_is_generic = any_param_used;4331 const param_type_is_generic = any_param_used;
44284332
4429 const main_tokens = tree.nodes.items(.main_token);4333 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
4430 const name_token = param.name_token orelse main_tokens[param_type_node];
4431 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;4334 const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param;
4432 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name);4335 const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name);
4433 assert(param_inst_expected == param_inst);4336 assert(param_inst_expected == param_inst);
...@@ -4463,7 +4366,7 @@ fn fnDeclInner(...@@ -4463,7 +4366,7 @@ fn fnDeclInner(
4463 // Parameters are in scope for the return type, so we use `params_scope` here.4366 // Parameters are in scope for the return type, so we use `params_scope` here.
4464 // The calling convention will not have parameters in scope, so we'll just use `scope`.4367 // The calling convention will not have parameters in scope, so we'll just use `scope`.
4465 // See #22263 for a proposal to solve the inconsistency here.4368 // See #22263 for a proposal to solve the inconsistency here.
4466 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal);4369 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal);
4467 if (ret_gz.instructionsSlice().len == 0) {4370 if (ret_gz.instructionsSlice().len == 0) {
4468 // In this case we will send a len=0 body which can be encoded more efficiently.4371 // In this case we will send a len=0 body which can be encoded more efficiently.
4469 break :inst inst;4372 break :inst inst;
...@@ -4480,12 +4383,12 @@ fn fnDeclInner(...@@ -4480,12 +4383,12 @@ fn fnDeclInner(
4480 var cc_gz = decl_gz.makeSubBlock(scope);4383 var cc_gz = decl_gz.makeSubBlock(scope);
4481 defer cc_gz.unstack();4384 defer cc_gz.unstack();
4482 const cc_ref: Zir.Inst.Ref = blk: {4385 const cc_ref: Zir.Inst.Ref = blk: {
4483 if (fn_proto.ast.callconv_expr != 0) {4386 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
4484 const inst = try expr(4387 const inst = try expr(
4485 &cc_gz,4388 &cc_gz,
4486 scope,4389 scope,
4487 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } },4390 .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(callconv_expr, .calling_convention) } },
4488 fn_proto.ast.callconv_expr,4391 callconv_expr,
4489 );4392 );
4490 if (cc_gz.instructionsSlice().len == 0) {4393 if (cc_gz.instructionsSlice().len == 0) {
4491 // In this case we will send a len=0 body which can be encoded more efficiently.4394 // In this case we will send a len=0 body which can be encoded more efficiently.
...@@ -4524,7 +4427,7 @@ fn fnDeclInner(...@@ -4524,7 +4427,7 @@ fn fnDeclInner(
4524 // Leave `astgen.src_hasher` unmodified; this will be used for hashing4427 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
4525 // the *whole* function declaration, including its body.4428 // the *whole* function declaration, including its body.
4526 var proto_hasher = astgen.src_hasher;4429 var proto_hasher = astgen.src_hasher;
4527 const proto_node = tree.nodes.items(.data)[decl_node].lhs;4430 const proto_node = tree.nodeData(decl_node).node_and_node[0];
4528 proto_hasher.update(tree.getNodeSource(proto_node));4431 proto_hasher.update(tree.getNodeSource(proto_node));
4529 var proto_hash: std.zig.SrcHash = undefined;4432 var proto_hash: std.zig.SrcHash = undefined;
4530 proto_hasher.final(&proto_hash);4433 proto_hasher.final(&proto_hash);
...@@ -4594,7 +4497,6 @@ fn globalVarDecl(...@@ -4594,7 +4497,6 @@ fn globalVarDecl(
4594 var_decl: Ast.full.VarDecl,4497 var_decl: Ast.full.VarDecl,
4595) InnerError!void {4498) InnerError!void {
4596 const tree = astgen.tree;4499 const tree = astgen.tree;
4597 const token_tags = tree.tokens.items(.tag);
45984500
4599 const old_hasher = astgen.src_hasher;4501 const old_hasher = astgen.src_hasher;
4600 defer astgen.src_hasher = old_hasher;4502 defer astgen.src_hasher = old_hasher;
...@@ -4602,16 +4504,16 @@ fn globalVarDecl(...@@ -4602,16 +4504,16 @@ fn globalVarDecl(
4602 astgen.src_hasher.update(tree.getNodeSource(node));4504 astgen.src_hasher.update(tree.getNodeSource(node));
4603 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));4505 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
46044506
4605 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;4507 const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var;
4606 const name_token = var_decl.ast.mut_token + 1;4508 const name_token = var_decl.ast.mut_token + 1;
4607 const is_pub = var_decl.visib_token != null;4509 const is_pub = var_decl.visib_token != null;
4608 const is_export = blk: {4510 const is_export = blk: {
4609 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;4511 const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
4610 break :blk token_tags[maybe_export_token] == .keyword_export;4512 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
4611 };4513 };
4612 const is_extern = blk: {4514 const is_extern = blk: {
4613 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;4515 const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
4614 break :blk token_tags[maybe_extern_token] == .keyword_extern;4516 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
4615 };4517 };
4616 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {4518 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
4617 if (!is_mutable) {4519 if (!is_mutable) {
...@@ -4637,10 +4539,10 @@ fn globalVarDecl(...@@ -4637,10 +4539,10 @@ fn globalVarDecl(
4637 const decl_inst = try gz.makeDeclaration(node);4539 const decl_inst = try gz.makeDeclaration(node);
4638 wip_members.nextDecl(decl_inst);4540 wip_members.nextDecl(decl_inst);
46394541
4640 if (var_decl.ast.init_node != 0) {4542 if (var_decl.ast.init_node.unwrap()) |init_node| {
4641 if (is_extern) {4543 if (is_extern) {
4642 return astgen.failNode(4544 return astgen.failNode(
4643 var_decl.ast.init_node,4545 init_node,
4644 "extern variables have no initializers",4546 "extern variables have no initializers",
4645 .{},4547 .{},
4646 );4548 );
...@@ -4651,7 +4553,7 @@ fn globalVarDecl(...@@ -4651,7 +4553,7 @@ fn globalVarDecl(
4651 }4553 }
4652 }4554 }
46534555
4654 if (is_extern and var_decl.ast.type_node == 0) {4556 if (is_extern and var_decl.ast.type_node == .none) {
4655 return astgen.failNode(node, "unable to infer variable type", .{});4557 return astgen.failNode(node, "unable to infer variable type", .{});
4656 }4558 }
46574559
...@@ -4668,45 +4570,45 @@ fn globalVarDecl(...@@ -4668,45 +4570,45 @@ fn globalVarDecl(
4668 };4570 };
4669 defer type_gz.unstack();4571 defer type_gz.unstack();
46704572
4671 if (var_decl.ast.type_node != 0) {4573 if (var_decl.ast.type_node.unwrap()) |type_node| {
4672 const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, var_decl.ast.type_node);4574 const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, type_node);
4673 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);4575 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
4674 }4576 }
46754577
4676 var align_gz = type_gz.makeSubBlock(scope);4578 var align_gz = type_gz.makeSubBlock(scope);
4677 defer align_gz.unstack();4579 defer align_gz.unstack();
46784580
4679 if (var_decl.ast.align_node != 0) {4581 if (var_decl.ast.align_node.unwrap()) |align_node| {
4680 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node);4582 const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_node);
4681 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);4583 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4682 }4584 }
46834585
4684 var linksection_gz = type_gz.makeSubBlock(scope);4586 var linksection_gz = type_gz.makeSubBlock(scope);
4685 defer linksection_gz.unstack();4587 defer linksection_gz.unstack();
46864588
4687 if (var_decl.ast.section_node != 0) {4589 if (var_decl.ast.section_node.unwrap()) |section_node| {
4688 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node);4590 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node);
4689 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);4591 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4690 }4592 }
46914593
4692 var addrspace_gz = type_gz.makeSubBlock(scope);4594 var addrspace_gz = type_gz.makeSubBlock(scope);
4693 defer addrspace_gz.unstack();4595 defer addrspace_gz.unstack();
46944596
4695 if (var_decl.ast.addrspace_node != 0) {4597 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
4696 const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space);4598 const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_node, .address_space);
4697 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node);4599 const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node);
4698 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);4600 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4699 }4601 }
47004602
4701 var init_gz = type_gz.makeSubBlock(scope);4603 var init_gz = type_gz.makeSubBlock(scope);
4702 defer init_gz.unstack();4604 defer init_gz.unstack();
47034605
4704 if (var_decl.ast.init_node != 0) {4606 if (var_decl.ast.init_node.unwrap()) |init_node| {
4705 init_gz.anon_name_strategy = .parent;4607 init_gz.anon_name_strategy = .parent;
4706 const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{4608 const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{
4707 .rl = .{ .coerced_ty = decl_inst.toRef() },4609 .rl = .{ .coerced_ty = decl_inst.toRef() },
4708 } else .{ .rl = .none };4610 } else .{ .rl = .none };
4709 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node);4611 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, init_node);
4710 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);4612 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
4711 }4613 }
47124614
...@@ -4740,8 +4642,7 @@ fn comptimeDecl(...@@ -4740,8 +4642,7 @@ fn comptimeDecl(
4740 node: Ast.Node.Index,4642 node: Ast.Node.Index,
4741) InnerError!void {4643) InnerError!void {
4742 const tree = astgen.tree;4644 const tree = astgen.tree;
4743 const node_datas = tree.nodes.items(.data);4645 const body_node = tree.nodeData(node).node;
4744 const body_node = node_datas[node].lhs;
47454646
4746 const old_hasher = astgen.src_hasher;4647 const old_hasher = astgen.src_hasher;
4747 defer astgen.src_hasher = old_hasher;4648 defer astgen.src_hasher = old_hasher;
...@@ -4804,7 +4705,6 @@ fn usingnamespaceDecl(...@@ -4804,7 +4705,6 @@ fn usingnamespaceDecl(
4804 node: Ast.Node.Index,4705 node: Ast.Node.Index,
4805) InnerError!void {4706) InnerError!void {
4806 const tree = astgen.tree;4707 const tree = astgen.tree;
4807 const node_datas = tree.nodes.items(.data);
48084708
4809 const old_hasher = astgen.src_hasher;4709 const old_hasher = astgen.src_hasher;
4810 defer astgen.src_hasher = old_hasher;4710 defer astgen.src_hasher = old_hasher;
...@@ -4812,13 +4712,9 @@ fn usingnamespaceDecl(...@@ -4812,13 +4712,9 @@ fn usingnamespaceDecl(
4812 astgen.src_hasher.update(tree.getNodeSource(node));4712 astgen.src_hasher.update(tree.getNodeSource(node));
4813 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));4713 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
48144714
4815 const type_expr = node_datas[node].lhs;4715 const type_expr = tree.nodeData(node).node;
4816 const is_pub = blk: {4716 const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub});
4817 const main_tokens = tree.nodes.items(.main_token);4717
4818 const token_tags = tree.tokens.items(.tag);
4819 const main_token = main_tokens[node];
4820 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
4821 };
4822 // Up top so the ZIR instruction index marks the start range of this4718 // Up top so the ZIR instruction index marks the start range of this
4823 // top-level declaration.4719 // top-level declaration.
4824 const decl_inst = try gz.makeDeclaration(node);4720 const decl_inst = try gz.makeDeclaration(node);
...@@ -4872,8 +4768,7 @@ fn testDecl(...@@ -4872,8 +4768,7 @@ fn testDecl(
4872 node: Ast.Node.Index,4768 node: Ast.Node.Index,
4873) InnerError!void {4769) InnerError!void {
4874 const tree = astgen.tree;4770 const tree = astgen.tree;
4875 const node_datas = tree.nodes.items(.data);4771 _, const body_node = tree.nodeData(node).opt_token_and_node;
4876 const body_node = node_datas[node].rhs;
48774772
4878 const old_hasher = astgen.src_hasher;4773 const old_hasher = astgen.src_hasher;
4879 defer astgen.src_hasher = old_hasher;4774 defer astgen.src_hasher = old_hasher;
...@@ -4905,12 +4800,10 @@ fn testDecl(...@@ -4905,12 +4800,10 @@ fn testDecl(
49054800
4906 const decl_column = astgen.source_column;4801 const decl_column = astgen.source_column;
49074802
4908 const main_tokens = tree.nodes.items(.main_token);4803 const test_token = tree.nodeMainToken(node);
4909 const token_tags = tree.tokens.items(.tag);
4910 const test_token = main_tokens[node];
49114804
4912 const test_name_token = test_token + 1;4805 const test_name_token = test_token + 1;
4913 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {4806 const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) {
4914 else => .empty,4807 else => .empty,
4915 .string_literal => name: {4808 .string_literal => name: {
4916 const name = try astgen.strLitAsString(test_name_token);4809 const name = try astgen.strLitAsString(test_name_token);
...@@ -4942,7 +4835,7 @@ fn testDecl(...@@ -4942,7 +4835,7 @@ fn testDecl(
4942 .local_val => {4835 .local_val => {
4943 const local_val = s.cast(Scope.LocalVal).?;4836 const local_val = s.cast(Scope.LocalVal).?;
4944 if (local_val.name == name_str_index) {4837 if (local_val.name == name_str_index) {
4945 local_val.used = test_name_token;4838 local_val.used = .fromToken(test_name_token);
4946 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{4839 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
4947 @tagName(local_val.id_cat),4840 @tagName(local_val.id_cat),
4948 }, &[_]u32{4841 }, &[_]u32{
...@@ -4956,7 +4849,7 @@ fn testDecl(...@@ -4956,7 +4849,7 @@ fn testDecl(
4956 .local_ptr => {4849 .local_ptr => {
4957 const local_ptr = s.cast(Scope.LocalPtr).?;4850 const local_ptr = s.cast(Scope.LocalPtr).?;
4958 if (local_ptr.name == name_str_index) {4851 if (local_ptr.name == name_str_index) {
4959 local_ptr.used = test_name_token;4852 local_ptr.used = .fromToken(test_name_token);
4960 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{4853 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
4961 @tagName(local_ptr.id_cat),4854 @tagName(local_ptr.id_cat),
4962 }, &[_]u32{4855 }, &[_]u32{
...@@ -5067,7 +4960,7 @@ fn testDecl(...@@ -5067,7 +4960,7 @@ fn testDecl(
5067 .src_line = decl_block.decl_line,4960 .src_line = decl_block.decl_line,
5068 .src_column = decl_column,4961 .src_column = decl_column,
50694962
5070 .kind = switch (token_tags[test_name_token]) {4963 .kind = switch (tree.tokenTag(test_name_token)) {
5071 .string_literal => .@"test",4964 .string_literal => .@"test",
5072 .identifier => .decltest,4965 .identifier => .decltest,
5073 else => .unnamed_test,4966 else => .unnamed_test,
...@@ -5091,7 +4984,7 @@ fn structDeclInner(...@@ -5091,7 +4984,7 @@ fn structDeclInner(
5091 node: Ast.Node.Index,4984 node: Ast.Node.Index,
5092 container_decl: Ast.full.ContainerDecl,4985 container_decl: Ast.full.ContainerDecl,
5093 layout: std.builtin.Type.ContainerLayout,4986 layout: std.builtin.Type.ContainerLayout,
5094 backing_int_node: Ast.Node.Index,4987 backing_int_node: Ast.Node.OptionalIndex,
5095) InnerError!Zir.Inst.Ref {4988) InnerError!Zir.Inst.Ref {
5096 const astgen = gz.astgen;4989 const astgen = gz.astgen;
5097 const gpa = astgen.gpa;4990 const gpa = astgen.gpa;
...@@ -5103,7 +4996,7 @@ fn structDeclInner(...@@ -5103,7 +4996,7 @@ fn structDeclInner(
5103 if (container_field.ast.tuple_like) break member_node;4996 if (container_field.ast.tuple_like) break member_node;
5104 } else break :is_tuple;4997 } else break :is_tuple;
51054998
5106 if (node == 0) {4999 if (node == .root) {
5107 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});5000 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});
5108 } else {5001 } else {
5109 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);5002 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
...@@ -5112,7 +5005,7 @@ fn structDeclInner(...@@ -5112,7 +5005,7 @@ fn structDeclInner(
51125005
5113 const decl_inst = try gz.reserveInstructionIndex();5006 const decl_inst = try gz.reserveInstructionIndex();
51145007
5115 if (container_decl.ast.members.len == 0 and backing_int_node == 0) {5008 if (container_decl.ast.members.len == 0 and backing_int_node == .none) {
5116 try gz.setStruct(decl_inst, .{5009 try gz.setStruct(decl_inst, .{
5117 .src_node = node,5010 .src_node = node,
5118 .layout = layout,5011 .layout = layout,
...@@ -5159,11 +5052,11 @@ fn structDeclInner(...@@ -5159,11 +5052,11 @@ fn structDeclInner(
51595052
5160 var backing_int_body_len: usize = 0;5053 var backing_int_body_len: usize = 0;
5161 const backing_int_ref: Zir.Inst.Ref = blk: {5054 const backing_int_ref: Zir.Inst.Ref = blk: {
5162 if (backing_int_node != 0) {5055 if (backing_int_node.unwrap()) |arg| {
5163 if (layout != .@"packed") {5056 if (layout != .@"packed") {
5164 return astgen.failNode(backing_int_node, "non-packed struct does not support backing integer type", .{});5057 return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{});
5165 } else {5058 } else {
5166 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node);5059 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg);
5167 if (!block_scope.isEmpty()) {5060 if (!block_scope.isEmpty()) {
5168 if (!block_scope.endsWithNoReturn()) {5061 if (!block_scope.endsWithNoReturn()) {
5169 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);5062 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);
...@@ -5208,8 +5101,8 @@ fn structDeclInner(...@@ -5208,8 +5101,8 @@ fn structDeclInner(
5208 defer astgen.src_hasher = old_hasher;5101 defer astgen.src_hasher = old_hasher;
5209 astgen.src_hasher = std.zig.SrcHasher.init(.{});5102 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5210 astgen.src_hasher.update(@tagName(layout));5103 astgen.src_hasher.update(@tagName(layout));
5211 if (backing_int_node != 0) {5104 if (backing_int_node.unwrap()) |arg| {
5212 astgen.src_hasher.update(tree.getNodeSource(backing_int_node));5105 astgen.src_hasher.update(tree.getNodeSource(arg));
5213 }5106 }
52145107
5215 var known_non_opv = false;5108 var known_non_opv = false;
...@@ -5226,18 +5119,18 @@ fn structDeclInner(...@@ -5226,18 +5119,18 @@ fn structDeclInner(
5226 astgen.src_hasher.update(tree.getNodeSource(member_node));5119 astgen.src_hasher.update(tree.getNodeSource(member_node));
52275120
5228 const field_name = try astgen.identAsString(member.ast.main_token);5121 const field_name = try astgen.identAsString(member.ast.main_token);
5229 member.convertToNonTupleLike(astgen.tree.nodes);5122 member.convertToNonTupleLike(astgen.tree);
5230 assert(!member.ast.tuple_like);5123 assert(!member.ast.tuple_like);
5231 wip_members.appendToField(@intFromEnum(field_name));5124 wip_members.appendToField(@intFromEnum(field_name));
52325125
5233 if (member.ast.type_expr == 0) {5126 const type_expr = member.ast.type_expr.unwrap() orelse {
5234 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});5127 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5235 }5128 };
52365129
5237 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);5130 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
5238 const have_type_body = !block_scope.isEmpty();5131 const have_type_body = !block_scope.isEmpty();
5239 const have_align = member.ast.align_expr != 0;5132 const have_align = member.ast.align_expr != .none;
5240 const have_value = member.ast.value_expr != 0;5133 const have_value = member.ast.value_expr != .none;
5241 const is_comptime = member.comptime_token != null;5134 const is_comptime = member.comptime_token != null;
52425135
5243 if (is_comptime) {5136 if (is_comptime) {
...@@ -5247,9 +5140,9 @@ fn structDeclInner(...@@ -5247,9 +5140,9 @@ fn structDeclInner(
5247 }5140 }
5248 } else {5141 } else {
5249 known_non_opv = known_non_opv or5142 known_non_opv = known_non_opv or
5250 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);5143 nodeImpliesMoreThanOnePossibleValue(tree, type_expr);
5251 known_comptime_only = known_comptime_only or5144 known_comptime_only = known_comptime_only or
5252 nodeImpliesComptimeOnly(tree, member.ast.type_expr);5145 nodeImpliesComptimeOnly(tree, type_expr);
5253 }5146 }
5254 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body });5147 wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body });
52555148
...@@ -5267,12 +5160,12 @@ fn structDeclInner(...@@ -5267,12 +5160,12 @@ fn structDeclInner(
5267 wip_members.appendToField(@intFromEnum(field_type));5160 wip_members.appendToField(@intFromEnum(field_type));
5268 }5161 }
52695162
5270 if (have_align) {5163 if (member.ast.align_expr.unwrap()) |align_expr| {
5271 if (layout == .@"packed") {5164 if (layout == .@"packed") {
5272 return astgen.failNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});5165 return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{});
5273 }5166 }
5274 any_aligned_fields = true;5167 any_aligned_fields = true;
5275 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr);5168 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr);
5276 if (!block_scope.endsWithNoReturn()) {5169 if (!block_scope.endsWithNoReturn()) {
5277 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);5170 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
5278 }5171 }
...@@ -5284,14 +5177,14 @@ fn structDeclInner(...@@ -5284,14 +5177,14 @@ fn structDeclInner(
5284 block_scope.instructions.items.len = block_scope.instructions_top;5177 block_scope.instructions.items.len = block_scope.instructions_top;
5285 }5178 }
52865179
5287 if (have_value) {5180 if (member.ast.value_expr.unwrap()) |value_expr| {
5288 any_default_inits = true;5181 any_default_inits = true;
52895182
5290 // The decl_inst is used as here so that we can easily reconstruct a mapping5183 // The decl_inst is used as here so that we can easily reconstruct a mapping
5291 // between it and the field type when the fields inits are analyzed.5184 // between it and the field type when the fields inits are analyzed.
5292 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } };5185 const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } };
52935186
5294 const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr);5187 const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr);
5295 if (!block_scope.endsWithNoReturn()) {5188 if (!block_scope.endsWithNoReturn()) {
5296 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);5189 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
5297 }5190 }
...@@ -5354,21 +5247,19 @@ fn tupleDecl(...@@ -5354,21 +5247,19 @@ fn tupleDecl(
5354 node: Ast.Node.Index,5247 node: Ast.Node.Index,
5355 container_decl: Ast.full.ContainerDecl,5248 container_decl: Ast.full.ContainerDecl,
5356 layout: std.builtin.Type.ContainerLayout,5249 layout: std.builtin.Type.ContainerLayout,
5357 backing_int_node: Ast.Node.Index,5250 backing_int_node: Ast.Node.OptionalIndex,
5358) InnerError!Zir.Inst.Ref {5251) InnerError!Zir.Inst.Ref {
5359 const astgen = gz.astgen;5252 const astgen = gz.astgen;
5360 const gpa = astgen.gpa;5253 const gpa = astgen.gpa;
5361 const tree = astgen.tree;5254 const tree = astgen.tree;
53625255
5363 const node_tags = tree.nodes.items(.tag);
5364
5365 switch (layout) {5256 switch (layout) {
5366 .auto => {},5257 .auto => {},
5367 .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}),5258 .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}),
5368 }5259 }
53695260
5370 if (backing_int_node != 0) {5261 if (backing_int_node.unwrap()) |arg| {
5371 return astgen.failNode(backing_int_node, "tuple does not support backing integer type", .{});5262 return astgen.failNode(arg, "tuple does not support backing integer type", .{});
5372 }5263 }
53735264
5374 // We will use the scratch buffer, starting here, for the field data:5265 // We will use the scratch buffer, starting here, for the field data:
...@@ -5383,7 +5274,7 @@ fn tupleDecl(...@@ -5383,7 +5274,7 @@ fn tupleDecl(
53835274
5384 for (container_decl.ast.members) |member_node| {5275 for (container_decl.ast.members) |member_node| {
5385 const field = tree.fullContainerField(member_node) orelse {5276 const field = tree.fullContainerField(member_node) orelse {
5386 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {5277 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) {
5387 .container_field_init,5278 .container_field_init,
5388 .container_field_align,5279 .container_field_align,
5389 .container_field,5280 .container_field,
...@@ -5402,23 +5293,23 @@ fn tupleDecl(...@@ -5402,23 +5293,23 @@ fn tupleDecl(
5402 return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});5293 return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});
5403 }5294 }
54045295
5405 if (field.ast.align_expr != 0) {5296 if (field.ast.align_expr != .none) {
5406 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});5297 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
5407 }5298 }
54085299
5409 if (field.ast.value_expr != 0 and field.comptime_token == null) {5300 if (field.ast.value_expr != .none and field.comptime_token == null) {
5410 return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});5301 return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});
5411 }5302 }
54125303
5413 if (field.ast.value_expr == 0 and field.comptime_token != null) {5304 if (field.ast.value_expr == .none and field.comptime_token != null) {
5414 return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});5305 return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});
5415 }5306 }
54165307
5417 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr);5308 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?);
5418 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));5309 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
54195310
5420 if (field.ast.value_expr != 0) {5311 if (field.ast.value_expr.unwrap()) |value_expr| {
5421 const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value);5312 const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, value_expr, .tuple_field_default_value);
5422 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));5313 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
5423 } else {5314 } else {
5424 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));5315 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
...@@ -5453,7 +5344,7 @@ fn unionDeclInner(...@@ -5453,7 +5344,7 @@ fn unionDeclInner(
5453 node: Ast.Node.Index,5344 node: Ast.Node.Index,
5454 members: []const Ast.Node.Index,5345 members: []const Ast.Node.Index,
5455 layout: std.builtin.Type.ContainerLayout,5346 layout: std.builtin.Type.ContainerLayout,
5456 arg_node: Ast.Node.Index,5347 opt_arg_node: Ast.Node.OptionalIndex,
5457 auto_enum_tok: ?Ast.TokenIndex,5348 auto_enum_tok: ?Ast.TokenIndex,
5458) InnerError!Zir.Inst.Ref {5349) InnerError!Zir.Inst.Ref {
5459 const decl_inst = try gz.reserveInstructionIndex();5350 const decl_inst = try gz.reserveInstructionIndex();
...@@ -5488,15 +5379,15 @@ fn unionDeclInner(...@@ -5488,15 +5379,15 @@ fn unionDeclInner(
5488 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");5379 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");
5489 const field_count: u32 = @intCast(members.len - decl_count);5380 const field_count: u32 = @intCast(members.len - decl_count);
54905381
5491 if (layout != .auto and (auto_enum_tok != null or arg_node != 0)) {5382 if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) {
5492 if (arg_node != 0) {5383 if (opt_arg_node.unwrap()) |arg_node| {
5493 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});5384 return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)});
5494 } else {5385 } else {
5495 return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)});5386 return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)});
5496 }5387 }
5497 }5388 }
54985389
5499 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)5390 const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node|
5500 try typeExpr(&block_scope, &namespace.base, arg_node)5391 try typeExpr(&block_scope, &namespace.base, arg_node)
5501 else5392 else
5502 .none;5393 .none;
...@@ -5512,7 +5403,7 @@ fn unionDeclInner(...@@ -5512,7 +5403,7 @@ fn unionDeclInner(
5512 astgen.src_hasher = std.zig.SrcHasher.init(.{});5403 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5513 astgen.src_hasher.update(@tagName(layout));5404 astgen.src_hasher.update(@tagName(layout));
5514 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});5405 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});
5515 if (arg_node != 0) {5406 if (opt_arg_node.unwrap()) |arg_node| {
5516 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));5407 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
5517 }5408 }
55185409
...@@ -5522,7 +5413,7 @@ fn unionDeclInner(...@@ -5522,7 +5413,7 @@ fn unionDeclInner(
5522 .field => |field| field,5413 .field => |field| field,
5523 };5414 };
5524 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));5415 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));
5525 member.convertToNonTupleLike(astgen.tree.nodes);5416 member.convertToNonTupleLike(astgen.tree);
5526 if (member.ast.tuple_like) {5417 if (member.ast.tuple_like) {
5527 return astgen.failTok(member.ast.main_token, "union field missing name", .{});5418 return astgen.failTok(member.ast.main_token, "union field missing name", .{});
5528 }5419 }
...@@ -5533,24 +5424,24 @@ fn unionDeclInner(...@@ -5533,24 +5424,24 @@ fn unionDeclInner(
5533 const field_name = try astgen.identAsString(member.ast.main_token);5424 const field_name = try astgen.identAsString(member.ast.main_token);
5534 wip_members.appendToField(@intFromEnum(field_name));5425 wip_members.appendToField(@intFromEnum(field_name));
55355426
5536 const have_type = member.ast.type_expr != 0;5427 const have_type = member.ast.type_expr != .none;
5537 const have_align = member.ast.align_expr != 0;5428 const have_align = member.ast.align_expr != .none;
5538 const have_value = member.ast.value_expr != 0;5429 const have_value = member.ast.value_expr != .none;
5539 const unused = false;5430 const unused = false;
5540 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });5431 wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused });
55415432
5542 if (have_type) {5433 if (member.ast.type_expr.unwrap()) |type_expr| {
5543 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);5434 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
5544 wip_members.appendToField(@intFromEnum(field_type));5435 wip_members.appendToField(@intFromEnum(field_type));
5545 } else if (arg_inst == .none and auto_enum_tok == null) {5436 } else if (arg_inst == .none and auto_enum_tok == null) {
5546 return astgen.failNode(member_node, "union field missing type", .{});5437 return astgen.failNode(member_node, "union field missing type", .{});
5547 }5438 }
5548 if (have_align) {5439 if (member.ast.align_expr.unwrap()) |align_expr| {
5549 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, member.ast.align_expr);5440 const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr);
5550 wip_members.appendToField(@intFromEnum(align_inst));5441 wip_members.appendToField(@intFromEnum(align_inst));
5551 any_aligned_fields = true;5442 any_aligned_fields = true;
5552 }5443 }
5553 if (have_value) {5444 if (member.ast.value_expr.unwrap()) |value_expr| {
5554 if (arg_inst == .none) {5445 if (arg_inst == .none) {
5555 return astgen.failNodeNotes(5446 return astgen.failNodeNotes(
5556 node,5447 node,
...@@ -5558,7 +5449,7 @@ fn unionDeclInner(...@@ -5558,7 +5449,7 @@ fn unionDeclInner(
5558 .{},5449 .{},
5559 &[_]u32{5450 &[_]u32{
5560 try astgen.errNoteNode(5451 try astgen.errNoteNode(
5561 member.ast.value_expr,5452 value_expr,
5562 "tag value specified here",5453 "tag value specified here",
5563 .{},5454 .{},
5564 ),5455 ),
...@@ -5572,14 +5463,14 @@ fn unionDeclInner(...@@ -5572,14 +5463,14 @@ fn unionDeclInner(
5572 .{},5463 .{},
5573 &[_]u32{5464 &[_]u32{
5574 try astgen.errNoteNode(5465 try astgen.errNoteNode(
5575 member.ast.value_expr,5466 value_expr,
5576 "tag value specified here",5467 "tag value specified here",
5577 .{},5468 .{},
5578 ),5469 ),
5579 },5470 },
5580 );5471 );
5581 }5472 }
5582 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5473 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5583 wip_members.appendToField(@intFromEnum(tag_value));5474 wip_members.appendToField(@intFromEnum(tag_value));
5584 }5475 }
5585 }5476 }
...@@ -5631,7 +5522,6 @@ fn containerDecl(...@@ -5631,7 +5522,6 @@ fn containerDecl(
5631 const astgen = gz.astgen;5522 const astgen = gz.astgen;
5632 const gpa = astgen.gpa;5523 const gpa = astgen.gpa;
5633 const tree = astgen.tree;5524 const tree = astgen.tree;
5634 const token_tags = tree.tokens.items(.tag);
56355525
5636 const prev_fn_block = astgen.fn_block;5526 const prev_fn_block = astgen.fn_block;
5637 astgen.fn_block = null;5527 astgen.fn_block = null;
...@@ -5640,9 +5530,9 @@ fn containerDecl(...@@ -5640,9 +5530,9 @@ fn containerDecl(
5640 // We must not create any types until Sema. Here the goal is only to generate5530 // We must not create any types until Sema. Here the goal is only to generate
5641 // ZIR for all the field types, alignments, and default value expressions.5531 // ZIR for all the field types, alignments, and default value expressions.
56425532
5643 switch (token_tags[container_decl.ast.main_token]) {5533 switch (tree.tokenTag(container_decl.ast.main_token)) {
5644 .keyword_struct => {5534 .keyword_struct => {
5645 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {5535 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
5646 .keyword_packed => .@"packed",5536 .keyword_packed => .@"packed",
5647 .keyword_extern => .@"extern",5537 .keyword_extern => .@"extern",
5648 else => unreachable,5538 else => unreachable,
...@@ -5652,7 +5542,7 @@ fn containerDecl(...@@ -5652,7 +5542,7 @@ fn containerDecl(
5652 return rvalue(gz, ri, result, node);5542 return rvalue(gz, ri, result, node);
5653 },5543 },
5654 .keyword_union => {5544 .keyword_union => {
5655 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {5545 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
5656 .keyword_packed => .@"packed",5546 .keyword_packed => .@"packed",
5657 .keyword_extern => .@"extern",5547 .keyword_extern => .@"extern",
5658 else => unreachable,5548 else => unreachable,
...@@ -5670,23 +5560,23 @@ fn containerDecl(...@@ -5670,23 +5560,23 @@ fn containerDecl(
5670 var values: usize = 0;5560 var values: usize = 0;
5671 var total_fields: usize = 0;5561 var total_fields: usize = 0;
5672 var decls: usize = 0;5562 var decls: usize = 0;
5673 var nonexhaustive_node: Ast.Node.Index = 0;5563 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
5674 var nonfinal_nonexhaustive = false;5564 var nonfinal_nonexhaustive = false;
5675 for (container_decl.ast.members) |member_node| {5565 for (container_decl.ast.members) |member_node| {
5676 var member = tree.fullContainerField(member_node) orelse {5566 var member = tree.fullContainerField(member_node) orelse {
5677 decls += 1;5567 decls += 1;
5678 continue;5568 continue;
5679 };5569 };
5680 member.convertToNonTupleLike(astgen.tree.nodes);5570 member.convertToNonTupleLike(astgen.tree);
5681 if (member.ast.tuple_like) {5571 if (member.ast.tuple_like) {
5682 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});5572 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
5683 }5573 }
5684 if (member.comptime_token) |comptime_token| {5574 if (member.comptime_token) |comptime_token| {
5685 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});5575 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
5686 }5576 }
5687 if (member.ast.type_expr != 0) {5577 if (member.ast.type_expr.unwrap()) |type_expr| {
5688 return astgen.failNodeNotes(5578 return astgen.failNodeNotes(
5689 member.ast.type_expr,5579 type_expr,
5690 "enum fields do not have types",5580 "enum fields do not have types",
5691 .{},5581 .{},
5692 &[_]u32{5582 &[_]u32{
...@@ -5698,13 +5588,13 @@ fn containerDecl(...@@ -5698,13 +5588,13 @@ fn containerDecl(
5698 },5588 },
5699 );5589 );
5700 }5590 }
5701 if (member.ast.align_expr != 0) {5591 if (member.ast.align_expr.unwrap()) |align_expr| {
5702 return astgen.failNode(member.ast.align_expr, "enum fields cannot be aligned", .{});5592 return astgen.failNode(align_expr, "enum fields cannot be aligned", .{});
5703 }5593 }
57045594
5705 const name_token = member.ast.main_token;5595 const name_token = member.ast.main_token;
5706 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {5596 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
5707 if (nonexhaustive_node != 0) {5597 if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| {
5708 return astgen.failNodeNotes(5598 return astgen.failNodeNotes(
5709 member_node,5599 member_node,
5710 "redundant non-exhaustive enum mark",5600 "redundant non-exhaustive enum mark",
...@@ -5718,40 +5608,41 @@ fn containerDecl(...@@ -5718,40 +5608,41 @@ fn containerDecl(
5718 },5608 },
5719 );5609 );
5720 }5610 }
5721 nonexhaustive_node = member_node;5611 opt_nonexhaustive_node = member_node.toOptional();
5722 if (member.ast.value_expr != 0) {5612 if (member.ast.value_expr.unwrap()) |value_expr| {
5723 return astgen.failNode(member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});5613 return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{});
5724 }5614 }
5725 continue;5615 continue;
5726 } else if (nonexhaustive_node != 0) {5616 } else if (opt_nonexhaustive_node != .none) {
5727 nonfinal_nonexhaustive = true;5617 nonfinal_nonexhaustive = true;
5728 }5618 }
5729 total_fields += 1;5619 total_fields += 1;
5730 if (member.ast.value_expr != 0) {5620 if (member.ast.value_expr.unwrap()) |value_expr| {
5731 if (container_decl.ast.arg == 0) {5621 if (container_decl.ast.arg == .none) {
5732 return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});5622 return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{});
5733 }5623 }
5734 values += 1;5624 values += 1;
5735 }5625 }
5736 }5626 }
5737 if (nonfinal_nonexhaustive) {5627 if (nonfinal_nonexhaustive) {
5738 return astgen.failNode(nonexhaustive_node, "'_' field of non-exhaustive enum must be last", .{});5628 return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{});
5739 }5629 }
5740 break :blk .{5630 break :blk .{
5741 .total_fields = total_fields,5631 .total_fields = total_fields,
5742 .values = values,5632 .values = values,
5743 .decls = decls,5633 .decls = decls,
5744 .nonexhaustive_node = nonexhaustive_node,5634 .nonexhaustive_node = opt_nonexhaustive_node,
5745 };5635 };
5746 };5636 };
5747 if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) {5637 if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) {
5638 const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?;
5748 return astgen.failNodeNotes(5639 return astgen.failNodeNotes(
5749 node,5640 node,
5750 "non-exhaustive enum missing integer tag type",5641 "non-exhaustive enum missing integer tag type",
5751 .{},5642 .{},
5752 &[_]u32{5643 &[_]u32{
5753 try astgen.errNoteNode(5644 try astgen.errNoteNode(
5754 counts.nonexhaustive_node,5645 nonexhaustive_node,
5755 "marked non-exhaustive here",5646 "marked non-exhaustive here",
5756 .{},5647 .{},
5757 ),5648 ),
...@@ -5760,7 +5651,7 @@ fn containerDecl(...@@ -5760,7 +5651,7 @@ fn containerDecl(
5760 }5651 }
5761 // In this case we must generate ZIR code for the tag values, similar to5652 // In this case we must generate ZIR code for the tag values, similar to
5762 // how structs are handled above.5653 // how structs are handled above.
5763 const nonexhaustive = counts.nonexhaustive_node != 0;5654 const nonexhaustive = counts.nonexhaustive_node != .none;
57645655
5765 const decl_inst = try gz.reserveInstructionIndex();5656 const decl_inst = try gz.reserveInstructionIndex();
57665657
...@@ -5790,8 +5681,8 @@ fn containerDecl(...@@ -5790,8 +5681,8 @@ fn containerDecl(
5790 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");5681 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
5791 namespace.base.tag = .namespace;5682 namespace.base.tag = .namespace;
57925683
5793 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)5684 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg|
5794 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type)5685 try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type)
5795 else5686 else
5796 .none;5687 .none;
57975688
...@@ -5803,31 +5694,31 @@ fn containerDecl(...@@ -5803,31 +5694,31 @@ fn containerDecl(
5803 const old_hasher = astgen.src_hasher;5694 const old_hasher = astgen.src_hasher;
5804 defer astgen.src_hasher = old_hasher;5695 defer astgen.src_hasher = old_hasher;
5805 astgen.src_hasher = std.zig.SrcHasher.init(.{});5696 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5806 if (container_decl.ast.arg != 0) {5697 if (container_decl.ast.arg.unwrap()) |arg| {
5807 astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg));5698 astgen.src_hasher.update(tree.getNodeSource(arg));
5808 }5699 }
5809 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});5700 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});
58105701
5811 for (container_decl.ast.members) |member_node| {5702 for (container_decl.ast.members) |member_node| {
5812 if (member_node == counts.nonexhaustive_node)5703 if (member_node.toOptional() == counts.nonexhaustive_node)
5813 continue;5704 continue;
5814 astgen.src_hasher.update(tree.getNodeSource(member_node));5705 astgen.src_hasher.update(tree.getNodeSource(member_node));
5815 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {5706 var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
5816 .decl => continue,5707 .decl => continue,
5817 .field => |field| field,5708 .field => |field| field,
5818 };5709 };
5819 member.convertToNonTupleLike(astgen.tree.nodes);5710 member.convertToNonTupleLike(astgen.tree);
5820 assert(member.comptime_token == null);5711 assert(member.comptime_token == null);
5821 assert(member.ast.type_expr == 0);5712 assert(member.ast.type_expr == .none);
5822 assert(member.ast.align_expr == 0);5713 assert(member.ast.align_expr == .none);
58235714
5824 const field_name = try astgen.identAsString(member.ast.main_token);5715 const field_name = try astgen.identAsString(member.ast.main_token);
5825 wip_members.appendToField(@intFromEnum(field_name));5716 wip_members.appendToField(@intFromEnum(field_name));
58265717
5827 const have_value = member.ast.value_expr != 0;5718 const have_value = member.ast.value_expr != .none;
5828 wip_members.nextField(bits_per_field, .{have_value});5719 wip_members.nextField(bits_per_field, .{have_value});
58295720
5830 if (have_value) {5721 if (member.ast.value_expr.unwrap()) |value_expr| {
5831 if (arg_inst == .none) {5722 if (arg_inst == .none) {
5832 return astgen.failNodeNotes(5723 return astgen.failNodeNotes(
5833 node,5724 node,
...@@ -5835,14 +5726,14 @@ fn containerDecl(...@@ -5835,14 +5726,14 @@ fn containerDecl(
5835 .{},5726 .{},
5836 &[_]u32{5727 &[_]u32{
5837 try astgen.errNoteNode(5728 try astgen.errNoteNode(
5838 member.ast.value_expr,5729 value_expr,
5839 "tag value specified here",5730 "tag value specified here",
5840 .{},5731 .{},
5841 ),5732 ),
5842 },5733 },
5843 );5734 );
5844 }5735 }
5845 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5736 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5846 wip_members.appendToField(@intFromEnum(tag_value_inst));5737 wip_members.appendToField(@intFromEnum(tag_value_inst));
5847 }5738 }
5848 }5739 }
...@@ -5882,7 +5773,7 @@ fn containerDecl(...@@ -5882,7 +5773,7 @@ fn containerDecl(
5882 return rvalue(gz, ri, decl_inst.toRef(), node);5773 return rvalue(gz, ri, decl_inst.toRef(), node);
5883 },5774 },
5884 .keyword_opaque => {5775 .keyword_opaque => {
5885 assert(container_decl.ast.arg == 0);5776 assert(container_decl.ast.arg == .none);
58865777
5887 const decl_inst = try gz.reserveInstructionIndex();5778 const decl_inst = try gz.reserveInstructionIndex();
58885779
...@@ -5953,9 +5844,7 @@ fn containerMember(...@@ -5953,9 +5844,7 @@ fn containerMember(
5953) InnerError!ContainerMemberResult {5844) InnerError!ContainerMemberResult {
5954 const astgen = gz.astgen;5845 const astgen = gz.astgen;
5955 const tree = astgen.tree;5846 const tree = astgen.tree;
5956 const node_tags = tree.nodes.items(.tag);5847 switch (tree.nodeTag(member_node)) {
5957 const node_datas = tree.nodes.items(.data);
5958 switch (node_tags[member_node]) {
5959 .container_field_init,5848 .container_field_init,
5960 .container_field_align,5849 .container_field_align,
5961 .container_field,5850 .container_field,
...@@ -5969,7 +5858,11 @@ fn containerMember(...@@ -5969,7 +5858,11 @@ fn containerMember(
5969 => {5858 => {
5970 var buf: [1]Ast.Node.Index = undefined;5859 var buf: [1]Ast.Node.Index = undefined;
5971 const full = tree.fullFnProto(&buf, member_node).?;5860 const full = tree.fullFnProto(&buf, member_node).?;
5972 const body = if (node_tags[member_node] == .fn_decl) node_datas[member_node].rhs else 0;5861
5862 const body: Ast.Node.OptionalIndex = if (tree.nodeTag(member_node) == .fn_decl)
5863 tree.nodeData(member_node).node_and_node[1].toOptional()
5864 else
5865 .none;
59735866
5974 const prev_decl_index = wip_members.decl_index;5867 const prev_decl_index = wip_members.decl_index;
5975 astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) {5868 astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) {
...@@ -6040,12 +5933,7 @@ fn containerMember(...@@ -6040,12 +5933,7 @@ fn containerMember(
6040 .@"usingnamespace",5933 .@"usingnamespace",
6041 .empty,5934 .empty,
6042 member_node,5935 member_node,
6043 is_pub: {5936 tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}),
6044 const main_tokens = tree.nodes.items(.main_token);
6045 const token_tags = tree.tokens.items(.tag);
6046 const main_token = main_tokens[member_node];
6047 break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub;
6048 },
6049 );5937 );
6050 },5938 },
6051 };5939 };
...@@ -6079,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi...@@ -6079,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
6079 const astgen = gz.astgen;5967 const astgen = gz.astgen;
6080 const gpa = astgen.gpa;5968 const gpa = astgen.gpa;
6081 const tree = astgen.tree;5969 const tree = astgen.tree;
6082 const main_tokens = tree.nodes.items(.main_token);
6083 const token_tags = tree.tokens.items(.tag);
60845970
6085 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len);5971 const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len);
6086 var fields_len: usize = 0;5972 var fields_len: usize = 0;
...@@ -6088,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi...@@ -6088,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
6088 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;5974 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;
6089 defer idents.deinit(gpa);5975 defer idents.deinit(gpa);
60905976
6091 const error_token = main_tokens[node];5977 const lbrace, const rbrace = tree.nodeData(node).token_and_token;
6092 var tok_i = error_token + 2;5978 for (lbrace + 1..rbrace) |i| {
6093 while (true) : (tok_i += 1) {5979 const tok_i: Ast.TokenIndex = @intCast(i);
6094 switch (token_tags[tok_i]) {5980 switch (tree.tokenTag(tok_i)) {
6095 .doc_comment, .comma => {},5981 .doc_comment, .comma => {},
6096 .identifier => {5982 .identifier => {
6097 const str_index = try astgen.identAsString(tok_i);5983 const str_index = try astgen.identAsString(tok_i);
...@@ -6117,7 +6003,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi...@@ -6117,7 +6003,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
6117 try astgen.extra.append(gpa, @intFromEnum(str_index));6003 try astgen.extra.append(gpa, @intFromEnum(str_index));
6118 fields_len += 1;6004 fields_len += 1;
6119 },6005 },
6120 .r_brace => break,
6121 else => unreachable,6006 else => unreachable,
6122 }6007 }
6123 }6008 }
...@@ -6143,10 +6028,10 @@ fn tryExpr(...@@ -6143,10 +6028,10 @@ fn tryExpr(
6143 return astgen.failNode(node, "'try' outside function scope", .{});6028 return astgen.failNode(node, "'try' outside function scope", .{});
6144 };6029 };
61456030
6146 if (parent_gz.any_defer_node != 0) {6031 if (parent_gz.any_defer_node.unwrap()) |any_defer_node| {
6147 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{6032 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{
6148 try astgen.errNoteNode(6033 try astgen.errNoteNode(
6149 parent_gz.any_defer_node,6034 any_defer_node,
6150 "defer expression here",6035 "defer expression here",
6151 .{},6036 .{},
6152 ),6037 ),
...@@ -6209,16 +6094,16 @@ fn orelseCatchExpr(...@@ -6209,16 +6094,16 @@ fn orelseCatchExpr(
6209 scope: *Scope,6094 scope: *Scope,
6210 ri: ResultInfo,6095 ri: ResultInfo,
6211 node: Ast.Node.Index,6096 node: Ast.Node.Index,
6212 lhs: Ast.Node.Index,
6213 cond_op: Zir.Inst.Tag,6097 cond_op: Zir.Inst.Tag,
6214 unwrap_op: Zir.Inst.Tag,6098 unwrap_op: Zir.Inst.Tag,
6215 unwrap_code_op: Zir.Inst.Tag,6099 unwrap_code_op: Zir.Inst.Tag,
6216 rhs: Ast.Node.Index,
6217 payload_token: ?Ast.TokenIndex,6100 payload_token: ?Ast.TokenIndex,
6218) InnerError!Zir.Inst.Ref {6101) InnerError!Zir.Inst.Ref {
6219 const astgen = parent_gz.astgen;6102 const astgen = parent_gz.astgen;
6220 const tree = astgen.tree;6103 const tree = astgen.tree;
62216104
6105 const lhs, const rhs = tree.nodeData(node).node_and_node;
6106
6222 const need_rl = astgen.nodes_need_rl.contains(node);6107 const need_rl = astgen.nodes_need_rl.contains(node);
6223 const block_ri: ResultInfo = if (need_rl) ri else .{6108 const block_ri: ResultInfo = if (need_rl) ri else .{
6224 .rl = switch (ri.rl) {6109 .rl = switch (ri.rl) {
...@@ -6351,12 +6236,8 @@ fn addFieldAccess(...@@ -6351,12 +6236,8 @@ fn addFieldAccess(
6351) InnerError!Zir.Inst.Ref {6236) InnerError!Zir.Inst.Ref {
6352 const astgen = gz.astgen;6237 const astgen = gz.astgen;
6353 const tree = astgen.tree;6238 const tree = astgen.tree;
6354 const main_tokens = tree.nodes.items(.main_token);
6355 const node_datas = tree.nodes.items(.data);
63566239
6357 const object_node = node_datas[node].lhs;6240 const object_node, const field_ident = tree.nodeData(node).node_and_token;
6358 const dot_token = main_tokens[node];
6359 const field_ident = dot_token + 1;
6360 const str_index = try astgen.identAsString(field_ident);6241 const str_index = try astgen.identAsString(field_ident);
6361 const lhs = try expr(gz, scope, lhs_ri, object_node);6242 const lhs = try expr(gz, scope, lhs_ri, object_node);
63626243
...@@ -6376,24 +6257,25 @@ fn arrayAccess(...@@ -6376,24 +6257,25 @@ fn arrayAccess(
6376 node: Ast.Node.Index,6257 node: Ast.Node.Index,
6377) InnerError!Zir.Inst.Ref {6258) InnerError!Zir.Inst.Ref {
6378 const tree = gz.astgen.tree;6259 const tree = gz.astgen.tree;
6379 const node_datas = tree.nodes.items(.data);
6380 switch (ri.rl) {6260 switch (ri.rl) {
6381 .ref, .ref_coerced_ty => {6261 .ref, .ref_coerced_ty => {
6382 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);6262 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6263 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node);
63836264
6384 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);6265 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63856266
6386 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);6267 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
6387 try emitDbgStmt(gz, cursor);6268 try emitDbgStmt(gz, cursor);
63886269
6389 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });6270 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6390 },6271 },
6391 else => {6272 else => {
6392 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);6273 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6274 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
63936275
6394 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);6276 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63956277
6396 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);6278 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
6397 try emitDbgStmt(gz, cursor);6279 try emitDbgStmt(gz, cursor);
63986280
6399 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);6281 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
...@@ -6410,22 +6292,22 @@ fn simpleBinOp(...@@ -6410,22 +6292,22 @@ fn simpleBinOp(
6410) InnerError!Zir.Inst.Ref {6292) InnerError!Zir.Inst.Ref {
6411 const astgen = gz.astgen;6293 const astgen = gz.astgen;
6412 const tree = astgen.tree;6294 const tree = astgen.tree;
6413 const node_datas = tree.nodes.items(.data);6295
6296 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
64146297
6415 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {6298 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
6416 const node_tags = tree.nodes.items(.tag);
6417 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";6299 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
6418 if (node_tags[node_datas[node].lhs] == .string_literal or6300 if (tree.nodeTag(lhs_node) == .string_literal or
6419 node_tags[node_datas[node].rhs] == .string_literal)6301 tree.nodeTag(rhs_node) == .string_literal)
6420 return astgen.failNode(node, "cannot compare strings with {s}", .{str});6302 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
6421 }6303 }
64226304
6423 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);6305 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node);
6424 const cursor = switch (op_inst_tag) {6306 const cursor = switch (op_inst_tag) {
6425 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),6307 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
6426 else => undefined,6308 else => undefined,
6427 };6309 };
6428 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);6310 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node);
64296311
6430 switch (op_inst_tag) {6312 switch (op_inst_tag) {
6431 .add, .sub, .mul, .div, .mod_rem => {6313 .add, .sub, .mul, .div, .mod_rem => {
...@@ -6459,16 +6341,16 @@ fn boolBinOp(...@@ -6459,16 +6341,16 @@ fn boolBinOp(
6459) InnerError!Zir.Inst.Ref {6341) InnerError!Zir.Inst.Ref {
6460 const astgen = gz.astgen;6342 const astgen = gz.astgen;
6461 const tree = astgen.tree;6343 const tree = astgen.tree;
6462 const node_datas = tree.nodes.items(.data);
64636344
6464 const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs);6345 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6346 const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node);
6465 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;6347 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;
64666348
6467 var rhs_scope = gz.makeSubBlock(scope);6349 var rhs_scope = gz.makeSubBlock(scope);
6468 defer rhs_scope.unstack();6350 defer rhs_scope.unstack();
6469 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint);6351 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint);
6470 if (!gz.refIsNoReturn(rhs)) {6352 if (!gz.refIsNoReturn(rhs)) {
6471 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);6353 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node);
6472 }6354 }
6473 try rhs_scope.setBoolBrBody(bool_br, lhs);6355 try rhs_scope.setBoolBrBody(bool_br, lhs);
64746356
...@@ -6485,7 +6367,6 @@ fn ifExpr(...@@ -6485,7 +6367,6 @@ fn ifExpr(
6485) InnerError!Zir.Inst.Ref {6367) InnerError!Zir.Inst.Ref {
6486 const astgen = parent_gz.astgen;6368 const astgen = parent_gz.astgen;
6487 const tree = astgen.tree;6369 const tree = astgen.tree;
6488 const token_tags = tree.tokens.items(.tag);
64896370
6490 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;6371 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
64916372
...@@ -6508,7 +6389,7 @@ fn ifExpr(...@@ -6508,7 +6389,7 @@ fn ifExpr(
6508 defer block_scope.unstack();6389 defer block_scope.unstack();
65096390
6510 const payload_is_ref = if (if_full.payload_token) |payload_token|6391 const payload_is_ref = if (if_full.payload_token) |payload_token|
6511 token_tags[payload_token] == .asterisk6392 tree.tokenTag(payload_token) == .asterisk
6512 else6393 else
6513 false;6394 false;
65146395
...@@ -6586,7 +6467,7 @@ fn ifExpr(...@@ -6586,7 +6467,7 @@ fn ifExpr(
6586 break :s &then_scope.base;6467 break :s &then_scope.base;
6587 }6468 }
6588 } else if (if_full.payload_token) |payload_token| {6469 } else if (if_full.payload_token) |payload_token| {
6589 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;6470 const ident_token = payload_token + @intFromBool(payload_is_ref);
6590 const tag: Zir.Inst.Tag = if (payload_is_ref)6471 const tag: Zir.Inst.Tag = if (payload_is_ref)
6591 .optional_payload_unsafe_ptr6472 .optional_payload_unsafe_ptr
6592 else6473 else
...@@ -6628,8 +6509,7 @@ fn ifExpr(...@@ -6628,8 +6509,7 @@ fn ifExpr(
6628 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))6509 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))
6629 _ = try else_scope.addSaveErrRetIndex(.always);6510 _ = try else_scope.addSaveErrRetIndex(.always);
66306511
6631 const else_node = if_full.ast.else_expr;6512 if (if_full.ast.else_expr.unwrap()) |else_node| {
6632 if (else_node != 0) {
6633 const sub_scope = s: {6513 const sub_scope = s: {
6634 if (if_full.error_token) |error_token| {6514 if (if_full.error_token) |error_token| {
6635 const tag: Zir.Inst.Tag = if (payload_is_ref)6515 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -6717,8 +6597,6 @@ fn whileExpr(...@@ -6717,8 +6597,6 @@ fn whileExpr(
6717) InnerError!Zir.Inst.Ref {6597) InnerError!Zir.Inst.Ref {
6718 const astgen = parent_gz.astgen;6598 const astgen = parent_gz.astgen;
6719 const tree = astgen.tree;6599 const tree = astgen.tree;
6720 const token_tags = tree.tokens.items(.tag);
6721 const token_starts = tree.tokens.items(.start);
67226600
6723 const need_rl = astgen.nodes_need_rl.contains(node);6601 const need_rl = astgen.nodes_need_rl.contains(node);
6724 const block_ri: ResultInfo = if (need_rl) ri else .{6602 const block_ri: ResultInfo = if (need_rl) ri else .{
...@@ -6755,7 +6633,7 @@ fn whileExpr(...@@ -6755,7 +6633,7 @@ fn whileExpr(
6755 defer cond_scope.unstack();6633 defer cond_scope.unstack();
67566634
6757 const payload_is_ref = if (while_full.payload_token) |payload_token|6635 const payload_is_ref = if (while_full.payload_token) |payload_token|
6758 token_tags[payload_token] == .asterisk6636 tree.tokenTag(payload_token) == .asterisk
6759 else6637 else
6760 false;6638 false;
67616639
...@@ -6841,7 +6719,6 @@ fn whileExpr(...@@ -6841,7 +6719,6 @@ fn whileExpr(
6841 break :s &then_scope.base;6719 break :s &then_scope.base;
6842 }6720 }
6843 } else if (while_full.payload_token) |payload_token| {6721 } else if (while_full.payload_token) |payload_token| {
6844 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
6845 const tag: Zir.Inst.Tag = if (payload_is_ref)6722 const tag: Zir.Inst.Tag = if (payload_is_ref)
6846 .optional_payload_unsafe_ptr6723 .optional_payload_unsafe_ptr
6847 else6724 else
...@@ -6849,6 +6726,7 @@ fn whileExpr(...@@ -6849,6 +6726,7 @@ fn whileExpr(
6849 // will add this instruction to then_scope.instructions below6726 // will add this instruction to then_scope.instructions below
6850 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);6727 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);
6851 opt_payload_inst = payload_inst.toOptional();6728 opt_payload_inst = payload_inst.toOptional();
6729 const ident_token = payload_token + @intFromBool(payload_is_ref);
6852 const ident_name = try astgen.identAsString(ident_token);6730 const ident_name = try astgen.identAsString(ident_token);
6853 const ident_bytes = tree.tokenSlice(ident_token);6731 const ident_bytes = tree.tokenSlice(ident_token);
6854 if (mem.eql(u8, "_", ident_bytes)) {6732 if (mem.eql(u8, "_", ident_bytes)) {
...@@ -6903,8 +6781,8 @@ fn whileExpr(...@@ -6903,8 +6781,8 @@ fn whileExpr(
6903 // are no jumps to it. This happens when the last statement of a while body is noreturn6781 // are no jumps to it. This happens when the last statement of a while body is noreturn
6904 // and there are no `continue` statements.6782 // and there are no `continue` statements.
6905 // Tracking issue: https://github.com/ziglang/zig/issues/91856783 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6906 if (while_full.ast.cont_expr != 0) {6784 if (while_full.ast.cont_expr.unwrap()) |cont_expr| {
6907 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);6785 _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr);
6908 }6786 }
69096787
6910 continue_scope.instructions_top = continue_scope.instructions.items.len;6788 continue_scope.instructions_top = continue_scope.instructions.items.len;
...@@ -6916,7 +6794,7 @@ fn whileExpr(...@@ -6916,7 +6794,7 @@ fn whileExpr(
6916 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6794 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6917 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6795 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6918 if (!continue_scope.endsWithNoReturn()) {6796 if (!continue_scope.endsWithNoReturn()) {
6919 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);6797 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
6920 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });6798 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
6921 _ = try parent_gz.add(.{6799 _ = try parent_gz.add(.{
6922 .tag = .extended,6800 .tag = .extended,
...@@ -6934,8 +6812,7 @@ fn whileExpr(...@@ -6934,8 +6812,7 @@ fn whileExpr(
6934 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);6812 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
6935 defer else_scope.unstack();6813 defer else_scope.unstack();
69366814
6937 const else_node = while_full.ast.else_expr;6815 if (while_full.ast.else_expr.unwrap()) |else_node| {
6938 if (else_node != 0) {
6939 const sub_scope = s: {6816 const sub_scope = s: {
6940 if (while_full.error_token) |error_token| {6817 if (while_full.error_token) |error_token| {
6941 const tag: Zir.Inst.Tag = if (payload_is_ref)6818 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -7033,10 +6910,6 @@ fn forExpr(...@@ -7033,10 +6910,6 @@ fn forExpr(
7033 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});6910 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});
7034 }6911 }
7035 const tree = astgen.tree;6912 const tree = astgen.tree;
7036 const token_tags = tree.tokens.items(.tag);
7037 const token_starts = tree.tokens.items(.start);
7038 const node_tags = tree.nodes.items(.tag);
7039 const node_data = tree.nodes.items(.data);
7040 const gpa = astgen.gpa;6913 const gpa = astgen.gpa;
70416914
7042 // For counters, this is the start value; for indexables, this is the base6915 // For counters, this is the start value; for indexables, this is the base
...@@ -7066,7 +6939,7 @@ fn forExpr(...@@ -7066,7 +6939,7 @@ fn forExpr(
7066 {6939 {
7067 var capture_token = for_full.payload_token;6940 var capture_token = for_full.payload_token;
7068 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {6941 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {
7069 const capture_is_ref = token_tags[capture_token] == .asterisk;6942 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
7070 const ident_tok = capture_token + @intFromBool(capture_is_ref);6943 const ident_tok = capture_token + @intFromBool(capture_is_ref);
7071 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");6944 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");
70726945
...@@ -7077,16 +6950,15 @@ fn forExpr(...@@ -7077,16 +6950,15 @@ fn forExpr(
7077 capture_token = ident_tok + 2;6950 capture_token = ident_tok + 2;
70786951
7079 try emitDbgNode(parent_gz, input);6952 try emitDbgNode(parent_gz, input);
7080 if (node_tags[input] == .for_range) {6953 if (tree.nodeTag(input) == .for_range) {
7081 if (capture_is_ref) {6954 if (capture_is_ref) {
7082 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});6955 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
7083 }6956 }
7084 const start_node = node_data[input].lhs;6957 const start_node, const end_node = tree.nodeData(input).node_and_opt_node;
7085 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);6958 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);
70866959
7087 const end_node = node_data[input].rhs;6960 const end_val = if (end_node.unwrap()) |end|
7088 const end_val = if (end_node != 0)6961 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end)
7089 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs)
7090 else6962 else
7091 .none;6963 .none;
70926964
...@@ -7179,7 +7051,7 @@ fn forExpr(...@@ -7179,7 +7051,7 @@ fn forExpr(
7179 var capture_token = for_full.payload_token;7051 var capture_token = for_full.payload_token;
7180 var capture_sub_scope: *Scope = &then_scope.base;7052 var capture_sub_scope: *Scope = &then_scope.base;
7181 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {7053 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {
7182 const capture_is_ref = token_tags[capture_token] == .asterisk;7054 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
7183 const ident_tok = capture_token + @intFromBool(capture_is_ref);7055 const ident_tok = capture_token + @intFromBool(capture_is_ref);
7184 const capture_name = tree.tokenSlice(ident_tok);7056 const capture_name = tree.tokenSlice(ident_tok);
7185 // Skip over the comma, and on to the next capture (or the ending pipe character).7057 // Skip over the comma, and on to the next capture (or the ending pipe character).
...@@ -7191,7 +7063,7 @@ fn forExpr(...@@ -7191,7 +7063,7 @@ fn forExpr(
7191 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);7063 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
71927064
7193 const capture_inst = inst: {7065 const capture_inst = inst: {
7194 const is_counter = node_tags[input] == .for_range;7066 const is_counter = tree.nodeTag(input) == .for_range;
71957067
7196 if (indexable_ref == .none) {7068 if (indexable_ref == .none) {
7197 // Special case: the main index can be used directly.7069 // Special case: the main index can be used directly.
...@@ -7238,7 +7110,7 @@ fn forExpr(...@@ -7238,7 +7110,7 @@ fn forExpr(
72387110
7239 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);7111 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
72407112
7241 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);7113 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
7242 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });7114 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
7243 _ = try parent_gz.add(.{7115 _ = try parent_gz.add(.{
7244 .tag = .extended,7116 .tag = .extended,
...@@ -7255,8 +7127,7 @@ fn forExpr(...@@ -7255,8 +7127,7 @@ fn forExpr(
7255 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);7127 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
7256 defer else_scope.unstack();7128 defer else_scope.unstack();
72577129
7258 const else_node = for_full.ast.else_expr;7130 if (for_full.ast.else_expr.unwrap()) |else_node| {
7259 if (else_node != 0) {
7260 const sub_scope = &else_scope.base;7131 const sub_scope = &else_scope.base;
7261 // Remove the continue block and break block so that `continue` and `break`7132 // Remove the continue block and break block so that `continue` and `break`
7262 // control flow apply to outer loops; not this one.7133 // control flow apply to outer loops; not this one.
...@@ -7324,10 +7195,6 @@ fn switchExprErrUnion(...@@ -7324,10 +7195,6 @@ fn switchExprErrUnion(
7324 const astgen = parent_gz.astgen;7195 const astgen = parent_gz.astgen;
7325 const gpa = astgen.gpa;7196 const gpa = astgen.gpa;
7326 const tree = astgen.tree;7197 const tree = astgen.tree;
7327 const node_datas = tree.nodes.items(.data);
7328 const node_tags = tree.nodes.items(.tag);
7329 const main_tokens = tree.nodes.items(.main_token);
7330 const token_tags = tree.tokens.items(.tag);
73317198
7332 const if_full = switch (node_ty) {7199 const if_full = switch (node_ty) {
7333 .@"catch" => undefined,7200 .@"catch" => undefined,
...@@ -7336,23 +7203,19 @@ fn switchExprErrUnion(...@@ -7336,23 +7203,19 @@ fn switchExprErrUnion(
73367203
7337 const switch_node, const operand_node, const error_payload = switch (node_ty) {7204 const switch_node, const operand_node, const error_payload = switch (node_ty) {
7338 .@"catch" => .{7205 .@"catch" => .{
7339 node_datas[catch_or_if_node].rhs,7206 tree.nodeData(catch_or_if_node).node_and_node[1],
7340 node_datas[catch_or_if_node].lhs,7207 tree.nodeData(catch_or_if_node).node_and_node[0],
7341 main_tokens[catch_or_if_node] + 2,7208 tree.nodeMainToken(catch_or_if_node) + 2,
7342 },7209 },
7343 .@"if" => .{7210 .@"if" => .{
7344 if_full.ast.else_expr,7211 if_full.ast.else_expr.unwrap().?,
7345 if_full.ast.cond_expr,7212 if_full.ast.cond_expr,
7346 if_full.error_token.?,7213 if_full.error_token.?,
7347 },7214 },
7348 };7215 };
7349 assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma);7216 const switch_full = tree.fullSwitch(switch_node).?;
73507217
7351 const do_err_trace = astgen.fn_block != null;7218 const do_err_trace = astgen.fn_block != null;
7352
7353 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
7354 const case_nodes = tree.extra_data[extra.start..extra.end];
7355
7356 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);7219 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);
7357 const block_ri: ResultInfo = if (need_rl) ri else .{7220 const block_ri: ResultInfo = if (need_rl) ri else .{
7358 .rl = switch (ri.rl) {7221 .rl = switch (ri.rl) {
...@@ -7364,7 +7227,7 @@ fn switchExprErrUnion(...@@ -7364,7 +7227,7 @@ fn switchExprErrUnion(
7364 };7227 };
73657228
7366 const payload_is_ref = switch (node_ty) {7229 const payload_is_ref = switch (node_ty) {
7367 .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk,7230 .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk,
7368 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,7231 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,
7369 };7232 };
73707233
...@@ -7376,9 +7239,9 @@ fn switchExprErrUnion(...@@ -7376,9 +7239,9 @@ fn switchExprErrUnion(
7376 var multi_cases_len: u32 = 0;7239 var multi_cases_len: u32 = 0;
7377 var inline_cases_len: u32 = 0;7240 var inline_cases_len: u32 = 0;
7378 var has_else = false;7241 var has_else = false;
7379 var else_node: Ast.Node.Index = 0;7242 var else_node: Ast.Node.OptionalIndex = .none;
7380 var else_src: ?Ast.TokenIndex = null;7243 var else_src: ?Ast.TokenIndex = null;
7381 for (case_nodes) |case_node| {7244 for (switch_full.ast.cases) |case_node| {
7382 const case = tree.fullSwitchCase(case_node).?;7245 const case = tree.fullSwitchCase(case_node).?;
73837246
7384 if (case.ast.values.len == 0) {7247 if (case.ast.values.len == 0) {
...@@ -7398,12 +7261,12 @@ fn switchExprErrUnion(...@@ -7398,12 +7261,12 @@ fn switchExprErrUnion(
7398 );7261 );
7399 }7262 }
7400 has_else = true;7263 has_else = true;
7401 else_node = case_node;7264 else_node = case_node.toOptional();
7402 else_src = case_src;7265 else_src = case_src;
7403 continue;7266 continue;
7404 } else if (case.ast.values.len == 1 and7267 } else if (case.ast.values.len == 1 and
7405 node_tags[case.ast.values[0]] == .identifier and7268 tree.nodeTag(case.ast.values[0]) == .identifier and
7406 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))7269 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
7407 {7270 {
7408 const case_src = case.ast.arrow_token - 1;7271 const case_src = case.ast.arrow_token - 1;
7409 return astgen.failTokNotes(7272 return astgen.failTokNotes(
...@@ -7421,11 +7284,11 @@ fn switchExprErrUnion(...@@ -7421,11 +7284,11 @@ fn switchExprErrUnion(
7421 }7284 }
74227285
7423 for (case.ast.values) |val| {7286 for (case.ast.values) |val| {
7424 if (node_tags[val] == .string_literal)7287 if (tree.nodeTag(val) == .string_literal)
7425 return astgen.failNode(val, "cannot switch on strings", .{});7288 return astgen.failNode(val, "cannot switch on strings", .{});
7426 }7289 }
74277290
7428 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {7291 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
7429 scalar_cases_len += 1;7292 scalar_cases_len += 1;
7430 } else {7293 } else {
7431 multi_cases_len += 1;7294 multi_cases_len += 1;
...@@ -7618,11 +7481,11 @@ fn switchExprErrUnion(...@@ -7618,11 +7481,11 @@ fn switchExprErrUnion(
7618 var multi_case_index: u32 = 0;7481 var multi_case_index: u32 = 0;
7619 var scalar_case_index: u32 = 0;7482 var scalar_case_index: u32 = 0;
7620 var any_uses_err_capture = false;7483 var any_uses_err_capture = false;
7621 for (case_nodes) |case_node| {7484 for (switch_full.ast.cases) |case_node| {
7622 const case = tree.fullSwitchCase(case_node).?;7485 const case = tree.fullSwitchCase(case_node).?;
76237486
7624 const is_multi_case = case.ast.values.len > 1 or7487 const is_multi_case = case.ast.values.len > 1 or
7625 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);7488 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
76267489
7627 var dbg_var_name: Zir.NullTerminatedString = .empty;7490 var dbg_var_name: Zir.NullTerminatedString = .empty;
7628 var dbg_var_inst: Zir.Inst.Ref = undefined;7491 var dbg_var_inst: Zir.Inst.Ref = undefined;
...@@ -7640,7 +7503,7 @@ fn switchExprErrUnion(...@@ -7640,7 +7503,7 @@ fn switchExprErrUnion(
7640 };7503 };
76417504
7642 const capture_token = case.payload_token orelse break :blk &err_scope.base;7505 const capture_token = case.payload_token orelse break :blk &err_scope.base;
7643 if (token_tags[capture_token] != .identifier) {7506 if (tree.tokenTag(capture_token) != .identifier) {
7644 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});7507 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});
7645 }7508 }
76467509
...@@ -7676,7 +7539,7 @@ fn switchExprErrUnion(...@@ -7676,7 +7539,7 @@ fn switchExprErrUnion(
7676 // items7539 // items
7677 var items_len: u32 = 0;7540 var items_len: u32 = 0;
7678 for (case.ast.values) |item_node| {7541 for (case.ast.values) |item_node| {
7679 if (node_tags[item_node] == .switch_range) continue;7542 if (tree.nodeTag(item_node) == .switch_range) continue;
7680 items_len += 1;7543 items_len += 1;
76817544
7682 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);7545 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
...@@ -7686,11 +7549,12 @@ fn switchExprErrUnion(...@@ -7686,11 +7549,12 @@ fn switchExprErrUnion(
7686 // ranges7549 // ranges
7687 var ranges_len: u32 = 0;7550 var ranges_len: u32 = 0;
7688 for (case.ast.values) |range| {7551 for (case.ast.values) |range| {
7689 if (node_tags[range] != .switch_range) continue;7552 if (tree.nodeTag(range) != .switch_range) continue;
7690 ranges_len += 1;7553 ranges_len += 1;
76917554
7692 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);7555 const first_node, const last_node = tree.nodeData(range).node_and_node;
7693 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);7556 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
7557 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
7694 try payloads.appendSlice(gpa, &[_]u32{7558 try payloads.appendSlice(gpa, &[_]u32{
7695 @intFromEnum(first), @intFromEnum(last),7559 @intFromEnum(first), @intFromEnum(last),
7696 });7560 });
...@@ -7699,7 +7563,7 @@ fn switchExprErrUnion(...@@ -7699,7 +7563,7 @@ fn switchExprErrUnion(
7699 payloads.items[header_index] = items_len;7563 payloads.items[header_index] = items_len;
7700 payloads.items[header_index + 1] = ranges_len;7564 payloads.items[header_index + 1] = ranges_len;
7701 break :blk header_index + 2;7565 break :blk header_index + 2;
7702 } else if (case_node == else_node) blk: {7566 } else if (case_node.toOptional() == else_node) blk: {
7703 payloads.items[case_table_start + 1] = header_index;7567 payloads.items[case_table_start + 1] = header_index;
7704 try payloads.resize(gpa, header_index + 1); // body_len7568 try payloads.resize(gpa, header_index + 1); // body_len
7705 break :blk header_index;7569 break :blk header_index;
...@@ -7729,7 +7593,7 @@ fn switchExprErrUnion(...@@ -7729,7 +7593,7 @@ fn switchExprErrUnion(
7729 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);7593 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);
7730 // check capture_scope, not err_scope to avoid false positive unused error capture7594 // check capture_scope, not err_scope to avoid false positive unused error capture
7731 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);7595 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
7732 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;7596 const uses_err = err_scope.used != .none or err_scope.discarded != .none;
7733 if (uses_err) {7597 if (uses_err) {
7734 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());7598 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());
7735 any_uses_err_capture = true;7599 any_uses_err_capture = true;
...@@ -7829,10 +7693,6 @@ fn switchExpr(...@@ -7829,10 +7693,6 @@ fn switchExpr(
7829 const astgen = parent_gz.astgen;7693 const astgen = parent_gz.astgen;
7830 const gpa = astgen.gpa;7694 const gpa = astgen.gpa;
7831 const tree = astgen.tree;7695 const tree = astgen.tree;
7832 const node_datas = tree.nodes.items(.data);
7833 const node_tags = tree.nodes.items(.tag);
7834 const main_tokens = tree.nodes.items(.main_token);
7835 const token_tags = tree.tokens.items(.tag);
7836 const operand_node = switch_full.ast.condition;7696 const operand_node = switch_full.ast.condition;
7837 const case_nodes = switch_full.ast.cases;7697 const case_nodes = switch_full.ast.cases;
78387698
...@@ -7864,17 +7724,17 @@ fn switchExpr(...@@ -7864,17 +7724,17 @@ fn switchExpr(
7864 var multi_cases_len: u32 = 0;7724 var multi_cases_len: u32 = 0;
7865 var inline_cases_len: u32 = 0;7725 var inline_cases_len: u32 = 0;
7866 var special_prong: Zir.SpecialProng = .none;7726 var special_prong: Zir.SpecialProng = .none;
7867 var special_node: Ast.Node.Index = 0;7727 var special_node: Ast.Node.OptionalIndex = .none;
7868 var else_src: ?Ast.TokenIndex = null;7728 var else_src: ?Ast.TokenIndex = null;
7869 var underscore_src: ?Ast.TokenIndex = null;7729 var underscore_src: ?Ast.TokenIndex = null;
7870 for (case_nodes) |case_node| {7730 for (case_nodes) |case_node| {
7871 const case = tree.fullSwitchCase(case_node).?;7731 const case = tree.fullSwitchCase(case_node).?;
7872 if (case.payload_token) |payload_token| {7732 if (case.payload_token) |payload_token| {
7873 const ident = if (token_tags[payload_token] == .asterisk) blk: {7733 const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: {
7874 any_payload_is_ref = true;7734 any_payload_is_ref = true;
7875 break :blk payload_token + 1;7735 break :blk payload_token + 1;
7876 } else payload_token;7736 } else payload_token;
7877 if (token_tags[ident + 1] == .comma) {7737 if (tree.tokenTag(ident + 1) == .comma) {
7878 any_has_tag_capture = true;7738 any_has_tag_capture = true;
7879 }7739 }
78807740
...@@ -7922,13 +7782,13 @@ fn switchExpr(...@@ -7922,13 +7782,13 @@ fn switchExpr(
7922 },7782 },
7923 );7783 );
7924 }7784 }
7925 special_node = case_node;7785 special_node = case_node.toOptional();
7926 special_prong = .@"else";7786 special_prong = .@"else";
7927 else_src = case_src;7787 else_src = case_src;
7928 continue;7788 continue;
7929 } else if (case.ast.values.len == 1 and7789 } else if (case.ast.values.len == 1 and
7930 node_tags[case.ast.values[0]] == .identifier and7790 tree.nodeTag(case.ast.values[0]) == .identifier and
7931 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))7791 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
7932 {7792 {
7933 const case_src = case.ast.arrow_token - 1;7793 const case_src = case.ast.arrow_token - 1;
7934 if (underscore_src) |src| {7794 if (underscore_src) |src| {
...@@ -7966,18 +7826,18 @@ fn switchExpr(...@@ -7966,18 +7826,18 @@ fn switchExpr(
7966 if (case.inline_token != null) {7826 if (case.inline_token != null) {
7967 return astgen.failTok(case_src, "cannot inline '_' prong", .{});7827 return astgen.failTok(case_src, "cannot inline '_' prong", .{});
7968 }7828 }
7969 special_node = case_node;7829 special_node = case_node.toOptional();
7970 special_prong = .under;7830 special_prong = .under;
7971 underscore_src = case_src;7831 underscore_src = case_src;
7972 continue;7832 continue;
7973 }7833 }
79747834
7975 for (case.ast.values) |val| {7835 for (case.ast.values) |val| {
7976 if (node_tags[val] == .string_literal)7836 if (tree.nodeTag(val) == .string_literal)
7977 return astgen.failNode(val, "cannot switch on strings", .{});7837 return astgen.failNode(val, "cannot switch on strings", .{});
7978 }7838 }
79797839
7980 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {7840 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
7981 scalar_cases_len += 1;7841 scalar_cases_len += 1;
7982 } else {7842 } else {
7983 multi_cases_len += 1;7843 multi_cases_len += 1;
...@@ -8066,7 +7926,7 @@ fn switchExpr(...@@ -8066,7 +7926,7 @@ fn switchExpr(
8066 const case = tree.fullSwitchCase(case_node).?;7926 const case = tree.fullSwitchCase(case_node).?;
80677927
8068 const is_multi_case = case.ast.values.len > 1 or7928 const is_multi_case = case.ast.values.len > 1 or
8069 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);7929 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
80707930
8071 var dbg_var_name: Zir.NullTerminatedString = .empty;7931 var dbg_var_name: Zir.NullTerminatedString = .empty;
8072 var dbg_var_inst: Zir.Inst.Ref = undefined;7932 var dbg_var_inst: Zir.Inst.Ref = undefined;
...@@ -8080,18 +7940,15 @@ fn switchExpr(...@@ -8080,18 +7940,15 @@ fn switchExpr(
80807940
8081 const sub_scope = blk: {7941 const sub_scope = blk: {
8082 const payload_token = case.payload_token orelse break :blk &case_scope.base;7942 const payload_token = case.payload_token orelse break :blk &case_scope.base;
8083 const ident = if (token_tags[payload_token] == .asterisk)7943 const capture_is_ref = tree.tokenTag(payload_token) == .asterisk;
8084 payload_token + 17944 const ident = payload_token + @intFromBool(capture_is_ref);
8085 else
8086 payload_token;
80877945
8088 const is_ptr = ident != payload_token;7946 capture = if (capture_is_ref) .by_ref else .by_val;
8089 capture = if (is_ptr) .by_ref else .by_val;
80907947
8091 const ident_slice = tree.tokenSlice(ident);7948 const ident_slice = tree.tokenSlice(ident);
8092 var payload_sub_scope: *Scope = undefined;7949 var payload_sub_scope: *Scope = undefined;
8093 if (mem.eql(u8, ident_slice, "_")) {7950 if (mem.eql(u8, ident_slice, "_")) {
8094 if (is_ptr) {7951 if (capture_is_ref) {
8095 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});7952 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
8096 }7953 }
8097 payload_sub_scope = &case_scope.base;7954 payload_sub_scope = &case_scope.base;
...@@ -8111,7 +7968,7 @@ fn switchExpr(...@@ -8111,7 +7968,7 @@ fn switchExpr(
8111 payload_sub_scope = &capture_val_scope.base;7968 payload_sub_scope = &capture_val_scope.base;
8112 }7969 }
81137970
8114 const tag_token = if (token_tags[ident + 1] == .comma)7971 const tag_token = if (tree.tokenTag(ident + 1) == .comma)
8115 ident + 27972 ident + 2
8116 else7973 else
8117 break :blk payload_sub_scope;7974 break :blk payload_sub_scope;
...@@ -8149,7 +8006,7 @@ fn switchExpr(...@@ -8149,7 +8006,7 @@ fn switchExpr(
8149 // items8006 // items
8150 var items_len: u32 = 0;8007 var items_len: u32 = 0;
8151 for (case.ast.values) |item_node| {8008 for (case.ast.values) |item_node| {
8152 if (node_tags[item_node] == .switch_range) continue;8009 if (tree.nodeTag(item_node) == .switch_range) continue;
8153 items_len += 1;8010 items_len += 1;
81548011
8155 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);8012 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
...@@ -8159,11 +8016,12 @@ fn switchExpr(...@@ -8159,11 +8016,12 @@ fn switchExpr(
8159 // ranges8016 // ranges
8160 var ranges_len: u32 = 0;8017 var ranges_len: u32 = 0;
8161 for (case.ast.values) |range| {8018 for (case.ast.values) |range| {
8162 if (node_tags[range] != .switch_range) continue;8019 if (tree.nodeTag(range) != .switch_range) continue;
8163 ranges_len += 1;8020 ranges_len += 1;
81648021
8165 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);8022 const first_node, const last_node = tree.nodeData(range).node_and_node;
8166 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);8023 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
8024 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
8167 try payloads.appendSlice(gpa, &[_]u32{8025 try payloads.appendSlice(gpa, &[_]u32{
8168 @intFromEnum(first), @intFromEnum(last),8026 @intFromEnum(first), @intFromEnum(last),
8169 });8027 });
...@@ -8172,7 +8030,7 @@ fn switchExpr(...@@ -8172,7 +8030,7 @@ fn switchExpr(
8172 payloads.items[header_index] = items_len;8030 payloads.items[header_index] = items_len;
8173 payloads.items[header_index + 1] = ranges_len;8031 payloads.items[header_index + 1] = ranges_len;
8174 break :blk header_index + 2;8032 break :blk header_index + 2;
8175 } else if (case_node == special_node) blk: {8033 } else if (case_node.toOptional() == special_node) blk: {
8176 payloads.items[case_table_start] = header_index;8034 payloads.items[case_table_start] = header_index;
8177 try payloads.resize(gpa, header_index + 1); // body_len8035 try payloads.resize(gpa, header_index + 1); // body_len
8178 break :blk header_index;8036 break :blk header_index;
...@@ -8285,17 +8143,15 @@ fn switchExpr(...@@ -8285,17 +8143,15 @@ fn switchExpr(
8285fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {8143fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
8286 const astgen = gz.astgen;8144 const astgen = gz.astgen;
8287 const tree = astgen.tree;8145 const tree = astgen.tree;
8288 const node_datas = tree.nodes.items(.data);
8289 const node_tags = tree.nodes.items(.tag);
82908146
8291 if (astgen.fn_block == null) {8147 if (astgen.fn_block == null) {
8292 return astgen.failNode(node, "'return' outside function scope", .{});8148 return astgen.failNode(node, "'return' outside function scope", .{});
8293 }8149 }
82948150
8295 if (gz.any_defer_node != 0) {8151 if (gz.any_defer_node.unwrap()) |any_defer_node| {
8296 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{8152 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{
8297 try astgen.errNoteNode(8153 try astgen.errNoteNode(
8298 gz.any_defer_node,8154 any_defer_node,
8299 "defer expression here",8155 "defer expression here",
8300 .{},8156 .{},
8301 ),8157 ),
...@@ -8313,8 +8169,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8313,8 +8169,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
83138169
8314 const defer_outer = &astgen.fn_block.?.base;8170 const defer_outer = &astgen.fn_block.?.base;
83158171
8316 const operand_node = node_datas[node].lhs;8172 const operand_node = tree.nodeData(node).opt_node.unwrap() orelse {
8317 if (operand_node == 0) {
8318 // Returning a void value; skip error defers.8173 // Returning a void value; skip error defers.
8319 try genDefers(gz, defer_outer, scope, .normal_only);8174 try genDefers(gz, defer_outer, scope, .normal_only);
83208175
...@@ -8323,12 +8178,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8323,12 +8178,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
83238178
8324 _ = try gz.addUnNode(.ret_node, .void_value, node);8179 _ = try gz.addUnNode(.ret_node, .void_value, node);
8325 return Zir.Inst.Ref.unreachable_value;8180 return Zir.Inst.Ref.unreachable_value;
8326 }8181 };
83278182
8328 if (node_tags[operand_node] == .error_value) {8183 if (tree.nodeTag(operand_node) == .error_value) {
8329 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic8184 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic
8330 // for detecting whether to add something to the function's inferred error set.8185 // for detecting whether to add something to the function's inferred error set.
8331 const ident_token = node_datas[operand_node].rhs;8186 const ident_token = tree.nodeMainToken(operand_node) + 2;
8332 const err_name_str_index = try astgen.identAsString(ident_token);8187 const err_name_str_index = try astgen.identAsString(ident_token);
8333 const defer_counts = countDefers(defer_outer, scope);8188 const defer_counts = countDefers(defer_outer, scope);
8334 if (!defer_counts.need_err_code) {8189 if (!defer_counts.need_err_code) {
...@@ -8459,9 +8314,8 @@ fn identifier(...@@ -8459,9 +8314,8 @@ fn identifier(
8459) InnerError!Zir.Inst.Ref {8314) InnerError!Zir.Inst.Ref {
8460 const astgen = gz.astgen;8315 const astgen = gz.astgen;
8461 const tree = astgen.tree;8316 const tree = astgen.tree;
8462 const main_tokens = tree.nodes.items(.main_token);
84638317
8464 const ident_token = main_tokens[ident];8318 const ident_token = tree.nodeMainToken(ident);
8465 const ident_name_raw = tree.tokenSlice(ident_token);8319 const ident_name_raw = tree.tokenSlice(ident_token);
8466 if (mem.eql(u8, ident_name_raw, "_")) {8320 if (mem.eql(u8, ident_name_raw, "_")) {
8467 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});8321 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
...@@ -8563,9 +8417,9 @@ fn localVarRef(...@@ -8563,9 +8417,9 @@ fn localVarRef(
8563 // Locals cannot shadow anything, so we do not need to look for ambiguous8417 // Locals cannot shadow anything, so we do not need to look for ambiguous
8564 // references in this case.8418 // references in this case.
8565 if (ri.rl == .discard and ri.ctx == .assignment) {8419 if (ri.rl == .discard and ri.ctx == .assignment) {
8566 local_val.discarded = ident_token;8420 local_val.discarded = .fromToken(ident_token);
8567 } else {8421 } else {
8568 local_val.used = ident_token;8422 local_val.used = .fromToken(ident_token);
8569 }8423 }
85708424
8571 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;8425 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
...@@ -8587,9 +8441,9 @@ fn localVarRef(...@@ -8587,9 +8441,9 @@ fn localVarRef(
8587 const local_ptr = s.cast(Scope.LocalPtr).?;8441 const local_ptr = s.cast(Scope.LocalPtr).?;
8588 if (local_ptr.name == name_str_index) {8442 if (local_ptr.name == name_str_index) {
8589 if (ri.rl == .discard and ri.ctx == .assignment) {8443 if (ri.rl == .discard and ri.ctx == .assignment) {
8590 local_ptr.discarded = ident_token;8444 local_ptr.discarded = .fromToken(ident_token);
8591 } else {8445 } else {
8592 local_ptr.used = ident_token;8446 local_ptr.used = .fromToken(ident_token);
8593 }8447 }
85948448
8595 // Can't close over a runtime variable8449 // Can't close over a runtime variable
...@@ -8802,8 +8656,7 @@ fn stringLiteral(...@@ -8802,8 +8656,7 @@ fn stringLiteral(
8802) InnerError!Zir.Inst.Ref {8656) InnerError!Zir.Inst.Ref {
8803 const astgen = gz.astgen;8657 const astgen = gz.astgen;
8804 const tree = astgen.tree;8658 const tree = astgen.tree;
8805 const main_tokens = tree.nodes.items(.main_token);8659 const str_lit_token = tree.nodeMainToken(node);
8806 const str_lit_token = main_tokens[node];
8807 const str = try astgen.strLitAsString(str_lit_token);8660 const str = try astgen.strLitAsString(str_lit_token);
8808 const result = try gz.add(.{8661 const result = try gz.add(.{
8809 .tag = .str,8662 .tag = .str,
...@@ -8835,8 +8688,7 @@ fn multilineStringLiteral(...@@ -8835,8 +8688,7 @@ fn multilineStringLiteral(
8835fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {8688fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
8836 const astgen = gz.astgen;8689 const astgen = gz.astgen;
8837 const tree = astgen.tree;8690 const tree = astgen.tree;
8838 const main_tokens = tree.nodes.items(.main_token);8691 const main_token = tree.nodeMainToken(node);
8839 const main_token = main_tokens[node];
8840 const slice = tree.tokenSlice(main_token);8692 const slice = tree.tokenSlice(main_token);
88418693
8842 switch (std.zig.parseCharLiteral(slice)) {8694 switch (std.zig.parseCharLiteral(slice)) {
...@@ -8853,8 +8705,7 @@ const Sign = enum { negative, positive };...@@ -8853,8 +8705,7 @@ const Sign = enum { negative, positive };
8853fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {8705fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
8854 const astgen = gz.astgen;8706 const astgen = gz.astgen;
8855 const tree = astgen.tree;8707 const tree = astgen.tree;
8856 const main_tokens = tree.nodes.items(.main_token);8708 const num_token = tree.nodeMainToken(node);
8857 const num_token = main_tokens[node];
8858 const bytes = tree.tokenSlice(num_token);8709 const bytes = tree.tokenSlice(num_token);
88598710
8860 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {8711 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
...@@ -8972,16 +8823,12 @@ fn asmExpr(...@@ -8972,16 +8823,12 @@ fn asmExpr(
8972) InnerError!Zir.Inst.Ref {8823) InnerError!Zir.Inst.Ref {
8973 const astgen = gz.astgen;8824 const astgen = gz.astgen;
8974 const tree = astgen.tree;8825 const tree = astgen.tree;
8975 const main_tokens = tree.nodes.items(.main_token);
8976 const node_datas = tree.nodes.items(.data);
8977 const node_tags = tree.nodes.items(.tag);
8978 const token_tags = tree.tokens.items(.tag);
89798826
8980 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };8827 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };
8981 const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) {8828 const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) {
8982 .string_literal => .{8829 .string_literal => .{
8983 .tag = .@"asm",8830 .tag = .@"asm",
8984 .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index,8831 .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index,
8985 },8832 },
8986 .multiline_string_literal => .{8833 .multiline_string_literal => .{
8987 .tag = .@"asm",8834 .tag = .@"asm",
...@@ -9016,17 +8863,17 @@ fn asmExpr(...@@ -9016,17 +8863,17 @@ fn asmExpr(
9016 var output_type_bits: u32 = 0;8863 var output_type_bits: u32 = 0;
90178864
9018 for (full.outputs, 0..) |output_node, i| {8865 for (full.outputs, 0..) |output_node, i| {
9019 const symbolic_name = main_tokens[output_node];8866 const symbolic_name = tree.nodeMainToken(output_node);
9020 const name = try astgen.identAsString(symbolic_name);8867 const name = try astgen.identAsString(symbolic_name);
9021 const constraint_token = symbolic_name + 2;8868 const constraint_token = symbolic_name + 2;
9022 const constraint = (try astgen.strLitAsString(constraint_token)).index;8869 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9023 const has_arrow = token_tags[symbolic_name + 4] == .arrow;8870 const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow;
9024 if (has_arrow) {8871 if (has_arrow) {
9025 if (output_type_bits != 0) {8872 if (output_type_bits != 0) {
9026 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});8873 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});
9027 }8874 }
9028 output_type_bits |= @as(u32, 1) << @intCast(i);8875 output_type_bits |= @as(u32, 1) << @intCast(i);
9029 const out_type_node = node_datas[output_node].lhs;8876 const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?;
9030 const out_type_inst = try typeExpr(gz, scope, out_type_node);8877 const out_type_inst = try typeExpr(gz, scope, out_type_node);
9031 outputs[i] = .{8878 outputs[i] = .{
9032 .name = name,8879 .name = name,
...@@ -9053,11 +8900,11 @@ fn asmExpr(...@@ -9053,11 +8900,11 @@ fn asmExpr(
9053 const inputs = inputs_buffer[0..full.inputs.len];8900 const inputs = inputs_buffer[0..full.inputs.len];
90548901
9055 for (full.inputs, 0..) |input_node, i| {8902 for (full.inputs, 0..) |input_node, i| {
9056 const symbolic_name = main_tokens[input_node];8903 const symbolic_name = tree.nodeMainToken(input_node);
9057 const name = try astgen.identAsString(symbolic_name);8904 const name = try astgen.identAsString(symbolic_name);
9058 const constraint_token = symbolic_name + 2;8905 const constraint_token = symbolic_name + 2;
9059 const constraint = (try astgen.strLitAsString(constraint_token)).index;8906 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9060 const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs);8907 const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]);
9061 inputs[i] = .{8908 inputs[i] = .{
9062 .name = name,8909 .name = name,
9063 .constraint = constraint,8910 .constraint = constraint,
...@@ -9078,10 +8925,10 @@ fn asmExpr(...@@ -9078,10 +8925,10 @@ fn asmExpr(
9078 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);8925 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);
9079 clobber_i += 1;8926 clobber_i += 1;
9080 tok_i += 1;8927 tok_i += 1;
9081 switch (token_tags[tok_i]) {8928 switch (tree.tokenTag(tok_i)) {
9082 .r_paren => break :clobbers,8929 .r_paren => break :clobbers,
9083 .comma => {8930 .comma => {
9084 if (token_tags[tok_i + 1] == .r_paren) {8931 if (tree.tokenTag(tok_i + 1) == .r_paren) {
9085 break :clobbers;8932 break :clobbers;
9086 } else {8933 } else {
9087 continue;8934 continue;
...@@ -9173,9 +9020,6 @@ fn ptrCast(...@@ -9173,9 +9020,6 @@ fn ptrCast(
9173) InnerError!Zir.Inst.Ref {9020) InnerError!Zir.Inst.Ref {
9174 const astgen = gz.astgen;9021 const astgen = gz.astgen;
9175 const tree = astgen.tree;9022 const tree = astgen.tree;
9176 const main_tokens = tree.nodes.items(.main_token);
9177 const node_datas = tree.nodes.items(.data);
9178 const node_tags = tree.nodes.items(.tag);
91799023
9180 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;9024 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
9181 var flags: Zir.Inst.FullPtrCastFlags = .{};9025 var flags: Zir.Inst.FullPtrCastFlags = .{};
...@@ -9184,23 +9028,26 @@ fn ptrCast(...@@ -9184,23 +9028,26 @@ fn ptrCast(
9184 // to handle `builtin_call_two`.9028 // to handle `builtin_call_two`.
9185 var node = root_node;9029 var node = root_node;
9186 while (true) {9030 while (true) {
9187 switch (node_tags[node]) {9031 switch (tree.nodeTag(node)) {
9188 .builtin_call_two, .builtin_call_two_comma => {},9032 .builtin_call_two, .builtin_call_two_comma => {},
9189 .grouped_expression => {9033 .grouped_expression => {
9190 // Handle the chaining even with redundant parentheses9034 // Handle the chaining even with redundant parentheses
9191 node = node_datas[node].lhs;9035 node = tree.nodeData(node).node_and_token[0];
9192 continue;9036 continue;
9193 },9037 },
9194 else => break,9038 else => break,
9195 }9039 }
91969040
9197 if (node_datas[node].lhs == 0) break; // 0 args9041 var buf: [2]Ast.Node.Index = undefined;
9042 const args = tree.builtinCallParams(&buf, node).?;
9043 std.debug.assert(args.len <= 2);
9044
9045 if (args.len == 0) break; // 0 args
91989046
9199 const builtin_token = main_tokens[node];9047 const builtin_token = tree.nodeMainToken(node);
9200 const builtin_name = tree.tokenSlice(builtin_token);9048 const builtin_name = tree.tokenSlice(builtin_token);
9201 const info = BuiltinFn.list.get(builtin_name) orelse break;9049 const info = BuiltinFn.list.get(builtin_name) orelse break;
9202 if (node_datas[node].rhs == 0) {9050 if (args.len == 1) {
9203 // 1 arg
9204 if (info.param_count != 1) break;9051 if (info.param_count != 1) break;
92059052
9206 switch (info.tag) {9053 switch (info.tag) {
...@@ -9218,9 +9065,9 @@ fn ptrCast(...@@ -9218,9 +9065,9 @@ fn ptrCast(
9218 },9065 },
9219 }9066 }
92209067
9221 node = node_datas[node].lhs;9068 node = args[0];
9222 } else {9069 } else {
9223 // 2 args9070 std.debug.assert(args.len == 2);
9224 if (info.param_count != 2) break;9071 if (info.param_count != 2) break;
92259072
9226 switch (info.tag) {9073 switch (info.tag) {
...@@ -9231,8 +9078,8 @@ fn ptrCast(...@@ -9231,8 +9078,8 @@ fn ptrCast(
9231 const flags_int: FlagsInt = @bitCast(flags);9078 const flags_int: FlagsInt = @bitCast(flags);
9232 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);9079 const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
9233 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");9080 const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
9234 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs, .field_name);9081 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, args[0], .field_name);
9235 const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);9082 const field_ptr = try expr(gz, scope, .{ .rl = .none }, args[1]);
9236 try emitDbgStmt(gz, cursor);9083 try emitDbgStmt(gz, cursor);
9237 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{9084 const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
9238 .src_node = gz.nodeIndexToRelative(node),9085 .src_node = gz.nodeIndexToRelative(node),
...@@ -9397,9 +9244,8 @@ fn builtinCall(...@@ -9397,9 +9244,8 @@ fn builtinCall(
9397) InnerError!Zir.Inst.Ref {9244) InnerError!Zir.Inst.Ref {
9398 const astgen = gz.astgen;9245 const astgen = gz.astgen;
9399 const tree = astgen.tree;9246 const tree = astgen.tree;
9400 const main_tokens = tree.nodes.items(.main_token);
94019247
9402 const builtin_token = main_tokens[node];9248 const builtin_token = tree.nodeMainToken(node);
9403 const builtin_name = tree.tokenSlice(builtin_token);9249 const builtin_name = tree.tokenSlice(builtin_token);
94049250
9405 // We handle the different builtins manually because they have different semantics depending9251 // We handle the different builtins manually because they have different semantics depending
...@@ -9440,14 +9286,13 @@ fn builtinCall(...@@ -9440,14 +9286,13 @@ fn builtinCall(
9440 return rvalue(gz, ri, .void_value, node);9286 return rvalue(gz, ri, .void_value, node);
9441 },9287 },
9442 .import => {9288 .import => {
9443 const node_tags = tree.nodes.items(.tag);
9444 const operand_node = params[0];9289 const operand_node = params[0];
94459290
9446 if (node_tags[operand_node] != .string_literal) {9291 if (tree.nodeTag(operand_node) != .string_literal) {
9447 // Spec reference: https://github.com/ziglang/zig/issues/22069292 // Spec reference: https://github.com/ziglang/zig/issues/2206
9448 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});9293 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
9449 }9294 }
9450 const str_lit_token = main_tokens[operand_node];9295 const str_lit_token = tree.nodeMainToken(operand_node);
9451 const str = try astgen.strLitAsString(str_lit_token);9296 const str = try astgen.strLitAsString(str_lit_token);
9452 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];9297 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];
9453 if (mem.indexOfScalar(u8, str_slice, 0) != null) {9298 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
...@@ -9558,8 +9403,7 @@ fn builtinCall(...@@ -9558,8 +9403,7 @@ fn builtinCall(
9558 std.mem.asBytes(&astgen.source_column),9403 std.mem.asBytes(&astgen.source_column),
9559 );9404 );
95609405
9561 const token_starts = tree.tokens.items(.start);9406 const node_start = tree.tokenStart(tree.firstToken(node));
9562 const node_start = token_starts[tree.firstToken(node)];
9563 astgen.advanceSourceCursor(node_start);9407 astgen.advanceSourceCursor(node_start);
9564 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{9408 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{
9565 .node = gz.nodeIndexToRelative(node),9409 .node = gz.nodeIndexToRelative(node),
...@@ -9839,7 +9683,7 @@ fn builtinCall(...@@ -9839,7 +9683,7 @@ fn builtinCall(
9839 .callee = callee,9683 .callee = callee,
9840 .args = args,9684 .args = args,
9841 .flags = .{9685 .flags = .{
9842 .is_nosuspend = gz.nosuspend_node != 0,9686 .is_nosuspend = gz.nosuspend_node != .none,
9843 .ensure_result_used = false,9687 .ensure_result_used = false,
9844 },9688 },
9845 });9689 });
...@@ -10064,13 +9908,11 @@ fn negation(...@@ -10064,13 +9908,11 @@ fn negation(
10064) InnerError!Zir.Inst.Ref {9908) InnerError!Zir.Inst.Ref {
10065 const astgen = gz.astgen;9909 const astgen = gz.astgen;
10066 const tree = astgen.tree;9910 const tree = astgen.tree;
10067 const node_tags = tree.nodes.items(.tag);
10068 const node_datas = tree.nodes.items(.data);
100699911
10070 // Check for float literal as the sub-expression because we want to preserve9912 // Check for float literal as the sub-expression because we want to preserve
10071 // its negativity rather than having it go through comptime subtraction.9913 // its negativity rather than having it go through comptime subtraction.
10072 const operand_node = node_datas[node].lhs;9914 const operand_node = tree.nodeData(node).node;
10073 if (node_tags[operand_node] == .number_literal) {9915 if (tree.nodeTag(operand_node) == .number_literal) {
10074 return numberLiteral(gz, ri, operand_node, node, .negative);9916 return numberLiteral(gz, ri, operand_node, node, .negative);
10075 }9917 }
100769918
...@@ -10186,7 +10028,7 @@ fn shiftOp(...@@ -10186,7 +10028,7 @@ fn shiftOp(
10186) InnerError!Zir.Inst.Ref {10028) InnerError!Zir.Inst.Ref {
10187 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);10029 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
1018810030
10189 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {10031 const cursor = switch (gz.astgen.tree.nodeTag(node)) {
10190 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),10032 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
10191 else => undefined,10033 else => undefined,
10192 };10034 };
...@@ -10194,7 +10036,7 @@ fn shiftOp(...@@ -10194,7 +10036,7 @@ fn shiftOp(
10194 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);10036 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
10195 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);10037 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
1019610038
10197 switch (gz.astgen.tree.nodes.items(.tag)[node]) {10039 switch (gz.astgen.tree.nodeTag(node)) {
10198 .shl, .shr => try emitDbgStmt(gz, cursor),10040 .shl, .shr => try emitDbgStmt(gz, cursor),
10199 else => undefined,10041 else => undefined,
10200 }10042 }
...@@ -10270,14 +10112,14 @@ fn callExpr(...@@ -10270,14 +10112,14 @@ fn callExpr(
10270 if (call.async_token != null) {10112 if (call.async_token != null) {
10271 break :blk .async_kw;10113 break :blk .async_kw;
10272 }10114 }
10273 if (gz.nosuspend_node != 0) {10115 if (gz.nosuspend_node != .none) {
10274 break :blk .no_async;10116 break :blk .no_async;
10275 }10117 }
10276 break :blk .auto;10118 break :blk .auto;
10277 };10119 };
1027810120
10279 {10121 {
10280 astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]);10122 astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen));
10281 const line = astgen.source_line - gz.decl_line;10123 const line = astgen.source_line - gz.decl_line;
10282 const column = astgen.source_column;10124 const column = astgen.source_column;
10283 // Sema expects a dbg_stmt immediately before call,10125 // Sema expects a dbg_stmt immediately before call,
...@@ -10288,7 +10130,6 @@ fn callExpr(...@@ -10288,7 +10130,6 @@ fn callExpr(
10288 .direct => |obj| assert(obj != .none),10130 .direct => |obj| assert(obj != .none),
10289 .field => |field| assert(field.obj_ptr != .none),10131 .field => |field| assert(field.obj_ptr != .none),
10290 }10132 }
10291 assert(node != 0);
1029210133
10293 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);10134 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
10294 const call_inst = call_index.toRef();10135 const call_inst = call_index.toRef();
...@@ -10399,14 +10240,10 @@ fn calleeExpr(...@@ -10399,14 +10240,10 @@ fn calleeExpr(
10399 const astgen = gz.astgen;10240 const astgen = gz.astgen;
10400 const tree = astgen.tree;10241 const tree = astgen.tree;
1040110242
10402 const tag = tree.nodes.items(.tag)[node];10243 const tag = tree.nodeTag(node);
10403 switch (tag) {10244 switch (tag) {
10404 .field_access => {10245 .field_access => {
10405 const main_tokens = tree.nodes.items(.main_token);10246 const object_node, const field_ident = tree.nodeData(node).node_and_token;
10406 const node_datas = tree.nodes.items(.data);
10407 const object_node = node_datas[node].lhs;
10408 const dot_token = main_tokens[node];
10409 const field_ident = dot_token + 1;
10410 const str_index = try astgen.identAsString(field_ident);10247 const str_index = try astgen.identAsString(field_ident);
10411 // Capture the object by reference so we can promote it to an10248 // Capture the object by reference so we can promote it to an
10412 // address in Sema if needed.10249 // address in Sema if needed.
...@@ -10431,7 +10268,7 @@ fn calleeExpr(...@@ -10431,7 +10268,7 @@ fn calleeExpr(
10431 // Decl literal call syntax, e.g.10268 // Decl literal call syntax, e.g.
10432 // `const foo: T = .init();`10269 // `const foo: T = .init();`
10433 // Look up `init` in `T`, but don't try and coerce it.10270 // Look up `init` in `T`, but don't try and coerce it.
10434 const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]);10271 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
10435 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{10272 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{
10436 .lhs = res_ty,10273 .lhs = res_ty,
10437 .field_name_start = str_index,10274 .field_name_start = str_index,
...@@ -10503,12 +10340,9 @@ comptime {...@@ -10503,12 +10340,9 @@ comptime {
10503}10340}
1050410341
10505fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {10342fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10506 const node_tags = tree.nodes.items(.tag);10343 switch (tree.nodeTag(node)) {
10507 const main_tokens = tree.nodes.items(.main_token);
10508
10509 switch (node_tags[node]) {
10510 .number_literal => {10344 .number_literal => {
10511 const ident = main_tokens[node];10345 const ident = tree.nodeMainToken(node);
10512 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {10346 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {
10513 .int => |number| switch (number) {10347 .int => |number| switch (number) {
10514 0 => true,10348 0 => true,
...@@ -10522,12 +10356,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {...@@ -10522,12 +10356,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10522}10356}
1052310357
10524fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {10358fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {
10525 const node_tags = tree.nodes.items(.tag);
10526 const node_datas = tree.nodes.items(.data);
10527
10528 var node = start_node;10359 var node = start_node;
10529 while (true) {10360 while (true) {
10530 switch (node_tags[node]) {10361 switch (tree.nodeTag(node)) {
10531 // These don't have the opportunity to call any runtime functions.10362 // These don't have the opportunity to call any runtime functions.
10532 .error_value,10363 .error_value,
10533 .identifier,10364 .identifier,
...@@ -10535,11 +10366,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool...@@ -10535,11 +10366,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
10535 => return false,10366 => return false,
1053610367
10537 // Forward the question to the LHS sub-expression.10368 // Forward the question to the LHS sub-expression.
10538 .grouped_expression,
10539 .@"try",10369 .@"try",
10540 .@"nosuspend",10370 .@"nosuspend",
10371 => node = tree.nodeData(node).node,
10372 .grouped_expression,
10541 .unwrap_optional,10373 .unwrap_optional,
10542 => node = node_datas[node].lhs,10374 => node = tree.nodeData(node).node_and_token[0],
1054310375
10544 // Anything that does not eval to an error is guaranteed to pop any10376 // Anything that does not eval to an error is guaranteed to pop any
10545 // additions to the error trace, so it effectively does not append.10377 // additions to the error trace, so it effectively does not append.
...@@ -10549,14 +10381,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool...@@ -10549,14 +10381,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
10549}10381}
1055010382
10551fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {10383fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
10552 const node_tags = tree.nodes.items(.tag);
10553 const node_datas = tree.nodes.items(.data);
10554 const main_tokens = tree.nodes.items(.main_token);
10555 const token_tags = tree.tokens.items(.tag);
10556
10557 var node = start_node;10384 var node = start_node;
10558 while (true) {10385 while (true) {
10559 switch (node_tags[node]) {10386 switch (tree.nodeTag(node)) {
10560 .root,10387 .root,
10561 .@"usingnamespace",10388 .@"usingnamespace",
10562 .test_decl,10389 .test_decl,
...@@ -10719,13 +10546,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10719,13 +10546,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10719 => return .never,10546 => return .never,
1072010547
10721 // Forward the question to the LHS sub-expression.10548 // Forward the question to the LHS sub-expression.
10722 .grouped_expression,
10723 .@"try",10549 .@"try",
10724 .@"await",10550 .@"await",
10725 .@"comptime",10551 .@"comptime",
10726 .@"nosuspend",10552 .@"nosuspend",
10553 => node = tree.nodeData(node).node,
10554 .grouped_expression,
10727 .unwrap_optional,10555 .unwrap_optional,
10728 => node = node_datas[node].lhs,10556 => node = tree.nodeData(node).node_and_token[0],
1072910557
10730 // LHS sub-expression may still be an error under the outer optional or error union10558 // LHS sub-expression may still be an error under the outer optional or error union
10731 .@"catch",10559 .@"catch",
...@@ -10737,8 +10565,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10737,8 +10565,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10737 .block,10565 .block,
10738 .block_semicolon,10566 .block_semicolon,
10739 => {10567 => {
10740 const lbrace = main_tokens[node];10568 const lbrace = tree.nodeMainToken(node);
10741 if (token_tags[lbrace - 1] == .colon) {10569 if (tree.tokenTag(lbrace - 1) == .colon) {
10742 // Labeled blocks may need a memory location to forward10570 // Labeled blocks may need a memory location to forward
10743 // to their break statements.10571 // to their break statements.
10744 return .maybe;10572 return .maybe;
...@@ -10752,7 +10580,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10752,7 +10580,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10752 .builtin_call_two,10580 .builtin_call_two,
10753 .builtin_call_two_comma,10581 .builtin_call_two_comma,
10754 => {10582 => {
10755 const builtin_token = main_tokens[node];10583 const builtin_token = tree.nodeMainToken(node);
10756 const builtin_name = tree.tokenSlice(builtin_token);10584 const builtin_name = tree.tokenSlice(builtin_token);
10757 // If the builtin is an invalid name, we don't cause an error here; instead10585 // If the builtin is an invalid name, we don't cause an error here; instead
10758 // let it pass, and the error will be "invalid builtin function" later.10586 // let it pass, and the error will be "invalid builtin function" later.
...@@ -10766,12 +10594,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10766,12 +10594,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10766/// Returns `true` if it is known the type expression has more than one possible value;10594/// Returns `true` if it is known the type expression has more than one possible value;
10767/// `false` otherwise.10595/// `false` otherwise.
10768fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {10596fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
10769 const node_tags = tree.nodes.items(.tag);
10770 const node_datas = tree.nodes.items(.data);
10771
10772 var node = start_node;10597 var node = start_node;
10773 while (true) {10598 while (true) {
10774 switch (node_tags[node]) {10599 switch (tree.nodeTag(node)) {
10775 .root,10600 .root,
10776 .@"usingnamespace",10601 .@"usingnamespace",
10777 .test_decl,10602 .test_decl,
...@@ -10934,13 +10759,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10934,13 +10759,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10934 => return false,10759 => return false,
1093510760
10936 // Forward the question to the LHS sub-expression.10761 // Forward the question to the LHS sub-expression.
10937 .grouped_expression,
10938 .@"try",10762 .@"try",
10939 .@"await",10763 .@"await",
10940 .@"comptime",10764 .@"comptime",
10941 .@"nosuspend",10765 .@"nosuspend",
10766 => node = tree.nodeData(node).node,
10767 .grouped_expression,
10942 .unwrap_optional,10768 .unwrap_optional,
10943 => node = node_datas[node].lhs,10769 => node = tree.nodeData(node).node_and_token[0],
1094410770
10945 .ptr_type_aligned,10771 .ptr_type_aligned,
10946 .ptr_type_sentinel,10772 .ptr_type_sentinel,
...@@ -10952,8 +10778,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10952,8 +10778,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10952 => return true,10778 => return true,
1095310779
10954 .identifier => {10780 .identifier => {
10955 const main_tokens = tree.nodes.items(.main_token);10781 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
10956 const ident_bytes = tree.tokenSlice(main_tokens[node]);
10957 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {10782 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
10958 .anyerror_type,10783 .anyerror_type,
10959 .anyframe_type,10784 .anyframe_type,
...@@ -11013,12 +10838,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -11013,12 +10838,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
11013/// Returns `true` if it is known the expression is a type that cannot be used at runtime;10838/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
11014/// `false` otherwise.10839/// `false` otherwise.
11015fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {10840fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
11016 const node_tags = tree.nodes.items(.tag);
11017 const node_datas = tree.nodes.items(.data);
11018
11019 var node = start_node;10841 var node = start_node;
11020 while (true) {10842 while (true) {
11021 switch (node_tags[node]) {10843 switch (tree.nodeTag(node)) {
11022 .root,10844 .root,
11023 .@"usingnamespace",10845 .@"usingnamespace",
11024 .test_decl,10846 .test_decl,
...@@ -11190,17 +11012,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11190,17 +11012,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
11190 => return true,11012 => return true,
1119111013
11192 // Forward the question to the LHS sub-expression.11014 // Forward the question to the LHS sub-expression.
11193 .grouped_expression,
11194 .@"try",11015 .@"try",
11195 .@"await",11016 .@"await",
11196 .@"comptime",11017 .@"comptime",
11197 .@"nosuspend",11018 .@"nosuspend",
11019 => node = tree.nodeData(node).node,
11020 .grouped_expression,
11198 .unwrap_optional,11021 .unwrap_optional,
11199 => node = node_datas[node].lhs,11022 => node = tree.nodeData(node).node_and_token[0],
1120011023
11201 .identifier => {11024 .identifier => {
11202 const main_tokens = tree.nodes.items(.main_token);11025 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
11203 const ident_bytes = tree.tokenSlice(main_tokens[node]);
11204 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {11026 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
11205 .anyerror_type,11027 .anyerror_type,
11206 .anyframe_type,11028 .anyframe_type,
...@@ -11259,8 +11081,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11259,8 +11081,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1125911081
11260/// Returns `true` if the node uses `gz.anon_name_strategy`.11082/// Returns `true` if the node uses `gz.anon_name_strategy`.
11261fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {11083fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11262 const node_tags = tree.nodes.items(.tag);11084 switch (tree.nodeTag(node)) {
11263 switch (node_tags[node]) {
11264 .container_decl,11085 .container_decl,
11265 .container_decl_trailing,11086 .container_decl_trailing,
11266 .container_decl_two,11087 .container_decl_two,
...@@ -11275,7 +11096,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {...@@ -11275,7 +11096,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11275 .tagged_union_enum_tag_trailing,11096 .tagged_union_enum_tag_trailing,
11276 => return true,11097 => return true,
11277 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {11098 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {
11278 const builtin_token = tree.nodes.items(.main_token)[node];11099 const builtin_token = tree.nodeMainToken(node);
11279 const builtin_name = tree.tokenSlice(builtin_token);11100 const builtin_name = tree.tokenSlice(builtin_token);
11280 return std.mem.eql(u8, builtin_name, "@Type");11101 return std.mem.eql(u8, builtin_name, "@Type");
11281 },11102 },
...@@ -11508,8 +11329,7 @@ fn rvalueInner(...@@ -11508,8 +11329,7 @@ fn rvalueInner(
11508/// See also `appendIdentStr` and `parseStrLit`.11329/// See also `appendIdentStr` and `parseStrLit`.
11509fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {11330fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {
11510 const tree = astgen.tree;11331 const tree = astgen.tree;
11511 const token_tags = tree.tokens.items(.tag);11332 assert(tree.tokenTag(token) == .identifier);
11512 assert(token_tags[token] == .identifier);
11513 const ident_name = tree.tokenSlice(token);11333 const ident_name = tree.tokenSlice(token);
11514 if (!mem.startsWith(u8, ident_name, "@")) {11334 if (!mem.startsWith(u8, ident_name, "@")) {
11515 return ident_name;11335 return ident_name;
...@@ -11535,8 +11355,7 @@ fn appendIdentStr(...@@ -11535,8 +11355,7 @@ fn appendIdentStr(
11535 buf: *ArrayListUnmanaged(u8),11355 buf: *ArrayListUnmanaged(u8),
11536) InnerError!void {11356) InnerError!void {
11537 const tree = astgen.tree;11357 const tree = astgen.tree;
11538 const token_tags = tree.tokens.items(.tag);11358 assert(tree.tokenTag(token) == .identifier);
11539 assert(token_tags[token] == .identifier);
11540 const ident_name = tree.tokenSlice(token);11359 const ident_name = tree.tokenSlice(token);
11541 if (!mem.startsWith(u8, ident_name, "@")) {11360 if (!mem.startsWith(u8, ident_name, "@")) {
11542 return buf.appendSlice(astgen.gpa, ident_name);11361 return buf.appendSlice(astgen.gpa, ident_name);
...@@ -11625,8 +11444,8 @@ fn appendErrorNodeNotes(...@@ -11625,8 +11444,8 @@ fn appendErrorNodeNotes(
11625 } else 0;11444 } else 0;
11626 try astgen.compile_errors.append(astgen.gpa, .{11445 try astgen.compile_errors.append(astgen.gpa, .{
11627 .msg = msg,11446 .msg = msg,
11628 .node = node,11447 .node = node.toOptional(),
11629 .token = 0,11448 .token = .none,
11630 .byte_offset = 0,11449 .byte_offset = 0,
11631 .notes = notes_index,11450 .notes = notes_index,
11632 });11451 });
...@@ -11717,8 +11536,8 @@ fn appendErrorTokNotesOff(...@@ -11717,8 +11536,8 @@ fn appendErrorTokNotesOff(
11717 } else 0;11536 } else 0;
11718 try astgen.compile_errors.append(gpa, .{11537 try astgen.compile_errors.append(gpa, .{
11719 .msg = msg,11538 .msg = msg,
11720 .node = 0,11539 .node = .none,
11721 .token = token,11540 .token = .fromToken(token),
11722 .byte_offset = byte_offset,11541 .byte_offset = byte_offset,
11723 .notes = notes_index,11542 .notes = notes_index,
11724 });11543 });
...@@ -11746,8 +11565,8 @@ fn errNoteTokOff(...@@ -11746,8 +11565,8 @@ fn errNoteTokOff(
11746 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);11565 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
11747 return astgen.addExtra(Zir.Inst.CompileErrors.Item{11566 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
11748 .msg = msg,11567 .msg = msg,
11749 .node = 0,11568 .node = .none,
11750 .token = token,11569 .token = .fromToken(token),
11751 .byte_offset = byte_offset,11570 .byte_offset = byte_offset,
11752 .notes = 0,11571 .notes = 0,
11753 });11572 });
...@@ -11765,8 +11584,8 @@ fn errNoteNode(...@@ -11765,8 +11584,8 @@ fn errNoteNode(
11765 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);11584 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
11766 return astgen.addExtra(Zir.Inst.CompileErrors.Item{11585 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
11767 .msg = msg,11586 .msg = msg,
11768 .node = node,11587 .node = node.toOptional(),
11769 .token = 0,11588 .token = .none,
11770 .byte_offset = 0,11589 .byte_offset = 0,
11771 .notes = 0,11590 .notes = 0,
11772 });11591 });
...@@ -11832,10 +11651,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {...@@ -11832,10 +11651,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1183211651
11833fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {11652fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
11834 const tree = astgen.tree;11653 const tree = astgen.tree;
11835 const node_datas = tree.nodes.items(.data);
1183611654
11837 const start = node_datas[node].lhs;11655 const start, const end = tree.nodeData(node).token_and_token;
11838 const end = node_datas[node].rhs;
1183911656
11840 const gpa = astgen.gpa;11657 const gpa = astgen.gpa;
11841 const string_bytes = &astgen.string_bytes;11658 const string_bytes = &astgen.string_bytes;
...@@ -11930,11 +11747,11 @@ const Scope = struct {...@@ -11930,11 +11747,11 @@ const Scope = struct {
11930 /// Source location of the corresponding variable declaration.11747 /// Source location of the corresponding variable declaration.
11931 token_src: Ast.TokenIndex,11748 token_src: Ast.TokenIndex,
11932 /// Track the first identifier where it is referenced.11749 /// Track the first identifier where it is referenced.
11933 /// 0 means never referenced.11750 /// .none means never referenced.
11934 used: Ast.TokenIndex = 0,11751 used: Ast.OptionalTokenIndex = .none,
11935 /// Track the identifier where it is discarded, like this `_ = foo;`.11752 /// Track the identifier where it is discarded, like this `_ = foo;`.
11936 /// 0 means never discarded.11753 /// .none means never discarded.
11937 discarded: Ast.TokenIndex = 0,11754 discarded: Ast.OptionalTokenIndex = .none,
11938 is_used_or_discarded: ?*bool = null,11755 is_used_or_discarded: ?*bool = null,
11939 /// String table index.11756 /// String table index.
11940 name: Zir.NullTerminatedString,11757 name: Zir.NullTerminatedString,
...@@ -11954,11 +11771,11 @@ const Scope = struct {...@@ -11954,11 +11771,11 @@ const Scope = struct {
11954 /// Source location of the corresponding variable declaration.11771 /// Source location of the corresponding variable declaration.
11955 token_src: Ast.TokenIndex,11772 token_src: Ast.TokenIndex,
11956 /// Track the first identifier where it is referenced.11773 /// Track the first identifier where it is referenced.
11957 /// 0 means never referenced.11774 /// .none means never referenced.
11958 used: Ast.TokenIndex = 0,11775 used: Ast.OptionalTokenIndex = .none,
11959 /// Track the identifier where it is discarded, like this `_ = foo;`.11776 /// Track the identifier where it is discarded, like this `_ = foo;`.
11960 /// 0 means never discarded.11777 /// .none means never discarded.
11961 discarded: Ast.TokenIndex = 0,11778 discarded: Ast.OptionalTokenIndex = .none,
11962 /// Whether this value is used as an lvalue after initialization.11779 /// Whether this value is used as an lvalue after initialization.
11963 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.11780 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.
11964 used_as_lvalue: bool = false,11781 used_as_lvalue: bool = false,
...@@ -12053,12 +11870,12 @@ const GenZir = struct {...@@ -12053,12 +11870,12 @@ const GenZir = struct {
12053 break_result_info: AstGen.ResultInfo = undefined,11870 break_result_info: AstGen.ResultInfo = undefined,
12054 continue_result_info: AstGen.ResultInfo = undefined,11871 continue_result_info: AstGen.ResultInfo = undefined,
1205511872
12056 suspend_node: Ast.Node.Index = 0,11873 suspend_node: Ast.Node.OptionalIndex = .none,
12057 nosuspend_node: Ast.Node.Index = 0,11874 nosuspend_node: Ast.Node.OptionalIndex = .none,
12058 /// Set if this GenZir is a defer.11875 /// Set if this GenZir is a defer.
12059 cur_defer_node: Ast.Node.Index = 0,11876 cur_defer_node: Ast.Node.OptionalIndex = .none,
12060 // Set if this GenZir is a defer or it is inside a defer.11877 // Set if this GenZir is a defer or it is inside a defer.
12061 any_defer_node: Ast.Node.Index = 0,11878 any_defer_node: Ast.Node.OptionalIndex = .none,
1206211879
12063 const unstacked_top = std.math.maxInt(usize);11880 const unstacked_top = std.math.maxInt(usize);
12064 /// Call unstack before adding any new instructions to containing GenZir.11881 /// Call unstack before adding any new instructions to containing GenZir.
...@@ -12139,12 +11956,12 @@ const GenZir = struct {...@@ -12139,12 +11956,12 @@ const GenZir = struct {
12139 return false;11956 return false;
12140 }11957 }
1214111958
12142 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 {11959 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset {
12143 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index));11960 return gz.decl_node_index.toOffset(node_index);
12144 }11961 }
1214511962
12146 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 {11963 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset {
12147 return token - gz.srcToken();11964 return .init(gz.srcToken(), token);
12148 }11965 }
1214911966
12150 fn srcToken(gz: GenZir) Ast.TokenIndex {11967 fn srcToken(gz: GenZir) Ast.TokenIndex {
...@@ -12297,7 +12114,7 @@ const GenZir = struct {...@@ -12297,7 +12114,7 @@ const GenZir = struct {
12297 proto_hash: std.zig.SrcHash,12114 proto_hash: std.zig.SrcHash,
12298 },12115 },
12299 ) !Zir.Inst.Ref {12116 ) !Zir.Inst.Ref {
12300 assert(args.src_node != 0);12117 assert(args.src_node != .root);
12301 const astgen = gz.astgen;12118 const astgen = gz.astgen;
12302 const gpa = astgen.gpa;12119 const gpa = astgen.gpa;
12303 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;12120 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
...@@ -12329,13 +12146,13 @@ const GenZir = struct {...@@ -12329,13 +12146,13 @@ const GenZir = struct {
12329 var src_locs_and_hash_buffer: [7]u32 = undefined;12146 var src_locs_and_hash_buffer: [7]u32 = undefined;
12330 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {12147 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {
12331 const tree = astgen.tree;12148 const tree = astgen.tree;
12332 const node_tags = tree.nodes.items(.tag);
12333 const node_datas = tree.nodes.items(.data);
12334 const token_starts = tree.tokens.items(.start);
12335 const fn_decl = args.src_node;12149 const fn_decl = args.src_node;
12336 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);12150 const block = switch (tree.nodeTag(fn_decl)) {
12337 const block = node_datas[fn_decl].rhs;12151 .fn_decl => tree.nodeData(fn_decl).node_and_node[1],
12338 const rbrace_start = token_starts[tree.lastToken(block)];12152 .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1],
12153 else => unreachable,
12154 };
12155 const rbrace_start = tree.tokenStart(tree.lastToken(block));
12339 astgen.advanceSourceCursor(rbrace_start);12156 astgen.advanceSourceCursor(rbrace_start);
12340 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);12157 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);
12341 const rbrace_column: u32 = @intCast(astgen.source_column);12158 const rbrace_column: u32 = @intCast(astgen.source_column);
...@@ -12742,7 +12559,7 @@ const GenZir = struct {...@@ -12742,7 +12559,7 @@ const GenZir = struct {
12742 .data = .{ .extended = .{12559 .data = .{ .extended = .{
12743 .opcode = opcode,12560 .opcode = opcode,
12744 .small = small,12561 .small = small,
12745 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),12562 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
12746 } },12563 } },
12747 });12564 });
12748 gz.instructions.appendAssumeCapacity(new_index);12565 gz.instructions.appendAssumeCapacity(new_index);
...@@ -12931,9 +12748,9 @@ const GenZir = struct {...@@ -12931,9 +12748,9 @@ const GenZir = struct {
12931 .operand = operand,12748 .operand = operand,
12932 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{12749 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{
12933 .operand_src_node = if (operand_src_node) |src_node|12750 .operand_src_node = if (operand_src_node) |src_node|
12934 gz.nodeIndexToRelative(src_node)12751 gz.nodeIndexToRelative(src_node).toOptional()
12935 else12752 else
12936 Zir.Inst.Break.no_src_node,12753 .none,
12937 .block_inst = block_inst,12754 .block_inst = block_inst,
12938 }),12755 }),
12939 } },12756 } },
...@@ -13022,7 +12839,7 @@ const GenZir = struct {...@@ -13022,7 +12839,7 @@ const GenZir = struct {
13022 .data = .{ .extended = .{12839 .data = .{ .extended = .{
13023 .opcode = opcode,12840 .opcode = opcode,
13024 .small = undefined,12841 .small = undefined,
13025 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),12842 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
13026 } },12843 } },
13027 });12844 });
13028 }12845 }
...@@ -13202,8 +13019,8 @@ const GenZir = struct {...@@ -13202,8 +13019,8 @@ const GenZir = struct {
13202 const astgen = gz.astgen;13019 const astgen = gz.astgen;
13203 const gpa = astgen.gpa;13020 const gpa = astgen.gpa;
1320413021
13205 // Node 0 is valid for the root `struct_decl` of a file!13022 // Node .root is valid for the root `struct_decl` of a file!
13206 assert(args.src_node != 0 or gz.parent.tag == .top);13023 assert(args.src_node != .root or gz.parent.tag == .top);
1320713024
13208 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13025 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1320913026
...@@ -13263,7 +13080,7 @@ const GenZir = struct {...@@ -13263,7 +13080,7 @@ const GenZir = struct {
13263 const astgen = gz.astgen;13080 const astgen = gz.astgen;
13264 const gpa = astgen.gpa;13081 const gpa = astgen.gpa;
1326513082
13266 assert(args.src_node != 0);13083 assert(args.src_node != .root);
1326713084
13268 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13085 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1326913086
...@@ -13325,7 +13142,7 @@ const GenZir = struct {...@@ -13325,7 +13142,7 @@ const GenZir = struct {
13325 const astgen = gz.astgen;13142 const astgen = gz.astgen;
13326 const gpa = astgen.gpa;13143 const gpa = astgen.gpa;
1332713144
13328 assert(args.src_node != 0);13145 assert(args.src_node != .root);
1332913146
13330 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13147 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1333113148
...@@ -13380,7 +13197,7 @@ const GenZir = struct {...@@ -13380,7 +13197,7 @@ const GenZir = struct {
13380 const astgen = gz.astgen;13197 const astgen = gz.astgen;
13381 const gpa = astgen.gpa;13198 const gpa = astgen.gpa;
1338213199
13383 assert(args.src_node != 0);13200 assert(args.src_node != .root);
1338413201
13385 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);13202 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);
13386 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{13203 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
...@@ -13574,9 +13391,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo...@@ -13574,9 +13391,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
13574 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };13391 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1357513392
13576 const tree = gz.astgen.tree;13393 const tree = gz.astgen.tree;
13577 const token_starts = tree.tokens.items(.start);13394 const node_start = tree.tokenStart(tree.nodeMainToken(node));
13578 const main_tokens = tree.nodes.items(.main_token);
13579 const node_start = token_starts[main_tokens[node]];
13580 gz.astgen.advanceSourceCursor(node_start);13395 gz.astgen.advanceSourceCursor(node_start);
1358113396
13582 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };13397 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
...@@ -13585,8 +13400,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo...@@ -13585,8 +13400,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
13585/// Advances the source cursor to the beginning of `node`.13400/// Advances the source cursor to the beginning of `node`.
13586fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {13401fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
13587 const tree = astgen.tree;13402 const tree = astgen.tree;
13588 const token_starts = tree.tokens.items(.start);13403 const node_start = tree.tokenStart(tree.firstToken(node));
13589 const node_start = token_starts[tree.firstToken(node)];
13590 astgen.advanceSourceCursor(node_start);13404 astgen.advanceSourceCursor(node_start);
13591}13405}
1359213406
...@@ -13641,9 +13455,6 @@ fn scanContainer(...@@ -13641,9 +13455,6 @@ fn scanContainer(
13641) !u32 {13455) !u32 {
13642 const gpa = astgen.gpa;13456 const gpa = astgen.gpa;
13643 const tree = astgen.tree;13457 const tree = astgen.tree;
13644 const node_tags = tree.nodes.items(.tag);
13645 const main_tokens = tree.nodes.items(.main_token);
13646 const token_tags = tree.tokens.items(.tag);
1364713458
13648 var any_invalid_declarations = false;13459 var any_invalid_declarations = false;
1364913460
...@@ -13673,7 +13484,7 @@ fn scanContainer(...@@ -13673,7 +13484,7 @@ fn scanContainer(
13673 var decl_count: u32 = 0;13484 var decl_count: u32 = 0;
13674 for (members) |member_node| {13485 for (members) |member_node| {
13675 const Kind = enum { decl, field };13486 const Kind = enum { decl, field };
13676 const kind: Kind, const name_token = switch (node_tags[member_node]) {13487 const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) {
13677 .container_field_init,13488 .container_field_init,
13678 .container_field_align,13489 .container_field_align,
13679 .container_field,13490 .container_field,
...@@ -13681,7 +13492,7 @@ fn scanContainer(...@@ -13681,7 +13492,7 @@ fn scanContainer(
13681 var full = tree.fullContainerField(member_node).?;13492 var full = tree.fullContainerField(member_node).?;
13682 switch (container_kind) {13493 switch (container_kind) {
13683 .@"struct", .@"opaque" => {},13494 .@"struct", .@"opaque" => {},
13684 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes),13495 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree),
13685 }13496 }
13686 if (full.ast.tuple_like) continue;13497 if (full.ast.tuple_like) continue;
13687 break :blk .{ .field, full.ast.main_token };13498 break :blk .{ .field, full.ast.main_token };
...@@ -13693,7 +13504,7 @@ fn scanContainer(...@@ -13693,7 +13504,7 @@ fn scanContainer(
13693 .aligned_var_decl,13504 .aligned_var_decl,
13694 => blk: {13505 => blk: {
13695 decl_count += 1;13506 decl_count += 1;
13696 break :blk .{ .decl, main_tokens[member_node] + 1 };13507 break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 };
13697 },13508 },
1369813509
13699 .fn_proto_simple,13510 .fn_proto_simple,
...@@ -13703,8 +13514,8 @@ fn scanContainer(...@@ -13703,8 +13514,8 @@ fn scanContainer(
13703 .fn_decl,13514 .fn_decl,
13704 => blk: {13515 => blk: {
13705 decl_count += 1;13516 decl_count += 1;
13706 const ident = main_tokens[member_node] + 1;13517 const ident = tree.nodeMainToken(member_node) + 1;
13707 if (token_tags[ident] != .identifier) {13518 if (tree.tokenTag(ident) != .identifier) {
13708 try astgen.appendErrorNode(member_node, "missing function name", .{});13519 try astgen.appendErrorNode(member_node, "missing function name", .{});
13709 any_invalid_declarations = true;13520 any_invalid_declarations = true;
13710 continue;13521 continue;
...@@ -13721,12 +13532,12 @@ fn scanContainer(...@@ -13721,12 +13532,12 @@ fn scanContainer(
13721 decl_count += 1;13532 decl_count += 1;
13722 // We don't want shadowing detection here, and test names work a bit differently, so13533 // We don't want shadowing detection here, and test names work a bit differently, so
13723 // we must do the redeclaration detection ourselves.13534 // we must do the redeclaration detection ourselves.
13724 const test_name_token = main_tokens[member_node] + 1;13535 const test_name_token = tree.nodeMainToken(member_node) + 1;
13725 const new_ent: NameEntry = .{13536 const new_ent: NameEntry = .{
13726 .tok = test_name_token,13537 .tok = test_name_token,
13727 .next = null,13538 .next = null,
13728 };13539 };
13729 switch (token_tags[test_name_token]) {13540 switch (tree.tokenTag(test_name_token)) {
13730 else => {}, // unnamed test13541 else => {}, // unnamed test
13731 .string_literal => {13542 .string_literal => {
13732 const name = try astgen.strLitAsString(test_name_token);13543 const name = try astgen.strLitAsString(test_name_token);
...@@ -14328,3 +14139,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !...@@ -14328,3 +14139,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !
14328 }14139 }
14329 return refs.items;14140 return refs.items;
14330}14141}
14142
14143test {
14144 _ = &generate;
14145}
lib/std/zig/AstRlAnnotate.zig+173-164
...@@ -92,27 +92,26 @@ fn containerDecl(...@@ -92,27 +92,26 @@ fn containerDecl(
92 full: Ast.full.ContainerDecl,92 full: Ast.full.ContainerDecl,
93) !void {93) !void {
94 const tree = astrl.tree;94 const tree = astrl.tree;
95 const token_tags = tree.tokens.items(.tag);95 switch (tree.tokenTag(full.ast.main_token)) {
96 switch (token_tags[full.ast.main_token]) {
97 .keyword_struct => {96 .keyword_struct => {
98 if (full.ast.arg != 0) {97 if (full.ast.arg.unwrap()) |arg| {
99 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);98 _ = try astrl.expr(arg, block, ResultInfo.type_only);
100 }99 }
101 for (full.ast.members) |member_node| {100 for (full.ast.members) |member_node| {
102 _ = try astrl.expr(member_node, block, ResultInfo.none);101 _ = try astrl.expr(member_node, block, ResultInfo.none);
103 }102 }
104 },103 },
105 .keyword_union => {104 .keyword_union => {
106 if (full.ast.arg != 0) {105 if (full.ast.arg.unwrap()) |arg| {
107 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);106 _ = try astrl.expr(arg, block, ResultInfo.type_only);
108 }107 }
109 for (full.ast.members) |member_node| {108 for (full.ast.members) |member_node| {
110 _ = try astrl.expr(member_node, block, ResultInfo.none);109 _ = try astrl.expr(member_node, block, ResultInfo.none);
111 }110 }
112 },111 },
113 .keyword_enum => {112 .keyword_enum => {
114 if (full.ast.arg != 0) {113 if (full.ast.arg.unwrap()) |arg| {
115 _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only);114 _ = try astrl.expr(arg, block, ResultInfo.type_only);
116 }115 }
117 for (full.ast.members) |member_node| {116 for (full.ast.members) |member_node| {
118 _ = try astrl.expr(member_node, block, ResultInfo.none);117 _ = try astrl.expr(member_node, block, ResultInfo.none);
...@@ -130,10 +129,7 @@ fn containerDecl(...@@ -130,10 +129,7 @@ fn containerDecl(
130/// Returns true if `rl` provides a result pointer and the expression consumes it.129/// Returns true if `rl` provides a result pointer and the expression consumes it.
131fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool {130fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool {
132 const tree = astrl.tree;131 const tree = astrl.tree;
133 const token_tags = tree.tokens.items(.tag);132 switch (tree.nodeTag(node)) {
134 const node_datas = tree.nodes.items(.data);
135 const node_tags = tree.nodes.items(.tag);
136 switch (node_tags[node]) {
137 .root,133 .root,
138 .switch_case_one,134 .switch_case_one,
139 .switch_case_inline_one,135 .switch_case_inline_one,
...@@ -145,8 +141,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -145,8 +141,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
145 .asm_input,141 .asm_input,
146 => unreachable,142 => unreachable,
147143
148 .@"errdefer", .@"defer" => {144 .@"errdefer" => {
149 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);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);
150 return false;150 return false;
151 },151 },
152152
...@@ -155,21 +155,22 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -155,21 +155,22 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
155 .container_field,155 .container_field,
156 => {156 => {
157 const full = tree.fullContainerField(node).?;157 const full = tree.fullContainerField(node).?;
158 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.type_only);158 const type_expr = full.ast.type_expr.unwrap().?;
159 if (full.ast.align_expr != 0) {159 _ = try astrl.expr(type_expr, block, ResultInfo.type_only);
160 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);160 if (full.ast.align_expr.unwrap()) |align_expr| {
161 _ = try astrl.expr(align_expr, block, ResultInfo.type_only);
161 }162 }
162 if (full.ast.value_expr != 0) {163 if (full.ast.value_expr.unwrap()) |value_expr| {
163 _ = try astrl.expr(full.ast.value_expr, block, ResultInfo.type_only);164 _ = try astrl.expr(value_expr, block, ResultInfo.type_only);
164 }165 }
165 return false;166 return false;
166 },167 },
167 .@"usingnamespace" => {168 .@"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);
169 return false;170 return false;
170 },171 },
171 .test_decl => {172 .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);
173 return false;174 return false;
174 },175 },
175 .global_var_decl,176 .global_var_decl,
...@@ -178,17 +179,17 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -178,17 +179,17 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
178 .aligned_var_decl,179 .aligned_var_decl,
179 => {180 => {
180 const full = tree.fullVarDecl(node).?;181 const full = tree.fullVarDecl(node).?;
181 const init_ri = if (full.ast.type_node != 0) init_ri: {182 const init_ri = if (full.ast.type_node.unwrap()) |type_node| init_ri: {
182 _ = try astrl.expr(full.ast.type_node, block, ResultInfo.type_only);183 _ = try astrl.expr(type_node, block, ResultInfo.type_only);
183 break :init_ri ResultInfo.typed_ptr;184 break :init_ri ResultInfo.typed_ptr;
184 } else ResultInfo.inferred_ptr;185 } else ResultInfo.inferred_ptr;
185 if (full.ast.init_node == 0) {186 const init_node = full.ast.init_node.unwrap() orelse {
186 // No init node, so we're done.187 // No init node, so we're done.
187 return false;188 return false;
188 }189 };
189 switch (token_tags[full.ast.mut_token]) {190 switch (tree.tokenTag(full.ast.mut_token)) {
190 .keyword_const => {191 .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);
192 if (init_consumes_rl) {193 if (init_consumes_rl) {
193 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});194 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
194 }195 }
...@@ -197,7 +198,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -197,7 +198,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
197 .keyword_var => {198 .keyword_var => {
198 // We'll create an alloc either way, so don't care if the199 // We'll create an alloc either way, so don't care if the
199 // result pointer is consumed.200 // result pointer is consumed.
200 _ = try astrl.expr(full.ast.init_node, block, init_ri);201 _ = try astrl.expr(init_node, block, init_ri);
201 return false;202 return false;
202 },203 },
203 else => unreachable,204 else => unreachable,
...@@ -213,8 +214,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -213,8 +214,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
213 return false;214 return false;
214 },215 },
215 .assign => {216 .assign => {
216 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);217 const lhs, const rhs = tree.nodeData(node).node_and_node;
217 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.typed_ptr);218 _ = try astrl.expr(lhs, block, ResultInfo.none);
219 _ = try astrl.expr(rhs, block, ResultInfo.typed_ptr);
218 return false;220 return false;
219 },221 },
220 .assign_shl,222 .assign_shl,
...@@ -235,13 +237,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -235,13 +237,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
235 .assign_mul_wrap,237 .assign_mul_wrap,
236 .assign_mul_sat,238 .assign_mul_sat,
237 => {239 => {
238 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);240 const lhs, const rhs = tree.nodeData(node).node_and_node;
239 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);241 _ = try astrl.expr(lhs, block, ResultInfo.none);
242 _ = try astrl.expr(rhs, block, ResultInfo.none);
240 return false;243 return false;
241 },244 },
242 .shl, .shr => {245 .shl, .shr => {
243 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);246 const lhs, const rhs = tree.nodeData(node).node_and_node;
244 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);247 _ = try astrl.expr(lhs, block, ResultInfo.none);
248 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
245 return false;249 return false;
246 },250 },
247 .add,251 .add,
...@@ -267,33 +271,38 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -267,33 +271,38 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
267 .less_or_equal,271 .less_or_equal,
268 .array_cat,272 .array_cat,
269 => {273 => {
270 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);274 const lhs, const rhs = tree.nodeData(node).node_and_node;
271 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);275 _ = try astrl.expr(lhs, block, ResultInfo.none);
276 _ = try astrl.expr(rhs, block, ResultInfo.none);
272 return false;277 return false;
273 },278 },
279
274 .array_mult => {280 .array_mult => {
275 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);281 const lhs, const rhs = tree.nodeData(node).node_and_node;
276 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);282 _ = try astrl.expr(lhs, block, ResultInfo.none);
283 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
277 return false;284 return false;
278 },285 },
279 .error_union, .merge_error_sets => {286 .error_union, .merge_error_sets => {
280 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);287 const lhs, const rhs = tree.nodeData(node).node_and_node;
281 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);288 _ = try astrl.expr(lhs, block, ResultInfo.none);
289 _ = try astrl.expr(rhs, block, ResultInfo.none);
282 return false;290 return false;
283 },291 },
284 .bool_and,292 .bool_and,
285 .bool_or,293 .bool_or,
286 => {294 => {
287 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);295 const lhs, const rhs = tree.nodeData(node).node_and_node;
288 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);296 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
297 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
289 return false;298 return false;
290 },299 },
291 .bool_not => {300 .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);
293 return false;302 return false;
294 },303 },
295 .bit_not, .negation, .negation_wrap => {304 .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);
297 return false;306 return false;
298 },307 },
299308
...@@ -313,17 +322,13 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -313,17 +322,13 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
313 .error_set_decl,322 .error_set_decl,
314 => return false,323 => return false,
315324
316 .builtin_call_two, .builtin_call_two_comma => {325 .builtin_call_two,
317 if (node_datas[node].lhs == 0) {326 .builtin_call_two_comma,
318 return astrl.builtinCall(block, ri, node, &.{});327 .builtin_call,
319 } else if (node_datas[node].rhs == 0) {328 .builtin_call_comma,
320 return astrl.builtinCall(block, ri, node, &.{node_datas[node].lhs});329 => {
321 } else {330 var buf: [2]Ast.Node.Index = undefined;
322 return astrl.builtinCall(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });331 const params = tree.builtinCallParams(&buf, node).?;
323 }
324 },
325 .builtin_call, .builtin_call_comma => {
326 const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
327 return astrl.builtinCall(block, ri, node, params);332 return astrl.builtinCall(block, ri, node, params);
328 },333 },
329334
...@@ -342,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -342,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
342 for (full.ast.params) |param_node| {347 for (full.ast.params) |param_node| {
343 _ = try astrl.expr(param_node, block, ResultInfo.type_only);348 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
344 }349 }
345 return switch (node_tags[node]) {350 return switch (tree.nodeTag(node)) {
346 .call_one,351 .call_one,
347 .call_one_comma,352 .call_one_comma,
348 .call,353 .call,
...@@ -358,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -358,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
358 },363 },
359364
360 .@"return" => {365 .@"return" => {
361 if (node_datas[node].lhs != 0) {366 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
362 const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr);367 const ret_val_consumes_rl = try astrl.expr(lhs, block, ResultInfo.typed_ptr);
363 if (ret_val_consumes_rl) {368 if (ret_val_consumes_rl) {
364 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});369 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
365 }370 }
...@@ -368,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -368,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
368 },373 },
369374
370 .field_access => {375 .field_access => {
371 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);376 const lhs, _ = tree.nodeData(node).node_and_token;
377 _ = try astrl.expr(lhs, block, ResultInfo.none);
372 return false;378 return false;
373 },379 },
374380
...@@ -380,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -380,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
380 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool386 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
381 }387 }
382388
383 if (full.ast.else_expr == 0) {389 if (full.ast.else_expr.unwrap()) |else_expr| {
384 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
385 return false;
386 } else {
387 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);390 const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri);
388 const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri);391 const else_uses_rl = try astrl.expr(else_expr, block, ri);
389 const uses_rl = then_uses_rl or else_uses_rl;392 const uses_rl = then_uses_rl or else_uses_rl;
390 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});393 if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
391 return uses_rl;394 return uses_rl;
395 } else {
396 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
397 return false;
392 }398 }
393 },399 },
394400
...@@ -409,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -409,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
409 .ri = ri,415 .ri = ri,
410 .consumes_res_ptr = false,416 .consumes_res_ptr = false,
411 };417 };
412 if (full.ast.cont_expr != 0) {418 if (full.ast.cont_expr.unwrap()) |cont_expr| {
413 _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none);419 _ = try astrl.expr(cont_expr, &new_block, ResultInfo.none);
414 }420 }
415 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);421 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
416 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {422 const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: {
417 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);423 break :else_rl try astrl.expr(else_expr, block, ri);
418 } else false;424 } else false;
419 if (new_block.consumes_res_ptr or else_consumes_rl) {425 if (new_block.consumes_res_ptr or else_consumes_rl) {
420 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});426 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
...@@ -430,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -430,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
430 break :label try astrl.identString(label_token);436 break :label try astrl.identString(label_token);
431 } else null;437 } else null;
432 for (full.ast.inputs) |input| {438 for (full.ast.inputs) |input| {
433 if (node_tags[input] == .for_range) {439 if (tree.nodeTag(input) == .for_range) {
434 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);440 const lhs, const opt_rhs = tree.nodeData(input).node_and_opt_node;
435 if (node_datas[input].rhs != 0) {441 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
436 _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only);442 if (opt_rhs.unwrap()) |rhs| {
443 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
437 }444 }
438 } else {445 } else {
439 _ = try astrl.expr(input, block, ResultInfo.none);446 _ = try astrl.expr(input, block, ResultInfo.none);
...@@ -447,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -447,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
447 .consumes_res_ptr = false,454 .consumes_res_ptr = false,
448 };455 };
449 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);456 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
450 const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: {457 const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: {
451 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);458 break :else_rl try astrl.expr(else_expr, block, ri);
452 } else false;459 } else false;
453 if (new_block.consumes_res_ptr or else_consumes_rl) {460 if (new_block.consumes_res_ptr or else_consumes_rl) {
454 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});461 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
...@@ -459,66 +466,68 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -459,66 +466,68 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
459 },466 },
460467
461 .slice_open => {468 .slice_open => {
462 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);469 const sliced, const start = tree.nodeData(node).node_and_node;
463 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);470 _ = try astrl.expr(sliced, block, ResultInfo.none);
471 _ = try astrl.expr(start, block, ResultInfo.type_only);
464 return false;472 return false;
465 },473 },
466 .slice => {474 .slice => {
467 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);475 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
468 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);476 const extra = tree.extraData(extra_index, Ast.Node.Slice);
477 _ = try astrl.expr(sliced, block, ResultInfo.none);
469 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);478 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
470 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
471 return false;480 return false;
472 },481 },
473 .slice_sentinel => {482 .slice_sentinel => {
474 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);483 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
475 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);484 const extra = tree.extraData(extra_index, Ast.Node.SliceSentinel);
485 _ = try astrl.expr(sliced, block, ResultInfo.none);
476 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);486 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
477 if (extra.end != 0) {487 if (extra.end.unwrap()) |end| {
478 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);488 _ = try astrl.expr(end, block, ResultInfo.type_only);
479 }489 }
480 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);490 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
481 return false;491 return false;
482 },492 },
483 .deref => {493 .deref => {
484 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);494 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
485 return false;495 return false;
486 },496 },
487 .address_of => {497 .address_of => {
488 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);498 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
489 return false;499 return false;
490 },500 },
491 .optional_type => {501 .optional_type => {
492 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);502 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
493 return false;503 return false;
494 },504 },
495 .grouped_expression,
496 .@"try",505 .@"try",
497 .@"await",506 .@"await",
498 .@"nosuspend",507 .@"nosuspend",
508 => return astrl.expr(tree.nodeData(node).node, block, ri),
509 .grouped_expression,
499 .unwrap_optional,510 .unwrap_optional,
500 => return astrl.expr(node_datas[node].lhs, block, ri),511 => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri),
501512
502 .block_two, .block_two_semicolon => {513 .block_two,
503 if (node_datas[node].lhs == 0) {514 .block_two_semicolon,
504 return astrl.blockExpr(block, ri, node, &.{});515 .block,
505 } else if (node_datas[node].rhs == 0) {516 .block_semicolon,
506 return astrl.blockExpr(block, ri, node, &.{node_datas[node].lhs});517 => {
507 } else {518 var buf: [2]Ast.Node.Index = undefined;
508 return astrl.blockExpr(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs });519 const statements = tree.blockStatements(&buf, node).?;
509 }
510 },
511 .block, .block_semicolon => {
512 const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs];
513 return astrl.blockExpr(block, ri, node, statements);520 return astrl.blockExpr(block, ri, node, statements);
514 },521 },
515 .anyframe_type => {522 .anyframe_type => {
516 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);523 _, const child_type = tree.nodeData(node).token_and_node;
524 _ = try astrl.expr(child_type, block, ResultInfo.type_only);
517 return false;525 return false;
518 },526 },
519 .@"catch", .@"orelse" => {527 .@"catch", .@"orelse" => {
520 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);528 const lhs, const rhs = tree.nodeData(node).node_and_node;
521 const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri);529 _ = try astrl.expr(lhs, block, ResultInfo.none);
530 const rhs_consumes_rl = try astrl.expr(rhs, block, ri);
522 if (rhs_consumes_rl) {531 if (rhs_consumes_rl) {
523 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});532 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
524 }533 }
...@@ -532,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -532,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
532 => {541 => {
533 const full = tree.fullPtrType(node).?;542 const full = tree.fullPtrType(node).?;
534 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);543 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
535 if (full.ast.sentinel != 0) {544 if (full.ast.sentinel.unwrap()) |sentinel| {
536 _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only);545 _ = try astrl.expr(sentinel, block, ResultInfo.type_only);
537 }546 }
538 if (full.ast.addrspace_node != 0) {547 if (full.ast.addrspace_node.unwrap()) |addrspace_node| {
539 _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only);548 _ = try astrl.expr(addrspace_node, block, ResultInfo.type_only);
540 }549 }
541 if (full.ast.align_node != 0) {550 if (full.ast.align_node.unwrap()) |align_node| {
542 _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only);551 _ = try astrl.expr(align_node, block, ResultInfo.type_only);
543 }552 }
544 if (full.ast.bit_range_start != 0) {553 if (full.ast.bit_range_start.unwrap()) |bit_range_start| {
545 assert(full.ast.bit_range_end != 0);554 const bit_range_end = full.ast.bit_range_end.unwrap().?;
546 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);555 _ = try astrl.expr(bit_range_start, block, ResultInfo.type_only);
547 _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only);556 _ = try astrl.expr(bit_range_end, block, ResultInfo.type_only);
548 }557 }
549 return false;558 return false;
550 },559 },
...@@ -568,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -568,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
568 },577 },
569578
570 .@"break" => {579 .@"break" => {
571 if (node_datas[node].rhs == 0) {580 const opt_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
581 const rhs = opt_rhs.unwrap() orelse {
572 // Breaks with void are not interesting582 // Breaks with void are not interesting
573 return false;583 return false;
574 }584 };
575585
576 var opt_cur_block = block;586 var opt_cur_block = block;
577 if (node_datas[node].lhs == 0) {587 if (opt_label.unwrap()) |label_token| {
578 // No label - we're breaking from a loop.588 const break_label = try astrl.identString(label_token);
579 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {589 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
580 if (cur_block.is_loop) break;590 const block_label = cur_block.label orelse continue;
591 if (std.mem.eql(u8, block_label, break_label)) break;
581 }592 }
582 } else {593 } else {
583 const break_label = try astrl.identString(node_datas[node].lhs);594 // No label - we're breaking from a loop.
584 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {595 while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) {
585 const block_label = cur_block.label orelse continue;596 if (cur_block.is_loop) break;
586 if (std.mem.eql(u8, block_label, break_label)) break;
587 }597 }
588 }598 }
589599
590 if (opt_cur_block) |target_block| {600 if (opt_cur_block) |target_block| {
591 const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri);601 const consumes_break_rl = try astrl.expr(rhs, block, target_block.ri);
592 if (consumes_break_rl) target_block.consumes_res_ptr = true;602 if (consumes_break_rl) target_block.consumes_res_ptr = true;
593 } else {603 } else {
594 // No corresponding scope to break from - AstGen will emit an error.604 // No corresponding scope to break from - AstGen will emit an error.
595 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);605 _ = try astrl.expr(rhs, block, ResultInfo.none);
596 }606 }
597607
598 return false;608 return false;
599 },609 },
600610
601 .array_type => {611 .array_type => {
602 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);612 const lhs, const rhs = tree.nodeData(node).node_and_node;
603 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);613 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
614 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
604 return false;615 return false;
605 },616 },
606 .array_type_sentinel => {617 .array_type_sentinel => {
607 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);618 const len_expr, const extra_index = tree.nodeData(node).node_and_extra;
608 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);619 const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
620 _ = try astrl.expr(len_expr, block, ResultInfo.type_only);
609 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);621 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
610 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);622 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
611 return false;623 return false;
612 },624 },
613 .array_access => {625 .array_access => {
614 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);626 const lhs, const rhs = tree.nodeData(node).node_and_node;
615 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);627 _ = try astrl.expr(lhs, block, ResultInfo.none);
628 _ = try astrl.expr(rhs, block, ResultInfo.type_only);
616 return false;629 return false;
617 },630 },
618 .@"comptime" => {631 .@"comptime" => {
619 // AstGen will emit an error if the scope is already comptime, so we can assume it is632 // AstGen will emit an error if the scope is already comptime, so we can assume it is
620 // not. This means the result location is not forwarded.633 // not. This means the result location is not forwarded.
621 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);634 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
622 return false;635 return false;
623 },636 },
624 .@"switch", .switch_comma => {637 .@"switch", .switch_comma => {
625 const operand_node = node_datas[node].lhs;638 const operand_node, const extra_index = tree.nodeData(node).node_and_extra;
626 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange);639 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
627 const case_nodes = tree.extra_data[extra.start..extra.end];
628640
629 _ = try astrl.expr(operand_node, block, ResultInfo.none);641 _ = try astrl.expr(operand_node, block, ResultInfo.none);
630642
...@@ -632,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -632,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
632 for (case_nodes) |case_node| {644 for (case_nodes) |case_node| {
633 const case = tree.fullSwitchCase(case_node).?;645 const case = tree.fullSwitchCase(case_node).?;
634 for (case.ast.values) |item_node| {646 for (case.ast.values) |item_node| {
635 if (node_tags[item_node] == .switch_range) {647 if (tree.nodeTag(item_node) == .switch_range) {
636 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);648 const lhs, const rhs = tree.nodeData(item_node).node_and_node;
637 _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none);649 _ = try astrl.expr(lhs, block, ResultInfo.none);
650 _ = try astrl.expr(rhs, block, ResultInfo.none);
638 } else {651 } else {
639 _ = try astrl.expr(item_node, block, ResultInfo.none);652 _ = try astrl.expr(item_node, block, ResultInfo.none);
640 }653 }
...@@ -649,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -649,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
649 return any_prong_consumed_rl;662 return any_prong_consumed_rl;
650 },663 },
651 .@"suspend" => {664 .@"suspend" => {
652 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);665 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
653 return false;666 return false;
654 },667 },
655 .@"resume" => {668 .@"resume" => {
656 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);669 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
657 return false;670 return false;
658 },671 },
659672
...@@ -669,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -669,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
669 var buf: [2]Ast.Node.Index = undefined;682 var buf: [2]Ast.Node.Index = undefined;
670 const full = tree.fullArrayInit(&buf, node).?;683 const full = tree.fullArrayInit(&buf, node).?;
671684
672 if (full.ast.type_expr != 0) {685 if (full.ast.type_expr.unwrap()) |type_expr| {
673 // Explicitly typed init does not participate in RLS686 // Explicitly typed init does not participate in RLS
674 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);687 _ = try astrl.expr(type_expr, block, ResultInfo.none);
675 for (full.ast.elements) |elem_init| {688 for (full.ast.elements) |elem_init| {
676 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);689 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
677 }690 }
...@@ -706,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -706,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
706 var buf: [2]Ast.Node.Index = undefined;719 var buf: [2]Ast.Node.Index = undefined;
707 const full = tree.fullStructInit(&buf, node).?;720 const full = tree.fullStructInit(&buf, node).?;
708721
709 if (full.ast.type_expr != 0) {722 if (full.ast.type_expr.unwrap()) |type_expr| {
710 // Explicitly typed init does not participate in RLS723 // Explicitly typed init does not participate in RLS
711 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);724 _ = try astrl.expr(type_expr, block, ResultInfo.none);
712 for (full.ast.fields) |field_init| {725 for (full.ast.fields) |field_init| {
713 _ = try astrl.expr(field_init, block, ResultInfo.type_only);726 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
714 }727 }
...@@ -736,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -736,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
736 .fn_proto_one,749 .fn_proto_one,
737 .fn_proto,750 .fn_proto,
738 .fn_decl,751 .fn_decl,
739 => {752 => |tag| {
740 var buf: [1]Ast.Node.Index = undefined;753 var buf: [1]Ast.Node.Index = undefined;
741 const full = tree.fullFnProto(&buf, node).?;754 const full = tree.fullFnProto(&buf, node).?;
742 const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0;755 const body_node = if (tag == .fn_decl) tree.nodeData(node).node_and_node[1].toOptional() else .none;
743 {756 {
744 var it = full.iterate(tree);757 var it = full.iterate(tree);
745 while (it.next()) |param| {758 while (it.next()) |param| {
746 if (param.anytype_ellipsis3 == null) {759 if (param.anytype_ellipsis3 == null) {
747 _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only);760 const type_expr = param.type_expr.?;
761 _ = try astrl.expr(type_expr, block, ResultInfo.type_only);
748 }762 }
749 }763 }
750 }764 }
751 if (full.ast.align_expr != 0) {765 if (full.ast.align_expr.unwrap()) |align_expr| {
752 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);766 _ = try astrl.expr(align_expr, block, ResultInfo.type_only);
753 }767 }
754 if (full.ast.addrspace_expr != 0) {768 if (full.ast.addrspace_expr.unwrap()) |addrspace_expr| {
755 _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only);769 _ = try astrl.expr(addrspace_expr, block, ResultInfo.type_only);
756 }770 }
757 if (full.ast.section_expr != 0) {771 if (full.ast.section_expr.unwrap()) |section_expr| {
758 _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only);772 _ = try astrl.expr(section_expr, block, ResultInfo.type_only);
759 }773 }
760 if (full.ast.callconv_expr != 0) {774 if (full.ast.callconv_expr.unwrap()) |callconv_expr| {
761 _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only);775 _ = try astrl.expr(callconv_expr, block, ResultInfo.type_only);
762 }776 }
763 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);777 const return_type = full.ast.return_type.unwrap().?;
764 if (body_node != 0) {778 _ = try astrl.expr(return_type, block, ResultInfo.type_only);
765 _ = try astrl.expr(body_node, block, ResultInfo.none);779 if (body_node.unwrap()) |body| {
780 _ = try astrl.expr(body, block, ResultInfo.none);
766 }781 }
767 return false;782 return false;
768 },783 },
...@@ -771,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -771,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
771786
772fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {787fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
773 const tree = astrl.tree;788 const tree = astrl.tree;
774 const token_tags = tree.tokens.items(.tag);789 assert(tree.tokenTag(token) == .identifier);
775 assert(token_tags[token] == .identifier);
776 const ident_name = tree.tokenSlice(token);790 const ident_name = tree.tokenSlice(token);
777 if (!std.mem.startsWith(u8, ident_name, "@")) {791 if (!std.mem.startsWith(u8, ident_name, "@")) {
778 return ident_name;792 return ident_name;
...@@ -785,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {...@@ -785,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
785799
786fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {800fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool {
787 const tree = astrl.tree;801 const tree = astrl.tree;
788 const token_tags = tree.tokens.items(.tag);
789 const main_tokens = tree.nodes.items(.main_token);
790802
791 const lbrace = main_tokens[node];803 const lbrace = tree.nodeMainToken(node);
792 if (token_tags[lbrace - 1] == .colon and804 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
793 token_tags[lbrace - 2] == .identifier)
794 {
795 // Labeled block805 // Labeled block
796 var new_block: Block = .{806 var new_block: Block = .{
797 .parent = parent_block,807 .parent = parent_block,
...@@ -820,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -820,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
820 _ = ri; // Currently, no builtin consumes its result location.830 _ = ri; // Currently, no builtin consumes its result location.
821831
822 const tree = astrl.tree;832 const tree = astrl.tree;
823 const main_tokens = tree.nodes.items(.main_token);833 const builtin_token = tree.nodeMainToken(node);
824 const builtin_token = main_tokens[node];
825 const builtin_name = tree.tokenSlice(builtin_token);834 const builtin_name = tree.tokenSlice(builtin_token);
826 const info = BuiltinFn.list.get(builtin_name) orelse return false;835 const info = BuiltinFn.list.get(builtin_name) orelse return false;
827 if (info.param_count) |expected| {836 if (info.param_count) |expected| {
lib/std/zig/ErrorBundle.zig+28-26
...@@ -481,13 +481,13 @@ pub const Wip = struct {...@@ -481,13 +481,13 @@ pub const Wip = struct {
481 const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);481 const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);
482 extra_index = item.end;482 extra_index = item.end;
483 const err_span = blk: {483 const err_span = blk: {
484 if (item.data.node != 0) {484 if (item.data.node.unwrap()) |node| {
485 break :blk tree.nodeToSpan(item.data.node);485 break :blk tree.nodeToSpan(node);
486 }486 } else if (item.data.token.unwrap()) |token| {
487 const token_starts = tree.tokens.items(.start);487 const start = tree.tokenStart(token) + item.data.byte_offset;
488 const start = token_starts[item.data.token] + item.data.byte_offset;488 const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset;
489 const end = start + @as(u32, @intCast(tree.tokenSlice(item.data.token).len)) - item.data.byte_offset;489 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
490 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };490 } else unreachable;
491 };491 };
492 const err_loc = std.zig.findLineColumn(source, err_span.main);492 const err_loc = std.zig.findLineColumn(source, err_span.main);
493493
...@@ -516,13 +516,13 @@ pub const Wip = struct {...@@ -516,13 +516,13 @@ pub const Wip = struct {
516 const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem);516 const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem);
517 const msg = zir.nullTerminatedString(note_item.data.msg);517 const msg = zir.nullTerminatedString(note_item.data.msg);
518 const span = blk: {518 const span = blk: {
519 if (note_item.data.node != 0) {519 if (note_item.data.node.unwrap()) |node| {
520 break :blk tree.nodeToSpan(note_item.data.node);520 break :blk tree.nodeToSpan(node);
521 }521 } else if (note_item.data.token.unwrap()) |token| {
522 const token_starts = tree.tokens.items(.start);522 const start = tree.tokenStart(token) + note_item.data.byte_offset;
523 const start = token_starts[note_item.data.token] + note_item.data.byte_offset;523 const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset;
524 const end = start + @as(u32, @intCast(tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset;524 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };
525 break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start };525 } else unreachable;
526 };526 };
527 const loc = std.zig.findLineColumn(source, span.main);527 const loc = std.zig.findLineColumn(source, span.main);
528528
...@@ -560,13 +560,14 @@ pub const Wip = struct {...@@ -560,13 +560,14 @@ pub const Wip = struct {
560560
561 for (zoir.compile_errors) |err| {561 for (zoir.compile_errors) |err| {
562 const err_span: std.zig.Ast.Span = span: {562 const err_span: std.zig.Ast.Span = span: {
563 if (err.token == std.zig.Zoir.CompileError.invalid_token) {563 if (err.token.unwrap()) |token| {
564 break :span tree.nodeToSpan(err.node_or_offset);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));
565 }570 }
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 };
570 };571 };
571 const err_loc = std.zig.findLineColumn(source, err_span.main);572 const err_loc = std.zig.findLineColumn(source, err_span.main);
572573
...@@ -588,13 +589,14 @@ pub const Wip = struct {...@@ -588,13 +589,14 @@ pub const Wip = struct {
588 for (notes_start.., err.first_note.., 0..err.note_count) |eb_note_idx, zoir_note_idx, _| {589 for (notes_start.., err.first_note.., 0..err.note_count) |eb_note_idx, zoir_note_idx, _| {
589 const note = zoir.error_notes[zoir_note_idx];590 const note = zoir.error_notes[zoir_note_idx];
590 const note_span: std.zig.Ast.Span = span: {591 const note_span: std.zig.Ast.Span = span: {
591 if (note.token == std.zig.Zoir.CompileError.invalid_token) {592 if (note.token.unwrap()) |token| {
592 break :span tree.nodeToSpan(note.node_or_offset);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));
593 }599 }
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 };
598 };600 };
599 const note_loc = std.zig.findLineColumn(source, note_span.main);601 const note_loc = std.zig.findLineColumn(source, note_span.main);
600602
lib/std/zig/Parse.zig+1076-1328
...@@ -4,52 +4,71 @@ pub const Error = error{ParseError} || Allocator.Error;...@@ -4,52 +4,71 @@ pub const Error = error{ParseError} || Allocator.Error;
44
5gpa: Allocator,5gpa: Allocator,
6source: []const u8,6source: []const u8,
7token_tags: []const Token.Tag,7tokens: Ast.TokenList.Slice,
8token_starts: []const Ast.ByteOffset,
9tok_i: TokenIndex,8tok_i: TokenIndex,
10errors: std.ArrayListUnmanaged(AstError),9errors: std.ArrayListUnmanaged(AstError),
11nodes: Ast.NodeList,10nodes: Ast.NodeList,
12extra_data: std.ArrayListUnmanaged(Node.Index),11extra_data: std.ArrayListUnmanaged(u32),
13scratch: std.ArrayListUnmanaged(Node.Index),12scratch: 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
15const SmallSpan = union(enum) {34const SmallSpan = union(enum) {
16 zero_or_one: Node.Index,35 zero_or_one: Node.OptionalIndex,
17 multi: Node.SubRange,36 multi: Node.SubRange,
18};37};
1938
20const Members = struct {39const Members = struct {
21 len: usize,40 len: usize,
22 lhs: Node.Index,41 /// Must be either `.opt_node_and_opt_node` if `len <= 2` or `.extra_range` otherwise.
23 rhs: Node.Index,42 data: Node.Data,
24 trailing: bool,43 trailing: bool,
2544
26 fn toSpan(self: Members, p: *Parse) !Node.SubRange {45 fn toSpan(self: Members, p: *Parse) !Node.SubRange {
27 if (self.len <= 2) {46 return switch (self.len) {
28 const nodes = [2]Node.Index{ self.lhs, self.rhs };47 0 => p.listToSpan(&.{}),
29 return p.listToSpan(nodes[0..self.len]);48 1 => p.listToSpan(&.{self.data.opt_node_and_opt_node[0].unwrap().?}),
30 } else {49 2 => p.listToSpan(&.{ self.data.opt_node_and_opt_node[0].unwrap().?, self.data.opt_node_and_opt_node[1].unwrap().? }),
31 return Node.SubRange{ .start = self.lhs, .end = self.rhs };50 else => self.data.extra_range,
32 }51 };
33 }52 }
34};53};
3554
36fn listToSpan(p: *Parse, list: []const Node.Index) !Node.SubRange {55fn listToSpan(p: *Parse, list: []const Node.Index) Allocator.Error!Node.SubRange {
37 try p.extra_data.appendSlice(p.gpa, list);56 try p.extra_data.appendSlice(p.gpa, @ptrCast(list));
38 return Node.SubRange{57 return .{
39 .start = @as(Node.Index, @intCast(p.extra_data.items.len - list.len)),58 .start = @enumFromInt(p.extra_data.items.len - list.len),
40 .end = @as(Node.Index, @intCast(p.extra_data.items.len)),59 .end = @enumFromInt(p.extra_data.items.len),
41 };60 };
42}61}
4362
44fn addNode(p: *Parse, elem: Ast.Node) Allocator.Error!Node.Index {63fn 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);
46 try p.nodes.append(p.gpa, elem);65 try p.nodes.append(p.gpa, elem);
47 return result;66 return result;
48}67}
4968
50fn setNode(p: *Parse, i: usize, elem: Ast.Node) Node.Index {69fn setNode(p: *Parse, i: usize, elem: Ast.Node) Node.Index {
51 p.nodes.set(i, elem);70 p.nodes.set(i, elem);
52 return @as(Node.Index, @intCast(i));71 return @enumFromInt(i);
53}72}
5473
55fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize {74fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize {
...@@ -69,13 +88,22 @@ fn unreserveNode(p: *Parse, node_index: usize) void {...@@ -69,13 +88,22 @@ fn unreserveNode(p: *Parse, node_index: usize) void {
69 }88 }
70}89}
7190
72fn addExtra(p: *Parse, extra: anytype) Allocator.Error!Node.Index {91fn addExtra(p: *Parse, extra: anytype) Allocator.Error!ExtraIndex {
73 const fields = std.meta.fields(@TypeOf(extra));92 const fields = std.meta.fields(@TypeOf(extra));
74 try p.extra_data.ensureUnusedCapacity(p.gpa, fields.len);93 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);
76 inline for (fields) |field| {95 inline for (fields) |field| {
77 comptime assert(field.type == Node.Index);96 const data: u32 = switch (field.type) {
78 p.extra_data.appendAssumeCapacity(@field(extra, field.name));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);
79 }107 }
80 return result;108 return result;
81}109}
...@@ -170,13 +198,10 @@ pub fn parseRoot(p: *Parse) !void {...@@ -170,13 +198,10 @@ pub fn parseRoot(p: *Parse) !void {
170 });198 });
171 const root_members = try p.parseContainerMembers();199 const root_members = try p.parseContainerMembers();
172 const root_decls = try root_members.toSpan(p);200 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) {
174 try p.warnExpected(.eof);202 try p.warnExpected(.eof);
175 }203 }
176 p.nodes.items(.data)[0] = .{204 p.nodes.items(.data)[0] = .{ .extra_range = root_decls };
177 .lhs = root_decls.start,
178 .rhs = root_decls.end,
179 };
180}205}
181206
182/// Parse in ZON mode. Subset of the language.207/// Parse in ZON mode. Subset of the language.
...@@ -196,13 +221,10 @@ pub fn parseZon(p: *Parse) !void {...@@ -196,13 +221,10 @@ pub fn parseZon(p: *Parse) !void {
196 },221 },
197 else => |e| return e,222 else => |e| return e,
198 };223 };
199 if (p.token_tags[p.tok_i] != .eof) {224 if (p.tokenTag(p.tok_i) != .eof) {
200 try p.warnExpected(.eof);225 try p.warnExpected(.eof);
201 }226 }
202 p.nodes.items(.data)[0] = .{227 p.nodes.items(.data)[0] = .{ .node = node_index };
203 .lhs = node_index,
204 .rhs = undefined,
205 };
206}228}
207229
208/// ContainerMembers <- ContainerDeclaration* (ContainerField COMMA)* (ContainerField / ContainerDeclaration*)230/// ContainerMembers <- ContainerDeclaration* (ContainerField COMMA)* (ContainerField / ContainerDeclaration*)
...@@ -235,13 +257,13 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -235,13 +257,13 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
235 while (true) {257 while (true) {
236 const doc_comment = try p.eatDocComments();258 const doc_comment = try p.eatDocComments();
237259
238 switch (p.token_tags[p.tok_i]) {260 switch (p.tokenTag(p.tok_i)) {
239 .keyword_test => {261 .keyword_test => {
240 if (doc_comment) |some| {262 if (doc_comment) |some| {
241 try p.warnMsg(.{ .tag = .test_doc_comment, .token = some });263 try p.warnMsg(.{ .tag = .test_doc_comment, .token = some });
242 }264 }
243 const test_decl_node = try p.expectTestDeclRecoverable();265 const maybe_test_decl_node = try p.expectTestDeclRecoverable();
244 if (test_decl_node != 0) {266 if (maybe_test_decl_node) |test_decl_node| {
245 if (field_state == .seen) {267 if (field_state == .seen) {
246 field_state = .{ .end = test_decl_node };268 field_state = .{ .end = test_decl_node };
247 }269 }
...@@ -249,27 +271,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -249,27 +271,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
249 }271 }
250 trailing = false;272 trailing = false;
251 },273 },
252 .keyword_comptime => switch (p.token_tags[p.tok_i + 1]) {274 .keyword_comptime => switch (p.tokenTag(p.tok_i + 1)) {
253 .l_brace => {275 .l_brace => {
254 if (doc_comment) |some| {276 if (doc_comment) |some| {
255 try p.warnMsg(.{ .tag = .comptime_doc_comment, .token = some });277 try p.warnMsg(.{ .tag = .comptime_doc_comment, .token = some });
256 }278 }
257 const comptime_token = p.nextToken();279 const comptime_token = p.nextToken();
258 const block = p.parseBlock() catch |err| switch (err) {280 const opt_block = p.parseBlock() catch |err| switch (err) {
259 error.OutOfMemory => return error.OutOfMemory,281 error.OutOfMemory => return error.OutOfMemory,
260 error.ParseError => blk: {282 error.ParseError => blk: {
261 p.findNextContainerMember();283 p.findNextContainerMember();
262 break :blk null_node;284 break :blk null;
263 },285 },
264 };286 };
265 if (block != 0) {287 if (opt_block) |block| {
266 const comptime_node = try p.addNode(.{288 const comptime_node = try p.addNode(.{
267 .tag = .@"comptime",289 .tag = .@"comptime",
268 .main_token = comptime_token,290 .main_token = comptime_token,
269 .data = .{291 .data = .{ .node = block },
270 .lhs = block,
271 .rhs = undefined,
272 },
273 });292 });
274 if (field_state == .seen) {293 if (field_state == .seen) {
275 field_state = .{ .end = comptime_node };294 field_state = .{ .end = comptime_node };
...@@ -294,7 +313,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -294,7 +313,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
294 .end => |node| {313 .end => |node| {
295 try p.warnMsg(.{314 try p.warnMsg(.{
296 .tag = .decl_between_fields,315 .tag = .decl_between_fields,
297 .token = p.nodes.items(.main_token)[node],316 .token = p.nodeMainToken(node),
298 });317 });
299 try p.warnMsg(.{318 try p.warnMsg(.{
300 .tag = .previous_field,319 .tag = .previous_field,
...@@ -311,7 +330,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -311,7 +330,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
311 },330 },
312 }331 }
313 try p.scratch.append(p.gpa, container_field);332 try p.scratch.append(p.gpa, container_field);
314 switch (p.token_tags[p.tok_i]) {333 switch (p.tokenTag(p.tok_i)) {
315 .comma => {334 .comma => {
316 p.tok_i += 1;335 p.tok_i += 1;
317 trailing = true;336 trailing = true;
...@@ -331,24 +350,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -331,24 +350,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
331 },350 },
332 .keyword_pub => {351 .keyword_pub => {
333 p.tok_i += 1;352 p.tok_i += 1;
334 const top_level_decl = try p.expectTopLevelDeclRecoverable();353 const opt_top_level_decl = try p.expectTopLevelDeclRecoverable();
335 if (top_level_decl != 0) {354 if (opt_top_level_decl) |top_level_decl| {
336 if (field_state == .seen) {355 if (field_state == .seen) {
337 field_state = .{ .end = top_level_decl };356 field_state = .{ .end = top_level_decl };
338 }357 }
339 try p.scratch.append(p.gpa, top_level_decl);358 try p.scratch.append(p.gpa, top_level_decl);
340 }359 }
341 trailing = p.token_tags[p.tok_i - 1] == .semicolon;360 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
342 },361 },
343 .keyword_usingnamespace => {362 .keyword_usingnamespace => {
344 const node = try p.expectUsingNamespaceRecoverable();363 const opt_node = try p.expectUsingNamespaceRecoverable();
345 if (node != 0) {364 if (opt_node) |node| {
346 if (field_state == .seen) {365 if (field_state == .seen) {
347 field_state = .{ .end = node };366 field_state = .{ .end = node };
348 }367 }
349 try p.scratch.append(p.gpa, node);368 try p.scratch.append(p.gpa, node);
350 }369 }
351 trailing = p.token_tags[p.tok_i - 1] == .semicolon;370 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
352 },371 },
353 .keyword_const,372 .keyword_const,
354 .keyword_var,373 .keyword_var,
...@@ -359,14 +378,14 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -359,14 +378,14 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
359 .keyword_noinline,378 .keyword_noinline,
360 .keyword_fn,379 .keyword_fn,
361 => {380 => {
362 const top_level_decl = try p.expectTopLevelDeclRecoverable();381 const opt_top_level_decl = try p.expectTopLevelDeclRecoverable();
363 if (top_level_decl != 0) {382 if (opt_top_level_decl) |top_level_decl| {
364 if (field_state == .seen) {383 if (field_state == .seen) {
365 field_state = .{ .end = top_level_decl };384 field_state = .{ .end = top_level_decl };
366 }385 }
367 try p.scratch.append(p.gpa, top_level_decl);386 try p.scratch.append(p.gpa, top_level_decl);
368 }387 }
369 trailing = p.token_tags[p.tok_i - 1] == .semicolon;388 trailing = p.tokenTag(p.tok_i - 1) == .semicolon;
370 },389 },
371 .eof, .r_brace => {390 .eof, .r_brace => {
372 if (doc_comment) |tok| {391 if (doc_comment) |tok| {
...@@ -399,7 +418,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -399,7 +418,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
399 .end => |node| {418 .end => |node| {
400 try p.warnMsg(.{419 try p.warnMsg(.{
401 .tag = .decl_between_fields,420 .tag = .decl_between_fields,
402 .token = p.nodes.items(.main_token)[node],421 .token = p.nodeMainToken(node),
403 });422 });
404 try p.warnMsg(.{423 try p.warnMsg(.{
405 .tag = .previous_field,424 .tag = .previous_field,
...@@ -416,7 +435,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -416,7 +435,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
416 },435 },
417 }436 }
418 try p.scratch.append(p.gpa, container_field);437 try p.scratch.append(p.gpa, container_field);
419 switch (p.token_tags[p.tok_i]) {438 switch (p.tokenTag(p.tok_i)) {
420 .comma => {439 .comma => {
421 p.tok_i += 1;440 p.tok_i += 1;
422 trailing = true;441 trailing = true;
...@@ -431,7 +450,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -431,7 +450,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
431 // There is not allowed to be a decl after a field with no comma.450 // There is not allowed to be a decl after a field with no comma.
432 // Report error but recover parser.451 // Report error but recover parser.
433 try p.warn(.expected_comma_after_field);452 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) {
435 try p.warnMsg(.{454 try p.warnMsg(.{
436 .tag = .var_const_decl,455 .tag = .var_const_decl,
437 .is_note = true,456 .is_note = true,
...@@ -445,34 +464,21 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {...@@ -445,34 +464,21 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members {
445 }464 }
446465
447 const items = p.scratch.items[scratch_top..];466 const items = p.scratch.items[scratch_top..];
448 switch (items.len) {467 if (items.len <= 2) {
449 0 => return Members{468 return Members{
450 .len = 0,469 .len = items.len,
451 .lhs = 0,470 .data = .{ .opt_node_and_opt_node = .{
452 .rhs = 0,471 if (items.len >= 1) items[0].toOptional() else .none,
453 .trailing = trailing,472 if (items.len >= 2) items[1].toOptional() else .none,
454 },473 } },
455 1 => return Members{
456 .len = 1,
457 .lhs = items[0],
458 .rhs = 0,
459 .trailing = trailing,474 .trailing = trailing,
460 },475 };
461 2 => return Members{476 } else {
462 .len = 2,477 return Members{
463 .lhs = items[0],478 .len = items.len,
464 .rhs = items[1],479 .data = .{ .extra_range = try p.listToSpan(items) },
465 .trailing = trailing,480 .trailing = trailing,
466 },481 };
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 },
476 }482 }
477}483}
478484
...@@ -481,7 +487,7 @@ fn findNextContainerMember(p: *Parse) void {...@@ -481,7 +487,7 @@ fn findNextContainerMember(p: *Parse) void {
481 var level: u32 = 0;487 var level: u32 = 0;
482 while (true) {488 while (true) {
483 const tok = p.nextToken();489 const tok = p.nextToken();
484 switch (p.token_tags[tok]) {490 switch (p.tokenTag(tok)) {
485 // Any of these can start a new top level declaration.491 // Any of these can start a new top level declaration.
486 .keyword_test,492 .keyword_test,
487 .keyword_comptime,493 .keyword_comptime,
...@@ -502,7 +508,7 @@ fn findNextContainerMember(p: *Parse) void {...@@ -502,7 +508,7 @@ fn findNextContainerMember(p: *Parse) void {
502 }508 }
503 },509 },
504 .identifier => {510 .identifier => {
505 if (p.token_tags[tok + 1] == .comma and level == 0) {511 if (p.tokenTag(tok + 1) == .comma and level == 0) {
506 p.tok_i -= 1;512 p.tok_i -= 1;
507 return;513 return;
508 }514 }
...@@ -539,7 +545,7 @@ fn findNextStmt(p: *Parse) void {...@@ -539,7 +545,7 @@ fn findNextStmt(p: *Parse) void {
539 var level: u32 = 0;545 var level: u32 = 0;
540 while (true) {546 while (true) {
541 const tok = p.nextToken();547 const tok = p.nextToken();
542 switch (p.token_tags[tok]) {548 switch (p.tokenTag(tok)) {
543 .l_brace => level += 1,549 .l_brace => level += 1,
544 .r_brace => {550 .r_brace => {
545 if (level == 0) {551 if (level == 0) {
...@@ -563,44 +569,45 @@ fn findNextStmt(p: *Parse) void {...@@ -563,44 +569,45 @@ fn findNextStmt(p: *Parse) void {
563}569}
564570
565/// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block571/// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block
566fn expectTestDecl(p: *Parse) !Node.Index {572fn expectTestDecl(p: *Parse) Error!Node.Index {
567 const test_token = p.assertToken(.keyword_test);573 const test_token = p.assertToken(.keyword_test);
568 const name_token = switch (p.token_tags[p.tok_i]) {574 const name_token: OptionalTokenIndex = switch (p.tokenTag(p.tok_i)) {
569 .string_literal, .identifier => p.nextToken(),575 .string_literal, .identifier => .fromToken(p.nextToken()),
570 else => null,576 else => .none,
571 };577 };
572 const block_node = try p.parseBlock();578 const block_node = try p.parseBlock() orelse return p.fail(.expected_block);
573 if (block_node == 0) return p.fail(.expected_block);
574 return p.addNode(.{579 return p.addNode(.{
575 .tag = .test_decl,580 .tag = .test_decl,
576 .main_token = test_token,581 .main_token = test_token,
577 .data = .{582 .data = .{ .opt_token_and_node = .{
578 .lhs = name_token orelse 0,583 name_token,
579 .rhs = block_node,584 block_node,
580 },585 } },
581 });586 });
582}587}
583588
584fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {589fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
585 return p.expectTestDecl() catch |err| switch (err) {590 if (p.expectTestDecl()) |node| {
591 return node;
592 } else |err| switch (err) {
586 error.OutOfMemory => return error.OutOfMemory,593 error.OutOfMemory => return error.OutOfMemory,
587 error.ParseError => {594 error.ParseError => {
588 p.findNextContainerMember();595 p.findNextContainerMember();
589 return null_node;596 return null;
590 },597 },
591 };598 }
592}599}
593600
594/// Decl601/// Decl
595/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)602/// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block)
596/// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl603/// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
597/// / KEYWORD_usingnamespace Expr SEMICOLON604/// / KEYWORD_usingnamespace Expr SEMICOLON
598fn expectTopLevelDecl(p: *Parse) !Node.Index {605fn expectTopLevelDecl(p: *Parse) !?Node.Index {
599 const extern_export_inline_token = p.nextToken();606 const extern_export_inline_token = p.nextToken();
600 var is_extern: bool = false;607 var is_extern: bool = false;
601 var expect_fn: bool = false;608 var expect_fn: bool = false;
602 var expect_var_or_fn: bool = false;609 var expect_var_or_fn: bool = false;
603 switch (p.token_tags[extern_export_inline_token]) {610 switch (p.tokenTag(extern_export_inline_token)) {
604 .keyword_extern => {611 .keyword_extern => {
605 _ = p.eatToken(.string_literal);612 _ = p.eatToken(.string_literal);
606 is_extern = true;613 is_extern = true;
...@@ -610,9 +617,9 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {...@@ -610,9 +617,9 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
610 .keyword_inline, .keyword_noinline => expect_fn = true,617 .keyword_inline, .keyword_noinline => expect_fn = true,
611 else => p.tok_i -= 1,618 else => p.tok_i -= 1,
612 }619 }
613 const fn_proto = try p.parseFnProto();620 const opt_fn_proto = try p.parseFnProto();
614 if (fn_proto != 0) {621 if (opt_fn_proto) |fn_proto| {
615 switch (p.token_tags[p.tok_i]) {622 switch (p.tokenTag(p.tok_i)) {
616 .semicolon => {623 .semicolon => {
617 p.tok_i += 1;624 p.tok_i += 1;
618 return fn_proto;625 return fn_proto;
...@@ -620,20 +627,19 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {...@@ -620,20 +627,19 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
620 .l_brace => {627 .l_brace => {
621 if (is_extern) {628 if (is_extern) {
622 try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token });629 try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token });
623 return null_node;630 return null;
624 }631 }
625 const fn_decl_index = try p.reserveNode(.fn_decl);632 const fn_decl_index = try p.reserveNode(.fn_decl);
626 errdefer p.unreserveNode(fn_decl_index);633 errdefer p.unreserveNode(fn_decl_index);
627634
628 const body_block = try p.parseBlock();635 const body_block = try p.parseBlock();
629 assert(body_block != 0);
630 return p.setNode(fn_decl_index, .{636 return p.setNode(fn_decl_index, .{
631 .tag = .fn_decl,637 .tag = .fn_decl,
632 .main_token = p.nodes.items(.main_token)[fn_proto],638 .main_token = p.nodeMainToken(fn_proto),
633 .data = .{639 .data = .{ .node_and_node = .{
634 .lhs = fn_proto,640 fn_proto,
635 .rhs = body_block,641 body_block.?,
636 },642 } },
637 });643 });
638 },644 },
639 else => {645 else => {
...@@ -641,7 +647,7 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {...@@ -641,7 +647,7 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
641 // a missing '}' we can assume this function was647 // a missing '}' we can assume this function was
642 // supposed to end here.648 // supposed to end here.
643 try p.warn(.expected_semi_or_lbrace);649 try p.warn(.expected_semi_or_lbrace);
644 return null_node;650 return null;
645 },651 },
646 }652 }
647 }653 }
...@@ -651,28 +657,25 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {...@@ -651,28 +657,25 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index {
651 }657 }
652658
653 const thread_local_token = p.eatToken(.keyword_threadlocal);659 const thread_local_token = p.eatToken(.keyword_threadlocal);
654 const var_decl = try p.parseGlobalVarDecl();660 if (try p.parseGlobalVarDecl()) |var_decl| return var_decl;
655 if (var_decl != 0) {
656 return var_decl;
657 }
658 if (thread_local_token != null) {661 if (thread_local_token != null) {
659 return p.fail(.expected_var_decl);662 return p.fail(.expected_var_decl);
660 }663 }
661 if (expect_var_or_fn) {664 if (expect_var_or_fn) {
662 return p.fail(.expected_var_decl_or_fn);665 return p.fail(.expected_var_decl_or_fn);
663 }666 }
664 if (p.token_tags[p.tok_i] != .keyword_usingnamespace) {667 if (p.tokenTag(p.tok_i) != .keyword_usingnamespace) {
665 return p.fail(.expected_pub_item);668 return p.fail(.expected_pub_item);
666 }669 }
667 return p.expectUsingNamespace();670 return try p.expectUsingNamespace();
668}671}
669672
670fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {673fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
671 return p.expectTopLevelDecl() catch |err| switch (err) {674 return p.expectTopLevelDecl() catch |err| switch (err) {
672 error.OutOfMemory => return error.OutOfMemory,675 error.OutOfMemory => return error.OutOfMemory,
673 error.ParseError => {676 error.ParseError => {
674 p.findNextContainerMember();677 p.findNextContainerMember();
675 return null_node;678 return null;
676 },679 },
677 };680 };
678}681}
...@@ -684,26 +687,23 @@ fn expectUsingNamespace(p: *Parse) !Node.Index {...@@ -684,26 +687,23 @@ fn expectUsingNamespace(p: *Parse) !Node.Index {
684 return p.addNode(.{687 return p.addNode(.{
685 .tag = .@"usingnamespace",688 .tag = .@"usingnamespace",
686 .main_token = usingnamespace_token,689 .main_token = usingnamespace_token,
687 .data = .{690 .data = .{ .node = expr },
688 .lhs = expr,
689 .rhs = undefined,
690 },
691 });691 });
692}692}
693693
694fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!Node.Index {694fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index {
695 return p.expectUsingNamespace() catch |err| switch (err) {695 return p.expectUsingNamespace() catch |err| switch (err) {
696 error.OutOfMemory => return error.OutOfMemory,696 error.OutOfMemory => return error.OutOfMemory,
697 error.ParseError => {697 error.ParseError => {
698 p.findNextContainerMember();698 p.findNextContainerMember();
699 return null_node;699 return null;
700 },700 },
701 };701 };
702}702}
703703
704/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr704/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
705fn parseFnProto(p: *Parse) !Node.Index {705fn parseFnProto(p: *Parse) !?Node.Index {
706 const fn_token = p.eatToken(.keyword_fn) orelse return null_node;706 const fn_token = p.eatToken(.keyword_fn) orelse return null;
707707
708 // We want the fn proto node to be before its children in the array.708 // We want the fn proto node to be before its children in the array.
709 const fn_proto_index = try p.reserveNode(.fn_proto);709 const fn_proto_index = try p.reserveNode(.fn_proto);
...@@ -718,33 +718,33 @@ fn parseFnProto(p: *Parse) !Node.Index {...@@ -718,33 +718,33 @@ fn parseFnProto(p: *Parse) !Node.Index {
718 _ = p.eatToken(.bang);718 _ = p.eatToken(.bang);
719719
720 const return_type_expr = try p.parseTypeExpr();720 const return_type_expr = try p.parseTypeExpr();
721 if (return_type_expr == 0) {721 if (return_type_expr == null) {
722 // most likely the user forgot to specify the return type.722 // most likely the user forgot to specify the return type.
723 // Mark return type as invalid and try to continue.723 // Mark return type as invalid and try to continue.
724 try p.warn(.expected_return_type);724 try p.warn(.expected_return_type);
725 }725 }
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) {
728 switch (params) {728 switch (params) {
729 .zero_or_one => |param| return p.setNode(fn_proto_index, .{729 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
730 .tag = .fn_proto_simple,730 .tag = .fn_proto_simple,
731 .main_token = fn_token,731 .main_token = fn_token,
732 .data = .{732 .data = .{ .opt_node_and_opt_node = .{
733 .lhs = param,733 param,
734 .rhs = return_type_expr,734 .fromOptional(return_type_expr),
735 },735 } },
736 }),736 }),
737 .multi => |span| {737 .multi => |span| {
738 return p.setNode(fn_proto_index, .{738 return p.setNode(fn_proto_index, .{
739 .tag = .fn_proto_multi,739 .tag = .fn_proto_multi,
740 .main_token = fn_token,740 .main_token = fn_token,
741 .data = .{741 .data = .{ .extra_and_opt_node = .{
742 .lhs = try p.addExtra(Node.SubRange{742 try p.addExtra(Node.SubRange{
743 .start = span.start,743 .start = span.start,
744 .end = span.end,744 .end = span.end,
745 }),745 }),
746 .rhs = return_type_expr,746 .fromOptional(return_type_expr),
747 },747 } },
748 });748 });
749 },749 },
750 }750 }
...@@ -753,109 +753,124 @@ fn parseFnProto(p: *Parse) !Node.Index {...@@ -753,109 +753,124 @@ fn parseFnProto(p: *Parse) !Node.Index {
753 .zero_or_one => |param| return p.setNode(fn_proto_index, .{753 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
754 .tag = .fn_proto_one,754 .tag = .fn_proto_one,
755 .main_token = fn_token,755 .main_token = fn_token,
756 .data = .{756 .data = .{ .extra_and_opt_node = .{
757 .lhs = try p.addExtra(Node.FnProtoOne{757 try p.addExtra(Node.FnProtoOne{
758 .param = param,758 .param = param,
759 .align_expr = align_expr,759 .align_expr = .fromOptional(align_expr),
760 .addrspace_expr = addrspace_expr,760 .addrspace_expr = .fromOptional(addrspace_expr),
761 .section_expr = section_expr,761 .section_expr = .fromOptional(section_expr),
762 .callconv_expr = callconv_expr,762 .callconv_expr = .fromOptional(callconv_expr),
763 }),763 }),
764 .rhs = return_type_expr,764 .fromOptional(return_type_expr),
765 },765 } },
766 }),766 }),
767 .multi => |span| {767 .multi => |span| {
768 return p.setNode(fn_proto_index, .{768 return p.setNode(fn_proto_index, .{
769 .tag = .fn_proto,769 .tag = .fn_proto,
770 .main_token = fn_token,770 .main_token = fn_token,
771 .data = .{771 .data = .{ .extra_and_opt_node = .{
772 .lhs = try p.addExtra(Node.FnProto{772 try p.addExtra(Node.FnProto{
773 .params_start = span.start,773 .params_start = span.start,
774 .params_end = span.end,774 .params_end = span.end,
775 .align_expr = align_expr,775 .align_expr = .fromOptional(align_expr),
776 .addrspace_expr = addrspace_expr,776 .addrspace_expr = .fromOptional(addrspace_expr),
777 .section_expr = section_expr,777 .section_expr = .fromOptional(section_expr),
778 .callconv_expr = callconv_expr,778 .callconv_expr = .fromOptional(callconv_expr),
779 }),779 }),
780 .rhs = return_type_expr,780 .fromOptional(return_type_expr),
781 },781 } },
782 });782 });
783 },783 },
784 }784 }
785}785}
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
787/// VarDeclProto <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection?797/// 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.798/// Returns a `*_var_decl` node with its rhs (init expression) initialized to .none.
789fn parseVarDeclProto(p: *Parse) !Node.Index {799fn parseVarDeclProto(p: *Parse) !?Node.Index {
790 const mut_token = p.eatToken(.keyword_const) orelse800 const mut_token = p.eatToken(.keyword_const) orelse
791 p.eatToken(.keyword_var) orelse801 p.eatToken(.keyword_var) orelse
792 return null_node;802 return null;
793803
794 _ = try p.expectToken(.identifier);804 _ = try p.expectToken(.identifier);
795 const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr();805 const opt_type_node = if (p.eatToken(.colon) == null) null else try p.expectTypeExpr();
796 const align_node = try p.parseByteAlign();806 const opt_align_node = try p.parseByteAlign();
797 const addrspace_node = try p.parseAddrSpace();807 const opt_addrspace_node = try p.parseAddrSpace();
798 const section_node = try p.parseLinkSection();808 const opt_section_node = try p.parseLinkSection();
799809
800 if (section_node == 0 and addrspace_node == 0) {810 if (opt_section_node == null and opt_addrspace_node == null) {
801 if (align_node == 0) {811 const align_node = opt_align_node orelse {
802 return p.addNode(.{812 return try p.addNode(.{
803 .tag = .simple_var_decl,813 .tag = .simple_var_decl,
804 .main_token = mut_token,814 .main_token = mut_token,
805 .data = .{815 .data = .{
806 .lhs = type_node,816 .opt_node_and_opt_node = .{
807 .rhs = 0,817 .fromOptional(opt_type_node),
818 .none, // set later with `setVarDeclInitExpr
819 },
808 },820 },
809 });821 });
810 }822 };
811823
812 if (type_node == 0) {824 const type_node = opt_type_node orelse {
813 return p.addNode(.{825 return try p.addNode(.{
814 .tag = .aligned_var_decl,826 .tag = .aligned_var_decl,
815 .main_token = mut_token,827 .main_token = mut_token,
816 .data = .{828 .data = .{
817 .lhs = align_node,829 .node_and_opt_node = .{
818 .rhs = 0,830 align_node,
831 .none, // set later with `setVarDeclInitExpr
832 },
819 },833 },
820 });834 });
821 }835 };
822836
823 return p.addNode(.{837 return try p.addNode(.{
824 .tag = .local_var_decl,838 .tag = .local_var_decl,
825 .main_token = mut_token,839 .main_token = mut_token,
826 .data = .{840 .data = .{
827 .lhs = try p.addExtra(Node.LocalVarDecl{841 .extra_and_opt_node = .{
828 .type_node = type_node,842 try p.addExtra(Node.LocalVarDecl{
829 .align_node = align_node,843 .type_node = type_node,
830 }),844 .align_node = align_node,
831 .rhs = 0,845 }),
846 .none, // set later with `setVarDeclInitExpr
847 },
832 },848 },
833 });849 });
834 } else {850 } else {
835 return p.addNode(.{851 return try p.addNode(.{
836 .tag = .global_var_decl,852 .tag = .global_var_decl,
837 .main_token = mut_token,853 .main_token = mut_token,
838 .data = .{854 .data = .{
839 .lhs = try p.addExtra(Node.GlobalVarDecl{855 .extra_and_opt_node = .{
840 .type_node = type_node,856 try p.addExtra(Node.GlobalVarDecl{
841 .align_node = align_node,857 .type_node = .fromOptional(opt_type_node),
842 .addrspace_node = addrspace_node,858 .align_node = .fromOptional(opt_align_node),
843 .section_node = section_node,859 .addrspace_node = .fromOptional(opt_addrspace_node),
844 }),860 .section_node = .fromOptional(opt_section_node),
845 .rhs = 0,861 }),
862 .none, // set later with `setVarDeclInitExpr
863 },
846 },864 },
847 });865 });
848 }866 }
849}867}
850868
851/// GlobalVarDecl <- VarDeclProto (EQUAL Expr?) SEMICOLON869/// GlobalVarDecl <- VarDeclProto (EQUAL Expr?) SEMICOLON
852fn parseGlobalVarDecl(p: *Parse) !Node.Index {870fn parseGlobalVarDecl(p: *Parse) !?Node.Index {
853 const var_decl = try p.parseVarDeclProto();871 const var_decl = try p.parseVarDeclProto() orelse return null;
854 if (var_decl == 0) {
855 return null_node;
856 }
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)) {
859 .equal_equal => blk: {874 .equal_equal => blk: {
860 try p.warn(.wrong_equal_var_decl);875 try p.warn(.wrong_equal_var_decl);
861 p.tok_i += 1;876 p.tok_i += 1;
...@@ -865,10 +880,10 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {...@@ -865,10 +880,10 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {
865 p.tok_i += 1;880 p.tok_i += 1;
866 break :blk try p.expectExpr();881 break :blk try p.expectExpr();
867 },882 },
868 else => 0,883 else => null,
869 };884 };
870885
871 p.nodes.items(.data)[var_decl].rhs = init_node;886 p.setVarDeclInitExpr(var_decl, .fromOptional(init_node));
872887
873 try p.expectSemicolon(.expected_semi_after_decl, false);888 try p.expectSemicolon(.expected_semi_after_decl, false);
874 return var_decl;889 return var_decl;
...@@ -878,40 +893,39 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {...@@ -878,40 +893,39 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index {
878fn expectContainerField(p: *Parse) !Node.Index {893fn expectContainerField(p: *Parse) !Node.Index {
879 _ = p.eatToken(.keyword_comptime);894 _ = p.eatToken(.keyword_comptime);
880 const main_token = p.tok_i;895 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 });
882 const type_expr = try p.expectTypeExpr();897 const type_expr = try p.expectTypeExpr();
883 const align_expr = try p.parseByteAlign();898 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) {
887 return p.addNode(.{902 return p.addNode(.{
888 .tag = .container_field_init,903 .tag = .container_field_init,
889 .main_token = main_token,904 .main_token = main_token,
890 .data = .{905 .data = .{ .node_and_opt_node = .{
891 .lhs = type_expr,906 type_expr,
892 .rhs = value_expr,907 .fromOptional(value_expr),
893 },908 } },
894 });909 });
895 } else if (value_expr == 0) {910 } else if (value_expr == null) {
896 return p.addNode(.{911 return p.addNode(.{
897 .tag = .container_field_align,912 .tag = .container_field_align,
898 .main_token = main_token,913 .main_token = main_token,
899 .data = .{914 .data = .{ .node_and_node = .{
900 .lhs = type_expr,915 type_expr,
901 .rhs = align_expr,916 align_expr.?,
902 },917 } },
903 });918 });
904 } else {919 } else {
905 return p.addNode(.{920 return p.addNode(.{
906 .tag = .container_field,921 .tag = .container_field,
907 .main_token = main_token,922 .main_token = main_token,
908 .data = .{923 .data = .{ .node_and_extra = .{
909 .lhs = type_expr,924 type_expr, try p.addExtra(Node.ContainerField{
910 .rhs = try p.addExtra(Node.ContainerField{925 .align_expr = align_expr.?,
911 .align_expr = align_expr,926 .value_expr = value_expr.?,
912 .value_expr = value_expr,
913 }),927 }),
914 },928 } },
915 });929 });
916 }930 }
917}931}
...@@ -927,15 +941,12 @@ fn expectContainerField(p: *Parse) !Node.Index {...@@ -927,15 +941,12 @@ fn expectContainerField(p: *Parse) !Node.Index {
927/// / VarDeclExprStatement941/// / VarDeclExprStatement
928fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {942fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
929 if (p.eatToken(.keyword_comptime)) |comptime_token| {943 if (p.eatToken(.keyword_comptime)) |comptime_token| {
930 const block_expr = try p.parseBlockExpr();944 const opt_block_expr = try p.parseBlockExpr();
931 if (block_expr != 0) {945 if (opt_block_expr) |block_expr| {
932 return p.addNode(.{946 return p.addNode(.{
933 .tag = .@"comptime",947 .tag = .@"comptime",
934 .main_token = comptime_token,948 .main_token = comptime_token,
935 .data = .{949 .data = .{ .node = block_expr },
936 .lhs = block_expr,
937 .rhs = undefined,
938 },
939 });950 });
940 }951 }
941952
...@@ -947,23 +958,17 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {...@@ -947,23 +958,17 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
947 return p.addNode(.{958 return p.addNode(.{
948 .tag = .@"comptime",959 .tag = .@"comptime",
949 .main_token = comptime_token,960 .main_token = comptime_token,
950 .data = .{961 .data = .{ .node = assign },
951 .lhs = assign,
952 .rhs = undefined,
953 },
954 });962 });
955 }963 }
956 }964 }
957965
958 switch (p.token_tags[p.tok_i]) {966 switch (p.tokenTag(p.tok_i)) {
959 .keyword_nosuspend => {967 .keyword_nosuspend => {
960 return p.addNode(.{968 return p.addNode(.{
961 .tag = .@"nosuspend",969 .tag = .@"nosuspend",
962 .main_token = p.nextToken(),970 .main_token = p.nextToken(),
963 .data = .{971 .data = .{ .node = try p.expectBlockExprStatement() },
964 .lhs = try p.expectBlockExprStatement(),
965 .rhs = undefined,
966 },
967 });972 });
968 },973 },
969 .keyword_suspend => {974 .keyword_suspend => {
...@@ -972,27 +977,21 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {...@@ -972,27 +977,21 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
972 return p.addNode(.{977 return p.addNode(.{
973 .tag = .@"suspend",978 .tag = .@"suspend",
974 .main_token = token,979 .main_token = token,
975 .data = .{980 .data = .{ .node = block_expr },
976 .lhs = block_expr,
977 .rhs = undefined,
978 },
979 });981 });
980 },982 },
981 .keyword_defer => if (allow_defer_var) return p.addNode(.{983 .keyword_defer => if (allow_defer_var) return p.addNode(.{
982 .tag = .@"defer",984 .tag = .@"defer",
983 .main_token = p.nextToken(),985 .main_token = p.nextToken(),
984 .data = .{986 .data = .{ .node = try p.expectBlockExprStatement() },
985 .lhs = undefined,
986 .rhs = try p.expectBlockExprStatement(),
987 },
988 }),987 }),
989 .keyword_errdefer => if (allow_defer_var) return p.addNode(.{988 .keyword_errdefer => if (allow_defer_var) return p.addNode(.{
990 .tag = .@"errdefer",989 .tag = .@"errdefer",
991 .main_token = p.nextToken(),990 .main_token = p.nextToken(),
992 .data = .{991 .data = .{ .opt_token_and_node = .{
993 .lhs = try p.parsePayload(),992 try p.parsePayload(),
994 .rhs = try p.expectBlockExprStatement(),993 try p.expectBlockExprStatement(),
995 },994 } },
996 }),995 }),
997 .keyword_if => return p.expectIfStatement(),996 .keyword_if => return p.expectIfStatement(),
998 .keyword_enum, .keyword_struct, .keyword_union => {997 .keyword_enum, .keyword_struct, .keyword_union => {
...@@ -1002,18 +1001,14 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {...@@ -1002,18 +1001,14 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
1002 return p.addNode(.{1001 return p.addNode(.{
1003 .tag = .identifier,1002 .tag = .identifier,
1004 .main_token = identifier,1003 .main_token = identifier,
1005 .data = .{1004 .data = undefined,
1006 .lhs = undefined,
1007 .rhs = undefined,
1008 },
1009 });1005 });
1010 }1006 }
1011 },1007 },
1012 else => {},1008 else => {},
1013 }1009 }
10141010
1015 const labeled_statement = try p.parseLabeledStatement();1011 if (try p.parseLabeledStatement()) |labeled_statement| return labeled_statement;
1016 if (labeled_statement != 0) return labeled_statement;
10171012
1018 if (allow_defer_var) {1013 if (allow_defer_var) {
1019 return p.expectVarDeclExprStatement(null);1014 return p.expectVarDeclExprStatement(null);
...@@ -1028,12 +1023,15 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {...@@ -1028,12 +1023,15 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index {
1028/// <- BlockExpr1023/// <- BlockExpr
1029/// / VarDeclExprStatement1024/// / VarDeclExprStatement
1030fn expectComptimeStatement(p: *Parse, comptime_token: TokenIndex) !Node.Index {1025fn expectComptimeStatement(p: *Parse, comptime_token: TokenIndex) !Node.Index {
1031 const block_expr = try p.parseBlockExpr();1026 const maybe_block_expr = try p.parseBlockExpr();
1032 if (block_expr != 0) {1027 if (maybe_block_expr) |block_expr| {
1033 return p.addNode(.{1028 return p.addNode(.{
1034 .tag = .@"comptime",1029 .tag = .@"comptime",
1035 .main_token = comptime_token,1030 .main_token = comptime_token,
1036 .data = .{ .lhs = block_expr, .rhs = undefined },1031 .data = .{
1032 .lhs = .{ .node = block_expr },
1033 .rhs = undefined,
1034 },
1037 });1035 });
1038 }1036 }
1039 return p.expectVarDeclExprStatement(comptime_token);1037 return p.expectVarDeclExprStatement(comptime_token);
...@@ -1047,12 +1045,11 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1047,12 +1045,11 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
1047 defer p.scratch.shrinkRetainingCapacity(scratch_top);1045 defer p.scratch.shrinkRetainingCapacity(scratch_top);
10481046
1049 while (true) {1047 while (true) {
1050 const var_decl_proto = try p.parseVarDeclProto();1048 const opt_var_decl_proto = try p.parseVarDeclProto();
1051 if (var_decl_proto != 0) {1049 if (opt_var_decl_proto) |var_decl| {
1052 try p.scratch.append(p.gpa, var_decl_proto);1050 try p.scratch.append(p.gpa, var_decl);
1053 } else {1051 } else {
1054 const expr = try p.parseExpr();1052 const expr = try p.parseExpr() orelse {
1055 if (expr == 0) {
1056 if (p.scratch.items.len == scratch_top) {1053 if (p.scratch.items.len == scratch_top) {
1057 // We parsed nothing1054 // We parsed nothing
1058 return p.fail(.expected_statement);1055 return p.fail(.expected_statement);
...@@ -1060,7 +1057,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1060,7 +1057,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
1060 // We've had at least one LHS, but had a bad comma1057 // We've had at least one LHS, but had a bad comma
1061 return p.fail(.expected_expr_or_var_decl);1058 return p.fail(.expected_expr_or_var_decl);
1062 }1059 }
1063 }1060 };
1064 try p.scratch.append(p.gpa, expr);1061 try p.scratch.append(p.gpa, expr);
1065 }1062 }
1066 _ = p.eatToken(.comma) orelse break;1063 _ = p.eatToken(.comma) orelse break;
...@@ -1079,7 +1076,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1079,7 +1076,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
1079 return p.failExpected(.equal);1076 return p.failExpected(.equal);
1080 }1077 }
1081 const lhs = p.scratch.items[scratch_top];1078 const lhs = p.scratch.items[scratch_top];
1082 switch (p.nodes.items(.tag)[lhs]) {1079 switch (p.nodeTag(lhs)) {
1083 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {1080 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {
1084 // Definitely a var decl, so allow recovering from ==1081 // Definitely a var decl, so allow recovering from ==
1085 if (p.eatToken(.equal_equal)) |tok| {1082 if (p.eatToken(.equal_equal)) |tok| {
...@@ -1097,10 +1094,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1097,10 +1094,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
1097 return p.addNode(.{1094 return p.addNode(.{
1098 .tag = .@"comptime",1095 .tag = .@"comptime",
1099 .main_token = t,1096 .main_token = t,
1100 .data = .{1097 .data = .{ .node = expr },
1101 .lhs = expr,
1102 .rhs = undefined,
1103 },
1104 });1098 });
1105 } else {1099 } else {
1106 return expr;1100 return expr;
...@@ -1112,9 +1106,9 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1112,9 +1106,9 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
11121106
1113 if (lhs_count == 1) {1107 if (lhs_count == 1) {
1114 const lhs = p.scratch.items[scratch_top];1108 const lhs = p.scratch.items[scratch_top];
1115 switch (p.nodes.items(.tag)[lhs]) {1109 switch (p.nodeTag(lhs)) {
1116 .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => {1110 .simple_var_decl, .aligned_var_decl, .local_var_decl, .global_var_decl => {
1117 p.nodes.items(.data)[lhs].rhs = rhs;1111 p.setVarDeclInitExpr(lhs, rhs.toOptional());
1118 // Don't need to wrap in comptime1112 // Don't need to wrap in comptime
1119 return lhs;1113 return lhs;
1120 },1114 },
...@@ -1123,16 +1117,16 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1123,16 +1117,16 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
1123 const expr = try p.addNode(.{1117 const expr = try p.addNode(.{
1124 .tag = .assign,1118 .tag = .assign,
1125 .main_token = equal_token,1119 .main_token = equal_token,
1126 .data = .{ .lhs = lhs, .rhs = rhs },1120 .data = .{ .node_and_node = .{
1121 lhs,
1122 rhs,
1123 } },
1127 });1124 });
1128 if (comptime_token) |t| {1125 if (comptime_token) |t| {
1129 return p.addNode(.{1126 return p.addNode(.{
1130 .tag = .@"comptime",1127 .tag = .@"comptime",
1131 .main_token = t,1128 .main_token = t,
1132 .data = .{1129 .data = .{ .node = expr },
1133 .lhs = expr,
1134 .rhs = undefined,
1135 },
1136 });1130 });
1137 } else {1131 } else {
1138 return expr;1132 return expr;
...@@ -1141,32 +1135,32 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde...@@ -1141,32 +1135,32 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde
11411135
1142 // An actual destructure! No need for any `comptime` wrapper here.1136 // 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);
1145 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);1139 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);
1146 p.extra_data.appendAssumeCapacity(@intCast(lhs_count));1140 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
1149 return p.addNode(.{1143 return p.addNode(.{
1150 .tag = .assign_destructure,1144 .tag = .assign_destructure,
1151 .main_token = equal_token,1145 .main_token = equal_token,
1152 .data = .{1146 .data = .{ .extra_and_node = .{
1153 .lhs = @intCast(extra_start),1147 extra_start,
1154 .rhs = rhs,1148 rhs,
1155 },1149 } },
1156 });1150 });
1157}1151}
11581152
1159/// If a parse error occurs, reports an error, but then finds the next statement1153/// If a parse error occurs, reports an error, but then finds the next statement
1160/// and returns that one instead. If a parse error occurs but there is no following1154/// and returns that one instead. If a parse error occurs but there is no following
1161/// statement, returns 0.1155/// statement, returns 0.
1162fn expectStatementRecoverable(p: *Parse) Error!Node.Index {1156fn expectStatementRecoverable(p: *Parse) Error!?Node.Index {
1163 while (true) {1157 while (true) {
1164 return p.expectStatement(true) catch |err| switch (err) {1158 return p.expectStatement(true) catch |err| switch (err) {
1165 error.OutOfMemory => return error.OutOfMemory,1159 error.OutOfMemory => return error.OutOfMemory,
1166 error.ParseError => {1160 error.ParseError => {
1167 p.findNextStmt(); // Try to skip to the next statement.1161 p.findNextStmt(); // Try to skip to the next statement.
1168 switch (p.token_tags[p.tok_i]) {1162 switch (p.tokenTag(p.tok_i)) {
1169 .r_brace => return null_node,1163 .r_brace => return null,
1170 .eof => return error.ParseError,1164 .eof => return error.ParseError,
1171 else => continue,1165 else => continue,
1172 }1166 }
...@@ -1190,19 +1184,18 @@ fn expectIfStatement(p: *Parse) !Node.Index {...@@ -1190,19 +1184,18 @@ fn expectIfStatement(p: *Parse) !Node.Index {
1190 var else_required = false;1184 var else_required = false;
1191 const then_expr = blk: {1185 const then_expr = blk: {
1192 const block_expr = try p.parseBlockExpr();1186 const block_expr = try p.parseBlockExpr();
1193 if (block_expr != 0) break :blk block_expr;1187 if (block_expr) |block| break :blk block;
1194 const assign_expr = try p.parseAssignExpr();1188 const assign_expr = try p.parseAssignExpr() orelse {
1195 if (assign_expr == 0) {
1196 return p.fail(.expected_block_or_assignment);1189 return p.fail(.expected_block_or_assignment);
1197 }1190 };
1198 if (p.eatToken(.semicolon)) |_| {1191 if (p.eatToken(.semicolon)) |_| {
1199 return p.addNode(.{1192 return p.addNode(.{
1200 .tag = .if_simple,1193 .tag = .if_simple,
1201 .main_token = if_token,1194 .main_token = if_token,
1202 .data = .{1195 .data = .{ .node_and_node = .{
1203 .lhs = condition,1196 condition,
1204 .rhs = assign_expr,1197 assign_expr,
1205 },1198 } },
1206 });1199 });
1207 }1200 }
1208 else_required = true;1201 else_required = true;
...@@ -1215,10 +1208,10 @@ fn expectIfStatement(p: *Parse) !Node.Index {...@@ -1215,10 +1208,10 @@ fn expectIfStatement(p: *Parse) !Node.Index {
1215 return p.addNode(.{1208 return p.addNode(.{
1216 .tag = .if_simple,1209 .tag = .if_simple,
1217 .main_token = if_token,1210 .main_token = if_token,
1218 .data = .{1211 .data = .{ .node_and_node = .{
1219 .lhs = condition,1212 condition,
1220 .rhs = then_expr,1213 then_expr,
1221 },1214 } },
1222 });1215 });
1223 };1216 };
1224 _ = try p.parsePayload();1217 _ = try p.parsePayload();
...@@ -1226,57 +1219,46 @@ fn expectIfStatement(p: *Parse) !Node.Index {...@@ -1226,57 +1219,46 @@ fn expectIfStatement(p: *Parse) !Node.Index {
1226 return p.addNode(.{1219 return p.addNode(.{
1227 .tag = .@"if",1220 .tag = .@"if",
1228 .main_token = if_token,1221 .main_token = if_token,
1229 .data = .{1222 .data = .{ .node_and_extra = .{
1230 .lhs = condition,1223 condition, try p.addExtra(Node.If{
1231 .rhs = try p.addExtra(Node.If{
1232 .then_expr = then_expr,1224 .then_expr = then_expr,
1233 .else_expr = else_expr,1225 .else_expr = else_expr,
1234 }),1226 }),
1235 },1227 } },
1236 });1228 });
1237}1229}
12381230
1239/// LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr)1231/// LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr)
1240fn parseLabeledStatement(p: *Parse) !Node.Index {1232fn parseLabeledStatement(p: *Parse) !?Node.Index {
1241 const label_token = p.parseBlockLabel();1233 const opt_label_token = p.parseBlockLabel();
1242 const block = try p.parseBlock();1234
1243 if (block != 0) return block;1235 if (try p.parseBlock()) |block| return block;
12441236 if (try p.parseLoopStatement()) |loop_stmt| return loop_stmt;
1245 const loop_stmt = try p.parseLoopStatement();1237 if (try p.parseSwitchExpr(opt_label_token != null)) |switch_expr| return switch_expr;
1246 if (loop_stmt != 0) return loop_stmt;1238
12471239 const label_token = opt_label_token orelse return null;
1248 const switch_expr = try p.parseSwitchExpr(label_token != 0);1240
1249 if (switch_expr != 0) return switch_expr;1241 const after_colon = p.tok_i;
12501242 if (try p.parseTypeExpr()) |_| {
1251 if (label_token != 0) {1243 const a = try p.parseByteAlign();
1252 const after_colon = p.tok_i;1244 const b = try p.parseAddrSpace();
1253 const node = try p.parseTypeExpr();1245 const c = try p.parseLinkSection();
1254 if (node != 0) {1246 const d = if (p.eatToken(.equal) == null) null else try p.expectExpr();
1255 const a = try p.parseByteAlign();1247 if (a != null or b != null or c != null or d != null) {
1256 const b = try p.parseAddrSpace();1248 return p.failMsg(.{ .tag = .expected_var_const, .token = label_token });
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 }
1262 }1249 }
1263 return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
1264 }1250 }
12651251 return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon });
1266 return null_node;
1267}1252}
12681253
1269/// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)1254/// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
1270fn parseLoopStatement(p: *Parse) !Node.Index {1255fn parseLoopStatement(p: *Parse) !?Node.Index {
1271 const inline_token = p.eatToken(.keyword_inline);1256 const inline_token = p.eatToken(.keyword_inline);
12721257
1273 const for_statement = try p.parseForStatement();1258 if (try p.parseForStatement()) |for_statement| return for_statement;
1274 if (for_statement != 0) return for_statement;1259 if (try p.parseWhileStatement()) |while_statement| return while_statement;
12751260
1276 const while_statement = try p.parseWhileStatement();1261 if (inline_token == null) return null;
1277 if (while_statement != 0) return while_statement;
1278
1279 if (inline_token == null) return null_node;
12801262
1281 // If we've seen "inline", there should have been a "for" or "while"1263 // If we've seen "inline", there should have been a "for" or "while"
1282 return p.fail(.expected_inlinable);1264 return p.fail(.expected_inlinable);
...@@ -1285,8 +1267,8 @@ fn parseLoopStatement(p: *Parse) !Node.Index {...@@ -1285,8 +1267,8 @@ fn parseLoopStatement(p: *Parse) !Node.Index {
1285/// ForStatement1267/// ForStatement
1286/// <- ForPrefix BlockExpr ( KEYWORD_else Statement )?1268/// <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
1287/// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )1269/// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
1288fn parseForStatement(p: *Parse) !Node.Index {1270fn parseForStatement(p: *Parse) !?Node.Index {
1289 const for_token = p.eatToken(.keyword_for) orelse return null_node;1271 const for_token = p.eatToken(.keyword_for) orelse return null;
12901272
1291 const scratch_top = p.scratch.items.len;1273 const scratch_top = p.scratch.items.len;
1292 defer p.scratch.shrinkRetainingCapacity(scratch_top);1274 defer p.scratch.shrinkRetainingCapacity(scratch_top);
...@@ -1296,11 +1278,10 @@ fn parseForStatement(p: *Parse) !Node.Index {...@@ -1296,11 +1278,10 @@ fn parseForStatement(p: *Parse) !Node.Index {
1296 var seen_semicolon = false;1278 var seen_semicolon = false;
1297 const then_expr = blk: {1279 const then_expr = blk: {
1298 const block_expr = try p.parseBlockExpr();1280 const block_expr = try p.parseBlockExpr();
1299 if (block_expr != 0) break :blk block_expr;1281 if (block_expr) |block| break :blk block;
1300 const assign_expr = try p.parseAssignExpr();1282 const assign_expr = try p.parseAssignExpr() orelse {
1301 if (assign_expr == 0) {
1302 return p.fail(.expected_block_or_assignment);1283 return p.fail(.expected_block_or_assignment);
1303 }1284 };
1304 if (p.eatToken(.semicolon)) |_| {1285 if (p.eatToken(.semicolon)) |_| {
1305 seen_semicolon = true;1286 seen_semicolon = true;
1306 break :blk assign_expr;1287 break :blk assign_expr;
...@@ -1316,28 +1297,25 @@ fn parseForStatement(p: *Parse) !Node.Index {...@@ -1316,28 +1297,25 @@ fn parseForStatement(p: *Parse) !Node.Index {
1316 has_else = true;1297 has_else = true;
1317 } else if (inputs == 1) {1298 } else if (inputs == 1) {
1318 if (else_required) try p.warn(.expected_semi_or_else);1299 if (else_required) try p.warn(.expected_semi_or_else);
1319 return p.addNode(.{1300 return try p.addNode(.{
1320 .tag = .for_simple,1301 .tag = .for_simple,
1321 .main_token = for_token,1302 .main_token = for_token,
1322 .data = .{1303 .data = .{ .node_and_node = .{
1323 .lhs = p.scratch.items[scratch_top],1304 p.scratch.items[scratch_top],
1324 .rhs = then_expr,1305 then_expr,
1325 },1306 } },
1326 });1307 });
1327 } else {1308 } else {
1328 if (else_required) try p.warn(.expected_semi_or_else);1309 if (else_required) try p.warn(.expected_semi_or_else);
1329 try p.scratch.append(p.gpa, then_expr);1310 try p.scratch.append(p.gpa, then_expr);
1330 }1311 }
1331 return p.addNode(.{1312 return try p.addNode(.{
1332 .tag = .@"for",1313 .tag = .@"for",
1333 .main_token = for_token,1314 .main_token = for_token,
1334 .data = .{1315 .data = .{ .@"for" = .{
1335 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,1316 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
1336 .rhs = @as(u32, @bitCast(Node.For{1317 .{ .inputs = @intCast(inputs), .has_else = has_else },
1337 .inputs = @as(u31, @intCast(inputs)),1318 } },
1338 .has_else = has_else,
1339 })),
1340 },
1341 });1319 });
1342}1320}
13431321
...@@ -1346,8 +1324,8 @@ fn parseForStatement(p: *Parse) !Node.Index {...@@ -1346,8 +1324,8 @@ fn parseForStatement(p: *Parse) !Node.Index {
1346/// WhileStatement1324/// WhileStatement
1347/// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?1325/// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
1348/// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )1326/// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
1349fn parseWhileStatement(p: *Parse) !Node.Index {1327fn parseWhileStatement(p: *Parse) !?Node.Index {
1350 const while_token = p.eatToken(.keyword_while) orelse return null_node;1328 const while_token = p.eatToken(.keyword_while) orelse return null;
1351 _ = try p.expectToken(.l_paren);1329 _ = try p.expectToken(.l_paren);
1352 const condition = try p.expectExpr();1330 const condition = try p.expectExpr();
1353 _ = try p.expectToken(.r_paren);1331 _ = try p.expectToken(.r_paren);
...@@ -1359,32 +1337,31 @@ fn parseWhileStatement(p: *Parse) !Node.Index {...@@ -1359,32 +1337,31 @@ fn parseWhileStatement(p: *Parse) !Node.Index {
1359 var else_required = false;1337 var else_required = false;
1360 const then_expr = blk: {1338 const then_expr = blk: {
1361 const block_expr = try p.parseBlockExpr();1339 const block_expr = try p.parseBlockExpr();
1362 if (block_expr != 0) break :blk block_expr;1340 if (block_expr) |block| break :blk block;
1363 const assign_expr = try p.parseAssignExpr();1341 const assign_expr = try p.parseAssignExpr() orelse {
1364 if (assign_expr == 0) {
1365 return p.fail(.expected_block_or_assignment);1342 return p.fail(.expected_block_or_assignment);
1366 }1343 };
1367 if (p.eatToken(.semicolon)) |_| {1344 if (p.eatToken(.semicolon)) |_| {
1368 if (cont_expr == 0) {1345 if (cont_expr == null) {
1369 return p.addNode(.{1346 return try p.addNode(.{
1370 .tag = .while_simple,1347 .tag = .while_simple,
1371 .main_token = while_token,1348 .main_token = while_token,
1372 .data = .{1349 .data = .{ .node_and_node = .{
1373 .lhs = condition,1350 condition,
1374 .rhs = assign_expr,1351 assign_expr,
1375 },1352 } },
1376 });1353 });
1377 } else {1354 } else {
1378 return p.addNode(.{1355 return try p.addNode(.{
1379 .tag = .while_cont,1356 .tag = .while_cont,
1380 .main_token = while_token,1357 .main_token = while_token,
1381 .data = .{1358 .data = .{ .node_and_extra = .{
1382 .lhs = condition,1359 condition,
1383 .rhs = try p.addExtra(Node.WhileCont{1360 try p.addExtra(Node.WhileCont{
1384 .cont_expr = cont_expr,1361 .cont_expr = cont_expr.?,
1385 .then_expr = assign_expr,1362 .then_expr = assign_expr,
1386 }),1363 }),
1387 },1364 } },
1388 });1365 });
1389 }1366 }
1390 }1367 }
...@@ -1395,84 +1372,77 @@ fn parseWhileStatement(p: *Parse) !Node.Index {...@@ -1395,84 +1372,77 @@ fn parseWhileStatement(p: *Parse) !Node.Index {
1395 if (else_required) {1372 if (else_required) {
1396 try p.warn(.expected_semi_or_else);1373 try p.warn(.expected_semi_or_else);
1397 }1374 }
1398 if (cont_expr == 0) {1375 if (cont_expr == null) {
1399 return p.addNode(.{1376 return try p.addNode(.{
1400 .tag = .while_simple,1377 .tag = .while_simple,
1401 .main_token = while_token,1378 .main_token = while_token,
1402 .data = .{1379 .data = .{ .node_and_node = .{
1403 .lhs = condition,1380 condition,
1404 .rhs = then_expr,1381 then_expr,
1405 },1382 } },
1406 });1383 });
1407 } else {1384 } else {
1408 return p.addNode(.{1385 return try p.addNode(.{
1409 .tag = .while_cont,1386 .tag = .while_cont,
1410 .main_token = while_token,1387 .main_token = while_token,
1411 .data = .{1388 .data = .{ .node_and_extra = .{
1412 .lhs = condition,1389 condition,
1413 .rhs = try p.addExtra(Node.WhileCont{1390 try p.addExtra(Node.WhileCont{
1414 .cont_expr = cont_expr,1391 .cont_expr = cont_expr.?,
1415 .then_expr = then_expr,1392 .then_expr = then_expr,
1416 }),1393 }),
1417 },1394 } },
1418 });1395 });
1419 }1396 }
1420 };1397 };
1421 _ = try p.parsePayload();1398 _ = try p.parsePayload();
1422 const else_expr = try p.expectStatement(false);1399 const else_expr = try p.expectStatement(false);
1423 return p.addNode(.{1400 return try p.addNode(.{
1424 .tag = .@"while",1401 .tag = .@"while",
1425 .main_token = while_token,1402 .main_token = while_token,
1426 .data = .{1403 .data = .{ .node_and_extra = .{
1427 .lhs = condition,1404 condition, try p.addExtra(Node.While{
1428 .rhs = try p.addExtra(Node.While{1405 .cont_expr = .fromOptional(cont_expr),
1429 .cont_expr = cont_expr,
1430 .then_expr = then_expr,1406 .then_expr = then_expr,
1431 .else_expr = else_expr,1407 .else_expr = else_expr,
1432 }),1408 }),
1433 },1409 } },
1434 });1410 });
1435}1411}
14361412
1437/// BlockExprStatement1413/// BlockExprStatement
1438/// <- BlockExpr1414/// <- BlockExpr
1439/// / AssignExpr SEMICOLON1415/// / AssignExpr SEMICOLON
1440fn parseBlockExprStatement(p: *Parse) !Node.Index {1416fn parseBlockExprStatement(p: *Parse) !?Node.Index {
1441 const block_expr = try p.parseBlockExpr();1417 const block_expr = try p.parseBlockExpr();
1442 if (block_expr != 0) {1418 if (block_expr) |expr| return expr;
1443 return block_expr;
1444 }
1445 const assign_expr = try p.parseAssignExpr();1419 const assign_expr = try p.parseAssignExpr();
1446 if (assign_expr != 0) {1420 if (assign_expr) |expr| {
1447 try p.expectSemicolon(.expected_semi_after_stmt, true);1421 try p.expectSemicolon(.expected_semi_after_stmt, true);
1448 return assign_expr;1422 return expr;
1449 }1423 }
1450 return null_node;1424 return null;
1451}1425}
14521426
1453fn expectBlockExprStatement(p: *Parse) !Node.Index {1427fn expectBlockExprStatement(p: *Parse) !Node.Index {
1454 const node = try p.parseBlockExprStatement();1428 return try p.parseBlockExprStatement() orelse return p.fail(.expected_block_or_expr);
1455 if (node == 0) {
1456 return p.fail(.expected_block_or_expr);
1457 }
1458 return node;
1459}1429}
14601430
1461/// BlockExpr <- BlockLabel? Block1431/// BlockExpr <- BlockLabel? Block
1462fn parseBlockExpr(p: *Parse) Error!Node.Index {1432fn parseBlockExpr(p: *Parse) Error!?Node.Index {
1463 switch (p.token_tags[p.tok_i]) {1433 switch (p.tokenTag(p.tok_i)) {
1464 .identifier => {1434 .identifier => {
1465 if (p.token_tags[p.tok_i + 1] == .colon and1435 if (p.tokenTag(p.tok_i + 1) == .colon and
1466 p.token_tags[p.tok_i + 2] == .l_brace)1436 p.tokenTag(p.tok_i + 2) == .l_brace)
1467 {1437 {
1468 p.tok_i += 2;1438 p.tok_i += 2;
1469 return p.parseBlock();1439 return p.parseBlock();
1470 } else {1440 } else {
1471 return null_node;1441 return null;
1472 }1442 }
1473 },1443 },
1474 .l_brace => return p.parseBlock(),1444 .l_brace => return p.parseBlock(),
1475 else => return null_node,1445 else => return null,
1476 }1446 }
1477}1447}
14781448
...@@ -1497,38 +1467,36 @@ fn parseBlockExpr(p: *Parse) Error!Node.Index {...@@ -1497,38 +1467,36 @@ fn parseBlockExpr(p: *Parse) Error!Node.Index {
1497/// / PLUSPERCENTEQUAL1467/// / PLUSPERCENTEQUAL
1498/// / MINUSPERCENTEQUAL1468/// / MINUSPERCENTEQUAL
1499/// / EQUAL1469/// / EQUAL
1500fn parseAssignExpr(p: *Parse) !Node.Index {1470fn parseAssignExpr(p: *Parse) !?Node.Index {
1501 const expr = try p.parseExpr();1471 const expr = try p.parseExpr() orelse return null;
1502 if (expr == 0) return null_node;1472 return try p.finishAssignExpr(expr);
1503 return p.finishAssignExpr(expr);
1504}1473}
15051474
1506/// SingleAssignExpr <- Expr (AssignOp Expr)?1475/// SingleAssignExpr <- Expr (AssignOp Expr)?
1507fn parseSingleAssignExpr(p: *Parse) !Node.Index {1476fn parseSingleAssignExpr(p: *Parse) !?Node.Index {
1508 const lhs = try p.parseExpr();1477 const lhs = try p.parseExpr() orelse return null;
1509 if (lhs == 0) return null_node;1478 const tag = assignOpNode(p.tokenTag(p.tok_i)) orelse return lhs;
1510 const tag = assignOpNode(p.token_tags[p.tok_i]) orelse return lhs;1479 return try p.addNode(.{
1511 return p.addNode(.{
1512 .tag = tag,1480 .tag = tag,
1513 .main_token = p.nextToken(),1481 .main_token = p.nextToken(),
1514 .data = .{1482 .data = .{ .node_and_node = .{
1515 .lhs = lhs,1483 lhs,
1516 .rhs = try p.expectExpr(),1484 try p.expectExpr(),
1517 },1485 } },
1518 });1486 });
1519}1487}
15201488
1521fn finishAssignExpr(p: *Parse, lhs: Node.Index) !Node.Index {1489fn 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);
1523 if (tok == .comma) return p.finishAssignDestructureExpr(lhs);1491 if (tok == .comma) return p.finishAssignDestructureExpr(lhs);
1524 const tag = assignOpNode(tok) orelse return lhs;1492 const tag = assignOpNode(tok) orelse return lhs;
1525 return p.addNode(.{1493 return p.addNode(.{
1526 .tag = tag,1494 .tag = tag,
1527 .main_token = p.nextToken(),1495 .main_token = p.nextToken(),
1528 .data = .{1496 .data = .{ .node_and_node = .{
1529 .lhs = lhs,1497 lhs,
1530 .rhs = try p.expectExpr(),1498 try p.expectExpr(),
1531 },1499 } },
1532 });1500 });
1533}1501}
15341502
...@@ -1574,48 +1542,35 @@ fn finishAssignDestructureExpr(p: *Parse, first_lhs: Node.Index) !Node.Index {...@@ -1574,48 +1542,35 @@ fn finishAssignDestructureExpr(p: *Parse, first_lhs: Node.Index) !Node.Index {
1574 const lhs_count = p.scratch.items.len - scratch_top;1542 const lhs_count = p.scratch.items.len - scratch_top;
1575 assert(lhs_count > 1); // we already had first_lhs, and must have at least one more lvalue1543 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);
1578 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);1546 try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1);
1579 p.extra_data.appendAssumeCapacity(@intCast(lhs_count));1547 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
1582 return p.addNode(.{1550 return p.addNode(.{
1583 .tag = .assign_destructure,1551 .tag = .assign_destructure,
1584 .main_token = equal_token,1552 .main_token = equal_token,
1585 .data = .{1553 .data = .{ .extra_and_node = .{
1586 .lhs = @intCast(extra_start),1554 extra_start,
1587 .rhs = rhs,1555 rhs,
1588 },1556 } },
1589 });1557 });
1590}1558}
15911559
1592fn expectSingleAssignExpr(p: *Parse) !Node.Index {1560fn expectSingleAssignExpr(p: *Parse) !Node.Index {
1593 const expr = try p.parseSingleAssignExpr();1561 return try p.parseSingleAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
1594 if (expr == 0) {
1595 return p.fail(.expected_expr_or_assignment);
1596 }
1597 return expr;
1598}1562}
15991563
1600fn expectAssignExpr(p: *Parse) !Node.Index {1564fn expectAssignExpr(p: *Parse) !Node.Index {
1601 const expr = try p.parseAssignExpr();1565 return try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
1602 if (expr == 0) {
1603 return p.fail(.expected_expr_or_assignment);
1604 }
1605 return expr;
1606}1566}
16071567
1608fn parseExpr(p: *Parse) Error!Node.Index {1568fn parseExpr(p: *Parse) Error!?Node.Index {
1609 return p.parseExprPrecedence(0);1569 return p.parseExprPrecedence(0);
1610}1570}
16111571
1612fn expectExpr(p: *Parse) Error!Node.Index {1572fn expectExpr(p: *Parse) Error!Node.Index {
1613 const node = try p.parseExpr();1573 return try p.parseExpr() orelse return p.fail(.expected_expr);
1614 if (node == 0) {
1615 return p.fail(.expected_expr);
1616 } else {
1617 return node;
1618 }
1619}1574}
16201575
1621const Assoc = enum {1576const Assoc = enum {
...@@ -1671,17 +1626,14 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec...@@ -1671,17 +1626,14 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec
1671 .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat },1626 .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat },
1672});1627});
16731628
1674fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {1629fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index {
1675 assert(min_prec >= 0);1630 assert(min_prec >= 0);
1676 var node = try p.parsePrefixExpr();1631 var node = try p.parsePrefixExpr() orelse return null;
1677 if (node == 0) {
1678 return null_node;
1679 }
16801632
1681 var banned_prec: i8 = -1;1633 var banned_prec: i8 = -1;
16821634
1683 while (true) {1635 while (true) {
1684 const tok_tag = p.token_tags[p.tok_i];1636 const tok_tag = p.tokenTag(p.tok_i);
1685 const info = operTable[@as(usize, @intCast(@intFromEnum(tok_tag)))];1637 const info = operTable[@as(usize, @intCast(@intFromEnum(tok_tag)))];
1686 if (info.prec < min_prec) {1638 if (info.prec < min_prec) {
1687 break;1639 break;
...@@ -1695,16 +1647,15 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {...@@ -1695,16 +1647,15 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
1695 if (tok_tag == .keyword_catch) {1647 if (tok_tag == .keyword_catch) {
1696 _ = try p.parsePayload();1648 _ = try p.parsePayload();
1697 }1649 }
1698 const rhs = try p.parseExprPrecedence(info.prec + 1);1650 const rhs = try p.parseExprPrecedence(info.prec + 1) orelse {
1699 if (rhs == 0) {
1700 try p.warn(.expected_expr);1651 try p.warn(.expected_expr);
1701 return node;1652 return node;
1702 }1653 };
17031654
1704 {1655 {
1705 const tok_len = tok_tag.lexeme().?.len;1656 const tok_len = tok_tag.lexeme().?.len;
1706 const char_before = p.source[p.token_starts[oper_token] - 1];1657 const char_before = p.source[p.tokenStart(oper_token) - 1];
1707 const char_after = p.source[p.token_starts[oper_token] + tok_len];1658 const char_after = p.source[p.tokenStart(oper_token) + tok_len];
1708 if (tok_tag == .ampersand and char_after == '&') {1659 if (tok_tag == .ampersand and char_after == '&') {
1709 // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and1660 // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and
1710 // The best the parser can do is recommend changing it to 'and' or ' & &'1661 // 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 {...@@ -1717,10 +1668,7 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
1717 node = try p.addNode(.{1668 node = try p.addNode(.{
1718 .tag = info.tag,1669 .tag = info.tag,
1719 .main_token = oper_token,1670 .main_token = oper_token,
1720 .data = .{1671 .data = .{ .node_and_node = .{ node, rhs } },
1721 .lhs = node,
1722 .rhs = rhs,
1723 },
1724 });1672 });
17251673
1726 if (info.assoc == Assoc.none) {1674 if (info.assoc == Assoc.none) {
...@@ -1741,8 +1689,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {...@@ -1741,8 +1689,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index {
1741/// / AMPERSAND1689/// / AMPERSAND
1742/// / KEYWORD_try1690/// / KEYWORD_try
1743/// / KEYWORD_await1691/// / KEYWORD_await
1744fn parsePrefixExpr(p: *Parse) Error!Node.Index {1692fn parsePrefixExpr(p: *Parse) Error!?Node.Index {
1745 const tag: Node.Tag = switch (p.token_tags[p.tok_i]) {1693 const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) {
1746 .bang => .bool_not,1694 .bang => .bool_not,
1747 .minus => .negation,1695 .minus => .negation,
1748 .tilde => .bit_not,1696 .tilde => .bit_not,
...@@ -1752,22 +1700,15 @@ fn parsePrefixExpr(p: *Parse) Error!Node.Index {...@@ -1752,22 +1700,15 @@ fn parsePrefixExpr(p: *Parse) Error!Node.Index {
1752 .keyword_await => .@"await",1700 .keyword_await => .@"await",
1753 else => return p.parsePrimaryExpr(),1701 else => return p.parsePrimaryExpr(),
1754 };1702 };
1755 return p.addNode(.{1703 return try p.addNode(.{
1756 .tag = tag,1704 .tag = tag,
1757 .main_token = p.nextToken(),1705 .main_token = p.nextToken(),
1758 .data = .{1706 .data = .{ .node = try p.expectPrefixExpr() },
1759 .lhs = try p.expectPrefixExpr(),
1760 .rhs = undefined,
1761 },
1762 });1707 });
1763}1708}
17641709
1765fn expectPrefixExpr(p: *Parse) Error!Node.Index {1710fn expectPrefixExpr(p: *Parse) Error!Node.Index {
1766 const node = try p.parsePrefixExpr();1711 return try p.parsePrefixExpr() orelse return p.fail(.expected_prefix_expr);
1767 if (node == 0) {
1768 return p.fail(.expected_prefix_expr);
1769 }
1770 return node;
1771}1712}
17721713
1773/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr1714/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
...@@ -1787,67 +1728,64 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index {...@@ -1787,67 +1728,64 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index {
1787/// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET1728/// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
1788///1729///
1789/// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET1730/// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET
1790fn parseTypeExpr(p: *Parse) Error!Node.Index {1731fn parseTypeExpr(p: *Parse) Error!?Node.Index {
1791 switch (p.token_tags[p.tok_i]) {1732 switch (p.tokenTag(p.tok_i)) {
1792 .question_mark => return p.addNode(.{1733 .question_mark => return try p.addNode(.{
1793 .tag = .optional_type,1734 .tag = .optional_type,
1794 .main_token = p.nextToken(),1735 .main_token = p.nextToken(),
1795 .data = .{1736 .data = .{ .node = try p.expectTypeExpr() },
1796 .lhs = try p.expectTypeExpr(),
1797 .rhs = undefined,
1798 },
1799 }),1737 }),
1800 .keyword_anyframe => switch (p.token_tags[p.tok_i + 1]) {1738 .keyword_anyframe => switch (p.tokenTag(p.tok_i + 1)) {
1801 .arrow => return p.addNode(.{1739 .arrow => return try p.addNode(.{
1802 .tag = .anyframe_type,1740 .tag = .anyframe_type,
1803 .main_token = p.nextToken(),1741 .main_token = p.nextToken(),
1804 .data = .{1742 .data = .{ .token_and_node = .{
1805 .lhs = p.nextToken(),1743 p.nextToken(),
1806 .rhs = try p.expectTypeExpr(),1744 try p.expectTypeExpr(),
1807 },1745 } },
1808 }),1746 }),
1809 else => return p.parseErrorUnionExpr(),1747 else => return try p.parseErrorUnionExpr(),
1810 },1748 },
1811 .asterisk => {1749 .asterisk => {
1812 const asterisk = p.nextToken();1750 const asterisk = p.nextToken();
1813 const mods = try p.parsePtrModifiers();1751 const mods = try p.parsePtrModifiers();
1814 const elem_type = try p.expectTypeExpr();1752 const elem_type = try p.expectTypeExpr();
1815 if (mods.bit_range_start != 0) {1753 if (mods.bit_range_start != .none) {
1816 return p.addNode(.{1754 return try p.addNode(.{
1817 .tag = .ptr_type_bit_range,1755 .tag = .ptr_type_bit_range,
1818 .main_token = asterisk,1756 .main_token = asterisk,
1819 .data = .{1757 .data = .{ .extra_and_node = .{
1820 .lhs = try p.addExtra(Node.PtrTypeBitRange{1758 try p.addExtra(Node.PtrTypeBitRange{
1821 .sentinel = 0,1759 .sentinel = .none,
1822 .align_node = mods.align_node,1760 .align_node = mods.align_node.unwrap().?,
1823 .addrspace_node = mods.addrspace_node,1761 .addrspace_node = mods.addrspace_node,
1824 .bit_range_start = mods.bit_range_start,1762 .bit_range_start = mods.bit_range_start.unwrap().?,
1825 .bit_range_end = mods.bit_range_end,1763 .bit_range_end = mods.bit_range_end.unwrap().?,
1826 }),1764 }),
1827 .rhs = elem_type,1765 elem_type,
1828 },1766 } },
1829 });1767 });
1830 } else if (mods.addrspace_node != 0) {1768 } else if (mods.addrspace_node != .none) {
1831 return p.addNode(.{1769 return try p.addNode(.{
1832 .tag = .ptr_type,1770 .tag = .ptr_type,
1833 .main_token = asterisk,1771 .main_token = asterisk,
1834 .data = .{1772 .data = .{ .extra_and_node = .{
1835 .lhs = try p.addExtra(Node.PtrType{1773 try p.addExtra(Node.PtrType{
1836 .sentinel = 0,1774 .sentinel = .none,
1837 .align_node = mods.align_node,1775 .align_node = mods.align_node,
1838 .addrspace_node = mods.addrspace_node,1776 .addrspace_node = mods.addrspace_node,
1839 }),1777 }),
1840 .rhs = elem_type,1778 elem_type,
1841 },1779 } },
1842 });1780 });
1843 } else {1781 } else {
1844 return p.addNode(.{1782 return try p.addNode(.{
1845 .tag = .ptr_type_aligned,1783 .tag = .ptr_type_aligned,
1846 .main_token = asterisk,1784 .main_token = asterisk,
1847 .data = .{1785 .data = .{ .opt_node_and_node = .{
1848 .lhs = mods.align_node,1786 mods.align_node,
1849 .rhs = elem_type,1787 elem_type,
1850 },1788 } },
1851 });1789 });
1852 }1790 }
1853 },1791 },
...@@ -1856,61 +1794,61 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {...@@ -1856,61 +1794,61 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
1856 const mods = try p.parsePtrModifiers();1794 const mods = try p.parsePtrModifiers();
1857 const elem_type = try p.expectTypeExpr();1795 const elem_type = try p.expectTypeExpr();
1858 const inner: Node.Index = inner: {1796 const inner: Node.Index = inner: {
1859 if (mods.bit_range_start != 0) {1797 if (mods.bit_range_start != .none) {
1860 break :inner try p.addNode(.{1798 break :inner try p.addNode(.{
1861 .tag = .ptr_type_bit_range,1799 .tag = .ptr_type_bit_range,
1862 .main_token = asterisk,1800 .main_token = asterisk,
1863 .data = .{1801 .data = .{ .extra_and_node = .{
1864 .lhs = try p.addExtra(Node.PtrTypeBitRange{1802 try p.addExtra(Node.PtrTypeBitRange{
1865 .sentinel = 0,1803 .sentinel = .none,
1866 .align_node = mods.align_node,1804 .align_node = mods.align_node.unwrap().?,
1867 .addrspace_node = mods.addrspace_node,1805 .addrspace_node = mods.addrspace_node,
1868 .bit_range_start = mods.bit_range_start,1806 .bit_range_start = mods.bit_range_start.unwrap().?,
1869 .bit_range_end = mods.bit_range_end,1807 .bit_range_end = mods.bit_range_end.unwrap().?,
1870 }),1808 }),
1871 .rhs = elem_type,1809 elem_type,
1872 },1810 } },
1873 });1811 });
1874 } else if (mods.addrspace_node != 0) {1812 } else if (mods.addrspace_node != .none) {
1875 break :inner try p.addNode(.{1813 break :inner try p.addNode(.{
1876 .tag = .ptr_type,1814 .tag = .ptr_type,
1877 .main_token = asterisk,1815 .main_token = asterisk,
1878 .data = .{1816 .data = .{ .extra_and_node = .{
1879 .lhs = try p.addExtra(Node.PtrType{1817 try p.addExtra(Node.PtrType{
1880 .sentinel = 0,1818 .sentinel = .none,
1881 .align_node = mods.align_node,1819 .align_node = mods.align_node,
1882 .addrspace_node = mods.addrspace_node,1820 .addrspace_node = mods.addrspace_node,
1883 }),1821 }),
1884 .rhs = elem_type,1822 elem_type,
1885 },1823 } },
1886 });1824 });
1887 } else {1825 } else {
1888 break :inner try p.addNode(.{1826 break :inner try p.addNode(.{
1889 .tag = .ptr_type_aligned,1827 .tag = .ptr_type_aligned,
1890 .main_token = asterisk,1828 .main_token = asterisk,
1891 .data = .{1829 .data = .{ .opt_node_and_node = .{
1892 .lhs = mods.align_node,1830 mods.align_node,
1893 .rhs = elem_type,1831 elem_type,
1894 },1832 } },
1895 });1833 });
1896 }1834 }
1897 };1835 };
1898 return p.addNode(.{1836 return try p.addNode(.{
1899 .tag = .ptr_type_aligned,1837 .tag = .ptr_type_aligned,
1900 .main_token = asterisk,1838 .main_token = asterisk,
1901 .data = .{1839 .data = .{ .opt_node_and_node = .{
1902 .lhs = 0,1840 .none,
1903 .rhs = inner,1841 inner,
1904 },1842 } },
1905 });1843 });
1906 },1844 },
1907 .l_bracket => switch (p.token_tags[p.tok_i + 1]) {1845 .l_bracket => switch (p.tokenTag(p.tok_i + 1)) {
1908 .asterisk => {1846 .asterisk => {
1909 const l_bracket = p.nextToken();1847 const l_bracket = p.nextToken();
1910 _ = p.nextToken();1848 _ = p.nextToken();
1911 var sentinel: Node.Index = 0;1849 var sentinel: ?Node.Index = null;
1912 if (p.eatToken(.identifier)) |ident| {1850 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)];
1914 if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.whitespace), "c")) {1852 if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.whitespace), "c")) {
1915 p.tok_i -= 1;1853 p.tok_i -= 1;
1916 }1854 }
...@@ -1920,107 +1858,107 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {...@@ -1920,107 +1858,107 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
1920 _ = try p.expectToken(.r_bracket);1858 _ = try p.expectToken(.r_bracket);
1921 const mods = try p.parsePtrModifiers();1859 const mods = try p.parsePtrModifiers();
1922 const elem_type = try p.expectTypeExpr();1860 const elem_type = try p.expectTypeExpr();
1923 if (mods.bit_range_start == 0) {1861 if (mods.bit_range_start == .none) {
1924 if (sentinel == 0 and mods.addrspace_node == 0) {1862 if (sentinel == null and mods.addrspace_node == .none) {
1925 return p.addNode(.{1863 return try p.addNode(.{
1926 .tag = .ptr_type_aligned,1864 .tag = .ptr_type_aligned,
1927 .main_token = l_bracket,1865 .main_token = l_bracket,
1928 .data = .{1866 .data = .{ .opt_node_and_node = .{
1929 .lhs = mods.align_node,1867 mods.align_node,
1930 .rhs = elem_type,1868 elem_type,
1931 },1869 } },
1932 });1870 });
1933 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {1871 } else if (mods.align_node == .none and mods.addrspace_node == .none) {
1934 return p.addNode(.{1872 return try p.addNode(.{
1935 .tag = .ptr_type_sentinel,1873 .tag = .ptr_type_sentinel,
1936 .main_token = l_bracket,1874 .main_token = l_bracket,
1937 .data = .{1875 .data = .{ .opt_node_and_node = .{
1938 .lhs = sentinel,1876 .fromOptional(sentinel),
1939 .rhs = elem_type,1877 elem_type,
1940 },1878 } },
1941 });1879 });
1942 } else {1880 } else {
1943 return p.addNode(.{1881 return try p.addNode(.{
1944 .tag = .ptr_type,1882 .tag = .ptr_type,
1945 .main_token = l_bracket,1883 .main_token = l_bracket,
1946 .data = .{1884 .data = .{ .extra_and_node = .{
1947 .lhs = try p.addExtra(Node.PtrType{1885 try p.addExtra(Node.PtrType{
1948 .sentinel = sentinel,1886 .sentinel = .fromOptional(sentinel),
1949 .align_node = mods.align_node,1887 .align_node = mods.align_node,
1950 .addrspace_node = mods.addrspace_node,1888 .addrspace_node = mods.addrspace_node,
1951 }),1889 }),
1952 .rhs = elem_type,1890 elem_type,
1953 },1891 } },
1954 });1892 });
1955 }1893 }
1956 } else {1894 } else {
1957 return p.addNode(.{1895 return try p.addNode(.{
1958 .tag = .ptr_type_bit_range,1896 .tag = .ptr_type_bit_range,
1959 .main_token = l_bracket,1897 .main_token = l_bracket,
1960 .data = .{1898 .data = .{ .extra_and_node = .{
1961 .lhs = try p.addExtra(Node.PtrTypeBitRange{1899 try p.addExtra(Node.PtrTypeBitRange{
1962 .sentinel = sentinel,1900 .sentinel = .fromOptional(sentinel),
1963 .align_node = mods.align_node,1901 .align_node = mods.align_node.unwrap().?,
1964 .addrspace_node = mods.addrspace_node,1902 .addrspace_node = mods.addrspace_node,
1965 .bit_range_start = mods.bit_range_start,1903 .bit_range_start = mods.bit_range_start.unwrap().?,
1966 .bit_range_end = mods.bit_range_end,1904 .bit_range_end = mods.bit_range_end.unwrap().?,
1967 }),1905 }),
1968 .rhs = elem_type,1906 elem_type,
1969 },1907 } },
1970 });1908 });
1971 }1909 }
1972 },1910 },
1973 else => {1911 else => {
1974 const lbracket = p.nextToken();1912 const lbracket = p.nextToken();
1975 const len_expr = try p.parseExpr();1913 const len_expr = try p.parseExpr();
1976 const sentinel: Node.Index = if (p.eatToken(.colon)) |_|1914 const sentinel: ?Node.Index = if (p.eatToken(.colon)) |_|
1977 try p.expectExpr()1915 try p.expectExpr()
1978 else1916 else
1979 0;1917 null;
1980 _ = try p.expectToken(.r_bracket);1918 _ = try p.expectToken(.r_bracket);
1981 if (len_expr == 0) {1919 if (len_expr == null) {
1982 const mods = try p.parsePtrModifiers();1920 const mods = try p.parsePtrModifiers();
1983 const elem_type = try p.expectTypeExpr();1921 const elem_type = try p.expectTypeExpr();
1984 if (mods.bit_range_start != 0) {1922 if (mods.bit_range_start.unwrap()) |bit_range_start| {
1985 try p.warnMsg(.{1923 try p.warnMsg(.{
1986 .tag = .invalid_bit_range,1924 .tag = .invalid_bit_range,
1987 .token = p.nodes.items(.main_token)[mods.bit_range_start],1925 .token = p.nodeMainToken(bit_range_start),
1988 });1926 });
1989 }1927 }
1990 if (sentinel == 0 and mods.addrspace_node == 0) {1928 if (sentinel == null and mods.addrspace_node == .none) {
1991 return p.addNode(.{1929 return try p.addNode(.{
1992 .tag = .ptr_type_aligned,1930 .tag = .ptr_type_aligned,
1993 .main_token = lbracket,1931 .main_token = lbracket,
1994 .data = .{1932 .data = .{ .opt_node_and_node = .{
1995 .lhs = mods.align_node,1933 mods.align_node,
1996 .rhs = elem_type,1934 elem_type,
1997 },1935 } },
1998 });1936 });
1999 } else if (mods.align_node == 0 and mods.addrspace_node == 0) {1937 } else if (mods.align_node == .none and mods.addrspace_node == .none) {
2000 return p.addNode(.{1938 return try p.addNode(.{
2001 .tag = .ptr_type_sentinel,1939 .tag = .ptr_type_sentinel,
2002 .main_token = lbracket,1940 .main_token = lbracket,
2003 .data = .{1941 .data = .{ .opt_node_and_node = .{
2004 .lhs = sentinel,1942 .fromOptional(sentinel),
2005 .rhs = elem_type,1943 elem_type,
2006 },1944 } },
2007 });1945 });
2008 } else {1946 } else {
2009 return p.addNode(.{1947 return try p.addNode(.{
2010 .tag = .ptr_type,1948 .tag = .ptr_type,
2011 .main_token = lbracket,1949 .main_token = lbracket,
2012 .data = .{1950 .data = .{ .extra_and_node = .{
2013 .lhs = try p.addExtra(Node.PtrType{1951 try p.addExtra(Node.PtrType{
2014 .sentinel = sentinel,1952 .sentinel = .fromOptional(sentinel),
2015 .align_node = mods.align_node,1953 .align_node = mods.align_node,
2016 .addrspace_node = mods.addrspace_node,1954 .addrspace_node = mods.addrspace_node,
2017 }),1955 }),
2018 .rhs = elem_type,1956 elem_type,
2019 },1957 } },
2020 });1958 });
2021 }1959 }
2022 } else {1960 } else {
2023 switch (p.token_tags[p.tok_i]) {1961 switch (p.tokenTag(p.tok_i)) {
2024 .keyword_align,1962 .keyword_align,
2025 .keyword_const,1963 .keyword_const,
2026 .keyword_volatile,1964 .keyword_volatile,
...@@ -2030,26 +1968,25 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {...@@ -2030,26 +1968,25 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
2030 else => {},1968 else => {},
2031 }1969 }
2032 const elem_type = try p.expectTypeExpr();1970 const elem_type = try p.expectTypeExpr();
2033 if (sentinel == 0) {1971 if (sentinel == null) {
2034 return p.addNode(.{1972 return try p.addNode(.{
2035 .tag = .array_type,1973 .tag = .array_type,
2036 .main_token = lbracket,1974 .main_token = lbracket,
2037 .data = .{1975 .data = .{ .node_and_node = .{
2038 .lhs = len_expr,1976 len_expr.?,
2039 .rhs = elem_type,1977 elem_type,
2040 },1978 } },
2041 });1979 });
2042 } else {1980 } else {
2043 return p.addNode(.{1981 return try p.addNode(.{
2044 .tag = .array_type_sentinel,1982 .tag = .array_type_sentinel,
2045 .main_token = lbracket,1983 .main_token = lbracket,
2046 .data = .{1984 .data = .{ .node_and_extra = .{
2047 .lhs = len_expr,1985 len_expr.?, try p.addExtra(Node.ArrayTypeSentinel{
2048 .rhs = try p.addExtra(Node.ArrayTypeSentinel{1986 .sentinel = sentinel.?,
2049 .sentinel = sentinel,
2050 .elem_type = elem_type,1987 .elem_type = elem_type,
2051 }),1988 }),
2052 },1989 } },
2053 });1990 });
2054 }1991 }
2055 }1992 }
...@@ -2060,11 +1997,7 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {...@@ -2060,11 +1997,7 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index {
2060}1997}
20611998
2062fn expectTypeExpr(p: *Parse) Error!Node.Index {1999fn expectTypeExpr(p: *Parse) Error!Node.Index {
2063 const node = try p.parseTypeExpr();2000 return try p.parseTypeExpr() orelse return p.fail(.expected_type_expr);
2064 if (node == 0) {
2065 return p.fail(.expected_type_expr);
2066 }
2067 return node;
2068}2001}
20692002
2070/// PrimaryExpr2003/// PrimaryExpr
...@@ -2079,169 +2012,135 @@ fn expectTypeExpr(p: *Parse) Error!Node.Index {...@@ -2079,169 +2012,135 @@ fn expectTypeExpr(p: *Parse) Error!Node.Index {
2079/// / BlockLabel? LoopExpr2012/// / BlockLabel? LoopExpr
2080/// / Block2013/// / Block
2081/// / CurlySuffixExpr2014/// / CurlySuffixExpr
2082fn parsePrimaryExpr(p: *Parse) !Node.Index {2015fn parsePrimaryExpr(p: *Parse) !?Node.Index {
2083 switch (p.token_tags[p.tok_i]) {2016 switch (p.tokenTag(p.tok_i)) {
2084 .keyword_asm => return p.expectAsmExpr(),2017 .keyword_asm => return try p.expectAsmExpr(),
2085 .keyword_if => return p.parseIfExpr(),2018 .keyword_if => return try p.parseIfExpr(),
2086 .keyword_break => {2019 .keyword_break => {
2087 return p.addNode(.{2020 return try p.addNode(.{
2088 .tag = .@"break",2021 .tag = .@"break",
2089 .main_token = p.nextToken(),2022 .main_token = p.nextToken(),
2090 .data = .{2023 .data = .{ .opt_token_and_opt_node = .{
2091 .lhs = try p.parseBreakLabel(),2024 try p.parseBreakLabel(),
2092 .rhs = try p.parseExpr(),2025 .fromOptional(try p.parseExpr()),
2093 },2026 } },
2094 });2027 });
2095 },2028 },
2096 .keyword_continue => {2029 .keyword_continue => {
2097 return p.addNode(.{2030 return try p.addNode(.{
2098 .tag = .@"continue",2031 .tag = .@"continue",
2099 .main_token = p.nextToken(),2032 .main_token = p.nextToken(),
2100 .data = .{2033 .data = .{ .opt_token_and_opt_node = .{
2101 .lhs = try p.parseBreakLabel(),2034 try p.parseBreakLabel(),
2102 .rhs = try p.parseExpr(),2035 .fromOptional(try p.parseExpr()),
2103 },2036 } },
2104 });2037 });
2105 },2038 },
2106 .keyword_comptime => {2039 .keyword_comptime => {
2107 return p.addNode(.{2040 return try p.addNode(.{
2108 .tag = .@"comptime",2041 .tag = .@"comptime",
2109 .main_token = p.nextToken(),2042 .main_token = p.nextToken(),
2110 .data = .{2043 .data = .{ .node = try p.expectExpr() },
2111 .lhs = try p.expectExpr(),
2112 .rhs = undefined,
2113 },
2114 });2044 });
2115 },2045 },
2116 .keyword_nosuspend => {2046 .keyword_nosuspend => {
2117 return p.addNode(.{2047 return try p.addNode(.{
2118 .tag = .@"nosuspend",2048 .tag = .@"nosuspend",
2119 .main_token = p.nextToken(),2049 .main_token = p.nextToken(),
2120 .data = .{2050 .data = .{ .node = try p.expectExpr() },
2121 .lhs = try p.expectExpr(),
2122 .rhs = undefined,
2123 },
2124 });2051 });
2125 },2052 },
2126 .keyword_resume => {2053 .keyword_resume => {
2127 return p.addNode(.{2054 return try p.addNode(.{
2128 .tag = .@"resume",2055 .tag = .@"resume",
2129 .main_token = p.nextToken(),2056 .main_token = p.nextToken(),
2130 .data = .{2057 .data = .{ .node = try p.expectExpr() },
2131 .lhs = try p.expectExpr(),
2132 .rhs = undefined,
2133 },
2134 });2058 });
2135 },2059 },
2136 .keyword_return => {2060 .keyword_return => {
2137 return p.addNode(.{2061 return try p.addNode(.{
2138 .tag = .@"return",2062 .tag = .@"return",
2139 .main_token = p.nextToken(),2063 .main_token = p.nextToken(),
2140 .data = .{2064 .data = .{ .opt_node = .fromOptional(try p.parseExpr()) },
2141 .lhs = try p.parseExpr(),
2142 .rhs = undefined,
2143 },
2144 });2065 });
2145 },2066 },
2146 .identifier => {2067 .identifier => {
2147 if (p.token_tags[p.tok_i + 1] == .colon) {2068 if (p.tokenTag(p.tok_i + 1) == .colon) {
2148 switch (p.token_tags[p.tok_i + 2]) {2069 switch (p.tokenTag(p.tok_i + 2)) {
2149 .keyword_inline => {2070 .keyword_inline => {
2150 p.tok_i += 3;2071 p.tok_i += 3;
2151 switch (p.token_tags[p.tok_i]) {2072 switch (p.tokenTag(p.tok_i)) {
2152 .keyword_for => return p.parseFor(expectExpr),2073 .keyword_for => return try p.parseFor(expectExpr),
2153 .keyword_while => return p.parseWhileExpr(),2074 .keyword_while => return try p.parseWhileExpr(),
2154 else => return p.fail(.expected_inlinable),2075 else => return p.fail(.expected_inlinable),
2155 }2076 }
2156 },2077 },
2157 .keyword_for => {2078 .keyword_for => {
2158 p.tok_i += 2;2079 p.tok_i += 2;
2159 return p.parseFor(expectExpr);2080 return try p.parseFor(expectExpr);
2160 },2081 },
2161 .keyword_while => {2082 .keyword_while => {
2162 p.tok_i += 2;2083 p.tok_i += 2;
2163 return p.parseWhileExpr();2084 return try p.parseWhileExpr();
2164 },2085 },
2165 .l_brace => {2086 .l_brace => {
2166 p.tok_i += 2;2087 p.tok_i += 2;
2167 return p.parseBlock();2088 return try p.parseBlock();
2168 },2089 },
2169 else => return p.parseCurlySuffixExpr(),2090 else => return try p.parseCurlySuffixExpr(),
2170 }2091 }
2171 } else {2092 } else {
2172 return p.parseCurlySuffixExpr();2093 return try p.parseCurlySuffixExpr();
2173 }2094 }
2174 },2095 },
2175 .keyword_inline => {2096 .keyword_inline => {
2176 p.tok_i += 1;2097 p.tok_i += 1;
2177 switch (p.token_tags[p.tok_i]) {2098 switch (p.tokenTag(p.tok_i)) {
2178 .keyword_for => return p.parseFor(expectExpr),2099 .keyword_for => return try p.parseFor(expectExpr),
2179 .keyword_while => return p.parseWhileExpr(),2100 .keyword_while => return try p.parseWhileExpr(),
2180 else => return p.fail(.expected_inlinable),2101 else => return p.fail(.expected_inlinable),
2181 }2102 }
2182 },2103 },
2183 .keyword_for => return p.parseFor(expectExpr),2104 .keyword_for => return try p.parseFor(expectExpr),
2184 .keyword_while => return p.parseWhileExpr(),2105 .keyword_while => return try p.parseWhileExpr(),
2185 .l_brace => return p.parseBlock(),2106 .l_brace => return try p.parseBlock(),
2186 else => return p.parseCurlySuffixExpr(),2107 else => return try p.parseCurlySuffixExpr(),
2187 }2108 }
2188}2109}
21892110
2190/// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?2111/// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
2191fn parseIfExpr(p: *Parse) !Node.Index {2112fn parseIfExpr(p: *Parse) !?Node.Index {
2192 return p.parseIf(expectExpr);2113 return try p.parseIf(expectExpr);
2193}2114}
21942115
2195/// Block <- LBRACE Statement* RBRACE2116/// Block <- LBRACE Statement* RBRACE
2196fn parseBlock(p: *Parse) !Node.Index {2117fn parseBlock(p: *Parse) !?Node.Index {
2197 const lbrace = p.eatToken(.l_brace) orelse return null_node;2118 const lbrace = p.eatToken(.l_brace) orelse return null;
2198 const scratch_top = p.scratch.items.len;2119 const scratch_top = p.scratch.items.len;
2199 defer p.scratch.shrinkRetainingCapacity(scratch_top);2120 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2200 while (true) {2121 while (true) {
2201 if (p.token_tags[p.tok_i] == .r_brace) break;2122 if (p.tokenTag(p.tok_i) == .r_brace) break;
2202 const statement = try p.expectStatementRecoverable();2123 const statement = try p.expectStatementRecoverable() orelse break;
2203 if (statement == 0) break;
2204 try p.scratch.append(p.gpa, statement);2124 try p.scratch.append(p.gpa, statement);
2205 }2125 }
2206 _ = try p.expectToken(.r_brace);2126 _ = try p.expectToken(.r_brace);
2207 const semicolon = (p.token_tags[p.tok_i - 2] == .semicolon);
2208 const statements = p.scratch.items[scratch_top..];2127 const statements = p.scratch.items[scratch_top..];
2209 switch (statements.len) {2128 const semicolon = statements.len != 0 and (p.tokenTag(p.tok_i - 2)) == .semicolon;
2210 0 => return p.addNode(.{2129 if (statements.len <= 2) {
2211 .tag = .block_two,2130 return try p.addNode(.{
2212 .main_token = lbrace,
2213 .data = .{
2214 .lhs = 0,
2215 .rhs = 0,
2216 },
2217 }),
2218 1 => return p.addNode(.{
2219 .tag = if (semicolon) .block_two_semicolon else .block_two,2131 .tag = if (semicolon) .block_two_semicolon else .block_two,
2220 .main_token = lbrace,2132 .main_token = lbrace,
2221 .data = .{2133 .data = .{ .opt_node_and_opt_node = .{
2222 .lhs = statements[0],2134 if (statements.len >= 1) statements[0].toOptional() else .none,
2223 .rhs = 0,2135 if (statements.len >= 2) statements[1].toOptional() else .none,
2224 },2136 } },
2225 }),2137 });
2226 2 => return p.addNode(.{2138 } else {
2227 .tag = if (semicolon) .block_two_semicolon else .block_two,2139 return try p.addNode(.{
2140 .tag = if (semicolon) .block_semicolon else .block,
2228 .main_token = lbrace,2141 .main_token = lbrace,
2229 .data = .{2142 .data = .{ .extra_range = try p.listToSpan(statements) },
2230 .lhs = statements[0],2143 });
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 },
2245 }2144 }
2246}2145}
22472146
...@@ -2260,15 +2159,15 @@ fn forPrefix(p: *Parse) Error!usize {...@@ -2260,15 +2159,15 @@ fn forPrefix(p: *Parse) Error!usize {
2260 input = try p.addNode(.{2159 input = try p.addNode(.{
2261 .tag = .for_range,2160 .tag = .for_range,
2262 .main_token = ellipsis,2161 .main_token = ellipsis,
2263 .data = .{2162 .data = .{ .node_and_opt_node = .{
2264 .lhs = input,2163 input,
2265 .rhs = try p.parseExpr(),2164 .fromOptional(try p.parseExpr()),
2266 },2165 } },
2267 });2166 });
2268 }2167 }
22692168
2270 try p.scratch.append(p.gpa, input);2169 try p.scratch.append(p.gpa, input);
2271 switch (p.token_tags[p.tok_i]) {2170 switch (p.tokenTag(p.tok_i)) {
2272 .comma => p.tok_i += 1,2171 .comma => p.tok_i += 1,
2273 .r_paren => {2172 .r_paren => {
2274 p.tok_i += 1;2173 p.tok_i += 1;
...@@ -2297,7 +2196,7 @@ fn forPrefix(p: *Parse) Error!usize {...@@ -2297,7 +2196,7 @@ fn forPrefix(p: *Parse) Error!usize {
2297 try p.warnMsg(.{ .tag = .extra_for_capture, .token = identifier });2196 try p.warnMsg(.{ .tag = .extra_for_capture, .token = identifier });
2298 warned_excess = true;2197 warned_excess = true;
2299 }2198 }
2300 switch (p.token_tags[p.tok_i]) {2199 switch (p.tokenTag(p.tok_i)) {
2301 .comma => p.tok_i += 1,2200 .comma => p.tok_i += 1,
2302 .pipe => {2201 .pipe => {
2303 p.tok_i += 1;2202 p.tok_i += 1;
...@@ -2311,7 +2210,7 @@ fn forPrefix(p: *Parse) Error!usize {...@@ -2311,7 +2210,7 @@ fn forPrefix(p: *Parse) Error!usize {
23112210
2312 if (captures < inputs) {2211 if (captures < inputs) {
2313 const index = p.scratch.items.len - captures;2212 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]);
2315 try p.warnMsg(.{ .tag = .for_input_not_captured, .token = input });2214 try p.warnMsg(.{ .tag = .for_input_not_captured, .token = input });
2316 }2215 }
2317 return inputs;2216 return inputs;
...@@ -2320,8 +2219,8 @@ fn forPrefix(p: *Parse) Error!usize {...@@ -2320,8 +2219,8 @@ fn forPrefix(p: *Parse) Error!usize {
2320/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?2219/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
2321///2220///
2322/// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?2221/// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
2323fn parseWhileExpr(p: *Parse) !Node.Index {2222fn parseWhileExpr(p: *Parse) !?Node.Index {
2324 const while_token = p.eatToken(.keyword_while) orelse return null_node;2223 const while_token = p.eatToken(.keyword_while) orelse return null;
2325 _ = try p.expectToken(.l_paren);2224 _ = try p.expectToken(.l_paren);
2326 const condition = try p.expectExpr();2225 const condition = try p.expectExpr();
2327 _ = try p.expectToken(.r_paren);2226 _ = try p.expectToken(.r_paren);
...@@ -2330,42 +2229,42 @@ fn parseWhileExpr(p: *Parse) !Node.Index {...@@ -2330,42 +2229,42 @@ fn parseWhileExpr(p: *Parse) !Node.Index {
23302229
2331 const then_expr = try p.expectExpr();2230 const then_expr = try p.expectExpr();
2332 _ = p.eatToken(.keyword_else) orelse {2231 _ = p.eatToken(.keyword_else) orelse {
2333 if (cont_expr == 0) {2232 if (cont_expr == null) {
2334 return p.addNode(.{2233 return try p.addNode(.{
2335 .tag = .while_simple,2234 .tag = .while_simple,
2336 .main_token = while_token,2235 .main_token = while_token,
2337 .data = .{2236 .data = .{ .node_and_node = .{
2338 .lhs = condition,2237 condition,
2339 .rhs = then_expr,2238 then_expr,
2340 },2239 } },
2341 });2240 });
2342 } else {2241 } else {
2343 return p.addNode(.{2242 return try p.addNode(.{
2344 .tag = .while_cont,2243 .tag = .while_cont,
2345 .main_token = while_token,2244 .main_token = while_token,
2346 .data = .{2245 .data = .{ .node_and_extra = .{
2347 .lhs = condition,2246 condition,
2348 .rhs = try p.addExtra(Node.WhileCont{2247 try p.addExtra(Node.WhileCont{
2349 .cont_expr = cont_expr,2248 .cont_expr = cont_expr.?,
2350 .then_expr = then_expr,2249 .then_expr = then_expr,
2351 }),2250 }),
2352 },2251 } },
2353 });2252 });
2354 }2253 }
2355 };2254 };
2356 _ = try p.parsePayload();2255 _ = try p.parsePayload();
2357 const else_expr = try p.expectExpr();2256 const else_expr = try p.expectExpr();
2358 return p.addNode(.{2257 return try p.addNode(.{
2359 .tag = .@"while",2258 .tag = .@"while",
2360 .main_token = while_token,2259 .main_token = while_token,
2361 .data = .{2260 .data = .{ .node_and_extra = .{
2362 .lhs = condition,2261 condition,
2363 .rhs = try p.addExtra(Node.While{2262 try p.addExtra(Node.While{
2364 .cont_expr = cont_expr,2263 .cont_expr = .fromOptional(cont_expr),
2365 .then_expr = then_expr,2264 .then_expr = then_expr,
2366 .else_expr = else_expr,2265 .else_expr = else_expr,
2367 }),2266 }),
2368 },2267 } },
2369 });2268 });
2370}2269}
23712270
...@@ -2375,9 +2274,8 @@ fn parseWhileExpr(p: *Parse) !Node.Index {...@@ -2375,9 +2274,8 @@ fn parseWhileExpr(p: *Parse) !Node.Index {
2375/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE2274/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
2376/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE2275/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
2377/// / LBRACE RBRACE2276/// / LBRACE RBRACE
2378fn parseCurlySuffixExpr(p: *Parse) !Node.Index {2277fn parseCurlySuffixExpr(p: *Parse) !?Node.Index {
2379 const lhs = try p.parseTypeExpr();2278 const lhs = try p.parseTypeExpr() orelse return null;
2380 if (lhs == 0) return null_node;
2381 const lbrace = p.eatToken(.l_brace) orelse return lhs;2279 const lbrace = p.eatToken(.l_brace) orelse return lhs;
23822280
2383 // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne;2281 // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne;
...@@ -2385,11 +2283,11 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {...@@ -2385,11 +2283,11 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
23852283
2386 const scratch_top = p.scratch.items.len;2284 const scratch_top = p.scratch.items.len;
2387 defer p.scratch.shrinkRetainingCapacity(scratch_top);2285 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2388 const field_init = try p.parseFieldInit();2286 const opt_field_init = try p.parseFieldInit();
2389 if (field_init != 0) {2287 if (opt_field_init) |field_init| {
2390 try p.scratch.append(p.gpa, field_init);2288 try p.scratch.append(p.gpa, field_init);
2391 while (true) {2289 while (true) {
2392 switch (p.token_tags[p.tok_i]) {2290 switch (p.tokenTag(p.tok_i)) {
2393 .comma => p.tok_i += 1,2291 .comma => p.tok_i += 1,
2394 .r_brace => {2292 .r_brace => {
2395 p.tok_i += 1;2293 p.tok_i += 1;
...@@ -2403,26 +2301,27 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {...@@ -2403,26 +2301,27 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
2403 const next = try p.expectFieldInit();2301 const next = try p.expectFieldInit();
2404 try p.scratch.append(p.gpa, next);2302 try p.scratch.append(p.gpa, next);
2405 }2303 }
2406 const comma = (p.token_tags[p.tok_i - 2] == .comma);2304 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2407 const inits = p.scratch.items[scratch_top..];2305 const inits = p.scratch.items[scratch_top..];
2408 switch (inits.len) {2306 std.debug.assert(inits.len != 0);
2409 0 => unreachable,2307 if (inits.len <= 1) {
2410 1 => return p.addNode(.{2308 return try p.addNode(.{
2411 .tag = if (comma) .struct_init_one_comma else .struct_init_one,2309 .tag = if (comma) .struct_init_one_comma else .struct_init_one,
2412 .main_token = lbrace,2310 .main_token = lbrace,
2413 .data = .{2311 .data = .{ .node_and_opt_node = .{
2414 .lhs = lhs,2312 lhs,
2415 .rhs = inits[0],2313 inits[0].toOptional(),
2416 },2314 } },
2417 }),2315 });
2418 else => return p.addNode(.{2316 } else {
2317 return try p.addNode(.{
2419 .tag = if (comma) .struct_init_comma else .struct_init,2318 .tag = if (comma) .struct_init_comma else .struct_init,
2420 .main_token = lbrace,2319 .main_token = lbrace,
2421 .data = .{2320 .data = .{ .node_and_extra = .{
2422 .lhs = lhs,2321 lhs,
2423 .rhs = try p.addExtra(try p.listToSpan(inits)),2322 try p.addExtra(try p.listToSpan(inits)),
2424 },2323 } },
2425 }),2324 });
2426 }2325 }
2427 }2326 }
24282327
...@@ -2430,7 +2329,7 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {...@@ -2430,7 +2329,7 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
2430 if (p.eatToken(.r_brace)) |_| break;2329 if (p.eatToken(.r_brace)) |_| break;
2431 const elem_init = try p.expectExpr();2330 const elem_init = try p.expectExpr();
2432 try p.scratch.append(p.gpa, elem_init);2331 try p.scratch.append(p.gpa, elem_init);
2433 switch (p.token_tags[p.tok_i]) {2332 switch (p.tokenTag(p.tok_i)) {
2434 .comma => p.tok_i += 1,2333 .comma => p.tok_i += 1,
2435 .r_brace => {2334 .r_brace => {
2436 p.tok_i += 1;2335 p.tok_i += 1;
...@@ -2441,48 +2340,47 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {...@@ -2441,48 +2340,47 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index {
2441 else => try p.warn(.expected_comma_after_initializer),2340 else => try p.warn(.expected_comma_after_initializer),
2442 }2341 }
2443 }2342 }
2444 const comma = (p.token_tags[p.tok_i - 2] == .comma);2343 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2445 const inits = p.scratch.items[scratch_top..];2344 const inits = p.scratch.items[scratch_top..];
2446 switch (inits.len) {2345 switch (inits.len) {
2447 0 => return p.addNode(.{2346 0 => return try p.addNode(.{
2448 .tag = .struct_init_one,2347 .tag = .struct_init_one,
2449 .main_token = lbrace,2348 .main_token = lbrace,
2450 .data = .{2349 .data = .{ .node_and_opt_node = .{
2451 .lhs = lhs,2350 lhs,
2452 .rhs = 0,2351 .none,
2453 },2352 } },
2454 }),2353 }),
2455 1 => return p.addNode(.{2354 1 => return try p.addNode(.{
2456 .tag = if (comma) .array_init_one_comma else .array_init_one,2355 .tag = if (comma) .array_init_one_comma else .array_init_one,
2457 .main_token = lbrace,2356 .main_token = lbrace,
2458 .data = .{2357 .data = .{ .node_and_node = .{
2459 .lhs = lhs,2358 lhs,
2460 .rhs = inits[0],2359 inits[0],
2461 },2360 } },
2462 }),2361 }),
2463 else => return p.addNode(.{2362 else => return try p.addNode(.{
2464 .tag = if (comma) .array_init_comma else .array_init,2363 .tag = if (comma) .array_init_comma else .array_init,
2465 .main_token = lbrace,2364 .main_token = lbrace,
2466 .data = .{2365 .data = .{ .node_and_extra = .{
2467 .lhs = lhs,2366 lhs,
2468 .rhs = try p.addExtra(try p.listToSpan(inits)),2367 try p.addExtra(try p.listToSpan(inits)),
2469 },2368 } },
2470 }),2369 }),
2471 }2370 }
2472}2371}
24732372
2474/// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?2373/// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
2475fn parseErrorUnionExpr(p: *Parse) !Node.Index {2374fn parseErrorUnionExpr(p: *Parse) !?Node.Index {
2476 const suffix_expr = try p.parseSuffixExpr();2375 const suffix_expr = try p.parseSuffixExpr() orelse return null;
2477 if (suffix_expr == 0) return null_node;
2478 const bang = p.eatToken(.bang) orelse return suffix_expr;2376 const bang = p.eatToken(.bang) orelse return suffix_expr;
2479 return p.addNode(.{2377 return try p.addNode(.{
2480 .tag = .error_union,2378 .tag = .error_union,
2481 .main_token = bang,2379 .main_token = bang,
2482 .data = .{2380 .data = .{ .node_and_node = .{
2483 .lhs = suffix_expr,2381 suffix_expr,
2484 .rhs = try p.expectTypeExpr(),2382 try p.expectTypeExpr(),
2485 },2383 } },
2486 });2384 });
2487}2385}
24882386
...@@ -2493,13 +2391,11 @@ fn parseErrorUnionExpr(p: *Parse) !Node.Index {...@@ -2493,13 +2391,11 @@ fn parseErrorUnionExpr(p: *Parse) !Node.Index {
2493/// FnCallArguments <- LPAREN ExprList RPAREN2391/// FnCallArguments <- LPAREN ExprList RPAREN
2494///2392///
2495/// ExprList <- (Expr COMMA)* Expr?2393/// ExprList <- (Expr COMMA)* Expr?
2496fn parseSuffixExpr(p: *Parse) !Node.Index {2394fn parseSuffixExpr(p: *Parse) !?Node.Index {
2497 if (p.eatToken(.keyword_async)) |_| {2395 if (p.eatToken(.keyword_async)) |_| {
2498 var res = try p.expectPrimaryTypeExpr();2396 var res = try p.expectPrimaryTypeExpr();
2499 while (true) {2397 while (true) {
2500 const node = try p.parseSuffixOp(res);2398 res = try p.parseSuffixOp(res) orelse break;
2501 if (node == 0) break;
2502 res = node;
2503 }2399 }
2504 const lparen = p.eatToken(.l_paren) orelse {2400 const lparen = p.eatToken(.l_paren) orelse {
2505 try p.warn(.expected_param_list);2401 try p.warn(.expected_param_list);
...@@ -2511,7 +2407,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2511,7 +2407,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
2511 if (p.eatToken(.r_paren)) |_| break;2407 if (p.eatToken(.r_paren)) |_| break;
2512 const param = try p.expectExpr();2408 const param = try p.expectExpr();
2513 try p.scratch.append(p.gpa, param);2409 try p.scratch.append(p.gpa, param);
2514 switch (p.token_tags[p.tok_i]) {2410 switch (p.tokenTag(p.tok_i)) {
2515 .comma => p.tok_i += 1,2411 .comma => p.tok_i += 1,
2516 .r_paren => {2412 .r_paren => {
2517 p.tok_i += 1;2413 p.tok_i += 1;
...@@ -2522,41 +2418,33 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2522,41 +2418,33 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
2522 else => try p.warn(.expected_comma_after_arg),2418 else => try p.warn(.expected_comma_after_arg),
2523 }2419 }
2524 }2420 }
2525 const comma = (p.token_tags[p.tok_i - 2] == .comma);2421 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2526 const params = p.scratch.items[scratch_top..];2422 const params = p.scratch.items[scratch_top..];
2527 switch (params.len) {2423 if (params.len <= 1) {
2528 0 => return p.addNode(.{2424 return try p.addNode(.{
2529 .tag = if (comma) .async_call_one_comma else .async_call_one,
2530 .main_token = lparen,
2531 .data = .{
2532 .lhs = res,
2533 .rhs = 0,
2534 },
2535 }),
2536 1 => return p.addNode(.{
2537 .tag = if (comma) .async_call_one_comma else .async_call_one,2425 .tag = if (comma) .async_call_one_comma else .async_call_one,
2538 .main_token = lparen,2426 .main_token = lparen,
2539 .data = .{2427 .data = .{ .node_and_opt_node = .{
2540 .lhs = res,2428 res,
2541 .rhs = params[0],2429 if (params.len >= 1) params[0].toOptional() else .none,
2542 },2430 } },
2543 }),2431 });
2544 else => return p.addNode(.{2432 } else {
2433 return try p.addNode(.{
2545 .tag = if (comma) .async_call_comma else .async_call,2434 .tag = if (comma) .async_call_comma else .async_call,
2546 .main_token = lparen,2435 .main_token = lparen,
2547 .data = .{2436 .data = .{ .node_and_extra = .{
2548 .lhs = res,2437 res,
2549 .rhs = try p.addExtra(try p.listToSpan(params)),2438 try p.addExtra(try p.listToSpan(params)),
2550 },2439 } },
2551 }),2440 });
2552 }2441 }
2553 }2442 }
25542443
2555 var res = try p.parsePrimaryTypeExpr();2444 var res = try p.parsePrimaryTypeExpr() orelse return null;
2556 if (res == 0) return res;
2557 while (true) {2445 while (true) {
2558 const suffix_op = try p.parseSuffixOp(res);2446 const opt_suffix_op = try p.parseSuffixOp(res);
2559 if (suffix_op != 0) {2447 if (opt_suffix_op) |suffix_op| {
2560 res = suffix_op;2448 res = suffix_op;
2561 continue;2449 continue;
2562 }2450 }
...@@ -2567,7 +2455,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2567,7 +2455,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
2567 if (p.eatToken(.r_paren)) |_| break;2455 if (p.eatToken(.r_paren)) |_| break;
2568 const param = try p.expectExpr();2456 const param = try p.expectExpr();
2569 try p.scratch.append(p.gpa, param);2457 try p.scratch.append(p.gpa, param);
2570 switch (p.token_tags[p.tok_i]) {2458 switch (p.tokenTag(p.tok_i)) {
2571 .comma => p.tok_i += 1,2459 .comma => p.tok_i += 1,
2572 .r_paren => {2460 .r_paren => {
2573 p.tok_i += 1;2461 p.tok_i += 1;
...@@ -2578,32 +2466,24 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2578,32 +2466,24 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
2578 else => try p.warn(.expected_comma_after_arg),2466 else => try p.warn(.expected_comma_after_arg),
2579 }2467 }
2580 }2468 }
2581 const comma = (p.token_tags[p.tok_i - 2] == .comma);2469 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2582 const params = p.scratch.items[scratch_top..];2470 const params = p.scratch.items[scratch_top..];
2583 res = switch (params.len) {2471 res = switch (params.len) {
2584 0 => try p.addNode(.{2472 0, 1 => try p.addNode(.{
2585 .tag = if (comma) .call_one_comma else .call_one,2473 .tag = if (comma) .call_one_comma else .call_one,
2586 .main_token = lparen,2474 .main_token = lparen,
2587 .data = .{2475 .data = .{ .node_and_opt_node = .{
2588 .lhs = res,2476 res,
2589 .rhs = 0,2477 if (params.len >= 1) .fromOptional(params[0]) else .none,
2590 },2478 } },
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 },
2599 }),2479 }),
2600 else => try p.addNode(.{2480 else => try p.addNode(.{
2601 .tag = if (comma) .call_comma else .call,2481 .tag = if (comma) .call_comma else .call,
2602 .main_token = lparen,2482 .main_token = lparen,
2603 .data = .{2483 .data = .{ .node_and_extra = .{
2604 .lhs = res,2484 res,
2605 .rhs = try p.addExtra(try p.listToSpan(params)),2485 try p.addExtra(try p.listToSpan(params)),
2606 },2486 } },
2607 }),2487 }),
2608 };2488 };
2609 }2489 }
...@@ -2650,155 +2530,131 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2650,155 +2530,131 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {
2650/// / BlockLabel? SwitchExpr2530/// / BlockLabel? SwitchExpr
2651///2531///
2652/// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)2532/// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
2653fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {2533fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index {
2654 switch (p.token_tags[p.tok_i]) {2534 switch (p.tokenTag(p.tok_i)) {
2655 .char_literal => return p.addNode(.{2535 .char_literal => return try p.addNode(.{
2656 .tag = .char_literal,2536 .tag = .char_literal,
2657 .main_token = p.nextToken(),2537 .main_token = p.nextToken(),
2658 .data = .{2538 .data = undefined,
2659 .lhs = undefined,
2660 .rhs = undefined,
2661 },
2662 }),2539 }),
2663 .number_literal => return p.addNode(.{2540 .number_literal => return try p.addNode(.{
2664 .tag = .number_literal,2541 .tag = .number_literal,
2665 .main_token = p.nextToken(),2542 .main_token = p.nextToken(),
2666 .data = .{2543 .data = undefined,
2667 .lhs = undefined,
2668 .rhs = undefined,
2669 },
2670 }),2544 }),
2671 .keyword_unreachable => return p.addNode(.{2545 .keyword_unreachable => return try p.addNode(.{
2672 .tag = .unreachable_literal,2546 .tag = .unreachable_literal,
2673 .main_token = p.nextToken(),2547 .main_token = p.nextToken(),
2674 .data = .{2548 .data = undefined,
2675 .lhs = undefined,
2676 .rhs = undefined,
2677 },
2678 }),2549 }),
2679 .keyword_anyframe => return p.addNode(.{2550 .keyword_anyframe => return try p.addNode(.{
2680 .tag = .anyframe_literal,2551 .tag = .anyframe_literal,
2681 .main_token = p.nextToken(),2552 .main_token = p.nextToken(),
2682 .data = .{2553 .data = undefined,
2683 .lhs = undefined,
2684 .rhs = undefined,
2685 },
2686 }),2554 }),
2687 .string_literal => {2555 .string_literal => {
2688 const main_token = p.nextToken();2556 const main_token = p.nextToken();
2689 return p.addNode(.{2557 return try p.addNode(.{
2690 .tag = .string_literal,2558 .tag = .string_literal,
2691 .main_token = main_token,2559 .main_token = main_token,
2692 .data = .{2560 .data = undefined,
2693 .lhs = undefined,
2694 .rhs = undefined,
2695 },
2696 });2561 });
2697 },2562 },
26982563
2699 .builtin => return p.parseBuiltinCall(),2564 .builtin => return try p.parseBuiltinCall(),
2700 .keyword_fn => return p.parseFnProto(),2565 .keyword_fn => return try p.parseFnProto(),
2701 .keyword_if => return p.parseIf(expectTypeExpr),2566 .keyword_if => return try p.parseIf(expectTypeExpr),
2702 .keyword_switch => return p.expectSwitchExpr(false),2567 .keyword_switch => return try p.expectSwitchExpr(false),
27032568
2704 .keyword_extern,2569 .keyword_extern,
2705 .keyword_packed,2570 .keyword_packed,
2706 => {2571 => {
2707 p.tok_i += 1;2572 p.tok_i += 1;
2708 return p.parseContainerDeclAuto();2573 return try p.parseContainerDeclAuto();
2709 },2574 },
27102575
2711 .keyword_struct,2576 .keyword_struct,
2712 .keyword_opaque,2577 .keyword_opaque,
2713 .keyword_enum,2578 .keyword_enum,
2714 .keyword_union,2579 .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(.{
2718 .tag = .@"comptime",2583 .tag = .@"comptime",
2719 .main_token = p.nextToken(),2584 .main_token = p.nextToken(),
2720 .data = .{2585 .data = .{ .node = try p.expectTypeExpr() },
2721 .lhs = try p.expectTypeExpr(),
2722 .rhs = undefined,
2723 },
2724 }),2586 }),
2725 .multiline_string_literal_line => {2587 .multiline_string_literal_line => {
2726 const first_line = p.nextToken();2588 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) {
2728 p.tok_i += 1;2590 p.tok_i += 1;
2729 }2591 }
2730 return p.addNode(.{2592 return try p.addNode(.{
2731 .tag = .multiline_string_literal,2593 .tag = .multiline_string_literal,
2732 .main_token = first_line,2594 .main_token = first_line,
2733 .data = .{2595 .data = .{ .token_and_token = .{
2734 .lhs = first_line,2596 first_line,
2735 .rhs = p.tok_i - 1,2597 p.tok_i - 1,
2736 },2598 } },
2737 });2599 });
2738 },2600 },
2739 .identifier => switch (p.token_tags[p.tok_i + 1]) {2601 .identifier => switch (p.tokenTag(p.tok_i + 1)) {
2740 .colon => switch (p.token_tags[p.tok_i + 2]) {2602 .colon => switch (p.tokenTag(p.tok_i + 2)) {
2741 .keyword_inline => {2603 .keyword_inline => {
2742 p.tok_i += 3;2604 p.tok_i += 3;
2743 switch (p.token_tags[p.tok_i]) {2605 switch (p.tokenTag(p.tok_i)) {
2744 .keyword_for => return p.parseFor(expectTypeExpr),2606 .keyword_for => return try p.parseFor(expectTypeExpr),
2745 .keyword_while => return p.parseWhileTypeExpr(),2607 .keyword_while => return try p.parseWhileTypeExpr(),
2746 else => return p.fail(.expected_inlinable),2608 else => return p.fail(.expected_inlinable),
2747 }2609 }
2748 },2610 },
2749 .keyword_for => {2611 .keyword_for => {
2750 p.tok_i += 2;2612 p.tok_i += 2;
2751 return p.parseFor(expectTypeExpr);2613 return try p.parseFor(expectTypeExpr);
2752 },2614 },
2753 .keyword_while => {2615 .keyword_while => {
2754 p.tok_i += 2;2616 p.tok_i += 2;
2755 return p.parseWhileTypeExpr();2617 return try p.parseWhileTypeExpr();
2756 },2618 },
2757 .keyword_switch => {2619 .keyword_switch => {
2758 p.tok_i += 2;2620 p.tok_i += 2;
2759 return p.expectSwitchExpr(true);2621 return try p.expectSwitchExpr(true);
2760 },2622 },
2761 .l_brace => {2623 .l_brace => {
2762 p.tok_i += 2;2624 p.tok_i += 2;
2763 return p.parseBlock();2625 return try p.parseBlock();
2764 },2626 },
2765 else => return p.addNode(.{2627 else => return try p.addNode(.{
2766 .tag = .identifier,2628 .tag = .identifier,
2767 .main_token = p.nextToken(),2629 .main_token = p.nextToken(),
2768 .data = .{2630 .data = undefined,
2769 .lhs = undefined,
2770 .rhs = undefined,
2771 },
2772 }),2631 }),
2773 },2632 },
2774 else => return p.addNode(.{2633 else => return try p.addNode(.{
2775 .tag = .identifier,2634 .tag = .identifier,
2776 .main_token = p.nextToken(),2635 .main_token = p.nextToken(),
2777 .data = .{2636 .data = undefined,
2778 .lhs = undefined,
2779 .rhs = undefined,
2780 },
2781 }),2637 }),
2782 },2638 },
2783 .keyword_inline => {2639 .keyword_inline => {
2784 p.tok_i += 1;2640 p.tok_i += 1;
2785 switch (p.token_tags[p.tok_i]) {2641 switch (p.tokenTag(p.tok_i)) {
2786 .keyword_for => return p.parseFor(expectTypeExpr),2642 .keyword_for => return try p.parseFor(expectTypeExpr),
2787 .keyword_while => return p.parseWhileTypeExpr(),2643 .keyword_while => return try p.parseWhileTypeExpr(),
2788 else => return p.fail(.expected_inlinable),2644 else => return p.fail(.expected_inlinable),
2789 }2645 }
2790 },2646 },
2791 .keyword_for => return p.parseFor(expectTypeExpr),2647 .keyword_for => return try p.parseFor(expectTypeExpr),
2792 .keyword_while => return p.parseWhileTypeExpr(),2648 .keyword_while => return try p.parseWhileTypeExpr(),
2793 .period => switch (p.token_tags[p.tok_i + 1]) {2649 .period => switch (p.tokenTag(p.tok_i + 1)) {
2794 .identifier => return p.addNode(.{2650 .identifier => {
2795 .tag = .enum_literal,2651 p.tok_i += 1;
2796 .data = .{2652 return try p.addNode(.{
2797 .lhs = p.nextToken(), // dot2653 .tag = .enum_literal,
2798 .rhs = undefined,2654 .main_token = p.nextToken(), // identifier
2799 },2655 .data = undefined,
2800 .main_token = p.nextToken(), // identifier2656 });
2801 }),2657 },
2802 .l_brace => {2658 .l_brace => {
2803 const lbrace = p.tok_i + 1;2659 const lbrace = p.tok_i + 1;
2804 p.tok_i = lbrace + 1;2660 p.tok_i = lbrace + 1;
...@@ -2808,11 +2664,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2808,11 +2664,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28082664
2809 const scratch_top = p.scratch.items.len;2665 const scratch_top = p.scratch.items.len;
2810 defer p.scratch.shrinkRetainingCapacity(scratch_top);2666 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2811 const field_init = try p.parseFieldInit();2667 const opt_field_init = try p.parseFieldInit();
2812 if (field_init != 0) {2668 if (opt_field_init) |field_init| {
2813 try p.scratch.append(p.gpa, field_init);2669 try p.scratch.append(p.gpa, field_init);
2814 while (true) {2670 while (true) {
2815 switch (p.token_tags[p.tok_i]) {2671 switch (p.tokenTag(p.tok_i)) {
2816 .comma => p.tok_i += 1,2672 .comma => p.tok_i += 1,
2817 .r_brace => {2673 .r_brace => {
2818 p.tok_i += 1;2674 p.tok_i += 1;
...@@ -2826,37 +2682,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2826,37 +2682,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2826 const next = try p.expectFieldInit();2682 const next = try p.expectFieldInit();
2827 try p.scratch.append(p.gpa, next);2683 try p.scratch.append(p.gpa, next);
2828 }2684 }
2829 const comma = (p.token_tags[p.tok_i - 2] == .comma);2685 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2830 const inits = p.scratch.items[scratch_top..];2686 const inits = p.scratch.items[scratch_top..];
2831 switch (inits.len) {2687 std.debug.assert(inits.len != 0);
2832 0 => unreachable,2688 if (inits.len <= 2) {
2833 1 => return p.addNode(.{2689 return try p.addNode(.{
2834 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,2690 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
2835 .main_token = lbrace,2691 .main_token = lbrace,
2836 .data = .{2692 .data = .{ .opt_node_and_opt_node = .{
2837 .lhs = inits[0],2693 if (inits.len >= 1) .fromOptional(inits[0]) else .none,
2838 .rhs = 0,2694 if (inits.len >= 2) .fromOptional(inits[1]) else .none,
2839 },2695 } },
2840 }),2696 });
2841 2 => return p.addNode(.{2697 } else {
2842 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,2698 return try p.addNode(.{
2699 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
2843 .main_token = lbrace,2700 .main_token = lbrace,
2844 .data = .{2701 .data = .{ .extra_range = try p.listToSpan(inits) },
2845 .lhs = inits[0],2702 });
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 },
2860 }2703 }
2861 }2704 }
28622705
...@@ -2864,7 +2707,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2864,7 +2707,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2864 if (p.eatToken(.r_brace)) |_| break;2707 if (p.eatToken(.r_brace)) |_| break;
2865 const elem_init = try p.expectExpr();2708 const elem_init = try p.expectExpr();
2866 try p.scratch.append(p.gpa, elem_init);2709 try p.scratch.append(p.gpa, elem_init);
2867 switch (p.token_tags[p.tok_i]) {2710 switch (p.tokenTag(p.tok_i)) {
2868 .comma => p.tok_i += 1,2711 .comma => p.tok_i += 1,
2869 .r_brace => {2712 .r_brace => {
2870 p.tok_i += 1;2713 p.tok_i += 1;
...@@ -2875,49 +2718,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2875,49 +2718,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2875 else => try p.warn(.expected_comma_after_initializer),2718 else => try p.warn(.expected_comma_after_initializer),
2876 }2719 }
2877 }2720 }
2878 const comma = (p.token_tags[p.tok_i - 2] == .comma);2721 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2879 const inits = p.scratch.items[scratch_top..];2722 const inits = p.scratch.items[scratch_top..];
2880 switch (inits.len) {2723 if (inits.len <= 2) {
2881 0 => return p.addNode(.{2724 return try p.addNode(.{
2882 .tag = .struct_init_dot_two,2725 .tag = if (inits.len == 0)
2726 .struct_init_dot_two
2727 else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
2883 .main_token = lbrace,2728 .main_token = lbrace,
2884 .data = .{2729 .data = .{ .opt_node_and_opt_node = .{
2885 .lhs = 0,2730 if (inits.len >= 1) inits[0].toOptional() else .none,
2886 .rhs = 0,2731 if (inits.len >= 2) inits[1].toOptional() else .none,
2887 },2732 } },
2888 }),2733 });
2889 1 => return p.addNode(.{2734 } else {
2890 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,2735 return try p.addNode(.{
2891 .main_token = lbrace,2736 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
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,
2899 .main_token = lbrace,2737 .main_token = lbrace,
2900 .data = .{2738 .data = .{ .extra_range = try p.listToSpan(inits) },
2901 .lhs = inits[0],2739 });
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 },
2916 }2740 }
2917 },2741 },
2918 else => return null_node,2742 else => return null,
2919 },2743 },
2920 .keyword_error => switch (p.token_tags[p.tok_i + 1]) {2744 .keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
2921 .l_brace => {2745 .l_brace => {
2922 const error_token = p.tok_i;2746 const error_token = p.tok_i;
2923 p.tok_i += 2;2747 p.tok_i += 2;
...@@ -2925,7 +2749,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2925,7 +2749,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2925 if (p.eatToken(.r_brace)) |_| break;2749 if (p.eatToken(.r_brace)) |_| break;
2926 _ = try p.eatDocComments();2750 _ = try p.eatDocComments();
2927 _ = try p.expectToken(.identifier);2751 _ = try p.expectToken(.identifier);
2928 switch (p.token_tags[p.tok_i]) {2752 switch (p.tokenTag(p.tok_i)) {
2929 .comma => p.tok_i += 1,2753 .comma => p.tok_i += 1,
2930 .r_brace => {2754 .r_brace => {
2931 p.tok_i += 1;2755 p.tok_i += 1;
...@@ -2936,12 +2760,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2936,12 +2760,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2936 else => try p.warn(.expected_comma_after_field),2760 else => try p.warn(.expected_comma_after_field),
2937 }2761 }
2938 }2762 }
2939 return p.addNode(.{2763 return try p.addNode(.{
2940 .tag = .error_set_decl,2764 .tag = .error_set_decl,
2941 .main_token = error_token,2765 .main_token = error_token,
2942 .data = .{2766 .data = .{
2943 .lhs = undefined,2767 .token_and_token = .{
2944 .rhs = p.tok_i - 1, // rbrace2768 error_token + 1, // lbrace
2769 p.tok_i - 1, // rbrace
2770 },
2945 },2771 },
2946 });2772 });
2947 },2773 },
...@@ -2951,41 +2777,34 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2951,41 +2777,34 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2951 if (period == null) try p.warnExpected(.period);2777 if (period == null) try p.warnExpected(.period);
2952 const identifier = p.eatToken(.identifier);2778 const identifier = p.eatToken(.identifier);
2953 if (identifier == null) try p.warnExpected(.identifier);2779 if (identifier == null) try p.warnExpected(.identifier);
2954 return p.addNode(.{2780 return try p.addNode(.{
2955 .tag = .error_value,2781 .tag = .error_value,
2956 .main_token = main_token,2782 .main_token = main_token,
2957 .data = .{2783 .data = undefined,
2958 .lhs = period orelse 0,
2959 .rhs = identifier orelse 0,
2960 },
2961 });2784 });
2962 },2785 },
2963 },2786 },
2964 .l_paren => return p.addNode(.{2787 .l_paren => return try p.addNode(.{
2965 .tag = .grouped_expression,2788 .tag = .grouped_expression,
2966 .main_token = p.nextToken(),2789 .main_token = p.nextToken(),
2967 .data = .{2790 .data = .{ .node_and_token = .{
2968 .lhs = try p.expectExpr(),2791 try p.expectExpr(),
2969 .rhs = try p.expectToken(.r_paren),2792 try p.expectToken(.r_paren),
2970 },2793 } },
2971 }),2794 }),
2972 else => return null_node,2795 else => return null,
2973 }2796 }
2974}2797}
29752798
2976fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {2799fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {
2977 const node = try p.parsePrimaryTypeExpr();2800 return try p.parsePrimaryTypeExpr() orelse return p.fail(.expected_primary_type_expr);
2978 if (node == 0) {
2979 return p.fail(.expected_primary_type_expr);
2980 }
2981 return node;
2982}2801}
29832802
2984/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?2803/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
2985///2804///
2986/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?2805/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
2987fn parseWhileTypeExpr(p: *Parse) !Node.Index {2806fn parseWhileTypeExpr(p: *Parse) !?Node.Index {
2988 const while_token = p.eatToken(.keyword_while) orelse return null_node;2807 const while_token = p.eatToken(.keyword_while) orelse return null;
2989 _ = try p.expectToken(.l_paren);2808 _ = try p.expectToken(.l_paren);
2990 const condition = try p.expectExpr();2809 const condition = try p.expectExpr();
2991 _ = try p.expectToken(.r_paren);2810 _ = try p.expectToken(.r_paren);
...@@ -2994,54 +2813,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {...@@ -2994,54 +2813,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {
29942813
2995 const then_expr = try p.expectTypeExpr();2814 const then_expr = try p.expectTypeExpr();
2996 _ = p.eatToken(.keyword_else) orelse {2815 _ = p.eatToken(.keyword_else) orelse {
2997 if (cont_expr == 0) {2816 if (cont_expr == null) {
2998 return p.addNode(.{2817 return try p.addNode(.{
2999 .tag = .while_simple,2818 .tag = .while_simple,
3000 .main_token = while_token,2819 .main_token = while_token,
3001 .data = .{2820 .data = .{ .node_and_node = .{
3002 .lhs = condition,2821 condition,
3003 .rhs = then_expr,2822 then_expr,
3004 },2823 } },
3005 });2824 });
3006 } else {2825 } else {
3007 return p.addNode(.{2826 return try p.addNode(.{
3008 .tag = .while_cont,2827 .tag = .while_cont,
3009 .main_token = while_token,2828 .main_token = while_token,
3010 .data = .{2829 .data = .{ .node_and_extra = .{
3011 .lhs = condition,2830 condition, try p.addExtra(Node.WhileCont{
3012 .rhs = try p.addExtra(Node.WhileCont{2831 .cont_expr = cont_expr.?,
3013 .cont_expr = cont_expr,
3014 .then_expr = then_expr,2832 .then_expr = then_expr,
3015 }),2833 }),
3016 },2834 } },
3017 });2835 });
3018 }2836 }
3019 };2837 };
3020 _ = try p.parsePayload();2838 _ = try p.parsePayload();
3021 const else_expr = try p.expectTypeExpr();2839 const else_expr = try p.expectTypeExpr();
3022 return p.addNode(.{2840 return try p.addNode(.{
3023 .tag = .@"while",2841 .tag = .@"while",
3024 .main_token = while_token,2842 .main_token = while_token,
3025 .data = .{2843 .data = .{ .node_and_extra = .{
3026 .lhs = condition,2844 condition, try p.addExtra(Node.While{
3027 .rhs = try p.addExtra(Node.While{2845 .cont_expr = .fromOptional(cont_expr),
3028 .cont_expr = cont_expr,
3029 .then_expr = then_expr,2846 .then_expr = then_expr,
3030 .else_expr = else_expr,2847 .else_expr = else_expr,
3031 }),2848 }),
3032 },2849 } },
3033 });2850 });
3034}2851}
30352852
3036/// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE2853/// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
3037fn parseSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {2854fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index {
3038 const switch_token = p.eatToken(.keyword_switch) orelse return null_node;2855 const switch_token = p.eatToken(.keyword_switch) orelse return null;
3039 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);
3040}2857}
30412858
3042fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {2859fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {
3043 const switch_token = p.assertToken(.keyword_switch);2860 const switch_token = p.assertToken(.keyword_switch);
3044 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);2861 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
3045}2862}
30462863
3047fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {2864fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
...@@ -3050,19 +2867,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {...@@ -3050,19 +2867,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
3050 _ = try p.expectToken(.r_paren);2867 _ = try p.expectToken(.r_paren);
3051 _ = try p.expectToken(.l_brace);2868 _ = try p.expectToken(.l_brace);
3052 const cases = try p.parseSwitchProngList();2869 const cases = try p.parseSwitchProngList();
3053 const trailing_comma = p.token_tags[p.tok_i - 1] == .comma;2870 const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma;
3054 _ = try p.expectToken(.r_brace);2871 _ = try p.expectToken(.r_brace);
30552872
3056 return p.addNode(.{2873 return p.addNode(.{
3057 .tag = if (trailing_comma) .switch_comma else .@"switch",2874 .tag = if (trailing_comma) .switch_comma else .@"switch",
3058 .main_token = main_token,2875 .main_token = main_token,
3059 .data = .{2876 .data = .{ .node_and_extra = .{
3060 .lhs = expr_node,2877 expr_node,
3061 .rhs = try p.addExtra(Node.SubRange{2878 try p.addExtra(Node.SubRange{
3062 .start = cases.start,2879 .start = cases.start,
3063 .end = cases.end,2880 .end = cases.end,
3064 }),2881 }),
3065 },2882 } },
3066 });2883 });
3067}2884}
30682885
...@@ -3089,10 +2906,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3089,10 +2906,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3089 return p.addNode(.{2906 return p.addNode(.{
3090 .tag = .asm_simple,2907 .tag = .asm_simple,
3091 .main_token = asm_token,2908 .main_token = asm_token,
3092 .data = .{2909 .data = .{ .node_and_token = .{
3093 .lhs = template,2910 template,
3094 .rhs = rparen,2911 rparen,
3095 },2912 } },
3096 });2913 });
3097 }2914 }
30982915
...@@ -3102,10 +2919,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3102,10 +2919,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3102 defer p.scratch.shrinkRetainingCapacity(scratch_top);2919 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31032920
3104 while (true) {2921 while (true) {
3105 const output_item = try p.parseAsmOutputItem();2922 const output_item = try p.parseAsmOutputItem() orelse break;
3106 if (output_item == 0) break;
3107 try p.scratch.append(p.gpa, output_item);2923 try p.scratch.append(p.gpa, output_item);
3108 switch (p.token_tags[p.tok_i]) {2924 switch (p.tokenTag(p.tok_i)) {
3109 .comma => p.tok_i += 1,2925 .comma => p.tok_i += 1,
3110 // All possible delimiters.2926 // All possible delimiters.
3111 .colon, .r_paren, .r_brace, .r_bracket => break,2927 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3115,10 +2931,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3115,10 +2931,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3115 }2931 }
3116 if (p.eatToken(.colon)) |_| {2932 if (p.eatToken(.colon)) |_| {
3117 while (true) {2933 while (true) {
3118 const input_item = try p.parseAsmInputItem();2934 const input_item = try p.parseAsmInputItem() orelse break;
3119 if (input_item == 0) break;
3120 try p.scratch.append(p.gpa, input_item);2935 try p.scratch.append(p.gpa, input_item);
3121 switch (p.token_tags[p.tok_i]) {2936 switch (p.tokenTag(p.tok_i)) {
3122 .comma => p.tok_i += 1,2937 .comma => p.tok_i += 1,
3123 // All possible delimiters.2938 // All possible delimiters.
3124 .colon, .r_paren, .r_brace, .r_bracket => break,2939 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3128,7 +2943,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3128,7 +2943,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3128 }2943 }
3129 if (p.eatToken(.colon)) |_| {2944 if (p.eatToken(.colon)) |_| {
3130 while (p.eatToken(.string_literal)) |_| {2945 while (p.eatToken(.string_literal)) |_| {
3131 switch (p.token_tags[p.tok_i]) {2946 switch (p.tokenTag(p.tok_i)) {
3132 .comma => p.tok_i += 1,2947 .comma => p.tok_i += 1,
3133 .colon, .r_paren, .r_brace, .r_bracket => break,2948 .colon, .r_paren, .r_brace, .r_bracket => break,
3134 // Likely just a missing comma; give error but continue parsing.2949 // Likely just a missing comma; give error but continue parsing.
...@@ -3142,121 +2957,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3142,121 +2957,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3142 return p.addNode(.{2957 return p.addNode(.{
3143 .tag = .@"asm",2958 .tag = .@"asm",
3144 .main_token = asm_token,2959 .main_token = asm_token,
3145 .data = .{2960 .data = .{ .node_and_extra = .{
3146 .lhs = template,2961 template,
3147 .rhs = try p.addExtra(Node.Asm{2962 try p.addExtra(Node.Asm{
3148 .items_start = span.start,2963 .items_start = span.start,
3149 .items_end = span.end,2964 .items_end = span.end,
3150 .rparen = rparen,2965 .rparen = rparen,
3151 }),2966 }),
3152 },2967 } },
3153 });2968 });
3154}2969}
31552970
3156/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN2971/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
3157fn parseAsmOutputItem(p: *Parse) !Node.Index {2972fn parseAsmOutputItem(p: *Parse) !?Node.Index {
3158 _ = p.eatToken(.l_bracket) orelse return null_node;2973 _ = p.eatToken(.l_bracket) orelse return null;
3159 const identifier = try p.expectToken(.identifier);2974 const identifier = try p.expectToken(.identifier);
3160 _ = try p.expectToken(.r_bracket);2975 _ = try p.expectToken(.r_bracket);
3161 _ = try p.expectToken(.string_literal);2976 _ = try p.expectToken(.string_literal);
3162 _ = try p.expectToken(.l_paren);2977 _ = try p.expectToken(.l_paren);
3163 const type_expr: Node.Index = blk: {2978 const type_expr: Node.OptionalIndex = blk: {
3164 if (p.eatToken(.arrow)) |_| {2979 if (p.eatToken(.arrow)) |_| {
3165 break :blk try p.expectTypeExpr();2980 break :blk .fromOptional(try p.expectTypeExpr());
3166 } else {2981 } else {
3167 _ = try p.expectToken(.identifier);2982 _ = try p.expectToken(.identifier);
3168 break :blk null_node;2983 break :blk .none;
3169 }2984 }
3170 };2985 };
3171 const rparen = try p.expectToken(.r_paren);2986 const rparen = try p.expectToken(.r_paren);
3172 return p.addNode(.{2987 return try p.addNode(.{
3173 .tag = .asm_output,2988 .tag = .asm_output,
3174 .main_token = identifier,2989 .main_token = identifier,
3175 .data = .{2990 .data = .{ .opt_node_and_token = .{
3176 .lhs = type_expr,2991 type_expr,
3177 .rhs = rparen,2992 rparen,
3178 },2993 } },
3179 });2994 });
3180}2995}
31812996
3182/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN2997/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
3183fn parseAsmInputItem(p: *Parse) !Node.Index {2998fn parseAsmInputItem(p: *Parse) !?Node.Index {
3184 _ = p.eatToken(.l_bracket) orelse return null_node;2999 _ = p.eatToken(.l_bracket) orelse return null;
3185 const identifier = try p.expectToken(.identifier);3000 const identifier = try p.expectToken(.identifier);
3186 _ = try p.expectToken(.r_bracket);3001 _ = try p.expectToken(.r_bracket);
3187 _ = try p.expectToken(.string_literal);3002 _ = try p.expectToken(.string_literal);
3188 _ = try p.expectToken(.l_paren);3003 _ = try p.expectToken(.l_paren);
3189 const expr = try p.expectExpr();3004 const expr = try p.expectExpr();
3190 const rparen = try p.expectToken(.r_paren);3005 const rparen = try p.expectToken(.r_paren);
3191 return p.addNode(.{3006 return try p.addNode(.{
3192 .tag = .asm_input,3007 .tag = .asm_input,
3193 .main_token = identifier,3008 .main_token = identifier,
3194 .data = .{3009 .data = .{ .node_and_token = .{
3195 .lhs = expr,3010 expr,
3196 .rhs = rparen,3011 rparen,
3197 },3012 } },
3198 });3013 });
3199}3014}
32003015
3201/// BreakLabel <- COLON IDENTIFIER3016/// BreakLabel <- COLON IDENTIFIER
3202fn parseBreakLabel(p: *Parse) !TokenIndex {3017fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex {
3203 _ = p.eatToken(.colon) orelse return null_node;3018 _ = p.eatToken(.colon) orelse return .none;
3204 return p.expectToken(.identifier);3019 const next_token = try p.expectToken(.identifier);
3020 return .fromToken(next_token);
3205}3021}
32063022
3207/// BlockLabel <- IDENTIFIER COLON3023/// BlockLabel <- IDENTIFIER COLON
3208fn parseBlockLabel(p: *Parse) TokenIndex {3024fn parseBlockLabel(p: *Parse) ?TokenIndex {
3209 if (p.token_tags[p.tok_i] == .identifier and3025 return p.eatTokens(&.{ .identifier, .colon });
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;
3217}3026}
32183027
3219/// FieldInit <- DOT IDENTIFIER EQUAL Expr3028/// FieldInit <- DOT IDENTIFIER EQUAL Expr
3220fn parseFieldInit(p: *Parse) !Node.Index {3029fn parseFieldInit(p: *Parse) !?Node.Index {
3221 if (p.token_tags[p.tok_i + 0] == .period and3030 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3222 p.token_tags[p.tok_i + 1] == .identifier and3031 return try p.expectExpr();
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;
3229 }3032 }
3033 return null;
3230}3034}
32313035
3232fn expectFieldInit(p: *Parse) !Node.Index {3036fn expectFieldInit(p: *Parse) !Node.Index {
3233 if (p.token_tags[p.tok_i] != .period or3037 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3234 p.token_tags[p.tok_i + 1] != .identifier or3038 return try p.expectExpr();
3235 p.token_tags[p.tok_i + 2] != .equal)3039 }
3236 return p.fail(.expected_initializer);3040 return p.fail(.expected_initializer);
3237
3238 p.tok_i += 3;
3239 return p.expectExpr();
3240}3041}
32413042
3242/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN3043/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
3243fn parseWhileContinueExpr(p: *Parse) !Node.Index {3044fn parseWhileContinueExpr(p: *Parse) !?Node.Index {
3244 _ = p.eatToken(.colon) orelse {3045 _ = p.eatToken(.colon) orelse {
3245 if (p.token_tags[p.tok_i] == .l_paren and3046 if (p.tokenTag(p.tok_i) == .l_paren and
3246 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))3047 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
3247 return p.fail(.expected_continue_expr);3048 return p.fail(.expected_continue_expr);
3248 return null_node;3049 return null;
3249 };3050 };
3250 _ = try p.expectToken(.l_paren);3051 _ = try p.expectToken(.l_paren);
3251 const node = try p.parseAssignExpr();3052 const node = try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment);
3252 if (node == 0) return p.fail(.expected_expr_or_assignment);
3253 _ = try p.expectToken(.r_paren);3053 _ = try p.expectToken(.r_paren);
3254 return node;3054 return node;
3255}3055}
32563056
3257/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN3057/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
3258fn parseLinkSection(p: *Parse) !Node.Index {3058fn parseLinkSection(p: *Parse) !?Node.Index {
3259 _ = p.eatToken(.keyword_linksection) orelse return null_node;3059 _ = p.eatToken(.keyword_linksection) orelse return null;
3260 _ = try p.expectToken(.l_paren);3060 _ = try p.expectToken(.l_paren);
3261 const expr_node = try p.expectExpr();3061 const expr_node = try p.expectExpr();
3262 _ = try p.expectToken(.r_paren);3062 _ = try p.expectToken(.r_paren);
...@@ -3264,8 +3064,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {...@@ -3264,8 +3064,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {
3264}3064}
32653065
3266/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN3066/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
3267fn parseCallconv(p: *Parse) !Node.Index {3067fn parseCallconv(p: *Parse) !?Node.Index {
3268 _ = p.eatToken(.keyword_callconv) orelse return null_node;3068 _ = p.eatToken(.keyword_callconv) orelse return null;
3269 _ = try p.expectToken(.l_paren);3069 _ = try p.expectToken(.l_paren);
3270 const expr_node = try p.expectExpr();3070 const expr_node = try p.expectExpr();
3271 _ = try p.expectToken(.r_paren);3071 _ = try p.expectToken(.r_paren);
...@@ -3273,8 +3073,8 @@ fn parseCallconv(p: *Parse) !Node.Index {...@@ -3273,8 +3073,8 @@ fn parseCallconv(p: *Parse) !Node.Index {
3273}3073}
32743074
3275/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN3075/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
3276fn parseAddrSpace(p: *Parse) !Node.Index {3076fn parseAddrSpace(p: *Parse) !?Node.Index {
3277 _ = p.eatToken(.keyword_addrspace) orelse return null_node;3077 _ = p.eatToken(.keyword_addrspace) orelse return null;
3278 _ = try p.expectToken(.l_paren);3078 _ = try p.expectToken(.l_paren);
3279 const expr_node = try p.expectExpr();3079 const expr_node = try p.expectExpr();
3280 _ = try p.expectToken(.r_paren);3080 _ = try p.expectToken(.r_paren);
...@@ -3292,59 +3092,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {...@@ -3292,59 +3092,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {
3292/// ParamType3092/// ParamType
3293/// <- KEYWORD_anytype3093/// <- KEYWORD_anytype
3294/// / TypeExpr3094/// / TypeExpr
3295fn expectParamDecl(p: *Parse) !Node.Index {3095fn expectParamDecl(p: *Parse) !?Node.Index {
3296 _ = try p.eatDocComments();3096 _ = try p.eatDocComments();
3297 switch (p.token_tags[p.tok_i]) {3097 switch (p.tokenTag(p.tok_i)) {
3298 .keyword_noalias, .keyword_comptime => p.tok_i += 1,3098 .keyword_noalias, .keyword_comptime => p.tok_i += 1,
3299 .ellipsis3 => {3099 .ellipsis3 => {
3300 p.tok_i += 1;3100 p.tok_i += 1;
3301 return null_node;3101 return null;
3302 },3102 },
3303 else => {},3103 else => {},
3304 }3104 }
3305 if (p.token_tags[p.tok_i] == .identifier and3105 _ = p.eatTokens(&.{ .identifier, .colon });
3306 p.token_tags[p.tok_i + 1] == .colon)3106 if (p.eatToken(.keyword_anytype)) |_| {
3307 {3107 return null;
3308 p.tok_i += 2;3108 } else {
3309 }3109 return try p.expectTypeExpr();
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(),
3316 }3110 }
3317}3111}
33183112
3319/// Payload <- PIPE IDENTIFIER PIPE3113/// Payload <- PIPE IDENTIFIER PIPE
3320fn parsePayload(p: *Parse) !TokenIndex {3114fn parsePayload(p: *Parse) Error!OptionalTokenIndex {
3321 _ = p.eatToken(.pipe) orelse return null_node;3115 _ = p.eatToken(.pipe) orelse return .none;
3322 const identifier = try p.expectToken(.identifier);3116 const identifier = try p.expectToken(.identifier);
3323 _ = try p.expectToken(.pipe);3117 _ = try p.expectToken(.pipe);
3324 return identifier;3118 return .fromToken(identifier);
3325}3119}
33263120
3327/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE3121/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
3328fn parsePtrPayload(p: *Parse) !TokenIndex {3122fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex {
3329 _ = p.eatToken(.pipe) orelse return null_node;3123 _ = p.eatToken(.pipe) orelse return .none;
3330 _ = p.eatToken(.asterisk);3124 _ = p.eatToken(.asterisk);
3331 const identifier = try p.expectToken(.identifier);3125 const identifier = try p.expectToken(.identifier);
3332 _ = try p.expectToken(.pipe);3126 _ = try p.expectToken(.pipe);
3333 return identifier;3127 return .fromToken(identifier);
3334}3128}
33353129
3336/// Returns the first identifier token, if any.3130/// Returns the first identifier token, if any.
3337///3131///
3338/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE3132/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
3339fn parsePtrIndexPayload(p: *Parse) !TokenIndex {3133fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex {
3340 _ = p.eatToken(.pipe) orelse return null_node;3134 _ = p.eatToken(.pipe) orelse return .none;
3341 _ = p.eatToken(.asterisk);3135 _ = p.eatToken(.asterisk);
3342 const identifier = try p.expectToken(.identifier);3136 const identifier = try p.expectToken(.identifier);
3343 if (p.eatToken(.comma) != null) {3137 if (p.eatToken(.comma) != null) {
3344 _ = try p.expectToken(.identifier);3138 _ = try p.expectToken(.identifier);
3345 }3139 }
3346 _ = try p.expectToken(.pipe);3140 _ = try p.expectToken(.pipe);
3347 return identifier;3141 return .fromToken(identifier);
3348}3142}
33493143
3350/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr3144/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
...@@ -3352,7 +3146,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {...@@ -3352,7 +3146,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
3352/// SwitchCase3146/// SwitchCase
3353/// <- SwitchItem (COMMA SwitchItem)* COMMA?3147/// <- SwitchItem (COMMA SwitchItem)* COMMA?
3354/// / KEYWORD_else3148/// / KEYWORD_else
3355fn parseSwitchProng(p: *Parse) !Node.Index {3149fn parseSwitchProng(p: *Parse) !?Node.Index {
3356 const scratch_top = p.scratch.items.len;3150 const scratch_top = p.scratch.items.len;
3357 defer p.scratch.shrinkRetainingCapacity(scratch_top);3151 defer p.scratch.shrinkRetainingCapacity(scratch_top);
33583152
...@@ -3360,97 +3154,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {...@@ -3360,97 +3154,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {
33603154
3361 if (p.eatToken(.keyword_else) == null) {3155 if (p.eatToken(.keyword_else) == null) {
3362 while (true) {3156 while (true) {
3363 const item = try p.parseSwitchItem();3157 const item = try p.parseSwitchItem() orelse break;
3364 if (item == 0) break;
3365 try p.scratch.append(p.gpa, item);3158 try p.scratch.append(p.gpa, item);
3366 if (p.eatToken(.comma) == null) break;3159 if (p.eatToken(.comma) == null) break;
3367 }3160 }
3368 if (scratch_top == p.scratch.items.len) {3161 if (scratch_top == p.scratch.items.len) {
3369 if (is_inline) p.tok_i -= 1;3162 if (is_inline) p.tok_i -= 1;
3370 return null_node;3163 return null;
3371 }3164 }
3372 }3165 }
3373 const arrow_token = try p.expectToken(.equal_angle_bracket_right);3166 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
3374 _ = try p.parsePtrIndexPayload();3167 _ = try p.parsePtrIndexPayload();
33753168
3376 const items = p.scratch.items[scratch_top..];3169 const items = p.scratch.items[scratch_top..];
3377 switch (items.len) {3170 if (items.len <= 1) {
3378 0 => return p.addNode(.{3171 return try p.addNode(.{
3379 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,3172 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
3380 .main_token = arrow_token,3173 .main_token = arrow_token,
3381 .data = .{3174 .data = .{ .opt_node_and_node = .{
3382 .lhs = 0,3175 if (items.len >= 1) items[0].toOptional() else .none,
3383 .rhs = try p.expectSingleAssignExpr(),3176 try p.expectSingleAssignExpr(),
3384 },3177 } },
3385 }),3178 });
3386 1 => return p.addNode(.{3179 } else {
3387 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,3180 return try p.addNode(.{
3388 .main_token = arrow_token,
3389 .data = .{
3390 .lhs = items[0],
3391 .rhs = try p.expectSingleAssignExpr(),
3392 },
3393 }),
3394 else => return p.addNode(.{
3395 .tag = if (is_inline) .switch_case_inline else .switch_case,3181 .tag = if (is_inline) .switch_case_inline else .switch_case,
3396 .main_token = arrow_token,3182 .main_token = arrow_token,
3397 .data = .{3183 .data = .{ .extra_and_node = .{
3398 .lhs = try p.addExtra(try p.listToSpan(items)),3184 try p.addExtra(try p.listToSpan(items)),
3399 .rhs = try p.expectSingleAssignExpr(),3185 try p.expectSingleAssignExpr(),
3400 },3186 } },
3401 }),3187 });
3402 }3188 }
3403}3189}
34043190
3405/// SwitchItem <- Expr (DOT3 Expr)?3191/// SwitchItem <- Expr (DOT3 Expr)?
3406fn parseSwitchItem(p: *Parse) !Node.Index {3192fn parseSwitchItem(p: *Parse) !?Node.Index {
3407 const expr = try p.parseExpr();3193 const expr = try p.parseExpr() orelse return null;
3408 if (expr == 0) return null_node;
34093194
3410 if (p.eatToken(.ellipsis3)) |token| {3195 if (p.eatToken(.ellipsis3)) |token| {
3411 return p.addNode(.{3196 return try p.addNode(.{
3412 .tag = .switch_range,3197 .tag = .switch_range,
3413 .main_token = token,3198 .main_token = token,
3414 .data = .{3199 .data = .{ .node_and_node = .{
3415 .lhs = expr,3200 expr,
3416 .rhs = try p.expectExpr(),3201 try p.expectExpr(),
3417 },3202 } },
3418 });3203 });
3419 }3204 }
3420 return expr;3205 return expr;
3421}3206}
34223207
3208/// The following invariant will hold:
3209/// - `(bit_range_start == .none) == (bit_range_end == .none)`
3210/// - `bit_range_start != .none` implies `align_node != .none`
3211/// - `bit_range_end != .none` implies `align_node != .none`
3423const PtrModifiers = struct {3212const PtrModifiers = struct {
3424 align_node: Node.Index,3213 align_node: Node.OptionalIndex,
3425 addrspace_node: Node.Index,3214 addrspace_node: Node.OptionalIndex,
3426 bit_range_start: Node.Index,3215 bit_range_start: Node.OptionalIndex,
3427 bit_range_end: Node.Index,3216 bit_range_end: Node.OptionalIndex,
3428};3217};
34293218
3430fn parsePtrModifiers(p: *Parse) !PtrModifiers {3219fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3431 var result: PtrModifiers = .{3220 var result: PtrModifiers = .{
3432 .align_node = 0,3221 .align_node = .none,
3433 .addrspace_node = 0,3222 .addrspace_node = .none,
3434 .bit_range_start = 0,3223 .bit_range_start = .none,
3435 .bit_range_end = 0,3224 .bit_range_end = .none,
3436 };3225 };
3437 var saw_const = false;3226 var saw_const = false;
3438 var saw_volatile = false;3227 var saw_volatile = false;
3439 var saw_allowzero = false;3228 var saw_allowzero = false;
3440 while (true) {3229 while (true) {
3441 switch (p.token_tags[p.tok_i]) {3230 switch (p.tokenTag(p.tok_i)) {
3442 .keyword_align => {3231 .keyword_align => {
3443 if (result.align_node != 0) {3232 if (result.align_node != .none) {
3444 try p.warn(.extra_align_qualifier);3233 try p.warn(.extra_align_qualifier);
3445 }3234 }
3446 p.tok_i += 1;3235 p.tok_i += 1;
3447 _ = try p.expectToken(.l_paren);3236 _ = try p.expectToken(.l_paren);
3448 result.align_node = try p.expectExpr();3237 result.align_node = (try p.expectExpr()).toOptional();
34493238
3450 if (p.eatToken(.colon)) |_| {3239 if (p.eatToken(.colon)) |_| {
3451 result.bit_range_start = try p.expectExpr();3240 result.bit_range_start = (try p.expectExpr()).toOptional();
3452 _ = try p.expectToken(.colon);3241 _ = try p.expectToken(.colon);
3453 result.bit_range_end = try p.expectExpr();3242 result.bit_range_end = (try p.expectExpr()).toOptional();
3454 }3243 }
34553244
3456 _ = try p.expectToken(.r_paren);3245 _ = try p.expectToken(.r_paren);
...@@ -3477,10 +3266,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {...@@ -3477,10 +3266,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3477 saw_allowzero = true;3266 saw_allowzero = true;
3478 },3267 },
3479 .keyword_addrspace => {3268 .keyword_addrspace => {
3480 if (result.addrspace_node != 0) {3269 if (result.addrspace_node != .none) {
3481 try p.warn(.extra_addrspace_qualifier);3270 try p.warn(.extra_addrspace_qualifier);
3482 }3271 }
3483 result.addrspace_node = try p.parseAddrSpace();3272 result.addrspace_node = .fromOptional(try p.parseAddrSpace());
3484 },3273 },
3485 else => return result,3274 else => return result,
3486 }3275 }
...@@ -3492,110 +3281,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {...@@ -3492,110 +3281,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3492/// / DOT IDENTIFIER3281/// / DOT IDENTIFIER
3493/// / DOTASTERISK3282/// / DOTASTERISK
3494/// / DOTQUESTIONMARK3283/// / DOTQUESTIONMARK
3495fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {3284fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
3496 switch (p.token_tags[p.tok_i]) {3285 switch (p.tokenTag(p.tok_i)) {
3497 .l_bracket => {3286 .l_bracket => {
3498 const lbracket = p.nextToken();3287 const lbracket = p.nextToken();
3499 const index_expr = try p.expectExpr();3288 const index_expr = try p.expectExpr();
35003289
3501 if (p.eatToken(.ellipsis2)) |_| {3290 if (p.eatToken(.ellipsis2)) |_| {
3502 const end_expr = try p.parseExpr();3291 const opt_end_expr = try p.parseExpr();
3503 if (p.eatToken(.colon)) |_| {3292 if (p.eatToken(.colon)) |_| {
3504 const sentinel = try p.expectExpr();3293 const sentinel = try p.expectExpr();
3505 _ = try p.expectToken(.r_bracket);3294 _ = try p.expectToken(.r_bracket);
3506 return p.addNode(.{3295 return try p.addNode(.{
3507 .tag = .slice_sentinel,3296 .tag = .slice_sentinel,
3508 .main_token = lbracket,3297 .main_token = lbracket,
3509 .data = .{3298 .data = .{ .node_and_extra = .{
3510 .lhs = lhs,3299 lhs, try p.addExtra(Node.SliceSentinel{
3511 .rhs = try p.addExtra(Node.SliceSentinel{
3512 .start = index_expr,3300 .start = index_expr,
3513 .end = end_expr,3301 .end = .fromOptional(opt_end_expr),
3514 .sentinel = sentinel,3302 .sentinel = sentinel,
3515 }),3303 }),
3516 },3304 } },
3517 });3305 });
3518 }3306 }
3519 _ = try p.expectToken(.r_bracket);3307 _ = try p.expectToken(.r_bracket);
3520 if (end_expr == 0) {3308 const end_expr = opt_end_expr orelse {
3521 return p.addNode(.{3309 return try p.addNode(.{
3522 .tag = .slice_open,3310 .tag = .slice_open,
3523 .main_token = lbracket,3311 .main_token = lbracket,
3524 .data = .{3312 .data = .{ .node_and_node = .{
3525 .lhs = lhs,3313 lhs,
3526 .rhs = index_expr,3314 index_expr,
3527 },3315 } },
3528 });3316 });
3529 }3317 };
3530 return p.addNode(.{3318 return try p.addNode(.{
3531 .tag = .slice,3319 .tag = .slice,
3532 .main_token = lbracket,3320 .main_token = lbracket,
3533 .data = .{3321 .data = .{ .node_and_extra = .{
3534 .lhs = lhs,3322 lhs, try p.addExtra(Node.Slice{
3535 .rhs = try p.addExtra(Node.Slice{
3536 .start = index_expr,3323 .start = index_expr,
3537 .end = end_expr,3324 .end = end_expr,
3538 }),3325 }),
3539 },3326 } },
3540 });3327 });
3541 }3328 }
3542 _ = try p.expectToken(.r_bracket);3329 _ = try p.expectToken(.r_bracket);
3543 return p.addNode(.{3330 return try p.addNode(.{
3544 .tag = .array_access,3331 .tag = .array_access,
3545 .main_token = lbracket,3332 .main_token = lbracket,
3546 .data = .{3333 .data = .{ .node_and_node = .{
3547 .lhs = lhs,3334 lhs,
3548 .rhs = index_expr,3335 index_expr,
3549 },3336 } },
3550 });3337 });
3551 },3338 },
3552 .period_asterisk => return p.addNode(.{3339 .period_asterisk => return try p.addNode(.{
3553 .tag = .deref,3340 .tag = .deref,
3554 .main_token = p.nextToken(),3341 .main_token = p.nextToken(),
3555 .data = .{3342 .data = .{ .node = lhs },
3556 .lhs = lhs,
3557 .rhs = undefined,
3558 },
3559 }),3343 }),
3560 .invalid_periodasterisks => {3344 .invalid_periodasterisks => {
3561 try p.warn(.asterisk_after_ptr_deref);3345 try p.warn(.asterisk_after_ptr_deref);
3562 return p.addNode(.{3346 return try p.addNode(.{
3563 .tag = .deref,3347 .tag = .deref,
3564 .main_token = p.nextToken(),3348 .main_token = p.nextToken(),
3565 .data = .{3349 .data = .{ .node = lhs },
3566 .lhs = lhs,
3567 .rhs = undefined,
3568 },
3569 });3350 });
3570 },3351 },
3571 .period => switch (p.token_tags[p.tok_i + 1]) {3352 .period => switch (p.tokenTag(p.tok_i + 1)) {
3572 .identifier => return p.addNode(.{3353 .identifier => return try p.addNode(.{
3573 .tag = .field_access,3354 .tag = .field_access,
3574 .main_token = p.nextToken(),3355 .main_token = p.nextToken(),
3575 .data = .{3356 .data = .{ .node_and_token = .{
3576 .lhs = lhs,3357 lhs,
3577 .rhs = p.nextToken(),3358 p.nextToken(),
3578 },3359 } },
3579 }),3360 }),
3580 .question_mark => return p.addNode(.{3361 .question_mark => return try p.addNode(.{
3581 .tag = .unwrap_optional,3362 .tag = .unwrap_optional,
3582 .main_token = p.nextToken(),3363 .main_token = p.nextToken(),
3583 .data = .{3364 .data = .{ .node_and_token = .{
3584 .lhs = lhs,3365 lhs,
3585 .rhs = p.nextToken(),3366 p.nextToken(),
3586 },3367 } },
3587 }),3368 }),
3588 .l_brace => {3369 .l_brace => {
3589 // this a misplaced `.{`, handle the error somewhere else3370 // this a misplaced `.{`, handle the error somewhere else
3590 return null_node;3371 return null;
3591 },3372 },
3592 else => {3373 else => {
3593 p.tok_i += 1;3374 p.tok_i += 1;
3594 try p.warn(.expected_suffix_op);3375 try p.warn(.expected_suffix_op);
3595 return null_node;3376 return null;
3596 },3377 },
3597 },3378 },
3598 else => return null_node,3379 else => return null,
3599 }3380 }
3600}3381}
36013382
...@@ -3608,17 +3389,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {...@@ -3608,17 +3389,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
3608/// / KEYWORD_opaque3389/// / KEYWORD_opaque
3609/// / KEYWORD_enum (LPAREN Expr RPAREN)?3390/// / KEYWORD_enum (LPAREN Expr RPAREN)?
3610/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?3391/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
3611fn parseContainerDeclAuto(p: *Parse) !Node.Index {3392fn parseContainerDeclAuto(p: *Parse) !?Node.Index {
3612 const main_token = p.nextToken();3393 const main_token = p.nextToken();
3613 const arg_expr = switch (p.token_tags[main_token]) {3394 const arg_expr = switch (p.tokenTag(main_token)) {
3614 .keyword_opaque => null_node,3395 .keyword_opaque => null,
3615 .keyword_struct, .keyword_enum => blk: {3396 .keyword_struct, .keyword_enum => blk: {
3616 if (p.eatToken(.l_paren)) |_| {3397 if (p.eatToken(.l_paren)) |_| {
3617 const expr = try p.expectExpr();3398 const expr = try p.expectExpr();
3618 _ = try p.expectToken(.r_paren);3399 _ = try p.expectToken(.r_paren);
3619 break :blk expr;3400 break :blk expr;
3620 } else {3401 } else {
3621 break :blk null_node;3402 break :blk null;
3622 }3403 }
3623 },3404 },
3624 .keyword_union => blk: {3405 .keyword_union => blk: {
...@@ -3633,16 +3414,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3633,16 +3414,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3633 const members = try p.parseContainerMembers();3414 const members = try p.parseContainerMembers();
3634 const members_span = try members.toSpan(p);3415 const members_span = try members.toSpan(p);
3635 _ = try p.expectToken(.r_brace);3416 _ = try p.expectToken(.r_brace);
3636 return p.addNode(.{3417 return try p.addNode(.{
3637 .tag = switch (members.trailing) {3418 .tag = switch (members.trailing) {
3638 true => .tagged_union_enum_tag_trailing,3419 true => .tagged_union_enum_tag_trailing,
3639 false => .tagged_union_enum_tag,3420 false => .tagged_union_enum_tag,
3640 },3421 },
3641 .main_token = main_token,3422 .main_token = main_token,
3642 .data = .{3423 .data = .{ .node_and_extra = .{
3643 .lhs = enum_tag_expr,3424 enum_tag_expr,
3644 .rhs = try p.addExtra(members_span),3425 try p.addExtra(members_span),
3645 },3426 } },
3646 });3427 });
3647 } else {3428 } else {
3648 _ = try p.expectToken(.r_paren);3429 _ = try p.expectToken(.r_paren);
...@@ -3651,29 +3432,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3651,29 +3432,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3651 const members = try p.parseContainerMembers();3432 const members = try p.parseContainerMembers();
3652 _ = try p.expectToken(.r_brace);3433 _ = try p.expectToken(.r_brace);
3653 if (members.len <= 2) {3434 if (members.len <= 2) {
3654 return p.addNode(.{3435 return try p.addNode(.{
3655 .tag = switch (members.trailing) {3436 .tag = switch (members.trailing) {
3656 true => .tagged_union_two_trailing,3437 true => .tagged_union_two_trailing,
3657 false => .tagged_union_two,3438 false => .tagged_union_two,
3658 },3439 },
3659 .main_token = main_token,3440 .main_token = main_token,
3660 .data = .{3441 .data = members.data,
3661 .lhs = members.lhs,
3662 .rhs = members.rhs,
3663 },
3664 });3442 });
3665 } else {3443 } else {
3666 const span = try members.toSpan(p);3444 const span = try members.toSpan(p);
3667 return p.addNode(.{3445 return try p.addNode(.{
3668 .tag = switch (members.trailing) {3446 .tag = switch (members.trailing) {
3669 true => .tagged_union_trailing,3447 true => .tagged_union_trailing,
3670 false => .tagged_union,3448 false => .tagged_union,
3671 },3449 },
3672 .main_token = main_token,3450 .main_token = main_token,
3673 .data = .{3451 .data = .{ .extra_range = span },
3674 .lhs = span.start,
3675 .rhs = span.end,
3676 },
3677 });3452 });
3678 }3453 }
3679 }3454 }
...@@ -3683,7 +3458,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3683,7 +3458,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3683 break :blk expr;3458 break :blk expr;
3684 }3459 }
3685 } else {3460 } else {
3686 break :blk null_node;3461 break :blk null;
3687 }3462 }
3688 },3463 },
3689 else => {3464 else => {
...@@ -3694,48 +3469,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3694,48 +3469,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3694 _ = try p.expectToken(.l_brace);3469 _ = try p.expectToken(.l_brace);
3695 const members = try p.parseContainerMembers();3470 const members = try p.parseContainerMembers();
3696 _ = try p.expectToken(.r_brace);3471 _ = try p.expectToken(.r_brace);
3697 if (arg_expr == 0) {3472 if (arg_expr == null) {
3698 if (members.len <= 2) {3473 if (members.len <= 2) {
3699 return p.addNode(.{3474 return try p.addNode(.{
3700 .tag = switch (members.trailing) {3475 .tag = switch (members.trailing) {
3701 true => .container_decl_two_trailing,3476 true => .container_decl_two_trailing,
3702 false => .container_decl_two,3477 false => .container_decl_two,
3703 },3478 },
3704 .main_token = main_token,3479 .main_token = main_token,
3705 .data = .{3480 .data = members.data,
3706 .lhs = members.lhs,
3707 .rhs = members.rhs,
3708 },
3709 });3481 });
3710 } else {3482 } else {
3711 const span = try members.toSpan(p);3483 const span = try members.toSpan(p);
3712 return p.addNode(.{3484 return try p.addNode(.{
3713 .tag = switch (members.trailing) {3485 .tag = switch (members.trailing) {
3714 true => .container_decl_trailing,3486 true => .container_decl_trailing,
3715 false => .container_decl,3487 false => .container_decl,
3716 },3488 },
3717 .main_token = main_token,3489 .main_token = main_token,
3718 .data = .{3490 .data = .{ .extra_range = span },
3719 .lhs = span.start,
3720 .rhs = span.end,
3721 },
3722 });3491 });
3723 }3492 }
3724 } else {3493 } else {
3725 const span = try members.toSpan(p);3494 const span = try members.toSpan(p);
3726 return p.addNode(.{3495 return try p.addNode(.{
3727 .tag = switch (members.trailing) {3496 .tag = switch (members.trailing) {
3728 true => .container_decl_arg_trailing,3497 true => .container_decl_arg_trailing,
3729 false => .container_decl_arg,3498 false => .container_decl_arg,
3730 },3499 },
3731 .main_token = main_token,3500 .main_token = main_token,
3732 .data = .{3501 .data = .{ .node_and_extra = .{
3733 .lhs = arg_expr,3502 arg_expr.?,
3734 .rhs = try p.addExtra(Node.SubRange{3503 try p.addExtra(Node.SubRange{
3735 .start = span.start,3504 .start = span.start,
3736 .end = span.end,3505 .end = span.end,
3737 }),3506 }),
3738 },3507 } },
3739 });3508 });
3740 }3509 }
3741}3510}
...@@ -3744,24 +3513,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3744,24 +3513,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3744/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.3513/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.
3745fn parseCStyleContainer(p: *Parse) Error!bool {3514fn parseCStyleContainer(p: *Parse) Error!bool {
3746 const main_token = p.tok_i;3515 const main_token = p.tok_i;
3747 switch (p.token_tags[p.tok_i]) {3516 switch (p.tokenTag(p.tok_i)) {
3748 .keyword_enum, .keyword_union, .keyword_struct => {},3517 .keyword_enum, .keyword_union, .keyword_struct => {},
3749 else => return false,3518 else => return false,
3750 }3519 }
3751 const identifier = p.tok_i + 1;3520 const identifier = p.tok_i + 1;
3752 if (p.token_tags[identifier] != .identifier) return false;3521 if (p.tokenTag(identifier) != .identifier) return false;
3753 p.tok_i += 2;3522 p.tok_i += 2;
37543523
3755 try p.warnMsg(.{3524 try p.warnMsg(.{
3756 .tag = .c_style_container,3525 .tag = .c_style_container,
3757 .token = identifier,3526 .token = identifier,
3758 .extra = .{ .expected_tag = p.token_tags[main_token] },3527 .extra = .{ .expected_tag = p.tokenTag(main_token) },
3759 });3528 });
3760 try p.warnMsg(.{3529 try p.warnMsg(.{
3761 .tag = .zig_style_container,3530 .tag = .zig_style_container,
3762 .is_note = true,3531 .is_note = true,
3763 .token = identifier,3532 .token = identifier,
3764 .extra = .{ .expected_tag = p.token_tags[main_token] },3533 .extra = .{ .expected_tag = p.tokenTag(main_token) },
3765 });3534 });
37663535
3767 _ = try p.expectToken(.l_brace);3536 _ = try p.expectToken(.l_brace);
...@@ -3774,8 +3543,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {...@@ -3774,8 +3543,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {
3774/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.3543/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.
3775///3544///
3776/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN3545/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
3777fn parseByteAlign(p: *Parse) !Node.Index {3546fn parseByteAlign(p: *Parse) !?Node.Index {
3778 _ = p.eatToken(.keyword_align) orelse return null_node;3547 _ = p.eatToken(.keyword_align) orelse return null;
3779 _ = try p.expectToken(.l_paren);3548 _ = try p.expectToken(.l_paren);
3780 const expr = try p.expectExpr();3549 const expr = try p.expectExpr();
3781 _ = try p.expectToken(.r_paren);3550 _ = try p.expectToken(.r_paren);
...@@ -3788,12 +3557,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {...@@ -3788,12 +3557,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {
3788 defer p.scratch.shrinkRetainingCapacity(scratch_top);3557 defer p.scratch.shrinkRetainingCapacity(scratch_top);
37893558
3790 while (true) {3559 while (true) {
3791 const item = try parseSwitchProng(p);3560 const item = try parseSwitchProng(p) orelse break;
3792 if (item == 0) break;
37933561
3794 try p.scratch.append(p.gpa, item);3562 try p.scratch.append(p.gpa, item);
37953563
3796 switch (p.token_tags[p.tok_i]) {3564 switch (p.tokenTag(p.tok_i)) {
3797 .comma => p.tok_i += 1,3565 .comma => p.tok_i += 1,
3798 // All possible delimiters.3566 // All possible delimiters.
3799 .colon, .r_paren, .r_brace, .r_bracket => break,3567 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3813,13 +3581,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {...@@ -3813,13 +3581,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
3813 while (true) {3581 while (true) {
3814 if (p.eatToken(.r_paren)) |_| break;3582 if (p.eatToken(.r_paren)) |_| break;
3815 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };3583 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
3816 const param = try p.expectParamDecl();3584 const opt_param = try p.expectParamDecl();
3817 if (param != 0) {3585 if (opt_param) |param| {
3818 try p.scratch.append(p.gpa, param);3586 try p.scratch.append(p.gpa, param);
3819 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {3587 } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) {
3820 if (varargs == .none) varargs = .seen;3588 if (varargs == .none) varargs = .seen;
3821 }3589 }
3822 switch (p.token_tags[p.tok_i]) {3590 switch (p.tokenTag(p.tok_i)) {
3823 .comma => p.tok_i += 1,3591 .comma => p.tok_i += 1,
3824 .r_paren => {3592 .r_paren => {
3825 p.tok_i += 1;3593 p.tok_i += 1;
...@@ -3835,9 +3603,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {...@@ -3835,9 +3603,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
3835 }3603 }
3836 const params = p.scratch.items[scratch_top..];3604 const params = p.scratch.items[scratch_top..];
3837 return switch (params.len) {3605 return switch (params.len) {
3838 0 => SmallSpan{ .zero_or_one = 0 },3606 0 => .{ .zero_or_one = .none },
3839 1 => SmallSpan{ .zero_or_one = params[0] },3607 1 => .{ .zero_or_one = params[0].toOptional() },
3840 else => SmallSpan{ .multi = try p.listToSpan(params) },3608 else => .{ .multi = try p.listToSpan(params) },
3841 };3609 };
3842}3610}
38433611
...@@ -3852,10 +3620,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3852,10 +3620,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3852 return p.addNode(.{3620 return p.addNode(.{
3853 .tag = .identifier,3621 .tag = .identifier,
3854 .main_token = builtin_token,3622 .main_token = builtin_token,
3855 .data = .{3623 .data = undefined,
3856 .lhs = undefined,
3857 .rhs = undefined,
3858 },
3859 });3624 });
3860 };3625 };
3861 const scratch_top = p.scratch.items.len;3626 const scratch_top = p.scratch.items.len;
...@@ -3864,7 +3629,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3864,7 +3629,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3864 if (p.eatToken(.r_paren)) |_| break;3629 if (p.eatToken(.r_paren)) |_| break;
3865 const param = try p.expectExpr();3630 const param = try p.expectExpr();
3866 try p.scratch.append(p.gpa, param);3631 try p.scratch.append(p.gpa, param);
3867 switch (p.token_tags[p.tok_i]) {3632 switch (p.tokenTag(p.tok_i)) {
3868 .comma => p.tok_i += 1,3633 .comma => p.tok_i += 1,
3869 .r_paren => {3634 .r_paren => {
3870 p.tok_i += 1;3635 p.tok_i += 1;
...@@ -3874,88 +3639,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3874,88 +3639,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3874 else => try p.warn(.expected_comma_after_arg),3639 else => try p.warn(.expected_comma_after_arg),
3875 }3640 }
3876 }3641 }
3877 const comma = (p.token_tags[p.tok_i - 2] == .comma);3642 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
3878 const params = p.scratch.items[scratch_top..];3643 const params = p.scratch.items[scratch_top..];
3879 switch (params.len) {3644 if (params.len <= 2) {
3880 0 => return p.addNode(.{3645 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(.{
3889 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,3646 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
3890 .main_token = builtin_token,3647 .main_token = builtin_token,
3891 .data = .{3648 .data = .{ .opt_node_and_opt_node = .{
3892 .lhs = params[0],3649 if (params.len >= 1) .fromOptional(params[0]) else .none,
3893 .rhs = 0,3650 if (params.len >= 2) .fromOptional(params[1]) else .none,
3894 },3651 } },
3895 }),3652 });
3896 2 => return p.addNode(.{3653 } else {
3897 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,3654 const span = try p.listToSpan(params);
3655 return p.addNode(.{
3656 .tag = if (comma) .builtin_call_comma else .builtin_call,
3898 .main_token = builtin_token,3657 .main_token = builtin_token,
3899 .data = .{3658 .data = .{ .extra_range = span },
3900 .lhs = params[0],3659 });
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 },
3915 }3660 }
3916}3661}
39173662
3918/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?3663/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
3919fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {3664fn 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;3665 const if_token = p.eatToken(.keyword_if) orelse return null;
3921 _ = try p.expectToken(.l_paren);3666 _ = try p.expectToken(.l_paren);
3922 const condition = try p.expectExpr();3667 const condition = try p.expectExpr();
3923 _ = try p.expectToken(.r_paren);3668 _ = try p.expectToken(.r_paren);
3924 _ = try p.parsePtrPayload();3669 _ = try p.parsePtrPayload();
39253670
3926 const then_expr = try bodyParseFn(p);3671 const then_expr = try bodyParseFn(p);
3927 assert(then_expr != 0);
39283672
3929 _ = p.eatToken(.keyword_else) orelse return p.addNode(.{3673 _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{
3930 .tag = .if_simple,3674 .tag = .if_simple,
3931 .main_token = if_token,3675 .main_token = if_token,
3932 .data = .{3676 .data = .{ .node_and_node = .{
3933 .lhs = condition,3677 condition,
3934 .rhs = then_expr,3678 then_expr,
3935 },3679 } },
3936 });3680 });
3937 _ = try p.parsePayload();3681 _ = try p.parsePayload();
3938 const else_expr = try bodyParseFn(p);3682 const else_expr = try bodyParseFn(p);
3939 assert(else_expr != 0);
39403683
3941 return p.addNode(.{3684 return try p.addNode(.{
3942 .tag = .@"if",3685 .tag = .@"if",
3943 .main_token = if_token,3686 .main_token = if_token,
3944 .data = .{3687 .data = .{ .node_and_extra = .{
3945 .lhs = condition,3688 condition,
3946 .rhs = try p.addExtra(Node.If{3689 try p.addExtra(Node.If{
3947 .then_expr = then_expr,3690 .then_expr = then_expr,
3948 .else_expr = else_expr,3691 .else_expr = else_expr,
3949 }),3692 }),
3950 },3693 } },
3951 });3694 });
3952}3695}
39533696
3954/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?3697/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
3955///3698///
3956/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?3699/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3957fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {3700fn 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;3701 const for_token = p.eatToken(.keyword_for) orelse return null;
39593702
3960 const scratch_top = p.scratch.items.len;3703 const scratch_top = p.scratch.items.len;
3961 defer p.scratch.shrinkRetainingCapacity(scratch_top);3704 defer p.scratch.shrinkRetainingCapacity(scratch_top);
...@@ -3969,27 +3712,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N...@@ -3969,27 +3712,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N
3969 try p.scratch.append(p.gpa, else_expr);3712 try p.scratch.append(p.gpa, else_expr);
3970 has_else = true;3713 has_else = true;
3971 } else if (inputs == 1) {3714 } else if (inputs == 1) {
3972 return p.addNode(.{3715 return try p.addNode(.{
3973 .tag = .for_simple,3716 .tag = .for_simple,
3974 .main_token = for_token,3717 .main_token = for_token,
3975 .data = .{3718 .data = .{ .node_and_node = .{
3976 .lhs = p.scratch.items[scratch_top],3719 p.scratch.items[scratch_top],
3977 .rhs = then_expr,3720 then_expr,
3978 },3721 } },
3979 });3722 });
3980 } else {3723 } else {
3981 try p.scratch.append(p.gpa, then_expr);3724 try p.scratch.append(p.gpa, then_expr);
3982 }3725 }
3983 return p.addNode(.{3726 return try p.addNode(.{
3984 .tag = .@"for",3727 .tag = .@"for",
3985 .main_token = for_token,3728 .main_token = for_token,
3986 .data = .{3729 .data = .{ .@"for" = .{
3987 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,3730 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3988 .rhs = @as(u32, @bitCast(Node.For{3731 .{ .inputs = @intCast(inputs), .has_else = has_else },
3989 .inputs = @as(u31, @intCast(inputs)),3732 } },
3990 .has_else = has_else,
3991 })),
3992 },
3993 });3733 });
3994}3734}
39953735
...@@ -4011,21 +3751,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {...@@ -4011,21 +3751,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
4011}3751}
40123752
4013fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool {3753fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool {
4014 return std.mem.indexOfScalar(u8, p.source[p.token_starts[token1]..p.token_starts[token2]], '\n') == null;3754 return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null;
4015}3755}
40163756
4017fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {3757fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {
4018 return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null;3758 return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null;
3759}
3760
3761fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex {
3762 const available_tags = p.tokens.items(.tag)[p.tok_i..];
3763 if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null;
3764 const result = p.tok_i;
3765 p.tok_i += @intCast(tags.len);
3766 return result;
4019}3767}
40203768
4021fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {3769fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {
4022 const token = p.nextToken();3770 const token = p.nextToken();
4023 assert(p.token_tags[token] == tag);3771 assert(p.tokenTag(token) == tag);
4024 return token;3772 return token;
4025}3773}
40263774
4027fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {3775fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4028 if (p.token_tags[p.tok_i] != tag) {3776 if (p.tokenTag(p.tok_i) != tag) {
4029 return p.failMsg(.{3777 return p.failMsg(.{
4030 .tag = .expected_token,3778 .tag = .expected_token,
4031 .token = p.tok_i,3779 .token = p.tok_i,
...@@ -4036,7 +3784,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {...@@ -4036,7 +3784,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4036}3784}
40373785
4038fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {3786fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {
4039 if (p.token_tags[p.tok_i] == .semicolon) {3787 if (p.tokenTag(p.tok_i) == .semicolon) {
4040 _ = p.nextToken();3788 _ = p.nextToken();
4041 return;3789 return;
4042 }3790 }
...@@ -4050,8 +3798,6 @@ fn nextToken(p: *Parse) TokenIndex {...@@ -4050,8 +3798,6 @@ fn nextToken(p: *Parse) TokenIndex {
4050 return result;3798 return result;
4051}3799}
40523800
4053const null_node: Node.Index = 0;
4054
4055const Parse = @This();3801const Parse = @This();
4056const std = @import("../std.zig");3802const std = @import("../std.zig");
4057const assert = std.debug.assert;3803const assert = std.debug.assert;
...@@ -4060,6 +3806,8 @@ const Ast = std.zig.Ast;...@@ -4060,6 +3806,8 @@ const Ast = std.zig.Ast;
4060const Node = Ast.Node;3806const Node = Ast.Node;
4061const AstError = Ast.Error;3807const AstError = Ast.Error;
4062const TokenIndex = Ast.TokenIndex;3808const TokenIndex = Ast.TokenIndex;
3809const OptionalTokenIndex = Ast.OptionalTokenIndex;
3810const ExtraIndex = Ast.ExtraIndex;
4063const Token = std.zig.Token;3811const Token = std.zig.Token;
40643812
4065test {3813test {
lib/std/zig/Zir.zig+52-45
...@@ -80,9 +80,18 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {...@@ -80,9 +80,18 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
80 Inst.Declaration.Name,80 Inst.Declaration.Name,
81 std.zig.SimpleComptimeReason,81 std.zig.SimpleComptimeReason,
82 NullTerminatedString,82 NullTerminatedString,
83 // Ast.TokenIndex is missing because it is a u32.
84 Ast.OptionalTokenIndex,
85 Ast.Node.Index,
86 Ast.Node.OptionalIndex,
83 => @enumFromInt(code.extra[i]),87 => @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
86 Inst.Call.Flags,95 Inst.Call.Flags,
87 Inst.BuiltinCall.Flags,96 Inst.BuiltinCall.Flags,
88 Inst.SwitchBlock.Bits,97 Inst.SwitchBlock.Bits,
...@@ -1904,22 +1913,22 @@ pub const Inst = struct {...@@ -1904,22 +1913,22 @@ pub const Inst = struct {
1904 /// `small` is `fields_len: u16`.1913 /// `small` is `fields_len: u16`.
1905 tuple_decl,1914 tuple_decl,
1906 /// Implements the `@This` builtin.1915 /// Implements the `@This` builtin.
1907 /// `operand` is `src_node: i32`.1916 /// `operand` is `src_node: Ast.Node.Offset`.
1908 this,1917 this,
1909 /// Implements the `@returnAddress` builtin.1918 /// Implements the `@returnAddress` builtin.
1910 /// `operand` is `src_node: i32`.1919 /// `operand` is `src_node: Ast.Node.Offset`.
1911 ret_addr,1920 ret_addr,
1912 /// Implements the `@src` builtin.1921 /// Implements the `@src` builtin.
1913 /// `operand` is payload index to `LineColumn`.1922 /// `operand` is payload index to `LineColumn`.
1914 builtin_src,1923 builtin_src,
1915 /// Implements the `@errorReturnTrace` builtin.1924 /// Implements the `@errorReturnTrace` builtin.
1916 /// `operand` is `src_node: i32`.1925 /// `operand` is `src_node: Ast.Node.Offset`.
1917 error_return_trace,1926 error_return_trace,
1918 /// Implements the `@frame` builtin.1927 /// Implements the `@frame` builtin.
1919 /// `operand` is `src_node: i32`.1928 /// `operand` is `src_node: Ast.Node.Offset`.
1920 frame,1929 frame,
1921 /// Implements the `@frameAddress` builtin.1930 /// Implements the `@frameAddress` builtin.
1922 /// `operand` is `src_node: i32`.1931 /// `operand` is `src_node: Ast.Node.Offset`.
1923 frame_address,1932 frame_address,
1924 /// Same as `alloc` from `Tag` but may contain an alignment instruction.1933 /// Same as `alloc` from `Tag` but may contain an alignment instruction.
1925 /// `operand` is payload index to `AllocExtended`.1934 /// `operand` is payload index to `AllocExtended`.
...@@ -2004,9 +2013,9 @@ pub const Inst = struct {...@@ -2004,9 +2013,9 @@ pub const Inst = struct {
2004 /// `operand` is payload index to `UnNode`.2013 /// `operand` is payload index to `UnNode`.
2005 await_nosuspend,2014 await_nosuspend,
2006 /// Implements `@breakpoint`.2015 /// Implements `@breakpoint`.
2007 /// `operand` is `src_node: i32`.2016 /// `operand` is `src_node: Ast.Node.Offset`.
2008 breakpoint,2017 breakpoint,
2009 /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`.2018 /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: Ast.Node.Offset`.
2010 disable_instrumentation,2019 disable_instrumentation,
2011 /// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`.2020 /// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`.
2012 disable_intrinsics,2021 disable_intrinsics,
...@@ -2040,7 +2049,7 @@ pub const Inst = struct {...@@ -2040,7 +2049,7 @@ pub const Inst = struct {
2040 /// `operand` is payload index to `UnNode`.2049 /// `operand` is payload index to `UnNode`.
2041 c_va_end,2050 c_va_end,
2042 /// Implement builtin `@cVaStart`.2051 /// Implement builtin `@cVaStart`.
2043 /// `operand` is `src_node: i32`.2052 /// `operand` is `src_node: Ast.Node.Offset`.
2044 c_va_start,2053 c_va_start,
2045 /// Implements the following builtins:2054 /// Implements the following builtins:
2046 /// `@ptrCast`, `@alignCast`, `@addrSpaceCast`, `@constCast`, `@volatileCast`.2055 /// `@ptrCast`, `@alignCast`, `@addrSpaceCast`, `@constCast`, `@volatileCast`.
...@@ -2067,7 +2076,7 @@ pub const Inst = struct {...@@ -2067,7 +2076,7 @@ pub const Inst = struct {
2067 /// `operand` is payload index to `UnNode`.2076 /// `operand` is payload index to `UnNode`.
2068 work_group_id,2077 work_group_id,
2069 /// Implements the `@inComptime` builtin.2078 /// Implements the `@inComptime` builtin.
2070 /// `operand` is `src_node: i32`.2079 /// `operand` is `src_node: Ast.Node.Offset`.
2071 in_comptime,2080 in_comptime,
2072 /// Restores the error return index to its last saved state in a given2081 /// Restores the error return index to its last saved state in a given
2073 /// block. If the block is `.none`, restores to the state from the point2082 /// block. If the block is `.none`, restores to the state from the point
...@@ -2077,7 +2086,7 @@ pub const Inst = struct {...@@ -2077,7 +2086,7 @@ pub const Inst = struct {
2077 /// `small` is undefined.2086 /// `small` is undefined.
2078 restore_err_ret_index,2087 restore_err_ret_index,
2079 /// Retrieves a value from the current type declaration scope's closure.2088 /// 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`.
2081 /// `small` is closure index.2090 /// `small` is closure index.
2082 closure_get,2091 closure_get,
2083 /// Used as a placeholder instruction which is just a dummy index for Sema to replace2092 /// Used as a placeholder instruction which is just a dummy index for Sema to replace
...@@ -2091,7 +2100,7 @@ pub const Inst = struct {...@@ -2091,7 +2100,7 @@ pub const Inst = struct {
2091 /// Uses the `pl_node` union field with payload `FieldParentPtr`.2100 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
2092 field_parent_ptr,2101 field_parent_ptr,
2093 /// Get a type or value from `std.builtin`.2102 /// Get a type or value from `std.builtin`.
2094 /// `operand` is `src_node: i32`.2103 /// `operand` is `src_node: Ast.Node.Offset`.
2095 /// `small` is an `Inst.BuiltinValue`.2104 /// `small` is an `Inst.BuiltinValue`.
2096 builtin_value,2105 builtin_value,
2097 /// Provide a `@branchHint` for the current block.2106 /// Provide a `@branchHint` for the current block.
...@@ -2286,28 +2295,28 @@ pub const Inst = struct {...@@ -2286,28 +2295,28 @@ pub const Inst = struct {
2286 /// Used for unary operators, with an AST node source location.2295 /// Used for unary operators, with an AST node source location.
2287 un_node: struct {2296 un_node: struct {
2288 /// Offset from Decl AST node index.2297 /// Offset from Decl AST node index.
2289 src_node: i32,2298 src_node: Ast.Node.Offset,
2290 /// The meaning of this operand depends on the corresponding `Tag`.2299 /// The meaning of this operand depends on the corresponding `Tag`.
2291 operand: Ref,2300 operand: Ref,
2292 },2301 },
2293 /// Used for unary operators, with a token source location.2302 /// Used for unary operators, with a token source location.
2294 un_tok: struct {2303 un_tok: struct {
2295 /// Offset from Decl AST token index.2304 /// Offset from Decl AST token index.
2296 src_tok: Ast.TokenIndex,2305 src_tok: Ast.TokenOffset,
2297 /// The meaning of this operand depends on the corresponding `Tag`.2306 /// The meaning of this operand depends on the corresponding `Tag`.
2298 operand: Ref,2307 operand: Ref,
2299 },2308 },
2300 pl_node: struct {2309 pl_node: struct {
2301 /// Offset from Decl AST node index.2310 /// Offset from Decl AST node index.
2302 /// `Tag` determines which kind of AST node this points to.2311 /// `Tag` determines which kind of AST node this points to.
2303 src_node: i32,2312 src_node: Ast.Node.Offset,
2304 /// index into extra.2313 /// index into extra.
2305 /// `Tag` determines what lives there.2314 /// `Tag` determines what lives there.
2306 payload_index: u32,2315 payload_index: u32,
2307 },2316 },
2308 pl_tok: struct {2317 pl_tok: struct {
2309 /// Offset from Decl AST token index.2318 /// Offset from Decl AST token index.
2310 src_tok: Ast.TokenIndex,2319 src_tok: Ast.TokenOffset,
2311 /// index into extra.2320 /// index into extra.
2312 /// `Tag` determines what lives there.2321 /// `Tag` determines what lives there.
2313 payload_index: u32,2322 payload_index: u32,
...@@ -2328,16 +2337,16 @@ pub const Inst = struct {...@@ -2328,16 +2337,16 @@ pub const Inst = struct {
2328 /// Offset into `string_bytes`. Null-terminated.2337 /// Offset into `string_bytes`. Null-terminated.
2329 start: NullTerminatedString,2338 start: NullTerminatedString,
2330 /// Offset from Decl AST token index.2339 /// Offset from Decl AST token index.
2331 src_tok: u32,2340 src_tok: Ast.TokenOffset,
23322341
2333 pub fn get(self: @This(), code: Zir) [:0]const u8 {2342 pub fn get(self: @This(), code: Zir) [:0]const u8 {
2334 return code.nullTerminatedString(self.start);2343 return code.nullTerminatedString(self.start);
2335 }2344 }
2336 },2345 },
2337 /// Offset from Decl AST token index.2346 /// Offset from Decl AST token index.
2338 tok: Ast.TokenIndex,2347 tok: Ast.TokenOffset,
2339 /// Offset from Decl AST node index.2348 /// Offset from Decl AST node index.
2340 node: i32,2349 node: Ast.Node.Offset,
2341 int: u64,2350 int: u64,
2342 float: f64,2351 float: f64,
2343 ptr_type: struct {2352 ptr_type: struct {
...@@ -2358,14 +2367,14 @@ pub const Inst = struct {...@@ -2358,14 +2367,14 @@ pub const Inst = struct {
2358 int_type: struct {2367 int_type: struct {
2359 /// Offset from Decl AST node index.2368 /// Offset from Decl AST node index.
2360 /// `Tag` determines which kind of AST node this points to.2369 /// `Tag` determines which kind of AST node this points to.
2361 src_node: i32,2370 src_node: Ast.Node.Offset,
2362 signedness: std.builtin.Signedness,2371 signedness: std.builtin.Signedness,
2363 bit_count: u16,2372 bit_count: u16,
2364 },2373 },
2365 @"unreachable": struct {2374 @"unreachable": struct {
2366 /// Offset from Decl AST node index.2375 /// Offset from Decl AST node index.
2367 /// `Tag` determines which kind of AST node this points to.2376 /// `Tag` determines which kind of AST node this points to.
2368 src_node: i32,2377 src_node: Ast.Node.Offset,
2369 },2378 },
2370 @"break": struct {2379 @"break": struct {
2371 operand: Ref,2380 operand: Ref,
...@@ -2377,7 +2386,7 @@ pub const Inst = struct {...@@ -2377,7 +2386,7 @@ pub const Inst = struct {
2377 /// with an AST node source location.2386 /// with an AST node source location.
2378 inst_node: struct {2387 inst_node: struct {
2379 /// Offset from Decl AST node index.2388 /// Offset from Decl AST node index.
2380 src_node: i32,2389 src_node: Ast.Node.Offset,
2381 /// The meaning of this operand depends on the corresponding `Tag`.2390 /// The meaning of this operand depends on the corresponding `Tag`.
2382 inst: Index,2391 inst: Index,
2383 },2392 },
...@@ -2456,9 +2465,7 @@ pub const Inst = struct {...@@ -2456,9 +2465,7 @@ pub const Inst = struct {
2456 };2465 };
24572466
2458 pub const Break = struct {2467 pub const Break = struct {
2459 pub const no_src_node = std.math.maxInt(i32);2468 operand_src_node: Ast.Node.OptionalOffset,
2460
2461 operand_src_node: i32,
2462 block_inst: Index,2469 block_inst: Index,
2463 };2470 };
24642471
...@@ -2467,7 +2474,7 @@ pub const Inst = struct {...@@ -2467,7 +2474,7 @@ pub const Inst = struct {
2467 /// 1. Input for every inputs_len2474 /// 1. Input for every inputs_len
2468 /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len.2475 /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len.
2469 pub const Asm = struct {2476 pub const Asm = struct {
2470 src_node: i32,2477 src_node: Ast.Node.Offset,
2471 // null-terminated string index2478 // null-terminated string index
2472 asm_source: NullTerminatedString,2479 asm_source: NullTerminatedString,
2473 /// 1 bit for each outputs_len: whether it uses `-> T` or not.2480 /// 1 bit for each outputs_len: whether it uses `-> T` or not.
...@@ -2582,7 +2589,7 @@ pub const Inst = struct {...@@ -2582,7 +2589,7 @@ pub const Inst = struct {
25822589
2583 /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).2590 /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`).
2584 pub const NodeMultiOp = struct {2591 pub const NodeMultiOp = struct {
2585 src_node: i32,2592 src_node: Ast.Node.Offset,
2586 };2593 };
25872594
2588 /// This data is stored inside extra, with trailing operands according to `body_len`.2595 /// This data is stored inside extra, with trailing operands according to `body_len`.
...@@ -3033,7 +3040,7 @@ pub const Inst = struct {...@@ -3033,7 +3040,7 @@ pub const Inst = struct {
3033 /// Trailing:3040 /// Trailing:
3034 /// 0. operand: Ref // for each `operands_len`3041 /// 0. operand: Ref // for each `operands_len`
3035 pub const TypeOfPeer = struct {3042 pub const TypeOfPeer = struct {
3036 src_node: i32,3043 src_node: Ast.Node.Offset,
3037 body_len: u32,3044 body_len: u32,
3038 body_index: u32,3045 body_index: u32,
3039 };3046 };
...@@ -3084,7 +3091,7 @@ pub const Inst = struct {...@@ -3084,7 +3091,7 @@ pub const Inst = struct {
3084 /// 4. host_size: Ref // if `has_bit_range` flag is set3091 /// 4. host_size: Ref // if `has_bit_range` flag is set
3085 pub const PtrType = struct {3092 pub const PtrType = struct {
3086 elem_type: Ref,3093 elem_type: Ref,
3087 src_node: i32,3094 src_node: Ast.Node.Offset,
3088 };3095 };
30893096
3090 pub const ArrayTypeSentinel = struct {3097 pub const ArrayTypeSentinel = struct {
...@@ -3116,7 +3123,7 @@ pub const Inst = struct {...@@ -3116,7 +3123,7 @@ pub const Inst = struct {
3116 start: Ref,3123 start: Ref,
3117 len: Ref,3124 len: Ref,
3118 sentinel: Ref,3125 sentinel: Ref,
3119 start_src_node_offset: i32,3126 start_src_node_offset: Ast.Node.Offset,
3120 };3127 };
31213128
3122 /// The meaning of these operands depends on the corresponding `Tag`.3129 /// The meaning of these operands depends on the corresponding `Tag`.
...@@ -3126,13 +3133,13 @@ pub const Inst = struct {...@@ -3126,13 +3133,13 @@ pub const Inst = struct {
3126 };3133 };
31273134
3128 pub const BinNode = struct {3135 pub const BinNode = struct {
3129 node: i32,3136 node: Ast.Node.Offset,
3130 lhs: Ref,3137 lhs: Ref,
3131 rhs: Ref,3138 rhs: Ref,
3132 };3139 };
31333140
3134 pub const UnNode = struct {3141 pub const UnNode = struct {
3135 node: i32,3142 node: Ast.Node.Offset,
3136 operand: Ref,3143 operand: Ref,
3137 };3144 };
31383145
...@@ -3186,7 +3193,7 @@ pub const Inst = struct {...@@ -3186,7 +3193,7 @@ pub const Inst = struct {
3186 pub const SwitchBlockErrUnion = struct {3193 pub const SwitchBlockErrUnion = struct {
3187 operand: Ref,3194 operand: Ref,
3188 bits: Bits,3195 bits: Bits,
3189 main_src_node_offset: i32,3196 main_src_node_offset: Ast.Node.Offset,
31903197
3191 pub const Bits = packed struct(u32) {3198 pub const Bits = packed struct(u32) {
3192 /// If true, one or more prongs have multiple items.3199 /// If true, one or more prongs have multiple items.
...@@ -3592,7 +3599,7 @@ pub const Inst = struct {...@@ -3592,7 +3599,7 @@ pub const Inst = struct {
3592 /// init: Inst.Ref, // `.none` for non-`comptime` fields3599 /// init: Inst.Ref, // `.none` for non-`comptime` fields
3593 /// }3600 /// }
3594 pub const TupleDecl = struct {3601 pub const TupleDecl = struct {
3595 src_node: i32, // relative3602 src_node: Ast.Node.Offset,
3596 };3603 };
35973604
3598 /// Trailing:3605 /// Trailing:
...@@ -3666,7 +3673,7 @@ pub const Inst = struct {...@@ -3666,7 +3673,7 @@ pub const Inst = struct {
3666 };3673 };
36673674
3668 pub const Cmpxchg = struct {3675 pub const Cmpxchg = struct {
3669 node: i32,3676 node: Ast.Node.Offset,
3670 ptr: Ref,3677 ptr: Ref,
3671 expected_value: Ref,3678 expected_value: Ref,
3672 new_value: Ref,3679 new_value: Ref,
...@@ -3706,7 +3713,7 @@ pub const Inst = struct {...@@ -3706,7 +3713,7 @@ pub const Inst = struct {
3706 };3713 };
37073714
3708 pub const FieldParentPtr = struct {3715 pub const FieldParentPtr = struct {
3709 src_node: i32,3716 src_node: Ast.Node.Offset,
3710 parent_ptr_type: Ref,3717 parent_ptr_type: Ref,
3711 field_name: Ref,3718 field_name: Ref,
3712 field_ptr: Ref,3719 field_ptr: Ref,
...@@ -3720,7 +3727,7 @@ pub const Inst = struct {...@@ -3720,7 +3727,7 @@ pub const Inst = struct {
3720 };3727 };
37213728
3722 pub const Select = struct {3729 pub const Select = struct {
3723 node: i32,3730 node: Ast.Node.Offset,
3724 elem_type: Ref,3731 elem_type: Ref,
3725 pred: Ref,3732 pred: Ref,
3726 a: Ref,3733 a: Ref,
...@@ -3728,7 +3735,7 @@ pub const Inst = struct {...@@ -3728,7 +3735,7 @@ pub const Inst = struct {
3728 };3735 };
37293736
3730 pub const AsyncCall = struct {3737 pub const AsyncCall = struct {
3731 node: i32,3738 node: Ast.Node.Offset,
3732 frame_buffer: Ref,3739 frame_buffer: Ref,
3733 result_ptr: Ref,3740 result_ptr: Ref,
3734 fn_ptr: Ref,3741 fn_ptr: Ref,
...@@ -3753,7 +3760,7 @@ pub const Inst = struct {...@@ -3753,7 +3760,7 @@ pub const Inst = struct {
3753 /// 0. type_inst: Ref, // if small 0b000X is set3760 /// 0. type_inst: Ref, // if small 0b000X is set
3754 /// 1. align_inst: Ref, // if small 0b00X0 is set3761 /// 1. align_inst: Ref, // if small 0b00X0 is set
3755 pub const AllocExtended = struct {3762 pub const AllocExtended = struct {
3756 src_node: i32,3763 src_node: Ast.Node.Offset,
37573764
3758 pub const Small = packed struct {3765 pub const Small = packed struct {
3759 has_type: bool,3766 has_type: bool,
...@@ -3778,9 +3785,9 @@ pub const Inst = struct {...@@ -3778,9 +3785,9 @@ pub const Inst = struct {
3778 pub const Item = struct {3785 pub const Item = struct {
3779 /// null terminated string index3786 /// null terminated string index
3780 msg: NullTerminatedString,3787 msg: NullTerminatedString,
3781 node: Ast.Node.Index,3788 node: Ast.Node.OptionalIndex,
3782 /// If node is 0 then this will be populated.3789 /// If node is .none then this will be populated.
3783 token: Ast.TokenIndex,3790 token: Ast.OptionalTokenIndex,
3784 /// Can be used in combination with `token`.3791 /// Can be used in combination with `token`.
3785 byte_offset: u32,3792 byte_offset: u32,
3786 /// 0 or a payload index of a `Block`, each is a payload3793 /// 0 or a payload index of a `Block`, each is a payload
...@@ -3818,7 +3825,7 @@ pub const Inst = struct {...@@ -3818,7 +3825,7 @@ pub const Inst = struct {
3818 };3825 };
38193826
3820 pub const Src = struct {3827 pub const Src = struct {
3821 node: i32,3828 node: Ast.Node.Offset,
3822 line: u32,3829 line: u32,
3823 column: u32,3830 column: u32,
3824 };3831 };
...@@ -3833,7 +3840,7 @@ pub const Inst = struct {...@@ -3833,7 +3840,7 @@ pub const Inst = struct {
3833 /// The value being destructured.3840 /// The value being destructured.
3834 operand: Ref,3841 operand: Ref,
3835 /// The `destructure_assign` node.3842 /// The `destructure_assign` node.
3836 destructure_node: i32,3843 destructure_node: Ast.Node.Offset,
3837 /// The expected field count.3844 /// The expected field count.
3838 expect_len: u32,3845 expect_len: u32,
3839 };3846 };
...@@ -3848,7 +3855,7 @@ pub const Inst = struct {...@@ -3848,7 +3855,7 @@ pub const Inst = struct {
3848 };3855 };
38493856
3850 pub const RestoreErrRetIndex = struct {3857 pub const RestoreErrRetIndex = struct {
3851 src_node: i32,3858 src_node: Ast.Node.Offset,
3852 /// If `.none`, restore the trace to its state upon function entry.3859 /// If `.none`, restore the trace to its state upon function entry.
3853 block: Ref,3860 block: Ref,
3854 /// If `.none`, restore unconditionally.3861 /// If `.none`, restore unconditionally.
lib/std/zig/Zoir.zig+4-6
...@@ -228,8 +228,8 @@ pub const NullTerminatedString = enum(u32) {...@@ -228,8 +228,8 @@ pub const NullTerminatedString = enum(u32) {
228228
229pub const CompileError = extern struct {229pub const CompileError = extern struct {
230 msg: NullTerminatedString,230 msg: NullTerminatedString,
231 token: Ast.TokenIndex,231 token: Ast.OptionalTokenIndex,
232 /// If `token == invalid_token`, this is an `Ast.Node.Index`.232 /// If `token == .none`, this is an `Ast.Node.Index`.
233 /// Otherwise, this is a byte offset into `token`.233 /// Otherwise, this is a byte offset into `token`.
234 node_or_offset: u32,234 node_or_offset: u32,
235235
...@@ -243,14 +243,12 @@ pub const CompileError = extern struct {...@@ -243,14 +243,12 @@ pub const CompileError = extern struct {
243243
244 pub const Note = extern struct {244 pub const Note = extern struct {
245 msg: NullTerminatedString,245 msg: NullTerminatedString,
246 token: Ast.TokenIndex,246 token: Ast.OptionalTokenIndex,
247 /// If `token == invalid_token`, this is an `Ast.Node.Index`.247 /// If `token == .none`, this is an `Ast.Node.Index`.
248 /// Otherwise, this is a byte offset into `token`.248 /// Otherwise, this is a byte offset into `token`.
249 node_or_offset: u32,249 node_or_offset: u32,
250 };250 };
251251
252 pub const invalid_token: Ast.TokenIndex = std.math.maxInt(Ast.TokenIndex);
253
254 comptime {252 comptime {
255 assert(std.meta.hasUniqueRepresentation(CompileError));253 assert(std.meta.hasUniqueRepresentation(CompileError));
256 assert(std.meta.hasUniqueRepresentation(Note));254 assert(std.meta.hasUniqueRepresentation(Note));
lib/std/zig/ZonGen.zig+44-56
...@@ -48,7 +48,7 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi...@@ -48,7 +48,7 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi
48 }48 }
4949
50 if (tree.errors.len == 0) {50 if (tree.errors.len == 0) {
51 const root_ast_node = tree.nodes.items(.data)[0].lhs;51 const root_ast_node = tree.rootDecls()[0];
52 try zg.nodes.append(gpa, undefined); // index 0; root node52 try zg.nodes.append(gpa, undefined); // index 0; root node
53 try zg.expr(root_ast_node, .root);53 try zg.expr(root_ast_node, .root);
54 } else {54 } else {
...@@ -97,11 +97,8 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi...@@ -97,11 +97,8 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi
97fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator.Error!void {97fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator.Error!void {
98 const gpa = zg.gpa;98 const gpa = zg.gpa;
99 const tree = zg.tree;99 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)) {
105 .root => unreachable,102 .root => unreachable,
106 .@"usingnamespace" => unreachable,103 .@"usingnamespace" => unreachable,
107 .test_decl => unreachable,104 .test_decl => unreachable,
...@@ -173,7 +170,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -173,7 +170,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
173 .bool_not,170 .bool_not,
174 .bit_not,171 .bit_not,
175 .negation_wrap,172 .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
178 .error_union,175 .error_union,
179 .merge_error_sets,176 .merge_error_sets,
...@@ -251,23 +248,20 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -251,23 +248,20 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
251 .slice_sentinel,248 .slice_sentinel,
252 => try zg.addErrorNode(node, "slice operator is not allowed in ZON", .{}),249 => 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", .{}),251 .deref, .address_of => try zg.addErrorTok(tree.nodeMainToken(node), "pointers are not available in ZON", .{}),
255 .unwrap_optional => try zg.addErrorTok(main_tokens[node], "optionals are not available in ZON", .{}),252 .unwrap_optional => try zg.addErrorTok(tree.nodeMainToken(node), "optionals are not available in ZON", .{}),
256 .error_value => try zg.addErrorNode(node, "errors are not available in ZON", .{}),253 .error_value => try zg.addErrorNode(node, "errors are not available in ZON", .{}),
257254
258 .array_access => try zg.addErrorTok(node, "array indexing is not allowed in ZON", .{}),255 .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}),
259256
260 .block_two,257 .block_two,
261 .block_two_semicolon,258 .block_two_semicolon,
262 .block,259 .block,
263 .block_semicolon,260 .block_semicolon,
264 => {261 => {
265 const size = switch (node_tags[node]) {262 var buffer: [2]Ast.Node.Index = undefined;
266 .block_two, .block_two_semicolon => @intFromBool(node_datas[node].lhs != 0) + @intFromBool(node_datas[node].rhs != 0),263 const statements = tree.blockStatements(&buffer, node).?;
267 .block, .block_semicolon => node_datas[node].rhs - node_datas[node].lhs,264 if (statements.len == 0) {
268 else => unreachable,
269 };
270 if (size == 0) {
271 try zg.addErrorNodeNotes(node, "void literals are not available in ZON", .{}, &.{265 try zg.addErrorNodeNotes(node, "void literals are not available in ZON", .{}, &.{
272 try zg.errNoteNode(node, "void union payloads can be represented by enum literals", .{}),266 try zg.errNoteNode(node, "void union payloads can be represented by enum literals", .{}),
273 });267 });
...@@ -288,9 +282,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -288,9 +282,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
288 var buf: [2]Ast.Node.Index = undefined;282 var buf: [2]Ast.Node.Index = undefined;
289283
290 const type_node = if (tree.fullArrayInit(&buf, node)) |full|284 const type_node = if (tree.fullArrayInit(&buf, node)) |full|
291 full.ast.type_expr285 full.ast.type_expr.unwrap().?
292 else if (tree.fullStructInit(&buf, node)) |full|286 else if (tree.fullStructInit(&buf, node)) |full|
293 full.ast.type_expr287 full.ast.type_expr.unwrap().?
294 else288 else
295 unreachable;289 unreachable;
296290
...@@ -300,18 +294,18 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -300,18 +294,18 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
300 },294 },
301295
302 .grouped_expression => {296 .grouped_expression => {
303 try zg.addErrorTokNotes(main_tokens[node], "expression grouping is not allowed in ZON", .{}, &.{297 try zg.addErrorTokNotes(tree.nodeMainToken(node), "expression grouping is not allowed in ZON", .{}, &.{
304 try zg.errNoteTok(main_tokens[node], "these parentheses are always redundant", .{}),298 try zg.errNoteTok(tree.nodeMainToken(node), "these parentheses are always redundant", .{}),
305 });299 });
306 return zg.expr(node_datas[node].lhs, dest_node);300 return zg.expr(tree.nodeData(node).node_and_token[0], dest_node);
307 },301 },
308302
309 .negation => {303 .negation => {
310 const child_node = node_datas[node].lhs;304 const child_node = tree.nodeData(node).node;
311 switch (node_tags[child_node]) {305 switch (tree.nodeTag(child_node)) {
312 .number_literal => return zg.numberLiteral(child_node, node, dest_node, .negative),306 .number_literal => return zg.numberLiteral(child_node, node, dest_node, .negative),
313 .identifier => {307 .identifier => {
314 const child_ident = tree.tokenSlice(main_tokens[child_node]);308 const child_ident = tree.tokenSlice(tree.nodeMainToken(child_node));
315 if (mem.eql(u8, child_ident, "inf")) {309 if (mem.eql(u8, child_ident, "inf")) {
316 zg.setNode(dest_node, .{310 zg.setNode(dest_node, .{
317 .tag = .neg_inf,311 .tag = .neg_inf,
...@@ -323,7 +317,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -323,7 +317,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
323 },317 },
324 else => {},318 else => {},
325 }319 }
326 try zg.addErrorTok(main_tokens[node], "expected number or 'inf' after '-'", .{});320 try zg.addErrorTok(tree.nodeMainToken(node), "expected number or 'inf' after '-'", .{});
327 },321 },
328 .number_literal => try zg.numberLiteral(node, node, dest_node, .positive),322 .number_literal => try zg.numberLiteral(node, node, dest_node, .positive),
329 .char_literal => try zg.charLiteral(node, dest_node),323 .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...@@ -331,7 +325,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
331 .identifier => try zg.identifier(node, dest_node),325 .identifier => try zg.identifier(node, dest_node),
332326
333 .enum_literal => {327 .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) {
335 error.BadString => undefined, // doesn't matter, there's an error329 error.BadString => undefined, // doesn't matter, there's an error
336 error.OutOfMemory => |e| return e,330 error.OutOfMemory => |e| return e,
337 };331 };
...@@ -369,7 +363,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -369,7 +363,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
369 var buf: [2]Ast.Node.Index = undefined;363 var buf: [2]Ast.Node.Index = undefined;
370 const full = tree.fullArrayInit(&buf, node).?;364 const full = tree.fullArrayInit(&buf, node).?;
371 assert(full.ast.elements.len != 0); // Otherwise it would be a struct init365 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
374 const first_elem: u32 = @intCast(zg.nodes.len);368 const first_elem: u32 = @intCast(zg.nodes.len);
375 try zg.nodes.resize(gpa, zg.nodes.len + full.ast.elements.len);369 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...@@ -398,7 +392,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
398 => {392 => {
399 var buf: [2]Ast.Node.Index = undefined;393 var buf: [2]Ast.Node.Index = undefined;
400 const full = tree.fullStructInit(&buf, node).?;394 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
403 if (full.ast.fields.len == 0) {397 if (full.ast.fields.len == 0) {
404 zg.setNode(dest_node, .{398 zg.setNode(dest_node, .{
...@@ -460,7 +454,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -460,7 +454,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
460454
461fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {455fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
462 const tree = zg.tree;456 const tree = zg.tree;
463 assert(tree.tokens.items(.tag)[ident_token] == .identifier);457 assert(tree.tokenTag(ident_token) == .identifier);
464 const ident_name = tree.tokenSlice(ident_token);458 const ident_name = tree.tokenSlice(ident_token);
465 if (!mem.startsWith(u8, ident_name, "@")) {459 if (!mem.startsWith(u8, ident_name, "@")) {
466 const start = zg.string_bytes.items.len;460 const start = zg.string_bytes.items.len;
...@@ -493,19 +487,16 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {...@@ -493,19 +487,16 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
493487
494/// Estimates the size of a string node without parsing it.488/// Estimates the size of a string node without parsing it.
495pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {489pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
496 switch (tree.nodes.items(.tag)[node]) {490 switch (tree.nodeTag(node)) {
497 // Parsed string literals are typically around the size of the raw strings.491 // Parsed string literals are typically around the size of the raw strings.
498 .string_literal => {492 .string_literal => {
499 const token = tree.nodes.items(.main_token)[node];493 const token = tree.nodeMainToken(node);
500 const raw_string = tree.tokenSlice(token);494 const raw_string = tree.tokenSlice(token);
501 return raw_string.len;495 return raw_string.len;
502 },496 },
503 // Multiline string literal lengths can be computed exactly.497 // Multiline string literal lengths can be computed exactly.
504 .multiline_string_literal => {498 .multiline_string_literal => {
505 const first_tok, const last_tok = bounds: {499 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
506 const node_data = tree.nodes.items(.data)[node];
507 break :bounds .{ node_data.lhs, node_data.rhs };
508 };
509500
510 var size = tree.tokenSlice(first_tok)[2..].len;501 var size = tree.tokenSlice(first_tok)[2..].len;
511 for (first_tok + 1..last_tok + 1) |tok_idx| {502 for (first_tok + 1..last_tok + 1) |tok_idx| {
...@@ -524,17 +515,14 @@ pub fn parseStrLit(...@@ -524,17 +515,14 @@ pub fn parseStrLit(
524 node: Ast.Node.Index,515 node: Ast.Node.Index,
525 writer: anytype,516 writer: anytype,
526) error{OutOfMemory}!std.zig.string_literal.Result {517) error{OutOfMemory}!std.zig.string_literal.Result {
527 switch (tree.nodes.items(.tag)[node]) {518 switch (tree.nodeTag(node)) {
528 .string_literal => {519 .string_literal => {
529 const token = tree.nodes.items(.main_token)[node];520 const token = tree.nodeMainToken(node);
530 const raw_string = tree.tokenSlice(token);521 const raw_string = tree.tokenSlice(token);
531 return std.zig.string_literal.parseWrite(writer, raw_string);522 return std.zig.string_literal.parseWrite(writer, raw_string);
532 },523 },
533 .multiline_string_literal => {524 .multiline_string_literal => {
534 const first_tok, const last_tok = bounds: {525 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
535 const node_data = tree.nodes.items(.data)[node];
536 break :bounds .{ node_data.lhs, node_data.rhs };
537 };
538526
539 // First line: do not append a newline.527 // First line: do not append a newline.
540 {528 {
...@@ -572,7 +560,7 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) !StringLiteralResult {...@@ -572,7 +560,7 @@ fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) !StringLiteralResult {
572 switch (try parseStrLit(zg.tree, str_node, zg.string_bytes.writer(zg.gpa))) {560 switch (try parseStrLit(zg.tree, str_node, zg.string_bytes.writer(zg.gpa))) {
573 .success => {},561 .success => {},
574 .failure => |err| {562 .failure => |err| {
575 const token = zg.tree.nodes.items(.main_token)[str_node];563 const token = zg.tree.nodeMainToken(str_node);
576 const raw_string = zg.tree.tokenSlice(token);564 const raw_string = zg.tree.tokenSlice(token);
577 try zg.lowerStrLitError(err, token, raw_string, 0);565 try zg.lowerStrLitError(err, token, raw_string, 0);
578 return error.BadString;566 return error.BadString;
...@@ -620,7 +608,7 @@ fn identAsString(zg: *ZonGen, ident_token: Ast.TokenIndex) !Zoir.NullTerminatedS...@@ -620,7 +608,7 @@ fn identAsString(zg: *ZonGen, ident_token: Ast.TokenIndex) !Zoir.NullTerminatedS
620608
621fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum { negative, positive }) !void {609fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum { negative, positive }) !void {
622 const tree = zg.tree;610 const tree = zg.tree;
623 const num_token = tree.nodes.items(.main_token)[num_node];611 const num_token = tree.nodeMainToken(num_node);
624 const num_bytes = tree.tokenSlice(num_token);612 const num_bytes = tree.tokenSlice(num_token);
625613
626 switch (std.zig.parseNumberLiteral(num_bytes)) {614 switch (std.zig.parseNumberLiteral(num_bytes)) {
...@@ -724,8 +712,8 @@ fn setBigIntLiteralNode(zg: *ZonGen, dest_node: Zoir.Node.Index, src_node: Ast.N...@@ -724,8 +712,8 @@ fn setBigIntLiteralNode(zg: *ZonGen, dest_node: Zoir.Node.Index, src_node: Ast.N
724712
725fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {713fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {
726 const tree = zg.tree;714 const tree = zg.tree;
727 assert(tree.nodes.items(.tag)[node] == .char_literal);715 assert(tree.nodeTag(node) == .char_literal);
728 const main_token = tree.nodes.items(.main_token)[node];716 const main_token = tree.nodeMainToken(node);
729 const slice = tree.tokenSlice(main_token);717 const slice = tree.tokenSlice(main_token);
730 switch (std.zig.parseCharLiteral(slice)) {718 switch (std.zig.parseCharLiteral(slice)) {
731 .success => |codepoint| zg.setNode(dest_node, .{719 .success => |codepoint| zg.setNode(dest_node, .{
...@@ -739,8 +727,8 @@ fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !v...@@ -739,8 +727,8 @@ fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !v
739727
740fn identifier(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {728fn identifier(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void {
741 const tree = zg.tree;729 const tree = zg.tree;
742 assert(tree.nodes.items(.tag)[node] == .identifier);730 assert(tree.nodeTag(node) == .identifier);
743 const main_token = tree.nodes.items(.main_token)[node];731 const main_token = tree.nodeMainToken(node);
744 const ident = tree.tokenSlice(main_token);732 const ident = tree.tokenSlice(main_token);
745733
746 const tag: Zoir.Node.Repr.Tag = t: {734 const tag: Zoir.Node.Repr.Tag = t: {
...@@ -823,8 +811,8 @@ fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, a...@@ -823,8 +811,8 @@ fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, a
823811
824 return .{812 return .{
825 .msg = @enumFromInt(message_idx),813 .msg = @enumFromInt(message_idx),
826 .token = Zoir.CompileError.invalid_token,814 .token = .none,
827 .node_or_offset = node,815 .node_or_offset = @intFromEnum(node),
828 };816 };
829}817}
830818
...@@ -836,33 +824,33 @@ fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, arg...@@ -836,33 +824,33 @@ fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, arg
836824
837 return .{825 return .{
838 .msg = @enumFromInt(message_idx),826 .msg = @enumFromInt(message_idx),
839 .token = tok,827 .token = .fromToken(tok),
840 .node_or_offset = 0,828 .node_or_offset = 0,
841 };829 };
842}830}
843831
844fn addErrorNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype) Allocator.Error!void {832fn 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, &.{});
846}834}
847fn addErrorTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype) Allocator.Error!void {835fn 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, &.{});
849}837}
850fn addErrorNodeNotes(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {838fn 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);
852}840}
853fn addErrorTokNotes(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {841fn 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);
855}843}
856fn addErrorTokOff(zg: *ZonGen, tok: Ast.TokenIndex, offset: u32, comptime format: []const u8, args: anytype) Allocator.Error!void {844fn 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, &.{});
858}846}
859fn addErrorTokNotesOff(zg: *ZonGen, tok: Ast.TokenIndex, offset: u32, comptime format: []const u8, args: anytype, notes: []const Zoir.CompileError.Note) Allocator.Error!void {847fn 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);
861}849}
862850
863fn addErrorInner(851fn addErrorInner(
864 zg: *ZonGen,852 zg: *ZonGen,
865 token: Ast.TokenIndex,853 token: Ast.OptionalTokenIndex,
866 node_or_offset: u32,854 node_or_offset: u32,
867 comptime format: []const u8,855 comptime format: []const u8,
868 args: anytype,856 args: anytype,
lib/std/zig/render.zig+469-530
...@@ -91,21 +91,22 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v...@@ -91,21 +91,22 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v
91 };91 };
9292
93 // Render all the line comments at the beginning of the file.93 // 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);
95 _ = try renderComments(&r, 0, comment_end_loc);95 _ = 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) {
98 try renderContainerDocComments(&r, 0);98 try renderContainerDocComments(&r, 0);
99 }99 }
100100
101 if (tree.mode == .zon) {101 switch (tree.mode) {
102 try renderExpression(102 .zig => try renderMembers(&r, tree.rootDecls()),
103 &r,103 .zon => {
104 tree.nodes.items(.data)[0].lhs,104 try renderExpression(
105 .newline,105 &r,
106 );106 tree.rootDecls()[0],
107 } else {107 .newline,
108 try renderMembers(&r, tree.rootDecls());108 );
109 },
109 }110 }
110111
111 if (auto_indenting_stream.disabled_offset) |disabled_offset| {112 if (auto_indenting_stream.disabled_offset) |disabled_offset| {
...@@ -141,24 +142,20 @@ fn renderMember(...@@ -141,24 +142,20 @@ fn renderMember(
141) Error!void {142) Error!void {
142 const tree = r.tree;143 const tree = r.tree;
143 const ais = r.ais;144 const ais = r.ais;
144 const node_tags = tree.nodes.items(.tag);
145 const token_tags = tree.tokens.items(.tag);
146 const main_tokens = tree.nodes.items(.main_token);
147 const datas = tree.nodes.items(.data);
148 if (r.fixups.omit_nodes.contains(decl)) return;145 if (r.fixups.omit_nodes.contains(decl)) return;
149 try renderDocComments(r, tree.firstToken(decl));146 try renderDocComments(r, tree.firstToken(decl));
150 switch (tree.nodes.items(.tag)[decl]) {147 switch (tree.nodeTag(decl)) {
151 .fn_decl => {148 .fn_decl => {
152 // Some examples:149 // Some examples:
153 // pub extern "foo" fn ...150 // pub extern "foo" fn ...
154 // export fn ...151 // export fn ...
155 const fn_proto = datas[decl].lhs;152 const fn_proto, const body_node = tree.nodeData(decl).node_and_node;
156 const fn_token = main_tokens[fn_proto];153 const fn_token = tree.nodeMainToken(fn_proto);
157 // Go back to the first token we should render here.154 // Go back to the first token we should render here.
158 var i = fn_token;155 var i = fn_token;
159 while (i > 0) {156 while (i > 0) {
160 i -= 1;157 i -= 1;
161 switch (token_tags[i]) {158 switch (tree.tokenTag(i)) {
162 .keyword_extern,159 .keyword_extern,
163 .keyword_export,160 .keyword_export,
164 .keyword_pub,161 .keyword_pub,
...@@ -173,31 +170,34 @@ fn renderMember(...@@ -173,31 +170,34 @@ fn renderMember(
173 },170 },
174 }171 }
175 }172 }
173
176 while (i < fn_token) : (i += 1) {174 while (i < fn_token) : (i += 1) {
177 try renderToken(r, i, .space);175 try renderToken(r, i, .space);
178 }176 }
179 switch (tree.nodes.items(.tag)[fn_proto]) {177 switch (tree.nodeTag(fn_proto)) {
180 .fn_proto_one, .fn_proto => {178 .fn_proto_one, .fn_proto => {
181 const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one)179 var buf: [1]Ast.Node.Index = undefined;
182 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr180 const opt_callconv_expr = if (tree.nodeTag(fn_proto) == .fn_proto_one)
181 tree.fnProtoOne(&buf, fn_proto).ast.callconv_expr
183 else182 else
184 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;183 tree.fnProto(fn_proto).ast.callconv_expr;
184
185 // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE185 // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE
186 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {186 if (opt_callconv_expr.unwrap()) |callconv_expr| {
187 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) {187 if (tree.nodeTag(callconv_expr) == .enum_literal) {
188 try ais.writer().writeAll("inline ");188 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
189 try ais.writer().writeAll("inline ");
190 }
189 }191 }
190 }192 }
191 },193 },
192 .fn_proto_simple, .fn_proto_multi => {},194 .fn_proto_simple, .fn_proto_multi => {},
193 else => unreachable,195 else => unreachable,
194 }196 }
195 assert(datas[decl].rhs != 0);
196 try renderExpression(r, fn_proto, .space);197 try renderExpression(r, fn_proto, .space);
197 const body_node = datas[decl].rhs;
198 if (r.fixups.gut_functions.contains(decl)) {198 if (r.fixups.gut_functions.contains(decl)) {
199 try ais.pushIndent(.normal);199 try ais.pushIndent(.normal);
200 const lbrace = tree.nodes.items(.main_token)[body_node];200 const lbrace = tree.nodeMainToken(body_node);
201 try renderToken(r, lbrace, .newline);201 try renderToken(r, lbrace, .newline);
202 try discardAllParams(r, fn_proto);202 try discardAllParams(r, fn_proto);
203 try ais.writer().writeAll("@trap();");203 try ais.writer().writeAll("@trap();");
...@@ -206,7 +206,7 @@ fn renderMember(...@@ -206,7 +206,7 @@ fn renderMember(
206 try renderToken(r, tree.lastToken(body_node), space); // rbrace206 try renderToken(r, tree.lastToken(body_node), space); // rbrace
207 } else if (r.fixups.unused_var_decls.count() != 0) {207 } else if (r.fixups.unused_var_decls.count() != 0) {
208 try ais.pushIndent(.normal);208 try ais.pushIndent(.normal);
209 const lbrace = tree.nodes.items(.main_token)[body_node];209 const lbrace = tree.nodeMainToken(body_node);
210 try renderToken(r, lbrace, .newline);210 try renderToken(r, lbrace, .newline);
211211
212 var fn_proto_buf: [1]Ast.Node.Index = undefined;212 var fn_proto_buf: [1]Ast.Node.Index = undefined;
...@@ -214,7 +214,7 @@ fn renderMember(...@@ -214,7 +214,7 @@ fn renderMember(
214 var it = full_fn_proto.iterate(&tree);214 var it = full_fn_proto.iterate(&tree);
215 while (it.next()) |param| {215 while (it.next()) |param| {
216 const name_ident = param.name_token.?;216 const name_ident = param.name_token.?;
217 assert(token_tags[name_ident] == .identifier);217 assert(tree.tokenTag(name_ident) == .identifier);
218 if (r.fixups.unused_var_decls.contains(name_ident)) {218 if (r.fixups.unused_var_decls.contains(name_ident)) {
219 const w = ais.writer();219 const w = ais.writer();
220 try w.writeAll("_ = ");220 try w.writeAll("_ = ");
...@@ -223,25 +223,7 @@ fn renderMember(...@@ -223,25 +223,7 @@ fn renderMember(
223 }223 }
224 }224 }
225 var statements_buf: [2]Ast.Node.Index = undefined;225 var statements_buf: [2]Ast.Node.Index = undefined;
226 const statements = switch (node_tags[body_node]) {226 const statements = tree.blockStatements(&statements_buf, body_node).?;
227 .block_two,
228 .block_two_semicolon,
229 => b: {
230 statements_buf = .{ datas[body_node].lhs, datas[body_node].rhs };
231 if (datas[body_node].lhs == 0) {
232 break :b statements_buf[0..0];
233 } else if (datas[body_node].rhs == 0) {
234 break :b statements_buf[0..1];
235 } else {
236 break :b statements_buf[0..2];
237 }
238 },
239 .block,
240 .block_semicolon,
241 => tree.extra_data[datas[body_node].lhs..datas[body_node].rhs],
242
243 else => unreachable,
244 };
245 return finishRenderBlock(r, body_node, statements, space);227 return finishRenderBlock(r, body_node, statements, space);
246 } else {228 } else {
247 return renderExpression(r, body_node, space);229 return renderExpression(r, body_node, space);
...@@ -254,11 +236,11 @@ fn renderMember(...@@ -254,11 +236,11 @@ fn renderMember(
254 => {236 => {
255 // Extern function prototypes are parsed as these tags.237 // Extern function prototypes are parsed as these tags.
256 // Go back to the first token we should render here.238 // Go back to the first token we should render here.
257 const fn_token = main_tokens[decl];239 const fn_token = tree.nodeMainToken(decl);
258 var i = fn_token;240 var i = fn_token;
259 while (i > 0) {241 while (i > 0) {
260 i -= 1;242 i -= 1;
261 switch (token_tags[i]) {243 switch (tree.tokenTag(i)) {
262 .keyword_extern,244 .keyword_extern,
263 .keyword_export,245 .keyword_export,
264 .keyword_pub,246 .keyword_pub,
...@@ -281,9 +263,9 @@ fn renderMember(...@@ -281,9 +263,9 @@ fn renderMember(
281 },263 },
282264
283 .@"usingnamespace" => {265 .@"usingnamespace" => {
284 const main_token = main_tokens[decl];266 const main_token = tree.nodeMainToken(decl);
285 const expr = datas[decl].lhs;267 const expr = tree.nodeData(decl).node;
286 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {268 if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) {
287 try renderToken(r, main_token - 1, .space); // pub269 try renderToken(r, main_token - 1, .space); // pub
288 }270 }
289 try renderToken(r, main_token, .space); // usingnamespace271 try renderToken(r, main_token, .space); // usingnamespace
...@@ -302,15 +284,17 @@ fn renderMember(...@@ -302,15 +284,17 @@ fn renderMember(
302 },284 },
303285
304 .test_decl => {286 .test_decl => {
305 const test_token = main_tokens[decl];287 const test_token = tree.nodeMainToken(decl);
288 const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node;
306 try renderToken(r, test_token, .space);289 try renderToken(r, test_token, .space);
307 const test_name_tag = token_tags[test_token + 1];290 if (opt_name_token.unwrap()) |name_token| {
308 switch (test_name_tag) {291 switch (tree.tokenTag(name_token)) {
309 .string_literal => try renderToken(r, test_token + 1, .space),292 .string_literal => try renderToken(r, name_token, .space),
310 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),293 .identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing),
311 else => {},294 else => unreachable,
295 }
312 }296 }
313 try renderExpression(r, datas[decl].rhs, space);297 try renderExpression(r, block_node, space);
314 },298 },
315299
316 .container_field_init,300 .container_field_init,
...@@ -338,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa...@@ -338,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa
338fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {322fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
339 const tree = r.tree;323 const tree = r.tree;
340 const ais = r.ais;324 const ais = r.ais;
341 const token_tags = tree.tokens.items(.tag);
342 const main_tokens = tree.nodes.items(.main_token);
343 const node_tags = tree.nodes.items(.tag);
344 const datas = tree.nodes.items(.data);
345 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {325 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
346 try ais.writer().writeAll(replacement);326 try ais.writer().writeAll(replacement);
347 try renderOnlySpace(r, space);327 try renderOnlySpace(r, space);
...@@ -349,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -349,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
349 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {329 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
350 return renderExpression(r, replacement, space);330 return renderExpression(r, replacement, space);
351 }331 }
352 switch (node_tags[node]) {332 switch (tree.nodeTag(node)) {
353 .identifier => {333 .identifier => {
354 const token_index = main_tokens[node];334 const token_index = tree.nodeMainToken(node);
355 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);335 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);
356 },336 },
357337
...@@ -360,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -360,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
360 .unreachable_literal,340 .unreachable_literal,
361 .anyframe_literal,341 .anyframe_literal,
362 .string_literal,342 .string_literal,
363 => return renderToken(r, main_tokens[node], space),343 => return renderToken(r, tree.nodeMainToken(node), space),
364344
365 .multiline_string_literal => {345 .multiline_string_literal => {
366 try ais.maybeInsertNewline();346 try ais.maybeInsertNewline();
367347
368 var i = datas[node].lhs;348 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
369 while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline);349 for (first_tok..last_tok + 1) |i| {
350 try renderToken(r, @intCast(i), .newline);
351 }
352
353 const next_token = last_tok + 1;
354 const next_token_tag = tree.tokenTag(next_token);
370355
371 // dedent the next thing that comes after a multiline string literal356 // dedent the next thing that comes after a multiline string literal
372 if (!ais.indentStackEmpty() and357 if (!ais.indentStackEmpty() and
373 token_tags[i] != .colon and358 next_token_tag != .colon and
374 ((token_tags[i] != .semicolon and token_tags[i] != .comma) or359 ((next_token_tag != .semicolon and next_token_tag != .comma) or
375 ais.lastSpaceModeIndent() < ais.currentIndent()))360 ais.lastSpaceModeIndent() < ais.currentIndent()))
376 {361 {
377 ais.popIndent();362 ais.popIndent();
...@@ -380,44 +365,35 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -380,44 +365,35 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
380365
381 switch (space) {366 switch (space) {
382 .none, .space, .newline, .skip => {},367 .none, .space, .newline, .skip => {},
383 .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon),368 .semicolon => if (next_token_tag == .semicolon) try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon),
384 .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma),369 .comma => if (next_token_tag == .comma) try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma),
385 .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space),370 .comma_space => if (next_token_tag == .comma) try renderToken(r, next_token, .space),
386 }371 }
387 },372 },
388373
389 .error_value => {374 .error_value => {
390 try renderToken(r, main_tokens[node], .none);375 const main_token = tree.nodeMainToken(node);
391 try renderToken(r, main_tokens[node] + 1, .none);376 try renderToken(r, main_token, .none);
392 return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote);377 try renderToken(r, main_token + 1, .none);
378 return renderIdentifier(r, main_token + 2, space, .eagerly_unquote);
393 },379 },
394380
395 .block_two,381 .block_two,
396 .block_two_semicolon,382 .block_two_semicolon,
397 => {
398 const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs };
399 if (datas[node].lhs == 0) {
400 return renderBlock(r, node, statements[0..0], space);
401 } else if (datas[node].rhs == 0) {
402 return renderBlock(r, node, statements[0..1], space);
403 } else {
404 return renderBlock(r, node, statements[0..2], space);
405 }
406 },
407 .block,383 .block,
408 .block_semicolon,384 .block_semicolon,
409 => {385 => {
410 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];386 var buf: [2]Ast.Node.Index = undefined;
387 const statements = tree.blockStatements(&buf, node).?;
411 return renderBlock(r, node, statements, space);388 return renderBlock(r, node, statements, space);
412 },389 },
413390
414 .@"errdefer" => {391 .@"errdefer" => {
415 const defer_token = main_tokens[node];392 const defer_token = tree.nodeMainToken(node);
416 const payload_token = datas[node].lhs;393 const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node;
417 const expr = datas[node].rhs;
418394
419 try renderToken(r, defer_token, .space);395 try renderToken(r, defer_token, .space);
420 if (payload_token != 0) {396 if (maybe_payload_token.unwrap()) |payload_token| {
421 try renderToken(r, payload_token - 1, .none); // |397 try renderToken(r, payload_token - 1, .none); // |
422 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier398 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
423 try renderToken(r, payload_token + 1, .space); // |399 try renderToken(r, payload_token + 1, .space); // |
...@@ -425,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -425,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
425 return renderExpression(r, expr, space);401 return renderExpression(r, expr, space);
426 },402 },
427403
428 .@"defer" => {404 .@"defer",
429 const defer_token = main_tokens[node];405 .@"comptime",
430 const expr = datas[node].rhs;406 .@"nosuspend",
431 try renderToken(r, defer_token, .space);407 .@"suspend",
432 return renderExpression(r, expr, space);408 => {
433 },409 const main_token = tree.nodeMainToken(node);
434 .@"comptime", .@"nosuspend" => {410 const item = tree.nodeData(node).node;
435 const comptime_token = main_tokens[node];411 try renderToken(r, main_token, .space);
436 const block = datas[node].lhs;412 return renderExpression(r, item, space);
437 try renderToken(r, comptime_token, .space);
438 return renderExpression(r, block, space);
439 },
440
441 .@"suspend" => {
442 const suspend_token = main_tokens[node];
443 const body = datas[node].lhs;
444 try renderToken(r, suspend_token, .space);
445 return renderExpression(r, body, space);
446 },413 },
447414
448 .@"catch" => {415 .@"catch" => {
449 const main_token = main_tokens[node];416 const main_token = tree.nodeMainToken(node);
450 const fallback_first = tree.firstToken(datas[node].rhs);417 const lhs, const rhs = tree.nodeData(node).node_and_node;
418 const fallback_first = tree.firstToken(rhs);
451419
452 const same_line = tree.tokensOnSameLine(main_token, fallback_first);420 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
453 const after_op_space = if (same_line) Space.space else Space.newline;421 const after_op_space = if (same_line) Space.space else Space.newline;
454422
455 try renderExpression(r, datas[node].lhs, .space); // target423 try renderExpression(r, lhs, .space); // target
456424
457 try ais.pushIndent(.normal);425 try ais.pushIndent(.normal);
458 if (token_tags[fallback_first - 1] == .pipe) {426 if (tree.tokenTag(fallback_first - 1) == .pipe) {
459 try renderToken(r, main_token, .space); // catch keyword427 try renderToken(r, main_token, .space); // catch keyword
460 try renderToken(r, main_token + 1, .none); // pipe428 try renderToken(r, main_token + 1, .none); // pipe
461 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier429 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
462 try renderToken(r, main_token + 3, after_op_space); // pipe430 try renderToken(r, main_token + 3, after_op_space); // pipe
463 } else {431 } else {
464 assert(token_tags[fallback_first - 1] == .keyword_catch);432 assert(tree.tokenTag(fallback_first - 1) == .keyword_catch);
465 try renderToken(r, main_token, after_op_space); // catch keyword433 try renderToken(r, main_token, after_op_space); // catch keyword
466 }434 }
467 try renderExpression(r, datas[node].rhs, space); // fallback435 try renderExpression(r, rhs, space); // fallback
468 ais.popIndent();436 ais.popIndent();
469 },437 },
470438
471 .field_access => {439 .field_access => {
472 const main_token = main_tokens[node];440 const lhs, const name_token = tree.nodeData(node).node_and_token;
473 const field_access = datas[node];441 const dot_token = name_token - 1;
474442
475 try ais.pushIndent(.field_access);443 try ais.pushIndent(.field_access);
476 try renderExpression(r, field_access.lhs, .none);444 try renderExpression(r, lhs, .none);
477445
478 // Allow a line break between the lhs and the dot if the lhs and rhs446 // Allow a line break between the lhs and the dot if the lhs and rhs
479 // are on different lines.447 // are on different lines.
480 const lhs_last_token = tree.lastToken(field_access.lhs);448 const lhs_last_token = tree.lastToken(lhs);
481 const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1);449 const same_line = tree.tokensOnSameLine(lhs_last_token, name_token);
482 if (!same_line and !hasComment(tree, lhs_last_token, main_token)) try ais.insertNewline();450 if (!same_line and !hasComment(tree, lhs_last_token, dot_token)) try ais.insertNewline();
483451
484 try renderToken(r, main_token, .none); // .452 try renderToken(r, dot_token, .none);
485453
486 try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field454 try renderIdentifier(r, name_token, space, .eagerly_unquote); // field
487 ais.popIndent();455 ais.popIndent();
488 },456 },
489457
490 .error_union,458 .error_union,
491 .switch_range,459 .switch_range,
492 => {460 => {
493 const infix = datas[node];461 const lhs, const rhs = tree.nodeData(node).node_and_node;
494 try renderExpression(r, infix.lhs, .none);462 try renderExpression(r, lhs, .none);
495 try renderToken(r, main_tokens[node], .none);463 try renderToken(r, tree.nodeMainToken(node), .none);
496 return renderExpression(r, infix.rhs, space);464 return renderExpression(r, rhs, space);
497 },465 },
498 .for_range => {466 .for_range => {
499 const infix = datas[node];467 const start, const opt_end = tree.nodeData(node).node_and_opt_node;
500 try renderExpression(r, infix.lhs, .none);468 try renderExpression(r, start, .none);
501 if (infix.rhs != 0) {469 if (opt_end.unwrap()) |end| {
502 try renderToken(r, main_tokens[node], .none);470 try renderToken(r, tree.nodeMainToken(node), .none);
503 return renderExpression(r, infix.rhs, space);471 return renderExpression(r, end, space);
504 } else {472 } else {
505 return renderToken(r, main_tokens[node], space);473 return renderToken(r, tree.nodeMainToken(node), space);
506 }474 }
507 },475 },
508476
...@@ -525,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -525,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
525 .assign_mul_wrap,493 .assign_mul_wrap,
526 .assign_mul_sat,494 .assign_mul_sat,
527 => {495 => {
528 const infix = datas[node];496 const lhs, const rhs = tree.nodeData(node).node_and_node;
529 try renderExpression(r, infix.lhs, .space);497 try renderExpression(r, lhs, .space);
530 const op_token = main_tokens[node];498 const op_token = tree.nodeMainToken(node);
531 try ais.pushIndent(.after_equals);499 try ais.pushIndent(.after_equals);
532 if (tree.tokensOnSameLine(op_token, op_token + 1)) {500 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
533 try renderToken(r, op_token, .space);501 try renderToken(r, op_token, .space);
534 } else {502 } else {
535 try renderToken(r, op_token, .newline);503 try renderToken(r, op_token, .newline);
536 }504 }
537 try renderExpression(r, infix.rhs, space);505 try renderExpression(r, rhs, space);
538 ais.popIndent();506 ais.popIndent();
539 },507 },
540508
...@@ -568,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -568,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
568 .sub_sat,536 .sub_sat,
569 .@"orelse",537 .@"orelse",
570 => {538 => {
571 const infix = datas[node];539 const lhs, const rhs = tree.nodeData(node).node_and_node;
572 try renderExpression(r, infix.lhs, .space);540 try renderExpression(r, lhs, .space);
573 const op_token = main_tokens[node];541 const op_token = tree.nodeMainToken(node);
574 try ais.pushIndent(.binop);542 try ais.pushIndent(.binop);
575 if (tree.tokensOnSameLine(op_token, op_token + 1)) {543 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
576 try renderToken(r, op_token, .space);544 try renderToken(r, op_token, .space);
577 } else {545 } else {
578 try renderToken(r, op_token, .newline);546 try renderToken(r, op_token, .newline);
579 }547 }
580 try renderExpression(r, infix.rhs, space);548 try renderExpression(r, rhs, space);
581 ais.popIndent();549 ais.popIndent();
582 },550 },
583551
...@@ -589,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -589,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
589557
590 for (full.ast.variables, 0..) |variable_node, i| {558 for (full.ast.variables, 0..) |variable_node, i| {
591 const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space;559 const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space;
592 switch (node_tags[variable_node]) {560 switch (tree.nodeTag(variable_node)) {
593 .global_var_decl,561 .global_var_decl,
594 .local_var_decl,562 .local_var_decl,
595 .simple_var_decl,563 .simple_var_decl,
...@@ -617,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -617,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
617 .optional_type,585 .optional_type,
618 .address_of,586 .address_of,
619 => {587 => {
620 try renderToken(r, main_tokens[node], .none);588 try renderToken(r, tree.nodeMainToken(node), .none);
621 return renderExpression(r, datas[node].lhs, space);589 return renderExpression(r, tree.nodeData(node).node, space);
622 },590 },
623591
624 .@"try",592 .@"try",
625 .@"resume",593 .@"resume",
626 .@"await",594 .@"await",
627 => {595 => {
628 try renderToken(r, main_tokens[node], .space);596 try renderToken(r, tree.nodeMainToken(node), .space);
629 return renderExpression(r, datas[node].lhs, space);597 return renderExpression(r, tree.nodeData(node).node, space);
630 },598 },
631599
632 .array_type,600 .array_type,
...@@ -679,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -679,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
679 },647 },
680648
681 .array_access => {649 .array_access => {
682 const suffix = datas[node];650 const lhs, const rhs = tree.nodeData(node).node_and_node;
683 const lbracket = tree.firstToken(suffix.rhs) - 1;651 const lbracket = tree.firstToken(rhs) - 1;
684 const rbracket = tree.lastToken(suffix.rhs) + 1;652 const rbracket = tree.lastToken(rhs) + 1;
685 const one_line = tree.tokensOnSameLine(lbracket, rbracket);653 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
686 const inner_space = if (one_line) Space.none else Space.newline;654 const inner_space = if (one_line) Space.none else Space.newline;
687 try renderExpression(r, suffix.lhs, .none);655 try renderExpression(r, lhs, .none);
688 try ais.pushIndent(.normal);656 try ais.pushIndent(.normal);
689 try renderToken(r, lbracket, inner_space); // [657 try renderToken(r, lbracket, inner_space); // [
690 try renderExpression(r, suffix.rhs, inner_space);658 try renderExpression(r, rhs, inner_space);
691 ais.popIndent();659 ais.popIndent();
692 return renderToken(r, rbracket, space); // ]660 return renderToken(r, rbracket, space); // ]
693 },661 },
694662
695 .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space),663 .slice_open,
664 .slice,
665 .slice_sentinel,
666 => return renderSlice(r, node, tree.fullSlice(node).?, space),
696667
697 .deref => {668 .deref => {
698 try renderExpression(r, datas[node].lhs, .none);669 try renderExpression(r, tree.nodeData(node).node, .none);
699 return renderToken(r, main_tokens[node], space);670 return renderToken(r, tree.nodeMainToken(node), space);
700 },671 },
701672
702 .unwrap_optional => {673 .unwrap_optional => {
703 try renderExpression(r, datas[node].lhs, .none);674 const lhs, const question_mark = tree.nodeData(node).node_and_token;
704 try renderToken(r, main_tokens[node], .none);675 const dot_token = question_mark - 1;
705 return renderToken(r, datas[node].rhs, space);676 try renderExpression(r, lhs, .none);
677 try renderToken(r, dot_token, .none);
678 return renderToken(r, question_mark, space);
706 },679 },
707680
708 .@"break", .@"continue" => {681 .@"break", .@"continue" => {
709 const main_token = main_tokens[node];682 const main_token = tree.nodeMainToken(node);
710 const label_token = datas[node].lhs;683 const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node;
711 const target = datas[node].rhs;684 if (opt_label_token == .none and opt_target == .none) {
712 if (label_token == 0 and target == 0) {
713 try renderToken(r, main_token, space); // break/continue685 try renderToken(r, main_token, space); // break/continue
714 } else if (label_token == 0 and target != 0) {686 } else if (opt_label_token == .none and opt_target != .none) {
687 const target = opt_target.unwrap().?;
715 try renderToken(r, main_token, .space); // break/continue688 try renderToken(r, main_token, .space); // break/continue
716 try renderExpression(r, target, space);689 try renderExpression(r, target, space);
717 } else if (label_token != 0 and target == 0) {690 } else if (opt_label_token != .none and opt_target == .none) {
691 const label_token = opt_label_token.unwrap().?;
718 try renderToken(r, main_token, .space); // break/continue692 try renderToken(r, main_token, .space); // break/continue
719 try renderToken(r, label_token - 1, .none); // :693 try renderToken(r, label_token - 1, .none); // :
720 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier694 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
721 } else if (label_token != 0 and target != 0) {695 } else if (opt_label_token != .none and opt_target != .none) {
696 const label_token = opt_label_token.unwrap().?;
697 const target = opt_target.unwrap().?;
722 try renderToken(r, main_token, .space); // break/continue698 try renderToken(r, main_token, .space); // break/continue
723 try renderToken(r, label_token - 1, .none); // :699 try renderToken(r, label_token - 1, .none); // :
724 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier700 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
725 try renderExpression(r, target, space);701 try renderExpression(r, target, space);
726 }702 } else unreachable;
727 },703 },
728704
729 .@"return" => {705 .@"return" => {
730 if (datas[node].lhs != 0) {706 if (tree.nodeData(node).opt_node.unwrap()) |expr| {
731 try renderToken(r, main_tokens[node], .space);707 try renderToken(r, tree.nodeMainToken(node), .space);
732 try renderExpression(r, datas[node].lhs, space);708 try renderExpression(r, expr, space);
733 } else {709 } else {
734 try renderToken(r, main_tokens[node], space);710 try renderToken(r, tree.nodeMainToken(node), space);
735 }711 }
736 },712 },
737713
738 .grouped_expression => {714 .grouped_expression => {
715 const expr, const rparen = tree.nodeData(node).node_and_token;
739 try ais.pushIndent(.normal);716 try ais.pushIndent(.normal);
740 try renderToken(r, main_tokens[node], .none); // lparen717 try renderToken(r, tree.nodeMainToken(node), .none); // lparen
741 try renderExpression(r, datas[node].lhs, .none);718 try renderExpression(r, expr, .none);
742 ais.popIndent();719 ais.popIndent();
743 return renderToken(r, datas[node].rhs, space); // rparen720 return renderToken(r, rparen, space);
744 },721 },
745722
746 .container_decl,723 .container_decl,
...@@ -761,9 +738,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -761,9 +738,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
761 },738 },
762739
763 .error_set_decl => {740 .error_set_decl => {
764 const error_token = main_tokens[node];741 const error_token = tree.nodeMainToken(node);
765 const lbrace = error_token + 1;742 const lbrace, const rbrace = tree.nodeData(node).token_and_token;
766 const rbrace = datas[node].rhs;
767743
768 try renderToken(r, error_token, .none);744 try renderToken(r, error_token, .none);
769745
...@@ -771,20 +747,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -771,20 +747,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
771 // There is nothing between the braces so render condensed: `error{}`747 // There is nothing between the braces so render condensed: `error{}`
772 try renderToken(r, lbrace, .none);748 try renderToken(r, lbrace, .none);
773 return renderToken(r, rbrace, space);749 return renderToken(r, rbrace, space);
774 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {750 } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) {
775 // There is exactly one member and no trailing comma or751 // There is exactly one member and no trailing comma or
776 // comments, so render without surrounding spaces: `error{Foo}`752 // comments, so render without surrounding spaces: `error{Foo}`
777 try renderToken(r, lbrace, .none);753 try renderToken(r, lbrace, .none);
778 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier754 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
779 return renderToken(r, rbrace, space);755 return renderToken(r, rbrace, space);
780 } else if (token_tags[rbrace - 1] == .comma) {756 } else if (tree.tokenTag(rbrace - 1) == .comma) {
781 // There is a trailing comma so render each member on a new line.757 // There is a trailing comma so render each member on a new line.
782 try ais.pushIndent(.normal);758 try ais.pushIndent(.normal);
783 try renderToken(r, lbrace, .newline);759 try renderToken(r, lbrace, .newline);
784 var i = lbrace + 1;760 var i = lbrace + 1;
785 while (i < rbrace) : (i += 1) {761 while (i < rbrace) : (i += 1) {
786 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);762 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
787 switch (token_tags[i]) {763 switch (tree.tokenTag(i)) {
788 .doc_comment => try renderToken(r, i, .newline),764 .doc_comment => try renderToken(r, i, .newline),
789 .identifier => {765 .identifier => {
790 try ais.pushSpace(.comma);766 try ais.pushSpace(.comma);
...@@ -802,7 +778,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -802,7 +778,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
802 try renderToken(r, lbrace, .space);778 try renderToken(r, lbrace, .space);
803 var i = lbrace + 1;779 var i = lbrace + 1;
804 while (i < rbrace) : (i += 1) {780 while (i < rbrace) : (i += 1) {
805 switch (token_tags[i]) {781 switch (tree.tokenTag(i)) {
806 .doc_comment => unreachable, // TODO782 .doc_comment => unreachable, // TODO
807 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),783 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),
808 .comma => {},784 .comma => {},
...@@ -813,18 +789,14 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -813,18 +789,14 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
813 }789 }
814 },790 },
815791
816 .builtin_call_two, .builtin_call_two_comma => {792 .builtin_call_two,
817 if (datas[node].lhs == 0) {793 .builtin_call_two_comma,
818 return renderBuiltinCall(r, main_tokens[node], &.{}, space);794 .builtin_call,
819 } else if (datas[node].rhs == 0) {795 .builtin_call_comma,
820 return renderBuiltinCall(r, main_tokens[node], &.{datas[node].lhs}, space);796 => {
821 } else {797 var buf: [2]Ast.Node.Index = undefined;
822 return renderBuiltinCall(r, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space);798 const params = tree.builtinCallParams(&buf, node).?;
823 }799 return renderBuiltinCall(r, tree.nodeMainToken(node), params, space);
824 },
825 .builtin_call, .builtin_call_comma => {
826 const params = tree.extra_data[datas[node].lhs..datas[node].rhs];
827 return renderBuiltinCall(r, main_tokens[node], params, space);
828 },800 },
829801
830 .fn_proto_simple,802 .fn_proto_simple,
...@@ -837,14 +809,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -837,14 +809,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
837 },809 },
838810
839 .anyframe_type => {811 .anyframe_type => {
840 const main_token = main_tokens[node];812 const main_token = tree.nodeMainToken(node);
841 if (datas[node].rhs != 0) {813 try renderToken(r, main_token, .none); // anyframe
842 try renderToken(r, main_token, .none); // anyframe814 try renderToken(r, main_token + 1, .none); // ->
843 try renderToken(r, main_token + 1, .none); // ->815 return renderExpression(r, tree.nodeData(node).token_and_node[1], space);
844 return renderExpression(r, datas[node].rhs, space);
845 } else {
846 return renderToken(r, main_token, space); // anyframe
847 }
848 },816 },
849817
850 .@"switch",818 .@"switch",
...@@ -901,8 +869,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -901,8 +869,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
901 => return renderAsm(r, tree.fullAsm(node).?, space),869 => return renderAsm(r, tree.fullAsm(node).?, space),
902870
903 .enum_literal => {871 .enum_literal => {
904 try renderToken(r, main_tokens[node] - 1, .none); // .872 try renderToken(r, tree.nodeMainToken(node) - 1, .none); // .
905 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name873 return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name
906 },874 },
907875
908 .fn_decl => unreachable,876 .fn_decl => unreachable,
...@@ -944,9 +912,9 @@ fn renderArrayType(...@@ -944,9 +912,9 @@ fn renderArrayType(
944 try ais.pushIndent(.normal);912 try ais.pushIndent(.normal);
945 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket913 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
946 try renderExpression(r, array_type.ast.elem_count, inner_space);914 try renderExpression(r, array_type.ast.elem_count, inner_space);
947 if (array_type.ast.sentinel != 0) {915 if (array_type.ast.sentinel.unwrap()) |sentinel| {
948 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon916 try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon
949 try renderExpression(r, array_type.ast.sentinel, inner_space);917 try renderExpression(r, sentinel, inner_space);
950 }918 }
951 ais.popIndent();919 ais.popIndent();
952 try renderToken(r, rbracket, .none); // rbracket920 try renderToken(r, rbracket, .none); // rbracket
...@@ -955,6 +923,7 @@ fn renderArrayType(...@@ -955,6 +923,7 @@ fn renderArrayType(
955923
956fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {924fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
957 const tree = r.tree;925 const tree = r.tree;
926 const main_token = ptr_type.ast.main_token;
958 switch (ptr_type.size) {927 switch (ptr_type.size) {
959 .one => {928 .one => {
960 // Since ** tokens exist and the same token is shared by two929 // Since ** tokens exist and the same token is shared by two
...@@ -962,41 +931,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi...@@ -962,41 +931,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
962 // in such a relationship. If so, skip rendering anything for931 // in such a relationship. If so, skip rendering anything for
963 // this pointer type and rely on the child to render our asterisk932 // this pointer type and rely on the child to render our asterisk
964 // as well when it renders the ** token.933 // as well when it renders the ** token.
965 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and934 if (tree.tokenTag(main_token) == .asterisk_asterisk and
966 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])935 main_token == tree.nodeMainToken(ptr_type.ast.child_type))
967 {936 {
968 return renderExpression(r, ptr_type.ast.child_type, space);937 return renderExpression(r, ptr_type.ast.child_type, space);
969 }938 }
970 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk939 try renderToken(r, main_token, .none); // asterisk
971 },940 },
972 .many => {941 .many => {
973 if (ptr_type.ast.sentinel == 0) {942 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
974 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket943 try renderToken(r, main_token, .none); // lbracket
975 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk944 try renderToken(r, main_token + 1, .none); // asterisk
976 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket945 try renderToken(r, main_token + 2, .none); // colon
946 try renderExpression(r, sentinel, .none);
947 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
977 } else {948 } else {
978 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket949 try renderToken(r, main_token, .none); // lbracket
979 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk950 try renderToken(r, main_token + 1, .none); // asterisk
980 try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon951 try renderToken(r, main_token + 2, .none); // rbracket
981 try renderExpression(r, ptr_type.ast.sentinel, .none);
982 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
983 }952 }
984 },953 },
985 .c => {954 .c => {
986 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket955 try renderToken(r, main_token, .none); // lbracket
987 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk956 try renderToken(r, main_token + 1, .none); // asterisk
988 try renderToken(r, ptr_type.ast.main_token + 2, .none); // c957 try renderToken(r, main_token + 2, .none); // c
989 try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket958 try renderToken(r, main_token + 3, .none); // rbracket
990 },959 },
991 .slice => {960 .slice => {
992 if (ptr_type.ast.sentinel == 0) {961 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
993 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket962 try renderToken(r, main_token, .none); // lbracket
994 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket963 try renderToken(r, main_token + 1, .none); // colon
964 try renderExpression(r, sentinel, .none);
965 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
995 } else {966 } else {
996 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket967 try renderToken(r, main_token, .none); // lbracket
997 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon968 try renderToken(r, main_token + 1, .none); // rbracket
998 try renderExpression(r, ptr_type.ast.sentinel, .none);
999 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
1000 }969 }
1001 },970 },
1002 }971 }
...@@ -1005,29 +974,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi...@@ -1005,29 +974,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
1005 try renderToken(r, allowzero_token, .space);974 try renderToken(r, allowzero_token, .space);
1006 }975 }
1007976
1008 if (ptr_type.ast.align_node != 0) {977 if (ptr_type.ast.align_node.unwrap()) |align_node| {
1009 const align_first = tree.firstToken(ptr_type.ast.align_node);978 const align_first = tree.firstToken(align_node);
1010 try renderToken(r, align_first - 2, .none); // align979 try renderToken(r, align_first - 2, .none); // align
1011 try renderToken(r, align_first - 1, .none); // lparen980 try renderToken(r, align_first - 1, .none); // lparen
1012 try renderExpression(r, ptr_type.ast.align_node, .none);981 try renderExpression(r, align_node, .none);
1013 if (ptr_type.ast.bit_range_start != 0) {982 if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| {
1014 assert(ptr_type.ast.bit_range_end != 0);983 const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?;
1015 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon984 try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon
1016 try renderExpression(r, ptr_type.ast.bit_range_start, .none);985 try renderExpression(r, bit_range_start, .none);
1017 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon986 try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon
1018 try renderExpression(r, ptr_type.ast.bit_range_end, .none);987 try renderExpression(r, bit_range_end, .none);
1019 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen988 try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen
1020 } else {989 } else {
1021 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen990 try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen
1022 }991 }
1023 }992 }
1024993
1025 if (ptr_type.ast.addrspace_node != 0) {994 if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| {
1026 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);995 const addrspace_first = tree.firstToken(addrspace_node);
1027 try renderToken(r, addrspace_first - 2, .none); // addrspace996 try renderToken(r, addrspace_first - 2, .none); // addrspace
1028 try renderToken(r, addrspace_first - 1, .none); // lparen997 try renderToken(r, addrspace_first - 1, .none); // lparen
1029 try renderExpression(r, ptr_type.ast.addrspace_node, .none);998 try renderExpression(r, addrspace_node, .none);
1030 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen999 try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen
1031 }1000 }
10321001
1033 if (ptr_type.const_token) |const_token| {1002 if (ptr_type.const_token) |const_token| {
...@@ -1048,13 +1017,12 @@ fn renderSlice(...@@ -1048,13 +1017,12 @@ fn renderSlice(
1048 space: Space,1017 space: Space,
1049) Error!void {1018) Error!void {
1050 const tree = r.tree;1019 const tree = r.tree;
1051 const node_tags = tree.nodes.items(.tag);1020 const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
1052 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or1021 if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
1053 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
1054 const after_start_space = if (after_start_space_bool) Space.space else Space.none;1022 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
1055 const after_dots_space = if (slice.ast.end != 0)1023 const after_dots_space = if (slice.ast.end != .none)
1056 after_start_space1024 after_start_space
1057 else if (slice.ast.sentinel != 0) Space.space else Space.none;1025 else if (slice.ast.sentinel != .none) Space.space else Space.none;
10581026
1059 try renderExpression(r, slice.ast.sliced, .none);1027 try renderExpression(r, slice.ast.sliced, .none);
1060 try renderToken(r, slice.ast.lbracket, .none); // lbracket1028 try renderToken(r, slice.ast.lbracket, .none); // lbracket
...@@ -1063,14 +1031,14 @@ fn renderSlice(...@@ -1063,14 +1031,14 @@ fn renderSlice(
1063 try renderExpression(r, slice.ast.start, after_start_space);1031 try renderExpression(r, slice.ast.start, after_start_space);
1064 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")1032 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
10651033
1066 if (slice.ast.end != 0) {1034 if (slice.ast.end.unwrap()) |end| {
1067 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;1035 const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none;
1068 try renderExpression(r, slice.ast.end, after_end_space);1036 try renderExpression(r, end, after_end_space);
1069 }1037 }
10701038
1071 if (slice.ast.sentinel != 0) {1039 if (slice.ast.sentinel.unwrap()) |sentinel| {
1072 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon1040 try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon
1073 try renderExpression(r, slice.ast.sentinel, .none);1041 try renderExpression(r, sentinel, .none);
1074 }1042 }
10751043
1076 try renderToken(r, tree.lastToken(slice_node), space); // rbracket1044 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
...@@ -1082,12 +1050,8 @@ fn renderAsmOutput(...@@ -1082,12 +1050,8 @@ fn renderAsmOutput(
1082 space: Space,1050 space: Space,
1083) Error!void {1051) Error!void {
1084 const tree = r.tree;1052 const tree = r.tree;
1085 const token_tags = tree.tokens.items(.tag);1053 assert(tree.nodeTag(asm_output) == .asm_output);
1086 const node_tags = tree.nodes.items(.tag);1054 const symbolic_name = tree.nodeMainToken(asm_output);
1087 const main_tokens = tree.nodes.items(.main_token);
1088 const datas = tree.nodes.items(.data);
1089 assert(node_tags[asm_output] == .asm_output);
1090 const symbolic_name = main_tokens[asm_output];
10911055
1092 try renderToken(r, symbolic_name - 1, .none); // lbracket1056 try renderToken(r, symbolic_name - 1, .none); // lbracket
1093 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident1057 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
...@@ -1095,10 +1059,11 @@ fn renderAsmOutput(...@@ -1095,10 +1059,11 @@ fn renderAsmOutput(
1095 try renderToken(r, symbolic_name + 2, .space); // "constraint"1059 try renderToken(r, symbolic_name + 2, .space); // "constraint"
1096 try renderToken(r, symbolic_name + 3, .none); // lparen1060 try renderToken(r, symbolic_name + 3, .none); // lparen
10971061
1098 if (token_tags[symbolic_name + 4] == .arrow) {1062 if (tree.tokenTag(symbolic_name + 4) == .arrow) {
1063 const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token;
1099 try renderToken(r, symbolic_name + 4, .space); // ->1064 try renderToken(r, symbolic_name + 4, .space); // ->
1100 try renderExpression(r, datas[asm_output].lhs, Space.none);1065 try renderExpression(r, type_expr.unwrap().?, Space.none);
1101 return renderToken(r, datas[asm_output].rhs, space); // rparen1066 return renderToken(r, rparen, space);
1102 } else {1067 } else {
1103 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident1068 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
1104 return renderToken(r, symbolic_name + 5, space); // rparen1069 return renderToken(r, symbolic_name + 5, space); // rparen
...@@ -1111,19 +1076,17 @@ fn renderAsmInput(...@@ -1111,19 +1076,17 @@ fn renderAsmInput(
1111 space: Space,1076 space: Space,
1112) Error!void {1077) Error!void {
1113 const tree = r.tree;1078 const tree = r.tree;
1114 const node_tags = tree.nodes.items(.tag);1079 assert(tree.nodeTag(asm_input) == .asm_input);
1115 const main_tokens = tree.nodes.items(.main_token);1080 const symbolic_name = tree.nodeMainToken(asm_input);
1116 const datas = tree.nodes.items(.data);1081 const expr, const rparen = tree.nodeData(asm_input).node_and_token;
1117 assert(node_tags[asm_input] == .asm_input);
1118 const symbolic_name = main_tokens[asm_input];
11191082
1120 try renderToken(r, symbolic_name - 1, .none); // lbracket1083 try renderToken(r, symbolic_name - 1, .none); // lbracket
1121 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident1084 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
1122 try renderToken(r, symbolic_name + 1, .space); // rbracket1085 try renderToken(r, symbolic_name + 1, .space); // rbracket
1123 try renderToken(r, symbolic_name + 2, .space); // "constraint"1086 try renderToken(r, symbolic_name + 2, .space); // "constraint"
1124 try renderToken(r, symbolic_name + 3, .none); // lparen1087 try renderToken(r, symbolic_name + 3, .none); // lparen
1125 try renderExpression(r, datas[asm_input].lhs, Space.none);1088 try renderExpression(r, expr, Space.none);
1126 return renderToken(r, datas[asm_input].rhs, space); // rparen1089 return renderToken(r, rparen, space);
1127}1090}
11281091
1129fn renderVarDecl(1092fn renderVarDecl(
...@@ -1179,15 +1142,15 @@ fn renderVarDeclWithoutFixups(...@@ -1179,15 +1142,15 @@ fn renderVarDeclWithoutFixups(
11791142
1180 try renderToken(r, var_decl.ast.mut_token, .space); // var1143 try renderToken(r, var_decl.ast.mut_token, .space); // var
11811144
1182 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or1145 if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or
1183 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1146 var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1184 var_decl.ast.init_node != 0)1147 var_decl.ast.init_node != .none)
1185 {1148 {
1186 const name_space = if (var_decl.ast.type_node == 0 and1149 const name_space = if (var_decl.ast.type_node == .none and
1187 (var_decl.ast.align_node != 0 or1150 (var_decl.ast.align_node != .none or
1188 var_decl.ast.addrspace_node != 0 or1151 var_decl.ast.addrspace_node != .none or
1189 var_decl.ast.section_node != 0 or1152 var_decl.ast.section_node != .none or
1190 var_decl.ast.init_node != 0))1153 var_decl.ast.init_node != .none))
1191 Space.space1154 Space.space
1192 else1155 else
1193 Space.none;1156 Space.none;
...@@ -1197,26 +1160,26 @@ fn renderVarDeclWithoutFixups(...@@ -1197,26 +1160,26 @@ fn renderVarDeclWithoutFixups(
1197 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name1160 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
1198 }1161 }
11991162
1200 if (var_decl.ast.type_node != 0) {1163 if (var_decl.ast.type_node.unwrap()) |type_node| {
1201 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :1164 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
1202 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or1165 if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or
1203 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)1166 var_decl.ast.section_node != .none or var_decl.ast.init_node != .none)
1204 {1167 {
1205 try renderExpression(r, var_decl.ast.type_node, .space);1168 try renderExpression(r, type_node, .space);
1206 } else {1169 } else {
1207 return renderExpression(r, var_decl.ast.type_node, space);1170 return renderExpression(r, type_node, space);
1208 }1171 }
1209 }1172 }
12101173
1211 if (var_decl.ast.align_node != 0) {1174 if (var_decl.ast.align_node.unwrap()) |align_node| {
1212 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;1175 const lparen = tree.firstToken(align_node) - 1;
1213 const align_kw = lparen - 1;1176 const align_kw = lparen - 1;
1214 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;1177 const rparen = tree.lastToken(align_node) + 1;
1215 try renderToken(r, align_kw, Space.none); // align1178 try renderToken(r, align_kw, Space.none); // align
1216 try renderToken(r, lparen, Space.none); // (1179 try renderToken(r, lparen, Space.none); // (
1217 try renderExpression(r, var_decl.ast.align_node, Space.none);1180 try renderExpression(r, align_node, Space.none);
1218 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1181 if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1219 var_decl.ast.init_node != 0)1182 var_decl.ast.init_node != .none)
1220 {1183 {
1221 try renderToken(r, rparen, .space); // )1184 try renderToken(r, rparen, .space); // )
1222 } else {1185 } else {
...@@ -1224,14 +1187,14 @@ fn renderVarDeclWithoutFixups(...@@ -1224,14 +1187,14 @@ fn renderVarDeclWithoutFixups(
1224 }1187 }
1225 }1188 }
12261189
1227 if (var_decl.ast.addrspace_node != 0) {1190 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
1228 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;1191 const lparen = tree.firstToken(addrspace_node) - 1;
1229 const addrspace_kw = lparen - 1;1192 const addrspace_kw = lparen - 1;
1230 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;1193 const rparen = tree.lastToken(addrspace_node) + 1;
1231 try renderToken(r, addrspace_kw, Space.none); // addrspace1194 try renderToken(r, addrspace_kw, Space.none); // addrspace
1232 try renderToken(r, lparen, Space.none); // (1195 try renderToken(r, lparen, Space.none); // (
1233 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);1196 try renderExpression(r, addrspace_node, Space.none);
1234 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {1197 if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) {
1235 try renderToken(r, rparen, .space); // )1198 try renderToken(r, rparen, .space); // )
1236 } else {1199 } else {
1237 try renderToken(r, rparen, .none); // )1200 try renderToken(r, rparen, .none); // )
...@@ -1239,27 +1202,27 @@ fn renderVarDeclWithoutFixups(...@@ -1239,27 +1202,27 @@ fn renderVarDeclWithoutFixups(
1239 }1202 }
1240 }1203 }
12411204
1242 if (var_decl.ast.section_node != 0) {1205 if (var_decl.ast.section_node.unwrap()) |section_node| {
1243 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;1206 const lparen = tree.firstToken(section_node) - 1;
1244 const section_kw = lparen - 1;1207 const section_kw = lparen - 1;
1245 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;1208 const rparen = tree.lastToken(section_node) + 1;
1246 try renderToken(r, section_kw, Space.none); // linksection1209 try renderToken(r, section_kw, Space.none); // linksection
1247 try renderToken(r, lparen, Space.none); // (1210 try renderToken(r, lparen, Space.none); // (
1248 try renderExpression(r, var_decl.ast.section_node, Space.none);1211 try renderExpression(r, section_node, Space.none);
1249 if (var_decl.ast.init_node != 0) {1212 if (var_decl.ast.init_node != .none) {
1250 try renderToken(r, rparen, .space); // )1213 try renderToken(r, rparen, .space); // )
1251 } else {1214 } else {
1252 return renderToken(r, rparen, space); // )1215 return renderToken(r, rparen, space); // )
1253 }1216 }
1254 }1217 }
12551218
1256 assert(var_decl.ast.init_node != 0);1219 const init_node = var_decl.ast.init_node.unwrap().?;
12571220
1258 const eq_token = tree.firstToken(var_decl.ast.init_node) - 1;1221 const eq_token = tree.firstToken(init_node) - 1;
1259 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1222 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
1260 try ais.pushIndent(.after_equals);1223 try ais.pushIndent(.after_equals);
1261 try renderToken(r, eq_token, eq_space); // =1224 try renderToken(r, eq_token, eq_space); // =
1262 try renderExpression(r, var_decl.ast.init_node, space); // ;1225 try renderExpression(r, init_node, space); // ;
1263 ais.popIndent();1226 ais.popIndent();
1264}1227}
12651228
...@@ -1268,7 +1231,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {...@@ -1268,7 +1231,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
1268 .ast = .{1231 .ast = .{
1269 .while_token = if_node.ast.if_token,1232 .while_token = if_node.ast.if_token,
1270 .cond_expr = if_node.ast.cond_expr,1233 .cond_expr = if_node.ast.cond_expr,
1271 .cont_expr = 0,1234 .cont_expr = .none,
1272 .then_expr = if_node.ast.then_expr,1235 .then_expr = if_node.ast.then_expr,
1273 .else_expr = if_node.ast.else_expr,1236 .else_expr = if_node.ast.else_expr,
1274 },1237 },
...@@ -1284,7 +1247,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {...@@ -1284,7 +1247,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
1284/// respective values set to null.1247/// respective values set to null.
1285fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {1248fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
1286 const tree = r.tree;1249 const tree = r.tree;
1287 const token_tags = tree.tokens.items(.tag);
12881250
1289 if (while_node.label_token) |label| {1251 if (while_node.label_token) |label| {
1290 try renderIdentifier(r, label, .none, .eagerly_unquote); // label1252 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
...@@ -1305,7 +1267,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1305,7 +1267,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1305 try renderToken(r, last_prefix_token, .space);1267 try renderToken(r, last_prefix_token, .space);
1306 try renderToken(r, payload_token - 1, .none); // |1268 try renderToken(r, payload_token - 1, .none); // |
1307 const ident = blk: {1269 const ident = blk: {
1308 if (token_tags[payload_token] == .asterisk) {1270 if (tree.tokenTag(payload_token) == .asterisk) {
1309 try renderToken(r, payload_token, .none); // *1271 try renderToken(r, payload_token, .none); // *
1310 break :blk payload_token + 1;1272 break :blk payload_token + 1;
1311 } else {1273 } else {
...@@ -1314,7 +1276,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1314,7 +1276,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1314 };1276 };
1315 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier1277 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1316 const pipe = blk: {1278 const pipe = blk: {
1317 if (token_tags[ident + 1] == .comma) {1279 if (tree.tokenTag(ident + 1) == .comma) {
1318 try renderToken(r, ident + 1, .space); // ,1280 try renderToken(r, ident + 1, .space); // ,
1319 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index1281 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
1320 break :blk ident + 3;1282 break :blk ident + 3;
...@@ -1325,13 +1287,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1325,13 +1287,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1325 last_prefix_token = pipe;1287 last_prefix_token = pipe;
1326 }1288 }
13271289
1328 if (while_node.ast.cont_expr != 0) {1290 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
1329 try renderToken(r, last_prefix_token, .space);1291 try renderToken(r, last_prefix_token, .space);
1330 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1292 const lparen = tree.firstToken(cont_expr) - 1;
1331 try renderToken(r, lparen - 1, .space); // :1293 try renderToken(r, lparen - 1, .space); // :
1332 try renderToken(r, lparen, .none); // lparen1294 try renderToken(r, lparen, .none); // lparen
1333 try renderExpression(r, while_node.ast.cont_expr, .none);1295 try renderExpression(r, cont_expr, .none);
1334 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen1296 last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen
1335 }1297 }
13361298
1337 try renderThenElse(1299 try renderThenElse(
...@@ -1349,15 +1311,14 @@ fn renderThenElse(...@@ -1349,15 +1311,14 @@ fn renderThenElse(
1349 r: *Render,1311 r: *Render,
1350 last_prefix_token: Ast.TokenIndex,1312 last_prefix_token: Ast.TokenIndex,
1351 then_expr: Ast.Node.Index,1313 then_expr: Ast.Node.Index,
1352 else_token: Ast.TokenIndex,1314 else_token: ?Ast.TokenIndex,
1353 maybe_error_token: ?Ast.TokenIndex,1315 maybe_error_token: ?Ast.TokenIndex,
1354 else_expr: Ast.Node.Index,1316 opt_else_expr: Ast.Node.OptionalIndex,
1355 space: Space,1317 space: Space,
1356) Error!void {1318) Error!void {
1357 const tree = r.tree;1319 const tree = r.tree;
1358 const ais = r.ais;1320 const ais = r.ais;
1359 const node_tags = tree.nodes.items(.tag);1321 const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
1360 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
1361 const indent_then_expr = !then_expr_is_block and1322 const indent_then_expr = !then_expr_is_block and
1362 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));1323 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
13631324
...@@ -1373,7 +1334,7 @@ fn renderThenElse(...@@ -1373,7 +1334,7 @@ fn renderThenElse(
1373 try renderToken(r, last_prefix_token, .space);1334 try renderToken(r, last_prefix_token, .space);
1374 }1335 }
13751336
1376 if (else_expr != 0) {1337 if (opt_else_expr.unwrap()) |else_expr| {
1377 if (indent_then_expr) {1338 if (indent_then_expr) {
1378 try renderExpression(r, then_expr, .newline);1339 try renderExpression(r, then_expr, .newline);
1379 } else {1340 } else {
...@@ -1382,18 +1343,18 @@ fn renderThenElse(...@@ -1382,18 +1343,18 @@ fn renderThenElse(
13821343
1383 if (indent_then_expr) ais.popIndent();1344 if (indent_then_expr) ais.popIndent();
13841345
1385 var last_else_token = else_token;1346 var last_else_token = else_token.?;
13861347
1387 if (maybe_error_token) |error_token| {1348 if (maybe_error_token) |error_token| {
1388 try renderToken(r, else_token, .space); // else1349 try renderToken(r, last_else_token, .space); // else
1389 try renderToken(r, error_token - 1, .none); // |1350 try renderToken(r, error_token - 1, .none); // |
1390 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier1351 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
1391 last_else_token = error_token + 1; // |1352 last_else_token = error_token + 1; // |
1392 }1353 }
13931354
1394 const indent_else_expr = indent_then_expr and1355 const indent_else_expr = indent_then_expr and
1395 !nodeIsBlock(node_tags[else_expr]) and1356 !nodeIsBlock(tree.nodeTag(else_expr)) and
1396 !nodeIsIfForWhileSwitch(node_tags[else_expr]);1357 !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr));
1397 if (indent_else_expr) {1358 if (indent_else_expr) {
1398 try ais.pushIndent(.normal);1359 try ais.pushIndent(.normal);
1399 try renderToken(r, last_else_token, .newline);1360 try renderToken(r, last_else_token, .newline);
...@@ -1430,21 +1391,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {...@@ -1430,21 +1391,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
14301391
1431 var cur = for_node.payload_token;1392 var cur = for_node.payload_token;
1432 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;1393 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
1433 if (token_tags[pipe - 1] == .comma) {1394 if (tree.tokenTag(@intCast(pipe - 1)) == .comma) {
1434 try ais.pushIndent(.normal);1395 try ais.pushIndent(.normal);
1435 try renderToken(r, cur - 1, .newline); // |1396 try renderToken(r, cur - 1, .newline); // |
1436 while (true) {1397 while (true) {
1437 if (token_tags[cur] == .asterisk) {1398 if (tree.tokenTag(cur) == .asterisk) {
1438 try renderToken(r, cur, .none); // *1399 try renderToken(r, cur, .none); // *
1439 cur += 1;1400 cur += 1;
1440 }1401 }
1441 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier1402 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1442 cur += 1;1403 cur += 1;
1443 if (token_tags[cur] == .comma) {1404 if (tree.tokenTag(cur) == .comma) {
1444 try renderToken(r, cur, .newline); // ,1405 try renderToken(r, cur, .newline); // ,
1445 cur += 1;1406 cur += 1;
1446 }1407 }
1447 if (token_tags[cur] == .pipe) {1408 if (tree.tokenTag(cur) == .pipe) {
1448 break;1409 break;
1449 }1410 }
1450 }1411 }
...@@ -1452,17 +1413,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {...@@ -1452,17 +1413,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
1452 } else {1413 } else {
1453 try renderToken(r, cur - 1, .none); // |1414 try renderToken(r, cur - 1, .none); // |
1454 while (true) {1415 while (true) {
1455 if (token_tags[cur] == .asterisk) {1416 if (tree.tokenTag(cur) == .asterisk) {
1456 try renderToken(r, cur, .none); // *1417 try renderToken(r, cur, .none); // *
1457 cur += 1;1418 cur += 1;
1458 }1419 }
1459 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier1420 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1460 cur += 1;1421 cur += 1;
1461 if (token_tags[cur] == .comma) {1422 if (tree.tokenTag(cur) == .comma) {
1462 try renderToken(r, cur, .space); // ,1423 try renderToken(r, cur, .space); // ,
1463 cur += 1;1424 cur += 1;
1464 }1425 }
1465 if (token_tags[cur] == .pipe) {1426 if (tree.tokenTag(cur) == .pipe) {
1466 break;1427 break;
1467 }1428 }
1468 }1429 }
...@@ -1488,7 +1449,7 @@ fn renderContainerField(...@@ -1488,7 +1449,7 @@ fn renderContainerField(
1488 const tree = r.tree;1449 const tree = r.tree;
1489 const ais = r.ais;1450 const ais = r.ais;
1490 var field = field_param;1451 var field = field_param;
1491 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);1452 if (container != .tuple) field.convertToNonTupleLike(&tree);
1492 const quote: QuoteBehavior = switch (container) {1453 const quote: QuoteBehavior = switch (container) {
1493 .@"enum" => .eagerly_unquote_except_underscore,1454 .@"enum" => .eagerly_unquote_except_underscore,
1494 .tuple, .other => .eagerly_unquote,1455 .tuple, .other => .eagerly_unquote,
...@@ -1497,67 +1458,74 @@ fn renderContainerField(...@@ -1497,67 +1458,74 @@ fn renderContainerField(
1497 if (field.comptime_token) |t| {1458 if (field.comptime_token) |t| {
1498 try renderToken(r, t, .space); // comptime1459 try renderToken(r, t, .space); // comptime
1499 }1460 }
1500 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {1461 if (field.ast.type_expr == .none and field.ast.value_expr == .none) {
1501 if (field.ast.align_expr != 0) {1462 if (field.ast.align_expr.unwrap()) |align_expr| {
1502 try renderIdentifier(r, field.ast.main_token, .space, quote); // name1463 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1503 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1464 const lparen_token = tree.firstToken(align_expr) - 1;
1504 const align_kw = lparen_token - 1;1465 const align_kw = lparen_token - 1;
1505 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1466 const rparen_token = tree.lastToken(align_expr) + 1;
1506 try renderToken(r, align_kw, .none); // align1467 try renderToken(r, align_kw, .none); // align
1507 try renderToken(r, lparen_token, .none); // (1468 try renderToken(r, lparen_token, .none); // (
1508 try renderExpression(r, field.ast.align_expr, .none); // alignment1469 try renderExpression(r, align_expr, .none); // alignment
1509 return renderToken(r, rparen_token, .space); // )1470 return renderToken(r, rparen_token, .space); // )
1510 }1471 }
1511 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name1472 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
1512 }1473 }
1513 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {1474 if (field.ast.type_expr != .none and field.ast.value_expr == .none) {
1475 const type_expr = field.ast.type_expr.unwrap().?;
1514 if (!field.ast.tuple_like) {1476 if (!field.ast.tuple_like) {
1515 try renderIdentifier(r, field.ast.main_token, .none, quote); // name1477 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1516 try renderToken(r, field.ast.main_token + 1, .space); // :1478 try renderToken(r, field.ast.main_token + 1, .space); // :
1517 }1479 }
15181480
1519 if (field.ast.align_expr != 0) {1481 if (field.ast.align_expr.unwrap()) |align_expr| {
1520 try renderExpression(r, field.ast.type_expr, .space); // type1482 try renderExpression(r, type_expr, .space); // type
1521 const align_token = tree.firstToken(field.ast.align_expr) - 2;1483 const align_token = tree.firstToken(align_expr) - 2;
1522 try renderToken(r, align_token, .none); // align1484 try renderToken(r, align_token, .none); // align
1523 try renderToken(r, align_token + 1, .none); // (1485 try renderToken(r, align_token + 1, .none); // (
1524 try renderExpression(r, field.ast.align_expr, .none); // alignment1486 try renderExpression(r, align_expr, .none); // alignment
1525 const rparen = tree.lastToken(field.ast.align_expr) + 1;1487 const rparen = tree.lastToken(align_expr) + 1;
1526 return renderTokenComma(r, rparen, space); // )1488 return renderTokenComma(r, rparen, space); // )
1527 } else {1489 } else {
1528 return renderExpressionComma(r, field.ast.type_expr, space); // type1490 return renderExpressionComma(r, type_expr, space); // type
1529 }1491 }
1530 }1492 }
1531 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {1493 if (field.ast.type_expr == .none and field.ast.value_expr != .none) {
1494 const value_expr = field.ast.value_expr.unwrap().?;
1495
1532 try renderIdentifier(r, field.ast.main_token, .space, quote); // name1496 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1533 if (field.ast.align_expr != 0) {1497 if (field.ast.align_expr.unwrap()) |align_expr| {
1534 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1498 const lparen_token = tree.firstToken(align_expr) - 1;
1535 const align_kw = lparen_token - 1;1499 const align_kw = lparen_token - 1;
1536 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1500 const rparen_token = tree.lastToken(align_expr) + 1;
1537 try renderToken(r, align_kw, .none); // align1501 try renderToken(r, align_kw, .none); // align
1538 try renderToken(r, lparen_token, .none); // (1502 try renderToken(r, lparen_token, .none); // (
1539 try renderExpression(r, field.ast.align_expr, .none); // alignment1503 try renderExpression(r, align_expr, .none); // alignment
1540 try renderToken(r, rparen_token, .space); // )1504 try renderToken(r, rparen_token, .space); // )
1541 }1505 }
1542 try renderToken(r, field.ast.main_token + 1, .space); // =1506 try renderToken(r, field.ast.main_token + 1, .space); // =
1543 return renderExpressionComma(r, field.ast.value_expr, space); // value1507 return renderExpressionComma(r, value_expr, space); // value
1544 }1508 }
1545 if (!field.ast.tuple_like) {1509 if (!field.ast.tuple_like) {
1546 try renderIdentifier(r, field.ast.main_token, .none, quote); // name1510 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1547 try renderToken(r, field.ast.main_token + 1, .space); // :1511 try renderToken(r, field.ast.main_token + 1, .space); // :
1548 }1512 }
1549 try renderExpression(r, field.ast.type_expr, .space); // type
15501513
1551 if (field.ast.align_expr != 0) {1514 const type_expr = field.ast.type_expr.unwrap().?;
1552 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1515 const value_expr = field.ast.value_expr.unwrap().?;
1516
1517 try renderExpression(r, type_expr, .space); // type
1518
1519 if (field.ast.align_expr.unwrap()) |align_expr| {
1520 const lparen_token = tree.firstToken(align_expr) - 1;
1553 const align_kw = lparen_token - 1;1521 const align_kw = lparen_token - 1;
1554 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1522 const rparen_token = tree.lastToken(align_expr) + 1;
1555 try renderToken(r, align_kw, .none); // align1523 try renderToken(r, align_kw, .none); // align
1556 try renderToken(r, lparen_token, .none); // (1524 try renderToken(r, lparen_token, .none); // (
1557 try renderExpression(r, field.ast.align_expr, .none); // alignment1525 try renderExpression(r, align_expr, .none); // alignment
1558 try renderToken(r, rparen_token, .space); // )1526 try renderToken(r, rparen_token, .space); // )
1559 }1527 }
1560 const eq_token = tree.firstToken(field.ast.value_expr) - 1;1528 const eq_token = tree.firstToken(value_expr) - 1;
1561 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1529 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
15621530
1563 try ais.pushIndent(.after_equals);1531 try ais.pushIndent(.after_equals);
...@@ -1565,19 +1533,18 @@ fn renderContainerField(...@@ -1565,19 +1533,18 @@ fn renderContainerField(
15651533
1566 if (eq_space == .space) {1534 if (eq_space == .space) {
1567 ais.popIndent();1535 ais.popIndent();
1568 try renderExpressionComma(r, field.ast.value_expr, space); // value1536 try renderExpressionComma(r, value_expr, space); // value
1569 return;1537 return;
1570 }1538 }
15711539
1572 const token_tags = tree.tokens.items(.tag);1540 const maybe_comma = tree.lastToken(value_expr) + 1;
1573 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
15741541
1575 if (token_tags[maybe_comma] == .comma) {1542 if (tree.tokenTag(maybe_comma) == .comma) {
1576 try renderExpression(r, field.ast.value_expr, .none); // value1543 try renderExpression(r, value_expr, .none); // value
1577 ais.popIndent();1544 ais.popIndent();
1578 try renderToken(r, maybe_comma, .newline);1545 try renderToken(r, maybe_comma, .newline);
1579 } else {1546 } else {
1580 try renderExpression(r, field.ast.value_expr, space); // value1547 try renderExpression(r, value_expr, space); // value
1581 ais.popIndent();1548 ais.popIndent();
1582 }1549 }
1583}1550}
...@@ -1590,8 +1557,6 @@ fn renderBuiltinCall(...@@ -1590,8 +1557,6 @@ fn renderBuiltinCall(
1590) Error!void {1557) Error!void {
1591 const tree = r.tree;1558 const tree = r.tree;
1592 const ais = r.ais;1559 const ais = r.ais;
1593 const token_tags = tree.tokens.items(.tag);
1594 const main_tokens = tree.nodes.items(.main_token);
15951560
1596 try renderToken(r, builtin_token, .none); // @name1561 try renderToken(r, builtin_token, .none); // @name
15971562
...@@ -1604,8 +1569,8 @@ fn renderBuiltinCall(...@@ -1604,8 +1569,8 @@ fn renderBuiltinCall(
1604 const slice = tree.tokenSlice(builtin_token);1569 const slice = tree.tokenSlice(builtin_token);
1605 if (mem.eql(u8, slice, "@import")) f: {1570 if (mem.eql(u8, slice, "@import")) f: {
1606 const param = params[0];1571 const param = params[0];
1607 const str_lit_token = main_tokens[param];1572 const str_lit_token = tree.nodeMainToken(param);
1608 assert(token_tags[str_lit_token] == .string_literal);1573 assert(tree.tokenTag(str_lit_token) == .string_literal);
1609 const token_bytes = tree.tokenSlice(str_lit_token);1574 const token_bytes = tree.tokenSlice(str_lit_token);
1610 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {1575 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {
1611 error.OutOfMemory => return error.OutOfMemory,1576 error.OutOfMemory => return error.OutOfMemory,
...@@ -1624,13 +1589,13 @@ fn renderBuiltinCall(...@@ -1624,13 +1589,13 @@ fn renderBuiltinCall(
1624 const last_param = params[params.len - 1];1589 const last_param = params[params.len - 1];
1625 const after_last_param_token = tree.lastToken(last_param) + 1;1590 const after_last_param_token = tree.lastToken(last_param) + 1;
16261591
1627 if (token_tags[after_last_param_token] != .comma) {1592 if (tree.tokenTag(after_last_param_token) != .comma) {
1628 // Render all on one line, no trailing comma.1593 // Render all on one line, no trailing comma.
1629 try renderToken(r, builtin_token + 1, .none); // (1594 try renderToken(r, builtin_token + 1, .none); // (
16301595
1631 for (params, 0..) |param_node, i| {1596 for (params, 0..) |param_node, i| {
1632 const first_param_token = tree.firstToken(param_node);1597 const first_param_token = tree.firstToken(param_node);
1633 if (token_tags[first_param_token] == .multiline_string_literal_line or1598 if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or
1634 hasSameLineComment(tree, first_param_token - 1))1599 hasSameLineComment(tree, first_param_token - 1))
1635 {1600 {
1636 try ais.pushIndent(.normal);1601 try ais.pushIndent(.normal);
...@@ -1665,11 +1630,9 @@ fn renderBuiltinCall(...@@ -1665,11 +1630,9 @@ fn renderBuiltinCall(
1665fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {1630fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
1666 const tree = r.tree;1631 const tree = r.tree;
1667 const ais = r.ais;1632 const ais = r.ais;
1668 const token_tags = tree.tokens.items(.tag);
1669 const token_starts = tree.tokens.items(.start);
16701633
1671 const after_fn_token = fn_proto.ast.fn_token + 1;1634 const after_fn_token = fn_proto.ast.fn_token + 1;
1672 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {1635 const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: {
1673 try renderToken(r, fn_proto.ast.fn_token, .space); // fn1636 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1674 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name1637 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
1675 break :blk after_fn_token + 1;1638 break :blk after_fn_token + 1;
...@@ -1677,41 +1640,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1677,41 +1640,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1677 try renderToken(r, fn_proto.ast.fn_token, .space); // fn1640 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1678 break :blk fn_proto.ast.fn_token + 1;1641 break :blk fn_proto.ast.fn_token + 1;
1679 };1642 };
1680 assert(token_tags[lparen] == .l_paren);1643 assert(tree.tokenTag(lparen) == .l_paren);
16811644
1682 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1645 const return_type = fn_proto.ast.return_type.unwrap().?;
1646 const maybe_bang = tree.firstToken(return_type) - 1;
1683 const rparen = blk: {1647 const rparen = blk: {
1684 // These may appear in any order, so we have to check the token_starts array1648 // These may appear in any order, so we have to check the token_starts array
1685 // to find out which is first.1649 // to find out which is first.
1686 var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang;1650 var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang;
1687 var smallest_start = token_starts[maybe_bang];1651 var smallest_start = tree.tokenStart(maybe_bang);
1688 if (fn_proto.ast.align_expr != 0) {1652 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1689 const tok = tree.firstToken(fn_proto.ast.align_expr) - 3;1653 const tok = tree.firstToken(align_expr) - 3;
1690 const start = token_starts[tok];1654 const start = tree.tokenStart(tok);
1691 if (start < smallest_start) {1655 if (start < smallest_start) {
1692 rparen = tok;1656 rparen = tok;
1693 smallest_start = start;1657 smallest_start = start;
1694 }1658 }
1695 }1659 }
1696 if (fn_proto.ast.addrspace_expr != 0) {1660 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1697 const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3;1661 const tok = tree.firstToken(addrspace_expr) - 3;
1698 const start = token_starts[tok];1662 const start = tree.tokenStart(tok);
1699 if (start < smallest_start) {1663 if (start < smallest_start) {
1700 rparen = tok;1664 rparen = tok;
1701 smallest_start = start;1665 smallest_start = start;
1702 }1666 }
1703 }1667 }
1704 if (fn_proto.ast.section_expr != 0) {1668 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1705 const tok = tree.firstToken(fn_proto.ast.section_expr) - 3;1669 const tok = tree.firstToken(section_expr) - 3;
1706 const start = token_starts[tok];1670 const start = tree.tokenStart(tok);
1707 if (start < smallest_start) {1671 if (start < smallest_start) {
1708 rparen = tok;1672 rparen = tok;
1709 smallest_start = start;1673 smallest_start = start;
1710 }1674 }
1711 }1675 }
1712 if (fn_proto.ast.callconv_expr != 0) {1676 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1713 const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3;1677 const tok = tree.firstToken(callconv_expr) - 3;
1714 const start = token_starts[tok];1678 const start = tree.tokenStart(tok);
1715 if (start < smallest_start) {1679 if (start < smallest_start) {
1716 rparen = tok;1680 rparen = tok;
1717 smallest_start = start;1681 smallest_start = start;
...@@ -1719,11 +1683,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1719,11 +1683,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1719 }1683 }
1720 break :blk rparen;1684 break :blk rparen;
1721 };1685 };
1722 assert(token_tags[rparen] == .r_paren);1686 assert(tree.tokenTag(rparen) == .r_paren);
17231687
1724 // The params list is a sparse set that does *not* include anytype or ... parameters.1688 // The params list is a sparse set that does *not* include anytype or ... parameters.
17251689
1726 const trailing_comma = token_tags[rparen - 1] == .comma;1690 const trailing_comma = tree.tokenTag(rparen - 1) == .comma;
1727 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {1691 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
1728 // Render all on one line, no trailing comma.1692 // Render all on one line, no trailing comma.
1729 try renderToken(r, lparen, .none); // (1693 try renderToken(r, lparen, .none); // (
...@@ -1732,7 +1696,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1732,7 +1696,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1732 var last_param_token = lparen;1696 var last_param_token = lparen;
1733 while (true) {1697 while (true) {
1734 last_param_token += 1;1698 last_param_token += 1;
1735 switch (token_tags[last_param_token]) {1699 switch (tree.tokenTag(last_param_token)) {
1736 .doc_comment => {1700 .doc_comment => {
1737 try renderToken(r, last_param_token, .newline);1701 try renderToken(r, last_param_token, .newline);
1738 continue;1702 continue;
...@@ -1757,15 +1721,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1757,15 +1721,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1757 },1721 },
1758 else => {}, // Parameter type without a name.1722 else => {}, // Parameter type without a name.
1759 }1723 }
1760 if (token_tags[last_param_token] == .identifier and1724 if (tree.tokenTag(last_param_token) == .identifier and
1761 token_tags[last_param_token + 1] == .colon)1725 tree.tokenTag(last_param_token + 1) == .colon)
1762 {1726 {
1763 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name1727 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1764 last_param_token += 1;1728 last_param_token = last_param_token + 1;
1765 try renderToken(r, last_param_token, .space); // :1729 try renderToken(r, last_param_token, .space); // :
1766 last_param_token += 1;1730 last_param_token += 1;
1767 }1731 }
1768 if (token_tags[last_param_token] == .keyword_anytype) {1732 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
1769 try renderToken(r, last_param_token, .none); // anytype1733 try renderToken(r, last_param_token, .none); // anytype
1770 continue;1734 continue;
1771 }1735 }
...@@ -1783,7 +1747,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1783,7 +1747,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1783 var last_param_token = lparen;1747 var last_param_token = lparen;
1784 while (true) {1748 while (true) {
1785 last_param_token += 1;1749 last_param_token += 1;
1786 switch (token_tags[last_param_token]) {1750 switch (tree.tokenTag(last_param_token)) {
1787 .doc_comment => {1751 .doc_comment => {
1788 try renderToken(r, last_param_token, .newline);1752 try renderToken(r, last_param_token, .newline);
1789 continue;1753 continue;
...@@ -1799,24 +1763,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1799,24 +1763,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1799 .identifier => {},1763 .identifier => {},
1800 .keyword_anytype => {1764 .keyword_anytype => {
1801 try renderToken(r, last_param_token, .comma); // anytype1765 try renderToken(r, last_param_token, .comma); // anytype
1802 if (token_tags[last_param_token + 1] == .comma)1766 if (tree.tokenTag(last_param_token + 1) == .comma)
1803 last_param_token += 1;1767 last_param_token += 1;
1804 continue;1768 continue;
1805 },1769 },
1806 .r_paren => break,1770 .r_paren => break,
1807 else => {}, // Parameter type without a name.1771 else => {}, // Parameter type without a name.
1808 }1772 }
1809 if (token_tags[last_param_token] == .identifier and1773 if (tree.tokenTag(last_param_token) == .identifier and
1810 token_tags[last_param_token + 1] == .colon)1774 tree.tokenTag(last_param_token + 1) == .colon)
1811 {1775 {
1812 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name1776 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1813 last_param_token += 1;1777 last_param_token += 1;
1814 try renderToken(r, last_param_token, .space); // :1778 try renderToken(r, last_param_token, .space); // :
1815 last_param_token += 1;1779 last_param_token += 1;
1816 }1780 }
1817 if (token_tags[last_param_token] == .keyword_anytype) {1781 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
1818 try renderToken(r, last_param_token, .comma); // anytype1782 try renderToken(r, last_param_token, .comma); // anytype
1819 if (token_tags[last_param_token + 1] == .comma)1783 if (tree.tokenTag(last_param_token + 1) == .comma)
1820 last_param_token += 1;1784 last_param_token += 1;
1821 continue;1785 continue;
1822 }1786 }
...@@ -1826,60 +1790,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1826,60 +1790,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1826 try renderExpression(r, param, .comma);1790 try renderExpression(r, param, .comma);
1827 ais.popSpace();1791 ais.popSpace();
1828 last_param_token = tree.lastToken(param);1792 last_param_token = tree.lastToken(param);
1829 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;1793 if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1;
1830 }1794 }
1831 ais.popIndent();1795 ais.popIndent();
1832 }1796 }
18331797
1834 try renderToken(r, rparen, .space); // )1798 try renderToken(r, rparen, .space); // )
18351799
1836 if (fn_proto.ast.align_expr != 0) {1800 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1837 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;1801 const align_lparen = tree.firstToken(align_expr) - 1;
1838 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;1802 const align_rparen = tree.lastToken(align_expr) + 1;
18391803
1840 try renderToken(r, align_lparen - 1, .none); // align1804 try renderToken(r, align_lparen - 1, .none); // align
1841 try renderToken(r, align_lparen, .none); // (1805 try renderToken(r, align_lparen, .none); // (
1842 try renderExpression(r, fn_proto.ast.align_expr, .none);1806 try renderExpression(r, align_expr, .none);
1843 try renderToken(r, align_rparen, .space); // )1807 try renderToken(r, align_rparen, .space); // )
1844 }1808 }
18451809
1846 if (fn_proto.ast.addrspace_expr != 0) {1810 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1847 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;1811 const align_lparen = tree.firstToken(addrspace_expr) - 1;
1848 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;1812 const align_rparen = tree.lastToken(addrspace_expr) + 1;
18491813
1850 try renderToken(r, align_lparen - 1, .none); // addrspace1814 try renderToken(r, align_lparen - 1, .none); // addrspace
1851 try renderToken(r, align_lparen, .none); // (1815 try renderToken(r, align_lparen, .none); // (
1852 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);1816 try renderExpression(r, addrspace_expr, .none);
1853 try renderToken(r, align_rparen, .space); // )1817 try renderToken(r, align_rparen, .space); // )
1854 }1818 }
18551819
1856 if (fn_proto.ast.section_expr != 0) {1820 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1857 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;1821 const section_lparen = tree.firstToken(section_expr) - 1;
1858 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;1822 const section_rparen = tree.lastToken(section_expr) + 1;
18591823
1860 try renderToken(r, section_lparen - 1, .none); // section1824 try renderToken(r, section_lparen - 1, .none); // section
1861 try renderToken(r, section_lparen, .none); // (1825 try renderToken(r, section_lparen, .none); // (
1862 try renderExpression(r, fn_proto.ast.section_expr, .none);1826 try renderExpression(r, section_expr, .none);
1863 try renderToken(r, section_rparen, .space); // )1827 try renderToken(r, section_rparen, .space); // )
1864 }1828 }
18651829
1866 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE1830 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1867 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));1831 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1868 const is_declaration = fn_proto.name_token != null;1832 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)));
1869 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {1833 const is_declaration = fn_proto.name_token != null;
1870 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;1834 if (!(is_declaration and is_callconv_inline)) {
1871 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;1835 const callconv_lparen = tree.firstToken(callconv_expr) - 1;
1836 const callconv_rparen = tree.lastToken(callconv_expr) + 1;
18721837
1873 try renderToken(r, callconv_lparen - 1, .none); // callconv1838 try renderToken(r, callconv_lparen - 1, .none); // callconv
1874 try renderToken(r, callconv_lparen, .none); // (1839 try renderToken(r, callconv_lparen, .none); // (
1875 try renderExpression(r, fn_proto.ast.callconv_expr, .none);1840 try renderExpression(r, callconv_expr, .none);
1876 try renderToken(r, callconv_rparen, .space); // )1841 try renderToken(r, callconv_rparen, .space); // )
1842 }
1877 }1843 }
18781844
1879 if (token_tags[maybe_bang] == .bang) {1845 if (tree.tokenTag(maybe_bang) == .bang) {
1880 try renderToken(r, maybe_bang, .none); // !1846 try renderToken(r, maybe_bang, .none); // !
1881 }1847 }
1882 return renderExpression(r, fn_proto.ast.return_type, space);1848 return renderExpression(r, return_type, space);
1883}1849}
18841850
1885fn renderSwitchCase(1851fn renderSwitchCase(
...@@ -1889,9 +1855,7 @@ fn renderSwitchCase(...@@ -1889,9 +1855,7 @@ fn renderSwitchCase(
1889) Error!void {1855) Error!void {
1890 const ais = r.ais;1856 const ais = r.ais;
1891 const tree = r.tree;1857 const tree = r.tree;
1892 const node_tags = tree.nodes.items(.tag);1858 const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
1893 const token_tags = tree.tokens.items(.tag);
1894 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
1895 const has_comment_before_arrow = blk: {1859 const has_comment_before_arrow = blk: {
1896 if (switch_case.ast.values.len == 0) break :blk false;1860 if (switch_case.ast.values.len == 0) break :blk false;
1897 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);1861 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);
...@@ -1918,7 +1882,7 @@ fn renderSwitchCase(...@@ -1918,7 +1882,7 @@ fn renderSwitchCase(
1918 }1882 }
19191883
1920 // Render the arrow and everything after it1884 // Render the arrow and everything after it
1921 const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal)1885 const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal)
1922 // Newline gets inserted when rendering the target expr.1886 // Newline gets inserted when rendering the target expr.
1923 Space.none1887 Space.none
1924 else1888 else
...@@ -1928,12 +1892,12 @@ fn renderSwitchCase(...@@ -1928,12 +1892,12 @@ fn renderSwitchCase(
19281892
1929 if (switch_case.payload_token) |payload_token| {1893 if (switch_case.payload_token) |payload_token| {
1930 try renderToken(r, payload_token - 1, .none); // pipe1894 try renderToken(r, payload_token - 1, .none); // pipe
1931 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);1895 const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk);
1932 if (token_tags[payload_token] == .asterisk) {1896 if (tree.tokenTag(payload_token) == .asterisk) {
1933 try renderToken(r, payload_token, .none); // asterisk1897 try renderToken(r, payload_token, .none); // asterisk
1934 }1898 }
1935 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier1899 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1936 if (token_tags[ident + 1] == .comma) {1900 if (tree.tokenTag(ident + 1) == .comma) {
1937 try renderToken(r, ident + 1, .space); // ,1901 try renderToken(r, ident + 1, .space); // ,
1938 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier1902 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
1939 try renderToken(r, ident + 3, pre_target_space); // pipe1903 try renderToken(r, ident + 3, pre_target_space); // pipe
...@@ -1953,12 +1917,9 @@ fn renderBlock(...@@ -1953,12 +1917,9 @@ fn renderBlock(
1953) Error!void {1917) Error!void {
1954 const tree = r.tree;1918 const tree = r.tree;
1955 const ais = r.ais;1919 const ais = r.ais;
1956 const token_tags = tree.tokens.items(.tag);1920 const lbrace = tree.nodeMainToken(block_node);
1957 const lbrace = tree.nodes.items(.main_token)[block_node];
19581921
1959 if (token_tags[lbrace - 1] == .colon and1922 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
1960 token_tags[lbrace - 2] == .identifier)
1961 {
1962 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier1923 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
1963 try renderToken(r, lbrace - 1, .space); // :1924 try renderToken(r, lbrace - 1, .space); // :
1964 }1925 }
...@@ -1980,13 +1941,12 @@ fn finishRenderBlock(...@@ -1980,13 +1941,12 @@ fn finishRenderBlock(
1980 space: Space,1941 space: Space,
1981) Error!void {1942) Error!void {
1982 const tree = r.tree;1943 const tree = r.tree;
1983 const node_tags = tree.nodes.items(.tag);
1984 const ais = r.ais;1944 const ais = r.ais;
1985 for (statements, 0..) |stmt, i| {1945 for (statements, 0..) |stmt, i| {
1986 if (i != 0) try renderExtraNewline(r, stmt);1946 if (i != 0) try renderExtraNewline(r, stmt);
1987 if (r.fixups.omit_nodes.contains(stmt)) continue;1947 if (r.fixups.omit_nodes.contains(stmt)) continue;
1988 try ais.pushSpace(.semicolon);1948 try ais.pushSpace(.semicolon);
1989 switch (node_tags[stmt]) {1949 switch (tree.nodeTag(stmt)) {
1990 .global_var_decl,1950 .global_var_decl,
1991 .local_var_decl,1951 .local_var_decl,
1992 .simple_var_decl,1952 .simple_var_decl,
...@@ -2010,12 +1970,13 @@ fn renderStructInit(...@@ -2010,12 +1970,13 @@ fn renderStructInit(
2010) Error!void {1970) Error!void {
2011 const tree = r.tree;1971 const tree = r.tree;
2012 const ais = r.ais;1972 const ais = r.ais;
2013 const token_tags = tree.tokens.items(.tag);1973
2014 if (struct_init.ast.type_expr == 0) {1974 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
2015 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .1975 try renderExpression(r, type_expr, .none); // T
2016 } else {1976 } else {
2017 try renderExpression(r, struct_init.ast.type_expr, .none); // T1977 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
2018 }1978 }
1979
2019 if (struct_init.ast.fields.len == 0) {1980 if (struct_init.ast.fields.len == 0) {
2020 try ais.pushIndent(.normal);1981 try ais.pushIndent(.normal);
2021 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace1982 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
...@@ -2024,7 +1985,7 @@ fn renderStructInit(...@@ -2024,7 +1985,7 @@ fn renderStructInit(
2024 }1985 }
20251986
2026 const rbrace = tree.lastToken(struct_node);1987 const rbrace = tree.lastToken(struct_node);
2027 const trailing_comma = token_tags[rbrace - 1] == .comma;1988 const trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
2028 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {1989 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
2029 // Render one field init per line.1990 // Render one field init per line.
2030 try ais.pushIndent(.normal);1991 try ais.pushIndent(.normal);
...@@ -2034,9 +1995,8 @@ fn renderStructInit(...@@ -2034,9 +1995,8 @@ fn renderStructInit(
2034 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name1995 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
2035 // Don't output a space after the = if expression is a multiline string,1996 // Don't output a space after the = if expression is a multiline string,
2036 // since then it will start on the next line.1997 // since then it will start on the next line.
2037 const nodes = tree.nodes.items(.tag);
2038 const field_node = struct_init.ast.fields[0];1998 const field_node = struct_init.ast.fields[0];
2039 const expr = nodes[field_node];1999 const expr = tree.nodeTag(field_node);
2040 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;2000 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
2041 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =2001 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
20422002
...@@ -2049,7 +2009,7 @@ fn renderStructInit(...@@ -2049,7 +2009,7 @@ fn renderStructInit(
2049 try renderExtraNewlineToken(r, init_token - 3);2009 try renderExtraNewlineToken(r, init_token - 3);
2050 try renderToken(r, init_token - 3, .none); // .2010 try renderToken(r, init_token - 3, .none); // .
2051 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name2011 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
2052 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;2012 space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
2053 try renderToken(r, init_token - 1, space_after_equal); // =2013 try renderToken(r, init_token - 1, space_after_equal); // =
20542014
2055 try ais.pushSpace(.comma);2015 try ais.pushSpace(.comma);
...@@ -2082,12 +2042,11 @@ fn renderArrayInit(...@@ -2082,12 +2042,11 @@ fn renderArrayInit(
2082 const tree = r.tree;2042 const tree = r.tree;
2083 const ais = r.ais;2043 const ais = r.ais;
2084 const gpa = r.gpa;2044 const gpa = r.gpa;
2085 const token_tags = tree.tokens.items(.tag);
20862045
2087 if (array_init.ast.type_expr == 0) {2046 if (array_init.ast.type_expr.unwrap()) |type_expr| {
2088 try renderToken(r, array_init.ast.lbrace - 1, .none); // .2047 try renderExpression(r, type_expr, .none); // T
2089 } else {2048 } else {
2090 try renderExpression(r, array_init.ast.type_expr, .none); // T2049 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
2091 }2050 }
20922051
2093 if (array_init.ast.elements.len == 0) {2052 if (array_init.ast.elements.len == 0) {
...@@ -2099,14 +2058,14 @@ fn renderArrayInit(...@@ -2099,14 +2058,14 @@ fn renderArrayInit(
20992058
2100 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];2059 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
2101 const last_elem_token = tree.lastToken(last_elem);2060 const last_elem_token = tree.lastToken(last_elem);
2102 const trailing_comma = token_tags[last_elem_token + 1] == .comma;2061 const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma;
2103 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;2062 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;
2104 assert(token_tags[rbrace] == .r_brace);2063 assert(tree.tokenTag(rbrace) == .r_brace);
21052064
2106 if (array_init.ast.elements.len == 1) {2065 if (array_init.ast.elements.len == 1) {
2107 const only_elem = array_init.ast.elements[0];2066 const only_elem = array_init.ast.elements[0];
2108 const first_token = tree.firstToken(only_elem);2067 const first_token = tree.firstToken(only_elem);
2109 if (token_tags[first_token] != .multiline_string_literal_line and2068 if (tree.tokenTag(first_token) != .multiline_string_literal_line and
2110 !anythingBetween(tree, last_elem_token, rbrace))2069 !anythingBetween(tree, last_elem_token, rbrace))
2111 {2070 {
2112 try renderToken(r, array_init.ast.lbrace, .none);2071 try renderToken(r, array_init.ast.lbrace, .none);
...@@ -2169,7 +2128,7 @@ fn renderArrayInit(...@@ -2169,7 +2128,7 @@ fn renderArrayInit(
2169 }2128 }
21702129
2171 const maybe_comma = expr_last_token + 1;2130 const maybe_comma = expr_last_token + 1;
2172 if (token_tags[maybe_comma] == .comma) {2131 if (tree.tokenTag(maybe_comma) == .comma) {
2173 if (hasSameLineComment(tree, maybe_comma))2132 if (hasSameLineComment(tree, maybe_comma))
2174 break :sec_end i - this_line_size + 1;2133 break :sec_end i - this_line_size + 1;
2175 }2134 }
...@@ -2309,13 +2268,12 @@ fn renderContainerDecl(...@@ -2309,13 +2268,12 @@ fn renderContainerDecl(
2309) Error!void {2268) Error!void {
2310 const tree = r.tree;2269 const tree = r.tree;
2311 const ais = r.ais;2270 const ais = r.ais;
2312 const token_tags = tree.tokens.items(.tag);
23132271
2314 if (container_decl.layout_token) |layout_token| {2272 if (container_decl.layout_token) |layout_token| {
2315 try renderToken(r, layout_token, .space);2273 try renderToken(r, layout_token, .space);
2316 }2274 }
23172275
2318 const container: Container = switch (token_tags[container_decl.ast.main_token]) {2276 const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) {
2319 .keyword_enum => .@"enum",2277 .keyword_enum => .@"enum",
2320 .keyword_struct => for (container_decl.ast.members) |member| {2278 .keyword_struct => for (container_decl.ast.members) |member| {
2321 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;2279 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
...@@ -2328,10 +2286,10 @@ fn renderContainerDecl(...@@ -2328,10 +2286,10 @@ fn renderContainerDecl(
2328 try renderToken(r, container_decl.ast.main_token, .none); // union2286 try renderToken(r, container_decl.ast.main_token, .none); // union
2329 try renderToken(r, enum_token - 1, .none); // lparen2287 try renderToken(r, enum_token - 1, .none); // lparen
2330 try renderToken(r, enum_token, .none); // enum2288 try renderToken(r, enum_token, .none); // enum
2331 if (container_decl.ast.arg != 0) {2289 if (container_decl.ast.arg.unwrap()) |arg| {
2332 try renderToken(r, enum_token + 1, .none); // lparen2290 try renderToken(r, enum_token + 1, .none); // lparen
2333 try renderExpression(r, container_decl.ast.arg, .none);2291 try renderExpression(r, arg, .none);
2334 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2292 const rparen = tree.lastToken(arg) + 1;
2335 try renderToken(r, rparen, .none); // rparen2293 try renderToken(r, rparen, .none); // rparen
2336 try renderToken(r, rparen + 1, .space); // rparen2294 try renderToken(r, rparen + 1, .space); // rparen
2337 lbrace = rparen + 2;2295 lbrace = rparen + 2;
...@@ -2339,11 +2297,11 @@ fn renderContainerDecl(...@@ -2339,11 +2297,11 @@ fn renderContainerDecl(
2339 try renderToken(r, enum_token + 1, .space); // rparen2297 try renderToken(r, enum_token + 1, .space); // rparen
2340 lbrace = enum_token + 2;2298 lbrace = enum_token + 2;
2341 }2299 }
2342 } else if (container_decl.ast.arg != 0) {2300 } else if (container_decl.ast.arg.unwrap()) |arg| {
2343 try renderToken(r, container_decl.ast.main_token, .none); // union2301 try renderToken(r, container_decl.ast.main_token, .none); // union
2344 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen2302 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2345 try renderExpression(r, container_decl.ast.arg, .none);2303 try renderExpression(r, arg, .none);
2346 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2304 const rparen = tree.lastToken(arg) + 1;
2347 try renderToken(r, rparen, .space); // rparen2305 try renderToken(r, rparen, .space); // rparen
2348 lbrace = rparen + 1;2306 lbrace = rparen + 1;
2349 } else {2307 } else {
...@@ -2352,9 +2310,10 @@ fn renderContainerDecl(...@@ -2352,9 +2310,10 @@ fn renderContainerDecl(
2352 }2310 }
23532311
2354 const rbrace = tree.lastToken(container_decl_node);2312 const rbrace = tree.lastToken(container_decl_node);
2313
2355 if (container_decl.ast.members.len == 0) {2314 if (container_decl.ast.members.len == 0) {
2356 try ais.pushIndent(.normal);2315 try ais.pushIndent(.normal);
2357 if (token_tags[lbrace + 1] == .container_doc_comment) {2316 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
2358 try renderToken(r, lbrace, .newline); // lbrace2317 try renderToken(r, lbrace, .newline); // lbrace
2359 try renderContainerDocComments(r, lbrace + 1);2318 try renderContainerDocComments(r, lbrace + 1);
2360 } else {2319 } else {
...@@ -2364,7 +2323,7 @@ fn renderContainerDecl(...@@ -2364,7 +2323,7 @@ fn renderContainerDecl(
2364 return renderToken(r, rbrace, space); // rbrace2323 return renderToken(r, rbrace, space); // rbrace
2365 }2324 }
23662325
2367 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;2326 const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
2368 if (!src_has_trailing_comma) one_line: {2327 if (!src_has_trailing_comma) one_line: {
2369 // We print all the members in-line unless one of the following conditions are true:2328 // We print all the members in-line unless one of the following conditions are true:
23702329
...@@ -2374,10 +2333,10 @@ fn renderContainerDecl(...@@ -2374,10 +2333,10 @@ fn renderContainerDecl(
2374 }2333 }
23752334
2376 // 2. The container has a container comment.2335 // 2. The container has a container comment.
2377 if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line;2336 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line;
23782337
2379 // 3. A member of the container has a doc comment.2338 // 3. A member of the container has a doc comment.
2380 for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| {2339 for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| {
2381 if (tag == .doc_comment) break :one_line;2340 if (tag == .doc_comment) break :one_line;
2382 }2341 }
23832342
...@@ -2397,12 +2356,12 @@ fn renderContainerDecl(...@@ -2397,12 +2356,12 @@ fn renderContainerDecl(
2397 // One member per line.2356 // One member per line.
2398 try ais.pushIndent(.normal);2357 try ais.pushIndent(.normal);
2399 try renderToken(r, lbrace, .newline); // lbrace2358 try renderToken(r, lbrace, .newline); // lbrace
2400 if (token_tags[lbrace + 1] == .container_doc_comment) {2359 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
2401 try renderContainerDocComments(r, lbrace + 1);2360 try renderContainerDocComments(r, lbrace + 1);
2402 }2361 }
2403 for (container_decl.ast.members, 0..) |member, i| {2362 for (container_decl.ast.members, 0..) |member, i| {
2404 if (i != 0) try renderExtraNewline(r, member);2363 if (i != 0) try renderExtraNewline(r, member);
2405 switch (tree.nodes.items(.tag)[member]) {2364 switch (tree.nodeTag(member)) {
2406 // For container fields, ensure a trailing comma is added if necessary.2365 // For container fields, ensure a trailing comma is added if necessary.
2407 .container_field_init,2366 .container_field_init,
2408 .container_field_align,2367 .container_field_align,
...@@ -2428,7 +2387,6 @@ fn renderAsm(...@@ -2428,7 +2387,6 @@ fn renderAsm(
2428) Error!void {2387) Error!void {
2429 const tree = r.tree;2388 const tree = r.tree;
2430 const ais = r.ais;2389 const ais = r.ais;
2431 const token_tags = tree.tokens.items(.tag);
24322390
2433 try renderToken(r, asm_node.ast.asm_token, .space); // asm2391 try renderToken(r, asm_node.ast.asm_token, .space); // asm
24342392
...@@ -2454,13 +2412,13 @@ fn renderAsm(...@@ -2454,13 +2412,13 @@ fn renderAsm(
2454 while (true) : (tok_i += 1) {2412 while (true) : (tok_i += 1) {
2455 try renderToken(r, tok_i, .none);2413 try renderToken(r, tok_i, .none);
2456 tok_i += 1;2414 tok_i += 1;
2457 switch (token_tags[tok_i]) {2415 switch (tree.tokenTag(tok_i)) {
2458 .r_paren => {2416 .r_paren => {
2459 ais.popIndent();2417 ais.popIndent();
2460 return renderToken(r, tok_i, space);2418 return renderToken(r, tok_i, space);
2461 },2419 },
2462 .comma => {2420 .comma => {
2463 if (token_tags[tok_i + 1] == .r_paren) {2421 if (tree.tokenTag(tok_i + 1) == .r_paren) {
2464 ais.popIndent();2422 ais.popIndent();
2465 return renderToken(r, tok_i + 1, space);2423 return renderToken(r, tok_i + 1, space);
2466 } else {2424 } else {
...@@ -2512,7 +2470,7 @@ fn renderAsm(...@@ -2512,7 +2470,7 @@ fn renderAsm(
2512 ais.popSpace();2470 ais.popSpace();
2513 const comma_or_colon = tree.lastToken(asm_output) + 1;2471 const comma_or_colon = tree.lastToken(asm_output) + 1;
2514 ais.popIndent();2472 ais.popIndent();
2515 break :colon2 switch (token_tags[comma_or_colon]) {2473 break :colon2 switch (tree.tokenTag(comma_or_colon)) {
2516 .comma => comma_or_colon + 1,2474 .comma => comma_or_colon + 1,
2517 else => comma_or_colon,2475 else => comma_or_colon,
2518 };2476 };
...@@ -2548,7 +2506,7 @@ fn renderAsm(...@@ -2548,7 +2506,7 @@ fn renderAsm(
2548 ais.popSpace();2506 ais.popSpace();
2549 const comma_or_colon = tree.lastToken(asm_input) + 1;2507 const comma_or_colon = tree.lastToken(asm_input) + 1;
2550 ais.popIndent();2508 ais.popIndent();
2551 break :colon3 switch (token_tags[comma_or_colon]) {2509 break :colon3 switch (tree.tokenTag(comma_or_colon)) {
2552 .comma => comma_or_colon + 1,2510 .comma => comma_or_colon + 1,
2553 else => comma_or_colon,2511 else => comma_or_colon,
2554 };2512 };
...@@ -2561,7 +2519,7 @@ fn renderAsm(...@@ -2561,7 +2519,7 @@ fn renderAsm(
2561 const first_clobber = asm_node.first_clobber.?;2519 const first_clobber = asm_node.first_clobber.?;
2562 var tok_i = first_clobber;2520 var tok_i = first_clobber;
2563 while (true) {2521 while (true) {
2564 switch (token_tags[tok_i + 1]) {2522 switch (tree.tokenTag(tok_i + 1)) {
2565 .r_paren => {2523 .r_paren => {
2566 ais.setIndentDelta(indent_delta);2524 ais.setIndentDelta(indent_delta);
2567 try renderToken(r, tok_i, .newline);2525 try renderToken(r, tok_i, .newline);
...@@ -2569,7 +2527,7 @@ fn renderAsm(...@@ -2569,7 +2527,7 @@ fn renderAsm(
2569 return renderToken(r, tok_i + 1, space);2527 return renderToken(r, tok_i + 1, space);
2570 },2528 },
2571 .comma => {2529 .comma => {
2572 switch (token_tags[tok_i + 2]) {2530 switch (tree.tokenTag(tok_i + 2)) {
2573 .r_paren => {2531 .r_paren => {
2574 ais.setIndentDelta(indent_delta);2532 ais.setIndentDelta(indent_delta);
2575 try renderToken(r, tok_i, .newline);2533 try renderToken(r, tok_i, .newline);
...@@ -2608,7 +2566,6 @@ fn renderParamList(...@@ -2608,7 +2566,6 @@ fn renderParamList(
2608) Error!void {2566) Error!void {
2609 const tree = r.tree;2567 const tree = r.tree;
2610 const ais = r.ais;2568 const ais = r.ais;
2611 const token_tags = tree.tokens.items(.tag);
26122569
2613 if (params.len == 0) {2570 if (params.len == 0) {
2614 try ais.pushIndent(.normal);2571 try ais.pushIndent(.normal);
...@@ -2619,7 +2576,7 @@ fn renderParamList(...@@ -2619,7 +2576,7 @@ fn renderParamList(
26192576
2620 const last_param = params[params.len - 1];2577 const last_param = params[params.len - 1];
2621 const after_last_param_tok = tree.lastToken(last_param) + 1;2578 const after_last_param_tok = tree.lastToken(last_param) + 1;
2622 if (token_tags[after_last_param_tok] == .comma) {2579 if (tree.tokenTag(after_last_param_tok) == .comma) {
2623 try ais.pushIndent(.normal);2580 try ais.pushIndent(.normal);
2624 try renderToken(r, lparen, .newline); // (2581 try renderToken(r, lparen, .newline); // (
2625 for (params, 0..) |param_node, i| {2582 for (params, 0..) |param_node, i| {
...@@ -2648,7 +2605,7 @@ fn renderParamList(...@@ -2648,7 +2605,7 @@ fn renderParamList(
2648 if (i + 1 < params.len) {2605 if (i + 1 < params.len) {
2649 const comma = tree.lastToken(param_node) + 1;2606 const comma = tree.lastToken(param_node) + 1;
2650 const next_multiline_string =2607 const next_multiline_string =
2651 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;2608 tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line;
2652 const comma_space: Space = if (next_multiline_string) .none else .space;2609 const comma_space: Space = if (next_multiline_string) .none else .space;
2653 try renderToken(r, comma, comma_space);2610 try renderToken(r, comma, comma_space);
2654 }2611 }
...@@ -2661,9 +2618,8 @@ fn renderParamList(...@@ -2661,9 +2618,8 @@ fn renderParamList(
2661/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2618/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2662fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {2619fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
2663 const tree = r.tree;2620 const tree = r.tree;
2664 const token_tags = tree.tokens.items(.tag);
2665 const maybe_comma = tree.lastToken(node) + 1;2621 const maybe_comma = tree.lastToken(node) + 1;
2666 if (token_tags[maybe_comma] == .comma and space != .comma) {2622 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2667 try renderExpression(r, node, .none);2623 try renderExpression(r, node, .none);
2668 return renderToken(r, maybe_comma, space);2624 return renderToken(r, maybe_comma, space);
2669 } else {2625 } else {
...@@ -2675,9 +2631,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v...@@ -2675,9 +2631,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v
2675/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2631/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2676fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {2632fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
2677 const tree = r.tree;2633 const tree = r.tree;
2678 const token_tags = tree.tokens.items(.tag);
2679 const maybe_comma = token + 1;2634 const maybe_comma = token + 1;
2680 if (token_tags[maybe_comma] == .comma and space != .comma) {2635 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2681 try renderToken(r, token, .none);2636 try renderToken(r, token, .none);
2682 return renderToken(r, maybe_comma, space);2637 return renderToken(r, maybe_comma, space);
2683 } else {2638 } else {
...@@ -2689,9 +2644,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void...@@ -2689,9 +2644,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void
2689/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2644/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2690fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2645fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2691 const tree = r.tree;2646 const tree = r.tree;
2692 const token_tags = tree.tokens.items(.tag);
2693 const maybe_comma = token + 1;2647 const maybe_comma = token + 1;
2694 if (token_tags[maybe_comma] == .comma and space != .comma) {2648 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2695 try renderIdentifier(r, token, .none, quote);2649 try renderIdentifier(r, token, .none, quote);
2696 return renderToken(r, maybe_comma, space);2650 return renderToken(r, maybe_comma, space);
2697 } else {2651 } else {
...@@ -2741,37 +2695,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:...@@ -2741,37 +2695,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
2741fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {2695fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2742 const tree = r.tree;2696 const tree = r.tree;
2743 const ais = r.ais;2697 const ais = r.ais;
2744 const token_tags = tree.tokens.items(.tag);
2745 const token_starts = tree.tokens.items(.start);
27462698
2747 const token_start = token_starts[token_index];2699 const next_token_tag = tree.tokenTag(token_index + 1);
27482700
2749 if (space == .skip) return;2701 if (space == .skip) return;
27502702
2751 if (space == .comma and token_tags[token_index + 1] != .comma) {2703 if (space == .comma and next_token_tag != .comma) {
2752 try ais.writer().writeByte(',');2704 try ais.writer().writeByte(',');
2753 }2705 }
2754 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);2706 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
2755 defer ais.disableSpaceMode();2707 defer ais.disableSpaceMode();
2756 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);2708 const comment = try renderComments(
2709 r,
2710 tree.tokenStart(token_index) + lexeme_len,
2711 tree.tokenStart(token_index + 1),
2712 );
2757 switch (space) {2713 switch (space) {
2758 .none => {},2714 .none => {},
2759 .space => if (!comment) try ais.writer().writeByte(' '),2715 .space => if (!comment) try ais.writer().writeByte(' '),
2760 .newline => if (!comment) try ais.insertNewline(),2716 .newline => if (!comment) try ais.insertNewline(),
27612717
2762 .comma => if (token_tags[token_index + 1] == .comma) {2718 .comma => if (next_token_tag == .comma) {
2763 try renderToken(r, token_index + 1, .newline);2719 try renderToken(r, token_index + 1, .newline);
2764 } else if (!comment) {2720 } else if (!comment) {
2765 try ais.insertNewline();2721 try ais.insertNewline();
2766 },2722 },
27672723
2768 .comma_space => if (token_tags[token_index + 1] == .comma) {2724 .comma_space => if (next_token_tag == .comma) {
2769 try renderToken(r, token_index + 1, .space);2725 try renderToken(r, token_index + 1, .space);
2770 } else if (!comment) {2726 } else if (!comment) {
2771 try ais.writer().writeByte(' ');2727 try ais.writer().writeByte(' ');
2772 },2728 },
27732729
2774 .semicolon => if (token_tags[token_index + 1] == .semicolon) {2730 .semicolon => if (next_token_tag == .semicolon) {
2775 try renderToken(r, token_index + 1, .newline);2731 try renderToken(r, token_index + 1, .newline);
2776 } else if (!comment) {2732 } else if (!comment) {
2777 try ais.insertNewline();2733 try ais.insertNewline();
...@@ -2802,8 +2758,7 @@ const QuoteBehavior = enum {...@@ -2802,8 +2758,7 @@ const QuoteBehavior = enum {
28022758
2803fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2759fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2804 const tree = r.tree;2760 const tree = r.tree;
2805 const token_tags = tree.tokens.items(.tag);2761 assert(tree.tokenTag(token_index) == .identifier);
2806 assert(token_tags[token_index] == .identifier);
2807 const lexeme = tokenSliceForRender(tree, token_index);2762 const lexeme = tokenSliceForRender(tree, token_index);
28082763
2809 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {2764 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
...@@ -2912,8 +2867,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote...@@ -2912,8 +2867,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote
2912fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {2867fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
2913 const tree = r.tree;2868 const tree = r.tree;
2914 const ais = r.ais;2869 const ais = r.ais;
2915 const token_tags = tree.tokens.items(.tag);2870 assert(tree.tokenTag(token_index) == .identifier);
2916 assert(token_tags[token_index] == .identifier);
2917 const lexeme = tokenSliceForRender(tree, token_index);2871 const lexeme = tokenSliceForRender(tree, token_index);
2918 assert(lexeme.len >= 3 and lexeme[0] == '@');2872 assert(lexeme.len >= 3 and lexeme[0] == '@');
29192873
...@@ -2966,12 +2920,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {...@@ -2966,12 +2920,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
2966/// fn_proto should be wrapped and have a trailing comma inserted even if2920/// fn_proto should be wrapped and have a trailing comma inserted even if
2967/// there is none in the source.2921/// there is none in the source.
2968fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {2922fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2969 const token_starts = tree.tokens.items(.start);2923 for (start_token..end_token) |i| {
29702924 const token: Ast.TokenIndex = @intCast(i);
2971 var i = start_token;2925 const start = tree.tokenStart(token) + tree.tokenSlice(token).len;
2972 while (i < end_token) : (i += 1) {2926 const end = tree.tokenStart(token + 1);
2973 const start = token_starts[i] + tree.tokenSlice(i).len;
2974 const end = token_starts[i + 1];
2975 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;2927 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;
2976 }2928 }
29772929
...@@ -2981,16 +2933,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)...@@ -2981,16 +2933,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)
2981/// Returns true if there exists a multiline string literal between the start2933/// Returns true if there exists a multiline string literal between the start
2982/// of token `start_token` and the start of token `end_token`.2934/// of token `start_token` and the start of token `end_token`.
2983fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {2935fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2984 const token_tags = tree.tokens.items(.tag);2936 return std.mem.indexOfScalar(
29852937 Token.Tag,
2986 for (token_tags[start_token..end_token]) |tag| {2938 tree.tokens.items(.tag)[start_token..end_token],
2987 switch (tag) {2939 .multiline_string_literal_line,
2988 .multiline_string_literal_line => return true,2940 ) != null;
2989 else => continue,
2990 }
2991 }
2992
2993 return false;
2994}2941}
29952942
2996/// Assumes that start is the first byte past the previous token and2943/// Assumes that start is the first byte past the previous token and
...@@ -3066,18 +3013,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {...@@ -3066,18 +3013,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
3066fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {3013fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
3067 const tree = r.tree;3014 const tree = r.tree;
3068 const ais = r.ais;3015 const ais = r.ais;
3069 const token_starts = tree.tokens.items(.start);3016 const token_start = tree.tokenStart(token_index);
3070 const token_start = token_starts[token_index];
3071 if (token_start == 0) return;3017 if (token_start == 0) return;
3072 const prev_token_end = if (token_index == 0)3018 const prev_token_end = if (token_index == 0)
3073 03019 0
3074 else3020 else
3075 token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len;3021 tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len;
30763022
3077 // If there is a immediately preceding comment or doc_comment,3023 // If there is a immediately preceding comment or doc_comment,
3078 // skip it because required extra newline has already been rendered.3024 // skip it because required extra newline has already been rendered.
3079 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;3025 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;
3080 if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return;3026 if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return;
30813027
3082 // Iterate backwards to the end of the previous token, stopping if a3028 // Iterate backwards to the end of the previous token, stopping if a
3083 // non-whitespace character is encountered or two newlines have been found.3029 // non-whitespace character is encountered or two newlines have been found.
...@@ -3095,10 +3041,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {...@@ -3095,10 +3041,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
3095fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {3041fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3096 const tree = r.tree;3042 const tree = r.tree;
3097 // Search backwards for the first doc comment.3043 // Search backwards for the first doc comment.
3098 const token_tags = tree.tokens.items(.tag);
3099 if (end_token == 0) return;3044 if (end_token == 0) return;
3100 var tok = end_token - 1;3045 var tok = end_token - 1;
3101 while (token_tags[tok] == .doc_comment) {3046 while (tree.tokenTag(tok) == .doc_comment) {
3102 if (tok == 0) break;3047 if (tok == 0) break;
3103 tok -= 1;3048 tok -= 1;
3104 } else {3049 } else {
...@@ -3108,7 +3053,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3108,7 +3053,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3108 if (first_tok == end_token) return;3053 if (first_tok == end_token) return;
31093054
3110 if (first_tok != 0) {3055 if (first_tok != 0) {
3111 const prev_token_tag = token_tags[first_tok - 1];3056 const prev_token_tag = tree.tokenTag(first_tok - 1);
31123057
3113 // Prevent accidental use of `renderDocComments` for a function argument doc comment3058 // Prevent accidental use of `renderDocComments` for a function argument doc comment
3114 assert(prev_token_tag != .l_paren);3059 assert(prev_token_tag != .l_paren);
...@@ -3118,7 +3063,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3118,7 +3063,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3118 }3063 }
3119 }3064 }
31203065
3121 while (token_tags[tok] == .doc_comment) : (tok += 1) {3066 while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) {
3122 try renderToken(r, tok, .newline);3067 try renderToken(r, tok, .newline);
3123 }3068 }
3124}3069}
...@@ -3126,15 +3071,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3126,15 +3071,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3126/// start_token is first container doc comment token.3071/// start_token is first container doc comment token.
3127fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {3072fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
3128 const tree = r.tree;3073 const tree = r.tree;
3129 const token_tags = tree.tokens.items(.tag);
3130 var tok = start_token;3074 var tok = start_token;
3131 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {3075 while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
3132 try renderToken(r, tok, .newline);3076 try renderToken(r, tok, .newline);
3133 }3077 }
3134 // Render extra newline if there is one between final container doc comment and3078 // Render extra newline if there is one between final container doc comment and
3135 // the next token. If the next token is a doc comment, that code path3079 // the next token. If the next token is a doc comment, that code path
3136 // will have its own logic to insert a newline.3080 // will have its own logic to insert a newline.
3137 if (token_tags[tok] != .doc_comment) {3081 if (tree.tokenTag(tok) != .doc_comment) {
3138 try renderExtraNewlineToken(r, tok);3082 try renderExtraNewlineToken(r, tok);
3139 }3083 }
3140}3084}
...@@ -3144,11 +3088,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {...@@ -3144,11 +3088,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
3144 const ais = r.ais;3088 const ais = r.ais;
3145 var buf: [1]Ast.Node.Index = undefined;3089 var buf: [1]Ast.Node.Index = undefined;
3146 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;3090 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;
3147 const token_tags = tree.tokens.items(.tag);
3148 var it = fn_proto.iterate(tree);3091 var it = fn_proto.iterate(tree);
3149 while (it.next()) |param| {3092 while (it.next()) |param| {
3150 const name_ident = param.name_token.?;3093 const name_ident = param.name_token.?;
3151 assert(token_tags[name_ident] == .identifier);3094 assert(tree.tokenTag(name_ident) == .identifier);
3152 const w = ais.writer();3095 const w = ais.writer();
3153 try w.writeAll("_ = ");3096 try w.writeAll("_ = ");
3154 try w.writeAll(tokenSliceForRender(r.tree, name_ident));3097 try w.writeAll(tokenSliceForRender(r.tree, name_ident));
...@@ -3158,7 +3101,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {...@@ -3158,7 +3101,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31583101
3159fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {3102fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3160 var ret = tree.tokenSlice(token_index);3103 var ret = tree.tokenSlice(token_index);
3161 switch (tree.tokens.items(.tag)[token_index]) {3104 switch (tree.tokenTag(token_index)) {
3162 .container_doc_comment, .doc_comment => {3105 .container_doc_comment, .doc_comment => {
3163 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);3106 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);
3164 },3107 },
...@@ -3168,8 +3111,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {...@@ -3168,8 +3111,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3168}3111}
31693112
3170fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {3113fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3171 const token_starts = tree.tokens.items(.start);3114 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
3172 const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]];
3173 for (between_source) |byte| switch (byte) {3115 for (between_source) |byte| switch (byte) {
3174 '\n' => return false,3116 '\n' => return false,
3175 '/' => return true,3117 '/' => return true,
...@@ -3182,8 +3124,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {...@@ -3182,8 +3124,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3182/// start_token and end_token.3124/// start_token and end_token.
3183fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {3125fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
3184 if (start_token + 1 != end_token) return true;3126 if (start_token + 1 != end_token) return true;
3185 const token_starts = tree.tokens.items(.start);3127 const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)];
3186 const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]];
3187 for (between_source) |byte| switch (byte) {3128 for (between_source) |byte| switch (byte) {
3188 '/' => return true,3129 '/' => return true,
3189 else => continue,3130 else => continue,
...@@ -3277,12 +3218,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {...@@ -3277,12 +3218,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {
32773218
3278// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.3219// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.
3279fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {3220fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {
3280 const token_tags = tree.tokens.items(.tag);
3281
3282 const first_token = tree.firstToken(exprs[0]);3221 const first_token = tree.firstToken(exprs[0]);
3283 if (tree.tokensOnSameLine(first_token, rtoken)) {3222 if (tree.tokensOnSameLine(first_token, rtoken)) {
3284 const maybe_comma = rtoken - 1;3223 const maybe_comma = rtoken - 1;
3285 if (token_tags[maybe_comma] == .comma)3224 if (tree.tokenTag(maybe_comma) == .comma)
3286 return 1;3225 return 1;
3287 return exprs.len; // no newlines3226 return exprs.len; // no newlines
3288 }3227 }
lib/std/zon/parse.zig+11-17
...@@ -196,16 +196,15 @@ pub const Error = union(enum) {...@@ -196,16 +196,15 @@ pub const Error = union(enum) {
196 return .{ .err = self, .status = status };196 return .{ .err = self, .status = status };
197 }197 }
198198
199 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.TokenIndex, node_or_offset: u32) Ast.Location {199 fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location {
200 if (maybe_token == Zoir.CompileError.invalid_token) {200 if (maybe_token.unwrap()) |token| {
201 const main_tokens = ast.nodes.items(.main_token);201 var location = ast.tokenLocation(0, 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);
207 location.column += node_or_offset;202 location.column += node_or_offset;
208 return location;203 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);
209 }208 }
210 }209 }
211};210};
...@@ -632,7 +631,7 @@ const Parser = struct {...@@ -632,7 +631,7 @@ const Parser = struct {
632 switch (try ZonGen.parseStrLit(self.ast, ast_node, buf.writer(self.gpa))) {631 switch (try ZonGen.parseStrLit(self.ast, ast_node, buf.writer(self.gpa))) {
633 .success => {},632 .success => {},
634 .failure => |err| {633 .failure => |err| {
635 const token = self.ast.nodes.items(.main_token)[ast_node];634 const token = self.ast.nodeMainToken(ast_node);
636 const raw_string = self.ast.tokenSlice(token);635 const raw_string = self.ast.tokenSlice(token);
637 return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)});636 return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)});
638 },637 },
...@@ -1005,8 +1004,7 @@ const Parser = struct {...@@ -1005,8 +1004,7 @@ const Parser = struct {
1005 args: anytype,1004 args: anytype,
1006 ) error{ OutOfMemory, ParseZon } {1005 ) error{ OutOfMemory, ParseZon } {
1007 @branchHint(.cold);1006 @branchHint(.cold);
1008 const main_tokens = self.ast.nodes.items(.main_token);1007 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
1009 const token = main_tokens[node.getAstNode(self.zoir)];
1010 return self.failTokenFmt(token, 0, fmt, args);1008 return self.failTokenFmt(token, 0, fmt, args);
1011 }1009 }
10121010
...@@ -1025,8 +1023,7 @@ const Parser = struct {...@@ -1025,8 +1023,7 @@ const Parser = struct {
1025 message: []const u8,1023 message: []const u8,
1026 ) error{ParseZon} {1024 ) error{ParseZon} {
1027 @branchHint(.cold);1025 @branchHint(.cold);
1028 const main_tokens = self.ast.nodes.items(.main_token);1026 const token = self.ast.nodeMainToken(node.getAstNode(self.zoir));
1029 const token = main_tokens[node.getAstNode(self.zoir)];
1030 return self.failToken(.{1027 return self.failToken(.{
1031 .token = token,1028 .token = token,
1032 .offset = 0,1029 .offset = 0,
...@@ -1059,10 +1056,7 @@ const Parser = struct {...@@ -1059,10 +1056,7 @@ const Parser = struct {
1059 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;1056 const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?;
1060 const field_node = struct_init.ast.fields[f];1057 const field_node = struct_init.ast.fields[f];
1061 break :b self.ast.firstToken(field_node) - 2;1058 break :b self.ast.firstToken(field_node) - 2;
1062 } else b: {1059 } else self.ast.nodeMainToken(node.getAstNode(self.zoir));
1063 const main_tokens = self.ast.nodes.items(.main_token);
1064 break :b main_tokens[node.getAstNode(self.zoir)];
1065 };
1066 switch (@typeInfo(T)) {1060 switch (@typeInfo(T)) {
1067 inline .@"struct", .@"union", .@"enum" => |info| {1061 inline .@"struct", .@"union", .@"enum" => |info| {
1068 const note: Error.TypeCheckFailure.Note = if (info.fields.len == 0) b: {1062 const note: Error.TypeCheckFailure.Note = if (info.fields.len == 0) b: {
src/Package/Fetch.zig+10-10
...@@ -30,7 +30,7 @@...@@ -30,7 +30,7 @@
30arena: std.heap.ArenaAllocator,30arena: std.heap.ArenaAllocator,
31location: Location,31location: Location,
32location_tok: std.zig.Ast.TokenIndex,32location_tok: std.zig.Ast.TokenIndex,
33hash_tok: std.zig.Ast.TokenIndex,33hash_tok: std.zig.Ast.OptionalTokenIndex,
34name_tok: std.zig.Ast.TokenIndex,34name_tok: std.zig.Ast.TokenIndex,
35lazy_status: LazyStatus,35lazy_status: LazyStatus,
36parent_package_root: Cache.Path,36parent_package_root: Cache.Path,
...@@ -317,8 +317,8 @@ pub fn run(f: *Fetch) RunError!void {...@@ -317,8 +317,8 @@ pub fn run(f: *Fetch) RunError!void {
317 f.location_tok,317 f.location_tok,
318 try eb.addString("expected path relative to build root; found absolute path"),318 try eb.addString("expected path relative to build root; found absolute path"),
319 );319 );
320 if (f.hash_tok != 0) return f.fail(320 if (f.hash_tok.unwrap()) |hash_tok| return f.fail(
321 f.hash_tok,321 hash_tok,
322 try eb.addString("path-based dependencies are not hashed"),322 try eb.addString("path-based dependencies are not hashed"),
323 );323 );
324 // Packages fetched by URL may not use relative paths to escape outside the324 // Packages fetched by URL may not use relative paths to escape outside the
...@@ -555,17 +555,18 @@ fn runResource(...@@ -555,17 +555,18 @@ fn runResource(
555 // job is done.555 // job is done.
556556
557 if (remote_hash) |declared_hash| {557 if (remote_hash) |declared_hash| {
558 const hash_tok = f.hash_tok.unwrap().?;
558 if (declared_hash.isOld()) {559 if (declared_hash.isOld()) {
559 const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest);560 const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest);
560 if (!std.mem.eql(u8, declared_hash.toSlice(), &actual_hex)) {561 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(
562 "hash mismatch: manifest declares {s} but the fetched package has {s}",563 "hash mismatch: manifest declares {s} but the fetched package has {s}",
563 .{ declared_hash.toSlice(), actual_hex },564 .{ declared_hash.toSlice(), actual_hex },
564 ));565 ));
565 }566 }
566 } else {567 } else {
567 if (!computed_package_hash.eql(&declared_hash)) {568 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(
569 "hash mismatch: manifest declares {s} but the fetched package has {s}",570 "hash mismatch: manifest declares {s} but the fetched package has {s}",
570 .{ declared_hash.toSlice(), computed_package_hash.toSlice() },571 .{ declared_hash.toSlice(), computed_package_hash.toSlice() },
571 ));572 ));
...@@ -813,15 +814,14 @@ fn srcLoc(...@@ -813,15 +814,14 @@ fn srcLoc(
813) Allocator.Error!ErrorBundle.SourceLocationIndex {814) Allocator.Error!ErrorBundle.SourceLocationIndex {
814 const ast = f.parent_manifest_ast orelse return .none;815 const ast = f.parent_manifest_ast orelse return .none;
815 const eb = &f.error_bundle;816 const eb = &f.error_bundle;
816 const token_starts = ast.tokens.items(.start);
817 const start_loc = ast.tokenLocation(0, tok);817 const start_loc = ast.tokenLocation(0, tok);
818 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});818 const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root});
819 const msg_off = 0;819 const msg_off = 0;
820 return eb.addSourceLocation(.{820 return eb.addSourceLocation(.{
821 .src_path = src_path,821 .src_path = src_path,
822 .span_start = token_starts[tok],822 .span_start = ast.tokenStart(tok),
823 .span_end = @intCast(token_starts[tok] + ast.tokenSlice(tok).len),823 .span_end = @intCast(ast.tokenStart(tok) + ast.tokenSlice(tok).len),
824 .span_main = token_starts[tok] + msg_off,824 .span_main = ast.tokenStart(tok) + msg_off,
825 .line = @intCast(start_loc.line),825 .line = @intCast(start_loc.line),
826 .column = @intCast(start_loc.column),826 .column = @intCast(start_loc.column),
827 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),827 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),
...@@ -2331,7 +2331,7 @@ const TestFetchBuilder = struct {...@@ -2331,7 +2331,7 @@ const TestFetchBuilder = struct {
2331 .arena = std.heap.ArenaAllocator.init(allocator),2331 .arena = std.heap.ArenaAllocator.init(allocator),
2332 .location = .{ .path_or_url = path_or_url },2332 .location = .{ .path_or_url = path_or_url },
2333 .location_tok = 0,2333 .location_tok = 0,
2334 .hash_tok = 0,2334 .hash_tok = .none,
2335 .name_tok = 0,2335 .name_tok = 0,
2336 .lazy_status = .eager,2336 .lazy_status = .eager,
2337 .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } },2337 .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 {...@@ -17,8 +17,8 @@ pub const Dependency = struct {
17 location_tok: Ast.TokenIndex,17 location_tok: Ast.TokenIndex,
18 location_node: Ast.Node.Index,18 location_node: Ast.Node.Index,
19 hash: ?[]const u8,19 hash: ?[]const u8,
20 hash_tok: Ast.TokenIndex,20 hash_tok: Ast.OptionalTokenIndex,
21 hash_node: Ast.Node.Index,21 hash_node: Ast.Node.OptionalIndex,
22 node: Ast.Node.Index,22 node: Ast.Node.Index,
23 name_tok: Ast.TokenIndex,23 name_tok: Ast.TokenIndex,
24 lazy: bool,24 lazy: bool,
...@@ -40,7 +40,7 @@ id: u32,...@@ -40,7 +40,7 @@ id: u32,
40version: std.SemanticVersion,40version: std.SemanticVersion,
41version_node: Ast.Node.Index,41version_node: Ast.Node.Index,
42dependencies: std.StringArrayHashMapUnmanaged(Dependency),42dependencies: std.StringArrayHashMapUnmanaged(Dependency),
43dependencies_node: Ast.Node.Index,43dependencies_node: Ast.Node.OptionalIndex,
44paths: std.StringArrayHashMapUnmanaged(void),44paths: std.StringArrayHashMapUnmanaged(void),
45minimum_zig_version: ?std.SemanticVersion,45minimum_zig_version: ?std.SemanticVersion,
4646
...@@ -58,10 +58,7 @@ pub const ParseOptions = struct {...@@ -58,10 +58,7 @@ pub const ParseOptions = struct {
58pub const Error = Allocator.Error;58pub const Error = Allocator.Error;
5959
60pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {60pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
61 const node_tags = ast.nodes.items(.tag);61 const main_node_index = ast.nodeData(.root).node;
62 const node_datas = ast.nodes.items(.data);
63 assert(node_tags[0] == .root);
64 const main_node_index = node_datas[0].lhs;
6562
66 var arena_instance = std.heap.ArenaAllocator.init(gpa);63 var arena_instance = std.heap.ArenaAllocator.init(gpa);
67 errdefer arena_instance.deinit();64 errdefer arena_instance.deinit();
...@@ -75,9 +72,9 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {...@@ -75,9 +72,9 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest {
75 .name = undefined,72 .name = undefined,
76 .id = 0,73 .id = 0,
77 .version = undefined,74 .version = undefined,
78 .version_node = 0,75 .version_node = undefined,
79 .dependencies = .{},76 .dependencies = .{},
80 .dependencies_node = 0,77 .dependencies_node = .none,
81 .paths = .{},78 .paths = .{},
82 .allow_missing_paths_field = options.allow_missing_paths_field,79 .allow_missing_paths_field = options.allow_missing_paths_field,
83 .allow_name_string = options.allow_name_string,80 .allow_name_string = options.allow_name_string,
...@@ -121,8 +118,6 @@ pub fn copyErrorsIntoBundle(...@@ -121,8 +118,6 @@ pub fn copyErrorsIntoBundle(
121 src_path: u32,118 src_path: u32,
122 eb: *std.zig.ErrorBundle.Wip,119 eb: *std.zig.ErrorBundle.Wip,
123) Allocator.Error!void {120) Allocator.Error!void {
124 const token_starts = ast.tokens.items(.start);
125
126 for (man.errors) |msg| {121 for (man.errors) |msg| {
127 const start_loc = ast.tokenLocation(0, msg.tok);122 const start_loc = ast.tokenLocation(0, msg.tok);
128123
...@@ -130,9 +125,9 @@ pub fn copyErrorsIntoBundle(...@@ -130,9 +125,9 @@ pub fn copyErrorsIntoBundle(
130 .msg = try eb.addString(msg.msg),125 .msg = try eb.addString(msg.msg),
131 .src_loc = try eb.addSourceLocation(.{126 .src_loc = try eb.addSourceLocation(.{
132 .src_path = src_path,127 .src_path = src_path,
133 .span_start = token_starts[msg.tok],128 .span_start = ast.tokenStart(msg.tok),
134 .span_end = @intCast(token_starts[msg.tok] + ast.tokenSlice(msg.tok).len),129 .span_end = @intCast(ast.tokenStart(msg.tok) + ast.tokenSlice(msg.tok).len),
135 .span_main = token_starts[msg.tok] + msg.off,130 .span_main = ast.tokenStart(msg.tok) + msg.off,
136 .line = @intCast(start_loc.line),131 .line = @intCast(start_loc.line),
137 .column = @intCast(start_loc.column),132 .column = @intCast(start_loc.column),
138 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),133 .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]),
...@@ -153,7 +148,7 @@ const Parse = struct {...@@ -153,7 +148,7 @@ const Parse = struct {
153 version: std.SemanticVersion,148 version: std.SemanticVersion,
154 version_node: Ast.Node.Index,149 version_node: Ast.Node.Index,
155 dependencies: std.StringArrayHashMapUnmanaged(Dependency),150 dependencies: std.StringArrayHashMapUnmanaged(Dependency),
156 dependencies_node: Ast.Node.Index,151 dependencies_node: Ast.Node.OptionalIndex,
157 paths: std.StringArrayHashMapUnmanaged(void),152 paths: std.StringArrayHashMapUnmanaged(void),
158 allow_missing_paths_field: bool,153 allow_missing_paths_field: bool,
159 allow_name_string: bool,154 allow_name_string: bool,
...@@ -164,8 +159,7 @@ const Parse = struct {...@@ -164,8 +159,7 @@ const Parse = struct {
164159
165 fn parseRoot(p: *Parse, node: Ast.Node.Index) !void {160 fn parseRoot(p: *Parse, node: Ast.Node.Index) !void {
166 const ast = p.ast;161 const ast = p.ast;
167 const main_tokens = ast.nodes.items(.main_token);162 const main_token = ast.nodeMainToken(node);
168 const main_token = main_tokens[node];
169163
170 var buf: [2]Ast.Node.Index = undefined;164 var buf: [2]Ast.Node.Index = undefined;
171 const struct_init = ast.fullStructInit(&buf, node) orelse {165 const struct_init = ast.fullStructInit(&buf, node) orelse {
...@@ -184,7 +178,7 @@ const Parse = struct {...@@ -184,7 +178,7 @@ const Parse = struct {
184 // things manually provides an opportunity to do any additional verification178 // things manually provides an opportunity to do any additional verification
185 // that is desirable on a per-field basis.179 // that is desirable on a per-field basis.
186 if (mem.eql(u8, field_name, "dependencies")) {180 if (mem.eql(u8, field_name, "dependencies")) {
187 p.dependencies_node = field_init;181 p.dependencies_node = field_init.toOptional();
188 try parseDependencies(p, field_init);182 try parseDependencies(p, field_init);
189 } else if (mem.eql(u8, field_name, "paths")) {183 } else if (mem.eql(u8, field_name, "paths")) {
190 have_included_paths = true;184 have_included_paths = true;
...@@ -198,17 +192,17 @@ const Parse = struct {...@@ -198,17 +192,17 @@ const Parse = struct {
198 p.version_node = field_init;192 p.version_node = field_init;
199 const version_text = try parseString(p, field_init);193 const version_text = try parseString(p, field_init);
200 if (version_text.len > max_version_len) {194 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 });
202 }196 }
203 p.version = std.SemanticVersion.parse(version_text) catch |err| v: {197 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)});
205 break :v undefined;199 break :v undefined;
206 };200 };
207 have_version = true;201 have_version = true;
208 } else if (mem.eql(u8, field_name, "minimum_zig_version")) {202 } else if (mem.eql(u8, field_name, "minimum_zig_version")) {
209 const version_text = try parseString(p, field_init);203 const version_text = try parseString(p, field_init);
210 p.minimum_zig_version = std.SemanticVersion.parse(version_text) catch |err| v: {204 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)});
212 break :v null;206 break :v null;
213 };207 };
214 } else {208 } else {
...@@ -251,11 +245,10 @@ const Parse = struct {...@@ -251,11 +245,10 @@ const Parse = struct {
251245
252 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {246 fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void {
253 const ast = p.ast;247 const ast = p.ast;
254 const main_tokens = ast.nodes.items(.main_token);
255248
256 var buf: [2]Ast.Node.Index = undefined;249 var buf: [2]Ast.Node.Index = undefined;
257 const struct_init = ast.fullStructInit(&buf, node) orelse {250 const struct_init = ast.fullStructInit(&buf, node) orelse {
258 const tok = main_tokens[node];251 const tok = ast.nodeMainToken(node);
259 return fail(p, tok, "expected dependencies expression to be a struct", .{});252 return fail(p, tok, "expected dependencies expression to be a struct", .{});
260 };253 };
261254
...@@ -269,23 +262,22 @@ const Parse = struct {...@@ -269,23 +262,22 @@ const Parse = struct {
269262
270 fn parseDependency(p: *Parse, node: Ast.Node.Index) !Dependency {263 fn parseDependency(p: *Parse, node: Ast.Node.Index) !Dependency {
271 const ast = p.ast;264 const ast = p.ast;
272 const main_tokens = ast.nodes.items(.main_token);
273265
274 var buf: [2]Ast.Node.Index = undefined;266 var buf: [2]Ast.Node.Index = undefined;
275 const struct_init = ast.fullStructInit(&buf, node) orelse {267 const struct_init = ast.fullStructInit(&buf, node) orelse {
276 const tok = main_tokens[node];268 const tok = ast.nodeMainToken(node);
277 return fail(p, tok, "expected dependency expression to be a struct", .{});269 return fail(p, tok, "expected dependency expression to be a struct", .{});
278 };270 };
279271
280 var dep: Dependency = .{272 var dep: Dependency = .{
281 .location = undefined,273 .location = undefined,
282 .location_tok = 0,274 .location_tok = undefined,
283 .location_node = undefined,275 .location_node = undefined,
284 .hash = null,276 .hash = null,
285 .hash_tok = 0,277 .hash_tok = .none,
286 .hash_node = undefined,278 .hash_node = .none,
287 .node = node,279 .node = node,
288 .name_tok = 0,280 .name_tok = undefined,
289 .lazy = false,281 .lazy = false,
290 };282 };
291 var has_location = false;283 var has_location = false;
...@@ -299,7 +291,7 @@ const Parse = struct {...@@ -299,7 +291,7 @@ const Parse = struct {
299 // that is desirable on a per-field basis.291 // that is desirable on a per-field basis.
300 if (mem.eql(u8, field_name, "url")) {292 if (mem.eql(u8, field_name, "url")) {
301 if (has_location) {293 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.", .{});
303 }295 }
304 dep.location = .{296 dep.location = .{
305 .url = parseString(p, field_init) catch |err| switch (err) {297 .url = parseString(p, field_init) catch |err| switch (err) {
...@@ -308,11 +300,11 @@ const Parse = struct {...@@ -308,11 +300,11 @@ const Parse = struct {
308 },300 },
309 };301 };
310 has_location = true;302 has_location = true;
311 dep.location_tok = main_tokens[field_init];303 dep.location_tok = ast.nodeMainToken(field_init);
312 dep.location_node = field_init;304 dep.location_node = field_init;
313 } else if (mem.eql(u8, field_name, "path")) {305 } else if (mem.eql(u8, field_name, "path")) {
314 if (has_location) {306 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.", .{});
316 }308 }
317 dep.location = .{309 dep.location = .{
318 .path = parseString(p, field_init) catch |err| switch (err) {310 .path = parseString(p, field_init) catch |err| switch (err) {
...@@ -321,15 +313,15 @@ const Parse = struct {...@@ -321,15 +313,15 @@ const Parse = struct {
321 },313 },
322 };314 };
323 has_location = true;315 has_location = true;
324 dep.location_tok = main_tokens[field_init];316 dep.location_tok = ast.nodeMainToken(field_init);
325 dep.location_node = field_init;317 dep.location_node = field_init;
326 } else if (mem.eql(u8, field_name, "hash")) {318 } else if (mem.eql(u8, field_name, "hash")) {
327 dep.hash = parseHash(p, field_init) catch |err| switch (err) {319 dep.hash = parseHash(p, field_init) catch |err| switch (err) {
328 error.ParseFailure => continue,320 error.ParseFailure => continue,
329 else => |e| return e,321 else => |e| return e,
330 };322 };
331 dep.hash_tok = main_tokens[field_init];323 dep.hash_tok = .fromToken(ast.nodeMainToken(field_init));
332 dep.hash_node = field_init;324 dep.hash_node = field_init.toOptional();
333 } else if (mem.eql(u8, field_name, "lazy")) {325 } else if (mem.eql(u8, field_name, "lazy")) {
334 dep.lazy = parseBool(p, field_init) catch |err| switch (err) {326 dep.lazy = parseBool(p, field_init) catch |err| switch (err) {
335 error.ParseFailure => continue,327 error.ParseFailure => continue,
...@@ -342,7 +334,7 @@ const Parse = struct {...@@ -342,7 +334,7 @@ const Parse = struct {
342 }334 }
343335
344 if (!has_location) {336 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'.", .{});
346 }338 }
347339
348 return dep;340 return dep;
...@@ -350,11 +342,10 @@ const Parse = struct {...@@ -350,11 +342,10 @@ const Parse = struct {
350342
351 fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void {343 fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void {
352 const ast = p.ast;344 const ast = p.ast;
353 const main_tokens = ast.nodes.items(.main_token);
354345
355 var buf: [2]Ast.Node.Index = undefined;346 var buf: [2]Ast.Node.Index = undefined;
356 const array_init = ast.fullArrayInit(&buf, node) orelse {347 const array_init = ast.fullArrayInit(&buf, node) orelse {
357 const tok = main_tokens[node];348 const tok = ast.nodeMainToken(node);
358 return fail(p, tok, "expected paths expression to be a list of strings", .{});349 return fail(p, tok, "expected paths expression to be a list of strings", .{});
359 };350 };
360351
...@@ -369,12 +360,10 @@ const Parse = struct {...@@ -369,12 +360,10 @@ const Parse = struct {
369360
370 fn parseBool(p: *Parse, node: Ast.Node.Index) !bool {361 fn parseBool(p: *Parse, node: Ast.Node.Index) !bool {
371 const ast = p.ast;362 const ast = p.ast;
372 const node_tags = ast.nodes.items(.tag);363 if (ast.nodeTag(node) != .identifier) {
373 const main_tokens = ast.nodes.items(.main_token);364 return fail(p, ast.nodeMainToken(node), "expected identifier", .{});
374 if (node_tags[node] != .identifier) {
375 return fail(p, main_tokens[node], "expected identifier", .{});
376 }365 }
377 const ident_token = main_tokens[node];366 const ident_token = ast.nodeMainToken(node);
378 const token_bytes = ast.tokenSlice(ident_token);367 const token_bytes = ast.tokenSlice(ident_token);
379 if (mem.eql(u8, token_bytes, "true")) {368 if (mem.eql(u8, token_bytes, "true")) {
380 return true;369 return true;
...@@ -387,10 +376,8 @@ const Parse = struct {...@@ -387,10 +376,8 @@ const Parse = struct {
387376
388 fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint {377 fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint {
389 const ast = p.ast;378 const ast = p.ast;
390 const node_tags = ast.nodes.items(.tag);379 const main_token = ast.nodeMainToken(node);
391 const main_tokens = ast.nodes.items(.main_token);380 if (ast.nodeTag(node) != .number_literal) {
392 const main_token = main_tokens[node];
393 if (node_tags[node] != .number_literal) {
394 return fail(p, main_token, "expected integer literal", .{});381 return fail(p, main_token, "expected integer literal", .{});
395 }382 }
396 const token_bytes = ast.tokenSlice(main_token);383 const token_bytes = ast.tokenSlice(main_token);
...@@ -406,11 +393,9 @@ const Parse = struct {...@@ -406,11 +393,9 @@ const Parse = struct {
406393
407 fn parseName(p: *Parse, node: Ast.Node.Index) ![]const u8 {394 fn parseName(p: *Parse, node: Ast.Node.Index) ![]const u8 {
408 const ast = p.ast;395 const ast = p.ast;
409 const node_tags = ast.nodes.items(.tag);396 const main_token = ast.nodeMainToken(node);
410 const main_tokens = ast.nodes.items(.main_token);
411 const main_token = main_tokens[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) {
414 const name = try parseString(p, node);399 const name = try parseString(p, node);
415 if (!std.zig.isValidId(name))400 if (!std.zig.isValidId(name))
416 return fail(p, main_token, "name must be a valid bare zig identifier (hint: switch from string to enum literal)", .{});401 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 {...@@ -423,7 +408,7 @@ const Parse = struct {
423 return name;408 return name;
424 }409 }
425410
426 if (node_tags[node] != .enum_literal)411 if (ast.nodeTag(node) != .enum_literal)
427 return fail(p, main_token, "expected enum literal", .{});412 return fail(p, main_token, "expected enum literal", .{});
428413
429 const ident_name = ast.tokenSlice(main_token);414 const ident_name = ast.tokenSlice(main_token);
...@@ -440,12 +425,10 @@ const Parse = struct {...@@ -440,12 +425,10 @@ const Parse = struct {
440425
441 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {426 fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 {
442 const ast = p.ast;427 const ast = p.ast;
443 const node_tags = ast.nodes.items(.tag);428 if (ast.nodeTag(node) != .string_literal) {
444 const main_tokens = ast.nodes.items(.main_token);429 return fail(p, ast.nodeMainToken(node), "expected string literal", .{});
445 if (node_tags[node] != .string_literal) {
446 return fail(p, main_tokens[node], "expected string literal", .{});
447 }430 }
448 const str_lit_token = main_tokens[node];431 const str_lit_token = ast.nodeMainToken(node);
449 const token_bytes = ast.tokenSlice(str_lit_token);432 const token_bytes = ast.tokenSlice(str_lit_token);
450 p.buf.clearRetainingCapacity();433 p.buf.clearRetainingCapacity();
451 try parseStrLit(p, str_lit_token, &p.buf, token_bytes, 0);434 try parseStrLit(p, str_lit_token, &p.buf, token_bytes, 0);
...@@ -455,8 +438,7 @@ const Parse = struct {...@@ -455,8 +438,7 @@ const Parse = struct {
455438
456 fn parseHash(p: *Parse, node: Ast.Node.Index) ![]const u8 {439 fn parseHash(p: *Parse, node: Ast.Node.Index) ![]const u8 {
457 const ast = p.ast;440 const ast = p.ast;
458 const main_tokens = ast.nodes.items(.main_token);441 const tok = ast.nodeMainToken(node);
459 const tok = main_tokens[node];
460 const h = try parseString(p, node);442 const h = try parseString(p, node);
461443
462 if (h.len > Package.Hash.max_len) {444 if (h.len > Package.Hash.max_len) {
...@@ -469,8 +451,7 @@ const Parse = struct {...@@ -469,8 +451,7 @@ const Parse = struct {
469 /// TODO: try to DRY this with AstGen.identifierTokenString451 /// TODO: try to DRY this with AstGen.identifierTokenString
470 fn identifierTokenString(p: *Parse, token: Ast.TokenIndex) InnerError![]const u8 {452 fn identifierTokenString(p: *Parse, token: Ast.TokenIndex) InnerError![]const u8 {
471 const ast = p.ast;453 const ast = p.ast;
472 const token_tags = ast.tokens.items(.tag);454 assert(ast.tokenTag(token) == .identifier);
473 assert(token_tags[token] == .identifier);
474 const ident_name = ast.tokenSlice(token);455 const ident_name = ast.tokenSlice(token);
475 if (!mem.startsWith(u8, ident_name, "@")) {456 if (!mem.startsWith(u8, ident_name, "@")) {
476 return ident_name;457 return ident_name;
src/Sema.zig+110-87
...@@ -407,18 +407,18 @@ pub const Block = struct {...@@ -407,18 +407,18 @@ pub const Block = struct {
407 return block.comptime_reason != null;407 return block.comptime_reason != null;
408 }408 }
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 {
411 return block.src(.{ .node_offset_builtin_call_arg = .{411 return block.src(.{ .node_offset_builtin_call_arg = .{
412 .builtin_call_node = builtin_call_node,412 .builtin_call_node = builtin_call_node,
413 .arg_index = arg_index,413 .arg_index = arg_index,
414 } });414 } });
415 }415 }
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 {
418 return block.src(LazySrcLoc.Offset.nodeOffset(node_offset));418 return block.src(LazySrcLoc.Offset.nodeOffset(node_offset));
419 }419 }
420420
421 fn tokenOffset(block: Block, tok_offset: u32) LazySrcLoc {421 fn tokenOffset(block: Block, tok_offset: std.zig.Ast.TokenOffset) LazySrcLoc {
422 return block.src(.{ .token_offset = tok_offset });422 return block.src(.{ .token_offset = tok_offset });
423 }423 }
424424
...@@ -1860,7 +1860,7 @@ fn analyzeBodyInner(...@@ -1860,7 +1860,7 @@ fn analyzeBodyInner(
1860 if (!block.isComptime()) break :blk try sema.zirTry(block, inst);1860 if (!block.isComptime()) break :blk try sema.zirTry(block, inst);
1861 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1861 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1862 const src = block.nodeOffset(inst_data.src_node);1862 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 });
1864 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);1864 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1865 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);1865 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
1866 const err_union = try sema.resolveInst(extra.data.operand);1866 const err_union = try sema.resolveInst(extra.data.operand);
...@@ -1883,7 +1883,7 @@ fn analyzeBodyInner(...@@ -1883,7 +1883,7 @@ fn analyzeBodyInner(
1883 if (!block.isComptime()) break :blk try sema.zirTryPtr(block, inst);1883 if (!block.isComptime()) break :blk try sema.zirTryPtr(block, inst);
1884 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;1884 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
1885 const src = block.nodeOffset(inst_data.src_node);1885 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 });
1887 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);1887 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
1888 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);1888 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len);
1889 const operand = try sema.resolveInst(extra.data.operand);1889 const operand = try sema.resolveInst(extra.data.operand);
...@@ -2166,7 +2166,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)...@@ -2166,7 +2166,7 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
2166 const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty));2166 const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty));
21672167
2168 // var st: StackTrace = undefined;2168 // 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);
2170 try stack_trace_ty.resolveFields(pt);2170 try stack_trace_ty.resolveFields(pt);
2171 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));2171 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
21722172
...@@ -2901,7 +2901,7 @@ fn zirStructDecl(...@@ -2901,7 +2901,7 @@ fn zirStructDecl(
2901 const tracked_inst = try block.trackZir(inst);2901 const tracked_inst = try block.trackZir(inst);
2902 const src: LazySrcLoc = .{2902 const src: LazySrcLoc = .{
2903 .base_node_inst = tracked_inst,2903 .base_node_inst = tracked_inst,
2904 .offset = LazySrcLoc.Offset.nodeOffset(0),2904 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
2905 };2905 };
29062906
2907 var extra_index = extra.end;2907 var extra_index = extra.end;
...@@ -3114,7 +3114,7 @@ fn zirEnumDecl(...@@ -3114,7 +3114,7 @@ fn zirEnumDecl(
3114 var extra_index: usize = extra.end;3114 var extra_index: usize = extra.end;
31153115
3116 const tracked_inst = try block.trackZir(inst);3116 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
3119 const tag_type_ref = if (small.has_tag_type) blk: {3119 const tag_type_ref = if (small.has_tag_type) blk: {
3120 const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);3120 const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
...@@ -3277,7 +3277,7 @@ fn zirUnionDecl(...@@ -3277,7 +3277,7 @@ fn zirUnionDecl(
3277 var extra_index: usize = extra.end;3277 var extra_index: usize = extra.end;
32783278
3279 const tracked_inst = try block.trackZir(inst);3279 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
3282 extra_index += @intFromBool(small.has_tag_type);3282 extra_index += @intFromBool(small.has_tag_type);
3283 const captures_len = if (small.has_captures_len) blk: {3283 const captures_len = if (small.has_captures_len) blk: {
...@@ -3402,7 +3402,7 @@ fn zirOpaqueDecl(...@@ -3402,7 +3402,7 @@ fn zirOpaqueDecl(
3402 var extra_index: usize = extra.end;3402 var extra_index: usize = extra.end;
34033403
3404 const tracked_inst = try block.trackZir(inst);3404 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
3407 const captures_len = if (small.has_captures_len) blk: {3407 const captures_len = if (small.has_captures_len) blk: {
3408 const captures_len = sema.code.extra[extra_index];3408 const captures_len = sema.code.extra[extra_index];
...@@ -3835,7 +3835,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3835,7 +3835,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3835 if (try elem_ty.comptimeOnlySema(pt)) {3835 if (try elem_ty.comptimeOnlySema(pt)) {
3836 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.3836 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
3837 // TODO: source location of runtime control flow3837 // 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 });
3839 return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)});3839 return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)});
3840 }3840 }
38413841
...@@ -6690,8 +6690,8 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6690,8 +6690,8 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError
6690 if (block.label) |label| {6690 if (block.label) |label| {
6691 if (label.zir_block == zir_block) {6691 if (label.zir_block == zir_block) {
6692 const br_ref = try start_block.addBr(label.merges.block_inst, operand);6692 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)6693 const src_loc = if (extra.operand_src_node.unwrap()) |operand_src_node|
6694 start_block.nodeOffset(extra.operand_src_node)6694 start_block.nodeOffset(operand_src_node)
6695 else6695 else
6696 null;6696 null;
6697 try label.merges.src_locs.append(sema.gpa, src_loc);6697 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...@@ -6715,8 +6715,7 @@ fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) Com
67156715
6716 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break";6716 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break";
6717 const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data;6717 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);6718 const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?);
6719 const operand_src = start_block.nodeOffset(extra.operand_src_node);
6720 const uncoerced_operand = try sema.resolveInst(inst_data.operand);6719 const uncoerced_operand = try sema.resolveInst(inst_data.operand);
6721 const switch_inst = extra.block_inst;6720 const switch_inst = extra.block_inst;
67226721
...@@ -7048,7 +7047,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -7048,7 +7047,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
70487047
7049 if (!block.ownerModule().error_tracing) return .none;7048 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);
7052 try stack_trace_ty.resolveFields(pt);7051 try stack_trace_ty.resolveFields(pt);
7053 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);7052 const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
7054 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {7053 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
...@@ -7346,7 +7345,7 @@ fn checkCallArgumentCount(...@@ -7346,7 +7345,7 @@ fn checkCallArgumentCount(
7346 if (maybe_func_inst) |func_inst| {7345 if (maybe_func_inst) |func_inst| {
7347 try sema.errNote(.{7346 try sema.errNote(.{
7348 .base_node_inst = func_inst,7347 .base_node_inst = func_inst,
7349 .offset = LazySrcLoc.Offset.nodeOffset(0),7348 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
7350 }, msg, "function declared here", .{});7349 }, msg, "function declared here", .{});
7351 }7350 }
7352 break :msg msg;7351 break :msg msg;
...@@ -7418,7 +7417,7 @@ const CallArgsInfo = union(enum) {...@@ -7418,7 +7417,7 @@ const CallArgsInfo = union(enum) {
7418 /// The list of resolved (but uncoerced) arguments is known ahead of time, but7417 /// The list of resolved (but uncoerced) arguments is known ahead of time, but
7419 /// originated from a usage of the @call builtin at the given node offset.7418 /// originated from a usage of the @call builtin at the given node offset.
7420 call_builtin: struct {7419 call_builtin: struct {
7421 call_node_offset: i32,7420 call_node_offset: std.zig.Ast.Node.Offset,
7422 args: []const Air.Inst.Ref,7421 args: []const Air.Inst.Ref,
7423 },7422 },
74247423
...@@ -7436,7 +7435,7 @@ const CallArgsInfo = union(enum) {...@@ -7436,7 +7435,7 @@ const CallArgsInfo = union(enum) {
7436 /// analyzing arguments.7435 /// analyzing arguments.
7437 call_inst: Zir.Inst.Index,7436 call_inst: Zir.Inst.Index,
7438 /// The node offset of `call_inst`.7437 /// The node offset of `call_inst`.
7439 call_node_offset: i32,7438 call_node_offset: std.zig.Ast.Node.Offset,
7440 /// The number of arguments to this call, not including `bound_arg`.7439 /// The number of arguments to this call, not including `bound_arg`.
7441 num_args: u32,7440 num_args: u32,
7442 /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it7441 /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it
...@@ -7599,7 +7598,7 @@ fn analyzeCall(...@@ -7599,7 +7598,7 @@ fn analyzeCall(
7599 const maybe_func_inst = try sema.funcDeclSrcInst(callee);7598 const maybe_func_inst = try sema.funcDeclSrcInst(callee);
7600 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{7599 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{
7601 .base_node_inst = fn_decl_inst,7600 .base_node_inst = fn_decl_inst,
7602 .offset = .{ .node_offset_fn_type_ret_ty = 0 },7601 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
7603 } else func_src;7602 } else func_src;
76047603
7605 const func_ty_info = zcu.typeToFunc(func_ty).?;7604 const func_ty_info = zcu.typeToFunc(func_ty).?;
...@@ -7613,7 +7612,7 @@ fn analyzeCall(...@@ -7613,7 +7612,7 @@ fn analyzeCall(
7613 errdefer msg.destroy(gpa);7612 errdefer msg.destroy(gpa);
7614 if (maybe_func_inst) |func_inst| try sema.errNote(.{7613 if (maybe_func_inst) |func_inst| try sema.errNote(.{
7615 .base_node_inst = func_inst,7614 .base_node_inst = func_inst,
7616 .offset = .nodeOffset(0),7615 .offset = .nodeOffset(.zero),
7617 }, msg, "function declared here", .{});7616 }, msg, "function declared here", .{});
7618 break :msg msg;7617 break :msg msg;
7619 });7618 });
...@@ -9574,7 +9573,7 @@ const Section = union(enum) {...@@ -9574,7 +9573,7 @@ const Section = union(enum) {
9574fn funcCommon(9573fn funcCommon(
9575 sema: *Sema,9574 sema: *Sema,
9576 block: *Block,9575 block: *Block,
9577 src_node_offset: i32,9576 src_node_offset: std.zig.Ast.Node.Offset,
9578 func_inst: Zir.Inst.Index,9577 func_inst: Zir.Inst.Index,
9579 cc: std.builtin.CallingConvention,9578 cc: std.builtin.CallingConvention,
9580 /// this might be Type.generic_poison9579 /// this might be Type.generic_poison
...@@ -9948,7 +9947,7 @@ fn finishFunc(...@@ -9948,7 +9947,7 @@ fn finishFunc(
9948 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {9947 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
9949 // Make sure that StackTrace's fields are resolved so that the backend can9948 // Make sure that StackTrace's fields are resolved so that the backend can
9950 // lower this fn type.9949 // 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);
9952 try unresolved_stack_trace_ty.resolveFields(pt);9951 try unresolved_stack_trace_ty.resolveFields(pt);
9953 }9952 }
99549953
...@@ -12599,7 +12598,7 @@ fn analyzeSwitchRuntimeBlock(...@@ -12599,7 +12598,7 @@ fn analyzeSwitchRuntimeBlock(
12599 union_originally: bool,12598 union_originally: bool,
12600 maybe_union_ty: Type,12599 maybe_union_ty: Type,
12601 err_set: bool,12600 err_set: bool,
12602 switch_node_offset: i32,12601 switch_node_offset: std.zig.Ast.Node.Offset,
12603 special_prong_src: LazySrcLoc,12602 special_prong_src: LazySrcLoc,
12604 seen_enum_fields: []?LazySrcLoc,12603 seen_enum_fields: []?LazySrcLoc,
12605 seen_errors: SwitchErrorSet,12604 seen_errors: SwitchErrorSet,
...@@ -13219,7 +13218,7 @@ fn resolveSwitchComptimeLoop(...@@ -13219,7 +13218,7 @@ fn resolveSwitchComptimeLoop(
13219 maybe_ptr_operand_ty: Type,13218 maybe_ptr_operand_ty: Type,
13220 cond_ty: Type,13219 cond_ty: Type,
13221 init_cond_val: Value,13220 init_cond_val: Value,
13222 switch_node_offset: i32,13221 switch_node_offset: std.zig.Ast.Node.Offset,
13223 special: SpecialProng,13222 special: SpecialProng,
13224 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),13223 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),
13225 scalar_cases_len: u32,13224 scalar_cases_len: u32,
...@@ -13255,7 +13254,7 @@ fn resolveSwitchComptimeLoop(...@@ -13255,7 +13254,7 @@ fn resolveSwitchComptimeLoop(
13255 const extra = sema.code.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data;13254 const extra = sema.code.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data;
13256 if (extra.block_inst != spa.switch_block_inst) return error.ComptimeBreak;13255 if (extra.block_inst != spa.switch_block_inst) return error.ComptimeBreak;
13257 // This is a `switch_continue` targeting this block. Change the operand and start over.13256 // 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().?);
13259 const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand);13258 const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand);
13260 const new_operand = try sema.coerce(child_block, maybe_ptr_operand_ty, new_operand_uncoerced, src);13259 const new_operand = try sema.coerce(child_block, maybe_ptr_operand_ty, new_operand_uncoerced, src);
1326113260
...@@ -13287,7 +13286,7 @@ fn resolveSwitchComptime(...@@ -13287,7 +13286,7 @@ fn resolveSwitchComptime(
13287 cond_operand: Air.Inst.Ref,13286 cond_operand: Air.Inst.Ref,
13288 operand_val: Value,13287 operand_val: Value,
13289 operand_ty: Type,13288 operand_ty: Type,
13290 switch_node_offset: i32,13289 switch_node_offset: std.zig.Ast.Node.Offset,
13291 special: SpecialProng,13290 special: SpecialProng,
13292 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),13291 case_vals: std.ArrayListUnmanaged(Air.Inst.Ref),
13293 scalar_cases_len: u32,13292 scalar_cases_len: u32,
...@@ -13837,7 +13836,7 @@ fn validateSwitchNoRange(...@@ -13837,7 +13836,7 @@ fn validateSwitchNoRange(
13837 block: *Block,13836 block: *Block,
13838 ranges_len: u32,13837 ranges_len: u32,
13839 operand_ty: Type,13838 operand_ty: Type,
13840 src_node_offset: i32,13839 src_node_offset: std.zig.Ast.Node.Offset,
13841) CompileError!void {13840) CompileError!void {
13842 if (ranges_len == 0)13841 if (ranges_len == 0)
13843 return;13842 return;
...@@ -14158,14 +14157,24 @@ fn zirShl(...@@ -14158,14 +14157,24 @@ fn zirShl(
14158 const pt = sema.pt;14157 const pt = sema.pt;
14159 const zcu = pt.zcu;14158 const zcu = pt.zcu;
14160 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;14159 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 });
14164 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;14160 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
14165 const lhs = try sema.resolveInst(extra.lhs);14161 const lhs = try sema.resolveInst(extra.lhs);
14166 const rhs = try sema.resolveInst(extra.rhs);14162 const rhs = try sema.resolveInst(extra.rhs);
14167 const lhs_ty = sema.typeOf(lhs);14163 const lhs_ty = sema.typeOf(lhs);
14168 const rhs_ty = sema.typeOf(rhs);14164 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
14169 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14178 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1417014179
14171 const scalar_ty = lhs_ty.scalarType(zcu);14180 const scalar_ty = lhs_ty.scalarType(zcu);
...@@ -14329,14 +14338,24 @@ fn zirShr(...@@ -14329,14 +14338,24 @@ fn zirShr(
14329 const pt = sema.pt;14338 const pt = sema.pt;
14330 const zcu = pt.zcu;14339 const zcu = pt.zcu;
14331 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;14340 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 });
14335 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;14341 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
14336 const lhs = try sema.resolveInst(extra.lhs);14342 const lhs = try sema.resolveInst(extra.lhs);
14337 const rhs = try sema.resolveInst(extra.rhs);14343 const rhs = try sema.resolveInst(extra.rhs);
14338 const lhs_ty = sema.typeOf(lhs);14344 const lhs_ty = sema.typeOf(lhs);
14339 const rhs_ty = sema.typeOf(rhs);14345 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
14340 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);14359 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
14341 const scalar_ty = lhs_ty.scalarType(zcu);14360 const scalar_ty = lhs_ty.scalarType(zcu);
1434214361
...@@ -14560,7 +14579,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -14560,7 +14579,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
14560fn analyzeTupleCat(14579fn analyzeTupleCat(
14561 sema: *Sema,14580 sema: *Sema,
14562 block: *Block,14581 block: *Block,
14563 src_node: i32,14582 src_node: std.zig.Ast.Node.Offset,
14564 lhs: Air.Inst.Ref,14583 lhs: Air.Inst.Ref,
14565 rhs: Air.Inst.Ref,14584 rhs: Air.Inst.Ref,
14566) CompileError!Air.Inst.Ref {14585) CompileError!Air.Inst.Ref {
...@@ -15005,7 +15024,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -15005,7 +15024,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
15005fn analyzeTupleMul(15024fn analyzeTupleMul(
15006 sema: *Sema,15025 sema: *Sema,
15007 block: *Block,15026 block: *Block,
15008 src_node: i32,15027 src_node: std.zig.Ast.Node.Offset,
15009 operand: Air.Inst.Ref,15028 operand: Air.Inst.Ref,
15010 factor: usize,15029 factor: usize,
15011) CompileError!Air.Inst.Ref {15030) CompileError!Air.Inst.Ref {
...@@ -15494,8 +15513,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15494,8 +15513,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15494 const zcu = pt.zcu;15513 const zcu = pt.zcu;
15495 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;15514 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
15496 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });15515 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 });15516 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15498 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });15517 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
15499 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;15518 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
15500 const lhs = try sema.resolveInst(extra.lhs);15519 const lhs = try sema.resolveInst(extra.lhs);
15501 const rhs = try sema.resolveInst(extra.rhs);15520 const rhs = try sema.resolveInst(extra.rhs);
...@@ -15660,8 +15679,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15660,8 +15679,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15660 const zcu = pt.zcu;15679 const zcu = pt.zcu;
15661 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;15680 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
15662 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });15681 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 });15682 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15664 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });15683 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
15665 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;15684 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
15666 const lhs = try sema.resolveInst(extra.lhs);15685 const lhs = try sema.resolveInst(extra.lhs);
15667 const rhs = try sema.resolveInst(extra.rhs);15686 const rhs = try sema.resolveInst(extra.rhs);
...@@ -15771,8 +15790,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15771,8 +15790,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15771 const zcu = pt.zcu;15790 const zcu = pt.zcu;
15772 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;15791 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
15773 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });15792 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 });15793 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
15775 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });15794 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
15776 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;15795 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
15777 const lhs = try sema.resolveInst(extra.lhs);15796 const lhs = try sema.resolveInst(extra.lhs);
15778 const rhs = try sema.resolveInst(extra.rhs);15797 const rhs = try sema.resolveInst(extra.rhs);
...@@ -16201,8 +16220,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -16201,8 +16220,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16201 const zcu = pt.zcu;16220 const zcu = pt.zcu;
16202 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;16221 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
16203 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });16222 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 });16223 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
16205 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });16224 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
16206 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;16225 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
16207 const lhs = try sema.resolveInst(extra.lhs);16226 const lhs = try sema.resolveInst(extra.lhs);
16208 const rhs = try sema.resolveInst(extra.rhs);16227 const rhs = try sema.resolveInst(extra.rhs);
...@@ -16297,8 +16316,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -16297,8 +16316,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16297 const zcu = pt.zcu;16316 const zcu = pt.zcu;
16298 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;16317 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
16299 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });16318 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 });16319 const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0);
16301 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });16320 const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1);
16302 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;16321 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
16303 const lhs = try sema.resolveInst(extra.lhs);16322 const lhs = try sema.resolveInst(extra.lhs);
16304 const rhs = try sema.resolveInst(extra.rhs);16323 const rhs = try sema.resolveInst(extra.rhs);
...@@ -17873,7 +17892,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17873,7 +17892,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17873 const ip = &zcu.intern_pool;17892 const ip = &zcu.intern_pool;
17874 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);17893 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);
1787517894
17876 const src_node: i32 = @bitCast(extended.operand);17895 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17877 const src = block.nodeOffset(src_node);17896 const src = block.nodeOffset(src_node);
1787817897
17879 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {17898 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
...@@ -17897,8 +17916,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17897,8 +17916,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17897 });17916 });
17898 break :name null;17917 break :name null;
17899 };17918 };
17900 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));17919 const node = src_node.toAbsolute(src_base_node);
17901 const token = tree.nodes.items(.main_token)[node];17920 const token = tree.nodeMainToken(node);
17902 break :name tree.tokenSlice(token);17921 break :name tree.tokenSlice(token);
17903 };17922 };
1790417923
...@@ -17925,8 +17944,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17925,8 +17944,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17925 });17944 });
17926 break :name null;17945 break :name null;
17927 };17946 };
17928 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));17947 const node = src_node.toAbsolute(src_base_node);
17929 const token = tree.nodes.items(.main_token)[node];17948 const token = tree.nodeMainToken(node);
17930 break :name tree.tokenSlice(token);17949 break :name tree.tokenSlice(token);
17931 };17950 };
1793217951
...@@ -17936,7 +17955,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17936,7 +17955,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17936 try sema.errMsg(src, "variable not accessible from inner function", .{});17955 try sema.errMsg(src, "variable not accessible from inner function", .{});
17937 errdefer msg.destroy(sema.gpa);17956 errdefer msg.destroy(sema.gpa);
1793817957
17939 try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{});17958 try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{});
1794017959
17941 // TODO add "declared here" note17960 // TODO add "declared here" note
17942 break :msg msg;17961 break :msg msg;
...@@ -17968,7 +17987,8 @@ fn zirFrameAddress(...@@ -17968,7 +17987,8 @@ fn zirFrameAddress(
17968 block: *Block,17987 block: *Block,
17969 extended: Zir.Inst.Extended.InstData,17988 extended: Zir.Inst.Extended.InstData,
17970) CompileError!Air.Inst.Ref {17989) CompileError!Air.Inst.Ref {
17971 const src = block.nodeOffset(@bitCast(extended.operand));17990 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17991 const src = block.nodeOffset(src_node);
17972 try sema.requireRuntimeBlock(block, src, null);17992 try sema.requireRuntimeBlock(block, src, null);
17973 return try block.addNoOp(.frame_addr);17993 return try block.addNoOp(.frame_addr);
17974}17994}
...@@ -18065,7 +18085,7 @@ fn zirBuiltinSrc(...@@ -18065,7 +18085,7 @@ fn zirBuiltinSrc(
18065 } });18085 } });
18066 };18086 };
1806718087
18068 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation);18088 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation);
18069 const fields = .{18089 const fields = .{
18070 // module: [:0]const u8,18090 // module: [:0]const u8,
18071 module_name_val,18091 module_name_val,
...@@ -19534,7 +19554,7 @@ fn zirCondbr(...@@ -19534,7 +19554,7 @@ fn zirCondbr(
19534fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19554fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19535 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;19555 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
19536 const src = parent_block.nodeOffset(inst_data.src_node);19556 const src = parent_block.nodeOffset(inst_data.src_node);
19537 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });19557 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
19538 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);19558 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
19539 const body = sema.code.bodySlice(extra.end, extra.data.body_len);19559 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
19540 const err_union = try sema.resolveInst(extra.data.operand);19560 const err_union = try sema.resolveInst(extra.data.operand);
...@@ -19593,7 +19613,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19593,7 +19613,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
19593fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19613fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19594 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;19614 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
19595 const src = parent_block.nodeOffset(inst_data.src_node);19615 const src = parent_block.nodeOffset(inst_data.src_node);
19596 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });19616 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
19597 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);19617 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
19598 const body = sema.code.bodySlice(extra.end, extra.data.body_len);19618 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
19599 const operand = try sema.resolveInst(extra.data.operand);19619 const operand = try sema.resolveInst(extra.data.operand);
...@@ -19796,7 +19816,7 @@ fn zirRetImplicit(...@@ -19796,7 +19816,7 @@ fn zirRetImplicit(
19796 }19816 }
1979719817
19798 const operand = try sema.resolveInst(inst_data.operand);19818 const operand = try sema.resolveInst(inst_data.operand);
19799 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 });19819 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
19800 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);19820 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
19801 if (base_tag == .noreturn) {19821 if (base_tag == .noreturn) {
19802 const msg = msg: {19822 const msg = msg: {
...@@ -21283,7 +21303,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -21283,7 +21303,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
21283 const pt = sema.pt;21303 const pt = sema.pt;
21284 const zcu = pt.zcu;21304 const zcu = pt.zcu;
21285 const ip = &zcu.intern_pool;21305 const ip = &zcu.intern_pool;
21286 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);21306 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
21287 try stack_trace_ty.resolveFields(pt);21307 try stack_trace_ty.resolveFields(pt);
21288 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);21308 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
21289 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());21309 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
...@@ -21305,7 +21325,8 @@ fn zirFrame(...@@ -21305,7 +21325,8 @@ fn zirFrame(
21305 block: *Block,21325 block: *Block,
21306 extended: Zir.Inst.Extended.InstData,21326 extended: Zir.Inst.Extended.InstData,
21307) CompileError!Air.Inst.Ref {21327) CompileError!Air.Inst.Ref {
21308 const src = block.nodeOffset(@bitCast(extended.operand));21328 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
21329 const src = block.nodeOffset(src_node);
21309 return sema.failWithUseOfAsync(block, src);21330 return sema.failWithUseOfAsync(block, src);
21310}21331}
2131121332
...@@ -21559,13 +21580,13 @@ fn zirReify(...@@ -21559,13 +21580,13 @@ fn zirReify(
21559 const tracked_inst = try block.trackZir(inst);21580 const tracked_inst = try block.trackZir(inst);
21560 const src: LazySrcLoc = .{21581 const src: LazySrcLoc = .{
21561 .base_node_inst = tracked_inst,21582 .base_node_inst = tracked_inst,
21562 .offset = LazySrcLoc.Offset.nodeOffset(0),21583 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
21563 };21584 };
21564 const operand_src: LazySrcLoc = .{21585 const operand_src: LazySrcLoc = .{
21565 .base_node_inst = tracked_inst,21586 .base_node_inst = tracked_inst,
21566 .offset = .{21587 .offset = .{
21567 .node_offset_builtin_call_arg = .{21588 .node_offset_builtin_call_arg = .{
21568 .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 021589 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
21569 .arg_index = 0,21590 .arg_index = 0,
21570 },21591 },
21571 },21592 },
...@@ -22873,7 +22894,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -22873,7 +22894,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
22873}22894}
2287422895
22875fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {22896fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22876 const src = block.nodeOffset(@bitCast(extended.operand));22897 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
22898 const src = block.nodeOffset(src_node);
2287722899
22878 const va_list_ty = try sema.getBuiltinType(src, .VaList);22900 const va_list_ty = try sema.getBuiltinType(src, .VaList);
22879 try sema.requireRuntimeBlock(block, src, null);22901 try sema.requireRuntimeBlock(block, src, null);
...@@ -24278,12 +24300,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -24278,12 +24300,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
24278fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {24300fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {
24279 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;24301 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24280 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });24302 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
24281 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });24303 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
24282 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });24304 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1);
24283 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;24305 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2428424306
24285 const ty = try sema.resolveType(block, lhs_src, extra.lhs);24307 const ty = try sema.resolveType(block, ty_src, extra.lhs);
24286 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name });24308 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name });
2428724309
24288 const pt = sema.pt;24310 const pt = sema.pt;
24289 const zcu = pt.zcu;24311 const zcu = pt.zcu;
...@@ -24291,15 +24313,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -24291,15 +24313,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
24291 try ty.resolveLayout(pt);24313 try ty.resolveLayout(pt);
24292 switch (ty.zigTypeTag(zcu)) {24314 switch (ty.zigTypeTag(zcu)) {
24293 .@"struct" => {},24315 .@"struct" => {},
24294 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),24316 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
24295 }24317 }
2429624318
24297 const field_index = if (ty.isTuple(zcu)) blk: {24319 const field_index = if (ty.isTuple(zcu)) blk: {
24298 if (field_name.eqlSlice("len", ip)) {24320 if (field_name.eqlSlice("len", ip)) {
24299 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});24321 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
24300 }24322 }
24301 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);24323 break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src);
24302 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);24324 } else try sema.structFieldIndex(block, ty, field_name, field_name_src);
2430324325
24304 if (ty.structFieldIsComptime(field_index, zcu)) {24326 if (ty.structFieldIsComptime(field_index, zcu)) {
24305 return sema.fail(block, src, "no offset available for comptime field", .{});24327 return sema.fail(block, src, "no offset available for comptime field", .{});
...@@ -25083,7 +25105,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -25083,7 +25105,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
25083fn analyzeShuffle(25105fn analyzeShuffle(
25084 sema: *Sema,25106 sema: *Sema,
25085 block: *Block,25107 block: *Block,
25086 src_node: i32,25108 src_node: std.zig.Ast.Node.Offset,
25087 elem_ty: Type,25109 elem_ty: Type,
25088 a_arg: Air.Inst.Ref,25110 a_arg: Air.Inst.Ref,
25089 b_arg: Air.Inst.Ref,25111 b_arg: Air.Inst.Ref,
...@@ -27010,7 +27032,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -27010,7 +27032,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
27010 const gpa = zcu.gpa;27032 const gpa = zcu.gpa;
27011 const ip = &zcu.intern_pool;27033 const ip = &zcu.intern_pool;
2701227034
27013 const src = block.nodeOffset(@bitCast(extended.operand));27035 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
27036 const src = block.nodeOffset(src_node);
27014 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);27037 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2701527038
27016 const ty = switch (value) {27039 const ty = switch (value) {
...@@ -29485,7 +29508,7 @@ const CoerceOpts = struct {...@@ -29485,7 +29508,7 @@ const CoerceOpts = struct {
29485 return .{29508 return .{
29486 .base_node_inst = func_inst,29509 .base_node_inst = func_inst,
29487 .offset = .{ .fn_proto_param_type = .{29510 .offset = .{ .fn_proto_param_type = .{
29488 .fn_proto_node_offset = 0,29511 .fn_proto_node_offset = .zero,
29489 .param_index = info.param_i,29512 .param_index = info.param_i,
29490 } },29513 } },
29491 };29514 };
...@@ -30090,7 +30113,7 @@ fn coerceExtra(...@@ -30090,7 +30113,7 @@ fn coerceExtra(
3009030113
30091 const ret_ty_src: LazySrcLoc = .{30114 const ret_ty_src: LazySrcLoc = .{
30092 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),30115 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30093 .offset = .{ .node_offset_fn_type_ret_ty = 0 },30116 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
30094 };30117 };
30095 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});30118 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});
30096 break :msg msg;30119 break :msg msg;
...@@ -30130,7 +30153,7 @@ fn coerceExtra(...@@ -30130,7 +30153,7 @@ fn coerceExtra(
30130 {30153 {
30131 const ret_ty_src: LazySrcLoc = .{30154 const ret_ty_src: LazySrcLoc = .{
30132 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),30155 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30133 .offset = .{ .node_offset_fn_type_ret_ty = 0 },30156 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
30134 };30157 };
30135 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {30158 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {
30136 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});30159 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
...@@ -32331,7 +32354,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav...@@ -32331,7 +32354,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
32331 if (zcu.analysis_in_progress.contains(anal_unit)) {32354 if (zcu.analysis_in_progress.contains(anal_unit)) {
32332 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{32355 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
32333 .base_node_inst = nav.analysis.?.zir_index,32356 .base_node_inst = nav.analysis.?.zir_index,
32334 .offset = LazySrcLoc.Offset.nodeOffset(0),32357 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
32335 }, "dependency loop detected", .{}));32358 }, "dependency loop detected", .{}));
32336 }32359 }
3233732360
...@@ -33948,7 +33971,7 @@ const PeerTypeCandidateSrc = union(enum) {...@@ -33948,7 +33971,7 @@ const PeerTypeCandidateSrc = union(enum) {
33948 /// index i in this slice33971 /// index i in this slice
33949 override: []const ?LazySrcLoc,33972 override: []const ?LazySrcLoc,
33950 /// resolvePeerTypes originates from a @TypeOf(...) call33973 /// resolvePeerTypes originates from a @TypeOf(...) call
33951 typeof_builtin_call_node_offset: i32,33974 typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset,
3395233975
33953 pub fn resolve(33976 pub fn resolve(
33954 self: PeerTypeCandidateSrc,33977 self: PeerTypeCandidateSrc,
...@@ -35551,7 +35574,7 @@ fn backingIntType(...@@ -35551,7 +35574,7 @@ fn backingIntType(
3555135574
35552 const backing_int_src: LazySrcLoc = .{35575 const backing_int_src: LazySrcLoc = .{
35553 .base_node_inst = struct_type.zir_index,35576 .base_node_inst = struct_type.zir_index,
35554 .offset = .{ .node_offset_container_tag = 0 },35577 .offset = .{ .node_offset_container_tag = .zero },
35555 };35578 };
35556 block.comptime_reason = .{ .reason = .{35579 block.comptime_reason = .{ .reason = .{
35557 .src = backing_int_src,35580 .src = backing_int_src,
...@@ -35572,7 +35595,7 @@ fn backingIntType(...@@ -35572,7 +35595,7 @@ fn backingIntType(
35572 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());35595 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
35573 } else {35596 } else {
35574 if (fields_bit_sum > std.math.maxInt(u16)) {35597 if (fields_bit_sum > std.math.maxInt(u16)) {
35575 return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});35598 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
35576 }35599 }
35577 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));35600 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
35578 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());35601 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
...@@ -36173,7 +36196,7 @@ fn structFields(...@@ -36173,7 +36196,7 @@ fn structFields(
36173 .comptime_reason = .{ .reason = .{36196 .comptime_reason = .{ .reason = .{
36174 .src = .{36197 .src = .{
36175 .base_node_inst = struct_type.zir_index,36198 .base_node_inst = struct_type.zir_index,
36176 .offset = .nodeOffset(0),36199 .offset = .nodeOffset(.zero),
36177 },36200 },
36178 .r = .{ .simple = .struct_fields },36201 .r = .{ .simple = .struct_fields },
36179 } },36202 } },
...@@ -36514,7 +36537,7 @@ fn unionFields(...@@ -36514,7 +36537,7 @@ fn unionFields(
3651436537
36515 const src: LazySrcLoc = .{36538 const src: LazySrcLoc = .{
36516 .base_node_inst = union_type.zir_index,36539 .base_node_inst = union_type.zir_index,
36517 .offset = .nodeOffset(0),36540 .offset = .nodeOffset(.zero),
36518 };36541 };
3651936542
36520 var block_scope: Block = .{36543 var block_scope: Block = .{
...@@ -36543,7 +36566,7 @@ fn unionFields(...@@ -36543,7 +36566,7 @@ fn unionFields(
36543 if (tag_type_ref != .none) {36566 if (tag_type_ref != .none) {
36544 const tag_ty_src: LazySrcLoc = .{36567 const tag_ty_src: LazySrcLoc = .{
36545 .base_node_inst = union_type.zir_index,36568 .base_node_inst = union_type.zir_index,
36546 .offset = .{ .node_offset_container_tag = 0 },36569 .offset = .{ .node_offset_container_tag = .zero },
36547 };36570 };
36548 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);36571 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
36549 if (small.auto_enum_tag) {36572 if (small.auto_enum_tag) {
...@@ -38523,7 +38546,7 @@ pub fn resolveDeclaredEnum(...@@ -38523,7 +38546,7 @@ pub fn resolveDeclaredEnum(
38523 const zcu = pt.zcu;38546 const zcu = pt.zcu;
38524 const gpa = zcu.gpa;38547 const gpa = zcu.gpa;
3852538548
38526 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };38549 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3852738550
38528 var arena: std.heap.ArenaAllocator = .init(gpa);38551 var arena: std.heap.ArenaAllocator = .init(gpa);
38529 defer arena.deinit();38552 defer arena.deinit();
...@@ -38610,7 +38633,7 @@ fn resolveDeclaredEnumInner(...@@ -38610,7 +38633,7 @@ fn resolveDeclaredEnumInner(
3861038633
38611 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;38634 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3861238635
38613 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };38636 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } };
3861438637
38615 const int_tag_ty = ty: {38638 const int_tag_ty = ty: {
38616 if (body.len != 0) {38639 if (body.len != 0) {
...@@ -38763,9 +38786,9 @@ pub fn resolveNavPtrModifiers(...@@ -38763,9 +38786,9 @@ pub fn resolveNavPtrModifiers(
38763 const gpa = zcu.gpa;38786 const gpa = zcu.gpa;
38764 const ip = &zcu.intern_pool;38787 const ip = &zcu.intern_pool;
3876538788
38766 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });38789 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
38767 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });38790 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
38768 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });38791 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3876938792
38770 const alignment: InternPool.Alignment = a: {38793 const alignment: InternPool.Alignment = a: {
38771 const align_body = zir_decl.align_body orelse break :a .none;38794 const align_body = zir_decl.align_body orelse break :a .none;
...@@ -38838,7 +38861,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,...@@ -38838,7 +38861,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3883838861
38839 const src: LazySrcLoc = .{38862 const src: LazySrcLoc = .{
38840 .base_node_inst = ip.getNav(nav).srcInst(ip),38863 .base_node_inst = ip.getNav(nav).srcInst(ip),
38841 .offset = .nodeOffset(0),38864 .offset = .nodeOffset(.zero),
38842 };38865 };
3884338866
38844 const result = try sema.analyzeNavVal(block, src, nav);38867 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 {...@@ -3505,7 +3505,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
3505 },3505 },
3506 else => return null,3506 else => return null,
3507 },3507 },
3508 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),3508 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero),
3509 };3509 };
3510}3510}
35113511
src/Zcu.zig+284-314
...@@ -134,7 +134,7 @@ failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empt...@@ -134,7 +134,7 @@ failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empt
134/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.134/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.
135compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {135compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
136 base_node_inst: InternPool.TrackedInst.Index,136 base_node_inst: InternPool.TrackedInst.Index,
137 node_offset: i32,137 node_offset: Ast.Node.Offset,
138 pub fn src(self: @This()) LazySrcLoc {138 pub fn src(self: @This()) LazySrcLoc {
139 return .{139 return .{
140 .base_node_inst = self.base_node_inst,140 .base_node_inst = self.base_node_inst,
...@@ -1034,10 +1034,6 @@ pub const SrcLoc = struct {...@@ -1034,10 +1034,6 @@ pub const SrcLoc = struct {
1034 return tree.firstToken(src_loc.base_node);1034 return tree.firstToken(src_loc.base_node);
1035 }1035 }
10361036
1037 pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
1038 return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node)));
1039 }
1040
1041 pub const Span = Ast.Span;1037 pub const Span = Ast.Span;
10421038
1043 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {1039 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
...@@ -1049,7 +1045,7 @@ pub const SrcLoc = struct {...@@ -1049,7 +1045,7 @@ pub const SrcLoc = struct {
10491045
1050 .token_abs => |tok_index| {1046 .token_abs => |tok_index| {
1051 const tree = try src_loc.file_scope.getTree(gpa);1047 const tree = try src_loc.file_scope.getTree(gpa);
1052 const start = tree.tokens.items(.start)[tok_index];1048 const start = tree.tokenStart(tok_index);
1053 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1049 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1054 return Span{ .start = start, .end = end, .main = start };1050 return Span{ .start = start, .end = end, .main = start };
1055 },1051 },
...@@ -1060,142 +1056,137 @@ pub const SrcLoc = struct {...@@ -1060,142 +1056,137 @@ pub const SrcLoc = struct {
1060 .byte_offset => |byte_off| {1056 .byte_offset => |byte_off| {
1061 const tree = try src_loc.file_scope.getTree(gpa);1057 const tree = try src_loc.file_scope.getTree(gpa);
1062 const tok_index = src_loc.baseSrcToken();1058 const tok_index = src_loc.baseSrcToken();
1063 const start = tree.tokens.items(.start)[tok_index] + byte_off;1059 const start = tree.tokenStart(tok_index) + byte_off;
1064 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1060 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1065 return Span{ .start = start, .end = end, .main = start };1061 return Span{ .start = start, .end = end, .main = start };
1066 },1062 },
1067 .token_offset => |tok_off| {1063 .token_offset => |tok_off| {
1068 const tree = try src_loc.file_scope.getTree(gpa);1064 const tree = try src_loc.file_scope.getTree(gpa);
1069 const tok_index = src_loc.baseSrcToken() + tok_off;1065 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());
1070 const start = tree.tokens.items(.start)[tok_index];1066 const start = tree.tokenStart(tok_index);
1071 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1067 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1072 return Span{ .start = start, .end = end, .main = start };1068 return Span{ .start = start, .end = end, .main = start };
1073 },1069 },
1074 .node_offset => |traced_off| {1070 .node_offset => |traced_off| {
1075 const node_off = traced_off.x;1071 const node_off = traced_off.x;
1076 const tree = try src_loc.file_scope.getTree(gpa);1072 const tree = try src_loc.file_scope.getTree(gpa);
1077 const node = src_loc.relativeToNodeIndex(node_off);1073 const node = node_off.toAbsolute(src_loc.base_node);
1078 return tree.nodeToSpan(node);1074 return tree.nodeToSpan(node);
1079 },1075 },
1080 .node_offset_main_token => |node_off| {1076 .node_offset_main_token => |node_off| {
1081 const tree = try src_loc.file_scope.getTree(gpa);1077 const tree = try src_loc.file_scope.getTree(gpa);
1082 const node = src_loc.relativeToNodeIndex(node_off);1078 const node = node_off.toAbsolute(src_loc.base_node);
1083 const main_token = tree.nodes.items(.main_token)[node];1079 const main_token = tree.nodeMainToken(node);
1084 return tree.tokensToSpan(main_token, main_token, main_token);1080 return tree.tokensToSpan(main_token, main_token, main_token);
1085 },1081 },
1086 .node_offset_bin_op => |node_off| {1082 .node_offset_bin_op => |node_off| {
1087 const tree = try src_loc.file_scope.getTree(gpa);1083 const tree = try src_loc.file_scope.getTree(gpa);
1088 const node = src_loc.relativeToNodeIndex(node_off);1084 const node = node_off.toAbsolute(src_loc.base_node);
1089 return tree.nodeToSpan(node);1085 return tree.nodeToSpan(node);
1090 },1086 },
1091 .node_offset_initializer => |node_off| {1087 .node_offset_initializer => |node_off| {
1092 const tree = try src_loc.file_scope.getTree(gpa);1088 const tree = try src_loc.file_scope.getTree(gpa);
1093 const node = src_loc.relativeToNodeIndex(node_off);1089 const node = node_off.toAbsolute(src_loc.base_node);
1094 return tree.tokensToSpan(1090 return tree.tokensToSpan(
1095 tree.firstToken(node) - 3,1091 tree.firstToken(node) - 3,
1096 tree.lastToken(node),1092 tree.lastToken(node),
1097 tree.nodes.items(.main_token)[node] - 2,1093 tree.nodeMainToken(node) - 2,
1098 );1094 );
1099 },1095 },
1100 .node_offset_var_decl_ty => |node_off| {1096 .node_offset_var_decl_ty => |node_off| {
1101 const tree = try src_loc.file_scope.getTree(gpa);1097 const tree = try src_loc.file_scope.getTree(gpa);
1102 const node = src_loc.relativeToNodeIndex(node_off);1098 const node = node_off.toAbsolute(src_loc.base_node);
1103 const node_tags = tree.nodes.items(.tag);1099 const full = switch (tree.nodeTag(node)) {
1104 const full = switch (node_tags[node]) {
1105 .global_var_decl,1100 .global_var_decl,
1106 .local_var_decl,1101 .local_var_decl,
1107 .simple_var_decl,1102 .simple_var_decl,
1108 .aligned_var_decl,1103 .aligned_var_decl,
1109 => tree.fullVarDecl(node).?,1104 => tree.fullVarDecl(node).?,
1110 .@"usingnamespace" => {1105 .@"usingnamespace" => {
1111 const node_data = tree.nodes.items(.data);1106 return tree.nodeToSpan(tree.nodeData(node).node);
1112 return tree.nodeToSpan(node_data[node].lhs);
1113 },1107 },
1114 else => unreachable,1108 else => unreachable,
1115 };1109 };
1116 if (full.ast.type_node != 0) {1110 if (full.ast.type_node.unwrap()) |type_node| {
1117 return tree.nodeToSpan(full.ast.type_node);1111 return tree.nodeToSpan(type_node);
1118 }1112 }
1119 const tok_index = full.ast.mut_token + 1; // the name token1113 const tok_index = full.ast.mut_token + 1; // the name token
1120 const start = tree.tokens.items(.start)[tok_index];1114 const start = tree.tokenStart(tok_index);
1121 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1115 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1122 return Span{ .start = start, .end = end, .main = start };1116 return Span{ .start = start, .end = end, .main = start };
1123 },1117 },
1124 .node_offset_var_decl_align => |node_off| {1118 .node_offset_var_decl_align => |node_off| {
1125 const tree = try src_loc.file_scope.getTree(gpa);1119 const tree = try src_loc.file_scope.getTree(gpa);
1126 const node = src_loc.relativeToNodeIndex(node_off);1120 const node = node_off.toAbsolute(src_loc.base_node);
1127 var buf: [1]Ast.Node.Index = undefined;1121 var buf: [1]Ast.Node.Index = undefined;
1128 const align_node = if (tree.fullVarDecl(node)) |v|1122 const align_node = if (tree.fullVarDecl(node)) |v|
1129 v.ast.align_node1123 v.ast.align_node.unwrap().?
1130 else if (tree.fullFnProto(&buf, node)) |f|1124 else if (tree.fullFnProto(&buf, node)) |f|
1131 f.ast.align_expr1125 f.ast.align_expr.unwrap().?
1132 else1126 else
1133 unreachable;1127 unreachable;
1134 return tree.nodeToSpan(align_node);1128 return tree.nodeToSpan(align_node);
1135 },1129 },
1136 .node_offset_var_decl_section => |node_off| {1130 .node_offset_var_decl_section => |node_off| {
1137 const tree = try src_loc.file_scope.getTree(gpa);1131 const tree = try src_loc.file_scope.getTree(gpa);
1138 const node = src_loc.relativeToNodeIndex(node_off);1132 const node = node_off.toAbsolute(src_loc.base_node);
1139 var buf: [1]Ast.Node.Index = undefined;1133 var buf: [1]Ast.Node.Index = undefined;
1140 const section_node = if (tree.fullVarDecl(node)) |v|1134 const section_node = if (tree.fullVarDecl(node)) |v|
1141 v.ast.section_node1135 v.ast.section_node.unwrap().?
1142 else if (tree.fullFnProto(&buf, node)) |f|1136 else if (tree.fullFnProto(&buf, node)) |f|
1143 f.ast.section_expr1137 f.ast.section_expr.unwrap().?
1144 else1138 else
1145 unreachable;1139 unreachable;
1146 return tree.nodeToSpan(section_node);1140 return tree.nodeToSpan(section_node);
1147 },1141 },
1148 .node_offset_var_decl_addrspace => |node_off| {1142 .node_offset_var_decl_addrspace => |node_off| {
1149 const tree = try src_loc.file_scope.getTree(gpa);1143 const tree = try src_loc.file_scope.getTree(gpa);
1150 const node = src_loc.relativeToNodeIndex(node_off);1144 const node = node_off.toAbsolute(src_loc.base_node);
1151 var buf: [1]Ast.Node.Index = undefined;1145 var buf: [1]Ast.Node.Index = undefined;
1152 const addrspace_node = if (tree.fullVarDecl(node)) |v|1146 const addrspace_node = if (tree.fullVarDecl(node)) |v|
1153 v.ast.addrspace_node1147 v.ast.addrspace_node.unwrap().?
1154 else if (tree.fullFnProto(&buf, node)) |f|1148 else if (tree.fullFnProto(&buf, node)) |f|
1155 f.ast.addrspace_expr1149 f.ast.addrspace_expr.unwrap().?
1156 else1150 else
1157 unreachable;1151 unreachable;
1158 return tree.nodeToSpan(addrspace_node);1152 return tree.nodeToSpan(addrspace_node);
1159 },1153 },
1160 .node_offset_var_decl_init => |node_off| {1154 .node_offset_var_decl_init => |node_off| {
1161 const tree = try src_loc.file_scope.getTree(gpa);1155 const tree = try src_loc.file_scope.getTree(gpa);
1162 const node = src_loc.relativeToNodeIndex(node_off);1156 const node = node_off.toAbsolute(src_loc.base_node);
1163 const full = tree.fullVarDecl(node).?;1157 const init_node = switch (tree.nodeTag(node)) {
1164 return tree.nodeToSpan(full.ast.init_node);1158 .global_var_decl,
1159 .local_var_decl,
1160 .aligned_var_decl,
1161 .simple_var_decl,
1162 => tree.fullVarDecl(node).?.ast.init_node.unwrap().?,
1163 .assign_destructure => tree.assignDestructure(node).ast.value_expr,
1164 else => unreachable,
1165 };
1166 return tree.nodeToSpan(init_node);
1165 },1167 },
1166 .node_offset_builtin_call_arg => |builtin_arg| {1168 .node_offset_builtin_call_arg => |builtin_arg| {
1167 const tree = try src_loc.file_scope.getTree(gpa);1169 const tree = try src_loc.file_scope.getTree(gpa);
1168 const node_datas = tree.nodes.items(.data);1170 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);
1169 const node_tags = tree.nodes.items(.tag);1171 var buf: [2]Ast.Node.Index = undefined;
1170 const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node);1172 const params = tree.builtinCallParams(&buf, node).?;
1171 const param = switch (node_tags[node]) {1173 return tree.nodeToSpan(params[builtin_arg.arg_index]);
1172 .builtin_call_two, .builtin_call_two_comma => switch (builtin_arg.arg_index) {
1173 0 => node_datas[node].lhs,
1174 1 => node_datas[node].rhs,
1175 else => unreachable,
1176 },
1177 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + builtin_arg.arg_index],
1178 else => unreachable,
1179 };
1180 return tree.nodeToSpan(param);
1181 },1174 },
1182 .node_offset_ptrcast_operand => |node_off| {1175 .node_offset_ptrcast_operand => |node_off| {
1183 const tree = try src_loc.file_scope.getTree(gpa);1176 const tree = try src_loc.file_scope.getTree(gpa);
1184 const main_tokens = tree.nodes.items(.main_token);
1185 const node_datas = tree.nodes.items(.data);
1186 const node_tags = tree.nodes.items(.tag);
11871177
1188 var node = src_loc.relativeToNodeIndex(node_off);1178 var node = node_off.toAbsolute(src_loc.base_node);
1189 while (true) {1179 while (true) {
1190 switch (node_tags[node]) {1180 switch (tree.nodeTag(node)) {
1191 .builtin_call_two, .builtin_call_two_comma => {},1181 .builtin_call_two, .builtin_call_two_comma => {},
1192 else => break,1182 else => break,
1193 }1183 }
11941184
1195 if (node_datas[node].lhs == 0) break; // 0 args1185 const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node;
1196 if (node_datas[node].rhs != 0) break; // 2 args1186 if (first_arg == .none) break; // 0 args
1187 if (second_arg != .none) break; // 2 args
11971188
1198 const builtin_token = main_tokens[node];1189 const builtin_token = tree.nodeMainToken(node);
1199 const builtin_name = tree.tokenSlice(builtin_token);1190 const builtin_name = tree.tokenSlice(builtin_token);
1200 const info = BuiltinFn.list.get(builtin_name) orelse break;1191 const info = BuiltinFn.list.get(builtin_name) orelse break;
12011192
...@@ -1209,16 +1200,15 @@ pub const SrcLoc = struct {...@@ -1209,16 +1200,15 @@ pub const SrcLoc = struct {
1209 => {},1200 => {},
1210 }1201 }
12111202
1212 node = node_datas[node].lhs;1203 node = first_arg.unwrap().?;
1213 }1204 }
12141205
1215 return tree.nodeToSpan(node);1206 return tree.nodeToSpan(node);
1216 },1207 },
1217 .node_offset_array_access_index => |node_off| {1208 .node_offset_array_access_index => |node_off| {
1218 const tree = try src_loc.file_scope.getTree(gpa);1209 const tree = try src_loc.file_scope.getTree(gpa);
1219 const node_datas = tree.nodes.items(.data);1210 const node = node_off.toAbsolute(src_loc.base_node);
1220 const node = src_loc.relativeToNodeIndex(node_off);1211 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1221 return tree.nodeToSpan(node_datas[node].rhs);
1222 },1212 },
1223 .node_offset_slice_ptr,1213 .node_offset_slice_ptr,
1224 .node_offset_slice_start,1214 .node_offset_slice_start,
...@@ -1226,32 +1216,30 @@ pub const SrcLoc = struct {...@@ -1226,32 +1216,30 @@ pub const SrcLoc = struct {
1226 .node_offset_slice_sentinel,1216 .node_offset_slice_sentinel,
1227 => |node_off| {1217 => |node_off| {
1228 const tree = try src_loc.file_scope.getTree(gpa);1218 const tree = try src_loc.file_scope.getTree(gpa);
1229 const node = src_loc.relativeToNodeIndex(node_off);1219 const node = node_off.toAbsolute(src_loc.base_node);
1230 const full = tree.fullSlice(node).?;1220 const full = tree.fullSlice(node).?;
1231 const part_node = switch (src_loc.lazy) {1221 const part_node = switch (src_loc.lazy) {
1232 .node_offset_slice_ptr => full.ast.sliced,1222 .node_offset_slice_ptr => full.ast.sliced,
1233 .node_offset_slice_start => full.ast.start,1223 .node_offset_slice_start => full.ast.start,
1234 .node_offset_slice_end => full.ast.end,1224 .node_offset_slice_end => full.ast.end.unwrap().?,
1235 .node_offset_slice_sentinel => full.ast.sentinel,1225 .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?,
1236 else => unreachable,1226 else => unreachable,
1237 };1227 };
1238 return tree.nodeToSpan(part_node);1228 return tree.nodeToSpan(part_node);
1239 },1229 },
1240 .node_offset_call_func => |node_off| {1230 .node_offset_call_func => |node_off| {
1241 const tree = try src_loc.file_scope.getTree(gpa);1231 const tree = try src_loc.file_scope.getTree(gpa);
1242 const node = src_loc.relativeToNodeIndex(node_off);1232 const node = node_off.toAbsolute(src_loc.base_node);
1243 var buf: [1]Ast.Node.Index = undefined;1233 var buf: [1]Ast.Node.Index = undefined;
1244 const full = tree.fullCall(&buf, node).?;1234 const full = tree.fullCall(&buf, node).?;
1245 return tree.nodeToSpan(full.ast.fn_expr);1235 return tree.nodeToSpan(full.ast.fn_expr);
1246 },1236 },
1247 .node_offset_field_name => |node_off| {1237 .node_offset_field_name => |node_off| {
1248 const tree = try src_loc.file_scope.getTree(gpa);1238 const tree = try src_loc.file_scope.getTree(gpa);
1249 const node_datas = tree.nodes.items(.data);1239 const node = node_off.toAbsolute(src_loc.base_node);
1250 const node_tags = tree.nodes.items(.tag);
1251 const node = src_loc.relativeToNodeIndex(node_off);
1252 var buf: [1]Ast.Node.Index = undefined;1240 var buf: [1]Ast.Node.Index = undefined;
1253 const tok_index = switch (node_tags[node]) {1241 const tok_index = switch (tree.nodeTag(node)) {
1254 .field_access => node_datas[node].rhs,1242 .field_access => tree.nodeData(node).node_and_token[1],
1255 .call_one,1243 .call_one,
1256 .call_one_comma,1244 .call_one_comma,
1257 .async_call_one,1245 .async_call_one,
...@@ -1266,43 +1254,41 @@ pub const SrcLoc = struct {...@@ -1266,43 +1254,41 @@ pub const SrcLoc = struct {
1266 },1254 },
1267 else => tree.firstToken(node) - 2,1255 else => tree.firstToken(node) - 2,
1268 };1256 };
1269 const start = tree.tokens.items(.start)[tok_index];1257 const start = tree.tokenStart(tok_index);
1270 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1258 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1271 return Span{ .start = start, .end = end, .main = start };1259 return Span{ .start = start, .end = end, .main = start };
1272 },1260 },
1273 .node_offset_field_name_init => |node_off| {1261 .node_offset_field_name_init => |node_off| {
1274 const tree = try src_loc.file_scope.getTree(gpa);1262 const tree = try src_loc.file_scope.getTree(gpa);
1275 const node = src_loc.relativeToNodeIndex(node_off);1263 const node = node_off.toAbsolute(src_loc.base_node);
1276 const tok_index = tree.firstToken(node) - 2;1264 const tok_index = tree.firstToken(node) - 2;
1277 const start = tree.tokens.items(.start)[tok_index];1265 const start = tree.tokenStart(tok_index);
1278 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1266 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1279 return Span{ .start = start, .end = end, .main = start };1267 return Span{ .start = start, .end = end, .main = start };
1280 },1268 },
1281 .node_offset_deref_ptr => |node_off| {1269 .node_offset_deref_ptr => |node_off| {
1282 const tree = try src_loc.file_scope.getTree(gpa);1270 const tree = try src_loc.file_scope.getTree(gpa);
1283 const node = src_loc.relativeToNodeIndex(node_off);1271 const node = node_off.toAbsolute(src_loc.base_node);
1284 return tree.nodeToSpan(node);1272 return tree.nodeToSpan(node);
1285 },1273 },
1286 .node_offset_asm_source => |node_off| {1274 .node_offset_asm_source => |node_off| {
1287 const tree = try src_loc.file_scope.getTree(gpa);1275 const tree = try src_loc.file_scope.getTree(gpa);
1288 const node = src_loc.relativeToNodeIndex(node_off);1276 const node = node_off.toAbsolute(src_loc.base_node);
1289 const full = tree.fullAsm(node).?;1277 const full = tree.fullAsm(node).?;
1290 return tree.nodeToSpan(full.ast.template);1278 return tree.nodeToSpan(full.ast.template);
1291 },1279 },
1292 .node_offset_asm_ret_ty => |node_off| {1280 .node_offset_asm_ret_ty => |node_off| {
1293 const tree = try src_loc.file_scope.getTree(gpa);1281 const tree = try src_loc.file_scope.getTree(gpa);
1294 const node = src_loc.relativeToNodeIndex(node_off);1282 const node = node_off.toAbsolute(src_loc.base_node);
1295 const full = tree.fullAsm(node).?;1283 const full = tree.fullAsm(node).?;
1296 const asm_output = full.outputs[0];1284 const asm_output = full.outputs[0];
1297 const node_datas = tree.nodes.items(.data);1285 return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?);
1298 return tree.nodeToSpan(node_datas[asm_output].lhs);
1299 },1286 },
13001287
1301 .node_offset_if_cond => |node_off| {1288 .node_offset_if_cond => |node_off| {
1302 const tree = try src_loc.file_scope.getTree(gpa);1289 const tree = try src_loc.file_scope.getTree(gpa);
1303 const node = src_loc.relativeToNodeIndex(node_off);1290 const node = node_off.toAbsolute(src_loc.base_node);
1304 const node_tags = tree.nodes.items(.tag);1291 const src_node = switch (tree.nodeTag(node)) {
1305 const src_node = switch (node_tags[node]) {
1306 .if_simple,1292 .if_simple,
1307 .@"if",1293 .@"if",
1308 => tree.fullIf(node).?.ast.cond_expr,1294 => tree.fullIf(node).?.ast.cond_expr,
...@@ -1329,20 +1315,19 @@ pub const SrcLoc = struct {...@@ -1329,20 +1315,19 @@ pub const SrcLoc = struct {
1329 },1315 },
1330 .for_input => |for_input| {1316 .for_input => |for_input| {
1331 const tree = try src_loc.file_scope.getTree(gpa);1317 const tree = try src_loc.file_scope.getTree(gpa);
1332 const node = src_loc.relativeToNodeIndex(for_input.for_node_offset);1318 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
1333 const for_full = tree.fullFor(node).?;1319 const for_full = tree.fullFor(node).?;
1334 const src_node = for_full.ast.inputs[for_input.input_index];1320 const src_node = for_full.ast.inputs[for_input.input_index];
1335 return tree.nodeToSpan(src_node);1321 return tree.nodeToSpan(src_node);
1336 },1322 },
1337 .for_capture_from_input => |node_off| {1323 .for_capture_from_input => |node_off| {
1338 const tree = try src_loc.file_scope.getTree(gpa);1324 const tree = try src_loc.file_scope.getTree(gpa);
1339 const token_tags = tree.tokens.items(.tag);1325 const input_node = node_off.toAbsolute(src_loc.base_node);
1340 const input_node = src_loc.relativeToNodeIndex(node_off);
1341 // We have to actually linear scan the whole AST to find the for loop1326 // We have to actually linear scan the whole AST to find the for loop
1342 // that contains this input.1327 // that contains this input.
1343 const node_tags = tree.nodes.items(.tag);1328 const node_tags = tree.nodes.items(.tag);
1344 for (node_tags, 0..) |node_tag, node_usize| {1329 for (node_tags, 0..) |node_tag, node_usize| {
1345 const node = @as(Ast.Node.Index, @intCast(node_usize));1330 const node: Ast.Node.Index = @enumFromInt(node_usize);
1346 switch (node_tag) {1331 switch (node_tag) {
1347 .for_simple, .@"for" => {1332 .for_simple, .@"for" => {
1348 const for_full = tree.fullFor(node).?;1333 const for_full = tree.fullFor(node).?;
...@@ -1351,7 +1336,7 @@ pub const SrcLoc = struct {...@@ -1351,7 +1336,7 @@ pub const SrcLoc = struct {
1351 var count = input_index;1336 var count = input_index;
1352 var tok = for_full.payload_token;1337 var tok = for_full.payload_token;
1353 while (true) {1338 while (true) {
1354 switch (token_tags[tok]) {1339 switch (tree.tokenTag(tok)) {
1355 .comma => {1340 .comma => {
1356 count -= 1;1341 count -= 1;
1357 tok += 1;1342 tok += 1;
...@@ -1378,13 +1363,12 @@ pub const SrcLoc = struct {...@@ -1378,13 +1363,12 @@ pub const SrcLoc = struct {
1378 },1363 },
1379 .call_arg => |call_arg| {1364 .call_arg => |call_arg| {
1380 const tree = try src_loc.file_scope.getTree(gpa);1365 const tree = try src_loc.file_scope.getTree(gpa);
1381 const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset);1366 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);
1382 var buf: [2]Ast.Node.Index = undefined;1367 var buf: [2]Ast.Node.Index = undefined;
1383 const call_full = tree.fullCall(buf[0..1], node) orelse {1368 const call_full = tree.fullCall(buf[0..1], node) orelse {
1384 const node_tags = tree.nodes.items(.tag);1369 assert(tree.nodeTag(node) == .builtin_call);
1385 assert(node_tags[node] == .builtin_call);1370 const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]);
1386 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];1371 switch (tree.nodeTag(call_args_node)) {
1387 switch (node_tags[call_args_node]) {
1388 .array_init_one,1372 .array_init_one,
1389 .array_init_one_comma,1373 .array_init_one_comma,
1390 .array_init_dot_two,1374 .array_init_dot_two,
...@@ -1416,7 +1400,7 @@ pub const SrcLoc = struct {...@@ -1416,7 +1400,7 @@ pub const SrcLoc = struct {
1416 },1400 },
1417 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {1401 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
1418 const tree = try src_loc.file_scope.getTree(gpa);1402 const tree = try src_loc.file_scope.getTree(gpa);
1419 const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset);1403 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);
1420 var buf: [1]Ast.Node.Index = undefined;1404 var buf: [1]Ast.Node.Index = undefined;
1421 const full = tree.fullFnProto(&buf, node).?;1405 const full = tree.fullFnProto(&buf, node).?;
1422 var it = full.iterate(tree);1406 var it = full.iterate(tree);
...@@ -1428,14 +1412,14 @@ pub const SrcLoc = struct {...@@ -1428,14 +1412,14 @@ pub const SrcLoc = struct {
1428 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {1412 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {
1429 return tree.tokenToSpan(tok);1413 return tree.tokenToSpan(tok);
1430 } else {1414 } else {
1431 return tree.nodeToSpan(param.type_expr);1415 return tree.nodeToSpan(param.type_expr.?);
1432 },1416 },
1433 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {1417 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {
1434 const first = param.comptime_noalias orelse param.name_token orelse tok;1418 const first = param.comptime_noalias orelse param.name_token orelse tok;
1435 return tree.tokensToSpan(first, tok, first);1419 return tree.tokensToSpan(first, tok, first);
1436 } else {1420 } else {
1437 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr);1421 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?);
1438 return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first);1422 return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first);
1439 },1423 },
1440 else => unreachable,1424 else => unreachable,
1441 }1425 }
...@@ -1444,28 +1428,24 @@ pub const SrcLoc = struct {...@@ -1444,28 +1428,24 @@ pub const SrcLoc = struct {
1444 },1428 },
1445 .node_offset_bin_lhs => |node_off| {1429 .node_offset_bin_lhs => |node_off| {
1446 const tree = try src_loc.file_scope.getTree(gpa);1430 const tree = try src_loc.file_scope.getTree(gpa);
1447 const node = src_loc.relativeToNodeIndex(node_off);1431 const node = node_off.toAbsolute(src_loc.base_node);
1448 const node_datas = tree.nodes.items(.data);1432 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
1449 return tree.nodeToSpan(node_datas[node].lhs);
1450 },1433 },
1451 .node_offset_bin_rhs => |node_off| {1434 .node_offset_bin_rhs => |node_off| {
1452 const tree = try src_loc.file_scope.getTree(gpa);1435 const tree = try src_loc.file_scope.getTree(gpa);
1453 const node = src_loc.relativeToNodeIndex(node_off);1436 const node = node_off.toAbsolute(src_loc.base_node);
1454 const node_datas = tree.nodes.items(.data);1437 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1455 return tree.nodeToSpan(node_datas[node].rhs);
1456 },1438 },
1457 .array_cat_lhs, .array_cat_rhs => |cat| {1439 .array_cat_lhs, .array_cat_rhs => |cat| {
1458 const tree = try src_loc.file_scope.getTree(gpa);1440 const tree = try src_loc.file_scope.getTree(gpa);
1459 const node = src_loc.relativeToNodeIndex(cat.array_cat_offset);1441 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);
1460 const node_datas = tree.nodes.items(.data);
1461 const arr_node = if (src_loc.lazy == .array_cat_lhs)1442 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1462 node_datas[node].lhs1443 tree.nodeData(node).node_and_node[0]
1463 else1444 else
1464 node_datas[node].rhs;1445 tree.nodeData(node).node_and_node[1];
14651446
1466 const node_tags = tree.nodes.items(.tag);
1467 var buf: [2]Ast.Node.Index = undefined;1447 var buf: [2]Ast.Node.Index = undefined;
1468 switch (node_tags[arr_node]) {1448 switch (tree.nodeTag(arr_node)) {
1469 .array_init_one,1449 .array_init_one,
1470 .array_init_one_comma,1450 .array_init_one_comma,
1471 .array_init_dot_two,1451 .array_init_dot_two,
...@@ -1482,27 +1462,30 @@ pub const SrcLoc = struct {...@@ -1482,27 +1462,30 @@ pub const SrcLoc = struct {
1482 }1462 }
1483 },1463 },
14841464
1465 .node_offset_try_operand => |node_off| {
1466 const tree = try src_loc.file_scope.getTree(gpa);
1467 const node = node_off.toAbsolute(src_loc.base_node);
1468 return tree.nodeToSpan(tree.nodeData(node).node);
1469 },
1470
1485 .node_offset_switch_operand => |node_off| {1471 .node_offset_switch_operand => |node_off| {
1486 const tree = try src_loc.file_scope.getTree(gpa);1472 const tree = try src_loc.file_scope.getTree(gpa);
1487 const node = src_loc.relativeToNodeIndex(node_off);1473 const node = node_off.toAbsolute(src_loc.base_node);
1488 const node_datas = tree.nodes.items(.data);1474 const condition, _ = tree.nodeData(node).node_and_extra;
1489 return tree.nodeToSpan(node_datas[node].lhs);1475 return tree.nodeToSpan(condition);
1490 },1476 },
14911477
1492 .node_offset_switch_special_prong => |node_off| {1478 .node_offset_switch_special_prong => |node_off| {
1493 const tree = try src_loc.file_scope.getTree(gpa);1479 const tree = try src_loc.file_scope.getTree(gpa);
1494 const switch_node = src_loc.relativeToNodeIndex(node_off);1480 const switch_node = node_off.toAbsolute(src_loc.base_node);
1495 const node_datas = tree.nodes.items(.data);1481 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1496 const node_tags = tree.nodes.items(.tag);1482 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1497 const main_tokens = tree.nodes.items(.main_token);
1498 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1499 const case_nodes = tree.extra_data[extra.start..extra.end];
1500 for (case_nodes) |case_node| {1483 for (case_nodes) |case_node| {
1501 const case = tree.fullSwitchCase(case_node).?;1484 const case = tree.fullSwitchCase(case_node).?;
1502 const is_special = (case.ast.values.len == 0) or1485 const is_special = (case.ast.values.len == 0) or
1503 (case.ast.values.len == 1 and1486 (case.ast.values.len == 1 and
1504 node_tags[case.ast.values[0]] == .identifier and1487 tree.nodeTag(case.ast.values[0]) == .identifier and
1505 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));1488 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
1506 if (!is_special) continue;1489 if (!is_special) continue;
15071490
1508 return tree.nodeToSpan(case_node);1491 return tree.nodeToSpan(case_node);
...@@ -1511,22 +1494,19 @@ pub const SrcLoc = struct {...@@ -1511,22 +1494,19 @@ pub const SrcLoc = struct {
15111494
1512 .node_offset_switch_range => |node_off| {1495 .node_offset_switch_range => |node_off| {
1513 const tree = try src_loc.file_scope.getTree(gpa);1496 const tree = try src_loc.file_scope.getTree(gpa);
1514 const switch_node = src_loc.relativeToNodeIndex(node_off);1497 const switch_node = node_off.toAbsolute(src_loc.base_node);
1515 const node_datas = tree.nodes.items(.data);1498 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1516 const node_tags = tree.nodes.items(.tag);1499 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1517 const main_tokens = tree.nodes.items(.main_token);
1518 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1519 const case_nodes = tree.extra_data[extra.start..extra.end];
1520 for (case_nodes) |case_node| {1500 for (case_nodes) |case_node| {
1521 const case = tree.fullSwitchCase(case_node).?;1501 const case = tree.fullSwitchCase(case_node).?;
1522 const is_special = (case.ast.values.len == 0) or1502 const is_special = (case.ast.values.len == 0) or
1523 (case.ast.values.len == 1 and1503 (case.ast.values.len == 1 and
1524 node_tags[case.ast.values[0]] == .identifier and1504 tree.nodeTag(case.ast.values[0]) == .identifier and
1525 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));1505 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
1526 if (is_special) continue;1506 if (is_special) continue;
15271507
1528 for (case.ast.values) |item_node| {1508 for (case.ast.values) |item_node| {
1529 if (node_tags[item_node] == .switch_range) {1509 if (tree.nodeTag(item_node) == .switch_range) {
1530 return tree.nodeToSpan(item_node);1510 return tree.nodeToSpan(item_node);
1531 }1511 }
1532 }1512 }
...@@ -1534,47 +1514,46 @@ pub const SrcLoc = struct {...@@ -1534,47 +1514,46 @@ pub const SrcLoc = struct {
1534 },1514 },
1535 .node_offset_fn_type_align => |node_off| {1515 .node_offset_fn_type_align => |node_off| {
1536 const tree = try src_loc.file_scope.getTree(gpa);1516 const tree = try src_loc.file_scope.getTree(gpa);
1537 const node = src_loc.relativeToNodeIndex(node_off);1517 const node = node_off.toAbsolute(src_loc.base_node);
1538 var buf: [1]Ast.Node.Index = undefined;1518 var buf: [1]Ast.Node.Index = undefined;
1539 const full = tree.fullFnProto(&buf, node).?;1519 const full = tree.fullFnProto(&buf, node).?;
1540 return tree.nodeToSpan(full.ast.align_expr);1520 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
1541 },1521 },
1542 .node_offset_fn_type_addrspace => |node_off| {1522 .node_offset_fn_type_addrspace => |node_off| {
1543 const tree = try src_loc.file_scope.getTree(gpa);1523 const tree = try src_loc.file_scope.getTree(gpa);
1544 const node = src_loc.relativeToNodeIndex(node_off);1524 const node = node_off.toAbsolute(src_loc.base_node);
1545 var buf: [1]Ast.Node.Index = undefined;1525 var buf: [1]Ast.Node.Index = undefined;
1546 const full = tree.fullFnProto(&buf, node).?;1526 const full = tree.fullFnProto(&buf, node).?;
1547 return tree.nodeToSpan(full.ast.addrspace_expr);1527 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
1548 },1528 },
1549 .node_offset_fn_type_section => |node_off| {1529 .node_offset_fn_type_section => |node_off| {
1550 const tree = try src_loc.file_scope.getTree(gpa);1530 const tree = try src_loc.file_scope.getTree(gpa);
1551 const node = src_loc.relativeToNodeIndex(node_off);1531 const node = node_off.toAbsolute(src_loc.base_node);
1552 var buf: [1]Ast.Node.Index = undefined;1532 var buf: [1]Ast.Node.Index = undefined;
1553 const full = tree.fullFnProto(&buf, node).?;1533 const full = tree.fullFnProto(&buf, node).?;
1554 return tree.nodeToSpan(full.ast.section_expr);1534 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
1555 },1535 },
1556 .node_offset_fn_type_cc => |node_off| {1536 .node_offset_fn_type_cc => |node_off| {
1557 const tree = try src_loc.file_scope.getTree(gpa);1537 const tree = try src_loc.file_scope.getTree(gpa);
1558 const node = src_loc.relativeToNodeIndex(node_off);1538 const node = node_off.toAbsolute(src_loc.base_node);
1559 var buf: [1]Ast.Node.Index = undefined;1539 var buf: [1]Ast.Node.Index = undefined;
1560 const full = tree.fullFnProto(&buf, node).?;1540 const full = tree.fullFnProto(&buf, node).?;
1561 return tree.nodeToSpan(full.ast.callconv_expr);1541 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);
1562 },1542 },
15631543
1564 .node_offset_fn_type_ret_ty => |node_off| {1544 .node_offset_fn_type_ret_ty => |node_off| {
1565 const tree = try src_loc.file_scope.getTree(gpa);1545 const tree = try src_loc.file_scope.getTree(gpa);
1566 const node = src_loc.relativeToNodeIndex(node_off);1546 const node = node_off.toAbsolute(src_loc.base_node);
1567 var buf: [1]Ast.Node.Index = undefined;1547 var buf: [1]Ast.Node.Index = undefined;
1568 const full = tree.fullFnProto(&buf, node).?;1548 const full = tree.fullFnProto(&buf, node).?;
1569 return tree.nodeToSpan(full.ast.return_type);1549 return tree.nodeToSpan(full.ast.return_type.unwrap().?);
1570 },1550 },
1571 .node_offset_param => |node_off| {1551 .node_offset_param => |node_off| {
1572 const tree = try src_loc.file_scope.getTree(gpa);1552 const tree = try src_loc.file_scope.getTree(gpa);
1573 const token_tags = tree.tokens.items(.tag);1553 const node = node_off.toAbsolute(src_loc.base_node);
1574 const node = src_loc.relativeToNodeIndex(node_off);
15751554
1576 var first_tok = tree.firstToken(node);1555 var first_tok = tree.firstToken(node);
1577 while (true) switch (token_tags[first_tok - 1]) {1556 while (true) switch (tree.tokenTag(first_tok - 1)) {
1578 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,1557 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
1579 else => break,1558 else => break,
1580 };1559 };
...@@ -1586,12 +1565,11 @@ pub const SrcLoc = struct {...@@ -1586,12 +1565,11 @@ pub const SrcLoc = struct {
1586 },1565 },
1587 .token_offset_param => |token_off| {1566 .token_offset_param => |token_off| {
1588 const tree = try src_loc.file_scope.getTree(gpa);1567 const tree = try src_loc.file_scope.getTree(gpa);
1589 const token_tags = tree.tokens.items(.tag);1568 const main_token = tree.nodeMainToken(src_loc.base_node);
1590 const main_token = tree.nodes.items(.main_token)[src_loc.base_node];1569 const tok_index = token_off.toAbsolute(main_token);
1591 const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token))));
15921570
1593 var first_tok = tok_index;1571 var first_tok = tok_index;
1594 while (true) switch (token_tags[first_tok - 1]) {1572 while (true) switch (tree.tokenTag(first_tok - 1)) {
1595 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,1573 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
1596 else => break,1574 else => break,
1597 };1575 };
...@@ -1604,109 +1582,108 @@ pub const SrcLoc = struct {...@@ -1604,109 +1582,108 @@ pub const SrcLoc = struct {
16041582
1605 .node_offset_anyframe_type => |node_off| {1583 .node_offset_anyframe_type => |node_off| {
1606 const tree = try src_loc.file_scope.getTree(gpa);1584 const tree = try src_loc.file_scope.getTree(gpa);
1607 const node_datas = tree.nodes.items(.data);1585 const parent_node = node_off.toAbsolute(src_loc.base_node);
1608 const parent_node = src_loc.relativeToNodeIndex(node_off);1586 _, const child_type = tree.nodeData(parent_node).token_and_node;
1609 return tree.nodeToSpan(node_datas[parent_node].rhs);1587 return tree.nodeToSpan(child_type);
1610 },1588 },
16111589
1612 .node_offset_lib_name => |node_off| {1590 .node_offset_lib_name => |node_off| {
1613 const tree = try src_loc.file_scope.getTree(gpa);1591 const tree = try src_loc.file_scope.getTree(gpa);
1614 const parent_node = src_loc.relativeToNodeIndex(node_off);1592 const parent_node = node_off.toAbsolute(src_loc.base_node);
1615 var buf: [1]Ast.Node.Index = undefined;1593 var buf: [1]Ast.Node.Index = undefined;
1616 const full = tree.fullFnProto(&buf, parent_node).?;1594 const full = tree.fullFnProto(&buf, parent_node).?;
1617 const tok_index = full.lib_name.?;1595 const tok_index = full.lib_name.?;
1618 const start = tree.tokens.items(.start)[tok_index];1596 const start = tree.tokenStart(tok_index);
1619 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1597 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1620 return Span{ .start = start, .end = end, .main = start };1598 return Span{ .start = start, .end = end, .main = start };
1621 },1599 },
16221600
1623 .node_offset_array_type_len => |node_off| {1601 .node_offset_array_type_len => |node_off| {
1624 const tree = try src_loc.file_scope.getTree(gpa);1602 const tree = try src_loc.file_scope.getTree(gpa);
1625 const parent_node = src_loc.relativeToNodeIndex(node_off);1603 const parent_node = node_off.toAbsolute(src_loc.base_node);
16261604
1627 const full = tree.fullArrayType(parent_node).?;1605 const full = tree.fullArrayType(parent_node).?;
1628 return tree.nodeToSpan(full.ast.elem_count);1606 return tree.nodeToSpan(full.ast.elem_count);
1629 },1607 },
1630 .node_offset_array_type_sentinel => |node_off| {1608 .node_offset_array_type_sentinel => |node_off| {
1631 const tree = try src_loc.file_scope.getTree(gpa);1609 const tree = try src_loc.file_scope.getTree(gpa);
1632 const parent_node = src_loc.relativeToNodeIndex(node_off);1610 const parent_node = node_off.toAbsolute(src_loc.base_node);
16331611
1634 const full = tree.fullArrayType(parent_node).?;1612 const full = tree.fullArrayType(parent_node).?;
1635 return tree.nodeToSpan(full.ast.sentinel);1613 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1636 },1614 },
1637 .node_offset_array_type_elem => |node_off| {1615 .node_offset_array_type_elem => |node_off| {
1638 const tree = try src_loc.file_scope.getTree(gpa);1616 const tree = try src_loc.file_scope.getTree(gpa);
1639 const parent_node = src_loc.relativeToNodeIndex(node_off);1617 const parent_node = node_off.toAbsolute(src_loc.base_node);
16401618
1641 const full = tree.fullArrayType(parent_node).?;1619 const full = tree.fullArrayType(parent_node).?;
1642 return tree.nodeToSpan(full.ast.elem_type);1620 return tree.nodeToSpan(full.ast.elem_type);
1643 },1621 },
1644 .node_offset_un_op => |node_off| {1622 .node_offset_un_op => |node_off| {
1645 const tree = try src_loc.file_scope.getTree(gpa);1623 const tree = try src_loc.file_scope.getTree(gpa);
1646 const node_datas = tree.nodes.items(.data);1624 const node = node_off.toAbsolute(src_loc.base_node);
1647 const node = src_loc.relativeToNodeIndex(node_off);1625 return tree.nodeToSpan(tree.nodeData(node).node);
1648
1649 return tree.nodeToSpan(node_datas[node].lhs);
1650 },1626 },
1651 .node_offset_ptr_elem => |node_off| {1627 .node_offset_ptr_elem => |node_off| {
1652 const tree = try src_loc.file_scope.getTree(gpa);1628 const tree = try src_loc.file_scope.getTree(gpa);
1653 const parent_node = src_loc.relativeToNodeIndex(node_off);1629 const parent_node = node_off.toAbsolute(src_loc.base_node);
16541630
1655 const full = tree.fullPtrType(parent_node).?;1631 const full = tree.fullPtrType(parent_node).?;
1656 return tree.nodeToSpan(full.ast.child_type);1632 return tree.nodeToSpan(full.ast.child_type);
1657 },1633 },
1658 .node_offset_ptr_sentinel => |node_off| {1634 .node_offset_ptr_sentinel => |node_off| {
1659 const tree = try src_loc.file_scope.getTree(gpa);1635 const tree = try src_loc.file_scope.getTree(gpa);
1660 const parent_node = src_loc.relativeToNodeIndex(node_off);1636 const parent_node = node_off.toAbsolute(src_loc.base_node);
16611637
1662 const full = tree.fullPtrType(parent_node).?;1638 const full = tree.fullPtrType(parent_node).?;
1663 return tree.nodeToSpan(full.ast.sentinel);1639 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1664 },1640 },
1665 .node_offset_ptr_align => |node_off| {1641 .node_offset_ptr_align => |node_off| {
1666 const tree = try src_loc.file_scope.getTree(gpa);1642 const tree = try src_loc.file_scope.getTree(gpa);
1667 const parent_node = src_loc.relativeToNodeIndex(node_off);1643 const parent_node = node_off.toAbsolute(src_loc.base_node);
16681644
1669 const full = tree.fullPtrType(parent_node).?;1645 const full = tree.fullPtrType(parent_node).?;
1670 return tree.nodeToSpan(full.ast.align_node);1646 return tree.nodeToSpan(full.ast.align_node.unwrap().?);
1671 },1647 },
1672 .node_offset_ptr_addrspace => |node_off| {1648 .node_offset_ptr_addrspace => |node_off| {
1673 const tree = try src_loc.file_scope.getTree(gpa);1649 const tree = try src_loc.file_scope.getTree(gpa);
1674 const parent_node = src_loc.relativeToNodeIndex(node_off);1650 const parent_node = node_off.toAbsolute(src_loc.base_node);
16751651
1676 const full = tree.fullPtrType(parent_node).?;1652 const full = tree.fullPtrType(parent_node).?;
1677 return tree.nodeToSpan(full.ast.addrspace_node);1653 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);
1678 },1654 },
1679 .node_offset_ptr_bitoffset => |node_off| {1655 .node_offset_ptr_bitoffset => |node_off| {
1680 const tree = try src_loc.file_scope.getTree(gpa);1656 const tree = try src_loc.file_scope.getTree(gpa);
1681 const parent_node = src_loc.relativeToNodeIndex(node_off);1657 const parent_node = node_off.toAbsolute(src_loc.base_node);
16821658
1683 const full = tree.fullPtrType(parent_node).?;1659 const full = tree.fullPtrType(parent_node).?;
1684 return tree.nodeToSpan(full.ast.bit_range_start);1660 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);
1685 },1661 },
1686 .node_offset_ptr_hostsize => |node_off| {1662 .node_offset_ptr_hostsize => |node_off| {
1687 const tree = try src_loc.file_scope.getTree(gpa);1663 const tree = try src_loc.file_scope.getTree(gpa);
1688 const parent_node = src_loc.relativeToNodeIndex(node_off);1664 const parent_node = node_off.toAbsolute(src_loc.base_node);
16891665
1690 const full = tree.fullPtrType(parent_node).?;1666 const full = tree.fullPtrType(parent_node).?;
1691 return tree.nodeToSpan(full.ast.bit_range_end);1667 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);
1692 },1668 },
1693 .node_offset_container_tag => |node_off| {1669 .node_offset_container_tag => |node_off| {
1694 const tree = try src_loc.file_scope.getTree(gpa);1670 const tree = try src_loc.file_scope.getTree(gpa);
1695 const node_tags = tree.nodes.items(.tag);1671 const parent_node = node_off.toAbsolute(src_loc.base_node);
1696 const parent_node = src_loc.relativeToNodeIndex(node_off);
16971672
1698 switch (node_tags[parent_node]) {1673 switch (tree.nodeTag(parent_node)) {
1699 .container_decl_arg, .container_decl_arg_trailing => {1674 .container_decl_arg, .container_decl_arg_trailing => {
1700 const full = tree.containerDeclArg(parent_node);1675 const full = tree.containerDeclArg(parent_node);
1701 return tree.nodeToSpan(full.ast.arg);1676 const arg_node = full.ast.arg.unwrap().?;
1677 return tree.nodeToSpan(arg_node);
1702 },1678 },
1703 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {1679 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
1704 const full = tree.taggedUnionEnumTag(parent_node);1680 const full = tree.taggedUnionEnumTag(parent_node);
1681 const arg_node = full.ast.arg.unwrap().?;
17051682
1706 return tree.tokensToSpan(1683 return tree.tokensToSpan(
1707 tree.firstToken(full.ast.arg) - 2,1684 tree.firstToken(arg_node) - 2,
1708 tree.lastToken(full.ast.arg) + 1,1685 tree.lastToken(arg_node) + 1,
1709 tree.nodes.items(.main_token)[full.ast.arg],1686 tree.nodeMainToken(arg_node),
1710 );1687 );
1711 },1688 },
1712 else => unreachable,1689 else => unreachable,
...@@ -1714,60 +1691,55 @@ pub const SrcLoc = struct {...@@ -1714,60 +1691,55 @@ pub const SrcLoc = struct {
1714 },1691 },
1715 .node_offset_field_default => |node_off| {1692 .node_offset_field_default => |node_off| {
1716 const tree = try src_loc.file_scope.getTree(gpa);1693 const tree = try src_loc.file_scope.getTree(gpa);
1717 const node_tags = tree.nodes.items(.tag);1694 const parent_node = node_off.toAbsolute(src_loc.base_node);
1718 const parent_node = src_loc.relativeToNodeIndex(node_off);
17191695
1720 const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {1696 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {
1721 .container_field => tree.containerField(parent_node),1697 .container_field => tree.containerField(parent_node),
1722 .container_field_init => tree.containerFieldInit(parent_node),1698 .container_field_init => tree.containerFieldInit(parent_node),
1723 else => unreachable,1699 else => unreachable,
1724 };1700 };
1725 return tree.nodeToSpan(full.ast.value_expr);1701 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);
1726 },1702 },
1727 .node_offset_init_ty => |node_off| {1703 .node_offset_init_ty => |node_off| {
1728 const tree = try src_loc.file_scope.getTree(gpa);1704 const tree = try src_loc.file_scope.getTree(gpa);
1729 const parent_node = src_loc.relativeToNodeIndex(node_off);1705 const parent_node = node_off.toAbsolute(src_loc.base_node);
17301706
1731 var buf: [2]Ast.Node.Index = undefined;1707 var buf: [2]Ast.Node.Index = undefined;
1732 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|1708 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|
1733 array_init.ast.type_expr1709 array_init.ast.type_expr.unwrap().?
1734 else1710 else
1735 tree.fullStructInit(&buf, parent_node).?.ast.type_expr;1711 tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?;
1736 return tree.nodeToSpan(type_expr);1712 return tree.nodeToSpan(type_expr);
1737 },1713 },
1738 .node_offset_store_ptr => |node_off| {1714 .node_offset_store_ptr => |node_off| {
1739 const tree = try src_loc.file_scope.getTree(gpa);1715 const tree = try src_loc.file_scope.getTree(gpa);
1740 const node_tags = tree.nodes.items(.tag);1716 const node = node_off.toAbsolute(src_loc.base_node);
1741 const node_datas = tree.nodes.items(.data);
1742 const node = src_loc.relativeToNodeIndex(node_off);
17431717
1744 switch (node_tags[node]) {1718 switch (tree.nodeTag(node)) {
1745 .assign => {1719 .assign => {
1746 return tree.nodeToSpan(node_datas[node].lhs);1720 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
1747 },1721 },
1748 else => return tree.nodeToSpan(node),1722 else => return tree.nodeToSpan(node),
1749 }1723 }
1750 },1724 },
1751 .node_offset_store_operand => |node_off| {1725 .node_offset_store_operand => |node_off| {
1752 const tree = try src_loc.file_scope.getTree(gpa);1726 const tree = try src_loc.file_scope.getTree(gpa);
1753 const node_tags = tree.nodes.items(.tag);1727 const node = node_off.toAbsolute(src_loc.base_node);
1754 const node_datas = tree.nodes.items(.data);
1755 const node = src_loc.relativeToNodeIndex(node_off);
17561728
1757 switch (node_tags[node]) {1729 switch (tree.nodeTag(node)) {
1758 .assign => {1730 .assign => {
1759 return tree.nodeToSpan(node_datas[node].rhs);1731 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1760 },1732 },
1761 else => return tree.nodeToSpan(node),1733 else => return tree.nodeToSpan(node),
1762 }1734 }
1763 },1735 },
1764 .node_offset_return_operand => |node_off| {1736 .node_offset_return_operand => |node_off| {
1765 const tree = try src_loc.file_scope.getTree(gpa);1737 const tree = try src_loc.file_scope.getTree(gpa);
1766 const node = src_loc.relativeToNodeIndex(node_off);1738 const node = node_off.toAbsolute(src_loc.base_node);
1767 const node_tags = tree.nodes.items(.tag);1739 if (tree.nodeTag(node) == .@"return") {
1768 const node_datas = tree.nodes.items(.data);1740 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
1769 if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) {1741 return tree.nodeToSpan(lhs);
1770 return tree.nodeToSpan(node_datas[node].lhs);1742 }
1771 }1743 }
1772 return tree.nodeToSpan(node);1744 return tree.nodeToSpan(node);
1773 },1745 },
...@@ -1777,7 +1749,7 @@ pub const SrcLoc = struct {...@@ -1777,7 +1749,7 @@ pub const SrcLoc = struct {
1777 .container_field_align,1749 .container_field_align,
1778 => |field_idx| {1750 => |field_idx| {
1779 const tree = try src_loc.file_scope.getTree(gpa);1751 const tree = try src_loc.file_scope.getTree(gpa);
1780 const node = src_loc.relativeToNodeIndex(0);1752 const node = src_loc.base_node;
1781 var buf: [2]Ast.Node.Index = undefined;1753 var buf: [2]Ast.Node.Index = undefined;
1782 const container_decl = tree.fullContainerDecl(&buf, node) orelse1754 const container_decl = tree.fullContainerDecl(&buf, node) orelse
1783 return tree.nodeToSpan(node);1755 return tree.nodeToSpan(node);
...@@ -1790,36 +1762,36 @@ pub const SrcLoc = struct {...@@ -1790,36 +1762,36 @@ pub const SrcLoc = struct {
1790 continue;1762 continue;
1791 }1763 }
1792 const field_component_node = switch (src_loc.lazy) {1764 const field_component_node = switch (src_loc.lazy) {
1793 .container_field_name => 0,1765 .container_field_name => .none,
1794 .container_field_value => field.ast.value_expr,1766 .container_field_value => field.ast.value_expr,
1795 .container_field_type => field.ast.type_expr,1767 .container_field_type => field.ast.type_expr,
1796 .container_field_align => field.ast.align_expr,1768 .container_field_align => field.ast.align_expr,
1797 else => unreachable,1769 else => unreachable,
1798 };1770 };
1799 if (field_component_node == 0) {1771 if (field_component_node.unwrap()) |component_node| {
1800 return tree.tokenToSpan(field.ast.main_token);1772 return tree.nodeToSpan(component_node);
1801 } else {1773 } else {
1802 return tree.nodeToSpan(field_component_node);1774 return tree.tokenToSpan(field.ast.main_token);
1803 }1775 }
1804 } else unreachable;1776 } else unreachable;
1805 },1777 },
1806 .tuple_field_type, .tuple_field_init => |field_info| {1778 .tuple_field_type, .tuple_field_init => |field_info| {
1807 const tree = try src_loc.file_scope.getTree(gpa);1779 const tree = try src_loc.file_scope.getTree(gpa);
1808 const node = src_loc.relativeToNodeIndex(0);1780 const node = src_loc.base_node;
1809 var buf: [2]Ast.Node.Index = undefined;1781 var buf: [2]Ast.Node.Index = undefined;
1810 const container_decl = tree.fullContainerDecl(&buf, node) orelse1782 const container_decl = tree.fullContainerDecl(&buf, node) orelse
1811 return tree.nodeToSpan(node);1783 return tree.nodeToSpan(node);
18121784
1813 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;1785 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;
1814 return tree.nodeToSpan(switch (src_loc.lazy) {1786 return tree.nodeToSpan(switch (src_loc.lazy) {
1815 .tuple_field_type => field.ast.type_expr,1787 .tuple_field_type => field.ast.type_expr.unwrap().?,
1816 .tuple_field_init => field.ast.value_expr,1788 .tuple_field_init => field.ast.value_expr.unwrap().?,
1817 else => unreachable,1789 else => unreachable,
1818 });1790 });
1819 },1791 },
1820 .init_elem => |init_elem| {1792 .init_elem => |init_elem| {
1821 const tree = try src_loc.file_scope.getTree(gpa);1793 const tree = try src_loc.file_scope.getTree(gpa);
1822 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);1794 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);
1823 var buf: [2]Ast.Node.Index = undefined;1795 var buf: [2]Ast.Node.Index = undefined;
1824 if (tree.fullArrayInit(&buf, init_node)) |full| {1796 if (tree.fullArrayInit(&buf, init_node)) |full| {
1825 const elem_node = full.ast.elements[init_elem.elem_index];1797 const elem_node = full.ast.elements[init_elem.elem_index];
...@@ -1829,7 +1801,7 @@ pub const SrcLoc = struct {...@@ -1829,7 +1801,7 @@ pub const SrcLoc = struct {
1829 return tree.tokensToSpan(1801 return tree.tokensToSpan(
1830 tree.firstToken(field_node) - 3,1802 tree.firstToken(field_node) - 3,
1831 tree.lastToken(field_node),1803 tree.lastToken(field_node),
1832 tree.nodes.items(.main_token)[field_node] - 2,1804 tree.nodeMainToken(field_node) - 2,
1833 );1805 );
1834 } else unreachable;1806 } else unreachable;
1835 },1807 },
...@@ -1858,14 +1830,10 @@ pub const SrcLoc = struct {...@@ -1858,14 +1830,10 @@ pub const SrcLoc = struct {
1858 else => unreachable,1830 else => unreachable,
1859 };1831 };
1860 const tree = try src_loc.file_scope.getTree(gpa);1832 const tree = try src_loc.file_scope.getTree(gpa);
1861 const node_datas = tree.nodes.items(.data);1833 const node = builtin_call_node.toAbsolute(src_loc.base_node);
1862 const node_tags = tree.nodes.items(.tag);1834 var builtin_buf: [2]Ast.Node.Index = undefined;
1863 const node = src_loc.relativeToNodeIndex(builtin_call_node);1835 const args = tree.builtinCallParams(&builtin_buf, node).?;
1864 const arg_node = switch (node_tags[node]) {1836 const arg_node = args[1];
1865 .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs,
1866 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1],
1867 else => unreachable,
1868 };
1869 var buf: [2]Ast.Node.Index = undefined;1837 var buf: [2]Ast.Node.Index = undefined;
1870 const full = tree.fullStructInit(&buf, arg_node) orelse1838 const full = tree.fullStructInit(&buf, arg_node) orelse
1871 return tree.nodeToSpan(arg_node);1839 return tree.nodeToSpan(arg_node);
...@@ -1877,7 +1845,7 @@ pub const SrcLoc = struct {...@@ -1877,7 +1845,7 @@ pub const SrcLoc = struct {
1877 return tree.tokensToSpan(1845 return tree.tokensToSpan(
1878 name_token - 1,1846 name_token - 1,
1879 tree.lastToken(field_node),1847 tree.lastToken(field_node),
1880 tree.nodes.items(.main_token)[field_node] - 2,1848 tree.nodeMainToken(field_node) - 2,
1881 );1849 );
1882 }1850 }
1883 }1851 }
...@@ -1901,12 +1869,9 @@ pub const SrcLoc = struct {...@@ -1901,12 +1869,9 @@ pub const SrcLoc = struct {
1901 };1869 };
19021870
1903 const tree = try src_loc.file_scope.getTree(gpa);1871 const tree = try src_loc.file_scope.getTree(gpa);
1904 const node_datas = tree.nodes.items(.data);1872 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);
1905 const node_tags = tree.nodes.items(.tag);1873 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1906 const main_tokens = tree.nodes.items(.main_token);1874 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1907 const switch_node = src_loc.relativeToNodeIndex(switch_node_offset);
1908 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1909 const case_nodes = tree.extra_data[extra.start..extra.end];
19101875
1911 var multi_i: u32 = 0;1876 var multi_i: u32 = 0;
1912 var scalar_i: u32 = 0;1877 var scalar_i: u32 = 0;
...@@ -1914,8 +1879,8 @@ pub const SrcLoc = struct {...@@ -1914,8 +1879,8 @@ pub const SrcLoc = struct {
1914 const case = tree.fullSwitchCase(case_node).?;1879 const case = tree.fullSwitchCase(case_node).?;
1915 const is_special = special: {1880 const is_special = special: {
1916 if (case.ast.values.len == 0) break :special true;1881 if (case.ast.values.len == 0) break :special true;
1917 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {1882 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) {
1918 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");1883 break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_");
1919 }1884 }
1920 break :special false;1885 break :special false;
1921 };1886 };
...@@ -1927,7 +1892,7 @@ pub const SrcLoc = struct {...@@ -1927,7 +1892,7 @@ pub const SrcLoc = struct {
1927 }1892 }
19281893
1929 const is_multi = case.ast.values.len != 1 or1894 const is_multi = case.ast.values.len != 1 or
1930 node_tags[case.ast.values[0]] == .switch_range;1895 tree.nodeTag(case.ast.values[0]) == .switch_range;
19311896
1932 switch (want_case_idx.kind) {1897 switch (want_case_idx.kind) {
1933 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,1898 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,
...@@ -1947,18 +1912,17 @@ pub const SrcLoc = struct {...@@ -1947,18 +1912,17 @@ pub const SrcLoc = struct {
1947 .switch_case_item_range_last,1912 .switch_case_item_range_last,
1948 => |x| x.item_idx,1913 => |x| x.item_idx,
1949 .switch_capture, .switch_tag_capture => {1914 .switch_capture, .switch_tag_capture => {
1950 const token_tags = tree.tokens.items(.tag);
1951 const start = switch (src_loc.lazy) {1915 const start = switch (src_loc.lazy) {
1952 .switch_capture => case.payload_token.?,1916 .switch_capture => case.payload_token.?,
1953 .switch_tag_capture => tok: {1917 .switch_tag_capture => tok: {
1954 var tok = case.payload_token.?;1918 var tok = case.payload_token.?;
1955 if (token_tags[tok] == .asterisk) tok += 1;1919 if (tree.tokenTag(tok) == .asterisk) tok += 1;
1956 tok += 2; // skip over comma1920 tok = tok + 2; // skip over comma
1957 break :tok tok;1921 break :tok tok;
1958 },1922 },
1959 else => unreachable,1923 else => unreachable,
1960 };1924 };
1961 const end = switch (token_tags[start]) {1925 const end = switch (tree.tokenTag(start)) {
1962 .asterisk => start + 1,1926 .asterisk => start + 1,
1963 else => start,1927 else => start,
1964 };1928 };
...@@ -1971,7 +1935,7 @@ pub const SrcLoc = struct {...@@ -1971,7 +1935,7 @@ pub const SrcLoc = struct {
1971 .single => {1935 .single => {
1972 var item_i: u32 = 0;1936 var item_i: u32 = 0;
1973 for (case.ast.values) |item_node| {1937 for (case.ast.values) |item_node| {
1974 if (node_tags[item_node] == .switch_range) continue;1938 if (tree.nodeTag(item_node) == .switch_range) continue;
1975 if (item_i != want_item.index) {1939 if (item_i != want_item.index) {
1976 item_i += 1;1940 item_i += 1;
1977 continue;1941 continue;
...@@ -1982,15 +1946,16 @@ pub const SrcLoc = struct {...@@ -1982,15 +1946,16 @@ pub const SrcLoc = struct {
1982 .range => {1946 .range => {
1983 var range_i: u32 = 0;1947 var range_i: u32 = 0;
1984 for (case.ast.values) |item_node| {1948 for (case.ast.values) |item_node| {
1985 if (node_tags[item_node] != .switch_range) continue;1949 if (tree.nodeTag(item_node) != .switch_range) continue;
1986 if (range_i != want_item.index) {1950 if (range_i != want_item.index) {
1987 range_i += 1;1951 range_i += 1;
1988 continue;1952 continue;
1989 }1953 }
1954 const first, const last = tree.nodeData(item_node).node_and_node;
1990 return switch (src_loc.lazy) {1955 return switch (src_loc.lazy) {
1991 .switch_case_item => tree.nodeToSpan(item_node),1956 .switch_case_item => tree.nodeToSpan(item_node),
1992 .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs),1957 .switch_case_item_range_first => tree.nodeToSpan(first),
1993 .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs),1958 .switch_case_item_range_last => tree.nodeToSpan(last),
1994 else => unreachable,1959 else => unreachable,
1995 };1960 };
1996 } else unreachable;1961 } else unreachable;
...@@ -2013,7 +1978,7 @@ pub const SrcLoc = struct {...@@ -2013,7 +1978,7 @@ pub const SrcLoc = struct {
2013 var param_it = full.iterate(tree);1978 var param_it = full.iterate(tree);
2014 for (0..param_idx) |_| assert(param_it.next() != null);1979 for (0..param_idx) |_| assert(param_it.next() != null);
2015 const param = param_it.next().?;1980 const param = param_it.next().?;
2016 return tree.nodeToSpan(param.type_expr);1981 return tree.nodeToSpan(param.type_expr.?);
2017 },1982 },
2018 }1983 }
2019 }1984 }
...@@ -2044,212 +2009,217 @@ pub const LazySrcLoc = struct {...@@ -2044,212 +2009,217 @@ pub const LazySrcLoc = struct {
2044 byte_abs: u32,2009 byte_abs: u32,
2045 /// The source location points to a token within a source file,2010 /// The source location points to a token within a source file,
2046 /// offset from 0. The source file is determined contextually.2011 /// offset from 0. The source file is determined contextually.
2047 token_abs: u32,2012 token_abs: Ast.TokenIndex,
2048 /// The source location points to an AST node within a source file,2013 /// The source location points to an AST node within a source file,
2049 /// offset from 0. The source file is determined contextually.2014 /// offset from 0. The source file is determined contextually.
2050 node_abs: u32,2015 node_abs: Ast.Node.Index,
2051 /// The source location points to a byte offset within a source file,2016 /// The source location points to a byte offset within a source file,
2052 /// offset from the byte offset of the base node within the file.2017 /// offset from the byte offset of the base node within the file.
2053 byte_offset: u32,2018 byte_offset: u32,
2054 /// This data is the offset into the token list from the base node's first token.2019 /// This data is the offset into the token list from the base node's first token.
2055 token_offset: u32,2020 token_offset: Ast.TokenOffset,
2056 /// The source location points to an AST node, which is this value offset2021 /// The source location points to an AST node, which is this value offset
2057 /// from its containing base node AST index.2022 /// from its containing base node AST index.
2058 node_offset: TracedOffset,2023 node_offset: TracedOffset,
2059 /// The source location points to the main token of an AST node, found2024 /// The source location points to the main token of an AST node, found
2060 /// by taking this AST node index offset from the containing base node.2025 /// by taking this AST node index offset from the containing base node.
2061 node_offset_main_token: i32,2026 node_offset_main_token: Ast.Node.Offset,
2062 /// The source location points to the beginning of a struct initializer.2027 /// The source location points to the beginning of a struct initializer.
2063 node_offset_initializer: i32,2028 node_offset_initializer: Ast.Node.Offset,
2064 /// The source location points to a variable declaration type expression,2029 /// The source location points to a variable declaration type expression,
2065 /// found by taking this AST node index offset from the containing2030 /// found by taking this AST node index offset from the containing
2066 /// base node, which points to a variable declaration AST node. Next, navigate2031 /// base node, which points to a variable declaration AST node. Next, navigate
2067 /// to the type expression.2032 /// to the type expression.
2068 node_offset_var_decl_ty: i32,2033 node_offset_var_decl_ty: Ast.Node.Offset,
2069 /// The source location points to the alignment expression of a var decl.2034 /// The source location points to the alignment expression of a var decl.
2070 node_offset_var_decl_align: i32,2035 node_offset_var_decl_align: Ast.Node.Offset,
2071 /// The source location points to the linksection expression of a var decl.2036 /// The source location points to the linksection expression of a var decl.
2072 node_offset_var_decl_section: i32,2037 node_offset_var_decl_section: Ast.Node.Offset,
2073 /// The source location points to the addrspace expression of a var decl.2038 /// The source location points to the addrspace expression of a var decl.
2074 node_offset_var_decl_addrspace: i32,2039 node_offset_var_decl_addrspace: Ast.Node.Offset,
2075 /// The source location points to the initializer of a var decl.2040 /// The source location points to the initializer of a var decl.
2076 node_offset_var_decl_init: i32,2041 node_offset_var_decl_init: Ast.Node.Offset,
2077 /// The source location points to the given argument of a builtin function call.2042 /// The source location points to the given argument of a builtin function call.
2078 /// `builtin_call_node` points to the builtin call.2043 /// `builtin_call_node` points to the builtin call.
2079 /// `arg_index` is the index of the argument which hte source location refers to.2044 /// `arg_index` is the index of the argument which hte source location refers to.
2080 node_offset_builtin_call_arg: struct {2045 node_offset_builtin_call_arg: struct {
2081 builtin_call_node: i32,2046 builtin_call_node: Ast.Node.Offset,
2082 arg_index: u32,2047 arg_index: u32,
2083 },2048 },
2084 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls2049 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls
2085 /// to pointer cast builtins (taking the first argument of the most nested).2050 /// to pointer cast builtins (taking the first argument of the most nested).
2086 node_offset_ptrcast_operand: i32,2051 node_offset_ptrcast_operand: Ast.Node.Offset,
2087 /// The source location points to the index expression of an array access2052 /// The source location points to the index expression of an array access
2088 /// expression, found by taking this AST node index offset from the containing2053 /// expression, found by taking this AST node index offset from the containing
2089 /// base node, which points to an array access AST node. Next, navigate2054 /// base node, which points to an array access AST node. Next, navigate
2090 /// to the index expression.2055 /// to the index expression.
2091 node_offset_array_access_index: i32,2056 node_offset_array_access_index: Ast.Node.Offset,
2092 /// The source location points to the LHS of a slice expression2057 /// The source location points to the LHS of a slice expression
2093 /// expression, found by taking this AST node index offset from the containing2058 /// expression, found by taking this AST node index offset from the containing
2094 /// base node, which points to a slice AST node. Next, navigate2059 /// base node, which points to a slice AST node. Next, navigate
2095 /// to the sentinel expression.2060 /// to the sentinel expression.
2096 node_offset_slice_ptr: i32,2061 node_offset_slice_ptr: Ast.Node.Offset,
2097 /// The source location points to start expression of a slice expression2062 /// The source location points to start expression of a slice expression
2098 /// expression, found by taking this AST node index offset from the containing2063 /// expression, found by taking this AST node index offset from the containing
2099 /// base node, which points to a slice AST node. Next, navigate2064 /// base node, which points to a slice AST node. Next, navigate
2100 /// to the sentinel expression.2065 /// to the sentinel expression.
2101 node_offset_slice_start: i32,2066 node_offset_slice_start: Ast.Node.Offset,
2102 /// The source location points to the end expression of a slice2067 /// The source location points to the end expression of a slice
2103 /// expression, found by taking this AST node index offset from the containing2068 /// expression, found by taking this AST node index offset from the containing
2104 /// base node, which points to a slice AST node. Next, navigate2069 /// base node, which points to a slice AST node. Next, navigate
2105 /// to the sentinel expression.2070 /// to the sentinel expression.
2106 node_offset_slice_end: i32,2071 node_offset_slice_end: Ast.Node.Offset,
2107 /// The source location points to the sentinel expression of a slice2072 /// The source location points to the sentinel expression of a slice
2108 /// expression, found by taking this AST node index offset from the containing2073 /// expression, found by taking this AST node index offset from the containing
2109 /// base node, which points to a slice AST node. Next, navigate2074 /// base node, which points to a slice AST node. Next, navigate
2110 /// to the sentinel expression.2075 /// to the sentinel expression.
2111 node_offset_slice_sentinel: i32,2076 node_offset_slice_sentinel: Ast.Node.Offset,
2112 /// The source location points to the callee expression of a function2077 /// The source location points to the callee expression of a function
2113 /// call expression, found by taking this AST node index offset from the containing2078 /// call expression, found by taking this AST node index offset from the containing
2114 /// base node, which points to a function call AST node. Next, navigate2079 /// base node, which points to a function call AST node. Next, navigate
2115 /// to the callee expression.2080 /// to the callee expression.
2116 node_offset_call_func: i32,2081 node_offset_call_func: Ast.Node.Offset,
2117 /// The payload is offset from the containing base node.2082 /// The payload is offset from the containing base node.
2118 /// The source location points to the field name of:2083 /// The source location points to the field name of:
2119 /// * a field access expression (`a.b`), or2084 /// * a field access expression (`a.b`), or
2120 /// * the callee of a method call (`a.b()`)2085 /// * the callee of a method call (`a.b()`)
2121 node_offset_field_name: i32,2086 node_offset_field_name: Ast.Node.Offset,
2122 /// The payload is offset from the containing base node.2087 /// The payload is offset from the containing base node.
2123 /// The source location points to the field name of the operand ("b" node)2088 /// The source location points to the field name of the operand ("b" node)
2124 /// of a field initialization expression (`.a = b`)2089 /// of a field initialization expression (`.a = b`)
2125 node_offset_field_name_init: i32,2090 node_offset_field_name_init: Ast.Node.Offset,
2126 /// The source location points to the pointer of a pointer deref expression,2091 /// The source location points to the pointer of a pointer deref expression,
2127 /// found by taking this AST node index offset from the containing2092 /// found by taking this AST node index offset from the containing
2128 /// base node, which points to a pointer deref AST node. Next, navigate2093 /// base node, which points to a pointer deref AST node. Next, navigate
2129 /// to the pointer expression.2094 /// to the pointer expression.
2130 node_offset_deref_ptr: i32,2095 node_offset_deref_ptr: Ast.Node.Offset,
2131 /// The source location points to the assembly source code of an inline assembly2096 /// The source location points to the assembly source code of an inline assembly
2132 /// expression, found by taking this AST node index offset from the containing2097 /// expression, found by taking this AST node index offset from the containing
2133 /// base node, which points to inline assembly AST node. Next, navigate2098 /// base node, which points to inline assembly AST node. Next, navigate
2134 /// to the asm template source code.2099 /// to the asm template source code.
2135 node_offset_asm_source: i32,2100 node_offset_asm_source: Ast.Node.Offset,
2136 /// The source location points to the return type of an inline assembly2101 /// The source location points to the return type of an inline assembly
2137 /// expression, found by taking this AST node index offset from the containing2102 /// expression, found by taking this AST node index offset from the containing
2138 /// base node, which points to inline assembly AST node. Next, navigate2103 /// base node, which points to inline assembly AST node. Next, navigate
2139 /// to the return type expression.2104 /// to the return type expression.
2140 node_offset_asm_ret_ty: i32,2105 node_offset_asm_ret_ty: Ast.Node.Offset,
2141 /// The source location points to the condition expression of an if2106 /// The source location points to the condition expression of an if
2142 /// expression, found by taking this AST node index offset from the containing2107 /// expression, found by taking this AST node index offset from the containing
2143 /// base node, which points to an if expression AST node. Next, navigate2108 /// base node, which points to an if expression AST node. Next, navigate
2144 /// to the condition expression.2109 /// to the condition expression.
2145 node_offset_if_cond: i32,2110 node_offset_if_cond: Ast.Node.Offset,
2146 /// The source location points to a binary expression, such as `a + b`, found2111 /// The source location points to a binary expression, such as `a + b`, found
2147 /// by taking this AST node index offset from the containing base node.2112 /// by taking this AST node index offset from the containing base node.
2148 node_offset_bin_op: i32,2113 node_offset_bin_op: Ast.Node.Offset,
2149 /// The source location points to the LHS of a binary expression, found2114 /// The source location points to the LHS of a binary expression, found
2150 /// by taking this AST node index offset from the containing base node,2115 /// by taking this AST node index offset from the containing base node,
2151 /// which points to a binary expression AST node. Next, navigate to the LHS.2116 /// which points to a binary expression AST node. Next, navigate to the LHS.
2152 node_offset_bin_lhs: i32,2117 node_offset_bin_lhs: Ast.Node.Offset,
2153 /// The source location points to the RHS of a binary expression, found2118 /// The source location points to the RHS of a binary expression, found
2154 /// by taking this AST node index offset from the containing base node,2119 /// by taking this AST node index offset from the containing base node,
2155 /// which points to a binary expression AST node. Next, navigate to the RHS.2120 /// which points to a binary expression AST node. Next, navigate to the RHS.
2156 node_offset_bin_rhs: i32,2121 node_offset_bin_rhs: Ast.Node.Offset,
2122 /// The source location points to the operand of a try expression, found
2123 /// by taking this AST node index offset from the containing base node,
2124 /// which points to a try expression AST node. Next, navigate to the
2125 /// operand expression.
2126 node_offset_try_operand: Ast.Node.Offset,
2157 /// The source location points to the operand of a switch expression, found2127 /// The source location points to the operand of a switch expression, found
2158 /// by taking this AST node index offset from the containing base node,2128 /// by taking this AST node index offset from the containing base node,
2159 /// which points to a switch expression AST node. Next, navigate to the operand.2129 /// which points to a switch expression AST node. Next, navigate to the operand.
2160 node_offset_switch_operand: i32,2130 node_offset_switch_operand: Ast.Node.Offset,
2161 /// The source location points to the else/`_` prong of a switch expression, found2131 /// The source location points to the else/`_` prong of a switch expression, found
2162 /// by taking this AST node index offset from the containing base node,2132 /// by taking this AST node index offset from the containing base node,
2163 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.2133 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.
2164 node_offset_switch_special_prong: i32,2134 node_offset_switch_special_prong: Ast.Node.Offset,
2165 /// The source location points to all the ranges of a switch expression, found2135 /// The source location points to all the ranges of a switch expression, found
2166 /// by taking this AST node index offset from the containing base node,2136 /// by taking this AST node index offset from the containing base node,
2167 /// which points to a switch expression AST node. Next, navigate to any of the2137 /// which points to a switch expression AST node. Next, navigate to any of the
2168 /// range nodes. The error applies to all of them.2138 /// range nodes. The error applies to all of them.
2169 node_offset_switch_range: i32,2139 node_offset_switch_range: Ast.Node.Offset,
2170 /// The source location points to the align expr of a function type2140 /// The source location points to the align expr of a function type
2171 /// expression, found by taking this AST node index offset from the containing2141 /// expression, found by taking this AST node index offset from the containing
2172 /// base node, which points to a function type AST node. Next, navigate to2142 /// base node, which points to a function type AST node. Next, navigate to
2173 /// the calling convention node.2143 /// the calling convention node.
2174 node_offset_fn_type_align: i32,2144 node_offset_fn_type_align: Ast.Node.Offset,
2175 /// The source location points to the addrspace expr of a function type2145 /// The source location points to the addrspace expr of a function type
2176 /// expression, found by taking this AST node index offset from the containing2146 /// expression, found by taking this AST node index offset from the containing
2177 /// base node, which points to a function type AST node. Next, navigate to2147 /// base node, which points to a function type AST node. Next, navigate to
2178 /// the calling convention node.2148 /// the calling convention node.
2179 node_offset_fn_type_addrspace: i32,2149 node_offset_fn_type_addrspace: Ast.Node.Offset,
2180 /// The source location points to the linksection expr of a function type2150 /// The source location points to the linksection expr of a function type
2181 /// expression, found by taking this AST node index offset from the containing2151 /// expression, found by taking this AST node index offset from the containing
2182 /// base node, which points to a function type AST node. Next, navigate to2152 /// base node, which points to a function type AST node. Next, navigate to
2183 /// the calling convention node.2153 /// the calling convention node.
2184 node_offset_fn_type_section: i32,2154 node_offset_fn_type_section: Ast.Node.Offset,
2185 /// The source location points to the calling convention of a function type2155 /// The source location points to the calling convention of a function type
2186 /// expression, found by taking this AST node index offset from the containing2156 /// expression, found by taking this AST node index offset from the containing
2187 /// base node, which points to a function type AST node. Next, navigate to2157 /// base node, which points to a function type AST node. Next, navigate to
2188 /// the calling convention node.2158 /// the calling convention node.
2189 node_offset_fn_type_cc: i32,2159 node_offset_fn_type_cc: Ast.Node.Offset,
2190 /// The source location points to the return type of a function type2160 /// The source location points to the return type of a function type
2191 /// expression, found by taking this AST node index offset from the containing2161 /// expression, found by taking this AST node index offset from the containing
2192 /// base node, which points to a function type AST node. Next, navigate to2162 /// base node, which points to a function type AST node. Next, navigate to
2193 /// the return type node.2163 /// the return type node.
2194 node_offset_fn_type_ret_ty: i32,2164 node_offset_fn_type_ret_ty: Ast.Node.Offset,
2195 node_offset_param: i32,2165 node_offset_param: Ast.Node.Offset,
2196 token_offset_param: i32,2166 token_offset_param: Ast.TokenOffset,
2197 /// The source location points to the type expression of an `anyframe->T`2167 /// The source location points to the type expression of an `anyframe->T`
2198 /// expression, found by taking this AST node index offset from the containing2168 /// expression, found by taking this AST node index offset from the containing
2199 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate2169 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate
2200 /// to the type expression.2170 /// to the type expression.
2201 node_offset_anyframe_type: i32,2171 node_offset_anyframe_type: Ast.Node.Offset,
2202 /// The source location points to the string literal of `extern "foo"`, found2172 /// The source location points to the string literal of `extern "foo"`, found
2203 /// by taking this AST node index offset from the containing2173 /// by taking this AST node index offset from the containing
2204 /// base node, which points to a function prototype or variable declaration2174 /// base node, which points to a function prototype or variable declaration
2205 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.2175 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
2206 node_offset_lib_name: i32,2176 node_offset_lib_name: Ast.Node.Offset,
2207 /// The source location points to the len expression of an `[N:S]T`2177 /// The source location points to the len expression of an `[N:S]T`
2208 /// expression, found by taking this AST node index offset from the containing2178 /// expression, found by taking this AST node index offset from the containing
2209 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2179 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2210 /// to the len expression.2180 /// to the len expression.
2211 node_offset_array_type_len: i32,2181 node_offset_array_type_len: Ast.Node.Offset,
2212 /// The source location points to the sentinel expression of an `[N:S]T`2182 /// The source location points to the sentinel expression of an `[N:S]T`
2213 /// expression, found by taking this AST node index offset from the containing2183 /// expression, found by taking this AST node index offset from the containing
2214 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2184 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2215 /// to the sentinel expression.2185 /// to the sentinel expression.
2216 node_offset_array_type_sentinel: i32,2186 node_offset_array_type_sentinel: Ast.Node.Offset,
2217 /// The source location points to the elem expression of an `[N:S]T`2187 /// The source location points to the elem expression of an `[N:S]T`
2218 /// expression, found by taking this AST node index offset from the containing2188 /// expression, found by taking this AST node index offset from the containing
2219 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2189 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2220 /// to the elem expression.2190 /// to the elem expression.
2221 node_offset_array_type_elem: i32,2191 node_offset_array_type_elem: Ast.Node.Offset,
2222 /// The source location points to the operand of an unary expression.2192 /// The source location points to the operand of an unary expression.
2223 node_offset_un_op: i32,2193 node_offset_un_op: Ast.Node.Offset,
2224 /// The source location points to the elem type of a pointer.2194 /// The source location points to the elem type of a pointer.
2225 node_offset_ptr_elem: i32,2195 node_offset_ptr_elem: Ast.Node.Offset,
2226 /// The source location points to the sentinel of a pointer.2196 /// The source location points to the sentinel of a pointer.
2227 node_offset_ptr_sentinel: i32,2197 node_offset_ptr_sentinel: Ast.Node.Offset,
2228 /// The source location points to the align expr of a pointer.2198 /// The source location points to the align expr of a pointer.
2229 node_offset_ptr_align: i32,2199 node_offset_ptr_align: Ast.Node.Offset,
2230 /// The source location points to the addrspace expr of a pointer.2200 /// The source location points to the addrspace expr of a pointer.
2231 node_offset_ptr_addrspace: i32,2201 node_offset_ptr_addrspace: Ast.Node.Offset,
2232 /// The source location points to the bit-offset of a pointer.2202 /// The source location points to the bit-offset of a pointer.
2233 node_offset_ptr_bitoffset: i32,2203 node_offset_ptr_bitoffset: Ast.Node.Offset,
2234 /// The source location points to the host size of a pointer.2204 /// The source location points to the host size of a pointer.
2235 node_offset_ptr_hostsize: i32,2205 node_offset_ptr_hostsize: Ast.Node.Offset,
2236 /// The source location points to the tag type of an union or an enum.2206 /// The source location points to the tag type of an union or an enum.
2237 node_offset_container_tag: i32,2207 node_offset_container_tag: Ast.Node.Offset,
2238 /// The source location points to the default value of a field.2208 /// The source location points to the default value of a field.
2239 node_offset_field_default: i32,2209 node_offset_field_default: Ast.Node.Offset,
2240 /// The source location points to the type of an array or struct initializer.2210 /// The source location points to the type of an array or struct initializer.
2241 node_offset_init_ty: i32,2211 node_offset_init_ty: Ast.Node.Offset,
2242 /// The source location points to the LHS of an assignment.2212 /// The source location points to the LHS of an assignment.
2243 node_offset_store_ptr: i32,2213 node_offset_store_ptr: Ast.Node.Offset,
2244 /// The source location points to the RHS of an assignment.2214 /// The source location points to the RHS of an assignment.
2245 node_offset_store_operand: i32,2215 node_offset_store_operand: Ast.Node.Offset,
2246 /// The source location points to the operand of a `return` statement, or2216 /// The source location points to the operand of a `return` statement, or
2247 /// the `return` itself if there is no explicit operand.2217 /// the `return` itself if there is no explicit operand.
2248 node_offset_return_operand: i32,2218 node_offset_return_operand: Ast.Node.Offset,
2249 /// The source location points to a for loop input.2219 /// The source location points to a for loop input.
2250 for_input: struct {2220 for_input: struct {
2251 /// Points to the for loop AST node.2221 /// Points to the for loop AST node.
2252 for_node_offset: i32,2222 for_node_offset: Ast.Node.Offset,
2253 /// Picks one of the inputs from the condition.2223 /// Picks one of the inputs from the condition.
2254 input_index: u32,2224 input_index: u32,
2255 },2225 },
...@@ -2257,11 +2227,11 @@ pub const LazySrcLoc = struct {...@@ -2257,11 +2227,11 @@ pub const LazySrcLoc = struct {
2257 /// by taking this AST node index offset from the containing2227 /// by taking this AST node index offset from the containing
2258 /// base node, which points to one of the input nodes of a for loop.2228 /// base node, which points to one of the input nodes of a for loop.
2259 /// Next, navigate to the corresponding capture.2229 /// Next, navigate to the corresponding capture.
2260 for_capture_from_input: i32,2230 for_capture_from_input: Ast.Node.Offset,
2261 /// The source location points to the argument node of a function call.2231 /// The source location points to the argument node of a function call.
2262 call_arg: struct {2232 call_arg: struct {
2263 /// Points to the function call AST node.2233 /// Points to the function call AST node.
2264 call_node_offset: i32,2234 call_node_offset: Ast.Node.Offset,
2265 /// The index of the argument the source location points to.2235 /// The index of the argument the source location points to.
2266 arg_index: u32,2236 arg_index: u32,
2267 },2237 },
...@@ -2288,25 +2258,25 @@ pub const LazySrcLoc = struct {...@@ -2288,25 +2258,25 @@ pub const LazySrcLoc = struct {
2288 /// array initialization expression.2258 /// array initialization expression.
2289 init_elem: struct {2259 init_elem: struct {
2290 /// Points to the AST node of the initialization expression.2260 /// Points to the AST node of the initialization expression.
2291 init_node_offset: i32,2261 init_node_offset: Ast.Node.Offset,
2292 /// The index of the field/element the source location points to.2262 /// The index of the field/element the source location points to.
2293 elem_index: u32,2263 elem_index: u32,
2294 },2264 },
2295 // The following source locations are like `init_elem`, but refer to a2265 // The following source locations are like `init_elem`, but refer to a
2296 // field with a specific name. If such a field is not given, the entire2266 // field with a specific name. If such a field is not given, the entire
2297 // initialization expression is used instead.2267 // initialization expression is used instead.
2298 // The `i32` points to the AST node of a builtin call, whose *second*2268 // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second*
2299 // argument is the init expression.2269 // argument is the init expression.
2300 init_field_name: i32,2270 init_field_name: Ast.Node.Offset,
2301 init_field_linkage: i32,2271 init_field_linkage: Ast.Node.Offset,
2302 init_field_section: i32,2272 init_field_section: Ast.Node.Offset,
2303 init_field_visibility: i32,2273 init_field_visibility: Ast.Node.Offset,
2304 init_field_rw: i32,2274 init_field_rw: Ast.Node.Offset,
2305 init_field_locality: i32,2275 init_field_locality: Ast.Node.Offset,
2306 init_field_cache: i32,2276 init_field_cache: Ast.Node.Offset,
2307 init_field_library: i32,2277 init_field_library: Ast.Node.Offset,
2308 init_field_thread_local: i32,2278 init_field_thread_local: Ast.Node.Offset,
2309 init_field_dll_import: i32,2279 init_field_dll_import: Ast.Node.Offset,
2310 /// The source location points to the value of an item in a specific2280 /// The source location points to the value of an item in a specific
2311 /// case of a `switch`.2281 /// case of a `switch`.
2312 switch_case_item: SwitchItem,2282 switch_case_item: SwitchItem,
...@@ -2331,14 +2301,14 @@ pub const LazySrcLoc = struct {...@@ -2331,14 +2301,14 @@ pub const LazySrcLoc = struct {
23312301
2332 pub const FnProtoParam = struct {2302 pub const FnProtoParam = struct {
2333 /// The offset of the function prototype AST node.2303 /// The offset of the function prototype AST node.
2334 fn_proto_node_offset: i32,2304 fn_proto_node_offset: Ast.Node.Offset,
2335 /// The index of the parameter the source location points to.2305 /// The index of the parameter the source location points to.
2336 param_index: u32,2306 param_index: u32,
2337 };2307 };
23382308
2339 pub const SwitchItem = struct {2309 pub const SwitchItem = struct {
2340 /// The offset of the switch AST node.2310 /// The offset of the switch AST node.
2341 switch_node_offset: i32,2311 switch_node_offset: Ast.Node.Offset,
2342 /// The index of the case to point to within this switch.2312 /// The index of the case to point to within this switch.
2343 case_idx: SwitchCaseIndex,2313 case_idx: SwitchCaseIndex,
2344 /// The index of the item to point to within this case.2314 /// The index of the item to point to within this case.
...@@ -2347,7 +2317,7 @@ pub const LazySrcLoc = struct {...@@ -2347,7 +2317,7 @@ pub const LazySrcLoc = struct {
23472317
2348 pub const SwitchCapture = struct {2318 pub const SwitchCapture = struct {
2349 /// The offset of the switch AST node.2319 /// The offset of the switch AST node.
2350 switch_node_offset: i32,2320 switch_node_offset: Ast.Node.Offset,
2351 /// The index of the case whose capture to point to.2321 /// The index of the case whose capture to point to.
2352 case_idx: SwitchCaseIndex,2322 case_idx: SwitchCaseIndex,
2353 };2323 };
...@@ -2369,34 +2339,34 @@ pub const LazySrcLoc = struct {...@@ -2369,34 +2339,34 @@ pub const LazySrcLoc = struct {
23692339
2370 pub const ArrayCat = struct {2340 pub const ArrayCat = struct {
2371 /// Points to the array concat AST node.2341 /// Points to the array concat AST node.
2372 array_cat_offset: i32,2342 array_cat_offset: Ast.Node.Offset,
2373 /// The index of the element the source location points to.2343 /// The index of the element the source location points to.
2374 elem_index: u32,2344 elem_index: u32,
2375 };2345 };
23762346
2377 pub const TupleField = struct {2347 pub const TupleField = struct {
2378 /// Points to the AST node of the tuple type decaration.2348 /// Points to the AST node of the tuple type decaration.
2379 tuple_decl_node_offset: i32,2349 tuple_decl_node_offset: Ast.Node.Offset,
2380 /// The index of the tuple field the source location points to.2350 /// The index of the tuple field the source location points to.
2381 elem_index: u32,2351 elem_index: u32,
2382 };2352 };
23832353
2384 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2354 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23852355
2386 noinline fn nodeOffsetDebug(node_offset: i32) Offset {2356 noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset {
2387 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };2357 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
2388 result.node_offset.trace.addAddr(@returnAddress(), "init");2358 result.node_offset.trace.addAddr(@returnAddress(), "init");
2389 return result;2359 return result;
2390 }2360 }
23912361
2392 fn nodeOffsetRelease(node_offset: i32) Offset {2362 fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset {
2393 return .{ .node_offset = .{ .x = node_offset } };2363 return .{ .node_offset = .{ .x = node_offset } };
2394 }2364 }
23952365
2396 /// This wraps a simple integer in debug builds so that later on we can find out2366 /// This wraps a simple integer in debug builds so that later on we can find out
2397 /// where in semantic analysis the value got set.2367 /// where in semantic analysis the value got set.
2398 pub const TracedOffset = struct {2368 pub const TracedOffset = struct {
2399 x: i32,2369 x: Ast.Node.Offset,
2400 trace: std.debug.Trace = std.debug.Trace.init,2370 trace: std.debug.Trace = std.debug.Trace.init,
24012371
2402 const want_tracing = false;2372 const want_tracing = false;
...@@ -2421,7 +2391,7 @@ pub const LazySrcLoc = struct {...@@ -2421,7 +2391,7 @@ pub const LazySrcLoc = struct {
24212391
2422 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,2392 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,
2423 // which may not exist e.g. in the case of errors in ZON files.2393 // which may not exist e.g. in the case of errors in ZON files.
2424 if (zir_inst == .main_struct_inst) return .{ file, 0 };2394 if (zir_inst == .main_struct_inst) return .{ file, .root };
24252395
2426 // Otherwise, make sure ZIR is loaded.2396 // Otherwise, make sure ZIR is loaded.
2427 const zir = file.zir.?;2397 const zir = file.zir.?;
...@@ -2454,7 +2424,7 @@ pub const LazySrcLoc = struct {...@@ -2454,7 +2424,7 @@ pub const LazySrcLoc = struct {
2454 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {2424 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {
2455 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{2425 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{
2456 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),2426 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),
2457 0,2427 .root,
2458 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;2428 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
2459 return .{2429 return .{
2460 .file_scope = file,2430 .file_scope = file,
...@@ -4023,7 +3993,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {...@@ -4023,7 +3993,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {
4023 const ip = &zcu.intern_pool;3993 const ip = &zcu.intern_pool;
4024 return .{3994 return .{
4025 .base_node_inst = ip.getNav(nav_index).srcInst(ip),3995 .base_node_inst = ip.getNav(nav_index).srcInst(ip),
4026 .offset = LazySrcLoc.Offset.nodeOffset(0),3996 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
4027 };3997 };
4028}3998}
40293999
src/Zcu/PerThread.zig+11-11
...@@ -841,7 +841,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu...@@ -841,7 +841,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
841 .comptime_reason = .{ .reason = .{841 .comptime_reason = .{ .reason = .{
842 .src = .{842 .src = .{
843 .base_node_inst = comptime_unit.zir_index,843 .base_node_inst = comptime_unit.zir_index,
844 .offset = .{ .token_offset = 0 },844 .offset = .{ .token_offset = .zero },
845 },845 },
846 .r = .{ .simple = .comptime_keyword },846 .r = .{ .simple = .comptime_keyword },
847 } },847 } },
...@@ -1042,11 +1042,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1042,11 +1042,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1042 const zir_decl = zir.getDeclaration(inst_resolved.inst);1042 const zir_decl = zir.getDeclaration(inst_resolved.inst);
1043 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));1043 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
10441044
1045 const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });1045 const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero });
1046 const init_src = block.src(.{ .node_offset_var_decl_init = 0 });1046 const init_src = block.src(.{ .node_offset_var_decl_init = .zero });
1047 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });1047 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
1048 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });1048 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
1049 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });1049 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
10501050
1051 block.comptime_reason = .{ .reason = .{1051 block.comptime_reason = .{ .reason = .{
1052 .src = init_src,1052 .src = init_src,
...@@ -1135,7 +1135,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1135,7 +1135,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1135 break :l zir.nullTerminatedString(zir_decl.lib_name);1135 break :l zir.nullTerminatedString(zir_decl.lib_name);
1136 } else null;1136 } else null;
1137 if (lib_name) |l| {1137 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 });
1139 try sema.handleExternLibName(&block, lib_name_src, l);1139 try sema.handleExternLibName(&block, lib_name_src, l);
1140 }1140 }
1141 break :val .fromInterned(try pt.getExtern(.{1141 break :val .fromInterned(try pt.getExtern(.{
...@@ -1233,7 +1233,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1233,7 +1233,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1233 }1233 }
12341234
1235 if (zir_decl.linkage == .@"export") {1235 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)) });
1237 const name_slice = zir.nullTerminatedString(zir_decl.name);1237 const name_slice = zir.nullTerminatedString(zir_decl.name);
1238 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);1238 const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls);
1239 try sema.analyzeExport(&block, export_src, .{ .name = name_ip }, nav_id);1239 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...@@ -1414,7 +1414,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
1414 const zir_decl = zir.getDeclaration(inst_resolved.inst);1414 const zir_decl = zir.getDeclaration(inst_resolved.inst);
1415 assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));1415 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
1419 block.comptime_reason = .{ .reason = .{1419 block.comptime_reason = .{ .reason = .{
1420 .src = ty_src,1420 .src = ty_src,
...@@ -2743,7 +2743,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2743,7 +2743,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2743 if (sema.fn_ret_ty_ies) |ies| {2743 if (sema.fn_ret_ty_ies) |ies| {
2744 sema.resolveInferredErrorSetPtr(&inner_block, .{2744 sema.resolveInferredErrorSetPtr(&inner_block, .{
2745 .base_node_inst = inner_block.src_base_inst,2745 .base_node_inst = inner_block.src_base_inst,
2746 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0),2746 .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero),
2747 }, ies) catch |err| switch (err) {2747 }, ies) catch |err| switch (err) {
2748 error.ComptimeReturn => unreachable,2748 error.ComptimeReturn => unreachable,
2749 error.ComptimeBreak => unreachable,2749 error.ComptimeBreak => unreachable,
...@@ -2762,7 +2762,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE...@@ -2762,7 +2762,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
2762 // result in circular dependency errors.2762 // result in circular dependency errors.
2763 // TODO: this can go away once we fix backends having to resolve `StackTrace`.2763 // TODO: this can go away once we fix backends having to resolve `StackTrace`.
2764 // The codegen timing guarantees that the parameter types will be populated.2764 // 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) {
2766 error.ComptimeReturn => unreachable,2766 error.ComptimeReturn => unreachable,
2767 error.ComptimeBreak => unreachable,2767 error.ComptimeBreak => unreachable,
2768 else => |e| return e,2768 else => |e| return e,
src/main.zig+13-7
...@@ -5224,7 +5224,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5224,7 +5224,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5224 .arena = std.heap.ArenaAllocator.init(gpa),5224 .arena = std.heap.ArenaAllocator.init(gpa),
5225 .location = .{ .relative_path = build_mod.root },5225 .location = .{ .relative_path = build_mod.root },
5226 .location_tok = 0,5226 .location_tok = 0,
5227 .hash_tok = 0,5227 .hash_tok = .none,
5228 .name_tok = 0,5228 .name_tok = 0,
5229 .lazy_status = .eager,5229 .lazy_status = .eager,
5230 .parent_package_root = build_mod.root,5230 .parent_package_root = build_mod.root,
...@@ -6285,8 +6285,10 @@ fn cmdAstCheck(...@@ -6285,8 +6285,10 @@ fn cmdAstCheck(
6285 file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset));6285 file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset));
6286 const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len *6286 const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len *
6287 (@sizeOf(Ast.Node.Tag) +6287 (@sizeOf(Ast.Node.Tag) +
6288 @sizeOf(Ast.Node.Data) +6288 @sizeOf(Ast.TokenIndex) +
6289 @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);
6290 const instruction_bytes = file.zir.?.instructions.len *6292 const instruction_bytes = file.zir.?.instructions.len *
6291 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include6293 // Here we don't use @sizeOf(Zir.Inst.Data) because it would include
6292 // the debug safety tag but we want to measure release size.6294 // the debug safety tag but we want to measure release size.
...@@ -7126,7 +7128,7 @@ fn cmdFetch(...@@ -7126,7 +7128,7 @@ fn cmdFetch(
7126 .arena = std.heap.ArenaAllocator.init(gpa),7128 .arena = std.heap.ArenaAllocator.init(gpa),
7127 .location = .{ .path_or_url = path_or_url },7129 .location = .{ .path_or_url = path_or_url },
7128 .location_tok = 0,7130 .location_tok = 0,
7129 .hash_tok = 0,7131 .hash_tok = .none,
7130 .name_tok = 0,7132 .name_tok = 0,
7131 .lazy_status = .eager,7133 .lazy_status = .eager,
7132 .parent_package_root = undefined,7134 .parent_package_root = undefined,
...@@ -7282,15 +7284,19 @@ fn cmdFetch(...@@ -7282,15 +7284,19 @@ fn cmdFetch(
72827284
7283 warn("overwriting existing dependency named '{s}'", .{name});7285 warn("overwriting existing dependency named '{s}'", .{name});
7284 try fixups.replace_nodes_with_string.put(gpa, dep.location_node, location_replace);7286 try fixups.replace_nodes_with_string.put(gpa, dep.location_node, location_replace);
7285 try fixups.replace_nodes_with_string.put(gpa, dep.hash_node, hash_replace);7287 if (dep.hash_node.unwrap()) |hash_node| {
7288 try fixups.replace_nodes_with_string.put(gpa, hash_node, hash_replace);
7289 } else {
7290 // https://github.com/ziglang/zig/issues/21690
7291 }
7286 } else if (manifest.dependencies.count() > 0) {7292 } else if (manifest.dependencies.count() > 0) {
7287 // Add fixup for adding another dependency.7293 // Add fixup for adding another dependency.
7288 const deps = manifest.dependencies.values();7294 const deps = manifest.dependencies.values();
7289 const last_dep_node = deps[deps.len - 1].node;7295 const last_dep_node = deps[deps.len - 1].node;
7290 try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text);7296 try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text);
7291 } else if (manifest.dependencies_node != 0) {7297 } else if (manifest.dependencies_node.unwrap()) |dependencies_node| {
7292 // Add fixup for replacing the entire dependencies struct.7298 // Add fixup for replacing the entire dependencies struct.
7293 try fixups.replace_nodes_with_string.put(gpa, manifest.dependencies_node, dependencies_init);7299 try fixups.replace_nodes_with_string.put(gpa, dependencies_node, dependencies_init);
7294 } else {7300 } else {
7295 // Add fixup for adding dependencies struct.7301 // Add fixup for adding dependencies struct.
7296 try fixups.append_string_after_node.put(gpa, manifest.version_node, dependencies_text);7302 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(...@@ -24,7 +24,7 @@ pub fn renderAsTextToFile(
24 .file = scope_file,24 .file = scope_file,
25 .code = scope_file.zir.?,25 .code = scope_file.zir.?,
26 .indent = 0,26 .indent = 0,
27 .parent_decl_node = 0,27 .parent_decl_node = .root,
28 .recurse_decls = true,28 .recurse_decls = true,
29 .recurse_blocks = true,29 .recurse_blocks = true,
30 };30 };
...@@ -185,10 +185,6 @@ const Writer = struct {...@@ -185,10 +185,6 @@ const Writer = struct {
185 }185 }
186 } = .{},186 } = .{},
187187
188 fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index {
189 return @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node)));
190 }
191
192 fn writeInstToStream(188 fn writeInstToStream(
193 self: *Writer,189 self: *Writer,
194 stream: anytype,190 stream: anytype,
...@@ -595,7 +591,7 @@ const Writer = struct {...@@ -595,7 +591,7 @@ const Writer = struct {
595 const prev_parent_decl_node = self.parent_decl_node;591 const prev_parent_decl_node = self.parent_decl_node;
596 self.parent_decl_node = inst_data.node;592 self.parent_decl_node = inst_data.node;
597 defer self.parent_decl_node = prev_parent_decl_node;593 defer self.parent_decl_node = prev_parent_decl_node;
598 try self.writeSrcNode(stream, 0);594 try self.writeSrcNode(stream, .zero);
599 },595 },
600596
601 .builtin_extern,597 .builtin_extern,
...@@ -631,7 +627,8 @@ const Writer = struct {...@@ -631,7 +627,8 @@ const Writer = struct {
631627
632 fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {628 fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
633 try stream.writeAll(")) ");629 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);
635 }632 }
636633
637 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {634 fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
...@@ -1579,7 +1576,7 @@ const Writer = struct {...@@ -1579,7 +1576,7 @@ const Writer = struct {
1579 try stream.writeByteNTimes(' ', self.indent);1576 try stream.writeByteNTimes(' ', self.indent);
1580 try stream.writeAll("}) ");1577 try stream.writeAll("}) ");
1581 }1578 }
1582 try self.writeSrcNode(stream, 0);1579 try self.writeSrcNode(stream, .zero);
1583 }1580 }
15841581
1585 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1582 fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
...@@ -1659,7 +1656,7 @@ const Writer = struct {...@@ -1659,7 +1656,7 @@ const Writer = struct {
16591656
1660 if (fields_len == 0) {1657 if (fields_len == 0) {
1661 try stream.writeAll("}) ");1658 try stream.writeAll("}) ");
1662 try self.writeSrcNode(stream, 0);1659 try self.writeSrcNode(stream, .zero);
1663 return;1660 return;
1664 }1661 }
1665 try stream.writeAll(", ");1662 try stream.writeAll(", ");
...@@ -1730,7 +1727,7 @@ const Writer = struct {...@@ -1730,7 +1727,7 @@ const Writer = struct {
1730 self.indent -= 2;1727 self.indent -= 2;
1731 try stream.writeByteNTimes(' ', self.indent);1728 try stream.writeByteNTimes(' ', self.indent);
1732 try stream.writeAll("}) ");1729 try stream.writeAll("}) ");
1733 try self.writeSrcNode(stream, 0);1730 try self.writeSrcNode(stream, .zero);
1734 }1731 }
17351732
1736 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1733 fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
...@@ -1849,7 +1846,7 @@ const Writer = struct {...@@ -1849,7 +1846,7 @@ const Writer = struct {
1849 try stream.writeByteNTimes(' ', self.indent);1846 try stream.writeByteNTimes(' ', self.indent);
1850 try stream.writeAll("}) ");1847 try stream.writeAll("}) ");
1851 }1848 }
1852 try self.writeSrcNode(stream, 0);1849 try self.writeSrcNode(stream, .zero);
1853 }1850 }
18541851
1855 fn writeOpaqueDecl(1852 fn writeOpaqueDecl(
...@@ -1893,7 +1890,7 @@ const Writer = struct {...@@ -1893,7 +1890,7 @@ const Writer = struct {
1893 try stream.writeByteNTimes(' ', self.indent);1890 try stream.writeByteNTimes(' ', self.indent);
1894 try stream.writeAll("}) ");1891 try stream.writeAll("}) ");
1895 }1892 }
1896 try self.writeSrcNode(stream, 0);1893 try self.writeSrcNode(stream, .zero);
1897 }1894 }
18981895
1899 fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {1896 fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
...@@ -2539,7 +2536,7 @@ const Writer = struct {...@@ -2539,7 +2536,7 @@ const Writer = struct {
2539 ret_ty_body: []const Zir.Inst.Index,2536 ret_ty_body: []const Zir.Inst.Index,
2540 ret_ty_is_generic: bool,2537 ret_ty_is_generic: bool,
2541 body: []const Zir.Inst.Index,2538 body: []const Zir.Inst.Index,
2542 src_node: i32,2539 src_node: Ast.Node.Offset,
2543 src_locs: Zir.Inst.Func.SrcLocs,2540 src_locs: Zir.Inst.Func.SrcLocs,
2544 noalias_bits: u32,2541 noalias_bits: u32,
2545 ) !void {2542 ) !void {
...@@ -2647,18 +2644,20 @@ const Writer = struct {...@@ -2647,18 +2644,20 @@ const Writer = struct {
2647 }2644 }
26482645
2649 try stream.writeAll(") ");2646 try stream.writeAll(") ");
2650 try self.writeSrcNode(stream, 0);2647 try self.writeSrcNode(stream, .zero);
2651 }2648 }
26522649
2653 fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2650 fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
2654 try stream.print("{d})) ", .{extended.small});2651 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);
2656 }2654 }
26572655
2658 fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2656 fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
2659 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);2657 const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2660 try stream.print("{s})) ", .{@tagName(val)});2658 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);
2662 }2661 }
26632662
2664 fn writeInplaceArithResultTy(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {2663 fn writeInplaceArithResultTy(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
...@@ -2760,9 +2759,9 @@ const Writer = struct {...@@ -2760,9 +2759,9 @@ const Writer = struct {
2760 try stream.writeAll(name);2759 try stream.writeAll(name);
2761 }2760 }
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 {
2764 const tree = self.file.tree orelse return;2763 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);
2766 const src_span = tree.nodeToSpan(abs_node);2765 const src_span = tree.nodeToSpan(abs_node);
2767 const start = self.line_col_cursor.find(tree.source, src_span.start);2766 const start = self.line_col_cursor.find(tree.source, src_span.start);
2768 const end = self.line_col_cursor.find(tree.source, src_span.end);2767 const end = self.line_col_cursor.find(tree.source, src_span.end);
...@@ -2772,10 +2771,10 @@ const Writer = struct {...@@ -2772,10 +2771,10 @@ const Writer = struct {
2772 });2771 });
2773 }2772 }
27742773
2775 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void {2774 fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void {
2776 const tree = self.file.tree orelse return;2775 const tree = self.file.tree orelse return;
2777 const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok;2776 const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node));
2778 const span_start = tree.tokens.items(.start)[abs_tok];2777 const span_start = tree.tokenStart(abs_tok);
2779 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));2778 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len));
2780 const start = self.line_col_cursor.find(tree.source, span_start);2779 const start = self.line_col_cursor.find(tree.source, span_start);
2781 const end = self.line_col_cursor.find(tree.source, span_end);2780 const end = self.line_col_cursor.find(tree.source, span_end);
...@@ -2785,9 +2784,9 @@ const Writer = struct {...@@ -2785,9 +2784,9 @@ const Writer = struct {
2785 });2784 });
2786 }2785 }
27872786
2788 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void {2787 fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void {
2789 const tree = self.file.tree orelse return;2788 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);
2791 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));2790 const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len));
2792 const start = self.line_col_cursor.find(tree.source, span_start);2791 const start = self.line_col_cursor.find(tree.source, span_start);
2793 const end = self.line_col_cursor.find(tree.source, span_end);2792 const end = self.line_col_cursor.find(tree.source, span_end);
test/cases/translate_c/continue_from_while.c created+14
...@@ -0,0 +1,14 @@
1void foo() {
2 for (;;) {
3 continue;
4 }
5}
6
7// translate-c
8// c_frontend=clang
9//
10// pub export fn foo() void {
11// while (true) {
12// continue;
13// }
14// }