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

std.zig.Ast: improve type safety

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

25 files changed, 4559 insertions(+), 5056 deletions(-)

lib/compiler/aro_translate_c/ast.zig+383-440
...@@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast {...@@ -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 = 0,
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+144-207
...@@ -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| {
...@@ -239,46 +230,27 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -239,46 +230,27 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
239 },230 },
240231
241 .@"errdefer" => {232 .@"errdefer" => {
242 const expr = datas[node].rhs;233 const expr = ast.nodeData(node).opt_token_and_node[1];
243 return walkExpression(w, expr);234 return walkExpression(w, expr);
244 },235 },
245236
246 .@"defer" => {237 .@"defer",
247 const expr = datas[node].rhs;238 .@"comptime",
248 return walkExpression(w, expr);239 .@"nosuspend",
249 },240 .@"suspend",
250 .@"comptime", .@"nosuspend" => {241 => {
251 const block = datas[node].lhs;242 return walkExpression(w, ast.nodeData(node).node);
252 return walkExpression(w, block);
253 },
254
255 .@"suspend" => {
256 const body = datas[node].lhs;
257 return walkExpression(w, body);
258 },
259
260 .@"catch" => {
261 try walkExpression(w, datas[node].lhs); // target
262 try walkExpression(w, datas[node].rhs); // fallback
263 },243 },
264244
265 .field_access => {245 .field_access => {
266 const field_access = datas[node];246 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
267 try walkExpression(w, field_access.lhs);
268 },247 },
269248
270 .error_union,
271 .switch_range,
272 => {
273 const infix = datas[node];
274 try walkExpression(w, infix.lhs);
275 return walkExpression(w, infix.rhs);
276 },
277 .for_range => {249 .for_range => {
278 const infix = datas[node];250 const start, const opt_end = ast.nodeData(node).node_and_opt_node;
279 try walkExpression(w, infix.lhs);251 try walkExpression(w, start);
280 if (infix.rhs != 0) {252 if (opt_end.unwrap()) |end| {
281 return walkExpression(w, infix.rhs);253 return walkExpression(w, end);
282 }254 }
283 },255 },
284256
...@@ -328,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -328,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
328 .sub,300 .sub,
329 .sub_wrap,301 .sub_wrap,
330 .sub_sat,302 .sub_sat,
303 .@"catch",
304 .error_union,
305 .switch_range,
331 .@"orelse",306 .@"orelse",
307 .array_access,
332 => {308 => {
333 const infix = datas[node];309 const lhs, const rhs = ast.nodeData(node).node_and_node;
334 try walkExpression(w, infix.lhs);310 try walkExpression(w, lhs);
335 try walkExpression(w, infix.rhs);311 try walkExpression(w, rhs);
336 },312 },
337313
338 .assign_destructure => {314 .assign_destructure => {
339 const full = ast.assignDestructure(node);315 const full = ast.assignDestructure(node);
340 for (full.ast.variables) |variable_node| {316 for (full.ast.variables) |variable_node| {
341 switch (node_tags[variable_node]) {317 switch (ast.nodeTag(variable_node)) {
342 .global_var_decl,318 .global_var_decl,
343 .local_var_decl,319 .local_var_decl,
344 .simple_var_decl,320 .simple_var_decl,
...@@ -357,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -357,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
357 .negation_wrap,333 .negation_wrap,
358 .optional_type,334 .optional_type,
359 .address_of,335 .address_of,
360 => {
361 return walkExpression(w, datas[node].lhs);
362 },
363
364 .@"try",336 .@"try",
365 .@"resume",337 .@"resume",
366 .@"await",338 .@"await",
339 .deref,
367 => {340 => {
368 return walkExpression(w, datas[node].lhs);341 return walkExpression(w, ast.nodeData(node).node);
369 },342 },
370343
371 .array_type,344 .array_type,
...@@ -417,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -417,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
417 return walkCall(w, ast.fullCall(&buf, node).?);390 return walkCall(w, ast.fullCall(&buf, node).?);
418 },391 },
419392
420 .array_access => {
421 const suffix = datas[node];
422 try walkExpression(w, suffix.lhs);
423 try walkExpression(w, suffix.rhs);
424 },
425
426 .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).?),
427394
428 .deref => {
429 try walkExpression(w, datas[node].lhs);
430 },
431
432 .unwrap_optional => {395 .unwrap_optional => {
433 try walkExpression(w, datas[node].lhs);396 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
434 },397 },
435398
436 .@"break" => {399 .@"break" => {
437 const label_token = datas[node].lhs;400 const label_token, const target = ast.nodeData(node).opt_token_and_opt_node;
438 const target = datas[node].rhs;401 if (label_token == .none and target == .none) {
439 if (label_token == 0 and target == 0) {
440 // no expressions402 // no expressions
441 } else if (label_token == 0 and target != 0) {403 } else if (label_token == .none and target != .none) {
442 try walkExpression(w, target);404 try walkExpression(w, target.unwrap().?);
443 } else if (label_token != 0 and target == 0) {405 } else if (label_token != .none and target == .none) {
444 try walkIdentifier(w, label_token);406 try walkIdentifier(w, label_token.unwrap().?);
445 } else if (label_token != 0 and target != 0) {407 } else if (label_token != .none and target != .none) {
446 try walkExpression(w, target);408 try walkExpression(w, target.unwrap().?);
447 }409 }
448 },410 },
449411
450 .@"continue" => {412 .@"continue" => {
451 const label = datas[node].lhs;413 const opt_label = ast.nodeData(node).opt_token_and_opt_node[0];
452 if (label != 0) {414 if (opt_label.unwrap()) |label| {
453 return walkIdentifier(w, label); // label415 return walkIdentifier(w, label);
454 }416 }
455 },417 },
456418
457 .@"return" => {419 .@"return" => {
458 if (datas[node].lhs != 0) {420 if (ast.nodeData(node).opt_node.unwrap()) |lhs| {
459 try walkExpression(w, datas[node].lhs);421 try walkExpression(w, lhs);
460 }422 }
461 },423 },
462424
463 .grouped_expression => {425 .grouped_expression => {
464 try walkExpression(w, datas[node].lhs);426 try walkExpression(w, ast.nodeData(node).node_and_token[0]);
465 },427 },
466428
467 .container_decl,429 .container_decl,
...@@ -482,13 +444,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -482,13 +444,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
482 },444 },
483445
484 .error_set_decl => {446 .error_set_decl => {
485 const error_token = main_tokens[node];447 const error_token = ast.nodeMainToken(node);
486 const lbrace = error_token + 1;448 const lbrace = error_token + 1;
487 const rbrace = datas[node].rhs;449 const rbrace = ast.nodeData(node).token;
488450
489 var i = lbrace + 1;451 var i = lbrace + 1;
490 while (i < rbrace) : (i += 1) {452 while (i < rbrace) : (i += 1) {
491 switch (token_tags[i]) {453 switch (ast.tokenTag(i)) {
492 .doc_comment => unreachable, // TODO454 .doc_comment => unreachable, // TODO
493 .identifier => try walkIdentifier(w, i),455 .identifier => try walkIdentifier(w, i),
494 .comma => {},456 .comma => {},
...@@ -517,20 +479,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -517,20 +479,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
517 },479 },
518480
519 .anyframe_type => {481 .anyframe_type => {
520 if (datas[node].rhs != 0) {482 _, const child_type = ast.nodeData(node).token_and_node;
521 return walkExpression(w, datas[node].rhs);483 return walkExpression(w, child_type);
522 }
523 },484 },
524485
525 .@"switch",486 .@"switch",
526 .switch_comma,487 .switch_comma,
527 => {488 => {
528 const condition = datas[node].lhs;489 const full = ast.fullSwitch(node).?;
529 const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange);490 try walkExpression(w, full.ast.condition); // condition expression
530 const cases = ast.extra_data[extra.start..extra.end];491 try walkExpressions(w, full.ast.cases);
531
532 try walkExpression(w, condition); // condition expression
533 try walkExpressions(w, cases);
534 },492 },
535493
536 .switch_case_one,494 .switch_case_one,
...@@ -557,7 +515,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -557,7 +515,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
557 => return walkAsm(w, ast.fullAsm(node).?),515 => return walkAsm(w, ast.fullAsm(node).?),
558516
559 .enum_literal => {517 .enum_literal => {
560 return walkIdentifier(w, main_tokens[node]); // name518 return walkIdentifier(w, ast.nodeMainToken(node)); // name
561 },519 },
562520
563 .fn_decl => unreachable,521 .fn_decl => unreachable,
...@@ -579,66 +537,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {...@@ -579,66 +537,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void {
579fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {537fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void {
580 _ = decl_node;538 _ = decl_node;
581539
582 if (var_decl.ast.type_node != 0) {540 if (var_decl.ast.type_node.unwrap()) |type_node| {
583 try walkExpression(w, var_decl.ast.type_node);541 try walkExpression(w, type_node);
584 }542 }
585543
586 if (var_decl.ast.align_node != 0) {544 if (var_decl.ast.align_node.unwrap()) |align_node| {
587 try walkExpression(w, var_decl.ast.align_node);545 try walkExpression(w, align_node);
588 }546 }
589547
590 if (var_decl.ast.addrspace_node != 0) {548 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
591 try walkExpression(w, var_decl.ast.addrspace_node);549 try walkExpression(w, addrspace_node);
592 }550 }
593551
594 if (var_decl.ast.section_node != 0) {552 if (var_decl.ast.section_node.unwrap()) |section_node| {
595 try walkExpression(w, var_decl.ast.section_node);553 try walkExpression(w, section_node);
596 }554 }
597555
598 if (var_decl.ast.init_node != 0) {556 if (var_decl.ast.init_node.unwrap()) |init_node| {
599 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {557 if (!isUndefinedIdent(w.ast, init_node)) {
600 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });558 try w.transformations.append(.{ .replace_with_undef = init_node });
601 }559 }
602 try walkExpression(w, var_decl.ast.init_node);560 try walkExpression(w, init_node);
603 }561 }
604}562}
605563
606fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {564fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void {
607 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name565 try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name
608566
609 if (var_decl.ast.type_node != 0) {567 if (var_decl.ast.type_node.unwrap()) |type_node| {
610 try walkExpression(w, var_decl.ast.type_node);568 try walkExpression(w, type_node);
611 }569 }
612570
613 if (var_decl.ast.align_node != 0) {571 if (var_decl.ast.align_node.unwrap()) |align_node| {
614 try walkExpression(w, var_decl.ast.align_node);572 try walkExpression(w, align_node);
615 }573 }
616574
617 if (var_decl.ast.addrspace_node != 0) {575 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
618 try walkExpression(w, var_decl.ast.addrspace_node);576 try walkExpression(w, addrspace_node);
619 }577 }
620578
621 if (var_decl.ast.section_node != 0) {579 if (var_decl.ast.section_node.unwrap()) |section_node| {
622 try walkExpression(w, var_decl.ast.section_node);580 try walkExpression(w, section_node);
623 }581 }
624582
625 if (var_decl.ast.init_node != 0) {583 if (var_decl.ast.init_node.unwrap()) |init_node| {
626 if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) {584 if (!isUndefinedIdent(w.ast, init_node)) {
627 try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node });585 try w.transformations.append(.{ .replace_with_undef = init_node });
628 }586 }
629 try walkExpression(w, var_decl.ast.init_node);587 try walkExpression(w, init_node);
630 }588 }
631}589}
632590
633fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {591fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void {
634 if (field.ast.type_expr != 0) {592 if (field.ast.type_expr.unwrap()) |type_expr| {
635 try walkExpression(w, field.ast.type_expr); // type593 try walkExpression(w, type_expr); // type
636 }594 }
637 if (field.ast.align_expr != 0) {595 if (field.ast.align_expr.unwrap()) |align_expr| {
638 try walkExpression(w, field.ast.align_expr); // alignment596 try walkExpression(w, align_expr); // alignment
639 }597 }
640 if (field.ast.value_expr != 0) {598 if (field.ast.value_expr.unwrap()) |value_expr| {
641 try walkExpression(w, field.ast.value_expr); // value599 try walkExpression(w, value_expr); // value
642 }600 }
643}601}
644602
...@@ -649,18 +607,17 @@ fn walkBlock(...@@ -649,18 +607,17 @@ fn walkBlock(
649) Error!void {607) Error!void {
650 _ = block_node;608 _ = block_node;
651 const ast = w.ast;609 const ast = w.ast;
652 const node_tags = ast.nodes.items(.tag);
653610
654 for (statements) |stmt| {611 for (statements) |stmt| {
655 switch (node_tags[stmt]) {612 switch (ast.nodeTag(stmt)) {
656 .global_var_decl,613 .global_var_decl,
657 .local_var_decl,614 .local_var_decl,
658 .simple_var_decl,615 .simple_var_decl,
659 .aligned_var_decl,616 .aligned_var_decl,
660 => {617 => {
661 const var_decl = ast.fullVarDecl(stmt).?;618 const var_decl = ast.fullVarDecl(stmt).?;
662 if (var_decl.ast.init_node != 0 and619 if (var_decl.ast.init_node != .none and
663 isUndefinedIdent(w.ast, var_decl.ast.init_node))620 isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?))
664 {621 {
665 try w.transformations.append(.{ .delete_var_decl = .{622 try w.transformations.append(.{ .delete_var_decl = .{
666 .var_decl_node = stmt,623 .var_decl_node = stmt,
...@@ -691,15 +648,15 @@ fn walkBlock(...@@ -691,15 +648,15 @@ fn walkBlock(
691648
692fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {649fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void {
693 try walkExpression(w, array_type.ast.elem_count);650 try walkExpression(w, array_type.ast.elem_count);
694 if (array_type.ast.sentinel != 0) {651 if (array_type.ast.sentinel.unwrap()) |sentinel| {
695 try walkExpression(w, array_type.ast.sentinel);652 try walkExpression(w, sentinel);
696 }653 }
697 return walkExpression(w, array_type.ast.elem_type);654 return walkExpression(w, array_type.ast.elem_type);
698}655}
699656
700fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {657fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void {
701 if (array_init.ast.type_expr != 0) {658 if (array_init.ast.type_expr.unwrap()) |type_expr| {
702 try walkExpression(w, array_init.ast.type_expr); // T659 try walkExpression(w, type_expr); // T
703 }660 }
704 for (array_init.ast.elements) |elem_init| {661 for (array_init.ast.elements) |elem_init| {
705 try walkExpression(w, elem_init);662 try walkExpression(w, elem_init);
...@@ -712,8 +669,8 @@ fn walkStructInit(...@@ -712,8 +669,8 @@ fn walkStructInit(
712 struct_init: Ast.full.StructInit,669 struct_init: Ast.full.StructInit,
713) Error!void {670) Error!void {
714 _ = struct_node;671 _ = struct_node;
715 if (struct_init.ast.type_expr != 0) {672 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
716 try walkExpression(w, struct_init.ast.type_expr); // T673 try walkExpression(w, type_expr); // T
717 }674 }
718 for (struct_init.ast.fields) |field_init| {675 for (struct_init.ast.fields) |field_init| {
719 try walkExpression(w, field_init);676 try walkExpression(w, field_init);
...@@ -733,18 +690,17 @@ fn walkSlice(...@@ -733,18 +690,17 @@ fn walkSlice(
733 _ = slice_node;690 _ = slice_node;
734 try walkExpression(w, slice.ast.sliced);691 try walkExpression(w, slice.ast.sliced);
735 try walkExpression(w, slice.ast.start);692 try walkExpression(w, slice.ast.start);
736 if (slice.ast.end != 0) {693 if (slice.ast.end.unwrap()) |end| {
737 try walkExpression(w, slice.ast.end);694 try walkExpression(w, end);
738 }695 }
739 if (slice.ast.sentinel != 0) {696 if (slice.ast.sentinel.unwrap()) |sentinel| {
740 try walkExpression(w, slice.ast.sentinel);697 try walkExpression(w, sentinel);
741 }698 }
742}699}
743700
744fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {701fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void {
745 const ast = w.ast;702 const ast = w.ast;
746 const token_tags = ast.tokens.items(.tag);703 assert(ast.tokenTag(name_ident) == .identifier);
747 assert(token_tags[name_ident] == .identifier);
748 const name_bytes = ast.tokenSlice(name_ident);704 const name_bytes = ast.tokenSlice(name_ident);
749 _ = w.unreferenced_globals.swapRemove(name_bytes);705 _ = w.unreferenced_globals.swapRemove(name_bytes);
750}706}
...@@ -760,8 +716,8 @@ fn walkContainerDecl(...@@ -760,8 +716,8 @@ fn walkContainerDecl(
760 container_decl: Ast.full.ContainerDecl,716 container_decl: Ast.full.ContainerDecl,
761) Error!void {717) Error!void {
762 _ = container_decl_node;718 _ = container_decl_node;
763 if (container_decl.ast.arg != 0) {719 if (container_decl.ast.arg.unwrap()) |arg| {
764 try walkExpression(w, container_decl.ast.arg);720 try walkExpression(w, arg);
765 }721 }
766 try walkMembers(w, container_decl.ast.members);722 try walkMembers(w, container_decl.ast.members);
767}723}
...@@ -772,14 +728,13 @@ fn walkBuiltinCall(...@@ -772,14 +728,13 @@ fn walkBuiltinCall(
772 params: []const Ast.Node.Index,728 params: []const Ast.Node.Index,
773) Error!void {729) Error!void {
774 const ast = w.ast;730 const ast = w.ast;
775 const main_tokens = ast.nodes.items(.main_token);731 const builtin_token = ast.nodeMainToken(call_node);
776 const builtin_token = main_tokens[call_node];
777 const builtin_name = ast.tokenSlice(builtin_token);732 const builtin_name = ast.tokenSlice(builtin_token);
778 const info = BuiltinFn.list.get(builtin_name).?;733 const info = BuiltinFn.list.get(builtin_name).?;
779 switch (info.tag) {734 switch (info.tag) {
780 .import => {735 .import => {
781 const operand_node = params[0];736 const operand_node = params[0];
782 const str_lit_token = main_tokens[operand_node];737 const str_lit_token = ast.nodeMainToken(operand_node);
783 const token_bytes = ast.tokenSlice(str_lit_token);738 const token_bytes = ast.tokenSlice(str_lit_token);
784 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {739 if (std.mem.endsWith(u8, token_bytes, ".zig\"")) {
785 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch740 const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch
...@@ -808,29 +763,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {...@@ -808,29 +763,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void {
808 {763 {
809 var it = fn_proto.iterate(ast);764 var it = fn_proto.iterate(ast);
810 while (it.next()) |param| {765 while (it.next()) |param| {
811 if (param.type_expr != 0) {766 if (param.type_expr) |type_expr| {
812 try walkExpression(w, param.type_expr);767 try walkExpression(w, type_expr);
813 }768 }
814 }769 }
815 }770 }
816771
817 if (fn_proto.ast.align_expr != 0) {772 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
818 try walkExpression(w, fn_proto.ast.align_expr);773 try walkExpression(w, align_expr);
819 }774 }
820775
821 if (fn_proto.ast.addrspace_expr != 0) {776 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
822 try walkExpression(w, fn_proto.ast.addrspace_expr);777 try walkExpression(w, addrspace_expr);
823 }778 }
824779
825 if (fn_proto.ast.section_expr != 0) {780 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
826 try walkExpression(w, fn_proto.ast.section_expr);781 try walkExpression(w, section_expr);
827 }782 }
828783
829 if (fn_proto.ast.callconv_expr != 0) {784 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
830 try walkExpression(w, fn_proto.ast.callconv_expr);785 try walkExpression(w, callconv_expr);
831 }786 }
832787
833 try walkExpression(w, fn_proto.ast.return_type);788 const return_type = fn_proto.ast.return_type.unwrap().?;
789 try walkExpression(w, return_type);
834}790}
835791
836fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {792fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void {
...@@ -847,16 +803,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {...@@ -847,16 +803,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void {
847}803}
848804
849fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {805fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void {
850 assert(while_node.ast.cond_expr != 0);
851 assert(while_node.ast.then_expr != 0);
852
853 // Perform these transformations in this priority order:806 // Perform these transformations in this priority order:
854 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.807 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
855 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.808 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
856 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.809 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
857 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.810 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
858 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and811 if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and
859 (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr)))812 (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?)))
860 {813 {
861 try w.transformations.ensureUnusedCapacity(1);814 try w.transformations.ensureUnusedCapacity(1);
862 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });815 w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr });
...@@ -873,45 +826,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E...@@ -873,45 +826,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E
873 try w.transformations.ensureUnusedCapacity(1);826 try w.transformations.ensureUnusedCapacity(1);
874 w.transformations.appendAssumeCapacity(.{ .replace_node = .{827 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
875 .to_replace = node_index,828 .to_replace = node_index,
876 .replacement = while_node.ast.else_expr,829 .replacement = while_node.ast.else_expr.unwrap().?,
877 } });830 } });
878 }831 }
879832
880 try walkExpression(w, while_node.ast.cond_expr); // condition833 try walkExpression(w, while_node.ast.cond_expr); // condition
881834
882 if (while_node.ast.cont_expr != 0) {835 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
883 try walkExpression(w, while_node.ast.cont_expr);836 try walkExpression(w, cont_expr);
884 }837 }
885838
886 if (while_node.ast.then_expr != 0) {839 try walkExpression(w, while_node.ast.then_expr);
887 try walkExpression(w, while_node.ast.then_expr);840
888 }841 if (while_node.ast.else_expr.unwrap()) |else_expr| {
889 if (while_node.ast.else_expr != 0) {842 try walkExpression(w, else_expr);
890 try walkExpression(w, while_node.ast.else_expr);
891 }843 }
892}844}
893845
894fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {846fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void {
895 try walkParamList(w, for_node.ast.inputs);847 try walkParamList(w, for_node.ast.inputs);
896 if (for_node.ast.then_expr != 0) {848 try walkExpression(w, for_node.ast.then_expr);
897 try walkExpression(w, for_node.ast.then_expr);849 if (for_node.ast.else_expr.unwrap()) |else_expr| {
898 }850 try walkExpression(w, else_expr);
899 if (for_node.ast.else_expr != 0) {
900 try walkExpression(w, for_node.ast.else_expr);
901 }851 }
902}852}
903853
904fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {854fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void {
905 assert(if_node.ast.cond_expr != 0);
906 assert(if_node.ast.then_expr != 0);
907
908 // Perform these transformations in this priority order:855 // Perform these transformations in this priority order:
909 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.856 // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already.
910 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.857 // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already.
911 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.858 // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression.
912 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.859 // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression.
913 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and860 if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and
914 (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr)))861 (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?)))
915 {862 {
916 try w.transformations.ensureUnusedCapacity(1);863 try w.transformations.ensureUnusedCapacity(1);
917 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });864 w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr });
...@@ -928,17 +875,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void...@@ -928,17 +875,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void
928 try w.transformations.ensureUnusedCapacity(1);875 try w.transformations.ensureUnusedCapacity(1);
929 w.transformations.appendAssumeCapacity(.{ .replace_node = .{876 w.transformations.appendAssumeCapacity(.{ .replace_node = .{
930 .to_replace = node_index,877 .to_replace = node_index,
931 .replacement = if_node.ast.else_expr,878 .replacement = if_node.ast.else_expr.unwrap().?,
932 } });879 } });
933 }880 }
934881
935 try walkExpression(w, if_node.ast.cond_expr); // condition882 try walkExpression(w, if_node.ast.cond_expr); // condition
936883 try walkExpression(w, if_node.ast.then_expr);
937 if (if_node.ast.then_expr != 0) {884 if (if_node.ast.else_expr.unwrap()) |else_expr| {
938 try walkExpression(w, if_node.ast.then_expr);885 try walkExpression(w, else_expr);
939 }
940 if (if_node.ast.else_expr != 0) {
941 try walkExpression(w, if_node.ast.else_expr);
942 }886 }
943}887}
944888
...@@ -958,9 +902,8 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {...@@ -958,9 +902,8 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void {
958/// Check if it is already gutted (i.e. its body replaced with `@trap()`).902/// Check if it is already gutted (i.e. its body replaced with `@trap()`).
959fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {903fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool {
960 // skip over discards904 // skip over discards
961 const node_tags = ast.nodes.items(.tag);
962 var statements_buf: [2]Ast.Node.Index = undefined;905 var statements_buf: [2]Ast.Node.Index = undefined;
963 const statements = switch (node_tags[body_node]) {906 const statements = switch (ast.nodeTag(body_node)) {
964 .block_two,907 .block_two,
965 .block_two_semicolon,908 .block_two_semicolon,
966 .block,909 .block,
...@@ -988,10 +931,7 @@ const StmtCategory = enum {...@@ -988,10 +931,7 @@ const StmtCategory = enum {
988};931};
989932
990fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {933fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
991 const node_tags = ast.nodes.items(.tag);934 switch (ast.nodeTag(stmt)) {
992 const datas = ast.nodes.items(.data);
993 const main_tokens = ast.nodes.items(.main_token);
994 switch (node_tags[stmt]) {
995 .builtin_call_two,935 .builtin_call_two,
996 .builtin_call_two_comma,936 .builtin_call_two_comma,
997 .builtin_call,937 .builtin_call,
...@@ -999,12 +939,12 @@ fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {...@@ -999,12 +939,12 @@ fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory {
999 => {939 => {
1000 var buf: [2]Ast.Node.Index = undefined;940 var buf: [2]Ast.Node.Index = undefined;
1001 const params = ast.builtinCallParams(&buf, stmt).?;941 const params = ast.builtinCallParams(&buf, stmt).?;
1002 return categorizeBuiltinCall(ast, main_tokens[stmt], params);942 return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params);
1003 },943 },
1004 .assign => {944 .assign => {
1005 const infix = datas[stmt];945 const lhs, const rhs = ast.nodeData(stmt).node_and_node;
1006 if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) {946 if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) {
1007 const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]);947 const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs));
1008 if (std.mem.eql(u8, name_bytes, "undefined")) {948 if (std.mem.eql(u8, name_bytes, "undefined")) {
1009 return .discard_undefined;949 return .discard_undefined;
1010 } else {950 } else {
...@@ -1046,11 +986,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {...@@ -1046,11 +986,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool {
1046}986}
1047987
1048fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {988fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool {
1049 const node_tags = ast.nodes.items(.tag);989 switch (ast.nodeTag(node)) {
1050 const main_tokens = ast.nodes.items(.main_token);
1051 switch (node_tags[node]) {
1052 .identifier => {990 .identifier => {
1053 const token_index = main_tokens[node];991 const token_index = ast.nodeMainToken(node);
1054 const name_bytes = ast.tokenSlice(token_index);992 const name_bytes = ast.tokenSlice(token_index);
1055 return std.mem.eql(u8, name_bytes, string);993 return std.mem.eql(u8, name_bytes, string);
1056 },994 },
...@@ -1059,11 +997,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo...@@ -1059,11 +997,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo
1059}997}
1060998
1061fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {999fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool {
1062 const node_tags = ast.nodes.items(.tag);1000 switch (ast.nodeTag(node)) {
1063 const node_data = ast.nodes.items(.data);
1064 switch (node_tags[node]) {
1065 .block_two => {1001 .block_two => {
1066 return node_data[node].lhs == 0 and node_data[node].rhs == 0;1002 const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node;
1003 return opt_lhs == .none and opt_rhs == .none;
1067 },1004 },
1068 else => return false,1005 else => return false,
1069 }1006 }
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+71-94
...@@ -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)) {
...@@ -259,9 +253,9 @@ pub const File = struct {...@@ -259,9 +253,9 @@ pub const File = struct {
259 .@"if",253 .@"if",
260 => {254 => {
261 const if_full = ast.fullIf(node).?;255 const if_full = ast.fullIf(node).?;
262 if (if_full.ast.else_expr != 0) {256 if (if_full.ast.else_expr.unwrap()) |else_expr| {
263 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);
264 const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr);258 const else_cat = categorize_expr_deep(file_index, else_expr);
265 if (then_cat == .type_type and else_cat == .type_type) {259 if (then_cat == .type_type and else_cat == .type_type) {
266 return .type_type;260 return .type_type;
267 } else if (then_cat == .error_set and else_cat == .error_set) {261 } else if (then_cat == .error_set and else_cat == .error_set) {
...@@ -320,11 +314,10 @@ pub const File = struct {...@@ -320,11 +314,10 @@ pub const File = struct {
320 params: []const Ast.Node.Index,314 params: []const Ast.Node.Index,
321 ) Category {315 ) Category {
322 const ast = file_index.get_ast();316 const ast = file_index.get_ast();
323 const main_tokens = ast.nodes.items(.main_token);317 const builtin_token = ast.nodeMainToken(node);
324 const builtin_token = main_tokens[node];
325 const builtin_name = ast.tokenSlice(builtin_token);318 const builtin_name = ast.tokenSlice(builtin_token);
326 if (std.mem.eql(u8, builtin_name, "@import")) {319 if (std.mem.eql(u8, builtin_name, "@import")) {
327 const str_lit_token = main_tokens[params[0]];320 const str_lit_token = ast.nodeMainToken(params[0]);
328 const str_bytes = ast.tokenSlice(str_lit_token);321 const str_bytes = ast.tokenSlice(str_lit_token);
329 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");
330 defer gpa.free(file_path);323 defer gpa.free(file_path);
...@@ -357,14 +350,12 @@ pub const File = struct {...@@ -357,14 +350,12 @@ pub const File = struct {
357350
358 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 {
359 const ast = file_index.get_ast();352 const ast = file_index.get_ast();
360 const node_datas = ast.nodes.items(.data);353 const full = ast.fullSwitch(node).?;
361 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);
362 const case_nodes = ast.extra_data[extra.start..extra.end];
363 var all_type_type = true;354 var all_type_type = true;
364 var all_error_set = true;355 var all_error_set = true;
365 var any_type = false;356 var any_type = false;
366 if (case_nodes.len == 0) return .{ .global_const = node };357 if (full.ast.cases.len == 0) return .{ .global_const = node };
367 for (case_nodes) |case_node| {358 for (full.ast.cases) |case_node| {
368 const case = ast.fullSwitchCase(case_node).?;359 const case = ast.fullSwitchCase(case_node).?;
369 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {360 switch (categorize_expr_deep(file_index, case.ast.target_expr)) {
370 .type_type => {361 .type_type => {
...@@ -410,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {...@@ -410,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index {
410 const scope = try gpa.create(Scope);401 const scope = try gpa.create(Scope);
411 scope.* = .{ .tag = .top };402 scope.* = .{ .tag = .top };
412403
413 const decl_index = try file_index.add_decl(0, .none);404 const decl_index = try file_index.add_decl(.root, .none);
414 try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot());405 try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot());
415406
416 const file = file_index.get();407 const file = file_index.get();
417 shrinkToFit(&file.ident_decls);408 shrinkToFit(&file.ident_decls);
...@@ -505,13 +496,12 @@ pub const Scope = struct {...@@ -505,13 +496,12 @@ pub const Scope = struct {
505 }496 }
506497
507 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 {
508 const main_tokens = ast.nodes.items(.main_token);
509 var it: *Scope = start_scope;499 var it: *Scope = start_scope;
510 while (true) switch (it.tag) {500 while (true) switch (it.tag) {
511 .top => break,501 .top => break,
512 .local => {502 .local => {
513 const local: *Local = @alignCast(@fieldParentPtr("base", it));503 const local: *Local = @alignCast(@fieldParentPtr("base", it));
514 const name_token = main_tokens[local.var_node] + 1;504 const name_token = ast.nodeMainToken(local.var_node) + 1;
515 const ident_name = ast.tokenSlice(name_token);505 const ident_name = ast.tokenSlice(name_token);
516 if (std.mem.eql(u8, ident_name, name)) {506 if (std.mem.eql(u8, ident_name, name)) {
517 return local.var_node;507 return local.var_node;
...@@ -538,8 +528,6 @@ fn struct_decl(...@@ -538,8 +528,6 @@ fn struct_decl(
538 container_decl: Ast.full.ContainerDecl,528 container_decl: Ast.full.ContainerDecl,
539) Oom!void {529) Oom!void {
540 const ast = w.file.get_ast();530 const ast = w.file.get_ast();
541 const node_tags = ast.nodes.items(.tag);
542 const node_datas = ast.nodes.items(.data);
543531
544 const namespace = try gpa.create(Scope.Namespace);532 const namespace = try gpa.create(Scope.Namespace);
545 namespace.* = .{533 namespace.* = .{
...@@ -549,7 +537,7 @@ fn struct_decl(...@@ -549,7 +537,7 @@ fn struct_decl(
549 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);537 try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base);
550 try w.scanDecls(namespace, container_decl.ast.members);538 try w.scanDecls(namespace, container_decl.ast.members);
551539
552 for (container_decl.ast.members) |member| switch (node_tags[member]) {540 for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) {
553 .container_field_init,541 .container_field_init,
554 .container_field_align,542 .container_field_align,
555 .container_field,543 .container_field,
...@@ -569,7 +557,7 @@ fn struct_decl(...@@ -569,7 +557,7 @@ fn struct_decl(
569 try w.file.get().doctests.put(gpa, member, doctest_node);557 try w.file.get().doctests.put(gpa, member, doctest_node);
570 }558 }
571 const decl_index = try w.file.add_decl(member, parent_decl);559 const decl_index = try w.file.add_decl(member, parent_decl);
572 const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0;560 const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none;
573 try w.fn_decl(&namespace.base, decl_index, body, full);561 try w.fn_decl(&namespace.base, decl_index, body, full);
574 },562 },
575563
...@@ -584,9 +572,9 @@ fn struct_decl(...@@ -584,9 +572,9 @@ fn struct_decl(
584572
585 .@"comptime",573 .@"comptime",
586 .@"usingnamespace",574 .@"usingnamespace",
587 => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs),575 => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node),
588576
589 .test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs),577 .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]),
590578
591 else => unreachable,579 else => unreachable,
592 };580 };
...@@ -633,13 +621,13 @@ fn fn_decl(...@@ -633,13 +621,13 @@ fn fn_decl(
633 w: *Walk,621 w: *Walk,
634 scope: *Scope,622 scope: *Scope,
635 parent_decl: Decl.Index,623 parent_decl: Decl.Index,
636 body: Ast.Node.Index,624 body: Ast.Node.OptionalIndex,
637 full: Ast.full.FnProto,625 full: Ast.full.FnProto,
638) Oom!void {626) Oom!void {
639 for (full.ast.params) |param| {627 for (full.ast.params) |param| {
640 try expr(w, scope, parent_decl, param);628 try expr(w, scope, parent_decl, param);
641 }629 }
642 try expr(w, scope, parent_decl, full.ast.return_type);630 try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?);
643 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);631 try maybe_expr(w, scope, parent_decl, full.ast.align_expr);
644 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);632 try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr);
645 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);633 try maybe_expr(w, scope, parent_decl, full.ast.section_expr);
...@@ -647,17 +635,13 @@ fn fn_decl(...@@ -647,17 +635,13 @@ fn fn_decl(
647 try maybe_expr(w, scope, parent_decl, body);635 try maybe_expr(w, scope, parent_decl, body);
648}636}
649637
650fn 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 {
651 if (node != 0) return expr(w, scope, parent_decl, node);639 if (node.unwrap()) |n| return expr(w, scope, parent_decl, n);
652}640}
653641
654fn 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 {
655 assert(node != 0);
656 const ast = w.file.get_ast();643 const ast = w.file.get_ast();
657 const node_tags = ast.nodes.items(.tag);644 switch (ast.nodeTag(node)) {
658 const node_datas = ast.nodes.items(.data);
659 const main_tokens = ast.nodes.items(.main_token);
660 switch (node_tags[node]) {
661 .root => unreachable, // Top-level declaration.645 .root => unreachable, // Top-level declaration.
662 .@"usingnamespace" => unreachable, // Top-level declaration.646 .@"usingnamespace" => unreachable, // Top-level declaration.
663 .test_decl => unreachable, // Top-level declaration.647 .test_decl => unreachable, // Top-level declaration.
...@@ -738,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -738,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
738 .array_access,722 .array_access,
739 .switch_range,723 .switch_range,
740 => {724 => {
741 try expr(w, scope, parent_decl, node_datas[node].lhs);725 const lhs, const rhs = ast.nodeData(node).node_and_node;
742 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);
743 },728 },
744729
745 .assign_destructure => {730 .assign_destructure => {
...@@ -752,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -752,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
752 .bit_not,737 .bit_not,
753 .negation,738 .negation,
754 .negation_wrap,739 .negation_wrap,
755 .@"return",
756 .deref,740 .deref,
757 .address_of,741 .address_of,
758 .optional_type,742 .optional_type,
759 .unwrap_optional,
760 .grouped_expression,
761 .@"comptime",743 .@"comptime",
762 .@"nosuspend",744 .@"nosuspend",
763 .@"suspend",745 .@"suspend",
764 .@"await",746 .@"await",
765 .@"resume",747 .@"resume",
766 .@"try",748 .@"try",
767 => try maybe_expr(w, scope, parent_decl, node_datas[node].lhs),749 => try expr(w, scope, parent_decl, ast.nodeData(node).node),
750 .unwrap_optional,
751 .grouped_expression,
752 => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
753 .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node),
768754
769 .anyframe_type,755 .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]),
770 .@"break",756 .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]),
771 => try maybe_expr(w, scope, parent_decl, node_datas[node].rhs),
772757
773 .identifier => {758 .identifier => {
774 const ident_token = main_tokens[node];759 const ident_token = ast.nodeMainToken(node);
775 const ident_name = ast.tokenSlice(ident_token);760 const ident_name = ast.tokenSlice(ident_token);
776 if (scope.lookup(ast, ident_name)) |var_node| {761 if (scope.lookup(ast, ident_name)) |var_node| {
777 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);
778 }763 }
779 },764 },
780 .field_access => {765 .field_access => {
781 const object_node = node_datas[node].lhs;766 const object_node, const field_ident = ast.nodeData(node).node_and_token;
782 const dot_token = main_tokens[node];
783 const field_ident = dot_token + 1;
784 try w.file.get().token_parents.put(gpa, field_ident, node);767 try w.file.get().token_parents.put(gpa, field_ident, node);
785 // This will populate the left-most field object if it is an768 // This will populate the left-most field object if it is an
786 // identifier, allowing rendering code to piece together the link.769 // identifier, allowing rendering code to piece together the link.
...@@ -857,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -857,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
857 .for_simple, .@"for" => {840 .for_simple, .@"for" => {
858 const full = ast.fullFor(node).?;841 const full = ast.fullFor(node).?;
859 for (full.ast.inputs) |input| {842 for (full.ast.inputs) |input| {
860 if (node_tags[input] == .for_range) {843 if (ast.nodeTag(input) == .for_range) {
861 try expr(w, scope, parent_decl, node_datas[input].lhs);844 const start, const end = ast.nodeData(input).node_and_opt_node;
862 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);
863 } else {847 } else {
864 try expr(w, scope, parent_decl, input);848 try expr(w, scope, parent_decl, input);
865 }849 }
...@@ -914,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -914,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
914 },898 },
915899
916 .array_type_sentinel => {900 .array_type_sentinel => {
917 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);901 const len_expr, const extra_index = ast.nodeData(node).node_and_extra;
918 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);
919 try expr(w, scope, parent_decl, extra.elem_type);904 try expr(w, scope, parent_decl, extra.elem_type);
920 try expr(w, scope, parent_decl, extra.sentinel);905 try expr(w, scope, parent_decl, extra.sentinel);
921 },906 },
922 .@"switch", .switch_comma => {907 .@"switch", .switch_comma => {
923 const operand_node = node_datas[node].lhs;908 const full = ast.fullSwitch(node).?;
924 try expr(w, scope, parent_decl, operand_node);909 try expr(w, scope, parent_decl, full.ast.condition);
925 const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange);910 for (full.ast.cases) |case_node| {
926 const case_nodes = ast.extra_data[extra.start..extra.end];
927 for (case_nodes) |case_node| {
928 const case = ast.fullSwitchCase(case_node).?;911 const case = ast.fullSwitchCase(case_node).?;
929 for (case.ast.values) |value_node| {912 for (case.ast.values) |value_node| {
930 try expr(w, scope, parent_decl, value_node);913 try expr(w, scope, parent_decl, value_node);
...@@ -973,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)...@@ -973,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index)
973 .fn_proto,956 .fn_proto,
974 => {957 => {
975 var buf: [1]Ast.Node.Index = undefined;958 var buf: [1]Ast.Node.Index = undefined;
976 return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?);959 return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?);
977 },960 },
978 }961 }
979}962}
...@@ -993,8 +976,7 @@ fn builtin_call(...@@ -993,8 +976,7 @@ fn builtin_call(
993 params: []const Ast.Node.Index,976 params: []const Ast.Node.Index,
994) Oom!void {977) Oom!void {
995 const ast = w.file.get_ast();978 const ast = w.file.get_ast();
996 const main_tokens = ast.nodes.items(.main_token);979 const builtin_token = ast.nodeMainToken(node);
997 const builtin_token = main_tokens[node];
998 const builtin_name = ast.tokenSlice(builtin_token);980 const builtin_name = ast.tokenSlice(builtin_token);
999 if (std.mem.eql(u8, builtin_name, "@This")) {981 if (std.mem.eql(u8, builtin_name, "@This")) {
1000 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());982 try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl());
...@@ -1012,13 +994,11 @@ fn block(...@@ -1012,13 +994,11 @@ fn block(
1012 statements: []const Ast.Node.Index,994 statements: []const Ast.Node.Index,
1013) Oom!void {995) Oom!void {
1014 const ast = w.file.get_ast();996 const ast = w.file.get_ast();
1015 const node_tags = ast.nodes.items(.tag);
1016 const node_datas = ast.nodes.items(.data);
1017997
1018 var scope = parent_scope;998 var scope = parent_scope;
1019999
1020 for (statements) |node| {1000 for (statements) |node| {
1021 switch (node_tags[node]) {1001 switch (ast.nodeTag(node)) {
1022 .global_var_decl,1002 .global_var_decl,
1023 .local_var_decl,1003 .local_var_decl,
1024 .simple_var_decl,1004 .simple_var_decl,
...@@ -1039,11 +1019,10 @@ fn block(...@@ -1039,11 +1019,10 @@ fn block(
1039 log.debug("walk assign_destructure not implemented yet", .{});1019 log.debug("walk assign_destructure not implemented yet", .{});
1040 },1020 },
10411021
1042 .grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs),1022 .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]),
10431023
1044 .@"defer",1024 .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node),
1045 .@"errdefer",1025 .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]),
1046 => try expr(w, scope, parent_decl, node_datas[node].rhs),
10471026
1048 else => try expr(w, scope, parent_decl, node),1027 else => try expr(w, scope, parent_decl, node),
1049 }1028 }
...@@ -1059,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W...@@ -1059,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W
10591038
1060fn 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 {
1061 const ast = w.file.get_ast();1040 const ast = w.file.get_ast();
1062 const node_tags = ast.nodes.items(.tag);
1063 const main_tokens = ast.nodes.items(.main_token);
1064 const token_tags = ast.tokens.items(.tag);
1065 const node_datas = ast.nodes.items(.data);
10661041
1067 for (members) |member_node| {1042 for (members) |member_node| {
1068 const name_token = switch (node_tags[member_node]) {1043 const name_token = switch (ast.nodeTag(member_node)) {
1069 .global_var_decl,1044 .global_var_decl,
1070 .local_var_decl,1045 .local_var_decl,
1071 .simple_var_decl,1046 .simple_var_decl,
1072 .aligned_var_decl,1047 .aligned_var_decl,
1073 => main_tokens[member_node] + 1,1048 => ast.nodeMainToken(member_node) + 1,
10741049
1075 .fn_proto_simple,1050 .fn_proto_simple,
1076 .fn_proto_multi,1051 .fn_proto_multi,
...@@ -1078,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In...@@ -1078,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In
1078 .fn_proto,1053 .fn_proto,
1079 .fn_decl,1054 .fn_decl,
1080 => blk: {1055 => blk: {
1081 const ident = main_tokens[member_node] + 1;1056 const ident = ast.nodeMainToken(member_node) + 1;
1082 if (token_tags[ident] != .identifier) continue;1057 if (ast.tokenTag(ident) != .identifier) continue;
1083 break :blk ident;1058 break :blk ident;
1084 },1059 },
10851060
1086 .test_decl => {1061 .test_decl => {
1087 const ident_token = node_datas[member_node].lhs;1062 const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0];
1088 const is_doctest = token_tags[ident_token] == .identifier;1063 if (opt_ident_token.unwrap()) |ident_token| {
1089 if (is_doctest) {1064 const is_doctest = ast.tokenTag(ident_token) == .identifier;
1090 const token_bytes = ast.tokenSlice(ident_token);1065 if (is_doctest) {
1091 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 }
1092 }1069 }
1093 continue;1070 continue;
1094 },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+965-844
...@@ -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,14 +886,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -797,14 +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_tags = tree.tokens.items(.tag);
804 var n = node;889 var n = node;
805 var end_offset: TokenIndex = 0;890 var end_offset: u32 = 0;
806 while (true) switch (tags[n]) {891 while (true) switch (tree.nodeTag(n)) {
807 .root => return @as(TokenIndex, @intCast(tree.tokens.len - 1)),892 .root => return @intCast(tree.tokens.len - 1),
808893
809 .@"usingnamespace",894 .@"usingnamespace",
810 .bool_not,895 .bool_not,
...@@ -819,11 +904,8 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -819,11 +904,8 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
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,44 +954,53 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -873,44 +954,53 @@ 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,
882 .fn_proto_multi,
883 .fn_proto_one,
884 .fn_proto,
885 .fn_decl,961 .fn_decl,
962 .array_type,
963 .switch_range,
964 => n = tree.nodeData(n).node_and_node[1],
965
966 .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1],
967 .@"defer" => n = tree.nodeData(n).node,
968 .anyframe_type => n = tree.nodeData(n).token_and_node[1],
969
970 .switch_case_one,
971 .switch_case_inline_one,
886 .ptr_type_aligned,972 .ptr_type_aligned,
887 .ptr_type_sentinel,973 .ptr_type_sentinel,
974 => n = tree.nodeData(n).opt_node_and_node[1],
975
976 .assign_destructure,
888 .ptr_type,977 .ptr_type,
889 .ptr_type_bit_range,978 .ptr_type_bit_range,
890 .array_type,
891 .switch_case_one,
892 .switch_case_inline_one,
893 .switch_case,979 .switch_case,
894 .switch_case_inline,980 .switch_case_inline,
895 .switch_range,981 => n = tree.nodeData(n).extra_and_node[1],
896 => n = datas[n].rhs,
897982
898 .for_range => if (datas[n].rhs != 0) {983 .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?,
899 n = datas[n].rhs;984 .fn_proto_multi,
900 } else {985 .fn_proto_one,
901 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 };
902 },993 },
903994
904 .field_access,995 .field_access,
905 .unwrap_optional,996 .unwrap_optional,
906 .grouped_expression,
907 .multiline_string_literal,
908 .error_set_decl,
909 .asm_simple,997 .asm_simple,
910 .asm_output,998 => return tree.nodeData(n).node_and_token[1] + end_offset,
911 .asm_input,999 .error_set_decl => return tree.nodeData(n).token + end_offset,
912 .error_value,1000 .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset,
913 => return datas[n].rhs + end_offset,1001 .multiline_string_literal => return tree.nodeData(n).token_and_token[1] + end_offset,
1002 .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset,
1003 .error_value => return tree.nodeData(n).opt_token_and_opt_token[1].unwrap().? + end_offset,
9141004
915 .anyframe_literal,1005 .anyframe_literal,
916 .char_literal,1006 .char_literal,
...@@ -920,80 +1010,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -920,80 +1010,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
920 .deref,1010 .deref,
921 .enum_literal,1011 .enum_literal,
922 .string_literal,1012 .string_literal,
923 => return main_tokens[n] + end_offset,1013 => return tree.nodeMainToken(n) + end_offset,
9241014
925 .@"return" => if (datas[n].lhs != 0) {1015 .@"return" => {
926 n = datas[n].lhs;1016 n = tree.nodeData(n).opt_node.unwrap() orelse {
927 } else {1017 return tree.nodeMainToken(n) + end_offset;
928 return main_tokens[n] + end_offset;1018 };
929 },1019 },
9301020
931 .call, .async_call => {1021 .call, .async_call => {
1022 _, const extra_index = tree.nodeData(n).node_and_extra;
1023 const params = tree.extraData(extra_index, Node.SubRange);
1024 assert(params.start != params.end);
932 end_offset += 1; // for the rparen1025 end_offset += 1; // for the rparen
933 const params = tree.extraData(datas[n].rhs, Node.SubRange);1026 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
934 assert(params.end - params.start > 0);
935 n = tree.extra_data[params.end - 1]; // last parameter
936 },1027 },
937 .tagged_union_enum_tag => {1028 .tagged_union_enum_tag => {
938 const members = tree.extraData(datas[n].rhs, Node.SubRange);1029 const arg, const extra_index = tree.nodeData(n).node_and_extra;
939 if (members.end - members.start == 0) {1030 const members = tree.extraData(extra_index, Node.SubRange);
1031 if (members.start == members.end) {
940 end_offset += 4; // for the rparen + rparen + lbrace + rbrace1032 end_offset += 4; // for the rparen + rparen + lbrace + rbrace
941 n = datas[n].lhs;1033 n = arg;
942 } else {1034 } else {
943 end_offset += 1; // for the rbrace1035 end_offset += 1; // for the rbrace
944 n = tree.extra_data[members.end - 1]; // last parameter1036 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
945 }1037 }
946 },1038 },
947 .call_comma,1039 .call_comma,
948 .async_call_comma,1040 .async_call_comma,
949 .tagged_union_enum_tag_trailing,1041 .tagged_union_enum_tag_trailing,
950 => {1042 => {
1043 _, const extra_index = tree.nodeData(n).node_and_extra;
1044 const params = tree.extraData(extra_index, Node.SubRange);
1045 assert(params.start != params.end);
951 end_offset += 2; // for the comma/semicolon + rparen/rbrace1046 end_offset += 2; // for the comma/semicolon + rparen/rbrace
952 const params = tree.extraData(datas[n].rhs, Node.SubRange);1047 n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter
953 assert(params.end > params.start);
954 n = tree.extra_data[params.end - 1]; // last parameter
955 },1048 },
956 .@"switch" => {1049 .@"switch" => {
957 const cases = tree.extraData(datas[n].rhs, Node.SubRange);1050 const condition, const extra_index = tree.nodeData(n).node_and_extra;
958 if (cases.end - cases.start == 0) {1051 const cases = tree.extraData(extra_index, Node.SubRange);
1052 if (cases.start == cases.end) {
959 end_offset += 3; // rparen, lbrace, rbrace1053 end_offset += 3; // rparen, lbrace, rbrace
960 n = datas[n].lhs; // condition expression1054 n = condition;
961 } else {1055 } else {
962 end_offset += 1; // for the rbrace1056 end_offset += 1; // for the rbrace
963 n = tree.extra_data[cases.end - 1]; // last case1057 n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case
964 }1058 }
965 },1059 },
966 .container_decl_arg => {1060 .container_decl_arg => {
967 const members = tree.extraData(datas[n].rhs, Node.SubRange);1061 const arg, const extra_index = tree.nodeData(n).node_and_extra;
968 if (members.end - members.start == 0) {1062 const members = tree.extraData(extra_index, Node.SubRange);
1063 if (members.end == members.start) {
969 end_offset += 3; // for the rparen + lbrace + rbrace1064 end_offset += 3; // for the rparen + lbrace + rbrace
970 n = datas[n].lhs;1065 n = arg;
971 } else {1066 } else {
972 end_offset += 1; // for the rbrace1067 end_offset += 1; // for the rbrace
973 n = tree.extra_data[members.end - 1]; // last parameter1068 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
974 }1069 }
975 },1070 },
976 .@"asm" => {1071 .@"asm" => {
977 const extra = tree.extraData(datas[n].rhs, Node.Asm);1072 _, const extra_index = tree.nodeData(n).node_and_extra;
1073 const extra = tree.extraData(extra_index, Node.Asm);
978 return extra.rparen + end_offset;1074 return extra.rparen + end_offset;
979 },1075 },
980 .array_init,1076 .array_init,
981 .struct_init,1077 .struct_init,
982 => {1078 => {
983 const elements = tree.extraData(datas[n].rhs, Node.SubRange);1079 _, const extra_index = tree.nodeData(n).node_and_extra;
984 assert(elements.end - elements.start > 0);1080 const elements = tree.extraData(extra_index, Node.SubRange);
1081 assert(elements.start != elements.end);
985 end_offset += 1; // for the rbrace1082 end_offset += 1; // for the rbrace
986 n = tree.extra_data[elements.end - 1]; // last element1083 n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element
987 },1084 },
988 .array_init_comma,1085 .array_init_comma,
989 .struct_init_comma,1086 .struct_init_comma,
990 .container_decl_arg_trailing,1087 .container_decl_arg_trailing,
991 .switch_comma,1088 .switch_comma,
992 => {1089 => {
993 const members = tree.extraData(datas[n].rhs, Node.SubRange);1090 _, const extra_index = tree.nodeData(n).node_and_extra;
994 assert(members.end - members.start > 0);1091 const members = tree.extraData(extra_index, Node.SubRange);
1092 assert(members.start != members.end);
995 end_offset += 2; // for the comma + rbrace1093 end_offset += 2; // for the comma + rbrace
996 n = tree.extra_data[members.end - 1]; // last parameter1094 n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter
997 },1095 },
998 .array_init_dot,1096 .array_init_dot,
999 .struct_init_dot,1097 .struct_init_dot,
...@@ -1002,9 +1100,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1002,9 +1100,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1002 .tagged_union,1100 .tagged_union,
1003 .builtin_call,1101 .builtin_call,
1004 => {1102 => {
1005 assert(datas[n].rhs - datas[n].lhs > 0);1103 const range = tree.nodeData(n).extra_range;
1104 assert(range.start != range.end);
1006 end_offset += 1; // for the rbrace1105 end_offset += 1; // for the rbrace
1007 n = tree.extra_data[datas[n].rhs - 1]; // last statement1106 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement
1008 },1107 },
1009 .array_init_dot_comma,1108 .array_init_dot_comma,
1010 .struct_init_dot_comma,1109 .struct_init_dot_comma,
...@@ -1013,20 +1112,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1013,20 +1112,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1013 .tagged_union_trailing,1112 .tagged_union_trailing,
1014 .builtin_call_comma,1113 .builtin_call_comma,
1015 => {1114 => {
1016 assert(datas[n].rhs - datas[n].lhs > 0);1115 const range = tree.nodeData(n).extra_range;
1116 assert(range.start != range.end);
1017 end_offset += 2; // for the comma/semicolon + rbrace/rparen1117 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1018 n = tree.extra_data[datas[n].rhs - 1]; // last member1118 n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member
1019 },1119 },
1020 .call_one,1120 .call_one,
1021 .async_call_one,1121 .async_call_one,
1022 .array_access,
1023 => {1122 => {
1024 end_offset += 1; // for the rparen/rbracket1123 _, const first_param = tree.nodeData(n).node_and_opt_node;
1025 if (datas[n].rhs == 0) {1124 end_offset += 1; // for the rparen
1026 return main_tokens[n] + end_offset;1125 n = first_param.unwrap() orelse {
1027 }1126 return tree.nodeMainToken(n) + end_offset;
1028 n = datas[n].rhs;1127 };
1029 },1128 },
1129
1030 .array_init_dot_two,1130 .array_init_dot_two,
1031 .block_two,1131 .block_two,
1032 .builtin_call_two,1132 .builtin_call_two,
...@@ -1034,14 +1134,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1034,14 +1134,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1034 .container_decl_two,1134 .container_decl_two,
1035 .tagged_union_two,1135 .tagged_union_two,
1036 => {1136 => {
1037 if (datas[n].rhs != 0) {1137 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1138 if (opt_rhs.unwrap()) |rhs| {
1038 end_offset += 1; // for the rparen/rbrace1139 end_offset += 1; // for the rparen/rbrace
1039 n = datas[n].rhs;1140 n = rhs;
1040 } else if (datas[n].lhs != 0) {1141 } else if (opt_lhs.unwrap()) |lhs| {
1041 end_offset += 1; // for the rparen/rbrace1142 end_offset += 1; // for the rparen/rbrace
1042 n = datas[n].lhs;1143 n = lhs;
1043 } else {1144 } else {
1044 switch (tags[n]) {1145 switch (tree.nodeTag(n)) {
1045 .array_init_dot_two,1146 .array_init_dot_two,
1046 .block_two,1147 .block_two,
1047 .struct_init_dot_two,1148 .struct_init_dot_two,
...@@ -1049,17 +1150,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1049,17 +1150,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1049 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace1150 .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace
1050 .container_decl_two => {1151 .container_decl_two => {
1051 var i: u32 = 2; // lbrace + rbrace1152 var i: u32 = 2; // lbrace + rbrace
1052 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;1153 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
1053 end_offset += i;1154 end_offset += i;
1054 },1155 },
1055 .tagged_union_two => {1156 .tagged_union_two => {
1056 var i: u32 = 5; // (enum) {}1157 var i: u32 = 5; // (enum) {}
1057 while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1;1158 while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1;
1058 end_offset += i;1159 end_offset += i;
1059 },1160 },
1060 else => unreachable,1161 else => unreachable,
1061 }1162 }
1062 return main_tokens[n] + end_offset;1163 return tree.nodeMainToken(n) + end_offset;
1063 }1164 }
1064 },1165 },
1065 .array_init_dot_two_comma,1166 .array_init_dot_two_comma,
...@@ -1069,341 +1170,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {...@@ -1069,341 +1170,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
1069 .container_decl_two_trailing,1170 .container_decl_two_trailing,
1070 .tagged_union_two_trailing,1171 .tagged_union_two_trailing,
1071 => {1172 => {
1173 const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node;
1072 end_offset += 2; // for the comma/semicolon + rbrace/rparen1174 end_offset += 2; // for the comma/semicolon + rbrace/rparen
1073 if (datas[n].rhs != 0) {1175 if (opt_rhs.unwrap()) |rhs| {
1074 n = datas[n].rhs;1176 n = rhs;
1075 } else if (datas[n].lhs != 0) {1177 } else if (opt_lhs.unwrap()) |lhs| {
1076 n = datas[n].lhs;1178 n = lhs;
1077 } else {1179 } else {
1078 unreachable;1180 unreachable;
1079 }1181 }
1080 },1182 },
1081 .simple_var_decl => {1183 .simple_var_decl => {
1082 if (datas[n].rhs != 0) {1184 const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node;
1083 n = datas[n].rhs;1185 if (init_node.unwrap()) |rhs| {
1084 } else if (datas[n].lhs != 0) {1186 n = rhs;
1085 n = datas[n].lhs;1187 } else if (type_node.unwrap()) |lhs| {
1188 n = lhs;
1086 } else {1189 } else {
1087 end_offset += 1; // from mut token to name1190 end_offset += 1; // from mut token to name
1088 return main_tokens[n] + end_offset;1191 return tree.nodeMainToken(n) + end_offset;
1089 }1192 }
1090 },1193 },
1091 .aligned_var_decl => {1194 .aligned_var_decl => {
1092 if (datas[n].rhs != 0) {1195 const align_node, const init_node = tree.nodeData(n).node_and_opt_node;
1093 n = datas[n].rhs;1196 if (init_node.unwrap()) |rhs| {
1094 } else if (datas[n].lhs != 0) {1197 n = rhs;
1095 end_offset += 1; // for the rparen
1096 n = datas[n].lhs;
1097 } else {1198 } else {
1098 end_offset += 1; // from mut token to name1199 end_offset += 1; // for the rparen
1099 return main_tokens[n] + end_offset;1200 n = align_node;
1100 }1201 }
1101 },1202 },
1102 .global_var_decl => {1203 .global_var_decl => {
1103 if (datas[n].rhs != 0) {1204 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1104 n = datas[n].rhs;1205 if (init_node.unwrap()) |rhs| {
1206 n = rhs;
1105 } else {1207 } else {
1106 const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl);1208 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1107 if (extra.section_node != 0) {1209 if (extra.section_node.unwrap()) |section_node| {
1108 end_offset += 1; // for the rparen1210 end_offset += 1; // for the rparen
1109 n = extra.section_node;1211 n = section_node;
1110 } else if (extra.align_node != 0) {1212 } else if (extra.align_node.unwrap()) |align_node| {
1111 end_offset += 1; // for the rparen1213 end_offset += 1; // for the rparen
1112 n = extra.align_node;1214 n = align_node;
1113 } else if (extra.type_node != 0) {1215 } else if (extra.type_node.unwrap()) |type_node| {
1114 n = extra.type_node;1216 n = type_node;
1115 } else {1217 } else {
1116 end_offset += 1; // from mut token to name1218 end_offset += 1; // from mut token to name
1117 return main_tokens[n] + end_offset;1219 return tree.nodeMainToken(n) + end_offset;
1118 }1220 }
1119 }1221 }
1120 },1222 },
1121 .local_var_decl => {1223 .local_var_decl => {
1122 if (datas[n].rhs != 0) {1224 const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node;
1123 n = datas[n].rhs;1225 if (init_node.unwrap()) |rhs| {
1226 n = rhs;
1124 } else {1227 } else {
1125 const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl);1228 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
1126 assert(extra.align_node != 0);
1127 end_offset += 1; // for the rparen1229 end_offset += 1; // for the rparen
1128 n = extra.align_node;1230 n = extra.align_node;
1129 }1231 }
1130 },1232 },
1131 .container_field_init => {1233 .container_field_init => {
1132 if (datas[n].rhs != 0) {1234 const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node;
1133 n = datas[n].rhs;1235 n = value_expr.unwrap() orelse type_expr;
1134 } else {
1135 assert(datas[n].lhs != 0);
1136 n = datas[n].lhs;
1137 }
1138 },1236 },
1139 .container_field_align => {1237
1140 assert(datas[n].rhs != 0);1238 .array_access,
1141 end_offset += 1; // for the rparen1239 .array_init_one,
1142 n = datas[n].rhs;1240 .container_field_align,
1241 => {
1242 _, const rhs = tree.nodeData(n).node_and_node;
1243 end_offset += 1; // for the rbracket/rbrace/rparen
1244 n = rhs;
1143 },1245 },
1144 .container_field => {1246 .container_field => {
1145 const extra = tree.extraData(datas[n].rhs, Node.ContainerField);1247 _, const extra_index = tree.nodeData(n).node_and_extra;
1146 assert(extra.value_expr != 0);1248 const extra = tree.extraData(extra_index, Node.ContainerField);
1147 n = extra.value_expr;1249 n = extra.value_expr;
1148 },1250 },
11491251
1150 .array_init_one,1252 .struct_init_one => {
1151 .struct_init_one,1253 _, const first_field = tree.nodeData(n).node_and_opt_node;
1152 => {
1153 end_offset += 1; // rbrace1254 end_offset += 1; // rbrace
1154 if (datas[n].rhs == 0) {1255 n = first_field.unwrap() orelse {
1155 return main_tokens[n] + end_offset;1256 return tree.nodeMainToken(n) + end_offset;
1156 } else {1257 };
1157 n = datas[n].rhs;1258 },
1158 }1259 .slice_open => {
1260 _, const start_node = tree.nodeData(n).node_and_node;
1261 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1262 n = start_node;
1263 },
1264 .array_init_one_comma => {
1265 _, const first_element = tree.nodeData(n).node_and_node;
1266 end_offset += 2; // comma + rbrace
1267 n = first_element;
1159 },1268 },
1160 .slice_open,
1161 .call_one_comma,1269 .call_one_comma,
1162 .async_call_one_comma,1270 .async_call_one_comma,
1163 .array_init_one_comma,
1164 .struct_init_one_comma,1271 .struct_init_one_comma,
1165 => {1272 => {
1273 _, const first_field = tree.nodeData(n).node_and_opt_node;
1166 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen1274 end_offset += 2; // ellipsis2 + rbracket, or comma + rparen
1167 n = datas[n].rhs;1275 n = first_field.unwrap().?;
1168 assert(n != 0);
1169 },1276 },
1170 .slice => {1277 .slice => {
1171 const extra = tree.extraData(datas[n].rhs, Node.Slice);1278 _, const extra_index = tree.nodeData(n).node_and_extra;
1172 assert(extra.end != 0); // should have used slice_open1279 const extra = tree.extraData(extra_index, Node.Slice);
1173 end_offset += 1; // rbracket1280 end_offset += 1; // rbracket
1174 n = extra.end;1281 n = extra.end;
1175 },1282 },
1176 .slice_sentinel => {1283 .slice_sentinel => {
1177 const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);1284 _, const extra_index = tree.nodeData(n).node_and_extra;
1178 assert(extra.sentinel != 0); // should have used slice1285 const extra = tree.extraData(extra_index, Node.SliceSentinel);
1179 end_offset += 1; // rbracket1286 end_offset += 1; // rbracket
1180 n = extra.sentinel;1287 n = extra.sentinel;
1181 },1288 },
11821289
1183 .@"continue", .@"break" => {1290 .@"continue", .@"break" => {
1184 if (datas[n].rhs != 0) {1291 const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node;
1185 n = datas[n].rhs;1292 if (opt_rhs.unwrap()) |rhs| {
1186 } else if (datas[n].lhs != 0) {1293 n = rhs;
1187 return datas[n].lhs + end_offset;1294 } else if (opt_label.unwrap()) |lhs| {
1295 return lhs + end_offset;
1188 } else {1296 } else {
1189 return main_tokens[n] + end_offset;1297 return tree.nodeMainToken(n) + end_offset;
1190 }1298 }
1191 },1299 },
1192 .while_cont => {1300 .while_cont => {
1193 const extra = tree.extraData(datas[n].rhs, Node.WhileCont);1301 _, const extra_index = tree.nodeData(n).node_and_extra;
1194 assert(extra.then_expr != 0);1302 const extra = tree.extraData(extra_index, Node.WhileCont);
1195 n = extra.then_expr;1303 n = extra.then_expr;
1196 },1304 },
1197 .@"while" => {1305 .@"while" => {
1198 const extra = tree.extraData(datas[n].rhs, Node.While);1306 _, const extra_index = tree.nodeData(n).node_and_extra;
1199 assert(extra.else_expr != 0);1307 const extra = tree.extraData(extra_index, Node.While);
1200 n = extra.else_expr;1308 n = extra.else_expr;
1201 },1309 },
1202 .@"if" => {1310 .@"if" => {
1203 const extra = tree.extraData(datas[n].rhs, Node.If);1311 _, const extra_index = tree.nodeData(n).node_and_extra;
1204 assert(extra.else_expr != 0);1312 const extra = tree.extraData(extra_index, Node.If);
1205 n = extra.else_expr;1313 n = extra.else_expr;
1206 },1314 },
1207 .@"for" => {1315 .@"for" => {
1208 const extra = @as(Node.For, @bitCast(datas[n].rhs));1316 const extra_index, const extra = tree.nodeData(n).@"for";
1209 n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)];1317 const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else);
1318 n = @enumFromInt(tree.extra_data[index]);
1210 },1319 },
1211 .array_type_sentinel => {1320 .array_type_sentinel => {
1212 const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel);1321 _, const extra_index = tree.nodeData(n).node_and_extra;
1322 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
1213 n = extra.elem_type;1323 n = extra.elem_type;
1214 },1324 },
1215 };1325 };
1216}1326}
12171327
1218pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {1328pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool {
1219 const token_starts = tree.tokens.items(.start);1329 const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)];
1220 const source = tree.source[token_starts[token1]..token_starts[token2]];
1221 return mem.indexOfScalar(u8, source, '\n') == null;1330 return mem.indexOfScalar(u8, source, '\n') == null;
1222}1331}
12231332
1224pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {1333pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 {
1225 const token_starts = tree.tokens.items(.start);
1226 const first_token = tree.firstToken(node);1334 const first_token = tree.firstToken(node);
1227 const last_token = tree.lastToken(node);1335 const last_token = tree.lastToken(node);
1228 const start = token_starts[first_token];1336 const start = tree.tokenStart(first_token);
1229 const end = token_starts[last_token] + tree.tokenSlice(last_token).len;1337 const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len;
1230 return tree.source[start..end];1338 return tree.source[start..end];
1231}1339}
12321340
1233pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1341pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1234 assert(tree.nodes.items(.tag)[node] == .global_var_decl);1342 assert(tree.nodeTag(node) == .global_var_decl);
1235 const data = tree.nodes.items(.data)[node];1343 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1236 const extra = tree.extraData(data.lhs, Node.GlobalVarDecl);1344 const extra = tree.extraData(extra_index, Node.GlobalVarDecl);
1237 return tree.fullVarDeclComponents(.{1345 return tree.fullVarDeclComponents(.{
1238 .type_node = extra.type_node,1346 .type_node = extra.type_node,
1239 .align_node = extra.align_node,1347 .align_node = extra.align_node,
1240 .addrspace_node = extra.addrspace_node,1348 .addrspace_node = extra.addrspace_node,
1241 .section_node = extra.section_node,1349 .section_node = extra.section_node,
1242 .init_node = data.rhs,1350 .init_node = init_node,
1243 .mut_token = tree.nodes.items(.main_token)[node],1351 .mut_token = tree.nodeMainToken(node),
1244 });1352 });
1245}1353}
12461354
1247pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1355pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1248 assert(tree.nodes.items(.tag)[node] == .local_var_decl);1356 assert(tree.nodeTag(node) == .local_var_decl);
1249 const data = tree.nodes.items(.data)[node];1357 const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node;
1250 const extra = tree.extraData(data.lhs, Node.LocalVarDecl);1358 const extra = tree.extraData(extra_index, Node.LocalVarDecl);
1251 return tree.fullVarDeclComponents(.{1359 return tree.fullVarDeclComponents(.{
1252 .type_node = extra.type_node,1360 .type_node = extra.type_node.toOptional(),
1253 .align_node = extra.align_node,1361 .align_node = extra.align_node.toOptional(),
1254 .addrspace_node = 0,1362 .addrspace_node = .none,
1255 .section_node = 0,1363 .section_node = .none,
1256 .init_node = data.rhs,1364 .init_node = init_node,
1257 .mut_token = tree.nodes.items(.main_token)[node],1365 .mut_token = tree.nodeMainToken(node),
1258 });1366 });
1259}1367}
12601368
1261pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1369pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1262 assert(tree.nodes.items(.tag)[node] == .simple_var_decl);1370 assert(tree.nodeTag(node) == .simple_var_decl);
1263 const data = tree.nodes.items(.data)[node];1371 const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node;
1264 return tree.fullVarDeclComponents(.{1372 return tree.fullVarDeclComponents(.{
1265 .type_node = data.lhs,1373 .type_node = type_node,
1266 .align_node = 0,1374 .align_node = .none,
1267 .addrspace_node = 0,1375 .addrspace_node = .none,
1268 .section_node = 0,1376 .section_node = .none,
1269 .init_node = data.rhs,1377 .init_node = init_node,
1270 .mut_token = tree.nodes.items(.main_token)[node],1378 .mut_token = tree.nodeMainToken(node),
1271 });1379 });
1272}1380}
12731381
1274pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {1382pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl {
1275 assert(tree.nodes.items(.tag)[node] == .aligned_var_decl);1383 assert(tree.nodeTag(node) == .aligned_var_decl);
1276 const data = tree.nodes.items(.data)[node];1384 const align_node, const init_node = tree.nodeData(node).node_and_opt_node;
1277 return tree.fullVarDeclComponents(.{1385 return tree.fullVarDeclComponents(.{
1278 .type_node = 0,1386 .type_node = .none,
1279 .align_node = data.lhs,1387 .align_node = align_node.toOptional(),
1280 .addrspace_node = 0,1388 .addrspace_node = .none,
1281 .section_node = 0,1389 .section_node = .none,
1282 .init_node = data.rhs,1390 .init_node = init_node,
1283 .mut_token = tree.nodes.items(.main_token)[node],1391 .mut_token = tree.nodeMainToken(node),
1284 });1392 });
1285}1393}
12861394
1287pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {1395pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure {
1288 const data = tree.nodes.items(.data)[node];1396 const extra_index, const value_expr = tree.nodeData(node).extra_and_node;
1289 const variable_count = tree.extra_data[data.lhs];1397 const variable_count = tree.extra_data[@intFromEnum(extra_index)];
1290 return tree.fullAssignDestructureComponents(.{1398 return tree.fullAssignDestructureComponents(.{
1291 .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count],1399 .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index),
1292 .equal_token = tree.nodes.items(.main_token)[node],1400 .equal_token = tree.nodeMainToken(node),
1293 .value_expr = data.rhs,1401 .value_expr = value_expr,
1294 });1402 });
1295}1403}
12961404
1297pub fn ifSimple(tree: Ast, node: Node.Index) full.If {1405pub fn ifSimple(tree: Ast, node: Node.Index) full.If {
1298 assert(tree.nodes.items(.tag)[node] == .if_simple);1406 assert(tree.nodeTag(node) == .if_simple);
1299 const data = tree.nodes.items(.data)[node];1407 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
1300 return tree.fullIfComponents(.{1408 return tree.fullIfComponents(.{
1301 .cond_expr = data.lhs,1409 .cond_expr = cond_expr,
1302 .then_expr = data.rhs,1410 .then_expr = then_expr,
1303 .else_expr = 0,1411 .else_expr = .none,
1304 .if_token = tree.nodes.items(.main_token)[node],1412 .if_token = tree.nodeMainToken(node),
1305 });1413 });
1306}1414}
13071415
1308pub fn ifFull(tree: Ast, node: Node.Index) full.If {1416pub fn ifFull(tree: Ast, node: Node.Index) full.If {
1309 assert(tree.nodes.items(.tag)[node] == .@"if");1417 assert(tree.nodeTag(node) == .@"if");
1310 const data = tree.nodes.items(.data)[node];1418 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1311 const extra = tree.extraData(data.rhs, Node.If);1419 const extra = tree.extraData(extra_index, Node.If);
1312 return tree.fullIfComponents(.{1420 return tree.fullIfComponents(.{
1313 .cond_expr = data.lhs,1421 .cond_expr = cond_expr,
1314 .then_expr = extra.then_expr,1422 .then_expr = extra.then_expr,
1315 .else_expr = extra.else_expr,1423 .else_expr = extra.else_expr.toOptional(),
1316 .if_token = tree.nodes.items(.main_token)[node],1424 .if_token = tree.nodeMainToken(node),
1317 });1425 });
1318}1426}
13191427
1320pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {1428pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField {
1321 assert(tree.nodes.items(.tag)[node] == .container_field);1429 assert(tree.nodeTag(node) == .container_field);
1322 const data = tree.nodes.items(.data)[node];1430 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1323 const extra = tree.extraData(data.rhs, Node.ContainerField);1431 const extra = tree.extraData(extra_index, Node.ContainerField);
1324 const main_token = tree.nodes.items(.main_token)[node];1432 const main_token = tree.nodeMainToken(node);
1325 return tree.fullContainerFieldComponents(.{1433 return tree.fullContainerFieldComponents(.{
1326 .main_token = main_token,1434 .main_token = main_token,
1327 .type_expr = data.lhs,1435 .type_expr = type_expr.toOptional(),
1328 .align_expr = extra.align_expr,1436 .align_expr = extra.align_expr.toOptional(),
1329 .value_expr = extra.value_expr,1437 .value_expr = extra.value_expr.toOptional(),
1330 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1438 .tuple_like = tree.tokenTag(main_token) != .identifier or
1331 tree.tokens.items(.tag)[main_token + 1] != .colon,1439 tree.tokenTag(main_token + 1) != .colon,
1332 });1440 });
1333}1441}
13341442
1335pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {1443pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField {
1336 assert(tree.nodes.items(.tag)[node] == .container_field_init);1444 assert(tree.nodeTag(node) == .container_field_init);
1337 const data = tree.nodes.items(.data)[node];1445 const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node;
1338 const main_token = tree.nodes.items(.main_token)[node];1446 const main_token = tree.nodeMainToken(node);
1339 return tree.fullContainerFieldComponents(.{1447 return tree.fullContainerFieldComponents(.{
1340 .main_token = main_token,1448 .main_token = main_token,
1341 .type_expr = data.lhs,1449 .type_expr = type_expr.toOptional(),
1342 .align_expr = 0,1450 .align_expr = .none,
1343 .value_expr = data.rhs,1451 .value_expr = value_expr,
1344 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1452 .tuple_like = tree.tokenTag(main_token) != .identifier or
1345 tree.tokens.items(.tag)[main_token + 1] != .colon,1453 tree.tokenTag(main_token + 1) != .colon,
1346 });1454 });
1347}1455}
13481456
1349pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {1457pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField {
1350 assert(tree.nodes.items(.tag)[node] == .container_field_align);1458 assert(tree.nodeTag(node) == .container_field_align);
1351 const data = tree.nodes.items(.data)[node];1459 const type_expr, const align_expr = tree.nodeData(node).node_and_node;
1352 const main_token = tree.nodes.items(.main_token)[node];1460 const main_token = tree.nodeMainToken(node);
1353 return tree.fullContainerFieldComponents(.{1461 return tree.fullContainerFieldComponents(.{
1354 .main_token = main_token,1462 .main_token = main_token,
1355 .type_expr = data.lhs,1463 .type_expr = type_expr.toOptional(),
1356 .align_expr = data.rhs,1464 .align_expr = align_expr.toOptional(),
1357 .value_expr = 0,1465 .value_expr = .none,
1358 .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or1466 .tuple_like = tree.tokenTag(main_token) != .identifier or
1359 tree.tokens.items(.tag)[main_token + 1] != .colon,1467 tree.tokenTag(main_token + 1) != .colon,
1360 });1468 });
1361}1469}
13621470
1363pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {1471pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1364 assert(tree.nodes.items(.tag)[node] == .fn_proto_simple);1472 assert(tree.nodeTag(node) == .fn_proto_simple);
1365 const data = tree.nodes.items(.data)[node];1473 const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node;
1366 buffer[0] = data.lhs;1474 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
1367 const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1];
1368 return tree.fullFnProtoComponents(.{1475 return tree.fullFnProtoComponents(.{
1369 .proto_node = node,1476 .proto_node = node,
1370 .fn_token = tree.nodes.items(.main_token)[node],1477 .fn_token = tree.nodeMainToken(node),
1371 .return_type = data.rhs,1478 .return_type = return_type,
1372 .params = params,1479 .params = params,
1373 .align_expr = 0,1480 .align_expr = .none,
1374 .addrspace_expr = 0,1481 .addrspace_expr = .none,
1375 .section_expr = 0,1482 .section_expr = .none,
1376 .callconv_expr = 0,1483 .callconv_expr = .none,
1377 });1484 });
1378}1485}
13791486
1380pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {1487pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto {
1381 assert(tree.nodes.items(.tag)[node] == .fn_proto_multi);1488 assert(tree.nodeTag(node) == .fn_proto_multi);
1382 const data = tree.nodes.items(.data)[node];1489 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1383 const params_range = tree.extraData(data.lhs, Node.SubRange);1490 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1384 const params = tree.extra_data[params_range.start..params_range.end];
1385 return tree.fullFnProtoComponents(.{1491 return tree.fullFnProtoComponents(.{
1386 .proto_node = node,1492 .proto_node = node,
1387 .fn_token = tree.nodes.items(.main_token)[node],1493 .fn_token = tree.nodeMainToken(node),
1388 .return_type = data.rhs,1494 .return_type = return_type,
1389 .params = params,1495 .params = params,
1390 .align_expr = 0,1496 .align_expr = .none,
1391 .addrspace_expr = 0,1497 .addrspace_expr = .none,
1392 .section_expr = 0,1498 .section_expr = .none,
1393 .callconv_expr = 0,1499 .callconv_expr = .none,
1394 });1500 });
1395}1501}
13961502
1397pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {1503pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto {
1398 assert(tree.nodes.items(.tag)[node] == .fn_proto_one);1504 assert(tree.nodeTag(node) == .fn_proto_one);
1399 const data = tree.nodes.items(.data)[node];1505 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1400 const extra = tree.extraData(data.lhs, Node.FnProtoOne);1506 const extra = tree.extraData(extra_index, Node.FnProtoOne);
1401 buffer[0] = extra.param;1507 const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param});
1402 const params = if (extra.param == 0) buffer[0..0] else buffer[0..1];
1403 return tree.fullFnProtoComponents(.{1508 return tree.fullFnProtoComponents(.{
1404 .proto_node = node,1509 .proto_node = node,
1405 .fn_token = tree.nodes.items(.main_token)[node],1510 .fn_token = tree.nodeMainToken(node),
1406 .return_type = data.rhs,1511 .return_type = return_type,
1407 .params = params,1512 .params = params,
1408 .align_expr = extra.align_expr,1513 .align_expr = extra.align_expr,
1409 .addrspace_expr = extra.addrspace_expr,1514 .addrspace_expr = extra.addrspace_expr,
...@@ -1413,14 +1518,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr...@@ -1413,14 +1518,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr
1413}1518}
14141519
1415pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {1520pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1416 assert(tree.nodes.items(.tag)[node] == .fn_proto);1521 assert(tree.nodeTag(node) == .fn_proto);
1417 const data = tree.nodes.items(.data)[node];1522 const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node;
1418 const extra = tree.extraData(data.lhs, Node.FnProto);1523 const extra = tree.extraData(extra_index, Node.FnProto);
1419 const params = tree.extra_data[extra.params_start..extra.params_end];1524 const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index);
1420 return tree.fullFnProtoComponents(.{1525 return tree.fullFnProtoComponents(.{
1421 .proto_node = node,1526 .proto_node = node,
1422 .fn_token = tree.nodes.items(.main_token)[node],1527 .fn_token = tree.nodeMainToken(node),
1423 .return_type = data.rhs,1528 .return_type = return_type,
1424 .params = params,1529 .params = params,
1425 .align_expr = extra.align_expr,1530 .align_expr = extra.align_expr,
1426 .addrspace_expr = extra.addrspace_expr,1531 .addrspace_expr = extra.addrspace_expr,
...@@ -1430,300 +1535,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {...@@ -1430,300 +1535,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto {
1430}1535}
14311536
1432pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {1537pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit {
1433 assert(tree.nodes.items(.tag)[node] == .struct_init_one or1538 assert(tree.nodeTag(node) == .struct_init_one or
1434 tree.nodes.items(.tag)[node] == .struct_init_one_comma);1539 tree.nodeTag(node) == .struct_init_one_comma);
1435 const data = tree.nodes.items(.data)[node];1540 const type_expr, const first_field = tree.nodeData(node).node_and_opt_node;
1436 buffer[0] = data.rhs;1541 const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field});
1437 const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1438 return .{1542 return .{
1439 .ast = .{1543 .ast = .{
1440 .lbrace = tree.nodes.items(.main_token)[node],1544 .lbrace = tree.nodeMainToken(node),
1441 .fields = fields,1545 .fields = fields,
1442 .type_expr = data.lhs,1546 .type_expr = type_expr.toOptional(),
1443 },1547 },
1444 };1548 };
1445}1549}
14461550
1447pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {1551pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit {
1448 assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or1552 assert(tree.nodeTag(node) == .struct_init_dot_two or
1449 tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma);1553 tree.nodeTag(node) == .struct_init_dot_two_comma);
1450 const data = tree.nodes.items(.data)[node];1554 const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1451 buffer.* = .{ data.lhs, data.rhs };
1452 const fields = if (data.rhs != 0)
1453 buffer[0..2]
1454 else if (data.lhs != 0)
1455 buffer[0..1]
1456 else
1457 buffer[0..0];
1458 return .{1555 return .{
1459 .ast = .{1556 .ast = .{
1460 .lbrace = tree.nodes.items(.main_token)[node],1557 .lbrace = tree.nodeMainToken(node),
1461 .fields = fields,1558 .fields = fields,
1462 .type_expr = 0,1559 .type_expr = .none,
1463 },1560 },
1464 };1561 };
1465}1562}
14661563
1467pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {1564pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit {
1468 assert(tree.nodes.items(.tag)[node] == .struct_init_dot or1565 assert(tree.nodeTag(node) == .struct_init_dot or
1469 tree.nodes.items(.tag)[node] == .struct_init_dot_comma);1566 tree.nodeTag(node) == .struct_init_dot_comma);
1470 const data = tree.nodes.items(.data)[node];1567 const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1471 return .{1568 return .{
1472 .ast = .{1569 .ast = .{
1473 .lbrace = tree.nodes.items(.main_token)[node],1570 .lbrace = tree.nodeMainToken(node),
1474 .fields = tree.extra_data[data.lhs..data.rhs],1571 .fields = fields,
1475 .type_expr = 0,1572 .type_expr = .none,
1476 },1573 },
1477 };1574 };
1478}1575}
14791576
1480pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {1577pub fn structInit(tree: Ast, node: Node.Index) full.StructInit {
1481 assert(tree.nodes.items(.tag)[node] == .struct_init or1578 assert(tree.nodeTag(node) == .struct_init or
1482 tree.nodes.items(.tag)[node] == .struct_init_comma);1579 tree.nodeTag(node) == .struct_init_comma);
1483 const data = tree.nodes.items(.data)[node];1580 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1484 const fields_range = tree.extraData(data.rhs, Node.SubRange);1581 const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1485 return .{1582 return .{
1486 .ast = .{1583 .ast = .{
1487 .lbrace = tree.nodes.items(.main_token)[node],1584 .lbrace = tree.nodeMainToken(node),
1488 .fields = tree.extra_data[fields_range.start..fields_range.end],1585 .fields = fields,
1489 .type_expr = data.lhs,1586 .type_expr = type_expr.toOptional(),
1490 },1587 },
1491 };1588 };
1492}1589}
14931590
1494pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {1591pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit {
1495 assert(tree.nodes.items(.tag)[node] == .array_init_one or1592 assert(tree.nodeTag(node) == .array_init_one or
1496 tree.nodes.items(.tag)[node] == .array_init_one_comma);1593 tree.nodeTag(node) == .array_init_one_comma);
1497 const data = tree.nodes.items(.data)[node];1594 const type_expr, buffer[0] = tree.nodeData(node).node_and_node;
1498 buffer[0] = data.rhs;
1499 const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1];
1500 return .{1595 return .{
1501 .ast = .{1596 .ast = .{
1502 .lbrace = tree.nodes.items(.main_token)[node],1597 .lbrace = tree.nodeMainToken(node),
1503 .elements = elements,1598 .elements = buffer[0..1],
1504 .type_expr = data.lhs,1599 .type_expr = type_expr.toOptional(),
1505 },1600 },
1506 };1601 };
1507}1602}
15081603
1509pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {1604pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit {
1510 assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or1605 assert(tree.nodeTag(node) == .array_init_dot_two or
1511 tree.nodes.items(.tag)[node] == .array_init_dot_two_comma);1606 tree.nodeTag(node) == .array_init_dot_two_comma);
1512 const data = tree.nodes.items(.data)[node];1607 const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1513 buffer.* = .{ data.lhs, data.rhs };
1514 const elements = if (data.rhs != 0)
1515 buffer[0..2]
1516 else if (data.lhs != 0)
1517 buffer[0..1]
1518 else
1519 buffer[0..0];
1520 return .{1608 return .{
1521 .ast = .{1609 .ast = .{
1522 .lbrace = tree.nodes.items(.main_token)[node],1610 .lbrace = tree.nodeMainToken(node),
1523 .elements = elements,1611 .elements = elements,
1524 .type_expr = 0,1612 .type_expr = .none,
1525 },1613 },
1526 };1614 };
1527}1615}
15281616
1529pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {1617pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit {
1530 assert(tree.nodes.items(.tag)[node] == .array_init_dot or1618 assert(tree.nodeTag(node) == .array_init_dot or
1531 tree.nodes.items(.tag)[node] == .array_init_dot_comma);1619 tree.nodeTag(node) == .array_init_dot_comma);
1532 const data = tree.nodes.items(.data)[node];1620 const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1533 return .{1621 return .{
1534 .ast = .{1622 .ast = .{
1535 .lbrace = tree.nodes.items(.main_token)[node],1623 .lbrace = tree.nodeMainToken(node),
1536 .elements = tree.extra_data[data.lhs..data.rhs],1624 .elements = elements,
1537 .type_expr = 0,1625 .type_expr = .none,
1538 },1626 },
1539 };1627 };
1540}1628}
15411629
1542pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {1630pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit {
1543 assert(tree.nodes.items(.tag)[node] == .array_init or1631 assert(tree.nodeTag(node) == .array_init or
1544 tree.nodes.items(.tag)[node] == .array_init_comma);1632 tree.nodeTag(node) == .array_init_comma);
1545 const data = tree.nodes.items(.data)[node];1633 const type_expr, const extra_index = tree.nodeData(node).node_and_extra;
1546 const elem_range = tree.extraData(data.rhs, Node.SubRange);1634 const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1547 return .{1635 return .{
1548 .ast = .{1636 .ast = .{
1549 .lbrace = tree.nodes.items(.main_token)[node],1637 .lbrace = tree.nodeMainToken(node),
1550 .elements = tree.extra_data[elem_range.start..elem_range.end],1638 .elements = elements,
1551 .type_expr = data.lhs,1639 .type_expr = type_expr.toOptional(),
1552 },1640 },
1553 };1641 };
1554}1642}
15551643
1556pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {1644pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType {
1557 assert(tree.nodes.items(.tag)[node] == .array_type);1645 assert(tree.nodeTag(node) == .array_type);
1558 const data = tree.nodes.items(.data)[node];1646 const elem_count, const elem_type = tree.nodeData(node).node_and_node;
1559 return .{1647 return .{
1560 .ast = .{1648 .ast = .{
1561 .lbracket = tree.nodes.items(.main_token)[node],1649 .lbracket = tree.nodeMainToken(node),
1562 .elem_count = data.lhs,1650 .elem_count = elem_count,
1563 .sentinel = 0,1651 .sentinel = .none,
1564 .elem_type = data.rhs,1652 .elem_type = elem_type,
1565 },1653 },
1566 };1654 };
1567}1655}
15681656
1569pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {1657pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType {
1570 assert(tree.nodes.items(.tag)[node] == .array_type_sentinel);1658 assert(tree.nodeTag(node) == .array_type_sentinel);
1571 const data = tree.nodes.items(.data)[node];1659 const elem_count, const extra_index = tree.nodeData(node).node_and_extra;
1572 const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel);1660 const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel);
1573 assert(extra.sentinel != 0);
1574 return .{1661 return .{
1575 .ast = .{1662 .ast = .{
1576 .lbracket = tree.nodes.items(.main_token)[node],1663 .lbracket = tree.nodeMainToken(node),
1577 .elem_count = data.lhs,1664 .elem_count = elem_count,
1578 .sentinel = extra.sentinel,1665 .sentinel = extra.sentinel.toOptional(),
1579 .elem_type = extra.elem_type,1666 .elem_type = extra.elem_type,
1580 },1667 },
1581 };1668 };
1582}1669}
15831670
1584pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {1671pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType {
1585 assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned);1672 assert(tree.nodeTag(node) == .ptr_type_aligned);
1586 const data = tree.nodes.items(.data)[node];1673 const align_node, const child_type = tree.nodeData(node).opt_node_and_node;
1587 return tree.fullPtrTypeComponents(.{1674 return tree.fullPtrTypeComponents(.{
1588 .main_token = tree.nodes.items(.main_token)[node],1675 .main_token = tree.nodeMainToken(node),
1589 .align_node = data.lhs,1676 .align_node = align_node,
1590 .addrspace_node = 0,1677 .addrspace_node = .none,
1591 .sentinel = 0,1678 .sentinel = .none,
1592 .bit_range_start = 0,1679 .bit_range_start = .none,
1593 .bit_range_end = 0,1680 .bit_range_end = .none,
1594 .child_type = data.rhs,1681 .child_type = child_type,
1595 });1682 });
1596}1683}
15971684
1598pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {1685pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType {
1599 assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel);1686 assert(tree.nodeTag(node) == .ptr_type_sentinel);
1600 const data = tree.nodes.items(.data)[node];1687 const sentinel, const child_type = tree.nodeData(node).opt_node_and_node;
1601 return tree.fullPtrTypeComponents(.{1688 return tree.fullPtrTypeComponents(.{
1602 .main_token = tree.nodes.items(.main_token)[node],1689 .main_token = tree.nodeMainToken(node),
1603 .align_node = 0,1690 .align_node = .none,
1604 .addrspace_node = 0,1691 .addrspace_node = .none,
1605 .sentinel = data.lhs,1692 .sentinel = sentinel,
1606 .bit_range_start = 0,1693 .bit_range_start = .none,
1607 .bit_range_end = 0,1694 .bit_range_end = .none,
1608 .child_type = data.rhs,1695 .child_type = child_type,
1609 });1696 });
1610}1697}
16111698
1612pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {1699pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType {
1613 assert(tree.nodes.items(.tag)[node] == .ptr_type);1700 assert(tree.nodeTag(node) == .ptr_type);
1614 const data = tree.nodes.items(.data)[node];1701 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1615 const extra = tree.extraData(data.lhs, Node.PtrType);1702 const extra = tree.extraData(extra_index, Node.PtrType);
1616 return tree.fullPtrTypeComponents(.{1703 return tree.fullPtrTypeComponents(.{
1617 .main_token = tree.nodes.items(.main_token)[node],1704 .main_token = tree.nodeMainToken(node),
1618 .align_node = extra.align_node,1705 .align_node = extra.align_node,
1619 .addrspace_node = extra.addrspace_node,1706 .addrspace_node = extra.addrspace_node,
1620 .sentinel = extra.sentinel,1707 .sentinel = extra.sentinel,
1621 .bit_range_start = 0,1708 .bit_range_start = .none,
1622 .bit_range_end = 0,1709 .bit_range_end = .none,
1623 .child_type = data.rhs,1710 .child_type = child_type,
1624 });1711 });
1625}1712}
16261713
1627pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {1714pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType {
1628 assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range);1715 assert(tree.nodeTag(node) == .ptr_type_bit_range);
1629 const data = tree.nodes.items(.data)[node];1716 const extra_index, const child_type = tree.nodeData(node).extra_and_node;
1630 const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange);1717 const extra = tree.extraData(extra_index, Node.PtrTypeBitRange);
1631 return tree.fullPtrTypeComponents(.{1718 return tree.fullPtrTypeComponents(.{
1632 .main_token = tree.nodes.items(.main_token)[node],1719 .main_token = tree.nodeMainToken(node),
1633 .align_node = extra.align_node,1720 .align_node = extra.align_node.toOptional(),
1634 .addrspace_node = extra.addrspace_node,1721 .addrspace_node = extra.addrspace_node,
1635 .sentinel = extra.sentinel,1722 .sentinel = extra.sentinel,
1636 .bit_range_start = extra.bit_range_start,1723 .bit_range_start = extra.bit_range_start.toOptional(),
1637 .bit_range_end = extra.bit_range_end,1724 .bit_range_end = extra.bit_range_end.toOptional(),
1638 .child_type = data.rhs,1725 .child_type = child_type,
1639 });1726 });
1640}1727}
16411728
1642pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {1729pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice {
1643 assert(tree.nodes.items(.tag)[node] == .slice_open);1730 assert(tree.nodeTag(node) == .slice_open);
1644 const data = tree.nodes.items(.data)[node];1731 const sliced, const start = tree.nodeData(node).node_and_node;
1645 return .{1732 return .{
1646 .ast = .{1733 .ast = .{
1647 .sliced = data.lhs,1734 .sliced = sliced,
1648 .lbracket = tree.nodes.items(.main_token)[node],1735 .lbracket = tree.nodeMainToken(node),
1649 .start = data.rhs,1736 .start = start,
1650 .end = 0,1737 .end = .none,
1651 .sentinel = 0,1738 .sentinel = .none,
1652 },1739 },
1653 };1740 };
1654}1741}
16551742
1656pub fn slice(tree: Ast, node: Node.Index) full.Slice {1743pub fn slice(tree: Ast, node: Node.Index) full.Slice {
1657 assert(tree.nodes.items(.tag)[node] == .slice);1744 assert(tree.nodeTag(node) == .slice);
1658 const data = tree.nodes.items(.data)[node];1745 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1659 const extra = tree.extraData(data.rhs, Node.Slice);1746 const extra = tree.extraData(extra_index, Node.Slice);
1660 return .{1747 return .{
1661 .ast = .{1748 .ast = .{
1662 .sliced = data.lhs,1749 .sliced = sliced,
1663 .lbracket = tree.nodes.items(.main_token)[node],1750 .lbracket = tree.nodeMainToken(node),
1664 .start = extra.start,1751 .start = extra.start,
1665 .end = extra.end,1752 .end = extra.end.toOptional(),
1666 .sentinel = 0,1753 .sentinel = .none,
1667 },1754 },
1668 };1755 };
1669}1756}
16701757
1671pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {1758pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice {
1672 assert(tree.nodes.items(.tag)[node] == .slice_sentinel);1759 assert(tree.nodeTag(node) == .slice_sentinel);
1673 const data = tree.nodes.items(.data)[node];1760 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
1674 const extra = tree.extraData(data.rhs, Node.SliceSentinel);1761 const extra = tree.extraData(extra_index, Node.SliceSentinel);
1675 return .{1762 return .{
1676 .ast = .{1763 .ast = .{
1677 .sliced = data.lhs,1764 .sliced = sliced,
1678 .lbracket = tree.nodes.items(.main_token)[node],1765 .lbracket = tree.nodeMainToken(node),
1679 .start = extra.start,1766 .start = extra.start,
1680 .end = extra.end,1767 .end = extra.end,
1681 .sentinel = extra.sentinel,1768 .sentinel = extra.sentinel.toOptional(),
1682 },1769 },
1683 };1770 };
1684}1771}
16851772
1686pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {1773pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1687 assert(tree.nodes.items(.tag)[node] == .container_decl_two or1774 assert(tree.nodeTag(node) == .container_decl_two or
1688 tree.nodes.items(.tag)[node] == .container_decl_two_trailing);1775 tree.nodeTag(node) == .container_decl_two_trailing);
1689 const data = tree.nodes.items(.data)[node];1776 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1690 buffer.* = .{ data.lhs, data.rhs };
1691 const members = if (data.rhs != 0)
1692 buffer[0..2]
1693 else if (data.lhs != 0)
1694 buffer[0..1]
1695 else
1696 buffer[0..0];
1697 return tree.fullContainerDeclComponents(.{1777 return tree.fullContainerDeclComponents(.{
1698 .main_token = tree.nodes.items(.main_token)[node],1778 .main_token = tree.nodeMainToken(node),
1699 .enum_token = null,1779 .enum_token = null,
1700 .members = members,1780 .members = members,
1701 .arg = 0,1781 .arg = .none,
1702 });1782 });
1703}1783}
17041784
1705pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {1785pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl {
1706 assert(tree.nodes.items(.tag)[node] == .container_decl or1786 assert(tree.nodeTag(node) == .container_decl or
1707 tree.nodes.items(.tag)[node] == .container_decl_trailing);1787 tree.nodeTag(node) == .container_decl_trailing);
1708 const data = tree.nodes.items(.data)[node];1788 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1709 return tree.fullContainerDeclComponents(.{1789 return tree.fullContainerDeclComponents(.{
1710 .main_token = tree.nodes.items(.main_token)[node],1790 .main_token = tree.nodeMainToken(node),
1711 .enum_token = null,1791 .enum_token = null,
1712 .members = tree.extra_data[data.lhs..data.rhs],1792 .members = members,
1713 .arg = 0,1793 .arg = .none,
1714 });1794 });
1715}1795}
17161796
1717pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {1797pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl {
1718 assert(tree.nodes.items(.tag)[node] == .container_decl_arg or1798 assert(tree.nodeTag(node) == .container_decl_arg or
1719 tree.nodes.items(.tag)[node] == .container_decl_arg_trailing);1799 tree.nodeTag(node) == .container_decl_arg_trailing);
1720 const data = tree.nodes.items(.data)[node];1800 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1721 const members_range = tree.extraData(data.rhs, Node.SubRange);1801 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1722 return tree.fullContainerDeclComponents(.{1802 return tree.fullContainerDeclComponents(.{
1723 .main_token = tree.nodes.items(.main_token)[node],1803 .main_token = tree.nodeMainToken(node),
1724 .enum_token = null,1804 .enum_token = null,
1725 .members = tree.extra_data[members_range.start..members_range.end],1805 .members = members,
1726 .arg = data.lhs,1806 .arg = arg.toOptional(),
1727 });1807 });
1728}1808}
17291809
...@@ -1731,175 +1811,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {...@@ -1731,175 +1811,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl {
1731 return .{1811 return .{
1732 .layout_token = null,1812 .layout_token = null,
1733 .ast = .{1813 .ast = .{
1734 .main_token = undefined,1814 .main_token = 0,
1735 .enum_token = null,1815 .enum_token = null,
1736 .members = tree.rootDecls(),1816 .members = tree.rootDecls(),
1737 .arg = 0,1817 .arg = .none,
1738 },1818 },
1739 };1819 };
1740}1820}
17411821
1742pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {1822pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl {
1743 assert(tree.nodes.items(.tag)[node] == .tagged_union_two or1823 assert(tree.nodeTag(node) == .tagged_union_two or
1744 tree.nodes.items(.tag)[node] == .tagged_union_two_trailing);1824 tree.nodeTag(node) == .tagged_union_two_trailing);
1745 const data = tree.nodes.items(.data)[node];1825 const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node);
1746 buffer.* = .{ data.lhs, data.rhs };1826 const main_token = tree.nodeMainToken(node);
1747 const members = if (data.rhs != 0)
1748 buffer[0..2]
1749 else if (data.lhs != 0)
1750 buffer[0..1]
1751 else
1752 buffer[0..0];
1753 const main_token = tree.nodes.items(.main_token)[node];
1754 return tree.fullContainerDeclComponents(.{1827 return tree.fullContainerDeclComponents(.{
1755 .main_token = main_token,1828 .main_token = main_token,
1756 .enum_token = main_token + 2, // union lparen enum1829 .enum_token = main_token + 2, // union lparen enum
1757 .members = members,1830 .members = members,
1758 .arg = 0,1831 .arg = .none,
1759 });1832 });
1760}1833}
17611834
1762pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {1835pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl {
1763 assert(tree.nodes.items(.tag)[node] == .tagged_union or1836 assert(tree.nodeTag(node) == .tagged_union or
1764 tree.nodes.items(.tag)[node] == .tagged_union_trailing);1837 tree.nodeTag(node) == .tagged_union_trailing);
1765 const data = tree.nodes.items(.data)[node];1838 const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index);
1766 const main_token = tree.nodes.items(.main_token)[node];1839 const main_token = tree.nodeMainToken(node);
1767 return tree.fullContainerDeclComponents(.{1840 return tree.fullContainerDeclComponents(.{
1768 .main_token = main_token,1841 .main_token = main_token,
1769 .enum_token = main_token + 2, // union lparen enum1842 .enum_token = main_token + 2, // union lparen enum
1770 .members = tree.extra_data[data.lhs..data.rhs],1843 .members = members,
1771 .arg = 0,1844 .arg = .none,
1772 });1845 });
1773}1846}
17741847
1775pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {1848pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {
1776 assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or1849 assert(tree.nodeTag(node) == .tagged_union_enum_tag or
1777 tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing);1850 tree.nodeTag(node) == .tagged_union_enum_tag_trailing);
1778 const data = tree.nodes.items(.data)[node];1851 const arg, const extra_index = tree.nodeData(node).node_and_extra;
1779 const members_range = tree.extraData(data.rhs, Node.SubRange);1852 const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1780 const main_token = tree.nodes.items(.main_token)[node];1853 const main_token = tree.nodeMainToken(node);
1781 return tree.fullContainerDeclComponents(.{1854 return tree.fullContainerDeclComponents(.{
1782 .main_token = main_token,1855 .main_token = main_token,
1783 .enum_token = main_token + 2, // union lparen enum1856 .enum_token = main_token + 2, // union lparen enum
1784 .members = tree.extra_data[members_range.start..members_range.end],1857 .members = members,
1785 .arg = data.lhs,1858 .arg = arg.toOptional(),
1786 });1859 });
1787}1860}
17881861
1789pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {1862pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {
1790 const data = &tree.nodes.items(.data)[node];1863 const main_token = tree.nodeMainToken(node);
1791 const main_token = tree.nodes.items(.main_token)[node];1864 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) {
1792 const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) {
1793 .identifier => .{ main_token + 2, main_token },1865 .identifier => .{ main_token + 2, main_token },
1794 .keyword_switch => .{ main_token, null },1866 .keyword_switch => .{ main_token, null },
1795 else => unreachable,1867 else => unreachable,
1796 };1868 };
1797 const extra = tree.extraData(data.rhs, Ast.Node.SubRange);1869 const condition, const extra_index = tree.nodeData(node).node_and_extra;
1870 const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index);
1798 return .{1871 return .{
1799 .ast = .{1872 .ast = .{
1800 .switch_token = switch_token,1873 .switch_token = switch_token,
1801 .condition = data.lhs,1874 .condition = condition,
1802 .cases = tree.extra_data[extra.start..extra.end],1875 .cases = cases,
1803 },1876 },
1804 .label_token = label_token,1877 .label_token = label_token,
1805 };1878 };
1806}1879}
18071880
1808pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {1881pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
1809 const data = &tree.nodes.items(.data)[node];1882 const first_value, const target_expr = tree.nodeData(node).opt_node_and_node;
1810 const values: *[1]Node.Index = &data.lhs;
1811 return tree.fullSwitchCaseComponents(.{1883 return tree.fullSwitchCaseComponents(.{
1812 .values = if (data.lhs == 0) values[0..0] else values[0..1],1884 .values = if (first_value == .none)
1813 .arrow_token = tree.nodes.items(.main_token)[node],1885 &.{}
1814 .target_expr = data.rhs,1886 else
1887 // Ensure that the returned slice points into the existing memory of the Ast
1888 (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1],
1889 .arrow_token = tree.nodeMainToken(node),
1890 .target_expr = target_expr,
1815 }, node);1891 }, node);
1816}1892}
18171893
1818pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {1894pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
1819 const data = tree.nodes.items(.data)[node];1895 const extra_index, const target_expr = tree.nodeData(node).extra_and_node;
1820 const extra = tree.extraData(data.lhs, Node.SubRange);1896 const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1821 return tree.fullSwitchCaseComponents(.{1897 return tree.fullSwitchCaseComponents(.{
1822 .values = tree.extra_data[extra.start..extra.end],1898 .values = values,
1823 .arrow_token = tree.nodes.items(.main_token)[node],1899 .arrow_token = tree.nodeMainToken(node),
1824 .target_expr = data.rhs,1900 .target_expr = target_expr,
1825 }, node);1901 }, node);
1826}1902}
18271903
1828pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {1904pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {
1829 const data = tree.nodes.items(.data)[node];1905 const template, const rparen = tree.nodeData(node).node_and_token;
1830 return tree.fullAsmComponents(.{1906 return tree.fullAsmComponents(.{
1831 .asm_token = tree.nodes.items(.main_token)[node],1907 .asm_token = tree.nodeMainToken(node),
1832 .template = data.lhs,1908 .template = template,
1833 .items = &.{},1909 .items = &.{},
1834 .rparen = data.rhs,1910 .rparen = rparen,
1835 });1911 });
1836}1912}
18371913
1838pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {1914pub fn asmFull(tree: Ast, node: Node.Index) full.Asm {
1839 const data = tree.nodes.items(.data)[node];1915 const template, const extra_index = tree.nodeData(node).node_and_extra;
1840 const extra = tree.extraData(data.rhs, Node.Asm);1916 const extra = tree.extraData(extra_index, Node.Asm);
1917 const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index);
1841 return tree.fullAsmComponents(.{1918 return tree.fullAsmComponents(.{
1842 .asm_token = tree.nodes.items(.main_token)[node],1919 .asm_token = tree.nodeMainToken(node),
1843 .template = data.lhs,1920 .template = template,
1844 .items = tree.extra_data[extra.items_start..extra.items_end],1921 .items = items,
1845 .rparen = extra.rparen,1922 .rparen = extra.rparen,
1846 });1923 });
1847}1924}
18481925
1849pub fn whileSimple(tree: Ast, node: Node.Index) full.While {1926pub fn whileSimple(tree: Ast, node: Node.Index) full.While {
1850 const data = tree.nodes.items(.data)[node];1927 const cond_expr, const then_expr = tree.nodeData(node).node_and_node;
1851 return tree.fullWhileComponents(.{1928 return tree.fullWhileComponents(.{
1852 .while_token = tree.nodes.items(.main_token)[node],1929 .while_token = tree.nodeMainToken(node),
1853 .cond_expr = data.lhs,1930 .cond_expr = cond_expr,
1854 .cont_expr = 0,1931 .cont_expr = .none,
1855 .then_expr = data.rhs,1932 .then_expr = then_expr,
1856 .else_expr = 0,1933 .else_expr = .none,
1857 });1934 });
1858}1935}
18591936
1860pub fn whileCont(tree: Ast, node: Node.Index) full.While {1937pub fn whileCont(tree: Ast, node: Node.Index) full.While {
1861 const data = tree.nodes.items(.data)[node];1938 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1862 const extra = tree.extraData(data.rhs, Node.WhileCont);1939 const extra = tree.extraData(extra_index, Node.WhileCont);
1863 return tree.fullWhileComponents(.{1940 return tree.fullWhileComponents(.{
1864 .while_token = tree.nodes.items(.main_token)[node],1941 .while_token = tree.nodeMainToken(node),
1865 .cond_expr = data.lhs,1942 .cond_expr = cond_expr,
1866 .cont_expr = extra.cont_expr,1943 .cont_expr = extra.cont_expr.toOptional(),
1867 .then_expr = extra.then_expr,1944 .then_expr = extra.then_expr,
1868 .else_expr = 0,1945 .else_expr = .none,
1869 });1946 });
1870}1947}
18711948
1872pub fn whileFull(tree: Ast, node: Node.Index) full.While {1949pub fn whileFull(tree: Ast, node: Node.Index) full.While {
1873 const data = tree.nodes.items(.data)[node];1950 const cond_expr, const extra_index = tree.nodeData(node).node_and_extra;
1874 const extra = tree.extraData(data.rhs, Node.While);1951 const extra = tree.extraData(extra_index, Node.While);
1875 return tree.fullWhileComponents(.{1952 return tree.fullWhileComponents(.{
1876 .while_token = tree.nodes.items(.main_token)[node],1953 .while_token = tree.nodeMainToken(node),
1877 .cond_expr = data.lhs,1954 .cond_expr = cond_expr,
1878 .cont_expr = extra.cont_expr,1955 .cont_expr = extra.cont_expr,
1879 .then_expr = extra.then_expr,1956 .then_expr = extra.then_expr,
1880 .else_expr = extra.else_expr,1957 .else_expr = extra.else_expr.toOptional(),
1881 });1958 });
1882}1959}
18831960
1884pub fn forSimple(tree: Ast, node: Node.Index) full.For {1961pub fn forSimple(tree: Ast, node: Node.Index) full.For {
1885 const data = &tree.nodes.items(.data)[node];1962 const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node;
1886 const inputs: *[1]Node.Index = &data.lhs;
1887 return tree.fullForComponents(.{1963 return tree.fullForComponents(.{
1888 .for_token = tree.nodes.items(.main_token)[node],1964 .for_token = tree.nodeMainToken(node),
1889 .inputs = inputs[0..1],1965 .inputs = (&data[0])[0..1],
1890 .then_expr = data.rhs,1966 .then_expr = data[1],
1891 .else_expr = 0,1967 .else_expr = .none,
1892 });1968 });
1893}1969}
18941970
1895pub fn forFull(tree: Ast, node: Node.Index) full.For {1971pub fn forFull(tree: Ast, node: Node.Index) full.For {
1896 const data = tree.nodes.items(.data)[node];1972 const extra_index, const extra = tree.nodeData(node).@"for";
1897 const extra = @as(Node.For, @bitCast(data.rhs));1973 const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index);
1898 const inputs = tree.extra_data[data.lhs..][0..extra.inputs];1974 const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]);
1899 const then_expr = tree.extra_data[data.lhs + extra.inputs];1975 const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none;
1900 const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0;
1901 return tree.fullForComponents(.{1976 return tree.fullForComponents(.{
1902 .for_token = tree.nodes.items(.main_token)[node],1977 .for_token = tree.nodeMainToken(node),
1903 .inputs = inputs,1978 .inputs = inputs,
1904 .then_expr = then_expr,1979 .then_expr = then_expr,
1905 .else_expr = else_expr,1980 .else_expr = else_expr,
...@@ -1907,28 +1982,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {...@@ -1907,28 +1982,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For {
1907}1982}
19081983
1909pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {1984pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call {
1910 const data = tree.nodes.items(.data)[node];1985 const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node;
1911 buffer.* = .{data.rhs};1986 const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param});
1912 const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0];
1913 return tree.fullCallComponents(.{1987 return tree.fullCallComponents(.{
1914 .lparen = tree.nodes.items(.main_token)[node],1988 .lparen = tree.nodeMainToken(node),
1915 .fn_expr = data.lhs,1989 .fn_expr = fn_expr,
1916 .params = params,1990 .params = params,
1917 });1991 });
1918}1992}
19191993
1920pub fn callFull(tree: Ast, node: Node.Index) full.Call {1994pub fn callFull(tree: Ast, node: Node.Index) full.Call {
1921 const data = tree.nodes.items(.data)[node];1995 const fn_expr, const extra_index = tree.nodeData(node).node_and_extra;
1922 const extra = tree.extraData(data.rhs, Node.SubRange);1996 const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index);
1923 return tree.fullCallComponents(.{1997 return tree.fullCallComponents(.{
1924 .lparen = tree.nodes.items(.main_token)[node],1998 .lparen = tree.nodeMainToken(node),
1925 .fn_expr = data.lhs,1999 .fn_expr = fn_expr,
1926 .params = tree.extra_data[extra.start..extra.end],2000 .params = params,
1927 });2001 });
1928}2002}
19292003
1930fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {2004fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl {
1931 const token_tags = tree.tokens.items(.tag);
1932 var result: full.VarDecl = .{2005 var result: full.VarDecl = .{
1933 .ast = info,2006 .ast = info,
1934 .visib_token = null,2007 .visib_token = null,
...@@ -1940,7 +2013,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl...@@ -1940,7 +2013,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
1940 var i = info.mut_token;2013 var i = info.mut_token;
1941 while (i > 0) {2014 while (i > 0) {
1942 i -= 1;2015 i -= 1;
1943 switch (token_tags[i]) {2016 switch (tree.tokenTag(i)) {
1944 .keyword_extern, .keyword_export => result.extern_export_token = i,2017 .keyword_extern, .keyword_export => result.extern_export_token = i,
1945 .keyword_comptime => result.comptime_token = i,2018 .keyword_comptime => result.comptime_token = i,
1946 .keyword_pub => result.visib_token = i,2019 .keyword_pub => result.visib_token = i,
...@@ -1953,14 +2026,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl...@@ -1953,14 +2026,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl
1953}2026}
19542027
1955fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {2028fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure {
1956 const token_tags = tree.tokens.items(.tag);
1957 const node_tags = tree.nodes.items(.tag);
1958 var result: full.AssignDestructure = .{2029 var result: full.AssignDestructure = .{
1959 .comptime_token = null,2030 .comptime_token = null,
1960 .ast = info,2031 .ast = info,
1961 };2032 };
1962 const first_variable_token = tree.firstToken(info.variables[0]);2033 const first_variable_token = tree.firstToken(info.variables[0]);
1963 const maybe_comptime_token = switch (node_tags[info.variables[0]]) {2034 const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) {
1964 .global_var_decl,2035 .global_var_decl,
1965 .local_var_decl,2036 .local_var_decl,
1966 .aligned_var_decl,2037 .aligned_var_decl,
...@@ -1968,14 +2039,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo...@@ -1968,14 +2039,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo
1968 => first_variable_token,2039 => first_variable_token,
1969 else => first_variable_token - 1,2040 else => first_variable_token - 1,
1970 };2041 };
1971 if (token_tags[maybe_comptime_token] == .keyword_comptime) {2042 if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) {
1972 result.comptime_token = maybe_comptime_token;2043 result.comptime_token = maybe_comptime_token;
1973 }2044 }
1974 return result;2045 return result;
1975}2046}
19762047
1977fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {2048fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
1978 const token_tags = tree.tokens.items(.tag);
1979 var result: full.If = .{2049 var result: full.If = .{
1980 .ast = info,2050 .ast = info,
1981 .payload_token = null,2051 .payload_token = null,
...@@ -1985,14 +2055,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {...@@ -1985,14 +2055,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
1985 // if (cond_expr) |x|2055 // if (cond_expr) |x|
1986 // ^ ^2056 // ^ ^
1987 const payload_pipe = tree.lastToken(info.cond_expr) + 2;2057 const payload_pipe = tree.lastToken(info.cond_expr) + 2;
1988 if (token_tags[payload_pipe] == .pipe) {2058 if (tree.tokenTag(payload_pipe) == .pipe) {
1989 result.payload_token = payload_pipe + 1;2059 result.payload_token = payload_pipe + 1;
1990 }2060 }
1991 if (info.else_expr != 0) {2061 if (info.else_expr != .none) {
1992 // then_expr else |x|2062 // then_expr else |x|
1993 // ^ ^2063 // ^ ^
1994 result.else_token = tree.lastToken(info.then_expr) + 1;2064 result.else_token = tree.lastToken(info.then_expr) + 1;
1995 if (token_tags[result.else_token + 1] == .pipe) {2065 if (tree.tokenTag(result.else_token + 1) == .pipe) {
1996 result.error_token = result.else_token + 2;2066 result.error_token = result.else_token + 2;
1997 }2067 }
1998 }2068 }
...@@ -2000,12 +2070,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {...@@ -2000,12 +2070,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If {
2000}2070}
20012071
2002fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {2072fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField {
2003 const token_tags = tree.tokens.items(.tag);
2004 var result: full.ContainerField = .{2073 var result: full.ContainerField = .{
2005 .ast = info,2074 .ast = info,
2006 .comptime_token = null,2075 .comptime_token = null,
2007 };2076 };
2008 if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) {2077 if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) {
2009 // comptime type = init,2078 // comptime type = init,
2010 // ^ ^2079 // ^ ^
2011 // comptime name: type = init,2080 // comptime name: type = init,
...@@ -2016,7 +2085,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)...@@ -2016,7 +2085,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components)
2016}2085}
20172086
2018fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {2087fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto {
2019 const token_tags = tree.tokens.items(.tag);
2020 var result: full.FnProto = .{2088 var result: full.FnProto = .{
2021 .ast = info,2089 .ast = info,
2022 .visib_token = null,2090 .visib_token = null,
...@@ -2028,7 +2096,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto...@@ -2028,7 +2096,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
2028 var i = info.fn_token;2096 var i = info.fn_token;
2029 while (i > 0) {2097 while (i > 0) {
2030 i -= 1;2098 i -= 1;
2031 switch (token_tags[i]) {2099 switch (tree.tokenTag(i)) {
2032 .keyword_extern,2100 .keyword_extern,
2033 .keyword_export,2101 .keyword_export,
2034 .keyword_inline,2102 .keyword_inline,
...@@ -2040,25 +2108,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto...@@ -2040,25 +2108,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto
2040 }2108 }
2041 }2109 }
2042 const after_fn_token = info.fn_token + 1;2110 const after_fn_token = info.fn_token + 1;
2043 if (token_tags[after_fn_token] == .identifier) {2111 if (tree.tokenTag(after_fn_token) == .identifier) {
2044 result.name_token = after_fn_token;2112 result.name_token = after_fn_token;
2045 result.lparen = after_fn_token + 1;2113 result.lparen = after_fn_token + 1;
2046 } else {2114 } else {
2047 result.lparen = after_fn_token;2115 result.lparen = after_fn_token;
2048 }2116 }
2049 assert(token_tags[result.lparen] == .l_paren);2117 assert(tree.tokenTag(result.lparen) == .l_paren);
20502118
2051 return result;2119 return result;
2052}2120}
20532121
2054fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {2122fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType {
2055 const token_tags = tree.tokens.items(.tag);2123 const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) {
2056 const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) {
2057 .asterisk,2124 .asterisk,
2058 .asterisk_asterisk,2125 .asterisk_asterisk,
2059 => .one,2126 => .one,
2060 .l_bracket => switch (token_tags[info.main_token + 1]) {2127 .l_bracket => switch (tree.tokenTag(info.main_token + 1)) {
2061 .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many,2128 .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many,
2062 else => .slice,2129 else => .slice,
2063 },2130 },
2064 else => unreachable,2131 else => unreachable,
...@@ -2074,23 +2141,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType...@@ -2074,23 +2141,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
2074 // here while looking for modifiers as that could result in false2141 // here while looking for modifiers as that could result in false
2075 // positives. Therefore, start after a sentinel if there is one and2142 // positives. Therefore, start after a sentinel if there is one and
2076 // skip over any align node and bit range nodes.2143 // skip over any align node and bit range nodes.
2077 var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) {2144 var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) {
2078 .many, .c => info.main_token + 1,2145 .many, .c => info.main_token + 1,
2079 else => info.main_token,2146 else => info.main_token,
2080 };2147 };
2081 const end = tree.firstToken(info.child_type);2148 const end = tree.firstToken(info.child_type);
2082 while (i < end) : (i += 1) {2149 while (i < end) : (i += 1) {
2083 switch (token_tags[i]) {2150 switch (tree.tokenTag(i)) {
2084 .keyword_allowzero => result.allowzero_token = i,2151 .keyword_allowzero => result.allowzero_token = i,
2085 .keyword_const => result.const_token = i,2152 .keyword_const => result.const_token = i,
2086 .keyword_volatile => result.volatile_token = i,2153 .keyword_volatile => result.volatile_token = i,
2087 .keyword_align => {2154 .keyword_align => {
2088 assert(info.align_node != 0);2155 const align_node = info.align_node.unwrap().?;
2089 if (info.bit_range_end != 0) {2156 if (info.bit_range_end.unwrap()) |bit_range_end| {
2090 assert(info.bit_range_start != 0);2157 assert(info.bit_range_start != .none);
2091 i = tree.lastToken(info.bit_range_end) + 1;2158 i = tree.lastToken(bit_range_end) + 1;
2092 } else {2159 } else {
2093 i = tree.lastToken(info.align_node) + 1;2160 i = tree.lastToken(align_node) + 1;
2094 }2161 }
2095 },2162 },
2096 else => {},2163 else => {},
...@@ -2100,30 +2167,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType...@@ -2100,30 +2167,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType
2100}2167}
21012168
2102fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {2169fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl {
2103 const token_tags = tree.tokens.items(.tag);
2104 var result: full.ContainerDecl = .{2170 var result: full.ContainerDecl = .{
2105 .ast = info,2171 .ast = info,
2106 .layout_token = null,2172 .layout_token = null,
2107 };2173 };
21082174
2109 if (info.main_token == 0) return result;2175 if (info.main_token == 0) return result; // .root
2176 const previous_token = info.main_token - 1;
21102177
2111 switch (token_tags[info.main_token - 1]) {2178 switch (tree.tokenTag(previous_token)) {
2112 .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1,2179 .keyword_extern, .keyword_packed => result.layout_token = previous_token,
2113 else => {},2180 else => {},
2114 }2181 }
2115 return result;2182 return result;
2116}2183}
21172184
2118fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {2185fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2119 const token_tags = tree.tokens.items(.tag);
2120 const tok_i = info.switch_token -| 1;2186 const tok_i = info.switch_token -| 1;
2121 var result: full.Switch = .{2187 var result: full.Switch = .{
2122 .ast = info,2188 .ast = info,
2123 .label_token = null,2189 .label_token = null,
2124 };2190 };
2125 if (token_tags[tok_i] == .colon and2191 if (tree.tokenTag(tok_i) == .colon and
2126 token_tags[tok_i -| 1] == .identifier)2192 tree.tokenTag(tok_i -| 1) == .identifier)
2127 {2193 {
2128 result.label_token = tok_i - 1;2194 result.label_token = tok_i - 1;
2129 }2195 }
...@@ -2131,26 +2197,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {...@@ -2131,26 +2197,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2131}2197}
21322198
2133fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {2199fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
2134 const token_tags = tree.tokens.items(.tag);
2135 const node_tags = tree.nodes.items(.tag);
2136 var result: full.SwitchCase = .{2200 var result: full.SwitchCase = .{
2137 .ast = info,2201 .ast = info,
2138 .payload_token = null,2202 .payload_token = null,
2139 .inline_token = null,2203 .inline_token = null,
2140 };2204 };
2141 if (token_tags[info.arrow_token + 1] == .pipe) {2205 if (tree.tokenTag(info.arrow_token + 1) == .pipe) {
2142 result.payload_token = info.arrow_token + 2;2206 result.payload_token = info.arrow_token + 2;
2143 }2207 }
2144 switch (node_tags[node]) {2208 result.inline_token = switch (tree.nodeTag(node)) {
2145 .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node),2209 .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0)
2146 else => {},2210 info.arrow_token - 2
2147 }2211 else
2212 tree.firstToken(result.ast.values[0]) - 1,
2213 else => null,
2214 };
2148 return result;2215 return result;
2149}2216}
21502217
2151fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {2218fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2152 const token_tags = tree.tokens.items(.tag);
2153 const node_tags = tree.nodes.items(.tag);
2154 var result: full.Asm = .{2219 var result: full.Asm = .{
2155 .ast = info,2220 .ast = info,
2156 .volatile_token = null,2221 .volatile_token = null,
...@@ -2158,11 +2223,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2158,11 +2223,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2158 .outputs = &.{},2223 .outputs = &.{},
2159 .first_clobber = null,2224 .first_clobber = null,
2160 };2225 };
2161 if (token_tags[info.asm_token + 1] == .keyword_volatile) {2226 if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) {
2162 result.volatile_token = info.asm_token + 1;2227 result.volatile_token = info.asm_token + 1;
2163 }2228 }
2164 const outputs_end: usize = for (info.items, 0..) |item, i| {2229 const outputs_end: usize = for (info.items, 0..) |item, i| {
2165 switch (node_tags[item]) {2230 switch (tree.nodeTag(item)) {
2166 .asm_output => continue,2231 .asm_output => continue,
2167 else => break i,2232 else => break i,
2168 }2233 }
...@@ -2174,10 +2239,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2174,10 +2239,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2174 if (info.items.len == 0) {2239 if (info.items.len == 0) {
2175 // asm ("foo" ::: "a", "b");2240 // asm ("foo" ::: "a", "b");
2176 const template_token = tree.lastToken(info.template);2241 const template_token = tree.lastToken(info.template);
2177 if (token_tags[template_token + 1] == .colon and2242 if (tree.tokenTag(template_token + 1) == .colon and
2178 token_tags[template_token + 2] == .colon and2243 tree.tokenTag(template_token + 2) == .colon and
2179 token_tags[template_token + 3] == .colon and2244 tree.tokenTag(template_token + 3) == .colon and
2180 token_tags[template_token + 4] == .string_literal)2245 tree.tokenTag(template_token + 4) == .string_literal)
2181 {2246 {
2182 result.first_clobber = template_token + 4;2247 result.first_clobber = template_token + 4;
2183 }2248 }
...@@ -2187,9 +2252,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2187,9 +2252,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2187 const rparen = tree.lastToken(last_input);2252 const rparen = tree.lastToken(last_input);
2188 var i = rparen + 1;2253 var i = rparen + 1;
2189 // Allow a (useless) comma right after the closing parenthesis.2254 // Allow a (useless) comma right after the closing parenthesis.
2190 if (token_tags[i] == .comma) i += 1;2255 if (tree.tokenTag(i) == .comma) i = i + 1;
2191 if (token_tags[i] == .colon and2256 if (tree.tokenTag(i) == .colon and
2192 token_tags[i + 1] == .string_literal)2257 tree.tokenTag(i + 1) == .string_literal)
2193 {2258 {
2194 result.first_clobber = i + 1;2259 result.first_clobber = i + 1;
2195 }2260 }
...@@ -2199,10 +2264,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2199,10 +2264,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2199 const rparen = tree.lastToken(last_output);2264 const rparen = tree.lastToken(last_output);
2200 var i = rparen + 1;2265 var i = rparen + 1;
2201 // Allow a (useless) comma right after the closing parenthesis.2266 // Allow a (useless) comma right after the closing parenthesis.
2202 if (token_tags[i] == .comma) i += 1;2267 if (tree.tokenTag(i) == .comma) i = i + 1;
2203 if (token_tags[i] == .colon and2268 if (tree.tokenTag(i) == .colon and
2204 token_tags[i + 1] == .colon and2269 tree.tokenTag(i + 1) == .colon and
2205 token_tags[i + 2] == .string_literal)2270 tree.tokenTag(i + 2) == .string_literal)
2206 {2271 {
2207 result.first_clobber = i + 2;2272 result.first_clobber = i + 2;
2208 }2273 }
...@@ -2212,7 +2277,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {...@@ -2212,7 +2277,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm {
2212}2277}
22132278
2214fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {2279fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2215 const token_tags = tree.tokens.items(.tag);
2216 var result: full.While = .{2280 var result: full.While = .{
2217 .ast = info,2281 .ast = info,
2218 .inline_token = null,2282 .inline_token = null,
...@@ -2221,25 +2285,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {...@@ -2221,25 +2285,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2221 .else_token = undefined,2285 .else_token = undefined,
2222 .error_token = null,2286 .error_token = null,
2223 };2287 };
2224 var tok_i = info.while_token -| 1;2288 var tok_i = info.while_token;
2225 if (token_tags[tok_i] == .keyword_inline) {2289 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2226 result.inline_token = tok_i;2290 result.inline_token = tok_i - 1;
2227 tok_i -|= 1;2291 tok_i = tok_i - 1;
2228 }2292 }
2229 if (token_tags[tok_i] == .colon and2293 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2230 token_tags[tok_i -| 1] == .identifier)2294 result.label_token = tok_i - 2;
2231 {
2232 result.label_token = tok_i - 1;
2233 }2295 }
2234 const last_cond_token = tree.lastToken(info.cond_expr);2296 const last_cond_token = tree.lastToken(info.cond_expr);
2235 if (token_tags[last_cond_token + 2] == .pipe) {2297 if (tree.tokenTag(last_cond_token + 2) == .pipe) {
2236 result.payload_token = last_cond_token + 3;2298 result.payload_token = last_cond_token + 3;
2237 }2299 }
2238 if (info.else_expr != 0) {2300 if (info.else_expr != .none) {
2239 // then_expr else |x|2301 // then_expr else |x|
2240 // ^ ^2302 // ^ ^
2241 result.else_token = tree.lastToken(info.then_expr) + 1;2303 result.else_token = tree.lastToken(info.then_expr) + 1;
2242 if (token_tags[result.else_token + 1] == .pipe) {2304 if (tree.tokenTag(result.else_token + 1) == .pipe) {
2243 result.error_token = result.else_token + 2;2305 result.error_token = result.else_token + 2;
2244 }2306 }
2245 }2307 }
...@@ -2247,7 +2309,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {...@@ -2247,7 +2309,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While {
2247}2309}
22482310
2249fn fullForComponents(tree: Ast, info: full.For.Components) full.For {2311fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2250 const token_tags = tree.tokens.items(.tag);
2251 var result: full.For = .{2312 var result: full.For = .{
2252 .ast = info,2313 .ast = info,
2253 .inline_token = null,2314 .inline_token = null,
...@@ -2255,39 +2316,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {...@@ -2255,39 +2316,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For {
2255 .payload_token = undefined,2316 .payload_token = undefined,
2256 .else_token = undefined,2317 .else_token = undefined,
2257 };2318 };
2258 var tok_i = info.for_token -| 1;2319 var tok_i = info.for_token;
2259 if (token_tags[tok_i] == .keyword_inline) {2320 if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) {
2260 result.inline_token = tok_i;2321 result.inline_token = tok_i - 1;
2261 tok_i -|= 1;2322 tok_i = tok_i - 1;
2262 }2323 }
2263 if (token_tags[tok_i] == .colon and2324 if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) {
2264 token_tags[tok_i -| 1] == .identifier)2325 result.label_token = tok_i - 2;
2265 {
2266 result.label_token = tok_i - 1;
2267 }2326 }
2268 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);2327 const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]);
2269 result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma);2328 result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma);
2270 if (info.else_expr != 0) {2329 if (info.else_expr != .none) {
2271 result.else_token = tree.lastToken(info.then_expr) + 1;2330 result.else_token = tree.lastToken(info.then_expr) + 1;
2272 }2331 }
2273 return result;2332 return result;
2274}2333}
22752334
2276fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {2335fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call {
2277 const token_tags = tree.tokens.items(.tag);
2278 var result: full.Call = .{2336 var result: full.Call = .{
2279 .ast = info,2337 .ast = info,
2280 .async_token = null,2338 .async_token = null,
2281 };2339 };
2282 const first_token = tree.firstToken(info.fn_expr);2340 const first_token = tree.firstToken(info.fn_expr);
2283 if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) {2341 if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) {
2284 result.async_token = first_token - 1;2342 result.async_token = first_token - 1;
2285 }2343 }
2286 return result;2344 return result;
2287}2345}
22882346
2289pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {2347pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2290 return switch (tree.nodes.items(.tag)[node]) {2348 return switch (tree.nodeTag(node)) {
2291 .global_var_decl => tree.globalVarDecl(node),2349 .global_var_decl => tree.globalVarDecl(node),
2292 .local_var_decl => tree.localVarDecl(node),2350 .local_var_decl => tree.localVarDecl(node),
2293 .aligned_var_decl => tree.alignedVarDecl(node),2351 .aligned_var_decl => tree.alignedVarDecl(node),
...@@ -2297,7 +2355,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {...@@ -2297,7 +2355,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl {
2297}2355}
22982356
2299pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {2357pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2300 return switch (tree.nodes.items(.tag)[node]) {2358 return switch (tree.nodeTag(node)) {
2301 .if_simple => tree.ifSimple(node),2359 .if_simple => tree.ifSimple(node),
2302 .@"if" => tree.ifFull(node),2360 .@"if" => tree.ifFull(node),
2303 else => null,2361 else => null,
...@@ -2305,7 +2363,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {...@@ -2305,7 +2363,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If {
2305}2363}
23062364
2307pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {2365pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2308 return switch (tree.nodes.items(.tag)[node]) {2366 return switch (tree.nodeTag(node)) {
2309 .while_simple => tree.whileSimple(node),2367 .while_simple => tree.whileSimple(node),
2310 .while_cont => tree.whileCont(node),2368 .while_cont => tree.whileCont(node),
2311 .@"while" => tree.whileFull(node),2369 .@"while" => tree.whileFull(node),
...@@ -2314,7 +2372,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {...@@ -2314,7 +2372,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While {
2314}2372}
23152373
2316pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {2374pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2317 return switch (tree.nodes.items(.tag)[node]) {2375 return switch (tree.nodeTag(node)) {
2318 .for_simple => tree.forSimple(node),2376 .for_simple => tree.forSimple(node),
2319 .@"for" => tree.forFull(node),2377 .@"for" => tree.forFull(node),
2320 else => null,2378 else => null,
...@@ -2322,7 +2380,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {...@@ -2322,7 +2380,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For {
2322}2380}
23232381
2324pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {2382pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2325 return switch (tree.nodes.items(.tag)[node]) {2383 return switch (tree.nodeTag(node)) {
2326 .container_field_init => tree.containerFieldInit(node),2384 .container_field_init => tree.containerFieldInit(node),
2327 .container_field_align => tree.containerFieldAlign(node),2385 .container_field_align => tree.containerFieldAlign(node),
2328 .container_field => tree.containerField(node),2386 .container_field => tree.containerField(node),
...@@ -2331,18 +2389,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {...@@ -2331,18 +2389,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField {
2331}2389}
23322390
2333pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {2391pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto {
2334 return switch (tree.nodes.items(.tag)[node]) {2392 return switch (tree.nodeTag(node)) {
2335 .fn_proto => tree.fnProto(node),2393 .fn_proto => tree.fnProto(node),
2336 .fn_proto_multi => tree.fnProtoMulti(node),2394 .fn_proto_multi => tree.fnProtoMulti(node),
2337 .fn_proto_one => tree.fnProtoOne(buffer, node),2395 .fn_proto_one => tree.fnProtoOne(buffer, node),
2338 .fn_proto_simple => tree.fnProtoSimple(buffer, node),2396 .fn_proto_simple => tree.fnProtoSimple(buffer, node),
2339 .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs),2397 .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]),
2340 else => null,2398 else => null,
2341 };2399 };
2342}2400}
23432401
2344pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {2402pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit {
2345 return switch (tree.nodes.items(.tag)[node]) {2403 return switch (tree.nodeTag(node)) {
2346 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),2404 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node),
2347 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),2405 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node),
2348 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),2406 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node),
...@@ -2352,7 +2410,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?...@@ -2352,7 +2410,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?
2352}2410}
23532411
2354pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {2412pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit {
2355 return switch (tree.nodes.items(.tag)[node]) {2413 return switch (tree.nodeTag(node)) {
2356 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),2414 .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node),
2357 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),2415 .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node),
2358 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),2416 .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node),
...@@ -2362,7 +2420,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full....@@ -2362,7 +2420,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.
2362}2420}
23632421
2364pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {2422pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2365 return switch (tree.nodes.items(.tag)[node]) {2423 return switch (tree.nodeTag(node)) {
2366 .array_type => tree.arrayType(node),2424 .array_type => tree.arrayType(node),
2367 .array_type_sentinel => tree.arrayTypeSentinel(node),2425 .array_type_sentinel => tree.arrayTypeSentinel(node),
2368 else => null,2426 else => null,
...@@ -2370,7 +2428,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {...@@ -2370,7 +2428,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType {
2370}2428}
23712429
2372pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {2430pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2373 return switch (tree.nodes.items(.tag)[node]) {2431 return switch (tree.nodeTag(node)) {
2374 .ptr_type_aligned => tree.ptrTypeAligned(node),2432 .ptr_type_aligned => tree.ptrTypeAligned(node),
2375 .ptr_type_sentinel => tree.ptrTypeSentinel(node),2433 .ptr_type_sentinel => tree.ptrTypeSentinel(node),
2376 .ptr_type => tree.ptrType(node),2434 .ptr_type => tree.ptrType(node),
...@@ -2380,7 +2438,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {...@@ -2380,7 +2438,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType {
2380}2438}
23812439
2382pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {2440pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2383 return switch (tree.nodes.items(.tag)[node]) {2441 return switch (tree.nodeTag(node)) {
2384 .slice_open => tree.sliceOpen(node),2442 .slice_open => tree.sliceOpen(node),
2385 .slice => tree.slice(node),2443 .slice => tree.slice(node),
2386 .slice_sentinel => tree.sliceSentinel(node),2444 .slice_sentinel => tree.sliceSentinel(node),
...@@ -2389,7 +2447,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {...@@ -2389,7 +2447,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice {
2389}2447}
23902448
2391pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {2449pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl {
2392 return switch (tree.nodes.items(.tag)[node]) {2450 return switch (tree.nodeTag(node)) {
2393 .root => tree.containerDeclRoot(),2451 .root => tree.containerDeclRoot(),
2394 .container_decl, .container_decl_trailing => tree.containerDecl(node),2452 .container_decl, .container_decl_trailing => tree.containerDecl(node),
2395 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),2453 .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node),
...@@ -2402,14 +2460,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index...@@ -2402,14 +2460,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index
2402}2460}
24032461
2404pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {2462pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {
2405 return switch (tree.nodes.items(.tag)[node]) {2463 return switch (tree.nodeTag(node)) {
2406 .@"switch", .switch_comma => tree.switchFull(node),2464 .@"switch", .switch_comma => tree.switchFull(node),
2407 else => null,2465 else => null,
2408 };2466 };
2409}2467}
24102468
2411pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {2469pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2412 return switch (tree.nodes.items(.tag)[node]) {2470 return switch (tree.nodeTag(node)) {
2413 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),2471 .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),
2414 .switch_case, .switch_case_inline => tree.switchCase(node),2472 .switch_case, .switch_case_inline => tree.switchCase(node),
2415 else => null,2473 else => null,
...@@ -2417,7 +2475,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {...@@ -2417,7 +2475,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
2417}2475}
24182476
2419pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {2477pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2420 return switch (tree.nodes.items(.tag)[node]) {2478 return switch (tree.nodeTag(node)) {
2421 .asm_simple => tree.asmSimple(node),2479 .asm_simple => tree.asmSimple(node),
2422 .@"asm" => tree.asmFull(node),2480 .@"asm" => tree.asmFull(node),
2423 else => null,2481 else => null,
...@@ -2425,7 +2483,7 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {...@@ -2425,7 +2483,7 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm {
2425}2483}
24262484
2427pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {2485pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call {
2428 return switch (tree.nodes.items(.tag)[node]) {2486 return switch (tree.nodeTag(node)) {
2429 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),2487 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
2430 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),2488 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node),
2431 else => null,2489 else => null,
...@@ -2433,37 +2491,17 @@ pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.C...@@ -2433,37 +2491,17 @@ pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.C
2433}2491}
24342492
2435pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {2493pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2436 const data = tree.nodes.items(.data)[node];2494 return switch (tree.nodeTag(node)) {
2437 return switch (tree.nodes.items(.tag)[node]) {2495 .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2438 .builtin_call_two, .builtin_call_two_comma => {2496 .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2439 buffer.* = .{ data.lhs, data.rhs };
2440 if (data.rhs != 0) {
2441 return buffer[0..2];
2442 } else if (data.lhs != 0) {
2443 return buffer[0..1];
2444 } else {
2445 return buffer[0..0];
2446 }
2447 },
2448 .builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs],
2449 else => null,2497 else => null,
2450 };2498 };
2451}2499}
24522500
2453pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {2501pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index {
2454 const data = tree.nodes.items(.data)[node];2502 return switch (tree.nodeTag(node)) {
2455 return switch (tree.nodes.items(.tag)[node]) {2503 .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node),
2456 .block_two, .block_two_semicolon => {2504 .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index),
2457 buffer.* = .{ data.lhs, data.rhs };
2458 if (data.rhs != 0) {
2459 return buffer[0..2];
2460 } else if (data.lhs != 0) {
2461 return buffer[0..1];
2462 } else {
2463 return buffer[0..0];
2464 }
2465 },
2466 .block, .block_semicolon => tree.extra_data[data.lhs..data.rhs],
2467 else => null,2505 else => null,
2468 };2506 };
2469}2507}
...@@ -2480,11 +2518,11 @@ pub const full = struct {...@@ -2480,11 +2518,11 @@ pub const full = struct {
24802518
2481 pub const Components = struct {2519 pub const Components = struct {
2482 mut_token: TokenIndex,2520 mut_token: TokenIndex,
2483 type_node: Node.Index,2521 type_node: Node.OptionalIndex,
2484 align_node: Node.Index,2522 align_node: Node.OptionalIndex,
2485 addrspace_node: Node.Index,2523 addrspace_node: Node.OptionalIndex,
2486 section_node: Node.Index,2524 section_node: Node.OptionalIndex,
2487 init_node: Node.Index,2525 init_node: Node.OptionalIndex,
2488 };2526 };
24892527
2490 pub fn firstToken(var_decl: VarDecl) TokenIndex {2528 pub fn firstToken(var_decl: VarDecl) TokenIndex {
...@@ -2513,7 +2551,7 @@ pub const full = struct {...@@ -2513,7 +2551,7 @@ pub const full = struct {
2513 payload_token: ?TokenIndex,2551 payload_token: ?TokenIndex,
2514 /// Points to the identifier after the `|`.2552 /// Points to the identifier after the `|`.
2515 error_token: ?TokenIndex,2553 error_token: ?TokenIndex,
2516 /// Populated only if else_expr != 0.2554 /// Populated only if else_expr != .none.
2517 else_token: TokenIndex,2555 else_token: TokenIndex,
2518 ast: Components,2556 ast: Components,
25192557
...@@ -2521,7 +2559,7 @@ pub const full = struct {...@@ -2521,7 +2559,7 @@ pub const full = struct {
2521 if_token: TokenIndex,2559 if_token: TokenIndex,
2522 cond_expr: Node.Index,2560 cond_expr: Node.Index,
2523 then_expr: Node.Index,2561 then_expr: Node.Index,
2524 else_expr: Node.Index,2562 else_expr: Node.OptionalIndex,
2525 };2563 };
2526 };2564 };
25272565
...@@ -2531,15 +2569,15 @@ pub const full = struct {...@@ -2531,15 +2569,15 @@ pub const full = struct {
2531 label_token: ?TokenIndex,2569 label_token: ?TokenIndex,
2532 payload_token: ?TokenIndex,2570 payload_token: ?TokenIndex,
2533 error_token: ?TokenIndex,2571 error_token: ?TokenIndex,
2534 /// Populated only if else_expr != 0.2572 /// Populated only if else_expr != none.
2535 else_token: TokenIndex,2573 else_token: TokenIndex,
25362574
2537 pub const Components = struct {2575 pub const Components = struct {
2538 while_token: TokenIndex,2576 while_token: TokenIndex,
2539 cond_expr: Node.Index,2577 cond_expr: Node.Index,
2540 cont_expr: Node.Index,2578 cont_expr: Node.OptionalIndex,
2541 then_expr: Node.Index,2579 then_expr: Node.Index,
2542 else_expr: Node.Index,2580 else_expr: Node.OptionalIndex,
2543 };2581 };
2544 };2582 };
25452583
...@@ -2548,14 +2586,14 @@ pub const full = struct {...@@ -2548,14 +2586,14 @@ pub const full = struct {
2548 inline_token: ?TokenIndex,2586 inline_token: ?TokenIndex,
2549 label_token: ?TokenIndex,2587 label_token: ?TokenIndex,
2550 payload_token: TokenIndex,2588 payload_token: TokenIndex,
2551 /// Populated only if else_expr != 0.2589 /// Populated only if else_expr != .none.
2552 else_token: TokenIndex,2590 else_token: ?TokenIndex,
25532591
2554 pub const Components = struct {2592 pub const Components = struct {
2555 for_token: TokenIndex,2593 for_token: TokenIndex,
2556 inputs: []const Node.Index,2594 inputs: []const Node.Index,
2557 then_expr: Node.Index,2595 then_expr: Node.Index,
2558 else_expr: Node.Index,2596 else_expr: Node.OptionalIndex,
2559 };2597 };
2560 };2598 };
25612599
...@@ -2565,9 +2603,10 @@ pub const full = struct {...@@ -2565,9 +2603,10 @@ pub const full = struct {
25652603
2566 pub const Components = struct {2604 pub const Components = struct {
2567 main_token: TokenIndex,2605 main_token: TokenIndex,
2568 type_expr: Node.Index,2606 /// Can only be `.none` after calling `convertToNonTupleLike`.
2569 align_expr: Node.Index,2607 type_expr: Node.OptionalIndex,
2570 value_expr: Node.Index,2608 align_expr: Node.OptionalIndex,
2609 value_expr: Node.OptionalIndex,
2571 tuple_like: bool,2610 tuple_like: bool,
2572 };2611 };
25732612
...@@ -2575,11 +2614,11 @@ pub const full = struct {...@@ -2575,11 +2614,11 @@ pub const full = struct {
2575 return cf.comptime_token orelse cf.ast.main_token;2614 return cf.comptime_token orelse cf.ast.main_token;
2576 }2615 }
25772616
2578 pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void {2617 pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void {
2579 if (!cf.ast.tuple_like) return;2618 if (!cf.ast.tuple_like) return;
2580 if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return;2619 if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return;
25812620
2582 cf.ast.type_expr = 0;2621 cf.ast.type_expr = .none;
2583 cf.ast.tuple_like = false;2622 cf.ast.tuple_like = false;
2584 }2623 }
2585 };2624 };
...@@ -2595,12 +2634,12 @@ pub const full = struct {...@@ -2595,12 +2634,12 @@ pub const full = struct {
2595 pub const Components = struct {2634 pub const Components = struct {
2596 proto_node: Node.Index,2635 proto_node: Node.Index,
2597 fn_token: TokenIndex,2636 fn_token: TokenIndex,
2598 return_type: Node.Index,2637 return_type: Node.OptionalIndex,
2599 params: []const Node.Index,2638 params: []const Node.Index,
2600 align_expr: Node.Index,2639 align_expr: Node.OptionalIndex,
2601 addrspace_expr: Node.Index,2640 addrspace_expr: Node.OptionalIndex,
2602 section_expr: Node.Index,2641 section_expr: Node.OptionalIndex,
2603 callconv_expr: Node.Index,2642 callconv_expr: Node.OptionalIndex,
2604 };2643 };
26052644
2606 pub const Param = struct {2645 pub const Param = struct {
...@@ -2608,7 +2647,7 @@ pub const full = struct {...@@ -2608,7 +2647,7 @@ pub const full = struct {
2608 name_token: ?TokenIndex,2647 name_token: ?TokenIndex,
2609 comptime_noalias: ?TokenIndex,2648 comptime_noalias: ?TokenIndex,
2610 anytype_ellipsis3: ?TokenIndex,2649 anytype_ellipsis3: ?TokenIndex,
2611 type_expr: Node.Index,2650 type_expr: ?Node.Index,
2612 };2651 };
26132652
2614 pub fn firstToken(fn_proto: FnProto) TokenIndex {2653 pub fn firstToken(fn_proto: FnProto) TokenIndex {
...@@ -2628,7 +2667,7 @@ pub const full = struct {...@@ -2628,7 +2667,7 @@ pub const full = struct {
2628 tok_flag: bool,2667 tok_flag: bool,
26292668
2630 pub fn next(it: *Iterator) ?Param {2669 pub fn next(it: *Iterator) ?Param {
2631 const token_tags = it.tree.tokens.items(.tag);2670 const tree = it.tree;
2632 while (true) {2671 while (true) {
2633 var first_doc_comment: ?TokenIndex = null;2672 var first_doc_comment: ?TokenIndex = null;
2634 var comptime_noalias: ?TokenIndex = null;2673 var comptime_noalias: ?TokenIndex = null;
...@@ -2638,8 +2677,8 @@ pub const full = struct {...@@ -2638,8 +2677,8 @@ pub const full = struct {
2638 return null;2677 return null;
2639 }2678 }
2640 const param_type = it.fn_proto.ast.params[it.param_i];2679 const param_type = it.fn_proto.ast.params[it.param_i];
2641 var tok_i = it.tree.firstToken(param_type) - 1;2680 var tok_i = tree.firstToken(param_type) - 1;
2642 while (true) : (tok_i -= 1) switch (token_tags[tok_i]) {2681 while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) {
2643 .colon => continue,2682 .colon => continue,
2644 .identifier => name_token = tok_i,2683 .identifier => name_token = tok_i,
2645 .doc_comment => first_doc_comment = tok_i,2684 .doc_comment => first_doc_comment = tok_i,
...@@ -2647,9 +2686,9 @@ pub const full = struct {...@@ -2647,9 +2686,9 @@ pub const full = struct {
2647 else => break,2686 else => break,
2648 };2687 };
2649 it.param_i += 1;2688 it.param_i += 1;
2650 it.tok_i = it.tree.lastToken(param_type) + 1;2689 it.tok_i = tree.lastToken(param_type) + 1;
2651 // Look for anytype and ... params afterwards.2690 // Look for anytype and ... params afterwards.
2652 if (token_tags[it.tok_i] == .comma) {2691 if (tree.tokenTag(it.tok_i) == .comma) {
2653 it.tok_i += 1;2692 it.tok_i += 1;
2654 }2693 }
2655 it.tok_flag = true;2694 it.tok_flag = true;
...@@ -2661,19 +2700,19 @@ pub const full = struct {...@@ -2661,19 +2700,19 @@ pub const full = struct {
2661 .type_expr = param_type,2700 .type_expr = param_type,
2662 };2701 };
2663 }2702 }
2664 if (token_tags[it.tok_i] == .comma) {2703 if (tree.tokenTag(it.tok_i) == .comma) {
2665 it.tok_i += 1;2704 it.tok_i += 1;
2666 }2705 }
2667 if (token_tags[it.tok_i] == .r_paren) {2706 if (tree.tokenTag(it.tok_i) == .r_paren) {
2668 return null;2707 return null;
2669 }2708 }
2670 if (token_tags[it.tok_i] == .doc_comment) {2709 if (tree.tokenTag(it.tok_i) == .doc_comment) {
2671 first_doc_comment = it.tok_i;2710 first_doc_comment = it.tok_i;
2672 while (token_tags[it.tok_i] == .doc_comment) {2711 while (tree.tokenTag(it.tok_i) == .doc_comment) {
2673 it.tok_i += 1;2712 it.tok_i += 1;
2674 }2713 }
2675 }2714 }
2676 switch (token_tags[it.tok_i]) {2715 switch (tree.tokenTag(it.tok_i)) {
2677 .ellipsis3 => {2716 .ellipsis3 => {
2678 it.tok_flag = false; // Next iteration should return null.2717 it.tok_flag = false; // Next iteration should return null.
2679 return Param{2718 return Param{
...@@ -2681,7 +2720,7 @@ pub const full = struct {...@@ -2681,7 +2720,7 @@ pub const full = struct {
2681 .comptime_noalias = null,2720 .comptime_noalias = null,
2682 .name_token = null,2721 .name_token = null,
2683 .anytype_ellipsis3 = it.tok_i,2722 .anytype_ellipsis3 = it.tok_i,
2684 .type_expr = 0,2723 .type_expr = null,
2685 };2724 };
2686 },2725 },
2687 .keyword_noalias, .keyword_comptime => {2726 .keyword_noalias, .keyword_comptime => {
...@@ -2690,20 +2729,20 @@ pub const full = struct {...@@ -2690,20 +2729,20 @@ pub const full = struct {
2690 },2729 },
2691 else => {},2730 else => {},
2692 }2731 }
2693 if (token_tags[it.tok_i] == .identifier and2732 if (tree.tokenTag(it.tok_i) == .identifier and
2694 token_tags[it.tok_i + 1] == .colon)2733 tree.tokenTag(it.tok_i + 1) == .colon)
2695 {2734 {
2696 name_token = it.tok_i;2735 name_token = it.tok_i;
2697 it.tok_i += 2;2736 it.tok_i += 2;
2698 }2737 }
2699 if (token_tags[it.tok_i] == .keyword_anytype) {2738 if (tree.tokenTag(it.tok_i) == .keyword_anytype) {
2700 it.tok_i += 1;2739 it.tok_i += 1;
2701 return Param{2740 return Param{
2702 .first_doc_comment = first_doc_comment,2741 .first_doc_comment = first_doc_comment,
2703 .comptime_noalias = comptime_noalias,2742 .comptime_noalias = comptime_noalias,
2704 .name_token = name_token,2743 .name_token = name_token,
2705 .anytype_ellipsis3 = it.tok_i - 1,2744 .anytype_ellipsis3 = it.tok_i - 1,
2706 .type_expr = 0,2745 .type_expr = null,
2707 };2746 };
2708 }2747 }
2709 it.tok_flag = false;2748 it.tok_flag = false;
...@@ -2728,7 +2767,7 @@ pub const full = struct {...@@ -2728,7 +2767,7 @@ pub const full = struct {
2728 pub const Components = struct {2767 pub const Components = struct {
2729 lbrace: TokenIndex,2768 lbrace: TokenIndex,
2730 fields: []const Node.Index,2769 fields: []const Node.Index,
2731 type_expr: Node.Index,2770 type_expr: Node.OptionalIndex,
2732 };2771 };
2733 };2772 };
27342773
...@@ -2738,7 +2777,7 @@ pub const full = struct {...@@ -2738,7 +2777,7 @@ pub const full = struct {
2738 pub const Components = struct {2777 pub const Components = struct {
2739 lbrace: TokenIndex,2778 lbrace: TokenIndex,
2740 elements: []const Node.Index,2779 elements: []const Node.Index,
2741 type_expr: Node.Index,2780 type_expr: Node.OptionalIndex,
2742 };2781 };
2743 };2782 };
27442783
...@@ -2748,7 +2787,7 @@ pub const full = struct {...@@ -2748,7 +2787,7 @@ pub const full = struct {
2748 pub const Components = struct {2787 pub const Components = struct {
2749 lbracket: TokenIndex,2788 lbracket: TokenIndex,
2750 elem_count: Node.Index,2789 elem_count: Node.Index,
2751 sentinel: Node.Index,2790 sentinel: Node.OptionalIndex,
2752 elem_type: Node.Index,2791 elem_type: Node.Index,
2753 };2792 };
2754 };2793 };
...@@ -2762,11 +2801,11 @@ pub const full = struct {...@@ -2762,11 +2801,11 @@ pub const full = struct {
27622801
2763 pub const Components = struct {2802 pub const Components = struct {
2764 main_token: TokenIndex,2803 main_token: TokenIndex,
2765 align_node: Node.Index,2804 align_node: Node.OptionalIndex,
2766 addrspace_node: Node.Index,2805 addrspace_node: Node.OptionalIndex,
2767 sentinel: Node.Index,2806 sentinel: Node.OptionalIndex,
2768 bit_range_start: Node.Index,2807 bit_range_start: Node.OptionalIndex,
2769 bit_range_end: Node.Index,2808 bit_range_end: Node.OptionalIndex,
2770 child_type: Node.Index,2809 child_type: Node.Index,
2771 };2810 };
2772 };2811 };
...@@ -2778,8 +2817,8 @@ pub const full = struct {...@@ -2778,8 +2817,8 @@ pub const full = struct {
2778 sliced: Node.Index,2817 sliced: Node.Index,
2779 lbracket: TokenIndex,2818 lbracket: TokenIndex,
2780 start: Node.Index,2819 start: Node.Index,
2781 end: Node.Index,2820 end: Node.OptionalIndex,
2782 sentinel: Node.Index,2821 sentinel: Node.OptionalIndex,
2783 };2822 };
2784 };2823 };
27852824
...@@ -2792,7 +2831,7 @@ pub const full = struct {...@@ -2792,7 +2831,7 @@ pub const full = struct {
2792 /// Populated when main_token is Keyword_union.2831 /// Populated when main_token is Keyword_union.
2793 enum_token: ?TokenIndex,2832 enum_token: ?TokenIndex,
2794 members: []const Node.Index,2833 members: []const Node.Index,
2795 arg: Node.Index,2834 arg: Node.OptionalIndex,
2796 };2835 };
2797 };2836 };
27982837
...@@ -2935,16 +2974,82 @@ pub const Error = struct {...@@ -2935,16 +2974,82 @@ pub const Error = struct {
2935 };2974 };
2936};2975};
29372976
2977/// Index into `extra_data`.
2978pub const ExtraIndex = enum(u32) {
2979 _,
2980};
2981
2938pub const Node = struct {2982pub const Node = struct {
2939 tag: Tag,2983 tag: Tag,
2940 main_token: TokenIndex,2984 main_token: TokenIndex,
2941 data: Data,2985 data: Data,
29422986
2943 pub const Index = u32;2987 /// Index into `nodes`.
2988 pub const Index = enum(u32) {
2989 root = 0,
2990 _,
2991
2992 pub fn toOptional(i: Index) OptionalIndex {
2993 const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
2994 assert(result != .none);
2995 return result;
2996 }
2997
2998 pub fn toOffset(base: Index, destination: Index) Offset {
2999 const base_i64: i64 = @intFromEnum(base);
3000 const destination_i64: i64 = @intFromEnum(destination);
3001 return @enumFromInt(destination_i64 - base_i64);
3002 }
3003 };
3004
3005 /// Index into `nodes`, or null.
3006 pub const OptionalIndex = enum(u32) {
3007 root = 0,
3008 none = std.math.maxInt(u32),
3009 _,
3010
3011 pub fn unwrap(oi: OptionalIndex) ?Index {
3012 return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
3013 }
3014
3015 pub fn fromOptional(oi: ?Index) OptionalIndex {
3016 return if (oi) |i| i.toOptional() else .none;
3017 }
3018 };
3019
3020 /// A relative node index.
3021 pub const Offset = enum(i32) {
3022 zero = 0,
3023 _,
3024
3025 pub fn toOptional(o: Offset) OptionalOffset {
3026 const result: OptionalOffset = @enumFromInt(@intFromEnum(o));
3027 assert(result != .none);
3028 return result;
3029 }
3030
3031 pub fn toAbsolute(offset: Offset, base: Index) Index {
3032 return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset));
3033 }
3034 };
3035
3036 /// A relative node index, or null.
3037 pub const OptionalOffset = enum(i32) {
3038 none = std.math.maxInt(i32),
3039 _,
3040
3041 pub fn unwrap(oo: OptionalOffset) ?Offset {
3042 return if (oo == .none) null else @enumFromInt(@intFromEnum(oo));
3043 }
3044 };
29443045
2945 comptime {3046 comptime {
2946 // Goal is to keep this under one byte for efficiency.3047 // Goal is to keep this under one byte for efficiency.
2947 assert(@sizeOf(Tag) == 1);3048 assert(@sizeOf(Tag) == 1);
3049
3050 if (!std.debug.runtime_safety) {
3051 assert(@sizeOf(Data) == 8);
3052 }
2948 }3053 }
29493054
2950 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of3055 /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of
...@@ -3435,9 +3540,26 @@ pub const Node = struct {...@@ -3435,9 +3540,26 @@ pub const Node = struct {
3435 }3540 }
3436 };3541 };
34373542
3438 pub const Data = struct {3543 pub const Data = union {
3439 lhs: Index,3544 node: Index,
3440 rhs: Index,3545 opt_node: OptionalIndex,
3546 token: TokenIndex,
3547 node_and_node: struct { Index, Index },
3548 opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex },
3549 node_and_opt_node: struct { Index, OptionalIndex },
3550 opt_node_and_node: struct { OptionalIndex, Index },
3551 node_and_extra: struct { Index, ExtraIndex },
3552 extra_and_node: struct { ExtraIndex, Index },
3553 extra_and_opt_node: struct { ExtraIndex, OptionalIndex },
3554 node_and_token: struct { Index, TokenIndex },
3555 token_and_node: struct { TokenIndex, Index },
3556 token_and_token: struct { TokenIndex, TokenIndex },
3557 opt_node_and_token: struct { OptionalIndex, TokenIndex },
3558 opt_token_and_node: struct { OptionalTokenIndex, Index },
3559 opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex },
3560 opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex },
3561 @"for": struct { ExtraIndex, For },
3562 extra_range: SubRange,
3441 };3563 };
34423564
3443 pub const LocalVarDecl = struct {3565 pub const LocalVarDecl = struct {
...@@ -3451,24 +3573,24 @@ pub const Node = struct {...@@ -3451,24 +3573,24 @@ pub const Node = struct {
3451 };3573 };
34523574
3453 pub const PtrType = struct {3575 pub const PtrType = struct {
3454 sentinel: Index,3576 sentinel: OptionalIndex,
3455 align_node: Index,3577 align_node: OptionalIndex,
3456 addrspace_node: Index,3578 addrspace_node: OptionalIndex,
3457 };3579 };
34583580
3459 pub const PtrTypeBitRange = struct {3581 pub const PtrTypeBitRange = struct {
3460 sentinel: Index,3582 sentinel: OptionalIndex,
3461 align_node: Index,3583 align_node: Index,
3462 addrspace_node: Index,3584 addrspace_node: OptionalIndex,
3463 bit_range_start: Index,3585 bit_range_start: Index,
3464 bit_range_end: Index,3586 bit_range_end: Index,
3465 };3587 };
34663588
3467 pub const SubRange = struct {3589 pub const SubRange = struct {
3468 /// Index into sub_list.3590 /// Index into extra_data.
3469 start: Index,3591 start: ExtraIndex,
3470 /// Index into sub_list.3592 /// Index into extra_data.
3471 end: Index,3593 end: ExtraIndex,
3472 };3594 };
34733595
3474 pub const If = struct {3596 pub const If = struct {
...@@ -3483,13 +3605,13 @@ pub const Node = struct {...@@ -3483,13 +3605,13 @@ pub const Node = struct {
34833605
3484 pub const GlobalVarDecl = struct {3606 pub const GlobalVarDecl = struct {
3485 /// Populated if there is an explicit type ascription.3607 /// Populated if there is an explicit type ascription.
3486 type_node: Index,3608 type_node: OptionalIndex,
3487 /// Populated if align(A) is present.3609 /// Populated if align(A) is present.
3488 align_node: Index,3610 align_node: OptionalIndex,
3489 /// Populated if addrspace(A) is present.3611 /// Populated if addrspace(A) is present.
3490 addrspace_node: Index,3612 addrspace_node: OptionalIndex,
3491 /// Populated if linksection(A) is present.3613 /// Populated if linksection(A) is present.
3492 section_node: Index,3614 section_node: OptionalIndex,
3493 };3615 };
34943616
3495 pub const Slice = struct {3617 pub const Slice = struct {
...@@ -3499,13 +3621,13 @@ pub const Node = struct {...@@ -3499,13 +3621,13 @@ pub const Node = struct {
34993621
3500 pub const SliceSentinel = struct {3622 pub const SliceSentinel = struct {
3501 start: Index,3623 start: Index,
3502 /// May be 0 if the slice is "open"3624 /// May be .none if the slice is "open"
3503 end: Index,3625 end: OptionalIndex,
3504 sentinel: Index,3626 sentinel: Index,
3505 };3627 };
35063628
3507 pub const While = struct {3629 pub const While = struct {
3508 cont_expr: Index,3630 cont_expr: OptionalIndex,
3509 then_expr: Index,3631 then_expr: Index,
3510 else_expr: Index,3632 else_expr: Index,
3511 };3633 };
...@@ -3522,44 +3644,44 @@ pub const Node = struct {...@@ -3522,44 +3644,44 @@ pub const Node = struct {
35223644
3523 pub const FnProtoOne = struct {3645 pub const FnProtoOne = struct {
3524 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.3646 /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.
3525 param: Index,3647 param: OptionalIndex,
3526 /// Populated if align(A) is present.3648 /// Populated if align(A) is present.
3527 align_expr: Index,3649 align_expr: OptionalIndex,
3528 /// Populated if addrspace(A) is present.3650 /// Populated if addrspace(A) is present.
3529 addrspace_expr: Index,3651 addrspace_expr: OptionalIndex,
3530 /// Populated if linksection(A) is present.3652 /// Populated if linksection(A) is present.
3531 section_expr: Index,3653 section_expr: OptionalIndex,
3532 /// Populated if callconv(A) is present.3654 /// Populated if callconv(A) is present.
3533 callconv_expr: Index,3655 callconv_expr: OptionalIndex,
3534 };3656 };
35353657
3536 pub const FnProto = struct {3658 pub const FnProto = struct {
3537 params_start: Index,3659 params_start: ExtraIndex,
3538 params_end: Index,3660 params_end: ExtraIndex,
3539 /// Populated if align(A) is present.3661 /// Populated if align(A) is present.
3540 align_expr: Index,3662 align_expr: OptionalIndex,
3541 /// Populated if addrspace(A) is present.3663 /// Populated if addrspace(A) is present.
3542 addrspace_expr: Index,3664 addrspace_expr: OptionalIndex,
3543 /// Populated if linksection(A) is present.3665 /// Populated if linksection(A) is present.
3544 section_expr: Index,3666 section_expr: OptionalIndex,
3545 /// Populated if callconv(A) is present.3667 /// Populated if callconv(A) is present.
3546 callconv_expr: Index,3668 callconv_expr: OptionalIndex,
3547 };3669 };
35483670
3549 pub const Asm = struct {3671 pub const Asm = struct {
3550 items_start: Index,3672 items_start: ExtraIndex,
3551 items_end: Index,3673 items_end: ExtraIndex,
3552 /// Needed to make lastToken() work.3674 /// Needed to make lastToken() work.
3553 rparen: TokenIndex,3675 rparen: TokenIndex,
3554 };3676 };
3555};3677};
35563678
3557pub fn nodeToSpan(tree: *const Ast, node: u32) Span {3679pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span {
3558 return tokensToSpan(3680 return tokensToSpan(
3559 tree,3681 tree,
3560 tree.firstToken(node),3682 tree.firstToken(node),
3561 tree.lastToken(node),3683 tree.lastToken(node),
3562 tree.nodes.items(.main_token)[node],3684 tree.nodeMainToken(node),
3563 );3685 );
3564}3686}
35653687
...@@ -3568,7 +3690,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {...@@ -3568,7 +3690,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
3568}3690}
35693691
3570pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {3692pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
3571 const token_starts = tree.tokens.items(.start);
3572 var start_tok = start;3693 var start_tok = start;
3573 var end_tok = end;3694 var end_tok = end;
35743695
...@@ -3582,9 +3703,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex...@@ -3582,9 +3703,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex
3582 start_tok = main;3703 start_tok = main;
3583 end_tok = main;3704 end_tok = main;
3584 }3705 }
3585 const start_off = token_starts[start_tok];3706 const start_off = tree.tokenStart(start_tok);
3586 const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len));3707 const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len));
3587 return Span{ .start = start_off, .end = end_off, .main = token_starts[main] };3708 return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) };
3588}3709}
35893710
3590const std = @import("../std.zig");3711const std = @import("../std.zig");
lib/std/zig/AstGen.zig+612-743
...@@ -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
...@@ -866,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -866,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
866 const if_full = tree.fullIf(node).?;872 const if_full = tree.fullIf(node).?;
867 no_switch_on_err: {873 no_switch_on_err: {
868 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;
869 const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err;875 const else_node = if_full.ast.else_expr.unwrap() orelse break :no_switch_on_err;
876 const full_switch = tree.fullSwitch(else_node) orelse break :no_switch_on_err;
870 if (full_switch.label_token != null) break :no_switch_on_err;877 if (full_switch.label_token != null) break :no_switch_on_err;
871 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;878 if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err;
872 if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err;879 if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err;
873 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");880 return switchExprErrUnion(gz, scope, ri.br(), node, .@"if");
874 }881 }
875 return ifExpr(gz, scope, ri.br(), node, if_full);882 return ifExpr(gz, scope, ri.br(), node, if_full);
...@@ -887,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -887,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
887 .slice_sentinel,894 .slice_sentinel,
888 => {895 => {
889 const full = tree.fullSlice(node).?;896 const full = tree.fullSlice(node).?;
890 if (full.ast.end != 0 and897 if (full.ast.end != .none and
891 node_tags[full.ast.sliced] == .slice_open and898 tree.nodeTag(full.ast.sliced) == .slice_open and
892 nodeIsTriviallyZero(tree, full.ast.start))899 nodeIsTriviallyZero(tree, full.ast.start))
893 {900 {
894 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;901 const lhs_extra = tree.sliceOpen(full.ast.sliced).ast;
...@@ -896,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -896,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
896 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);903 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced);
897 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);
898 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);905 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
899 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().?);
900 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;
901 try emitDbgStmt(gz, cursor);908 try emitDbgStmt(gz, cursor);
902 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{909 const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{
903 .lhs = lhs,910 .lhs = lhs,
...@@ -912,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -912,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
912919
913 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);920 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
914 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);
915 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;
916 const sentinel = if (full.ast.sentinel != 0) s: {923 const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| s: {
917 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);924 const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node);
918 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, full.ast.sentinel);925 break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, sentinel);
919 } else .none;926 } else .none;
920 try emitDbgStmt(gz, cursor);927 try emitDbgStmt(gz, cursor);
921 if (sentinel != .none) {928 if (sentinel != .none) {
...@@ -943,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -943,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
943 },950 },
944951
945 .deref => {952 .deref => {
946 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);953 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node);
947 _ = try gz.addUnNode(.validate_deref, lhs, node);954 _ = try gz.addUnNode(.validate_deref, lhs, node);
948 switch (ri.rl) {955 switch (ri.rl) {
949 .ref, .ref_coerced_ty => return lhs,956 .ref, .ref_coerced_ty => return lhs,
...@@ -958,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -958,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
958 _ = 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));
959 break :rl .{ .ref_coerced_ty = res_ty_inst };966 break :rl .{ .ref_coerced_ty = res_ty_inst };
960 } else .ref;967 } else .ref;
961 const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs);968 const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node);
962 return rvalue(gz, ri, result, node);969 return rvalue(gz, ri, result, node);
963 },970 },
964 .optional_type => {971 .optional_type => {
965 const operand = try typeExpr(gz, scope, node_datas[node].lhs);972 const operand = try typeExpr(gz, scope, tree.nodeData(node).node);
966 const result = try gz.addUnNode(.optional_type, operand, node);973 const result = try gz.addUnNode(.optional_type, operand, node);
967 return rvalue(gz, ri, result, node);974 return rvalue(gz, ri, result, node);
968 },975 },
969 .unwrap_optional => switch (ri.rl) {976 .unwrap_optional => switch (ri.rl) {
970 .ref, .ref_coerced_ty => {977 .ref, .ref_coerced_ty => {
971 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);978 const lhs = try expr(gz, scope, .{ .rl = .ref }, tree.nodeData(node).node_and_token[0]);
972979
973 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);980 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
974 try emitDbgStmt(gz, cursor);981 try emitDbgStmt(gz, cursor);
...@@ -976,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -976,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
976 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);983 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
977 },984 },
978 else => {985 else => {
979 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);986 const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]);
980987
981 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);988 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
982 try emitDbgStmt(gz, cursor);989 try emitDbgStmt(gz, cursor);
...@@ -994,7 +1001,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -994,7 +1001,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
994 return blockExpr(gz, scope, ri, node, statements, .normal);1001 return blockExpr(gz, scope, ri, node, statements, .normal);
995 },1002 },
996 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {1003 .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| {
997 const str_index = try astgen.identAsString(main_tokens[node]);1004 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
998 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{1005 const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{
999 .lhs = res_ty,1006 .lhs = res_ty,
1000 .field_name_start = str_index,1007 .field_name_start = str_index,
...@@ -1004,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1004,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1004 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us1011 .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us
1005 .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),
1006 }1013 }
1007 } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal),1014 } else return simpleStrTok(gz, ri, tree.nodeMainToken(node), node, .enum_literal),
1008 .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value),1015 .error_value => return simpleStrTok(gz, ri, tree.nodeData(node).opt_token_and_opt_token[1].unwrap().?, node, .error_value),
1009 // TODO restore this when implementing https://github.com/ziglang/zig/issues/60251016 // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025
1010 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),1017 // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node),
1011 .anyframe_literal => {1018 .anyframe_literal => {
...@@ -1013,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1013,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1013 return rvalue(gz, ri, result, node);1020 return rvalue(gz, ri, result, node);
1014 },1021 },
1015 .anyframe_type => {1022 .anyframe_type => {
1016 const return_type = try typeExpr(gz, scope, node_datas[node].rhs);1023 const return_type = try typeExpr(gz, scope, tree.nodeData(node).token_and_node[1]);
1017 const result = try gz.addUnNode(.anyframe_type, return_type, node);1024 const result = try gz.addUnNode(.anyframe_type, return_type, node);
1018 return rvalue(gz, ri, result, node);1025 return rvalue(gz, ri, result, node);
1019 },1026 },
1020 .@"catch" => {1027 .@"catch" => {
1021 const catch_token = main_tokens[node];1028 const catch_token = tree.nodeMainToken(node);
1022 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)
1023 catch_token + 21030 catch_token + 2
1024 else1031 else
1025 null;1032 null;
1026 no_switch_on_err: {1033 no_switch_on_err: {
1027 const capture_token = payload_token orelse break :no_switch_on_err;1034 const capture_token = payload_token orelse break :no_switch_on_err;
1028 const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err;1035 const full_switch = tree.fullSwitch(tree.nodeData(node).node_and_node[1]) orelse break :no_switch_on_err;
1029 if (full_switch.label_token != null) break :no_switch_on_err;1036 if (full_switch.label_token != null) break :no_switch_on_err;
1030 if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err;1037 if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err;
1031 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err;1038 if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err;
1032 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");1039 return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch");
1033 }1040 }
1034 switch (ri.rl) {1041 switch (ri.rl) {
...@@ -1037,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1037,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1037 scope,1044 scope,
1038 ri,1045 ri,
1039 node,1046 node,
1040 node_datas[node].lhs,
1041 .is_non_err_ptr,1047 .is_non_err_ptr,
1042 .err_union_payload_unsafe_ptr,1048 .err_union_payload_unsafe_ptr,
1043 .err_union_code_ptr,1049 .err_union_code_ptr,
1044 node_datas[node].rhs,
1045 payload_token,1050 payload_token,
1046 ),1051 ),
1047 else => return orelseCatchExpr(1052 else => return orelseCatchExpr(
...@@ -1049,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1049,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1049 scope,1054 scope,
1050 ri,1055 ri,
1051 node,1056 node,
1052 node_datas[node].lhs,
1053 .is_non_err,1057 .is_non_err,
1054 .err_union_payload_unsafe,1058 .err_union_payload_unsafe,
1055 .err_union_code,1059 .err_union_code,
1056 node_datas[node].rhs,
1057 payload_token,1060 payload_token,
1058 ),1061 ),
1059 }1062 }
...@@ -1064,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1064,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1064 scope,1067 scope,
1065 ri,1068 ri,
1066 node,1069 node,
1067 node_datas[node].lhs,
1068 .is_non_null_ptr,1070 .is_non_null_ptr,
1069 .optional_payload_unsafe_ptr,1071 .optional_payload_unsafe_ptr,
1070 undefined,1072 undefined,
1071 node_datas[node].rhs,
1072 null,1073 null,
1073 ),1074 ),
1074 else => return orelseCatchExpr(1075 else => return orelseCatchExpr(
...@@ -1076,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1076,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1076 scope,1077 scope,
1077 ri,1078 ri,
1078 node,1079 node,
1079 node_datas[node].lhs,
1080 .is_non_null,1080 .is_non_null,
1081 .optional_payload_unsafe,1081 .optional_payload_unsafe,
1082 undefined,1082 undefined,
1083 node_datas[node].rhs,
1084 null,1083 null,
1085 ),1084 ),
1086 },1085 },
...@@ -1110,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1110,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
11101109
1111 .@"break" => return breakExpr(gz, scope, node),1110 .@"break" => return breakExpr(gz, scope, node),
1112 .@"continue" => return continueExpr(gz, scope, node),1111 .@"continue" => return continueExpr(gz, scope, node),
1113 .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs),1112 .grouped_expression => return expr(gz, scope, ri, tree.nodeData(node).node_and_token[0]),
1114 .array_type => return arrayType(gz, scope, ri, node),1113 .array_type => return arrayType(gz, scope, ri, node),
1115 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),1114 .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node),
1116 .char_literal => return charLiteral(gz, ri, node),1115 .char_literal => return charLiteral(gz, ri, node),
...@@ -1124,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -1124,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
1124 .@"await" => return awaitExpr(gz, scope, ri, node),1123 .@"await" => return awaitExpr(gz, scope, ri, node),
1125 .@"resume" => return resumeExpr(gz, scope, ri, node),1124 .@"resume" => return resumeExpr(gz, scope, ri, node),
11261125
1127 .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs),1126 .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node),
11281127
1129 .array_init_one,1128 .array_init_one,
1130 .array_init_one_comma,1129 .array_init_one_comma,
...@@ -1171,16 +1170,14 @@ fn nosuspendExpr(...@@ -1171,16 +1170,14 @@ fn nosuspendExpr(
1171) InnerError!Zir.Inst.Ref {1170) InnerError!Zir.Inst.Ref {
1172 const astgen = gz.astgen;1171 const astgen = gz.astgen;
1173 const tree = astgen.tree;1172 const tree = astgen.tree;
1174 const node_datas = tree.nodes.items(.data);1173 const body_node = tree.nodeData(node).node;
1175 const body_node = node_datas[node].lhs;1174 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
1176 assert(body_node != 0);
1177 if (gz.nosuspend_node != 0) {
1178 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{1175 try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{
1179 try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}),1176 try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}),
1180 });1177 });
1181 }1178 }
1182 gz.nosuspend_node = node;1179 gz.nosuspend_node = node.toOptional();
1183 defer gz.nosuspend_node = 0;1180 defer gz.nosuspend_node = .none;
1184 return expr(gz, scope, ri, body_node);1181 return expr(gz, scope, ri, body_node);
1185}1182}
11861183
...@@ -1192,26 +1189,24 @@ fn suspendExpr(...@@ -1192,26 +1189,24 @@ fn suspendExpr(
1192 const astgen = gz.astgen;1189 const astgen = gz.astgen;
1193 const gpa = astgen.gpa;1190 const gpa = astgen.gpa;
1194 const tree = astgen.tree;1191 const tree = astgen.tree;
1195 const node_datas = tree.nodes.items(.data);1192 const body_node = tree.nodeData(node).node;
1196 const body_node = node_datas[node].lhs;
11971193
1198 if (gz.nosuspend_node != 0) {1194 if (gz.nosuspend_node.unwrap()) |nosuspend_node| {
1199 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{1195 return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{
1200 try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}),1196 try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}),
1201 });1197 });
1202 }1198 }
1203 if (gz.suspend_node != 0) {1199 if (gz.suspend_node.unwrap()) |suspend_node| {
1204 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{1200 return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{
1205 try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}),1201 try astgen.errNoteNode(suspend_node, "other suspend block here", .{}),
1206 });1202 });
1207 }1203 }
1208 assert(body_node != 0);
12091204
1210 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);1205 const suspend_inst = try gz.makeBlockInst(.suspend_block, node);
1211 try gz.instructions.append(gpa, suspend_inst);1206 try gz.instructions.append(gpa, suspend_inst);
12121207
1213 var suspend_scope = gz.makeSubBlock(scope);1208 var suspend_scope = gz.makeSubBlock(scope);
1214 suspend_scope.suspend_node = node;1209 suspend_scope.suspend_node = node.toOptional();
1215 defer suspend_scope.unstack();1210 defer suspend_scope.unstack();
12161211
1217 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);
...@@ -1231,16 +1226,15 @@ fn awaitExpr(...@@ -1231,16 +1226,15 @@ fn awaitExpr(
1231) InnerError!Zir.Inst.Ref {1226) InnerError!Zir.Inst.Ref {
1232 const astgen = gz.astgen;1227 const astgen = gz.astgen;
1233 const tree = astgen.tree;1228 const tree = astgen.tree;
1234 const node_datas = tree.nodes.items(.data);1229 const rhs_node = tree.nodeData(node).node;
1235 const rhs_node = node_datas[node].lhs;
12361230
1237 if (gz.suspend_node != 0) {1231 if (gz.suspend_node.unwrap()) |suspend_node| {
1238 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{1232 return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
1239 try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),1233 try astgen.errNoteNode(suspend_node, "suspend block here", .{}),
1240 });1234 });
1241 }1235 }
1242 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);1236 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1243 const result = if (gz.nosuspend_node != 0)1237 const result = if (gz.nosuspend_node != .none)
1244 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{1238 try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{
1245 .node = gz.nodeIndexToRelative(node),1239 .node = gz.nodeIndexToRelative(node),
1246 .operand = operand,1240 .operand = operand,
...@@ -1259,8 +1253,7 @@ fn resumeExpr(...@@ -1259,8 +1253,7 @@ fn resumeExpr(
1259) InnerError!Zir.Inst.Ref {1253) InnerError!Zir.Inst.Ref {
1260 const astgen = gz.astgen;1254 const astgen = gz.astgen;
1261 const tree = astgen.tree;1255 const tree = astgen.tree;
1262 const node_datas = tree.nodes.items(.data);1256 const rhs_node = tree.nodeData(node).node;
1263 const rhs_node = node_datas[node].lhs;
1264 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);1257 const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node);
1265 const result = try gz.addUnNode(.@"resume", operand, node);1258 const result = try gz.addUnNode(.@"resume", operand, node);
1266 return rvalue(gz, ri, result, node);1259 return rvalue(gz, ri, result, node);
...@@ -1275,33 +1268,33 @@ fn fnProtoExpr(...@@ -1275,33 +1268,33 @@ fn fnProtoExpr(
1275) InnerError!Zir.Inst.Ref {1268) InnerError!Zir.Inst.Ref {
1276 const astgen = gz.astgen;1269 const astgen = gz.astgen;
1277 const tree = astgen.tree;1270 const tree = astgen.tree;
1278 const token_tags = tree.tokens.items(.tag);
12791271
1280 if (fn_proto.name_token) |some| {1272 if (fn_proto.name_token) |some| {
1281 return astgen.failTok(some, "function type cannot have a name", .{});1273 return astgen.failTok(some, "function type cannot have a name", .{});
1282 }1274 }
12831275
1284 if (fn_proto.ast.align_expr != 0) {1276 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1285 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", .{});
1286 }1278 }
12871279
1288 if (fn_proto.ast.addrspace_expr != 0) {1280 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1289 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", .{});
1290 }1282 }
12911283
1292 if (fn_proto.ast.section_expr != 0) {1284 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1293 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", .{});
1294 }1286 }
12951287
1296 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1288 const return_type = fn_proto.ast.return_type.unwrap().?;
1297 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;
1298 if (is_inferred_error) {1291 if (is_inferred_error) {
1299 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", .{});
1300 }1293 }
13011294
1302 const is_extern = blk: {1295 const is_extern = blk: {
1303 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;
1304 break :blk token_tags[maybe_extern_token] == .keyword_extern;1297 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
1305 };1298 };
1306 assert(!is_extern);1299 assert(!is_extern);
13071300
...@@ -1318,7 +1311,6 @@ fn fnProtoExprInner(...@@ -1318,7 +1311,6 @@ fn fnProtoExprInner(
1318) InnerError!Zir.Inst.Ref {1311) InnerError!Zir.Inst.Ref {
1319 const astgen = gz.astgen;1312 const astgen = gz.astgen;
1320 const tree = astgen.tree;1313 const tree = astgen.tree;
1321 const token_tags = tree.tokens.items(.tag);
13221314
1323 var block_scope = gz.makeSubBlock(scope);1315 var block_scope = gz.makeSubBlock(scope);
1324 defer block_scope.unstack();1316 defer block_scope.unstack();
...@@ -1330,7 +1322,7 @@ fn fnProtoExprInner(...@@ -1330,7 +1322,7 @@ fn fnProtoExprInner(
1330 var param_type_i: usize = 0;1322 var param_type_i: usize = 0;
1331 var it = fn_proto.iterate(tree);1323 var it = fn_proto.iterate(tree);
1332 while (it.next()) |param| : (param_type_i += 1) {1324 while (it.next()) |param| : (param_type_i += 1) {
1333 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {1325 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
1334 .keyword_noalias => is_comptime: {1326 .keyword_noalias => is_comptime: {
1335 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
1336 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", .{}));
...@@ -1341,7 +1333,7 @@ fn fnProtoExprInner(...@@ -1341,7 +1333,7 @@ fn fnProtoExprInner(
1341 } else false;1333 } else false;
13421334
1343 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {1335 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
1344 switch (token_tags[token]) {1336 switch (tree.tokenTag(token)) {
1345 .keyword_anytype => break :blk true,1337 .keyword_anytype => break :blk true,
1346 .ellipsis3 => break :is_var_args true,1338 .ellipsis3 => break :is_var_args true,
1347 else => unreachable,1339 else => unreachable,
...@@ -1364,16 +1356,14 @@ fn fnProtoExprInner(...@@ -1364,16 +1356,14 @@ fn fnProtoExprInner(
1364 .param_anytype;1356 .param_anytype;
1365 _ = try block_scope.addStrTok(tag, param_name, name_token);1357 _ = try block_scope.addStrTok(tag, param_name, name_token);
1366 } else {1358 } else {
1367 const param_type_node = param.type_expr;1359 const param_type_node = param.type_expr.?;
1368 assert(param_type_node != 0);
1369 var param_gz = block_scope.makeSubBlock(scope);1360 var param_gz = block_scope.makeSubBlock(scope);
1370 defer param_gz.unstack();1361 defer param_gz.unstack();
1371 param_gz.is_comptime = true;1362 param_gz.is_comptime = true;
1372 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);
1373 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);
1374 _ = 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);
1375 const main_tokens = tree.nodes.items(.main_token);1366 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
1376 const name_token = param.name_token orelse main_tokens[param_type_node];
1377 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;
1378 // 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
1379 // arguments (we haven't set up scopes here).1369 // arguments (we haven't set up scopes here).
...@@ -1384,12 +1374,12 @@ fn fnProtoExprInner(...@@ -1384,12 +1374,12 @@ fn fnProtoExprInner(
1384 break :is_var_args false;1374 break :is_var_args false;
1385 };1375 };
13861376
1387 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)1377 const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr|
1388 try comptimeExpr(1378 try comptimeExpr(
1389 &block_scope,1379 &block_scope,
1390 scope,1380 scope,
1391 .{ .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) } },
1392 fn_proto.ast.callconv_expr,1382 callconv_expr,
1393 .@"callconv",1383 .@"callconv",
1394 )1384 )
1395 else if (implicit_ccc)1385 else if (implicit_ccc)
...@@ -1397,7 +1387,8 @@ fn fnProtoExprInner(...@@ -1397,7 +1387,8 @@ fn fnProtoExprInner(
1397 else1387 else
1398 .none;1388 .none;
13991389
1400 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty);1390 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
1391 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty);
14011392
1402 const result = try block_scope.addFunc(.{1393 const result = try block_scope.addFunc(.{
1403 .src_node = fn_proto.ast.proto_node,1394 .src_node = fn_proto.ast.proto_node,
...@@ -1437,33 +1428,32 @@ fn arrayInitExpr(...@@ -1437,33 +1428,32 @@ fn arrayInitExpr(
1437) InnerError!Zir.Inst.Ref {1428) InnerError!Zir.Inst.Ref {
1438 const astgen = gz.astgen;1429 const astgen = gz.astgen;
1439 const tree = astgen.tree;1430 const tree = astgen.tree;
1440 const node_tags = tree.nodes.items(.tag);
1441 const main_tokens = tree.nodes.items(.main_token);
14421431
1443 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.
14441433
1445 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: {
1446 if (array_init.ast.type_expr == 0) break :inst .{ .none, .none };1435 const type_expr = array_init.ast.type_expr.unwrap() orelse break :inst .{ .none, .none };
14471436
1448 infer: {1437 infer: {
1449 const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer;1438 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse break :infer;
1450 // This intentionally does not support `@"_"` syntax.1439 // This intentionally does not support `@"_"` syntax.
1451 if (node_tags[array_type.ast.elem_count] == .identifier and1440 if (tree.nodeTag(array_type.ast.elem_count) == .identifier and
1452 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)), "_"))
1453 {1442 {
1454 const len_inst = try gz.addInt(array_init.ast.elements.len);1443 const len_inst = try gz.addInt(array_init.ast.elements.len);
1455 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);
1456 if (array_type.ast.sentinel == 0) {1445 if (array_type.ast.sentinel == .none) {
1457 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{
1458 .lhs = len_inst,1447 .lhs = len_inst,
1459 .rhs = elem_type,1448 .rhs = elem_type,
1460 });1449 });
1461 break :inst .{ array_type_inst, elem_type };1450 break :inst .{ array_type_inst, elem_type };
1462 } else {1451 } else {
1463 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);1452 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1453 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
1464 const array_type_inst = try gz.addPlNode(1454 const array_type_inst = try gz.addPlNode(
1465 .array_type_sentinel,1455 .array_type_sentinel,
1466 array_init.ast.type_expr,1456 type_expr,
1467 Zir.Inst.ArrayTypeSentinel{1457 Zir.Inst.ArrayTypeSentinel{
1468 .len = len_inst,1458 .len = len_inst,
1469 .elem_type = elem_type,1459 .elem_type = elem_type,
...@@ -1474,7 +1464,7 @@ fn arrayInitExpr(...@@ -1474,7 +1464,7 @@ fn arrayInitExpr(
1474 }1464 }
1475 }1465 }
1476 }1466 }
1477 const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);1467 const array_type_inst = try typeExpr(gz, scope, type_expr);
1478 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{1468 _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{
1479 .ty = array_type_inst,1469 .ty = array_type_inst,
1480 .init_count = @intCast(array_init.ast.elements.len),1470 .init_count = @intCast(array_init.ast.elements.len),
...@@ -1682,7 +1672,7 @@ fn structInitExpr(...@@ -1682,7 +1672,7 @@ fn structInitExpr(
1682 const astgen = gz.astgen;1672 const astgen = gz.astgen;
1683 const tree = astgen.tree;1673 const tree = astgen.tree;
16841674
1685 if (struct_init.ast.type_expr == 0) {1675 if (struct_init.ast.type_expr == .none) {
1686 if (struct_init.ast.fields.len == 0) {1676 if (struct_init.ast.fields.len == 0) {
1687 // Anonymous init with no fields.1677 // Anonymous init with no fields.
1688 switch (ri.rl) {1678 switch (ri.rl) {
...@@ -1706,32 +1696,32 @@ fn structInitExpr(...@@ -1706,32 +1696,32 @@ fn structInitExpr(
1706 }1696 }
1707 }1697 }
1708 } else array: {1698 } else array: {
1709 const node_tags = tree.nodes.items(.tag);1699 const type_expr = struct_init.ast.type_expr.unwrap().?;
1710 const main_tokens = tree.nodes.items(.main_token);1700 const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse {
1711 const array_type: Ast.full.ArrayType = tree.fullArrayType(struct_init.ast.type_expr) orelse {
1712 if (struct_init.ast.fields.len == 0) {1701 if (struct_init.ast.fields.len == 0) {
1713 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1702 const ty_inst = try typeExpr(gz, scope, type_expr);
1714 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1703 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1715 return rvalue(gz, ri, result, node);1704 return rvalue(gz, ri, result, node);
1716 }1705 }
1717 break :array;1706 break :array;
1718 };1707 };
1719 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
1720 // This intentionally does not support `@"_"` syntax.1709 // This intentionally does not support `@"_"` syntax.
1721 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_");1710 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_");
1722 if (struct_init.ast.fields.len == 0) {1711 if (struct_init.ast.fields.len == 0) {
1723 if (is_inferred_array_len) {1712 if (is_inferred_array_len) {
1724 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);
1725 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {1714 const array_type_inst = if (array_type.ast.sentinel == .none) blk: {
1726 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{
1727 .lhs = .zero_usize,1716 .lhs = .zero_usize,
1728 .rhs = elem_type,1717 .rhs = elem_type,
1729 });1718 });
1730 } else blk: {1719 } else blk: {
1731 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);1720 const sentinel_node = array_type.ast.sentinel.unwrap().?;
1721 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel);
1732 break :blk try gz.addPlNode(1722 break :blk try gz.addPlNode(
1733 .array_type_sentinel,1723 .array_type_sentinel,
1734 struct_init.ast.type_expr,1724 type_expr,
1735 Zir.Inst.ArrayTypeSentinel{1725 Zir.Inst.ArrayTypeSentinel{
1736 .len = .zero_usize,1726 .len = .zero_usize,
1737 .elem_type = elem_type,1727 .elem_type = elem_type,
...@@ -1742,12 +1732,12 @@ fn structInitExpr(...@@ -1742,12 +1732,12 @@ fn structInitExpr(
1742 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);
1743 return rvalue(gz, ri, result, node);1733 return rvalue(gz, ri, result, node);
1744 }1734 }
1745 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1735 const ty_inst = try typeExpr(gz, scope, type_expr);
1746 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);1736 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1747 return rvalue(gz, ri, result, node);1737 return rvalue(gz, ri, result, node);
1748 } else {1738 } else {
1749 return astgen.failNode(1739 return astgen.failNode(
1750 struct_init.ast.type_expr,1740 type_expr,
1751 "initializing array with struct syntax",1741 "initializing array with struct syntax",
1752 .{},1742 .{},
1753 );1743 );
...@@ -1806,9 +1796,9 @@ fn structInitExpr(...@@ -1806,9 +1796,9 @@ fn structInitExpr(
1806 }1796 }
1807 }1797 }
18081798
1809 if (struct_init.ast.type_expr != 0) {1799 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
1810 // Typed inits do not use RLS for language simplicity.1800 // Typed inits do not use RLS for language simplicity.
1811 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);1801 const ty_inst = try typeExpr(gz, scope, type_expr);
1812 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);1802 _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node);
1813 switch (ri.rl) {1803 switch (ri.rl) {
1814 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),1804 .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true),
...@@ -1997,9 +1987,7 @@ fn comptimeExpr2(...@@ -1997,9 +1987,7 @@ fn comptimeExpr2(
1997 // 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
1998 // 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.
1999 const tree = gz.astgen.tree;1989 const tree = gz.astgen.tree;
2000 const main_tokens = tree.nodes.items(.main_token);1990 switch (tree.nodeTag(node)) {
2001 const node_tags = tree.nodes.items(.tag);
2002 switch (node_tags[node]) {
2003 .identifier => {1991 .identifier => {
2004 // 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
2005 // special handling for this case.1993 // special handling for this case.
...@@ -2052,8 +2040,7 @@ fn comptimeExpr2(...@@ -2052,8 +2040,7 @@ fn comptimeExpr2(
2052 // 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
2053 // 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`).
2054 .block_two, .block_two_semicolon, .block, .block_semicolon => {2042 .block_two, .block_two_semicolon, .block, .block_semicolon => {
2055 const token_tags = tree.tokens.items(.tag);2043 const lbrace = tree.nodeMainToken(node);
2056 const lbrace = main_tokens[node];
2057 // 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
2058 // refer to runtime memory. A runtime-to-comptime boundary has to remove2045 // refer to runtime memory. A runtime-to-comptime boundary has to remove
2059 // result location information, compute the result, and copy it to the true2046 // result location information, compute the result, and copy it to the true
...@@ -2065,11 +2052,10 @@ fn comptimeExpr2(...@@ -2065,11 +2052,10 @@ fn comptimeExpr2(
2065 else2052 else
2066 .none,2053 .none,
2067 };2054 };
2068 if (token_tags[lbrace - 1] == .colon and2055 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2069 token_tags[lbrace - 2] == .identifier)
2070 {
2071 var buf: [2]Ast.Node.Index = undefined;2056 var buf: [2]Ast.Node.Index = undefined;
2072 const stmts = tree.blockStatements(&buf, node).?;2057 const stmts = tree.blockStatements(&buf, node).?;
2058
2073 // Replace result location and copy back later - see above.2059 // Replace result location and copy back later - see above.
2074 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);2060 const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal);
2075 return rvalue(gz, ri, block_ref, node);2061 return rvalue(gz, ri, block_ref, node);
...@@ -2117,8 +2103,7 @@ fn comptimeExprAst(...@@ -2117,8 +2103,7 @@ fn comptimeExprAst(
2117 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});2103 try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{});
2118 }2104 }
2119 const tree = astgen.tree;2105 const tree = astgen.tree;
2120 const node_datas = tree.nodes.items(.data);2106 const body_node = tree.nodeData(node).node;
2121 const body_node = node_datas[node].lhs;
2122 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);2107 return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
2123}2108}
21242109
...@@ -2156,9 +2141,7 @@ fn restoreErrRetIndex(...@@ -2156,9 +2141,7 @@ fn restoreErrRetIndex(
2156fn 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 {
2157 const astgen = parent_gz.astgen;2142 const astgen = parent_gz.astgen;
2158 const tree = astgen.tree;2143 const tree = astgen.tree;
2159 const node_datas = tree.nodes.items(.data);2144 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
2160 const break_label = node_datas[node].lhs;
2161 const rhs = node_datas[node].rhs;
21622145
2163 // Look for the label in the scope.2146 // Look for the label in the scope.
2164 var scope = parent_scope;2147 var scope = parent_scope;
...@@ -2167,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2167,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2167 .gen_zir => {2150 .gen_zir => {
2168 const block_gz = scope.cast(GenZir).?;2151 const block_gz = scope.cast(GenZir).?;
21692152
2170 if (block_gz.cur_defer_node != 0) {2153 if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| {
2171 // We are breaking out of a `defer` block.2154 // We are breaking out of a `defer` block.
2172 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{2155 return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{
2173 try astgen.errNoteNode(2156 try astgen.errNoteNode(
2174 block_gz.cur_defer_node,2157 cur_defer_node,
2175 "defer expression here",2158 "defer expression here",
2176 .{},2159 .{},
2177 ),2160 ),
...@@ -2179,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2179,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2179 }2162 }
21802163
2181 const block_inst = blk: {2164 const block_inst = blk: {
2182 if (break_label != 0) {2165 if (opt_break_label.unwrap()) |break_label| {
2183 if (block_gz.label) |*label| {2166 if (block_gz.label) |*label| {
2184 if (try astgen.tokenIdentEql(label.token, break_label)) {2167 if (try astgen.tokenIdentEql(label.token, break_label)) {
2185 label.used = true;2168 label.used = true;
...@@ -2200,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2200,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2200 else2183 else
2201 .@"break";2184 .@"break";
22022185
2203 if (rhs == 0) {2186 const rhs = opt_rhs.unwrap() orelse {
2204 _ = 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);
22052188
2206 try genDefers(parent_gz, scope, parent_scope, .normal_only);2189 try genDefers(parent_gz, scope, parent_scope, .normal_only);
...@@ -2211,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2211,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
22112194
2212 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);2195 _ = try parent_gz.addBreak(break_tag, block_inst, .void_value);
2213 return Zir.Inst.Ref.unreachable_value;2196 return Zir.Inst.Ref.unreachable_value;
2214 }2197 };
22152198
2216 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);
22172200
...@@ -2243,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2243,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2243 .top => unreachable,2226 .top => unreachable,
2244 }2227 }
2245 }2228 }
2246 if (break_label != 0) {2229 if (opt_break_label.unwrap()) |break_label| {
2247 const label_name = try astgen.identifierTokenString(break_label);2230 const label_name = try astgen.identifierTokenString(break_label);
2248 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});2231 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
2249 } else {2232 } else {
...@@ -2254,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn...@@ -2254,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn
2254fn 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 {
2255 const astgen = parent_gz.astgen;2238 const astgen = parent_gz.astgen;
2256 const tree = astgen.tree;2239 const tree = astgen.tree;
2257 const node_datas = tree.nodes.items(.data);2240 const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
2258 const break_label = node_datas[node].lhs;
2259 const rhs = node_datas[node].rhs;
22602241
2261 if (break_label == 0 and rhs != 0) {2242 if (opt_break_label == .none and opt_rhs != .none) {
2262 return astgen.failNode(node, "cannot continue with operand without label", .{});2243 return astgen.failNode(node, "cannot continue with operand without label", .{});
2263 }2244 }
22642245
...@@ -2269,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2269,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2269 .gen_zir => {2250 .gen_zir => {
2270 const gen_zir = scope.cast(GenZir).?;2251 const gen_zir = scope.cast(GenZir).?;
22712252
2272 if (gen_zir.cur_defer_node != 0) {2253 if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| {
2273 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{2254 return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{
2274 try astgen.errNoteNode(2255 try astgen.errNoteNode(
2275 gen_zir.cur_defer_node,2256 cur_defer_node,
2276 "defer expression here",2257 "defer expression here",
2277 .{},2258 .{},
2278 ),2259 ),
...@@ -2282,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2282,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2282 scope = gen_zir.parent;2263 scope = gen_zir.parent;
2283 continue;2264 continue;
2284 };2265 };
2285 if (break_label != 0) blk: {2266 if (opt_break_label.unwrap()) |break_label| blk: {
2286 if (gen_zir.label) |*label| {2267 if (gen_zir.label) |*label| {
2287 if (try astgen.tokenIdentEql(label.token, break_label)) {2268 if (try astgen.tokenIdentEql(label.token, break_label)) {
2288 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)];
2289 if (rhs != 0) switch (maybe_switch_tag) {2270 if (opt_rhs != .none) switch (maybe_switch_tag) {
2290 .switch_block, .switch_block_ref => {},2271 .switch_block, .switch_block_ref => {},
2291 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),2272 else => return astgen.failNode(node, "cannot continue loop with operand", .{}),
2292 } else switch (maybe_switch_tag) {2273 } else switch (maybe_switch_tag) {
...@@ -2314,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2314,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2314 }2295 }
2315 }2296 }
23162297
2317 if (rhs != 0) {2298 if (opt_rhs.unwrap()) |rhs| {
2318 // We need to figure out the result info to use.2299 // We need to figure out the result info to use.
2319 // The type should match2300 // The type should match
2320 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);
...@@ -2353,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)...@@ -2353,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
2353 .top => unreachable,2334 .top => unreachable,
2354 }2335 }
2355 }2336 }
2356 if (break_label != 0) {2337 if (opt_break_label.unwrap()) |break_label| {
2357 const label_name = try astgen.identifierTokenString(break_label);2338 const label_name = try astgen.identifierTokenString(break_label);
2358 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});2339 return astgen.failTok(break_label, "label not found: '{s}'", .{label_name});
2359 } else {2340 } else {
...@@ -2373,15 +2354,14 @@ fn fullBodyExpr(...@@ -2373,15 +2354,14 @@ fn fullBodyExpr(
2373 block_kind: BlockKind,2354 block_kind: BlockKind,
2374) InnerError!Zir.Inst.Ref {2355) InnerError!Zir.Inst.Ref {
2375 const tree = gz.astgen.tree;2356 const tree = gz.astgen.tree;
2376 const main_tokens = tree.nodes.items(.main_token);2357
2377 const token_tags = tree.tokens.items(.tag);
2378 var stmt_buf: [2]Ast.Node.Index = undefined;2358 var stmt_buf: [2]Ast.Node.Index = undefined;
2379 const statements = tree.blockStatements(&stmt_buf, node).?;2359 const statements = tree.blockStatements(&stmt_buf, node) orelse
2360 return expr(gz, scope, ri, node);
23802361
2381 const lbrace = main_tokens[node];2362 const lbrace = tree.nodeMainToken(node);
2382 if (token_tags[lbrace - 1] == .colon and2363
2383 token_tags[lbrace - 2] == .identifier)2364 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2384 {
2385 // 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,
2386 // 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
2387 // 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.
...@@ -2406,13 +2386,9 @@ fn blockExpr(...@@ -2406,13 +2386,9 @@ fn blockExpr(
2406) InnerError!Zir.Inst.Ref {2386) InnerError!Zir.Inst.Ref {
2407 const astgen = gz.astgen;2387 const astgen = gz.astgen;
2408 const tree = astgen.tree;2388 const tree = astgen.tree;
2409 const main_tokens = tree.nodes.items(.main_token);
2410 const token_tags = tree.tokens.items(.tag);
24112389
2412 const lbrace = main_tokens[block_node];2390 const lbrace = tree.nodeMainToken(block_node);
2413 if (token_tags[lbrace - 1] == .colon and2391 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
2414 token_tags[lbrace - 2] == .identifier)
2415 {
2416 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);2392 return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind);
2417 }2393 }
24182394
...@@ -2489,12 +2465,10 @@ fn labeledBlockExpr(...@@ -2489,12 +2465,10 @@ fn labeledBlockExpr(
2489) InnerError!Zir.Inst.Ref {2465) InnerError!Zir.Inst.Ref {
2490 const astgen = gz.astgen;2466 const astgen = gz.astgen;
2491 const tree = astgen.tree;2467 const tree = astgen.tree;
2492 const main_tokens = tree.nodes.items(.main_token);
2493 const token_tags = tree.tokens.items(.tag);
24942468
2495 const lbrace = main_tokens[block_node];2469 const lbrace = tree.nodeMainToken(block_node);
2496 const label_token = lbrace - 2;2470 const label_token = lbrace - 2;
2497 assert(token_tags[label_token] == .identifier);2471 assert(tree.tokenTag(label_token) == .identifier);
24982472
2499 try astgen.checkLabelRedefinition(parent_scope, label_token);2473 try astgen.checkLabelRedefinition(parent_scope, label_token);
25002474
...@@ -2555,8 +2529,6 @@ fn labeledBlockExpr(...@@ -2555,8 +2529,6 @@ fn labeledBlockExpr(
2555fn 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 {
2556 const astgen = gz.astgen;2530 const astgen = gz.astgen;
2557 const tree = astgen.tree;2531 const tree = astgen.tree;
2558 const node_tags = tree.nodes.items(.tag);
2559 const node_data = tree.nodes.items(.data);
25602532
2561 if (statements.len == 0) return;2533 if (statements.len == 0) return;
25622534
...@@ -2564,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2564,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2564 defer block_arena.deinit();2536 defer block_arena.deinit();
2565 const block_arena_allocator = block_arena.allocator();2537 const block_arena_allocator = block_arena.allocator();
25662538
2567 var noreturn_src_node: Ast.Node.Index = 0;2539 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
2568 var scope = parent_scope;2540 var scope = parent_scope;
2569 for (statements, 0..) |statement, stmt_idx| {2541 for (statements, 0..) |statement, stmt_idx| {
2570 if (noreturn_src_node != 0) {2542 if (noreturn_src_node.unwrap()) |src_node| {
2571 try astgen.appendErrorNodeNotes(2543 try astgen.appendErrorNodeNotes(
2572 statement,2544 statement,
2573 "unreachable code",2545 "unreachable code",
2574 .{},2546 .{},
2575 &[_]u32{2547 &[_]u32{
2576 try astgen.errNoteNode(2548 try astgen.errNoteNode(
2577 noreturn_src_node,2549 src_node,
2578 "control flow is diverted here",2550 "control flow is diverted here",
2579 .{},2551 .{},
2580 ),2552 ),
...@@ -2587,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2587,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2587 };2559 };
2588 var inner_node = statement;2560 var inner_node = statement;
2589 while (true) {2561 while (true) {
2590 switch (node_tags[inner_node]) {2562 switch (tree.nodeTag(inner_node)) {
2591 // zig fmt: off2563 // zig fmt: off
2592 .global_var_decl,2564 .global_var_decl,
2593 .local_var_decl,2565 .local_var_decl,
...@@ -2617,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2617,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2617 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),2589 .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap),
26182590
2619 .grouped_expression => {2591 .grouped_expression => {
2620 inner_node = node_data[statement].lhs;2592 inner_node = tree.nodeData(statement).node_and_token[0];
2621 continue;2593 continue;
2622 },2594 },
26232595
...@@ -2649,15 +2621,15 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2649,15 +2621,15 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2649 }2621 }
2650 }2622 }
26512623
2652 if (noreturn_src_node == 0) {2624 if (noreturn_src_node == .none) {
2653 try genDefers(gz, parent_scope, scope, .normal_only);2625 try genDefers(gz, parent_scope, scope, .normal_only);
2654 }2626 }
2655 try checkUsed(gz, parent_scope, scope);2627 try checkUsed(gz, parent_scope, scope);
2656}2628}
26572629
2658/// 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
2659/// definitely `noreturn`. Otherwise returns 0.2631/// definitely `noreturn`. Otherwise returns .none.
2660fn 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 {
2661 try emitDbgNode(gz, statement);2633 try emitDbgNode(gz, statement);
2662 // 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
2663 // 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.
...@@ -2665,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2665,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2665 return addEnsureResult(gz, maybe_unused_result, statement);2637 return addEnsureResult(gz, maybe_unused_result, statement);
2666}2638}
26672639
2668fn 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 {
2669 var noreturn_src_node: Ast.Node.Index = 0;2641 var noreturn_src_node: Ast.Node.OptionalIndex = .none;
2670 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {2642 const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {
2671 // Note that this array becomes invalid after appending more items to it2643 // Note that this array becomes invalid after appending more items to it
2672 // in the above while loop.2644 // in the above while loop.
...@@ -2927,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2927,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2927 .check_comptime_control_flow,2899 .check_comptime_control_flow,
2928 .switch_continue,2900 .switch_continue,
2929 => {2901 => {
2930 noreturn_src_node = statement;2902 noreturn_src_node = statement.toOptional();
2931 break :b true;2903 break :b true;
2932 },2904 },
29332905
...@@ -2969,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2969,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2969 .none => unreachable,2941 .none => unreachable,
29702942
2971 .unreachable_value => b: {2943 .unreachable_value => b: {
2972 noreturn_src_node = statement;2944 noreturn_src_node = statement.toOptional();
2973 break :b true;2945 break :b true;
2974 },2946 },
29752947
...@@ -3098,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v...@@ -3098,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v
3098 .gen_zir => scope = scope.cast(GenZir).?.parent,3070 .gen_zir => scope = scope.cast(GenZir).?.parent,
3099 .local_val => {3071 .local_val => {
3100 const s = scope.cast(Scope.LocalVal).?;3072 const s = scope.cast(Scope.LocalVal).?;
3101 if (s.used == 0 and s.discarded == 0) {3073 if (s.used == .none and s.discarded == .none) {
3102 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)});
3103 } else if (s.used != 0 and s.discarded != 0) {3075 } else if (s.used != .none and s.discarded != .none) {
3104 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{
3105 try gz.astgen.errNoteTok(s.used, "used here", .{}),3077 try gz.astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
3106 });3078 });
3107 }3079 }
3108 scope = s.parent;3080 scope = s.parent;
3109 },3081 },
3110 .local_ptr => {3082 .local_ptr => {
3111 const s = scope.cast(Scope.LocalPtr).?;3083 const s = scope.cast(Scope.LocalPtr).?;
3112 if (s.used == 0 and s.discarded == 0) {3084 if (s.used == .none and s.discarded == .none) {
3113 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)});
3114 } else {3086 } else {
3115 if (s.used != 0 and s.discarded != 0) {3087 if (s.used != .none and s.discarded != .none) {
3116 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{
3117 try astgen.errNoteTok(s.used, "used here", .{}),3089 try astgen.errNoteTok(s.used.unwrap().?, "used here", .{}),
3118 });3090 });
3119 }3091 }
3120 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {3092 if (s.id_cat == .@"local variable" and !s.used_as_lvalue) {
...@@ -3141,19 +3113,15 @@ fn deferStmt(...@@ -3141,19 +3113,15 @@ fn deferStmt(
3141 scope_tag: Scope.Tag,3113 scope_tag: Scope.Tag,
3142) InnerError!*Scope {3114) InnerError!*Scope {
3143 var defer_gen = gz.makeSubBlock(scope);3115 var defer_gen = gz.makeSubBlock(scope);
3144 defer_gen.cur_defer_node = node;3116 defer_gen.cur_defer_node = node.toOptional();
3145 defer_gen.any_defer_node = node;3117 defer_gen.any_defer_node = node.toOptional();
3146 defer defer_gen.unstack();3118 defer defer_gen.unstack();
31473119
3148 const tree = gz.astgen.tree;3120 const tree = gz.astgen.tree;
3149 const node_datas = tree.nodes.items(.data);
3150 const expr_node = node_datas[node].rhs;
3151
3152 const payload_token = node_datas[node].lhs;
3153 var local_val_scope: Scope.LocalVal = undefined;3121 var local_val_scope: Scope.LocalVal = undefined;
3154 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;3122 var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none;
3155 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: {
3156 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;
3157 const ident_name = try gz.astgen.identAsString(payload_token);3125 const ident_name = try gz.astgen.identAsString(payload_token);
3158 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {3126 if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) {
3159 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", .{});
...@@ -3181,6 +3149,11 @@ fn deferStmt(...@@ -3181,6 +3149,11 @@ fn deferStmt(
3181 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);
3182 break :blk &local_val_scope.base;3150 break :blk &local_val_scope.base;
3183 };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 };
3184 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);3157 _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node);
3185 try checkUsed(gz, scope, sub_scope);3158 try checkUsed(gz, scope, sub_scope);
3186 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);3159 _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value);
...@@ -3215,8 +3188,6 @@ fn varDecl(...@@ -3215,8 +3188,6 @@ fn varDecl(
3215 try emitDbgNode(gz, node);3188 try emitDbgNode(gz, node);
3216 const astgen = gz.astgen;3189 const astgen = gz.astgen;
3217 const tree = astgen.tree;3190 const tree = astgen.tree;
3218 const token_tags = tree.tokens.items(.tag);
3219 const main_tokens = tree.nodes.items(.main_token);
32203191
3221 const name_token = var_decl.ast.mut_token + 1;3192 const name_token = var_decl.ast.mut_token + 1;
3222 const ident_name_raw = tree.tokenSlice(name_token);3193 const ident_name_raw = tree.tokenSlice(name_token);
...@@ -3230,27 +3201,27 @@ fn varDecl(...@@ -3230,27 +3201,27 @@ fn varDecl(
3230 ident_name,3201 ident_name,
3231 name_token,3202 name_token,
3232 ident_name_raw,3203 ident_name_raw,
3233 if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable",3204 if (tree.tokenTag(var_decl.ast.mut_token) == .keyword_const) .@"local constant" else .@"local variable",
3234 );3205 );
32353206
3236 if (var_decl.ast.init_node == 0) {3207 const init_node = var_decl.ast.init_node.unwrap() orelse {
3237 return astgen.failNode(node, "variables must be initialized", .{});3208 return astgen.failNode(node, "variables must be initialized", .{});
3238 }3209 };
32393210
3240 if (var_decl.ast.addrspace_node != 0) {3211 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3241 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});
3242 }3213 }
32433214
3244 if (var_decl.ast.section_node != 0) {3215 if (var_decl.ast.section_node.unwrap()) |section_node| {
3245 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});
3246 }3217 }
32473218
3248 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|
3249 try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node)3220 try expr(gz, scope, coerced_align_ri, align_node)
3250 else3221 else
3251 .none;3222 .none;
32523223
3253 switch (token_tags[var_decl.ast.mut_token]) {3224 switch (tree.tokenTag(var_decl.ast.mut_token)) {
3254 .keyword_const => {3225 .keyword_const => {
3255 if (var_decl.comptime_token) |comptime_token| {3226 if (var_decl.comptime_token) |comptime_token| {
3256 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'", .{});
...@@ -3262,25 +3233,24 @@ fn varDecl(...@@ -3262,25 +3233,24 @@ fn varDecl(
3262 // 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
3263 // 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
3264 // the variable, no memory location needed.3235 // the variable, no memory location needed.
3265 const type_node = var_decl.ast.type_node;
3266 if (align_inst == .none and3236 if (align_inst == .none and
3267 !astgen.nodes_need_rl.contains(node))3237 !astgen.nodes_need_rl.contains(node))
3268 {3238 {
3269 const result_info: ResultInfo = if (type_node != 0) .{3239 const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{
3270 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },3240 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },
3271 .ctx = .const_init,3241 .ctx = .const_init,
3272 } else .{ .rl = .none, .ctx = .const_init };3242 } else .{ .rl = .none, .ctx = .const_init };
3273 const prev_anon_name_strategy = gz.anon_name_strategy;3243 const prev_anon_name_strategy = gz.anon_name_strategy;
3274 gz.anon_name_strategy = .dbg_var;3244 gz.anon_name_strategy = .dbg_var;
3275 const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);3245 const init_inst = try reachableExprComptime(gz, scope, result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
3276 gz.anon_name_strategy = prev_anon_name_strategy;3246 gz.anon_name_strategy = prev_anon_name_strategy;
32773247
3278 _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node);3248 _ = try gz.addUnNode(.validate_const, init_inst, init_node);
3279 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);3249 try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
32803250
3281 // 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
3282 // 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.
3283 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))3253 if (nodeMayAppendToErrorTrace(tree, init_node))
3284 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });3254 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
32853255
3286 const sub_scope = try block_arena.create(Scope.LocalVal);3256 const sub_scope = try block_arena.create(Scope.LocalVal);
...@@ -3296,9 +3266,9 @@ fn varDecl(...@@ -3296,9 +3266,9 @@ fn varDecl(
3296 }3266 }
32973267
3298 const is_comptime = gz.is_comptime or3268 const is_comptime = gz.is_comptime or
3299 tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime";3269 tree.nodeTag(init_node) == .@"comptime";
33003270
3301 const init_rl: ResultInfo.Loc = if (type_node != 0) init_rl: {3271 const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: {
3302 const type_inst = try typeExpr(gz, scope, type_node);3272 const type_inst = try typeExpr(gz, scope, type_node);
3303 if (align_inst == .none) {3273 if (align_inst == .none) {
3304 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) } };
...@@ -3339,11 +3309,11 @@ fn varDecl(...@@ -3339,11 +3309,11 @@ fn varDecl(
3339 const prev_anon_name_strategy = gz.anon_name_strategy;3309 const prev_anon_name_strategy = gz.anon_name_strategy;
3340 gz.anon_name_strategy = .dbg_var;3310 gz.anon_name_strategy = .dbg_var;
3341 defer gz.anon_name_strategy = prev_anon_name_strategy;3311 defer gz.anon_name_strategy = prev_anon_name_strategy;
3342 const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);3312 const init_inst = try reachableExprComptime(gz, scope, init_result_info, init_node, node, if (force_comptime) .comptime_keyword else null);
33433313
3344 // 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
3345 // 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.
3346 if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node))3316 if (nodeMayAppendToErrorTrace(tree, init_node))
3347 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });3317 _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst });
33483318
3349 const const_ptr = if (resolve_inferred)3319 const const_ptr = if (resolve_inferred)
...@@ -3369,8 +3339,8 @@ fn varDecl(...@@ -3369,8 +3339,8 @@ fn varDecl(
3369 if (var_decl.comptime_token != null and gz.is_comptime)3339 if (var_decl.comptime_token != null and gz.is_comptime)
3370 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", .{});
3371 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;
3372 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: {
3373 const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);3343 const type_inst = try typeExpr(gz, scope, type_node);
3374 const alloc = alloc: {3344 const alloc = alloc: {
3375 if (align_inst == .none) {3345 if (align_inst == .none) {
3376 const tag: Zir.Inst.Tag = if (is_comptime)3346 const tag: Zir.Inst.Tag = if (is_comptime)
...@@ -3415,7 +3385,7 @@ fn varDecl(...@@ -3415,7 +3385,7 @@ fn varDecl(
3415 gz,3385 gz,
3416 scope,3386 scope,
3417 result_info,3387 result_info,
3418 var_decl.ast.init_node,3388 init_node,
3419 node,3389 node,
3420 if (var_decl.comptime_token != null) .comptime_keyword else null,3390 if (var_decl.comptime_token != null) .comptime_keyword else null,
3421 );3391 );
...@@ -3458,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi...@@ -3458,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
3458 try emitDbgNode(gz, infix_node);3428 try emitDbgNode(gz, infix_node);
3459 const astgen = gz.astgen;3429 const astgen = gz.astgen;
3460 const tree = astgen.tree;3430 const tree = astgen.tree;
3461 const node_datas = tree.nodes.items(.data);
3462 const main_tokens = tree.nodes.items(.main_token);
3463 const node_tags = tree.nodes.items(.tag);
34643431
3465 const lhs = node_datas[infix_node].lhs;3432 const lhs, const rhs = tree.nodeData(infix_node).node_and_node;
3466 const rhs = node_datas[infix_node].rhs;3433 if (tree.nodeTag(lhs) == .identifier) {
3467 if (node_tags[lhs] == .identifier) {
3468 // This intentionally does not support `@"_"` syntax.3434 // This intentionally does not support `@"_"` syntax.
3469 const ident_name = tree.tokenSlice(main_tokens[lhs]);3435 const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs));
3470 if (mem.eql(u8, ident_name, "_")) {3436 if (mem.eql(u8, ident_name, "_")) {
3471 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);3437 _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs);
3472 return;3438 return;
...@@ -3484,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro...@@ -3484,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
3484 try emitDbgNode(gz, node);3450 try emitDbgNode(gz, node);
3485 const astgen = gz.astgen;3451 const astgen = gz.astgen;
3486 const tree = astgen.tree;3452 const tree = astgen.tree;
3487 const main_tokens = tree.nodes.items(.main_token);
3488 const node_tags = tree.nodes.items(.tag);
34893453
3490 const full = tree.assignDestructure(node);3454 const full = tree.assignDestructure(node);
3491 if (full.comptime_token != null and gz.is_comptime) {3455 if (full.comptime_token != null and gz.is_comptime) {
...@@ -3503,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro...@@ -3503,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
35033467
3504 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);
3505 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3469 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3506 if (node_tags[variable_node] == .identifier) {3470 if (tree.nodeTag(variable_node) == .identifier) {
3507 // This intentionally does not support `@"_"` syntax.3471 // This intentionally does not support `@"_"` syntax.
3508 const ident_name = tree.tokenSlice(main_tokens[variable_node]);3472 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
3509 if (mem.eql(u8, ident_name, "_")) {3473 if (mem.eql(u8, ident_name, "_")) {
3510 variable_rl.* = .discard;3474 variable_rl.* = .discard;
3511 continue;3475 continue;
...@@ -3542,9 +3506,6 @@ fn assignDestructureMaybeDecls(...@@ -3542,9 +3506,6 @@ fn assignDestructureMaybeDecls(
3542 try emitDbgNode(gz, node);3506 try emitDbgNode(gz, node);
3543 const astgen = gz.astgen;3507 const astgen = gz.astgen;
3544 const tree = astgen.tree;3508 const tree = astgen.tree;
3545 const token_tags = tree.tokens.items(.tag);
3546 const main_tokens = tree.nodes.items(.main_token);
3547 const node_tags = tree.nodes.items(.tag);
35483509
3549 const full = tree.assignDestructure(node);3510 const full = tree.assignDestructure(node);
3550 if (full.comptime_token != null and gz.is_comptime) {3511 if (full.comptime_token != null and gz.is_comptime) {
...@@ -3552,7 +3513,7 @@ fn assignDestructureMaybeDecls(...@@ -3552,7 +3513,7 @@ fn assignDestructureMaybeDecls(
3552 }3513 }
35533514
3554 const is_comptime = full.comptime_token != null or gz.is_comptime;3515 const is_comptime = full.comptime_token != null or gz.is_comptime;
3555 const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime";3516 const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime";
35563517
3557 // 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.
3558 // 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
...@@ -3565,10 +3526,10 @@ fn assignDestructureMaybeDecls(...@@ -3565,10 +3526,10 @@ fn assignDestructureMaybeDecls(
3565 var any_non_const_variables = false;3526 var any_non_const_variables = false;
3566 var any_lvalue_expr = false;3527 var any_lvalue_expr = false;
3567 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3528 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3568 switch (node_tags[variable_node]) {3529 switch (tree.nodeTag(variable_node)) {
3569 .identifier => {3530 .identifier => {
3570 // This intentionally does not support `@"_"` syntax.3531 // This intentionally does not support `@"_"` syntax.
3571 const ident_name = tree.tokenSlice(main_tokens[variable_node]);3532 const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node));
3572 if (mem.eql(u8, ident_name, "_")) {3533 if (mem.eql(u8, ident_name, "_")) {
3573 any_non_const_variables = true;3534 any_non_const_variables = true;
3574 variable_rl.* = .discard;3535 variable_rl.* = .discard;
...@@ -3586,14 +3547,14 @@ fn assignDestructureMaybeDecls(...@@ -3586,14 +3547,14 @@ fn assignDestructureMaybeDecls(
35863547
3587 // 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.
35883549
3589 if (full_var_decl.ast.addrspace_node != 0) {3550 if (full_var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
3590 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});
3591 }3552 }
3592 if (full_var_decl.ast.section_node != 0) {3553 if (full_var_decl.ast.section_node.unwrap()) |section_node| {
3593 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});
3594 }3555 }
35953556
3596 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {3557 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
3597 .keyword_var => false,3558 .keyword_var => false,
3598 .keyword_const => true,3559 .keyword_const => true,
3599 else => unreachable,3560 else => unreachable,
...@@ -3603,14 +3564,14 @@ fn assignDestructureMaybeDecls(...@@ -3603,14 +3564,14 @@ fn assignDestructureMaybeDecls(
3603 // 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.
3604 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);
36053566
3606 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|
3607 try expr(gz, scope, coerced_align_ri, full_var_decl.ast.align_node)3568 try expr(gz, scope, coerced_align_ri, align_node)
3608 else3569 else
3609 .none;3570 .none;
36103571
3611 if (full_var_decl.ast.type_node != 0) {3572 if (full_var_decl.ast.type_node.unwrap()) |type_node| {
3612 // Typed alloc3573 // Typed alloc
3613 const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node);3574 const type_inst = try typeExpr(gz, scope, type_node);
3614 const ptr = if (align_inst == .none) ptr: {3575 const ptr = if (align_inst == .none) ptr: {
3615 const tag: Zir.Inst.Tag = if (is_const)3576 const tag: Zir.Inst.Tag = if (is_const)
3616 .alloc3577 .alloc
...@@ -3679,7 +3640,7 @@ fn assignDestructureMaybeDecls(...@@ -3679,7 +3640,7 @@ fn assignDestructureMaybeDecls(
3679 // evaluate the lvalues from within the possible block_comptime.3640 // evaluate the lvalues from within the possible block_comptime.
3680 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {3641 for (rl_components, full.ast.variables) |*variable_rl, variable_node| {
3681 if (variable_rl.* != .typed_ptr) continue;3642 if (variable_rl.* != .typed_ptr) continue;
3682 switch (node_tags[variable_node]) {3643 switch (tree.nodeTag(variable_node)) {
3683 .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,
3684 else => {},3645 else => {},
3685 }3646 }
...@@ -3708,7 +3669,7 @@ fn assignDestructureMaybeDecls(...@@ -3708,7 +3669,7 @@ fn assignDestructureMaybeDecls(
3708 // If there were any `const` decls, make the pointer constant.3669 // If there were any `const` decls, make the pointer constant.
3709 var cur_scope = scope;3670 var cur_scope = scope;
3710 for (rl_components, full.ast.variables) |variable_rl, variable_node| {3671 for (rl_components, full.ast.variables) |variable_rl, variable_node| {
3711 switch (node_tags[variable_node]) {3672 switch (tree.nodeTag(variable_node)) {
3712 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},3673 .local_var_decl, .simple_var_decl, .aligned_var_decl => {},
3713 else => continue, // We were mutating an existing lvalue - nothing to do3674 else => continue, // We were mutating an existing lvalue - nothing to do
3714 }3675 }
...@@ -3718,7 +3679,7 @@ fn assignDestructureMaybeDecls(...@@ -3718,7 +3679,7 @@ fn assignDestructureMaybeDecls(
3718 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },3679 .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false },
3719 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },3680 .inferred_ptr => |ptr_inst| .{ ptr_inst, true },
3720 };3681 };
3721 const is_const = switch (token_tags[full_var_decl.ast.mut_token]) {3682 const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) {
3722 .keyword_var => false,3683 .keyword_var => false,
3723 .keyword_const => true,3684 .keyword_const => true,
3724 else => unreachable,3685 else => unreachable,
...@@ -3769,9 +3730,9 @@ fn assignOp(...@@ -3769,9 +3730,9 @@ fn assignOp(
3769 try emitDbgNode(gz, infix_node);3730 try emitDbgNode(gz, infix_node);
3770 const astgen = gz.astgen;3731 const astgen = gz.astgen;
3771 const tree = astgen.tree;3732 const tree = astgen.tree;
3772 const node_datas = tree.nodes.items(.data);
37733733
3774 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3734 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3735 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
37753736
3776 const cursor = switch (op_inst_tag) {3737 const cursor = switch (op_inst_tag) {
3777 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),3738 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
...@@ -3797,7 +3758,7 @@ fn assignOp(...@@ -3797,7 +3758,7 @@ fn assignOp(
3797 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type3758 else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type
3798 };3759 };
3799 // 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.
3800 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, node_datas[infix_node].rhs);3761 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, rhs_node);
38013762
3802 switch (op_inst_tag) {3763 switch (op_inst_tag) {
3803 .add, .sub, .mul, .div, .mod_rem => {3764 .add, .sub, .mul, .div, .mod_rem => {
...@@ -3824,12 +3785,12 @@ fn assignShift(...@@ -3824,12 +3785,12 @@ fn assignShift(
3824 try emitDbgNode(gz, infix_node);3785 try emitDbgNode(gz, infix_node);
3825 const astgen = gz.astgen;3786 const astgen = gz.astgen;
3826 const tree = astgen.tree;3787 const tree = astgen.tree;
3827 const node_datas = tree.nodes.items(.data);
38283788
3829 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3789 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3790 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
3830 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3791 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3831 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);
3832 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs);3793 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, rhs_node);
38333794
3834 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{
3835 .lhs = lhs,3796 .lhs = lhs,
...@@ -3845,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE...@@ -3845,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE
3845 try emitDbgNode(gz, infix_node);3806 try emitDbgNode(gz, infix_node);
3846 const astgen = gz.astgen;3807 const astgen = gz.astgen;
3847 const tree = astgen.tree;3808 const tree = astgen.tree;
3848 const node_datas = tree.nodes.items(.data);
38493809
3850 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3810 const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node;
3811 const lhs_ptr = try lvalExpr(gz, scope, lhs_node);
3851 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3812 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3852 // 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.
3853 const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs);3814 const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node);
38543815
3855 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{
3856 .lhs = lhs,3817 .lhs = lhs,
...@@ -3885,7 +3846,7 @@ fn ptrType(...@@ -3885,7 +3846,7 @@ fn ptrType(
3885 var bit_end_ref: Zir.Inst.Ref = .none;3846 var bit_end_ref: Zir.Inst.Ref = .none;
3886 var trailing_count: u32 = 0;3847 var trailing_count: u32 = 0;
38873848
3888 if (ptr_info.ast.sentinel != 0) {3849 if (ptr_info.ast.sentinel.unwrap()) |sentinel| {
3889 // 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
3890 // 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.
3891 gz.astgen.source_offset = source_offset;3852 gz.astgen.source_offset = source_offset;
...@@ -3896,7 +3857,7 @@ fn ptrType(...@@ -3896,7 +3857,7 @@ fn ptrType(
3896 gz,3857 gz,
3897 scope,3858 scope,
3898 .{ .rl = .{ .ty = elem_type } },3859 .{ .rl = .{ .ty = elem_type } },
3899 ptr_info.ast.sentinel,3860 sentinel,
3900 switch (ptr_info.size) {3861 switch (ptr_info.size) {
3901 .slice => .slice_sentinel,3862 .slice => .slice_sentinel,
3902 else => .pointer_sentinel,3863 else => .pointer_sentinel,
...@@ -3904,27 +3865,27 @@ fn ptrType(...@@ -3904,27 +3865,27 @@ fn ptrType(
3904 );3865 );
3905 trailing_count += 1;3866 trailing_count += 1;
3906 }3867 }
3907 if (ptr_info.ast.addrspace_node != 0) {3868 if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| {
3908 gz.astgen.source_offset = source_offset;3869 gz.astgen.source_offset = source_offset;
3909 gz.astgen.source_line = source_line;3870 gz.astgen.source_line = source_line;
3910 gz.astgen.source_column = source_column;3871 gz.astgen.source_column = source_column;
39113872
3912 const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space);3873 const addrspace_ty = try gz.addBuiltinValue(addrspace_node, .address_space);
3913 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");
3914 trailing_count += 1;3875 trailing_count += 1;
3915 }3876 }
3916 if (ptr_info.ast.align_node != 0) {3877 if (ptr_info.ast.align_node.unwrap()) |align_node| {
3917 gz.astgen.source_offset = source_offset;3878 gz.astgen.source_offset = source_offset;
3918 gz.astgen.source_line = source_line;3879 gz.astgen.source_line = source_line;
3919 gz.astgen.source_column = source_column;3880 gz.astgen.source_column = source_column;
39203881
3921 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align");3882 align_ref = try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align");
3922 trailing_count += 1;3883 trailing_count += 1;
3923 }3884 }
3924 if (ptr_info.ast.bit_range_start != 0) {3885 if (ptr_info.ast.bit_range_start.unwrap()) |bit_range_start| {
3925 assert(ptr_info.ast.bit_range_end != 0);3886 const bit_range_end = ptr_info.ast.bit_range_end.unwrap().?;
3926 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);
3927 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);
3928 trailing_count += 2;3889 trailing_count += 2;
3929 }3890 }
39303891
...@@ -3977,18 +3938,15 @@ fn ptrType(...@@ -3977,18 +3938,15 @@ fn ptrType(
3977fn 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 {
3978 const astgen = gz.astgen;3939 const astgen = gz.astgen;
3979 const tree = astgen.tree;3940 const tree = astgen.tree;
3980 const node_datas = tree.nodes.items(.data);
3981 const node_tags = tree.nodes.items(.tag);
3982 const main_tokens = tree.nodes.items(.main_token);
39833941
3984 const len_node = node_datas[node].lhs;3942 const len_node, const elem_type_node = tree.nodeData(node).node_and_node;
3985 if (node_tags[len_node] == .identifier and3943 if (tree.nodeTag(len_node) == .identifier and
3986 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))3944 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
3987 {3945 {
3988 return astgen.failNode(len_node, "unable to infer array size", .{});3946 return astgen.failNode(len_node, "unable to infer array size", .{});
3989 }3947 }
3990 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);
3991 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);3949 const elem_type = try typeExpr(gz, scope, elem_type_node);
39923950
3993 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{3951 const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
3994 .lhs = len,3952 .lhs = len,
...@@ -4000,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !...@@ -4000,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
4000fn 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 {
4001 const astgen = gz.astgen;3959 const astgen = gz.astgen;
4002 const tree = astgen.tree;3960 const tree = astgen.tree;
4003 const node_datas = tree.nodes.items(.data);3961
4004 const node_tags = tree.nodes.items(.tag);3962 const len_node, const extra_index = tree.nodeData(node).node_and_extra;
4005 const main_tokens = tree.nodes.items(.main_token);3963 const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel);
4006 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);3964
40073965 if (tree.nodeTag(len_node) == .identifier and
4008 const len_node = node_datas[node].lhs;3966 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_"))
4009 if (node_tags[len_node] == .identifier and
4010 mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_"))
4011 {3967 {
4012 return astgen.failNode(len_node, "unable to infer array size", .{});3968 return astgen.failNode(len_node, "unable to infer array size", .{});
4013 }3969 }
...@@ -4107,11 +4063,10 @@ fn fnDecl(...@@ -4107,11 +4063,10 @@ fn fnDecl(
4107 scope: *Scope,4063 scope: *Scope,
4108 wip_members: *WipMembers,4064 wip_members: *WipMembers,
4109 decl_node: Ast.Node.Index,4065 decl_node: Ast.Node.Index,
4110 body_node: Ast.Node.Index,4066 body_node: Ast.Node.OptionalIndex,
4111 fn_proto: Ast.full.FnProto,4067 fn_proto: Ast.full.FnProto,
4112) InnerError!void {4068) InnerError!void {
4113 const tree = astgen.tree;4069 const tree = astgen.tree;
4114 const token_tags = tree.tokens.items(.tag);
41154070
4116 const old_hasher = astgen.src_hasher;4071 const old_hasher = astgen.src_hasher;
4117 defer astgen.src_hasher = old_hasher;4072 defer astgen.src_hasher = old_hasher;
...@@ -4140,15 +4095,15 @@ fn fnDecl(...@@ -4140,15 +4095,15 @@ fn fnDecl(
4140 const is_pub = fn_proto.visib_token != null;4095 const is_pub = fn_proto.visib_token != null;
4141 const is_export = blk: {4096 const is_export = blk: {
4142 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;
4143 break :blk token_tags[maybe_export_token] == .keyword_export;4098 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
4144 };4099 };
4145 const is_extern = blk: {4100 const is_extern = blk: {
4146 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;
4147 break :blk token_tags[maybe_extern_token] == .keyword_extern;4102 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
4148 };4103 };
4149 const has_inline_keyword = blk: {4104 const has_inline_keyword = blk: {
4150 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;
4151 break :blk token_tags[maybe_inline_token] == .keyword_inline;4106 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
4152 };4107 };
4153 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: {
4154 const lib_name_str = try astgen.strLitAsString(lib_name_token);4109 const lib_name_str = try astgen.strLitAsString(lib_name_token);
...@@ -4160,16 +4115,18 @@ fn fnDecl(...@@ -4160,16 +4115,18 @@ fn fnDecl(
4160 }4115 }
4161 break :blk lib_name_str.index;4116 break :blk lib_name_str.index;
4162 } else .empty;4117 } else .empty;
4163 if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) {4118 if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) {
4164 return astgen.failNode(4119 return astgen.failNode(
4165 fn_proto.ast.callconv_expr,4120 fn_proto.ast.callconv_expr.unwrap().?,
4166 "explicit callconv incompatible with inline keyword",4121 "explicit callconv incompatible with inline keyword",
4167 .{},4122 .{},
4168 );4123 );
4169 }4124 }
4170 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;4125
4171 const is_inferred_error = token_tags[maybe_bang] == .bang;4126 const return_type = fn_proto.ast.return_type.unwrap().?;
4172 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) {
4173 if (!is_extern) {4130 if (!is_extern) {
4174 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", .{});
4175 }4132 }
...@@ -4202,28 +4159,28 @@ fn fnDecl(...@@ -4202,28 +4159,28 @@ fn fnDecl(
4202 var align_gz = type_gz.makeSubBlock(scope);4159 var align_gz = type_gz.makeSubBlock(scope);
4203 defer align_gz.unstack();4160 defer align_gz.unstack();
42044161
4205 if (fn_proto.ast.align_expr != 0) {4162 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
4206 astgen.restoreSourceCursor(saved_cursor);4163 astgen.restoreSourceCursor(saved_cursor);
4207 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr);4164 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr);
4208 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4165 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4209 }4166 }
42104167
4211 var linksection_gz = align_gz.makeSubBlock(scope);4168 var linksection_gz = align_gz.makeSubBlock(scope);
4212 defer linksection_gz.unstack();4169 defer linksection_gz.unstack();
42134170
4214 if (fn_proto.ast.section_expr != 0) {4171 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
4215 astgen.restoreSourceCursor(saved_cursor);4172 astgen.restoreSourceCursor(saved_cursor);
4216 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr);4173 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr);
4217 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4174 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4218 }4175 }
42194176
4220 var addrspace_gz = linksection_gz.makeSubBlock(scope);4177 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4221 defer addrspace_gz.unstack();4178 defer addrspace_gz.unstack();
42224179
4223 if (fn_proto.ast.addrspace_expr != 0) {4180 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
4224 astgen.restoreSourceCursor(saved_cursor);4181 astgen.restoreSourceCursor(saved_cursor);
4225 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);
4226 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);
4227 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4184 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4228 }4185 }
42294186
...@@ -4233,7 +4190,7 @@ fn fnDecl(...@@ -4233,7 +4190,7 @@ fn fnDecl(
4233 if (!is_extern) {4190 if (!is_extern) {
4234 // We include a function *value*, not a type.4191 // We include a function *value*, not a type.
4235 astgen.restoreSourceCursor(saved_cursor);4192 astgen.restoreSourceCursor(saved_cursor);
4236 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto);4193 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto);
4237 }4194 }
42384195
4239 // *Now* we can incorporate the full source code into the hasher.4196 // *Now* we can incorporate the full source code into the hasher.
...@@ -4272,18 +4229,19 @@ fn fnDeclInner(...@@ -4272,18 +4229,19 @@ fn fnDeclInner(
4272 fn_proto: Ast.full.FnProto,4229 fn_proto: Ast.full.FnProto,
4273) InnerError!void {4230) InnerError!void {
4274 const tree = astgen.tree;4231 const tree = astgen.tree;
4275 const token_tags = tree.tokens.items(.tag);
42764232
4277 const is_noinline = blk: {4233 const is_noinline = blk: {
4278 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;
4279 break :blk token_tags[maybe_noinline_token] == .keyword_noinline;4235 break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline;
4280 };4236 };
4281 const has_inline_keyword = blk: {4237 const has_inline_keyword = blk: {
4282 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;
4283 break :blk token_tags[maybe_inline_token] == .keyword_inline;4239 break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline;
4284 };4240 };
4285 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;4241
4286 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;
42874245
4288 // 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.
4289 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);
...@@ -4297,7 +4255,7 @@ fn fnDeclInner(...@@ -4297,7 +4255,7 @@ fn fnDeclInner(
4297 var param_type_i: usize = 0;4255 var param_type_i: usize = 0;
4298 var it = fn_proto.iterate(tree);4256 var it = fn_proto.iterate(tree);
4299 while (it.next()) |param| : (param_type_i += 1) {4257 while (it.next()) |param| : (param_type_i += 1) {
4300 const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) {4258 const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) {
4301 .keyword_noalias => is_comptime: {4259 .keyword_noalias => is_comptime: {
4302 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
4303 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", .{}));
...@@ -4308,7 +4266,7 @@ fn fnDeclInner(...@@ -4308,7 +4266,7 @@ fn fnDeclInner(
4308 } else false;4266 } else false;
43094267
4310 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {4268 const is_anytype = if (param.anytype_ellipsis3) |token| blk: {
4311 switch (token_tags[token]) {4269 switch (tree.tokenTag(token)) {
4312 .keyword_anytype => break :blk true,4270 .keyword_anytype => break :blk true,
4313 .ellipsis3 => break :is_var_args true,4271 .ellipsis3 => break :is_var_args true,
4314 else => unreachable,4272 else => unreachable,
...@@ -4327,30 +4285,31 @@ fn fnDeclInner(...@@ -4327,30 +4285,31 @@ fn fnDeclInner(
4327 if (param.anytype_ellipsis3) |tok| {4285 if (param.anytype_ellipsis3) |tok| {
4328 return astgen.failTok(tok, "missing parameter name", .{});4286 return astgen.failTok(tok, "missing parameter name", .{});
4329 } else {4287 } else {
4288 const type_expr = param.type_expr.?;
4330 ambiguous: {4289 ambiguous: {
4331 if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous;4290 if (tree.nodeTag(type_expr) != .identifier) break :ambiguous;
4332 const main_token = tree.nodes.items(.main_token)[param.type_expr];4291 const main_token = tree.nodeMainToken(type_expr);
4333 const identifier_str = tree.tokenSlice(main_token);4292 const identifier_str = tree.tokenSlice(main_token);
4334 if (isPrimitive(identifier_str)) break :ambiguous;4293 if (isPrimitive(identifier_str)) break :ambiguous;
4335 return astgen.failNodeNotes(4294 return astgen.failNodeNotes(
4336 param.type_expr,4295 type_expr,
4337 "missing parameter name or type",4296 "missing parameter name or type",
4338 .{},4297 .{},
4339 &[_]u32{4298 &[_]u32{
4340 try astgen.errNoteNode(4299 try astgen.errNoteNode(
4341 param.type_expr,4300 type_expr,
4342 "if this is a name, annotate its type '{s}: T'",4301 "if this is a name, annotate its type '{s}: T'",
4343 .{identifier_str},4302 .{identifier_str},
4344 ),4303 ),
4345 try astgen.errNoteNode(4304 try astgen.errNoteNode(
4346 param.type_expr,4305 type_expr,
4347 "if this is a type, give it a name '<name>: {s}'",4306 "if this is a type, give it a name '<name>: {s}'",
4348 .{identifier_str},4307 .{identifier_str},
4349 ),4308 ),
4350 },4309 },
4351 );4310 );
4352 }4311 }
4353 return astgen.failNode(param.type_expr, "missing parameter name", .{});4312 return astgen.failNode(type_expr, "missing parameter name", .{});
4354 }4313 }
4355 };4314 };
43564315
...@@ -4362,8 +4321,7 @@ fn fnDeclInner(...@@ -4362,8 +4321,7 @@ fn fnDeclInner(
4362 .param_anytype;4321 .param_anytype;
4363 break :param try decl_gz.addStrTok(tag, param_name, name_token);4322 break :param try decl_gz.addStrTok(tag, param_name, name_token);
4364 } else param: {4323 } else param: {
4365 const param_type_node = param.type_expr;4324 const param_type_node = param.type_expr.?;
4366 assert(param_type_node != 0);
4367 any_param_used = false; // we will check this later4325 any_param_used = false; // we will check this later
4368 var param_gz = decl_gz.makeSubBlock(scope);4326 var param_gz = decl_gz.makeSubBlock(scope);
4369 defer param_gz.unstack();4327 defer param_gz.unstack();
...@@ -4372,8 +4330,7 @@ fn fnDeclInner(...@@ -4372,8 +4330,7 @@ fn fnDeclInner(
4372 _ = 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);
4373 const param_type_is_generic = any_param_used;4331 const param_type_is_generic = any_param_used;
43744332
4375 const main_tokens = tree.nodes.items(.main_token);4333 const name_token = param.name_token orelse tree.nodeMainToken(param_type_node);
4376 const name_token = param.name_token orelse main_tokens[param_type_node];
4377 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;
4378 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);
4379 assert(param_inst_expected == param_inst);4336 assert(param_inst_expected == param_inst);
...@@ -4409,7 +4366,7 @@ fn fnDeclInner(...@@ -4409,7 +4366,7 @@ fn fnDeclInner(
4409 // 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.
4410 // 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`.
4411 // See #22263 for a proposal to solve the inconsistency here.4368 // See #22263 for a proposal to solve the inconsistency here.
4412 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal);4369 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal);
4413 if (ret_gz.instructionsSlice().len == 0) {4370 if (ret_gz.instructionsSlice().len == 0) {
4414 // 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.
4415 break :inst inst;4372 break :inst inst;
...@@ -4426,12 +4383,12 @@ fn fnDeclInner(...@@ -4426,12 +4383,12 @@ fn fnDeclInner(
4426 var cc_gz = decl_gz.makeSubBlock(scope);4383 var cc_gz = decl_gz.makeSubBlock(scope);
4427 defer cc_gz.unstack();4384 defer cc_gz.unstack();
4428 const cc_ref: Zir.Inst.Ref = blk: {4385 const cc_ref: Zir.Inst.Ref = blk: {
4429 if (fn_proto.ast.callconv_expr != 0) {4386 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
4430 const inst = try expr(4387 const inst = try expr(
4431 &cc_gz,4388 &cc_gz,
4432 scope,4389 scope,
4433 .{ .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) } },
4434 fn_proto.ast.callconv_expr,4391 callconv_expr,
4435 );4392 );
4436 if (cc_gz.instructionsSlice().len == 0) {4393 if (cc_gz.instructionsSlice().len == 0) {
4437 // 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.
...@@ -4470,7 +4427,7 @@ fn fnDeclInner(...@@ -4470,7 +4427,7 @@ fn fnDeclInner(
4470 // Leave `astgen.src_hasher` unmodified; this will be used for hashing4427 // Leave `astgen.src_hasher` unmodified; this will be used for hashing
4471 // the *whole* function declaration, including its body.4428 // the *whole* function declaration, including its body.
4472 var proto_hasher = astgen.src_hasher;4429 var proto_hasher = astgen.src_hasher;
4473 const proto_node = tree.nodes.items(.data)[decl_node].lhs;4430 const proto_node = tree.nodeData(decl_node).node_and_node[0];
4474 proto_hasher.update(tree.getNodeSource(proto_node));4431 proto_hasher.update(tree.getNodeSource(proto_node));
4475 var proto_hash: std.zig.SrcHash = undefined;4432 var proto_hash: std.zig.SrcHash = undefined;
4476 proto_hasher.final(&proto_hash);4433 proto_hasher.final(&proto_hash);
...@@ -4540,7 +4497,6 @@ fn globalVarDecl(...@@ -4540,7 +4497,6 @@ fn globalVarDecl(
4540 var_decl: Ast.full.VarDecl,4497 var_decl: Ast.full.VarDecl,
4541) InnerError!void {4498) InnerError!void {
4542 const tree = astgen.tree;4499 const tree = astgen.tree;
4543 const token_tags = tree.tokens.items(.tag);
45444500
4545 const old_hasher = astgen.src_hasher;4501 const old_hasher = astgen.src_hasher;
4546 defer astgen.src_hasher = old_hasher;4502 defer astgen.src_hasher = old_hasher;
...@@ -4548,16 +4504,16 @@ fn globalVarDecl(...@@ -4548,16 +4504,16 @@ fn globalVarDecl(
4548 astgen.src_hasher.update(tree.getNodeSource(node));4504 astgen.src_hasher.update(tree.getNodeSource(node));
4549 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));4505 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
45504506
4551 const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;4507 const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var;
4552 const name_token = var_decl.ast.mut_token + 1;4508 const name_token = var_decl.ast.mut_token + 1;
4553 const is_pub = var_decl.visib_token != null;4509 const is_pub = var_decl.visib_token != null;
4554 const is_export = blk: {4510 const is_export = blk: {
4555 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;
4556 break :blk token_tags[maybe_export_token] == .keyword_export;4512 break :blk tree.tokenTag(maybe_export_token) == .keyword_export;
4557 };4513 };
4558 const is_extern = blk: {4514 const is_extern = blk: {
4559 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;
4560 break :blk token_tags[maybe_extern_token] == .keyword_extern;4516 break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern;
4561 };4517 };
4562 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {4518 const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
4563 if (!is_mutable) {4519 if (!is_mutable) {
...@@ -4583,10 +4539,10 @@ fn globalVarDecl(...@@ -4583,10 +4539,10 @@ fn globalVarDecl(
4583 const decl_inst = try gz.makeDeclaration(node);4539 const decl_inst = try gz.makeDeclaration(node);
4584 wip_members.nextDecl(decl_inst);4540 wip_members.nextDecl(decl_inst);
45854541
4586 if (var_decl.ast.init_node != 0) {4542 if (var_decl.ast.init_node.unwrap()) |init_node| {
4587 if (is_extern) {4543 if (is_extern) {
4588 return astgen.failNode(4544 return astgen.failNode(
4589 var_decl.ast.init_node,4545 init_node,
4590 "extern variables have no initializers",4546 "extern variables have no initializers",
4591 .{},4547 .{},
4592 );4548 );
...@@ -4597,7 +4553,7 @@ fn globalVarDecl(...@@ -4597,7 +4553,7 @@ fn globalVarDecl(
4597 }4553 }
4598 }4554 }
45994555
4600 if (is_extern and var_decl.ast.type_node == 0) {4556 if (is_extern and var_decl.ast.type_node == .none) {
4601 return astgen.failNode(node, "unable to infer variable type", .{});4557 return astgen.failNode(node, "unable to infer variable type", .{});
4602 }4558 }
46034559
...@@ -4614,45 +4570,45 @@ fn globalVarDecl(...@@ -4614,45 +4570,45 @@ fn globalVarDecl(
4614 };4570 };
4615 defer type_gz.unstack();4571 defer type_gz.unstack();
46164572
4617 if (var_decl.ast.type_node != 0) {4573 if (var_decl.ast.type_node.unwrap()) |type_node| {
4618 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);
4619 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);4575 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node);
4620 }4576 }
46214577
4622 var align_gz = type_gz.makeSubBlock(scope);4578 var align_gz = type_gz.makeSubBlock(scope);
4623 defer align_gz.unstack();4579 defer align_gz.unstack();
46244580
4625 if (var_decl.ast.align_node != 0) {4581 if (var_decl.ast.align_node.unwrap()) |align_node| {
4626 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);
4627 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);4583 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4628 }4584 }
46294585
4630 var linksection_gz = type_gz.makeSubBlock(scope);4586 var linksection_gz = type_gz.makeSubBlock(scope);
4631 defer linksection_gz.unstack();4587 defer linksection_gz.unstack();
46324588
4633 if (var_decl.ast.section_node != 0) {4589 if (var_decl.ast.section_node.unwrap()) |section_node| {
4634 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);
4635 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);4591 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4636 }4592 }
46374593
4638 var addrspace_gz = type_gz.makeSubBlock(scope);4594 var addrspace_gz = type_gz.makeSubBlock(scope);
4639 defer addrspace_gz.unstack();4595 defer addrspace_gz.unstack();
46404596
4641 if (var_decl.ast.addrspace_node != 0) {4597 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
4642 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);
4643 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);
4644 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);4600 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4645 }4601 }
46464602
4647 var init_gz = type_gz.makeSubBlock(scope);4603 var init_gz = type_gz.makeSubBlock(scope);
4648 defer init_gz.unstack();4604 defer init_gz.unstack();
46494605
4650 if (var_decl.ast.init_node != 0) {4606 if (var_decl.ast.init_node.unwrap()) |init_node| {
4651 init_gz.anon_name_strategy = .parent;4607 init_gz.anon_name_strategy = .parent;
4652 const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{4608 const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{
4653 .rl = .{ .coerced_ty = decl_inst.toRef() },4609 .rl = .{ .coerced_ty = decl_inst.toRef() },
4654 } else .{ .rl = .none };4610 } else .{ .rl = .none };
4655 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node);4611 const init_inst = try expr(&init_gz, &init_gz.base, init_ri, init_node);
4656 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);4612 _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node);
4657 }4613 }
46584614
...@@ -4686,8 +4642,7 @@ fn comptimeDecl(...@@ -4686,8 +4642,7 @@ fn comptimeDecl(
4686 node: Ast.Node.Index,4642 node: Ast.Node.Index,
4687) InnerError!void {4643) InnerError!void {
4688 const tree = astgen.tree;4644 const tree = astgen.tree;
4689 const node_datas = tree.nodes.items(.data);4645 const body_node = tree.nodeData(node).node;
4690 const body_node = node_datas[node].lhs;
46914646
4692 const old_hasher = astgen.src_hasher;4647 const old_hasher = astgen.src_hasher;
4693 defer astgen.src_hasher = old_hasher;4648 defer astgen.src_hasher = old_hasher;
...@@ -4750,7 +4705,6 @@ fn usingnamespaceDecl(...@@ -4750,7 +4705,6 @@ fn usingnamespaceDecl(
4750 node: Ast.Node.Index,4705 node: Ast.Node.Index,
4751) InnerError!void {4706) InnerError!void {
4752 const tree = astgen.tree;4707 const tree = astgen.tree;
4753 const node_datas = tree.nodes.items(.data);
47544708
4755 const old_hasher = astgen.src_hasher;4709 const old_hasher = astgen.src_hasher;
4756 defer astgen.src_hasher = old_hasher;4710 defer astgen.src_hasher = old_hasher;
...@@ -4758,13 +4712,9 @@ fn usingnamespaceDecl(...@@ -4758,13 +4712,9 @@ fn usingnamespaceDecl(
4758 astgen.src_hasher.update(tree.getNodeSource(node));4712 astgen.src_hasher.update(tree.getNodeSource(node));
4759 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));4713 astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column));
47604714
4761 const type_expr = node_datas[node].lhs;4715 const type_expr = tree.nodeData(node).node;
4762 const is_pub = blk: {4716 const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub});
4763 const main_tokens = tree.nodes.items(.main_token);4717
4764 const token_tags = tree.tokens.items(.tag);
4765 const main_token = main_tokens[node];
4766 break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub);
4767 };
4768 // 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
4769 // top-level declaration.4719 // top-level declaration.
4770 const decl_inst = try gz.makeDeclaration(node);4720 const decl_inst = try gz.makeDeclaration(node);
...@@ -4818,8 +4768,7 @@ fn testDecl(...@@ -4818,8 +4768,7 @@ fn testDecl(
4818 node: Ast.Node.Index,4768 node: Ast.Node.Index,
4819) InnerError!void {4769) InnerError!void {
4820 const tree = astgen.tree;4770 const tree = astgen.tree;
4821 const node_datas = tree.nodes.items(.data);4771 _, const body_node = tree.nodeData(node).opt_token_and_node;
4822 const body_node = node_datas[node].rhs;
48234772
4824 const old_hasher = astgen.src_hasher;4773 const old_hasher = astgen.src_hasher;
4825 defer astgen.src_hasher = old_hasher;4774 defer astgen.src_hasher = old_hasher;
...@@ -4851,12 +4800,10 @@ fn testDecl(...@@ -4851,12 +4800,10 @@ fn testDecl(
48514800
4852 const decl_column = astgen.source_column;4801 const decl_column = astgen.source_column;
48534802
4854 const main_tokens = tree.nodes.items(.main_token);4803 const test_token = tree.nodeMainToken(node);
4855 const token_tags = tree.tokens.items(.tag);
4856 const test_token = main_tokens[node];
48574804
4858 const test_name_token = test_token + 1;4805 const test_name_token = test_token + 1;
4859 const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) {4806 const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) {
4860 else => .empty,4807 else => .empty,
4861 .string_literal => name: {4808 .string_literal => name: {
4862 const name = try astgen.strLitAsString(test_name_token);4809 const name = try astgen.strLitAsString(test_name_token);
...@@ -4888,7 +4835,7 @@ fn testDecl(...@@ -4888,7 +4835,7 @@ fn testDecl(
4888 .local_val => {4835 .local_val => {
4889 const local_val = s.cast(Scope.LocalVal).?;4836 const local_val = s.cast(Scope.LocalVal).?;
4890 if (local_val.name == name_str_index) {4837 if (local_val.name == name_str_index) {
4891 local_val.used = test_name_token;4838 local_val.used = .fromToken(test_name_token);
4892 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{4839 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
4893 @tagName(local_val.id_cat),4840 @tagName(local_val.id_cat),
4894 }, &[_]u32{4841 }, &[_]u32{
...@@ -4902,7 +4849,7 @@ fn testDecl(...@@ -4902,7 +4849,7 @@ fn testDecl(
4902 .local_ptr => {4849 .local_ptr => {
4903 const local_ptr = s.cast(Scope.LocalPtr).?;4850 const local_ptr = s.cast(Scope.LocalPtr).?;
4904 if (local_ptr.name == name_str_index) {4851 if (local_ptr.name == name_str_index) {
4905 local_ptr.used = test_name_token;4852 local_ptr.used = .fromToken(test_name_token);
4906 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{4853 return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{
4907 @tagName(local_ptr.id_cat),4854 @tagName(local_ptr.id_cat),
4908 }, &[_]u32{4855 }, &[_]u32{
...@@ -5013,7 +4960,7 @@ fn testDecl(...@@ -5013,7 +4960,7 @@ fn testDecl(
5013 .src_line = decl_block.decl_line,4960 .src_line = decl_block.decl_line,
5014 .src_column = decl_column,4961 .src_column = decl_column,
50154962
5016 .kind = switch (token_tags[test_name_token]) {4963 .kind = switch (tree.tokenTag(test_name_token)) {
5017 .string_literal => .@"test",4964 .string_literal => .@"test",
5018 .identifier => .decltest,4965 .identifier => .decltest,
5019 else => .unnamed_test,4966 else => .unnamed_test,
...@@ -5037,7 +4984,7 @@ fn structDeclInner(...@@ -5037,7 +4984,7 @@ fn structDeclInner(
5037 node: Ast.Node.Index,4984 node: Ast.Node.Index,
5038 container_decl: Ast.full.ContainerDecl,4985 container_decl: Ast.full.ContainerDecl,
5039 layout: std.builtin.Type.ContainerLayout,4986 layout: std.builtin.Type.ContainerLayout,
5040 backing_int_node: Ast.Node.Index,4987 backing_int_node: Ast.Node.OptionalIndex,
5041) InnerError!Zir.Inst.Ref {4988) InnerError!Zir.Inst.Ref {
5042 const astgen = gz.astgen;4989 const astgen = gz.astgen;
5043 const gpa = astgen.gpa;4990 const gpa = astgen.gpa;
...@@ -5049,7 +4996,7 @@ fn structDeclInner(...@@ -5049,7 +4996,7 @@ fn structDeclInner(
5049 if (container_field.ast.tuple_like) break member_node;4996 if (container_field.ast.tuple_like) break member_node;
5050 } else break :is_tuple;4997 } else break :is_tuple;
50514998
5052 if (node == 0) {4999 if (node == .root) {
5053 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});5000 return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{});
5054 } else {5001 } else {
5055 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);5002 return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node);
...@@ -5058,7 +5005,7 @@ fn structDeclInner(...@@ -5058,7 +5005,7 @@ fn structDeclInner(
50585005
5059 const decl_inst = try gz.reserveInstructionIndex();5006 const decl_inst = try gz.reserveInstructionIndex();
50605007
5061 if (container_decl.ast.members.len == 0 and backing_int_node == 0) {5008 if (container_decl.ast.members.len == 0 and backing_int_node == .none) {
5062 try gz.setStruct(decl_inst, .{5009 try gz.setStruct(decl_inst, .{
5063 .src_node = node,5010 .src_node = node,
5064 .layout = layout,5011 .layout = layout,
...@@ -5105,11 +5052,11 @@ fn structDeclInner(...@@ -5105,11 +5052,11 @@ fn structDeclInner(
51055052
5106 var backing_int_body_len: usize = 0;5053 var backing_int_body_len: usize = 0;
5107 const backing_int_ref: Zir.Inst.Ref = blk: {5054 const backing_int_ref: Zir.Inst.Ref = blk: {
5108 if (backing_int_node != 0) {5055 if (backing_int_node.unwrap()) |arg| {
5109 if (layout != .@"packed") {5056 if (layout != .@"packed") {
5110 return astgen.failNode(backing_int_node, "non-packed struct does not support backing integer type", .{});5057 return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{});
5111 } else {5058 } else {
5112 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node);5059 const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg);
5113 if (!block_scope.isEmpty()) {5060 if (!block_scope.isEmpty()) {
5114 if (!block_scope.endsWithNoReturn()) {5061 if (!block_scope.endsWithNoReturn()) {
5115 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);5062 _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref);
...@@ -5154,8 +5101,8 @@ fn structDeclInner(...@@ -5154,8 +5101,8 @@ fn structDeclInner(
5154 defer astgen.src_hasher = old_hasher;5101 defer astgen.src_hasher = old_hasher;
5155 astgen.src_hasher = std.zig.SrcHasher.init(.{});5102 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5156 astgen.src_hasher.update(@tagName(layout));5103 astgen.src_hasher.update(@tagName(layout));
5157 if (backing_int_node != 0) {5104 if (backing_int_node.unwrap()) |arg| {
5158 astgen.src_hasher.update(tree.getNodeSource(backing_int_node));5105 astgen.src_hasher.update(tree.getNodeSource(arg));
5159 }5106 }
51605107
5161 var known_non_opv = false;5108 var known_non_opv = false;
...@@ -5172,18 +5119,18 @@ fn structDeclInner(...@@ -5172,18 +5119,18 @@ fn structDeclInner(
5172 astgen.src_hasher.update(tree.getNodeSource(member_node));5119 astgen.src_hasher.update(tree.getNodeSource(member_node));
51735120
5174 const field_name = try astgen.identAsString(member.ast.main_token);5121 const field_name = try astgen.identAsString(member.ast.main_token);
5175 member.convertToNonTupleLike(astgen.tree.nodes);5122 member.convertToNonTupleLike(astgen.tree);
5176 assert(!member.ast.tuple_like);5123 assert(!member.ast.tuple_like);
5177 wip_members.appendToField(@intFromEnum(field_name));5124 wip_members.appendToField(@intFromEnum(field_name));
51785125
5179 if (member.ast.type_expr == 0) {5126 const type_expr = member.ast.type_expr.unwrap() orelse {
5180 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});5127 return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
5181 }5128 };
51825129
5183 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);5130 const field_type = try typeExpr(&block_scope, &namespace.base, type_expr);
5184 const have_type_body = !block_scope.isEmpty();5131 const have_type_body = !block_scope.isEmpty();
5185 const have_align = member.ast.align_expr != 0;5132 const have_align = member.ast.align_expr != .none;
5186 const have_value = member.ast.value_expr != 0;5133 const have_value = member.ast.value_expr != .none;
5187 const is_comptime = member.comptime_token != null;5134 const is_comptime = member.comptime_token != null;
51885135
5189 if (is_comptime) {5136 if (is_comptime) {
...@@ -5193,9 +5140,9 @@ fn structDeclInner(...@@ -5193,9 +5140,9 @@ fn structDeclInner(
5193 }5140 }
5194 } else {5141 } else {
5195 known_non_opv = known_non_opv or5142 known_non_opv = known_non_opv or
5196 nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr);5143 nodeImpliesMoreThanOnePossibleValue(tree, type_expr);
5197 known_comptime_only = known_comptime_only or5144 known_comptime_only = known_comptime_only or
5198 nodeImpliesComptimeOnly(tree, member.ast.type_expr);5145 nodeImpliesComptimeOnly(tree, type_expr);
5199 }5146 }
5200 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 });
52015148
...@@ -5213,12 +5160,12 @@ fn structDeclInner(...@@ -5213,12 +5160,12 @@ fn structDeclInner(
5213 wip_members.appendToField(@intFromEnum(field_type));5160 wip_members.appendToField(@intFromEnum(field_type));
5214 }5161 }
52155162
5216 if (have_align) {5163 if (member.ast.align_expr.unwrap()) |align_expr| {
5217 if (layout == .@"packed") {5164 if (layout == .@"packed") {
5218 return astgen.failNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{});5165 return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{});
5219 }5166 }
5220 any_aligned_fields = true;5167 any_aligned_fields = true;
5221 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr);5168 const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr);
5222 if (!block_scope.endsWithNoReturn()) {5169 if (!block_scope.endsWithNoReturn()) {
5223 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);5170 _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref);
5224 }5171 }
...@@ -5230,14 +5177,14 @@ fn structDeclInner(...@@ -5230,14 +5177,14 @@ fn structDeclInner(
5230 block_scope.instructions.items.len = block_scope.instructions_top;5177 block_scope.instructions.items.len = block_scope.instructions_top;
5231 }5178 }
52325179
5233 if (have_value) {5180 if (member.ast.value_expr.unwrap()) |value_expr| {
5234 any_default_inits = true;5181 any_default_inits = true;
52355182
5236 // 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
5237 // 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.
5238 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() } };
52395186
5240 const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr);5187 const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr);
5241 if (!block_scope.endsWithNoReturn()) {5188 if (!block_scope.endsWithNoReturn()) {
5242 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);5189 _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst);
5243 }5190 }
...@@ -5300,21 +5247,19 @@ fn tupleDecl(...@@ -5300,21 +5247,19 @@ fn tupleDecl(
5300 node: Ast.Node.Index,5247 node: Ast.Node.Index,
5301 container_decl: Ast.full.ContainerDecl,5248 container_decl: Ast.full.ContainerDecl,
5302 layout: std.builtin.Type.ContainerLayout,5249 layout: std.builtin.Type.ContainerLayout,
5303 backing_int_node: Ast.Node.Index,5250 backing_int_node: Ast.Node.OptionalIndex,
5304) InnerError!Zir.Inst.Ref {5251) InnerError!Zir.Inst.Ref {
5305 const astgen = gz.astgen;5252 const astgen = gz.astgen;
5306 const gpa = astgen.gpa;5253 const gpa = astgen.gpa;
5307 const tree = astgen.tree;5254 const tree = astgen.tree;
53085255
5309 const node_tags = tree.nodes.items(.tag);
5310
5311 switch (layout) {5256 switch (layout) {
5312 .auto => {},5257 .auto => {},
5313 .@"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)}),
5314 }5259 }
53155260
5316 if (backing_int_node != 0) {5261 if (backing_int_node.unwrap()) |arg| {
5317 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", .{});
5318 }5263 }
53195264
5320 // 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:
...@@ -5329,7 +5274,7 @@ fn tupleDecl(...@@ -5329,7 +5274,7 @@ fn tupleDecl(
53295274
5330 for (container_decl.ast.members) |member_node| {5275 for (container_decl.ast.members) |member_node| {
5331 const field = tree.fullContainerField(member_node) orelse {5276 const field = tree.fullContainerField(member_node) orelse {
5332 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) {5277 const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) {
5333 .container_field_init,5278 .container_field_init,
5334 .container_field_align,5279 .container_field_align,
5335 .container_field,5280 .container_field,
...@@ -5348,23 +5293,23 @@ fn tupleDecl(...@@ -5348,23 +5293,23 @@ fn tupleDecl(
5348 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", .{});
5349 }5294 }
53505295
5351 if (field.ast.align_expr != 0) {5296 if (field.ast.align_expr != .none) {
5352 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});5297 return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
5353 }5298 }
53545299
5355 if (field.ast.value_expr != 0 and field.comptime_token == null) {5300 if (field.ast.value_expr != .none and field.comptime_token == null) {
5356 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", .{});
5357 }5302 }
53585303
5359 if (field.ast.value_expr == 0 and field.comptime_token != null) {5304 if (field.ast.value_expr == .none and field.comptime_token != null) {
5360 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", .{});
5361 }5306 }
53625307
5363 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr);5308 const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?);
5364 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));5309 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
53655310
5366 if (field.ast.value_expr != 0) {5311 if (field.ast.value_expr.unwrap()) |value_expr| {
5367 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);
5368 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));5313 astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
5369 } else {5314 } else {
5370 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));5315 astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
...@@ -5399,7 +5344,7 @@ fn unionDeclInner(...@@ -5399,7 +5344,7 @@ fn unionDeclInner(
5399 node: Ast.Node.Index,5344 node: Ast.Node.Index,
5400 members: []const Ast.Node.Index,5345 members: []const Ast.Node.Index,
5401 layout: std.builtin.Type.ContainerLayout,5346 layout: std.builtin.Type.ContainerLayout,
5402 arg_node: Ast.Node.Index,5347 opt_arg_node: Ast.Node.OptionalIndex,
5403 auto_enum_tok: ?Ast.TokenIndex,5348 auto_enum_tok: ?Ast.TokenIndex,
5404) InnerError!Zir.Inst.Ref {5349) InnerError!Zir.Inst.Ref {
5405 const decl_inst = try gz.reserveInstructionIndex();5350 const decl_inst = try gz.reserveInstructionIndex();
...@@ -5434,15 +5379,15 @@ fn unionDeclInner(...@@ -5434,15 +5379,15 @@ fn unionDeclInner(
5434 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");5379 const decl_count = try astgen.scanContainer(&namespace, members, .@"union");
5435 const field_count: u32 = @intCast(members.len - decl_count);5380 const field_count: u32 = @intCast(members.len - decl_count);
54365381
5437 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)) {
5438 if (arg_node != 0) {5383 if (opt_arg_node.unwrap()) |arg_node| {
5439 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)});
5440 } else {5385 } else {
5441 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)});
5442 }5387 }
5443 }5388 }
54445389
5445 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)5390 const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node|
5446 try typeExpr(&block_scope, &namespace.base, arg_node)5391 try typeExpr(&block_scope, &namespace.base, arg_node)
5447 else5392 else
5448 .none;5393 .none;
...@@ -5458,7 +5403,7 @@ fn unionDeclInner(...@@ -5458,7 +5403,7 @@ fn unionDeclInner(
5458 astgen.src_hasher = std.zig.SrcHasher.init(.{});5403 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5459 astgen.src_hasher.update(@tagName(layout));5404 astgen.src_hasher.update(@tagName(layout));
5460 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});5405 astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)});
5461 if (arg_node != 0) {5406 if (opt_arg_node.unwrap()) |arg_node| {
5462 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));5407 astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node));
5463 }5408 }
54645409
...@@ -5468,7 +5413,7 @@ fn unionDeclInner(...@@ -5468,7 +5413,7 @@ fn unionDeclInner(
5468 .field => |field| field,5413 .field => |field| field,
5469 };5414 };
5470 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));5415 astgen.src_hasher.update(astgen.tree.getNodeSource(member_node));
5471 member.convertToNonTupleLike(astgen.tree.nodes);5416 member.convertToNonTupleLike(astgen.tree);
5472 if (member.ast.tuple_like) {5417 if (member.ast.tuple_like) {
5473 return astgen.failTok(member.ast.main_token, "union field missing name", .{});5418 return astgen.failTok(member.ast.main_token, "union field missing name", .{});
5474 }5419 }
...@@ -5479,24 +5424,24 @@ fn unionDeclInner(...@@ -5479,24 +5424,24 @@ fn unionDeclInner(
5479 const field_name = try astgen.identAsString(member.ast.main_token);5424 const field_name = try astgen.identAsString(member.ast.main_token);
5480 wip_members.appendToField(@intFromEnum(field_name));5425 wip_members.appendToField(@intFromEnum(field_name));
54815426
5482 const have_type = member.ast.type_expr != 0;5427 const have_type = member.ast.type_expr != .none;
5483 const have_align = member.ast.align_expr != 0;5428 const have_align = member.ast.align_expr != .none;
5484 const have_value = member.ast.value_expr != 0;5429 const have_value = member.ast.value_expr != .none;
5485 const unused = false;5430 const unused = false;
5486 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 });
54875432
5488 if (have_type) {5433 if (member.ast.type_expr.unwrap()) |type_expr| {
5489 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);
5490 wip_members.appendToField(@intFromEnum(field_type));5435 wip_members.appendToField(@intFromEnum(field_type));
5491 } else if (arg_inst == .none and auto_enum_tok == null) {5436 } else if (arg_inst == .none and auto_enum_tok == null) {
5492 return astgen.failNode(member_node, "union field missing type", .{});5437 return astgen.failNode(member_node, "union field missing type", .{});
5493 }5438 }
5494 if (have_align) {5439 if (member.ast.align_expr.unwrap()) |align_expr| {
5495 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);
5496 wip_members.appendToField(@intFromEnum(align_inst));5441 wip_members.appendToField(@intFromEnum(align_inst));
5497 any_aligned_fields = true;5442 any_aligned_fields = true;
5498 }5443 }
5499 if (have_value) {5444 if (member.ast.value_expr.unwrap()) |value_expr| {
5500 if (arg_inst == .none) {5445 if (arg_inst == .none) {
5501 return astgen.failNodeNotes(5446 return astgen.failNodeNotes(
5502 node,5447 node,
...@@ -5504,7 +5449,7 @@ fn unionDeclInner(...@@ -5504,7 +5449,7 @@ fn unionDeclInner(
5504 .{},5449 .{},
5505 &[_]u32{5450 &[_]u32{
5506 try astgen.errNoteNode(5451 try astgen.errNoteNode(
5507 member.ast.value_expr,5452 value_expr,
5508 "tag value specified here",5453 "tag value specified here",
5509 .{},5454 .{},
5510 ),5455 ),
...@@ -5518,14 +5463,14 @@ fn unionDeclInner(...@@ -5518,14 +5463,14 @@ fn unionDeclInner(
5518 .{},5463 .{},
5519 &[_]u32{5464 &[_]u32{
5520 try astgen.errNoteNode(5465 try astgen.errNoteNode(
5521 member.ast.value_expr,5466 value_expr,
5522 "tag value specified here",5467 "tag value specified here",
5523 .{},5468 .{},
5524 ),5469 ),
5525 },5470 },
5526 );5471 );
5527 }5472 }
5528 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5473 const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5529 wip_members.appendToField(@intFromEnum(tag_value));5474 wip_members.appendToField(@intFromEnum(tag_value));
5530 }5475 }
5531 }5476 }
...@@ -5577,7 +5522,6 @@ fn containerDecl(...@@ -5577,7 +5522,6 @@ fn containerDecl(
5577 const astgen = gz.astgen;5522 const astgen = gz.astgen;
5578 const gpa = astgen.gpa;5523 const gpa = astgen.gpa;
5579 const tree = astgen.tree;5524 const tree = astgen.tree;
5580 const token_tags = tree.tokens.items(.tag);
55815525
5582 const prev_fn_block = astgen.fn_block;5526 const prev_fn_block = astgen.fn_block;
5583 astgen.fn_block = null;5527 astgen.fn_block = null;
...@@ -5586,9 +5530,9 @@ fn containerDecl(...@@ -5586,9 +5530,9 @@ fn containerDecl(
5586 // 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
5587 // ZIR for all the field types, alignments, and default value expressions.5531 // ZIR for all the field types, alignments, and default value expressions.
55885532
5589 switch (token_tags[container_decl.ast.main_token]) {5533 switch (tree.tokenTag(container_decl.ast.main_token)) {
5590 .keyword_struct => {5534 .keyword_struct => {
5591 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {5535 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
5592 .keyword_packed => .@"packed",5536 .keyword_packed => .@"packed",
5593 .keyword_extern => .@"extern",5537 .keyword_extern => .@"extern",
5594 else => unreachable,5538 else => unreachable,
...@@ -5598,7 +5542,7 @@ fn containerDecl(...@@ -5598,7 +5542,7 @@ fn containerDecl(
5598 return rvalue(gz, ri, result, node);5542 return rvalue(gz, ri, result, node);
5599 },5543 },
5600 .keyword_union => {5544 .keyword_union => {
5601 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) {5545 const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) {
5602 .keyword_packed => .@"packed",5546 .keyword_packed => .@"packed",
5603 .keyword_extern => .@"extern",5547 .keyword_extern => .@"extern",
5604 else => unreachable,5548 else => unreachable,
...@@ -5616,23 +5560,23 @@ fn containerDecl(...@@ -5616,23 +5560,23 @@ fn containerDecl(
5616 var values: usize = 0;5560 var values: usize = 0;
5617 var total_fields: usize = 0;5561 var total_fields: usize = 0;
5618 var decls: usize = 0;5562 var decls: usize = 0;
5619 var nonexhaustive_node: Ast.Node.Index = 0;5563 var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none;
5620 var nonfinal_nonexhaustive = false;5564 var nonfinal_nonexhaustive = false;
5621 for (container_decl.ast.members) |member_node| {5565 for (container_decl.ast.members) |member_node| {
5622 var member = tree.fullContainerField(member_node) orelse {5566 var member = tree.fullContainerField(member_node) orelse {
5623 decls += 1;5567 decls += 1;
5624 continue;5568 continue;
5625 };5569 };
5626 member.convertToNonTupleLike(astgen.tree.nodes);5570 member.convertToNonTupleLike(astgen.tree);
5627 if (member.ast.tuple_like) {5571 if (member.ast.tuple_like) {
5628 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});5572 return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
5629 }5573 }
5630 if (member.comptime_token) |comptime_token| {5574 if (member.comptime_token) |comptime_token| {
5631 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});5575 return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
5632 }5576 }
5633 if (member.ast.type_expr != 0) {5577 if (member.ast.type_expr.unwrap()) |type_expr| {
5634 return astgen.failNodeNotes(5578 return astgen.failNodeNotes(
5635 member.ast.type_expr,5579 type_expr,
5636 "enum fields do not have types",5580 "enum fields do not have types",
5637 .{},5581 .{},
5638 &[_]u32{5582 &[_]u32{
...@@ -5644,13 +5588,13 @@ fn containerDecl(...@@ -5644,13 +5588,13 @@ fn containerDecl(
5644 },5588 },
5645 );5589 );
5646 }5590 }
5647 if (member.ast.align_expr != 0) {5591 if (member.ast.align_expr.unwrap()) |align_expr| {
5648 return astgen.failNode(member.ast.align_expr, "enum fields cannot be aligned", .{});5592 return astgen.failNode(align_expr, "enum fields cannot be aligned", .{});
5649 }5593 }
56505594
5651 const name_token = member.ast.main_token;5595 const name_token = member.ast.main_token;
5652 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {5596 if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
5653 if (nonexhaustive_node != 0) {5597 if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| {
5654 return astgen.failNodeNotes(5598 return astgen.failNodeNotes(
5655 member_node,5599 member_node,
5656 "redundant non-exhaustive enum mark",5600 "redundant non-exhaustive enum mark",
...@@ -5664,40 +5608,41 @@ fn containerDecl(...@@ -5664,40 +5608,41 @@ fn containerDecl(
5664 },5608 },
5665 );5609 );
5666 }5610 }
5667 nonexhaustive_node = member_node;5611 opt_nonexhaustive_node = member_node.toOptional();
5668 if (member.ast.value_expr != 0) {5612 if (member.ast.value_expr.unwrap()) |value_expr| {
5669 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", .{});
5670 }5614 }
5671 continue;5615 continue;
5672 } else if (nonexhaustive_node != 0) {5616 } else if (opt_nonexhaustive_node != .none) {
5673 nonfinal_nonexhaustive = true;5617 nonfinal_nonexhaustive = true;
5674 }5618 }
5675 total_fields += 1;5619 total_fields += 1;
5676 if (member.ast.value_expr != 0) {5620 if (member.ast.value_expr.unwrap()) |value_expr| {
5677 if (container_decl.ast.arg == 0) {5621 if (container_decl.ast.arg == .none) {
5678 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", .{});
5679 }5623 }
5680 values += 1;5624 values += 1;
5681 }5625 }
5682 }5626 }
5683 if (nonfinal_nonexhaustive) {5627 if (nonfinal_nonexhaustive) {
5684 return astgen.failNode(nonexhaustive_node, "'_' field of non-exhaustive enum must be last", .{});5628 return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{});
5685 }5629 }
5686 break :blk .{5630 break :blk .{
5687 .total_fields = total_fields,5631 .total_fields = total_fields,
5688 .values = values,5632 .values = values,
5689 .decls = decls,5633 .decls = decls,
5690 .nonexhaustive_node = nonexhaustive_node,5634 .nonexhaustive_node = opt_nonexhaustive_node,
5691 };5635 };
5692 };5636 };
5693 if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) {5637 if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) {
5638 const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?;
5694 return astgen.failNodeNotes(5639 return astgen.failNodeNotes(
5695 node,5640 node,
5696 "non-exhaustive enum missing integer tag type",5641 "non-exhaustive enum missing integer tag type",
5697 .{},5642 .{},
5698 &[_]u32{5643 &[_]u32{
5699 try astgen.errNoteNode(5644 try astgen.errNoteNode(
5700 counts.nonexhaustive_node,5645 nonexhaustive_node,
5701 "marked non-exhaustive here",5646 "marked non-exhaustive here",
5702 .{},5647 .{},
5703 ),5648 ),
...@@ -5706,7 +5651,7 @@ fn containerDecl(...@@ -5706,7 +5651,7 @@ fn containerDecl(
5706 }5651 }
5707 // 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
5708 // how structs are handled above.5653 // how structs are handled above.
5709 const nonexhaustive = counts.nonexhaustive_node != 0;5654 const nonexhaustive = counts.nonexhaustive_node != .none;
57105655
5711 const decl_inst = try gz.reserveInstructionIndex();5656 const decl_inst = try gz.reserveInstructionIndex();
57125657
...@@ -5736,8 +5681,8 @@ fn containerDecl(...@@ -5736,8 +5681,8 @@ fn containerDecl(
5736 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");5681 _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum");
5737 namespace.base.tag = .namespace;5682 namespace.base.tag = .namespace;
57385683
5739 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|
5740 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)
5741 else5686 else
5742 .none;5687 .none;
57435688
...@@ -5749,31 +5694,31 @@ fn containerDecl(...@@ -5749,31 +5694,31 @@ fn containerDecl(
5749 const old_hasher = astgen.src_hasher;5694 const old_hasher = astgen.src_hasher;
5750 defer astgen.src_hasher = old_hasher;5695 defer astgen.src_hasher = old_hasher;
5751 astgen.src_hasher = std.zig.SrcHasher.init(.{});5696 astgen.src_hasher = std.zig.SrcHasher.init(.{});
5752 if (container_decl.ast.arg != 0) {5697 if (container_decl.ast.arg.unwrap()) |arg| {
5753 astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg));5698 astgen.src_hasher.update(tree.getNodeSource(arg));
5754 }5699 }
5755 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});5700 astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)});
57565701
5757 for (container_decl.ast.members) |member_node| {5702 for (container_decl.ast.members) |member_node| {
5758 if (member_node == counts.nonexhaustive_node)5703 if (member_node.toOptional() == counts.nonexhaustive_node)
5759 continue;5704 continue;
5760 astgen.src_hasher.update(tree.getNodeSource(member_node));5705 astgen.src_hasher.update(tree.getNodeSource(member_node));
5761 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)) {
5762 .decl => continue,5707 .decl => continue,
5763 .field => |field| field,5708 .field => |field| field,
5764 };5709 };
5765 member.convertToNonTupleLike(astgen.tree.nodes);5710 member.convertToNonTupleLike(astgen.tree);
5766 assert(member.comptime_token == null);5711 assert(member.comptime_token == null);
5767 assert(member.ast.type_expr == 0);5712 assert(member.ast.type_expr == .none);
5768 assert(member.ast.align_expr == 0);5713 assert(member.ast.align_expr == .none);
57695714
5770 const field_name = try astgen.identAsString(member.ast.main_token);5715 const field_name = try astgen.identAsString(member.ast.main_token);
5771 wip_members.appendToField(@intFromEnum(field_name));5716 wip_members.appendToField(@intFromEnum(field_name));
57725717
5773 const have_value = member.ast.value_expr != 0;5718 const have_value = member.ast.value_expr != .none;
5774 wip_members.nextField(bits_per_field, .{have_value});5719 wip_members.nextField(bits_per_field, .{have_value});
57755720
5776 if (have_value) {5721 if (member.ast.value_expr.unwrap()) |value_expr| {
5777 if (arg_inst == .none) {5722 if (arg_inst == .none) {
5778 return astgen.failNodeNotes(5723 return astgen.failNodeNotes(
5779 node,5724 node,
...@@ -5781,14 +5726,14 @@ fn containerDecl(...@@ -5781,14 +5726,14 @@ fn containerDecl(
5781 .{},5726 .{},
5782 &[_]u32{5727 &[_]u32{
5783 try astgen.errNoteNode(5728 try astgen.errNoteNode(
5784 member.ast.value_expr,5729 value_expr,
5785 "tag value specified here",5730 "tag value specified here",
5786 .{},5731 .{},
5787 ),5732 ),
5788 },5733 },
5789 );5734 );
5790 }5735 }
5791 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr);5736 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr);
5792 wip_members.appendToField(@intFromEnum(tag_value_inst));5737 wip_members.appendToField(@intFromEnum(tag_value_inst));
5793 }5738 }
5794 }5739 }
...@@ -5828,7 +5773,7 @@ fn containerDecl(...@@ -5828,7 +5773,7 @@ fn containerDecl(
5828 return rvalue(gz, ri, decl_inst.toRef(), node);5773 return rvalue(gz, ri, decl_inst.toRef(), node);
5829 },5774 },
5830 .keyword_opaque => {5775 .keyword_opaque => {
5831 assert(container_decl.ast.arg == 0);5776 assert(container_decl.ast.arg == .none);
58325777
5833 const decl_inst = try gz.reserveInstructionIndex();5778 const decl_inst = try gz.reserveInstructionIndex();
58345779
...@@ -5899,9 +5844,7 @@ fn containerMember(...@@ -5899,9 +5844,7 @@ fn containerMember(
5899) InnerError!ContainerMemberResult {5844) InnerError!ContainerMemberResult {
5900 const astgen = gz.astgen;5845 const astgen = gz.astgen;
5901 const tree = astgen.tree;5846 const tree = astgen.tree;
5902 const node_tags = tree.nodes.items(.tag);5847 switch (tree.nodeTag(member_node)) {
5903 const node_datas = tree.nodes.items(.data);
5904 switch (node_tags[member_node]) {
5905 .container_field_init,5848 .container_field_init,
5906 .container_field_align,5849 .container_field_align,
5907 .container_field,5850 .container_field,
...@@ -5915,7 +5858,11 @@ fn containerMember(...@@ -5915,7 +5858,11 @@ fn containerMember(
5915 => {5858 => {
5916 var buf: [1]Ast.Node.Index = undefined;5859 var buf: [1]Ast.Node.Index = undefined;
5917 const full = tree.fullFnProto(&buf, member_node).?;5860 const full = tree.fullFnProto(&buf, member_node).?;
5918 const body = if (node_tags[member_node] == .fn_decl) node_datas[member_node].rhs else 0;5861
5862 const body: Ast.Node.OptionalIndex = if (tree.nodeTag(member_node) == .fn_decl)
5863 tree.nodeData(member_node).node_and_node[1].toOptional()
5864 else
5865 .none;
59195866
5920 const prev_decl_index = wip_members.decl_index;5867 const prev_decl_index = wip_members.decl_index;
5921 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) {
...@@ -5986,12 +5933,7 @@ fn containerMember(...@@ -5986,12 +5933,7 @@ fn containerMember(
5986 .@"usingnamespace",5933 .@"usingnamespace",
5987 .empty,5934 .empty,
5988 member_node,5935 member_node,
5989 is_pub: {5936 tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}),
5990 const main_tokens = tree.nodes.items(.main_token);
5991 const token_tags = tree.tokens.items(.tag);
5992 const main_token = main_tokens[member_node];
5993 break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub;
5994 },
5995 );5937 );
5996 },5938 },
5997 };5939 };
...@@ -6025,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi...@@ -6025,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
6025 const astgen = gz.astgen;5967 const astgen = gz.astgen;
6026 const gpa = astgen.gpa;5968 const gpa = astgen.gpa;
6027 const tree = astgen.tree;5969 const tree = astgen.tree;
6028 const main_tokens = tree.nodes.items(.main_token);
6029 const token_tags = tree.tokens.items(.tag);
60305970
6031 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);
6032 var fields_len: usize = 0;5972 var fields_len: usize = 0;
...@@ -6034,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi...@@ -6034,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi
6034 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;5974 var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty;
6035 defer idents.deinit(gpa);5975 defer idents.deinit(gpa);
60365976
6037 const error_token = main_tokens[node];5977 const error_token = tree.nodeMainToken(node);
6038 var tok_i = error_token + 2;5978 var tok_i = error_token + 2;
6039 while (true) : (tok_i += 1) {5979 while (true) : (tok_i += 1) {
6040 switch (token_tags[tok_i]) {5980 switch (tree.tokenTag(tok_i)) {
6041 .doc_comment, .comma => {},5981 .doc_comment, .comma => {},
6042 .identifier => {5982 .identifier => {
6043 const str_index = try astgen.identAsString(tok_i);5983 const str_index = try astgen.identAsString(tok_i);
...@@ -6089,10 +6029,10 @@ fn tryExpr(...@@ -6089,10 +6029,10 @@ fn tryExpr(
6089 return astgen.failNode(node, "'try' outside function scope", .{});6029 return astgen.failNode(node, "'try' outside function scope", .{});
6090 };6030 };
60916031
6092 if (parent_gz.any_defer_node != 0) {6032 if (parent_gz.any_defer_node.unwrap()) |any_defer_node| {
6093 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{6033 return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{
6094 try astgen.errNoteNode(6034 try astgen.errNoteNode(
6095 parent_gz.any_defer_node,6035 any_defer_node,
6096 "defer expression here",6036 "defer expression here",
6097 .{},6037 .{},
6098 ),6038 ),
...@@ -6155,16 +6095,16 @@ fn orelseCatchExpr(...@@ -6155,16 +6095,16 @@ fn orelseCatchExpr(
6155 scope: *Scope,6095 scope: *Scope,
6156 ri: ResultInfo,6096 ri: ResultInfo,
6157 node: Ast.Node.Index,6097 node: Ast.Node.Index,
6158 lhs: Ast.Node.Index,
6159 cond_op: Zir.Inst.Tag,6098 cond_op: Zir.Inst.Tag,
6160 unwrap_op: Zir.Inst.Tag,6099 unwrap_op: Zir.Inst.Tag,
6161 unwrap_code_op: Zir.Inst.Tag,6100 unwrap_code_op: Zir.Inst.Tag,
6162 rhs: Ast.Node.Index,
6163 payload_token: ?Ast.TokenIndex,6101 payload_token: ?Ast.TokenIndex,
6164) InnerError!Zir.Inst.Ref {6102) InnerError!Zir.Inst.Ref {
6165 const astgen = parent_gz.astgen;6103 const astgen = parent_gz.astgen;
6166 const tree = astgen.tree;6104 const tree = astgen.tree;
61676105
6106 const lhs, const rhs = tree.nodeData(node).node_and_node;
6107
6168 const need_rl = astgen.nodes_need_rl.contains(node);6108 const need_rl = astgen.nodes_need_rl.contains(node);
6169 const block_ri: ResultInfo = if (need_rl) ri else .{6109 const block_ri: ResultInfo = if (need_rl) ri else .{
6170 .rl = switch (ri.rl) {6110 .rl = switch (ri.rl) {
...@@ -6297,12 +6237,8 @@ fn addFieldAccess(...@@ -6297,12 +6237,8 @@ fn addFieldAccess(
6297) InnerError!Zir.Inst.Ref {6237) InnerError!Zir.Inst.Ref {
6298 const astgen = gz.astgen;6238 const astgen = gz.astgen;
6299 const tree = astgen.tree;6239 const tree = astgen.tree;
6300 const main_tokens = tree.nodes.items(.main_token);
6301 const node_datas = tree.nodes.items(.data);
63026240
6303 const object_node = node_datas[node].lhs;6241 const object_node, const field_ident = tree.nodeData(node).node_and_token;
6304 const dot_token = main_tokens[node];
6305 const field_ident = dot_token + 1;
6306 const str_index = try astgen.identAsString(field_ident);6242 const str_index = try astgen.identAsString(field_ident);
6307 const lhs = try expr(gz, scope, lhs_ri, object_node);6243 const lhs = try expr(gz, scope, lhs_ri, object_node);
63086244
...@@ -6322,24 +6258,25 @@ fn arrayAccess(...@@ -6322,24 +6258,25 @@ fn arrayAccess(
6322 node: Ast.Node.Index,6258 node: Ast.Node.Index,
6323) InnerError!Zir.Inst.Ref {6259) InnerError!Zir.Inst.Ref {
6324 const tree = gz.astgen.tree;6260 const tree = gz.astgen.tree;
6325 const node_datas = tree.nodes.items(.data);
6326 switch (ri.rl) {6261 switch (ri.rl) {
6327 .ref, .ref_coerced_ty => {6262 .ref, .ref_coerced_ty => {
6328 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);6263 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6264 const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node);
63296265
6330 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);6266 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63316267
6332 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);6268 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
6333 try emitDbgStmt(gz, cursor);6269 try emitDbgStmt(gz, cursor);
63346270
6335 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });6271 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
6336 },6272 },
6337 else => {6273 else => {
6338 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);6274 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6275 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
63396276
6340 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);6277 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
63416278
6342 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);6279 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node);
6343 try emitDbgStmt(gz, cursor);6280 try emitDbgStmt(gz, cursor);
63446281
6345 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);6282 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
...@@ -6356,22 +6293,22 @@ fn simpleBinOp(...@@ -6356,22 +6293,22 @@ fn simpleBinOp(
6356) InnerError!Zir.Inst.Ref {6293) InnerError!Zir.Inst.Ref {
6357 const astgen = gz.astgen;6294 const astgen = gz.astgen;
6358 const tree = astgen.tree;6295 const tree = astgen.tree;
6359 const node_datas = tree.nodes.items(.data);6296
6297 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
63606298
6361 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {6299 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
6362 const node_tags = tree.nodes.items(.tag);
6363 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";6300 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
6364 if (node_tags[node_datas[node].lhs] == .string_literal or6301 if (tree.nodeTag(lhs_node) == .string_literal or
6365 node_tags[node_datas[node].rhs] == .string_literal)6302 tree.nodeTag(rhs_node) == .string_literal)
6366 return astgen.failNode(node, "cannot compare strings with {s}", .{str});6303 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
6367 }6304 }
63686305
6369 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);6306 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node);
6370 const cursor = switch (op_inst_tag) {6307 const cursor = switch (op_inst_tag) {
6371 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),6308 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
6372 else => undefined,6309 else => undefined,
6373 };6310 };
6374 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);6311 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node);
63756312
6376 switch (op_inst_tag) {6313 switch (op_inst_tag) {
6377 .add, .sub, .mul, .div, .mod_rem => {6314 .add, .sub, .mul, .div, .mod_rem => {
...@@ -6405,16 +6342,16 @@ fn boolBinOp(...@@ -6405,16 +6342,16 @@ fn boolBinOp(
6405) InnerError!Zir.Inst.Ref {6342) InnerError!Zir.Inst.Ref {
6406 const astgen = gz.astgen;6343 const astgen = gz.astgen;
6407 const tree = astgen.tree;6344 const tree = astgen.tree;
6408 const node_datas = tree.nodes.items(.data);
64096345
6410 const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs);6346 const lhs_node, const rhs_node = tree.nodeData(node).node_and_node;
6347 const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node);
6411 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;6348 const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?;
64126349
6413 var rhs_scope = gz.makeSubBlock(scope);6350 var rhs_scope = gz.makeSubBlock(scope);
6414 defer rhs_scope.unstack();6351 defer rhs_scope.unstack();
6415 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint);6352 const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint);
6416 if (!gz.refIsNoReturn(rhs)) {6353 if (!gz.refIsNoReturn(rhs)) {
6417 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs);6354 _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node);
6418 }6355 }
6419 try rhs_scope.setBoolBrBody(bool_br, lhs);6356 try rhs_scope.setBoolBrBody(bool_br, lhs);
64206357
...@@ -6431,7 +6368,6 @@ fn ifExpr(...@@ -6431,7 +6368,6 @@ fn ifExpr(
6431) InnerError!Zir.Inst.Ref {6368) InnerError!Zir.Inst.Ref {
6432 const astgen = parent_gz.astgen;6369 const astgen = parent_gz.astgen;
6433 const tree = astgen.tree;6370 const tree = astgen.tree;
6434 const token_tags = tree.tokens.items(.tag);
64356371
6436 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;6372 const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
64376373
...@@ -6454,7 +6390,7 @@ fn ifExpr(...@@ -6454,7 +6390,7 @@ fn ifExpr(
6454 defer block_scope.unstack();6390 defer block_scope.unstack();
64556391
6456 const payload_is_ref = if (if_full.payload_token) |payload_token|6392 const payload_is_ref = if (if_full.payload_token) |payload_token|
6457 token_tags[payload_token] == .asterisk6393 tree.tokenTag(payload_token) == .asterisk
6458 else6394 else
6459 false;6395 false;
64606396
...@@ -6532,7 +6468,7 @@ fn ifExpr(...@@ -6532,7 +6468,7 @@ fn ifExpr(
6532 break :s &then_scope.base;6468 break :s &then_scope.base;
6533 }6469 }
6534 } else if (if_full.payload_token) |payload_token| {6470 } else if (if_full.payload_token) |payload_token| {
6535 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;6471 const ident_token = payload_token + @intFromBool(payload_is_ref);
6536 const tag: Zir.Inst.Tag = if (payload_is_ref)6472 const tag: Zir.Inst.Tag = if (payload_is_ref)
6537 .optional_payload_unsafe_ptr6473 .optional_payload_unsafe_ptr
6538 else6474 else
...@@ -6574,8 +6510,7 @@ fn ifExpr(...@@ -6574,8 +6510,7 @@ fn ifExpr(
6574 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))6510 if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr))
6575 _ = try else_scope.addSaveErrRetIndex(.always);6511 _ = try else_scope.addSaveErrRetIndex(.always);
65766512
6577 const else_node = if_full.ast.else_expr;6513 if (if_full.ast.else_expr.unwrap()) |else_node| {
6578 if (else_node != 0) {
6579 const sub_scope = s: {6514 const sub_scope = s: {
6580 if (if_full.error_token) |error_token| {6515 if (if_full.error_token) |error_token| {
6581 const tag: Zir.Inst.Tag = if (payload_is_ref)6516 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -6663,8 +6598,6 @@ fn whileExpr(...@@ -6663,8 +6598,6 @@ fn whileExpr(
6663) InnerError!Zir.Inst.Ref {6598) InnerError!Zir.Inst.Ref {
6664 const astgen = parent_gz.astgen;6599 const astgen = parent_gz.astgen;
6665 const tree = astgen.tree;6600 const tree = astgen.tree;
6666 const token_tags = tree.tokens.items(.tag);
6667 const token_starts = tree.tokens.items(.start);
66686601
6669 const need_rl = astgen.nodes_need_rl.contains(node);6602 const need_rl = astgen.nodes_need_rl.contains(node);
6670 const block_ri: ResultInfo = if (need_rl) ri else .{6603 const block_ri: ResultInfo = if (need_rl) ri else .{
...@@ -6701,7 +6634,7 @@ fn whileExpr(...@@ -6701,7 +6634,7 @@ fn whileExpr(
6701 defer cond_scope.unstack();6634 defer cond_scope.unstack();
67026635
6703 const payload_is_ref = if (while_full.payload_token) |payload_token|6636 const payload_is_ref = if (while_full.payload_token) |payload_token|
6704 token_tags[payload_token] == .asterisk6637 tree.tokenTag(payload_token) == .asterisk
6705 else6638 else
6706 false;6639 false;
67076640
...@@ -6787,7 +6720,6 @@ fn whileExpr(...@@ -6787,7 +6720,6 @@ fn whileExpr(
6787 break :s &then_scope.base;6720 break :s &then_scope.base;
6788 }6721 }
6789 } else if (while_full.payload_token) |payload_token| {6722 } else if (while_full.payload_token) |payload_token| {
6790 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
6791 const tag: Zir.Inst.Tag = if (payload_is_ref)6723 const tag: Zir.Inst.Tag = if (payload_is_ref)
6792 .optional_payload_unsafe_ptr6724 .optional_payload_unsafe_ptr
6793 else6725 else
...@@ -6795,6 +6727,7 @@ fn whileExpr(...@@ -6795,6 +6727,7 @@ fn whileExpr(
6795 // will add this instruction to then_scope.instructions below6727 // will add this instruction to then_scope.instructions below
6796 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);6728 const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr);
6797 opt_payload_inst = payload_inst.toOptional();6729 opt_payload_inst = payload_inst.toOptional();
6730 const ident_token = payload_token + @intFromBool(payload_is_ref);
6798 const ident_name = try astgen.identAsString(ident_token);6731 const ident_name = try astgen.identAsString(ident_token);
6799 const ident_bytes = tree.tokenSlice(ident_token);6732 const ident_bytes = tree.tokenSlice(ident_token);
6800 if (mem.eql(u8, "_", ident_bytes)) {6733 if (mem.eql(u8, "_", ident_bytes)) {
...@@ -6849,8 +6782,8 @@ fn whileExpr(...@@ -6849,8 +6782,8 @@ fn whileExpr(
6849 // are no jumps to it. This happens when the last statement of a while body is noreturn6782 // are no jumps to it. This happens when the last statement of a while body is noreturn
6850 // and there are no `continue` statements.6783 // and there are no `continue` statements.
6851 // Tracking issue: https://github.com/ziglang/zig/issues/91856784 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6852 if (while_full.ast.cont_expr != 0) {6785 if (while_full.ast.cont_expr.unwrap()) |cont_expr| {
6853 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);6786 _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr);
6854 }6787 }
68556788
6856 continue_scope.instructions_top = continue_scope.instructions.items.len;6789 continue_scope.instructions_top = continue_scope.instructions.items.len;
...@@ -6862,7 +6795,7 @@ fn whileExpr(...@@ -6862,7 +6795,7 @@ fn whileExpr(
6862 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);6795 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6863 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";6796 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6864 if (!continue_scope.endsWithNoReturn()) {6797 if (!continue_scope.endsWithNoReturn()) {
6865 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);6798 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
6866 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });6799 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
6867 _ = try parent_gz.add(.{6800 _ = try parent_gz.add(.{
6868 .tag = .extended,6801 .tag = .extended,
...@@ -6880,8 +6813,7 @@ fn whileExpr(...@@ -6880,8 +6813,7 @@ fn whileExpr(
6880 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);6813 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
6881 defer else_scope.unstack();6814 defer else_scope.unstack();
68826815
6883 const else_node = while_full.ast.else_expr;6816 if (while_full.ast.else_expr.unwrap()) |else_node| {
6884 if (else_node != 0) {
6885 const sub_scope = s: {6817 const sub_scope = s: {
6886 if (while_full.error_token) |error_token| {6818 if (while_full.error_token) |error_token| {
6887 const tag: Zir.Inst.Tag = if (payload_is_ref)6819 const tag: Zir.Inst.Tag = if (payload_is_ref)
...@@ -6979,10 +6911,6 @@ fn forExpr(...@@ -6979,10 +6911,6 @@ fn forExpr(
6979 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});6911 try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{});
6980 }6912 }
6981 const tree = astgen.tree;6913 const tree = astgen.tree;
6982 const token_tags = tree.tokens.items(.tag);
6983 const token_starts = tree.tokens.items(.start);
6984 const node_tags = tree.nodes.items(.tag);
6985 const node_data = tree.nodes.items(.data);
6986 const gpa = astgen.gpa;6914 const gpa = astgen.gpa;
69876915
6988 // For counters, this is the start value; for indexables, this is the base6916 // For counters, this is the start value; for indexables, this is the base
...@@ -7012,7 +6940,7 @@ fn forExpr(...@@ -7012,7 +6940,7 @@ fn forExpr(
7012 {6940 {
7013 var capture_token = for_full.payload_token;6941 var capture_token = for_full.payload_token;
7014 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {6942 for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| {
7015 const capture_is_ref = token_tags[capture_token] == .asterisk;6943 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
7016 const ident_tok = capture_token + @intFromBool(capture_is_ref);6944 const ident_tok = capture_token + @intFromBool(capture_is_ref);
7017 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");6945 const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_");
70186946
...@@ -7023,16 +6951,15 @@ fn forExpr(...@@ -7023,16 +6951,15 @@ fn forExpr(
7023 capture_token = ident_tok + 2;6951 capture_token = ident_tok + 2;
70246952
7025 try emitDbgNode(parent_gz, input);6953 try emitDbgNode(parent_gz, input);
7026 if (node_tags[input] == .for_range) {6954 if (tree.nodeTag(input) == .for_range) {
7027 if (capture_is_ref) {6955 if (capture_is_ref) {
7028 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});6956 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
7029 }6957 }
7030 const start_node = node_data[input].lhs;6958 const start_node, const end_node = tree.nodeData(input).node_and_opt_node;
7031 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);6959 const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node);
70326960
7033 const end_node = node_data[input].rhs;6961 const end_val = if (end_node.unwrap()) |end|
7034 const end_val = if (end_node != 0)6962 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end)
7035 try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs)
7036 else6963 else
7037 .none;6964 .none;
70386965
...@@ -7125,7 +7052,7 @@ fn forExpr(...@@ -7125,7 +7052,7 @@ fn forExpr(
7125 var capture_token = for_full.payload_token;7052 var capture_token = for_full.payload_token;
7126 var capture_sub_scope: *Scope = &then_scope.base;7053 var capture_sub_scope: *Scope = &then_scope.base;
7127 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {7054 for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| {
7128 const capture_is_ref = token_tags[capture_token] == .asterisk;7055 const capture_is_ref = tree.tokenTag(capture_token) == .asterisk;
7129 const ident_tok = capture_token + @intFromBool(capture_is_ref);7056 const ident_tok = capture_token + @intFromBool(capture_is_ref);
7130 const capture_name = tree.tokenSlice(ident_tok);7057 const capture_name = tree.tokenSlice(ident_tok);
7131 // Skip over the comma, and on to the next capture (or the ending pipe character).7058 // Skip over the comma, and on to the next capture (or the ending pipe character).
...@@ -7137,7 +7064,7 @@ fn forExpr(...@@ -7137,7 +7064,7 @@ fn forExpr(
7137 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);7064 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
71387065
7139 const capture_inst = inst: {7066 const capture_inst = inst: {
7140 const is_counter = node_tags[input] == .for_range;7067 const is_counter = tree.nodeTag(input) == .for_range;
71417068
7142 if (indexable_ref == .none) {7069 if (indexable_ref == .none) {
7143 // Special case: the main index can be used directly.7070 // Special case: the main index can be used directly.
...@@ -7184,7 +7111,7 @@ fn forExpr(...@@ -7184,7 +7111,7 @@ fn forExpr(
71847111
7185 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);7112 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
71867113
7187 astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);7114 astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node)));
7188 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });7115 try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
7189 _ = try parent_gz.add(.{7116 _ = try parent_gz.add(.{
7190 .tag = .extended,7117 .tag = .extended,
...@@ -7201,8 +7128,7 @@ fn forExpr(...@@ -7201,8 +7128,7 @@ fn forExpr(
7201 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);7128 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
7202 defer else_scope.unstack();7129 defer else_scope.unstack();
72037130
7204 const else_node = for_full.ast.else_expr;7131 if (for_full.ast.else_expr.unwrap()) |else_node| {
7205 if (else_node != 0) {
7206 const sub_scope = &else_scope.base;7132 const sub_scope = &else_scope.base;
7207 // Remove the continue block and break block so that `continue` and `break`7133 // Remove the continue block and break block so that `continue` and `break`
7208 // control flow apply to outer loops; not this one.7134 // control flow apply to outer loops; not this one.
...@@ -7270,10 +7196,6 @@ fn switchExprErrUnion(...@@ -7270,10 +7196,6 @@ fn switchExprErrUnion(
7270 const astgen = parent_gz.astgen;7196 const astgen = parent_gz.astgen;
7271 const gpa = astgen.gpa;7197 const gpa = astgen.gpa;
7272 const tree = astgen.tree;7198 const tree = astgen.tree;
7273 const node_datas = tree.nodes.items(.data);
7274 const node_tags = tree.nodes.items(.tag);
7275 const main_tokens = tree.nodes.items(.main_token);
7276 const token_tags = tree.tokens.items(.tag);
72777199
7278 const if_full = switch (node_ty) {7200 const if_full = switch (node_ty) {
7279 .@"catch" => undefined,7201 .@"catch" => undefined,
...@@ -7282,23 +7204,19 @@ fn switchExprErrUnion(...@@ -7282,23 +7204,19 @@ fn switchExprErrUnion(
72827204
7283 const switch_node, const operand_node, const error_payload = switch (node_ty) {7205 const switch_node, const operand_node, const error_payload = switch (node_ty) {
7284 .@"catch" => .{7206 .@"catch" => .{
7285 node_datas[catch_or_if_node].rhs,7207 tree.nodeData(catch_or_if_node).node_and_node[1],
7286 node_datas[catch_or_if_node].lhs,7208 tree.nodeData(catch_or_if_node).node_and_node[0],
7287 main_tokens[catch_or_if_node] + 2,7209 tree.nodeMainToken(catch_or_if_node) + 2,
7288 },7210 },
7289 .@"if" => .{7211 .@"if" => .{
7290 if_full.ast.else_expr,7212 if_full.ast.else_expr.unwrap().?,
7291 if_full.ast.cond_expr,7213 if_full.ast.cond_expr,
7292 if_full.error_token.?,7214 if_full.error_token.?,
7293 },7215 },
7294 };7216 };
7295 assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma);7217 const switch_full = tree.fullSwitch(switch_node).?;
72967218
7297 const do_err_trace = astgen.fn_block != null;7219 const do_err_trace = astgen.fn_block != null;
7298
7299 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
7300 const case_nodes = tree.extra_data[extra.start..extra.end];
7301
7302 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);7220 const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node);
7303 const block_ri: ResultInfo = if (need_rl) ri else .{7221 const block_ri: ResultInfo = if (need_rl) ri else .{
7304 .rl = switch (ri.rl) {7222 .rl = switch (ri.rl) {
...@@ -7310,7 +7228,7 @@ fn switchExprErrUnion(...@@ -7310,7 +7228,7 @@ fn switchExprErrUnion(
7310 };7228 };
73117229
7312 const payload_is_ref = switch (node_ty) {7230 const payload_is_ref = switch (node_ty) {
7313 .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk,7231 .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk,
7314 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,7232 .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty,
7315 };7233 };
73167234
...@@ -7322,9 +7240,9 @@ fn switchExprErrUnion(...@@ -7322,9 +7240,9 @@ fn switchExprErrUnion(
7322 var multi_cases_len: u32 = 0;7240 var multi_cases_len: u32 = 0;
7323 var inline_cases_len: u32 = 0;7241 var inline_cases_len: u32 = 0;
7324 var has_else = false;7242 var has_else = false;
7325 var else_node: Ast.Node.Index = 0;7243 var else_node: Ast.Node.OptionalIndex = .none;
7326 var else_src: ?Ast.TokenIndex = null;7244 var else_src: ?Ast.TokenIndex = null;
7327 for (case_nodes) |case_node| {7245 for (switch_full.ast.cases) |case_node| {
7328 const case = tree.fullSwitchCase(case_node).?;7246 const case = tree.fullSwitchCase(case_node).?;
73297247
7330 if (case.ast.values.len == 0) {7248 if (case.ast.values.len == 0) {
...@@ -7344,12 +7262,12 @@ fn switchExprErrUnion(...@@ -7344,12 +7262,12 @@ fn switchExprErrUnion(
7344 );7262 );
7345 }7263 }
7346 has_else = true;7264 has_else = true;
7347 else_node = case_node;7265 else_node = case_node.toOptional();
7348 else_src = case_src;7266 else_src = case_src;
7349 continue;7267 continue;
7350 } else if (case.ast.values.len == 1 and7268 } else if (case.ast.values.len == 1 and
7351 node_tags[case.ast.values[0]] == .identifier and7269 tree.nodeTag(case.ast.values[0]) == .identifier and
7352 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))7270 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
7353 {7271 {
7354 const case_src = case.ast.arrow_token - 1;7272 const case_src = case.ast.arrow_token - 1;
7355 return astgen.failTokNotes(7273 return astgen.failTokNotes(
...@@ -7367,11 +7285,11 @@ fn switchExprErrUnion(...@@ -7367,11 +7285,11 @@ fn switchExprErrUnion(
7367 }7285 }
73687286
7369 for (case.ast.values) |val| {7287 for (case.ast.values) |val| {
7370 if (node_tags[val] == .string_literal)7288 if (tree.nodeTag(val) == .string_literal)
7371 return astgen.failNode(val, "cannot switch on strings", .{});7289 return astgen.failNode(val, "cannot switch on strings", .{});
7372 }7290 }
73737291
7374 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {7292 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
7375 scalar_cases_len += 1;7293 scalar_cases_len += 1;
7376 } else {7294 } else {
7377 multi_cases_len += 1;7295 multi_cases_len += 1;
...@@ -7564,11 +7482,11 @@ fn switchExprErrUnion(...@@ -7564,11 +7482,11 @@ fn switchExprErrUnion(
7564 var multi_case_index: u32 = 0;7482 var multi_case_index: u32 = 0;
7565 var scalar_case_index: u32 = 0;7483 var scalar_case_index: u32 = 0;
7566 var any_uses_err_capture = false;7484 var any_uses_err_capture = false;
7567 for (case_nodes) |case_node| {7485 for (switch_full.ast.cases) |case_node| {
7568 const case = tree.fullSwitchCase(case_node).?;7486 const case = tree.fullSwitchCase(case_node).?;
75697487
7570 const is_multi_case = case.ast.values.len > 1 or7488 const is_multi_case = case.ast.values.len > 1 or
7571 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);7489 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
75727490
7573 var dbg_var_name: Zir.NullTerminatedString = .empty;7491 var dbg_var_name: Zir.NullTerminatedString = .empty;
7574 var dbg_var_inst: Zir.Inst.Ref = undefined;7492 var dbg_var_inst: Zir.Inst.Ref = undefined;
...@@ -7586,7 +7504,7 @@ fn switchExprErrUnion(...@@ -7586,7 +7504,7 @@ fn switchExprErrUnion(
7586 };7504 };
75877505
7588 const capture_token = case.payload_token orelse break :blk &err_scope.base;7506 const capture_token = case.payload_token orelse break :blk &err_scope.base;
7589 if (token_tags[capture_token] != .identifier) {7507 if (tree.tokenTag(capture_token) != .identifier) {
7590 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});7508 return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{});
7591 }7509 }
75927510
...@@ -7622,7 +7540,7 @@ fn switchExprErrUnion(...@@ -7622,7 +7540,7 @@ fn switchExprErrUnion(
7622 // items7540 // items
7623 var items_len: u32 = 0;7541 var items_len: u32 = 0;
7624 for (case.ast.values) |item_node| {7542 for (case.ast.values) |item_node| {
7625 if (node_tags[item_node] == .switch_range) continue;7543 if (tree.nodeTag(item_node) == .switch_range) continue;
7626 items_len += 1;7544 items_len += 1;
76277545
7628 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);7546 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
...@@ -7632,11 +7550,12 @@ fn switchExprErrUnion(...@@ -7632,11 +7550,12 @@ fn switchExprErrUnion(
7632 // ranges7550 // ranges
7633 var ranges_len: u32 = 0;7551 var ranges_len: u32 = 0;
7634 for (case.ast.values) |range| {7552 for (case.ast.values) |range| {
7635 if (node_tags[range] != .switch_range) continue;7553 if (tree.nodeTag(range) != .switch_range) continue;
7636 ranges_len += 1;7554 ranges_len += 1;
76377555
7638 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);7556 const first_node, const last_node = tree.nodeData(range).node_and_node;
7639 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);7557 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
7558 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
7640 try payloads.appendSlice(gpa, &[_]u32{7559 try payloads.appendSlice(gpa, &[_]u32{
7641 @intFromEnum(first), @intFromEnum(last),7560 @intFromEnum(first), @intFromEnum(last),
7642 });7561 });
...@@ -7645,7 +7564,7 @@ fn switchExprErrUnion(...@@ -7645,7 +7564,7 @@ fn switchExprErrUnion(
7645 payloads.items[header_index] = items_len;7564 payloads.items[header_index] = items_len;
7646 payloads.items[header_index + 1] = ranges_len;7565 payloads.items[header_index + 1] = ranges_len;
7647 break :blk header_index + 2;7566 break :blk header_index + 2;
7648 } else if (case_node == else_node) blk: {7567 } else if (case_node.toOptional() == else_node) blk: {
7649 payloads.items[case_table_start + 1] = header_index;7568 payloads.items[case_table_start + 1] = header_index;
7650 try payloads.resize(gpa, header_index + 1); // body_len7569 try payloads.resize(gpa, header_index + 1); // body_len
7651 break :blk header_index;7570 break :blk header_index;
...@@ -7675,7 +7594,7 @@ fn switchExprErrUnion(...@@ -7675,7 +7594,7 @@ fn switchExprErrUnion(
7675 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);7594 const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint);
7676 // check capture_scope, not err_scope to avoid false positive unused error capture7595 // check capture_scope, not err_scope to avoid false positive unused error capture
7677 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);7596 try checkUsed(parent_gz, &case_scope.base, err_scope.parent);
7678 const uses_err = err_scope.used != 0 or err_scope.discarded != 0;7597 const uses_err = err_scope.used != .none or err_scope.discarded != .none;
7679 if (uses_err) {7598 if (uses_err) {
7680 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());7599 try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef());
7681 any_uses_err_capture = true;7600 any_uses_err_capture = true;
...@@ -7775,10 +7694,6 @@ fn switchExpr(...@@ -7775,10 +7694,6 @@ fn switchExpr(
7775 const astgen = parent_gz.astgen;7694 const astgen = parent_gz.astgen;
7776 const gpa = astgen.gpa;7695 const gpa = astgen.gpa;
7777 const tree = astgen.tree;7696 const tree = astgen.tree;
7778 const node_datas = tree.nodes.items(.data);
7779 const node_tags = tree.nodes.items(.tag);
7780 const main_tokens = tree.nodes.items(.main_token);
7781 const token_tags = tree.tokens.items(.tag);
7782 const operand_node = switch_full.ast.condition;7697 const operand_node = switch_full.ast.condition;
7783 const case_nodes = switch_full.ast.cases;7698 const case_nodes = switch_full.ast.cases;
77847699
...@@ -7810,17 +7725,17 @@ fn switchExpr(...@@ -7810,17 +7725,17 @@ fn switchExpr(
7810 var multi_cases_len: u32 = 0;7725 var multi_cases_len: u32 = 0;
7811 var inline_cases_len: u32 = 0;7726 var inline_cases_len: u32 = 0;
7812 var special_prong: Zir.SpecialProng = .none;7727 var special_prong: Zir.SpecialProng = .none;
7813 var special_node: Ast.Node.Index = 0;7728 var special_node: Ast.Node.OptionalIndex = .none;
7814 var else_src: ?Ast.TokenIndex = null;7729 var else_src: ?Ast.TokenIndex = null;
7815 var underscore_src: ?Ast.TokenIndex = null;7730 var underscore_src: ?Ast.TokenIndex = null;
7816 for (case_nodes) |case_node| {7731 for (case_nodes) |case_node| {
7817 const case = tree.fullSwitchCase(case_node).?;7732 const case = tree.fullSwitchCase(case_node).?;
7818 if (case.payload_token) |payload_token| {7733 if (case.payload_token) |payload_token| {
7819 const ident = if (token_tags[payload_token] == .asterisk) blk: {7734 const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: {
7820 any_payload_is_ref = true;7735 any_payload_is_ref = true;
7821 break :blk payload_token + 1;7736 break :blk payload_token + 1;
7822 } else payload_token;7737 } else payload_token;
7823 if (token_tags[ident + 1] == .comma) {7738 if (tree.tokenTag(ident + 1) == .comma) {
7824 any_has_tag_capture = true;7739 any_has_tag_capture = true;
7825 }7740 }
78267741
...@@ -7868,13 +7783,13 @@ fn switchExpr(...@@ -7868,13 +7783,13 @@ fn switchExpr(
7868 },7783 },
7869 );7784 );
7870 }7785 }
7871 special_node = case_node;7786 special_node = case_node.toOptional();
7872 special_prong = .@"else";7787 special_prong = .@"else";
7873 else_src = case_src;7788 else_src = case_src;
7874 continue;7789 continue;
7875 } else if (case.ast.values.len == 1 and7790 } else if (case.ast.values.len == 1 and
7876 node_tags[case.ast.values[0]] == .identifier and7791 tree.nodeTag(case.ast.values[0]) == .identifier and
7877 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"))7792 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"))
7878 {7793 {
7879 const case_src = case.ast.arrow_token - 1;7794 const case_src = case.ast.arrow_token - 1;
7880 if (underscore_src) |src| {7795 if (underscore_src) |src| {
...@@ -7912,18 +7827,18 @@ fn switchExpr(...@@ -7912,18 +7827,18 @@ fn switchExpr(
7912 if (case.inline_token != null) {7827 if (case.inline_token != null) {
7913 return astgen.failTok(case_src, "cannot inline '_' prong", .{});7828 return astgen.failTok(case_src, "cannot inline '_' prong", .{});
7914 }7829 }
7915 special_node = case_node;7830 special_node = case_node.toOptional();
7916 special_prong = .under;7831 special_prong = .under;
7917 underscore_src = case_src;7832 underscore_src = case_src;
7918 continue;7833 continue;
7919 }7834 }
79207835
7921 for (case.ast.values) |val| {7836 for (case.ast.values) |val| {
7922 if (node_tags[val] == .string_literal)7837 if (tree.nodeTag(val) == .string_literal)
7923 return astgen.failNode(val, "cannot switch on strings", .{});7838 return astgen.failNode(val, "cannot switch on strings", .{});
7924 }7839 }
79257840
7926 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {7841 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) {
7927 scalar_cases_len += 1;7842 scalar_cases_len += 1;
7928 } else {7843 } else {
7929 multi_cases_len += 1;7844 multi_cases_len += 1;
...@@ -8012,7 +7927,7 @@ fn switchExpr(...@@ -8012,7 +7927,7 @@ fn switchExpr(
8012 const case = tree.fullSwitchCase(case_node).?;7927 const case = tree.fullSwitchCase(case_node).?;
80137928
8014 const is_multi_case = case.ast.values.len > 1 or7929 const is_multi_case = case.ast.values.len > 1 or
8015 (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range);7930 (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range);
80167931
8017 var dbg_var_name: Zir.NullTerminatedString = .empty;7932 var dbg_var_name: Zir.NullTerminatedString = .empty;
8018 var dbg_var_inst: Zir.Inst.Ref = undefined;7933 var dbg_var_inst: Zir.Inst.Ref = undefined;
...@@ -8026,18 +7941,15 @@ fn switchExpr(...@@ -8026,18 +7941,15 @@ fn switchExpr(
80267941
8027 const sub_scope = blk: {7942 const sub_scope = blk: {
8028 const payload_token = case.payload_token orelse break :blk &case_scope.base;7943 const payload_token = case.payload_token orelse break :blk &case_scope.base;
8029 const ident = if (token_tags[payload_token] == .asterisk)7944 const capture_is_ref = tree.tokenTag(payload_token) == .asterisk;
8030 payload_token + 17945 const ident = payload_token + @intFromBool(capture_is_ref);
8031 else
8032 payload_token;
80337946
8034 const is_ptr = ident != payload_token;7947 capture = if (capture_is_ref) .by_ref else .by_val;
8035 capture = if (is_ptr) .by_ref else .by_val;
80367948
8037 const ident_slice = tree.tokenSlice(ident);7949 const ident_slice = tree.tokenSlice(ident);
8038 var payload_sub_scope: *Scope = undefined;7950 var payload_sub_scope: *Scope = undefined;
8039 if (mem.eql(u8, ident_slice, "_")) {7951 if (mem.eql(u8, ident_slice, "_")) {
8040 if (is_ptr) {7952 if (capture_is_ref) {
8041 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});7953 return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{});
8042 }7954 }
8043 payload_sub_scope = &case_scope.base;7955 payload_sub_scope = &case_scope.base;
...@@ -8057,7 +7969,7 @@ fn switchExpr(...@@ -8057,7 +7969,7 @@ fn switchExpr(
8057 payload_sub_scope = &capture_val_scope.base;7969 payload_sub_scope = &capture_val_scope.base;
8058 }7970 }
80597971
8060 const tag_token = if (token_tags[ident + 1] == .comma)7972 const tag_token = if (tree.tokenTag(ident + 1) == .comma)
8061 ident + 27973 ident + 2
8062 else7974 else
8063 break :blk payload_sub_scope;7975 break :blk payload_sub_scope;
...@@ -8095,7 +8007,7 @@ fn switchExpr(...@@ -8095,7 +8007,7 @@ fn switchExpr(
8095 // items8007 // items
8096 var items_len: u32 = 0;8008 var items_len: u32 = 0;
8097 for (case.ast.values) |item_node| {8009 for (case.ast.values) |item_node| {
8098 if (node_tags[item_node] == .switch_range) continue;8010 if (tree.nodeTag(item_node) == .switch_range) continue;
8099 items_len += 1;8011 items_len += 1;
81008012
8101 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);8013 const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
...@@ -8105,11 +8017,12 @@ fn switchExpr(...@@ -8105,11 +8017,12 @@ fn switchExpr(
8105 // ranges8017 // ranges
8106 var ranges_len: u32 = 0;8018 var ranges_len: u32 = 0;
8107 for (case.ast.values) |range| {8019 for (case.ast.values) |range| {
8108 if (node_tags[range] != .switch_range) continue;8020 if (tree.nodeTag(range) != .switch_range) continue;
8109 ranges_len += 1;8021 ranges_len += 1;
81108022
8111 const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);8023 const first_node, const last_node = tree.nodeData(range).node_and_node;
8112 const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);8024 const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item);
8025 const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item);
8113 try payloads.appendSlice(gpa, &[_]u32{8026 try payloads.appendSlice(gpa, &[_]u32{
8114 @intFromEnum(first), @intFromEnum(last),8027 @intFromEnum(first), @intFromEnum(last),
8115 });8028 });
...@@ -8118,7 +8031,7 @@ fn switchExpr(...@@ -8118,7 +8031,7 @@ fn switchExpr(
8118 payloads.items[header_index] = items_len;8031 payloads.items[header_index] = items_len;
8119 payloads.items[header_index + 1] = ranges_len;8032 payloads.items[header_index + 1] = ranges_len;
8120 break :blk header_index + 2;8033 break :blk header_index + 2;
8121 } else if (case_node == special_node) blk: {8034 } else if (case_node.toOptional() == special_node) blk: {
8122 payloads.items[case_table_start] = header_index;8035 payloads.items[case_table_start] = header_index;
8123 try payloads.resize(gpa, header_index + 1); // body_len8036 try payloads.resize(gpa, header_index + 1); // body_len
8124 break :blk header_index;8037 break :blk header_index;
...@@ -8231,17 +8144,15 @@ fn switchExpr(...@@ -8231,17 +8144,15 @@ fn switchExpr(
8231fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {8144fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
8232 const astgen = gz.astgen;8145 const astgen = gz.astgen;
8233 const tree = astgen.tree;8146 const tree = astgen.tree;
8234 const node_datas = tree.nodes.items(.data);
8235 const node_tags = tree.nodes.items(.tag);
82368147
8237 if (astgen.fn_block == null) {8148 if (astgen.fn_block == null) {
8238 return astgen.failNode(node, "'return' outside function scope", .{});8149 return astgen.failNode(node, "'return' outside function scope", .{});
8239 }8150 }
82408151
8241 if (gz.any_defer_node != 0) {8152 if (gz.any_defer_node.unwrap()) |any_defer_node| {
8242 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{8153 return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{
8243 try astgen.errNoteNode(8154 try astgen.errNoteNode(
8244 gz.any_defer_node,8155 any_defer_node,
8245 "defer expression here",8156 "defer expression here",
8246 .{},8157 .{},
8247 ),8158 ),
...@@ -8259,8 +8170,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8259,8 +8170,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
82598170
8260 const defer_outer = &astgen.fn_block.?.base;8171 const defer_outer = &astgen.fn_block.?.base;
82618172
8262 const operand_node = node_datas[node].lhs;8173 const operand_node = tree.nodeData(node).opt_node.unwrap() orelse {
8263 if (operand_node == 0) {
8264 // Returning a void value; skip error defers.8174 // Returning a void value; skip error defers.
8265 try genDefers(gz, defer_outer, scope, .normal_only);8175 try genDefers(gz, defer_outer, scope, .normal_only);
82668176
...@@ -8269,12 +8179,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -8269,12 +8179,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
82698179
8270 _ = try gz.addUnNode(.ret_node, .void_value, node);8180 _ = try gz.addUnNode(.ret_node, .void_value, node);
8271 return Zir.Inst.Ref.unreachable_value;8181 return Zir.Inst.Ref.unreachable_value;
8272 }8182 };
82738183
8274 if (node_tags[operand_node] == .error_value) {8184 if (tree.nodeTag(operand_node) == .error_value) {
8275 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic8185 // Hot path for `return error.Foo`. This bypasses result location logic as well as logic
8276 // for detecting whether to add something to the function's inferred error set.8186 // for detecting whether to add something to the function's inferred error set.
8277 const ident_token = node_datas[operand_node].rhs;8187 const ident_token = tree.nodeData(operand_node).opt_token_and_opt_token[1].unwrap().?;
8278 const err_name_str_index = try astgen.identAsString(ident_token);8188 const err_name_str_index = try astgen.identAsString(ident_token);
8279 const defer_counts = countDefers(defer_outer, scope);8189 const defer_counts = countDefers(defer_outer, scope);
8280 if (!defer_counts.need_err_code) {8190 if (!defer_counts.need_err_code) {
...@@ -8405,9 +8315,8 @@ fn identifier(...@@ -8405,9 +8315,8 @@ fn identifier(
8405) InnerError!Zir.Inst.Ref {8315) InnerError!Zir.Inst.Ref {
8406 const astgen = gz.astgen;8316 const astgen = gz.astgen;
8407 const tree = astgen.tree;8317 const tree = astgen.tree;
8408 const main_tokens = tree.nodes.items(.main_token);
84098318
8410 const ident_token = main_tokens[ident];8319 const ident_token = tree.nodeMainToken(ident);
8411 const ident_name_raw = tree.tokenSlice(ident_token);8320 const ident_name_raw = tree.tokenSlice(ident_token);
8412 if (mem.eql(u8, ident_name_raw, "_")) {8321 if (mem.eql(u8, ident_name_raw, "_")) {
8413 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});8322 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
...@@ -8509,9 +8418,9 @@ fn localVarRef(...@@ -8509,9 +8418,9 @@ fn localVarRef(
8509 // Locals cannot shadow anything, so we do not need to look for ambiguous8418 // Locals cannot shadow anything, so we do not need to look for ambiguous
8510 // references in this case.8419 // references in this case.
8511 if (ri.rl == .discard and ri.ctx == .assignment) {8420 if (ri.rl == .discard and ri.ctx == .assignment) {
8512 local_val.discarded = ident_token;8421 local_val.discarded = .fromToken(ident_token);
8513 } else {8422 } else {
8514 local_val.used = ident_token;8423 local_val.used = .fromToken(ident_token);
8515 }8424 }
85168425
8517 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;8426 if (local_val.is_used_or_discarded) |ptr| ptr.* = true;
...@@ -8533,9 +8442,9 @@ fn localVarRef(...@@ -8533,9 +8442,9 @@ fn localVarRef(
8533 const local_ptr = s.cast(Scope.LocalPtr).?;8442 const local_ptr = s.cast(Scope.LocalPtr).?;
8534 if (local_ptr.name == name_str_index) {8443 if (local_ptr.name == name_str_index) {
8535 if (ri.rl == .discard and ri.ctx == .assignment) {8444 if (ri.rl == .discard and ri.ctx == .assignment) {
8536 local_ptr.discarded = ident_token;8445 local_ptr.discarded = .fromToken(ident_token);
8537 } else {8446 } else {
8538 local_ptr.used = ident_token;8447 local_ptr.used = .fromToken(ident_token);
8539 }8448 }
85408449
8541 // Can't close over a runtime variable8450 // Can't close over a runtime variable
...@@ -8748,8 +8657,7 @@ fn stringLiteral(...@@ -8748,8 +8657,7 @@ fn stringLiteral(
8748) InnerError!Zir.Inst.Ref {8657) InnerError!Zir.Inst.Ref {
8749 const astgen = gz.astgen;8658 const astgen = gz.astgen;
8750 const tree = astgen.tree;8659 const tree = astgen.tree;
8751 const main_tokens = tree.nodes.items(.main_token);8660 const str_lit_token = tree.nodeMainToken(node);
8752 const str_lit_token = main_tokens[node];
8753 const str = try astgen.strLitAsString(str_lit_token);8661 const str = try astgen.strLitAsString(str_lit_token);
8754 const result = try gz.add(.{8662 const result = try gz.add(.{
8755 .tag = .str,8663 .tag = .str,
...@@ -8781,8 +8689,7 @@ fn multilineStringLiteral(...@@ -8781,8 +8689,7 @@ fn multilineStringLiteral(
8781fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {8689fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
8782 const astgen = gz.astgen;8690 const astgen = gz.astgen;
8783 const tree = astgen.tree;8691 const tree = astgen.tree;
8784 const main_tokens = tree.nodes.items(.main_token);8692 const main_token = tree.nodeMainToken(node);
8785 const main_token = main_tokens[node];
8786 const slice = tree.tokenSlice(main_token);8693 const slice = tree.tokenSlice(main_token);
87878694
8788 switch (std.zig.parseCharLiteral(slice)) {8695 switch (std.zig.parseCharLiteral(slice)) {
...@@ -8799,8 +8706,7 @@ const Sign = enum { negative, positive };...@@ -8799,8 +8706,7 @@ const Sign = enum { negative, positive };
8799fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {8706fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
8800 const astgen = gz.astgen;8707 const astgen = gz.astgen;
8801 const tree = astgen.tree;8708 const tree = astgen.tree;
8802 const main_tokens = tree.nodes.items(.main_token);8709 const num_token = tree.nodeMainToken(node);
8803 const num_token = main_tokens[node];
8804 const bytes = tree.tokenSlice(num_token);8710 const bytes = tree.tokenSlice(num_token);
88058711
8806 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {8712 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
...@@ -8918,16 +8824,12 @@ fn asmExpr(...@@ -8918,16 +8824,12 @@ fn asmExpr(
8918) InnerError!Zir.Inst.Ref {8824) InnerError!Zir.Inst.Ref {
8919 const astgen = gz.astgen;8825 const astgen = gz.astgen;
8920 const tree = astgen.tree;8826 const tree = astgen.tree;
8921 const main_tokens = tree.nodes.items(.main_token);
8922 const node_datas = tree.nodes.items(.data);
8923 const node_tags = tree.nodes.items(.tag);
8924 const token_tags = tree.tokens.items(.tag);
89258827
8926 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };8828 const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString };
8927 const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) {8829 const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) {
8928 .string_literal => .{8830 .string_literal => .{
8929 .tag = .@"asm",8831 .tag = .@"asm",
8930 .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index,8832 .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index,
8931 },8833 },
8932 .multiline_string_literal => .{8834 .multiline_string_literal => .{
8933 .tag = .@"asm",8835 .tag = .@"asm",
...@@ -8962,17 +8864,17 @@ fn asmExpr(...@@ -8962,17 +8864,17 @@ fn asmExpr(
8962 var output_type_bits: u32 = 0;8864 var output_type_bits: u32 = 0;
89638865
8964 for (full.outputs, 0..) |output_node, i| {8866 for (full.outputs, 0..) |output_node, i| {
8965 const symbolic_name = main_tokens[output_node];8867 const symbolic_name = tree.nodeMainToken(output_node);
8966 const name = try astgen.identAsString(symbolic_name);8868 const name = try astgen.identAsString(symbolic_name);
8967 const constraint_token = symbolic_name + 2;8869 const constraint_token = symbolic_name + 2;
8968 const constraint = (try astgen.strLitAsString(constraint_token)).index;8870 const constraint = (try astgen.strLitAsString(constraint_token)).index;
8969 const has_arrow = token_tags[symbolic_name + 4] == .arrow;8871 const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow;
8970 if (has_arrow) {8872 if (has_arrow) {
8971 if (output_type_bits != 0) {8873 if (output_type_bits != 0) {
8972 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});8874 return astgen.failNode(output_node, "inline assembly allows up to one output value", .{});
8973 }8875 }
8974 output_type_bits |= @as(u32, 1) << @intCast(i);8876 output_type_bits |= @as(u32, 1) << @intCast(i);
8975 const out_type_node = node_datas[output_node].lhs;8877 const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?;
8976 const out_type_inst = try typeExpr(gz, scope, out_type_node);8878 const out_type_inst = try typeExpr(gz, scope, out_type_node);
8977 outputs[i] = .{8879 outputs[i] = .{
8978 .name = name,8880 .name = name,
...@@ -8999,11 +8901,11 @@ fn asmExpr(...@@ -8999,11 +8901,11 @@ fn asmExpr(
8999 const inputs = inputs_buffer[0..full.inputs.len];8901 const inputs = inputs_buffer[0..full.inputs.len];
90008902
9001 for (full.inputs, 0..) |input_node, i| {8903 for (full.inputs, 0..) |input_node, i| {
9002 const symbolic_name = main_tokens[input_node];8904 const symbolic_name = tree.nodeMainToken(input_node);
9003 const name = try astgen.identAsString(symbolic_name);8905 const name = try astgen.identAsString(symbolic_name);
9004 const constraint_token = symbolic_name + 2;8906 const constraint_token = symbolic_name + 2;
9005 const constraint = (try astgen.strLitAsString(constraint_token)).index;8907 const constraint = (try astgen.strLitAsString(constraint_token)).index;
9006 const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs);8908 const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]);
9007 inputs[i] = .{8909 inputs[i] = .{
9008 .name = name,8910 .name = name,
9009 .constraint = constraint,8911 .constraint = constraint,
...@@ -9024,10 +8926,10 @@ fn asmExpr(...@@ -9024,10 +8926,10 @@ fn asmExpr(
9024 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);8926 clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index);
9025 clobber_i += 1;8927 clobber_i += 1;
9026 tok_i += 1;8928 tok_i += 1;
9027 switch (token_tags[tok_i]) {8929 switch (tree.tokenTag(tok_i)) {
9028 .r_paren => break :clobbers,8930 .r_paren => break :clobbers,
9029 .comma => {8931 .comma => {
9030 if (token_tags[tok_i + 1] == .r_paren) {8932 if (tree.tokenTag(tok_i + 1) == .r_paren) {
9031 break :clobbers;8933 break :clobbers;
9032 } else {8934 } else {
9033 continue;8935 continue;
...@@ -9119,9 +9021,6 @@ fn ptrCast(...@@ -9119,9 +9021,6 @@ fn ptrCast(
9119) InnerError!Zir.Inst.Ref {9021) InnerError!Zir.Inst.Ref {
9120 const astgen = gz.astgen;9022 const astgen = gz.astgen;
9121 const tree = astgen.tree;9023 const tree = astgen.tree;
9122 const main_tokens = tree.nodes.items(.main_token);
9123 const node_datas = tree.nodes.items(.data);
9124 const node_tags = tree.nodes.items(.tag);
91259024
9126 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;9025 const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?;
9127 var flags: Zir.Inst.FullPtrCastFlags = .{};9026 var flags: Zir.Inst.FullPtrCastFlags = .{};
...@@ -9130,11 +9029,11 @@ fn ptrCast(...@@ -9130,11 +9029,11 @@ fn ptrCast(
9130 // to handle `builtin_call_two`.9029 // to handle `builtin_call_two`.
9131 var node = root_node;9030 var node = root_node;
9132 while (true) {9031 while (true) {
9133 switch (node_tags[node]) {9032 switch (tree.nodeTag(node)) {
9134 .builtin_call_two, .builtin_call_two_comma => {},9033 .builtin_call_two, .builtin_call_two_comma => {},
9135 .grouped_expression => {9034 .grouped_expression => {
9136 // Handle the chaining even with redundant parentheses9035 // Handle the chaining even with redundant parentheses
9137 node = node_datas[node].lhs;9036 node = tree.nodeData(node).node_and_token[0];
9138 continue;9037 continue;
9139 },9038 },
9140 else => break,9039 else => break,
...@@ -9144,7 +9043,9 @@ fn ptrCast(...@@ -9144,7 +9043,9 @@ fn ptrCast(
9144 const args = tree.builtinCallParams(&buf, node).?;9043 const args = tree.builtinCallParams(&buf, node).?;
9145 std.debug.assert(args.len <= 2);9044 std.debug.assert(args.len <= 2);
91469045
9147 const builtin_token = main_tokens[node];9046 if (args.len == 0) break; // 0 args
9047
9048 const builtin_token = tree.nodeMainToken(node);
9148 const builtin_name = tree.tokenSlice(builtin_token);9049 const builtin_name = tree.tokenSlice(builtin_token);
9149 const info = BuiltinFn.list.get(builtin_name) orelse break;9050 const info = BuiltinFn.list.get(builtin_name) orelse break;
9150 if (args.len == 1) {9051 if (args.len == 1) {
...@@ -9344,9 +9245,8 @@ fn builtinCall(...@@ -9344,9 +9245,8 @@ fn builtinCall(
9344) InnerError!Zir.Inst.Ref {9245) InnerError!Zir.Inst.Ref {
9345 const astgen = gz.astgen;9246 const astgen = gz.astgen;
9346 const tree = astgen.tree;9247 const tree = astgen.tree;
9347 const main_tokens = tree.nodes.items(.main_token);
93489248
9349 const builtin_token = main_tokens[node];9249 const builtin_token = tree.nodeMainToken(node);
9350 const builtin_name = tree.tokenSlice(builtin_token);9250 const builtin_name = tree.tokenSlice(builtin_token);
93519251
9352 // We handle the different builtins manually because they have different semantics depending9252 // We handle the different builtins manually because they have different semantics depending
...@@ -9387,14 +9287,13 @@ fn builtinCall(...@@ -9387,14 +9287,13 @@ fn builtinCall(
9387 return rvalue(gz, ri, .void_value, node);9287 return rvalue(gz, ri, .void_value, node);
9388 },9288 },
9389 .import => {9289 .import => {
9390 const node_tags = tree.nodes.items(.tag);
9391 const operand_node = params[0];9290 const operand_node = params[0];
93929291
9393 if (node_tags[operand_node] != .string_literal) {9292 if (tree.nodeTag(operand_node) != .string_literal) {
9394 // Spec reference: https://github.com/ziglang/zig/issues/22069293 // Spec reference: https://github.com/ziglang/zig/issues/2206
9395 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});9294 return astgen.failNode(operand_node, "@import operand must be a string literal", .{});
9396 }9295 }
9397 const str_lit_token = main_tokens[operand_node];9296 const str_lit_token = tree.nodeMainToken(operand_node);
9398 const str = try astgen.strLitAsString(str_lit_token);9297 const str = try astgen.strLitAsString(str_lit_token);
9399 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];9298 const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len];
9400 if (mem.indexOfScalar(u8, str_slice, 0) != null) {9299 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
...@@ -9505,8 +9404,7 @@ fn builtinCall(...@@ -9505,8 +9404,7 @@ fn builtinCall(
9505 std.mem.asBytes(&astgen.source_column),9404 std.mem.asBytes(&astgen.source_column),
9506 );9405 );
95079406
9508 const token_starts = tree.tokens.items(.start);9407 const node_start = tree.tokenStart(tree.firstToken(node));
9509 const node_start = token_starts[tree.firstToken(node)];
9510 astgen.advanceSourceCursor(node_start);9408 astgen.advanceSourceCursor(node_start);
9511 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{9409 const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{
9512 .node = gz.nodeIndexToRelative(node),9410 .node = gz.nodeIndexToRelative(node),
...@@ -9786,7 +9684,7 @@ fn builtinCall(...@@ -9786,7 +9684,7 @@ fn builtinCall(
9786 .callee = callee,9684 .callee = callee,
9787 .args = args,9685 .args = args,
9788 .flags = .{9686 .flags = .{
9789 .is_nosuspend = gz.nosuspend_node != 0,9687 .is_nosuspend = gz.nosuspend_node != .none,
9790 .ensure_result_used = false,9688 .ensure_result_used = false,
9791 },9689 },
9792 });9690 });
...@@ -10011,13 +9909,11 @@ fn negation(...@@ -10011,13 +9909,11 @@ fn negation(
10011) InnerError!Zir.Inst.Ref {9909) InnerError!Zir.Inst.Ref {
10012 const astgen = gz.astgen;9910 const astgen = gz.astgen;
10013 const tree = astgen.tree;9911 const tree = astgen.tree;
10014 const node_tags = tree.nodes.items(.tag);
10015 const node_datas = tree.nodes.items(.data);
100169912
10017 // Check for float literal as the sub-expression because we want to preserve9913 // Check for float literal as the sub-expression because we want to preserve
10018 // its negativity rather than having it go through comptime subtraction.9914 // its negativity rather than having it go through comptime subtraction.
10019 const operand_node = node_datas[node].lhs;9915 const operand_node = tree.nodeData(node).node;
10020 if (node_tags[operand_node] == .number_literal) {9916 if (tree.nodeTag(operand_node) == .number_literal) {
10021 return numberLiteral(gz, ri, operand_node, node, .negative);9917 return numberLiteral(gz, ri, operand_node, node, .negative);
10022 }9918 }
100239919
...@@ -10133,7 +10029,7 @@ fn shiftOp(...@@ -10133,7 +10029,7 @@ fn shiftOp(
10133) InnerError!Zir.Inst.Ref {10029) InnerError!Zir.Inst.Ref {
10134 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);10030 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
1013510031
10136 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {10032 const cursor = switch (gz.astgen.tree.nodeTag(node)) {
10137 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),10033 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
10138 else => undefined,10034 else => undefined,
10139 };10035 };
...@@ -10141,7 +10037,7 @@ fn shiftOp(...@@ -10141,7 +10037,7 @@ fn shiftOp(
10141 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);10037 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
10142 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);10038 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
1014310039
10144 switch (gz.astgen.tree.nodes.items(.tag)[node]) {10040 switch (gz.astgen.tree.nodeTag(node)) {
10145 .shl, .shr => try emitDbgStmt(gz, cursor),10041 .shl, .shr => try emitDbgStmt(gz, cursor),
10146 else => undefined,10042 else => undefined,
10147 }10043 }
...@@ -10217,14 +10113,14 @@ fn callExpr(...@@ -10217,14 +10113,14 @@ fn callExpr(
10217 if (call.async_token != null) {10113 if (call.async_token != null) {
10218 break :blk .async_kw;10114 break :blk .async_kw;
10219 }10115 }
10220 if (gz.nosuspend_node != 0) {10116 if (gz.nosuspend_node != .none) {
10221 break :blk .no_async;10117 break :blk .no_async;
10222 }10118 }
10223 break :blk .auto;10119 break :blk .auto;
10224 };10120 };
1022510121
10226 {10122 {
10227 astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]);10123 astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen));
10228 const line = astgen.source_line - gz.decl_line;10124 const line = astgen.source_line - gz.decl_line;
10229 const column = astgen.source_column;10125 const column = astgen.source_column;
10230 // Sema expects a dbg_stmt immediately before call,10126 // Sema expects a dbg_stmt immediately before call,
...@@ -10235,7 +10131,6 @@ fn callExpr(...@@ -10235,7 +10131,6 @@ fn callExpr(
10235 .direct => |obj| assert(obj != .none),10131 .direct => |obj| assert(obj != .none),
10236 .field => |field| assert(field.obj_ptr != .none),10132 .field => |field| assert(field.obj_ptr != .none),
10237 }10133 }
10238 assert(node != 0);
1023910134
10240 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);10135 const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
10241 const call_inst = call_index.toRef();10136 const call_inst = call_index.toRef();
...@@ -10346,14 +10241,10 @@ fn calleeExpr(...@@ -10346,14 +10241,10 @@ fn calleeExpr(
10346 const astgen = gz.astgen;10241 const astgen = gz.astgen;
10347 const tree = astgen.tree;10242 const tree = astgen.tree;
1034810243
10349 const tag = tree.nodes.items(.tag)[node];10244 const tag = tree.nodeTag(node);
10350 switch (tag) {10245 switch (tag) {
10351 .field_access => {10246 .field_access => {
10352 const main_tokens = tree.nodes.items(.main_token);10247 const object_node, const field_ident = tree.nodeData(node).node_and_token;
10353 const node_datas = tree.nodes.items(.data);
10354 const object_node = node_datas[node].lhs;
10355 const dot_token = main_tokens[node];
10356 const field_ident = dot_token + 1;
10357 const str_index = try astgen.identAsString(field_ident);10248 const str_index = try astgen.identAsString(field_ident);
10358 // Capture the object by reference so we can promote it to an10249 // Capture the object by reference so we can promote it to an
10359 // address in Sema if needed.10250 // address in Sema if needed.
...@@ -10378,7 +10269,7 @@ fn calleeExpr(...@@ -10378,7 +10269,7 @@ fn calleeExpr(
10378 // Decl literal call syntax, e.g.10269 // Decl literal call syntax, e.g.
10379 // `const foo: T = .init();`10270 // `const foo: T = .init();`
10380 // Look up `init` in `T`, but don't try and coerce it.10271 // Look up `init` in `T`, but don't try and coerce it.
10381 const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]);10272 const str_index = try astgen.identAsString(tree.nodeMainToken(node));
10382 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{10273 const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{
10383 .lhs = res_ty,10274 .lhs = res_ty,
10384 .field_name_start = str_index,10275 .field_name_start = str_index,
...@@ -10450,12 +10341,9 @@ comptime {...@@ -10450,12 +10341,9 @@ comptime {
10450}10341}
1045110342
10452fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {10343fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10453 const node_tags = tree.nodes.items(.tag);10344 switch (tree.nodeTag(node)) {
10454 const main_tokens = tree.nodes.items(.main_token);
10455
10456 switch (node_tags[node]) {
10457 .number_literal => {10345 .number_literal => {
10458 const ident = main_tokens[node];10346 const ident = tree.nodeMainToken(node);
10459 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {10347 return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) {
10460 .int => |number| switch (number) {10348 .int => |number| switch (number) {
10461 0 => true,10349 0 => true,
...@@ -10469,12 +10357,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {...@@ -10469,12 +10357,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool {
10469}10357}
1047010358
10471fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {10359fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool {
10472 const node_tags = tree.nodes.items(.tag);
10473 const node_datas = tree.nodes.items(.data);
10474
10475 var node = start_node;10360 var node = start_node;
10476 while (true) {10361 while (true) {
10477 switch (node_tags[node]) {10362 switch (tree.nodeTag(node)) {
10478 // These don't have the opportunity to call any runtime functions.10363 // These don't have the opportunity to call any runtime functions.
10479 .error_value,10364 .error_value,
10480 .identifier,10365 .identifier,
...@@ -10482,11 +10367,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool...@@ -10482,11 +10367,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
10482 => return false,10367 => return false,
1048310368
10484 // Forward the question to the LHS sub-expression.10369 // Forward the question to the LHS sub-expression.
10485 .grouped_expression,
10486 .@"try",10370 .@"try",
10487 .@"nosuspend",10371 .@"nosuspend",
10372 => node = tree.nodeData(node).node,
10373 .grouped_expression,
10488 .unwrap_optional,10374 .unwrap_optional,
10489 => node = node_datas[node].lhs,10375 => node = tree.nodeData(node).node_and_token[0],
1049010376
10491 // Anything that does not eval to an error is guaranteed to pop any10377 // Anything that does not eval to an error is guaranteed to pop any
10492 // additions to the error trace, so it effectively does not append.10378 // additions to the error trace, so it effectively does not append.
...@@ -10496,14 +10382,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool...@@ -10496,14 +10382,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool
10496}10382}
1049710383
10498fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {10384fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError {
10499 const node_tags = tree.nodes.items(.tag);
10500 const node_datas = tree.nodes.items(.data);
10501 const main_tokens = tree.nodes.items(.main_token);
10502 const token_tags = tree.tokens.items(.tag);
10503
10504 var node = start_node;10385 var node = start_node;
10505 while (true) {10386 while (true) {
10506 switch (node_tags[node]) {10387 switch (tree.nodeTag(node)) {
10507 .root,10388 .root,
10508 .@"usingnamespace",10389 .@"usingnamespace",
10509 .test_decl,10390 .test_decl,
...@@ -10666,13 +10547,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10666,13 +10547,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10666 => return .never,10547 => return .never,
1066710548
10668 // Forward the question to the LHS sub-expression.10549 // Forward the question to the LHS sub-expression.
10669 .grouped_expression,
10670 .@"try",10550 .@"try",
10671 .@"await",10551 .@"await",
10672 .@"comptime",10552 .@"comptime",
10673 .@"nosuspend",10553 .@"nosuspend",
10554 => node = tree.nodeData(node).node,
10555 .grouped_expression,
10674 .unwrap_optional,10556 .unwrap_optional,
10675 => node = node_datas[node].lhs,10557 => node = tree.nodeData(node).node_and_token[0],
1067610558
10677 // LHS sub-expression may still be an error under the outer optional or error union10559 // LHS sub-expression may still be an error under the outer optional or error union
10678 .@"catch",10560 .@"catch",
...@@ -10684,8 +10566,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10684,8 +10566,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10684 .block,10566 .block,
10685 .block_semicolon,10567 .block_semicolon,
10686 => {10568 => {
10687 const lbrace = main_tokens[node];10569 const lbrace = tree.nodeMainToken(node);
10688 if (token_tags[lbrace - 1] == .colon) {10570 if (tree.tokenTag(lbrace - 1) == .colon) {
10689 // Labeled blocks may need a memory location to forward10571 // Labeled blocks may need a memory location to forward
10690 // to their break statements.10572 // to their break statements.
10691 return .maybe;10573 return .maybe;
...@@ -10699,7 +10581,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10699,7 +10581,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10699 .builtin_call_two,10581 .builtin_call_two,
10700 .builtin_call_two_comma,10582 .builtin_call_two_comma,
10701 => {10583 => {
10702 const builtin_token = main_tokens[node];10584 const builtin_token = tree.nodeMainToken(node);
10703 const builtin_name = tree.tokenSlice(builtin_token);10585 const builtin_name = tree.tokenSlice(builtin_token);
10704 // If the builtin is an invalid name, we don't cause an error here; instead10586 // If the builtin is an invalid name, we don't cause an error here; instead
10705 // let it pass, and the error will be "invalid builtin function" later.10587 // let it pass, and the error will be "invalid builtin function" later.
...@@ -10713,12 +10595,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev...@@ -10713,12 +10595,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
10713/// Returns `true` if it is known the type expression has more than one possible value;10595/// Returns `true` if it is known the type expression has more than one possible value;
10714/// `false` otherwise.10596/// `false` otherwise.
10715fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {10597fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool {
10716 const node_tags = tree.nodes.items(.tag);
10717 const node_datas = tree.nodes.items(.data);
10718
10719 var node = start_node;10598 var node = start_node;
10720 while (true) {10599 while (true) {
10721 switch (node_tags[node]) {10600 switch (tree.nodeTag(node)) {
10722 .root,10601 .root,
10723 .@"usingnamespace",10602 .@"usingnamespace",
10724 .test_decl,10603 .test_decl,
...@@ -10881,13 +10760,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10881,13 +10760,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10881 => return false,10760 => return false,
1088210761
10883 // Forward the question to the LHS sub-expression.10762 // Forward the question to the LHS sub-expression.
10884 .grouped_expression,
10885 .@"try",10763 .@"try",
10886 .@"await",10764 .@"await",
10887 .@"comptime",10765 .@"comptime",
10888 .@"nosuspend",10766 .@"nosuspend",
10767 => node = tree.nodeData(node).node,
10768 .grouped_expression,
10889 .unwrap_optional,10769 .unwrap_optional,
10890 => node = node_datas[node].lhs,10770 => node = tree.nodeData(node).node_and_token[0],
1089110771
10892 .ptr_type_aligned,10772 .ptr_type_aligned,
10893 .ptr_type_sentinel,10773 .ptr_type_sentinel,
...@@ -10899,8 +10779,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10899,8 +10779,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10899 => return true,10779 => return true,
1090010780
10901 .identifier => {10781 .identifier => {
10902 const main_tokens = tree.nodes.items(.main_token);10782 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
10903 const ident_bytes = tree.tokenSlice(main_tokens[node]);
10904 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {10783 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
10905 .anyerror_type,10784 .anyerror_type,
10906 .anyframe_type,10785 .anyframe_type,
...@@ -10960,12 +10839,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In...@@ -10960,12 +10839,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
10960/// Returns `true` if it is known the expression is a type that cannot be used at runtime;10839/// Returns `true` if it is known the expression is a type that cannot be used at runtime;
10961/// `false` otherwise.10840/// `false` otherwise.
10962fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {10841fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
10963 const node_tags = tree.nodes.items(.tag);
10964 const node_datas = tree.nodes.items(.data);
10965
10966 var node = start_node;10842 var node = start_node;
10967 while (true) {10843 while (true) {
10968 switch (node_tags[node]) {10844 switch (tree.nodeTag(node)) {
10969 .root,10845 .root,
10970 .@"usingnamespace",10846 .@"usingnamespace",
10971 .test_decl,10847 .test_decl,
...@@ -11137,17 +11013,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11137,17 +11013,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
11137 => return true,11013 => return true,
1113811014
11139 // Forward the question to the LHS sub-expression.11015 // Forward the question to the LHS sub-expression.
11140 .grouped_expression,
11141 .@"try",11016 .@"try",
11142 .@"await",11017 .@"await",
11143 .@"comptime",11018 .@"comptime",
11144 .@"nosuspend",11019 .@"nosuspend",
11020 => node = tree.nodeData(node).node,
11021 .grouped_expression,
11145 .unwrap_optional,11022 .unwrap_optional,
11146 => node = node_datas[node].lhs,11023 => node = tree.nodeData(node).node_and_token[0],
1114711024
11148 .identifier => {11025 .identifier => {
11149 const main_tokens = tree.nodes.items(.main_token);11026 const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node));
11150 const ident_bytes = tree.tokenSlice(main_tokens[node]);
11151 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {11027 if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) {
11152 .anyerror_type,11028 .anyerror_type,
11153 .anyframe_type,11029 .anyframe_type,
...@@ -11206,8 +11082,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {...@@ -11206,8 +11082,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
1120611082
11207/// Returns `true` if the node uses `gz.anon_name_strategy`.11083/// Returns `true` if the node uses `gz.anon_name_strategy`.
11208fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {11084fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11209 const node_tags = tree.nodes.items(.tag);11085 switch (tree.nodeTag(node)) {
11210 switch (node_tags[node]) {
11211 .container_decl,11086 .container_decl,
11212 .container_decl_trailing,11087 .container_decl_trailing,
11213 .container_decl_two,11088 .container_decl_two,
...@@ -11222,7 +11097,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {...@@ -11222,7 +11097,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool {
11222 .tagged_union_enum_tag_trailing,11097 .tagged_union_enum_tag_trailing,
11223 => return true,11098 => return true,
11224 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {11099 .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => {
11225 const builtin_token = tree.nodes.items(.main_token)[node];11100 const builtin_token = tree.nodeMainToken(node);
11226 const builtin_name = tree.tokenSlice(builtin_token);11101 const builtin_name = tree.tokenSlice(builtin_token);
11227 return std.mem.eql(u8, builtin_name, "@Type");11102 return std.mem.eql(u8, builtin_name, "@Type");
11228 },11103 },
...@@ -11455,8 +11330,7 @@ fn rvalueInner(...@@ -11455,8 +11330,7 @@ fn rvalueInner(
11455/// See also `appendIdentStr` and `parseStrLit`.11330/// See also `appendIdentStr` and `parseStrLit`.
11456fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {11331fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 {
11457 const tree = astgen.tree;11332 const tree = astgen.tree;
11458 const token_tags = tree.tokens.items(.tag);11333 assert(tree.tokenTag(token) == .identifier);
11459 assert(token_tags[token] == .identifier);
11460 const ident_name = tree.tokenSlice(token);11334 const ident_name = tree.tokenSlice(token);
11461 if (!mem.startsWith(u8, ident_name, "@")) {11335 if (!mem.startsWith(u8, ident_name, "@")) {
11462 return ident_name;11336 return ident_name;
...@@ -11482,8 +11356,7 @@ fn appendIdentStr(...@@ -11482,8 +11356,7 @@ fn appendIdentStr(
11482 buf: *ArrayListUnmanaged(u8),11356 buf: *ArrayListUnmanaged(u8),
11483) InnerError!void {11357) InnerError!void {
11484 const tree = astgen.tree;11358 const tree = astgen.tree;
11485 const token_tags = tree.tokens.items(.tag);11359 assert(tree.tokenTag(token) == .identifier);
11486 assert(token_tags[token] == .identifier);
11487 const ident_name = tree.tokenSlice(token);11360 const ident_name = tree.tokenSlice(token);
11488 if (!mem.startsWith(u8, ident_name, "@")) {11361 if (!mem.startsWith(u8, ident_name, "@")) {
11489 return buf.appendSlice(astgen.gpa, ident_name);11362 return buf.appendSlice(astgen.gpa, ident_name);
...@@ -11572,8 +11445,8 @@ fn appendErrorNodeNotes(...@@ -11572,8 +11445,8 @@ fn appendErrorNodeNotes(
11572 } else 0;11445 } else 0;
11573 try astgen.compile_errors.append(astgen.gpa, .{11446 try astgen.compile_errors.append(astgen.gpa, .{
11574 .msg = msg,11447 .msg = msg,
11575 .node = node,11448 .node = node.toOptional(),
11576 .token = 0,11449 .token = .none,
11577 .byte_offset = 0,11450 .byte_offset = 0,
11578 .notes = notes_index,11451 .notes = notes_index,
11579 });11452 });
...@@ -11664,8 +11537,8 @@ fn appendErrorTokNotesOff(...@@ -11664,8 +11537,8 @@ fn appendErrorTokNotesOff(
11664 } else 0;11537 } else 0;
11665 try astgen.compile_errors.append(gpa, .{11538 try astgen.compile_errors.append(gpa, .{
11666 .msg = msg,11539 .msg = msg,
11667 .node = 0,11540 .node = .none,
11668 .token = token,11541 .token = .fromToken(token),
11669 .byte_offset = byte_offset,11542 .byte_offset = byte_offset,
11670 .notes = notes_index,11543 .notes = notes_index,
11671 });11544 });
...@@ -11693,8 +11566,8 @@ fn errNoteTokOff(...@@ -11693,8 +11566,8 @@ fn errNoteTokOff(
11693 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);11566 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
11694 return astgen.addExtra(Zir.Inst.CompileErrors.Item{11567 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
11695 .msg = msg,11568 .msg = msg,
11696 .node = 0,11569 .node = .none,
11697 .token = token,11570 .token = .fromToken(token),
11698 .byte_offset = byte_offset,11571 .byte_offset = byte_offset,
11699 .notes = 0,11572 .notes = 0,
11700 });11573 });
...@@ -11712,8 +11585,8 @@ fn errNoteNode(...@@ -11712,8 +11585,8 @@ fn errNoteNode(
11712 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);11585 try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
11713 return astgen.addExtra(Zir.Inst.CompileErrors.Item{11586 return astgen.addExtra(Zir.Inst.CompileErrors.Item{
11714 .msg = msg,11587 .msg = msg,
11715 .node = node,11588 .node = node.toOptional(),
11716 .token = 0,11589 .token = .none,
11717 .byte_offset = 0,11590 .byte_offset = 0,
11718 .notes = 0,11591 .notes = 0,
11719 });11592 });
...@@ -11779,10 +11652,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {...@@ -11779,10 +11652,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice {
1177911652
11780fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {11653fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice {
11781 const tree = astgen.tree;11654 const tree = astgen.tree;
11782 const node_datas = tree.nodes.items(.data);
1178311655
11784 const start = node_datas[node].lhs;11656 const start, const end = tree.nodeData(node).token_and_token;
11785 const end = node_datas[node].rhs;
1178611657
11787 const gpa = astgen.gpa;11658 const gpa = astgen.gpa;
11788 const string_bytes = &astgen.string_bytes;11659 const string_bytes = &astgen.string_bytes;
...@@ -11877,11 +11748,11 @@ const Scope = struct {...@@ -11877,11 +11748,11 @@ const Scope = struct {
11877 /// Source location of the corresponding variable declaration.11748 /// Source location of the corresponding variable declaration.
11878 token_src: Ast.TokenIndex,11749 token_src: Ast.TokenIndex,
11879 /// Track the first identifier where it is referenced.11750 /// Track the first identifier where it is referenced.
11880 /// 0 means never referenced.11751 /// .none means never referenced.
11881 used: Ast.TokenIndex = 0,11752 used: Ast.OptionalTokenIndex = .none,
11882 /// Track the identifier where it is discarded, like this `_ = foo;`.11753 /// Track the identifier where it is discarded, like this `_ = foo;`.
11883 /// 0 means never discarded.11754 /// .none means never discarded.
11884 discarded: Ast.TokenIndex = 0,11755 discarded: Ast.OptionalTokenIndex = .none,
11885 is_used_or_discarded: ?*bool = null,11756 is_used_or_discarded: ?*bool = null,
11886 /// String table index.11757 /// String table index.
11887 name: Zir.NullTerminatedString,11758 name: Zir.NullTerminatedString,
...@@ -11901,11 +11772,11 @@ const Scope = struct {...@@ -11901,11 +11772,11 @@ const Scope = struct {
11901 /// Source location of the corresponding variable declaration.11772 /// Source location of the corresponding variable declaration.
11902 token_src: Ast.TokenIndex,11773 token_src: Ast.TokenIndex,
11903 /// Track the first identifier where it is referenced.11774 /// Track the first identifier where it is referenced.
11904 /// 0 means never referenced.11775 /// .none means never referenced.
11905 used: Ast.TokenIndex = 0,11776 used: Ast.OptionalTokenIndex = .none,
11906 /// Track the identifier where it is discarded, like this `_ = foo;`.11777 /// Track the identifier where it is discarded, like this `_ = foo;`.
11907 /// 0 means never discarded.11778 /// .none means never discarded.
11908 discarded: Ast.TokenIndex = 0,11779 discarded: Ast.OptionalTokenIndex = .none,
11909 /// Whether this value is used as an lvalue after initialization.11780 /// Whether this value is used as an lvalue after initialization.
11910 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.11781 /// If not, we know it can be `const`, so will emit a compile error if it is `var`.
11911 used_as_lvalue: bool = false,11782 used_as_lvalue: bool = false,
...@@ -12000,12 +11871,12 @@ const GenZir = struct {...@@ -12000,12 +11871,12 @@ const GenZir = struct {
12000 break_result_info: AstGen.ResultInfo = undefined,11871 break_result_info: AstGen.ResultInfo = undefined,
12001 continue_result_info: AstGen.ResultInfo = undefined,11872 continue_result_info: AstGen.ResultInfo = undefined,
1200211873
12003 suspend_node: Ast.Node.Index = 0,11874 suspend_node: Ast.Node.OptionalIndex = .none,
12004 nosuspend_node: Ast.Node.Index = 0,11875 nosuspend_node: Ast.Node.OptionalIndex = .none,
12005 /// Set if this GenZir is a defer.11876 /// Set if this GenZir is a defer.
12006 cur_defer_node: Ast.Node.Index = 0,11877 cur_defer_node: Ast.Node.OptionalIndex = .none,
12007 // Set if this GenZir is a defer or it is inside a defer.11878 // Set if this GenZir is a defer or it is inside a defer.
12008 any_defer_node: Ast.Node.Index = 0,11879 any_defer_node: Ast.Node.OptionalIndex = .none,
1200911880
12010 const unstacked_top = std.math.maxInt(usize);11881 const unstacked_top = std.math.maxInt(usize);
12011 /// Call unstack before adding any new instructions to containing GenZir.11882 /// Call unstack before adding any new instructions to containing GenZir.
...@@ -12086,12 +11957,12 @@ const GenZir = struct {...@@ -12086,12 +11957,12 @@ const GenZir = struct {
12086 return false;11957 return false;
12087 }11958 }
1208811959
12089 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 {11960 fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset {
12090 return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index));11961 return gz.decl_node_index.toOffset(node_index);
12091 }11962 }
1209211963
12093 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 {11964 fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset {
12094 return token - gz.srcToken();11965 return .init(gz.srcToken(), token);
12095 }11966 }
1209611967
12097 fn srcToken(gz: GenZir) Ast.TokenIndex {11968 fn srcToken(gz: GenZir) Ast.TokenIndex {
...@@ -12244,7 +12115,7 @@ const GenZir = struct {...@@ -12244,7 +12115,7 @@ const GenZir = struct {
12244 proto_hash: std.zig.SrcHash,12115 proto_hash: std.zig.SrcHash,
12245 },12116 },
12246 ) !Zir.Inst.Ref {12117 ) !Zir.Inst.Ref {
12247 assert(args.src_node != 0);12118 assert(args.src_node != .root);
12248 const astgen = gz.astgen;12119 const astgen = gz.astgen;
12249 const gpa = astgen.gpa;12120 const gpa = astgen.gpa;
12250 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;12121 const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref;
...@@ -12276,13 +12147,13 @@ const GenZir = struct {...@@ -12276,13 +12147,13 @@ const GenZir = struct {
12276 var src_locs_and_hash_buffer: [7]u32 = undefined;12147 var src_locs_and_hash_buffer: [7]u32 = undefined;
12277 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {12148 const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: {
12278 const tree = astgen.tree;12149 const tree = astgen.tree;
12279 const node_tags = tree.nodes.items(.tag);
12280 const node_datas = tree.nodes.items(.data);
12281 const token_starts = tree.tokens.items(.start);
12282 const fn_decl = args.src_node;12150 const fn_decl = args.src_node;
12283 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);12151 const block = switch (tree.nodeTag(fn_decl)) {
12284 const block = node_datas[fn_decl].rhs;12152 .fn_decl => tree.nodeData(fn_decl).node_and_node[1],
12285 const rbrace_start = token_starts[tree.lastToken(block)];12153 .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1],
12154 else => unreachable,
12155 };
12156 const rbrace_start = tree.tokenStart(tree.lastToken(block));
12286 astgen.advanceSourceCursor(rbrace_start);12157 astgen.advanceSourceCursor(rbrace_start);
12287 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);12158 const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line);
12288 const rbrace_column: u32 = @intCast(astgen.source_column);12159 const rbrace_column: u32 = @intCast(astgen.source_column);
...@@ -12689,7 +12560,7 @@ const GenZir = struct {...@@ -12689,7 +12560,7 @@ const GenZir = struct {
12689 .data = .{ .extended = .{12560 .data = .{ .extended = .{
12690 .opcode = opcode,12561 .opcode = opcode,
12691 .small = small,12562 .small = small,
12692 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),12563 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
12693 } },12564 } },
12694 });12565 });
12695 gz.instructions.appendAssumeCapacity(new_index);12566 gz.instructions.appendAssumeCapacity(new_index);
...@@ -12878,9 +12749,9 @@ const GenZir = struct {...@@ -12878,9 +12749,9 @@ const GenZir = struct {
12878 .operand = operand,12749 .operand = operand,
12879 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{12750 .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{
12880 .operand_src_node = if (operand_src_node) |src_node|12751 .operand_src_node = if (operand_src_node) |src_node|
12881 gz.nodeIndexToRelative(src_node)12752 gz.nodeIndexToRelative(src_node).toOptional()
12882 else12753 else
12883 Zir.Inst.Break.no_src_node,12754 .none,
12884 .block_inst = block_inst,12755 .block_inst = block_inst,
12885 }),12756 }),
12886 } },12757 } },
...@@ -12969,7 +12840,7 @@ const GenZir = struct {...@@ -12969,7 +12840,7 @@ const GenZir = struct {
12969 .data = .{ .extended = .{12840 .data = .{ .extended = .{
12970 .opcode = opcode,12841 .opcode = opcode,
12971 .small = undefined,12842 .small = undefined,
12972 .operand = @bitCast(gz.nodeIndexToRelative(src_node)),12843 .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))),
12973 } },12844 } },
12974 });12845 });
12975 }12846 }
...@@ -13149,8 +13020,8 @@ const GenZir = struct {...@@ -13149,8 +13020,8 @@ const GenZir = struct {
13149 const astgen = gz.astgen;13020 const astgen = gz.astgen;
13150 const gpa = astgen.gpa;13021 const gpa = astgen.gpa;
1315113022
13152 // Node 0 is valid for the root `struct_decl` of a file!13023 // Node .root is valid for the root `struct_decl` of a file!
13153 assert(args.src_node != 0 or gz.parent.tag == .top);13024 assert(args.src_node != .root or gz.parent.tag == .top);
1315413025
13155 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13026 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1315613027
...@@ -13210,7 +13081,7 @@ const GenZir = struct {...@@ -13210,7 +13081,7 @@ const GenZir = struct {
13210 const astgen = gz.astgen;13081 const astgen = gz.astgen;
13211 const gpa = astgen.gpa;13082 const gpa = astgen.gpa;
1321213083
13213 assert(args.src_node != 0);13084 assert(args.src_node != .root);
1321413085
13215 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13086 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1321613087
...@@ -13272,7 +13143,7 @@ const GenZir = struct {...@@ -13272,7 +13143,7 @@ const GenZir = struct {
13272 const astgen = gz.astgen;13143 const astgen = gz.astgen;
13273 const gpa = astgen.gpa;13144 const gpa = astgen.gpa;
1327413145
13275 assert(args.src_node != 0);13146 assert(args.src_node != .root);
1327613147
13277 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);13148 const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash);
1327813149
...@@ -13327,7 +13198,7 @@ const GenZir = struct {...@@ -13327,7 +13198,7 @@ const GenZir = struct {
13327 const astgen = gz.astgen;13198 const astgen = gz.astgen;
13328 const gpa = astgen.gpa;13199 const gpa = astgen.gpa;
1332913200
13330 assert(args.src_node != 0);13201 assert(args.src_node != .root);
1333113202
13332 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);13203 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2);
13333 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{13204 const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
...@@ -13521,9 +13392,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo...@@ -13521,9 +13392,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
13521 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };13392 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1352213393
13523 const tree = gz.astgen.tree;13394 const tree = gz.astgen.tree;
13524 const token_starts = tree.tokens.items(.start);13395 const node_start = tree.tokenStart(tree.nodeMainToken(node));
13525 const main_tokens = tree.nodes.items(.main_token);
13526 const node_start = token_starts[main_tokens[node]];
13527 gz.astgen.advanceSourceCursor(node_start);13396 gz.astgen.advanceSourceCursor(node_start);
1352813397
13529 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };13398 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
...@@ -13532,8 +13401,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo...@@ -13532,8 +13401,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo
13532/// Advances the source cursor to the beginning of `node`.13401/// Advances the source cursor to the beginning of `node`.
13533fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {13402fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void {
13534 const tree = astgen.tree;13403 const tree = astgen.tree;
13535 const token_starts = tree.tokens.items(.start);13404 const node_start = tree.tokenStart(tree.firstToken(node));
13536 const node_start = token_starts[tree.firstToken(node)];
13537 astgen.advanceSourceCursor(node_start);13405 astgen.advanceSourceCursor(node_start);
13538}13406}
1353913407
...@@ -13588,9 +13456,6 @@ fn scanContainer(...@@ -13588,9 +13456,6 @@ fn scanContainer(
13588) !u32 {13456) !u32 {
13589 const gpa = astgen.gpa;13457 const gpa = astgen.gpa;
13590 const tree = astgen.tree;13458 const tree = astgen.tree;
13591 const node_tags = tree.nodes.items(.tag);
13592 const main_tokens = tree.nodes.items(.main_token);
13593 const token_tags = tree.tokens.items(.tag);
1359413459
13595 var any_invalid_declarations = false;13460 var any_invalid_declarations = false;
1359613461
...@@ -13620,7 +13485,7 @@ fn scanContainer(...@@ -13620,7 +13485,7 @@ fn scanContainer(
13620 var decl_count: u32 = 0;13485 var decl_count: u32 = 0;
13621 for (members) |member_node| {13486 for (members) |member_node| {
13622 const Kind = enum { decl, field };13487 const Kind = enum { decl, field };
13623 const kind: Kind, const name_token = switch (node_tags[member_node]) {13488 const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) {
13624 .container_field_init,13489 .container_field_init,
13625 .container_field_align,13490 .container_field_align,
13626 .container_field,13491 .container_field,
...@@ -13628,7 +13493,7 @@ fn scanContainer(...@@ -13628,7 +13493,7 @@ fn scanContainer(
13628 var full = tree.fullContainerField(member_node).?;13493 var full = tree.fullContainerField(member_node).?;
13629 switch (container_kind) {13494 switch (container_kind) {
13630 .@"struct", .@"opaque" => {},13495 .@"struct", .@"opaque" => {},
13631 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes),13496 .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree),
13632 }13497 }
13633 if (full.ast.tuple_like) continue;13498 if (full.ast.tuple_like) continue;
13634 break :blk .{ .field, full.ast.main_token };13499 break :blk .{ .field, full.ast.main_token };
...@@ -13640,7 +13505,7 @@ fn scanContainer(...@@ -13640,7 +13505,7 @@ fn scanContainer(
13640 .aligned_var_decl,13505 .aligned_var_decl,
13641 => blk: {13506 => blk: {
13642 decl_count += 1;13507 decl_count += 1;
13643 break :blk .{ .decl, main_tokens[member_node] + 1 };13508 break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 };
13644 },13509 },
1364513510
13646 .fn_proto_simple,13511 .fn_proto_simple,
...@@ -13650,8 +13515,8 @@ fn scanContainer(...@@ -13650,8 +13515,8 @@ fn scanContainer(
13650 .fn_decl,13515 .fn_decl,
13651 => blk: {13516 => blk: {
13652 decl_count += 1;13517 decl_count += 1;
13653 const ident = main_tokens[member_node] + 1;13518 const ident = tree.nodeMainToken(member_node) + 1;
13654 if (token_tags[ident] != .identifier) {13519 if (tree.tokenTag(ident) != .identifier) {
13655 try astgen.appendErrorNode(member_node, "missing function name", .{});13520 try astgen.appendErrorNode(member_node, "missing function name", .{});
13656 any_invalid_declarations = true;13521 any_invalid_declarations = true;
13657 continue;13522 continue;
...@@ -13668,12 +13533,12 @@ fn scanContainer(...@@ -13668,12 +13533,12 @@ fn scanContainer(
13668 decl_count += 1;13533 decl_count += 1;
13669 // We don't want shadowing detection here, and test names work a bit differently, so13534 // We don't want shadowing detection here, and test names work a bit differently, so
13670 // we must do the redeclaration detection ourselves.13535 // we must do the redeclaration detection ourselves.
13671 const test_name_token = main_tokens[member_node] + 1;13536 const test_name_token = tree.nodeMainToken(member_node) + 1;
13672 const new_ent: NameEntry = .{13537 const new_ent: NameEntry = .{
13673 .tok = test_name_token,13538 .tok = test_name_token,
13674 .next = null,13539 .next = null,
13675 };13540 };
13676 switch (token_tags[test_name_token]) {13541 switch (tree.tokenTag(test_name_token)) {
13677 else => {}, // unnamed test13542 else => {}, // unnamed test
13678 .string_literal => {13543 .string_literal => {
13679 const name = try astgen.strLitAsString(test_name_token);13544 const name = try astgen.strLitAsString(test_name_token);
...@@ -14275,3 +14140,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !...@@ -14275,3 +14140,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) !
14275 }14140 }
14276 return refs.items;14141 return refs.items;
14277}14142}
14143
14144test {
14145 _ = &generate;
14146}
lib/std/zig/AstRlAnnotate.zig+159-142
...@@ -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
...@@ -338,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -338,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
338 for (full.ast.params) |param_node| {347 for (full.ast.params) |param_node| {
339 _ = try astrl.expr(param_node, block, ResultInfo.type_only);348 _ = try astrl.expr(param_node, block, ResultInfo.type_only);
340 }349 }
341 return switch (node_tags[node]) {350 return switch (tree.nodeTag(node)) {
342 .call_one,351 .call_one,
343 .call_one_comma,352 .call_one_comma,
344 .call,353 .call,
...@@ -354,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -354,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
354 },363 },
355364
356 .@"return" => {365 .@"return" => {
357 if (node_datas[node].lhs != 0) {366 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
358 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);
359 if (ret_val_consumes_rl) {368 if (ret_val_consumes_rl) {
360 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});369 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
361 }370 }
...@@ -364,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -364,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
364 },373 },
365374
366 .field_access => {375 .field_access => {
367 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);376 const lhs, _ = tree.nodeData(node).node_and_token;
377 _ = try astrl.expr(lhs, block, ResultInfo.none);
368 return false;378 return false;
369 },379 },
370380
...@@ -376,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -376,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
376 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool386 _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool
377 }387 }
378388
379 if (full.ast.else_expr == 0) {389 if (full.ast.else_expr.unwrap()) |else_expr| {
380 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
381 return false;
382 } else {
383 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);
384 const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri);391 const else_uses_rl = try astrl.expr(else_expr, block, ri);
385 const uses_rl = then_uses_rl or else_uses_rl;392 const uses_rl = then_uses_rl or else_uses_rl;
386 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, {});
387 return uses_rl;394 return uses_rl;
395 } else {
396 _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none);
397 return false;
388 }398 }
389 },399 },
390400
...@@ -405,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -405,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
405 .ri = ri,415 .ri = ri,
406 .consumes_res_ptr = false,416 .consumes_res_ptr = false,
407 };417 };
408 if (full.ast.cont_expr != 0) {418 if (full.ast.cont_expr.unwrap()) |cont_expr| {
409 _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none);419 _ = try astrl.expr(cont_expr, &new_block, ResultInfo.none);
410 }420 }
411 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);421 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
412 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: {
413 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);423 break :else_rl try astrl.expr(else_expr, block, ri);
414 } else false;424 } else false;
415 if (new_block.consumes_res_ptr or else_consumes_rl) {425 if (new_block.consumes_res_ptr or else_consumes_rl) {
416 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});426 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
...@@ -426,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -426,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
426 break :label try astrl.identString(label_token);436 break :label try astrl.identString(label_token);
427 } else null;437 } else null;
428 for (full.ast.inputs) |input| {438 for (full.ast.inputs) |input| {
429 if (node_tags[input] == .for_range) {439 if (tree.nodeTag(input) == .for_range) {
430 _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only);440 const lhs, const opt_rhs = tree.nodeData(input).node_and_opt_node;
431 if (node_datas[input].rhs != 0) {441 _ = try astrl.expr(lhs, block, ResultInfo.type_only);
432 _ = 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);
433 }444 }
434 } else {445 } else {
435 _ = try astrl.expr(input, block, ResultInfo.none);446 _ = try astrl.expr(input, block, ResultInfo.none);
...@@ -443,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -443,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
443 .consumes_res_ptr = false,454 .consumes_res_ptr = false,
444 };455 };
445 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);456 _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none);
446 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: {
447 break :else_rl try astrl.expr(full.ast.else_expr, block, ri);458 break :else_rl try astrl.expr(else_expr, block, ri);
448 } else false;459 } else false;
449 if (new_block.consumes_res_ptr or else_consumes_rl) {460 if (new_block.consumes_res_ptr or else_consumes_rl) {
450 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});461 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
...@@ -455,45 +466,49 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -455,45 +466,49 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
455 },466 },
456467
457 .slice_open => {468 .slice_open => {
458 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);469 const sliced, const start = tree.nodeData(node).node_and_node;
459 _ = 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);
460 return false;472 return false;
461 },473 },
462 .slice => {474 .slice => {
463 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);475 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
464 _ = 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);
465 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);478 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
466 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);479 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);
467 return false;480 return false;
468 },481 },
469 .slice_sentinel => {482 .slice_sentinel => {
470 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);483 const sliced, const extra_index = tree.nodeData(node).node_and_extra;
471 _ = 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);
472 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);486 _ = try astrl.expr(extra.start, block, ResultInfo.type_only);
473 if (extra.end != 0) {487 if (extra.end.unwrap()) |end| {
474 _ = try astrl.expr(extra.end, block, ResultInfo.type_only);488 _ = try astrl.expr(end, block, ResultInfo.type_only);
475 }489 }
476 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);490 _ = try astrl.expr(extra.sentinel, block, ResultInfo.none);
477 return false;491 return false;
478 },492 },
479 .deref => {493 .deref => {
480 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);494 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
481 return false;495 return false;
482 },496 },
483 .address_of => {497 .address_of => {
484 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);498 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
485 return false;499 return false;
486 },500 },
487 .optional_type => {501 .optional_type => {
488 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);502 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only);
489 return false;503 return false;
490 },504 },
491 .grouped_expression,
492 .@"try",505 .@"try",
493 .@"await",506 .@"await",
494 .@"nosuspend",507 .@"nosuspend",
508 => return astrl.expr(tree.nodeData(node).node, block, ri),
509 .grouped_expression,
495 .unwrap_optional,510 .unwrap_optional,
496 => return astrl.expr(node_datas[node].lhs, block, ri),511 => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri),
497512
498 .block_two,513 .block_two,
499 .block_two_semicolon,514 .block_two_semicolon,
...@@ -505,12 +520,14 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -505,12 +520,14 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
505 return astrl.blockExpr(block, ri, node, statements);520 return astrl.blockExpr(block, ri, node, statements);
506 },521 },
507 .anyframe_type => {522 .anyframe_type => {
508 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only);523 _, const child_type = tree.nodeData(node).token_and_node;
524 _ = try astrl.expr(child_type, block, ResultInfo.type_only);
509 return false;525 return false;
510 },526 },
511 .@"catch", .@"orelse" => {527 .@"catch", .@"orelse" => {
512 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);528 const lhs, const rhs = tree.nodeData(node).node_and_node;
513 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);
514 if (rhs_consumes_rl) {531 if (rhs_consumes_rl) {
515 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});532 try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {});
516 }533 }
...@@ -524,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -524,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
524 => {541 => {
525 const full = tree.fullPtrType(node).?;542 const full = tree.fullPtrType(node).?;
526 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);543 _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only);
527 if (full.ast.sentinel != 0) {544 if (full.ast.sentinel.unwrap()) |sentinel| {
528 _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only);545 _ = try astrl.expr(sentinel, block, ResultInfo.type_only);
529 }546 }
530 if (full.ast.addrspace_node != 0) {547 if (full.ast.addrspace_node.unwrap()) |addrspace_node| {
531 _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only);548 _ = try astrl.expr(addrspace_node, block, ResultInfo.type_only);
532 }549 }
533 if (full.ast.align_node != 0) {550 if (full.ast.align_node.unwrap()) |align_node| {
534 _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only);551 _ = try astrl.expr(align_node, block, ResultInfo.type_only);
535 }552 }
536 if (full.ast.bit_range_start != 0) {553 if (full.ast.bit_range_start.unwrap()) |bit_range_start| {
537 assert(full.ast.bit_range_end != 0);554 const bit_range_end = full.ast.bit_range_end.unwrap().?;
538 _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only);555 _ = try astrl.expr(bit_range_start, block, ResultInfo.type_only);
539 _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only);556 _ = try astrl.expr(bit_range_end, block, ResultInfo.type_only);
540 }557 }
541 return false;558 return false;
542 },559 },
...@@ -560,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -560,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
560 },577 },
561578
562 .@"break" => {579 .@"break" => {
563 if (node_datas[node].rhs == 0) {580 const opt_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node;
581 const rhs = opt_rhs.unwrap() orelse {
564 // Breaks with void are not interesting582 // Breaks with void are not interesting
565 return false;583 return false;
566 }584 };
567585
568 var opt_cur_block = block;586 var opt_cur_block = block;
569 if (node_datas[node].lhs == 0) {587 if (opt_label.unwrap()) |label_token| {
570 // No label - we're breaking from a loop.588 const break_label = try astrl.identString(label_token);
571 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) {
572 if (cur_block.is_loop) break;590 const block_label = cur_block.label orelse continue;
591 if (std.mem.eql(u8, block_label, break_label)) break;
573 }592 }
574 } else {593 } else {
575 const break_label = try astrl.identString(node_datas[node].lhs);594 // No label - we're breaking from a loop.
576 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) {
577 const block_label = cur_block.label orelse continue;596 if (cur_block.is_loop) break;
578 if (std.mem.eql(u8, block_label, break_label)) break;
579 }597 }
580 }598 }
581599
582 if (opt_cur_block) |target_block| {600 if (opt_cur_block) |target_block| {
583 const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri);601 const consumes_break_rl = try astrl.expr(rhs, block, target_block.ri);
584 if (consumes_break_rl) target_block.consumes_res_ptr = true;602 if (consumes_break_rl) target_block.consumes_res_ptr = true;
585 } else {603 } else {
586 // No corresponding scope to break from - AstGen will emit an error.604 // No corresponding scope to break from - AstGen will emit an error.
587 _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none);605 _ = try astrl.expr(rhs, block, ResultInfo.none);
588 }606 }
589607
590 return false;608 return false;
591 },609 },
592610
593 .array_type => {611 .array_type => {
594 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only);612 const lhs, const rhs = tree.nodeData(node).node_and_node;
595 _ = 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);
596 return false;615 return false;
597 },616 },
598 .array_type_sentinel => {617 .array_type_sentinel => {
599 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel);618 const len_expr, const extra_index = tree.nodeData(node).node_and_extra;
600 _ = 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);
601 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);621 _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only);
602 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);622 _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only);
603 return false;623 return false;
604 },624 },
605 .array_access => {625 .array_access => {
606 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);626 const lhs, const rhs = tree.nodeData(node).node_and_node;
607 _ = 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);
608 return false;629 return false;
609 },630 },
610 .@"comptime" => {631 .@"comptime" => {
611 // 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
612 // not. This means the result location is not forwarded.633 // not. This means the result location is not forwarded.
613 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);634 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
614 return false;635 return false;
615 },636 },
616 .@"switch", .switch_comma => {637 .@"switch", .switch_comma => {
617 const operand_node = node_datas[node].lhs;638 const operand_node, const extra_index = tree.nodeData(node).node_and_extra;
618 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);
619 const case_nodes = tree.extra_data[extra.start..extra.end];
620640
621 _ = try astrl.expr(operand_node, block, ResultInfo.none);641 _ = try astrl.expr(operand_node, block, ResultInfo.none);
622642
...@@ -624,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -624,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
624 for (case_nodes) |case_node| {644 for (case_nodes) |case_node| {
625 const case = tree.fullSwitchCase(case_node).?;645 const case = tree.fullSwitchCase(case_node).?;
626 for (case.ast.values) |item_node| {646 for (case.ast.values) |item_node| {
627 if (node_tags[item_node] == .switch_range) {647 if (tree.nodeTag(item_node) == .switch_range) {
628 _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none);648 const lhs, const rhs = tree.nodeData(item_node).node_and_node;
629 _ = 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);
630 } else {651 } else {
631 _ = try astrl.expr(item_node, block, ResultInfo.none);652 _ = try astrl.expr(item_node, block, ResultInfo.none);
632 }653 }
...@@ -641,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -641,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
641 return any_prong_consumed_rl;662 return any_prong_consumed_rl;
642 },663 },
643 .@"suspend" => {664 .@"suspend" => {
644 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);665 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
645 return false;666 return false;
646 },667 },
647 .@"resume" => {668 .@"resume" => {
648 _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none);669 _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none);
649 return false;670 return false;
650 },671 },
651672
...@@ -661,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -661,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
661 var buf: [2]Ast.Node.Index = undefined;682 var buf: [2]Ast.Node.Index = undefined;
662 const full = tree.fullArrayInit(&buf, node).?;683 const full = tree.fullArrayInit(&buf, node).?;
663684
664 if (full.ast.type_expr != 0) {685 if (full.ast.type_expr.unwrap()) |type_expr| {
665 // Explicitly typed init does not participate in RLS686 // Explicitly typed init does not participate in RLS
666 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);687 _ = try astrl.expr(type_expr, block, ResultInfo.none);
667 for (full.ast.elements) |elem_init| {688 for (full.ast.elements) |elem_init| {
668 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);689 _ = try astrl.expr(elem_init, block, ResultInfo.type_only);
669 }690 }
...@@ -698,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -698,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
698 var buf: [2]Ast.Node.Index = undefined;719 var buf: [2]Ast.Node.Index = undefined;
699 const full = tree.fullStructInit(&buf, node).?;720 const full = tree.fullStructInit(&buf, node).?;
700721
701 if (full.ast.type_expr != 0) {722 if (full.ast.type_expr.unwrap()) |type_expr| {
702 // Explicitly typed init does not participate in RLS723 // Explicitly typed init does not participate in RLS
703 _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none);724 _ = try astrl.expr(type_expr, block, ResultInfo.none);
704 for (full.ast.fields) |field_init| {725 for (full.ast.fields) |field_init| {
705 _ = try astrl.expr(field_init, block, ResultInfo.type_only);726 _ = try astrl.expr(field_init, block, ResultInfo.type_only);
706 }727 }
...@@ -728,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -728,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
728 .fn_proto_one,749 .fn_proto_one,
729 .fn_proto,750 .fn_proto,
730 .fn_decl,751 .fn_decl,
731 => {752 => |tag| {
732 var buf: [1]Ast.Node.Index = undefined;753 var buf: [1]Ast.Node.Index = undefined;
733 const full = tree.fullFnProto(&buf, node).?;754 const full = tree.fullFnProto(&buf, node).?;
734 const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0;755 const body_node = if (tag == .fn_decl) tree.nodeData(node).node_and_node[1].toOptional() else .none;
735 {756 {
736 var it = full.iterate(tree);757 var it = full.iterate(tree);
737 while (it.next()) |param| {758 while (it.next()) |param| {
738 if (param.anytype_ellipsis3 == null) {759 if (param.anytype_ellipsis3 == null) {
739 _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only);760 const type_expr = param.type_expr.?;
761 _ = try astrl.expr(type_expr, block, ResultInfo.type_only);
740 }762 }
741 }763 }
742 }764 }
743 if (full.ast.align_expr != 0) {765 if (full.ast.align_expr.unwrap()) |align_expr| {
744 _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only);766 _ = try astrl.expr(align_expr, block, ResultInfo.type_only);
745 }767 }
746 if (full.ast.addrspace_expr != 0) {768 if (full.ast.addrspace_expr.unwrap()) |addrspace_expr| {
747 _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only);769 _ = try astrl.expr(addrspace_expr, block, ResultInfo.type_only);
748 }770 }
749 if (full.ast.section_expr != 0) {771 if (full.ast.section_expr.unwrap()) |section_expr| {
750 _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only);772 _ = try astrl.expr(section_expr, block, ResultInfo.type_only);
751 }773 }
752 if (full.ast.callconv_expr != 0) {774 if (full.ast.callconv_expr.unwrap()) |callconv_expr| {
753 _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only);775 _ = try astrl.expr(callconv_expr, block, ResultInfo.type_only);
754 }776 }
755 _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only);777 const return_type = full.ast.return_type.unwrap().?;
756 if (body_node != 0) {778 _ = try astrl.expr(return_type, block, ResultInfo.type_only);
757 _ = try astrl.expr(body_node, block, ResultInfo.none);779 if (body_node.unwrap()) |body| {
780 _ = try astrl.expr(body, block, ResultInfo.none);
758 }781 }
759 return false;782 return false;
760 },783 },
...@@ -763,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI...@@ -763,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI
763786
764fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {787fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
765 const tree = astrl.tree;788 const tree = astrl.tree;
766 const token_tags = tree.tokens.items(.tag);789 assert(tree.tokenTag(token) == .identifier);
767 assert(token_tags[token] == .identifier);
768 const ident_name = tree.tokenSlice(token);790 const ident_name = tree.tokenSlice(token);
769 if (!std.mem.startsWith(u8, ident_name, "@")) {791 if (!std.mem.startsWith(u8, ident_name, "@")) {
770 return ident_name;792 return ident_name;
...@@ -777,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {...@@ -777,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 {
777799
778fn 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 {
779 const tree = astrl.tree;801 const tree = astrl.tree;
780 const token_tags = tree.tokens.items(.tag);
781 const main_tokens = tree.nodes.items(.main_token);
782802
783 const lbrace = main_tokens[node];803 const lbrace = tree.nodeMainToken(node);
784 if (token_tags[lbrace - 1] == .colon and804 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
785 token_tags[lbrace - 2] == .identifier)
786 {
787 // Labeled block805 // Labeled block
788 var new_block: Block = .{806 var new_block: Block = .{
789 .parent = parent_block,807 .parent = parent_block,
...@@ -812,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -812,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
812 _ = ri; // Currently, no builtin consumes its result location.830 _ = ri; // Currently, no builtin consumes its result location.
813831
814 const tree = astrl.tree;832 const tree = astrl.tree;
815 const main_tokens = tree.nodes.items(.main_token);833 const builtin_token = tree.nodeMainToken(node);
816 const builtin_token = main_tokens[node];
817 const builtin_name = tree.tokenSlice(builtin_token);834 const builtin_name = tree.tokenSlice(builtin_token);
818 const info = BuiltinFn.list.get(builtin_name) orelse return false;835 const info = BuiltinFn.list.get(builtin_name) orelse return false;
819 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+1070-1327
...@@ -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,
472 if (items.len >= 2) items[1].toOptional() else .none,
473 } },
453 .trailing = trailing,474 .trailing = trailing,
454 },475 };
455 1 => return Members{476 } else {
456 .len = 1,477 return Members{
457 .lhs = items[0],478 .len = items.len,
458 .rhs = 0,479 .data = .{ .extra_range = try p.listToSpan(items) },
459 .trailing = trailing,
460 },
461 2 => return Members{
462 .len = 2,
463 .lhs = items[0],
464 .rhs = items[1],
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,2425 .tag = if (comma) .async_call_one_comma else .async_call_one,
2530 .main_token = lparen,2426 .main_token = lparen,
2531 .data = .{2427 .data = .{ .node_and_opt_node = .{
2532 .lhs = res,2428 res,
2533 .rhs = 0,2429 if (params.len >= 1) params[0].toOptional() else .none,
2534 },2430 } },
2535 }),2431 });
2536 1 => return p.addNode(.{2432 } else {
2537 .tag = if (comma) .async_call_one_comma else .async_call_one,2433 return try p.addNode(.{
2538 .main_token = lparen,
2539 .data = .{
2540 .lhs = res,
2541 .rhs = params[0],
2542 },
2543 }),
2544 else => return 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,153 +2530,126 @@ fn parseSuffixExpr(p: *Parse) !Node.Index {...@@ -2650,153 +2530,126 @@ 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 => return try p.addNode(.{
2795 .tag = .enum_literal,2651 .tag = .enum_literal,
2796 .data = .{2652 .data = .{ .token = p.nextToken() }, // dot
2797 .lhs = p.nextToken(), // dot
2798 .rhs = undefined,
2799 },
2800 .main_token = p.nextToken(), // identifier2653 .main_token = p.nextToken(), // identifier
2801 }),2654 }),
2802 .l_brace => {2655 .l_brace => {
...@@ -2808,11 +2661,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2808,11 +2661,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
28082661
2809 const scratch_top = p.scratch.items.len;2662 const scratch_top = p.scratch.items.len;
2810 defer p.scratch.shrinkRetainingCapacity(scratch_top);2663 defer p.scratch.shrinkRetainingCapacity(scratch_top);
2811 const field_init = try p.parseFieldInit();2664 const opt_field_init = try p.parseFieldInit();
2812 if (field_init != 0) {2665 if (opt_field_init) |field_init| {
2813 try p.scratch.append(p.gpa, field_init);2666 try p.scratch.append(p.gpa, field_init);
2814 while (true) {2667 while (true) {
2815 switch (p.token_tags[p.tok_i]) {2668 switch (p.tokenTag(p.tok_i)) {
2816 .comma => p.tok_i += 1,2669 .comma => p.tok_i += 1,
2817 .r_brace => {2670 .r_brace => {
2818 p.tok_i += 1;2671 p.tok_i += 1;
...@@ -2826,37 +2679,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2826,37 +2679,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2826 const next = try p.expectFieldInit();2679 const next = try p.expectFieldInit();
2827 try p.scratch.append(p.gpa, next);2680 try p.scratch.append(p.gpa, next);
2828 }2681 }
2829 const comma = (p.token_tags[p.tok_i - 2] == .comma);2682 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2830 const inits = p.scratch.items[scratch_top..];2683 const inits = p.scratch.items[scratch_top..];
2831 switch (inits.len) {2684 std.debug.assert(inits.len != 0);
2832 0 => unreachable,2685 if (inits.len <= 2) {
2833 1 => return p.addNode(.{2686 return try p.addNode(.{
2834 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,2687 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
2835 .main_token = lbrace,2688 .main_token = lbrace,
2836 .data = .{2689 .data = .{ .opt_node_and_opt_node = .{
2837 .lhs = inits[0],2690 if (inits.len >= 1) .fromOptional(inits[0]) else .none,
2838 .rhs = 0,2691 if (inits.len >= 2) .fromOptional(inits[1]) else .none,
2839 },2692 } },
2840 }),2693 });
2841 2 => return p.addNode(.{2694 } else {
2842 .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,2695 return try p.addNode(.{
2696 .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
2843 .main_token = lbrace,2697 .main_token = lbrace,
2844 .data = .{2698 .data = .{ .extra_range = try p.listToSpan(inits) },
2845 .lhs = inits[0],2699 });
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 }2700 }
2861 }2701 }
28622702
...@@ -2864,7 +2704,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2864,7 +2704,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2864 if (p.eatToken(.r_brace)) |_| break;2704 if (p.eatToken(.r_brace)) |_| break;
2865 const elem_init = try p.expectExpr();2705 const elem_init = try p.expectExpr();
2866 try p.scratch.append(p.gpa, elem_init);2706 try p.scratch.append(p.gpa, elem_init);
2867 switch (p.token_tags[p.tok_i]) {2707 switch (p.tokenTag(p.tok_i)) {
2868 .comma => p.tok_i += 1,2708 .comma => p.tok_i += 1,
2869 .r_brace => {2709 .r_brace => {
2870 p.tok_i += 1;2710 p.tok_i += 1;
...@@ -2875,49 +2715,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2875,49 +2715,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2875 else => try p.warn(.expected_comma_after_initializer),2715 else => try p.warn(.expected_comma_after_initializer),
2876 }2716 }
2877 }2717 }
2878 const comma = (p.token_tags[p.tok_i - 2] == .comma);2718 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
2879 const inits = p.scratch.items[scratch_top..];2719 const inits = p.scratch.items[scratch_top..];
2880 switch (inits.len) {2720 if (inits.len <= 2) {
2881 0 => return p.addNode(.{2721 return try p.addNode(.{
2882 .tag = .struct_init_dot_two,2722 .tag = if (inits.len == 0)
2883 .main_token = lbrace,2723 .struct_init_dot_two
2884 .data = .{2724 else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
2885 .lhs = 0,
2886 .rhs = 0,
2887 },
2888 }),
2889 1 => return p.addNode(.{
2890 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,
2891 .main_token = lbrace,2725 .main_token = lbrace,
2892 .data = .{2726 .data = .{ .opt_node_and_opt_node = .{
2893 .lhs = inits[0],2727 if (inits.len >= 1) inits[0].toOptional() else .none,
2894 .rhs = 0,2728 if (inits.len >= 2) inits[1].toOptional() else .none,
2895 },2729 } },
2896 }),2730 });
2897 2 => return p.addNode(.{2731 } else {
2898 .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two,2732 return try p.addNode(.{
2733 .tag = if (comma) .array_init_dot_comma else .array_init_dot,
2899 .main_token = lbrace,2734 .main_token = lbrace,
2900 .data = .{2735 .data = .{ .extra_range = try p.listToSpan(inits) },
2901 .lhs = inits[0],2736 });
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 }2737 }
2917 },2738 },
2918 else => return null_node,2739 else => return null,
2919 },2740 },
2920 .keyword_error => switch (p.token_tags[p.tok_i + 1]) {2741 .keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
2921 .l_brace => {2742 .l_brace => {
2922 const error_token = p.tok_i;2743 const error_token = p.tok_i;
2923 p.tok_i += 2;2744 p.tok_i += 2;
...@@ -2925,7 +2746,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2925,7 +2746,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2925 if (p.eatToken(.r_brace)) |_| break;2746 if (p.eatToken(.r_brace)) |_| break;
2926 _ = try p.eatDocComments();2747 _ = try p.eatDocComments();
2927 _ = try p.expectToken(.identifier);2748 _ = try p.expectToken(.identifier);
2928 switch (p.token_tags[p.tok_i]) {2749 switch (p.tokenTag(p.tok_i)) {
2929 .comma => p.tok_i += 1,2750 .comma => p.tok_i += 1,
2930 .r_brace => {2751 .r_brace => {
2931 p.tok_i += 1;2752 p.tok_i += 1;
...@@ -2936,13 +2757,10 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2936,13 +2757,10 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2936 else => try p.warn(.expected_comma_after_field),2757 else => try p.warn(.expected_comma_after_field),
2937 }2758 }
2938 }2759 }
2939 return p.addNode(.{2760 return try p.addNode(.{
2940 .tag = .error_set_decl,2761 .tag = .error_set_decl,
2941 .main_token = error_token,2762 .main_token = error_token,
2942 .data = .{2763 .data = .{ .token = p.tok_i - 1 }, // rbrace
2943 .lhs = undefined,
2944 .rhs = p.tok_i - 1, // rbrace
2945 },
2946 });2764 });
2947 },2765 },
2948 else => {2766 else => {
...@@ -2951,41 +2769,37 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {...@@ -2951,41 +2769,37 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index {
2951 if (period == null) try p.warnExpected(.period);2769 if (period == null) try p.warnExpected(.period);
2952 const identifier = p.eatToken(.identifier);2770 const identifier = p.eatToken(.identifier);
2953 if (identifier == null) try p.warnExpected(.identifier);2771 if (identifier == null) try p.warnExpected(.identifier);
2954 return p.addNode(.{2772 return try p.addNode(.{
2955 .tag = .error_value,2773 .tag = .error_value,
2956 .main_token = main_token,2774 .main_token = main_token,
2957 .data = .{2775 .data = .{ .opt_token_and_opt_token = .{
2958 .lhs = period orelse 0,2776 .fromOptional(period),
2959 .rhs = identifier orelse 0,2777 .fromOptional(identifier),
2960 },2778 } },
2961 });2779 });
2962 },2780 },
2963 },2781 },
2964 .l_paren => return p.addNode(.{2782 .l_paren => return try p.addNode(.{
2965 .tag = .grouped_expression,2783 .tag = .grouped_expression,
2966 .main_token = p.nextToken(),2784 .main_token = p.nextToken(),
2967 .data = .{2785 .data = .{ .node_and_token = .{
2968 .lhs = try p.expectExpr(),2786 try p.expectExpr(),
2969 .rhs = try p.expectToken(.r_paren),2787 try p.expectToken(.r_paren),
2970 },2788 } },
2971 }),2789 }),
2972 else => return null_node,2790 else => return null,
2973 }2791 }
2974}2792}
29752793
2976fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {2794fn expectPrimaryTypeExpr(p: *Parse) !Node.Index {
2977 const node = try p.parsePrimaryTypeExpr();2795 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}2796}
29832797
2984/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?2798/// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
2985///2799///
2986/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?2800/// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
2987fn parseWhileTypeExpr(p: *Parse) !Node.Index {2801fn parseWhileTypeExpr(p: *Parse) !?Node.Index {
2988 const while_token = p.eatToken(.keyword_while) orelse return null_node;2802 const while_token = p.eatToken(.keyword_while) orelse return null;
2989 _ = try p.expectToken(.l_paren);2803 _ = try p.expectToken(.l_paren);
2990 const condition = try p.expectExpr();2804 const condition = try p.expectExpr();
2991 _ = try p.expectToken(.r_paren);2805 _ = try p.expectToken(.r_paren);
...@@ -2994,54 +2808,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {...@@ -2994,54 +2808,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index {
29942808
2995 const then_expr = try p.expectTypeExpr();2809 const then_expr = try p.expectTypeExpr();
2996 _ = p.eatToken(.keyword_else) orelse {2810 _ = p.eatToken(.keyword_else) orelse {
2997 if (cont_expr == 0) {2811 if (cont_expr == null) {
2998 return p.addNode(.{2812 return try p.addNode(.{
2999 .tag = .while_simple,2813 .tag = .while_simple,
3000 .main_token = while_token,2814 .main_token = while_token,
3001 .data = .{2815 .data = .{ .node_and_node = .{
3002 .lhs = condition,2816 condition,
3003 .rhs = then_expr,2817 then_expr,
3004 },2818 } },
3005 });2819 });
3006 } else {2820 } else {
3007 return p.addNode(.{2821 return try p.addNode(.{
3008 .tag = .while_cont,2822 .tag = .while_cont,
3009 .main_token = while_token,2823 .main_token = while_token,
3010 .data = .{2824 .data = .{ .node_and_extra = .{
3011 .lhs = condition,2825 condition, try p.addExtra(Node.WhileCont{
3012 .rhs = try p.addExtra(Node.WhileCont{2826 .cont_expr = cont_expr.?,
3013 .cont_expr = cont_expr,
3014 .then_expr = then_expr,2827 .then_expr = then_expr,
3015 }),2828 }),
3016 },2829 } },
3017 });2830 });
3018 }2831 }
3019 };2832 };
3020 _ = try p.parsePayload();2833 _ = try p.parsePayload();
3021 const else_expr = try p.expectTypeExpr();2834 const else_expr = try p.expectTypeExpr();
3022 return p.addNode(.{2835 return try p.addNode(.{
3023 .tag = .@"while",2836 .tag = .@"while",
3024 .main_token = while_token,2837 .main_token = while_token,
3025 .data = .{2838 .data = .{ .node_and_extra = .{
3026 .lhs = condition,2839 condition, try p.addExtra(Node.While{
3027 .rhs = try p.addExtra(Node.While{2840 .cont_expr = .fromOptional(cont_expr),
3028 .cont_expr = cont_expr,
3029 .then_expr = then_expr,2841 .then_expr = then_expr,
3030 .else_expr = else_expr,2842 .else_expr = else_expr,
3031 }),2843 }),
3032 },2844 } },
3033 });2845 });
3034}2846}
30352847
3036/// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE2848/// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
3037fn parseSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {2849fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index {
3038 const switch_token = p.eatToken(.keyword_switch) orelse return null_node;2850 const switch_token = p.eatToken(.keyword_switch) orelse return null;
3039 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);2851 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
3040}2852}
30412853
3042fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {2854fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index {
3043 const switch_token = p.assertToken(.keyword_switch);2855 const switch_token = p.assertToken(.keyword_switch);
3044 return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);2856 return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token);
3045}2857}
30462858
3047fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {2859fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
...@@ -3050,19 +2862,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {...@@ -3050,19 +2862,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index {
3050 _ = try p.expectToken(.r_paren);2862 _ = try p.expectToken(.r_paren);
3051 _ = try p.expectToken(.l_brace);2863 _ = try p.expectToken(.l_brace);
3052 const cases = try p.parseSwitchProngList();2864 const cases = try p.parseSwitchProngList();
3053 const trailing_comma = p.token_tags[p.tok_i - 1] == .comma;2865 const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma;
3054 _ = try p.expectToken(.r_brace);2866 _ = try p.expectToken(.r_brace);
30552867
3056 return p.addNode(.{2868 return p.addNode(.{
3057 .tag = if (trailing_comma) .switch_comma else .@"switch",2869 .tag = if (trailing_comma) .switch_comma else .@"switch",
3058 .main_token = main_token,2870 .main_token = main_token,
3059 .data = .{2871 .data = .{ .node_and_extra = .{
3060 .lhs = expr_node,2872 expr_node,
3061 .rhs = try p.addExtra(Node.SubRange{2873 try p.addExtra(Node.SubRange{
3062 .start = cases.start,2874 .start = cases.start,
3063 .end = cases.end,2875 .end = cases.end,
3064 }),2876 }),
3065 },2877 } },
3066 });2878 });
3067}2879}
30682880
...@@ -3089,10 +2901,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3089,10 +2901,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3089 return p.addNode(.{2901 return p.addNode(.{
3090 .tag = .asm_simple,2902 .tag = .asm_simple,
3091 .main_token = asm_token,2903 .main_token = asm_token,
3092 .data = .{2904 .data = .{ .node_and_token = .{
3093 .lhs = template,2905 template,
3094 .rhs = rparen,2906 rparen,
3095 },2907 } },
3096 });2908 });
3097 }2909 }
30982910
...@@ -3102,10 +2914,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3102,10 +2914,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3102 defer p.scratch.shrinkRetainingCapacity(scratch_top);2914 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31032915
3104 while (true) {2916 while (true) {
3105 const output_item = try p.parseAsmOutputItem();2917 const output_item = try p.parseAsmOutputItem() orelse break;
3106 if (output_item == 0) break;
3107 try p.scratch.append(p.gpa, output_item);2918 try p.scratch.append(p.gpa, output_item);
3108 switch (p.token_tags[p.tok_i]) {2919 switch (p.tokenTag(p.tok_i)) {
3109 .comma => p.tok_i += 1,2920 .comma => p.tok_i += 1,
3110 // All possible delimiters.2921 // All possible delimiters.
3111 .colon, .r_paren, .r_brace, .r_bracket => break,2922 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3115,10 +2926,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3115,10 +2926,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3115 }2926 }
3116 if (p.eatToken(.colon)) |_| {2927 if (p.eatToken(.colon)) |_| {
3117 while (true) {2928 while (true) {
3118 const input_item = try p.parseAsmInputItem();2929 const input_item = try p.parseAsmInputItem() orelse break;
3119 if (input_item == 0) break;
3120 try p.scratch.append(p.gpa, input_item);2930 try p.scratch.append(p.gpa, input_item);
3121 switch (p.token_tags[p.tok_i]) {2931 switch (p.tokenTag(p.tok_i)) {
3122 .comma => p.tok_i += 1,2932 .comma => p.tok_i += 1,
3123 // All possible delimiters.2933 // All possible delimiters.
3124 .colon, .r_paren, .r_brace, .r_bracket => break,2934 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3128,7 +2938,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3128,7 +2938,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3128 }2938 }
3129 if (p.eatToken(.colon)) |_| {2939 if (p.eatToken(.colon)) |_| {
3130 while (p.eatToken(.string_literal)) |_| {2940 while (p.eatToken(.string_literal)) |_| {
3131 switch (p.token_tags[p.tok_i]) {2941 switch (p.tokenTag(p.tok_i)) {
3132 .comma => p.tok_i += 1,2942 .comma => p.tok_i += 1,
3133 .colon, .r_paren, .r_brace, .r_bracket => break,2943 .colon, .r_paren, .r_brace, .r_bracket => break,
3134 // Likely just a missing comma; give error but continue parsing.2944 // Likely just a missing comma; give error but continue parsing.
...@@ -3142,121 +2952,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {...@@ -3142,121 +2952,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index {
3142 return p.addNode(.{2952 return p.addNode(.{
3143 .tag = .@"asm",2953 .tag = .@"asm",
3144 .main_token = asm_token,2954 .main_token = asm_token,
3145 .data = .{2955 .data = .{ .node_and_extra = .{
3146 .lhs = template,2956 template,
3147 .rhs = try p.addExtra(Node.Asm{2957 try p.addExtra(Node.Asm{
3148 .items_start = span.start,2958 .items_start = span.start,
3149 .items_end = span.end,2959 .items_end = span.end,
3150 .rparen = rparen,2960 .rparen = rparen,
3151 }),2961 }),
3152 },2962 } },
3153 });2963 });
3154}2964}
31552965
3156/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN2966/// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
3157fn parseAsmOutputItem(p: *Parse) !Node.Index {2967fn parseAsmOutputItem(p: *Parse) !?Node.Index {
3158 _ = p.eatToken(.l_bracket) orelse return null_node;2968 _ = p.eatToken(.l_bracket) orelse return null;
3159 const identifier = try p.expectToken(.identifier);2969 const identifier = try p.expectToken(.identifier);
3160 _ = try p.expectToken(.r_bracket);2970 _ = try p.expectToken(.r_bracket);
3161 _ = try p.expectToken(.string_literal);2971 _ = try p.expectToken(.string_literal);
3162 _ = try p.expectToken(.l_paren);2972 _ = try p.expectToken(.l_paren);
3163 const type_expr: Node.Index = blk: {2973 const type_expr: Node.OptionalIndex = blk: {
3164 if (p.eatToken(.arrow)) |_| {2974 if (p.eatToken(.arrow)) |_| {
3165 break :blk try p.expectTypeExpr();2975 break :blk .fromOptional(try p.expectTypeExpr());
3166 } else {2976 } else {
3167 _ = try p.expectToken(.identifier);2977 _ = try p.expectToken(.identifier);
3168 break :blk null_node;2978 break :blk .none;
3169 }2979 }
3170 };2980 };
3171 const rparen = try p.expectToken(.r_paren);2981 const rparen = try p.expectToken(.r_paren);
3172 return p.addNode(.{2982 return try p.addNode(.{
3173 .tag = .asm_output,2983 .tag = .asm_output,
3174 .main_token = identifier,2984 .main_token = identifier,
3175 .data = .{2985 .data = .{ .opt_node_and_token = .{
3176 .lhs = type_expr,2986 type_expr,
3177 .rhs = rparen,2987 rparen,
3178 },2988 } },
3179 });2989 });
3180}2990}
31812991
3182/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN2992/// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
3183fn parseAsmInputItem(p: *Parse) !Node.Index {2993fn parseAsmInputItem(p: *Parse) !?Node.Index {
3184 _ = p.eatToken(.l_bracket) orelse return null_node;2994 _ = p.eatToken(.l_bracket) orelse return null;
3185 const identifier = try p.expectToken(.identifier);2995 const identifier = try p.expectToken(.identifier);
3186 _ = try p.expectToken(.r_bracket);2996 _ = try p.expectToken(.r_bracket);
3187 _ = try p.expectToken(.string_literal);2997 _ = try p.expectToken(.string_literal);
3188 _ = try p.expectToken(.l_paren);2998 _ = try p.expectToken(.l_paren);
3189 const expr = try p.expectExpr();2999 const expr = try p.expectExpr();
3190 const rparen = try p.expectToken(.r_paren);3000 const rparen = try p.expectToken(.r_paren);
3191 return p.addNode(.{3001 return try p.addNode(.{
3192 .tag = .asm_input,3002 .tag = .asm_input,
3193 .main_token = identifier,3003 .main_token = identifier,
3194 .data = .{3004 .data = .{ .node_and_token = .{
3195 .lhs = expr,3005 expr,
3196 .rhs = rparen,3006 rparen,
3197 },3007 } },
3198 });3008 });
3199}3009}
32003010
3201/// BreakLabel <- COLON IDENTIFIER3011/// BreakLabel <- COLON IDENTIFIER
3202fn parseBreakLabel(p: *Parse) !TokenIndex {3012fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex {
3203 _ = p.eatToken(.colon) orelse return null_node;3013 _ = p.eatToken(.colon) orelse return .none;
3204 return p.expectToken(.identifier);3014 const next_token = try p.expectToken(.identifier);
3015 return .fromToken(next_token);
3205}3016}
32063017
3207/// BlockLabel <- IDENTIFIER COLON3018/// BlockLabel <- IDENTIFIER COLON
3208fn parseBlockLabel(p: *Parse) TokenIndex {3019fn parseBlockLabel(p: *Parse) ?TokenIndex {
3209 if (p.token_tags[p.tok_i] == .identifier and3020 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}3021}
32183022
3219/// FieldInit <- DOT IDENTIFIER EQUAL Expr3023/// FieldInit <- DOT IDENTIFIER EQUAL Expr
3220fn parseFieldInit(p: *Parse) !Node.Index {3024fn parseFieldInit(p: *Parse) !?Node.Index {
3221 if (p.token_tags[p.tok_i + 0] == .period and3025 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3222 p.token_tags[p.tok_i + 1] == .identifier and3026 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 }3027 }
3028 return null;
3230}3029}
32313030
3232fn expectFieldInit(p: *Parse) !Node.Index {3031fn expectFieldInit(p: *Parse) !Node.Index {
3233 if (p.token_tags[p.tok_i] != .period or3032 if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| {
3234 p.token_tags[p.tok_i + 1] != .identifier or3033 return try p.expectExpr();
3235 p.token_tags[p.tok_i + 2] != .equal)3034 }
3236 return p.fail(.expected_initializer);3035 return p.fail(.expected_initializer);
3237
3238 p.tok_i += 3;
3239 return p.expectExpr();
3240}3036}
32413037
3242/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN3038/// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
3243fn parseWhileContinueExpr(p: *Parse) !Node.Index {3039fn parseWhileContinueExpr(p: *Parse) !?Node.Index {
3244 _ = p.eatToken(.colon) orelse {3040 _ = p.eatToken(.colon) orelse {
3245 if (p.token_tags[p.tok_i] == .l_paren and3041 if (p.tokenTag(p.tok_i) == .l_paren and
3246 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))3042 p.tokensOnSameLine(p.tok_i - 1, p.tok_i))
3247 return p.fail(.expected_continue_expr);3043 return p.fail(.expected_continue_expr);
3248 return null_node;3044 return null;
3249 };3045 };
3250 _ = try p.expectToken(.l_paren);3046 _ = try p.expectToken(.l_paren);
3251 const node = try p.parseAssignExpr();3047 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);3048 _ = try p.expectToken(.r_paren);
3254 return node;3049 return node;
3255}3050}
32563051
3257/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN3052/// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
3258fn parseLinkSection(p: *Parse) !Node.Index {3053fn parseLinkSection(p: *Parse) !?Node.Index {
3259 _ = p.eatToken(.keyword_linksection) orelse return null_node;3054 _ = p.eatToken(.keyword_linksection) orelse return null;
3260 _ = try p.expectToken(.l_paren);3055 _ = try p.expectToken(.l_paren);
3261 const expr_node = try p.expectExpr();3056 const expr_node = try p.expectExpr();
3262 _ = try p.expectToken(.r_paren);3057 _ = try p.expectToken(.r_paren);
...@@ -3264,8 +3059,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {...@@ -3264,8 +3059,8 @@ fn parseLinkSection(p: *Parse) !Node.Index {
3264}3059}
32653060
3266/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN3061/// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
3267fn parseCallconv(p: *Parse) !Node.Index {3062fn parseCallconv(p: *Parse) !?Node.Index {
3268 _ = p.eatToken(.keyword_callconv) orelse return null_node;3063 _ = p.eatToken(.keyword_callconv) orelse return null;
3269 _ = try p.expectToken(.l_paren);3064 _ = try p.expectToken(.l_paren);
3270 const expr_node = try p.expectExpr();3065 const expr_node = try p.expectExpr();
3271 _ = try p.expectToken(.r_paren);3066 _ = try p.expectToken(.r_paren);
...@@ -3273,8 +3068,8 @@ fn parseCallconv(p: *Parse) !Node.Index {...@@ -3273,8 +3068,8 @@ fn parseCallconv(p: *Parse) !Node.Index {
3273}3068}
32743069
3275/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN3070/// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN
3276fn parseAddrSpace(p: *Parse) !Node.Index {3071fn parseAddrSpace(p: *Parse) !?Node.Index {
3277 _ = p.eatToken(.keyword_addrspace) orelse return null_node;3072 _ = p.eatToken(.keyword_addrspace) orelse return null;
3278 _ = try p.expectToken(.l_paren);3073 _ = try p.expectToken(.l_paren);
3279 const expr_node = try p.expectExpr();3074 const expr_node = try p.expectExpr();
3280 _ = try p.expectToken(.r_paren);3075 _ = try p.expectToken(.r_paren);
...@@ -3292,59 +3087,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {...@@ -3292,59 +3087,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index {
3292/// ParamType3087/// ParamType
3293/// <- KEYWORD_anytype3088/// <- KEYWORD_anytype
3294/// / TypeExpr3089/// / TypeExpr
3295fn expectParamDecl(p: *Parse) !Node.Index {3090fn expectParamDecl(p: *Parse) !?Node.Index {
3296 _ = try p.eatDocComments();3091 _ = try p.eatDocComments();
3297 switch (p.token_tags[p.tok_i]) {3092 switch (p.tokenTag(p.tok_i)) {
3298 .keyword_noalias, .keyword_comptime => p.tok_i += 1,3093 .keyword_noalias, .keyword_comptime => p.tok_i += 1,
3299 .ellipsis3 => {3094 .ellipsis3 => {
3300 p.tok_i += 1;3095 p.tok_i += 1;
3301 return null_node;3096 return null;
3302 },3097 },
3303 else => {},3098 else => {},
3304 }3099 }
3305 if (p.token_tags[p.tok_i] == .identifier and3100 _ = p.eatTokens(&.{ .identifier, .colon });
3306 p.token_tags[p.tok_i + 1] == .colon)3101 if (p.eatToken(.keyword_anytype)) |_| {
3307 {3102 return null;
3308 p.tok_i += 2;3103 } else {
3309 }3104 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 }3105 }
3317}3106}
33183107
3319/// Payload <- PIPE IDENTIFIER PIPE3108/// Payload <- PIPE IDENTIFIER PIPE
3320fn parsePayload(p: *Parse) !TokenIndex {3109fn parsePayload(p: *Parse) Error!OptionalTokenIndex {
3321 _ = p.eatToken(.pipe) orelse return null_node;3110 _ = p.eatToken(.pipe) orelse return .none;
3322 const identifier = try p.expectToken(.identifier);3111 const identifier = try p.expectToken(.identifier);
3323 _ = try p.expectToken(.pipe);3112 _ = try p.expectToken(.pipe);
3324 return identifier;3113 return .fromToken(identifier);
3325}3114}
33263115
3327/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE3116/// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
3328fn parsePtrPayload(p: *Parse) !TokenIndex {3117fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex {
3329 _ = p.eatToken(.pipe) orelse return null_node;3118 _ = p.eatToken(.pipe) orelse return .none;
3330 _ = p.eatToken(.asterisk);3119 _ = p.eatToken(.asterisk);
3331 const identifier = try p.expectToken(.identifier);3120 const identifier = try p.expectToken(.identifier);
3332 _ = try p.expectToken(.pipe);3121 _ = try p.expectToken(.pipe);
3333 return identifier;3122 return .fromToken(identifier);
3334}3123}
33353124
3336/// Returns the first identifier token, if any.3125/// Returns the first identifier token, if any.
3337///3126///
3338/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE3127/// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
3339fn parsePtrIndexPayload(p: *Parse) !TokenIndex {3128fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex {
3340 _ = p.eatToken(.pipe) orelse return null_node;3129 _ = p.eatToken(.pipe) orelse return .none;
3341 _ = p.eatToken(.asterisk);3130 _ = p.eatToken(.asterisk);
3342 const identifier = try p.expectToken(.identifier);3131 const identifier = try p.expectToken(.identifier);
3343 if (p.eatToken(.comma) != null) {3132 if (p.eatToken(.comma) != null) {
3344 _ = try p.expectToken(.identifier);3133 _ = try p.expectToken(.identifier);
3345 }3134 }
3346 _ = try p.expectToken(.pipe);3135 _ = try p.expectToken(.pipe);
3347 return identifier;3136 return .fromToken(identifier);
3348}3137}
33493138
3350/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr3139/// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr
...@@ -3352,7 +3141,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {...@@ -3352,7 +3141,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex {
3352/// SwitchCase3141/// SwitchCase
3353/// <- SwitchItem (COMMA SwitchItem)* COMMA?3142/// <- SwitchItem (COMMA SwitchItem)* COMMA?
3354/// / KEYWORD_else3143/// / KEYWORD_else
3355fn parseSwitchProng(p: *Parse) !Node.Index {3144fn parseSwitchProng(p: *Parse) !?Node.Index {
3356 const scratch_top = p.scratch.items.len;3145 const scratch_top = p.scratch.items.len;
3357 defer p.scratch.shrinkRetainingCapacity(scratch_top);3146 defer p.scratch.shrinkRetainingCapacity(scratch_top);
33583147
...@@ -3360,97 +3149,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {...@@ -3360,97 +3149,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index {
33603149
3361 if (p.eatToken(.keyword_else) == null) {3150 if (p.eatToken(.keyword_else) == null) {
3362 while (true) {3151 while (true) {
3363 const item = try p.parseSwitchItem();3152 const item = try p.parseSwitchItem() orelse break;
3364 if (item == 0) break;
3365 try p.scratch.append(p.gpa, item);3153 try p.scratch.append(p.gpa, item);
3366 if (p.eatToken(.comma) == null) break;3154 if (p.eatToken(.comma) == null) break;
3367 }3155 }
3368 if (scratch_top == p.scratch.items.len) {3156 if (scratch_top == p.scratch.items.len) {
3369 if (is_inline) p.tok_i -= 1;3157 if (is_inline) p.tok_i -= 1;
3370 return null_node;3158 return null;
3371 }3159 }
3372 }3160 }
3373 const arrow_token = try p.expectToken(.equal_angle_bracket_right);3161 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
3374 _ = try p.parsePtrIndexPayload();3162 _ = try p.parsePtrIndexPayload();
33753163
3376 const items = p.scratch.items[scratch_top..];3164 const items = p.scratch.items[scratch_top..];
3377 switch (items.len) {3165 if (items.len <= 1) {
3378 0 => return p.addNode(.{3166 return try p.addNode(.{
3379 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,3167 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
3380 .main_token = arrow_token,3168 .main_token = arrow_token,
3381 .data = .{3169 .data = .{ .opt_node_and_node = .{
3382 .lhs = 0,3170 if (items.len >= 1) items[0].toOptional() else .none,
3383 .rhs = try p.expectSingleAssignExpr(),3171 try p.expectSingleAssignExpr(),
3384 },3172 } },
3385 }),3173 });
3386 1 => return p.addNode(.{3174 } else {
3387 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,3175 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,3176 .tag = if (is_inline) .switch_case_inline else .switch_case,
3396 .main_token = arrow_token,3177 .main_token = arrow_token,
3397 .data = .{3178 .data = .{ .extra_and_node = .{
3398 .lhs = try p.addExtra(try p.listToSpan(items)),3179 try p.addExtra(try p.listToSpan(items)),
3399 .rhs = try p.expectSingleAssignExpr(),3180 try p.expectSingleAssignExpr(),
3400 },3181 } },
3401 }),3182 });
3402 }3183 }
3403}3184}
34043185
3405/// SwitchItem <- Expr (DOT3 Expr)?3186/// SwitchItem <- Expr (DOT3 Expr)?
3406fn parseSwitchItem(p: *Parse) !Node.Index {3187fn parseSwitchItem(p: *Parse) !?Node.Index {
3407 const expr = try p.parseExpr();3188 const expr = try p.parseExpr() orelse return null;
3408 if (expr == 0) return null_node;
34093189
3410 if (p.eatToken(.ellipsis3)) |token| {3190 if (p.eatToken(.ellipsis3)) |token| {
3411 return p.addNode(.{3191 return try p.addNode(.{
3412 .tag = .switch_range,3192 .tag = .switch_range,
3413 .main_token = token,3193 .main_token = token,
3414 .data = .{3194 .data = .{ .node_and_node = .{
3415 .lhs = expr,3195 expr,
3416 .rhs = try p.expectExpr(),3196 try p.expectExpr(),
3417 },3197 } },
3418 });3198 });
3419 }3199 }
3420 return expr;3200 return expr;
3421}3201}
34223202
3203/// The following invariant will hold:
3204/// - `(bit_range_start == .none) == (bit_range_end == .none)`
3205/// - `bit_range_start != .none` implies `align_node != .none`
3206/// - `bit_range_end != .none` implies `align_node != .none`
3423const PtrModifiers = struct {3207const PtrModifiers = struct {
3424 align_node: Node.Index,3208 align_node: Node.OptionalIndex,
3425 addrspace_node: Node.Index,3209 addrspace_node: Node.OptionalIndex,
3426 bit_range_start: Node.Index,3210 bit_range_start: Node.OptionalIndex,
3427 bit_range_end: Node.Index,3211 bit_range_end: Node.OptionalIndex,
3428};3212};
34293213
3430fn parsePtrModifiers(p: *Parse) !PtrModifiers {3214fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3431 var result: PtrModifiers = .{3215 var result: PtrModifiers = .{
3432 .align_node = 0,3216 .align_node = .none,
3433 .addrspace_node = 0,3217 .addrspace_node = .none,
3434 .bit_range_start = 0,3218 .bit_range_start = .none,
3435 .bit_range_end = 0,3219 .bit_range_end = .none,
3436 };3220 };
3437 var saw_const = false;3221 var saw_const = false;
3438 var saw_volatile = false;3222 var saw_volatile = false;
3439 var saw_allowzero = false;3223 var saw_allowzero = false;
3440 while (true) {3224 while (true) {
3441 switch (p.token_tags[p.tok_i]) {3225 switch (p.tokenTag(p.tok_i)) {
3442 .keyword_align => {3226 .keyword_align => {
3443 if (result.align_node != 0) {3227 if (result.align_node != .none) {
3444 try p.warn(.extra_align_qualifier);3228 try p.warn(.extra_align_qualifier);
3445 }3229 }
3446 p.tok_i += 1;3230 p.tok_i += 1;
3447 _ = try p.expectToken(.l_paren);3231 _ = try p.expectToken(.l_paren);
3448 result.align_node = try p.expectExpr();3232 result.align_node = (try p.expectExpr()).toOptional();
34493233
3450 if (p.eatToken(.colon)) |_| {3234 if (p.eatToken(.colon)) |_| {
3451 result.bit_range_start = try p.expectExpr();3235 result.bit_range_start = (try p.expectExpr()).toOptional();
3452 _ = try p.expectToken(.colon);3236 _ = try p.expectToken(.colon);
3453 result.bit_range_end = try p.expectExpr();3237 result.bit_range_end = (try p.expectExpr()).toOptional();
3454 }3238 }
34553239
3456 _ = try p.expectToken(.r_paren);3240 _ = try p.expectToken(.r_paren);
...@@ -3477,10 +3261,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {...@@ -3477,10 +3261,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3477 saw_allowzero = true;3261 saw_allowzero = true;
3478 },3262 },
3479 .keyword_addrspace => {3263 .keyword_addrspace => {
3480 if (result.addrspace_node != 0) {3264 if (result.addrspace_node != .none) {
3481 try p.warn(.extra_addrspace_qualifier);3265 try p.warn(.extra_addrspace_qualifier);
3482 }3266 }
3483 result.addrspace_node = try p.parseAddrSpace();3267 result.addrspace_node = .fromOptional(try p.parseAddrSpace());
3484 },3268 },
3485 else => return result,3269 else => return result,
3486 }3270 }
...@@ -3492,110 +3276,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {...@@ -3492,110 +3276,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers {
3492/// / DOT IDENTIFIER3276/// / DOT IDENTIFIER
3493/// / DOTASTERISK3277/// / DOTASTERISK
3494/// / DOTQUESTIONMARK3278/// / DOTQUESTIONMARK
3495fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {3279fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
3496 switch (p.token_tags[p.tok_i]) {3280 switch (p.tokenTag(p.tok_i)) {
3497 .l_bracket => {3281 .l_bracket => {
3498 const lbracket = p.nextToken();3282 const lbracket = p.nextToken();
3499 const index_expr = try p.expectExpr();3283 const index_expr = try p.expectExpr();
35003284
3501 if (p.eatToken(.ellipsis2)) |_| {3285 if (p.eatToken(.ellipsis2)) |_| {
3502 const end_expr = try p.parseExpr();3286 const opt_end_expr = try p.parseExpr();
3503 if (p.eatToken(.colon)) |_| {3287 if (p.eatToken(.colon)) |_| {
3504 const sentinel = try p.expectExpr();3288 const sentinel = try p.expectExpr();
3505 _ = try p.expectToken(.r_bracket);3289 _ = try p.expectToken(.r_bracket);
3506 return p.addNode(.{3290 return try p.addNode(.{
3507 .tag = .slice_sentinel,3291 .tag = .slice_sentinel,
3508 .main_token = lbracket,3292 .main_token = lbracket,
3509 .data = .{3293 .data = .{ .node_and_extra = .{
3510 .lhs = lhs,3294 lhs, try p.addExtra(Node.SliceSentinel{
3511 .rhs = try p.addExtra(Node.SliceSentinel{
3512 .start = index_expr,3295 .start = index_expr,
3513 .end = end_expr,3296 .end = .fromOptional(opt_end_expr),
3514 .sentinel = sentinel,3297 .sentinel = sentinel,
3515 }),3298 }),
3516 },3299 } },
3517 });3300 });
3518 }3301 }
3519 _ = try p.expectToken(.r_bracket);3302 _ = try p.expectToken(.r_bracket);
3520 if (end_expr == 0) {3303 const end_expr = opt_end_expr orelse {
3521 return p.addNode(.{3304 return try p.addNode(.{
3522 .tag = .slice_open,3305 .tag = .slice_open,
3523 .main_token = lbracket,3306 .main_token = lbracket,
3524 .data = .{3307 .data = .{ .node_and_node = .{
3525 .lhs = lhs,3308 lhs,
3526 .rhs = index_expr,3309 index_expr,
3527 },3310 } },
3528 });3311 });
3529 }3312 };
3530 return p.addNode(.{3313 return try p.addNode(.{
3531 .tag = .slice,3314 .tag = .slice,
3532 .main_token = lbracket,3315 .main_token = lbracket,
3533 .data = .{3316 .data = .{ .node_and_extra = .{
3534 .lhs = lhs,3317 lhs, try p.addExtra(Node.Slice{
3535 .rhs = try p.addExtra(Node.Slice{
3536 .start = index_expr,3318 .start = index_expr,
3537 .end = end_expr,3319 .end = end_expr,
3538 }),3320 }),
3539 },3321 } },
3540 });3322 });
3541 }3323 }
3542 _ = try p.expectToken(.r_bracket);3324 _ = try p.expectToken(.r_bracket);
3543 return p.addNode(.{3325 return try p.addNode(.{
3544 .tag = .array_access,3326 .tag = .array_access,
3545 .main_token = lbracket,3327 .main_token = lbracket,
3546 .data = .{3328 .data = .{ .node_and_node = .{
3547 .lhs = lhs,3329 lhs,
3548 .rhs = index_expr,3330 index_expr,
3549 },3331 } },
3550 });3332 });
3551 },3333 },
3552 .period_asterisk => return p.addNode(.{3334 .period_asterisk => return try p.addNode(.{
3553 .tag = .deref,3335 .tag = .deref,
3554 .main_token = p.nextToken(),3336 .main_token = p.nextToken(),
3555 .data = .{3337 .data = .{ .node = lhs },
3556 .lhs = lhs,
3557 .rhs = undefined,
3558 },
3559 }),3338 }),
3560 .invalid_periodasterisks => {3339 .invalid_periodasterisks => {
3561 try p.warn(.asterisk_after_ptr_deref);3340 try p.warn(.asterisk_after_ptr_deref);
3562 return p.addNode(.{3341 return try p.addNode(.{
3563 .tag = .deref,3342 .tag = .deref,
3564 .main_token = p.nextToken(),3343 .main_token = p.nextToken(),
3565 .data = .{3344 .data = .{ .node = lhs },
3566 .lhs = lhs,
3567 .rhs = undefined,
3568 },
3569 });3345 });
3570 },3346 },
3571 .period => switch (p.token_tags[p.tok_i + 1]) {3347 .period => switch (p.tokenTag(p.tok_i + 1)) {
3572 .identifier => return p.addNode(.{3348 .identifier => return try p.addNode(.{
3573 .tag = .field_access,3349 .tag = .field_access,
3574 .main_token = p.nextToken(),3350 .main_token = p.nextToken(),
3575 .data = .{3351 .data = .{ .node_and_token = .{
3576 .lhs = lhs,3352 lhs,
3577 .rhs = p.nextToken(),3353 p.nextToken(),
3578 },3354 } },
3579 }),3355 }),
3580 .question_mark => return p.addNode(.{3356 .question_mark => return try p.addNode(.{
3581 .tag = .unwrap_optional,3357 .tag = .unwrap_optional,
3582 .main_token = p.nextToken(),3358 .main_token = p.nextToken(),
3583 .data = .{3359 .data = .{ .node_and_token = .{
3584 .lhs = lhs,3360 lhs,
3585 .rhs = p.nextToken(),3361 p.nextToken(),
3586 },3362 } },
3587 }),3363 }),
3588 .l_brace => {3364 .l_brace => {
3589 // this a misplaced `.{`, handle the error somewhere else3365 // this a misplaced `.{`, handle the error somewhere else
3590 return null_node;3366 return null;
3591 },3367 },
3592 else => {3368 else => {
3593 p.tok_i += 1;3369 p.tok_i += 1;
3594 try p.warn(.expected_suffix_op);3370 try p.warn(.expected_suffix_op);
3595 return null_node;3371 return null;
3596 },3372 },
3597 },3373 },
3598 else => return null_node,3374 else => return null,
3599 }3375 }
3600}3376}
36013377
...@@ -3608,17 +3384,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {...@@ -3608,17 +3384,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index {
3608/// / KEYWORD_opaque3384/// / KEYWORD_opaque
3609/// / KEYWORD_enum (LPAREN Expr RPAREN)?3385/// / KEYWORD_enum (LPAREN Expr RPAREN)?
3610/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?3386/// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
3611fn parseContainerDeclAuto(p: *Parse) !Node.Index {3387fn parseContainerDeclAuto(p: *Parse) !?Node.Index {
3612 const main_token = p.nextToken();3388 const main_token = p.nextToken();
3613 const arg_expr = switch (p.token_tags[main_token]) {3389 const arg_expr = switch (p.tokenTag(main_token)) {
3614 .keyword_opaque => null_node,3390 .keyword_opaque => null,
3615 .keyword_struct, .keyword_enum => blk: {3391 .keyword_struct, .keyword_enum => blk: {
3616 if (p.eatToken(.l_paren)) |_| {3392 if (p.eatToken(.l_paren)) |_| {
3617 const expr = try p.expectExpr();3393 const expr = try p.expectExpr();
3618 _ = try p.expectToken(.r_paren);3394 _ = try p.expectToken(.r_paren);
3619 break :blk expr;3395 break :blk expr;
3620 } else {3396 } else {
3621 break :blk null_node;3397 break :blk null;
3622 }3398 }
3623 },3399 },
3624 .keyword_union => blk: {3400 .keyword_union => blk: {
...@@ -3633,16 +3409,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3633,16 +3409,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3633 const members = try p.parseContainerMembers();3409 const members = try p.parseContainerMembers();
3634 const members_span = try members.toSpan(p);3410 const members_span = try members.toSpan(p);
3635 _ = try p.expectToken(.r_brace);3411 _ = try p.expectToken(.r_brace);
3636 return p.addNode(.{3412 return try p.addNode(.{
3637 .tag = switch (members.trailing) {3413 .tag = switch (members.trailing) {
3638 true => .tagged_union_enum_tag_trailing,3414 true => .tagged_union_enum_tag_trailing,
3639 false => .tagged_union_enum_tag,3415 false => .tagged_union_enum_tag,
3640 },3416 },
3641 .main_token = main_token,3417 .main_token = main_token,
3642 .data = .{3418 .data = .{ .node_and_extra = .{
3643 .lhs = enum_tag_expr,3419 enum_tag_expr,
3644 .rhs = try p.addExtra(members_span),3420 try p.addExtra(members_span),
3645 },3421 } },
3646 });3422 });
3647 } else {3423 } else {
3648 _ = try p.expectToken(.r_paren);3424 _ = try p.expectToken(.r_paren);
...@@ -3651,29 +3427,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3651,29 +3427,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3651 const members = try p.parseContainerMembers();3427 const members = try p.parseContainerMembers();
3652 _ = try p.expectToken(.r_brace);3428 _ = try p.expectToken(.r_brace);
3653 if (members.len <= 2) {3429 if (members.len <= 2) {
3654 return p.addNode(.{3430 return try p.addNode(.{
3655 .tag = switch (members.trailing) {3431 .tag = switch (members.trailing) {
3656 true => .tagged_union_two_trailing,3432 true => .tagged_union_two_trailing,
3657 false => .tagged_union_two,3433 false => .tagged_union_two,
3658 },3434 },
3659 .main_token = main_token,3435 .main_token = main_token,
3660 .data = .{3436 .data = members.data,
3661 .lhs = members.lhs,
3662 .rhs = members.rhs,
3663 },
3664 });3437 });
3665 } else {3438 } else {
3666 const span = try members.toSpan(p);3439 const span = try members.toSpan(p);
3667 return p.addNode(.{3440 return try p.addNode(.{
3668 .tag = switch (members.trailing) {3441 .tag = switch (members.trailing) {
3669 true => .tagged_union_trailing,3442 true => .tagged_union_trailing,
3670 false => .tagged_union,3443 false => .tagged_union,
3671 },3444 },
3672 .main_token = main_token,3445 .main_token = main_token,
3673 .data = .{3446 .data = .{ .extra_range = span },
3674 .lhs = span.start,
3675 .rhs = span.end,
3676 },
3677 });3447 });
3678 }3448 }
3679 }3449 }
...@@ -3683,7 +3453,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3683,7 +3453,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3683 break :blk expr;3453 break :blk expr;
3684 }3454 }
3685 } else {3455 } else {
3686 break :blk null_node;3456 break :blk null;
3687 }3457 }
3688 },3458 },
3689 else => {3459 else => {
...@@ -3694,48 +3464,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3694,48 +3464,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3694 _ = try p.expectToken(.l_brace);3464 _ = try p.expectToken(.l_brace);
3695 const members = try p.parseContainerMembers();3465 const members = try p.parseContainerMembers();
3696 _ = try p.expectToken(.r_brace);3466 _ = try p.expectToken(.r_brace);
3697 if (arg_expr == 0) {3467 if (arg_expr == null) {
3698 if (members.len <= 2) {3468 if (members.len <= 2) {
3699 return p.addNode(.{3469 return try p.addNode(.{
3700 .tag = switch (members.trailing) {3470 .tag = switch (members.trailing) {
3701 true => .container_decl_two_trailing,3471 true => .container_decl_two_trailing,
3702 false => .container_decl_two,3472 false => .container_decl_two,
3703 },3473 },
3704 .main_token = main_token,3474 .main_token = main_token,
3705 .data = .{3475 .data = members.data,
3706 .lhs = members.lhs,
3707 .rhs = members.rhs,
3708 },
3709 });3476 });
3710 } else {3477 } else {
3711 const span = try members.toSpan(p);3478 const span = try members.toSpan(p);
3712 return p.addNode(.{3479 return try p.addNode(.{
3713 .tag = switch (members.trailing) {3480 .tag = switch (members.trailing) {
3714 true => .container_decl_trailing,3481 true => .container_decl_trailing,
3715 false => .container_decl,3482 false => .container_decl,
3716 },3483 },
3717 .main_token = main_token,3484 .main_token = main_token,
3718 .data = .{3485 .data = .{ .extra_range = span },
3719 .lhs = span.start,
3720 .rhs = span.end,
3721 },
3722 });3486 });
3723 }3487 }
3724 } else {3488 } else {
3725 const span = try members.toSpan(p);3489 const span = try members.toSpan(p);
3726 return p.addNode(.{3490 return try p.addNode(.{
3727 .tag = switch (members.trailing) {3491 .tag = switch (members.trailing) {
3728 true => .container_decl_arg_trailing,3492 true => .container_decl_arg_trailing,
3729 false => .container_decl_arg,3493 false => .container_decl_arg,
3730 },3494 },
3731 .main_token = main_token,3495 .main_token = main_token,
3732 .data = .{3496 .data = .{ .node_and_extra = .{
3733 .lhs = arg_expr,3497 arg_expr.?,
3734 .rhs = try p.addExtra(Node.SubRange{3498 try p.addExtra(Node.SubRange{
3735 .start = span.start,3499 .start = span.start,
3736 .end = span.end,3500 .end = span.end,
3737 }),3501 }),
3738 },3502 } },
3739 });3503 });
3740 }3504 }
3741}3505}
...@@ -3744,24 +3508,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {...@@ -3744,24 +3508,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index {
3744/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.3508/// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'.
3745fn parseCStyleContainer(p: *Parse) Error!bool {3509fn parseCStyleContainer(p: *Parse) Error!bool {
3746 const main_token = p.tok_i;3510 const main_token = p.tok_i;
3747 switch (p.token_tags[p.tok_i]) {3511 switch (p.tokenTag(p.tok_i)) {
3748 .keyword_enum, .keyword_union, .keyword_struct => {},3512 .keyword_enum, .keyword_union, .keyword_struct => {},
3749 else => return false,3513 else => return false,
3750 }3514 }
3751 const identifier = p.tok_i + 1;3515 const identifier = p.tok_i + 1;
3752 if (p.token_tags[identifier] != .identifier) return false;3516 if (p.tokenTag(identifier) != .identifier) return false;
3753 p.tok_i += 2;3517 p.tok_i += 2;
37543518
3755 try p.warnMsg(.{3519 try p.warnMsg(.{
3756 .tag = .c_style_container,3520 .tag = .c_style_container,
3757 .token = identifier,3521 .token = identifier,
3758 .extra = .{ .expected_tag = p.token_tags[main_token] },3522 .extra = .{ .expected_tag = p.tokenTag(main_token) },
3759 });3523 });
3760 try p.warnMsg(.{3524 try p.warnMsg(.{
3761 .tag = .zig_style_container,3525 .tag = .zig_style_container,
3762 .is_note = true,3526 .is_note = true,
3763 .token = identifier,3527 .token = identifier,
3764 .extra = .{ .expected_tag = p.token_tags[main_token] },3528 .extra = .{ .expected_tag = p.tokenTag(main_token) },
3765 });3529 });
37663530
3767 _ = try p.expectToken(.l_brace);3531 _ = try p.expectToken(.l_brace);
...@@ -3774,8 +3538,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {...@@ -3774,8 +3538,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool {
3774/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.3538/// Holds temporary data until we are ready to construct the full ContainerDecl AST node.
3775///3539///
3776/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN3540/// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
3777fn parseByteAlign(p: *Parse) !Node.Index {3541fn parseByteAlign(p: *Parse) !?Node.Index {
3778 _ = p.eatToken(.keyword_align) orelse return null_node;3542 _ = p.eatToken(.keyword_align) orelse return null;
3779 _ = try p.expectToken(.l_paren);3543 _ = try p.expectToken(.l_paren);
3780 const expr = try p.expectExpr();3544 const expr = try p.expectExpr();
3781 _ = try p.expectToken(.r_paren);3545 _ = try p.expectToken(.r_paren);
...@@ -3788,12 +3552,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {...@@ -3788,12 +3552,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange {
3788 defer p.scratch.shrinkRetainingCapacity(scratch_top);3552 defer p.scratch.shrinkRetainingCapacity(scratch_top);
37893553
3790 while (true) {3554 while (true) {
3791 const item = try parseSwitchProng(p);3555 const item = try parseSwitchProng(p) orelse break;
3792 if (item == 0) break;
37933556
3794 try p.scratch.append(p.gpa, item);3557 try p.scratch.append(p.gpa, item);
37953558
3796 switch (p.token_tags[p.tok_i]) {3559 switch (p.tokenTag(p.tok_i)) {
3797 .comma => p.tok_i += 1,3560 .comma => p.tok_i += 1,
3798 // All possible delimiters.3561 // All possible delimiters.
3799 .colon, .r_paren, .r_brace, .r_bracket => break,3562 .colon, .r_paren, .r_brace, .r_bracket => break,
...@@ -3813,13 +3576,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {...@@ -3813,13 +3576,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
3813 while (true) {3576 while (true) {
3814 if (p.eatToken(.r_paren)) |_| break;3577 if (p.eatToken(.r_paren)) |_| break;
3815 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };3578 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
3816 const param = try p.expectParamDecl();3579 const opt_param = try p.expectParamDecl();
3817 if (param != 0) {3580 if (opt_param) |param| {
3818 try p.scratch.append(p.gpa, param);3581 try p.scratch.append(p.gpa, param);
3819 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {3582 } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) {
3820 if (varargs == .none) varargs = .seen;3583 if (varargs == .none) varargs = .seen;
3821 }3584 }
3822 switch (p.token_tags[p.tok_i]) {3585 switch (p.tokenTag(p.tok_i)) {
3823 .comma => p.tok_i += 1,3586 .comma => p.tok_i += 1,
3824 .r_paren => {3587 .r_paren => {
3825 p.tok_i += 1;3588 p.tok_i += 1;
...@@ -3835,9 +3598,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {...@@ -3835,9 +3598,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan {
3835 }3598 }
3836 const params = p.scratch.items[scratch_top..];3599 const params = p.scratch.items[scratch_top..];
3837 return switch (params.len) {3600 return switch (params.len) {
3838 0 => SmallSpan{ .zero_or_one = 0 },3601 0 => .{ .zero_or_one = .none },
3839 1 => SmallSpan{ .zero_or_one = params[0] },3602 1 => .{ .zero_or_one = params[0].toOptional() },
3840 else => SmallSpan{ .multi = try p.listToSpan(params) },3603 else => .{ .multi = try p.listToSpan(params) },
3841 };3604 };
3842}3605}
38433606
...@@ -3852,10 +3615,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3852,10 +3615,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3852 return p.addNode(.{3615 return p.addNode(.{
3853 .tag = .identifier,3616 .tag = .identifier,
3854 .main_token = builtin_token,3617 .main_token = builtin_token,
3855 .data = .{3618 .data = undefined,
3856 .lhs = undefined,
3857 .rhs = undefined,
3858 },
3859 });3619 });
3860 };3620 };
3861 const scratch_top = p.scratch.items.len;3621 const scratch_top = p.scratch.items.len;
...@@ -3864,7 +3624,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3864,7 +3624,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3864 if (p.eatToken(.r_paren)) |_| break;3624 if (p.eatToken(.r_paren)) |_| break;
3865 const param = try p.expectExpr();3625 const param = try p.expectExpr();
3866 try p.scratch.append(p.gpa, param);3626 try p.scratch.append(p.gpa, param);
3867 switch (p.token_tags[p.tok_i]) {3627 switch (p.tokenTag(p.tok_i)) {
3868 .comma => p.tok_i += 1,3628 .comma => p.tok_i += 1,
3869 .r_paren => {3629 .r_paren => {
3870 p.tok_i += 1;3630 p.tok_i += 1;
...@@ -3874,88 +3634,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {...@@ -3874,88 +3634,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index {
3874 else => try p.warn(.expected_comma_after_arg),3634 else => try p.warn(.expected_comma_after_arg),
3875 }3635 }
3876 }3636 }
3877 const comma = (p.token_tags[p.tok_i - 2] == .comma);3637 const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
3878 const params = p.scratch.items[scratch_top..];3638 const params = p.scratch.items[scratch_top..];
3879 switch (params.len) {3639 if (params.len <= 2) {
3880 0 => return p.addNode(.{3640 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,3641 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,
3890 .main_token = builtin_token,3642 .main_token = builtin_token,
3891 .data = .{3643 .data = .{ .opt_node_and_opt_node = .{
3892 .lhs = params[0],3644 if (params.len >= 1) .fromOptional(params[0]) else .none,
3893 .rhs = 0,3645 if (params.len >= 2) .fromOptional(params[1]) else .none,
3894 },3646 } },
3895 }),3647 });
3896 2 => return p.addNode(.{3648 } else {
3897 .tag = if (comma) .builtin_call_two_comma else .builtin_call_two,3649 const span = try p.listToSpan(params);
3650 return p.addNode(.{
3651 .tag = if (comma) .builtin_call_comma else .builtin_call,
3898 .main_token = builtin_token,3652 .main_token = builtin_token,
3899 .data = .{3653 .data = .{ .extra_range = span },
3900 .lhs = params[0],3654 });
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 }3655 }
3916}3656}
39173657
3918/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?3658/// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
3919fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {3659fn 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;3660 const if_token = p.eatToken(.keyword_if) orelse return null;
3921 _ = try p.expectToken(.l_paren);3661 _ = try p.expectToken(.l_paren);
3922 const condition = try p.expectExpr();3662 const condition = try p.expectExpr();
3923 _ = try p.expectToken(.r_paren);3663 _ = try p.expectToken(.r_paren);
3924 _ = try p.parsePtrPayload();3664 _ = try p.parsePtrPayload();
39253665
3926 const then_expr = try bodyParseFn(p);3666 const then_expr = try bodyParseFn(p);
3927 assert(then_expr != 0);
39283667
3929 _ = p.eatToken(.keyword_else) orelse return p.addNode(.{3668 _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{
3930 .tag = .if_simple,3669 .tag = .if_simple,
3931 .main_token = if_token,3670 .main_token = if_token,
3932 .data = .{3671 .data = .{ .node_and_node = .{
3933 .lhs = condition,3672 condition,
3934 .rhs = then_expr,3673 then_expr,
3935 },3674 } },
3936 });3675 });
3937 _ = try p.parsePayload();3676 _ = try p.parsePayload();
3938 const else_expr = try bodyParseFn(p);3677 const else_expr = try bodyParseFn(p);
3939 assert(else_expr != 0);
39403678
3941 return p.addNode(.{3679 return try p.addNode(.{
3942 .tag = .@"if",3680 .tag = .@"if",
3943 .main_token = if_token,3681 .main_token = if_token,
3944 .data = .{3682 .data = .{ .node_and_extra = .{
3945 .lhs = condition,3683 condition,
3946 .rhs = try p.addExtra(Node.If{3684 try p.addExtra(Node.If{
3947 .then_expr = then_expr,3685 .then_expr = then_expr,
3948 .else_expr = else_expr,3686 .else_expr = else_expr,
3949 }),3687 }),
3950 },3688 } },
3951 });3689 });
3952}3690}
39533691
3954/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?3692/// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
3955///3693///
3956/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?3694/// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
3957fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !Node.Index {3695fn 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;3696 const for_token = p.eatToken(.keyword_for) orelse return null;
39593697
3960 const scratch_top = p.scratch.items.len;3698 const scratch_top = p.scratch.items.len;
3961 defer p.scratch.shrinkRetainingCapacity(scratch_top);3699 defer p.scratch.shrinkRetainingCapacity(scratch_top);
...@@ -3969,27 +3707,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N...@@ -3969,27 +3707,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N
3969 try p.scratch.append(p.gpa, else_expr);3707 try p.scratch.append(p.gpa, else_expr);
3970 has_else = true;3708 has_else = true;
3971 } else if (inputs == 1) {3709 } else if (inputs == 1) {
3972 return p.addNode(.{3710 return try p.addNode(.{
3973 .tag = .for_simple,3711 .tag = .for_simple,
3974 .main_token = for_token,3712 .main_token = for_token,
3975 .data = .{3713 .data = .{ .node_and_node = .{
3976 .lhs = p.scratch.items[scratch_top],3714 p.scratch.items[scratch_top],
3977 .rhs = then_expr,3715 then_expr,
3978 },3716 } },
3979 });3717 });
3980 } else {3718 } else {
3981 try p.scratch.append(p.gpa, then_expr);3719 try p.scratch.append(p.gpa, then_expr);
3982 }3720 }
3983 return p.addNode(.{3721 return try p.addNode(.{
3984 .tag = .@"for",3722 .tag = .@"for",
3985 .main_token = for_token,3723 .main_token = for_token,
3986 .data = .{3724 .data = .{ .@"for" = .{
3987 .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start,3725 (try p.listToSpan(p.scratch.items[scratch_top..])).start,
3988 .rhs = @as(u32, @bitCast(Node.For{3726 .{ .inputs = @intCast(inputs), .has_else = has_else },
3989 .inputs = @as(u31, @intCast(inputs)),3727 } },
3990 .has_else = has_else,
3991 })),
3992 },
3993 });3728 });
3994}3729}
39953730
...@@ -4011,21 +3746,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {...@@ -4011,21 +3746,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex {
4011}3746}
40123747
4013fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool {3748fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool {
4014 return std.mem.indexOfScalar(u8, p.source[p.token_starts[token1]..p.token_starts[token2]], '\n') == null;3749 return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null;
4015}3750}
40163751
4017fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {3752fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex {
4018 return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null;3753 return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null;
3754}
3755
3756fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex {
3757 const available_tags = p.tokens.items(.tag)[p.tok_i..];
3758 if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null;
3759 const result = p.tok_i;
3760 p.tok_i += @intCast(tags.len);
3761 return result;
4019}3762}
40203763
4021fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {3764fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex {
4022 const token = p.nextToken();3765 const token = p.nextToken();
4023 assert(p.token_tags[token] == tag);3766 assert(p.tokenTag(token) == tag);
4024 return token;3767 return token;
4025}3768}
40263769
4027fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {3770fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4028 if (p.token_tags[p.tok_i] != tag) {3771 if (p.tokenTag(p.tok_i) != tag) {
4029 return p.failMsg(.{3772 return p.failMsg(.{
4030 .tag = .expected_token,3773 .tag = .expected_token,
4031 .token = p.tok_i,3774 .token = p.tok_i,
...@@ -4036,7 +3779,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {...@@ -4036,7 +3779,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex {
4036}3779}
40373780
4038fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {3781fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void {
4039 if (p.token_tags[p.tok_i] == .semicolon) {3782 if (p.tokenTag(p.tok_i) == .semicolon) {
4040 _ = p.nextToken();3783 _ = p.nextToken();
4041 return;3784 return;
4042 }3785 }
...@@ -4050,8 +3793,6 @@ fn nextToken(p: *Parse) TokenIndex {...@@ -4050,8 +3793,6 @@ fn nextToken(p: *Parse) TokenIndex {
4050 return result;3793 return result;
4051}3794}
40523795
4053const null_node: Node.Index = 0;
4054
4055const Parse = @This();3796const Parse = @This();
4056const std = @import("../std.zig");3797const std = @import("../std.zig");
4057const assert = std.debug.assert;3798const assert = std.debug.assert;
...@@ -4060,6 +3801,8 @@ const Ast = std.zig.Ast;...@@ -4060,6 +3801,8 @@ const Ast = std.zig.Ast;
4060const Node = Ast.Node;3801const Node = Ast.Node;
4061const AstError = Ast.Error;3802const AstError = Ast.Error;
4062const TokenIndex = Ast.TokenIndex;3803const TokenIndex = Ast.TokenIndex;
3804const OptionalTokenIndex = Ast.OptionalTokenIndex;
3805const ExtraIndex = Ast.ExtraIndex;
4063const Token = std.zig.Token;3806const Token = std.zig.Token;
40643807
4065test {3808test {
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+43-55
...@@ -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,8 +248,8 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -251,8 +248,8 @@ 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.addErrorNode(node, "array indexing is not allowed in ZON", .{}),255 .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}),
...@@ -262,12 +259,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator...@@ -262,12 +259,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
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+459-487
...@@ -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,23 +142,20 @@ fn renderMember(...@@ -141,23 +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 token_tags = tree.tokens.items(.tag);
145 const main_tokens = tree.nodes.items(.main_token);
146 const datas = tree.nodes.items(.data);
147 if (r.fixups.omit_nodes.contains(decl)) return;145 if (r.fixups.omit_nodes.contains(decl)) return;
148 try renderDocComments(r, tree.firstToken(decl));146 try renderDocComments(r, tree.firstToken(decl));
149 switch (tree.nodes.items(.tag)[decl]) {147 switch (tree.nodeTag(decl)) {
150 .fn_decl => {148 .fn_decl => {
151 // Some examples:149 // Some examples:
152 // pub extern "foo" fn ...150 // pub extern "foo" fn ...
153 // export fn ...151 // export fn ...
154 const fn_proto = datas[decl].lhs;152 const fn_proto, const body_node = tree.nodeData(decl).node_and_node;
155 const fn_token = main_tokens[fn_proto];153 const fn_token = tree.nodeMainToken(fn_proto);
156 // Go back to the first token we should render here.154 // Go back to the first token we should render here.
157 var i = fn_token;155 var i = fn_token;
158 while (i > 0) {156 while (i > 0) {
159 i -= 1;157 i -= 1;
160 switch (token_tags[i]) {158 switch (tree.tokenTag(i)) {
161 .keyword_extern,159 .keyword_extern,
162 .keyword_export,160 .keyword_export,
163 .keyword_pub,161 .keyword_pub,
...@@ -172,31 +170,34 @@ fn renderMember(...@@ -172,31 +170,34 @@ fn renderMember(
172 },170 },
173 }171 }
174 }172 }
173
175 while (i < fn_token) : (i += 1) {174 while (i < fn_token) : (i += 1) {
176 try renderToken(r, i, .space);175 try renderToken(r, i, .space);
177 }176 }
178 switch (tree.nodes.items(.tag)[fn_proto]) {177 switch (tree.nodeTag(fn_proto)) {
179 .fn_proto_one, .fn_proto => {178 .fn_proto_one, .fn_proto => {
180 const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one)179 var buf: [1]Ast.Node.Index = undefined;
181 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
182 else182 else
183 tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr;183 tree.fnProto(fn_proto).ast.callconv_expr;
184
184 // 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
185 if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) {186 if (opt_callconv_expr.unwrap()) |callconv_expr| {
186 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) {187 if (tree.nodeTag(callconv_expr) == .enum_literal) {
187 try ais.writer().writeAll("inline ");188 if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
189 try ais.writer().writeAll("inline ");
190 }
188 }191 }
189 }192 }
190 },193 },
191 .fn_proto_simple, .fn_proto_multi => {},194 .fn_proto_simple, .fn_proto_multi => {},
192 else => unreachable,195 else => unreachable,
193 }196 }
194 assert(datas[decl].rhs != 0);
195 try renderExpression(r, fn_proto, .space);197 try renderExpression(r, fn_proto, .space);
196 const body_node = datas[decl].rhs;
197 if (r.fixups.gut_functions.contains(decl)) {198 if (r.fixups.gut_functions.contains(decl)) {
198 try ais.pushIndent(.normal);199 try ais.pushIndent(.normal);
199 const lbrace = tree.nodes.items(.main_token)[body_node];200 const lbrace = tree.nodeMainToken(body_node);
200 try renderToken(r, lbrace, .newline);201 try renderToken(r, lbrace, .newline);
201 try discardAllParams(r, fn_proto);202 try discardAllParams(r, fn_proto);
202 try ais.writer().writeAll("@trap();");203 try ais.writer().writeAll("@trap();");
...@@ -205,7 +206,7 @@ fn renderMember(...@@ -205,7 +206,7 @@ fn renderMember(
205 try renderToken(r, tree.lastToken(body_node), space); // rbrace206 try renderToken(r, tree.lastToken(body_node), space); // rbrace
206 } else if (r.fixups.unused_var_decls.count() != 0) {207 } else if (r.fixups.unused_var_decls.count() != 0) {
207 try ais.pushIndent(.normal);208 try ais.pushIndent(.normal);
208 const lbrace = tree.nodes.items(.main_token)[body_node];209 const lbrace = tree.nodeMainToken(body_node);
209 try renderToken(r, lbrace, .newline);210 try renderToken(r, lbrace, .newline);
210211
211 var fn_proto_buf: [1]Ast.Node.Index = undefined;212 var fn_proto_buf: [1]Ast.Node.Index = undefined;
...@@ -213,7 +214,7 @@ fn renderMember(...@@ -213,7 +214,7 @@ fn renderMember(
213 var it = full_fn_proto.iterate(&tree);214 var it = full_fn_proto.iterate(&tree);
214 while (it.next()) |param| {215 while (it.next()) |param| {
215 const name_ident = param.name_token.?;216 const name_ident = param.name_token.?;
216 assert(token_tags[name_ident] == .identifier);217 assert(tree.tokenTag(name_ident) == .identifier);
217 if (r.fixups.unused_var_decls.contains(name_ident)) {218 if (r.fixups.unused_var_decls.contains(name_ident)) {
218 const w = ais.writer();219 const w = ais.writer();
219 try w.writeAll("_ = ");220 try w.writeAll("_ = ");
...@@ -235,11 +236,11 @@ fn renderMember(...@@ -235,11 +236,11 @@ fn renderMember(
235 => {236 => {
236 // Extern function prototypes are parsed as these tags.237 // Extern function prototypes are parsed as these tags.
237 // Go back to the first token we should render here.238 // Go back to the first token we should render here.
238 const fn_token = main_tokens[decl];239 const fn_token = tree.nodeMainToken(decl);
239 var i = fn_token;240 var i = fn_token;
240 while (i > 0) {241 while (i > 0) {
241 i -= 1;242 i -= 1;
242 switch (token_tags[i]) {243 switch (tree.tokenTag(i)) {
243 .keyword_extern,244 .keyword_extern,
244 .keyword_export,245 .keyword_export,
245 .keyword_pub,246 .keyword_pub,
...@@ -262,9 +263,9 @@ fn renderMember(...@@ -262,9 +263,9 @@ fn renderMember(
262 },263 },
263264
264 .@"usingnamespace" => {265 .@"usingnamespace" => {
265 const main_token = main_tokens[decl];266 const main_token = tree.nodeMainToken(decl);
266 const expr = datas[decl].lhs;267 const expr = tree.nodeData(decl).node;
267 if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) {268 if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) {
268 try renderToken(r, main_token - 1, .space); // pub269 try renderToken(r, main_token - 1, .space); // pub
269 }270 }
270 try renderToken(r, main_token, .space); // usingnamespace271 try renderToken(r, main_token, .space); // usingnamespace
...@@ -283,15 +284,17 @@ fn renderMember(...@@ -283,15 +284,17 @@ fn renderMember(
283 },284 },
284285
285 .test_decl => {286 .test_decl => {
286 const test_token = main_tokens[decl];287 const test_token = tree.nodeMainToken(decl);
288 const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node;
287 try renderToken(r, test_token, .space);289 try renderToken(r, test_token, .space);
288 const test_name_tag = token_tags[test_token + 1];290 if (opt_name_token.unwrap()) |name_token| {
289 switch (test_name_tag) {291 switch (tree.tokenTag(name_token)) {
290 .string_literal => try renderToken(r, test_token + 1, .space),292 .string_literal => try renderToken(r, name_token, .space),
291 .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing),293 .identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing),
292 else => {},294 else => unreachable,
295 }
293 }296 }
294 try renderExpression(r, datas[decl].rhs, space);297 try renderExpression(r, block_node, space);
295 },298 },
296299
297 .container_field_init,300 .container_field_init,
...@@ -319,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa...@@ -319,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa
319fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {322fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
320 const tree = r.tree;323 const tree = r.tree;
321 const ais = r.ais;324 const ais = r.ais;
322 const token_tags = tree.tokens.items(.tag);
323 const main_tokens = tree.nodes.items(.main_token);
324 const node_tags = tree.nodes.items(.tag);
325 const datas = tree.nodes.items(.data);
326 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {325 if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
327 try ais.writer().writeAll(replacement);326 try ais.writer().writeAll(replacement);
328 try renderOnlySpace(r, space);327 try renderOnlySpace(r, space);
...@@ -330,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -330,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
330 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {329 } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
331 return renderExpression(r, replacement, space);330 return renderExpression(r, replacement, space);
332 }331 }
333 switch (node_tags[node]) {332 switch (tree.nodeTag(node)) {
334 .identifier => {333 .identifier => {
335 const token_index = main_tokens[node];334 const token_index = tree.nodeMainToken(node);
336 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);335 return renderIdentifier(r, token_index, space, .preserve_when_shadowing);
337 },336 },
338337
...@@ -341,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -341,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
341 .unreachable_literal,340 .unreachable_literal,
342 .anyframe_literal,341 .anyframe_literal,
343 .string_literal,342 .string_literal,
344 => return renderToken(r, main_tokens[node], space),343 => return renderToken(r, tree.nodeMainToken(node), space),
345344
346 .multiline_string_literal => {345 .multiline_string_literal => {
347 try ais.maybeInsertNewline();346 try ais.maybeInsertNewline();
348347
349 var i = datas[node].lhs;348 const first_tok, const last_tok = tree.nodeData(node).token_and_token;
350 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);
351355
352 // dedent the next thing that comes after a multiline string literal356 // dedent the next thing that comes after a multiline string literal
353 if (!ais.indentStackEmpty() and357 if (!ais.indentStackEmpty() and
354 token_tags[i] != .colon and358 next_token_tag != .colon and
355 ((token_tags[i] != .semicolon and token_tags[i] != .comma) or359 ((next_token_tag != .semicolon and next_token_tag != .comma) or
356 ais.lastSpaceModeIndent() < ais.currentIndent()))360 ais.lastSpaceModeIndent() < ais.currentIndent()))
357 {361 {
358 ais.popIndent();362 ais.popIndent();
...@@ -361,16 +365,17 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -361,16 +365,17 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
361365
362 switch (space) {366 switch (space) {
363 .none, .space, .newline, .skip => {},367 .none, .space, .newline, .skip => {},
364 .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),
365 .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),
366 .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),
367 }371 }
368 },372 },
369373
370 .error_value => {374 .error_value => {
371 try renderToken(r, main_tokens[node], .none);375 const main_token = tree.nodeMainToken(node);
372 try renderToken(r, main_tokens[node] + 1, .none);376 try renderToken(r, main_token, .none);
373 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);
374 },379 },
375380
376 .block_two,381 .block_two,
...@@ -384,12 +389,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -384,12 +389,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
384 },389 },
385390
386 .@"errdefer" => {391 .@"errdefer" => {
387 const defer_token = main_tokens[node];392 const defer_token = tree.nodeMainToken(node);
388 const payload_token = datas[node].lhs;393 const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node;
389 const expr = datas[node].rhs;
390394
391 try renderToken(r, defer_token, .space);395 try renderToken(r, defer_token, .space);
392 if (payload_token != 0) {396 if (maybe_payload_token.unwrap()) |payload_token| {
393 try renderToken(r, payload_token - 1, .none); // |397 try renderToken(r, payload_token - 1, .none); // |
394 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier398 try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier
395 try renderToken(r, payload_token + 1, .space); // |399 try renderToken(r, payload_token + 1, .space); // |
...@@ -397,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -397,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
397 return renderExpression(r, expr, space);401 return renderExpression(r, expr, space);
398 },402 },
399403
400 .@"defer" => {404 .@"defer",
401 const defer_token = main_tokens[node];405 .@"comptime",
402 const expr = datas[node].rhs;406 .@"nosuspend",
403 try renderToken(r, defer_token, .space);407 .@"suspend",
404 return renderExpression(r, expr, space);408 => {
405 },409 const main_token = tree.nodeMainToken(node);
406 .@"comptime", .@"nosuspend" => {410 const item = tree.nodeData(node).node;
407 const comptime_token = main_tokens[node];411 try renderToken(r, main_token, .space);
408 const block = datas[node].lhs;412 return renderExpression(r, item, space);
409 try renderToken(r, comptime_token, .space);
410 return renderExpression(r, block, space);
411 },
412
413 .@"suspend" => {
414 const suspend_token = main_tokens[node];
415 const body = datas[node].lhs;
416 try renderToken(r, suspend_token, .space);
417 return renderExpression(r, body, space);
418 },413 },
419414
420 .@"catch" => {415 .@"catch" => {
421 const main_token = main_tokens[node];416 const main_token = tree.nodeMainToken(node);
422 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);
423419
424 const same_line = tree.tokensOnSameLine(main_token, fallback_first);420 const same_line = tree.tokensOnSameLine(main_token, fallback_first);
425 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;
426422
427 try renderExpression(r, datas[node].lhs, .space); // target423 try renderExpression(r, lhs, .space); // target
428424
429 try ais.pushIndent(.normal);425 try ais.pushIndent(.normal);
430 if (token_tags[fallback_first - 1] == .pipe) {426 if (tree.tokenTag(fallback_first - 1) == .pipe) {
431 try renderToken(r, main_token, .space); // catch keyword427 try renderToken(r, main_token, .space); // catch keyword
432 try renderToken(r, main_token + 1, .none); // pipe428 try renderToken(r, main_token + 1, .none); // pipe
433 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier429 try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier
434 try renderToken(r, main_token + 3, after_op_space); // pipe430 try renderToken(r, main_token + 3, after_op_space); // pipe
435 } else {431 } else {
436 assert(token_tags[fallback_first - 1] == .keyword_catch);432 assert(tree.tokenTag(fallback_first - 1) == .keyword_catch);
437 try renderToken(r, main_token, after_op_space); // catch keyword433 try renderToken(r, main_token, after_op_space); // catch keyword
438 }434 }
439 try renderExpression(r, datas[node].rhs, space); // fallback435 try renderExpression(r, rhs, space); // fallback
440 ais.popIndent();436 ais.popIndent();
441 },437 },
442438
443 .field_access => {439 .field_access => {
444 const main_token = main_tokens[node];440 const lhs, const name_token = tree.nodeData(node).node_and_token;
445 const field_access = datas[node];441 const dot_token = name_token - 1;
446442
447 try ais.pushIndent(.field_access);443 try ais.pushIndent(.field_access);
448 try renderExpression(r, field_access.lhs, .none);444 try renderExpression(r, lhs, .none);
449445
450 // 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
451 // are on different lines.447 // are on different lines.
452 const lhs_last_token = tree.lastToken(field_access.lhs);448 const lhs_last_token = tree.lastToken(lhs);
453 const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1);449 const same_line = tree.tokensOnSameLine(lhs_last_token, name_token);
454 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();
455451
456 try renderToken(r, main_token, .none); // .452 try renderToken(r, dot_token, .none);
457453
458 try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field454 try renderIdentifier(r, name_token, space, .eagerly_unquote); // field
459 ais.popIndent();455 ais.popIndent();
460 },456 },
461457
462 .error_union,458 .error_union,
463 .switch_range,459 .switch_range,
464 => {460 => {
465 const infix = datas[node];461 const lhs, const rhs = tree.nodeData(node).node_and_node;
466 try renderExpression(r, infix.lhs, .none);462 try renderExpression(r, lhs, .none);
467 try renderToken(r, main_tokens[node], .none);463 try renderToken(r, tree.nodeMainToken(node), .none);
468 return renderExpression(r, infix.rhs, space);464 return renderExpression(r, rhs, space);
469 },465 },
470 .for_range => {466 .for_range => {
471 const infix = datas[node];467 const start, const opt_end = tree.nodeData(node).node_and_opt_node;
472 try renderExpression(r, infix.lhs, .none);468 try renderExpression(r, start, .none);
473 if (infix.rhs != 0) {469 if (opt_end.unwrap()) |end| {
474 try renderToken(r, main_tokens[node], .none);470 try renderToken(r, tree.nodeMainToken(node), .none);
475 return renderExpression(r, infix.rhs, space);471 return renderExpression(r, end, space);
476 } else {472 } else {
477 return renderToken(r, main_tokens[node], space);473 return renderToken(r, tree.nodeMainToken(node), space);
478 }474 }
479 },475 },
480476
...@@ -497,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -497,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
497 .assign_mul_wrap,493 .assign_mul_wrap,
498 .assign_mul_sat,494 .assign_mul_sat,
499 => {495 => {
500 const infix = datas[node];496 const lhs, const rhs = tree.nodeData(node).node_and_node;
501 try renderExpression(r, infix.lhs, .space);497 try renderExpression(r, lhs, .space);
502 const op_token = main_tokens[node];498 const op_token = tree.nodeMainToken(node);
503 try ais.pushIndent(.after_equals);499 try ais.pushIndent(.after_equals);
504 if (tree.tokensOnSameLine(op_token, op_token + 1)) {500 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
505 try renderToken(r, op_token, .space);501 try renderToken(r, op_token, .space);
506 } else {502 } else {
507 try renderToken(r, op_token, .newline);503 try renderToken(r, op_token, .newline);
508 }504 }
509 try renderExpression(r, infix.rhs, space);505 try renderExpression(r, rhs, space);
510 ais.popIndent();506 ais.popIndent();
511 },507 },
512508
...@@ -540,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -540,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
540 .sub_sat,536 .sub_sat,
541 .@"orelse",537 .@"orelse",
542 => {538 => {
543 const infix = datas[node];539 const lhs, const rhs = tree.nodeData(node).node_and_node;
544 try renderExpression(r, infix.lhs, .space);540 try renderExpression(r, lhs, .space);
545 const op_token = main_tokens[node];541 const op_token = tree.nodeMainToken(node);
546 try ais.pushIndent(.binop);542 try ais.pushIndent(.binop);
547 if (tree.tokensOnSameLine(op_token, op_token + 1)) {543 if (tree.tokensOnSameLine(op_token, op_token + 1)) {
548 try renderToken(r, op_token, .space);544 try renderToken(r, op_token, .space);
549 } else {545 } else {
550 try renderToken(r, op_token, .newline);546 try renderToken(r, op_token, .newline);
551 }547 }
552 try renderExpression(r, infix.rhs, space);548 try renderExpression(r, rhs, space);
553 ais.popIndent();549 ais.popIndent();
554 },550 },
555551
...@@ -561,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -561,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
561557
562 for (full.ast.variables, 0..) |variable_node, i| {558 for (full.ast.variables, 0..) |variable_node, i| {
563 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;
564 switch (node_tags[variable_node]) {560 switch (tree.nodeTag(variable_node)) {
565 .global_var_decl,561 .global_var_decl,
566 .local_var_decl,562 .local_var_decl,
567 .simple_var_decl,563 .simple_var_decl,
...@@ -589,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -589,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
589 .optional_type,585 .optional_type,
590 .address_of,586 .address_of,
591 => {587 => {
592 try renderToken(r, main_tokens[node], .none);588 try renderToken(r, tree.nodeMainToken(node), .none);
593 return renderExpression(r, datas[node].lhs, space);589 return renderExpression(r, tree.nodeData(node).node, space);
594 },590 },
595591
596 .@"try",592 .@"try",
597 .@"resume",593 .@"resume",
598 .@"await",594 .@"await",
599 => {595 => {
600 try renderToken(r, main_tokens[node], .space);596 try renderToken(r, tree.nodeMainToken(node), .space);
601 return renderExpression(r, datas[node].lhs, space);597 return renderExpression(r, tree.nodeData(node).node, space);
602 },598 },
603599
604 .array_type,600 .array_type,
...@@ -651,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -651,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
651 },647 },
652648
653 .array_access => {649 .array_access => {
654 const suffix = datas[node];650 const lhs, const rhs = tree.nodeData(node).node_and_node;
655 const lbracket = tree.firstToken(suffix.rhs) - 1;651 const lbracket = tree.firstToken(rhs) - 1;
656 const rbracket = tree.lastToken(suffix.rhs) + 1;652 const rbracket = tree.lastToken(rhs) + 1;
657 const one_line = tree.tokensOnSameLine(lbracket, rbracket);653 const one_line = tree.tokensOnSameLine(lbracket, rbracket);
658 const inner_space = if (one_line) Space.none else Space.newline;654 const inner_space = if (one_line) Space.none else Space.newline;
659 try renderExpression(r, suffix.lhs, .none);655 try renderExpression(r, lhs, .none);
660 try ais.pushIndent(.normal);656 try ais.pushIndent(.normal);
661 try renderToken(r, lbracket, inner_space); // [657 try renderToken(r, lbracket, inner_space); // [
662 try renderExpression(r, suffix.rhs, inner_space);658 try renderExpression(r, rhs, inner_space);
663 ais.popIndent();659 ais.popIndent();
664 return renderToken(r, rbracket, space); // ]660 return renderToken(r, rbracket, space); // ]
665 },661 },
666662
667 .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space),663 .slice_open,
664 .slice,
665 .slice_sentinel,
666 => return renderSlice(r, node, tree.fullSlice(node).?, space),
668667
669 .deref => {668 .deref => {
670 try renderExpression(r, datas[node].lhs, .none);669 try renderExpression(r, tree.nodeData(node).node, .none);
671 return renderToken(r, main_tokens[node], space);670 return renderToken(r, tree.nodeMainToken(node), space);
672 },671 },
673672
674 .unwrap_optional => {673 .unwrap_optional => {
675 try renderExpression(r, datas[node].lhs, .none);674 const lhs, const question_mark = tree.nodeData(node).node_and_token;
676 try renderToken(r, main_tokens[node], .none);675 const dot_token = question_mark - 1;
677 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);
678 },679 },
679680
680 .@"break", .@"continue" => {681 .@"break", .@"continue" => {
681 const main_token = main_tokens[node];682 const main_token = tree.nodeMainToken(node);
682 const label_token = datas[node].lhs;683 const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node;
683 const target = datas[node].rhs;684 if (opt_label_token == .none and opt_target == .none) {
684 if (label_token == 0 and target == 0) {
685 try renderToken(r, main_token, space); // break/continue685 try renderToken(r, main_token, space); // break/continue
686 } else if (label_token == 0 and target != 0) {686 } else if (opt_label_token == .none and opt_target != .none) {
687 const target = opt_target.unwrap().?;
687 try renderToken(r, main_token, .space); // break/continue688 try renderToken(r, main_token, .space); // break/continue
688 try renderExpression(r, target, space);689 try renderExpression(r, target, space);
689 } else if (label_token != 0 and target == 0) {690 } else if (opt_label_token != .none and opt_target == .none) {
691 const label_token = opt_label_token.unwrap().?;
690 try renderToken(r, main_token, .space); // break/continue692 try renderToken(r, main_token, .space); // break/continue
691 try renderToken(r, label_token - 1, .none); // :693 try renderToken(r, label_token - 1, .none); // :
692 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier694 try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier
693 } else if (label_token != 0 and target != 0) {695 } else if (opt_label_token != .none and opt_target != .none) {
696 const label_token = opt_label_token.unwrap().?;
697 const target = opt_target.unwrap().?;
694 try renderToken(r, main_token, .space); // break/continue698 try renderToken(r, main_token, .space); // break/continue
695 try renderToken(r, label_token - 1, .none); // :699 try renderToken(r, label_token - 1, .none); // :
696 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier700 try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier
697 try renderExpression(r, target, space);701 try renderExpression(r, target, space);
698 }702 } else unreachable;
699 },703 },
700704
701 .@"return" => {705 .@"return" => {
702 if (datas[node].lhs != 0) {706 if (tree.nodeData(node).opt_node.unwrap()) |expr| {
703 try renderToken(r, main_tokens[node], .space);707 try renderToken(r, tree.nodeMainToken(node), .space);
704 try renderExpression(r, datas[node].lhs, space);708 try renderExpression(r, expr, space);
705 } else {709 } else {
706 try renderToken(r, main_tokens[node], space);710 try renderToken(r, tree.nodeMainToken(node), space);
707 }711 }
708 },712 },
709713
710 .grouped_expression => {714 .grouped_expression => {
715 const expr, const rparen = tree.nodeData(node).node_and_token;
711 try ais.pushIndent(.normal);716 try ais.pushIndent(.normal);
712 try renderToken(r, main_tokens[node], .none); // lparen717 try renderToken(r, tree.nodeMainToken(node), .none); // lparen
713 try renderExpression(r, datas[node].lhs, .none);718 try renderExpression(r, expr, .none);
714 ais.popIndent();719 ais.popIndent();
715 return renderToken(r, datas[node].rhs, space); // rparen720 return renderToken(r, rparen, space);
716 },721 },
717722
718 .container_decl,723 .container_decl,
...@@ -733,9 +738,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -733,9 +738,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
733 },738 },
734739
735 .error_set_decl => {740 .error_set_decl => {
736 const error_token = main_tokens[node];741 const error_token = tree.nodeMainToken(node);
737 const lbrace = error_token + 1;742 const lbrace = error_token + 1;
738 const rbrace = datas[node].rhs;743 const rbrace = tree.nodeData(node).token;
739744
740 try renderToken(r, error_token, .none);745 try renderToken(r, error_token, .none);
741746
...@@ -743,20 +748,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -743,20 +748,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
743 // There is nothing between the braces so render condensed: `error{}`748 // There is nothing between the braces so render condensed: `error{}`
744 try renderToken(r, lbrace, .none);749 try renderToken(r, lbrace, .none);
745 return renderToken(r, rbrace, space);750 return renderToken(r, rbrace, space);
746 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) {751 } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) {
747 // There is exactly one member and no trailing comma or752 // There is exactly one member and no trailing comma or
748 // comments, so render without surrounding spaces: `error{Foo}`753 // comments, so render without surrounding spaces: `error{Foo}`
749 try renderToken(r, lbrace, .none);754 try renderToken(r, lbrace, .none);
750 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier755 try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier
751 return renderToken(r, rbrace, space);756 return renderToken(r, rbrace, space);
752 } else if (token_tags[rbrace - 1] == .comma) {757 } else if (tree.tokenTag(rbrace - 1) == .comma) {
753 // There is a trailing comma so render each member on a new line.758 // There is a trailing comma so render each member on a new line.
754 try ais.pushIndent(.normal);759 try ais.pushIndent(.normal);
755 try renderToken(r, lbrace, .newline);760 try renderToken(r, lbrace, .newline);
756 var i = lbrace + 1;761 var i = lbrace + 1;
757 while (i < rbrace) : (i += 1) {762 while (i < rbrace) : (i += 1) {
758 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);763 if (i > lbrace + 1) try renderExtraNewlineToken(r, i);
759 switch (token_tags[i]) {764 switch (tree.tokenTag(i)) {
760 .doc_comment => try renderToken(r, i, .newline),765 .doc_comment => try renderToken(r, i, .newline),
761 .identifier => {766 .identifier => {
762 try ais.pushSpace(.comma);767 try ais.pushSpace(.comma);
...@@ -774,7 +779,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -774,7 +779,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
774 try renderToken(r, lbrace, .space);779 try renderToken(r, lbrace, .space);
775 var i = lbrace + 1;780 var i = lbrace + 1;
776 while (i < rbrace) : (i += 1) {781 while (i < rbrace) : (i += 1) {
777 switch (token_tags[i]) {782 switch (tree.tokenTag(i)) {
778 .doc_comment => unreachable, // TODO783 .doc_comment => unreachable, // TODO
779 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),784 .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote),
780 .comma => {},785 .comma => {},
...@@ -792,7 +797,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -792,7 +797,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
792 => {797 => {
793 var buf: [2]Ast.Node.Index = undefined;798 var buf: [2]Ast.Node.Index = undefined;
794 const params = tree.builtinCallParams(&buf, node).?;799 const params = tree.builtinCallParams(&buf, node).?;
795 return renderBuiltinCall(r, main_tokens[node], params, space);800 return renderBuiltinCall(r, tree.nodeMainToken(node), params, space);
796 },801 },
797802
798 .fn_proto_simple,803 .fn_proto_simple,
...@@ -805,14 +810,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -805,14 +810,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
805 },810 },
806811
807 .anyframe_type => {812 .anyframe_type => {
808 const main_token = main_tokens[node];813 const main_token = tree.nodeMainToken(node);
809 if (datas[node].rhs != 0) {814 try renderToken(r, main_token, .none); // anyframe
810 try renderToken(r, main_token, .none); // anyframe815 try renderToken(r, main_token + 1, .none); // ->
811 try renderToken(r, main_token + 1, .none); // ->816 return renderExpression(r, tree.nodeData(node).token_and_node[1], space);
812 return renderExpression(r, datas[node].rhs, space);
813 } else {
814 return renderToken(r, main_token, space); // anyframe
815 }
816 },817 },
817818
818 .@"switch",819 .@"switch",
...@@ -869,8 +870,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {...@@ -869,8 +870,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
869 => return renderAsm(r, tree.fullAsm(node).?, space),870 => return renderAsm(r, tree.fullAsm(node).?, space),
870871
871 .enum_literal => {872 .enum_literal => {
872 try renderToken(r, main_tokens[node] - 1, .none); // .873 try renderToken(r, tree.nodeMainToken(node) - 1, .none); // .
873 return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name874 return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name
874 },875 },
875876
876 .fn_decl => unreachable,877 .fn_decl => unreachable,
...@@ -912,9 +913,9 @@ fn renderArrayType(...@@ -912,9 +913,9 @@ fn renderArrayType(
912 try ais.pushIndent(.normal);913 try ais.pushIndent(.normal);
913 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket914 try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket
914 try renderExpression(r, array_type.ast.elem_count, inner_space);915 try renderExpression(r, array_type.ast.elem_count, inner_space);
915 if (array_type.ast.sentinel != 0) {916 if (array_type.ast.sentinel.unwrap()) |sentinel| {
916 try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon917 try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon
917 try renderExpression(r, array_type.ast.sentinel, inner_space);918 try renderExpression(r, sentinel, inner_space);
918 }919 }
919 ais.popIndent();920 ais.popIndent();
920 try renderToken(r, rbracket, .none); // rbracket921 try renderToken(r, rbracket, .none); // rbracket
...@@ -923,6 +924,7 @@ fn renderArrayType(...@@ -923,6 +924,7 @@ fn renderArrayType(
923924
924fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {925fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
925 const tree = r.tree;926 const tree = r.tree;
927 const main_token = ptr_type.ast.main_token;
926 switch (ptr_type.size) {928 switch (ptr_type.size) {
927 .one => {929 .one => {
928 // Since ** tokens exist and the same token is shared by two930 // Since ** tokens exist and the same token is shared by two
...@@ -930,41 +932,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi...@@ -930,41 +932,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
930 // in such a relationship. If so, skip rendering anything for932 // in such a relationship. If so, skip rendering anything for
931 // this pointer type and rely on the child to render our asterisk933 // this pointer type and rely on the child to render our asterisk
932 // as well when it renders the ** token.934 // as well when it renders the ** token.
933 if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and935 if (tree.tokenTag(main_token) == .asterisk_asterisk and
934 ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type])936 main_token == tree.nodeMainToken(ptr_type.ast.child_type))
935 {937 {
936 return renderExpression(r, ptr_type.ast.child_type, space);938 return renderExpression(r, ptr_type.ast.child_type, space);
937 }939 }
938 try renderToken(r, ptr_type.ast.main_token, .none); // asterisk940 try renderToken(r, main_token, .none); // asterisk
939 },941 },
940 .many => {942 .many => {
941 if (ptr_type.ast.sentinel == 0) {943 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
942 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket944 try renderToken(r, main_token, .none); // lbracket
943 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk945 try renderToken(r, main_token + 1, .none); // asterisk
944 try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket946 try renderToken(r, main_token + 2, .none); // colon
947 try renderExpression(r, sentinel, .none);
948 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
945 } else {949 } else {
946 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket950 try renderToken(r, main_token, .none); // lbracket
947 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk951 try renderToken(r, main_token + 1, .none); // asterisk
948 try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon952 try renderToken(r, main_token + 2, .none); // rbracket
949 try renderExpression(r, ptr_type.ast.sentinel, .none);
950 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
951 }953 }
952 },954 },
953 .c => {955 .c => {
954 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket956 try renderToken(r, main_token, .none); // lbracket
955 try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk957 try renderToken(r, main_token + 1, .none); // asterisk
956 try renderToken(r, ptr_type.ast.main_token + 2, .none); // c958 try renderToken(r, main_token + 2, .none); // c
957 try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket959 try renderToken(r, main_token + 3, .none); // rbracket
958 },960 },
959 .slice => {961 .slice => {
960 if (ptr_type.ast.sentinel == 0) {962 if (ptr_type.ast.sentinel.unwrap()) |sentinel| {
961 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket963 try renderToken(r, main_token, .none); // lbracket
962 try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket964 try renderToken(r, main_token + 1, .none); // colon
965 try renderExpression(r, sentinel, .none);
966 try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket
963 } else {967 } else {
964 try renderToken(r, ptr_type.ast.main_token, .none); // lbracket968 try renderToken(r, main_token, .none); // lbracket
965 try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon969 try renderToken(r, main_token + 1, .none); // rbracket
966 try renderExpression(r, ptr_type.ast.sentinel, .none);
967 try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket
968 }970 }
969 },971 },
970 }972 }
...@@ -973,29 +975,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi...@@ -973,29 +975,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi
973 try renderToken(r, allowzero_token, .space);975 try renderToken(r, allowzero_token, .space);
974 }976 }
975977
976 if (ptr_type.ast.align_node != 0) {978 if (ptr_type.ast.align_node.unwrap()) |align_node| {
977 const align_first = tree.firstToken(ptr_type.ast.align_node);979 const align_first = tree.firstToken(align_node);
978 try renderToken(r, align_first - 2, .none); // align980 try renderToken(r, align_first - 2, .none); // align
979 try renderToken(r, align_first - 1, .none); // lparen981 try renderToken(r, align_first - 1, .none); // lparen
980 try renderExpression(r, ptr_type.ast.align_node, .none);982 try renderExpression(r, align_node, .none);
981 if (ptr_type.ast.bit_range_start != 0) {983 if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| {
982 assert(ptr_type.ast.bit_range_end != 0);984 const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?;
983 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon985 try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon
984 try renderExpression(r, ptr_type.ast.bit_range_start, .none);986 try renderExpression(r, bit_range_start, .none);
985 try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon987 try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon
986 try renderExpression(r, ptr_type.ast.bit_range_end, .none);988 try renderExpression(r, bit_range_end, .none);
987 try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen989 try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen
988 } else {990 } else {
989 try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen991 try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen
990 }992 }
991 }993 }
992994
993 if (ptr_type.ast.addrspace_node != 0) {995 if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| {
994 const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node);996 const addrspace_first = tree.firstToken(addrspace_node);
995 try renderToken(r, addrspace_first - 2, .none); // addrspace997 try renderToken(r, addrspace_first - 2, .none); // addrspace
996 try renderToken(r, addrspace_first - 1, .none); // lparen998 try renderToken(r, addrspace_first - 1, .none); // lparen
997 try renderExpression(r, ptr_type.ast.addrspace_node, .none);999 try renderExpression(r, addrspace_node, .none);
998 try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen1000 try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen
999 }1001 }
10001002
1001 if (ptr_type.const_token) |const_token| {1003 if (ptr_type.const_token) |const_token| {
...@@ -1016,13 +1018,12 @@ fn renderSlice(...@@ -1016,13 +1018,12 @@ fn renderSlice(
1016 space: Space,1018 space: Space,
1017) Error!void {1019) Error!void {
1018 const tree = r.tree;1020 const tree = r.tree;
1019 const node_tags = tree.nodes.items(.tag);1021 const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
1020 const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or1022 if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
1021 if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
1022 const after_start_space = if (after_start_space_bool) Space.space else Space.none;1023 const after_start_space = if (after_start_space_bool) Space.space else Space.none;
1023 const after_dots_space = if (slice.ast.end != 0)1024 const after_dots_space = if (slice.ast.end != .none)
1024 after_start_space1025 after_start_space
1025 else if (slice.ast.sentinel != 0) Space.space else Space.none;1026 else if (slice.ast.sentinel != .none) Space.space else Space.none;
10261027
1027 try renderExpression(r, slice.ast.sliced, .none);1028 try renderExpression(r, slice.ast.sliced, .none);
1028 try renderToken(r, slice.ast.lbracket, .none); // lbracket1029 try renderToken(r, slice.ast.lbracket, .none); // lbracket
...@@ -1031,14 +1032,14 @@ fn renderSlice(...@@ -1031,14 +1032,14 @@ fn renderSlice(
1031 try renderExpression(r, slice.ast.start, after_start_space);1032 try renderExpression(r, slice.ast.start, after_start_space);
1032 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")1033 try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..")
10331034
1034 if (slice.ast.end != 0) {1035 if (slice.ast.end.unwrap()) |end| {
1035 const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none;1036 const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none;
1036 try renderExpression(r, slice.ast.end, after_end_space);1037 try renderExpression(r, end, after_end_space);
1037 }1038 }
10381039
1039 if (slice.ast.sentinel != 0) {1040 if (slice.ast.sentinel.unwrap()) |sentinel| {
1040 try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon1041 try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon
1041 try renderExpression(r, slice.ast.sentinel, .none);1042 try renderExpression(r, sentinel, .none);
1042 }1043 }
10431044
1044 try renderToken(r, tree.lastToken(slice_node), space); // rbracket1045 try renderToken(r, tree.lastToken(slice_node), space); // rbracket
...@@ -1050,12 +1051,8 @@ fn renderAsmOutput(...@@ -1050,12 +1051,8 @@ fn renderAsmOutput(
1050 space: Space,1051 space: Space,
1051) Error!void {1052) Error!void {
1052 const tree = r.tree;1053 const tree = r.tree;
1053 const token_tags = tree.tokens.items(.tag);1054 assert(tree.nodeTag(asm_output) == .asm_output);
1054 const node_tags = tree.nodes.items(.tag);1055 const symbolic_name = tree.nodeMainToken(asm_output);
1055 const main_tokens = tree.nodes.items(.main_token);
1056 const datas = tree.nodes.items(.data);
1057 assert(node_tags[asm_output] == .asm_output);
1058 const symbolic_name = main_tokens[asm_output];
10591056
1060 try renderToken(r, symbolic_name - 1, .none); // lbracket1057 try renderToken(r, symbolic_name - 1, .none); // lbracket
1061 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident1058 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
...@@ -1063,10 +1060,11 @@ fn renderAsmOutput(...@@ -1063,10 +1060,11 @@ fn renderAsmOutput(
1063 try renderToken(r, symbolic_name + 2, .space); // "constraint"1060 try renderToken(r, symbolic_name + 2, .space); // "constraint"
1064 try renderToken(r, symbolic_name + 3, .none); // lparen1061 try renderToken(r, symbolic_name + 3, .none); // lparen
10651062
1066 if (token_tags[symbolic_name + 4] == .arrow) {1063 if (tree.tokenTag(symbolic_name + 4) == .arrow) {
1064 const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token;
1067 try renderToken(r, symbolic_name + 4, .space); // ->1065 try renderToken(r, symbolic_name + 4, .space); // ->
1068 try renderExpression(r, datas[asm_output].lhs, Space.none);1066 try renderExpression(r, type_expr.unwrap().?, Space.none);
1069 return renderToken(r, datas[asm_output].rhs, space); // rparen1067 return renderToken(r, rparen, space);
1070 } else {1068 } else {
1071 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident1069 try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident
1072 return renderToken(r, symbolic_name + 5, space); // rparen1070 return renderToken(r, symbolic_name + 5, space); // rparen
...@@ -1079,19 +1077,17 @@ fn renderAsmInput(...@@ -1079,19 +1077,17 @@ fn renderAsmInput(
1079 space: Space,1077 space: Space,
1080) Error!void {1078) Error!void {
1081 const tree = r.tree;1079 const tree = r.tree;
1082 const node_tags = tree.nodes.items(.tag);1080 assert(tree.nodeTag(asm_input) == .asm_input);
1083 const main_tokens = tree.nodes.items(.main_token);1081 const symbolic_name = tree.nodeMainToken(asm_input);
1084 const datas = tree.nodes.items(.data);1082 const expr, const rparen = tree.nodeData(asm_input).node_and_token;
1085 assert(node_tags[asm_input] == .asm_input);
1086 const symbolic_name = main_tokens[asm_input];
10871083
1088 try renderToken(r, symbolic_name - 1, .none); // lbracket1084 try renderToken(r, symbolic_name - 1, .none); // lbracket
1089 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident1085 try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident
1090 try renderToken(r, symbolic_name + 1, .space); // rbracket1086 try renderToken(r, symbolic_name + 1, .space); // rbracket
1091 try renderToken(r, symbolic_name + 2, .space); // "constraint"1087 try renderToken(r, symbolic_name + 2, .space); // "constraint"
1092 try renderToken(r, symbolic_name + 3, .none); // lparen1088 try renderToken(r, symbolic_name + 3, .none); // lparen
1093 try renderExpression(r, datas[asm_input].lhs, Space.none);1089 try renderExpression(r, expr, Space.none);
1094 return renderToken(r, datas[asm_input].rhs, space); // rparen1090 return renderToken(r, rparen, space);
1095}1091}
10961092
1097fn renderVarDecl(1093fn renderVarDecl(
...@@ -1147,15 +1143,15 @@ fn renderVarDeclWithoutFixups(...@@ -1147,15 +1143,15 @@ fn renderVarDeclWithoutFixups(
11471143
1148 try renderToken(r, var_decl.ast.mut_token, .space); // var1144 try renderToken(r, var_decl.ast.mut_token, .space); // var
11491145
1150 if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or1146 if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or
1151 var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1147 var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1152 var_decl.ast.init_node != 0)1148 var_decl.ast.init_node != .none)
1153 {1149 {
1154 const name_space = if (var_decl.ast.type_node == 0 and1150 const name_space = if (var_decl.ast.type_node == .none and
1155 (var_decl.ast.align_node != 0 or1151 (var_decl.ast.align_node != .none or
1156 var_decl.ast.addrspace_node != 0 or1152 var_decl.ast.addrspace_node != .none or
1157 var_decl.ast.section_node != 0 or1153 var_decl.ast.section_node != .none or
1158 var_decl.ast.init_node != 0))1154 var_decl.ast.init_node != .none))
1159 Space.space1155 Space.space
1160 else1156 else
1161 Space.none;1157 Space.none;
...@@ -1165,26 +1161,26 @@ fn renderVarDeclWithoutFixups(...@@ -1165,26 +1161,26 @@ fn renderVarDeclWithoutFixups(
1165 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name1161 return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name
1166 }1162 }
11671163
1168 if (var_decl.ast.type_node != 0) {1164 if (var_decl.ast.type_node.unwrap()) |type_node| {
1169 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :1165 try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // :
1170 if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or1166 if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or
1171 var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0)1167 var_decl.ast.section_node != .none or var_decl.ast.init_node != .none)
1172 {1168 {
1173 try renderExpression(r, var_decl.ast.type_node, .space);1169 try renderExpression(r, type_node, .space);
1174 } else {1170 } else {
1175 return renderExpression(r, var_decl.ast.type_node, space);1171 return renderExpression(r, type_node, space);
1176 }1172 }
1177 }1173 }
11781174
1179 if (var_decl.ast.align_node != 0) {1175 if (var_decl.ast.align_node.unwrap()) |align_node| {
1180 const lparen = tree.firstToken(var_decl.ast.align_node) - 1;1176 const lparen = tree.firstToken(align_node) - 1;
1181 const align_kw = lparen - 1;1177 const align_kw = lparen - 1;
1182 const rparen = tree.lastToken(var_decl.ast.align_node) + 1;1178 const rparen = tree.lastToken(align_node) + 1;
1183 try renderToken(r, align_kw, Space.none); // align1179 try renderToken(r, align_kw, Space.none); // align
1184 try renderToken(r, lparen, Space.none); // (1180 try renderToken(r, lparen, Space.none); // (
1185 try renderExpression(r, var_decl.ast.align_node, Space.none);1181 try renderExpression(r, align_node, Space.none);
1186 if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or1182 if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or
1187 var_decl.ast.init_node != 0)1183 var_decl.ast.init_node != .none)
1188 {1184 {
1189 try renderToken(r, rparen, .space); // )1185 try renderToken(r, rparen, .space); // )
1190 } else {1186 } else {
...@@ -1192,14 +1188,14 @@ fn renderVarDeclWithoutFixups(...@@ -1192,14 +1188,14 @@ fn renderVarDeclWithoutFixups(
1192 }1188 }
1193 }1189 }
11941190
1195 if (var_decl.ast.addrspace_node != 0) {1191 if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| {
1196 const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1;1192 const lparen = tree.firstToken(addrspace_node) - 1;
1197 const addrspace_kw = lparen - 1;1193 const addrspace_kw = lparen - 1;
1198 const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1;1194 const rparen = tree.lastToken(addrspace_node) + 1;
1199 try renderToken(r, addrspace_kw, Space.none); // addrspace1195 try renderToken(r, addrspace_kw, Space.none); // addrspace
1200 try renderToken(r, lparen, Space.none); // (1196 try renderToken(r, lparen, Space.none); // (
1201 try renderExpression(r, var_decl.ast.addrspace_node, Space.none);1197 try renderExpression(r, addrspace_node, Space.none);
1202 if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) {1198 if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) {
1203 try renderToken(r, rparen, .space); // )1199 try renderToken(r, rparen, .space); // )
1204 } else {1200 } else {
1205 try renderToken(r, rparen, .none); // )1201 try renderToken(r, rparen, .none); // )
...@@ -1207,27 +1203,27 @@ fn renderVarDeclWithoutFixups(...@@ -1207,27 +1203,27 @@ fn renderVarDeclWithoutFixups(
1207 }1203 }
1208 }1204 }
12091205
1210 if (var_decl.ast.section_node != 0) {1206 if (var_decl.ast.section_node.unwrap()) |section_node| {
1211 const lparen = tree.firstToken(var_decl.ast.section_node) - 1;1207 const lparen = tree.firstToken(section_node) - 1;
1212 const section_kw = lparen - 1;1208 const section_kw = lparen - 1;
1213 const rparen = tree.lastToken(var_decl.ast.section_node) + 1;1209 const rparen = tree.lastToken(section_node) + 1;
1214 try renderToken(r, section_kw, Space.none); // linksection1210 try renderToken(r, section_kw, Space.none); // linksection
1215 try renderToken(r, lparen, Space.none); // (1211 try renderToken(r, lparen, Space.none); // (
1216 try renderExpression(r, var_decl.ast.section_node, Space.none);1212 try renderExpression(r, section_node, Space.none);
1217 if (var_decl.ast.init_node != 0) {1213 if (var_decl.ast.init_node != .none) {
1218 try renderToken(r, rparen, .space); // )1214 try renderToken(r, rparen, .space); // )
1219 } else {1215 } else {
1220 return renderToken(r, rparen, space); // )1216 return renderToken(r, rparen, space); // )
1221 }1217 }
1222 }1218 }
12231219
1224 assert(var_decl.ast.init_node != 0);1220 const init_node = var_decl.ast.init_node.unwrap().?;
12251221
1226 const eq_token = tree.firstToken(var_decl.ast.init_node) - 1;1222 const eq_token = tree.firstToken(init_node) - 1;
1227 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1223 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
1228 try ais.pushIndent(.after_equals);1224 try ais.pushIndent(.after_equals);
1229 try renderToken(r, eq_token, eq_space); // =1225 try renderToken(r, eq_token, eq_space); // =
1230 try renderExpression(r, var_decl.ast.init_node, space); // ;1226 try renderExpression(r, init_node, space); // ;
1231 ais.popIndent();1227 ais.popIndent();
1232}1228}
12331229
...@@ -1236,7 +1232,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {...@@ -1236,7 +1232,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
1236 .ast = .{1232 .ast = .{
1237 .while_token = if_node.ast.if_token,1233 .while_token = if_node.ast.if_token,
1238 .cond_expr = if_node.ast.cond_expr,1234 .cond_expr = if_node.ast.cond_expr,
1239 .cont_expr = 0,1235 .cont_expr = .none,
1240 .then_expr = if_node.ast.then_expr,1236 .then_expr = if_node.ast.then_expr,
1241 .else_expr = if_node.ast.else_expr,1237 .else_expr = if_node.ast.else_expr,
1242 },1238 },
...@@ -1252,7 +1248,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {...@@ -1252,7 +1248,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
1252/// respective values set to null.1248/// respective values set to null.
1253fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {1249fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
1254 const tree = r.tree;1250 const tree = r.tree;
1255 const token_tags = tree.tokens.items(.tag);
12561251
1257 if (while_node.label_token) |label| {1252 if (while_node.label_token) |label| {
1258 try renderIdentifier(r, label, .none, .eagerly_unquote); // label1253 try renderIdentifier(r, label, .none, .eagerly_unquote); // label
...@@ -1273,7 +1268,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1273,7 +1268,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1273 try renderToken(r, last_prefix_token, .space);1268 try renderToken(r, last_prefix_token, .space);
1274 try renderToken(r, payload_token - 1, .none); // |1269 try renderToken(r, payload_token - 1, .none); // |
1275 const ident = blk: {1270 const ident = blk: {
1276 if (token_tags[payload_token] == .asterisk) {1271 if (tree.tokenTag(payload_token) == .asterisk) {
1277 try renderToken(r, payload_token, .none); // *1272 try renderToken(r, payload_token, .none); // *
1278 break :blk payload_token + 1;1273 break :blk payload_token + 1;
1279 } else {1274 } else {
...@@ -1282,7 +1277,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1282,7 +1277,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1282 };1277 };
1283 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier1278 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1284 const pipe = blk: {1279 const pipe = blk: {
1285 if (token_tags[ident + 1] == .comma) {1280 if (tree.tokenTag(ident + 1) == .comma) {
1286 try renderToken(r, ident + 1, .space); // ,1281 try renderToken(r, ident + 1, .space); // ,
1287 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index1282 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index
1288 break :blk ident + 3;1283 break :blk ident + 3;
...@@ -1293,13 +1288,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void...@@ -1293,13 +1288,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void
1293 last_prefix_token = pipe;1288 last_prefix_token = pipe;
1294 }1289 }
12951290
1296 if (while_node.ast.cont_expr != 0) {1291 if (while_node.ast.cont_expr.unwrap()) |cont_expr| {
1297 try renderToken(r, last_prefix_token, .space);1292 try renderToken(r, last_prefix_token, .space);
1298 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;1293 const lparen = tree.firstToken(cont_expr) - 1;
1299 try renderToken(r, lparen - 1, .space); // :1294 try renderToken(r, lparen - 1, .space); // :
1300 try renderToken(r, lparen, .none); // lparen1295 try renderToken(r, lparen, .none); // lparen
1301 try renderExpression(r, while_node.ast.cont_expr, .none);1296 try renderExpression(r, cont_expr, .none);
1302 last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen1297 last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen
1303 }1298 }
13041299
1305 try renderThenElse(1300 try renderThenElse(
...@@ -1317,15 +1312,14 @@ fn renderThenElse(...@@ -1317,15 +1312,14 @@ fn renderThenElse(
1317 r: *Render,1312 r: *Render,
1318 last_prefix_token: Ast.TokenIndex,1313 last_prefix_token: Ast.TokenIndex,
1319 then_expr: Ast.Node.Index,1314 then_expr: Ast.Node.Index,
1320 else_token: Ast.TokenIndex,1315 else_token: ?Ast.TokenIndex,
1321 maybe_error_token: ?Ast.TokenIndex,1316 maybe_error_token: ?Ast.TokenIndex,
1322 else_expr: Ast.Node.Index,1317 opt_else_expr: Ast.Node.OptionalIndex,
1323 space: Space,1318 space: Space,
1324) Error!void {1319) Error!void {
1325 const tree = r.tree;1320 const tree = r.tree;
1326 const ais = r.ais;1321 const ais = r.ais;
1327 const node_tags = tree.nodes.items(.tag);1322 const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
1328 const then_expr_is_block = nodeIsBlock(node_tags[then_expr]);
1329 const indent_then_expr = !then_expr_is_block and1323 const indent_then_expr = !then_expr_is_block and
1330 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));1324 !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr));
13311325
...@@ -1341,7 +1335,7 @@ fn renderThenElse(...@@ -1341,7 +1335,7 @@ fn renderThenElse(
1341 try renderToken(r, last_prefix_token, .space);1335 try renderToken(r, last_prefix_token, .space);
1342 }1336 }
13431337
1344 if (else_expr != 0) {1338 if (opt_else_expr.unwrap()) |else_expr| {
1345 if (indent_then_expr) {1339 if (indent_then_expr) {
1346 try renderExpression(r, then_expr, .newline);1340 try renderExpression(r, then_expr, .newline);
1347 } else {1341 } else {
...@@ -1350,18 +1344,18 @@ fn renderThenElse(...@@ -1350,18 +1344,18 @@ fn renderThenElse(
13501344
1351 if (indent_then_expr) ais.popIndent();1345 if (indent_then_expr) ais.popIndent();
13521346
1353 var last_else_token = else_token;1347 var last_else_token = else_token.?;
13541348
1355 if (maybe_error_token) |error_token| {1349 if (maybe_error_token) |error_token| {
1356 try renderToken(r, else_token, .space); // else1350 try renderToken(r, last_else_token, .space); // else
1357 try renderToken(r, error_token - 1, .none); // |1351 try renderToken(r, error_token - 1, .none); // |
1358 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier1352 try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier
1359 last_else_token = error_token + 1; // |1353 last_else_token = error_token + 1; // |
1360 }1354 }
13611355
1362 const indent_else_expr = indent_then_expr and1356 const indent_else_expr = indent_then_expr and
1363 !nodeIsBlock(node_tags[else_expr]) and1357 !nodeIsBlock(tree.nodeTag(else_expr)) and
1364 !nodeIsIfForWhileSwitch(node_tags[else_expr]);1358 !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr));
1365 if (indent_else_expr) {1359 if (indent_else_expr) {
1366 try ais.pushIndent(.normal);1360 try ais.pushIndent(.normal);
1367 try renderToken(r, last_else_token, .newline);1361 try renderToken(r, last_else_token, .newline);
...@@ -1398,21 +1392,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {...@@ -1398,21 +1392,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
13981392
1399 var cur = for_node.payload_token;1393 var cur = for_node.payload_token;
1400 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;1394 const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?;
1401 if (token_tags[pipe - 1] == .comma) {1395 if (tree.tokenTag(@intCast(pipe - 1)) == .comma) {
1402 try ais.pushIndent(.normal);1396 try ais.pushIndent(.normal);
1403 try renderToken(r, cur - 1, .newline); // |1397 try renderToken(r, cur - 1, .newline); // |
1404 while (true) {1398 while (true) {
1405 if (token_tags[cur] == .asterisk) {1399 if (tree.tokenTag(cur) == .asterisk) {
1406 try renderToken(r, cur, .none); // *1400 try renderToken(r, cur, .none); // *
1407 cur += 1;1401 cur += 1;
1408 }1402 }
1409 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier1403 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1410 cur += 1;1404 cur += 1;
1411 if (token_tags[cur] == .comma) {1405 if (tree.tokenTag(cur) == .comma) {
1412 try renderToken(r, cur, .newline); // ,1406 try renderToken(r, cur, .newline); // ,
1413 cur += 1;1407 cur += 1;
1414 }1408 }
1415 if (token_tags[cur] == .pipe) {1409 if (tree.tokenTag(cur) == .pipe) {
1416 break;1410 break;
1417 }1411 }
1418 }1412 }
...@@ -1420,17 +1414,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {...@@ -1420,17 +1414,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
1420 } else {1414 } else {
1421 try renderToken(r, cur - 1, .none); // |1415 try renderToken(r, cur - 1, .none); // |
1422 while (true) {1416 while (true) {
1423 if (token_tags[cur] == .asterisk) {1417 if (tree.tokenTag(cur) == .asterisk) {
1424 try renderToken(r, cur, .none); // *1418 try renderToken(r, cur, .none); // *
1425 cur += 1;1419 cur += 1;
1426 }1420 }
1427 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier1421 try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier
1428 cur += 1;1422 cur += 1;
1429 if (token_tags[cur] == .comma) {1423 if (tree.tokenTag(cur) == .comma) {
1430 try renderToken(r, cur, .space); // ,1424 try renderToken(r, cur, .space); // ,
1431 cur += 1;1425 cur += 1;
1432 }1426 }
1433 if (token_tags[cur] == .pipe) {1427 if (tree.tokenTag(cur) == .pipe) {
1434 break;1428 break;
1435 }1429 }
1436 }1430 }
...@@ -1456,7 +1450,7 @@ fn renderContainerField(...@@ -1456,7 +1450,7 @@ fn renderContainerField(
1456 const tree = r.tree;1450 const tree = r.tree;
1457 const ais = r.ais;1451 const ais = r.ais;
1458 var field = field_param;1452 var field = field_param;
1459 if (container != .tuple) field.convertToNonTupleLike(tree.nodes);1453 if (container != .tuple) field.convertToNonTupleLike(&tree);
1460 const quote: QuoteBehavior = switch (container) {1454 const quote: QuoteBehavior = switch (container) {
1461 .@"enum" => .eagerly_unquote_except_underscore,1455 .@"enum" => .eagerly_unquote_except_underscore,
1462 .tuple, .other => .eagerly_unquote,1456 .tuple, .other => .eagerly_unquote,
...@@ -1465,67 +1459,74 @@ fn renderContainerField(...@@ -1465,67 +1459,74 @@ fn renderContainerField(
1465 if (field.comptime_token) |t| {1459 if (field.comptime_token) |t| {
1466 try renderToken(r, t, .space); // comptime1460 try renderToken(r, t, .space); // comptime
1467 }1461 }
1468 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {1462 if (field.ast.type_expr == .none and field.ast.value_expr == .none) {
1469 if (field.ast.align_expr != 0) {1463 if (field.ast.align_expr.unwrap()) |align_expr| {
1470 try renderIdentifier(r, field.ast.main_token, .space, quote); // name1464 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1471 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1465 const lparen_token = tree.firstToken(align_expr) - 1;
1472 const align_kw = lparen_token - 1;1466 const align_kw = lparen_token - 1;
1473 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1467 const rparen_token = tree.lastToken(align_expr) + 1;
1474 try renderToken(r, align_kw, .none); // align1468 try renderToken(r, align_kw, .none); // align
1475 try renderToken(r, lparen_token, .none); // (1469 try renderToken(r, lparen_token, .none); // (
1476 try renderExpression(r, field.ast.align_expr, .none); // alignment1470 try renderExpression(r, align_expr, .none); // alignment
1477 return renderToken(r, rparen_token, .space); // )1471 return renderToken(r, rparen_token, .space); // )
1478 }1472 }
1479 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name1473 return renderIdentifierComma(r, field.ast.main_token, space, quote); // name
1480 }1474 }
1481 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {1475 if (field.ast.type_expr != .none and field.ast.value_expr == .none) {
1476 const type_expr = field.ast.type_expr.unwrap().?;
1482 if (!field.ast.tuple_like) {1477 if (!field.ast.tuple_like) {
1483 try renderIdentifier(r, field.ast.main_token, .none, quote); // name1478 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1484 try renderToken(r, field.ast.main_token + 1, .space); // :1479 try renderToken(r, field.ast.main_token + 1, .space); // :
1485 }1480 }
14861481
1487 if (field.ast.align_expr != 0) {1482 if (field.ast.align_expr.unwrap()) |align_expr| {
1488 try renderExpression(r, field.ast.type_expr, .space); // type1483 try renderExpression(r, type_expr, .space); // type
1489 const align_token = tree.firstToken(field.ast.align_expr) - 2;1484 const align_token = tree.firstToken(align_expr) - 2;
1490 try renderToken(r, align_token, .none); // align1485 try renderToken(r, align_token, .none); // align
1491 try renderToken(r, align_token + 1, .none); // (1486 try renderToken(r, align_token + 1, .none); // (
1492 try renderExpression(r, field.ast.align_expr, .none); // alignment1487 try renderExpression(r, align_expr, .none); // alignment
1493 const rparen = tree.lastToken(field.ast.align_expr) + 1;1488 const rparen = tree.lastToken(align_expr) + 1;
1494 return renderTokenComma(r, rparen, space); // )1489 return renderTokenComma(r, rparen, space); // )
1495 } else {1490 } else {
1496 return renderExpressionComma(r, field.ast.type_expr, space); // type1491 return renderExpressionComma(r, type_expr, space); // type
1497 }1492 }
1498 }1493 }
1499 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {1494 if (field.ast.type_expr == .none and field.ast.value_expr != .none) {
1495 const value_expr = field.ast.value_expr.unwrap().?;
1496
1500 try renderIdentifier(r, field.ast.main_token, .space, quote); // name1497 try renderIdentifier(r, field.ast.main_token, .space, quote); // name
1501 if (field.ast.align_expr != 0) {1498 if (field.ast.align_expr.unwrap()) |align_expr| {
1502 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1499 const lparen_token = tree.firstToken(align_expr) - 1;
1503 const align_kw = lparen_token - 1;1500 const align_kw = lparen_token - 1;
1504 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1501 const rparen_token = tree.lastToken(align_expr) + 1;
1505 try renderToken(r, align_kw, .none); // align1502 try renderToken(r, align_kw, .none); // align
1506 try renderToken(r, lparen_token, .none); // (1503 try renderToken(r, lparen_token, .none); // (
1507 try renderExpression(r, field.ast.align_expr, .none); // alignment1504 try renderExpression(r, align_expr, .none); // alignment
1508 try renderToken(r, rparen_token, .space); // )1505 try renderToken(r, rparen_token, .space); // )
1509 }1506 }
1510 try renderToken(r, field.ast.main_token + 1, .space); // =1507 try renderToken(r, field.ast.main_token + 1, .space); // =
1511 return renderExpressionComma(r, field.ast.value_expr, space); // value1508 return renderExpressionComma(r, value_expr, space); // value
1512 }1509 }
1513 if (!field.ast.tuple_like) {1510 if (!field.ast.tuple_like) {
1514 try renderIdentifier(r, field.ast.main_token, .none, quote); // name1511 try renderIdentifier(r, field.ast.main_token, .none, quote); // name
1515 try renderToken(r, field.ast.main_token + 1, .space); // :1512 try renderToken(r, field.ast.main_token + 1, .space); // :
1516 }1513 }
1517 try renderExpression(r, field.ast.type_expr, .space); // type
15181514
1519 if (field.ast.align_expr != 0) {1515 const type_expr = field.ast.type_expr.unwrap().?;
1520 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;1516 const value_expr = field.ast.value_expr.unwrap().?;
1517
1518 try renderExpression(r, type_expr, .space); // type
1519
1520 if (field.ast.align_expr.unwrap()) |align_expr| {
1521 const lparen_token = tree.firstToken(align_expr) - 1;
1521 const align_kw = lparen_token - 1;1522 const align_kw = lparen_token - 1;
1522 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;1523 const rparen_token = tree.lastToken(align_expr) + 1;
1523 try renderToken(r, align_kw, .none); // align1524 try renderToken(r, align_kw, .none); // align
1524 try renderToken(r, lparen_token, .none); // (1525 try renderToken(r, lparen_token, .none); // (
1525 try renderExpression(r, field.ast.align_expr, .none); // alignment1526 try renderExpression(r, align_expr, .none); // alignment
1526 try renderToken(r, rparen_token, .space); // )1527 try renderToken(r, rparen_token, .space); // )
1527 }1528 }
1528 const eq_token = tree.firstToken(field.ast.value_expr) - 1;1529 const eq_token = tree.firstToken(value_expr) - 1;
1529 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;1530 const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline;
15301531
1531 try ais.pushIndent(.after_equals);1532 try ais.pushIndent(.after_equals);
...@@ -1533,19 +1534,18 @@ fn renderContainerField(...@@ -1533,19 +1534,18 @@ fn renderContainerField(
15331534
1534 if (eq_space == .space) {1535 if (eq_space == .space) {
1535 ais.popIndent();1536 ais.popIndent();
1536 try renderExpressionComma(r, field.ast.value_expr, space); // value1537 try renderExpressionComma(r, value_expr, space); // value
1537 return;1538 return;
1538 }1539 }
15391540
1540 const token_tags = tree.tokens.items(.tag);1541 const maybe_comma = tree.lastToken(value_expr) + 1;
1541 const maybe_comma = tree.lastToken(field.ast.value_expr) + 1;
15421542
1543 if (token_tags[maybe_comma] == .comma) {1543 if (tree.tokenTag(maybe_comma) == .comma) {
1544 try renderExpression(r, field.ast.value_expr, .none); // value1544 try renderExpression(r, value_expr, .none); // value
1545 ais.popIndent();1545 ais.popIndent();
1546 try renderToken(r, maybe_comma, .newline);1546 try renderToken(r, maybe_comma, .newline);
1547 } else {1547 } else {
1548 try renderExpression(r, field.ast.value_expr, space); // value1548 try renderExpression(r, value_expr, space); // value
1549 ais.popIndent();1549 ais.popIndent();
1550 }1550 }
1551}1551}
...@@ -1558,8 +1558,6 @@ fn renderBuiltinCall(...@@ -1558,8 +1558,6 @@ fn renderBuiltinCall(
1558) Error!void {1558) Error!void {
1559 const tree = r.tree;1559 const tree = r.tree;
1560 const ais = r.ais;1560 const ais = r.ais;
1561 const token_tags = tree.tokens.items(.tag);
1562 const main_tokens = tree.nodes.items(.main_token);
15631561
1564 try renderToken(r, builtin_token, .none); // @name1562 try renderToken(r, builtin_token, .none); // @name
15651563
...@@ -1572,8 +1570,8 @@ fn renderBuiltinCall(...@@ -1572,8 +1570,8 @@ fn renderBuiltinCall(
1572 const slice = tree.tokenSlice(builtin_token);1570 const slice = tree.tokenSlice(builtin_token);
1573 if (mem.eql(u8, slice, "@import")) f: {1571 if (mem.eql(u8, slice, "@import")) f: {
1574 const param = params[0];1572 const param = params[0];
1575 const str_lit_token = main_tokens[param];1573 const str_lit_token = tree.nodeMainToken(param);
1576 assert(token_tags[str_lit_token] == .string_literal);1574 assert(tree.tokenTag(str_lit_token) == .string_literal);
1577 const token_bytes = tree.tokenSlice(str_lit_token);1575 const token_bytes = tree.tokenSlice(str_lit_token);
1578 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {1576 const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) {
1579 error.OutOfMemory => return error.OutOfMemory,1577 error.OutOfMemory => return error.OutOfMemory,
...@@ -1592,13 +1590,13 @@ fn renderBuiltinCall(...@@ -1592,13 +1590,13 @@ fn renderBuiltinCall(
1592 const last_param = params[params.len - 1];1590 const last_param = params[params.len - 1];
1593 const after_last_param_token = tree.lastToken(last_param) + 1;1591 const after_last_param_token = tree.lastToken(last_param) + 1;
15941592
1595 if (token_tags[after_last_param_token] != .comma) {1593 if (tree.tokenTag(after_last_param_token) != .comma) {
1596 // Render all on one line, no trailing comma.1594 // Render all on one line, no trailing comma.
1597 try renderToken(r, builtin_token + 1, .none); // (1595 try renderToken(r, builtin_token + 1, .none); // (
15981596
1599 for (params, 0..) |param_node, i| {1597 for (params, 0..) |param_node, i| {
1600 const first_param_token = tree.firstToken(param_node);1598 const first_param_token = tree.firstToken(param_node);
1601 if (token_tags[first_param_token] == .multiline_string_literal_line or1599 if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or
1602 hasSameLineComment(tree, first_param_token - 1))1600 hasSameLineComment(tree, first_param_token - 1))
1603 {1601 {
1604 try ais.pushIndent(.normal);1602 try ais.pushIndent(.normal);
...@@ -1633,11 +1631,9 @@ fn renderBuiltinCall(...@@ -1633,11 +1631,9 @@ fn renderBuiltinCall(
1633fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {1631fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
1634 const tree = r.tree;1632 const tree = r.tree;
1635 const ais = r.ais;1633 const ais = r.ais;
1636 const token_tags = tree.tokens.items(.tag);
1637 const token_starts = tree.tokens.items(.start);
16381634
1639 const after_fn_token = fn_proto.ast.fn_token + 1;1635 const after_fn_token = fn_proto.ast.fn_token + 1;
1640 const lparen = if (token_tags[after_fn_token] == .identifier) blk: {1636 const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: {
1641 try renderToken(r, fn_proto.ast.fn_token, .space); // fn1637 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1642 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name1638 try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name
1643 break :blk after_fn_token + 1;1639 break :blk after_fn_token + 1;
...@@ -1645,41 +1641,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1645,41 +1641,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1645 try renderToken(r, fn_proto.ast.fn_token, .space); // fn1641 try renderToken(r, fn_proto.ast.fn_token, .space); // fn
1646 break :blk fn_proto.ast.fn_token + 1;1642 break :blk fn_proto.ast.fn_token + 1;
1647 };1643 };
1648 assert(token_tags[lparen] == .l_paren);1644 assert(tree.tokenTag(lparen) == .l_paren);
16491645
1650 const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;1646 const return_type = fn_proto.ast.return_type.unwrap().?;
1647 const maybe_bang = tree.firstToken(return_type) - 1;
1651 const rparen = blk: {1648 const rparen = blk: {
1652 // These may appear in any order, so we have to check the token_starts array1649 // These may appear in any order, so we have to check the token_starts array
1653 // to find out which is first.1650 // to find out which is first.
1654 var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang;1651 var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang;
1655 var smallest_start = token_starts[maybe_bang];1652 var smallest_start = tree.tokenStart(maybe_bang);
1656 if (fn_proto.ast.align_expr != 0) {1653 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1657 const tok = tree.firstToken(fn_proto.ast.align_expr) - 3;1654 const tok = tree.firstToken(align_expr) - 3;
1658 const start = token_starts[tok];1655 const start = tree.tokenStart(tok);
1659 if (start < smallest_start) {1656 if (start < smallest_start) {
1660 rparen = tok;1657 rparen = tok;
1661 smallest_start = start;1658 smallest_start = start;
1662 }1659 }
1663 }1660 }
1664 if (fn_proto.ast.addrspace_expr != 0) {1661 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1665 const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3;1662 const tok = tree.firstToken(addrspace_expr) - 3;
1666 const start = token_starts[tok];1663 const start = tree.tokenStart(tok);
1667 if (start < smallest_start) {1664 if (start < smallest_start) {
1668 rparen = tok;1665 rparen = tok;
1669 smallest_start = start;1666 smallest_start = start;
1670 }1667 }
1671 }1668 }
1672 if (fn_proto.ast.section_expr != 0) {1669 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1673 const tok = tree.firstToken(fn_proto.ast.section_expr) - 3;1670 const tok = tree.firstToken(section_expr) - 3;
1674 const start = token_starts[tok];1671 const start = tree.tokenStart(tok);
1675 if (start < smallest_start) {1672 if (start < smallest_start) {
1676 rparen = tok;1673 rparen = tok;
1677 smallest_start = start;1674 smallest_start = start;
1678 }1675 }
1679 }1676 }
1680 if (fn_proto.ast.callconv_expr != 0) {1677 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1681 const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3;1678 const tok = tree.firstToken(callconv_expr) - 3;
1682 const start = token_starts[tok];1679 const start = tree.tokenStart(tok);
1683 if (start < smallest_start) {1680 if (start < smallest_start) {
1684 rparen = tok;1681 rparen = tok;
1685 smallest_start = start;1682 smallest_start = start;
...@@ -1687,11 +1684,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1687,11 +1684,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1687 }1684 }
1688 break :blk rparen;1685 break :blk rparen;
1689 };1686 };
1690 assert(token_tags[rparen] == .r_paren);1687 assert(tree.tokenTag(rparen) == .r_paren);
16911688
1692 // The params list is a sparse set that does *not* include anytype or ... parameters.1689 // The params list is a sparse set that does *not* include anytype or ... parameters.
16931690
1694 const trailing_comma = token_tags[rparen - 1] == .comma;1691 const trailing_comma = tree.tokenTag(rparen - 1) == .comma;
1695 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {1692 if (!trailing_comma and !hasComment(tree, lparen, rparen)) {
1696 // Render all on one line, no trailing comma.1693 // Render all on one line, no trailing comma.
1697 try renderToken(r, lparen, .none); // (1694 try renderToken(r, lparen, .none); // (
...@@ -1700,7 +1697,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1700,7 +1697,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1700 var last_param_token = lparen;1697 var last_param_token = lparen;
1701 while (true) {1698 while (true) {
1702 last_param_token += 1;1699 last_param_token += 1;
1703 switch (token_tags[last_param_token]) {1700 switch (tree.tokenTag(last_param_token)) {
1704 .doc_comment => {1701 .doc_comment => {
1705 try renderToken(r, last_param_token, .newline);1702 try renderToken(r, last_param_token, .newline);
1706 continue;1703 continue;
...@@ -1725,15 +1722,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1725,15 +1722,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1725 },1722 },
1726 else => {}, // Parameter type without a name.1723 else => {}, // Parameter type without a name.
1727 }1724 }
1728 if (token_tags[last_param_token] == .identifier and1725 if (tree.tokenTag(last_param_token) == .identifier and
1729 token_tags[last_param_token + 1] == .colon)1726 tree.tokenTag(last_param_token + 1) == .colon)
1730 {1727 {
1731 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name1728 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1732 last_param_token += 1;1729 last_param_token = last_param_token + 1;
1733 try renderToken(r, last_param_token, .space); // :1730 try renderToken(r, last_param_token, .space); // :
1734 last_param_token += 1;1731 last_param_token += 1;
1735 }1732 }
1736 if (token_tags[last_param_token] == .keyword_anytype) {1733 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
1737 try renderToken(r, last_param_token, .none); // anytype1734 try renderToken(r, last_param_token, .none); // anytype
1738 continue;1735 continue;
1739 }1736 }
...@@ -1751,7 +1748,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1751,7 +1748,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1751 var last_param_token = lparen;1748 var last_param_token = lparen;
1752 while (true) {1749 while (true) {
1753 last_param_token += 1;1750 last_param_token += 1;
1754 switch (token_tags[last_param_token]) {1751 switch (tree.tokenTag(last_param_token)) {
1755 .doc_comment => {1752 .doc_comment => {
1756 try renderToken(r, last_param_token, .newline);1753 try renderToken(r, last_param_token, .newline);
1757 continue;1754 continue;
...@@ -1767,24 +1764,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1767,24 +1764,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1767 .identifier => {},1764 .identifier => {},
1768 .keyword_anytype => {1765 .keyword_anytype => {
1769 try renderToken(r, last_param_token, .comma); // anytype1766 try renderToken(r, last_param_token, .comma); // anytype
1770 if (token_tags[last_param_token + 1] == .comma)1767 if (tree.tokenTag(last_param_token + 1) == .comma)
1771 last_param_token += 1;1768 last_param_token += 1;
1772 continue;1769 continue;
1773 },1770 },
1774 .r_paren => break,1771 .r_paren => break,
1775 else => {}, // Parameter type without a name.1772 else => {}, // Parameter type without a name.
1776 }1773 }
1777 if (token_tags[last_param_token] == .identifier and1774 if (tree.tokenTag(last_param_token) == .identifier and
1778 token_tags[last_param_token + 1] == .colon)1775 tree.tokenTag(last_param_token + 1) == .colon)
1779 {1776 {
1780 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name1777 try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name
1781 last_param_token += 1;1778 last_param_token += 1;
1782 try renderToken(r, last_param_token, .space); // :1779 try renderToken(r, last_param_token, .space); // :
1783 last_param_token += 1;1780 last_param_token += 1;
1784 }1781 }
1785 if (token_tags[last_param_token] == .keyword_anytype) {1782 if (tree.tokenTag(last_param_token) == .keyword_anytype) {
1786 try renderToken(r, last_param_token, .comma); // anytype1783 try renderToken(r, last_param_token, .comma); // anytype
1787 if (token_tags[last_param_token + 1] == .comma)1784 if (tree.tokenTag(last_param_token + 1) == .comma)
1788 last_param_token += 1;1785 last_param_token += 1;
1789 continue;1786 continue;
1790 }1787 }
...@@ -1794,60 +1791,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi...@@ -1794,60 +1791,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi
1794 try renderExpression(r, param, .comma);1791 try renderExpression(r, param, .comma);
1795 ais.popSpace();1792 ais.popSpace();
1796 last_param_token = tree.lastToken(param);1793 last_param_token = tree.lastToken(param);
1797 if (token_tags[last_param_token + 1] == .comma) last_param_token += 1;1794 if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1;
1798 }1795 }
1799 ais.popIndent();1796 ais.popIndent();
1800 }1797 }
18011798
1802 try renderToken(r, rparen, .space); // )1799 try renderToken(r, rparen, .space); // )
18031800
1804 if (fn_proto.ast.align_expr != 0) {1801 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
1805 const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1;1802 const align_lparen = tree.firstToken(align_expr) - 1;
1806 const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1;1803 const align_rparen = tree.lastToken(align_expr) + 1;
18071804
1808 try renderToken(r, align_lparen - 1, .none); // align1805 try renderToken(r, align_lparen - 1, .none); // align
1809 try renderToken(r, align_lparen, .none); // (1806 try renderToken(r, align_lparen, .none); // (
1810 try renderExpression(r, fn_proto.ast.align_expr, .none);1807 try renderExpression(r, align_expr, .none);
1811 try renderToken(r, align_rparen, .space); // )1808 try renderToken(r, align_rparen, .space); // )
1812 }1809 }
18131810
1814 if (fn_proto.ast.addrspace_expr != 0) {1811 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
1815 const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1;1812 const align_lparen = tree.firstToken(addrspace_expr) - 1;
1816 const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1;1813 const align_rparen = tree.lastToken(addrspace_expr) + 1;
18171814
1818 try renderToken(r, align_lparen - 1, .none); // addrspace1815 try renderToken(r, align_lparen - 1, .none); // addrspace
1819 try renderToken(r, align_lparen, .none); // (1816 try renderToken(r, align_lparen, .none); // (
1820 try renderExpression(r, fn_proto.ast.addrspace_expr, .none);1817 try renderExpression(r, addrspace_expr, .none);
1821 try renderToken(r, align_rparen, .space); // )1818 try renderToken(r, align_rparen, .space); // )
1822 }1819 }
18231820
1824 if (fn_proto.ast.section_expr != 0) {1821 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
1825 const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1;1822 const section_lparen = tree.firstToken(section_expr) - 1;
1826 const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1;1823 const section_rparen = tree.lastToken(section_expr) + 1;
18271824
1828 try renderToken(r, section_lparen - 1, .none); // section1825 try renderToken(r, section_lparen - 1, .none); // section
1829 try renderToken(r, section_lparen, .none); // (1826 try renderToken(r, section_lparen, .none); // (
1830 try renderExpression(r, fn_proto.ast.section_expr, .none);1827 try renderExpression(r, section_expr, .none);
1831 try renderToken(r, section_rparen, .space); // )1828 try renderToken(r, section_rparen, .space); // )
1832 }1829 }
18331830
1834 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE1831 if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| {
1835 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr]));1832 // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE
1836 const is_declaration = fn_proto.name_token != null;1833 const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)));
1837 if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) {1834 const is_declaration = fn_proto.name_token != null;
1838 const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1;1835 if (!(is_declaration and is_callconv_inline)) {
1839 const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1;1836 const callconv_lparen = tree.firstToken(callconv_expr) - 1;
1837 const callconv_rparen = tree.lastToken(callconv_expr) + 1;
18401838
1841 try renderToken(r, callconv_lparen - 1, .none); // callconv1839 try renderToken(r, callconv_lparen - 1, .none); // callconv
1842 try renderToken(r, callconv_lparen, .none); // (1840 try renderToken(r, callconv_lparen, .none); // (
1843 try renderExpression(r, fn_proto.ast.callconv_expr, .none);1841 try renderExpression(r, callconv_expr, .none);
1844 try renderToken(r, callconv_rparen, .space); // )1842 try renderToken(r, callconv_rparen, .space); // )
1843 }
1845 }1844 }
18461845
1847 if (token_tags[maybe_bang] == .bang) {1846 if (tree.tokenTag(maybe_bang) == .bang) {
1848 try renderToken(r, maybe_bang, .none); // !1847 try renderToken(r, maybe_bang, .none); // !
1849 }1848 }
1850 return renderExpression(r, fn_proto.ast.return_type, space);1849 return renderExpression(r, return_type, space);
1851}1850}
18521851
1853fn renderSwitchCase(1852fn renderSwitchCase(
...@@ -1857,9 +1856,7 @@ fn renderSwitchCase(...@@ -1857,9 +1856,7 @@ fn renderSwitchCase(
1857) Error!void {1856) Error!void {
1858 const ais = r.ais;1857 const ais = r.ais;
1859 const tree = r.tree;1858 const tree = r.tree;
1860 const node_tags = tree.nodes.items(.tag);1859 const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
1861 const token_tags = tree.tokens.items(.tag);
1862 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma;
1863 const has_comment_before_arrow = blk: {1860 const has_comment_before_arrow = blk: {
1864 if (switch_case.ast.values.len == 0) break :blk false;1861 if (switch_case.ast.values.len == 0) break :blk false;
1865 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);1862 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);
...@@ -1886,7 +1883,7 @@ fn renderSwitchCase(...@@ -1886,7 +1883,7 @@ fn renderSwitchCase(
1886 }1883 }
18871884
1888 // Render the arrow and everything after it1885 // Render the arrow and everything after it
1889 const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal)1886 const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal)
1890 // Newline gets inserted when rendering the target expr.1887 // Newline gets inserted when rendering the target expr.
1891 Space.none1888 Space.none
1892 else1889 else
...@@ -1896,12 +1893,12 @@ fn renderSwitchCase(...@@ -1896,12 +1893,12 @@ fn renderSwitchCase(
18961893
1897 if (switch_case.payload_token) |payload_token| {1894 if (switch_case.payload_token) |payload_token| {
1898 try renderToken(r, payload_token - 1, .none); // pipe1895 try renderToken(r, payload_token - 1, .none); // pipe
1899 const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk);1896 const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk);
1900 if (token_tags[payload_token] == .asterisk) {1897 if (tree.tokenTag(payload_token) == .asterisk) {
1901 try renderToken(r, payload_token, .none); // asterisk1898 try renderToken(r, payload_token, .none); // asterisk
1902 }1899 }
1903 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier1900 try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier
1904 if (token_tags[ident + 1] == .comma) {1901 if (tree.tokenTag(ident + 1) == .comma) {
1905 try renderToken(r, ident + 1, .space); // ,1902 try renderToken(r, ident + 1, .space); // ,
1906 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier1903 try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier
1907 try renderToken(r, ident + 3, pre_target_space); // pipe1904 try renderToken(r, ident + 3, pre_target_space); // pipe
...@@ -1921,12 +1918,9 @@ fn renderBlock(...@@ -1921,12 +1918,9 @@ fn renderBlock(
1921) Error!void {1918) Error!void {
1922 const tree = r.tree;1919 const tree = r.tree;
1923 const ais = r.ais;1920 const ais = r.ais;
1924 const token_tags = tree.tokens.items(.tag);1921 const lbrace = tree.nodeMainToken(block_node);
1925 const lbrace = tree.nodes.items(.main_token)[block_node];
19261922
1927 if (token_tags[lbrace - 1] == .colon and1923 if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) {
1928 token_tags[lbrace - 2] == .identifier)
1929 {
1930 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier1924 try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier
1931 try renderToken(r, lbrace - 1, .space); // :1925 try renderToken(r, lbrace - 1, .space); // :
1932 }1926 }
...@@ -1948,13 +1942,12 @@ fn finishRenderBlock(...@@ -1948,13 +1942,12 @@ fn finishRenderBlock(
1948 space: Space,1942 space: Space,
1949) Error!void {1943) Error!void {
1950 const tree = r.tree;1944 const tree = r.tree;
1951 const node_tags = tree.nodes.items(.tag);
1952 const ais = r.ais;1945 const ais = r.ais;
1953 for (statements, 0..) |stmt, i| {1946 for (statements, 0..) |stmt, i| {
1954 if (i != 0) try renderExtraNewline(r, stmt);1947 if (i != 0) try renderExtraNewline(r, stmt);
1955 if (r.fixups.omit_nodes.contains(stmt)) continue;1948 if (r.fixups.omit_nodes.contains(stmt)) continue;
1956 try ais.pushSpace(.semicolon);1949 try ais.pushSpace(.semicolon);
1957 switch (node_tags[stmt]) {1950 switch (tree.nodeTag(stmt)) {
1958 .global_var_decl,1951 .global_var_decl,
1959 .local_var_decl,1952 .local_var_decl,
1960 .simple_var_decl,1953 .simple_var_decl,
...@@ -1978,12 +1971,13 @@ fn renderStructInit(...@@ -1978,12 +1971,13 @@ fn renderStructInit(
1978) Error!void {1971) Error!void {
1979 const tree = r.tree;1972 const tree = r.tree;
1980 const ais = r.ais;1973 const ais = r.ais;
1981 const token_tags = tree.tokens.items(.tag);1974
1982 if (struct_init.ast.type_expr == 0) {1975 if (struct_init.ast.type_expr.unwrap()) |type_expr| {
1983 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .1976 try renderExpression(r, type_expr, .none); // T
1984 } else {1977 } else {
1985 try renderExpression(r, struct_init.ast.type_expr, .none); // T1978 try renderToken(r, struct_init.ast.lbrace - 1, .none); // .
1986 }1979 }
1980
1987 if (struct_init.ast.fields.len == 0) {1981 if (struct_init.ast.fields.len == 0) {
1988 try ais.pushIndent(.normal);1982 try ais.pushIndent(.normal);
1989 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace1983 try renderToken(r, struct_init.ast.lbrace, .none); // lbrace
...@@ -1992,7 +1986,7 @@ fn renderStructInit(...@@ -1992,7 +1986,7 @@ fn renderStructInit(
1992 }1986 }
19931987
1994 const rbrace = tree.lastToken(struct_node);1988 const rbrace = tree.lastToken(struct_node);
1995 const trailing_comma = token_tags[rbrace - 1] == .comma;1989 const trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
1996 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {1990 if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) {
1997 // Render one field init per line.1991 // Render one field init per line.
1998 try ais.pushIndent(.normal);1992 try ais.pushIndent(.normal);
...@@ -2002,9 +1996,8 @@ fn renderStructInit(...@@ -2002,9 +1996,8 @@ fn renderStructInit(
2002 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name1996 try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name
2003 // Don't output a space after the = if expression is a multiline string,1997 // Don't output a space after the = if expression is a multiline string,
2004 // since then it will start on the next line.1998 // since then it will start on the next line.
2005 const nodes = tree.nodes.items(.tag);
2006 const field_node = struct_init.ast.fields[0];1999 const field_node = struct_init.ast.fields[0];
2007 const expr = nodes[field_node];2000 const expr = tree.nodeTag(field_node);
2008 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;2001 var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space;
2009 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =2002 try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // =
20102003
...@@ -2017,7 +2010,7 @@ fn renderStructInit(...@@ -2017,7 +2010,7 @@ fn renderStructInit(
2017 try renderExtraNewlineToken(r, init_token - 3);2010 try renderExtraNewlineToken(r, init_token - 3);
2018 try renderToken(r, init_token - 3, .none); // .2011 try renderToken(r, init_token - 3, .none); // .
2019 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name2012 try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name
2020 space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space;2013 space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space;
2021 try renderToken(r, init_token - 1, space_after_equal); // =2014 try renderToken(r, init_token - 1, space_after_equal); // =
20222015
2023 try ais.pushSpace(.comma);2016 try ais.pushSpace(.comma);
...@@ -2050,12 +2043,11 @@ fn renderArrayInit(...@@ -2050,12 +2043,11 @@ fn renderArrayInit(
2050 const tree = r.tree;2043 const tree = r.tree;
2051 const ais = r.ais;2044 const ais = r.ais;
2052 const gpa = r.gpa;2045 const gpa = r.gpa;
2053 const token_tags = tree.tokens.items(.tag);
20542046
2055 if (array_init.ast.type_expr == 0) {2047 if (array_init.ast.type_expr.unwrap()) |type_expr| {
2056 try renderToken(r, array_init.ast.lbrace - 1, .none); // .2048 try renderExpression(r, type_expr, .none); // T
2057 } else {2049 } else {
2058 try renderExpression(r, array_init.ast.type_expr, .none); // T2050 try renderToken(r, array_init.ast.lbrace - 1, .none); // .
2059 }2051 }
20602052
2061 if (array_init.ast.elements.len == 0) {2053 if (array_init.ast.elements.len == 0) {
...@@ -2067,14 +2059,14 @@ fn renderArrayInit(...@@ -2067,14 +2059,14 @@ fn renderArrayInit(
20672059
2068 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];2060 const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1];
2069 const last_elem_token = tree.lastToken(last_elem);2061 const last_elem_token = tree.lastToken(last_elem);
2070 const trailing_comma = token_tags[last_elem_token + 1] == .comma;2062 const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma;
2071 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;2063 const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1;
2072 assert(token_tags[rbrace] == .r_brace);2064 assert(tree.tokenTag(rbrace) == .r_brace);
20732065
2074 if (array_init.ast.elements.len == 1) {2066 if (array_init.ast.elements.len == 1) {
2075 const only_elem = array_init.ast.elements[0];2067 const only_elem = array_init.ast.elements[0];
2076 const first_token = tree.firstToken(only_elem);2068 const first_token = tree.firstToken(only_elem);
2077 if (token_tags[first_token] != .multiline_string_literal_line and2069 if (tree.tokenTag(first_token) != .multiline_string_literal_line and
2078 !anythingBetween(tree, last_elem_token, rbrace))2070 !anythingBetween(tree, last_elem_token, rbrace))
2079 {2071 {
2080 try renderToken(r, array_init.ast.lbrace, .none);2072 try renderToken(r, array_init.ast.lbrace, .none);
...@@ -2137,7 +2129,7 @@ fn renderArrayInit(...@@ -2137,7 +2129,7 @@ fn renderArrayInit(
2137 }2129 }
21382130
2139 const maybe_comma = expr_last_token + 1;2131 const maybe_comma = expr_last_token + 1;
2140 if (token_tags[maybe_comma] == .comma) {2132 if (tree.tokenTag(maybe_comma) == .comma) {
2141 if (hasSameLineComment(tree, maybe_comma))2133 if (hasSameLineComment(tree, maybe_comma))
2142 break :sec_end i - this_line_size + 1;2134 break :sec_end i - this_line_size + 1;
2143 }2135 }
...@@ -2277,13 +2269,12 @@ fn renderContainerDecl(...@@ -2277,13 +2269,12 @@ fn renderContainerDecl(
2277) Error!void {2269) Error!void {
2278 const tree = r.tree;2270 const tree = r.tree;
2279 const ais = r.ais;2271 const ais = r.ais;
2280 const token_tags = tree.tokens.items(.tag);
22812272
2282 if (container_decl.layout_token) |layout_token| {2273 if (container_decl.layout_token) |layout_token| {
2283 try renderToken(r, layout_token, .space);2274 try renderToken(r, layout_token, .space);
2284 }2275 }
22852276
2286 const container: Container = switch (token_tags[container_decl.ast.main_token]) {2277 const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) {
2287 .keyword_enum => .@"enum",2278 .keyword_enum => .@"enum",
2288 .keyword_struct => for (container_decl.ast.members) |member| {2279 .keyword_struct => for (container_decl.ast.members) |member| {
2289 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;2280 if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other;
...@@ -2296,10 +2287,10 @@ fn renderContainerDecl(...@@ -2296,10 +2287,10 @@ fn renderContainerDecl(
2296 try renderToken(r, container_decl.ast.main_token, .none); // union2287 try renderToken(r, container_decl.ast.main_token, .none); // union
2297 try renderToken(r, enum_token - 1, .none); // lparen2288 try renderToken(r, enum_token - 1, .none); // lparen
2298 try renderToken(r, enum_token, .none); // enum2289 try renderToken(r, enum_token, .none); // enum
2299 if (container_decl.ast.arg != 0) {2290 if (container_decl.ast.arg.unwrap()) |arg| {
2300 try renderToken(r, enum_token + 1, .none); // lparen2291 try renderToken(r, enum_token + 1, .none); // lparen
2301 try renderExpression(r, container_decl.ast.arg, .none);2292 try renderExpression(r, arg, .none);
2302 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2293 const rparen = tree.lastToken(arg) + 1;
2303 try renderToken(r, rparen, .none); // rparen2294 try renderToken(r, rparen, .none); // rparen
2304 try renderToken(r, rparen + 1, .space); // rparen2295 try renderToken(r, rparen + 1, .space); // rparen
2305 lbrace = rparen + 2;2296 lbrace = rparen + 2;
...@@ -2307,11 +2298,11 @@ fn renderContainerDecl(...@@ -2307,11 +2298,11 @@ fn renderContainerDecl(
2307 try renderToken(r, enum_token + 1, .space); // rparen2298 try renderToken(r, enum_token + 1, .space); // rparen
2308 lbrace = enum_token + 2;2299 lbrace = enum_token + 2;
2309 }2300 }
2310 } else if (container_decl.ast.arg != 0) {2301 } else if (container_decl.ast.arg.unwrap()) |arg| {
2311 try renderToken(r, container_decl.ast.main_token, .none); // union2302 try renderToken(r, container_decl.ast.main_token, .none); // union
2312 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen2303 try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen
2313 try renderExpression(r, container_decl.ast.arg, .none);2304 try renderExpression(r, arg, .none);
2314 const rparen = tree.lastToken(container_decl.ast.arg) + 1;2305 const rparen = tree.lastToken(arg) + 1;
2315 try renderToken(r, rparen, .space); // rparen2306 try renderToken(r, rparen, .space); // rparen
2316 lbrace = rparen + 1;2307 lbrace = rparen + 1;
2317 } else {2308 } else {
...@@ -2320,9 +2311,10 @@ fn renderContainerDecl(...@@ -2320,9 +2311,10 @@ fn renderContainerDecl(
2320 }2311 }
23212312
2322 const rbrace = tree.lastToken(container_decl_node);2313 const rbrace = tree.lastToken(container_decl_node);
2314
2323 if (container_decl.ast.members.len == 0) {2315 if (container_decl.ast.members.len == 0) {
2324 try ais.pushIndent(.normal);2316 try ais.pushIndent(.normal);
2325 if (token_tags[lbrace + 1] == .container_doc_comment) {2317 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
2326 try renderToken(r, lbrace, .newline); // lbrace2318 try renderToken(r, lbrace, .newline); // lbrace
2327 try renderContainerDocComments(r, lbrace + 1);2319 try renderContainerDocComments(r, lbrace + 1);
2328 } else {2320 } else {
...@@ -2332,7 +2324,7 @@ fn renderContainerDecl(...@@ -2332,7 +2324,7 @@ fn renderContainerDecl(
2332 return renderToken(r, rbrace, space); // rbrace2324 return renderToken(r, rbrace, space); // rbrace
2333 }2325 }
23342326
2335 const src_has_trailing_comma = token_tags[rbrace - 1] == .comma;2327 const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma;
2336 if (!src_has_trailing_comma) one_line: {2328 if (!src_has_trailing_comma) one_line: {
2337 // We print all the members in-line unless one of the following conditions are true:2329 // We print all the members in-line unless one of the following conditions are true:
23382330
...@@ -2342,10 +2334,10 @@ fn renderContainerDecl(...@@ -2342,10 +2334,10 @@ fn renderContainerDecl(
2342 }2334 }
23432335
2344 // 2. The container has a container comment.2336 // 2. The container has a container comment.
2345 if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line;2337 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line;
23462338
2347 // 3. A member of the container has a doc comment.2339 // 3. A member of the container has a doc comment.
2348 for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| {2340 for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| {
2349 if (tag == .doc_comment) break :one_line;2341 if (tag == .doc_comment) break :one_line;
2350 }2342 }
23512343
...@@ -2365,12 +2357,12 @@ fn renderContainerDecl(...@@ -2365,12 +2357,12 @@ fn renderContainerDecl(
2365 // One member per line.2357 // One member per line.
2366 try ais.pushIndent(.normal);2358 try ais.pushIndent(.normal);
2367 try renderToken(r, lbrace, .newline); // lbrace2359 try renderToken(r, lbrace, .newline); // lbrace
2368 if (token_tags[lbrace + 1] == .container_doc_comment) {2360 if (tree.tokenTag(lbrace + 1) == .container_doc_comment) {
2369 try renderContainerDocComments(r, lbrace + 1);2361 try renderContainerDocComments(r, lbrace + 1);
2370 }2362 }
2371 for (container_decl.ast.members, 0..) |member, i| {2363 for (container_decl.ast.members, 0..) |member, i| {
2372 if (i != 0) try renderExtraNewline(r, member);2364 if (i != 0) try renderExtraNewline(r, member);
2373 switch (tree.nodes.items(.tag)[member]) {2365 switch (tree.nodeTag(member)) {
2374 // For container fields, ensure a trailing comma is added if necessary.2366 // For container fields, ensure a trailing comma is added if necessary.
2375 .container_field_init,2367 .container_field_init,
2376 .container_field_align,2368 .container_field_align,
...@@ -2396,7 +2388,6 @@ fn renderAsm(...@@ -2396,7 +2388,6 @@ fn renderAsm(
2396) Error!void {2388) Error!void {
2397 const tree = r.tree;2389 const tree = r.tree;
2398 const ais = r.ais;2390 const ais = r.ais;
2399 const token_tags = tree.tokens.items(.tag);
24002391
2401 try renderToken(r, asm_node.ast.asm_token, .space); // asm2392 try renderToken(r, asm_node.ast.asm_token, .space); // asm
24022393
...@@ -2422,13 +2413,13 @@ fn renderAsm(...@@ -2422,13 +2413,13 @@ fn renderAsm(
2422 while (true) : (tok_i += 1) {2413 while (true) : (tok_i += 1) {
2423 try renderToken(r, tok_i, .none);2414 try renderToken(r, tok_i, .none);
2424 tok_i += 1;2415 tok_i += 1;
2425 switch (token_tags[tok_i]) {2416 switch (tree.tokenTag(tok_i)) {
2426 .r_paren => {2417 .r_paren => {
2427 ais.popIndent();2418 ais.popIndent();
2428 return renderToken(r, tok_i, space);2419 return renderToken(r, tok_i, space);
2429 },2420 },
2430 .comma => {2421 .comma => {
2431 if (token_tags[tok_i + 1] == .r_paren) {2422 if (tree.tokenTag(tok_i + 1) == .r_paren) {
2432 ais.popIndent();2423 ais.popIndent();
2433 return renderToken(r, tok_i + 1, space);2424 return renderToken(r, tok_i + 1, space);
2434 } else {2425 } else {
...@@ -2480,7 +2471,7 @@ fn renderAsm(...@@ -2480,7 +2471,7 @@ fn renderAsm(
2480 ais.popSpace();2471 ais.popSpace();
2481 const comma_or_colon = tree.lastToken(asm_output) + 1;2472 const comma_or_colon = tree.lastToken(asm_output) + 1;
2482 ais.popIndent();2473 ais.popIndent();
2483 break :colon2 switch (token_tags[comma_or_colon]) {2474 break :colon2 switch (tree.tokenTag(comma_or_colon)) {
2484 .comma => comma_or_colon + 1,2475 .comma => comma_or_colon + 1,
2485 else => comma_or_colon,2476 else => comma_or_colon,
2486 };2477 };
...@@ -2516,7 +2507,7 @@ fn renderAsm(...@@ -2516,7 +2507,7 @@ fn renderAsm(
2516 ais.popSpace();2507 ais.popSpace();
2517 const comma_or_colon = tree.lastToken(asm_input) + 1;2508 const comma_or_colon = tree.lastToken(asm_input) + 1;
2518 ais.popIndent();2509 ais.popIndent();
2519 break :colon3 switch (token_tags[comma_or_colon]) {2510 break :colon3 switch (tree.tokenTag(comma_or_colon)) {
2520 .comma => comma_or_colon + 1,2511 .comma => comma_or_colon + 1,
2521 else => comma_or_colon,2512 else => comma_or_colon,
2522 };2513 };
...@@ -2529,7 +2520,7 @@ fn renderAsm(...@@ -2529,7 +2520,7 @@ fn renderAsm(
2529 const first_clobber = asm_node.first_clobber.?;2520 const first_clobber = asm_node.first_clobber.?;
2530 var tok_i = first_clobber;2521 var tok_i = first_clobber;
2531 while (true) {2522 while (true) {
2532 switch (token_tags[tok_i + 1]) {2523 switch (tree.tokenTag(tok_i + 1)) {
2533 .r_paren => {2524 .r_paren => {
2534 ais.setIndentDelta(indent_delta);2525 ais.setIndentDelta(indent_delta);
2535 try renderToken(r, tok_i, .newline);2526 try renderToken(r, tok_i, .newline);
...@@ -2537,7 +2528,7 @@ fn renderAsm(...@@ -2537,7 +2528,7 @@ fn renderAsm(
2537 return renderToken(r, tok_i + 1, space);2528 return renderToken(r, tok_i + 1, space);
2538 },2529 },
2539 .comma => {2530 .comma => {
2540 switch (token_tags[tok_i + 2]) {2531 switch (tree.tokenTag(tok_i + 2)) {
2541 .r_paren => {2532 .r_paren => {
2542 ais.setIndentDelta(indent_delta);2533 ais.setIndentDelta(indent_delta);
2543 try renderToken(r, tok_i, .newline);2534 try renderToken(r, tok_i, .newline);
...@@ -2576,7 +2567,6 @@ fn renderParamList(...@@ -2576,7 +2567,6 @@ fn renderParamList(
2576) Error!void {2567) Error!void {
2577 const tree = r.tree;2568 const tree = r.tree;
2578 const ais = r.ais;2569 const ais = r.ais;
2579 const token_tags = tree.tokens.items(.tag);
25802570
2581 if (params.len == 0) {2571 if (params.len == 0) {
2582 try ais.pushIndent(.normal);2572 try ais.pushIndent(.normal);
...@@ -2587,7 +2577,7 @@ fn renderParamList(...@@ -2587,7 +2577,7 @@ fn renderParamList(
25872577
2588 const last_param = params[params.len - 1];2578 const last_param = params[params.len - 1];
2589 const after_last_param_tok = tree.lastToken(last_param) + 1;2579 const after_last_param_tok = tree.lastToken(last_param) + 1;
2590 if (token_tags[after_last_param_tok] == .comma) {2580 if (tree.tokenTag(after_last_param_tok) == .comma) {
2591 try ais.pushIndent(.normal);2581 try ais.pushIndent(.normal);
2592 try renderToken(r, lparen, .newline); // (2582 try renderToken(r, lparen, .newline); // (
2593 for (params, 0..) |param_node, i| {2583 for (params, 0..) |param_node, i| {
...@@ -2616,7 +2606,7 @@ fn renderParamList(...@@ -2616,7 +2606,7 @@ fn renderParamList(
2616 if (i + 1 < params.len) {2606 if (i + 1 < params.len) {
2617 const comma = tree.lastToken(param_node) + 1;2607 const comma = tree.lastToken(param_node) + 1;
2618 const next_multiline_string =2608 const next_multiline_string =
2619 token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line;2609 tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line;
2620 const comma_space: Space = if (next_multiline_string) .none else .space;2610 const comma_space: Space = if (next_multiline_string) .none else .space;
2621 try renderToken(r, comma, comma_space);2611 try renderToken(r, comma, comma_space);
2622 }2612 }
...@@ -2629,9 +2619,8 @@ fn renderParamList(...@@ -2629,9 +2619,8 @@ fn renderParamList(
2629/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2619/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2630fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {2620fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
2631 const tree = r.tree;2621 const tree = r.tree;
2632 const token_tags = tree.tokens.items(.tag);
2633 const maybe_comma = tree.lastToken(node) + 1;2622 const maybe_comma = tree.lastToken(node) + 1;
2634 if (token_tags[maybe_comma] == .comma and space != .comma) {2623 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2635 try renderExpression(r, node, .none);2624 try renderExpression(r, node, .none);
2636 return renderToken(r, maybe_comma, space);2625 return renderToken(r, maybe_comma, space);
2637 } else {2626 } else {
...@@ -2643,9 +2632,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v...@@ -2643,9 +2632,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v
2643/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2632/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2644fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {2633fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
2645 const tree = r.tree;2634 const tree = r.tree;
2646 const token_tags = tree.tokens.items(.tag);
2647 const maybe_comma = token + 1;2635 const maybe_comma = token + 1;
2648 if (token_tags[maybe_comma] == .comma and space != .comma) {2636 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2649 try renderToken(r, token, .none);2637 try renderToken(r, token, .none);
2650 return renderToken(r, maybe_comma, space);2638 return renderToken(r, maybe_comma, space);
2651 } else {2639 } else {
...@@ -2657,9 +2645,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void...@@ -2657,9 +2645,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void
2657/// If a comma is present, and `space` is `Space.comma`, render only a single comma.2645/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
2658fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2646fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2659 const tree = r.tree;2647 const tree = r.tree;
2660 const token_tags = tree.tokens.items(.tag);
2661 const maybe_comma = token + 1;2648 const maybe_comma = token + 1;
2662 if (token_tags[maybe_comma] == .comma and space != .comma) {2649 if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
2663 try renderIdentifier(r, token, .none, quote);2650 try renderIdentifier(r, token, .none, quote);
2664 return renderToken(r, maybe_comma, space);2651 return renderToken(r, maybe_comma, space);
2665 } else {2652 } else {
...@@ -2709,37 +2696,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:...@@ -2709,37 +2696,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
2709fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {2696fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
2710 const tree = r.tree;2697 const tree = r.tree;
2711 const ais = r.ais;2698 const ais = r.ais;
2712 const token_tags = tree.tokens.items(.tag);
2713 const token_starts = tree.tokens.items(.start);
27142699
2715 const token_start = token_starts[token_index];2700 const next_token_tag = tree.tokenTag(token_index + 1);
27162701
2717 if (space == .skip) return;2702 if (space == .skip) return;
27182703
2719 if (space == .comma and token_tags[token_index + 1] != .comma) {2704 if (space == .comma and next_token_tag != .comma) {
2720 try ais.writer().writeByte(',');2705 try ais.writer().writeByte(',');
2721 }2706 }
2722 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);2707 if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
2723 defer ais.disableSpaceMode();2708 defer ais.disableSpaceMode();
2724 const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]);2709 const comment = try renderComments(
2710 r,
2711 tree.tokenStart(token_index) + lexeme_len,
2712 tree.tokenStart(token_index + 1),
2713 );
2725 switch (space) {2714 switch (space) {
2726 .none => {},2715 .none => {},
2727 .space => if (!comment) try ais.writer().writeByte(' '),2716 .space => if (!comment) try ais.writer().writeByte(' '),
2728 .newline => if (!comment) try ais.insertNewline(),2717 .newline => if (!comment) try ais.insertNewline(),
27292718
2730 .comma => if (token_tags[token_index + 1] == .comma) {2719 .comma => if (next_token_tag == .comma) {
2731 try renderToken(r, token_index + 1, .newline);2720 try renderToken(r, token_index + 1, .newline);
2732 } else if (!comment) {2721 } else if (!comment) {
2733 try ais.insertNewline();2722 try ais.insertNewline();
2734 },2723 },
27352724
2736 .comma_space => if (token_tags[token_index + 1] == .comma) {2725 .comma_space => if (next_token_tag == .comma) {
2737 try renderToken(r, token_index + 1, .space);2726 try renderToken(r, token_index + 1, .space);
2738 } else if (!comment) {2727 } else if (!comment) {
2739 try ais.writer().writeByte(' ');2728 try ais.writer().writeByte(' ');
2740 },2729 },
27412730
2742 .semicolon => if (token_tags[token_index + 1] == .semicolon) {2731 .semicolon => if (next_token_tag == .semicolon) {
2743 try renderToken(r, token_index + 1, .newline);2732 try renderToken(r, token_index + 1, .newline);
2744 } else if (!comment) {2733 } else if (!comment) {
2745 try ais.insertNewline();2734 try ais.insertNewline();
...@@ -2770,8 +2759,7 @@ const QuoteBehavior = enum {...@@ -2770,8 +2759,7 @@ const QuoteBehavior = enum {
27702759
2771fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {2760fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
2772 const tree = r.tree;2761 const tree = r.tree;
2773 const token_tags = tree.tokens.items(.tag);2762 assert(tree.tokenTag(token_index) == .identifier);
2774 assert(token_tags[token_index] == .identifier);
2775 const lexeme = tokenSliceForRender(tree, token_index);2763 const lexeme = tokenSliceForRender(tree, token_index);
27762764
2777 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {2765 if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
...@@ -2880,8 +2868,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote...@@ -2880,8 +2868,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote
2880fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {2868fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void {
2881 const tree = r.tree;2869 const tree = r.tree;
2882 const ais = r.ais;2870 const ais = r.ais;
2883 const token_tags = tree.tokens.items(.tag);2871 assert(tree.tokenTag(token_index) == .identifier);
2884 assert(token_tags[token_index] == .identifier);
2885 const lexeme = tokenSliceForRender(tree, token_index);2872 const lexeme = tokenSliceForRender(tree, token_index);
2886 assert(lexeme.len >= 3 and lexeme[0] == '@');2873 assert(lexeme.len >= 3 and lexeme[0] == '@');
28872874
...@@ -2934,12 +2921,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {...@@ -2934,12 +2921,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
2934/// fn_proto should be wrapped and have a trailing comma inserted even if2921/// fn_proto should be wrapped and have a trailing comma inserted even if
2935/// there is none in the source.2922/// there is none in the source.
2936fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {2923fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2937 const token_starts = tree.tokens.items(.start);2924 for (start_token..end_token) |i| {
29382925 const token: Ast.TokenIndex = @intCast(i);
2939 var i = start_token;2926 const start = tree.tokenStart(token) + tree.tokenSlice(token).len;
2940 while (i < end_token) : (i += 1) {2927 const end = tree.tokenStart(token + 1);
2941 const start = token_starts[i] + tree.tokenSlice(i).len;
2942 const end = token_starts[i + 1];
2943 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;2928 if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true;
2944 }2929 }
29452930
...@@ -2949,16 +2934,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)...@@ -2949,16 +2934,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex)
2949/// Returns true if there exists a multiline string literal between the start2934/// Returns true if there exists a multiline string literal between the start
2950/// of token `start_token` and the start of token `end_token`.2935/// of token `start_token` and the start of token `end_token`.
2951fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {2936fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
2952 const token_tags = tree.tokens.items(.tag);2937 return std.mem.indexOfScalar(
29532938 Token.Tag,
2954 for (token_tags[start_token..end_token]) |tag| {2939 tree.tokens.items(.tag)[start_token..end_token],
2955 switch (tag) {2940 .multiline_string_literal_line,
2956 .multiline_string_literal_line => return true,2941 ) != null;
2957 else => continue,
2958 }
2959 }
2960
2961 return false;
2962}2942}
29632943
2964/// Assumes that start is the first byte past the previous token and2944/// Assumes that start is the first byte past the previous token and
...@@ -3034,18 +3014,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {...@@ -3034,18 +3014,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
3034fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {3014fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
3035 const tree = r.tree;3015 const tree = r.tree;
3036 const ais = r.ais;3016 const ais = r.ais;
3037 const token_starts = tree.tokens.items(.start);3017 const token_start = tree.tokenStart(token_index);
3038 const token_start = token_starts[token_index];
3039 if (token_start == 0) return;3018 if (token_start == 0) return;
3040 const prev_token_end = if (token_index == 0)3019 const prev_token_end = if (token_index == 0)
3041 03020 0
3042 else3021 else
3043 token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len;3022 tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len;
30443023
3045 // If there is a immediately preceding comment or doc_comment,3024 // If there is a immediately preceding comment or doc_comment,
3046 // skip it because required extra newline has already been rendered.3025 // skip it because required extra newline has already been rendered.
3047 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;3026 if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return;
3048 if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return;3027 if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return;
30493028
3050 // Iterate backwards to the end of the previous token, stopping if a3029 // Iterate backwards to the end of the previous token, stopping if a
3051 // non-whitespace character is encountered or two newlines have been found.3030 // non-whitespace character is encountered or two newlines have been found.
...@@ -3063,10 +3042,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {...@@ -3063,10 +3042,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
3063fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {3042fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3064 const tree = r.tree;3043 const tree = r.tree;
3065 // Search backwards for the first doc comment.3044 // Search backwards for the first doc comment.
3066 const token_tags = tree.tokens.items(.tag);
3067 if (end_token == 0) return;3045 if (end_token == 0) return;
3068 var tok = end_token - 1;3046 var tok = end_token - 1;
3069 while (token_tags[tok] == .doc_comment) {3047 while (tree.tokenTag(tok) == .doc_comment) {
3070 if (tok == 0) break;3048 if (tok == 0) break;
3071 tok -= 1;3049 tok -= 1;
3072 } else {3050 } else {
...@@ -3076,7 +3054,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3076,7 +3054,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3076 if (first_tok == end_token) return;3054 if (first_tok == end_token) return;
30773055
3078 if (first_tok != 0) {3056 if (first_tok != 0) {
3079 const prev_token_tag = token_tags[first_tok - 1];3057 const prev_token_tag = tree.tokenTag(first_tok - 1);
30803058
3081 // Prevent accidental use of `renderDocComments` for a function argument doc comment3059 // Prevent accidental use of `renderDocComments` for a function argument doc comment
3082 assert(prev_token_tag != .l_paren);3060 assert(prev_token_tag != .l_paren);
...@@ -3086,7 +3064,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3086,7 +3064,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3086 }3064 }
3087 }3065 }
30883066
3089 while (token_tags[tok] == .doc_comment) : (tok += 1) {3067 while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) {
3090 try renderToken(r, tok, .newline);3068 try renderToken(r, tok, .newline);
3091 }3069 }
3092}3070}
...@@ -3094,15 +3072,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {...@@ -3094,15 +3072,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
3094/// start_token is first container doc comment token.3072/// start_token is first container doc comment token.
3095fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {3073fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
3096 const tree = r.tree;3074 const tree = r.tree;
3097 const token_tags = tree.tokens.items(.tag);
3098 var tok = start_token;3075 var tok = start_token;
3099 while (token_tags[tok] == .container_doc_comment) : (tok += 1) {3076 while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
3100 try renderToken(r, tok, .newline);3077 try renderToken(r, tok, .newline);
3101 }3078 }
3102 // Render extra newline if there is one between final container doc comment and3079 // Render extra newline if there is one between final container doc comment and
3103 // the next token. If the next token is a doc comment, that code path3080 // the next token. If the next token is a doc comment, that code path
3104 // will have its own logic to insert a newline.3081 // will have its own logic to insert a newline.
3105 if (token_tags[tok] != .doc_comment) {3082 if (tree.tokenTag(tok) != .doc_comment) {
3106 try renderExtraNewlineToken(r, tok);3083 try renderExtraNewlineToken(r, tok);
3107 }3084 }
3108}3085}
...@@ -3112,11 +3089,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {...@@ -3112,11 +3089,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
3112 const ais = r.ais;3089 const ais = r.ais;
3113 var buf: [1]Ast.Node.Index = undefined;3090 var buf: [1]Ast.Node.Index = undefined;
3114 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;3091 const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?;
3115 const token_tags = tree.tokens.items(.tag);
3116 var it = fn_proto.iterate(tree);3092 var it = fn_proto.iterate(tree);
3117 while (it.next()) |param| {3093 while (it.next()) |param| {
3118 const name_ident = param.name_token.?;3094 const name_ident = param.name_token.?;
3119 assert(token_tags[name_ident] == .identifier);3095 assert(tree.tokenTag(name_ident) == .identifier);
3120 const w = ais.writer();3096 const w = ais.writer();
3121 try w.writeAll("_ = ");3097 try w.writeAll("_ = ");
3122 try w.writeAll(tokenSliceForRender(r.tree, name_ident));3098 try w.writeAll(tokenSliceForRender(r.tree, name_ident));
...@@ -3126,7 +3102,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {...@@ -3126,7 +3102,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
31263102
3127fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {3103fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3128 var ret = tree.tokenSlice(token_index);3104 var ret = tree.tokenSlice(token_index);
3129 switch (tree.tokens.items(.tag)[token_index]) {3105 switch (tree.tokenTag(token_index)) {
3130 .container_doc_comment, .doc_comment => {3106 .container_doc_comment, .doc_comment => {
3131 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);3107 ret = mem.trimRight(u8, ret, &std.ascii.whitespace);
3132 },3108 },
...@@ -3136,8 +3112,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {...@@ -3136,8 +3112,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 {
3136}3112}
31373113
3138fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {3114fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3139 const token_starts = tree.tokens.items(.start);3115 const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)];
3140 const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]];
3141 for (between_source) |byte| switch (byte) {3116 for (between_source) |byte| switch (byte) {
3142 '\n' => return false,3117 '\n' => return false,
3143 '/' => return true,3118 '/' => return true,
...@@ -3150,8 +3125,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {...@@ -3150,8 +3125,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool {
3150/// start_token and end_token.3125/// start_token and end_token.
3151fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {3126fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool {
3152 if (start_token + 1 != end_token) return true;3127 if (start_token + 1 != end_token) return true;
3153 const token_starts = tree.tokens.items(.start);3128 const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)];
3154 const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]];
3155 for (between_source) |byte| switch (byte) {3129 for (between_source) |byte| switch (byte) {
3156 '/' => return true,3130 '/' => return true,
3157 else => continue,3131 else => continue,
...@@ -3245,12 +3219,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {...@@ -3245,12 +3219,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool {
32453219
3246// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.3220// Returns the number of nodes in `exprs` that are on the same line as `rtoken`.
3247fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {3221fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize {
3248 const token_tags = tree.tokens.items(.tag);
3249
3250 const first_token = tree.firstToken(exprs[0]);3222 const first_token = tree.firstToken(exprs[0]);
3251 if (tree.tokensOnSameLine(first_token, rtoken)) {3223 if (tree.tokensOnSameLine(first_token, rtoken)) {
3252 const maybe_comma = rtoken - 1;3224 const maybe_comma = rtoken - 1;
3253 if (token_tags[maybe_comma] == .comma)3225 if (tree.tokenTag(maybe_comma) == .comma)
3254 return 1;3226 return 1;
3255 return exprs.len; // no newlines3227 return exprs.len; // no newlines
3256 }3228 }
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]),
...@@ -2322,7 +2322,7 @@ const TestFetchBuilder = struct {...@@ -2322,7 +2322,7 @@ const TestFetchBuilder = struct {
2322 .arena = std.heap.ArenaAllocator.init(allocator),2322 .arena = std.heap.ArenaAllocator.init(allocator),
2323 .location = .{ .path_or_url = path_or_url },2323 .location = .{ .path_or_url = path_or_url },
2324 .location_tok = 0,2324 .location_tok = 0,
2325 .hash_tok = 0,2325 .hash_tok = .none,
2326 .name_tok = 0,2326 .name_tok = 0,
2327 .lazy_status = .eager,2327 .lazy_status = .eager,
2328 .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } },2328 .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);
...@@ -17867,7 +17886,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17867,7 +17886,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17867 const ip = &zcu.intern_pool;17886 const ip = &zcu.intern_pool;
17868 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);17887 const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu);
1786917888
17870 const src_node: i32 = @bitCast(extended.operand);17889 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17871 const src = block.nodeOffset(src_node);17890 const src = block.nodeOffset(src_node);
1787217891
17873 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {17892 const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) {
...@@ -17891,8 +17910,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17891,8 +17910,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17891 });17910 });
17892 break :name null;17911 break :name null;
17893 };17912 };
17894 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));17913 const node = src_node.toAbsolute(src_base_node);
17895 const token = tree.nodes.items(.main_token)[node];17914 const token = tree.nodeMainToken(node);
17896 break :name tree.tokenSlice(token);17915 break :name tree.tokenSlice(token);
17897 };17916 };
1789817917
...@@ -17919,8 +17938,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17919,8 +17938,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17919 });17938 });
17920 break :name null;17939 break :name null;
17921 };17940 };
17922 const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node)));17941 const node = src_node.toAbsolute(src_base_node);
17923 const token = tree.nodes.items(.main_token)[node];17942 const token = tree.nodeMainToken(node);
17924 break :name tree.tokenSlice(token);17943 break :name tree.tokenSlice(token);
17925 };17944 };
1792617945
...@@ -17930,7 +17949,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17930,7 +17949,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17930 try sema.errMsg(src, "variable not accessible from inner function", .{});17949 try sema.errMsg(src, "variable not accessible from inner function", .{});
17931 errdefer msg.destroy(sema.gpa);17950 errdefer msg.destroy(sema.gpa);
1793217951
17933 try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{});17952 try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{});
1793417953
17935 // TODO add "declared here" note17954 // TODO add "declared here" note
17936 break :msg msg;17955 break :msg msg;
...@@ -17962,7 +17981,8 @@ fn zirFrameAddress(...@@ -17962,7 +17981,8 @@ fn zirFrameAddress(
17962 block: *Block,17981 block: *Block,
17963 extended: Zir.Inst.Extended.InstData,17982 extended: Zir.Inst.Extended.InstData,
17964) CompileError!Air.Inst.Ref {17983) CompileError!Air.Inst.Ref {
17965 const src = block.nodeOffset(@bitCast(extended.operand));17984 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
17985 const src = block.nodeOffset(src_node);
17966 try sema.requireRuntimeBlock(block, src, null);17986 try sema.requireRuntimeBlock(block, src, null);
17967 return try block.addNoOp(.frame_addr);17987 return try block.addNoOp(.frame_addr);
17968}17988}
...@@ -18059,7 +18079,7 @@ fn zirBuiltinSrc(...@@ -18059,7 +18079,7 @@ fn zirBuiltinSrc(
18059 } });18079 } });
18060 };18080 };
1806118081
18062 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation);18082 const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation);
18063 const fields = .{18083 const fields = .{
18064 // module: [:0]const u8,18084 // module: [:0]const u8,
18065 module_name_val,18085 module_name_val,
...@@ -19528,7 +19548,7 @@ fn zirCondbr(...@@ -19528,7 +19548,7 @@ fn zirCondbr(
19528fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19548fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19529 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;19549 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
19530 const src = parent_block.nodeOffset(inst_data.src_node);19550 const src = parent_block.nodeOffset(inst_data.src_node);
19531 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });19551 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
19532 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);19552 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
19533 const body = sema.code.bodySlice(extra.end, extra.data.body_len);19553 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
19534 const err_union = try sema.resolveInst(extra.data.operand);19554 const err_union = try sema.resolveInst(extra.data.operand);
...@@ -19587,7 +19607,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -19587,7 +19607,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
19587fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {19607fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19588 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;19608 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
19589 const src = parent_block.nodeOffset(inst_data.src_node);19609 const src = parent_block.nodeOffset(inst_data.src_node);
19590 const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node });19610 const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node });
19591 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);19611 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index);
19592 const body = sema.code.bodySlice(extra.end, extra.data.body_len);19612 const body = sema.code.bodySlice(extra.end, extra.data.body_len);
19593 const operand = try sema.resolveInst(extra.data.operand);19613 const operand = try sema.resolveInst(extra.data.operand);
...@@ -19790,7 +19810,7 @@ fn zirRetImplicit(...@@ -19790,7 +19810,7 @@ fn zirRetImplicit(
19790 }19810 }
1979119811
19792 const operand = try sema.resolveInst(inst_data.operand);19812 const operand = try sema.resolveInst(inst_data.operand);
19793 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 });19813 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
19794 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);19814 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
19795 if (base_tag == .noreturn) {19815 if (base_tag == .noreturn) {
19796 const msg = msg: {19816 const msg = msg: {
...@@ -21277,7 +21297,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -21277,7 +21297,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
21277 const pt = sema.pt;21297 const pt = sema.pt;
21278 const zcu = pt.zcu;21298 const zcu = pt.zcu;
21279 const ip = &zcu.intern_pool;21299 const ip = &zcu.intern_pool;
21280 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace);21300 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
21281 try stack_trace_ty.resolveFields(pt);21301 try stack_trace_ty.resolveFields(pt);
21282 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);21302 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
21283 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());21303 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
...@@ -21299,7 +21319,8 @@ fn zirFrame(...@@ -21299,7 +21319,8 @@ fn zirFrame(
21299 block: *Block,21319 block: *Block,
21300 extended: Zir.Inst.Extended.InstData,21320 extended: Zir.Inst.Extended.InstData,
21301) CompileError!Air.Inst.Ref {21321) CompileError!Air.Inst.Ref {
21302 const src = block.nodeOffset(@bitCast(extended.operand));21322 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
21323 const src = block.nodeOffset(src_node);
21303 return sema.failWithUseOfAsync(block, src);21324 return sema.failWithUseOfAsync(block, src);
21304}21325}
2130521326
...@@ -21553,13 +21574,13 @@ fn zirReify(...@@ -21553,13 +21574,13 @@ fn zirReify(
21553 const tracked_inst = try block.trackZir(inst);21574 const tracked_inst = try block.trackZir(inst);
21554 const src: LazySrcLoc = .{21575 const src: LazySrcLoc = .{
21555 .base_node_inst = tracked_inst,21576 .base_node_inst = tracked_inst,
21556 .offset = LazySrcLoc.Offset.nodeOffset(0),21577 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
21557 };21578 };
21558 const operand_src: LazySrcLoc = .{21579 const operand_src: LazySrcLoc = .{
21559 .base_node_inst = tracked_inst,21580 .base_node_inst = tracked_inst,
21560 .offset = .{21581 .offset = .{
21561 .node_offset_builtin_call_arg = .{21582 .node_offset_builtin_call_arg = .{
21562 .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 021583 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
21563 .arg_index = 0,21584 .arg_index = 0,
21564 },21585 },
21565 },21586 },
...@@ -22867,7 +22888,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -22867,7 +22888,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
22867}22888}
2286822889
22869fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {22890fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22870 const src = block.nodeOffset(@bitCast(extended.operand));22891 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
22892 const src = block.nodeOffset(src_node);
2287122893
22872 const va_list_ty = try sema.getBuiltinType(src, .VaList);22894 const va_list_ty = try sema.getBuiltinType(src, .VaList);
22873 try sema.requireRuntimeBlock(block, src, null);22895 try sema.requireRuntimeBlock(block, src, null);
...@@ -24272,12 +24294,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -24272,12 +24294,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
24272fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {24294fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 {
24273 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;24295 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
24274 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });24296 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node });
24275 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node });24297 const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
24276 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node });24298 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1);
24277 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;24299 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2427824300
24279 const ty = try sema.resolveType(block, lhs_src, extra.lhs);24301 const ty = try sema.resolveType(block, ty_src, extra.lhs);
24280 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name });24302 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name });
2428124303
24282 const pt = sema.pt;24304 const pt = sema.pt;
24283 const zcu = pt.zcu;24305 const zcu = pt.zcu;
...@@ -24285,15 +24307,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -24285,15 +24307,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
24285 try ty.resolveLayout(pt);24307 try ty.resolveLayout(pt);
24286 switch (ty.zigTypeTag(zcu)) {24308 switch (ty.zigTypeTag(zcu)) {
24287 .@"struct" => {},24309 .@"struct" => {},
24288 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),24310 else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}),
24289 }24311 }
2429024312
24291 const field_index = if (ty.isTuple(zcu)) blk: {24313 const field_index = if (ty.isTuple(zcu)) blk: {
24292 if (field_name.eqlSlice("len", ip)) {24314 if (field_name.eqlSlice("len", ip)) {
24293 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});24315 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
24294 }24316 }
24295 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);24317 break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src);
24296 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);24318 } else try sema.structFieldIndex(block, ty, field_name, field_name_src);
2429724319
24298 if (ty.structFieldIsComptime(field_index, zcu)) {24320 if (ty.structFieldIsComptime(field_index, zcu)) {
24299 return sema.fail(block, src, "no offset available for comptime field", .{});24321 return sema.fail(block, src, "no offset available for comptime field", .{});
...@@ -25077,7 +25099,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -25077,7 +25099,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
25077fn analyzeShuffle(25099fn analyzeShuffle(
25078 sema: *Sema,25100 sema: *Sema,
25079 block: *Block,25101 block: *Block,
25080 src_node: i32,25102 src_node: std.zig.Ast.Node.Offset,
25081 elem_ty: Type,25103 elem_ty: Type,
25082 a_arg: Air.Inst.Ref,25104 a_arg: Air.Inst.Ref,
25083 b_arg: Air.Inst.Ref,25105 b_arg: Air.Inst.Ref,
...@@ -27004,7 +27026,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -27004,7 +27026,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
27004 const gpa = zcu.gpa;27026 const gpa = zcu.gpa;
27005 const ip = &zcu.intern_pool;27027 const ip = &zcu.intern_pool;
2700627028
27007 const src = block.nodeOffset(@bitCast(extended.operand));27029 const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand)));
27030 const src = block.nodeOffset(src_node);
27008 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);27031 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2700927032
27010 const ty = switch (value) {27033 const ty = switch (value) {
...@@ -29479,7 +29502,7 @@ const CoerceOpts = struct {...@@ -29479,7 +29502,7 @@ const CoerceOpts = struct {
29479 return .{29502 return .{
29480 .base_node_inst = func_inst,29503 .base_node_inst = func_inst,
29481 .offset = .{ .fn_proto_param_type = .{29504 .offset = .{ .fn_proto_param_type = .{
29482 .fn_proto_node_offset = 0,29505 .fn_proto_node_offset = .zero,
29483 .param_index = info.param_i,29506 .param_index = info.param_i,
29484 } },29507 } },
29485 };29508 };
...@@ -30084,7 +30107,7 @@ fn coerceExtra(...@@ -30084,7 +30107,7 @@ fn coerceExtra(
3008430107
30085 const ret_ty_src: LazySrcLoc = .{30108 const ret_ty_src: LazySrcLoc = .{
30086 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),30109 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30087 .offset = .{ .node_offset_fn_type_ret_ty = 0 },30110 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
30088 };30111 };
30089 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});30112 try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{});
30090 break :msg msg;30113 break :msg msg;
...@@ -30124,7 +30147,7 @@ fn coerceExtra(...@@ -30124,7 +30147,7 @@ fn coerceExtra(
30124 {30147 {
30125 const ret_ty_src: LazySrcLoc = .{30148 const ret_ty_src: LazySrcLoc = .{
30126 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),30149 .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip),
30127 .offset = .{ .node_offset_fn_type_ret_ty = 0 },30150 .offset = .{ .node_offset_fn_type_ret_ty = .zero },
30128 };30151 };
30129 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {30152 if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) {
30130 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});30153 try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{});
...@@ -32325,7 +32348,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav...@@ -32325,7 +32348,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav
32325 if (zcu.analysis_in_progress.contains(anal_unit)) {32348 if (zcu.analysis_in_progress.contains(anal_unit)) {
32326 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{32349 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{
32327 .base_node_inst = nav.analysis.?.zir_index,32350 .base_node_inst = nav.analysis.?.zir_index,
32328 .offset = LazySrcLoc.Offset.nodeOffset(0),32351 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
32329 }, "dependency loop detected", .{}));32352 }, "dependency loop detected", .{}));
32330 }32353 }
3233132354
...@@ -33942,7 +33965,7 @@ const PeerTypeCandidateSrc = union(enum) {...@@ -33942,7 +33965,7 @@ const PeerTypeCandidateSrc = union(enum) {
33942 /// index i in this slice33965 /// index i in this slice
33943 override: []const ?LazySrcLoc,33966 override: []const ?LazySrcLoc,
33944 /// resolvePeerTypes originates from a @TypeOf(...) call33967 /// resolvePeerTypes originates from a @TypeOf(...) call
33945 typeof_builtin_call_node_offset: i32,33968 typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset,
3394633969
33947 pub fn resolve(33970 pub fn resolve(
33948 self: PeerTypeCandidateSrc,33971 self: PeerTypeCandidateSrc,
...@@ -35545,7 +35568,7 @@ fn backingIntType(...@@ -35545,7 +35568,7 @@ fn backingIntType(
3554535568
35546 const backing_int_src: LazySrcLoc = .{35569 const backing_int_src: LazySrcLoc = .{
35547 .base_node_inst = struct_type.zir_index,35570 .base_node_inst = struct_type.zir_index,
35548 .offset = .{ .node_offset_container_tag = 0 },35571 .offset = .{ .node_offset_container_tag = .zero },
35549 };35572 };
35550 block.comptime_reason = .{ .reason = .{35573 block.comptime_reason = .{ .reason = .{
35551 .src = backing_int_src,35574 .src = backing_int_src,
...@@ -35566,7 +35589,7 @@ fn backingIntType(...@@ -35566,7 +35589,7 @@ fn backingIntType(
35566 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());35589 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
35567 } else {35590 } else {
35568 if (fields_bit_sum > std.math.maxInt(u16)) {35591 if (fields_bit_sum > std.math.maxInt(u16)) {
35569 return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});35592 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
35570 }35593 }
35571 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));35594 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
35572 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());35595 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
...@@ -36167,7 +36190,7 @@ fn structFields(...@@ -36167,7 +36190,7 @@ fn structFields(
36167 .comptime_reason = .{ .reason = .{36190 .comptime_reason = .{ .reason = .{
36168 .src = .{36191 .src = .{
36169 .base_node_inst = struct_type.zir_index,36192 .base_node_inst = struct_type.zir_index,
36170 .offset = .nodeOffset(0),36193 .offset = .nodeOffset(.zero),
36171 },36194 },
36172 .r = .{ .simple = .struct_fields },36195 .r = .{ .simple = .struct_fields },
36173 } },36196 } },
...@@ -36508,7 +36531,7 @@ fn unionFields(...@@ -36508,7 +36531,7 @@ fn unionFields(
3650836531
36509 const src: LazySrcLoc = .{36532 const src: LazySrcLoc = .{
36510 .base_node_inst = union_type.zir_index,36533 .base_node_inst = union_type.zir_index,
36511 .offset = .nodeOffset(0),36534 .offset = .nodeOffset(.zero),
36512 };36535 };
3651336536
36514 var block_scope: Block = .{36537 var block_scope: Block = .{
...@@ -36537,7 +36560,7 @@ fn unionFields(...@@ -36537,7 +36560,7 @@ fn unionFields(
36537 if (tag_type_ref != .none) {36560 if (tag_type_ref != .none) {
36538 const tag_ty_src: LazySrcLoc = .{36561 const tag_ty_src: LazySrcLoc = .{
36539 .base_node_inst = union_type.zir_index,36562 .base_node_inst = union_type.zir_index,
36540 .offset = .{ .node_offset_container_tag = 0 },36563 .offset = .{ .node_offset_container_tag = .zero },
36541 };36564 };
36542 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);36565 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
36543 if (small.auto_enum_tag) {36566 if (small.auto_enum_tag) {
...@@ -38512,7 +38535,7 @@ pub fn resolveDeclaredEnum(...@@ -38512,7 +38535,7 @@ pub fn resolveDeclaredEnum(
38512 const zcu = pt.zcu;38535 const zcu = pt.zcu;
38513 const gpa = zcu.gpa;38536 const gpa = zcu.gpa;
3851438537
38515 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) };38538 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3851638539
38517 var arena: std.heap.ArenaAllocator = .init(gpa);38540 var arena: std.heap.ArenaAllocator = .init(gpa);
38518 defer arena.deinit();38541 defer arena.deinit();
...@@ -38599,7 +38622,7 @@ fn resolveDeclaredEnumInner(...@@ -38599,7 +38622,7 @@ fn resolveDeclaredEnumInner(
3859938622
38600 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;38623 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3860138624
38602 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } };38625 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } };
3860338626
38604 const int_tag_ty = ty: {38627 const int_tag_ty = ty: {
38605 if (body.len != 0) {38628 if (body.len != 0) {
...@@ -38752,9 +38775,9 @@ pub fn resolveNavPtrModifiers(...@@ -38752,9 +38775,9 @@ pub fn resolveNavPtrModifiers(
38752 const gpa = zcu.gpa;38775 const gpa = zcu.gpa;
38753 const ip = &zcu.intern_pool;38776 const ip = &zcu.intern_pool;
3875438777
38755 const align_src = block.src(.{ .node_offset_var_decl_align = 0 });38778 const align_src = block.src(.{ .node_offset_var_decl_align = .zero });
38756 const section_src = block.src(.{ .node_offset_var_decl_section = 0 });38779 const section_src = block.src(.{ .node_offset_var_decl_section = .zero });
38757 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });38780 const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero });
3875838781
38759 const alignment: InternPool.Alignment = a: {38782 const alignment: InternPool.Alignment = a: {
38760 const align_body = zir_decl.align_body orelse break :a .none;38783 const align_body = zir_decl.align_body orelse break :a .none;
...@@ -38827,7 +38850,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,...@@ -38827,7 +38850,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3882738850
38828 const src: LazySrcLoc = .{38851 const src: LazySrcLoc = .{
38829 .base_node_inst = ip.getNav(nav).srcInst(ip),38852 .base_node_inst = ip.getNav(nav).srcInst(ip),
38830 .offset = .nodeOffset(0),38853 .offset = .nodeOffset(.zero),
38831 };38854 };
3883238855
38833 const result = try sema.analyzeNavVal(block, src, nav);38856 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+278-295
...@@ -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,
...@@ -1031,10 +1031,6 @@ pub const SrcLoc = struct {...@@ -1031,10 +1031,6 @@ pub const SrcLoc = struct {
1031 return tree.firstToken(src_loc.base_node);1031 return tree.firstToken(src_loc.base_node);
1032 }1032 }
10331033
1034 pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
1035 return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node)));
1036 }
1037
1038 pub const Span = Ast.Span;1034 pub const Span = Ast.Span;
10391035
1040 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {1036 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
...@@ -1046,7 +1042,7 @@ pub const SrcLoc = struct {...@@ -1046,7 +1042,7 @@ pub const SrcLoc = struct {
10461042
1047 .token_abs => |tok_index| {1043 .token_abs => |tok_index| {
1048 const tree = try src_loc.file_scope.getTree(gpa);1044 const tree = try src_loc.file_scope.getTree(gpa);
1049 const start = tree.tokens.items(.start)[tok_index];1045 const start = tree.tokenStart(tok_index);
1050 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1046 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1051 return Span{ .start = start, .end = end, .main = start };1047 return Span{ .start = start, .end = end, .main = start };
1052 },1048 },
...@@ -1057,133 +1053,137 @@ pub const SrcLoc = struct {...@@ -1057,133 +1053,137 @@ pub const SrcLoc = struct {
1057 .byte_offset => |byte_off| {1053 .byte_offset => |byte_off| {
1058 const tree = try src_loc.file_scope.getTree(gpa);1054 const tree = try src_loc.file_scope.getTree(gpa);
1059 const tok_index = src_loc.baseSrcToken();1055 const tok_index = src_loc.baseSrcToken();
1060 const start = tree.tokens.items(.start)[tok_index] + byte_off;1056 const start = tree.tokenStart(tok_index) + byte_off;
1061 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1057 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1062 return Span{ .start = start, .end = end, .main = start };1058 return Span{ .start = start, .end = end, .main = start };
1063 },1059 },
1064 .token_offset => |tok_off| {1060 .token_offset => |tok_off| {
1065 const tree = try src_loc.file_scope.getTree(gpa);1061 const tree = try src_loc.file_scope.getTree(gpa);
1066 const tok_index = src_loc.baseSrcToken() + tok_off;1062 const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken());
1067 const start = tree.tokens.items(.start)[tok_index];1063 const start = tree.tokenStart(tok_index);
1068 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1064 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1069 return Span{ .start = start, .end = end, .main = start };1065 return Span{ .start = start, .end = end, .main = start };
1070 },1066 },
1071 .node_offset => |traced_off| {1067 .node_offset => |traced_off| {
1072 const node_off = traced_off.x;1068 const node_off = traced_off.x;
1073 const tree = try src_loc.file_scope.getTree(gpa);1069 const tree = try src_loc.file_scope.getTree(gpa);
1074 const node = src_loc.relativeToNodeIndex(node_off);1070 const node = node_off.toAbsolute(src_loc.base_node);
1075 return tree.nodeToSpan(node);1071 return tree.nodeToSpan(node);
1076 },1072 },
1077 .node_offset_main_token => |node_off| {1073 .node_offset_main_token => |node_off| {
1078 const tree = try src_loc.file_scope.getTree(gpa);1074 const tree = try src_loc.file_scope.getTree(gpa);
1079 const node = src_loc.relativeToNodeIndex(node_off);1075 const node = node_off.toAbsolute(src_loc.base_node);
1080 const main_token = tree.nodes.items(.main_token)[node];1076 const main_token = tree.nodeMainToken(node);
1081 return tree.tokensToSpan(main_token, main_token, main_token);1077 return tree.tokensToSpan(main_token, main_token, main_token);
1082 },1078 },
1083 .node_offset_bin_op => |node_off| {1079 .node_offset_bin_op => |node_off| {
1084 const tree = try src_loc.file_scope.getTree(gpa);1080 const tree = try src_loc.file_scope.getTree(gpa);
1085 const node = src_loc.relativeToNodeIndex(node_off);1081 const node = node_off.toAbsolute(src_loc.base_node);
1086 return tree.nodeToSpan(node);1082 return tree.nodeToSpan(node);
1087 },1083 },
1088 .node_offset_initializer => |node_off| {1084 .node_offset_initializer => |node_off| {
1089 const tree = try src_loc.file_scope.getTree(gpa);1085 const tree = try src_loc.file_scope.getTree(gpa);
1090 const node = src_loc.relativeToNodeIndex(node_off);1086 const node = node_off.toAbsolute(src_loc.base_node);
1091 return tree.tokensToSpan(1087 return tree.tokensToSpan(
1092 tree.firstToken(node) - 3,1088 tree.firstToken(node) - 3,
1093 tree.lastToken(node),1089 tree.lastToken(node),
1094 tree.nodes.items(.main_token)[node] - 2,1090 tree.nodeMainToken(node) - 2,
1095 );1091 );
1096 },1092 },
1097 .node_offset_var_decl_ty => |node_off| {1093 .node_offset_var_decl_ty => |node_off| {
1098 const tree = try src_loc.file_scope.getTree(gpa);1094 const tree = try src_loc.file_scope.getTree(gpa);
1099 const node = src_loc.relativeToNodeIndex(node_off);1095 const node = node_off.toAbsolute(src_loc.base_node);
1100 const node_tags = tree.nodes.items(.tag);1096 const full = switch (tree.nodeTag(node)) {
1101 const full = switch (node_tags[node]) {
1102 .global_var_decl,1097 .global_var_decl,
1103 .local_var_decl,1098 .local_var_decl,
1104 .simple_var_decl,1099 .simple_var_decl,
1105 .aligned_var_decl,1100 .aligned_var_decl,
1106 => tree.fullVarDecl(node).?,1101 => tree.fullVarDecl(node).?,
1107 .@"usingnamespace" => {1102 .@"usingnamespace" => {
1108 const node_data = tree.nodes.items(.data);1103 return tree.nodeToSpan(tree.nodeData(node).node);
1109 return tree.nodeToSpan(node_data[node].lhs);
1110 },1104 },
1111 else => unreachable,1105 else => unreachable,
1112 };1106 };
1113 if (full.ast.type_node != 0) {1107 if (full.ast.type_node.unwrap()) |type_node| {
1114 return tree.nodeToSpan(full.ast.type_node);1108 return tree.nodeToSpan(type_node);
1115 }1109 }
1116 const tok_index = full.ast.mut_token + 1; // the name token1110 const tok_index = full.ast.mut_token + 1; // the name token
1117 const start = tree.tokens.items(.start)[tok_index];1111 const start = tree.tokenStart(tok_index);
1118 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1112 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1119 return Span{ .start = start, .end = end, .main = start };1113 return Span{ .start = start, .end = end, .main = start };
1120 },1114 },
1121 .node_offset_var_decl_align => |node_off| {1115 .node_offset_var_decl_align => |node_off| {
1122 const tree = try src_loc.file_scope.getTree(gpa);1116 const tree = try src_loc.file_scope.getTree(gpa);
1123 const node = src_loc.relativeToNodeIndex(node_off);1117 const node = node_off.toAbsolute(src_loc.base_node);
1124 var buf: [1]Ast.Node.Index = undefined;1118 var buf: [1]Ast.Node.Index = undefined;
1125 const align_node = if (tree.fullVarDecl(node)) |v|1119 const align_node = if (tree.fullVarDecl(node)) |v|
1126 v.ast.align_node1120 v.ast.align_node.unwrap().?
1127 else if (tree.fullFnProto(&buf, node)) |f|1121 else if (tree.fullFnProto(&buf, node)) |f|
1128 f.ast.align_expr1122 f.ast.align_expr.unwrap().?
1129 else1123 else
1130 unreachable;1124 unreachable;
1131 return tree.nodeToSpan(align_node);1125 return tree.nodeToSpan(align_node);
1132 },1126 },
1133 .node_offset_var_decl_section => |node_off| {1127 .node_offset_var_decl_section => |node_off| {
1134 const tree = try src_loc.file_scope.getTree(gpa);1128 const tree = try src_loc.file_scope.getTree(gpa);
1135 const node = src_loc.relativeToNodeIndex(node_off);1129 const node = node_off.toAbsolute(src_loc.base_node);
1136 var buf: [1]Ast.Node.Index = undefined;1130 var buf: [1]Ast.Node.Index = undefined;
1137 const section_node = if (tree.fullVarDecl(node)) |v|1131 const section_node = if (tree.fullVarDecl(node)) |v|
1138 v.ast.section_node1132 v.ast.section_node.unwrap().?
1139 else if (tree.fullFnProto(&buf, node)) |f|1133 else if (tree.fullFnProto(&buf, node)) |f|
1140 f.ast.section_expr1134 f.ast.section_expr.unwrap().?
1141 else1135 else
1142 unreachable;1136 unreachable;
1143 return tree.nodeToSpan(section_node);1137 return tree.nodeToSpan(section_node);
1144 },1138 },
1145 .node_offset_var_decl_addrspace => |node_off| {1139 .node_offset_var_decl_addrspace => |node_off| {
1146 const tree = try src_loc.file_scope.getTree(gpa);1140 const tree = try src_loc.file_scope.getTree(gpa);
1147 const node = src_loc.relativeToNodeIndex(node_off);1141 const node = node_off.toAbsolute(src_loc.base_node);
1148 var buf: [1]Ast.Node.Index = undefined;1142 var buf: [1]Ast.Node.Index = undefined;
1149 const addrspace_node = if (tree.fullVarDecl(node)) |v|1143 const addrspace_node = if (tree.fullVarDecl(node)) |v|
1150 v.ast.addrspace_node1144 v.ast.addrspace_node.unwrap().?
1151 else if (tree.fullFnProto(&buf, node)) |f|1145 else if (tree.fullFnProto(&buf, node)) |f|
1152 f.ast.addrspace_expr1146 f.ast.addrspace_expr.unwrap().?
1153 else1147 else
1154 unreachable;1148 unreachable;
1155 return tree.nodeToSpan(addrspace_node);1149 return tree.nodeToSpan(addrspace_node);
1156 },1150 },
1157 .node_offset_var_decl_init => |node_off| {1151 .node_offset_var_decl_init => |node_off| {
1158 const tree = try src_loc.file_scope.getTree(gpa);1152 const tree = try src_loc.file_scope.getTree(gpa);
1159 const node = src_loc.relativeToNodeIndex(node_off);1153 const node = node_off.toAbsolute(src_loc.base_node);
1160 const full = tree.fullVarDecl(node).?;1154 const init_node = switch (tree.nodeTag(node)) {
1161 return tree.nodeToSpan(full.ast.init_node);1155 .global_var_decl,
1156 .local_var_decl,
1157 .aligned_var_decl,
1158 .simple_var_decl,
1159 => tree.fullVarDecl(node).?.ast.init_node.unwrap().?,
1160 .assign_destructure => tree.assignDestructure(node).ast.value_expr,
1161 else => unreachable,
1162 };
1163 return tree.nodeToSpan(init_node);
1162 },1164 },
1163 .node_offset_builtin_call_arg => |builtin_arg| {1165 .node_offset_builtin_call_arg => |builtin_arg| {
1164 const tree = try src_loc.file_scope.getTree(gpa);1166 const tree = try src_loc.file_scope.getTree(gpa);
1165 const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node);1167 const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node);
1166 var buf: [2]Ast.Node.Index = undefined;1168 var buf: [2]Ast.Node.Index = undefined;
1167 const params = tree.builtinCallParams(&buf, node).?;1169 const params = tree.builtinCallParams(&buf, node).?;
1168 return tree.nodeToSpan(params[builtin_arg.arg_index]);1170 return tree.nodeToSpan(params[builtin_arg.arg_index]);
1169 },1171 },
1170 .node_offset_ptrcast_operand => |node_off| {1172 .node_offset_ptrcast_operand => |node_off| {
1171 const tree = try src_loc.file_scope.getTree(gpa);1173 const tree = try src_loc.file_scope.getTree(gpa);
1172 const main_tokens = tree.nodes.items(.main_token);
1173 const node_datas = tree.nodes.items(.data);
1174 const node_tags = tree.nodes.items(.tag);
11751174
1176 var node = src_loc.relativeToNodeIndex(node_off);1175 var node = node_off.toAbsolute(src_loc.base_node);
1177 while (true) {1176 while (true) {
1178 switch (node_tags[node]) {1177 switch (tree.nodeTag(node)) {
1179 .builtin_call_two, .builtin_call_two_comma => {},1178 .builtin_call_two, .builtin_call_two_comma => {},
1180 else => break,1179 else => break,
1181 }1180 }
11821181
1183 if (node_datas[node].lhs == 0) break; // 0 args1182 const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node;
1184 if (node_datas[node].rhs != 0) break; // 2 args1183 if (first_arg == .none) break; // 0 args
1184 if (second_arg != .none) break; // 2 args
11851185
1186 const builtin_token = main_tokens[node];1186 const builtin_token = tree.nodeMainToken(node);
1187 const builtin_name = tree.tokenSlice(builtin_token);1187 const builtin_name = tree.tokenSlice(builtin_token);
1188 const info = BuiltinFn.list.get(builtin_name) orelse break;1188 const info = BuiltinFn.list.get(builtin_name) orelse break;
11891189
...@@ -1197,16 +1197,15 @@ pub const SrcLoc = struct {...@@ -1197,16 +1197,15 @@ pub const SrcLoc = struct {
1197 => {},1197 => {},
1198 }1198 }
11991199
1200 node = node_datas[node].lhs;1200 node = first_arg.unwrap().?;
1201 }1201 }
12021202
1203 return tree.nodeToSpan(node);1203 return tree.nodeToSpan(node);
1204 },1204 },
1205 .node_offset_array_access_index => |node_off| {1205 .node_offset_array_access_index => |node_off| {
1206 const tree = try src_loc.file_scope.getTree(gpa);1206 const tree = try src_loc.file_scope.getTree(gpa);
1207 const node_datas = tree.nodes.items(.data);1207 const node = node_off.toAbsolute(src_loc.base_node);
1208 const node = src_loc.relativeToNodeIndex(node_off);1208 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1209 return tree.nodeToSpan(node_datas[node].rhs);
1210 },1209 },
1211 .node_offset_slice_ptr,1210 .node_offset_slice_ptr,
1212 .node_offset_slice_start,1211 .node_offset_slice_start,
...@@ -1214,32 +1213,30 @@ pub const SrcLoc = struct {...@@ -1214,32 +1213,30 @@ pub const SrcLoc = struct {
1214 .node_offset_slice_sentinel,1213 .node_offset_slice_sentinel,
1215 => |node_off| {1214 => |node_off| {
1216 const tree = try src_loc.file_scope.getTree(gpa);1215 const tree = try src_loc.file_scope.getTree(gpa);
1217 const node = src_loc.relativeToNodeIndex(node_off);1216 const node = node_off.toAbsolute(src_loc.base_node);
1218 const full = tree.fullSlice(node).?;1217 const full = tree.fullSlice(node).?;
1219 const part_node = switch (src_loc.lazy) {1218 const part_node = switch (src_loc.lazy) {
1220 .node_offset_slice_ptr => full.ast.sliced,1219 .node_offset_slice_ptr => full.ast.sliced,
1221 .node_offset_slice_start => full.ast.start,1220 .node_offset_slice_start => full.ast.start,
1222 .node_offset_slice_end => full.ast.end,1221 .node_offset_slice_end => full.ast.end.unwrap().?,
1223 .node_offset_slice_sentinel => full.ast.sentinel,1222 .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?,
1224 else => unreachable,1223 else => unreachable,
1225 };1224 };
1226 return tree.nodeToSpan(part_node);1225 return tree.nodeToSpan(part_node);
1227 },1226 },
1228 .node_offset_call_func => |node_off| {1227 .node_offset_call_func => |node_off| {
1229 const tree = try src_loc.file_scope.getTree(gpa);1228 const tree = try src_loc.file_scope.getTree(gpa);
1230 const node = src_loc.relativeToNodeIndex(node_off);1229 const node = node_off.toAbsolute(src_loc.base_node);
1231 var buf: [1]Ast.Node.Index = undefined;1230 var buf: [1]Ast.Node.Index = undefined;
1232 const full = tree.fullCall(&buf, node).?;1231 const full = tree.fullCall(&buf, node).?;
1233 return tree.nodeToSpan(full.ast.fn_expr);1232 return tree.nodeToSpan(full.ast.fn_expr);
1234 },1233 },
1235 .node_offset_field_name => |node_off| {1234 .node_offset_field_name => |node_off| {
1236 const tree = try src_loc.file_scope.getTree(gpa);1235 const tree = try src_loc.file_scope.getTree(gpa);
1237 const node_datas = tree.nodes.items(.data);1236 const node = node_off.toAbsolute(src_loc.base_node);
1238 const node_tags = tree.nodes.items(.tag);
1239 const node = src_loc.relativeToNodeIndex(node_off);
1240 var buf: [1]Ast.Node.Index = undefined;1237 var buf: [1]Ast.Node.Index = undefined;
1241 const tok_index = switch (node_tags[node]) {1238 const tok_index = switch (tree.nodeTag(node)) {
1242 .field_access => node_datas[node].rhs,1239 .field_access => tree.nodeData(node).node_and_token[1],
1243 .call_one,1240 .call_one,
1244 .call_one_comma,1241 .call_one_comma,
1245 .async_call_one,1242 .async_call_one,
...@@ -1254,43 +1251,41 @@ pub const SrcLoc = struct {...@@ -1254,43 +1251,41 @@ pub const SrcLoc = struct {
1254 },1251 },
1255 else => tree.firstToken(node) - 2,1252 else => tree.firstToken(node) - 2,
1256 };1253 };
1257 const start = tree.tokens.items(.start)[tok_index];1254 const start = tree.tokenStart(tok_index);
1258 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1255 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1259 return Span{ .start = start, .end = end, .main = start };1256 return Span{ .start = start, .end = end, .main = start };
1260 },1257 },
1261 .node_offset_field_name_init => |node_off| {1258 .node_offset_field_name_init => |node_off| {
1262 const tree = try src_loc.file_scope.getTree(gpa);1259 const tree = try src_loc.file_scope.getTree(gpa);
1263 const node = src_loc.relativeToNodeIndex(node_off);1260 const node = node_off.toAbsolute(src_loc.base_node);
1264 const tok_index = tree.firstToken(node) - 2;1261 const tok_index = tree.firstToken(node) - 2;
1265 const start = tree.tokens.items(.start)[tok_index];1262 const start = tree.tokenStart(tok_index);
1266 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1263 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1267 return Span{ .start = start, .end = end, .main = start };1264 return Span{ .start = start, .end = end, .main = start };
1268 },1265 },
1269 .node_offset_deref_ptr => |node_off| {1266 .node_offset_deref_ptr => |node_off| {
1270 const tree = try src_loc.file_scope.getTree(gpa);1267 const tree = try src_loc.file_scope.getTree(gpa);
1271 const node = src_loc.relativeToNodeIndex(node_off);1268 const node = node_off.toAbsolute(src_loc.base_node);
1272 return tree.nodeToSpan(node);1269 return tree.nodeToSpan(node);
1273 },1270 },
1274 .node_offset_asm_source => |node_off| {1271 .node_offset_asm_source => |node_off| {
1275 const tree = try src_loc.file_scope.getTree(gpa);1272 const tree = try src_loc.file_scope.getTree(gpa);
1276 const node = src_loc.relativeToNodeIndex(node_off);1273 const node = node_off.toAbsolute(src_loc.base_node);
1277 const full = tree.fullAsm(node).?;1274 const full = tree.fullAsm(node).?;
1278 return tree.nodeToSpan(full.ast.template);1275 return tree.nodeToSpan(full.ast.template);
1279 },1276 },
1280 .node_offset_asm_ret_ty => |node_off| {1277 .node_offset_asm_ret_ty => |node_off| {
1281 const tree = try src_loc.file_scope.getTree(gpa);1278 const tree = try src_loc.file_scope.getTree(gpa);
1282 const node = src_loc.relativeToNodeIndex(node_off);1279 const node = node_off.toAbsolute(src_loc.base_node);
1283 const full = tree.fullAsm(node).?;1280 const full = tree.fullAsm(node).?;
1284 const asm_output = full.outputs[0];1281 const asm_output = full.outputs[0];
1285 const node_datas = tree.nodes.items(.data);1282 return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?);
1286 return tree.nodeToSpan(node_datas[asm_output].lhs);
1287 },1283 },
12881284
1289 .node_offset_if_cond => |node_off| {1285 .node_offset_if_cond => |node_off| {
1290 const tree = try src_loc.file_scope.getTree(gpa);1286 const tree = try src_loc.file_scope.getTree(gpa);
1291 const node = src_loc.relativeToNodeIndex(node_off);1287 const node = node_off.toAbsolute(src_loc.base_node);
1292 const node_tags = tree.nodes.items(.tag);1288 const src_node = switch (tree.nodeTag(node)) {
1293 const src_node = switch (node_tags[node]) {
1294 .if_simple,1289 .if_simple,
1295 .@"if",1290 .@"if",
1296 => tree.fullIf(node).?.ast.cond_expr,1291 => tree.fullIf(node).?.ast.cond_expr,
...@@ -1317,20 +1312,19 @@ pub const SrcLoc = struct {...@@ -1317,20 +1312,19 @@ pub const SrcLoc = struct {
1317 },1312 },
1318 .for_input => |for_input| {1313 .for_input => |for_input| {
1319 const tree = try src_loc.file_scope.getTree(gpa);1314 const tree = try src_loc.file_scope.getTree(gpa);
1320 const node = src_loc.relativeToNodeIndex(for_input.for_node_offset);1315 const node = for_input.for_node_offset.toAbsolute(src_loc.base_node);
1321 const for_full = tree.fullFor(node).?;1316 const for_full = tree.fullFor(node).?;
1322 const src_node = for_full.ast.inputs[for_input.input_index];1317 const src_node = for_full.ast.inputs[for_input.input_index];
1323 return tree.nodeToSpan(src_node);1318 return tree.nodeToSpan(src_node);
1324 },1319 },
1325 .for_capture_from_input => |node_off| {1320 .for_capture_from_input => |node_off| {
1326 const tree = try src_loc.file_scope.getTree(gpa);1321 const tree = try src_loc.file_scope.getTree(gpa);
1327 const token_tags = tree.tokens.items(.tag);1322 const input_node = node_off.toAbsolute(src_loc.base_node);
1328 const input_node = src_loc.relativeToNodeIndex(node_off);
1329 // We have to actually linear scan the whole AST to find the for loop1323 // We have to actually linear scan the whole AST to find the for loop
1330 // that contains this input.1324 // that contains this input.
1331 const node_tags = tree.nodes.items(.tag);1325 const node_tags = tree.nodes.items(.tag);
1332 for (node_tags, 0..) |node_tag, node_usize| {1326 for (node_tags, 0..) |node_tag, node_usize| {
1333 const node = @as(Ast.Node.Index, @intCast(node_usize));1327 const node: Ast.Node.Index = @enumFromInt(node_usize);
1334 switch (node_tag) {1328 switch (node_tag) {
1335 .for_simple, .@"for" => {1329 .for_simple, .@"for" => {
1336 const for_full = tree.fullFor(node).?;1330 const for_full = tree.fullFor(node).?;
...@@ -1339,7 +1333,7 @@ pub const SrcLoc = struct {...@@ -1339,7 +1333,7 @@ pub const SrcLoc = struct {
1339 var count = input_index;1333 var count = input_index;
1340 var tok = for_full.payload_token;1334 var tok = for_full.payload_token;
1341 while (true) {1335 while (true) {
1342 switch (token_tags[tok]) {1336 switch (tree.tokenTag(tok)) {
1343 .comma => {1337 .comma => {
1344 count -= 1;1338 count -= 1;
1345 tok += 1;1339 tok += 1;
...@@ -1366,13 +1360,12 @@ pub const SrcLoc = struct {...@@ -1366,13 +1360,12 @@ pub const SrcLoc = struct {
1366 },1360 },
1367 .call_arg => |call_arg| {1361 .call_arg => |call_arg| {
1368 const tree = try src_loc.file_scope.getTree(gpa);1362 const tree = try src_loc.file_scope.getTree(gpa);
1369 const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset);1363 const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node);
1370 var buf: [2]Ast.Node.Index = undefined;1364 var buf: [2]Ast.Node.Index = undefined;
1371 const call_full = tree.fullCall(buf[0..1], node) orelse {1365 const call_full = tree.fullCall(buf[0..1], node) orelse {
1372 const node_tags = tree.nodes.items(.tag);1366 assert(tree.nodeTag(node) == .builtin_call);
1373 assert(node_tags[node] == .builtin_call);1367 const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]);
1374 const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1];1368 switch (tree.nodeTag(call_args_node)) {
1375 switch (node_tags[call_args_node]) {
1376 .array_init_one,1369 .array_init_one,
1377 .array_init_one_comma,1370 .array_init_one_comma,
1378 .array_init_dot_two,1371 .array_init_dot_two,
...@@ -1404,7 +1397,7 @@ pub const SrcLoc = struct {...@@ -1404,7 +1397,7 @@ pub const SrcLoc = struct {
1404 },1397 },
1405 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {1398 .fn_proto_param, .fn_proto_param_type => |fn_proto_param| {
1406 const tree = try src_loc.file_scope.getTree(gpa);1399 const tree = try src_loc.file_scope.getTree(gpa);
1407 const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset);1400 const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node);
1408 var buf: [1]Ast.Node.Index = undefined;1401 var buf: [1]Ast.Node.Index = undefined;
1409 const full = tree.fullFnProto(&buf, node).?;1402 const full = tree.fullFnProto(&buf, node).?;
1410 var it = full.iterate(tree);1403 var it = full.iterate(tree);
...@@ -1416,14 +1409,14 @@ pub const SrcLoc = struct {...@@ -1416,14 +1409,14 @@ pub const SrcLoc = struct {
1416 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {1409 .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| {
1417 return tree.tokenToSpan(tok);1410 return tree.tokenToSpan(tok);
1418 } else {1411 } else {
1419 return tree.nodeToSpan(param.type_expr);1412 return tree.nodeToSpan(param.type_expr.?);
1420 },1413 },
1421 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {1414 .fn_proto_param => if (param.anytype_ellipsis3) |tok| {
1422 const first = param.comptime_noalias orelse param.name_token orelse tok;1415 const first = param.comptime_noalias orelse param.name_token orelse tok;
1423 return tree.tokensToSpan(first, tok, first);1416 return tree.tokensToSpan(first, tok, first);
1424 } else {1417 } else {
1425 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr);1418 const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?);
1426 return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first);1419 return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first);
1427 },1420 },
1428 else => unreachable,1421 else => unreachable,
1429 }1422 }
...@@ -1432,28 +1425,24 @@ pub const SrcLoc = struct {...@@ -1432,28 +1425,24 @@ pub const SrcLoc = struct {
1432 },1425 },
1433 .node_offset_bin_lhs => |node_off| {1426 .node_offset_bin_lhs => |node_off| {
1434 const tree = try src_loc.file_scope.getTree(gpa);1427 const tree = try src_loc.file_scope.getTree(gpa);
1435 const node = src_loc.relativeToNodeIndex(node_off);1428 const node = node_off.toAbsolute(src_loc.base_node);
1436 const node_datas = tree.nodes.items(.data);1429 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
1437 return tree.nodeToSpan(node_datas[node].lhs);
1438 },1430 },
1439 .node_offset_bin_rhs => |node_off| {1431 .node_offset_bin_rhs => |node_off| {
1440 const tree = try src_loc.file_scope.getTree(gpa);1432 const tree = try src_loc.file_scope.getTree(gpa);
1441 const node = src_loc.relativeToNodeIndex(node_off);1433 const node = node_off.toAbsolute(src_loc.base_node);
1442 const node_datas = tree.nodes.items(.data);1434 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1443 return tree.nodeToSpan(node_datas[node].rhs);
1444 },1435 },
1445 .array_cat_lhs, .array_cat_rhs => |cat| {1436 .array_cat_lhs, .array_cat_rhs => |cat| {
1446 const tree = try src_loc.file_scope.getTree(gpa);1437 const tree = try src_loc.file_scope.getTree(gpa);
1447 const node = src_loc.relativeToNodeIndex(cat.array_cat_offset);1438 const node = cat.array_cat_offset.toAbsolute(src_loc.base_node);
1448 const node_datas = tree.nodes.items(.data);
1449 const arr_node = if (src_loc.lazy == .array_cat_lhs)1439 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1450 node_datas[node].lhs1440 tree.nodeData(node).node_and_node[0]
1451 else1441 else
1452 node_datas[node].rhs;1442 tree.nodeData(node).node_and_node[1];
14531443
1454 const node_tags = tree.nodes.items(.tag);
1455 var buf: [2]Ast.Node.Index = undefined;1444 var buf: [2]Ast.Node.Index = undefined;
1456 switch (node_tags[arr_node]) {1445 switch (tree.nodeTag(arr_node)) {
1457 .array_init_one,1446 .array_init_one,
1458 .array_init_one_comma,1447 .array_init_one_comma,
1459 .array_init_dot_two,1448 .array_init_dot_two,
...@@ -1470,27 +1459,30 @@ pub const SrcLoc = struct {...@@ -1470,27 +1459,30 @@ pub const SrcLoc = struct {
1470 }1459 }
1471 },1460 },
14721461
1462 .node_offset_try_operand => |node_off| {
1463 const tree = try src_loc.file_scope.getTree(gpa);
1464 const node = node_off.toAbsolute(src_loc.base_node);
1465 return tree.nodeToSpan(tree.nodeData(node).node);
1466 },
1467
1473 .node_offset_switch_operand => |node_off| {1468 .node_offset_switch_operand => |node_off| {
1474 const tree = try src_loc.file_scope.getTree(gpa);1469 const tree = try src_loc.file_scope.getTree(gpa);
1475 const node = src_loc.relativeToNodeIndex(node_off);1470 const node = node_off.toAbsolute(src_loc.base_node);
1476 const node_datas = tree.nodes.items(.data);1471 const condition, _ = tree.nodeData(node).node_and_extra;
1477 return tree.nodeToSpan(node_datas[node].lhs);1472 return tree.nodeToSpan(condition);
1478 },1473 },
14791474
1480 .node_offset_switch_special_prong => |node_off| {1475 .node_offset_switch_special_prong => |node_off| {
1481 const tree = try src_loc.file_scope.getTree(gpa);1476 const tree = try src_loc.file_scope.getTree(gpa);
1482 const switch_node = src_loc.relativeToNodeIndex(node_off);1477 const switch_node = node_off.toAbsolute(src_loc.base_node);
1483 const node_datas = tree.nodes.items(.data);1478 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1484 const node_tags = tree.nodes.items(.tag);1479 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1485 const main_tokens = tree.nodes.items(.main_token);
1486 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1487 const case_nodes = tree.extra_data[extra.start..extra.end];
1488 for (case_nodes) |case_node| {1480 for (case_nodes) |case_node| {
1489 const case = tree.fullSwitchCase(case_node).?;1481 const case = tree.fullSwitchCase(case_node).?;
1490 const is_special = (case.ast.values.len == 0) or1482 const is_special = (case.ast.values.len == 0) or
1491 (case.ast.values.len == 1 and1483 (case.ast.values.len == 1 and
1492 node_tags[case.ast.values[0]] == .identifier and1484 tree.nodeTag(case.ast.values[0]) == .identifier and
1493 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));1485 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
1494 if (!is_special) continue;1486 if (!is_special) continue;
14951487
1496 return tree.nodeToSpan(case_node);1488 return tree.nodeToSpan(case_node);
...@@ -1499,22 +1491,19 @@ pub const SrcLoc = struct {...@@ -1499,22 +1491,19 @@ pub const SrcLoc = struct {
14991491
1500 .node_offset_switch_range => |node_off| {1492 .node_offset_switch_range => |node_off| {
1501 const tree = try src_loc.file_scope.getTree(gpa);1493 const tree = try src_loc.file_scope.getTree(gpa);
1502 const switch_node = src_loc.relativeToNodeIndex(node_off);1494 const switch_node = node_off.toAbsolute(src_loc.base_node);
1503 const node_datas = tree.nodes.items(.data);1495 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1504 const node_tags = tree.nodes.items(.tag);1496 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1505 const main_tokens = tree.nodes.items(.main_token);
1506 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1507 const case_nodes = tree.extra_data[extra.start..extra.end];
1508 for (case_nodes) |case_node| {1497 for (case_nodes) |case_node| {
1509 const case = tree.fullSwitchCase(case_node).?;1498 const case = tree.fullSwitchCase(case_node).?;
1510 const is_special = (case.ast.values.len == 0) or1499 const is_special = (case.ast.values.len == 0) or
1511 (case.ast.values.len == 1 and1500 (case.ast.values.len == 1 and
1512 node_tags[case.ast.values[0]] == .identifier and1501 tree.nodeTag(case.ast.values[0]) == .identifier and
1513 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));1502 mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"));
1514 if (is_special) continue;1503 if (is_special) continue;
15151504
1516 for (case.ast.values) |item_node| {1505 for (case.ast.values) |item_node| {
1517 if (node_tags[item_node] == .switch_range) {1506 if (tree.nodeTag(item_node) == .switch_range) {
1518 return tree.nodeToSpan(item_node);1507 return tree.nodeToSpan(item_node);
1519 }1508 }
1520 }1509 }
...@@ -1522,47 +1511,46 @@ pub const SrcLoc = struct {...@@ -1522,47 +1511,46 @@ pub const SrcLoc = struct {
1522 },1511 },
1523 .node_offset_fn_type_align => |node_off| {1512 .node_offset_fn_type_align => |node_off| {
1524 const tree = try src_loc.file_scope.getTree(gpa);1513 const tree = try src_loc.file_scope.getTree(gpa);
1525 const node = src_loc.relativeToNodeIndex(node_off);1514 const node = node_off.toAbsolute(src_loc.base_node);
1526 var buf: [1]Ast.Node.Index = undefined;1515 var buf: [1]Ast.Node.Index = undefined;
1527 const full = tree.fullFnProto(&buf, node).?;1516 const full = tree.fullFnProto(&buf, node).?;
1528 return tree.nodeToSpan(full.ast.align_expr);1517 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
1529 },1518 },
1530 .node_offset_fn_type_addrspace => |node_off| {1519 .node_offset_fn_type_addrspace => |node_off| {
1531 const tree = try src_loc.file_scope.getTree(gpa);1520 const tree = try src_loc.file_scope.getTree(gpa);
1532 const node = src_loc.relativeToNodeIndex(node_off);1521 const node = node_off.toAbsolute(src_loc.base_node);
1533 var buf: [1]Ast.Node.Index = undefined;1522 var buf: [1]Ast.Node.Index = undefined;
1534 const full = tree.fullFnProto(&buf, node).?;1523 const full = tree.fullFnProto(&buf, node).?;
1535 return tree.nodeToSpan(full.ast.addrspace_expr);1524 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
1536 },1525 },
1537 .node_offset_fn_type_section => |node_off| {1526 .node_offset_fn_type_section => |node_off| {
1538 const tree = try src_loc.file_scope.getTree(gpa);1527 const tree = try src_loc.file_scope.getTree(gpa);
1539 const node = src_loc.relativeToNodeIndex(node_off);1528 const node = node_off.toAbsolute(src_loc.base_node);
1540 var buf: [1]Ast.Node.Index = undefined;1529 var buf: [1]Ast.Node.Index = undefined;
1541 const full = tree.fullFnProto(&buf, node).?;1530 const full = tree.fullFnProto(&buf, node).?;
1542 return tree.nodeToSpan(full.ast.section_expr);1531 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
1543 },1532 },
1544 .node_offset_fn_type_cc => |node_off| {1533 .node_offset_fn_type_cc => |node_off| {
1545 const tree = try src_loc.file_scope.getTree(gpa);1534 const tree = try src_loc.file_scope.getTree(gpa);
1546 const node = src_loc.relativeToNodeIndex(node_off);1535 const node = node_off.toAbsolute(src_loc.base_node);
1547 var buf: [1]Ast.Node.Index = undefined;1536 var buf: [1]Ast.Node.Index = undefined;
1548 const full = tree.fullFnProto(&buf, node).?;1537 const full = tree.fullFnProto(&buf, node).?;
1549 return tree.nodeToSpan(full.ast.callconv_expr);1538 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);
1550 },1539 },
15511540
1552 .node_offset_fn_type_ret_ty => |node_off| {1541 .node_offset_fn_type_ret_ty => |node_off| {
1553 const tree = try src_loc.file_scope.getTree(gpa);1542 const tree = try src_loc.file_scope.getTree(gpa);
1554 const node = src_loc.relativeToNodeIndex(node_off);1543 const node = node_off.toAbsolute(src_loc.base_node);
1555 var buf: [1]Ast.Node.Index = undefined;1544 var buf: [1]Ast.Node.Index = undefined;
1556 const full = tree.fullFnProto(&buf, node).?;1545 const full = tree.fullFnProto(&buf, node).?;
1557 return tree.nodeToSpan(full.ast.return_type);1546 return tree.nodeToSpan(full.ast.return_type.unwrap().?);
1558 },1547 },
1559 .node_offset_param => |node_off| {1548 .node_offset_param => |node_off| {
1560 const tree = try src_loc.file_scope.getTree(gpa);1549 const tree = try src_loc.file_scope.getTree(gpa);
1561 const token_tags = tree.tokens.items(.tag);1550 const node = node_off.toAbsolute(src_loc.base_node);
1562 const node = src_loc.relativeToNodeIndex(node_off);
15631551
1564 var first_tok = tree.firstToken(node);1552 var first_tok = tree.firstToken(node);
1565 while (true) switch (token_tags[first_tok - 1]) {1553 while (true) switch (tree.tokenTag(first_tok - 1)) {
1566 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,1554 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
1567 else => break,1555 else => break,
1568 };1556 };
...@@ -1574,12 +1562,11 @@ pub const SrcLoc = struct {...@@ -1574,12 +1562,11 @@ pub const SrcLoc = struct {
1574 },1562 },
1575 .token_offset_param => |token_off| {1563 .token_offset_param => |token_off| {
1576 const tree = try src_loc.file_scope.getTree(gpa);1564 const tree = try src_loc.file_scope.getTree(gpa);
1577 const token_tags = tree.tokens.items(.tag);1565 const main_token = tree.nodeMainToken(src_loc.base_node);
1578 const main_token = tree.nodes.items(.main_token)[src_loc.base_node];1566 const tok_index = token_off.toAbsolute(main_token);
1579 const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token))));
15801567
1581 var first_tok = tok_index;1568 var first_tok = tok_index;
1582 while (true) switch (token_tags[first_tok - 1]) {1569 while (true) switch (tree.tokenTag(first_tok - 1)) {
1583 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,1570 .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
1584 else => break,1571 else => break,
1585 };1572 };
...@@ -1592,109 +1579,108 @@ pub const SrcLoc = struct {...@@ -1592,109 +1579,108 @@ pub const SrcLoc = struct {
15921579
1593 .node_offset_anyframe_type => |node_off| {1580 .node_offset_anyframe_type => |node_off| {
1594 const tree = try src_loc.file_scope.getTree(gpa);1581 const tree = try src_loc.file_scope.getTree(gpa);
1595 const node_datas = tree.nodes.items(.data);1582 const parent_node = node_off.toAbsolute(src_loc.base_node);
1596 const parent_node = src_loc.relativeToNodeIndex(node_off);1583 _, const child_type = tree.nodeData(parent_node).token_and_node;
1597 return tree.nodeToSpan(node_datas[parent_node].rhs);1584 return tree.nodeToSpan(child_type);
1598 },1585 },
15991586
1600 .node_offset_lib_name => |node_off| {1587 .node_offset_lib_name => |node_off| {
1601 const tree = try src_loc.file_scope.getTree(gpa);1588 const tree = try src_loc.file_scope.getTree(gpa);
1602 const parent_node = src_loc.relativeToNodeIndex(node_off);1589 const parent_node = node_off.toAbsolute(src_loc.base_node);
1603 var buf: [1]Ast.Node.Index = undefined;1590 var buf: [1]Ast.Node.Index = undefined;
1604 const full = tree.fullFnProto(&buf, parent_node).?;1591 const full = tree.fullFnProto(&buf, parent_node).?;
1605 const tok_index = full.lib_name.?;1592 const tok_index = full.lib_name.?;
1606 const start = tree.tokens.items(.start)[tok_index];1593 const start = tree.tokenStart(tok_index);
1607 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));1594 const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len));
1608 return Span{ .start = start, .end = end, .main = start };1595 return Span{ .start = start, .end = end, .main = start };
1609 },1596 },
16101597
1611 .node_offset_array_type_len => |node_off| {1598 .node_offset_array_type_len => |node_off| {
1612 const tree = try src_loc.file_scope.getTree(gpa);1599 const tree = try src_loc.file_scope.getTree(gpa);
1613 const parent_node = src_loc.relativeToNodeIndex(node_off);1600 const parent_node = node_off.toAbsolute(src_loc.base_node);
16141601
1615 const full = tree.fullArrayType(parent_node).?;1602 const full = tree.fullArrayType(parent_node).?;
1616 return tree.nodeToSpan(full.ast.elem_count);1603 return tree.nodeToSpan(full.ast.elem_count);
1617 },1604 },
1618 .node_offset_array_type_sentinel => |node_off| {1605 .node_offset_array_type_sentinel => |node_off| {
1619 const tree = try src_loc.file_scope.getTree(gpa);1606 const tree = try src_loc.file_scope.getTree(gpa);
1620 const parent_node = src_loc.relativeToNodeIndex(node_off);1607 const parent_node = node_off.toAbsolute(src_loc.base_node);
16211608
1622 const full = tree.fullArrayType(parent_node).?;1609 const full = tree.fullArrayType(parent_node).?;
1623 return tree.nodeToSpan(full.ast.sentinel);1610 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1624 },1611 },
1625 .node_offset_array_type_elem => |node_off| {1612 .node_offset_array_type_elem => |node_off| {
1626 const tree = try src_loc.file_scope.getTree(gpa);1613 const tree = try src_loc.file_scope.getTree(gpa);
1627 const parent_node = src_loc.relativeToNodeIndex(node_off);1614 const parent_node = node_off.toAbsolute(src_loc.base_node);
16281615
1629 const full = tree.fullArrayType(parent_node).?;1616 const full = tree.fullArrayType(parent_node).?;
1630 return tree.nodeToSpan(full.ast.elem_type);1617 return tree.nodeToSpan(full.ast.elem_type);
1631 },1618 },
1632 .node_offset_un_op => |node_off| {1619 .node_offset_un_op => |node_off| {
1633 const tree = try src_loc.file_scope.getTree(gpa);1620 const tree = try src_loc.file_scope.getTree(gpa);
1634 const node_datas = tree.nodes.items(.data);1621 const node = node_off.toAbsolute(src_loc.base_node);
1635 const node = src_loc.relativeToNodeIndex(node_off);1622 return tree.nodeToSpan(tree.nodeData(node).node);
1636
1637 return tree.nodeToSpan(node_datas[node].lhs);
1638 },1623 },
1639 .node_offset_ptr_elem => |node_off| {1624 .node_offset_ptr_elem => |node_off| {
1640 const tree = try src_loc.file_scope.getTree(gpa);1625 const tree = try src_loc.file_scope.getTree(gpa);
1641 const parent_node = src_loc.relativeToNodeIndex(node_off);1626 const parent_node = node_off.toAbsolute(src_loc.base_node);
16421627
1643 const full = tree.fullPtrType(parent_node).?;1628 const full = tree.fullPtrType(parent_node).?;
1644 return tree.nodeToSpan(full.ast.child_type);1629 return tree.nodeToSpan(full.ast.child_type);
1645 },1630 },
1646 .node_offset_ptr_sentinel => |node_off| {1631 .node_offset_ptr_sentinel => |node_off| {
1647 const tree = try src_loc.file_scope.getTree(gpa);1632 const tree = try src_loc.file_scope.getTree(gpa);
1648 const parent_node = src_loc.relativeToNodeIndex(node_off);1633 const parent_node = node_off.toAbsolute(src_loc.base_node);
16491634
1650 const full = tree.fullPtrType(parent_node).?;1635 const full = tree.fullPtrType(parent_node).?;
1651 return tree.nodeToSpan(full.ast.sentinel);1636 return tree.nodeToSpan(full.ast.sentinel.unwrap().?);
1652 },1637 },
1653 .node_offset_ptr_align => |node_off| {1638 .node_offset_ptr_align => |node_off| {
1654 const tree = try src_loc.file_scope.getTree(gpa);1639 const tree = try src_loc.file_scope.getTree(gpa);
1655 const parent_node = src_loc.relativeToNodeIndex(node_off);1640 const parent_node = node_off.toAbsolute(src_loc.base_node);
16561641
1657 const full = tree.fullPtrType(parent_node).?;1642 const full = tree.fullPtrType(parent_node).?;
1658 return tree.nodeToSpan(full.ast.align_node);1643 return tree.nodeToSpan(full.ast.align_node.unwrap().?);
1659 },1644 },
1660 .node_offset_ptr_addrspace => |node_off| {1645 .node_offset_ptr_addrspace => |node_off| {
1661 const tree = try src_loc.file_scope.getTree(gpa);1646 const tree = try src_loc.file_scope.getTree(gpa);
1662 const parent_node = src_loc.relativeToNodeIndex(node_off);1647 const parent_node = node_off.toAbsolute(src_loc.base_node);
16631648
1664 const full = tree.fullPtrType(parent_node).?;1649 const full = tree.fullPtrType(parent_node).?;
1665 return tree.nodeToSpan(full.ast.addrspace_node);1650 return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?);
1666 },1651 },
1667 .node_offset_ptr_bitoffset => |node_off| {1652 .node_offset_ptr_bitoffset => |node_off| {
1668 const tree = try src_loc.file_scope.getTree(gpa);1653 const tree = try src_loc.file_scope.getTree(gpa);
1669 const parent_node = src_loc.relativeToNodeIndex(node_off);1654 const parent_node = node_off.toAbsolute(src_loc.base_node);
16701655
1671 const full = tree.fullPtrType(parent_node).?;1656 const full = tree.fullPtrType(parent_node).?;
1672 return tree.nodeToSpan(full.ast.bit_range_start);1657 return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?);
1673 },1658 },
1674 .node_offset_ptr_hostsize => |node_off| {1659 .node_offset_ptr_hostsize => |node_off| {
1675 const tree = try src_loc.file_scope.getTree(gpa);1660 const tree = try src_loc.file_scope.getTree(gpa);
1676 const parent_node = src_loc.relativeToNodeIndex(node_off);1661 const parent_node = node_off.toAbsolute(src_loc.base_node);
16771662
1678 const full = tree.fullPtrType(parent_node).?;1663 const full = tree.fullPtrType(parent_node).?;
1679 return tree.nodeToSpan(full.ast.bit_range_end);1664 return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?);
1680 },1665 },
1681 .node_offset_container_tag => |node_off| {1666 .node_offset_container_tag => |node_off| {
1682 const tree = try src_loc.file_scope.getTree(gpa);1667 const tree = try src_loc.file_scope.getTree(gpa);
1683 const node_tags = tree.nodes.items(.tag);1668 const parent_node = node_off.toAbsolute(src_loc.base_node);
1684 const parent_node = src_loc.relativeToNodeIndex(node_off);
16851669
1686 switch (node_tags[parent_node]) {1670 switch (tree.nodeTag(parent_node)) {
1687 .container_decl_arg, .container_decl_arg_trailing => {1671 .container_decl_arg, .container_decl_arg_trailing => {
1688 const full = tree.containerDeclArg(parent_node);1672 const full = tree.containerDeclArg(parent_node);
1689 return tree.nodeToSpan(full.ast.arg);1673 const arg_node = full.ast.arg.unwrap().?;
1674 return tree.nodeToSpan(arg_node);
1690 },1675 },
1691 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {1676 .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
1692 const full = tree.taggedUnionEnumTag(parent_node);1677 const full = tree.taggedUnionEnumTag(parent_node);
1678 const arg_node = full.ast.arg.unwrap().?;
16931679
1694 return tree.tokensToSpan(1680 return tree.tokensToSpan(
1695 tree.firstToken(full.ast.arg) - 2,1681 tree.firstToken(arg_node) - 2,
1696 tree.lastToken(full.ast.arg) + 1,1682 tree.lastToken(arg_node) + 1,
1697 tree.nodes.items(.main_token)[full.ast.arg],1683 tree.nodeMainToken(arg_node),
1698 );1684 );
1699 },1685 },
1700 else => unreachable,1686 else => unreachable,
...@@ -1702,60 +1688,55 @@ pub const SrcLoc = struct {...@@ -1702,60 +1688,55 @@ pub const SrcLoc = struct {
1702 },1688 },
1703 .node_offset_field_default => |node_off| {1689 .node_offset_field_default => |node_off| {
1704 const tree = try src_loc.file_scope.getTree(gpa);1690 const tree = try src_loc.file_scope.getTree(gpa);
1705 const node_tags = tree.nodes.items(.tag);1691 const parent_node = node_off.toAbsolute(src_loc.base_node);
1706 const parent_node = src_loc.relativeToNodeIndex(node_off);
17071692
1708 const full: Ast.full.ContainerField = switch (node_tags[parent_node]) {1693 const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) {
1709 .container_field => tree.containerField(parent_node),1694 .container_field => tree.containerField(parent_node),
1710 .container_field_init => tree.containerFieldInit(parent_node),1695 .container_field_init => tree.containerFieldInit(parent_node),
1711 else => unreachable,1696 else => unreachable,
1712 };1697 };
1713 return tree.nodeToSpan(full.ast.value_expr);1698 return tree.nodeToSpan(full.ast.value_expr.unwrap().?);
1714 },1699 },
1715 .node_offset_init_ty => |node_off| {1700 .node_offset_init_ty => |node_off| {
1716 const tree = try src_loc.file_scope.getTree(gpa);1701 const tree = try src_loc.file_scope.getTree(gpa);
1717 const parent_node = src_loc.relativeToNodeIndex(node_off);1702 const parent_node = node_off.toAbsolute(src_loc.base_node);
17181703
1719 var buf: [2]Ast.Node.Index = undefined;1704 var buf: [2]Ast.Node.Index = undefined;
1720 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|1705 const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init|
1721 array_init.ast.type_expr1706 array_init.ast.type_expr.unwrap().?
1722 else1707 else
1723 tree.fullStructInit(&buf, parent_node).?.ast.type_expr;1708 tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?;
1724 return tree.nodeToSpan(type_expr);1709 return tree.nodeToSpan(type_expr);
1725 },1710 },
1726 .node_offset_store_ptr => |node_off| {1711 .node_offset_store_ptr => |node_off| {
1727 const tree = try src_loc.file_scope.getTree(gpa);1712 const tree = try src_loc.file_scope.getTree(gpa);
1728 const node_tags = tree.nodes.items(.tag);1713 const node = node_off.toAbsolute(src_loc.base_node);
1729 const node_datas = tree.nodes.items(.data);
1730 const node = src_loc.relativeToNodeIndex(node_off);
17311714
1732 switch (node_tags[node]) {1715 switch (tree.nodeTag(node)) {
1733 .assign => {1716 .assign => {
1734 return tree.nodeToSpan(node_datas[node].lhs);1717 return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]);
1735 },1718 },
1736 else => return tree.nodeToSpan(node),1719 else => return tree.nodeToSpan(node),
1737 }1720 }
1738 },1721 },
1739 .node_offset_store_operand => |node_off| {1722 .node_offset_store_operand => |node_off| {
1740 const tree = try src_loc.file_scope.getTree(gpa);1723 const tree = try src_loc.file_scope.getTree(gpa);
1741 const node_tags = tree.nodes.items(.tag);1724 const node = node_off.toAbsolute(src_loc.base_node);
1742 const node_datas = tree.nodes.items(.data);
1743 const node = src_loc.relativeToNodeIndex(node_off);
17441725
1745 switch (node_tags[node]) {1726 switch (tree.nodeTag(node)) {
1746 .assign => {1727 .assign => {
1747 return tree.nodeToSpan(node_datas[node].rhs);1728 return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]);
1748 },1729 },
1749 else => return tree.nodeToSpan(node),1730 else => return tree.nodeToSpan(node),
1750 }1731 }
1751 },1732 },
1752 .node_offset_return_operand => |node_off| {1733 .node_offset_return_operand => |node_off| {
1753 const tree = try src_loc.file_scope.getTree(gpa);1734 const tree = try src_loc.file_scope.getTree(gpa);
1754 const node = src_loc.relativeToNodeIndex(node_off);1735 const node = node_off.toAbsolute(src_loc.base_node);
1755 const node_tags = tree.nodes.items(.tag);1736 if (tree.nodeTag(node) == .@"return") {
1756 const node_datas = tree.nodes.items(.data);1737 if (tree.nodeData(node).opt_node.unwrap()) |lhs| {
1757 if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) {1738 return tree.nodeToSpan(lhs);
1758 return tree.nodeToSpan(node_datas[node].lhs);1739 }
1759 }1740 }
1760 return tree.nodeToSpan(node);1741 return tree.nodeToSpan(node);
1761 },1742 },
...@@ -1765,7 +1746,7 @@ pub const SrcLoc = struct {...@@ -1765,7 +1746,7 @@ pub const SrcLoc = struct {
1765 .container_field_align,1746 .container_field_align,
1766 => |field_idx| {1747 => |field_idx| {
1767 const tree = try src_loc.file_scope.getTree(gpa);1748 const tree = try src_loc.file_scope.getTree(gpa);
1768 const node = src_loc.relativeToNodeIndex(0);1749 const node = src_loc.base_node;
1769 var buf: [2]Ast.Node.Index = undefined;1750 var buf: [2]Ast.Node.Index = undefined;
1770 const container_decl = tree.fullContainerDecl(&buf, node) orelse1751 const container_decl = tree.fullContainerDecl(&buf, node) orelse
1771 return tree.nodeToSpan(node);1752 return tree.nodeToSpan(node);
...@@ -1778,36 +1759,36 @@ pub const SrcLoc = struct {...@@ -1778,36 +1759,36 @@ pub const SrcLoc = struct {
1778 continue;1759 continue;
1779 }1760 }
1780 const field_component_node = switch (src_loc.lazy) {1761 const field_component_node = switch (src_loc.lazy) {
1781 .container_field_name => 0,1762 .container_field_name => .none,
1782 .container_field_value => field.ast.value_expr,1763 .container_field_value => field.ast.value_expr,
1783 .container_field_type => field.ast.type_expr,1764 .container_field_type => field.ast.type_expr,
1784 .container_field_align => field.ast.align_expr,1765 .container_field_align => field.ast.align_expr,
1785 else => unreachable,1766 else => unreachable,
1786 };1767 };
1787 if (field_component_node == 0) {1768 if (field_component_node.unwrap()) |component_node| {
1788 return tree.tokenToSpan(field.ast.main_token);1769 return tree.nodeToSpan(component_node);
1789 } else {1770 } else {
1790 return tree.nodeToSpan(field_component_node);1771 return tree.tokenToSpan(field.ast.main_token);
1791 }1772 }
1792 } else unreachable;1773 } else unreachable;
1793 },1774 },
1794 .tuple_field_type, .tuple_field_init => |field_info| {1775 .tuple_field_type, .tuple_field_init => |field_info| {
1795 const tree = try src_loc.file_scope.getTree(gpa);1776 const tree = try src_loc.file_scope.getTree(gpa);
1796 const node = src_loc.relativeToNodeIndex(0);1777 const node = src_loc.base_node;
1797 var buf: [2]Ast.Node.Index = undefined;1778 var buf: [2]Ast.Node.Index = undefined;
1798 const container_decl = tree.fullContainerDecl(&buf, node) orelse1779 const container_decl = tree.fullContainerDecl(&buf, node) orelse
1799 return tree.nodeToSpan(node);1780 return tree.nodeToSpan(node);
18001781
1801 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;1782 const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?;
1802 return tree.nodeToSpan(switch (src_loc.lazy) {1783 return tree.nodeToSpan(switch (src_loc.lazy) {
1803 .tuple_field_type => field.ast.type_expr,1784 .tuple_field_type => field.ast.type_expr.unwrap().?,
1804 .tuple_field_init => field.ast.value_expr,1785 .tuple_field_init => field.ast.value_expr.unwrap().?,
1805 else => unreachable,1786 else => unreachable,
1806 });1787 });
1807 },1788 },
1808 .init_elem => |init_elem| {1789 .init_elem => |init_elem| {
1809 const tree = try src_loc.file_scope.getTree(gpa);1790 const tree = try src_loc.file_scope.getTree(gpa);
1810 const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset);1791 const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node);
1811 var buf: [2]Ast.Node.Index = undefined;1792 var buf: [2]Ast.Node.Index = undefined;
1812 if (tree.fullArrayInit(&buf, init_node)) |full| {1793 if (tree.fullArrayInit(&buf, init_node)) |full| {
1813 const elem_node = full.ast.elements[init_elem.elem_index];1794 const elem_node = full.ast.elements[init_elem.elem_index];
...@@ -1817,7 +1798,7 @@ pub const SrcLoc = struct {...@@ -1817,7 +1798,7 @@ pub const SrcLoc = struct {
1817 return tree.tokensToSpan(1798 return tree.tokensToSpan(
1818 tree.firstToken(field_node) - 3,1799 tree.firstToken(field_node) - 3,
1819 tree.lastToken(field_node),1800 tree.lastToken(field_node),
1820 tree.nodes.items(.main_token)[field_node] - 2,1801 tree.nodeMainToken(field_node) - 2,
1821 );1802 );
1822 } else unreachable;1803 } else unreachable;
1823 },1804 },
...@@ -1846,7 +1827,7 @@ pub const SrcLoc = struct {...@@ -1846,7 +1827,7 @@ pub const SrcLoc = struct {
1846 else => unreachable,1827 else => unreachable,
1847 };1828 };
1848 const tree = try src_loc.file_scope.getTree(gpa);1829 const tree = try src_loc.file_scope.getTree(gpa);
1849 const node = src_loc.relativeToNodeIndex(builtin_call_node);1830 const node = builtin_call_node.toAbsolute(src_loc.base_node);
1850 var builtin_buf: [2]Ast.Node.Index = undefined;1831 var builtin_buf: [2]Ast.Node.Index = undefined;
1851 const args = tree.builtinCallParams(&builtin_buf, node).?;1832 const args = tree.builtinCallParams(&builtin_buf, node).?;
1852 const arg_node = args[1];1833 const arg_node = args[1];
...@@ -1861,7 +1842,7 @@ pub const SrcLoc = struct {...@@ -1861,7 +1842,7 @@ pub const SrcLoc = struct {
1861 return tree.tokensToSpan(1842 return tree.tokensToSpan(
1862 name_token - 1,1843 name_token - 1,
1863 tree.lastToken(field_node),1844 tree.lastToken(field_node),
1864 tree.nodes.items(.main_token)[field_node] - 2,1845 tree.nodeMainToken(field_node) - 2,
1865 );1846 );
1866 }1847 }
1867 }1848 }
...@@ -1885,12 +1866,9 @@ pub const SrcLoc = struct {...@@ -1885,12 +1866,9 @@ pub const SrcLoc = struct {
1885 };1866 };
18861867
1887 const tree = try src_loc.file_scope.getTree(gpa);1868 const tree = try src_loc.file_scope.getTree(gpa);
1888 const node_datas = tree.nodes.items(.data);1869 const switch_node = switch_node_offset.toAbsolute(src_loc.base_node);
1889 const node_tags = tree.nodes.items(.tag);1870 _, const extra_index = tree.nodeData(switch_node).node_and_extra;
1890 const main_tokens = tree.nodes.items(.main_token);1871 const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index);
1891 const switch_node = src_loc.relativeToNodeIndex(switch_node_offset);
1892 const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange);
1893 const case_nodes = tree.extra_data[extra.start..extra.end];
18941872
1895 var multi_i: u32 = 0;1873 var multi_i: u32 = 0;
1896 var scalar_i: u32 = 0;1874 var scalar_i: u32 = 0;
...@@ -1898,8 +1876,8 @@ pub const SrcLoc = struct {...@@ -1898,8 +1876,8 @@ pub const SrcLoc = struct {
1898 const case = tree.fullSwitchCase(case_node).?;1876 const case = tree.fullSwitchCase(case_node).?;
1899 const is_special = special: {1877 const is_special = special: {
1900 if (case.ast.values.len == 0) break :special true;1878 if (case.ast.values.len == 0) break :special true;
1901 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) {1879 if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) {
1902 break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_");1880 break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_");
1903 }1881 }
1904 break :special false;1882 break :special false;
1905 };1883 };
...@@ -1911,7 +1889,7 @@ pub const SrcLoc = struct {...@@ -1911,7 +1889,7 @@ pub const SrcLoc = struct {
1911 }1889 }
19121890
1913 const is_multi = case.ast.values.len != 1 or1891 const is_multi = case.ast.values.len != 1 or
1914 node_tags[case.ast.values[0]] == .switch_range;1892 tree.nodeTag(case.ast.values[0]) == .switch_range;
19151893
1916 switch (want_case_idx.kind) {1894 switch (want_case_idx.kind) {
1917 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,1895 .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case,
...@@ -1931,18 +1909,17 @@ pub const SrcLoc = struct {...@@ -1931,18 +1909,17 @@ pub const SrcLoc = struct {
1931 .switch_case_item_range_last,1909 .switch_case_item_range_last,
1932 => |x| x.item_idx,1910 => |x| x.item_idx,
1933 .switch_capture, .switch_tag_capture => {1911 .switch_capture, .switch_tag_capture => {
1934 const token_tags = tree.tokens.items(.tag);
1935 const start = switch (src_loc.lazy) {1912 const start = switch (src_loc.lazy) {
1936 .switch_capture => case.payload_token.?,1913 .switch_capture => case.payload_token.?,
1937 .switch_tag_capture => tok: {1914 .switch_tag_capture => tok: {
1938 var tok = case.payload_token.?;1915 var tok = case.payload_token.?;
1939 if (token_tags[tok] == .asterisk) tok += 1;1916 if (tree.tokenTag(tok) == .asterisk) tok += 1;
1940 tok += 2; // skip over comma1917 tok = tok + 2; // skip over comma
1941 break :tok tok;1918 break :tok tok;
1942 },1919 },
1943 else => unreachable,1920 else => unreachable,
1944 };1921 };
1945 const end = switch (token_tags[start]) {1922 const end = switch (tree.tokenTag(start)) {
1946 .asterisk => start + 1,1923 .asterisk => start + 1,
1947 else => start,1924 else => start,
1948 };1925 };
...@@ -1955,7 +1932,7 @@ pub const SrcLoc = struct {...@@ -1955,7 +1932,7 @@ pub const SrcLoc = struct {
1955 .single => {1932 .single => {
1956 var item_i: u32 = 0;1933 var item_i: u32 = 0;
1957 for (case.ast.values) |item_node| {1934 for (case.ast.values) |item_node| {
1958 if (node_tags[item_node] == .switch_range) continue;1935 if (tree.nodeTag(item_node) == .switch_range) continue;
1959 if (item_i != want_item.index) {1936 if (item_i != want_item.index) {
1960 item_i += 1;1937 item_i += 1;
1961 continue;1938 continue;
...@@ -1966,15 +1943,16 @@ pub const SrcLoc = struct {...@@ -1966,15 +1943,16 @@ pub const SrcLoc = struct {
1966 .range => {1943 .range => {
1967 var range_i: u32 = 0;1944 var range_i: u32 = 0;
1968 for (case.ast.values) |item_node| {1945 for (case.ast.values) |item_node| {
1969 if (node_tags[item_node] != .switch_range) continue;1946 if (tree.nodeTag(item_node) != .switch_range) continue;
1970 if (range_i != want_item.index) {1947 if (range_i != want_item.index) {
1971 range_i += 1;1948 range_i += 1;
1972 continue;1949 continue;
1973 }1950 }
1951 const first, const last = tree.nodeData(item_node).node_and_node;
1974 return switch (src_loc.lazy) {1952 return switch (src_loc.lazy) {
1975 .switch_case_item => tree.nodeToSpan(item_node),1953 .switch_case_item => tree.nodeToSpan(item_node),
1976 .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs),1954 .switch_case_item_range_first => tree.nodeToSpan(first),
1977 .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs),1955 .switch_case_item_range_last => tree.nodeToSpan(last),
1978 else => unreachable,1956 else => unreachable,
1979 };1957 };
1980 } else unreachable;1958 } else unreachable;
...@@ -1997,7 +1975,7 @@ pub const SrcLoc = struct {...@@ -1997,7 +1975,7 @@ pub const SrcLoc = struct {
1997 var param_it = full.iterate(tree);1975 var param_it = full.iterate(tree);
1998 for (0..param_idx) |_| assert(param_it.next() != null);1976 for (0..param_idx) |_| assert(param_it.next() != null);
1999 const param = param_it.next().?;1977 const param = param_it.next().?;
2000 return tree.nodeToSpan(param.type_expr);1978 return tree.nodeToSpan(param.type_expr.?);
2001 },1979 },
2002 }1980 }
2003 }1981 }
...@@ -2028,212 +2006,217 @@ pub const LazySrcLoc = struct {...@@ -2028,212 +2006,217 @@ pub const LazySrcLoc = struct {
2028 byte_abs: u32,2006 byte_abs: u32,
2029 /// The source location points to a token within a source file,2007 /// The source location points to a token within a source file,
2030 /// offset from 0. The source file is determined contextually.2008 /// offset from 0. The source file is determined contextually.
2031 token_abs: u32,2009 token_abs: Ast.TokenIndex,
2032 /// The source location points to an AST node within a source file,2010 /// The source location points to an AST node within a source file,
2033 /// offset from 0. The source file is determined contextually.2011 /// offset from 0. The source file is determined contextually.
2034 node_abs: u32,2012 node_abs: Ast.Node.Index,
2035 /// The source location points to a byte offset within a source file,2013 /// The source location points to a byte offset within a source file,
2036 /// offset from the byte offset of the base node within the file.2014 /// offset from the byte offset of the base node within the file.
2037 byte_offset: u32,2015 byte_offset: u32,
2038 /// This data is the offset into the token list from the base node's first token.2016 /// This data is the offset into the token list from the base node's first token.
2039 token_offset: u32,2017 token_offset: Ast.TokenOffset,
2040 /// The source location points to an AST node, which is this value offset2018 /// The source location points to an AST node, which is this value offset
2041 /// from its containing base node AST index.2019 /// from its containing base node AST index.
2042 node_offset: TracedOffset,2020 node_offset: TracedOffset,
2043 /// The source location points to the main token of an AST node, found2021 /// The source location points to the main token of an AST node, found
2044 /// by taking this AST node index offset from the containing base node.2022 /// by taking this AST node index offset from the containing base node.
2045 node_offset_main_token: i32,2023 node_offset_main_token: Ast.Node.Offset,
2046 /// The source location points to the beginning of a struct initializer.2024 /// The source location points to the beginning of a struct initializer.
2047 node_offset_initializer: i32,2025 node_offset_initializer: Ast.Node.Offset,
2048 /// The source location points to a variable declaration type expression,2026 /// The source location points to a variable declaration type expression,
2049 /// found by taking this AST node index offset from the containing2027 /// found by taking this AST node index offset from the containing
2050 /// base node, which points to a variable declaration AST node. Next, navigate2028 /// base node, which points to a variable declaration AST node. Next, navigate
2051 /// to the type expression.2029 /// to the type expression.
2052 node_offset_var_decl_ty: i32,2030 node_offset_var_decl_ty: Ast.Node.Offset,
2053 /// The source location points to the alignment expression of a var decl.2031 /// The source location points to the alignment expression of a var decl.
2054 node_offset_var_decl_align: i32,2032 node_offset_var_decl_align: Ast.Node.Offset,
2055 /// The source location points to the linksection expression of a var decl.2033 /// The source location points to the linksection expression of a var decl.
2056 node_offset_var_decl_section: i32,2034 node_offset_var_decl_section: Ast.Node.Offset,
2057 /// The source location points to the addrspace expression of a var decl.2035 /// The source location points to the addrspace expression of a var decl.
2058 node_offset_var_decl_addrspace: i32,2036 node_offset_var_decl_addrspace: Ast.Node.Offset,
2059 /// The source location points to the initializer of a var decl.2037 /// The source location points to the initializer of a var decl.
2060 node_offset_var_decl_init: i32,2038 node_offset_var_decl_init: Ast.Node.Offset,
2061 /// The source location points to the given argument of a builtin function call.2039 /// The source location points to the given argument of a builtin function call.
2062 /// `builtin_call_node` points to the builtin call.2040 /// `builtin_call_node` points to the builtin call.
2063 /// `arg_index` is the index of the argument which hte source location refers to.2041 /// `arg_index` is the index of the argument which hte source location refers to.
2064 node_offset_builtin_call_arg: struct {2042 node_offset_builtin_call_arg: struct {
2065 builtin_call_node: i32,2043 builtin_call_node: Ast.Node.Offset,
2066 arg_index: u32,2044 arg_index: u32,
2067 },2045 },
2068 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls2046 /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls
2069 /// to pointer cast builtins (taking the first argument of the most nested).2047 /// to pointer cast builtins (taking the first argument of the most nested).
2070 node_offset_ptrcast_operand: i32,2048 node_offset_ptrcast_operand: Ast.Node.Offset,
2071 /// The source location points to the index expression of an array access2049 /// The source location points to the index expression of an array access
2072 /// expression, found by taking this AST node index offset from the containing2050 /// expression, found by taking this AST node index offset from the containing
2073 /// base node, which points to an array access AST node. Next, navigate2051 /// base node, which points to an array access AST node. Next, navigate
2074 /// to the index expression.2052 /// to the index expression.
2075 node_offset_array_access_index: i32,2053 node_offset_array_access_index: Ast.Node.Offset,
2076 /// The source location points to the LHS of a slice expression2054 /// The source location points to the LHS of a slice expression
2077 /// expression, found by taking this AST node index offset from the containing2055 /// expression, found by taking this AST node index offset from the containing
2078 /// base node, which points to a slice AST node. Next, navigate2056 /// base node, which points to a slice AST node. Next, navigate
2079 /// to the sentinel expression.2057 /// to the sentinel expression.
2080 node_offset_slice_ptr: i32,2058 node_offset_slice_ptr: Ast.Node.Offset,
2081 /// The source location points to start expression of a slice expression2059 /// The source location points to start expression of a slice expression
2082 /// expression, found by taking this AST node index offset from the containing2060 /// expression, found by taking this AST node index offset from the containing
2083 /// base node, which points to a slice AST node. Next, navigate2061 /// base node, which points to a slice AST node. Next, navigate
2084 /// to the sentinel expression.2062 /// to the sentinel expression.
2085 node_offset_slice_start: i32,2063 node_offset_slice_start: Ast.Node.Offset,
2086 /// The source location points to the end expression of a slice2064 /// The source location points to the end expression of a slice
2087 /// expression, found by taking this AST node index offset from the containing2065 /// expression, found by taking this AST node index offset from the containing
2088 /// base node, which points to a slice AST node. Next, navigate2066 /// base node, which points to a slice AST node. Next, navigate
2089 /// to the sentinel expression.2067 /// to the sentinel expression.
2090 node_offset_slice_end: i32,2068 node_offset_slice_end: Ast.Node.Offset,
2091 /// The source location points to the sentinel expression of a slice2069 /// The source location points to the sentinel expression of a slice
2092 /// expression, found by taking this AST node index offset from the containing2070 /// expression, found by taking this AST node index offset from the containing
2093 /// base node, which points to a slice AST node. Next, navigate2071 /// base node, which points to a slice AST node. Next, navigate
2094 /// to the sentinel expression.2072 /// to the sentinel expression.
2095 node_offset_slice_sentinel: i32,2073 node_offset_slice_sentinel: Ast.Node.Offset,
2096 /// The source location points to the callee expression of a function2074 /// The source location points to the callee expression of a function
2097 /// call expression, found by taking this AST node index offset from the containing2075 /// call expression, found by taking this AST node index offset from the containing
2098 /// base node, which points to a function call AST node. Next, navigate2076 /// base node, which points to a function call AST node. Next, navigate
2099 /// to the callee expression.2077 /// to the callee expression.
2100 node_offset_call_func: i32,2078 node_offset_call_func: Ast.Node.Offset,
2101 /// The payload is offset from the containing base node.2079 /// The payload is offset from the containing base node.
2102 /// The source location points to the field name of:2080 /// The source location points to the field name of:
2103 /// * a field access expression (`a.b`), or2081 /// * a field access expression (`a.b`), or
2104 /// * the callee of a method call (`a.b()`)2082 /// * the callee of a method call (`a.b()`)
2105 node_offset_field_name: i32,2083 node_offset_field_name: Ast.Node.Offset,
2106 /// The payload is offset from the containing base node.2084 /// The payload is offset from the containing base node.
2107 /// The source location points to the field name of the operand ("b" node)2085 /// The source location points to the field name of the operand ("b" node)
2108 /// of a field initialization expression (`.a = b`)2086 /// of a field initialization expression (`.a = b`)
2109 node_offset_field_name_init: i32,2087 node_offset_field_name_init: Ast.Node.Offset,
2110 /// The source location points to the pointer of a pointer deref expression,2088 /// The source location points to the pointer of a pointer deref expression,
2111 /// found by taking this AST node index offset from the containing2089 /// found by taking this AST node index offset from the containing
2112 /// base node, which points to a pointer deref AST node. Next, navigate2090 /// base node, which points to a pointer deref AST node. Next, navigate
2113 /// to the pointer expression.2091 /// to the pointer expression.
2114 node_offset_deref_ptr: i32,2092 node_offset_deref_ptr: Ast.Node.Offset,
2115 /// The source location points to the assembly source code of an inline assembly2093 /// The source location points to the assembly source code of an inline assembly
2116 /// expression, found by taking this AST node index offset from the containing2094 /// expression, found by taking this AST node index offset from the containing
2117 /// base node, which points to inline assembly AST node. Next, navigate2095 /// base node, which points to inline assembly AST node. Next, navigate
2118 /// to the asm template source code.2096 /// to the asm template source code.
2119 node_offset_asm_source: i32,2097 node_offset_asm_source: Ast.Node.Offset,
2120 /// The source location points to the return type of an inline assembly2098 /// The source location points to the return type of an inline assembly
2121 /// expression, found by taking this AST node index offset from the containing2099 /// expression, found by taking this AST node index offset from the containing
2122 /// base node, which points to inline assembly AST node. Next, navigate2100 /// base node, which points to inline assembly AST node. Next, navigate
2123 /// to the return type expression.2101 /// to the return type expression.
2124 node_offset_asm_ret_ty: i32,2102 node_offset_asm_ret_ty: Ast.Node.Offset,
2125 /// The source location points to the condition expression of an if2103 /// The source location points to the condition expression of an if
2126 /// expression, found by taking this AST node index offset from the containing2104 /// expression, found by taking this AST node index offset from the containing
2127 /// base node, which points to an if expression AST node. Next, navigate2105 /// base node, which points to an if expression AST node. Next, navigate
2128 /// to the condition expression.2106 /// to the condition expression.
2129 node_offset_if_cond: i32,2107 node_offset_if_cond: Ast.Node.Offset,
2130 /// The source location points to a binary expression, such as `a + b`, found2108 /// The source location points to a binary expression, such as `a + b`, found
2131 /// by taking this AST node index offset from the containing base node.2109 /// by taking this AST node index offset from the containing base node.
2132 node_offset_bin_op: i32,2110 node_offset_bin_op: Ast.Node.Offset,
2133 /// The source location points to the LHS of a binary expression, found2111 /// The source location points to the LHS of a binary expression, found
2134 /// 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,
2135 /// which points to a binary expression AST node. Next, navigate to the LHS.2113 /// which points to a binary expression AST node. Next, navigate to the LHS.
2136 node_offset_bin_lhs: i32,2114 node_offset_bin_lhs: Ast.Node.Offset,
2137 /// The source location points to the RHS of a binary expression, found2115 /// The source location points to the RHS of a binary expression, found
2138 /// by taking this AST node index offset from the containing base node,2116 /// by taking this AST node index offset from the containing base node,
2139 /// which points to a binary expression AST node. Next, navigate to the RHS.2117 /// which points to a binary expression AST node. Next, navigate to the RHS.
2140 node_offset_bin_rhs: i32,2118 node_offset_bin_rhs: Ast.Node.Offset,
2119 /// The source location points to the operand of a try expression, found
2120 /// by taking this AST node index offset from the containing base node,
2121 /// which points to a try expression AST node. Next, navigate to the
2122 /// operand expression.
2123 node_offset_try_operand: Ast.Node.Offset,
2141 /// The source location points to the operand of a switch expression, found2124 /// The source location points to the operand of a switch expression, found
2142 /// by taking this AST node index offset from the containing base node,2125 /// by taking this AST node index offset from the containing base node,
2143 /// which points to a switch expression AST node. Next, navigate to the operand.2126 /// which points to a switch expression AST node. Next, navigate to the operand.
2144 node_offset_switch_operand: i32,2127 node_offset_switch_operand: Ast.Node.Offset,
2145 /// The source location points to the else/`_` prong of a switch expression, found2128 /// The source location points to the else/`_` prong of a switch expression, found
2146 /// by taking this AST node index offset from the containing base node,2129 /// by taking this AST node index offset from the containing base node,
2147 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.2130 /// which points to a switch expression AST node. Next, navigate to the else/`_` prong.
2148 node_offset_switch_special_prong: i32,2131 node_offset_switch_special_prong: Ast.Node.Offset,
2149 /// The source location points to all the ranges of a switch expression, found2132 /// The source location points to all the ranges of a switch expression, found
2150 /// by taking this AST node index offset from the containing base node,2133 /// by taking this AST node index offset from the containing base node,
2151 /// which points to a switch expression AST node. Next, navigate to any of the2134 /// which points to a switch expression AST node. Next, navigate to any of the
2152 /// range nodes. The error applies to all of them.2135 /// range nodes. The error applies to all of them.
2153 node_offset_switch_range: i32,2136 node_offset_switch_range: Ast.Node.Offset,
2154 /// The source location points to the align expr of a function type2137 /// The source location points to the align expr of a function type
2155 /// expression, found by taking this AST node index offset from the containing2138 /// expression, found by taking this AST node index offset from the containing
2156 /// base node, which points to a function type AST node. Next, navigate to2139 /// base node, which points to a function type AST node. Next, navigate to
2157 /// the calling convention node.2140 /// the calling convention node.
2158 node_offset_fn_type_align: i32,2141 node_offset_fn_type_align: Ast.Node.Offset,
2159 /// The source location points to the addrspace expr of a function type2142 /// The source location points to the addrspace expr of a function type
2160 /// expression, found by taking this AST node index offset from the containing2143 /// expression, found by taking this AST node index offset from the containing
2161 /// base node, which points to a function type AST node. Next, navigate to2144 /// base node, which points to a function type AST node. Next, navigate to
2162 /// the calling convention node.2145 /// the calling convention node.
2163 node_offset_fn_type_addrspace: i32,2146 node_offset_fn_type_addrspace: Ast.Node.Offset,
2164 /// The source location points to the linksection expr of a function type2147 /// The source location points to the linksection expr of a function type
2165 /// expression, found by taking this AST node index offset from the containing2148 /// expression, found by taking this AST node index offset from the containing
2166 /// base node, which points to a function type AST node. Next, navigate to2149 /// base node, which points to a function type AST node. Next, navigate to
2167 /// the calling convention node.2150 /// the calling convention node.
2168 node_offset_fn_type_section: i32,2151 node_offset_fn_type_section: Ast.Node.Offset,
2169 /// The source location points to the calling convention of a function type2152 /// The source location points to the calling convention of a function type
2170 /// expression, found by taking this AST node index offset from the containing2153 /// expression, found by taking this AST node index offset from the containing
2171 /// base node, which points to a function type AST node. Next, navigate to2154 /// base node, which points to a function type AST node. Next, navigate to
2172 /// the calling convention node.2155 /// the calling convention node.
2173 node_offset_fn_type_cc: i32,2156 node_offset_fn_type_cc: Ast.Node.Offset,
2174 /// The source location points to the return type of a function type2157 /// The source location points to the return type of a function type
2175 /// expression, found by taking this AST node index offset from the containing2158 /// expression, found by taking this AST node index offset from the containing
2176 /// base node, which points to a function type AST node. Next, navigate to2159 /// base node, which points to a function type AST node. Next, navigate to
2177 /// the return type node.2160 /// the return type node.
2178 node_offset_fn_type_ret_ty: i32,2161 node_offset_fn_type_ret_ty: Ast.Node.Offset,
2179 node_offset_param: i32,2162 node_offset_param: Ast.Node.Offset,
2180 token_offset_param: i32,2163 token_offset_param: Ast.TokenOffset,
2181 /// The source location points to the type expression of an `anyframe->T`2164 /// The source location points to the type expression of an `anyframe->T`
2182 /// expression, found by taking this AST node index offset from the containing2165 /// expression, found by taking this AST node index offset from the containing
2183 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate2166 /// base node, which points to a `anyframe->T` expression AST node. Next, navigate
2184 /// to the type expression.2167 /// to the type expression.
2185 node_offset_anyframe_type: i32,2168 node_offset_anyframe_type: Ast.Node.Offset,
2186 /// The source location points to the string literal of `extern "foo"`, found2169 /// The source location points to the string literal of `extern "foo"`, found
2187 /// by taking this AST node index offset from the containing2170 /// by taking this AST node index offset from the containing
2188 /// base node, which points to a function prototype or variable declaration2171 /// base node, which points to a function prototype or variable declaration
2189 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.2172 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
2190 node_offset_lib_name: i32,2173 node_offset_lib_name: Ast.Node.Offset,
2191 /// The source location points to the len expression of an `[N:S]T`2174 /// The source location points to the len expression of an `[N:S]T`
2192 /// expression, found by taking this AST node index offset from the containing2175 /// expression, found by taking this AST node index offset from the containing
2193 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2176 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2194 /// to the len expression.2177 /// to the len expression.
2195 node_offset_array_type_len: i32,2178 node_offset_array_type_len: Ast.Node.Offset,
2196 /// The source location points to the sentinel expression of an `[N:S]T`2179 /// The source location points to the sentinel expression of an `[N:S]T`
2197 /// expression, found by taking this AST node index offset from the containing2180 /// expression, found by taking this AST node index offset from the containing
2198 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2181 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2199 /// to the sentinel expression.2182 /// to the sentinel expression.
2200 node_offset_array_type_sentinel: i32,2183 node_offset_array_type_sentinel: Ast.Node.Offset,
2201 /// The source location points to the elem expression of an `[N:S]T`2184 /// The source location points to the elem expression of an `[N:S]T`
2202 /// expression, found by taking this AST node index offset from the containing2185 /// expression, found by taking this AST node index offset from the containing
2203 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate2186 /// base node, which points to an `[N:S]T` expression AST node. Next, navigate
2204 /// to the elem expression.2187 /// to the elem expression.
2205 node_offset_array_type_elem: i32,2188 node_offset_array_type_elem: Ast.Node.Offset,
2206 /// The source location points to the operand of an unary expression.2189 /// The source location points to the operand of an unary expression.
2207 node_offset_un_op: i32,2190 node_offset_un_op: Ast.Node.Offset,
2208 /// The source location points to the elem type of a pointer.2191 /// The source location points to the elem type of a pointer.
2209 node_offset_ptr_elem: i32,2192 node_offset_ptr_elem: Ast.Node.Offset,
2210 /// The source location points to the sentinel of a pointer.2193 /// The source location points to the sentinel of a pointer.
2211 node_offset_ptr_sentinel: i32,2194 node_offset_ptr_sentinel: Ast.Node.Offset,
2212 /// The source location points to the align expr of a pointer.2195 /// The source location points to the align expr of a pointer.
2213 node_offset_ptr_align: i32,2196 node_offset_ptr_align: Ast.Node.Offset,
2214 /// The source location points to the addrspace expr of a pointer.2197 /// The source location points to the addrspace expr of a pointer.
2215 node_offset_ptr_addrspace: i32,2198 node_offset_ptr_addrspace: Ast.Node.Offset,
2216 /// The source location points to the bit-offset of a pointer.2199 /// The source location points to the bit-offset of a pointer.
2217 node_offset_ptr_bitoffset: i32,2200 node_offset_ptr_bitoffset: Ast.Node.Offset,
2218 /// The source location points to the host size of a pointer.2201 /// The source location points to the host size of a pointer.
2219 node_offset_ptr_hostsize: i32,2202 node_offset_ptr_hostsize: Ast.Node.Offset,
2220 /// The source location points to the tag type of an union or an enum.2203 /// The source location points to the tag type of an union or an enum.
2221 node_offset_container_tag: i32,2204 node_offset_container_tag: Ast.Node.Offset,
2222 /// The source location points to the default value of a field.2205 /// The source location points to the default value of a field.
2223 node_offset_field_default: i32,2206 node_offset_field_default: Ast.Node.Offset,
2224 /// The source location points to the type of an array or struct initializer.2207 /// The source location points to the type of an array or struct initializer.
2225 node_offset_init_ty: i32,2208 node_offset_init_ty: Ast.Node.Offset,
2226 /// The source location points to the LHS of an assignment.2209 /// The source location points to the LHS of an assignment.
2227 node_offset_store_ptr: i32,2210 node_offset_store_ptr: Ast.Node.Offset,
2228 /// The source location points to the RHS of an assignment.2211 /// The source location points to the RHS of an assignment.
2229 node_offset_store_operand: i32,2212 node_offset_store_operand: Ast.Node.Offset,
2230 /// The source location points to the operand of a `return` statement, or2213 /// The source location points to the operand of a `return` statement, or
2231 /// the `return` itself if there is no explicit operand.2214 /// the `return` itself if there is no explicit operand.
2232 node_offset_return_operand: i32,2215 node_offset_return_operand: Ast.Node.Offset,
2233 /// The source location points to a for loop input.2216 /// The source location points to a for loop input.
2234 for_input: struct {2217 for_input: struct {
2235 /// Points to the for loop AST node.2218 /// Points to the for loop AST node.
2236 for_node_offset: i32,2219 for_node_offset: Ast.Node.Offset,
2237 /// Picks one of the inputs from the condition.2220 /// Picks one of the inputs from the condition.
2238 input_index: u32,2221 input_index: u32,
2239 },2222 },
...@@ -2241,11 +2224,11 @@ pub const LazySrcLoc = struct {...@@ -2241,11 +2224,11 @@ pub const LazySrcLoc = struct {
2241 /// by taking this AST node index offset from the containing2224 /// by taking this AST node index offset from the containing
2242 /// base node, which points to one of the input nodes of a for loop.2225 /// base node, which points to one of the input nodes of a for loop.
2243 /// Next, navigate to the corresponding capture.2226 /// Next, navigate to the corresponding capture.
2244 for_capture_from_input: i32,2227 for_capture_from_input: Ast.Node.Offset,
2245 /// The source location points to the argument node of a function call.2228 /// The source location points to the argument node of a function call.
2246 call_arg: struct {2229 call_arg: struct {
2247 /// Points to the function call AST node.2230 /// Points to the function call AST node.
2248 call_node_offset: i32,2231 call_node_offset: Ast.Node.Offset,
2249 /// The index of the argument the source location points to.2232 /// The index of the argument the source location points to.
2250 arg_index: u32,2233 arg_index: u32,
2251 },2234 },
...@@ -2272,25 +2255,25 @@ pub const LazySrcLoc = struct {...@@ -2272,25 +2255,25 @@ pub const LazySrcLoc = struct {
2272 /// array initialization expression.2255 /// array initialization expression.
2273 init_elem: struct {2256 init_elem: struct {
2274 /// Points to the AST node of the initialization expression.2257 /// Points to the AST node of the initialization expression.
2275 init_node_offset: i32,2258 init_node_offset: Ast.Node.Offset,
2276 /// The index of the field/element the source location points to.2259 /// The index of the field/element the source location points to.
2277 elem_index: u32,2260 elem_index: u32,
2278 },2261 },
2279 // The following source locations are like `init_elem`, but refer to a2262 // The following source locations are like `init_elem`, but refer to a
2280 // field with a specific name. If such a field is not given, the entire2263 // field with a specific name. If such a field is not given, the entire
2281 // initialization expression is used instead.2264 // initialization expression is used instead.
2282 // The `i32` points to the AST node of a builtin call, whose *second*2265 // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second*
2283 // argument is the init expression.2266 // argument is the init expression.
2284 init_field_name: i32,2267 init_field_name: Ast.Node.Offset,
2285 init_field_linkage: i32,2268 init_field_linkage: Ast.Node.Offset,
2286 init_field_section: i32,2269 init_field_section: Ast.Node.Offset,
2287 init_field_visibility: i32,2270 init_field_visibility: Ast.Node.Offset,
2288 init_field_rw: i32,2271 init_field_rw: Ast.Node.Offset,
2289 init_field_locality: i32,2272 init_field_locality: Ast.Node.Offset,
2290 init_field_cache: i32,2273 init_field_cache: Ast.Node.Offset,
2291 init_field_library: i32,2274 init_field_library: Ast.Node.Offset,
2292 init_field_thread_local: i32,2275 init_field_thread_local: Ast.Node.Offset,
2293 init_field_dll_import: i32,2276 init_field_dll_import: Ast.Node.Offset,
2294 /// The source location points to the value of an item in a specific2277 /// The source location points to the value of an item in a specific
2295 /// case of a `switch`.2278 /// case of a `switch`.
2296 switch_case_item: SwitchItem,2279 switch_case_item: SwitchItem,
...@@ -2315,14 +2298,14 @@ pub const LazySrcLoc = struct {...@@ -2315,14 +2298,14 @@ pub const LazySrcLoc = struct {
23152298
2316 pub const FnProtoParam = struct {2299 pub const FnProtoParam = struct {
2317 /// The offset of the function prototype AST node.2300 /// The offset of the function prototype AST node.
2318 fn_proto_node_offset: i32,2301 fn_proto_node_offset: Ast.Node.Offset,
2319 /// The index of the parameter the source location points to.2302 /// The index of the parameter the source location points to.
2320 param_index: u32,2303 param_index: u32,
2321 };2304 };
23222305
2323 pub const SwitchItem = struct {2306 pub const SwitchItem = struct {
2324 /// The offset of the switch AST node.2307 /// The offset of the switch AST node.
2325 switch_node_offset: i32,2308 switch_node_offset: Ast.Node.Offset,
2326 /// The index of the case to point to within this switch.2309 /// The index of the case to point to within this switch.
2327 case_idx: SwitchCaseIndex,2310 case_idx: SwitchCaseIndex,
2328 /// The index of the item to point to within this case.2311 /// The index of the item to point to within this case.
...@@ -2331,7 +2314,7 @@ pub const LazySrcLoc = struct {...@@ -2331,7 +2314,7 @@ pub const LazySrcLoc = struct {
23312314
2332 pub const SwitchCapture = struct {2315 pub const SwitchCapture = struct {
2333 /// The offset of the switch AST node.2316 /// The offset of the switch AST node.
2334 switch_node_offset: i32,2317 switch_node_offset: Ast.Node.Offset,
2335 /// The index of the case whose capture to point to.2318 /// The index of the case whose capture to point to.
2336 case_idx: SwitchCaseIndex,2319 case_idx: SwitchCaseIndex,
2337 };2320 };
...@@ -2353,34 +2336,34 @@ pub const LazySrcLoc = struct {...@@ -2353,34 +2336,34 @@ pub const LazySrcLoc = struct {
23532336
2354 pub const ArrayCat = struct {2337 pub const ArrayCat = struct {
2355 /// Points to the array concat AST node.2338 /// Points to the array concat AST node.
2356 array_cat_offset: i32,2339 array_cat_offset: Ast.Node.Offset,
2357 /// The index of the element the source location points to.2340 /// The index of the element the source location points to.
2358 elem_index: u32,2341 elem_index: u32,
2359 };2342 };
23602343
2361 pub const TupleField = struct {2344 pub const TupleField = struct {
2362 /// Points to the AST node of the tuple type decaration.2345 /// Points to the AST node of the tuple type decaration.
2363 tuple_decl_node_offset: i32,2346 tuple_decl_node_offset: Ast.Node.Offset,
2364 /// The index of the tuple field the source location points to.2347 /// The index of the tuple field the source location points to.
2365 elem_index: u32,2348 elem_index: u32,
2366 };2349 };
23672350
2368 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2351 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23692352
2370 noinline fn nodeOffsetDebug(node_offset: i32) Offset {2353 noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset {
2371 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };2354 var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } };
2372 result.node_offset.trace.addAddr(@returnAddress(), "init");2355 result.node_offset.trace.addAddr(@returnAddress(), "init");
2373 return result;2356 return result;
2374 }2357 }
23752358
2376 fn nodeOffsetRelease(node_offset: i32) Offset {2359 fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset {
2377 return .{ .node_offset = .{ .x = node_offset } };2360 return .{ .node_offset = .{ .x = node_offset } };
2378 }2361 }
23792362
2380 /// This wraps a simple integer in debug builds so that later on we can find out2363 /// This wraps a simple integer in debug builds so that later on we can find out
2381 /// where in semantic analysis the value got set.2364 /// where in semantic analysis the value got set.
2382 pub const TracedOffset = struct {2365 pub const TracedOffset = struct {
2383 x: i32,2366 x: Ast.Node.Offset,
2384 trace: std.debug.Trace = std.debug.Trace.init,2367 trace: std.debug.Trace = std.debug.Trace.init,
23852368
2386 const want_tracing = false;2369 const want_tracing = false;
...@@ -2405,7 +2388,7 @@ pub const LazySrcLoc = struct {...@@ -2405,7 +2388,7 @@ pub const LazySrcLoc = struct {
24052388
2406 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,2389 // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR,
2407 // which may not exist e.g. in the case of errors in ZON files.2390 // which may not exist e.g. in the case of errors in ZON files.
2408 if (zir_inst == .main_struct_inst) return .{ file, 0 };2391 if (zir_inst == .main_struct_inst) return .{ file, .root };
24092392
2410 // Otherwise, make sure ZIR is loaded.2393 // Otherwise, make sure ZIR is loaded.
2411 const zir = file.zir.?;2394 const zir = file.zir.?;
...@@ -2438,7 +2421,7 @@ pub const LazySrcLoc = struct {...@@ -2438,7 +2421,7 @@ pub const LazySrcLoc = struct {
2438 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {2421 pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc {
2439 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{2422 const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{
2440 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),2423 zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)),
2441 0,2424 .root,
2442 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;2425 } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null;
2443 return .{2426 return .{
2444 .file_scope = file,2427 .file_scope = file,
...@@ -4007,7 +3990,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {...@@ -4007,7 +3990,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc {
4007 const ip = &zcu.intern_pool;3990 const ip = &zcu.intern_pool;
4008 return .{3991 return .{
4009 .base_node_inst = ip.getNav(nav_index).srcInst(ip),3992 .base_node_inst = ip.getNav(nav_index).srcInst(ip),
4010 .offset = LazySrcLoc.Offset.nodeOffset(0),3993 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
4011 };3994 };
4012}3995}
40133996
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+10-8
...@@ -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,8 +7284,8 @@ fn cmdFetch(...@@ -7282,8 +7284,8 @@ 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 if (dep.hash_node != 0) {7287 if (dep.hash_node.unwrap()) |hash_node| {
7286 try fixups.replace_nodes_with_string.put(gpa, dep.hash_node, hash_replace);7288 try fixups.replace_nodes_with_string.put(gpa, hash_node, hash_replace);
7287 } else {7289 } else {
7288 // https://github.com/ziglang/zig/issues/216907290 // https://github.com/ziglang/zig/issues/21690
7289 }7291 }
...@@ -7292,9 +7294,9 @@ fn cmdFetch(...@@ -7292,9 +7294,9 @@ fn cmdFetch(
7292 const deps = manifest.dependencies.values();7294 const deps = manifest.dependencies.values();
7293 const last_dep_node = deps[deps.len - 1].node;7295 const last_dep_node = deps[deps.len - 1].node;
7294 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);
7295 } else if (manifest.dependencies_node != 0) {7297 } else if (manifest.dependencies_node.unwrap()) |dependencies_node| {
7296 // Add fixup for replacing the entire dependencies struct.7298 // Add fixup for replacing the entire dependencies struct.
7297 try fixups.replace_nodes_with_string.put(gpa, manifest.dependencies_node, dependencies_init);7299 try fixups.replace_nodes_with_string.put(gpa, dependencies_node, dependencies_init);
7298 } else {7300 } else {
7299 // Add fixup for adding dependencies struct.7301 // Add fixup for adding dependencies struct.
7300 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);