| author | |
| committer | |
| log | d0911786c95dfa7a63ec348bb4a9870da12f62e4 |
| tree | c2ee731b2fcb53504dbade8077084bf935197c06 |
| parent | a0401cf3e4aed014abc1189890f4c1c756a12737 |
| parent | 4129f7ff5a03cb3cd85a3ad5e3360098ab8ed796 |
| signature |
improve type safety of std.zig.Ast26 files changed, 5404 insertions(+), 5704 deletions(-)
lib/compiler/aro_translate_c/ast.zig+383-440| ... | ... | @@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast { |
| 775 | 775 | ctx.nodes.appendAssumeCapacity(.{ |
| 776 | 776 | .tag = .root, |
| 777 | 777 | .main_token = 0, |
| 778 | .data = .{ | |
| 779 | .lhs = undefined, | |
| 780 | .rhs = undefined, | |
| 781 | }, | |
| 778 | .data = undefined, | |
| 782 | 779 | }); |
| 783 | 780 | |
| 784 | 781 | const root_members = blk: { |
| ... | ... | @@ -793,10 +790,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast { |
| 793 | 790 | break :blk try ctx.listToSpan(result.items); |
| 794 | 791 | }; |
| 795 | 792 | |
| 796 | ctx.nodes.items(.data)[0] = .{ | |
| 797 | .lhs = root_members.start, | |
| 798 | .rhs = root_members.end, | |
| 799 | }; | |
| 793 | ctx.nodes.items(.data)[0] = .{ .extra_range = root_members }; | |
| 800 | 794 | |
| 801 | 795 | try ctx.tokens.append(gpa, .{ |
| 802 | 796 | .tag = .eof, |
| ... | ... | @@ -814,15 +808,18 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast { |
| 814 | 808 | } |
| 815 | 809 | |
| 816 | 810 | const NodeIndex = std.zig.Ast.Node.Index; |
| 811 | const NodeOptionalIndex = std.zig.Ast.Node.OptionalIndex; | |
| 817 | 812 | const NodeSubRange = std.zig.Ast.Node.SubRange; |
| 818 | 813 | const TokenIndex = std.zig.Ast.TokenIndex; |
| 814 | const TokenOptionalIndex = std.zig.Ast.OptionalTokenIndex; | |
| 819 | 815 | const TokenTag = std.zig.Token.Tag; |
| 816 | const ExtraIndex = std.zig.Ast.ExtraIndex; | |
| 820 | 817 | |
| 821 | 818 | const Context = struct { |
| 822 | 819 | gpa: Allocator, |
| 823 | 820 | buf: std.ArrayList(u8), |
| 824 | 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 | 823 | tokens: std.zig.Ast.TokenList = .{}, |
| 827 | 824 | |
| 828 | 825 | fn addTokenFmt(c: *Context, tag: TokenTag, comptime format: []const u8, args: anytype) Allocator.Error!TokenIndex { |
| ... | ... | @@ -834,7 +831,7 @@ const Context = struct { |
| 834 | 831 | .start = @as(u32, @intCast(start_index)), |
| 835 | 832 | }); |
| 836 | 833 | |
| 837 | return @as(u32, @intCast(c.tokens.len - 1)); | |
| 834 | return @intCast(c.tokens.len - 1); | |
| 838 | 835 | } |
| 839 | 836 | |
| 840 | 837 | fn addToken(c: *Context, tag: TokenTag, bytes: []const u8) Allocator.Error!TokenIndex { |
| ... | ... | @@ -848,26 +845,33 @@ const Context = struct { |
| 848 | 845 | } |
| 849 | 846 | |
| 850 | 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 | 849 | return NodeSubRange{ |
| 853 | .start = @as(NodeIndex, @intCast(c.extra_data.items.len - list.len)), | |
| 854 | .end = @as(NodeIndex, @intCast(c.extra_data.items.len)), | |
| 850 | .start = @enumFromInt(c.extra_data.items.len - list.len), | |
| 851 | .end = @enumFromInt(c.extra_data.items.len), | |
| 855 | 852 | }; |
| 856 | 853 | } |
| 857 | 854 | |
| 858 | 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 | 857 | try c.nodes.append(c.gpa, elem); |
| 861 | 858 | return result; |
| 862 | 859 | } |
| 863 | 860 | |
| 864 | fn addExtra(c: *Context, extra: anytype) Allocator.Error!NodeIndex { | |
| 861 | fn addExtra(c: *Context, extra: anytype) Allocator.Error!std.zig.Ast.ExtraIndex { | |
| 865 | 862 | const fields = std.meta.fields(@TypeOf(extra)); |
| 866 | 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 | 865 | inline for (fields) |field| { |
| 869 | comptime std.debug.assert(field.type == NodeIndex); | |
| 870 | c.extra_data.appendAssumeCapacity(@field(extra, field.name)); | |
| 866 | switch (field.type) { | |
| 867 | NodeIndex, | |
| 868 | NodeOptionalIndex, | |
| 869 | TokenIndex, | |
| 870 | TokenOptionalIndex, | |
| 871 | ExtraIndex, | |
| 872 | => c.extra_data.appendAssumeCapacity(@intFromEnum(@field(extra, field.name))), | |
| 873 | else => @compileError("unexpected field type"), | |
| 874 | } | |
| 871 | 875 | } |
| 872 | 876 | return result; |
| 873 | 877 | } |
| ... | ... | @@ -894,7 +898,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 894 | 898 | try c.buf.append('\n'); |
| 895 | 899 | try c.buf.appendSlice(payload); |
| 896 | 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 | 903 | .helpers_cast => { |
| 900 | 904 | const payload = node.castTag(.helpers_cast).?.data; |
| ... | ... | @@ -991,26 +995,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 991 | 995 | .@"continue" => return c.addNode(.{ |
| 992 | 996 | .tag = .@"continue", |
| 993 | 997 | .main_token = try c.addToken(.keyword_continue, "continue"), |
| 994 | .data = .{ | |
| 995 | .lhs = 0, | |
| 996 | .rhs = undefined, | |
| 997 | }, | |
| 998 | .data = .{ .opt_token_and_opt_node = .{ .none, .none } }, | |
| 998 | 999 | }), |
| 999 | 1000 | .return_void => return c.addNode(.{ |
| 1000 | 1001 | .tag = .@"return", |
| 1001 | 1002 | .main_token = try c.addToken(.keyword_return, "return"), |
| 1002 | .data = .{ | |
| 1003 | .lhs = 0, | |
| 1004 | .rhs = undefined, | |
| 1005 | }, | |
| 1003 | .data = .{ .opt_node = .none }, | |
| 1006 | 1004 | }), |
| 1007 | 1005 | .@"break" => return c.addNode(.{ |
| 1008 | 1006 | .tag = .@"break", |
| 1009 | 1007 | .main_token = try c.addToken(.keyword_break, "break"), |
| 1010 | .data = .{ | |
| 1011 | .lhs = 0, | |
| 1012 | .rhs = 0, | |
| 1013 | }, | |
| 1008 | .data = .{ .opt_token_and_opt_node = .{ .none, .none } }, | |
| 1014 | 1009 | }), |
| 1015 | 1010 | .break_val => { |
| 1016 | 1011 | const payload = node.castTag(.break_val).?.data; |
| ... | ... | @@ -1018,14 +1013,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1018 | 1013 | const break_label = if (payload.label) |some| blk: { |
| 1019 | 1014 | _ = try c.addToken(.colon, ":"); |
| 1020 | 1015 | break :blk try c.addIdentifier(some); |
| 1021 | } else 0; | |
| 1016 | } else null; | |
| 1022 | 1017 | return c.addNode(.{ |
| 1023 | 1018 | .tag = .@"break", |
| 1024 | 1019 | .main_token = tok, |
| 1025 | .data = .{ | |
| 1026 | .lhs = break_label, | |
| 1027 | .rhs = try renderNode(c, payload.val), | |
| 1028 | }, | |
| 1020 | .data = .{ .opt_token_and_opt_node = .{ | |
| 1021 | .fromOptional(break_label), | |
| 1022 | (try renderNode(c, payload.val)).toOptional(), | |
| 1023 | } }, | |
| 1029 | 1024 | }); |
| 1030 | 1025 | }, |
| 1031 | 1026 | .@"return" => { |
| ... | ... | @@ -1033,10 +1028,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1033 | 1028 | return c.addNode(.{ |
| 1034 | 1029 | .tag = .@"return", |
| 1035 | 1030 | .main_token = try c.addToken(.keyword_return, "return"), |
| 1036 | .data = .{ | |
| 1037 | .lhs = try renderNode(c, payload), | |
| 1038 | .rhs = undefined, | |
| 1039 | }, | |
| 1031 | .data = .{ .opt_node = (try renderNode(c, payload)).toOptional() }, | |
| 1040 | 1032 | }); |
| 1041 | 1033 | }, |
| 1042 | 1034 | .@"comptime" => { |
| ... | ... | @@ -1044,10 +1036,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1044 | 1036 | return c.addNode(.{ |
| 1045 | 1037 | .tag = .@"comptime", |
| 1046 | 1038 | .main_token = try c.addToken(.keyword_comptime, "comptime"), |
| 1047 | .data = .{ | |
| 1048 | .lhs = try renderNode(c, payload), | |
| 1049 | .rhs = undefined, | |
| 1050 | }, | |
| 1039 | .data = .{ .node = try renderNode(c, payload) }, | |
| 1051 | 1040 | }); |
| 1052 | 1041 | }, |
| 1053 | 1042 | .@"defer" => { |
| ... | ... | @@ -1055,10 +1044,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1055 | 1044 | return c.addNode(.{ |
| 1056 | 1045 | .tag = .@"defer", |
| 1057 | 1046 | .main_token = try c.addToken(.keyword_defer, "defer"), |
| 1058 | .data = .{ | |
| 1059 | .lhs = undefined, | |
| 1060 | .rhs = try renderNode(c, payload), | |
| 1061 | }, | |
| 1047 | .data = .{ .node = try renderNode(c, payload) }, | |
| 1062 | 1048 | }); |
| 1063 | 1049 | }, |
| 1064 | 1050 | .asm_simple => { |
| ... | ... | @@ -1068,10 +1054,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1068 | 1054 | return c.addNode(.{ |
| 1069 | 1055 | .tag = .asm_simple, |
| 1070 | 1056 | .main_token = asm_token, |
| 1071 | .data = .{ | |
| 1072 | .lhs = try renderNode(c, payload), | |
| 1073 | .rhs = try c.addToken(.r_paren, ")"), | |
| 1074 | }, | |
| 1057 | .data = .{ .node_and_token = .{ | |
| 1058 | try renderNode(c, payload), | |
| 1059 | try c.addToken(.r_paren, ")"), | |
| 1060 | } }, | |
| 1075 | 1061 | }); |
| 1076 | 1062 | }, |
| 1077 | 1063 | .type => { |
| ... | ... | @@ -1104,10 +1090,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1104 | 1090 | return c.addNode(.{ |
| 1105 | 1091 | .tag = .address_of, |
| 1106 | 1092 | .main_token = tok, |
| 1107 | .data = .{ | |
| 1108 | .lhs = arg, | |
| 1109 | .rhs = undefined, | |
| 1110 | }, | |
| 1093 | .data = .{ .node = arg }, | |
| 1111 | 1094 | }); |
| 1112 | 1095 | }, |
| 1113 | 1096 | .float_literal => { |
| ... | ... | @@ -1191,13 +1174,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1191 | 1174 | return c.addNode(.{ |
| 1192 | 1175 | .tag = .slice, |
| 1193 | 1176 | .main_token = l_bracket, |
| 1194 | .data = .{ | |
| 1195 | .lhs = string, | |
| 1196 | .rhs = try c.addExtra(std.zig.Ast.Node.Slice{ | |
| 1177 | .data = .{ .node_and_extra = .{ | |
| 1178 | string, | |
| 1179 | try c.addExtra(std.zig.Ast.Node.Slice{ | |
| 1197 | 1180 | .start = start, |
| 1198 | 1181 | .end = end, |
| 1199 | 1182 | }), |
| 1200 | }, | |
| 1183 | } }, | |
| 1201 | 1184 | }); |
| 1202 | 1185 | }, |
| 1203 | 1186 | .fail_decl => { |
| ... | ... | @@ -1220,20 +1203,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1220 | 1203 | const compile_error = try c.addNode(.{ |
| 1221 | 1204 | .tag = .builtin_call_two, |
| 1222 | 1205 | .main_token = compile_error_tok, |
| 1223 | .data = .{ | |
| 1224 | .lhs = err_msg, | |
| 1225 | .rhs = 0, | |
| 1226 | }, | |
| 1206 | .data = .{ .opt_node_and_opt_node = .{ err_msg.toOptional(), .none } }, | |
| 1227 | 1207 | }); |
| 1228 | 1208 | _ = try c.addToken(.semicolon, ";"); |
| 1229 | 1209 | |
| 1230 | 1210 | return c.addNode(.{ |
| 1231 | 1211 | .tag = .simple_var_decl, |
| 1232 | 1212 | .main_token = const_tok, |
| 1233 | .data = .{ | |
| 1234 | .lhs = 0, | |
| 1235 | .rhs = compile_error, | |
| 1236 | }, | |
| 1213 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1214 | .none, | |
| 1215 | compile_error.toOptional(), | |
| 1216 | } }, | |
| 1237 | 1217 | }); |
| 1238 | 1218 | }, |
| 1239 | 1219 | .pub_var_simple, .var_simple => { |
| ... | ... | @@ -1249,10 +1229,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1249 | 1229 | return c.addNode(.{ |
| 1250 | 1230 | .tag = .simple_var_decl, |
| 1251 | 1231 | .main_token = const_tok, |
| 1252 | .data = .{ | |
| 1253 | .lhs = 0, | |
| 1254 | .rhs = init, | |
| 1255 | }, | |
| 1232 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1233 | .none, | |
| 1234 | init.toOptional(), | |
| 1235 | } }, | |
| 1256 | 1236 | }); |
| 1257 | 1237 | }, |
| 1258 | 1238 | .static_local_var => { |
| ... | ... | @@ -1268,10 +1248,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1268 | 1248 | const container_def = try c.addNode(.{ |
| 1269 | 1249 | .tag = .container_decl_two_trailing, |
| 1270 | 1250 | .main_token = kind_tok, |
| 1271 | .data = .{ | |
| 1272 | .lhs = try renderNode(c, payload.init), | |
| 1273 | .rhs = 0, | |
| 1274 | }, | |
| 1251 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1252 | (try renderNode(c, payload.init)).toOptional(), | |
| 1253 | .none, | |
| 1254 | } }, | |
| 1275 | 1255 | }); |
| 1276 | 1256 | _ = try c.addToken(.r_brace, "}"); |
| 1277 | 1257 | _ = try c.addToken(.semicolon, ";"); |
| ... | ... | @@ -1279,10 +1259,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1279 | 1259 | return c.addNode(.{ |
| 1280 | 1260 | .tag = .simple_var_decl, |
| 1281 | 1261 | .main_token = const_tok, |
| 1282 | .data = .{ | |
| 1283 | .lhs = 0, | |
| 1284 | .rhs = container_def, | |
| 1285 | }, | |
| 1262 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1263 | .none, | |
| 1264 | container_def.toOptional(), | |
| 1265 | } }, | |
| 1286 | 1266 | }); |
| 1287 | 1267 | }, |
| 1288 | 1268 | .extern_local_var => { |
| ... | ... | @@ -1298,10 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1298 | 1278 | const container_def = try c.addNode(.{ |
| 1299 | 1279 | .tag = .container_decl_two_trailing, |
| 1300 | 1280 | .main_token = kind_tok, |
| 1301 | .data = .{ | |
| 1302 | .lhs = try renderNode(c, payload.init), | |
| 1303 | .rhs = 0, | |
| 1304 | }, | |
| 1281 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1282 | (try renderNode(c, payload.init)).toOptional(), | |
| 1283 | .none, | |
| 1284 | } }, | |
| 1305 | 1285 | }); |
| 1306 | 1286 | _ = try c.addToken(.r_brace, "}"); |
| 1307 | 1287 | _ = try c.addToken(.semicolon, ";"); |
| ... | ... | @@ -1309,10 +1289,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1309 | 1289 | return c.addNode(.{ |
| 1310 | 1290 | .tag = .simple_var_decl, |
| 1311 | 1291 | .main_token = const_tok, |
| 1312 | .data = .{ | |
| 1313 | .lhs = 0, | |
| 1314 | .rhs = container_def, | |
| 1315 | }, | |
| 1292 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1293 | .none, | |
| 1294 | container_def.toOptional(), | |
| 1295 | } }, | |
| 1316 | 1296 | }); |
| 1317 | 1297 | }, |
| 1318 | 1298 | .mut_str => { |
| ... | ... | @@ -1324,10 +1304,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1324 | 1304 | |
| 1325 | 1305 | const deref = try c.addNode(.{ |
| 1326 | 1306 | .tag = .deref, |
| 1327 | .data = .{ | |
| 1328 | .lhs = try renderNodeGrouped(c, payload.init), | |
| 1329 | .rhs = undefined, | |
| 1330 | }, | |
| 1307 | .data = .{ .node = try renderNodeGrouped(c, payload.init) }, | |
| 1331 | 1308 | .main_token = try c.addToken(.period_asterisk, ".*"), |
| 1332 | 1309 | }); |
| 1333 | 1310 | _ = try c.addToken(.semicolon, ";"); |
| ... | ... | @@ -1335,7 +1312,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1335 | 1312 | return c.addNode(.{ |
| 1336 | 1313 | .tag = .simple_var_decl, |
| 1337 | 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 | 1321 | .var_decl => return renderVar(c, node), |
| ... | ... | @@ -1359,10 +1339,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1359 | 1339 | return c.addNode(.{ |
| 1360 | 1340 | .tag = .simple_var_decl, |
| 1361 | 1341 | .main_token = mut_tok, |
| 1362 | .data = .{ | |
| 1363 | .lhs = 0, | |
| 1364 | .rhs = init, | |
| 1365 | }, | |
| 1342 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1343 | .none, | |
| 1344 | init.toOptional(), | |
| 1345 | } }, | |
| 1366 | 1346 | }); |
| 1367 | 1347 | }, |
| 1368 | 1348 | .int_cast => { |
| ... | ... | @@ -1505,10 +1485,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1505 | 1485 | return c.addNode(.{ |
| 1506 | 1486 | .tag = .address_of, |
| 1507 | 1487 | .main_token = ampersand, |
| 1508 | .data = .{ | |
| 1509 | .lhs = base, | |
| 1510 | .rhs = undefined, | |
| 1511 | }, | |
| 1488 | .data = .{ .node = base }, | |
| 1512 | 1489 | }); |
| 1513 | 1490 | }, |
| 1514 | 1491 | .deref => { |
| ... | ... | @@ -1518,10 +1495,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1518 | 1495 | return c.addNode(.{ |
| 1519 | 1496 | .tag = .deref, |
| 1520 | 1497 | .main_token = deref_tok, |
| 1521 | .data = .{ | |
| 1522 | .lhs = operand, | |
| 1523 | .rhs = undefined, | |
| 1524 | }, | |
| 1498 | .data = .{ .node = operand }, | |
| 1525 | 1499 | }); |
| 1526 | 1500 | }, |
| 1527 | 1501 | .unwrap => { |
| ... | ... | @@ -1532,10 +1506,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1532 | 1506 | return c.addNode(.{ |
| 1533 | 1507 | .tag = .unwrap_optional, |
| 1534 | 1508 | .main_token = period, |
| 1535 | .data = .{ | |
| 1536 | .lhs = operand, | |
| 1537 | .rhs = question_mark, | |
| 1538 | }, | |
| 1509 | .data = .{ .node_and_token = .{ | |
| 1510 | operand, | |
| 1511 | question_mark, | |
| 1512 | } }, | |
| 1539 | 1513 | }); |
| 1540 | 1514 | }, |
| 1541 | 1515 | .c_pointer, .single_pointer => { |
| ... | ... | @@ -1557,10 +1531,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1557 | 1531 | return c.addNode(.{ |
| 1558 | 1532 | .tag = .ptr_type_aligned, |
| 1559 | 1533 | .main_token = main_token, |
| 1560 | .data = .{ | |
| 1561 | .lhs = 0, | |
| 1562 | .rhs = elem_type, | |
| 1563 | }, | |
| 1534 | .data = .{ .opt_node_and_node = .{ | |
| 1535 | .none, | |
| 1536 | elem_type, | |
| 1537 | } }, | |
| 1564 | 1538 | }); |
| 1565 | 1539 | }, |
| 1566 | 1540 | .add => return renderBinOpGrouped(c, node, .add, .plus, "+"), |
| ... | ... | @@ -1606,10 +1580,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1606 | 1580 | return c.addNode(.{ |
| 1607 | 1581 | .tag = .block_two, |
| 1608 | 1582 | .main_token = l_brace, |
| 1609 | .data = .{ | |
| 1610 | .lhs = 0, | |
| 1611 | .rhs = 0, | |
| 1612 | }, | |
| 1583 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1584 | .none, | |
| 1585 | .none, | |
| 1586 | } }, | |
| 1613 | 1587 | }); |
| 1614 | 1588 | }, |
| 1615 | 1589 | .block_single => { |
| ... | ... | @@ -1623,10 +1597,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1623 | 1597 | return c.addNode(.{ |
| 1624 | 1598 | .tag = .block_two_semicolon, |
| 1625 | 1599 | .main_token = l_brace, |
| 1626 | .data = .{ | |
| 1627 | .lhs = stmt, | |
| 1628 | .rhs = 0, | |
| 1629 | }, | |
| 1600 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1601 | stmt.toOptional(), | |
| 1602 | .none, | |
| 1603 | } }, | |
| 1630 | 1604 | }); |
| 1631 | 1605 | }, |
| 1632 | 1606 | .block => { |
| ... | ... | @@ -1641,7 +1615,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1641 | 1615 | defer stmts.deinit(); |
| 1642 | 1616 | for (payload.stmts) |stmt| { |
| 1643 | 1617 | const res = try renderNode(c, stmt); |
| 1644 | if (res == 0) continue; | |
| 1618 | if (@intFromEnum(res) == 0) continue; | |
| 1645 | 1619 | try addSemicolonIfNeeded(c, stmt); |
| 1646 | 1620 | try stmts.append(res); |
| 1647 | 1621 | } |
| ... | ... | @@ -1652,17 +1626,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1652 | 1626 | return c.addNode(.{ |
| 1653 | 1627 | .tag = if (semicolon) .block_semicolon else .block, |
| 1654 | 1628 | .main_token = l_brace, |
| 1655 | .data = .{ | |
| 1656 | .lhs = span.start, | |
| 1657 | .rhs = span.end, | |
| 1658 | }, | |
| 1629 | .data = .{ .extra_range = span }, | |
| 1659 | 1630 | }); |
| 1660 | 1631 | }, |
| 1661 | 1632 | .func => return renderFunc(c, node), |
| 1662 | 1633 | .pub_inline_fn => return renderMacroFunc(c, node), |
| 1663 | 1634 | .discard => { |
| 1664 | 1635 | const payload = node.castTag(.discard).?.data; |
| 1665 | if (payload.should_skip) return @as(NodeIndex, 0); | |
| 1636 | if (payload.should_skip) return @enumFromInt(0); | |
| 1666 | 1637 | |
| 1667 | 1638 | const lhs = try c.addNode(.{ |
| 1668 | 1639 | .tag = .identifier, |
| ... | ... | @@ -1680,19 +1651,19 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1680 | 1651 | return c.addNode(.{ |
| 1681 | 1652 | .tag = .assign, |
| 1682 | 1653 | .main_token = main_token, |
| 1683 | .data = .{ | |
| 1684 | .lhs = lhs, | |
| 1685 | .rhs = try renderNode(c, addr_of), | |
| 1686 | }, | |
| 1654 | .data = .{ .node_and_node = .{ | |
| 1655 | lhs, | |
| 1656 | try renderNode(c, addr_of), | |
| 1657 | } }, | |
| 1687 | 1658 | }); |
| 1688 | 1659 | } else { |
| 1689 | 1660 | return c.addNode(.{ |
| 1690 | 1661 | .tag = .assign, |
| 1691 | 1662 | .main_token = main_token, |
| 1692 | .data = .{ | |
| 1693 | .lhs = lhs, | |
| 1694 | .rhs = try renderNode(c, payload.value), | |
| 1695 | }, | |
| 1663 | .data = .{ .node_and_node = .{ | |
| 1664 | lhs, | |
| 1665 | try renderNode(c, payload.value), | |
| 1666 | } }, | |
| 1696 | 1667 | }); |
| 1697 | 1668 | } |
| 1698 | 1669 | }, |
| ... | ... | @@ -1709,29 +1680,29 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1709 | 1680 | const res = try renderNode(c, some); |
| 1710 | 1681 | _ = try c.addToken(.r_paren, ")"); |
| 1711 | 1682 | break :blk res; |
| 1712 | } else 0; | |
| 1683 | } else null; | |
| 1713 | 1684 | const body = try renderNode(c, payload.body); |
| 1714 | 1685 | |
| 1715 | if (cont_expr == 0) { | |
| 1686 | if (cont_expr == null) { | |
| 1716 | 1687 | return c.addNode(.{ |
| 1717 | 1688 | .tag = .while_simple, |
| 1718 | 1689 | .main_token = while_tok, |
| 1719 | .data = .{ | |
| 1720 | .lhs = cond, | |
| 1721 | .rhs = body, | |
| 1722 | }, | |
| 1690 | .data = .{ .node_and_node = .{ | |
| 1691 | cond, | |
| 1692 | body, | |
| 1693 | } }, | |
| 1723 | 1694 | }); |
| 1724 | 1695 | } else { |
| 1725 | 1696 | return c.addNode(.{ |
| 1726 | 1697 | .tag = .while_cont, |
| 1727 | 1698 | .main_token = while_tok, |
| 1728 | .data = .{ | |
| 1729 | .lhs = cond, | |
| 1730 | .rhs = try c.addExtra(std.zig.Ast.Node.WhileCont{ | |
| 1731 | .cont_expr = cont_expr, | |
| 1699 | .data = .{ .node_and_extra = .{ | |
| 1700 | cond, | |
| 1701 | try c.addExtra(std.zig.Ast.Node.WhileCont{ | |
| 1702 | .cont_expr = cont_expr.?, | |
| 1732 | 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 | 1721 | return c.addNode(.{ |
| 1751 | 1722 | .tag = .while_simple, |
| 1752 | 1723 | .main_token = while_tok, |
| 1753 | .data = .{ | |
| 1754 | .lhs = cond, | |
| 1755 | .rhs = body, | |
| 1756 | }, | |
| 1724 | .data = .{ .node_and_node = .{ | |
| 1725 | cond, | |
| 1726 | body, | |
| 1727 | } }, | |
| 1757 | 1728 | }); |
| 1758 | 1729 | }, |
| 1759 | 1730 | .@"if" => { |
| ... | ... | @@ -1767,10 +1738,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1767 | 1738 | const else_node = payload.@"else" orelse return c.addNode(.{ |
| 1768 | 1739 | .tag = .if_simple, |
| 1769 | 1740 | .main_token = if_tok, |
| 1770 | .data = .{ | |
| 1771 | .lhs = cond, | |
| 1772 | .rhs = then_expr, | |
| 1773 | }, | |
| 1741 | .data = .{ .node_and_node = .{ | |
| 1742 | cond, | |
| 1743 | then_expr, | |
| 1744 | } }, | |
| 1774 | 1745 | }); |
| 1775 | 1746 | _ = try c.addToken(.keyword_else, "else"); |
| 1776 | 1747 | const else_expr = try renderNode(c, else_node); |
| ... | ... | @@ -1778,13 +1749,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1778 | 1749 | return c.addNode(.{ |
| 1779 | 1750 | .tag = .@"if", |
| 1780 | 1751 | .main_token = if_tok, |
| 1781 | .data = .{ | |
| 1782 | .lhs = cond, | |
| 1783 | .rhs = try c.addExtra(std.zig.Ast.Node.If{ | |
| 1752 | .data = .{ .node_and_extra = .{ | |
| 1753 | cond, | |
| 1754 | try c.addExtra(std.zig.Ast.Node.If{ | |
| 1784 | 1755 | .then_expr = then_expr, |
| 1785 | 1756 | .else_expr = else_expr, |
| 1786 | 1757 | }), |
| 1787 | }, | |
| 1758 | } }, | |
| 1788 | 1759 | }); |
| 1789 | 1760 | }, |
| 1790 | 1761 | .if_not_break => { |
| ... | ... | @@ -1794,28 +1765,25 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1794 | 1765 | const cond = try c.addNode(.{ |
| 1795 | 1766 | .tag = .bool_not, |
| 1796 | 1767 | .main_token = try c.addToken(.bang, "!"), |
| 1797 | .data = .{ | |
| 1798 | .lhs = try renderNodeGrouped(c, payload), | |
| 1799 | .rhs = undefined, | |
| 1800 | }, | |
| 1768 | .data = .{ .node = try renderNodeGrouped(c, payload) }, | |
| 1801 | 1769 | }); |
| 1802 | 1770 | _ = try c.addToken(.r_paren, ")"); |
| 1803 | 1771 | const then_expr = try c.addNode(.{ |
| 1804 | 1772 | .tag = .@"break", |
| 1805 | 1773 | .main_token = try c.addToken(.keyword_break, "break"), |
| 1806 | .data = .{ | |
| 1807 | .lhs = 0, | |
| 1808 | .rhs = 0, | |
| 1809 | }, | |
| 1774 | .data = .{ .opt_token_and_opt_node = .{ | |
| 1775 | .none, | |
| 1776 | .none, | |
| 1777 | } }, | |
| 1810 | 1778 | }); |
| 1811 | 1779 | |
| 1812 | 1780 | return c.addNode(.{ |
| 1813 | 1781 | .tag = .if_simple, |
| 1814 | 1782 | .main_token = if_tok, |
| 1815 | .data = .{ | |
| 1816 | .lhs = cond, | |
| 1817 | .rhs = then_expr, | |
| 1818 | }, | |
| 1783 | .data = .{ .node_and_node = .{ | |
| 1784 | cond, | |
| 1785 | then_expr, | |
| 1786 | } }, | |
| 1819 | 1787 | }); |
| 1820 | 1788 | }, |
| 1821 | 1789 | .@"switch" => { |
| ... | ... | @@ -1837,13 +1805,12 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1837 | 1805 | return c.addNode(.{ |
| 1838 | 1806 | .tag = .switch_comma, |
| 1839 | 1807 | .main_token = switch_tok, |
| 1840 | .data = .{ | |
| 1841 | .lhs = cond, | |
| 1842 | .rhs = try c.addExtra(NodeSubRange{ | |
| 1808 | .data = .{ .node_and_extra = .{ | |
| 1809 | cond, try c.addExtra(NodeSubRange{ | |
| 1843 | 1810 | .start = span.start, |
| 1844 | 1811 | .end = span.end, |
| 1845 | 1812 | }), |
| 1846 | }, | |
| 1813 | } }, | |
| 1847 | 1814 | }); |
| 1848 | 1815 | }, |
| 1849 | 1816 | .switch_else => { |
| ... | ... | @@ -1852,43 +1819,42 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1852 | 1819 | return c.addNode(.{ |
| 1853 | 1820 | .tag = .switch_case_one, |
| 1854 | 1821 | .main_token = try c.addToken(.equal_angle_bracket_right, "=>"), |
| 1855 | .data = .{ | |
| 1856 | .lhs = 0, | |
| 1857 | .rhs = try renderNode(c, payload), | |
| 1858 | }, | |
| 1822 | .data = .{ .opt_node_and_node = .{ | |
| 1823 | .none, | |
| 1824 | try renderNode(c, payload), | |
| 1825 | } }, | |
| 1859 | 1826 | }); |
| 1860 | 1827 | }, |
| 1861 | 1828 | .switch_prong => { |
| 1862 | 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 | 1831 | defer c.gpa.free(items); |
| 1865 | items[0] = 0; | |
| 1866 | for (payload.cases, 0..) |item, i| { | |
| 1832 | for (payload.cases, items, 0..) |case, *item, i| { | |
| 1867 | 1833 | if (i != 0) _ = try c.addToken(.comma, ","); |
| 1868 | items[i] = try renderNode(c, item); | |
| 1834 | item.* = try renderNode(c, case); | |
| 1869 | 1835 | } |
| 1870 | 1836 | _ = try c.addToken(.r_brace, "}"); |
| 1871 | 1837 | if (items.len < 2) { |
| 1872 | 1838 | return c.addNode(.{ |
| 1873 | 1839 | .tag = .switch_case_one, |
| 1874 | 1840 | .main_token = try c.addToken(.equal_angle_bracket_right, "=>"), |
| 1875 | .data = .{ | |
| 1876 | .lhs = items[0], | |
| 1877 | .rhs = try renderNode(c, payload.cond), | |
| 1878 | }, | |
| 1841 | .data = .{ .opt_node_and_node = .{ | |
| 1842 | if (items.len == 0) .none else items[0].toOptional(), | |
| 1843 | try renderNode(c, payload.cond), | |
| 1844 | } }, | |
| 1879 | 1845 | }); |
| 1880 | 1846 | } else { |
| 1881 | 1847 | const span = try c.listToSpan(items); |
| 1882 | 1848 | return c.addNode(.{ |
| 1883 | 1849 | .tag = .switch_case, |
| 1884 | 1850 | .main_token = try c.addToken(.equal_angle_bracket_right, "=>"), |
| 1885 | .data = .{ | |
| 1886 | .lhs = try c.addExtra(NodeSubRange{ | |
| 1851 | .data = .{ .extra_and_node = .{ | |
| 1852 | try c.addExtra(NodeSubRange{ | |
| 1887 | 1853 | .start = span.start, |
| 1888 | 1854 | .end = span.end, |
| 1889 | 1855 | }), |
| 1890 | .rhs = try renderNode(c, payload.cond), | |
| 1891 | }, | |
| 1856 | try renderNode(c, payload.cond), | |
| 1857 | } }, | |
| 1892 | 1858 | }); |
| 1893 | 1859 | } |
| 1894 | 1860 | }, |
| ... | ... | @@ -1900,10 +1866,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1900 | 1866 | return c.addNode(.{ |
| 1901 | 1867 | .tag = .container_decl_two, |
| 1902 | 1868 | .main_token = opaque_tok, |
| 1903 | .data = .{ | |
| 1904 | .lhs = 0, | |
| 1905 | .rhs = 0, | |
| 1906 | }, | |
| 1869 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1870 | .none, | |
| 1871 | .none, | |
| 1872 | } }, | |
| 1907 | 1873 | }); |
| 1908 | 1874 | }, |
| 1909 | 1875 | .array_access => { |
| ... | ... | @@ -1915,10 +1881,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1915 | 1881 | return c.addNode(.{ |
| 1916 | 1882 | .tag = .array_access, |
| 1917 | 1883 | .main_token = l_bracket, |
| 1918 | .data = .{ | |
| 1919 | .lhs = lhs, | |
| 1920 | .rhs = index_expr, | |
| 1921 | }, | |
| 1884 | .data = .{ .node_and_node = .{ | |
| 1885 | lhs, | |
| 1886 | index_expr, | |
| 1887 | } }, | |
| 1922 | 1888 | }); |
| 1923 | 1889 | }, |
| 1924 | 1890 | .array_type => { |
| ... | ... | @@ -1940,22 +1906,22 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1940 | 1906 | const init = try c.addNode(.{ |
| 1941 | 1907 | .tag = .array_init_one, |
| 1942 | 1908 | .main_token = l_brace, |
| 1943 | .data = .{ | |
| 1944 | .lhs = type_expr, | |
| 1945 | .rhs = val, | |
| 1946 | }, | |
| 1909 | .data = .{ .node_and_node = .{ | |
| 1910 | type_expr, | |
| 1911 | val, | |
| 1912 | } }, | |
| 1947 | 1913 | }); |
| 1948 | 1914 | return c.addNode(.{ |
| 1949 | 1915 | .tag = .array_cat, |
| 1950 | 1916 | .main_token = try c.addToken(.asterisk_asterisk, "**"), |
| 1951 | .data = .{ | |
| 1952 | .lhs = init, | |
| 1953 | .rhs = try c.addNode(.{ | |
| 1917 | .data = .{ .node_and_node = .{ | |
| 1918 | init, | |
| 1919 | try c.addNode(.{ | |
| 1954 | 1920 | .tag = .number_literal, |
| 1955 | 1921 | .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.count}), |
| 1956 | 1922 | .data = undefined, |
| 1957 | 1923 | }), |
| 1958 | }, | |
| 1924 | } }, | |
| 1959 | 1925 | }); |
| 1960 | 1926 | }, |
| 1961 | 1927 | .empty_array => { |
| ... | ... | @@ -1989,7 +1955,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1989 | 1955 | const type_node = if (payload.type) |enum_const_type| blk: { |
| 1990 | 1956 | _ = try c.addToken(.colon, ":"); |
| 1991 | 1957 | break :blk try renderNode(c, enum_const_type); |
| 1992 | } else 0; | |
| 1958 | } else null; | |
| 1993 | 1959 | |
| 1994 | 1960 | _ = try c.addToken(.equal, "="); |
| 1995 | 1961 | |
| ... | ... | @@ -1999,20 +1965,18 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 1999 | 1965 | return c.addNode(.{ |
| 2000 | 1966 | .tag = .simple_var_decl, |
| 2001 | 1967 | .main_token = const_tok, |
| 2002 | .data = .{ | |
| 2003 | .lhs = type_node, | |
| 2004 | .rhs = init_node, | |
| 2005 | }, | |
| 1968 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1969 | .fromOptional(type_node), | |
| 1970 | init_node.toOptional(), | |
| 1971 | } }, | |
| 2006 | 1972 | }); |
| 2007 | 1973 | }, |
| 2008 | 1974 | .tuple => { |
| 2009 | 1975 | const payload = node.castTag(.tuple).?.data; |
| 2010 | 1976 | _ = try c.addToken(.period, "."); |
| 2011 | 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 | 1979 | defer c.gpa.free(inits); |
| 2014 | inits[0] = 0; | |
| 2015 | inits[1] = 0; | |
| 2016 | 1980 | for (payload, 0..) |init, i| { |
| 2017 | 1981 | if (i != 0) _ = try c.addToken(.comma, ","); |
| 2018 | 1982 | inits[i] = try renderNode(c, init); |
| ... | ... | @@ -2022,20 +1986,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2022 | 1986 | return c.addNode(.{ |
| 2023 | 1987 | .tag = .array_init_dot_two, |
| 2024 | 1988 | .main_token = l_brace, |
| 2025 | .data = .{ | |
| 2026 | .lhs = inits[0], | |
| 2027 | .rhs = inits[1], | |
| 2028 | }, | |
| 1989 | .data = .{ .opt_node_and_opt_node = .{ | |
| 1990 | if (inits.len < 1) .none else inits[0].toOptional(), | |
| 1991 | if (inits.len < 2) .none else inits[1].toOptional(), | |
| 1992 | } }, | |
| 2029 | 1993 | }); |
| 2030 | 1994 | } else { |
| 2031 | 1995 | const span = try c.listToSpan(inits); |
| 2032 | 1996 | return c.addNode(.{ |
| 2033 | 1997 | .tag = .array_init_dot, |
| 2034 | 1998 | .main_token = l_brace, |
| 2035 | .data = .{ | |
| 2036 | .lhs = span.start, | |
| 2037 | .rhs = span.end, | |
| 2038 | }, | |
| 1999 | .data = .{ .extra_range = span }, | |
| 2039 | 2000 | }); |
| 2040 | 2001 | } |
| 2041 | 2002 | }, |
| ... | ... | @@ -2043,10 +2004,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2043 | 2004 | const payload = node.castTag(.container_init_dot).?.data; |
| 2044 | 2005 | _ = try c.addToken(.period, "."); |
| 2045 | 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 | 2008 | defer c.gpa.free(inits); |
| 2048 | inits[0] = 0; | |
| 2049 | inits[1] = 0; | |
| 2050 | 2009 | for (payload, 0..) |init, i| { |
| 2051 | 2010 | _ = try c.addToken(.period, "."); |
| 2052 | 2011 | _ = try c.addIdentifier(init.name); |
| ... | ... | @@ -2060,20 +2019,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2060 | 2019 | return c.addNode(.{ |
| 2061 | 2020 | .tag = .struct_init_dot_two_comma, |
| 2062 | 2021 | .main_token = l_brace, |
| 2063 | .data = .{ | |
| 2064 | .lhs = inits[0], | |
| 2065 | .rhs = inits[1], | |
| 2066 | }, | |
| 2022 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2023 | if (inits.len < 1) .none else inits[0].toOptional(), | |
| 2024 | if (inits.len < 2) .none else inits[1].toOptional(), | |
| 2025 | } }, | |
| 2067 | 2026 | }); |
| 2068 | 2027 | } else { |
| 2069 | 2028 | const span = try c.listToSpan(inits); |
| 2070 | 2029 | return c.addNode(.{ |
| 2071 | 2030 | .tag = .struct_init_dot_comma, |
| 2072 | 2031 | .main_token = l_brace, |
| 2073 | .data = .{ | |
| 2074 | .lhs = span.start, | |
| 2075 | .rhs = span.end, | |
| 2076 | }, | |
| 2032 | .data = .{ .extra_range = span }, | |
| 2077 | 2033 | }); |
| 2078 | 2034 | } |
| 2079 | 2035 | }, |
| ... | ... | @@ -2082,9 +2038,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2082 | 2038 | const lhs = try renderNode(c, payload.lhs); |
| 2083 | 2039 | |
| 2084 | 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 | 2042 | defer c.gpa.free(inits); |
| 2087 | inits[0] = 0; | |
| 2088 | 2043 | for (payload.inits, 0..) |init, i| { |
| 2089 | 2044 | _ = try c.addToken(.period, "."); |
| 2090 | 2045 | _ = try c.addIdentifier(init.name); |
| ... | ... | @@ -2098,31 +2053,30 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 2098 | 2053 | 0 => c.addNode(.{ |
| 2099 | 2054 | .tag = .struct_init_one, |
| 2100 | 2055 | .main_token = l_brace, |
| 2101 | .data = .{ | |
| 2102 | .lhs = lhs, | |
| 2103 | .rhs = 0, | |
| 2104 | }, | |
| 2056 | .data = .{ .node_and_opt_node = .{ | |
| 2057 | lhs, | |
| 2058 | .none, | |
| 2059 | } }, | |
| 2105 | 2060 | }), |
| 2106 | 2061 | 1 => c.addNode(.{ |
| 2107 | 2062 | .tag = .struct_init_one_comma, |
| 2108 | 2063 | .main_token = l_brace, |
| 2109 | .data = .{ | |
| 2110 | .lhs = lhs, | |
| 2111 | .rhs = inits[0], | |
| 2112 | }, | |
| 2064 | .data = .{ .node_and_opt_node = .{ | |
| 2065 | lhs, | |
| 2066 | inits[0].toOptional(), | |
| 2067 | } }, | |
| 2113 | 2068 | }), |
| 2114 | 2069 | else => blk: { |
| 2115 | 2070 | const span = try c.listToSpan(inits); |
| 2116 | 2071 | break :blk c.addNode(.{ |
| 2117 | 2072 | .tag = .struct_init_comma, |
| 2118 | 2073 | .main_token = l_brace, |
| 2119 | .data = .{ | |
| 2120 | .lhs = lhs, | |
| 2121 | .rhs = try c.addExtra(NodeSubRange{ | |
| 2074 | .data = .{ .node_and_extra = .{ | |
| 2075 | lhs, try c.addExtra(NodeSubRange{ | |
| 2122 | 2076 | .start = span.start, |
| 2123 | 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 | 2101 | const num_vars = payload.variables.len; |
| 2148 | 2102 | const num_funcs = payload.functions.len; |
| 2149 | 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 | 2105 | defer c.gpa.free(members); |
| 2152 | members[0] = 0; | |
| 2153 | members[1] = 0; | |
| 2154 | 2106 | |
| 2155 | 2107 | for (payload.fields, 0..) |field, i| { |
| 2156 | 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 | 2119 | }); |
| 2168 | 2120 | _ = try c.addToken(.r_paren, ")"); |
| 2169 | 2121 | break :blk align_expr; |
| 2170 | } else 0; | |
| 2122 | } else null; | |
| 2171 | 2123 | |
| 2172 | 2124 | const value_expr = if (field.default_value) |value| blk: { |
| 2173 | 2125 | _ = try c.addToken(.equal, "="); |
| 2174 | 2126 | break :blk try renderNode(c, value); |
| 2175 | } else 0; | |
| 2127 | } else null; | |
| 2176 | 2128 | |
| 2177 | members[i] = try c.addNode(if (align_expr == 0) .{ | |
| 2129 | members[i] = try c.addNode(if (align_expr == null) .{ | |
| 2178 | 2130 | .tag = .container_field_init, |
| 2179 | 2131 | .main_token = name_tok, |
| 2180 | .data = .{ | |
| 2181 | .lhs = type_expr, | |
| 2182 | .rhs = value_expr, | |
| 2183 | }, | |
| 2184 | } else if (value_expr == 0) .{ | |
| 2132 | .data = .{ .node_and_opt_node = .{ | |
| 2133 | type_expr, | |
| 2134 | .fromOptional(value_expr), | |
| 2135 | } }, | |
| 2136 | } else if (value_expr == null) .{ | |
| 2185 | 2137 | .tag = .container_field_align, |
| 2186 | 2138 | .main_token = name_tok, |
| 2187 | .data = .{ | |
| 2188 | .lhs = type_expr, | |
| 2189 | .rhs = align_expr, | |
| 2190 | }, | |
| 2139 | .data = .{ .node_and_node = .{ | |
| 2140 | type_expr, | |
| 2141 | align_expr.?, | |
| 2142 | } }, | |
| 2191 | 2143 | } else .{ |
| 2192 | 2144 | .tag = .container_field, |
| 2193 | 2145 | .main_token = name_tok, |
| 2194 | .data = .{ | |
| 2195 | .lhs = type_expr, | |
| 2196 | .rhs = try c.addExtra(std.zig.Ast.Node.ContainerField{ | |
| 2197 | .align_expr = align_expr, | |
| 2198 | .value_expr = value_expr, | |
| 2146 | .data = .{ .node_and_extra = .{ | |
| 2147 | type_expr, try c.addExtra(std.zig.Ast.Node.ContainerField{ | |
| 2148 | .align_expr = align_expr.?, | |
| 2149 | .value_expr = value_expr.?, | |
| 2199 | 2150 | }), |
| 2200 | }, | |
| 2151 | } }, | |
| 2201 | 2152 | }); |
| 2202 | 2153 | _ = try c.addToken(.comma, ","); |
| 2203 | 2154 | } |
| ... | ... | @@ -2213,29 +2164,26 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex { |
| 2213 | 2164 | return c.addNode(.{ |
| 2214 | 2165 | .tag = .container_decl_two, |
| 2215 | 2166 | .main_token = kind_tok, |
| 2216 | .data = .{ | |
| 2217 | .lhs = 0, | |
| 2218 | .rhs = 0, | |
| 2219 | }, | |
| 2167 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2168 | .none, | |
| 2169 | .none, | |
| 2170 | } }, | |
| 2220 | 2171 | }); |
| 2221 | 2172 | } else if (total_members <= 2) { |
| 2222 | 2173 | return c.addNode(.{ |
| 2223 | 2174 | .tag = if (num_funcs == 0) .container_decl_two_trailing else .container_decl_two, |
| 2224 | 2175 | .main_token = kind_tok, |
| 2225 | .data = .{ | |
| 2226 | .lhs = members[0], | |
| 2227 | .rhs = members[1], | |
| 2228 | }, | |
| 2176 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2177 | if (members.len < 1) .none else members[0].toOptional(), | |
| 2178 | if (members.len < 2) .none else members[1].toOptional(), | |
| 2179 | } }, | |
| 2229 | 2180 | }); |
| 2230 | 2181 | } else { |
| 2231 | 2182 | const span = try c.listToSpan(members); |
| 2232 | 2183 | return c.addNode(.{ |
| 2233 | 2184 | .tag = if (num_funcs == 0) .container_decl_trailing else .container_decl, |
| 2234 | 2185 | .main_token = kind_tok, |
| 2235 | .data = .{ | |
| 2236 | .lhs = span.start, | |
| 2237 | .rhs = span.end, | |
| 2238 | }, | |
| 2186 | .data = .{ .extra_range = span }, | |
| 2239 | 2187 | }); |
| 2240 | 2188 | } |
| 2241 | 2189 | } |
| ... | ... | @@ -2244,45 +2192,52 @@ fn renderFieldAccess(c: *Context, lhs: NodeIndex, field_name: []const u8) !NodeI |
| 2244 | 2192 | return c.addNode(.{ |
| 2245 | 2193 | .tag = .field_access, |
| 2246 | 2194 | .main_token = try c.addToken(.period, "."), |
| 2247 | .data = .{ | |
| 2248 | .lhs = lhs, | |
| 2249 | .rhs = try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}), | |
| 2250 | }, | |
| 2195 | .data = .{ .node_and_token = .{ | |
| 2196 | lhs, | |
| 2197 | try c.addTokenFmt(.identifier, "{p}", .{std.zig.fmtId(field_name)}), | |
| 2198 | } }, | |
| 2251 | 2199 | }); |
| 2252 | 2200 | } |
| 2253 | 2201 | |
| 2254 | 2202 | fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex { |
| 2255 | 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 | 2205 | defer c.gpa.free(rendered); |
| 2258 | rendered[0] = 0; | |
| 2259 | 2206 | for (inits, 0..) |init, i| { |
| 2260 | 2207 | rendered[i] = try renderNode(c, init); |
| 2261 | 2208 | _ = try c.addToken(.comma, ","); |
| 2262 | 2209 | } |
| 2263 | 2210 | _ = try c.addToken(.r_brace, "}"); |
| 2264 | if (inits.len < 2) { | |
| 2265 | return c.addNode(.{ | |
| 2266 | .tag = .array_init_one_comma, | |
| 2211 | switch (inits.len) { | |
| 2212 | 0 => return c.addNode(.{ | |
| 2213 | .tag = .struct_init_one, | |
| 2267 | 2214 | .main_token = l_brace, |
| 2268 | .data = .{ | |
| 2269 | .lhs = lhs, | |
| 2270 | .rhs = rendered[0], | |
| 2271 | }, | |
| 2272 | }); | |
| 2273 | } else { | |
| 2274 | const span = try c.listToSpan(rendered); | |
| 2275 | return c.addNode(.{ | |
| 2276 | .tag = .array_init_comma, | |
| 2215 | .data = .{ .node_and_opt_node = .{ | |
| 2216 | lhs, | |
| 2217 | .none, | |
| 2218 | } }, | |
| 2219 | }), | |
| 2220 | 1 => return c.addNode(.{ | |
| 2221 | .tag = .array_init_one_comma, | |
| 2277 | 2222 | .main_token = l_brace, |
| 2278 | .data = .{ | |
| 2279 | .lhs = lhs, | |
| 2280 | .rhs = try c.addExtra(NodeSubRange{ | |
| 2281 | .start = span.start, | |
| 2282 | .end = span.end, | |
| 2283 | }), | |
| 2284 | }, | |
| 2285 | }); | |
| 2223 | .data = .{ .node_and_node = .{ | |
| 2224 | lhs, | |
| 2225 | rendered[0], | |
| 2226 | } }, | |
| 2227 | }), | |
| 2228 | else => { | |
| 2229 | const span = try c.listToSpan(rendered); | |
| 2230 | return c.addNode(.{ | |
| 2231 | .tag = .array_init_comma, | |
| 2232 | .main_token = l_brace, | |
| 2233 | .data = .{ .node_and_extra = .{ | |
| 2234 | lhs, try c.addExtra(NodeSubRange{ | |
| 2235 | .start = span.start, | |
| 2236 | .end = span.end, | |
| 2237 | }), | |
| 2238 | } }, | |
| 2239 | }); | |
| 2240 | }, | |
| 2286 | 2241 | } |
| 2287 | 2242 | } |
| 2288 | 2243 | |
| ... | ... | @@ -2298,10 +2253,10 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex { |
| 2298 | 2253 | return c.addNode(.{ |
| 2299 | 2254 | .tag = .array_type, |
| 2300 | 2255 | .main_token = l_bracket, |
| 2301 | .data = .{ | |
| 2302 | .lhs = len_expr, | |
| 2303 | .rhs = elem_type_expr, | |
| 2304 | }, | |
| 2256 | .data = .{ .node_and_node = .{ | |
| 2257 | len_expr, | |
| 2258 | elem_type_expr, | |
| 2259 | } }, | |
| 2305 | 2260 | }); |
| 2306 | 2261 | } |
| 2307 | 2262 | |
| ... | ... | @@ -2325,13 +2280,13 @@ fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIn |
| 2325 | 2280 | return c.addNode(.{ |
| 2326 | 2281 | .tag = .array_type_sentinel, |
| 2327 | 2282 | .main_token = l_bracket, |
| 2328 | .data = .{ | |
| 2329 | .lhs = len_expr, | |
| 2330 | .rhs = try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{ | |
| 2283 | .data = .{ .node_and_extra = .{ | |
| 2284 | len_expr, | |
| 2285 | try c.addExtra(std.zig.Ast.Node.ArrayTypeSentinel{ | |
| 2331 | 2286 | .sentinel = sentinel_expr, |
| 2332 | 2287 | .elem_type = elem_type_expr, |
| 2333 | 2288 | }), |
| 2334 | }, | |
| 2289 | } }, | |
| 2335 | 2290 | }); |
| 2336 | 2291 | } |
| 2337 | 2292 | |
| ... | ... | @@ -2482,10 +2437,10 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2482 | 2437 | => return c.addNode(.{ |
| 2483 | 2438 | .tag = .grouped_expression, |
| 2484 | 2439 | .main_token = try c.addToken(.l_paren, "("), |
| 2485 | .data = .{ | |
| 2486 | .lhs = try renderNode(c, node), | |
| 2487 | .rhs = try c.addToken(.r_paren, ")"), | |
| 2488 | }, | |
| 2440 | .data = .{ .node_and_token = .{ | |
| 2441 | try renderNode(c, node), | |
| 2442 | try c.addToken(.r_paren, ")"), | |
| 2443 | } }, | |
| 2489 | 2444 | }), |
| 2490 | 2445 | .ellipsis3, |
| 2491 | 2446 | .switch_prong, |
| ... | ... | @@ -2539,10 +2494,7 @@ fn renderPrefixOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: T |
| 2539 | 2494 | return c.addNode(.{ |
| 2540 | 2495 | .tag = tag, |
| 2541 | 2496 | .main_token = try c.addToken(tok_tag, bytes), |
| 2542 | .data = .{ | |
| 2543 | .lhs = try renderNodeGrouped(c, payload), | |
| 2544 | .rhs = undefined, | |
| 2545 | }, | |
| 2497 | .data = .{ .node = try renderNodeGrouped(c, payload) }, | |
| 2546 | 2498 | }); |
| 2547 | 2499 | } |
| 2548 | 2500 | |
| ... | ... | @@ -2552,10 +2504,10 @@ fn renderBinOpGrouped(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_ta |
| 2552 | 2504 | return c.addNode(.{ |
| 2553 | 2505 | .tag = tag, |
| 2554 | 2506 | .main_token = try c.addToken(tok_tag, bytes), |
| 2555 | .data = .{ | |
| 2556 | .lhs = lhs, | |
| 2557 | .rhs = try renderNodeGrouped(c, payload.rhs), | |
| 2558 | }, | |
| 2507 | .data = .{ .node_and_node = .{ | |
| 2508 | lhs, | |
| 2509 | try renderNodeGrouped(c, payload.rhs), | |
| 2510 | } }, | |
| 2559 | 2511 | }); |
| 2560 | 2512 | } |
| 2561 | 2513 | |
| ... | ... | @@ -2565,10 +2517,10 @@ fn renderBinOp(c: *Context, node: Node, tag: std.zig.Ast.Node.Tag, tok_tag: Toke |
| 2565 | 2517 | return c.addNode(.{ |
| 2566 | 2518 | .tag = tag, |
| 2567 | 2519 | .main_token = try c.addToken(tok_tag, bytes), |
| 2568 | .data = .{ | |
| 2569 | .lhs = lhs, | |
| 2570 | .rhs = try renderNode(c, payload.rhs), | |
| 2571 | }, | |
| 2520 | .data = .{ .node_and_node = .{ | |
| 2521 | lhs, | |
| 2522 | try renderNode(c, payload.rhs), | |
| 2523 | } }, | |
| 2572 | 2524 | }); |
| 2573 | 2525 | } |
| 2574 | 2526 | |
| ... | ... | @@ -2586,10 +2538,7 @@ fn renderStdImport(c: *Context, parts: []const []const u8) !NodeIndex { |
| 2586 | 2538 | const import_node = try c.addNode(.{ |
| 2587 | 2539 | .tag = .builtin_call_two, |
| 2588 | 2540 | .main_token = import_tok, |
| 2589 | .data = .{ | |
| 2590 | .lhs = std_node, | |
| 2591 | .rhs = 0, | |
| 2592 | }, | |
| 2541 | .data = .{ .opt_node_and_opt_node = .{ std_node.toOptional(), .none } }, | |
| 2593 | 2542 | }); |
| 2594 | 2543 | |
| 2595 | 2544 | var access_chain = import_node; |
| ... | ... | @@ -2605,20 +2554,14 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex { |
| 2605 | 2554 | 0 => try c.addNode(.{ |
| 2606 | 2555 | .tag = .call_one, |
| 2607 | 2556 | .main_token = lparen, |
| 2608 | .data = .{ | |
| 2609 | .lhs = lhs, | |
| 2610 | .rhs = 0, | |
| 2611 | }, | |
| 2557 | .data = .{ .node_and_opt_node = .{ lhs, .none } }, | |
| 2612 | 2558 | }), |
| 2613 | 2559 | 1 => blk: { |
| 2614 | 2560 | const arg = try renderNode(c, args[0]); |
| 2615 | 2561 | break :blk try c.addNode(.{ |
| 2616 | 2562 | .tag = .call_one, |
| 2617 | 2563 | .main_token = lparen, |
| 2618 | .data = .{ | |
| 2619 | .lhs = lhs, | |
| 2620 | .rhs = arg, | |
| 2621 | }, | |
| 2564 | .data = .{ .node_and_opt_node = .{ lhs, arg.toOptional() } }, | |
| 2622 | 2565 | }); |
| 2623 | 2566 | }, |
| 2624 | 2567 | else => blk: { |
| ... | ... | @@ -2633,13 +2576,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex { |
| 2633 | 2576 | break :blk try c.addNode(.{ |
| 2634 | 2577 | .tag = .call, |
| 2635 | 2578 | .main_token = lparen, |
| 2636 | .data = .{ | |
| 2637 | .lhs = lhs, | |
| 2638 | .rhs = try c.addExtra(NodeSubRange{ | |
| 2639 | .start = span.start, | |
| 2640 | .end = span.end, | |
| 2641 | }), | |
| 2642 | }, | |
| 2579 | .data = .{ .node_and_extra = .{ | |
| 2580 | lhs, | |
| 2581 | try c.addExtra(NodeSubRange{ .start = span.start, .end = span.end }), | |
| 2582 | } }, | |
| 2643 | 2583 | }); |
| 2644 | 2584 | }, |
| 2645 | 2585 | }; |
| ... | ... | @@ -2650,10 +2590,10 @@ fn renderCall(c: *Context, lhs: NodeIndex, args: []const Node) !NodeIndex { |
| 2650 | 2590 | fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !NodeIndex { |
| 2651 | 2591 | const builtin_tok = try c.addToken(.builtin, builtin); |
| 2652 | 2592 | _ = try c.addToken(.l_paren, "("); |
| 2653 | var arg_1: NodeIndex = 0; | |
| 2654 | var arg_2: NodeIndex = 0; | |
| 2655 | var arg_3: NodeIndex = 0; | |
| 2656 | var arg_4: NodeIndex = 0; | |
| 2593 | var arg_1: NodeIndex = undefined; | |
| 2594 | var arg_2: NodeIndex = undefined; | |
| 2595 | var arg_3: NodeIndex = undefined; | |
| 2596 | var arg_4: NodeIndex = undefined; | |
| 2657 | 2597 | switch (args.len) { |
| 2658 | 2598 | 0 => {}, |
| 2659 | 2599 | 1 => { |
| ... | ... | @@ -2681,10 +2621,10 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node |
| 2681 | 2621 | return c.addNode(.{ |
| 2682 | 2622 | .tag = .builtin_call_two, |
| 2683 | 2623 | .main_token = builtin_tok, |
| 2684 | .data = .{ | |
| 2685 | .lhs = arg_1, | |
| 2686 | .rhs = arg_2, | |
| 2687 | }, | |
| 2624 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2625 | if (args.len < 1) .none else arg_1.toOptional(), | |
| 2626 | if (args.len < 2) .none else arg_2.toOptional(), | |
| 2627 | } }, | |
| 2688 | 2628 | }); |
| 2689 | 2629 | } else { |
| 2690 | 2630 | std.debug.assert(args.len == 4); |
| ... | ... | @@ -2693,10 +2633,7 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node |
| 2693 | 2633 | return c.addNode(.{ |
| 2694 | 2634 | .tag = .builtin_call, |
| 2695 | 2635 | .main_token = builtin_tok, |
| 2696 | .data = .{ | |
| 2697 | .lhs = params.start, | |
| 2698 | .rhs = params.end, | |
| 2699 | }, | |
| 2636 | .data = .{ .extra_range = params }, | |
| 2700 | 2637 | }); |
| 2701 | 2638 | } |
| 2702 | 2639 | } |
| ... | ... | @@ -2725,7 +2662,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex { |
| 2725 | 2662 | }); |
| 2726 | 2663 | _ = try c.addToken(.r_paren, ")"); |
| 2727 | 2664 | break :blk res; |
| 2728 | } else 0; | |
| 2665 | } else null; | |
| 2729 | 2666 | |
| 2730 | 2667 | const section_node = if (payload.linksection_string) |some| blk: { |
| 2731 | 2668 | _ = try c.addToken(.keyword_linksection, "linksection"); |
| ... | ... | @@ -2737,50 +2674,50 @@ fn renderVar(c: *Context, node: Node) !NodeIndex { |
| 2737 | 2674 | }); |
| 2738 | 2675 | _ = try c.addToken(.r_paren, ")"); |
| 2739 | 2676 | break :blk res; |
| 2740 | } else 0; | |
| 2677 | } else null; | |
| 2741 | 2678 | |
| 2742 | 2679 | const init_node = if (payload.init) |some| blk: { |
| 2743 | 2680 | _ = try c.addToken(.equal, "="); |
| 2744 | 2681 | break :blk try renderNode(c, some); |
| 2745 | } else 0; | |
| 2682 | } else null; | |
| 2746 | 2683 | _ = try c.addToken(.semicolon, ";"); |
| 2747 | 2684 | |
| 2748 | if (section_node == 0) { | |
| 2749 | if (align_node == 0) { | |
| 2685 | if (section_node == null) { | |
| 2686 | if (align_node == null) { | |
| 2750 | 2687 | return c.addNode(.{ |
| 2751 | 2688 | .tag = .simple_var_decl, |
| 2752 | 2689 | .main_token = mut_tok, |
| 2753 | .data = .{ | |
| 2754 | .lhs = type_node, | |
| 2755 | .rhs = init_node, | |
| 2756 | }, | |
| 2690 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2691 | type_node.toOptional(), | |
| 2692 | .fromOptional(init_node), | |
| 2693 | } }, | |
| 2757 | 2694 | }); |
| 2758 | 2695 | } else { |
| 2759 | 2696 | return c.addNode(.{ |
| 2760 | 2697 | .tag = .local_var_decl, |
| 2761 | 2698 | .main_token = mut_tok, |
| 2762 | .data = .{ | |
| 2763 | .lhs = try c.addExtra(std.zig.Ast.Node.LocalVarDecl{ | |
| 2699 | .data = .{ .extra_and_opt_node = .{ | |
| 2700 | try c.addExtra(std.zig.Ast.Node.LocalVarDecl{ | |
| 2764 | 2701 | .type_node = type_node, |
| 2765 | .align_node = align_node, | |
| 2702 | .align_node = align_node.?, | |
| 2766 | 2703 | }), |
| 2767 | .rhs = init_node, | |
| 2768 | }, | |
| 2704 | .fromOptional(init_node), | |
| 2705 | } }, | |
| 2769 | 2706 | }); |
| 2770 | 2707 | } |
| 2771 | 2708 | } else { |
| 2772 | 2709 | return c.addNode(.{ |
| 2773 | 2710 | .tag = .global_var_decl, |
| 2774 | 2711 | .main_token = mut_tok, |
| 2775 | .data = .{ | |
| 2776 | .lhs = try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{ | |
| 2777 | .type_node = type_node, | |
| 2778 | .align_node = align_node, | |
| 2779 | .section_node = section_node, | |
| 2780 | .addrspace_node = 0, | |
| 2712 | .data = .{ .extra_and_opt_node = .{ | |
| 2713 | try c.addExtra(std.zig.Ast.Node.GlobalVarDecl{ | |
| 2714 | .type_node = type_node.toOptional(), | |
| 2715 | .align_node = .fromOptional(align_node), | |
| 2716 | .section_node = .fromOptional(section_node), | |
| 2717 | .addrspace_node = .none, | |
| 2781 | 2718 | }), |
| 2782 | .rhs = init_node, | |
| 2783 | }, | |
| 2719 | .fromOptional(init_node), | |
| 2720 | } }, | |
| 2784 | 2721 | }); |
| 2785 | 2722 | } |
| 2786 | 2723 | } |
| ... | ... | @@ -2809,7 +2746,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2809 | 2746 | }); |
| 2810 | 2747 | _ = try c.addToken(.r_paren, ")"); |
| 2811 | 2748 | break :blk res; |
| 2812 | } else 0; | |
| 2749 | } else null; | |
| 2813 | 2750 | |
| 2814 | 2751 | const section_expr = if (payload.linksection_string) |some| blk: { |
| 2815 | 2752 | _ = try c.addToken(.keyword_linksection, "linksection"); |
| ... | ... | @@ -2821,7 +2758,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2821 | 2758 | }); |
| 2822 | 2759 | _ = try c.addToken(.r_paren, ")"); |
| 2823 | 2760 | break :blk res; |
| 2824 | } else 0; | |
| 2761 | } else null; | |
| 2825 | 2762 | |
| 2826 | 2763 | const callconv_expr = if (payload.explicit_callconv) |some| blk: { |
| 2827 | 2764 | _ = try c.addToken(.keyword_callconv, "callconv"); |
| ... | ... | @@ -2856,48 +2793,52 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2856 | 2793 | const inner_lbrace = try c.addToken(.l_brace, "{"); |
| 2857 | 2794 | _ = try c.addToken(.r_brace, "}"); |
| 2858 | 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 | 2804 | break :cc_node try c.addNode(.{ |
| 2860 | 2805 | .tag = .struct_init_dot_two, |
| 2861 | 2806 | .main_token = outer_lbrace, |
| 2862 | .data = .{ | |
| 2863 | .lhs = try c.addNode(.{ | |
| 2864 | .tag = .struct_init_dot_two, | |
| 2865 | .main_token = inner_lbrace, | |
| 2866 | .data = .{ .lhs = 0, .rhs = 0 }, | |
| 2867 | }), | |
| 2868 | .rhs = 0, | |
| 2869 | }, | |
| 2807 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2808 | inner_node.toOptional(), | |
| 2809 | .none, | |
| 2810 | } }, | |
| 2870 | 2811 | }); |
| 2871 | 2812 | }, |
| 2872 | 2813 | }; |
| 2873 | 2814 | _ = try c.addToken(.r_paren, ")"); |
| 2874 | 2815 | break :blk cc_node; |
| 2875 | } else 0; | |
| 2816 | } else null; | |
| 2876 | 2817 | |
| 2877 | 2818 | const return_type_expr = try renderNode(c, payload.return_type); |
| 2878 | 2819 | |
| 2879 | 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 | 2822 | if (params.items.len < 2) |
| 2882 | 2823 | break :blk c.addNode(.{ |
| 2883 | 2824 | .tag = .fn_proto_simple, |
| 2884 | 2825 | .main_token = fn_token, |
| 2885 | .data = .{ | |
| 2886 | .lhs = params.items[0], | |
| 2887 | .rhs = return_type_expr, | |
| 2888 | }, | |
| 2826 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2827 | if (params.items.len == 0) .none else params.items[0].toOptional(), | |
| 2828 | return_type_expr.toOptional(), | |
| 2829 | } }, | |
| 2889 | 2830 | }) |
| 2890 | 2831 | else |
| 2891 | 2832 | break :blk c.addNode(.{ |
| 2892 | 2833 | .tag = .fn_proto_multi, |
| 2893 | 2834 | .main_token = fn_token, |
| 2894 | .data = .{ | |
| 2895 | .lhs = try c.addExtra(NodeSubRange{ | |
| 2835 | .data = .{ .extra_and_opt_node = .{ | |
| 2836 | try c.addExtra(NodeSubRange{ | |
| 2896 | 2837 | .start = span.start, |
| 2897 | 2838 | .end = span.end, |
| 2898 | 2839 | }), |
| 2899 | .rhs = return_type_expr, | |
| 2900 | }, | |
| 2840 | return_type_expr.toOptional(), | |
| 2841 | } }, | |
| 2901 | 2842 | }); |
| 2902 | 2843 | } |
| 2903 | 2844 | if (params.items.len < 2) |
| ... | ... | @@ -2905,14 +2846,16 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2905 | 2846 | .tag = .fn_proto_one, |
| 2906 | 2847 | .main_token = fn_token, |
| 2907 | 2848 | .data = .{ |
| 2908 | .lhs = try c.addExtra(std.zig.Ast.Node.FnProtoOne{ | |
| 2909 | .param = params.items[0], | |
| 2910 | .align_expr = align_expr, | |
| 2911 | .addrspace_expr = 0, // TODO | |
| 2912 | .section_expr = section_expr, | |
| 2913 | .callconv_expr = callconv_expr, | |
| 2914 | }), | |
| 2915 | .rhs = return_type_expr, | |
| 2849 | .extra_and_opt_node = .{ | |
| 2850 | try c.addExtra(std.zig.Ast.Node.FnProtoOne{ | |
| 2851 | .param = if (params.items.len == 0) .none else params.items[0].toOptional(), | |
| 2852 | .align_expr = .fromOptional(align_expr), | |
| 2853 | .addrspace_expr = .none, // TODO | |
| 2854 | .section_expr = .fromOptional(section_expr), | |
| 2855 | .callconv_expr = .fromOptional(callconv_expr), | |
| 2856 | }), | |
| 2857 | return_type_expr.toOptional(), | |
| 2858 | }, | |
| 2916 | 2859 | }, |
| 2917 | 2860 | }) |
| 2918 | 2861 | else |
| ... | ... | @@ -2920,15 +2863,17 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2920 | 2863 | .tag = .fn_proto, |
| 2921 | 2864 | .main_token = fn_token, |
| 2922 | 2865 | .data = .{ |
| 2923 | .lhs = try c.addExtra(std.zig.Ast.Node.FnProto{ | |
| 2924 | .params_start = span.start, | |
| 2925 | .params_end = span.end, | |
| 2926 | .align_expr = align_expr, | |
| 2927 | .addrspace_expr = 0, // TODO | |
| 2928 | .section_expr = section_expr, | |
| 2929 | .callconv_expr = callconv_expr, | |
| 2930 | }), | |
| 2931 | .rhs = return_type_expr, | |
| 2866 | .extra_and_opt_node = .{ | |
| 2867 | try c.addExtra(std.zig.Ast.Node.FnProto{ | |
| 2868 | .params_start = span.start, | |
| 2869 | .params_end = span.end, | |
| 2870 | .align_expr = .fromOptional(align_expr), | |
| 2871 | .addrspace_expr = .none, // TODO | |
| 2872 | .section_expr = .fromOptional(section_expr), | |
| 2873 | .callconv_expr = .fromOptional(callconv_expr), | |
| 2874 | }), | |
| 2875 | return_type_expr.toOptional(), | |
| 2876 | }, | |
| 2932 | 2877 | }, |
| 2933 | 2878 | }); |
| 2934 | 2879 | }; |
| ... | ... | @@ -2943,10 +2888,10 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex { |
| 2943 | 2888 | return c.addNode(.{ |
| 2944 | 2889 | .tag = .fn_decl, |
| 2945 | 2890 | .main_token = fn_token, |
| 2946 | .data = .{ | |
| 2947 | .lhs = fn_proto, | |
| 2948 | .rhs = body, | |
| 2949 | }, | |
| 2891 | .data = .{ .node_and_node = .{ | |
| 2892 | fn_proto, | |
| 2893 | body, | |
| 2894 | } }, | |
| 2950 | 2895 | }); |
| 2951 | 2896 | } |
| 2952 | 2897 | |
| ... | ... | @@ -2959,8 +2904,6 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex { |
| 2959 | 2904 | |
| 2960 | 2905 | const params = try renderParams(c, payload.params, false); |
| 2961 | 2906 | defer params.deinit(); |
| 2962 | var span: NodeSubRange = undefined; | |
| 2963 | if (params.items.len > 1) span = try c.listToSpan(params.items); | |
| 2964 | 2907 | |
| 2965 | 2908 | const return_type_expr = try renderNodeGrouped(c, payload.return_type); |
| 2966 | 2909 | |
| ... | ... | @@ -2969,38 +2912,39 @@ fn renderMacroFunc(c: *Context, node: Node) !NodeIndex { |
| 2969 | 2912 | break :blk try c.addNode(.{ |
| 2970 | 2913 | .tag = .fn_proto_simple, |
| 2971 | 2914 | .main_token = fn_token, |
| 2972 | .data = .{ | |
| 2973 | .lhs = params.items[0], | |
| 2974 | .rhs = return_type_expr, | |
| 2975 | }, | |
| 2915 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2916 | if (params.items.len == 0) .none else params.items[0].toOptional(), | |
| 2917 | return_type_expr.toOptional(), | |
| 2918 | } }, | |
| 2976 | 2919 | }); |
| 2977 | 2920 | } else { |
| 2921 | const span: NodeSubRange = try c.listToSpan(params.items); | |
| 2978 | 2922 | break :blk try c.addNode(.{ |
| 2979 | 2923 | .tag = .fn_proto_multi, |
| 2980 | 2924 | .main_token = fn_token, |
| 2981 | .data = .{ | |
| 2982 | .lhs = try c.addExtra(std.zig.Ast.Node.SubRange{ | |
| 2925 | .data = .{ .extra_and_opt_node = .{ | |
| 2926 | try c.addExtra(std.zig.Ast.Node.SubRange{ | |
| 2983 | 2927 | .start = span.start, |
| 2984 | 2928 | .end = span.end, |
| 2985 | 2929 | }), |
| 2986 | .rhs = return_type_expr, | |
| 2987 | }, | |
| 2930 | return_type_expr.toOptional(), | |
| 2931 | } }, | |
| 2988 | 2932 | }); |
| 2989 | 2933 | } |
| 2990 | 2934 | }; |
| 2991 | 2935 | return c.addNode(.{ |
| 2992 | 2936 | .tag = .fn_decl, |
| 2993 | 2937 | .main_token = fn_token, |
| 2994 | .data = .{ | |
| 2995 | .lhs = fn_proto, | |
| 2996 | .rhs = try renderNode(c, payload.body), | |
| 2997 | }, | |
| 2938 | .data = .{ .node_and_node = .{ | |
| 2939 | fn_proto, | |
| 2940 | try renderNode(c, payload.body), | |
| 2941 | } }, | |
| 2998 | 2942 | }); |
| 2999 | 2943 | } |
| 3000 | 2944 | |
| 3001 | 2945 | fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.ArrayList(NodeIndex) { |
| 3002 | 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 | 2948 | errdefer rendered.deinit(); |
| 3005 | 2949 | |
| 3006 | 2950 | for (params, 0..) |param, i| { |
| ... | ... | @@ -3022,6 +2966,5 @@ fn renderParams(c: *Context, params: []Payload.Param, is_var_args: bool) !std.Ar |
| 3022 | 2966 | } |
| 3023 | 2967 | _ = try c.addToken(.r_paren, ")"); |
| 3024 | 2968 | |
| 3025 | if (rendered.items.len == 0) rendered.appendAssumeCapacity(0); | |
| 3026 | 2969 | return rendered; |
| 3027 | 2970 | } |
lib/compiler/reduce.zig+1-1| ... | ... | @@ -220,7 +220,7 @@ pub fn main() !void { |
| 220 | 220 | mem.eql(u8, msg, "unused function parameter") or |
| 221 | 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 | 224 | try more_fixups.unused_var_decls.put(gpa, ident_token, {}); |
| 225 | 225 | } else { |
| 226 | 226 | std.debug.print("found other ZIR error: '{s}'\n", .{msg}); |
lib/compiler/reduce/Walk.zig+160-253| ... | ... | @@ -98,29 +98,26 @@ const ScanDeclsAction = enum { add, remove }; |
| 98 | 98 | fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction) Error!void { |
| 99 | 99 | const ast = w.ast; |
| 100 | 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); | |
| 104 | 101 | |
| 105 | 102 | for (members) |member_node| { |
| 106 | const name_token = switch (node_tags[member_node]) { | |
| 103 | const name_token = switch (ast.nodeTag(member_node)) { | |
| 107 | 104 | .global_var_decl, |
| 108 | 105 | .local_var_decl, |
| 109 | 106 | .simple_var_decl, |
| 110 | 107 | .aligned_var_decl, |
| 111 | => main_tokens[member_node] + 1, | |
| 108 | => ast.nodeMainToken(member_node) + 1, | |
| 112 | 109 | |
| 113 | 110 | .fn_proto_simple, |
| 114 | 111 | .fn_proto_multi, |
| 115 | 112 | .fn_proto_one, |
| 116 | 113 | .fn_proto, |
| 117 | 114 | .fn_decl, |
| 118 | => main_tokens[member_node] + 1, | |
| 115 | => ast.nodeMainToken(member_node) + 1, | |
| 119 | 116 | |
| 120 | 117 | else => continue, |
| 121 | 118 | }; |
| 122 | 119 | |
| 123 | assert(token_tags[name_token] == .identifier); | |
| 120 | assert(ast.tokenTag(name_token) == .identifier); | |
| 124 | 121 | const name_bytes = ast.tokenSlice(name_token); |
| 125 | 122 | |
| 126 | 123 | switch (action) { |
| ... | ... | @@ -145,12 +142,10 @@ fn scanDecls(w: *Walk, members: []const Ast.Node.Index, action: ScanDeclsAction) |
| 145 | 142 | |
| 146 | 143 | fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void { |
| 147 | 144 | const ast = w.ast; |
| 148 | const datas = ast.nodes.items(.data); | |
| 149 | switch (ast.nodes.items(.tag)[decl]) { | |
| 145 | switch (ast.nodeTag(decl)) { | |
| 150 | 146 | .fn_decl => { |
| 151 | const fn_proto = datas[decl].lhs; | |
| 147 | const fn_proto, const body_node = ast.nodeData(decl).node_and_node; | |
| 152 | 148 | try walkExpression(w, fn_proto); |
| 153 | const body_node = datas[decl].rhs; | |
| 154 | 149 | if (!isFnBodyGutted(ast, body_node)) { |
| 155 | 150 | w.replace_names.clearRetainingCapacity(); |
| 156 | 151 | try w.transformations.append(.{ .gut_function = decl }); |
| ... | ... | @@ -167,7 +162,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void { |
| 167 | 162 | |
| 168 | 163 | .@"usingnamespace" => { |
| 169 | 164 | try w.transformations.append(.{ .delete_node = decl }); |
| 170 | const expr = datas[decl].lhs; | |
| 165 | const expr = ast.nodeData(decl).node; | |
| 171 | 166 | try walkExpression(w, expr); |
| 172 | 167 | }, |
| 173 | 168 | |
| ... | ... | @@ -179,7 +174,7 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void { |
| 179 | 174 | |
| 180 | 175 | .test_decl => { |
| 181 | 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 | }, |
| 184 | 179 | |
| 185 | 180 | .container_field_init, |
| ... | ... | @@ -202,14 +197,10 @@ fn walkMember(w: *Walk, decl: Ast.Node.Index) Error!void { |
| 202 | 197 | |
| 203 | 198 | fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 204 | 199 | const ast = w.ast; |
| 205 | const token_tags = ast.tokens.items(.tag); | |
| 206 | const main_tokens = ast.nodes.items(.main_token); | |
| 207 | const node_tags = ast.nodes.items(.tag); | |
| 208 | const datas = ast.nodes.items(.data); | |
| 209 | switch (node_tags[node]) { | |
| 200 | switch (ast.nodeTag(node)) { | |
| 210 | 201 | .identifier => { |
| 211 | const name_ident = main_tokens[node]; | |
| 212 | assert(token_tags[name_ident] == .identifier); | |
| 202 | const name_ident = ast.nodeMainToken(node); | |
| 203 | assert(ast.tokenTag(name_ident) == .identifier); | |
| 213 | 204 | const name_bytes = ast.tokenSlice(name_ident); |
| 214 | 205 | _ = w.unreferenced_globals.swapRemove(name_bytes); |
| 215 | 206 | if (w.replace_names.get(name_bytes)) |index| { |
| ... | ... | @@ -230,64 +221,36 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 230 | 221 | |
| 231 | 222 | .block_two, |
| 232 | 223 | .block_two_semicolon, |
| 233 | => { | |
| 234 | const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs }; | |
| 235 | if (datas[node].lhs == 0) { | |
| 236 | return walkBlock(w, node, statements[0..0]); | |
| 237 | } else if (datas[node].rhs == 0) { | |
| 238 | return walkBlock(w, node, statements[0..1]); | |
| 239 | } else { | |
| 240 | return walkBlock(w, node, statements[0..2]); | |
| 241 | } | |
| 242 | }, | |
| 243 | 224 | .block, |
| 244 | 225 | .block_semicolon, |
| 245 | 226 | => { |
| 246 | const statements = ast.extra_data[datas[node].lhs..datas[node].rhs]; | |
| 227 | var buf: [2]Ast.Node.Index = undefined; | |
| 228 | const statements = ast.blockStatements(&buf, node).?; | |
| 247 | 229 | return walkBlock(w, node, statements); |
| 248 | 230 | }, |
| 249 | 231 | |
| 250 | 232 | .@"errdefer" => { |
| 251 | const expr = datas[node].rhs; | |
| 233 | const expr = ast.nodeData(node).opt_token_and_node[1]; | |
| 252 | 234 | return walkExpression(w, expr); |
| 253 | 235 | }, |
| 254 | 236 | |
| 255 | .@"defer" => { | |
| 256 | const expr = datas[node].rhs; | |
| 257 | return walkExpression(w, expr); | |
| 258 | }, | |
| 259 | .@"comptime", .@"nosuspend" => { | |
| 260 | const block = datas[node].lhs; | |
| 261 | return walkExpression(w, block); | |
| 262 | }, | |
| 263 | ||
| 264 | .@"suspend" => { | |
| 265 | const body = datas[node].lhs; | |
| 266 | return walkExpression(w, body); | |
| 267 | }, | |
| 268 | ||
| 269 | .@"catch" => { | |
| 270 | try walkExpression(w, datas[node].lhs); // target | |
| 271 | try walkExpression(w, datas[node].rhs); // fallback | |
| 237 | .@"defer", | |
| 238 | .@"comptime", | |
| 239 | .@"nosuspend", | |
| 240 | .@"suspend", | |
| 241 | => { | |
| 242 | return walkExpression(w, ast.nodeData(node).node); | |
| 272 | 243 | }, |
| 273 | 244 | |
| 274 | 245 | .field_access => { |
| 275 | const field_access = datas[node]; | |
| 276 | try walkExpression(w, field_access.lhs); | |
| 246 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 277 | 247 | }, |
| 278 | 248 | |
| 279 | .error_union, | |
| 280 | .switch_range, | |
| 281 | => { | |
| 282 | const infix = datas[node]; | |
| 283 | try walkExpression(w, infix.lhs); | |
| 284 | return walkExpression(w, infix.rhs); | |
| 285 | }, | |
| 286 | 249 | .for_range => { |
| 287 | const infix = datas[node]; | |
| 288 | try walkExpression(w, infix.lhs); | |
| 289 | if (infix.rhs != 0) { | |
| 290 | return walkExpression(w, infix.rhs); | |
| 250 | const start, const opt_end = ast.nodeData(node).node_and_opt_node; | |
| 251 | try walkExpression(w, start); | |
| 252 | if (opt_end.unwrap()) |end| { | |
| 253 | return walkExpression(w, end); | |
| 291 | 254 | } |
| 292 | 255 | }, |
| 293 | 256 | |
| ... | ... | @@ -337,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 337 | 300 | .sub, |
| 338 | 301 | .sub_wrap, |
| 339 | 302 | .sub_sat, |
| 303 | .@"catch", | |
| 304 | .error_union, | |
| 305 | .switch_range, | |
| 340 | 306 | .@"orelse", |
| 307 | .array_access, | |
| 341 | 308 | => { |
| 342 | const infix = datas[node]; | |
| 343 | try walkExpression(w, infix.lhs); | |
| 344 | try walkExpression(w, infix.rhs); | |
| 309 | const lhs, const rhs = ast.nodeData(node).node_and_node; | |
| 310 | try walkExpression(w, lhs); | |
| 311 | try walkExpression(w, rhs); | |
| 345 | 312 | }, |
| 346 | 313 | |
| 347 | 314 | .assign_destructure => { |
| 348 | 315 | const full = ast.assignDestructure(node); |
| 349 | 316 | for (full.ast.variables) |variable_node| { |
| 350 | switch (node_tags[variable_node]) { | |
| 317 | switch (ast.nodeTag(variable_node)) { | |
| 351 | 318 | .global_var_decl, |
| 352 | 319 | .local_var_decl, |
| 353 | 320 | .simple_var_decl, |
| ... | ... | @@ -366,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 366 | 333 | .negation_wrap, |
| 367 | 334 | .optional_type, |
| 368 | 335 | .address_of, |
| 369 | => { | |
| 370 | return walkExpression(w, datas[node].lhs); | |
| 371 | }, | |
| 372 | ||
| 373 | 336 | .@"try", |
| 374 | 337 | .@"resume", |
| 375 | 338 | .@"await", |
| 339 | .deref, | |
| 376 | 340 | => { |
| 377 | return walkExpression(w, datas[node].lhs); | |
| 341 | return walkExpression(w, ast.nodeData(node).node); | |
| 378 | 342 | }, |
| 379 | 343 | |
| 380 | 344 | .array_type, |
| ... | ... | @@ -426,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 426 | 390 | return walkCall(w, ast.fullCall(&buf, node).?); |
| 427 | 391 | }, |
| 428 | 392 | |
| 429 | .array_access => { | |
| 430 | const suffix = datas[node]; | |
| 431 | try walkExpression(w, suffix.lhs); | |
| 432 | try walkExpression(w, suffix.rhs); | |
| 433 | }, | |
| 434 | ||
| 435 | 393 | .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?), |
| 436 | 394 | |
| 437 | .deref => { | |
| 438 | try walkExpression(w, datas[node].lhs); | |
| 439 | }, | |
| 440 | ||
| 441 | 395 | .unwrap_optional => { |
| 442 | try walkExpression(w, datas[node].lhs); | |
| 396 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 443 | 397 | }, |
| 444 | 398 | |
| 445 | 399 | .@"break" => { |
| 446 | const label_token = datas[node].lhs; | |
| 447 | const target = datas[node].rhs; | |
| 448 | if (label_token == 0 and target == 0) { | |
| 400 | const label_token, const target = ast.nodeData(node).opt_token_and_opt_node; | |
| 401 | if (label_token == .none and target == .none) { | |
| 449 | 402 | // no expressions |
| 450 | } else if (label_token == 0 and target != 0) { | |
| 451 | try walkExpression(w, target); | |
| 452 | } else if (label_token != 0 and target == 0) { | |
| 453 | try walkIdentifier(w, label_token); | |
| 454 | } else if (label_token != 0 and target != 0) { | |
| 455 | try walkExpression(w, target); | |
| 403 | } else if (label_token == .none and target != .none) { | |
| 404 | try walkExpression(w, target.unwrap().?); | |
| 405 | } else if (label_token != .none and target == .none) { | |
| 406 | try walkIdentifier(w, label_token.unwrap().?); | |
| 407 | } else if (label_token != .none and target != .none) { | |
| 408 | try walkExpression(w, target.unwrap().?); | |
| 456 | 409 | } |
| 457 | 410 | }, |
| 458 | 411 | |
| 459 | 412 | .@"continue" => { |
| 460 | const label = datas[node].lhs; | |
| 461 | if (label != 0) { | |
| 462 | return walkIdentifier(w, label); // label | |
| 413 | const opt_label = ast.nodeData(node).opt_token_and_opt_node[0]; | |
| 414 | if (opt_label.unwrap()) |label| { | |
| 415 | return walkIdentifier(w, label); | |
| 463 | 416 | } |
| 464 | 417 | }, |
| 465 | 418 | |
| 466 | 419 | .@"return" => { |
| 467 | if (datas[node].lhs != 0) { | |
| 468 | try walkExpression(w, datas[node].lhs); | |
| 420 | if (ast.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 421 | try walkExpression(w, lhs); | |
| 469 | 422 | } |
| 470 | 423 | }, |
| 471 | 424 | |
| 472 | 425 | .grouped_expression => { |
| 473 | try walkExpression(w, datas[node].lhs); | |
| 426 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 474 | 427 | }, |
| 475 | 428 | |
| 476 | 429 | .container_decl, |
| ... | ... | @@ -491,13 +444,11 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 491 | 444 | }, |
| 492 | 445 | |
| 493 | 446 | .error_set_decl => { |
| 494 | const error_token = main_tokens[node]; | |
| 495 | const lbrace = error_token + 1; | |
| 496 | const rbrace = datas[node].rhs; | |
| 447 | const lbrace, const rbrace = ast.nodeData(node).token_and_token; | |
| 497 | 448 | |
| 498 | 449 | var i = lbrace + 1; |
| 499 | 450 | while (i < rbrace) : (i += 1) { |
| 500 | switch (token_tags[i]) { | |
| 451 | switch (ast.tokenTag(i)) { | |
| 501 | 452 | .doc_comment => unreachable, // TODO |
| 502 | 453 | .identifier => try walkIdentifier(w, i), |
| 503 | 454 | .comma => {}, |
| ... | ... | @@ -506,17 +457,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 506 | 457 | } |
| 507 | 458 | }, |
| 508 | 459 | |
| 509 | .builtin_call_two, .builtin_call_two_comma => { | |
| 510 | if (datas[node].lhs == 0) { | |
| 511 | return walkBuiltinCall(w, node, &.{}); | |
| 512 | } else if (datas[node].rhs == 0) { | |
| 513 | return walkBuiltinCall(w, node, &.{datas[node].lhs}); | |
| 514 | } else { | |
| 515 | return walkBuiltinCall(w, node, &.{ datas[node].lhs, datas[node].rhs }); | |
| 516 | } | |
| 517 | }, | |
| 518 | .builtin_call, .builtin_call_comma => { | |
| 519 | const params = ast.extra_data[datas[node].lhs..datas[node].rhs]; | |
| 460 | .builtin_call_two, | |
| 461 | .builtin_call_two_comma, | |
| 462 | .builtin_call, | |
| 463 | .builtin_call_comma, | |
| 464 | => { | |
| 465 | var buf: [2]Ast.Node.Index = undefined; | |
| 466 | const params = ast.builtinCallParams(&buf, node).?; | |
| 520 | 467 | return walkBuiltinCall(w, node, params); |
| 521 | 468 | }, |
| 522 | 469 | |
| ... | ... | @@ -530,20 +477,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 530 | 477 | }, |
| 531 | 478 | |
| 532 | 479 | .anyframe_type => { |
| 533 | if (datas[node].rhs != 0) { | |
| 534 | return walkExpression(w, datas[node].rhs); | |
| 535 | } | |
| 480 | _, const child_type = ast.nodeData(node).token_and_node; | |
| 481 | return walkExpression(w, child_type); | |
| 536 | 482 | }, |
| 537 | 483 | |
| 538 | 484 | .@"switch", |
| 539 | 485 | .switch_comma, |
| 540 | 486 | => { |
| 541 | const condition = datas[node].lhs; | |
| 542 | const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange); | |
| 543 | const cases = ast.extra_data[extra.start..extra.end]; | |
| 544 | ||
| 545 | try walkExpression(w, condition); // condition expression | |
| 546 | try walkExpressions(w, cases); | |
| 487 | const full = ast.fullSwitch(node).?; | |
| 488 | try walkExpression(w, full.ast.condition); // condition expression | |
| 489 | try walkExpressions(w, full.ast.cases); | |
| 547 | 490 | }, |
| 548 | 491 | |
| 549 | 492 | .switch_case_one, |
| ... | ... | @@ -570,7 +513,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 570 | 513 | => return walkAsm(w, ast.fullAsm(node).?), |
| 571 | 514 | |
| 572 | 515 | .enum_literal => { |
| 573 | return walkIdentifier(w, main_tokens[node]); // name | |
| 516 | return walkIdentifier(w, ast.nodeMainToken(node)); // name | |
| 574 | 517 | }, |
| 575 | 518 | |
| 576 | 519 | .fn_decl => unreachable, |
| ... | ... | @@ -592,66 +535,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 592 | 535 | fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void { |
| 593 | 536 | _ = decl_node; |
| 594 | 537 | |
| 595 | if (var_decl.ast.type_node != 0) { | |
| 596 | try walkExpression(w, var_decl.ast.type_node); | |
| 538 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 539 | try walkExpression(w, type_node); | |
| 597 | 540 | } |
| 598 | 541 | |
| 599 | if (var_decl.ast.align_node != 0) { | |
| 600 | try walkExpression(w, var_decl.ast.align_node); | |
| 542 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 543 | try walkExpression(w, align_node); | |
| 601 | 544 | } |
| 602 | 545 | |
| 603 | if (var_decl.ast.addrspace_node != 0) { | |
| 604 | try walkExpression(w, var_decl.ast.addrspace_node); | |
| 546 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 547 | try walkExpression(w, addrspace_node); | |
| 605 | 548 | } |
| 606 | 549 | |
| 607 | if (var_decl.ast.section_node != 0) { | |
| 608 | try walkExpression(w, var_decl.ast.section_node); | |
| 550 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 551 | try walkExpression(w, section_node); | |
| 609 | 552 | } |
| 610 | 553 | |
| 611 | if (var_decl.ast.init_node != 0) { | |
| 612 | if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) { | |
| 613 | try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node }); | |
| 554 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 555 | if (!isUndefinedIdent(w.ast, init_node)) { | |
| 556 | try w.transformations.append(.{ .replace_with_undef = init_node }); | |
| 614 | 557 | } |
| 615 | try walkExpression(w, var_decl.ast.init_node); | |
| 558 | try walkExpression(w, init_node); | |
| 616 | 559 | } |
| 617 | 560 | } |
| 618 | 561 | |
| 619 | 562 | fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void { |
| 620 | 563 | try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name |
| 621 | 564 | |
| 622 | if (var_decl.ast.type_node != 0) { | |
| 623 | try walkExpression(w, var_decl.ast.type_node); | |
| 565 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 566 | try walkExpression(w, type_node); | |
| 624 | 567 | } |
| 625 | 568 | |
| 626 | if (var_decl.ast.align_node != 0) { | |
| 627 | try walkExpression(w, var_decl.ast.align_node); | |
| 569 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 570 | try walkExpression(w, align_node); | |
| 628 | 571 | } |
| 629 | 572 | |
| 630 | if (var_decl.ast.addrspace_node != 0) { | |
| 631 | try walkExpression(w, var_decl.ast.addrspace_node); | |
| 573 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 574 | try walkExpression(w, addrspace_node); | |
| 632 | 575 | } |
| 633 | 576 | |
| 634 | if (var_decl.ast.section_node != 0) { | |
| 635 | try walkExpression(w, var_decl.ast.section_node); | |
| 577 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 578 | try walkExpression(w, section_node); | |
| 636 | 579 | } |
| 637 | 580 | |
| 638 | if (var_decl.ast.init_node != 0) { | |
| 639 | if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) { | |
| 640 | try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node }); | |
| 581 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 582 | if (!isUndefinedIdent(w.ast, init_node)) { | |
| 583 | try w.transformations.append(.{ .replace_with_undef = init_node }); | |
| 641 | 584 | } |
| 642 | try walkExpression(w, var_decl.ast.init_node); | |
| 585 | try walkExpression(w, init_node); | |
| 643 | 586 | } |
| 644 | 587 | } |
| 645 | 588 | |
| 646 | 589 | fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void { |
| 647 | if (field.ast.type_expr != 0) { | |
| 648 | try walkExpression(w, field.ast.type_expr); // type | |
| 590 | if (field.ast.type_expr.unwrap()) |type_expr| { | |
| 591 | try walkExpression(w, type_expr); // type | |
| 649 | 592 | } |
| 650 | if (field.ast.align_expr != 0) { | |
| 651 | try walkExpression(w, field.ast.align_expr); // alignment | |
| 593 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 594 | try walkExpression(w, align_expr); // alignment | |
| 652 | 595 | } |
| 653 | if (field.ast.value_expr != 0) { | |
| 654 | try walkExpression(w, field.ast.value_expr); // value | |
| 596 | if (field.ast.value_expr.unwrap()) |value_expr| { | |
| 597 | try walkExpression(w, value_expr); // value | |
| 655 | 598 | } |
| 656 | 599 | } |
| 657 | 600 | |
| ... | ... | @@ -662,18 +605,17 @@ fn walkBlock( |
| 662 | 605 | ) Error!void { |
| 663 | 606 | _ = block_node; |
| 664 | 607 | const ast = w.ast; |
| 665 | const node_tags = ast.nodes.items(.tag); | |
| 666 | 608 | |
| 667 | 609 | for (statements) |stmt| { |
| 668 | switch (node_tags[stmt]) { | |
| 610 | switch (ast.nodeTag(stmt)) { | |
| 669 | 611 | .global_var_decl, |
| 670 | 612 | .local_var_decl, |
| 671 | 613 | .simple_var_decl, |
| 672 | 614 | .aligned_var_decl, |
| 673 | 615 | => { |
| 674 | 616 | const var_decl = ast.fullVarDecl(stmt).?; |
| 675 | if (var_decl.ast.init_node != 0 and | |
| 676 | isUndefinedIdent(w.ast, var_decl.ast.init_node)) | |
| 617 | if (var_decl.ast.init_node != .none and | |
| 618 | isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?)) | |
| 677 | 619 | { |
| 678 | 620 | try w.transformations.append(.{ .delete_var_decl = .{ |
| 679 | 621 | .var_decl_node = stmt, |
| ... | ... | @@ -704,15 +646,15 @@ fn walkBlock( |
| 704 | 646 | |
| 705 | 647 | fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void { |
| 706 | 648 | try walkExpression(w, array_type.ast.elem_count); |
| 707 | if (array_type.ast.sentinel != 0) { | |
| 708 | try walkExpression(w, array_type.ast.sentinel); | |
| 649 | if (array_type.ast.sentinel.unwrap()) |sentinel| { | |
| 650 | try walkExpression(w, sentinel); | |
| 709 | 651 | } |
| 710 | 652 | return walkExpression(w, array_type.ast.elem_type); |
| 711 | 653 | } |
| 712 | 654 | |
| 713 | 655 | fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void { |
| 714 | if (array_init.ast.type_expr != 0) { | |
| 715 | try walkExpression(w, array_init.ast.type_expr); // T | |
| 656 | if (array_init.ast.type_expr.unwrap()) |type_expr| { | |
| 657 | try walkExpression(w, type_expr); // T | |
| 716 | 658 | } |
| 717 | 659 | for (array_init.ast.elements) |elem_init| { |
| 718 | 660 | try walkExpression(w, elem_init); |
| ... | ... | @@ -725,8 +667,8 @@ fn walkStructInit( |
| 725 | 667 | struct_init: Ast.full.StructInit, |
| 726 | 668 | ) Error!void { |
| 727 | 669 | _ = struct_node; |
| 728 | if (struct_init.ast.type_expr != 0) { | |
| 729 | try walkExpression(w, struct_init.ast.type_expr); // T | |
| 670 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 671 | try walkExpression(w, type_expr); // T | |
| 730 | 672 | } |
| 731 | 673 | for (struct_init.ast.fields) |field_init| { |
| 732 | 674 | try walkExpression(w, field_init); |
| ... | ... | @@ -746,18 +688,17 @@ fn walkSlice( |
| 746 | 688 | _ = slice_node; |
| 747 | 689 | try walkExpression(w, slice.ast.sliced); |
| 748 | 690 | try walkExpression(w, slice.ast.start); |
| 749 | if (slice.ast.end != 0) { | |
| 750 | try walkExpression(w, slice.ast.end); | |
| 691 | if (slice.ast.end.unwrap()) |end| { | |
| 692 | try walkExpression(w, end); | |
| 751 | 693 | } |
| 752 | if (slice.ast.sentinel != 0) { | |
| 753 | try walkExpression(w, slice.ast.sentinel); | |
| 694 | if (slice.ast.sentinel.unwrap()) |sentinel| { | |
| 695 | try walkExpression(w, sentinel); | |
| 754 | 696 | } |
| 755 | 697 | } |
| 756 | 698 | |
| 757 | 699 | fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void { |
| 758 | 700 | const ast = w.ast; |
| 759 | const token_tags = ast.tokens.items(.tag); | |
| 760 | assert(token_tags[name_ident] == .identifier); | |
| 701 | assert(ast.tokenTag(name_ident) == .identifier); | |
| 761 | 702 | const name_bytes = ast.tokenSlice(name_ident); |
| 762 | 703 | _ = w.unreferenced_globals.swapRemove(name_bytes); |
| 763 | 704 | } |
| ... | ... | @@ -773,8 +714,8 @@ fn walkContainerDecl( |
| 773 | 714 | container_decl: Ast.full.ContainerDecl, |
| 774 | 715 | ) Error!void { |
| 775 | 716 | _ = container_decl_node; |
| 776 | if (container_decl.ast.arg != 0) { | |
| 777 | try walkExpression(w, container_decl.ast.arg); | |
| 717 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 718 | try walkExpression(w, arg); | |
| 778 | 719 | } |
| 779 | 720 | try walkMembers(w, container_decl.ast.members); |
| 780 | 721 | } |
| ... | ... | @@ -785,14 +726,13 @@ fn walkBuiltinCall( |
| 785 | 726 | params: []const Ast.Node.Index, |
| 786 | 727 | ) Error!void { |
| 787 | 728 | const ast = w.ast; |
| 788 | const main_tokens = ast.nodes.items(.main_token); | |
| 789 | const builtin_token = main_tokens[call_node]; | |
| 729 | const builtin_token = ast.nodeMainToken(call_node); | |
| 790 | 730 | const builtin_name = ast.tokenSlice(builtin_token); |
| 791 | 731 | const info = BuiltinFn.list.get(builtin_name).?; |
| 792 | 732 | switch (info.tag) { |
| 793 | 733 | .import => { |
| 794 | 734 | const operand_node = params[0]; |
| 795 | const str_lit_token = main_tokens[operand_node]; | |
| 735 | const str_lit_token = ast.nodeMainToken(operand_node); | |
| 796 | 736 | const token_bytes = ast.tokenSlice(str_lit_token); |
| 797 | 737 | if (std.mem.endsWith(u8, token_bytes, ".zig\"")) { |
| 798 | 738 | const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch |
| ... | ... | @@ -821,29 +761,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void { |
| 821 | 761 | { |
| 822 | 762 | var it = fn_proto.iterate(ast); |
| 823 | 763 | while (it.next()) |param| { |
| 824 | if (param.type_expr != 0) { | |
| 825 | try walkExpression(w, param.type_expr); | |
| 764 | if (param.type_expr) |type_expr| { | |
| 765 | try walkExpression(w, type_expr); | |
| 826 | 766 | } |
| 827 | 767 | } |
| 828 | 768 | } |
| 829 | 769 | |
| 830 | if (fn_proto.ast.align_expr != 0) { | |
| 831 | try walkExpression(w, fn_proto.ast.align_expr); | |
| 770 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 771 | try walkExpression(w, align_expr); | |
| 832 | 772 | } |
| 833 | 773 | |
| 834 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 835 | try walkExpression(w, fn_proto.ast.addrspace_expr); | |
| 774 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 775 | try walkExpression(w, addrspace_expr); | |
| 836 | 776 | } |
| 837 | 777 | |
| 838 | if (fn_proto.ast.section_expr != 0) { | |
| 839 | try walkExpression(w, fn_proto.ast.section_expr); | |
| 778 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 779 | try walkExpression(w, section_expr); | |
| 840 | 780 | } |
| 841 | 781 | |
| 842 | if (fn_proto.ast.callconv_expr != 0) { | |
| 843 | try walkExpression(w, fn_proto.ast.callconv_expr); | |
| 782 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 783 | try walkExpression(w, callconv_expr); | |
| 844 | 784 | } |
| 845 | 785 | |
| 846 | try walkExpression(w, fn_proto.ast.return_type); | |
| 786 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 787 | try walkExpression(w, return_type); | |
| 847 | 788 | } |
| 848 | 789 | |
| 849 | 790 | fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void { |
| ... | ... | @@ -860,16 +801,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void { |
| 860 | 801 | } |
| 861 | 802 | |
| 862 | 803 | fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void { |
| 863 | assert(while_node.ast.cond_expr != 0); | |
| 864 | assert(while_node.ast.then_expr != 0); | |
| 865 | ||
| 866 | 804 | // Perform these transformations in this priority order: |
| 867 | 805 | // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already. |
| 868 | 806 | // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already. |
| 869 | 807 | // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression. |
| 870 | 808 | // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression. |
| 871 | 809 | if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and |
| 872 | (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr))) | |
| 810 | (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?))) | |
| 873 | 811 | { |
| 874 | 812 | try w.transformations.ensureUnusedCapacity(1); |
| 875 | 813 | w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr }); |
| ... | ... | @@ -886,45 +824,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E |
| 886 | 824 | try w.transformations.ensureUnusedCapacity(1); |
| 887 | 825 | w.transformations.appendAssumeCapacity(.{ .replace_node = .{ |
| 888 | 826 | .to_replace = node_index, |
| 889 | .replacement = while_node.ast.else_expr, | |
| 827 | .replacement = while_node.ast.else_expr.unwrap().?, | |
| 890 | 828 | } }); |
| 891 | 829 | } |
| 892 | 830 | |
| 893 | 831 | try walkExpression(w, while_node.ast.cond_expr); // condition |
| 894 | 832 | |
| 895 | if (while_node.ast.cont_expr != 0) { | |
| 896 | try walkExpression(w, while_node.ast.cont_expr); | |
| 833 | if (while_node.ast.cont_expr.unwrap()) |cont_expr| { | |
| 834 | try walkExpression(w, cont_expr); | |
| 897 | 835 | } |
| 898 | 836 | |
| 899 | if (while_node.ast.then_expr != 0) { | |
| 900 | try walkExpression(w, while_node.ast.then_expr); | |
| 901 | } | |
| 902 | if (while_node.ast.else_expr != 0) { | |
| 903 | try walkExpression(w, while_node.ast.else_expr); | |
| 837 | try walkExpression(w, while_node.ast.then_expr); | |
| 838 | ||
| 839 | if (while_node.ast.else_expr.unwrap()) |else_expr| { | |
| 840 | try walkExpression(w, else_expr); | |
| 904 | 841 | } |
| 905 | 842 | } |
| 906 | 843 | |
| 907 | 844 | fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void { |
| 908 | 845 | try walkParamList(w, for_node.ast.inputs); |
| 909 | if (for_node.ast.then_expr != 0) { | |
| 910 | try walkExpression(w, for_node.ast.then_expr); | |
| 911 | } | |
| 912 | if (for_node.ast.else_expr != 0) { | |
| 913 | try walkExpression(w, for_node.ast.else_expr); | |
| 846 | try walkExpression(w, for_node.ast.then_expr); | |
| 847 | if (for_node.ast.else_expr.unwrap()) |else_expr| { | |
| 848 | try walkExpression(w, else_expr); | |
| 914 | 849 | } |
| 915 | 850 | } |
| 916 | 851 | |
| 917 | 852 | fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void { |
| 918 | assert(if_node.ast.cond_expr != 0); | |
| 919 | assert(if_node.ast.then_expr != 0); | |
| 920 | ||
| 921 | 853 | // Perform these transformations in this priority order: |
| 922 | 854 | // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already. |
| 923 | 855 | // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already. |
| 924 | 856 | // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression. |
| 925 | 857 | // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression. |
| 926 | 858 | if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and |
| 927 | (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr))) | |
| 859 | (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?))) | |
| 928 | 860 | { |
| 929 | 861 | try w.transformations.ensureUnusedCapacity(1); |
| 930 | 862 | w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr }); |
| ... | ... | @@ -941,17 +873,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void |
| 941 | 873 | try w.transformations.ensureUnusedCapacity(1); |
| 942 | 874 | w.transformations.appendAssumeCapacity(.{ .replace_node = .{ |
| 943 | 875 | .to_replace = node_index, |
| 944 | .replacement = if_node.ast.else_expr, | |
| 876 | .replacement = if_node.ast.else_expr.unwrap().?, | |
| 945 | 877 | } }); |
| 946 | 878 | } |
| 947 | 879 | |
| 948 | 880 | try walkExpression(w, if_node.ast.cond_expr); // condition |
| 949 | ||
| 950 | if (if_node.ast.then_expr != 0) { | |
| 951 | try walkExpression(w, if_node.ast.then_expr); | |
| 952 | } | |
| 953 | if (if_node.ast.else_expr != 0) { | |
| 954 | try walkExpression(w, if_node.ast.else_expr); | |
| 881 | try walkExpression(w, if_node.ast.then_expr); | |
| 882 | if (if_node.ast.else_expr.unwrap()) |else_expr| { | |
| 883 | try walkExpression(w, else_expr); | |
| 955 | 884 | } |
| 956 | 885 | } |
| 957 | 886 | |
| ... | ... | @@ -971,25 +900,13 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void { |
| 971 | 900 | /// Check if it is already gutted (i.e. its body replaced with `@trap()`). |
| 972 | 901 | fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool { |
| 973 | 902 | // skip over discards |
| 974 | const node_tags = ast.nodes.items(.tag); | |
| 975 | const datas = ast.nodes.items(.data); | |
| 976 | 903 | var statements_buf: [2]Ast.Node.Index = undefined; |
| 977 | const statements = switch (node_tags[body_node]) { | |
| 904 | const statements = switch (ast.nodeTag(body_node)) { | |
| 978 | 905 | .block_two, |
| 979 | 906 | .block_two_semicolon, |
| 980 | => blk: { | |
| 981 | statements_buf[0..2].* = .{ datas[body_node].lhs, datas[body_node].rhs }; | |
| 982 | break :blk if (datas[body_node].lhs == 0) | |
| 983 | statements_buf[0..0] | |
| 984 | else if (datas[body_node].rhs == 0) | |
| 985 | statements_buf[0..1] | |
| 986 | else | |
| 987 | statements_buf[0..2]; | |
| 988 | }, | |
| 989 | ||
| 990 | 907 | .block, |
| 991 | 908 | .block_semicolon, |
| 992 | => ast.extra_data[datas[body_node].lhs..datas[body_node].rhs], | |
| 909 | => ast.blockStatements(&statements_buf, body_node).?, | |
| 993 | 910 | |
| 994 | 911 | else => return false, |
| 995 | 912 | }; |
| ... | ... | @@ -1012,27 +929,20 @@ const StmtCategory = enum { |
| 1012 | 929 | }; |
| 1013 | 930 | |
| 1014 | 931 | fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory { |
| 1015 | const node_tags = ast.nodes.items(.tag); | |
| 1016 | const datas = ast.nodes.items(.data); | |
| 1017 | const main_tokens = ast.nodes.items(.main_token); | |
| 1018 | switch (node_tags[stmt]) { | |
| 1019 | .builtin_call_two, .builtin_call_two_comma => { | |
| 1020 | if (datas[stmt].lhs == 0) { | |
| 1021 | return categorizeBuiltinCall(ast, main_tokens[stmt], &.{}); | |
| 1022 | } else if (datas[stmt].rhs == 0) { | |
| 1023 | return categorizeBuiltinCall(ast, main_tokens[stmt], &.{datas[stmt].lhs}); | |
| 1024 | } else { | |
| 1025 | return categorizeBuiltinCall(ast, main_tokens[stmt], &.{ datas[stmt].lhs, datas[stmt].rhs }); | |
| 1026 | } | |
| 1027 | }, | |
| 1028 | .builtin_call, .builtin_call_comma => { | |
| 1029 | const params = ast.extra_data[datas[stmt].lhs..datas[stmt].rhs]; | |
| 1030 | return categorizeBuiltinCall(ast, main_tokens[stmt], params); | |
| 932 | switch (ast.nodeTag(stmt)) { | |
| 933 | .builtin_call_two, | |
| 934 | .builtin_call_two_comma, | |
| 935 | .builtin_call, | |
| 936 | .builtin_call_comma, | |
| 937 | => { | |
| 938 | var buf: [2]Ast.Node.Index = undefined; | |
| 939 | const params = ast.builtinCallParams(&buf, stmt).?; | |
| 940 | return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params); | |
| 1031 | 941 | }, |
| 1032 | 942 | .assign => { |
| 1033 | const infix = datas[stmt]; | |
| 1034 | if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) { | |
| 1035 | const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]); | |
| 943 | const lhs, const rhs = ast.nodeData(stmt).node_and_node; | |
| 944 | if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) { | |
| 945 | const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs)); | |
| 1036 | 946 | if (std.mem.eql(u8, name_bytes, "undefined")) { |
| 1037 | 947 | return .discard_undefined; |
| 1038 | 948 | } else { |
| ... | ... | @@ -1074,11 +984,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool { |
| 1074 | 984 | } |
| 1075 | 985 | |
| 1076 | 986 | fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool { |
| 1077 | const node_tags = ast.nodes.items(.tag); | |
| 1078 | const main_tokens = ast.nodes.items(.main_token); | |
| 1079 | switch (node_tags[node]) { | |
| 987 | switch (ast.nodeTag(node)) { | |
| 1080 | 988 | .identifier => { |
| 1081 | const token_index = main_tokens[node]; | |
| 989 | const token_index = ast.nodeMainToken(node); | |
| 1082 | 990 | const name_bytes = ast.tokenSlice(token_index); |
| 1083 | 991 | return std.mem.eql(u8, name_bytes, string); |
| 1084 | 992 | }, |
| ... | ... | @@ -1087,11 +995,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo |
| 1087 | 995 | } |
| 1088 | 996 | |
| 1089 | 997 | fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool { |
| 1090 | const node_tags = ast.nodes.items(.tag); | |
| 1091 | const node_data = ast.nodes.items(.data); | |
| 1092 | switch (node_tags[node]) { | |
| 998 | switch (ast.nodeTag(node)) { | |
| 1093 | 999 | .block_two => { |
| 1094 | return node_data[node].lhs == 0 and node_data[node].rhs == 0; | |
| 1000 | const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node; | |
| 1001 | return opt_lhs == .none and opt_rhs == .none; | |
| 1095 | 1002 | }, |
| 1096 | 1003 | else => return false, |
| 1097 | 1004 | } |
lib/docs/wasm/Decl.zig+30-60| ... | ... | @@ -15,8 +15,7 @@ parent: Index, |
| 15 | 15 | pub const ExtraInfo = struct { |
| 16 | 16 | is_pub: bool, |
| 17 | 17 | name: []const u8, |
| 18 | /// This might not be a doc_comment token in which case there are no doc comments. | |
| 19 | first_doc_comment: Ast.TokenIndex, | |
| 18 | first_doc_comment: Ast.OptionalTokenIndex, | |
| 20 | 19 | }; |
| 21 | 20 | |
| 22 | 21 | pub const Index = enum(u32) { |
| ... | ... | @@ -34,16 +33,14 @@ pub fn is_pub(d: *const Decl) bool { |
| 34 | 33 | |
| 35 | 34 | pub fn extra_info(d: *const Decl) ExtraInfo { |
| 36 | 35 | const ast = d.file.get_ast(); |
| 37 | const token_tags = ast.tokens.items(.tag); | |
| 38 | const node_tags = ast.nodes.items(.tag); | |
| 39 | switch (node_tags[d.ast_node]) { | |
| 36 | switch (ast.nodeTag(d.ast_node)) { | |
| 40 | 37 | .root => return .{ |
| 41 | 38 | .name = "", |
| 42 | 39 | .is_pub = true, |
| 43 | .first_doc_comment = if (token_tags[0] == .container_doc_comment) | |
| 44 | 0 | |
| 40 | .first_doc_comment = if (ast.tokenTag(0) == .container_doc_comment) | |
| 41 | .fromToken(0) | |
| 45 | 42 | else |
| 46 | token_tags.len - 1, | |
| 43 | .none, | |
| 47 | 44 | }, |
| 48 | 45 | |
| 49 | 46 | .global_var_decl, |
| ... | ... | @@ -53,7 +50,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo { |
| 53 | 50 | => { |
| 54 | 51 | const var_decl = ast.fullVarDecl(d.ast_node).?; |
| 55 | 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 | 54 | const ident_name = ast.tokenSlice(name_token); |
| 58 | 55 | return .{ |
| 59 | 56 | .name = ident_name, |
| ... | ... | @@ -71,7 +68,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo { |
| 71 | 68 | var buf: [1]Ast.Node.Index = undefined; |
| 72 | 69 | const fn_proto = ast.fullFnProto(&buf, d.ast_node).?; |
| 73 | 70 | const name_token = fn_proto.name_token.?; |
| 74 | assert(token_tags[name_token] == .identifier); | |
| 71 | assert(ast.tokenTag(name_token) == .identifier); | |
| 75 | 72 | const ident_name = ast.tokenSlice(name_token); |
| 76 | 73 | return .{ |
| 77 | 74 | .name = ident_name, |
| ... | ... | @@ -89,9 +86,7 @@ pub fn extra_info(d: *const Decl) ExtraInfo { |
| 89 | 86 | |
| 90 | 87 | pub fn value_node(d: *const Decl) ?Ast.Node.Index { |
| 91 | 88 | const ast = d.file.get_ast(); |
| 92 | const node_tags = ast.nodes.items(.tag); | |
| 93 | const token_tags = ast.tokens.items(.tag); | |
| 94 | return switch (node_tags[d.ast_node]) { | |
| 89 | return switch (ast.nodeTag(d.ast_node)) { | |
| 95 | 90 | .fn_proto, |
| 96 | 91 | .fn_proto_multi, |
| 97 | 92 | .fn_proto_one, |
| ... | ... | @@ -106,8 +101,8 @@ pub fn value_node(d: *const Decl) ?Ast.Node.Index { |
| 106 | 101 | .aligned_var_decl, |
| 107 | 102 | => { |
| 108 | 103 | const var_decl = ast.fullVarDecl(d.ast_node).?; |
| 109 | if (token_tags[var_decl.ast.mut_token] == .keyword_const) | |
| 110 | return var_decl.ast.init_node; | |
| 104 | if (ast.tokenTag(var_decl.ast.mut_token) == .keyword_const) | |
| 105 | return var_decl.ast.init_node.unwrap(); | |
| 111 | 106 | |
| 112 | 107 | return null; |
| 113 | 108 | }, |
| ... | ... | @@ -148,19 +143,12 @@ pub fn get_child(decl: *const Decl, name: []const u8) ?Decl.Index { |
| 148 | 143 | pub fn get_type_fn_return_type_fn(decl: *const Decl) ?Decl.Index { |
| 149 | 144 | if (decl.get_type_fn_return_expr()) |return_expr| { |
| 150 | 145 | const ast = decl.file.get_ast(); |
| 151 | const node_tags = ast.nodes.items(.tag); | |
| 152 | ||
| 153 | switch (node_tags[return_expr]) { | |
| 154 | .call, .call_comma, .call_one, .call_one_comma => { | |
| 155 | const node_data = ast.nodes.items(.data); | |
| 156 | const function = node_data[return_expr].lhs; | |
| 157 | const token = ast.nodes.items(.main_token)[function]; | |
| 158 | const name = ast.tokenSlice(token); | |
| 159 | if (decl.lookup(name)) |function_decl| { | |
| 160 | return function_decl; | |
| 161 | } | |
| 162 | }, | |
| 163 | else => {}, | |
| 146 | var buffer: [1]Ast.Node.Index = undefined; | |
| 147 | const call = ast.fullCall(&buffer, return_expr) orelse return null; | |
| 148 | const token = ast.nodeMainToken(call.ast.fn_expr); | |
| 149 | const name = ast.tokenSlice(token); | |
| 150 | if (decl.lookup(name)) |function_decl| { | |
| 151 | return function_decl; | |
| 164 | 152 | } |
| 165 | 153 | } |
| 166 | 154 | return null; |
| ... | ... | @@ -171,35 +159,18 @@ pub fn get_type_fn_return_expr(decl: *const Decl) ?Ast.Node.Index { |
| 171 | 159 | switch (decl.categorize()) { |
| 172 | 160 | .type_function => { |
| 173 | 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; | |
| 178 | 162 | |
| 179 | switch (node_tags[body_node]) { | |
| 180 | .block, .block_semicolon => { | |
| 181 | const statements = ast.extra_data[node_data[body_node].lhs..node_data[body_node].rhs]; | |
| 182 | // Look for the return statement | |
| 183 | for (statements) |stmt| { | |
| 184 | if (node_tags[stmt] == .@"return") { | |
| 185 | return node_data[stmt].lhs; | |
| 186 | } | |
| 187 | } | |
| 188 | return null; | |
| 189 | }, | |
| 190 | .block_two, .block_two_semicolon => { | |
| 191 | if (node_tags[node_data[body_node].lhs] == .@"return") { | |
| 192 | return node_data[node_data[body_node].lhs].lhs; | |
| 193 | } | |
| 194 | if (node_data[body_node].rhs != 0 and | |
| 195 | node_tags[node_data[body_node].rhs] == .@"return") | |
| 196 | { | |
| 197 | return node_data[node_data[body_node].rhs].lhs; | |
| 198 | } | |
| 199 | return null; | |
| 200 | }, | |
| 201 | else => return null, | |
| 163 | const body_node = ast.nodeData(decl.ast_node).node_and_node[1]; | |
| 164 | ||
| 165 | var buf: [2]Ast.Node.Index = undefined; | |
| 166 | const statements = ast.blockStatements(&buf, body_node) orelse return null; | |
| 167 | ||
| 168 | for (statements) |stmt| { | |
| 169 | if (ast.nodeTag(stmt) == .@"return") { | |
| 170 | return ast.nodeData(stmt).node; | |
| 171 | } | |
| 202 | 172 | } |
| 173 | return null; | |
| 203 | 174 | }, |
| 204 | 175 | else => return null, |
| 205 | 176 | } |
| ... | ... | @@ -269,16 +240,15 @@ pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) O |
| 269 | 240 | } |
| 270 | 241 | } |
| 271 | 242 | |
| 272 | pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.TokenIndex { | |
| 273 | const token_tags = ast.tokens.items(.tag); | |
| 243 | pub fn findFirstDocComment(ast: *const Ast, token: Ast.TokenIndex) Ast.OptionalTokenIndex { | |
| 274 | 244 | var it = token; |
| 275 | 245 | while (it > 0) { |
| 276 | 246 | it -= 1; |
| 277 | if (token_tags[it] != .doc_comment) { | |
| 278 | return it + 1; | |
| 247 | if (ast.tokenTag(it) != .doc_comment) { | |
| 248 | return .fromToken(it + 1); | |
| 279 | 249 | } |
| 280 | 250 | } |
| 281 | return it; | |
| 251 | return .none; | |
| 282 | 252 | } |
| 283 | 253 | |
| 284 | 254 | /// Successively looks up each component. |
lib/docs/wasm/Walk.zig+92-134| ... | ... | @@ -91,12 +91,10 @@ pub const File = struct { |
| 91 | 91 | |
| 92 | 92 | pub fn categorize_decl(file_index: File.Index, node: Ast.Node.Index) Category { |
| 93 | 93 | const ast = file_index.get_ast(); |
| 94 | const node_tags = ast.nodes.items(.tag); | |
| 95 | const token_tags = ast.tokens.items(.tag); | |
| 96 | switch (node_tags[node]) { | |
| 94 | switch (ast.nodeTag(node)) { | |
| 97 | 95 | .root => { |
| 98 | 96 | for (ast.rootDecls()) |member| { |
| 99 | switch (node_tags[member]) { | |
| 97 | switch (ast.nodeTag(member)) { | |
| 100 | 98 | .container_field_init, |
| 101 | 99 | .container_field_align, |
| 102 | 100 | .container_field, |
| ... | ... | @@ -113,10 +111,12 @@ pub const File = struct { |
| 113 | 111 | .aligned_var_decl, |
| 114 | 112 | => { |
| 115 | 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 | 115 | return .{ .global_variable = node }; |
| 116 | const init_node = var_decl.ast.init_node.unwrap() orelse | |
| 117 | return .{ .global_const = node }; | |
| 118 | 118 | |
| 119 | return categorize_expr(file_index, var_decl.ast.init_node); | |
| 119 | return categorize_expr(file_index, init_node); | |
| 120 | 120 | }, |
| 121 | 121 | |
| 122 | 122 | .fn_proto, |
| ... | ... | @@ -139,7 +139,7 @@ pub const File = struct { |
| 139 | 139 | node: Ast.Node.Index, |
| 140 | 140 | full: Ast.full.FnProto, |
| 141 | 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 | 143 | .namespace, .container, .error_set, .type_type => .{ .type_function = node }, |
| 144 | 144 | else => .{ .function = node }, |
| 145 | 145 | }; |
| ... | ... | @@ -155,12 +155,8 @@ pub const File = struct { |
| 155 | 155 | pub fn categorize_expr(file_index: File.Index, node: Ast.Node.Index) Category { |
| 156 | 156 | const file = file_index.get(); |
| 157 | 157 | const ast = file_index.get_ast(); |
| 158 | const node_tags = ast.nodes.items(.tag); | |
| 159 | const node_datas = ast.nodes.items(.data); | |
| 160 | const main_tokens = ast.nodes.items(.main_token); | |
| 161 | const token_tags = ast.tokens.items(.tag); | |
| 162 | //log.debug("categorize_expr tag {s}", .{@tagName(node_tags[node])}); | |
| 163 | return switch (node_tags[node]) { | |
| 158 | //log.debug("categorize_expr tag {s}", .{@tagName(ast.nodeTag(node))}); | |
| 159 | return switch (ast.nodeTag(node)) { | |
| 164 | 160 | .container_decl, |
| 165 | 161 | .container_decl_trailing, |
| 166 | 162 | .container_decl_arg, |
| ... | ... | @@ -176,11 +172,11 @@ pub const File = struct { |
| 176 | 172 | => { |
| 177 | 173 | var buf: [2]Ast.Node.Index = undefined; |
| 178 | 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 | 176 | return .{ .container = node }; |
| 181 | 177 | } |
| 182 | 178 | for (container_decl.ast.members) |member| { |
| 183 | switch (node_tags[member]) { | |
| 179 | switch (ast.nodeTag(member)) { | |
| 184 | 180 | .container_field_init, |
| 185 | 181 | .container_field_align, |
| 186 | 182 | .container_field, |
| ... | ... | @@ -196,7 +192,7 @@ pub const File = struct { |
| 196 | 192 | => .{ .error_set = node }, |
| 197 | 193 | |
| 198 | 194 | .identifier => { |
| 199 | const name_token = ast.nodes.items(.main_token)[node]; | |
| 195 | const name_token = ast.nodeMainToken(node); | |
| 200 | 196 | const ident_name = ast.tokenSlice(name_token); |
| 201 | 197 | if (std.mem.eql(u8, ident_name, "type")) |
| 202 | 198 | return .type_type; |
| ... | ... | @@ -217,9 +213,7 @@ pub const File = struct { |
| 217 | 213 | }, |
| 218 | 214 | |
| 219 | 215 | .field_access => { |
| 220 | const object_node = node_datas[node].lhs; | |
| 221 | const dot_token = main_tokens[node]; | |
| 222 | const field_ident = dot_token + 1; | |
| 216 | const object_node, const field_ident = ast.nodeData(node).node_and_token; | |
| 223 | 217 | const field_name = ast.tokenSlice(field_ident); |
| 224 | 218 | |
| 225 | 219 | switch (categorize_expr(file_index, object_node)) { |
| ... | ... | @@ -232,20 +226,13 @@ pub const File = struct { |
| 232 | 226 | return .{ .global_const = node }; |
| 233 | 227 | }, |
| 234 | 228 | |
| 235 | .builtin_call_two, .builtin_call_two_comma => { | |
| 236 | if (node_datas[node].lhs == 0) { | |
| 237 | const params = [_]Ast.Node.Index{}; | |
| 238 | return categorize_builtin_call(file_index, node, &params); | |
| 239 | } else if (node_datas[node].rhs == 0) { | |
| 240 | const params = [_]Ast.Node.Index{node_datas[node].lhs}; | |
| 241 | return categorize_builtin_call(file_index, node, &params); | |
| 242 | } else { | |
| 243 | const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 244 | return categorize_builtin_call(file_index, node, &params); | |
| 245 | } | |
| 246 | }, | |
| 247 | .builtin_call, .builtin_call_comma => { | |
| 248 | const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 229 | .builtin_call_two, | |
| 230 | .builtin_call_two_comma, | |
| 231 | .builtin_call, | |
| 232 | .builtin_call_comma, | |
| 233 | => { | |
| 234 | var buf: [2]Ast.Node.Index = undefined; | |
| 235 | const params = ast.builtinCallParams(&buf, node).?; | |
| 249 | 236 | return categorize_builtin_call(file_index, node, params); |
| 250 | 237 | }, |
| 251 | 238 | |
| ... | ... | @@ -266,9 +253,9 @@ pub const File = struct { |
| 266 | 253 | .@"if", |
| 267 | 254 | => { |
| 268 | 255 | const if_full = ast.fullIf(node).?; |
| 269 | if (if_full.ast.else_expr != 0) { | |
| 256 | if (if_full.ast.else_expr.unwrap()) |else_expr| { | |
| 270 | 257 | const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr); |
| 271 | const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr); | |
| 258 | const else_cat = categorize_expr_deep(file_index, else_expr); | |
| 272 | 259 | if (then_cat == .type_type and else_cat == .type_type) { |
| 273 | 260 | return .type_type; |
| 274 | 261 | } else if (then_cat == .error_set and else_cat == .error_set) { |
| ... | ... | @@ -327,11 +314,10 @@ pub const File = struct { |
| 327 | 314 | params: []const Ast.Node.Index, |
| 328 | 315 | ) Category { |
| 329 | 316 | const ast = file_index.get_ast(); |
| 330 | const main_tokens = ast.nodes.items(.main_token); | |
| 331 | const builtin_token = main_tokens[node]; | |
| 317 | const builtin_token = ast.nodeMainToken(node); | |
| 332 | 318 | const builtin_name = ast.tokenSlice(builtin_token); |
| 333 | 319 | if (std.mem.eql(u8, builtin_name, "@import")) { |
| 334 | const str_lit_token = main_tokens[params[0]]; | |
| 320 | const str_lit_token = ast.nodeMainToken(params[0]); | |
| 335 | 321 | const str_bytes = ast.tokenSlice(str_lit_token); |
| 336 | 322 | const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM"); |
| 337 | 323 | defer gpa.free(file_path); |
| ... | ... | @@ -364,14 +350,12 @@ pub const File = struct { |
| 364 | 350 | |
| 365 | 351 | fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category { |
| 366 | 352 | const ast = file_index.get_ast(); |
| 367 | const node_datas = ast.nodes.items(.data); | |
| 368 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 369 | const case_nodes = ast.extra_data[extra.start..extra.end]; | |
| 353 | const full = ast.fullSwitch(node).?; | |
| 370 | 354 | var all_type_type = true; |
| 371 | 355 | var all_error_set = true; |
| 372 | 356 | var any_type = false; |
| 373 | if (case_nodes.len == 0) return .{ .global_const = node }; | |
| 374 | for (case_nodes) |case_node| { | |
| 357 | if (full.ast.cases.len == 0) return .{ .global_const = node }; | |
| 358 | for (full.ast.cases) |case_node| { | |
| 375 | 359 | const case = ast.fullSwitchCase(case_node).?; |
| 376 | 360 | switch (categorize_expr_deep(file_index, case.ast.target_expr)) { |
| 377 | 361 | .type_type => { |
| ... | ... | @@ -417,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index { |
| 417 | 401 | const scope = try gpa.create(Scope); |
| 418 | 402 | scope.* = .{ .tag = .top }; |
| 419 | 403 | |
| 420 | const decl_index = try file_index.add_decl(0, .none); | |
| 421 | try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot()); | |
| 404 | const decl_index = try file_index.add_decl(.root, .none); | |
| 405 | try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot()); | |
| 422 | 406 | |
| 423 | 407 | const file = file_index.get(); |
| 424 | 408 | shrinkToFit(&file.ident_decls); |
| ... | ... | @@ -512,13 +496,12 @@ pub const Scope = struct { |
| 512 | 496 | } |
| 513 | 497 | |
| 514 | 498 | pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index { |
| 515 | const main_tokens = ast.nodes.items(.main_token); | |
| 516 | 499 | var it: *Scope = start_scope; |
| 517 | 500 | while (true) switch (it.tag) { |
| 518 | 501 | .top => break, |
| 519 | 502 | .local => { |
| 520 | 503 | const local: *Local = @alignCast(@fieldParentPtr("base", it)); |
| 521 | const name_token = main_tokens[local.var_node] + 1; | |
| 504 | const name_token = ast.nodeMainToken(local.var_node) + 1; | |
| 522 | 505 | const ident_name = ast.tokenSlice(name_token); |
| 523 | 506 | if (std.mem.eql(u8, ident_name, name)) { |
| 524 | 507 | return local.var_node; |
| ... | ... | @@ -545,8 +528,6 @@ fn struct_decl( |
| 545 | 528 | container_decl: Ast.full.ContainerDecl, |
| 546 | 529 | ) Oom!void { |
| 547 | 530 | const ast = w.file.get_ast(); |
| 548 | const node_tags = ast.nodes.items(.tag); | |
| 549 | const node_datas = ast.nodes.items(.data); | |
| 550 | 531 | |
| 551 | 532 | const namespace = try gpa.create(Scope.Namespace); |
| 552 | 533 | namespace.* = .{ |
| ... | ... | @@ -556,7 +537,7 @@ fn struct_decl( |
| 556 | 537 | try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base); |
| 557 | 538 | try w.scanDecls(namespace, container_decl.ast.members); |
| 558 | 539 | |
| 559 | for (container_decl.ast.members) |member| switch (node_tags[member]) { | |
| 540 | for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) { | |
| 560 | 541 | .container_field_init, |
| 561 | 542 | .container_field_align, |
| 562 | 543 | .container_field, |
| ... | ... | @@ -576,7 +557,7 @@ fn struct_decl( |
| 576 | 557 | try w.file.get().doctests.put(gpa, member, doctest_node); |
| 577 | 558 | } |
| 578 | 559 | const decl_index = try w.file.add_decl(member, parent_decl); |
| 579 | const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0; | |
| 560 | const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none; | |
| 580 | 561 | try w.fn_decl(&namespace.base, decl_index, body, full); |
| 581 | 562 | }, |
| 582 | 563 | |
| ... | ... | @@ -591,9 +572,9 @@ fn struct_decl( |
| 591 | 572 | |
| 592 | 573 | .@"comptime", |
| 593 | 574 | .@"usingnamespace", |
| 594 | => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs), | |
| 575 | => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node), | |
| 595 | 576 | |
| 596 | .test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs), | |
| 577 | .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]), | |
| 597 | 578 | |
| 598 | 579 | else => unreachable, |
| 599 | 580 | }; |
| ... | ... | @@ -640,13 +621,13 @@ fn fn_decl( |
| 640 | 621 | w: *Walk, |
| 641 | 622 | scope: *Scope, |
| 642 | 623 | parent_decl: Decl.Index, |
| 643 | body: Ast.Node.Index, | |
| 624 | body: Ast.Node.OptionalIndex, | |
| 644 | 625 | full: Ast.full.FnProto, |
| 645 | 626 | ) Oom!void { |
| 646 | 627 | for (full.ast.params) |param| { |
| 647 | 628 | try expr(w, scope, parent_decl, param); |
| 648 | 629 | } |
| 649 | try expr(w, scope, parent_decl, full.ast.return_type); | |
| 630 | try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?); | |
| 650 | 631 | try maybe_expr(w, scope, parent_decl, full.ast.align_expr); |
| 651 | 632 | try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr); |
| 652 | 633 | try maybe_expr(w, scope, parent_decl, full.ast.section_expr); |
| ... | ... | @@ -654,17 +635,13 @@ fn fn_decl( |
| 654 | 635 | try maybe_expr(w, scope, parent_decl, body); |
| 655 | 636 | } |
| 656 | 637 | |
| 657 | fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void { | |
| 658 | if (node != 0) return expr(w, scope, parent_decl, node); | |
| 638 | fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.OptionalIndex) Oom!void { | |
| 639 | if (node.unwrap()) |n| return expr(w, scope, parent_decl, n); | |
| 659 | 640 | } |
| 660 | 641 | |
| 661 | 642 | fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void { |
| 662 | assert(node != 0); | |
| 663 | 643 | const ast = w.file.get_ast(); |
| 664 | const node_tags = ast.nodes.items(.tag); | |
| 665 | const node_datas = ast.nodes.items(.data); | |
| 666 | const main_tokens = ast.nodes.items(.main_token); | |
| 667 | switch (node_tags[node]) { | |
| 644 | switch (ast.nodeTag(node)) { | |
| 668 | 645 | .root => unreachable, // Top-level declaration. |
| 669 | 646 | .@"usingnamespace" => unreachable, // Top-level declaration. |
| 670 | 647 | .test_decl => unreachable, // Top-level declaration. |
| ... | ... | @@ -745,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 745 | 722 | .array_access, |
| 746 | 723 | .switch_range, |
| 747 | 724 | => { |
| 748 | try expr(w, scope, parent_decl, node_datas[node].lhs); | |
| 749 | try expr(w, scope, parent_decl, node_datas[node].rhs); | |
| 725 | const lhs, const rhs = ast.nodeData(node).node_and_node; | |
| 726 | try expr(w, scope, parent_decl, lhs); | |
| 727 | try expr(w, scope, parent_decl, rhs); | |
| 750 | 728 | }, |
| 751 | 729 | |
| 752 | 730 | .assign_destructure => { |
| ... | ... | @@ -759,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 759 | 737 | .bit_not, |
| 760 | 738 | .negation, |
| 761 | 739 | .negation_wrap, |
| 762 | .@"return", | |
| 763 | 740 | .deref, |
| 764 | 741 | .address_of, |
| 765 | 742 | .optional_type, |
| 766 | .unwrap_optional, | |
| 767 | .grouped_expression, | |
| 768 | 743 | .@"comptime", |
| 769 | 744 | .@"nosuspend", |
| 770 | 745 | .@"suspend", |
| 771 | 746 | .@"await", |
| 772 | 747 | .@"resume", |
| 773 | 748 | .@"try", |
| 774 | => try maybe_expr(w, scope, parent_decl, node_datas[node].lhs), | |
| 749 | => try expr(w, scope, parent_decl, ast.nodeData(node).node), | |
| 750 | .unwrap_optional, | |
| 751 | .grouped_expression, | |
| 752 | => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]), | |
| 753 | .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node), | |
| 775 | 754 | |
| 776 | .anyframe_type, | |
| 777 | .@"break", | |
| 778 | => try maybe_expr(w, scope, parent_decl, node_datas[node].rhs), | |
| 755 | .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]), | |
| 756 | .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]), | |
| 779 | 757 | |
| 780 | 758 | .identifier => { |
| 781 | const ident_token = main_tokens[node]; | |
| 759 | const ident_token = ast.nodeMainToken(node); | |
| 782 | 760 | const ident_name = ast.tokenSlice(ident_token); |
| 783 | 761 | if (scope.lookup(ast, ident_name)) |var_node| { |
| 784 | 762 | try w.file.get().ident_decls.put(gpa, ident_token, var_node); |
| 785 | 763 | } |
| 786 | 764 | }, |
| 787 | 765 | .field_access => { |
| 788 | const object_node = node_datas[node].lhs; | |
| 789 | const dot_token = main_tokens[node]; | |
| 790 | const field_ident = dot_token + 1; | |
| 766 | const object_node, const field_ident = ast.nodeData(node).node_and_token; | |
| 791 | 767 | try w.file.get().token_parents.put(gpa, field_ident, node); |
| 792 | 768 | // This will populate the left-most field object if it is an |
| 793 | 769 | // identifier, allowing rendering code to piece together the link. |
| ... | ... | @@ -818,20 +794,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 818 | 794 | try expr(w, scope, parent_decl, full.ast.template); |
| 819 | 795 | }, |
| 820 | 796 | |
| 821 | .builtin_call_two, .builtin_call_two_comma => { | |
| 822 | if (node_datas[node].lhs == 0) { | |
| 823 | const params = [_]Ast.Node.Index{}; | |
| 824 | return builtin_call(w, scope, parent_decl, node, &params); | |
| 825 | } else if (node_datas[node].rhs == 0) { | |
| 826 | const params = [_]Ast.Node.Index{node_datas[node].lhs}; | |
| 827 | return builtin_call(w, scope, parent_decl, node, &params); | |
| 828 | } else { | |
| 829 | const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 830 | return builtin_call(w, scope, parent_decl, node, &params); | |
| 831 | } | |
| 832 | }, | |
| 833 | .builtin_call, .builtin_call_comma => { | |
| 834 | const params = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 797 | .builtin_call_two, | |
| 798 | .builtin_call_two_comma, | |
| 799 | .builtin_call, | |
| 800 | .builtin_call_comma, | |
| 801 | => { | |
| 802 | var buf: [2]Ast.Node.Index = undefined; | |
| 803 | const params = ast.builtinCallParams(&buf, node).?; | |
| 835 | 804 | return builtin_call(w, scope, parent_decl, node, params); |
| 836 | 805 | }, |
| 837 | 806 | |
| ... | ... | @@ -871,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 871 | 840 | .for_simple, .@"for" => { |
| 872 | 841 | const full = ast.fullFor(node).?; |
| 873 | 842 | for (full.ast.inputs) |input| { |
| 874 | if (node_tags[input] == .for_range) { | |
| 875 | try expr(w, scope, parent_decl, node_datas[input].lhs); | |
| 876 | try maybe_expr(w, scope, parent_decl, node_datas[input].rhs); | |
| 843 | if (ast.nodeTag(input) == .for_range) { | |
| 844 | const start, const end = ast.nodeData(input).node_and_opt_node; | |
| 845 | try expr(w, scope, parent_decl, start); | |
| 846 | try maybe_expr(w, scope, parent_decl, end); | |
| 877 | 847 | } else { |
| 878 | 848 | try expr(w, scope, parent_decl, input); |
| 879 | 849 | } |
| ... | ... | @@ -886,18 +856,13 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 886 | 856 | .slice_open => return slice(w, scope, parent_decl, ast.sliceOpen(node)), |
| 887 | 857 | .slice_sentinel => return slice(w, scope, parent_decl, ast.sliceSentinel(node)), |
| 888 | 858 | |
| 889 | .block_two, .block_two_semicolon => { | |
| 890 | const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 891 | if (node_datas[node].lhs == 0) { | |
| 892 | return block(w, scope, parent_decl, statements[0..0]); | |
| 893 | } else if (node_datas[node].rhs == 0) { | |
| 894 | return block(w, scope, parent_decl, statements[0..1]); | |
| 895 | } else { | |
| 896 | return block(w, scope, parent_decl, statements[0..2]); | |
| 897 | } | |
| 898 | }, | |
| 899 | .block, .block_semicolon => { | |
| 900 | const statements = ast.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 859 | .block_two, | |
| 860 | .block_two_semicolon, | |
| 861 | .block, | |
| 862 | .block_semicolon, | |
| 863 | => { | |
| 864 | var buf: [2]Ast.Node.Index = undefined; | |
| 865 | const statements = ast.blockStatements(&buf, node).?; | |
| 901 | 866 | return block(w, scope, parent_decl, statements); |
| 902 | 867 | }, |
| 903 | 868 | |
| ... | ... | @@ -933,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 933 | 898 | }, |
| 934 | 899 | |
| 935 | 900 | .array_type_sentinel => { |
| 936 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 937 | try expr(w, scope, parent_decl, node_datas[node].lhs); | |
| 901 | const len_expr, const extra_index = ast.nodeData(node).node_and_extra; | |
| 902 | const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 903 | try expr(w, scope, parent_decl, len_expr); | |
| 938 | 904 | try expr(w, scope, parent_decl, extra.elem_type); |
| 939 | 905 | try expr(w, scope, parent_decl, extra.sentinel); |
| 940 | 906 | }, |
| 941 | 907 | .@"switch", .switch_comma => { |
| 942 | const operand_node = node_datas[node].lhs; | |
| 943 | try expr(w, scope, parent_decl, operand_node); | |
| 944 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 945 | const case_nodes = ast.extra_data[extra.start..extra.end]; | |
| 946 | for (case_nodes) |case_node| { | |
| 908 | const full = ast.fullSwitch(node).?; | |
| 909 | try expr(w, scope, parent_decl, full.ast.condition); | |
| 910 | for (full.ast.cases) |case_node| { | |
| 947 | 911 | const case = ast.fullSwitchCase(case_node).?; |
| 948 | 912 | for (case.ast.values) |value_node| { |
| 949 | 913 | try expr(w, scope, parent_decl, value_node); |
| ... | ... | @@ -992,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 992 | 956 | .fn_proto, |
| 993 | 957 | => { |
| 994 | 958 | var buf: [1]Ast.Node.Index = undefined; |
| 995 | return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?); | |
| 959 | return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?); | |
| 996 | 960 | }, |
| 997 | 961 | } |
| 998 | 962 | } |
| ... | ... | @@ -1012,8 +976,7 @@ fn builtin_call( |
| 1012 | 976 | params: []const Ast.Node.Index, |
| 1013 | 977 | ) Oom!void { |
| 1014 | 978 | const ast = w.file.get_ast(); |
| 1015 | const main_tokens = ast.nodes.items(.main_token); | |
| 1016 | const builtin_token = main_tokens[node]; | |
| 979 | const builtin_token = ast.nodeMainToken(node); | |
| 1017 | 980 | const builtin_name = ast.tokenSlice(builtin_token); |
| 1018 | 981 | if (std.mem.eql(u8, builtin_name, "@This")) { |
| 1019 | 982 | try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl()); |
| ... | ... | @@ -1031,13 +994,11 @@ fn block( |
| 1031 | 994 | statements: []const Ast.Node.Index, |
| 1032 | 995 | ) Oom!void { |
| 1033 | 996 | const ast = w.file.get_ast(); |
| 1034 | const node_tags = ast.nodes.items(.tag); | |
| 1035 | const node_datas = ast.nodes.items(.data); | |
| 1036 | 997 | |
| 1037 | 998 | var scope = parent_scope; |
| 1038 | 999 | |
| 1039 | 1000 | for (statements) |node| { |
| 1040 | switch (node_tags[node]) { | |
| 1001 | switch (ast.nodeTag(node)) { | |
| 1041 | 1002 | .global_var_decl, |
| 1042 | 1003 | .local_var_decl, |
| 1043 | 1004 | .simple_var_decl, |
| ... | ... | @@ -1058,11 +1019,10 @@ fn block( |
| 1058 | 1019 | log.debug("walk assign_destructure not implemented yet", .{}); |
| 1059 | 1020 | }, |
| 1060 | 1021 | |
| 1061 | .grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs), | |
| 1022 | .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]), | |
| 1062 | 1023 | |
| 1063 | .@"defer", | |
| 1064 | .@"errdefer", | |
| 1065 | => try expr(w, scope, parent_decl, node_datas[node].rhs), | |
| 1024 | .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node), | |
| 1025 | .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]), | |
| 1066 | 1026 | |
| 1067 | 1027 | else => try expr(w, scope, parent_decl, node), |
| 1068 | 1028 | } |
| ... | ... | @@ -1078,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W |
| 1078 | 1038 | |
| 1079 | 1039 | fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void { |
| 1080 | 1040 | const ast = w.file.get_ast(); |
| 1081 | const node_tags = ast.nodes.items(.tag); | |
| 1082 | const main_tokens = ast.nodes.items(.main_token); | |
| 1083 | const token_tags = ast.tokens.items(.tag); | |
| 1084 | const node_datas = ast.nodes.items(.data); | |
| 1085 | 1041 | |
| 1086 | 1042 | for (members) |member_node| { |
| 1087 | const name_token = switch (node_tags[member_node]) { | |
| 1043 | const name_token = switch (ast.nodeTag(member_node)) { | |
| 1088 | 1044 | .global_var_decl, |
| 1089 | 1045 | .local_var_decl, |
| 1090 | 1046 | .simple_var_decl, |
| 1091 | 1047 | .aligned_var_decl, |
| 1092 | => main_tokens[member_node] + 1, | |
| 1048 | => ast.nodeMainToken(member_node) + 1, | |
| 1093 | 1049 | |
| 1094 | 1050 | .fn_proto_simple, |
| 1095 | 1051 | .fn_proto_multi, |
| ... | ... | @@ -1097,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In |
| 1097 | 1053 | .fn_proto, |
| 1098 | 1054 | .fn_decl, |
| 1099 | 1055 | => blk: { |
| 1100 | const ident = main_tokens[member_node] + 1; | |
| 1101 | if (token_tags[ident] != .identifier) continue; | |
| 1056 | const ident = ast.nodeMainToken(member_node) + 1; | |
| 1057 | if (ast.tokenTag(ident) != .identifier) continue; | |
| 1102 | 1058 | break :blk ident; |
| 1103 | 1059 | }, |
| 1104 | 1060 | |
| 1105 | 1061 | .test_decl => { |
| 1106 | const ident_token = node_datas[member_node].lhs; | |
| 1107 | const is_doctest = token_tags[ident_token] == .identifier; | |
| 1108 | if (is_doctest) { | |
| 1109 | const token_bytes = ast.tokenSlice(ident_token); | |
| 1110 | try namespace.doctests.put(gpa, token_bytes, member_node); | |
| 1062 | const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0]; | |
| 1063 | if (opt_ident_token.unwrap()) |ident_token| { | |
| 1064 | const is_doctest = ast.tokenTag(ident_token) == .identifier; | |
| 1065 | if (is_doctest) { | |
| 1066 | const token_bytes = ast.tokenSlice(ident_token); | |
| 1067 | try namespace.doctests.put(gpa, token_bytes, member_node); | |
| 1068 | } | |
| 1111 | 1069 | } |
| 1112 | 1070 | continue; |
| 1113 | 1071 | }, |
lib/docs/wasm/html_render.zig+9-18| ... | ... | @@ -41,14 +41,10 @@ pub fn fileSourceHtml( |
| 41 | 41 | var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty; |
| 42 | 42 | }; |
| 43 | 43 | |
| 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 | 44 | const start_token = ast.firstToken(root_node); |
| 49 | 45 | const end_token = ast.lastToken(root_node) + 1; |
| 50 | 46 | |
| 51 | var cursor: usize = token_starts[start_token]; | |
| 47 | var cursor: usize = ast.tokenStart(start_token); | |
| 52 | 48 | |
| 53 | 49 | var indent: usize = 0; |
| 54 | 50 | if (std.mem.lastIndexOf(u8, ast.source[0..cursor], "\n")) |newline_index| { |
| ... | ... | @@ -64,8 +60,8 @@ pub fn fileSourceHtml( |
| 64 | 60 | var next_annotate_index: usize = 0; |
| 65 | 61 | |
| 66 | 62 | for ( |
| 67 | token_tags[start_token..end_token], | |
| 68 | token_starts[start_token..end_token], | |
| 63 | ast.tokens.items(.tag)[start_token..end_token], | |
| 64 | ast.tokens.items(.start)[start_token..end_token], | |
| 69 | 65 | start_token.., |
| 70 | 66 | ) |tag, start, token_index| { |
| 71 | 67 | const between = ast.source[cursor..start]; |
| ... | ... | @@ -184,7 +180,7 @@ pub fn fileSourceHtml( |
| 184 | 180 | .identifier => i: { |
| 185 | 181 | if (options.fn_link != .none) { |
| 186 | 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 | 184 | if (token_index == fn_token + 1) { |
| 189 | 185 | try out.appendSlice(gpa, "<a class=\"tok-fn\" href=\"#"); |
| 190 | 186 | _ = missing_feature_url_escape; |
| ... | ... | @@ -196,7 +192,7 @@ pub fn fileSourceHtml( |
| 196 | 192 | } |
| 197 | 193 | } |
| 198 | 194 | |
| 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 | 196 | try out.appendSlice(gpa, "<span class=\"tok-fn\">"); |
| 201 | 197 | try appendEscaped(out, slice); |
| 202 | 198 | try out.appendSlice(gpa, "</span>"); |
| ... | ... | @@ -358,16 +354,11 @@ fn walkFieldAccesses( |
| 358 | 354 | node: Ast.Node.Index, |
| 359 | 355 | ) Oom!void { |
| 360 | 356 | const ast = file_index.get_ast(); |
| 361 | const node_tags = ast.nodes.items(.tag); | |
| 362 | assert(node_tags[node] == .field_access); | |
| 363 | const node_datas = ast.nodes.items(.data); | |
| 364 | const main_tokens = ast.nodes.items(.main_token); | |
| 365 | const object_node = node_datas[node].lhs; | |
| 366 | const dot_token = main_tokens[node]; | |
| 367 | const field_ident = dot_token + 1; | |
| 368 | switch (node_tags[object_node]) { | |
| 357 | assert(ast.nodeTag(node) == .field_access); | |
| 358 | const object_node, const field_ident = ast.nodeData(node).node_and_token; | |
| 359 | switch (ast.nodeTag(object_node)) { | |
| 369 | 360 | .identifier => { |
| 370 | const lhs_ident = main_tokens[object_node]; | |
| 361 | const lhs_ident = ast.nodeMainToken(object_node); | |
| 371 | 362 | try resolveIdentLink(file_index, out, lhs_ident); |
| 372 | 363 | }, |
| 373 | 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 | 124 | @memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items); |
| 125 | 125 | |
| 126 | 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 | } | |
| 128 | 130 | |
| 129 | 131 | if (ignore_case) { |
| 130 | 132 | ascii_lower(g.full_path_search_text_lower.items); |
| ... | ... | @@ -227,18 +229,15 @@ const ErrorIdentifier = packed struct(u64) { |
| 227 | 229 | fn hasDocs(ei: ErrorIdentifier) bool { |
| 228 | 230 | const decl_index = ei.decl_index; |
| 229 | 231 | const ast = decl_index.get().file.get_ast(); |
| 230 | const token_tags = ast.tokens.items(.tag); | |
| 231 | 232 | const token_index = ei.token_index; |
| 232 | 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 | } |
| 235 | 236 | |
| 236 | 237 | fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void { |
| 237 | 238 | const decl_index = ei.decl_index; |
| 238 | 239 | const ast = decl_index.get().file.get_ast(); |
| 239 | 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 | 241 | const has_link = base_decl != decl_index; |
| 243 | 242 | |
| 244 | 243 | try out.appendSlice(gpa, "<dt>"); |
| ... | ... | @@ -253,7 +252,7 @@ const ErrorIdentifier = packed struct(u64) { |
| 253 | 252 | } |
| 254 | 253 | try out.appendSlice(gpa, "</dt>"); |
| 255 | 254 | |
| 256 | if (has_docs) { | |
| 255 | if (Decl.findFirstDocComment(ast, ei.token_index).unwrap()) |first_doc_comment| { | |
| 257 | 256 | try out.appendSlice(gpa, "<dd>"); |
| 258 | 257 | try render_docs(out, decl_index, first_doc_comment, false); |
| 259 | 258 | try out.appendSlice(gpa, "</dd>"); |
| ... | ... | @@ -319,17 +318,16 @@ fn addErrorsFromExpr( |
| 319 | 318 | ) Oom!void { |
| 320 | 319 | const decl = decl_index.get(); |
| 321 | 320 | const ast = decl.file.get_ast(); |
| 322 | const node_tags = ast.nodes.items(.tag); | |
| 323 | const node_datas = ast.nodes.items(.data); | |
| 324 | 321 | |
| 325 | 322 | switch (decl.file.categorize_expr(node)) { |
| 326 | .error_set => |n| switch (node_tags[n]) { | |
| 323 | .error_set => |n| switch (ast.nodeTag(n)) { | |
| 327 | 324 | .error_set_decl => { |
| 328 | 325 | try addErrorsFromNode(decl_index, out, node); |
| 329 | 326 | }, |
| 330 | 327 | .merge_error_sets => { |
| 331 | try addErrorsFromExpr(decl_index, out, node_datas[node].lhs); | |
| 332 | try addErrorsFromExpr(decl_index, out, node_datas[node].rhs); | |
| 328 | const lhs, const rhs = ast.nodeData(n).node_and_node; | |
| 329 | try addErrorsFromExpr(decl_index, out, lhs); | |
| 330 | try addErrorsFromExpr(decl_index, out, rhs); | |
| 333 | 331 | }, |
| 334 | 332 | else => unreachable, |
| 335 | 333 | }, |
| ... | ... | @@ -347,11 +345,9 @@ fn addErrorsFromNode( |
| 347 | 345 | ) Oom!void { |
| 348 | 346 | const decl = decl_index.get(); |
| 349 | 347 | const ast = decl.file.get_ast(); |
| 350 | const main_tokens = ast.nodes.items(.main_token); | |
| 351 | const token_tags = ast.tokens.items(.tag); | |
| 352 | const error_token = main_tokens[node]; | |
| 348 | const error_token = ast.nodeMainToken(node); | |
| 353 | 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 | 351 | .doc_comment, .comma => {}, |
| 356 | 352 | .identifier => { |
| 357 | 353 | const name = ast.tokenSlice(tok_i); |
| ... | ... | @@ -391,15 +387,13 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 391 | 387 | |
| 392 | 388 | switch (decl.categorize()) { |
| 393 | 389 | .type_function => { |
| 394 | const node_tags = ast.nodes.items(.tag); | |
| 395 | ||
| 396 | 390 | // If the type function returns a reference to another type function, get the fields from there |
| 397 | 391 | if (decl.get_type_fn_return_type_fn()) |function_decl| { |
| 398 | 392 | return decl_fields_fallible(function_decl); |
| 399 | 393 | } |
| 400 | 394 | // If the type function returns a container, such as a `struct`, read that container's fields |
| 401 | 395 | if (decl.get_type_fn_return_expr()) |return_expr| { |
| 402 | switch (node_tags[return_expr]) { | |
| 396 | switch (ast.nodeTag(return_expr)) { | |
| 403 | 397 | .container_decl, .container_decl_trailing, .container_decl_two, .container_decl_two_trailing, .container_decl_arg, .container_decl_arg_trailing => { |
| 404 | 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 | 414 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; |
| 421 | 415 | }; |
| 422 | 416 | g.result.clearRetainingCapacity(); |
| 423 | const node_tags = ast.nodes.items(.tag); | |
| 424 | 417 | var buf: [2]Ast.Node.Index = undefined; |
| 425 | 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 | 420 | .container_field_init, |
| 428 | 421 | .container_field_align, |
| 429 | 422 | .container_field, |
| ... | ... | @@ -478,9 +471,8 @@ fn decl_field_html_fallible( |
| 478 | 471 | try out.appendSlice(gpa, "</code></pre>"); |
| 479 | 472 | |
| 480 | 473 | const field = ast.fullContainerField(field_node).?; |
| 481 | const first_doc_comment = Decl.findFirstDocComment(ast, field.firstToken()); | |
| 482 | 474 | |
| 483 | if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) { | |
| 475 | if (Decl.findFirstDocComment(ast, field.firstToken()).unwrap()) |first_doc_comment| { | |
| 484 | 476 | try out.appendSlice(gpa, "<div class=\"fieldDocs\">"); |
| 485 | 477 | try render_docs(out, decl_index, first_doc_comment, false); |
| 486 | 478 | try out.appendSlice(gpa, "</div>"); |
| ... | ... | @@ -494,14 +486,13 @@ fn decl_param_html_fallible( |
| 494 | 486 | ) !void { |
| 495 | 487 | const decl = decl_index.get(); |
| 496 | 488 | const ast = decl.file.get_ast(); |
| 497 | const token_tags = ast.tokens.items(.tag); | |
| 498 | 489 | const colon = ast.firstToken(param_node) - 1; |
| 499 | 490 | const name_token = colon - 1; |
| 500 | 491 | const first_doc_comment = f: { |
| 501 | 492 | var it = ast.firstToken(param_node); |
| 502 | 493 | while (it > 0) { |
| 503 | 494 | it -= 1; |
| 504 | switch (token_tags[it]) { | |
| 495 | switch (ast.tokenTag(it)) { | |
| 505 | 496 | .doc_comment, .colon, .identifier, .keyword_comptime, .keyword_noalias => {}, |
| 506 | 497 | else => break, |
| 507 | 498 | } |
| ... | ... | @@ -516,7 +507,7 @@ fn decl_param_html_fallible( |
| 516 | 507 | try fileSourceHtml(decl.file, out, param_node, .{}); |
| 517 | 508 | try out.appendSlice(gpa, "</code></pre>"); |
| 518 | 509 | |
| 519 | if (ast.tokens.items(.tag)[first_doc_comment] == .doc_comment) { | |
| 510 | if (ast.tokenTag(first_doc_comment) == .doc_comment) { | |
| 520 | 511 | try out.appendSlice(gpa, "<div class=\"fieldDocs\">"); |
| 521 | 512 | try render_docs(out, decl_index, first_doc_comment, false); |
| 522 | 513 | try out.appendSlice(gpa, "</div>"); |
| ... | ... | @@ -526,10 +517,8 @@ fn decl_param_html_fallible( |
| 526 | 517 | export fn decl_fn_proto_html(decl_index: Decl.Index, linkify_fn_name: bool) String { |
| 527 | 518 | const decl = decl_index.get(); |
| 528 | 519 | const ast = decl.file.get_ast(); |
| 529 | const node_tags = ast.nodes.items(.tag); | |
| 530 | const node_datas = ast.nodes.items(.data); | |
| 531 | const proto_node = switch (node_tags[decl.ast_node]) { | |
| 532 | .fn_decl => node_datas[decl.ast_node].lhs, | |
| 520 | const proto_node = switch (ast.nodeTag(decl.ast_node)) { | |
| 521 | .fn_decl => ast.nodeData(decl.ast_node).node_and_node[0], | |
| 533 | 522 | |
| 534 | 523 | .fn_proto, |
| 535 | 524 | .fn_proto_one, |
| ... | ... | @@ -586,17 +575,16 @@ export fn decl_parent(decl_index: Decl.Index) Decl.Index { |
| 586 | 575 | return decl.parent; |
| 587 | 576 | } |
| 588 | 577 | |
| 589 | export fn fn_error_set(decl_index: Decl.Index) Ast.Node.Index { | |
| 578 | export fn fn_error_set(decl_index: Decl.Index) Ast.Node.OptionalIndex { | |
| 590 | 579 | const decl = decl_index.get(); |
| 591 | 580 | const ast = decl.file.get_ast(); |
| 592 | 581 | var buf: [1]Ast.Node.Index = undefined; |
| 593 | 582 | const full = ast.fullFnProto(&buf, decl.ast_node).?; |
| 594 | const node_tags = ast.nodes.items(.tag); | |
| 595 | const node_datas = ast.nodes.items(.data); | |
| 596 | return switch (node_tags[full.ast.return_type]) { | |
| 597 | .error_set_decl => full.ast.return_type, | |
| 598 | .error_union => node_datas[full.ast.return_type].lhs, | |
| 599 | else => 0, | |
| 583 | const return_type = full.ast.return_type.unwrap().?; | |
| 584 | return switch (ast.nodeTag(return_type)) { | |
| 585 | .error_set_decl => return_type.toOptional(), | |
| 586 | .error_union => ast.nodeData(return_type).node_and_node[0].toOptional(), | |
| 587 | else => .none, | |
| 600 | 588 | }; |
| 601 | 589 | } |
| 602 | 590 | |
| ... | ... | @@ -609,21 +597,19 @@ export fn decl_file_path(decl_index: Decl.Index) String { |
| 609 | 597 | export fn decl_category_name(decl_index: Decl.Index) String { |
| 610 | 598 | const decl = decl_index.get(); |
| 611 | 599 | const ast = decl.file.get_ast(); |
| 612 | const token_tags = ast.tokens.items(.tag); | |
| 613 | 600 | const name = switch (decl.categorize()) { |
| 614 | 601 | .namespace, .container => |node| { |
| 615 | const node_tags = ast.nodes.items(.tag); | |
| 616 | if (node_tags[decl.ast_node] == .root) | |
| 602 | if (ast.nodeTag(decl.ast_node) == .root) | |
| 617 | 603 | return String.init("struct"); |
| 618 | 604 | string_result.clearRetainingCapacity(); |
| 619 | 605 | var buf: [2]Ast.Node.Index = undefined; |
| 620 | 606 | const container_decl = ast.fullContainerDecl(&buf, node).?; |
| 621 | 607 | if (container_decl.layout_token) |t| { |
| 622 | if (token_tags[t] == .keyword_extern) { | |
| 608 | if (ast.tokenTag(t) == .keyword_extern) { | |
| 623 | 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 | 613 | string_result.appendSlice(gpa, main_token_tag.lexeme().?) catch @panic("OOM"); |
| 628 | 614 | return String.init(string_result.items); |
| 629 | 615 | }, |
| ... | ... | @@ -656,7 +642,9 @@ export fn decl_name(decl_index: Decl.Index) String { |
| 656 | 642 | export fn decl_docs_html(decl_index: Decl.Index, short: bool) String { |
| 657 | 643 | const decl = decl_index.get(); |
| 658 | 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 | 648 | return String.init(string_result.items); |
| 661 | 649 | } |
| 662 | 650 | |
| ... | ... | @@ -665,10 +653,9 @@ fn collect_docs( |
| 665 | 653 | ast: *const Ast, |
| 666 | 654 | first_doc_comment: Ast.TokenIndex, |
| 667 | 655 | ) Oom!void { |
| 668 | const token_tags = ast.tokens.items(.tag); | |
| 669 | 656 | list.clearRetainingCapacity(); |
| 670 | 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 | 659 | .doc_comment, .container_doc_comment => { |
| 673 | 660 | // It is tempting to trim this string but think carefully about how |
| 674 | 661 | // that will affect the markdown parser. |
| ... | ... | @@ -687,12 +674,11 @@ fn render_docs( |
| 687 | 674 | ) Oom!void { |
| 688 | 675 | const decl = decl_index.get(); |
| 689 | 676 | const ast = decl.file.get_ast(); |
| 690 | const token_tags = ast.tokens.items(.tag); | |
| 691 | 677 | |
| 692 | 678 | var parser = try markdown.Parser.init(gpa); |
| 693 | 679 | defer parser.deinit(); |
| 694 | 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 | 682 | .doc_comment, .container_doc_comment => { |
| 697 | 683 | const line = ast.tokenSlice(it)[3..]; |
| 698 | 684 | if (short and line.len == 0) break; |
| ... | ... | @@ -767,9 +753,9 @@ export fn decl_type_html(decl_index: Decl.Index) String { |
| 767 | 753 | t: { |
| 768 | 754 | // If there is an explicit type, use it. |
| 769 | 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 | 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 | 759 | .skip_comments = true, |
| 774 | 760 | .collapse_whitespace = true, |
| 775 | 761 | }) catch |e| { |
lib/std/zig/Ast.zig+1681-1229| ... | ... | @@ -8,15 +8,12 @@ |
| 8 | 8 | source: [:0]const u8, |
| 9 | 9 | |
| 10 | 10 | tokens: 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. | |
| 13 | 11 | nodes: NodeList.Slice, |
| 14 | extra_data: []Node.Index, | |
| 12 | extra_data: []u32, | |
| 15 | 13 | mode: Mode = .zig, |
| 16 | 14 | |
| 17 | 15 | errors: []const Error, |
| 18 | 16 | |
| 19 | pub const TokenIndex = u32; | |
| 20 | 17 | pub const ByteOffset = u32; |
| 21 | 18 | |
| 22 | 19 | pub const TokenList = std.MultiArrayList(struct { |
| ... | ... | @@ -25,6 +22,91 @@ pub const TokenList = std.MultiArrayList(struct { |
| 25 | 22 | }); |
| 26 | 23 | pub const NodeList = std.MultiArrayList(Node); |
| 27 | 24 | |
| 25 | /// Index into `tokens`. | |
| 26 | pub const TokenIndex = u32; | |
| 27 | ||
| 28 | /// Index into `tokens`, or null. | |
| 29 | pub 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. | |
| 47 | pub 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. | |
| 69 | pub 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 | ||
| 78 | pub fn tokenTag(tree: *const Ast, token_index: TokenIndex) Token.Tag { | |
| 79 | return tree.tokens.items(.tag)[token_index]; | |
| 80 | } | |
| 81 | ||
| 82 | pub fn tokenStart(tree: *const Ast, token_index: TokenIndex) ByteOffset { | |
| 83 | return tree.tokens.items(.start)[token_index]; | |
| 84 | } | |
| 85 | ||
| 86 | pub fn nodeTag(tree: *const Ast, node: Node.Index) Node.Tag { | |
| 87 | return tree.nodes.items(.tag)[@intFromEnum(node)]; | |
| 88 | } | |
| 89 | ||
| 90 | pub fn nodeMainToken(tree: *const Ast, node: Node.Index) TokenIndex { | |
| 91 | return tree.nodes.items(.main_token)[@intFromEnum(node)]; | |
| 92 | } | |
| 93 | ||
| 94 | pub fn nodeData(tree: *const Ast, node: Node.Index) Node.Data { | |
| 95 | return tree.nodes.items(.data)[@intFromEnum(node)]; | |
| 96 | } | |
| 97 | ||
| 98 | pub 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 | ||
| 28 | 110 | pub const Location = struct { |
| 29 | 111 | line: usize, |
| 30 | 112 | column: usize, |
| ... | ... | @@ -77,8 +159,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A |
| 77 | 159 | var parser: Parse = .{ |
| 78 | 160 | .source = source, |
| 79 | 161 | .gpa = gpa, |
| 80 | .token_tags = tokens.items(.tag), | |
| 81 | .token_starts = tokens.items(.start), | |
| 162 | .tokens = tokens.slice(), | |
| 82 | 163 | .errors = .{}, |
| 83 | 164 | .nodes = .{}, |
| 84 | 165 | .extra_data = .{}, |
| ... | ... | @@ -143,7 +224,7 @@ pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenInde |
| 143 | 224 | .line_start = start_offset, |
| 144 | 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); | |
| 147 | 228 | |
| 148 | 229 | // Scan to by line until we go past the token start |
| 149 | 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 | 256 | } |
| 176 | 257 | |
| 177 | 258 | pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 { |
| 178 | const token_starts = tree.tokens.items(.start); | |
| 179 | const token_tags = tree.tokens.items(.tag); | |
| 180 | const token_tag = token_tags[token_index]; | |
| 259 | const token_tag = tree.tokenTag(token_index); | |
| 181 | 260 | |
| 182 | 261 | // Many tokens can be determined entirely by their tag. |
| 183 | 262 | if (token_tag.lexeme()) |lexeme| { |
| ... | ... | @@ -187,33 +266,54 @@ pub fn tokenSlice(tree: Ast, token_index: TokenIndex) []const u8 { |
| 187 | 266 | // For some tokens, re-tokenization is needed to find the end. |
| 188 | 267 | var tokenizer: std.zig.Tokenizer = .{ |
| 189 | 268 | .buffer = tree.source, |
| 190 | .index = token_starts[token_index], | |
| 269 | .index = tree.tokenStart(token_index), | |
| 191 | 270 | }; |
| 192 | 271 | const token = tokenizer.next(); |
| 193 | 272 | assert(token.tag == token_tag); |
| 194 | 273 | return tree.source[token.loc.start..token.loc.end]; |
| 195 | 274 | } |
| 196 | 275 | |
| 197 | pub fn extraData(tree: Ast, index: usize, comptime T: type) T { | |
| 276 | pub 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 | ||
| 280 | pub 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 | ||
| 284 | pub fn extraData(tree: Ast, index: ExtraIndex, comptime T: type) T { | |
| 198 | 285 | const fields = std.meta.fields(T); |
| 199 | 286 | var result: T = undefined; |
| 200 | 287 | inline for (fields, 0..) |field, i| { |
| 201 | comptime assert(field.type == Node.Index); | |
| 202 | @field(result, field.name) = tree.extra_data[index + i]; | |
| 288 | @field(result, field.name) = switch (field.type) { | |
| 289 | Node.Index, | |
| 290 | Node.OptionalIndex, | |
| 291 | OptionalTokenIndex, | |
| 292 | ExtraIndex, | |
| 293 | => @enumFromInt(tree.extra_data[@intFromEnum(index) + i]), | |
| 294 | TokenIndex => tree.extra_data[@intFromEnum(index) + i], | |
| 295 | else => @compileError("unexpected field type: " ++ @typeName(field.type)), | |
| 296 | }; | |
| 203 | 297 | } |
| 204 | 298 | return result; |
| 205 | 299 | } |
| 206 | 300 | |
| 301 | fn 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 | ||
| 207 | 308 | pub fn rootDecls(tree: Ast) []const Node.Index { |
| 208 | const nodes_data = tree.nodes.items(.data); | |
| 209 | return switch (tree.mode) { | |
| 210 | .zig => tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs], | |
| 211 | .zon => (&nodes_data[0].lhs)[0..1], | |
| 212 | }; | |
| 309 | switch (tree.mode) { | |
| 310 | .zig => return tree.extraDataSlice(tree.nodeData(.root).extra_range, Node.Index), | |
| 311 | // Ensure that the returned slice points into the existing memory of the Ast | |
| 312 | .zon => return (&tree.nodes.items(.data)[@intFromEnum(Node.Index.root)].node)[0..1], | |
| 313 | } | |
| 213 | 314 | } |
| 214 | 315 | |
| 215 | 316 | pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 216 | const token_tags = tree.tokens.items(.tag); | |
| 217 | 317 | switch (parse_error.tag) { |
| 218 | 318 | .asterisk_after_ptr_deref => { |
| 219 | 319 | // 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 | 328 | }, |
| 229 | 329 | .expected_block => { |
| 230 | 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 | 334 | .expected_block_or_assignment => { |
| 235 | 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 | 339 | .expected_block_or_expr => { |
| 240 | 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 | 344 | .expected_block_or_field => { |
| 245 | 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 | 349 | .expected_container_members => { |
| 250 | 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 | 354 | .expected_expr => { |
| 255 | 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 | 359 | .expected_expr_or_assignment => { |
| 260 | 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 | 364 | .expected_expr_or_var_decl => { |
| 265 | 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 | 369 | .expected_fn => { |
| 270 | 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 | 374 | .expected_inlinable => { |
| 275 | 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 | 379 | .expected_labelable => { |
| 280 | 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 | 384 | .expected_param_list => { |
| 285 | 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 | 389 | .expected_prefix_expr => { |
| 290 | 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 | 394 | .expected_primary_type_expr => { |
| 295 | 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 | 399 | .expected_pub_item => { |
| ... | ... | @@ -301,7 +401,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 301 | 401 | }, |
| 302 | 402 | .expected_return_type => { |
| 303 | 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 | 407 | .expected_semi_or_else => { |
| ... | ... | @@ -312,37 +412,37 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 312 | 412 | }, |
| 313 | 413 | .expected_statement => { |
| 314 | 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 | 418 | .expected_suffix_op => { |
| 319 | 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 | 423 | .expected_type_expr => { |
| 324 | 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 | 428 | .expected_var_decl => { |
| 329 | 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 | 433 | .expected_var_decl_or_fn => { |
| 334 | 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 | 438 | .expected_loop_payload => { |
| 339 | 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 | 443 | .expected_container => { |
| 344 | 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 | 448 | .extern_fn_body => { |
| ... | ... | @@ -365,7 +465,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 365 | 465 | }, |
| 366 | 466 | .ptr_mod_on_array_child_type => { |
| 367 | 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 | 471 | .invalid_bit_range => { |
| ... | ... | @@ -421,7 +521,7 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void { |
| 421 | 521 | return stream.writeAll("expected field initializer"); |
| 422 | 522 | }, |
| 423 | 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 | 526 | .invalid_ampersand_ampersand => { |
| 427 | 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 | 572 | }, |
| 473 | 573 | |
| 474 | 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 | 576 | const expected_symbol = parse_error.extra.expected_tag.symbol(); |
| 477 | 577 | switch (found_tag) { |
| 478 | 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 | 587 | } |
| 488 | 588 | |
| 489 | 589 | pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 490 | const tags = tree.nodes.items(.tag); | |
| 491 | const datas = tree.nodes.items(.data); | |
| 492 | const main_tokens = tree.nodes.items(.main_token); | |
| 493 | const token_tags = tree.tokens.items(.tag); | |
| 494 | var end_offset: TokenIndex = 0; | |
| 590 | var end_offset: u32 = 0; | |
| 495 | 591 | var n = node; |
| 496 | while (true) switch (tags[n]) { | |
| 592 | while (true) switch (tree.nodeTag(n)) { | |
| 497 | 593 | .root => return 0, |
| 498 | 594 | |
| 499 | 595 | .test_decl, |
| ... | ... | @@ -537,7 +633,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 537 | 633 | .array_type, |
| 538 | 634 | .array_type_sentinel, |
| 539 | 635 | .error_value, |
| 540 | => return main_tokens[n] - end_offset, | |
| 636 | => return tree.nodeMainToken(n) - end_offset, | |
| 541 | 637 | |
| 542 | 638 | .array_init_dot, |
| 543 | 639 | .array_init_dot_comma, |
| ... | ... | @@ -548,11 +644,9 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 548 | 644 | .struct_init_dot_two, |
| 549 | 645 | .struct_init_dot_two_comma, |
| 550 | 646 | .enum_literal, |
| 551 | => return main_tokens[n] - 1 - end_offset, | |
| 647 | => return tree.nodeMainToken(n) - 1 - end_offset, | |
| 552 | 648 | |
| 553 | 649 | .@"catch", |
| 554 | .field_access, | |
| 555 | .unwrap_optional, | |
| 556 | 650 | .equal_equal, |
| 557 | 651 | .bang_equal, |
| 558 | 652 | .less_than, |
| ... | ... | @@ -601,33 +695,37 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 601 | 695 | .bool_and, |
| 602 | 696 | .bool_or, |
| 603 | 697 | .slice_open, |
| 604 | .slice, | |
| 605 | .slice_sentinel, | |
| 606 | .deref, | |
| 607 | 698 | .array_access, |
| 608 | 699 | .array_init_one, |
| 609 | 700 | .array_init_one_comma, |
| 610 | .array_init, | |
| 611 | .array_init_comma, | |
| 701 | .switch_range, | |
| 702 | .error_union, | |
| 703 | => n = tree.nodeData(n).node_and_node[0], | |
| 704 | ||
| 705 | .for_range, | |
| 706 | .call_one, | |
| 707 | .call_one_comma, | |
| 612 | 708 | .struct_init_one, |
| 613 | 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 | 720 | .struct_init, |
| 615 | 721 | .struct_init_comma, |
| 616 | .call_one, | |
| 617 | .call_one_comma, | |
| 618 | 722 | .call, |
| 619 | 723 | .call_comma, |
| 620 | .switch_range, | |
| 621 | .for_range, | |
| 622 | .error_union, | |
| 623 | => n = datas[n].lhs, | |
| 724 | => n = tree.nodeData(n).node_and_extra[0], | |
| 624 | 725 | |
| 625 | .assign_destructure => { | |
| 626 | const extra_idx = datas[n].lhs; | |
| 627 | const lhs_len = tree.extra_data[extra_idx]; | |
| 628 | assert(lhs_len > 0); | |
| 629 | n = tree.extra_data[extra_idx + 1]; | |
| 630 | }, | |
| 726 | .deref => n = tree.nodeData(n).node, | |
| 727 | ||
| 728 | .assign_destructure => n = tree.assignDestructure(n).ast.variables[0], | |
| 631 | 729 | |
| 632 | 730 | .fn_decl, |
| 633 | 731 | .fn_proto_simple, |
| ... | ... | @@ -635,10 +733,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 635 | 733 | .fn_proto_one, |
| 636 | 734 | .fn_proto, |
| 637 | 735 | => { |
| 638 | var i = main_tokens[n]; // fn token | |
| 736 | var i = tree.nodeMainToken(n); // fn token | |
| 639 | 737 | while (i > 0) { |
| 640 | 738 | i -= 1; |
| 641 | switch (token_tags[i]) { | |
| 739 | switch (tree.tokenTag(i)) { | |
| 642 | 740 | .keyword_extern, |
| 643 | 741 | .keyword_export, |
| 644 | 742 | .keyword_pub, |
| ... | ... | @@ -654,30 +752,33 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 654 | 752 | }, |
| 655 | 753 | |
| 656 | 754 | .@"usingnamespace" => { |
| 657 | const main_token = main_tokens[n]; | |
| 658 | if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) { | |
| 659 | end_offset += 1; | |
| 660 | } | |
| 755 | const main_token: TokenIndex = tree.nodeMainToken(n); | |
| 756 | const has_visib_token = tree.isTokenPrecededByTags(main_token, &.{.keyword_pub}); | |
| 757 | end_offset += @intFromBool(has_visib_token); | |
| 661 | 758 | return main_token - end_offset; |
| 662 | 759 | }, |
| 663 | 760 | |
| 664 | 761 | .async_call_one, |
| 665 | 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 | 768 | .async_call, |
| 667 | 769 | .async_call_comma, |
| 668 | 770 | => { |
| 669 | 771 | end_offset += 1; // async token |
| 670 | n = datas[n].lhs; | |
| 772 | n = tree.nodeData(n).node_and_extra[0]; | |
| 671 | 773 | }, |
| 672 | 774 | |
| 673 | 775 | .container_field_init, |
| 674 | 776 | .container_field_align, |
| 675 | 777 | .container_field, |
| 676 | 778 | => { |
| 677 | const name_token = main_tokens[n]; | |
| 678 | if (name_token > 0 and token_tags[name_token - 1] == .keyword_comptime) { | |
| 679 | end_offset += 1; | |
| 680 | } | |
| 779 | const name_token = tree.nodeMainToken(n); | |
| 780 | const has_comptime_token = tree.isTokenPrecededByTags(name_token, &.{.keyword_comptime}); | |
| 781 | end_offset += @intFromBool(has_comptime_token); | |
| 681 | 782 | return name_token - end_offset; |
| 682 | 783 | }, |
| 683 | 784 | |
| ... | ... | @@ -686,10 +787,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 686 | 787 | .simple_var_decl, |
| 687 | 788 | .aligned_var_decl, |
| 688 | 789 | => { |
| 689 | var i = main_tokens[n]; // mut token | |
| 790 | var i = tree.nodeMainToken(n); // mut token | |
| 690 | 791 | while (i > 0) { |
| 691 | 792 | i -= 1; |
| 692 | switch (token_tags[i]) { | |
| 793 | switch (tree.tokenTag(i)) { | |
| 693 | 794 | .keyword_extern, |
| 694 | 795 | .keyword_export, |
| 695 | 796 | .keyword_comptime, |
| ... | ... | @@ -710,10 +811,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 710 | 811 | .block_two_semicolon, |
| 711 | 812 | => { |
| 712 | 813 | // Look for a label. |
| 713 | const lbrace = main_tokens[n]; | |
| 714 | if (token_tags[lbrace - 1] == .colon and | |
| 715 | token_tags[lbrace - 2] == .identifier) | |
| 716 | { | |
| 814 | const lbrace = tree.nodeMainToken(n); | |
| 815 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 717 | 816 | end_offset += 2; |
| 718 | 817 | } |
| 719 | 818 | return lbrace - end_offset; |
| ... | ... | @@ -732,8 +831,8 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 732 | 831 | .tagged_union_enum_tag, |
| 733 | 832 | .tagged_union_enum_tag_trailing, |
| 734 | 833 | => { |
| 735 | const main_token = main_tokens[n]; | |
| 736 | switch (token_tags[main_token -| 1]) { | |
| 834 | const main_token = tree.nodeMainToken(n); | |
| 835 | switch (tree.tokenTag(main_token -| 1)) { | |
| 737 | 836 | .keyword_packed, .keyword_extern => end_offset += 1, |
| 738 | 837 | else => {}, |
| 739 | 838 | } |
| ... | ... | @@ -744,36 +843,26 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 744 | 843 | .ptr_type_sentinel, |
| 745 | 844 | .ptr_type, |
| 746 | 845 | .ptr_type_bit_range, |
| 747 | => return main_tokens[n] - end_offset, | |
| 846 | => return tree.nodeMainToken(n) - end_offset, | |
| 748 | 847 | |
| 749 | .switch_case_one => { | |
| 750 | if (datas[n].lhs == 0) { | |
| 751 | return main_tokens[n] - 1 - end_offset; // else token | |
| 752 | } else { | |
| 753 | n = datas[n].lhs; | |
| 754 | } | |
| 755 | }, | |
| 756 | .switch_case_inline_one => { | |
| 757 | if (datas[n].lhs == 0) { | |
| 758 | return main_tokens[n] - 2 - end_offset; // else token | |
| 848 | .switch_case_one, | |
| 849 | .switch_case_inline_one, | |
| 850 | .switch_case, | |
| 851 | .switch_case_inline, | |
| 852 | => { | |
| 853 | const full_switch = tree.fullSwitchCase(n).?; | |
| 854 | if (full_switch.inline_token) |inline_token| { | |
| 855 | return inline_token; | |
| 856 | } else if (full_switch.ast.values.len == 0) { | |
| 857 | return full_switch.ast.arrow_token - 1 - end_offset; // else token | |
| 759 | 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 | }, | |
| 773 | 862 | |
| 774 | 863 | .asm_output, .asm_input => { |
| 775 | assert(token_tags[main_tokens[n] - 1] == .l_bracket); | |
| 776 | return main_tokens[n] - 1 - end_offset; | |
| 864 | assert(tree.tokenTag(tree.nodeMainToken(n) - 1) == .l_bracket); | |
| 865 | return tree.nodeMainToken(n) - 1 - end_offset; | |
| 777 | 866 | }, |
| 778 | 867 | |
| 779 | 868 | .while_simple, |
| ... | ... | @@ -783,13 +872,13 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 783 | 872 | .@"for", |
| 784 | 873 | => { |
| 785 | 874 | // Look for a label and inline. |
| 786 | const main_token = main_tokens[n]; | |
| 875 | const main_token = tree.nodeMainToken(n); | |
| 787 | 876 | var result = main_token; |
| 788 | if (token_tags[result -| 1] == .keyword_inline) { | |
| 789 | result -= 1; | |
| 877 | if (tree.isTokenPrecededByTags(result, &.{.keyword_inline})) { | |
| 878 | result = result - 1; | |
| 790 | 879 | } |
| 791 | if (token_tags[result -| 1] == .colon) { | |
| 792 | result -|= 2; | |
| 880 | if (tree.isTokenPrecededByTags(result, &.{ .identifier, .colon })) { | |
| 881 | result = result - 2; | |
| 793 | 882 | } |
| 794 | 883 | return result - end_offset; |
| 795 | 884 | }, |
| ... | ... | @@ -797,15 +886,10 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 797 | 886 | } |
| 798 | 887 | |
| 799 | 888 | pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 800 | const tags = tree.nodes.items(.tag); | |
| 801 | const datas = tree.nodes.items(.data); | |
| 802 | const main_tokens = tree.nodes.items(.main_token); | |
| 803 | const token_starts = tree.tokens.items(.start); | |
| 804 | const token_tags = tree.tokens.items(.tag); | |
| 805 | 889 | var n = node; |
| 806 | var end_offset: TokenIndex = 0; | |
| 807 | while (true) switch (tags[n]) { | |
| 808 | .root => return @as(TokenIndex, @intCast(tree.tokens.len - 1)), | |
| 890 | var end_offset: u32 = 0; | |
| 891 | while (true) switch (tree.nodeTag(n)) { | |
| 892 | .root => return @intCast(tree.tokens.len - 1), | |
| 809 | 893 | |
| 810 | 894 | .@"usingnamespace", |
| 811 | 895 | .bool_not, |
| ... | ... | @@ -816,14 +900,12 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 816 | 900 | .@"try", |
| 817 | 901 | .@"await", |
| 818 | 902 | .optional_type, |
| 903 | .@"suspend", | |
| 819 | 904 | .@"resume", |
| 820 | 905 | .@"nosuspend", |
| 821 | 906 | .@"comptime", |
| 822 | => n = datas[n].lhs, | |
| 907 | => n = tree.nodeData(n).node, | |
| 823 | 908 | |
| 824 | .test_decl, | |
| 825 | .@"errdefer", | |
| 826 | .@"defer", | |
| 827 | 909 | .@"catch", |
| 828 | 910 | .equal_equal, |
| 829 | 911 | .bang_equal, |
| ... | ... | @@ -849,7 +931,6 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 849 | 931 | .assign_add_sat, |
| 850 | 932 | .assign_sub_sat, |
| 851 | 933 | .assign, |
| 852 | .assign_destructure, | |
| 853 | 934 | .merge_error_sets, |
| 854 | 935 | .mul, |
| 855 | 936 | .div, |
| ... | ... | @@ -873,41 +954,52 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 873 | 954 | .@"orelse", |
| 874 | 955 | .bool_and, |
| 875 | 956 | .bool_or, |
| 876 | .anyframe_type, | |
| 877 | 957 | .error_union, |
| 878 | 958 | .if_simple, |
| 879 | 959 | .while_simple, |
| 880 | 960 | .for_simple, |
| 881 | .fn_proto_simple, | |
| 882 | .fn_proto_multi, | |
| 961 | .fn_decl, | |
| 962 | .array_type, | |
| 963 | .switch_range, | |
| 964 | => n = tree.nodeData(n).node_and_node[1], | |
| 965 | ||
| 966 | .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1], | |
| 967 | .@"defer" => n = tree.nodeData(n).node, | |
| 968 | .anyframe_type => n = tree.nodeData(n).token_and_node[1], | |
| 969 | ||
| 970 | .switch_case_one, | |
| 971 | .switch_case_inline_one, | |
| 883 | 972 | .ptr_type_aligned, |
| 884 | 973 | .ptr_type_sentinel, |
| 974 | => n = tree.nodeData(n).opt_node_and_node[1], | |
| 975 | ||
| 976 | .assign_destructure, | |
| 885 | 977 | .ptr_type, |
| 886 | 978 | .ptr_type_bit_range, |
| 887 | .array_type, | |
| 888 | .switch_case_one, | |
| 889 | .switch_case_inline_one, | |
| 890 | 979 | .switch_case, |
| 891 | 980 | .switch_case_inline, |
| 892 | .switch_range, | |
| 893 | => n = datas[n].rhs, | |
| 981 | => n = tree.nodeData(n).extra_and_node[1], | |
| 894 | 982 | |
| 895 | .for_range => if (datas[n].rhs != 0) { | |
| 896 | n = datas[n].rhs; | |
| 897 | } else { | |
| 898 | return main_tokens[n] + end_offset; | |
| 983 | .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?, | |
| 984 | .fn_proto_multi, | |
| 985 | .fn_proto_one, | |
| 986 | .fn_proto, | |
| 987 | => n = tree.nodeData(n).extra_and_opt_node[1].unwrap().?, | |
| 988 | ||
| 989 | .for_range => { | |
| 990 | n = tree.nodeData(n).node_and_opt_node[1].unwrap() orelse { | |
| 991 | return tree.nodeMainToken(n) + end_offset; | |
| 992 | }; | |
| 899 | 993 | }, |
| 900 | 994 | |
| 901 | 995 | .field_access, |
| 902 | 996 | .unwrap_optional, |
| 903 | .grouped_expression, | |
| 904 | .multiline_string_literal, | |
| 905 | .error_set_decl, | |
| 906 | 997 | .asm_simple, |
| 907 | .asm_output, | |
| 908 | .asm_input, | |
| 909 | .error_value, | |
| 910 | => return datas[n].rhs + end_offset, | |
| 998 | => return tree.nodeData(n).node_and_token[1] + end_offset, | |
| 999 | .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset, | |
| 1000 | .multiline_string_literal, .error_set_decl => return tree.nodeData(n).token_and_token[1] + end_offset, | |
| 1001 | .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset, | |
| 1002 | .error_value => return tree.nodeMainToken(n) + 2 + end_offset, | |
| 911 | 1003 | |
| 912 | 1004 | .anyframe_literal, |
| 913 | 1005 | .char_literal, |
| ... | ... | @@ -917,82 +1009,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 917 | 1009 | .deref, |
| 918 | 1010 | .enum_literal, |
| 919 | 1011 | .string_literal, |
| 920 | => return main_tokens[n] + end_offset, | |
| 1012 | => return tree.nodeMainToken(n) + end_offset, | |
| 921 | 1013 | |
| 922 | .@"return" => if (datas[n].lhs != 0) { | |
| 923 | n = datas[n].lhs; | |
| 924 | } else { | |
| 925 | return main_tokens[n] + end_offset; | |
| 1014 | .@"return" => { | |
| 1015 | n = tree.nodeData(n).opt_node.unwrap() orelse { | |
| 1016 | return tree.nodeMainToken(n) + end_offset; | |
| 1017 | }; | |
| 926 | 1018 | }, |
| 927 | 1019 | |
| 928 | 1020 | .call, .async_call => { |
| 1021 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1022 | const params = tree.extraData(extra_index, Node.SubRange); | |
| 1023 | assert(params.start != params.end); | |
| 929 | 1024 | end_offset += 1; // for the rparen |
| 930 | const params = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 931 | if (params.end - params.start == 0) { | |
| 932 | return main_tokens[n] + end_offset; | |
| 933 | } | |
| 934 | n = tree.extra_data[params.end - 1]; // last parameter | |
| 1025 | n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter | |
| 935 | 1026 | }, |
| 936 | 1027 | .tagged_union_enum_tag => { |
| 937 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 938 | if (members.end - members.start == 0) { | |
| 1028 | const arg, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1029 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1030 | if (members.start == members.end) { | |
| 939 | 1031 | end_offset += 4; // for the rparen + rparen + lbrace + rbrace |
| 940 | n = datas[n].lhs; | |
| 1032 | n = arg; | |
| 941 | 1033 | } else { |
| 942 | 1034 | end_offset += 1; // for the rbrace |
| 943 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1035 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 944 | 1036 | } |
| 945 | 1037 | }, |
| 946 | 1038 | .call_comma, |
| 947 | 1039 | .async_call_comma, |
| 948 | 1040 | .tagged_union_enum_tag_trailing, |
| 949 | 1041 | => { |
| 1042 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1043 | const params = tree.extraData(extra_index, Node.SubRange); | |
| 1044 | assert(params.start != params.end); | |
| 950 | 1045 | end_offset += 2; // for the comma/semicolon + rparen/rbrace |
| 951 | const params = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 952 | assert(params.end > params.start); | |
| 953 | n = tree.extra_data[params.end - 1]; // last parameter | |
| 1046 | n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter | |
| 954 | 1047 | }, |
| 955 | 1048 | .@"switch" => { |
| 956 | const cases = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 957 | if (cases.end - cases.start == 0) { | |
| 1049 | const condition, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1050 | const cases = tree.extraData(extra_index, Node.SubRange); | |
| 1051 | if (cases.start == cases.end) { | |
| 958 | 1052 | end_offset += 3; // rparen, lbrace, rbrace |
| 959 | n = datas[n].lhs; // condition expression | |
| 1053 | n = condition; | |
| 960 | 1054 | } else { |
| 961 | 1055 | end_offset += 1; // for the rbrace |
| 962 | n = tree.extra_data[cases.end - 1]; // last case | |
| 1056 | n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case | |
| 963 | 1057 | } |
| 964 | 1058 | }, |
| 965 | 1059 | .container_decl_arg => { |
| 966 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 967 | if (members.end - members.start == 0) { | |
| 1060 | const arg, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1061 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1062 | if (members.end == members.start) { | |
| 968 | 1063 | end_offset += 3; // for the rparen + lbrace + rbrace |
| 969 | n = datas[n].lhs; | |
| 1064 | n = arg; | |
| 970 | 1065 | } else { |
| 971 | 1066 | end_offset += 1; // for the rbrace |
| 972 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1067 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 973 | 1068 | } |
| 974 | 1069 | }, |
| 975 | 1070 | .@"asm" => { |
| 976 | const extra = tree.extraData(datas[n].rhs, Node.Asm); | |
| 1071 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1072 | const extra = tree.extraData(extra_index, Node.Asm); | |
| 977 | 1073 | return extra.rparen + end_offset; |
| 978 | 1074 | }, |
| 979 | 1075 | .array_init, |
| 980 | 1076 | .struct_init, |
| 981 | 1077 | => { |
| 982 | const elements = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 983 | assert(elements.end - elements.start > 0); | |
| 1078 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1079 | const elements = tree.extraData(extra_index, Node.SubRange); | |
| 1080 | assert(elements.start != elements.end); | |
| 984 | 1081 | end_offset += 1; // for the rbrace |
| 985 | n = tree.extra_data[elements.end - 1]; // last element | |
| 1082 | n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element | |
| 986 | 1083 | }, |
| 987 | 1084 | .array_init_comma, |
| 988 | 1085 | .struct_init_comma, |
| 989 | 1086 | .container_decl_arg_trailing, |
| 990 | 1087 | .switch_comma, |
| 991 | 1088 | => { |
| 992 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 993 | assert(members.end - members.start > 0); | |
| 1089 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1090 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1091 | assert(members.start != members.end); | |
| 994 | 1092 | end_offset += 2; // for the comma + rbrace |
| 995 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1093 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 996 | 1094 | }, |
| 997 | 1095 | .array_init_dot, |
| 998 | 1096 | .struct_init_dot, |
| ... | ... | @@ -1001,9 +1099,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1001 | 1099 | .tagged_union, |
| 1002 | 1100 | .builtin_call, |
| 1003 | 1101 | => { |
| 1004 | assert(datas[n].rhs - datas[n].lhs > 0); | |
| 1102 | const range = tree.nodeData(n).extra_range; | |
| 1103 | assert(range.start != range.end); | |
| 1005 | 1104 | end_offset += 1; // for the rbrace |
| 1006 | n = tree.extra_data[datas[n].rhs - 1]; // last statement | |
| 1105 | n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement | |
| 1007 | 1106 | }, |
| 1008 | 1107 | .array_init_dot_comma, |
| 1009 | 1108 | .struct_init_dot_comma, |
| ... | ... | @@ -1012,20 +1111,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1012 | 1111 | .tagged_union_trailing, |
| 1013 | 1112 | .builtin_call_comma, |
| 1014 | 1113 | => { |
| 1015 | assert(datas[n].rhs - datas[n].lhs > 0); | |
| 1114 | const range = tree.nodeData(n).extra_range; | |
| 1115 | assert(range.start != range.end); | |
| 1016 | 1116 | end_offset += 2; // for the comma/semicolon + rbrace/rparen |
| 1017 | n = tree.extra_data[datas[n].rhs - 1]; // last member | |
| 1117 | n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member | |
| 1018 | 1118 | }, |
| 1019 | 1119 | .call_one, |
| 1020 | 1120 | .async_call_one, |
| 1021 | .array_access, | |
| 1022 | 1121 | => { |
| 1023 | end_offset += 1; // for the rparen/rbracket | |
| 1024 | if (datas[n].rhs == 0) { | |
| 1025 | return main_tokens[n] + end_offset; | |
| 1026 | } | |
| 1027 | n = datas[n].rhs; | |
| 1122 | _, const first_param = tree.nodeData(n).node_and_opt_node; | |
| 1123 | end_offset += 1; // for the rparen | |
| 1124 | n = first_param.unwrap() orelse { | |
| 1125 | return tree.nodeMainToken(n) + end_offset; | |
| 1126 | }; | |
| 1028 | 1127 | }, |
| 1128 | ||
| 1029 | 1129 | .array_init_dot_two, |
| 1030 | 1130 | .block_two, |
| 1031 | 1131 | .builtin_call_two, |
| ... | ... | @@ -1033,14 +1133,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1033 | 1133 | .container_decl_two, |
| 1034 | 1134 | .tagged_union_two, |
| 1035 | 1135 | => { |
| 1036 | if (datas[n].rhs != 0) { | |
| 1136 | const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; | |
| 1137 | if (opt_rhs.unwrap()) |rhs| { | |
| 1037 | 1138 | end_offset += 1; // for the rparen/rbrace |
| 1038 | n = datas[n].rhs; | |
| 1039 | } else if (datas[n].lhs != 0) { | |
| 1139 | n = rhs; | |
| 1140 | } else if (opt_lhs.unwrap()) |lhs| { | |
| 1040 | 1141 | end_offset += 1; // for the rparen/rbrace |
| 1041 | n = datas[n].lhs; | |
| 1142 | n = lhs; | |
| 1042 | 1143 | } else { |
| 1043 | switch (tags[n]) { | |
| 1144 | switch (tree.nodeTag(n)) { | |
| 1044 | 1145 | .array_init_dot_two, |
| 1045 | 1146 | .block_two, |
| 1046 | 1147 | .struct_init_dot_two, |
| ... | ... | @@ -1048,17 +1149,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1048 | 1149 | .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace |
| 1049 | 1150 | .container_decl_two => { |
| 1050 | 1151 | var i: u32 = 2; // lbrace + rbrace |
| 1051 | while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1; | |
| 1152 | while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; | |
| 1052 | 1153 | end_offset += i; |
| 1053 | 1154 | }, |
| 1054 | 1155 | .tagged_union_two => { |
| 1055 | 1156 | var i: u32 = 5; // (enum) {} |
| 1056 | while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1; | |
| 1157 | while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; | |
| 1057 | 1158 | end_offset += i; |
| 1058 | 1159 | }, |
| 1059 | 1160 | else => unreachable, |
| 1060 | 1161 | } |
| 1061 | return main_tokens[n] + end_offset; | |
| 1162 | return tree.nodeMainToken(n) + end_offset; | |
| 1062 | 1163 | } |
| 1063 | 1164 | }, |
| 1064 | 1165 | .array_init_dot_two_comma, |
| ... | ... | @@ -1068,459 +1169,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1068 | 1169 | .container_decl_two_trailing, |
| 1069 | 1170 | .tagged_union_two_trailing, |
| 1070 | 1171 | => { |
| 1172 | const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; | |
| 1071 | 1173 | end_offset += 2; // for the comma/semicolon + rbrace/rparen |
| 1072 | if (datas[n].rhs != 0) { | |
| 1073 | n = datas[n].rhs; | |
| 1074 | } else if (datas[n].lhs != 0) { | |
| 1075 | n = datas[n].lhs; | |
| 1174 | if (opt_rhs.unwrap()) |rhs| { | |
| 1175 | n = rhs; | |
| 1176 | } else if (opt_lhs.unwrap()) |lhs| { | |
| 1177 | n = lhs; | |
| 1076 | 1178 | } else { |
| 1077 | 1179 | unreachable; |
| 1078 | 1180 | } |
| 1079 | 1181 | }, |
| 1080 | 1182 | .simple_var_decl => { |
| 1081 | if (datas[n].rhs != 0) { | |
| 1082 | n = datas[n].rhs; | |
| 1083 | } else if (datas[n].lhs != 0) { | |
| 1084 | n = datas[n].lhs; | |
| 1183 | const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node; | |
| 1184 | if (init_node.unwrap()) |rhs| { | |
| 1185 | n = rhs; | |
| 1186 | } else if (type_node.unwrap()) |lhs| { | |
| 1187 | n = lhs; | |
| 1085 | 1188 | } else { |
| 1086 | 1189 | end_offset += 1; // from mut token to name |
| 1087 | return main_tokens[n] + end_offset; | |
| 1190 | return tree.nodeMainToken(n) + end_offset; | |
| 1088 | 1191 | } |
| 1089 | 1192 | }, |
| 1090 | 1193 | .aligned_var_decl => { |
| 1091 | if (datas[n].rhs != 0) { | |
| 1092 | n = datas[n].rhs; | |
| 1093 | } else if (datas[n].lhs != 0) { | |
| 1094 | end_offset += 1; // for the rparen | |
| 1095 | n = datas[n].lhs; | |
| 1194 | const align_node, const init_node = tree.nodeData(n).node_and_opt_node; | |
| 1195 | if (init_node.unwrap()) |rhs| { | |
| 1196 | n = rhs; | |
| 1096 | 1197 | } else { |
| 1097 | end_offset += 1; // from mut token to name | |
| 1098 | return main_tokens[n] + end_offset; | |
| 1198 | end_offset += 1; // for the rparen | |
| 1199 | n = align_node; | |
| 1099 | 1200 | } |
| 1100 | 1201 | }, |
| 1101 | 1202 | .global_var_decl => { |
| 1102 | if (datas[n].rhs != 0) { | |
| 1103 | n = datas[n].rhs; | |
| 1203 | const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; | |
| 1204 | if (init_node.unwrap()) |rhs| { | |
| 1205 | n = rhs; | |
| 1104 | 1206 | } else { |
| 1105 | const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl); | |
| 1106 | if (extra.section_node != 0) { | |
| 1207 | const extra = tree.extraData(extra_index, Node.GlobalVarDecl); | |
| 1208 | if (extra.section_node.unwrap()) |section_node| { | |
| 1107 | 1209 | end_offset += 1; // for the rparen |
| 1108 | n = extra.section_node; | |
| 1109 | } else if (extra.align_node != 0) { | |
| 1210 | n = section_node; | |
| 1211 | } else if (extra.align_node.unwrap()) |align_node| { | |
| 1110 | 1212 | end_offset += 1; // for the rparen |
| 1111 | n = extra.align_node; | |
| 1112 | } else if (extra.type_node != 0) { | |
| 1113 | n = extra.type_node; | |
| 1213 | n = align_node; | |
| 1214 | } else if (extra.type_node.unwrap()) |type_node| { | |
| 1215 | n = type_node; | |
| 1114 | 1216 | } else { |
| 1115 | 1217 | end_offset += 1; // from mut token to name |
| 1116 | return main_tokens[n] + end_offset; | |
| 1218 | return tree.nodeMainToken(n) + end_offset; | |
| 1117 | 1219 | } |
| 1118 | 1220 | } |
| 1119 | 1221 | }, |
| 1120 | 1222 | .local_var_decl => { |
| 1121 | if (datas[n].rhs != 0) { | |
| 1122 | n = datas[n].rhs; | |
| 1223 | const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; | |
| 1224 | if (init_node.unwrap()) |rhs| { | |
| 1225 | n = rhs; | |
| 1123 | 1226 | } else { |
| 1124 | const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl); | |
| 1125 | if (extra.align_node != 0) { | |
| 1126 | end_offset += 1; // for the rparen | |
| 1127 | n = extra.align_node; | |
| 1128 | } else if (extra.type_node != 0) { | |
| 1129 | n = extra.type_node; | |
| 1130 | } else { | |
| 1131 | end_offset += 1; // from mut token to name | |
| 1132 | return main_tokens[n] + end_offset; | |
| 1133 | } | |
| 1227 | const extra = tree.extraData(extra_index, Node.LocalVarDecl); | |
| 1228 | end_offset += 1; // for the rparen | |
| 1229 | n = extra.align_node; | |
| 1134 | 1230 | } |
| 1135 | 1231 | }, |
| 1136 | 1232 | .container_field_init => { |
| 1137 | if (datas[n].rhs != 0) { | |
| 1138 | n = datas[n].rhs; | |
| 1139 | } else if (datas[n].lhs != 0) { | |
| 1140 | n = datas[n].lhs; | |
| 1141 | } else { | |
| 1142 | return main_tokens[n] + end_offset; | |
| 1143 | } | |
| 1233 | const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node; | |
| 1234 | n = value_expr.unwrap() orelse type_expr; | |
| 1144 | 1235 | }, |
| 1145 | .container_field_align => { | |
| 1146 | if (datas[n].rhs != 0) { | |
| 1147 | end_offset += 1; // for the rparen | |
| 1148 | n = datas[n].rhs; | |
| 1149 | } else if (datas[n].lhs != 0) { | |
| 1150 | n = datas[n].lhs; | |
| 1151 | } else { | |
| 1152 | return main_tokens[n] + end_offset; | |
| 1153 | } | |
| 1236 | ||
| 1237 | .array_access, | |
| 1238 | .array_init_one, | |
| 1239 | .container_field_align, | |
| 1240 | => { | |
| 1241 | _, const rhs = tree.nodeData(n).node_and_node; | |
| 1242 | end_offset += 1; // for the rbracket/rbrace/rparen | |
| 1243 | n = rhs; | |
| 1154 | 1244 | }, |
| 1155 | 1245 | .container_field => { |
| 1156 | const extra = tree.extraData(datas[n].rhs, Node.ContainerField); | |
| 1157 | if (extra.value_expr != 0) { | |
| 1158 | n = extra.value_expr; | |
| 1159 | } else if (extra.align_expr != 0) { | |
| 1160 | end_offset += 1; // for the rparen | |
| 1161 | n = extra.align_expr; | |
| 1162 | } else if (datas[n].lhs != 0) { | |
| 1163 | n = datas[n].lhs; | |
| 1164 | } else { | |
| 1165 | return main_tokens[n] + end_offset; | |
| 1166 | } | |
| 1246 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1247 | const extra = tree.extraData(extra_index, Node.ContainerField); | |
| 1248 | n = extra.value_expr; | |
| 1167 | 1249 | }, |
| 1168 | 1250 | |
| 1169 | .array_init_one, | |
| 1170 | .struct_init_one, | |
| 1171 | => { | |
| 1251 | .struct_init_one => { | |
| 1252 | _, const first_field = tree.nodeData(n).node_and_opt_node; | |
| 1172 | 1253 | end_offset += 1; // rbrace |
| 1173 | if (datas[n].rhs == 0) { | |
| 1174 | return main_tokens[n] + end_offset; | |
| 1175 | } else { | |
| 1176 | n = datas[n].rhs; | |
| 1177 | } | |
| 1254 | n = first_field.unwrap() orelse { | |
| 1255 | return tree.nodeMainToken(n) + end_offset; | |
| 1256 | }; | |
| 1257 | }, | |
| 1258 | .slice_open => { | |
| 1259 | _, const start_node = tree.nodeData(n).node_and_node; | |
| 1260 | end_offset += 2; // ellipsis2 + rbracket, or comma + rparen | |
| 1261 | n = start_node; | |
| 1262 | }, | |
| 1263 | .array_init_one_comma => { | |
| 1264 | _, const first_element = tree.nodeData(n).node_and_node; | |
| 1265 | end_offset += 2; // comma + rbrace | |
| 1266 | n = first_element; | |
| 1178 | 1267 | }, |
| 1179 | .slice_open, | |
| 1180 | 1268 | .call_one_comma, |
| 1181 | 1269 | .async_call_one_comma, |
| 1182 | .array_init_one_comma, | |
| 1183 | 1270 | .struct_init_one_comma, |
| 1184 | 1271 | => { |
| 1272 | _, const first_field = tree.nodeData(n).node_and_opt_node; | |
| 1185 | 1273 | end_offset += 2; // ellipsis2 + rbracket, or comma + rparen |
| 1186 | n = datas[n].rhs; | |
| 1187 | assert(n != 0); | |
| 1274 | n = first_field.unwrap().?; | |
| 1188 | 1275 | }, |
| 1189 | 1276 | .slice => { |
| 1190 | const extra = tree.extraData(datas[n].rhs, Node.Slice); | |
| 1191 | assert(extra.end != 0); // should have used slice_open | |
| 1277 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1278 | const extra = tree.extraData(extra_index, Node.Slice); | |
| 1192 | 1279 | end_offset += 1; // rbracket |
| 1193 | 1280 | n = extra.end; |
| 1194 | 1281 | }, |
| 1195 | 1282 | .slice_sentinel => { |
| 1196 | const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel); | |
| 1197 | assert(extra.sentinel != 0); // should have used slice | |
| 1283 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1284 | const extra = tree.extraData(extra_index, Node.SliceSentinel); | |
| 1198 | 1285 | end_offset += 1; // rbracket |
| 1199 | 1286 | n = extra.sentinel; |
| 1200 | 1287 | }, |
| 1201 | 1288 | |
| 1202 | 1289 | .@"continue", .@"break" => { |
| 1203 | if (datas[n].rhs != 0) { | |
| 1204 | n = datas[n].rhs; | |
| 1205 | } else if (datas[n].lhs != 0) { | |
| 1206 | return datas[n].lhs + end_offset; | |
| 1207 | } else { | |
| 1208 | return main_tokens[n] + end_offset; | |
| 1209 | } | |
| 1210 | }, | |
| 1211 | .fn_decl => { | |
| 1212 | if (datas[n].rhs != 0) { | |
| 1213 | n = datas[n].rhs; | |
| 1290 | const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node; | |
| 1291 | if (opt_rhs.unwrap()) |rhs| { | |
| 1292 | n = rhs; | |
| 1293 | } else if (opt_label.unwrap()) |lhs| { | |
| 1294 | return lhs + end_offset; | |
| 1214 | 1295 | } else { |
| 1215 | n = datas[n].lhs; | |
| 1296 | return tree.nodeMainToken(n) + end_offset; | |
| 1216 | 1297 | } |
| 1217 | 1298 | }, |
| 1218 | .fn_proto_one => { | |
| 1219 | const extra = tree.extraData(datas[n].lhs, Node.FnProtoOne); | |
| 1220 | // addrspace, linksection, callconv, align can appear in any order, so we | |
| 1221 | // find the last one here. | |
| 1222 | var max_node: Node.Index = datas[n].rhs; | |
| 1223 | var max_start = token_starts[main_tokens[max_node]]; | |
| 1224 | var max_offset: TokenIndex = 0; | |
| 1225 | if (extra.align_expr != 0) { | |
| 1226 | const start = token_starts[main_tokens[extra.align_expr]]; | |
| 1227 | if (start > max_start) { | |
| 1228 | max_node = extra.align_expr; | |
| 1229 | max_start = start; | |
| 1230 | max_offset = 1; // for the rparen | |
| 1231 | } | |
| 1232 | } | |
| 1233 | if (extra.addrspace_expr != 0) { | |
| 1234 | const start = token_starts[main_tokens[extra.addrspace_expr]]; | |
| 1235 | if (start > max_start) { | |
| 1236 | max_node = extra.addrspace_expr; | |
| 1237 | max_start = start; | |
| 1238 | max_offset = 1; // for the rparen | |
| 1239 | } | |
| 1240 | } | |
| 1241 | if (extra.section_expr != 0) { | |
| 1242 | const start = token_starts[main_tokens[extra.section_expr]]; | |
| 1243 | if (start > max_start) { | |
| 1244 | max_node = extra.section_expr; | |
| 1245 | max_start = start; | |
| 1246 | max_offset = 1; // for the rparen | |
| 1247 | } | |
| 1248 | } | |
| 1249 | if (extra.callconv_expr != 0) { | |
| 1250 | const start = token_starts[main_tokens[extra.callconv_expr]]; | |
| 1251 | if (start > max_start) { | |
| 1252 | max_node = extra.callconv_expr; | |
| 1253 | max_start = start; | |
| 1254 | max_offset = 1; // for the rparen | |
| 1255 | } | |
| 1256 | } | |
| 1257 | n = max_node; | |
| 1258 | end_offset += max_offset; | |
| 1259 | }, | |
| 1260 | .fn_proto => { | |
| 1261 | const extra = tree.extraData(datas[n].lhs, Node.FnProto); | |
| 1262 | // addrspace, linksection, callconv, align can appear in any order, so we | |
| 1263 | // find the last one here. | |
| 1264 | var max_node: Node.Index = datas[n].rhs; | |
| 1265 | var max_start = token_starts[main_tokens[max_node]]; | |
| 1266 | var max_offset: TokenIndex = 0; | |
| 1267 | if (extra.align_expr != 0) { | |
| 1268 | const start = token_starts[main_tokens[extra.align_expr]]; | |
| 1269 | if (start > max_start) { | |
| 1270 | max_node = extra.align_expr; | |
| 1271 | max_start = start; | |
| 1272 | max_offset = 1; // for the rparen | |
| 1273 | } | |
| 1274 | } | |
| 1275 | if (extra.addrspace_expr != 0) { | |
| 1276 | const start = token_starts[main_tokens[extra.addrspace_expr]]; | |
| 1277 | if (start > max_start) { | |
| 1278 | max_node = extra.addrspace_expr; | |
| 1279 | max_start = start; | |
| 1280 | max_offset = 1; // for the rparen | |
| 1281 | } | |
| 1282 | } | |
| 1283 | if (extra.section_expr != 0) { | |
| 1284 | const start = token_starts[main_tokens[extra.section_expr]]; | |
| 1285 | if (start > max_start) { | |
| 1286 | max_node = extra.section_expr; | |
| 1287 | max_start = start; | |
| 1288 | max_offset = 1; // for the rparen | |
| 1289 | } | |
| 1290 | } | |
| 1291 | if (extra.callconv_expr != 0) { | |
| 1292 | const start = token_starts[main_tokens[extra.callconv_expr]]; | |
| 1293 | if (start > max_start) { | |
| 1294 | max_node = extra.callconv_expr; | |
| 1295 | max_start = start; | |
| 1296 | max_offset = 1; // for the rparen | |
| 1297 | } | |
| 1298 | } | |
| 1299 | n = max_node; | |
| 1300 | end_offset += max_offset; | |
| 1301 | }, | |
| 1302 | 1299 | .while_cont => { |
| 1303 | const extra = tree.extraData(datas[n].rhs, Node.WhileCont); | |
| 1304 | assert(extra.then_expr != 0); | |
| 1300 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1301 | const extra = tree.extraData(extra_index, Node.WhileCont); | |
| 1305 | 1302 | n = extra.then_expr; |
| 1306 | 1303 | }, |
| 1307 | 1304 | .@"while" => { |
| 1308 | const extra = tree.extraData(datas[n].rhs, Node.While); | |
| 1309 | assert(extra.else_expr != 0); | |
| 1305 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1306 | const extra = tree.extraData(extra_index, Node.While); | |
| 1310 | 1307 | n = extra.else_expr; |
| 1311 | 1308 | }, |
| 1312 | 1309 | .@"if" => { |
| 1313 | const extra = tree.extraData(datas[n].rhs, Node.If); | |
| 1314 | assert(extra.else_expr != 0); | |
| 1310 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1311 | const extra = tree.extraData(extra_index, Node.If); | |
| 1315 | 1312 | n = extra.else_expr; |
| 1316 | 1313 | }, |
| 1317 | 1314 | .@"for" => { |
| 1318 | const extra = @as(Node.For, @bitCast(datas[n].rhs)); | |
| 1319 | n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)]; | |
| 1320 | }, | |
| 1321 | .@"suspend" => { | |
| 1322 | if (datas[n].lhs != 0) { | |
| 1323 | n = datas[n].lhs; | |
| 1324 | } else { | |
| 1325 | return main_tokens[n] + end_offset; | |
| 1326 | } | |
| 1315 | const extra_index, const extra = tree.nodeData(n).@"for"; | |
| 1316 | const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else); | |
| 1317 | n = @enumFromInt(tree.extra_data[index]); | |
| 1327 | 1318 | }, |
| 1328 | 1319 | .array_type_sentinel => { |
| 1329 | const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel); | |
| 1320 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1321 | const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel); | |
| 1330 | 1322 | n = extra.elem_type; |
| 1331 | 1323 | }, |
| 1332 | 1324 | }; |
| 1333 | 1325 | } |
| 1334 | 1326 | |
| 1335 | 1327 | pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool { |
| 1336 | const token_starts = tree.tokens.items(.start); | |
| 1337 | const source = tree.source[token_starts[token1]..token_starts[token2]]; | |
| 1328 | const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)]; | |
| 1338 | 1329 | return mem.indexOfScalar(u8, source, '\n') == null; |
| 1339 | 1330 | } |
| 1340 | 1331 | |
| 1341 | 1332 | pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 { |
| 1342 | const token_starts = tree.tokens.items(.start); | |
| 1343 | 1333 | const first_token = tree.firstToken(node); |
| 1344 | 1334 | const last_token = tree.lastToken(node); |
| 1345 | const start = token_starts[first_token]; | |
| 1346 | const end = token_starts[last_token] + tree.tokenSlice(last_token).len; | |
| 1335 | const start = tree.tokenStart(first_token); | |
| 1336 | const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len; | |
| 1347 | 1337 | return tree.source[start..end]; |
| 1348 | 1338 | } |
| 1349 | 1339 | |
| 1350 | 1340 | pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1351 | assert(tree.nodes.items(.tag)[node] == .global_var_decl); | |
| 1352 | const data = tree.nodes.items(.data)[node]; | |
| 1353 | const extra = tree.extraData(data.lhs, Node.GlobalVarDecl); | |
| 1341 | assert(tree.nodeTag(node) == .global_var_decl); | |
| 1342 | const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node; | |
| 1343 | const extra = tree.extraData(extra_index, Node.GlobalVarDecl); | |
| 1354 | 1344 | return tree.fullVarDeclComponents(.{ |
| 1355 | 1345 | .type_node = extra.type_node, |
| 1356 | 1346 | .align_node = extra.align_node, |
| 1357 | 1347 | .addrspace_node = extra.addrspace_node, |
| 1358 | 1348 | .section_node = extra.section_node, |
| 1359 | .init_node = data.rhs, | |
| 1360 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1349 | .init_node = init_node, | |
| 1350 | .mut_token = tree.nodeMainToken(node), | |
| 1361 | 1351 | }); |
| 1362 | 1352 | } |
| 1363 | 1353 | |
| 1364 | 1354 | pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1365 | assert(tree.nodes.items(.tag)[node] == .local_var_decl); | |
| 1366 | const data = tree.nodes.items(.data)[node]; | |
| 1367 | const extra = tree.extraData(data.lhs, Node.LocalVarDecl); | |
| 1355 | assert(tree.nodeTag(node) == .local_var_decl); | |
| 1356 | const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node; | |
| 1357 | const extra = tree.extraData(extra_index, Node.LocalVarDecl); | |
| 1368 | 1358 | return tree.fullVarDeclComponents(.{ |
| 1369 | .type_node = extra.type_node, | |
| 1370 | .align_node = extra.align_node, | |
| 1371 | .addrspace_node = 0, | |
| 1372 | .section_node = 0, | |
| 1373 | .init_node = data.rhs, | |
| 1374 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1359 | .type_node = extra.type_node.toOptional(), | |
| 1360 | .align_node = extra.align_node.toOptional(), | |
| 1361 | .addrspace_node = .none, | |
| 1362 | .section_node = .none, | |
| 1363 | .init_node = init_node, | |
| 1364 | .mut_token = tree.nodeMainToken(node), | |
| 1375 | 1365 | }); |
| 1376 | 1366 | } |
| 1377 | 1367 | |
| 1378 | 1368 | pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1379 | assert(tree.nodes.items(.tag)[node] == .simple_var_decl); | |
| 1380 | const data = tree.nodes.items(.data)[node]; | |
| 1369 | assert(tree.nodeTag(node) == .simple_var_decl); | |
| 1370 | const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node; | |
| 1381 | 1371 | return tree.fullVarDeclComponents(.{ |
| 1382 | .type_node = data.lhs, | |
| 1383 | .align_node = 0, | |
| 1384 | .addrspace_node = 0, | |
| 1385 | .section_node = 0, | |
| 1386 | .init_node = data.rhs, | |
| 1387 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1372 | .type_node = type_node, | |
| 1373 | .align_node = .none, | |
| 1374 | .addrspace_node = .none, | |
| 1375 | .section_node = .none, | |
| 1376 | .init_node = init_node, | |
| 1377 | .mut_token = tree.nodeMainToken(node), | |
| 1388 | 1378 | }); |
| 1389 | 1379 | } |
| 1390 | 1380 | |
| 1391 | 1381 | pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1392 | assert(tree.nodes.items(.tag)[node] == .aligned_var_decl); | |
| 1393 | const data = tree.nodes.items(.data)[node]; | |
| 1382 | assert(tree.nodeTag(node) == .aligned_var_decl); | |
| 1383 | const align_node, const init_node = tree.nodeData(node).node_and_opt_node; | |
| 1394 | 1384 | return tree.fullVarDeclComponents(.{ |
| 1395 | .type_node = 0, | |
| 1396 | .align_node = data.lhs, | |
| 1397 | .addrspace_node = 0, | |
| 1398 | .section_node = 0, | |
| 1399 | .init_node = data.rhs, | |
| 1400 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1385 | .type_node = .none, | |
| 1386 | .align_node = align_node.toOptional(), | |
| 1387 | .addrspace_node = .none, | |
| 1388 | .section_node = .none, | |
| 1389 | .init_node = init_node, | |
| 1390 | .mut_token = tree.nodeMainToken(node), | |
| 1401 | 1391 | }); |
| 1402 | 1392 | } |
| 1403 | 1393 | |
| 1404 | 1394 | pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure { |
| 1405 | const data = tree.nodes.items(.data)[node]; | |
| 1406 | const variable_count = tree.extra_data[data.lhs]; | |
| 1395 | const extra_index, const value_expr = tree.nodeData(node).extra_and_node; | |
| 1396 | const variable_count = tree.extra_data[@intFromEnum(extra_index)]; | |
| 1407 | 1397 | return tree.fullAssignDestructureComponents(.{ |
| 1408 | .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count], | |
| 1409 | .equal_token = tree.nodes.items(.main_token)[node], | |
| 1410 | .value_expr = data.rhs, | |
| 1398 | .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index), | |
| 1399 | .equal_token = tree.nodeMainToken(node), | |
| 1400 | .value_expr = value_expr, | |
| 1411 | 1401 | }); |
| 1412 | 1402 | } |
| 1413 | 1403 | |
| 1414 | 1404 | pub fn ifSimple(tree: Ast, node: Node.Index) full.If { |
| 1415 | assert(tree.nodes.items(.tag)[node] == .if_simple); | |
| 1416 | const data = tree.nodes.items(.data)[node]; | |
| 1405 | assert(tree.nodeTag(node) == .if_simple); | |
| 1406 | const cond_expr, const then_expr = tree.nodeData(node).node_and_node; | |
| 1417 | 1407 | return tree.fullIfComponents(.{ |
| 1418 | .cond_expr = data.lhs, | |
| 1419 | .then_expr = data.rhs, | |
| 1420 | .else_expr = 0, | |
| 1421 | .if_token = tree.nodes.items(.main_token)[node], | |
| 1408 | .cond_expr = cond_expr, | |
| 1409 | .then_expr = then_expr, | |
| 1410 | .else_expr = .none, | |
| 1411 | .if_token = tree.nodeMainToken(node), | |
| 1422 | 1412 | }); |
| 1423 | 1413 | } |
| 1424 | 1414 | |
| 1425 | 1415 | pub fn ifFull(tree: Ast, node: Node.Index) full.If { |
| 1426 | assert(tree.nodes.items(.tag)[node] == .@"if"); | |
| 1427 | const data = tree.nodes.items(.data)[node]; | |
| 1428 | const extra = tree.extraData(data.rhs, Node.If); | |
| 1416 | assert(tree.nodeTag(node) == .@"if"); | |
| 1417 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1418 | const extra = tree.extraData(extra_index, Node.If); | |
| 1429 | 1419 | return tree.fullIfComponents(.{ |
| 1430 | .cond_expr = data.lhs, | |
| 1420 | .cond_expr = cond_expr, | |
| 1431 | 1421 | .then_expr = extra.then_expr, |
| 1432 | .else_expr = extra.else_expr, | |
| 1433 | .if_token = tree.nodes.items(.main_token)[node], | |
| 1422 | .else_expr = extra.else_expr.toOptional(), | |
| 1423 | .if_token = tree.nodeMainToken(node), | |
| 1434 | 1424 | }); |
| 1435 | 1425 | } |
| 1436 | 1426 | |
| 1437 | 1427 | pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField { |
| 1438 | assert(tree.nodes.items(.tag)[node] == .container_field); | |
| 1439 | const data = tree.nodes.items(.data)[node]; | |
| 1440 | const extra = tree.extraData(data.rhs, Node.ContainerField); | |
| 1441 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1428 | assert(tree.nodeTag(node) == .container_field); | |
| 1429 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1430 | const extra = tree.extraData(extra_index, Node.ContainerField); | |
| 1431 | const main_token = tree.nodeMainToken(node); | |
| 1442 | 1432 | return tree.fullContainerFieldComponents(.{ |
| 1443 | 1433 | .main_token = main_token, |
| 1444 | .type_expr = data.lhs, | |
| 1445 | .align_expr = extra.align_expr, | |
| 1446 | .value_expr = extra.value_expr, | |
| 1447 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1448 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1434 | .type_expr = type_expr.toOptional(), | |
| 1435 | .align_expr = extra.align_expr.toOptional(), | |
| 1436 | .value_expr = extra.value_expr.toOptional(), | |
| 1437 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1438 | tree.tokenTag(main_token + 1) != .colon, | |
| 1449 | 1439 | }); |
| 1450 | 1440 | } |
| 1451 | 1441 | |
| 1452 | 1442 | pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField { |
| 1453 | assert(tree.nodes.items(.tag)[node] == .container_field_init); | |
| 1454 | const data = tree.nodes.items(.data)[node]; | |
| 1455 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1443 | assert(tree.nodeTag(node) == .container_field_init); | |
| 1444 | const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node; | |
| 1445 | const main_token = tree.nodeMainToken(node); | |
| 1456 | 1446 | return tree.fullContainerFieldComponents(.{ |
| 1457 | 1447 | .main_token = main_token, |
| 1458 | .type_expr = data.lhs, | |
| 1459 | .align_expr = 0, | |
| 1460 | .value_expr = data.rhs, | |
| 1461 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1462 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1448 | .type_expr = type_expr.toOptional(), | |
| 1449 | .align_expr = .none, | |
| 1450 | .value_expr = value_expr, | |
| 1451 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1452 | tree.tokenTag(main_token + 1) != .colon, | |
| 1463 | 1453 | }); |
| 1464 | 1454 | } |
| 1465 | 1455 | |
| 1466 | 1456 | pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField { |
| 1467 | assert(tree.nodes.items(.tag)[node] == .container_field_align); | |
| 1468 | const data = tree.nodes.items(.data)[node]; | |
| 1469 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1457 | assert(tree.nodeTag(node) == .container_field_align); | |
| 1458 | const type_expr, const align_expr = tree.nodeData(node).node_and_node; | |
| 1459 | const main_token = tree.nodeMainToken(node); | |
| 1470 | 1460 | return tree.fullContainerFieldComponents(.{ |
| 1471 | 1461 | .main_token = main_token, |
| 1472 | .type_expr = data.lhs, | |
| 1473 | .align_expr = data.rhs, | |
| 1474 | .value_expr = 0, | |
| 1475 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1476 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1462 | .type_expr = type_expr.toOptional(), | |
| 1463 | .align_expr = align_expr.toOptional(), | |
| 1464 | .value_expr = .none, | |
| 1465 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1466 | tree.tokenTag(main_token + 1) != .colon, | |
| 1477 | 1467 | }); |
| 1478 | 1468 | } |
| 1479 | 1469 | |
| 1480 | 1470 | pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { |
| 1481 | assert(tree.nodes.items(.tag)[node] == .fn_proto_simple); | |
| 1482 | const data = tree.nodes.items(.data)[node]; | |
| 1483 | buffer[0] = data.lhs; | |
| 1484 | const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1471 | assert(tree.nodeTag(node) == .fn_proto_simple); | |
| 1472 | const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node; | |
| 1473 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param}); | |
| 1485 | 1474 | return tree.fullFnProtoComponents(.{ |
| 1486 | 1475 | .proto_node = node, |
| 1487 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1488 | .return_type = data.rhs, | |
| 1476 | .fn_token = tree.nodeMainToken(node), | |
| 1477 | .return_type = return_type, | |
| 1489 | 1478 | .params = params, |
| 1490 | .align_expr = 0, | |
| 1491 | .addrspace_expr = 0, | |
| 1492 | .section_expr = 0, | |
| 1493 | .callconv_expr = 0, | |
| 1479 | .align_expr = .none, | |
| 1480 | .addrspace_expr = .none, | |
| 1481 | .section_expr = .none, | |
| 1482 | .callconv_expr = .none, | |
| 1494 | 1483 | }); |
| 1495 | 1484 | } |
| 1496 | 1485 | |
| 1497 | 1486 | pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto { |
| 1498 | assert(tree.nodes.items(.tag)[node] == .fn_proto_multi); | |
| 1499 | const data = tree.nodes.items(.data)[node]; | |
| 1500 | const params_range = tree.extraData(data.lhs, Node.SubRange); | |
| 1501 | const params = tree.extra_data[params_range.start..params_range.end]; | |
| 1487 | assert(tree.nodeTag(node) == .fn_proto_multi); | |
| 1488 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1489 | const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1502 | 1490 | return tree.fullFnProtoComponents(.{ |
| 1503 | 1491 | .proto_node = node, |
| 1504 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1505 | .return_type = data.rhs, | |
| 1492 | .fn_token = tree.nodeMainToken(node), | |
| 1493 | .return_type = return_type, | |
| 1506 | 1494 | .params = params, |
| 1507 | .align_expr = 0, | |
| 1508 | .addrspace_expr = 0, | |
| 1509 | .section_expr = 0, | |
| 1510 | .callconv_expr = 0, | |
| 1495 | .align_expr = .none, | |
| 1496 | .addrspace_expr = .none, | |
| 1497 | .section_expr = .none, | |
| 1498 | .callconv_expr = .none, | |
| 1511 | 1499 | }); |
| 1512 | 1500 | } |
| 1513 | 1501 | |
| 1514 | 1502 | pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { |
| 1515 | assert(tree.nodes.items(.tag)[node] == .fn_proto_one); | |
| 1516 | const data = tree.nodes.items(.data)[node]; | |
| 1517 | const extra = tree.extraData(data.lhs, Node.FnProtoOne); | |
| 1518 | buffer[0] = extra.param; | |
| 1519 | const params = if (extra.param == 0) buffer[0..0] else buffer[0..1]; | |
| 1503 | assert(tree.nodeTag(node) == .fn_proto_one); | |
| 1504 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1505 | const extra = tree.extraData(extra_index, Node.FnProtoOne); | |
| 1506 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param}); | |
| 1520 | 1507 | return tree.fullFnProtoComponents(.{ |
| 1521 | 1508 | .proto_node = node, |
| 1522 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1523 | .return_type = data.rhs, | |
| 1509 | .fn_token = tree.nodeMainToken(node), | |
| 1510 | .return_type = return_type, | |
| 1524 | 1511 | .params = params, |
| 1525 | 1512 | .align_expr = extra.align_expr, |
| 1526 | 1513 | .addrspace_expr = extra.addrspace_expr, |
| ... | ... | @@ -1530,14 +1517,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr |
| 1530 | 1517 | } |
| 1531 | 1518 | |
| 1532 | 1519 | pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto { |
| 1533 | assert(tree.nodes.items(.tag)[node] == .fn_proto); | |
| 1534 | const data = tree.nodes.items(.data)[node]; | |
| 1535 | const extra = tree.extraData(data.lhs, Node.FnProto); | |
| 1536 | const params = tree.extra_data[extra.params_start..extra.params_end]; | |
| 1520 | assert(tree.nodeTag(node) == .fn_proto); | |
| 1521 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1522 | const extra = tree.extraData(extra_index, Node.FnProto); | |
| 1523 | const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index); | |
| 1537 | 1524 | return tree.fullFnProtoComponents(.{ |
| 1538 | 1525 | .proto_node = node, |
| 1539 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1540 | .return_type = data.rhs, | |
| 1526 | .fn_token = tree.nodeMainToken(node), | |
| 1527 | .return_type = return_type, | |
| 1541 | 1528 | .params = params, |
| 1542 | 1529 | .align_expr = extra.align_expr, |
| 1543 | 1530 | .addrspace_expr = extra.addrspace_expr, |
| ... | ... | @@ -1547,300 +1534,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto { |
| 1547 | 1534 | } |
| 1548 | 1535 | |
| 1549 | 1536 | pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit { |
| 1550 | assert(tree.nodes.items(.tag)[node] == .struct_init_one or | |
| 1551 | tree.nodes.items(.tag)[node] == .struct_init_one_comma); | |
| 1552 | const data = tree.nodes.items(.data)[node]; | |
| 1553 | buffer[0] = data.rhs; | |
| 1554 | const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1537 | assert(tree.nodeTag(node) == .struct_init_one or | |
| 1538 | tree.nodeTag(node) == .struct_init_one_comma); | |
| 1539 | const type_expr, const first_field = tree.nodeData(node).node_and_opt_node; | |
| 1540 | const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field}); | |
| 1555 | 1541 | return .{ |
| 1556 | 1542 | .ast = .{ |
| 1557 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1543 | .lbrace = tree.nodeMainToken(node), | |
| 1558 | 1544 | .fields = fields, |
| 1559 | .type_expr = data.lhs, | |
| 1545 | .type_expr = type_expr.toOptional(), | |
| 1560 | 1546 | }, |
| 1561 | 1547 | }; |
| 1562 | 1548 | } |
| 1563 | 1549 | |
| 1564 | 1550 | pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit { |
| 1565 | assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or | |
| 1566 | tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma); | |
| 1567 | const data = tree.nodes.items(.data)[node]; | |
| 1568 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1569 | const fields = if (data.rhs != 0) | |
| 1570 | buffer[0..2] | |
| 1571 | else if (data.lhs != 0) | |
| 1572 | buffer[0..1] | |
| 1573 | else | |
| 1574 | buffer[0..0]; | |
| 1551 | assert(tree.nodeTag(node) == .struct_init_dot_two or | |
| 1552 | tree.nodeTag(node) == .struct_init_dot_two_comma); | |
| 1553 | const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1575 | 1554 | return .{ |
| 1576 | 1555 | .ast = .{ |
| 1577 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1556 | .lbrace = tree.nodeMainToken(node), | |
| 1578 | 1557 | .fields = fields, |
| 1579 | .type_expr = 0, | |
| 1558 | .type_expr = .none, | |
| 1580 | 1559 | }, |
| 1581 | 1560 | }; |
| 1582 | 1561 | } |
| 1583 | 1562 | |
| 1584 | 1563 | pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit { |
| 1585 | assert(tree.nodes.items(.tag)[node] == .struct_init_dot or | |
| 1586 | tree.nodes.items(.tag)[node] == .struct_init_dot_comma); | |
| 1587 | const data = tree.nodes.items(.data)[node]; | |
| 1564 | assert(tree.nodeTag(node) == .struct_init_dot or | |
| 1565 | tree.nodeTag(node) == .struct_init_dot_comma); | |
| 1566 | const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1588 | 1567 | return .{ |
| 1589 | 1568 | .ast = .{ |
| 1590 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1591 | .fields = tree.extra_data[data.lhs..data.rhs], | |
| 1592 | .type_expr = 0, | |
| 1569 | .lbrace = tree.nodeMainToken(node), | |
| 1570 | .fields = fields, | |
| 1571 | .type_expr = .none, | |
| 1593 | 1572 | }, |
| 1594 | 1573 | }; |
| 1595 | 1574 | } |
| 1596 | 1575 | |
| 1597 | 1576 | pub fn structInit(tree: Ast, node: Node.Index) full.StructInit { |
| 1598 | assert(tree.nodes.items(.tag)[node] == .struct_init or | |
| 1599 | tree.nodes.items(.tag)[node] == .struct_init_comma); | |
| 1600 | const data = tree.nodes.items(.data)[node]; | |
| 1601 | const fields_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1577 | assert(tree.nodeTag(node) == .struct_init or | |
| 1578 | tree.nodeTag(node) == .struct_init_comma); | |
| 1579 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1580 | const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1602 | 1581 | return .{ |
| 1603 | 1582 | .ast = .{ |
| 1604 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1605 | .fields = tree.extra_data[fields_range.start..fields_range.end], | |
| 1606 | .type_expr = data.lhs, | |
| 1583 | .lbrace = tree.nodeMainToken(node), | |
| 1584 | .fields = fields, | |
| 1585 | .type_expr = type_expr.toOptional(), | |
| 1607 | 1586 | }, |
| 1608 | 1587 | }; |
| 1609 | 1588 | } |
| 1610 | 1589 | |
| 1611 | 1590 | pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit { |
| 1612 | assert(tree.nodes.items(.tag)[node] == .array_init_one or | |
| 1613 | tree.nodes.items(.tag)[node] == .array_init_one_comma); | |
| 1614 | const data = tree.nodes.items(.data)[node]; | |
| 1615 | buffer[0] = data.rhs; | |
| 1616 | const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1591 | assert(tree.nodeTag(node) == .array_init_one or | |
| 1592 | tree.nodeTag(node) == .array_init_one_comma); | |
| 1593 | const type_expr, buffer[0] = tree.nodeData(node).node_and_node; | |
| 1617 | 1594 | return .{ |
| 1618 | 1595 | .ast = .{ |
| 1619 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1620 | .elements = elements, | |
| 1621 | .type_expr = data.lhs, | |
| 1596 | .lbrace = tree.nodeMainToken(node), | |
| 1597 | .elements = buffer[0..1], | |
| 1598 | .type_expr = type_expr.toOptional(), | |
| 1622 | 1599 | }, |
| 1623 | 1600 | }; |
| 1624 | 1601 | } |
| 1625 | 1602 | |
| 1626 | 1603 | pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit { |
| 1627 | assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or | |
| 1628 | tree.nodes.items(.tag)[node] == .array_init_dot_two_comma); | |
| 1629 | const data = tree.nodes.items(.data)[node]; | |
| 1630 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1631 | const elements = if (data.rhs != 0) | |
| 1632 | buffer[0..2] | |
| 1633 | else if (data.lhs != 0) | |
| 1634 | buffer[0..1] | |
| 1635 | else | |
| 1636 | buffer[0..0]; | |
| 1604 | assert(tree.nodeTag(node) == .array_init_dot_two or | |
| 1605 | tree.nodeTag(node) == .array_init_dot_two_comma); | |
| 1606 | const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1637 | 1607 | return .{ |
| 1638 | 1608 | .ast = .{ |
| 1639 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1609 | .lbrace = tree.nodeMainToken(node), | |
| 1640 | 1610 | .elements = elements, |
| 1641 | .type_expr = 0, | |
| 1611 | .type_expr = .none, | |
| 1642 | 1612 | }, |
| 1643 | 1613 | }; |
| 1644 | 1614 | } |
| 1645 | 1615 | |
| 1646 | 1616 | pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit { |
| 1647 | assert(tree.nodes.items(.tag)[node] == .array_init_dot or | |
| 1648 | tree.nodes.items(.tag)[node] == .array_init_dot_comma); | |
| 1649 | const data = tree.nodes.items(.data)[node]; | |
| 1617 | assert(tree.nodeTag(node) == .array_init_dot or | |
| 1618 | tree.nodeTag(node) == .array_init_dot_comma); | |
| 1619 | const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1650 | 1620 | return .{ |
| 1651 | 1621 | .ast = .{ |
| 1652 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1653 | .elements = tree.extra_data[data.lhs..data.rhs], | |
| 1654 | .type_expr = 0, | |
| 1622 | .lbrace = tree.nodeMainToken(node), | |
| 1623 | .elements = elements, | |
| 1624 | .type_expr = .none, | |
| 1655 | 1625 | }, |
| 1656 | 1626 | }; |
| 1657 | 1627 | } |
| 1658 | 1628 | |
| 1659 | 1629 | pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit { |
| 1660 | assert(tree.nodes.items(.tag)[node] == .array_init or | |
| 1661 | tree.nodes.items(.tag)[node] == .array_init_comma); | |
| 1662 | const data = tree.nodes.items(.data)[node]; | |
| 1663 | const elem_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1630 | assert(tree.nodeTag(node) == .array_init or | |
| 1631 | tree.nodeTag(node) == .array_init_comma); | |
| 1632 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1633 | const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1664 | 1634 | return .{ |
| 1665 | 1635 | .ast = .{ |
| 1666 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1667 | .elements = tree.extra_data[elem_range.start..elem_range.end], | |
| 1668 | .type_expr = data.lhs, | |
| 1636 | .lbrace = tree.nodeMainToken(node), | |
| 1637 | .elements = elements, | |
| 1638 | .type_expr = type_expr.toOptional(), | |
| 1669 | 1639 | }, |
| 1670 | 1640 | }; |
| 1671 | 1641 | } |
| 1672 | 1642 | |
| 1673 | 1643 | pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType { |
| 1674 | assert(tree.nodes.items(.tag)[node] == .array_type); | |
| 1675 | const data = tree.nodes.items(.data)[node]; | |
| 1644 | assert(tree.nodeTag(node) == .array_type); | |
| 1645 | const elem_count, const elem_type = tree.nodeData(node).node_and_node; | |
| 1676 | 1646 | return .{ |
| 1677 | 1647 | .ast = .{ |
| 1678 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1679 | .elem_count = data.lhs, | |
| 1680 | .sentinel = 0, | |
| 1681 | .elem_type = data.rhs, | |
| 1648 | .lbracket = tree.nodeMainToken(node), | |
| 1649 | .elem_count = elem_count, | |
| 1650 | .sentinel = .none, | |
| 1651 | .elem_type = elem_type, | |
| 1682 | 1652 | }, |
| 1683 | 1653 | }; |
| 1684 | 1654 | } |
| 1685 | 1655 | |
| 1686 | 1656 | pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType { |
| 1687 | assert(tree.nodes.items(.tag)[node] == .array_type_sentinel); | |
| 1688 | const data = tree.nodes.items(.data)[node]; | |
| 1689 | const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel); | |
| 1690 | assert(extra.sentinel != 0); | |
| 1657 | assert(tree.nodeTag(node) == .array_type_sentinel); | |
| 1658 | const elem_count, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1659 | const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel); | |
| 1691 | 1660 | return .{ |
| 1692 | 1661 | .ast = .{ |
| 1693 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1694 | .elem_count = data.lhs, | |
| 1695 | .sentinel = extra.sentinel, | |
| 1662 | .lbracket = tree.nodeMainToken(node), | |
| 1663 | .elem_count = elem_count, | |
| 1664 | .sentinel = extra.sentinel.toOptional(), | |
| 1696 | 1665 | .elem_type = extra.elem_type, |
| 1697 | 1666 | }, |
| 1698 | 1667 | }; |
| 1699 | 1668 | } |
| 1700 | 1669 | |
| 1701 | 1670 | pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType { |
| 1702 | assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned); | |
| 1703 | const data = tree.nodes.items(.data)[node]; | |
| 1671 | assert(tree.nodeTag(node) == .ptr_type_aligned); | |
| 1672 | const align_node, const child_type = tree.nodeData(node).opt_node_and_node; | |
| 1704 | 1673 | return tree.fullPtrTypeComponents(.{ |
| 1705 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1706 | .align_node = data.lhs, | |
| 1707 | .addrspace_node = 0, | |
| 1708 | .sentinel = 0, | |
| 1709 | .bit_range_start = 0, | |
| 1710 | .bit_range_end = 0, | |
| 1711 | .child_type = data.rhs, | |
| 1674 | .main_token = tree.nodeMainToken(node), | |
| 1675 | .align_node = align_node, | |
| 1676 | .addrspace_node = .none, | |
| 1677 | .sentinel = .none, | |
| 1678 | .bit_range_start = .none, | |
| 1679 | .bit_range_end = .none, | |
| 1680 | .child_type = child_type, | |
| 1712 | 1681 | }); |
| 1713 | 1682 | } |
| 1714 | 1683 | |
| 1715 | 1684 | pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType { |
| 1716 | assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel); | |
| 1717 | const data = tree.nodes.items(.data)[node]; | |
| 1685 | assert(tree.nodeTag(node) == .ptr_type_sentinel); | |
| 1686 | const sentinel, const child_type = tree.nodeData(node).opt_node_and_node; | |
| 1718 | 1687 | return tree.fullPtrTypeComponents(.{ |
| 1719 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1720 | .align_node = 0, | |
| 1721 | .addrspace_node = 0, | |
| 1722 | .sentinel = data.lhs, | |
| 1723 | .bit_range_start = 0, | |
| 1724 | .bit_range_end = 0, | |
| 1725 | .child_type = data.rhs, | |
| 1688 | .main_token = tree.nodeMainToken(node), | |
| 1689 | .align_node = .none, | |
| 1690 | .addrspace_node = .none, | |
| 1691 | .sentinel = sentinel, | |
| 1692 | .bit_range_start = .none, | |
| 1693 | .bit_range_end = .none, | |
| 1694 | .child_type = child_type, | |
| 1726 | 1695 | }); |
| 1727 | 1696 | } |
| 1728 | 1697 | |
| 1729 | 1698 | pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType { |
| 1730 | assert(tree.nodes.items(.tag)[node] == .ptr_type); | |
| 1731 | const data = tree.nodes.items(.data)[node]; | |
| 1732 | const extra = tree.extraData(data.lhs, Node.PtrType); | |
| 1699 | assert(tree.nodeTag(node) == .ptr_type); | |
| 1700 | const extra_index, const child_type = tree.nodeData(node).extra_and_node; | |
| 1701 | const extra = tree.extraData(extra_index, Node.PtrType); | |
| 1733 | 1702 | return tree.fullPtrTypeComponents(.{ |
| 1734 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1703 | .main_token = tree.nodeMainToken(node), | |
| 1735 | 1704 | .align_node = extra.align_node, |
| 1736 | 1705 | .addrspace_node = extra.addrspace_node, |
| 1737 | 1706 | .sentinel = extra.sentinel, |
| 1738 | .bit_range_start = 0, | |
| 1739 | .bit_range_end = 0, | |
| 1740 | .child_type = data.rhs, | |
| 1707 | .bit_range_start = .none, | |
| 1708 | .bit_range_end = .none, | |
| 1709 | .child_type = child_type, | |
| 1741 | 1710 | }); |
| 1742 | 1711 | } |
| 1743 | 1712 | |
| 1744 | 1713 | pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType { |
| 1745 | assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range); | |
| 1746 | const data = tree.nodes.items(.data)[node]; | |
| 1747 | const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange); | |
| 1714 | assert(tree.nodeTag(node) == .ptr_type_bit_range); | |
| 1715 | const extra_index, const child_type = tree.nodeData(node).extra_and_node; | |
| 1716 | const extra = tree.extraData(extra_index, Node.PtrTypeBitRange); | |
| 1748 | 1717 | return tree.fullPtrTypeComponents(.{ |
| 1749 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1750 | .align_node = extra.align_node, | |
| 1718 | .main_token = tree.nodeMainToken(node), | |
| 1719 | .align_node = extra.align_node.toOptional(), | |
| 1751 | 1720 | .addrspace_node = extra.addrspace_node, |
| 1752 | 1721 | .sentinel = extra.sentinel, |
| 1753 | .bit_range_start = extra.bit_range_start, | |
| 1754 | .bit_range_end = extra.bit_range_end, | |
| 1755 | .child_type = data.rhs, | |
| 1722 | .bit_range_start = extra.bit_range_start.toOptional(), | |
| 1723 | .bit_range_end = extra.bit_range_end.toOptional(), | |
| 1724 | .child_type = child_type, | |
| 1756 | 1725 | }); |
| 1757 | 1726 | } |
| 1758 | 1727 | |
| 1759 | 1728 | pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice { |
| 1760 | assert(tree.nodes.items(.tag)[node] == .slice_open); | |
| 1761 | const data = tree.nodes.items(.data)[node]; | |
| 1729 | assert(tree.nodeTag(node) == .slice_open); | |
| 1730 | const sliced, const start = tree.nodeData(node).node_and_node; | |
| 1762 | 1731 | return .{ |
| 1763 | 1732 | .ast = .{ |
| 1764 | .sliced = data.lhs, | |
| 1765 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1766 | .start = data.rhs, | |
| 1767 | .end = 0, | |
| 1768 | .sentinel = 0, | |
| 1733 | .sliced = sliced, | |
| 1734 | .lbracket = tree.nodeMainToken(node), | |
| 1735 | .start = start, | |
| 1736 | .end = .none, | |
| 1737 | .sentinel = .none, | |
| 1769 | 1738 | }, |
| 1770 | 1739 | }; |
| 1771 | 1740 | } |
| 1772 | 1741 | |
| 1773 | 1742 | pub fn slice(tree: Ast, node: Node.Index) full.Slice { |
| 1774 | assert(tree.nodes.items(.tag)[node] == .slice); | |
| 1775 | const data = tree.nodes.items(.data)[node]; | |
| 1776 | const extra = tree.extraData(data.rhs, Node.Slice); | |
| 1743 | assert(tree.nodeTag(node) == .slice); | |
| 1744 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1745 | const extra = tree.extraData(extra_index, Node.Slice); | |
| 1777 | 1746 | return .{ |
| 1778 | 1747 | .ast = .{ |
| 1779 | .sliced = data.lhs, | |
| 1780 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1748 | .sliced = sliced, | |
| 1749 | .lbracket = tree.nodeMainToken(node), | |
| 1781 | 1750 | .start = extra.start, |
| 1782 | .end = extra.end, | |
| 1783 | .sentinel = 0, | |
| 1751 | .end = extra.end.toOptional(), | |
| 1752 | .sentinel = .none, | |
| 1784 | 1753 | }, |
| 1785 | 1754 | }; |
| 1786 | 1755 | } |
| 1787 | 1756 | |
| 1788 | 1757 | pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice { |
| 1789 | assert(tree.nodes.items(.tag)[node] == .slice_sentinel); | |
| 1790 | const data = tree.nodes.items(.data)[node]; | |
| 1791 | const extra = tree.extraData(data.rhs, Node.SliceSentinel); | |
| 1758 | assert(tree.nodeTag(node) == .slice_sentinel); | |
| 1759 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1760 | const extra = tree.extraData(extra_index, Node.SliceSentinel); | |
| 1792 | 1761 | return .{ |
| 1793 | 1762 | .ast = .{ |
| 1794 | .sliced = data.lhs, | |
| 1795 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1763 | .sliced = sliced, | |
| 1764 | .lbracket = tree.nodeMainToken(node), | |
| 1796 | 1765 | .start = extra.start, |
| 1797 | 1766 | .end = extra.end, |
| 1798 | .sentinel = extra.sentinel, | |
| 1767 | .sentinel = extra.sentinel.toOptional(), | |
| 1799 | 1768 | }, |
| 1800 | 1769 | }; |
| 1801 | 1770 | } |
| 1802 | 1771 | |
| 1803 | 1772 | pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { |
| 1804 | assert(tree.nodes.items(.tag)[node] == .container_decl_two or | |
| 1805 | tree.nodes.items(.tag)[node] == .container_decl_two_trailing); | |
| 1806 | const data = tree.nodes.items(.data)[node]; | |
| 1807 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1808 | const members = if (data.rhs != 0) | |
| 1809 | buffer[0..2] | |
| 1810 | else if (data.lhs != 0) | |
| 1811 | buffer[0..1] | |
| 1812 | else | |
| 1813 | buffer[0..0]; | |
| 1773 | assert(tree.nodeTag(node) == .container_decl_two or | |
| 1774 | tree.nodeTag(node) == .container_decl_two_trailing); | |
| 1775 | const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1814 | 1776 | return tree.fullContainerDeclComponents(.{ |
| 1815 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1777 | .main_token = tree.nodeMainToken(node), | |
| 1816 | 1778 | .enum_token = null, |
| 1817 | 1779 | .members = members, |
| 1818 | .arg = 0, | |
| 1780 | .arg = .none, | |
| 1819 | 1781 | }); |
| 1820 | 1782 | } |
| 1821 | 1783 | |
| 1822 | 1784 | pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1823 | assert(tree.nodes.items(.tag)[node] == .container_decl or | |
| 1824 | tree.nodes.items(.tag)[node] == .container_decl_trailing); | |
| 1825 | const data = tree.nodes.items(.data)[node]; | |
| 1785 | assert(tree.nodeTag(node) == .container_decl or | |
| 1786 | tree.nodeTag(node) == .container_decl_trailing); | |
| 1787 | const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1826 | 1788 | return tree.fullContainerDeclComponents(.{ |
| 1827 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1789 | .main_token = tree.nodeMainToken(node), | |
| 1828 | 1790 | .enum_token = null, |
| 1829 | .members = tree.extra_data[data.lhs..data.rhs], | |
| 1830 | .arg = 0, | |
| 1791 | .members = members, | |
| 1792 | .arg = .none, | |
| 1831 | 1793 | }); |
| 1832 | 1794 | } |
| 1833 | 1795 | |
| 1834 | 1796 | pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1835 | assert(tree.nodes.items(.tag)[node] == .container_decl_arg or | |
| 1836 | tree.nodes.items(.tag)[node] == .container_decl_arg_trailing); | |
| 1837 | const data = tree.nodes.items(.data)[node]; | |
| 1838 | const members_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1797 | assert(tree.nodeTag(node) == .container_decl_arg or | |
| 1798 | tree.nodeTag(node) == .container_decl_arg_trailing); | |
| 1799 | const arg, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1800 | const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1839 | 1801 | return tree.fullContainerDeclComponents(.{ |
| 1840 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1802 | .main_token = tree.nodeMainToken(node), | |
| 1841 | 1803 | .enum_token = null, |
| 1842 | .members = tree.extra_data[members_range.start..members_range.end], | |
| 1843 | .arg = data.lhs, | |
| 1804 | .members = members, | |
| 1805 | .arg = arg.toOptional(), | |
| 1844 | 1806 | }); |
| 1845 | 1807 | } |
| 1846 | 1808 | |
| ... | ... | @@ -1848,175 +1810,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl { |
| 1848 | 1810 | return .{ |
| 1849 | 1811 | .layout_token = null, |
| 1850 | 1812 | .ast = .{ |
| 1851 | .main_token = undefined, | |
| 1813 | .main_token = 0, | |
| 1852 | 1814 | .enum_token = null, |
| 1853 | 1815 | .members = tree.rootDecls(), |
| 1854 | .arg = 0, | |
| 1816 | .arg = .none, | |
| 1855 | 1817 | }, |
| 1856 | 1818 | }; |
| 1857 | 1819 | } |
| 1858 | 1820 | |
| 1859 | 1821 | pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { |
| 1860 | assert(tree.nodes.items(.tag)[node] == .tagged_union_two or | |
| 1861 | tree.nodes.items(.tag)[node] == .tagged_union_two_trailing); | |
| 1862 | const data = tree.nodes.items(.data)[node]; | |
| 1863 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1864 | const members = if (data.rhs != 0) | |
| 1865 | buffer[0..2] | |
| 1866 | else if (data.lhs != 0) | |
| 1867 | buffer[0..1] | |
| 1868 | else | |
| 1869 | buffer[0..0]; | |
| 1870 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1822 | assert(tree.nodeTag(node) == .tagged_union_two or | |
| 1823 | tree.nodeTag(node) == .tagged_union_two_trailing); | |
| 1824 | const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1825 | const main_token = tree.nodeMainToken(node); | |
| 1871 | 1826 | return tree.fullContainerDeclComponents(.{ |
| 1872 | 1827 | .main_token = main_token, |
| 1873 | 1828 | .enum_token = main_token + 2, // union lparen enum |
| 1874 | 1829 | .members = members, |
| 1875 | .arg = 0, | |
| 1830 | .arg = .none, | |
| 1876 | 1831 | }); |
| 1877 | 1832 | } |
| 1878 | 1833 | |
| 1879 | 1834 | pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1880 | assert(tree.nodes.items(.tag)[node] == .tagged_union or | |
| 1881 | tree.nodes.items(.tag)[node] == .tagged_union_trailing); | |
| 1882 | const data = tree.nodes.items(.data)[node]; | |
| 1883 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1835 | assert(tree.nodeTag(node) == .tagged_union or | |
| 1836 | tree.nodeTag(node) == .tagged_union_trailing); | |
| 1837 | const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1838 | const main_token = tree.nodeMainToken(node); | |
| 1884 | 1839 | return tree.fullContainerDeclComponents(.{ |
| 1885 | 1840 | .main_token = main_token, |
| 1886 | 1841 | .enum_token = main_token + 2, // union lparen enum |
| 1887 | .members = tree.extra_data[data.lhs..data.rhs], | |
| 1888 | .arg = 0, | |
| 1842 | .members = members, | |
| 1843 | .arg = .none, | |
| 1889 | 1844 | }); |
| 1890 | 1845 | } |
| 1891 | 1846 | |
| 1892 | 1847 | pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1893 | assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or | |
| 1894 | tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing); | |
| 1895 | const data = tree.nodes.items(.data)[node]; | |
| 1896 | const members_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1897 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1848 | assert(tree.nodeTag(node) == .tagged_union_enum_tag or | |
| 1849 | tree.nodeTag(node) == .tagged_union_enum_tag_trailing); | |
| 1850 | const arg, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1851 | const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1852 | const main_token = tree.nodeMainToken(node); | |
| 1898 | 1853 | return tree.fullContainerDeclComponents(.{ |
| 1899 | 1854 | .main_token = main_token, |
| 1900 | 1855 | .enum_token = main_token + 2, // union lparen enum |
| 1901 | .members = tree.extra_data[members_range.start..members_range.end], | |
| 1902 | .arg = data.lhs, | |
| 1856 | .members = members, | |
| 1857 | .arg = arg.toOptional(), | |
| 1903 | 1858 | }); |
| 1904 | 1859 | } |
| 1905 | 1860 | |
| 1906 | 1861 | pub fn switchFull(tree: Ast, node: Node.Index) full.Switch { |
| 1907 | const data = &tree.nodes.items(.data)[node]; | |
| 1908 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1909 | const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) { | |
| 1862 | const main_token = tree.nodeMainToken(node); | |
| 1863 | const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) { | |
| 1910 | 1864 | .identifier => .{ main_token + 2, main_token }, |
| 1911 | 1865 | .keyword_switch => .{ main_token, null }, |
| 1912 | 1866 | else => unreachable, |
| 1913 | 1867 | }; |
| 1914 | const extra = tree.extraData(data.rhs, Ast.Node.SubRange); | |
| 1868 | const condition, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1869 | const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index); | |
| 1915 | 1870 | return .{ |
| 1916 | 1871 | .ast = .{ |
| 1917 | 1872 | .switch_token = switch_token, |
| 1918 | .condition = data.lhs, | |
| 1919 | .cases = tree.extra_data[extra.start..extra.end], | |
| 1873 | .condition = condition, | |
| 1874 | .cases = cases, | |
| 1920 | 1875 | }, |
| 1921 | 1876 | .label_token = label_token, |
| 1922 | 1877 | }; |
| 1923 | 1878 | } |
| 1924 | 1879 | |
| 1925 | 1880 | pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1926 | const data = &tree.nodes.items(.data)[node]; | |
| 1927 | const values: *[1]Node.Index = &data.lhs; | |
| 1881 | const first_value, const target_expr = tree.nodeData(node).opt_node_and_node; | |
| 1928 | 1882 | return tree.fullSwitchCaseComponents(.{ |
| 1929 | .values = if (data.lhs == 0) values[0..0] else values[0..1], | |
| 1930 | .arrow_token = tree.nodes.items(.main_token)[node], | |
| 1931 | .target_expr = data.rhs, | |
| 1883 | .values = if (first_value == .none) | |
| 1884 | &.{} | |
| 1885 | else | |
| 1886 | // Ensure that the returned slice points into the existing memory of the Ast | |
| 1887 | (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1], | |
| 1888 | .arrow_token = tree.nodeMainToken(node), | |
| 1889 | .target_expr = target_expr, | |
| 1932 | 1890 | }, node); |
| 1933 | 1891 | } |
| 1934 | 1892 | |
| 1935 | 1893 | pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1936 | const data = tree.nodes.items(.data)[node]; | |
| 1937 | const extra = tree.extraData(data.lhs, Node.SubRange); | |
| 1894 | const extra_index, const target_expr = tree.nodeData(node).extra_and_node; | |
| 1895 | const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1938 | 1896 | return tree.fullSwitchCaseComponents(.{ |
| 1939 | .values = tree.extra_data[extra.start..extra.end], | |
| 1940 | .arrow_token = tree.nodes.items(.main_token)[node], | |
| 1941 | .target_expr = data.rhs, | |
| 1897 | .values = values, | |
| 1898 | .arrow_token = tree.nodeMainToken(node), | |
| 1899 | .target_expr = target_expr, | |
| 1942 | 1900 | }, node); |
| 1943 | 1901 | } |
| 1944 | 1902 | |
| 1945 | 1903 | pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { |
| 1946 | const data = tree.nodes.items(.data)[node]; | |
| 1904 | const template, const rparen = tree.nodeData(node).node_and_token; | |
| 1947 | 1905 | return tree.fullAsmComponents(.{ |
| 1948 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1949 | .template = data.lhs, | |
| 1906 | .asm_token = tree.nodeMainToken(node), | |
| 1907 | .template = template, | |
| 1950 | 1908 | .items = &.{}, |
| 1951 | .rparen = data.rhs, | |
| 1909 | .rparen = rparen, | |
| 1952 | 1910 | }); |
| 1953 | 1911 | } |
| 1954 | 1912 | |
| 1955 | 1913 | pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { |
| 1956 | const data = tree.nodes.items(.data)[node]; | |
| 1957 | const extra = tree.extraData(data.rhs, Node.Asm); | |
| 1914 | const template, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1915 | const extra = tree.extraData(extra_index, Node.Asm); | |
| 1916 | const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index); | |
| 1958 | 1917 | return tree.fullAsmComponents(.{ |
| 1959 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1960 | .template = data.lhs, | |
| 1961 | .items = tree.extra_data[extra.items_start..extra.items_end], | |
| 1918 | .asm_token = tree.nodeMainToken(node), | |
| 1919 | .template = template, | |
| 1920 | .items = items, | |
| 1962 | 1921 | .rparen = extra.rparen, |
| 1963 | 1922 | }); |
| 1964 | 1923 | } |
| 1965 | 1924 | |
| 1966 | 1925 | pub fn whileSimple(tree: Ast, node: Node.Index) full.While { |
| 1967 | const data = tree.nodes.items(.data)[node]; | |
| 1926 | const cond_expr, const then_expr = tree.nodeData(node).node_and_node; | |
| 1968 | 1927 | return tree.fullWhileComponents(.{ |
| 1969 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1970 | .cond_expr = data.lhs, | |
| 1971 | .cont_expr = 0, | |
| 1972 | .then_expr = data.rhs, | |
| 1973 | .else_expr = 0, | |
| 1928 | .while_token = tree.nodeMainToken(node), | |
| 1929 | .cond_expr = cond_expr, | |
| 1930 | .cont_expr = .none, | |
| 1931 | .then_expr = then_expr, | |
| 1932 | .else_expr = .none, | |
| 1974 | 1933 | }); |
| 1975 | 1934 | } |
| 1976 | 1935 | |
| 1977 | 1936 | pub fn whileCont(tree: Ast, node: Node.Index) full.While { |
| 1978 | const data = tree.nodes.items(.data)[node]; | |
| 1979 | const extra = tree.extraData(data.rhs, Node.WhileCont); | |
| 1937 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1938 | const extra = tree.extraData(extra_index, Node.WhileCont); | |
| 1980 | 1939 | return tree.fullWhileComponents(.{ |
| 1981 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1982 | .cond_expr = data.lhs, | |
| 1983 | .cont_expr = extra.cont_expr, | |
| 1940 | .while_token = tree.nodeMainToken(node), | |
| 1941 | .cond_expr = cond_expr, | |
| 1942 | .cont_expr = extra.cont_expr.toOptional(), | |
| 1984 | 1943 | .then_expr = extra.then_expr, |
| 1985 | .else_expr = 0, | |
| 1944 | .else_expr = .none, | |
| 1986 | 1945 | }); |
| 1987 | 1946 | } |
| 1988 | 1947 | |
| 1989 | 1948 | pub fn whileFull(tree: Ast, node: Node.Index) full.While { |
| 1990 | const data = tree.nodes.items(.data)[node]; | |
| 1991 | const extra = tree.extraData(data.rhs, Node.While); | |
| 1949 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1950 | const extra = tree.extraData(extra_index, Node.While); | |
| 1992 | 1951 | return tree.fullWhileComponents(.{ |
| 1993 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1994 | .cond_expr = data.lhs, | |
| 1952 | .while_token = tree.nodeMainToken(node), | |
| 1953 | .cond_expr = cond_expr, | |
| 1995 | 1954 | .cont_expr = extra.cont_expr, |
| 1996 | 1955 | .then_expr = extra.then_expr, |
| 1997 | .else_expr = extra.else_expr, | |
| 1956 | .else_expr = extra.else_expr.toOptional(), | |
| 1998 | 1957 | }); |
| 1999 | 1958 | } |
| 2000 | 1959 | |
| 2001 | 1960 | pub fn forSimple(tree: Ast, node: Node.Index) full.For { |
| 2002 | const data = &tree.nodes.items(.data)[node]; | |
| 2003 | const inputs: *[1]Node.Index = &data.lhs; | |
| 1961 | const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node; | |
| 2004 | 1962 | return tree.fullForComponents(.{ |
| 2005 | .for_token = tree.nodes.items(.main_token)[node], | |
| 2006 | .inputs = inputs[0..1], | |
| 2007 | .then_expr = data.rhs, | |
| 2008 | .else_expr = 0, | |
| 1963 | .for_token = tree.nodeMainToken(node), | |
| 1964 | .inputs = (&data[0])[0..1], | |
| 1965 | .then_expr = data[1], | |
| 1966 | .else_expr = .none, | |
| 2009 | 1967 | }); |
| 2010 | 1968 | } |
| 2011 | 1969 | |
| 2012 | 1970 | pub fn forFull(tree: Ast, node: Node.Index) full.For { |
| 2013 | const data = tree.nodes.items(.data)[node]; | |
| 2014 | const extra = @as(Node.For, @bitCast(data.rhs)); | |
| 2015 | const inputs = tree.extra_data[data.lhs..][0..extra.inputs]; | |
| 2016 | const then_expr = tree.extra_data[data.lhs + extra.inputs]; | |
| 2017 | const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0; | |
| 1971 | const extra_index, const extra = tree.nodeData(node).@"for"; | |
| 1972 | const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index); | |
| 1973 | const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]); | |
| 1974 | const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none; | |
| 2018 | 1975 | return tree.fullForComponents(.{ |
| 2019 | .for_token = tree.nodes.items(.main_token)[node], | |
| 1976 | .for_token = tree.nodeMainToken(node), | |
| 2020 | 1977 | .inputs = inputs, |
| 2021 | 1978 | .then_expr = then_expr, |
| 2022 | 1979 | .else_expr = else_expr, |
| ... | ... | @@ -2024,28 +1981,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For { |
| 2024 | 1981 | } |
| 2025 | 1982 | |
| 2026 | 1983 | pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call { |
| 2027 | const data = tree.nodes.items(.data)[node]; | |
| 2028 | buffer.* = .{data.rhs}; | |
| 2029 | const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0]; | |
| 1984 | const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node; | |
| 1985 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param}); | |
| 2030 | 1986 | return tree.fullCallComponents(.{ |
| 2031 | .lparen = tree.nodes.items(.main_token)[node], | |
| 2032 | .fn_expr = data.lhs, | |
| 1987 | .lparen = tree.nodeMainToken(node), | |
| 1988 | .fn_expr = fn_expr, | |
| 2033 | 1989 | .params = params, |
| 2034 | 1990 | }); |
| 2035 | 1991 | } |
| 2036 | 1992 | |
| 2037 | 1993 | pub fn callFull(tree: Ast, node: Node.Index) full.Call { |
| 2038 | const data = tree.nodes.items(.data)[node]; | |
| 2039 | const extra = tree.extraData(data.rhs, Node.SubRange); | |
| 1994 | const fn_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1995 | const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 2040 | 1996 | return tree.fullCallComponents(.{ |
| 2041 | .lparen = tree.nodes.items(.main_token)[node], | |
| 2042 | .fn_expr = data.lhs, | |
| 2043 | .params = tree.extra_data[extra.start..extra.end], | |
| 1997 | .lparen = tree.nodeMainToken(node), | |
| 1998 | .fn_expr = fn_expr, | |
| 1999 | .params = params, | |
| 2044 | 2000 | }); |
| 2045 | 2001 | } |
| 2046 | 2002 | |
| 2047 | 2003 | fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl { |
| 2048 | const token_tags = tree.tokens.items(.tag); | |
| 2049 | 2004 | var result: full.VarDecl = .{ |
| 2050 | 2005 | .ast = info, |
| 2051 | 2006 | .visib_token = null, |
| ... | ... | @@ -2057,7 +2012,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl |
| 2057 | 2012 | var i = info.mut_token; |
| 2058 | 2013 | while (i > 0) { |
| 2059 | 2014 | i -= 1; |
| 2060 | switch (token_tags[i]) { | |
| 2015 | switch (tree.tokenTag(i)) { | |
| 2061 | 2016 | .keyword_extern, .keyword_export => result.extern_export_token = i, |
| 2062 | 2017 | .keyword_comptime => result.comptime_token = i, |
| 2063 | 2018 | .keyword_pub => result.visib_token = i, |
| ... | ... | @@ -2070,14 +2025,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl |
| 2070 | 2025 | } |
| 2071 | 2026 | |
| 2072 | 2027 | fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure { |
| 2073 | const token_tags = tree.tokens.items(.tag); | |
| 2074 | const node_tags = tree.nodes.items(.tag); | |
| 2075 | 2028 | var result: full.AssignDestructure = .{ |
| 2076 | 2029 | .comptime_token = null, |
| 2077 | 2030 | .ast = info, |
| 2078 | 2031 | }; |
| 2079 | 2032 | const first_variable_token = tree.firstToken(info.variables[0]); |
| 2080 | const maybe_comptime_token = switch (node_tags[info.variables[0]]) { | |
| 2033 | const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) { | |
| 2081 | 2034 | .global_var_decl, |
| 2082 | 2035 | .local_var_decl, |
| 2083 | 2036 | .aligned_var_decl, |
| ... | ... | @@ -2085,14 +2038,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo |
| 2085 | 2038 | => first_variable_token, |
| 2086 | 2039 | else => first_variable_token - 1, |
| 2087 | 2040 | }; |
| 2088 | if (token_tags[maybe_comptime_token] == .keyword_comptime) { | |
| 2041 | if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) { | |
| 2089 | 2042 | result.comptime_token = maybe_comptime_token; |
| 2090 | 2043 | } |
| 2091 | 2044 | return result; |
| 2092 | 2045 | } |
| 2093 | 2046 | |
| 2094 | 2047 | fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 2095 | const token_tags = tree.tokens.items(.tag); | |
| 2096 | 2048 | var result: full.If = .{ |
| 2097 | 2049 | .ast = info, |
| 2098 | 2050 | .payload_token = null, |
| ... | ... | @@ -2102,14 +2054,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 2102 | 2054 | // if (cond_expr) |x| |
| 2103 | 2055 | // ^ ^ |
| 2104 | 2056 | const payload_pipe = tree.lastToken(info.cond_expr) + 2; |
| 2105 | if (token_tags[payload_pipe] == .pipe) { | |
| 2057 | if (tree.tokenTag(payload_pipe) == .pipe) { | |
| 2106 | 2058 | result.payload_token = payload_pipe + 1; |
| 2107 | 2059 | } |
| 2108 | if (info.else_expr != 0) { | |
| 2060 | if (info.else_expr != .none) { | |
| 2109 | 2061 | // then_expr else |x| |
| 2110 | 2062 | // ^ ^ |
| 2111 | 2063 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 2112 | if (token_tags[result.else_token + 1] == .pipe) { | |
| 2064 | if (tree.tokenTag(result.else_token + 1) == .pipe) { | |
| 2113 | 2065 | result.error_token = result.else_token + 2; |
| 2114 | 2066 | } |
| 2115 | 2067 | } |
| ... | ... | @@ -2117,12 +2069,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 2117 | 2069 | } |
| 2118 | 2070 | |
| 2119 | 2071 | fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField { |
| 2120 | const token_tags = tree.tokens.items(.tag); | |
| 2121 | 2072 | var result: full.ContainerField = .{ |
| 2122 | 2073 | .ast = info, |
| 2123 | 2074 | .comptime_token = null, |
| 2124 | 2075 | }; |
| 2125 | if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) { | |
| 2076 | if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) { | |
| 2126 | 2077 | // comptime type = init, |
| 2127 | 2078 | // ^ ^ |
| 2128 | 2079 | // comptime name: type = init, |
| ... | ... | @@ -2133,7 +2084,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) |
| 2133 | 2084 | } |
| 2134 | 2085 | |
| 2135 | 2086 | fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto { |
| 2136 | const token_tags = tree.tokens.items(.tag); | |
| 2137 | 2087 | var result: full.FnProto = .{ |
| 2138 | 2088 | .ast = info, |
| 2139 | 2089 | .visib_token = null, |
| ... | ... | @@ -2145,7 +2095,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto |
| 2145 | 2095 | var i = info.fn_token; |
| 2146 | 2096 | while (i > 0) { |
| 2147 | 2097 | i -= 1; |
| 2148 | switch (token_tags[i]) { | |
| 2098 | switch (tree.tokenTag(i)) { | |
| 2149 | 2099 | .keyword_extern, |
| 2150 | 2100 | .keyword_export, |
| 2151 | 2101 | .keyword_inline, |
| ... | ... | @@ -2157,25 +2107,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto |
| 2157 | 2107 | } |
| 2158 | 2108 | } |
| 2159 | 2109 | const after_fn_token = info.fn_token + 1; |
| 2160 | if (token_tags[after_fn_token] == .identifier) { | |
| 2110 | if (tree.tokenTag(after_fn_token) == .identifier) { | |
| 2161 | 2111 | result.name_token = after_fn_token; |
| 2162 | 2112 | result.lparen = after_fn_token + 1; |
| 2163 | 2113 | } else { |
| 2164 | 2114 | result.lparen = after_fn_token; |
| 2165 | 2115 | } |
| 2166 | assert(token_tags[result.lparen] == .l_paren); | |
| 2116 | assert(tree.tokenTag(result.lparen) == .l_paren); | |
| 2167 | 2117 | |
| 2168 | 2118 | return result; |
| 2169 | 2119 | } |
| 2170 | 2120 | |
| 2171 | 2121 | fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType { |
| 2172 | const token_tags = tree.tokens.items(.tag); | |
| 2173 | const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) { | |
| 2122 | const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) { | |
| 2174 | 2123 | .asterisk, |
| 2175 | 2124 | .asterisk_asterisk, |
| 2176 | 2125 | => .one, |
| 2177 | .l_bracket => switch (token_tags[info.main_token + 1]) { | |
| 2178 | .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many, | |
| 2126 | .l_bracket => switch (tree.tokenTag(info.main_token + 1)) { | |
| 2127 | .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many, | |
| 2179 | 2128 | else => .slice, |
| 2180 | 2129 | }, |
| 2181 | 2130 | else => unreachable, |
| ... | ... | @@ -2191,23 +2140,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType |
| 2191 | 2140 | // here while looking for modifiers as that could result in false |
| 2192 | 2141 | // positives. Therefore, start after a sentinel if there is one and |
| 2193 | 2142 | // skip over any align node and bit range nodes. |
| 2194 | var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) { | |
| 2143 | var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) { | |
| 2195 | 2144 | .many, .c => info.main_token + 1, |
| 2196 | 2145 | else => info.main_token, |
| 2197 | 2146 | }; |
| 2198 | 2147 | const end = tree.firstToken(info.child_type); |
| 2199 | 2148 | while (i < end) : (i += 1) { |
| 2200 | switch (token_tags[i]) { | |
| 2149 | switch (tree.tokenTag(i)) { | |
| 2201 | 2150 | .keyword_allowzero => result.allowzero_token = i, |
| 2202 | 2151 | .keyword_const => result.const_token = i, |
| 2203 | 2152 | .keyword_volatile => result.volatile_token = i, |
| 2204 | 2153 | .keyword_align => { |
| 2205 | assert(info.align_node != 0); | |
| 2206 | if (info.bit_range_end != 0) { | |
| 2207 | assert(info.bit_range_start != 0); | |
| 2208 | i = tree.lastToken(info.bit_range_end) + 1; | |
| 2154 | const align_node = info.align_node.unwrap().?; | |
| 2155 | if (info.bit_range_end.unwrap()) |bit_range_end| { | |
| 2156 | assert(info.bit_range_start != .none); | |
| 2157 | i = tree.lastToken(bit_range_end) + 1; | |
| 2209 | 2158 | } else { |
| 2210 | i = tree.lastToken(info.align_node) + 1; | |
| 2159 | i = tree.lastToken(align_node) + 1; | |
| 2211 | 2160 | } |
| 2212 | 2161 | }, |
| 2213 | 2162 | else => {}, |
| ... | ... | @@ -2217,30 +2166,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType |
| 2217 | 2166 | } |
| 2218 | 2167 | |
| 2219 | 2168 | fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl { |
| 2220 | const token_tags = tree.tokens.items(.tag); | |
| 2221 | 2169 | var result: full.ContainerDecl = .{ |
| 2222 | 2170 | .ast = info, |
| 2223 | 2171 | .layout_token = null, |
| 2224 | 2172 | }; |
| 2225 | 2173 | |
| 2226 | if (info.main_token == 0) return result; | |
| 2174 | if (info.main_token == 0) return result; // .root | |
| 2175 | const previous_token = info.main_token - 1; | |
| 2227 | 2176 | |
| 2228 | switch (token_tags[info.main_token - 1]) { | |
| 2229 | .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1, | |
| 2177 | switch (tree.tokenTag(previous_token)) { | |
| 2178 | .keyword_extern, .keyword_packed => result.layout_token = previous_token, | |
| 2230 | 2179 | else => {}, |
| 2231 | 2180 | } |
| 2232 | 2181 | return result; |
| 2233 | 2182 | } |
| 2234 | 2183 | |
| 2235 | 2184 | fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch { |
| 2236 | const token_tags = tree.tokens.items(.tag); | |
| 2237 | 2185 | const tok_i = info.switch_token -| 1; |
| 2238 | 2186 | var result: full.Switch = .{ |
| 2239 | 2187 | .ast = info, |
| 2240 | 2188 | .label_token = null, |
| 2241 | 2189 | }; |
| 2242 | if (token_tags[tok_i] == .colon and | |
| 2243 | token_tags[tok_i -| 1] == .identifier) | |
| 2190 | if (tree.tokenTag(tok_i) == .colon and | |
| 2191 | tree.tokenTag(tok_i -| 1) == .identifier) | |
| 2244 | 2192 | { |
| 2245 | 2193 | result.label_token = tok_i - 1; |
| 2246 | 2194 | } |
| ... | ... | @@ -2248,26 +2196,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch { |
| 2248 | 2196 | } |
| 2249 | 2197 | |
| 2250 | 2198 | fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase { |
| 2251 | const token_tags = tree.tokens.items(.tag); | |
| 2252 | const node_tags = tree.nodes.items(.tag); | |
| 2253 | 2199 | var result: full.SwitchCase = .{ |
| 2254 | 2200 | .ast = info, |
| 2255 | 2201 | .payload_token = null, |
| 2256 | 2202 | .inline_token = null, |
| 2257 | 2203 | }; |
| 2258 | if (token_tags[info.arrow_token + 1] == .pipe) { | |
| 2204 | if (tree.tokenTag(info.arrow_token + 1) == .pipe) { | |
| 2259 | 2205 | result.payload_token = info.arrow_token + 2; |
| 2260 | 2206 | } |
| 2261 | switch (node_tags[node]) { | |
| 2262 | .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node), | |
| 2263 | else => {}, | |
| 2264 | } | |
| 2207 | result.inline_token = switch (tree.nodeTag(node)) { | |
| 2208 | .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0) | |
| 2209 | info.arrow_token - 2 | |
| 2210 | else | |
| 2211 | tree.firstToken(result.ast.values[0]) - 1, | |
| 2212 | else => null, | |
| 2213 | }; | |
| 2265 | 2214 | return result; |
| 2266 | 2215 | } |
| 2267 | 2216 | |
| 2268 | 2217 | fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2269 | const token_tags = tree.tokens.items(.tag); | |
| 2270 | const node_tags = tree.nodes.items(.tag); | |
| 2271 | 2218 | var result: full.Asm = .{ |
| 2272 | 2219 | .ast = info, |
| 2273 | 2220 | .volatile_token = null, |
| ... | ... | @@ -2275,11 +2222,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2275 | 2222 | .outputs = &.{}, |
| 2276 | 2223 | .first_clobber = null, |
| 2277 | 2224 | }; |
| 2278 | if (token_tags[info.asm_token + 1] == .keyword_volatile) { | |
| 2225 | if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) { | |
| 2279 | 2226 | result.volatile_token = info.asm_token + 1; |
| 2280 | 2227 | } |
| 2281 | 2228 | const outputs_end: usize = for (info.items, 0..) |item, i| { |
| 2282 | switch (node_tags[item]) { | |
| 2229 | switch (tree.nodeTag(item)) { | |
| 2283 | 2230 | .asm_output => continue, |
| 2284 | 2231 | else => break i, |
| 2285 | 2232 | } |
| ... | ... | @@ -2291,10 +2238,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2291 | 2238 | if (info.items.len == 0) { |
| 2292 | 2239 | // asm ("foo" ::: "a", "b"); |
| 2293 | 2240 | const template_token = tree.lastToken(info.template); |
| 2294 | if (token_tags[template_token + 1] == .colon and | |
| 2295 | token_tags[template_token + 2] == .colon and | |
| 2296 | token_tags[template_token + 3] == .colon and | |
| 2297 | token_tags[template_token + 4] == .string_literal) | |
| 2241 | if (tree.tokenTag(template_token + 1) == .colon and | |
| 2242 | tree.tokenTag(template_token + 2) == .colon and | |
| 2243 | tree.tokenTag(template_token + 3) == .colon and | |
| 2244 | tree.tokenTag(template_token + 4) == .string_literal) | |
| 2298 | 2245 | { |
| 2299 | 2246 | result.first_clobber = template_token + 4; |
| 2300 | 2247 | } |
| ... | ... | @@ -2304,9 +2251,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2304 | 2251 | const rparen = tree.lastToken(last_input); |
| 2305 | 2252 | var i = rparen + 1; |
| 2306 | 2253 | // Allow a (useless) comma right after the closing parenthesis. |
| 2307 | if (token_tags[i] == .comma) i += 1; | |
| 2308 | if (token_tags[i] == .colon and | |
| 2309 | token_tags[i + 1] == .string_literal) | |
| 2254 | if (tree.tokenTag(i) == .comma) i = i + 1; | |
| 2255 | if (tree.tokenTag(i) == .colon and | |
| 2256 | tree.tokenTag(i + 1) == .string_literal) | |
| 2310 | 2257 | { |
| 2311 | 2258 | result.first_clobber = i + 1; |
| 2312 | 2259 | } |
| ... | ... | @@ -2316,10 +2263,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2316 | 2263 | const rparen = tree.lastToken(last_output); |
| 2317 | 2264 | var i = rparen + 1; |
| 2318 | 2265 | // Allow a (useless) comma right after the closing parenthesis. |
| 2319 | if (token_tags[i] == .comma) i += 1; | |
| 2320 | if (token_tags[i] == .colon and | |
| 2321 | token_tags[i + 1] == .colon and | |
| 2322 | token_tags[i + 2] == .string_literal) | |
| 2266 | if (tree.tokenTag(i) == .comma) i = i + 1; | |
| 2267 | if (tree.tokenTag(i) == .colon and | |
| 2268 | tree.tokenTag(i + 1) == .colon and | |
| 2269 | tree.tokenTag(i + 2) == .string_literal) | |
| 2323 | 2270 | { |
| 2324 | 2271 | result.first_clobber = i + 2; |
| 2325 | 2272 | } |
| ... | ... | @@ -2329,7 +2276,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2329 | 2276 | } |
| 2330 | 2277 | |
| 2331 | 2278 | fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2332 | const token_tags = tree.tokens.items(.tag); | |
| 2333 | 2279 | var result: full.While = .{ |
| 2334 | 2280 | .ast = info, |
| 2335 | 2281 | .inline_token = null, |
| ... | ... | @@ -2338,25 +2284,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2338 | 2284 | .else_token = undefined, |
| 2339 | 2285 | .error_token = null, |
| 2340 | 2286 | }; |
| 2341 | var tok_i = info.while_token -| 1; | |
| 2342 | if (token_tags[tok_i] == .keyword_inline) { | |
| 2343 | result.inline_token = tok_i; | |
| 2344 | tok_i -|= 1; | |
| 2287 | var tok_i = info.while_token; | |
| 2288 | if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) { | |
| 2289 | result.inline_token = tok_i - 1; | |
| 2290 | tok_i = tok_i - 1; | |
| 2345 | 2291 | } |
| 2346 | if (token_tags[tok_i] == .colon and | |
| 2347 | token_tags[tok_i -| 1] == .identifier) | |
| 2348 | { | |
| 2349 | result.label_token = tok_i - 1; | |
| 2292 | if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) { | |
| 2293 | result.label_token = tok_i - 2; | |
| 2350 | 2294 | } |
| 2351 | 2295 | const last_cond_token = tree.lastToken(info.cond_expr); |
| 2352 | if (token_tags[last_cond_token + 2] == .pipe) { | |
| 2296 | if (tree.tokenTag(last_cond_token + 2) == .pipe) { | |
| 2353 | 2297 | result.payload_token = last_cond_token + 3; |
| 2354 | 2298 | } |
| 2355 | if (info.else_expr != 0) { | |
| 2299 | if (info.else_expr != .none) { | |
| 2356 | 2300 | // then_expr else |x| |
| 2357 | 2301 | // ^ ^ |
| 2358 | 2302 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 2359 | if (token_tags[result.else_token + 1] == .pipe) { | |
| 2303 | if (tree.tokenTag(result.else_token + 1) == .pipe) { | |
| 2360 | 2304 | result.error_token = result.else_token + 2; |
| 2361 | 2305 | } |
| 2362 | 2306 | } |
| ... | ... | @@ -2364,7 +2308,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2364 | 2308 | } |
| 2365 | 2309 | |
| 2366 | 2310 | fn fullForComponents(tree: Ast, info: full.For.Components) full.For { |
| 2367 | const token_tags = tree.tokens.items(.tag); | |
| 2368 | 2311 | var result: full.For = .{ |
| 2369 | 2312 | .ast = info, |
| 2370 | 2313 | .inline_token = null, |
| ... | ... | @@ -2372,39 +2315,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For { |
| 2372 | 2315 | .payload_token = undefined, |
| 2373 | 2316 | .else_token = undefined, |
| 2374 | 2317 | }; |
| 2375 | var tok_i = info.for_token -| 1; | |
| 2376 | if (token_tags[tok_i] == .keyword_inline) { | |
| 2377 | result.inline_token = tok_i; | |
| 2378 | tok_i -|= 1; | |
| 2318 | var tok_i = info.for_token; | |
| 2319 | if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) { | |
| 2320 | result.inline_token = tok_i - 1; | |
| 2321 | tok_i = tok_i - 1; | |
| 2379 | 2322 | } |
| 2380 | if (token_tags[tok_i] == .colon and | |
| 2381 | token_tags[tok_i -| 1] == .identifier) | |
| 2382 | { | |
| 2383 | result.label_token = tok_i - 1; | |
| 2323 | if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) { | |
| 2324 | result.label_token = tok_i - 2; | |
| 2384 | 2325 | } |
| 2385 | 2326 | const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]); |
| 2386 | result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma); | |
| 2387 | if (info.else_expr != 0) { | |
| 2327 | result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma); | |
| 2328 | if (info.else_expr != .none) { | |
| 2388 | 2329 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 2389 | 2330 | } |
| 2390 | 2331 | return result; |
| 2391 | 2332 | } |
| 2392 | 2333 | |
| 2393 | 2334 | fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call { |
| 2394 | const token_tags = tree.tokens.items(.tag); | |
| 2395 | 2335 | var result: full.Call = .{ |
| 2396 | 2336 | .ast = info, |
| 2397 | 2337 | .async_token = null, |
| 2398 | 2338 | }; |
| 2399 | 2339 | const first_token = tree.firstToken(info.fn_expr); |
| 2400 | if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) { | |
| 2340 | if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) { | |
| 2401 | 2341 | result.async_token = first_token - 1; |
| 2402 | 2342 | } |
| 2403 | 2343 | return result; |
| 2404 | 2344 | } |
| 2405 | 2345 | |
| 2406 | 2346 | pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl { |
| 2407 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2347 | return switch (tree.nodeTag(node)) { | |
| 2408 | 2348 | .global_var_decl => tree.globalVarDecl(node), |
| 2409 | 2349 | .local_var_decl => tree.localVarDecl(node), |
| 2410 | 2350 | .aligned_var_decl => tree.alignedVarDecl(node), |
| ... | ... | @@ -2414,7 +2354,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl { |
| 2414 | 2354 | } |
| 2415 | 2355 | |
| 2416 | 2356 | pub fn fullIf(tree: Ast, node: Node.Index) ?full.If { |
| 2417 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2357 | return switch (tree.nodeTag(node)) { | |
| 2418 | 2358 | .if_simple => tree.ifSimple(node), |
| 2419 | 2359 | .@"if" => tree.ifFull(node), |
| 2420 | 2360 | else => null, |
| ... | ... | @@ -2422,7 +2362,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If { |
| 2422 | 2362 | } |
| 2423 | 2363 | |
| 2424 | 2364 | pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While { |
| 2425 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2365 | return switch (tree.nodeTag(node)) { | |
| 2426 | 2366 | .while_simple => tree.whileSimple(node), |
| 2427 | 2367 | .while_cont => tree.whileCont(node), |
| 2428 | 2368 | .@"while" => tree.whileFull(node), |
| ... | ... | @@ -2431,7 +2371,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While { |
| 2431 | 2371 | } |
| 2432 | 2372 | |
| 2433 | 2373 | pub fn fullFor(tree: Ast, node: Node.Index) ?full.For { |
| 2434 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2374 | return switch (tree.nodeTag(node)) { | |
| 2435 | 2375 | .for_simple => tree.forSimple(node), |
| 2436 | 2376 | .@"for" => tree.forFull(node), |
| 2437 | 2377 | else => null, |
| ... | ... | @@ -2439,7 +2379,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For { |
| 2439 | 2379 | } |
| 2440 | 2380 | |
| 2441 | 2381 | pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField { |
| 2442 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2382 | return switch (tree.nodeTag(node)) { | |
| 2443 | 2383 | .container_field_init => tree.containerFieldInit(node), |
| 2444 | 2384 | .container_field_align => tree.containerFieldAlign(node), |
| 2445 | 2385 | .container_field => tree.containerField(node), |
| ... | ... | @@ -2448,18 +2388,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField { |
| 2448 | 2388 | } |
| 2449 | 2389 | |
| 2450 | 2390 | pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto { |
| 2451 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2391 | return switch (tree.nodeTag(node)) { | |
| 2452 | 2392 | .fn_proto => tree.fnProto(node), |
| 2453 | 2393 | .fn_proto_multi => tree.fnProtoMulti(node), |
| 2454 | 2394 | .fn_proto_one => tree.fnProtoOne(buffer, node), |
| 2455 | 2395 | .fn_proto_simple => tree.fnProtoSimple(buffer, node), |
| 2456 | .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs), | |
| 2396 | .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]), | |
| 2457 | 2397 | else => null, |
| 2458 | 2398 | }; |
| 2459 | 2399 | } |
| 2460 | 2400 | |
| 2461 | 2401 | pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit { |
| 2462 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2402 | return switch (tree.nodeTag(node)) { | |
| 2463 | 2403 | .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node), |
| 2464 | 2404 | .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node), |
| 2465 | 2405 | .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node), |
| ... | ... | @@ -2469,7 +2409,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ? |
| 2469 | 2409 | } |
| 2470 | 2410 | |
| 2471 | 2411 | pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit { |
| 2472 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2412 | return switch (tree.nodeTag(node)) { | |
| 2473 | 2413 | .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node), |
| 2474 | 2414 | .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node), |
| 2475 | 2415 | .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node), |
| ... | ... | @@ -2479,7 +2419,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full. |
| 2479 | 2419 | } |
| 2480 | 2420 | |
| 2481 | 2421 | pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType { |
| 2482 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2422 | return switch (tree.nodeTag(node)) { | |
| 2483 | 2423 | .array_type => tree.arrayType(node), |
| 2484 | 2424 | .array_type_sentinel => tree.arrayTypeSentinel(node), |
| 2485 | 2425 | else => null, |
| ... | ... | @@ -2487,7 +2427,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType { |
| 2487 | 2427 | } |
| 2488 | 2428 | |
| 2489 | 2429 | pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType { |
| 2490 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2430 | return switch (tree.nodeTag(node)) { | |
| 2491 | 2431 | .ptr_type_aligned => tree.ptrTypeAligned(node), |
| 2492 | 2432 | .ptr_type_sentinel => tree.ptrTypeSentinel(node), |
| 2493 | 2433 | .ptr_type => tree.ptrType(node), |
| ... | ... | @@ -2497,7 +2437,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType { |
| 2497 | 2437 | } |
| 2498 | 2438 | |
| 2499 | 2439 | pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice { |
| 2500 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2440 | return switch (tree.nodeTag(node)) { | |
| 2501 | 2441 | .slice_open => tree.sliceOpen(node), |
| 2502 | 2442 | .slice => tree.slice(node), |
| 2503 | 2443 | .slice_sentinel => tree.sliceSentinel(node), |
| ... | ... | @@ -2506,7 +2446,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice { |
| 2506 | 2446 | } |
| 2507 | 2447 | |
| 2508 | 2448 | pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl { |
| 2509 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2449 | return switch (tree.nodeTag(node)) { | |
| 2510 | 2450 | .root => tree.containerDeclRoot(), |
| 2511 | 2451 | .container_decl, .container_decl_trailing => tree.containerDecl(node), |
| 2512 | 2452 | .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node), |
| ... | ... | @@ -2519,14 +2459,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index |
| 2519 | 2459 | } |
| 2520 | 2460 | |
| 2521 | 2461 | pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch { |
| 2522 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2462 | return switch (tree.nodeTag(node)) { | |
| 2523 | 2463 | .@"switch", .switch_comma => tree.switchFull(node), |
| 2524 | 2464 | else => null, |
| 2525 | 2465 | }; |
| 2526 | 2466 | } |
| 2527 | 2467 | |
| 2528 | 2468 | pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase { |
| 2529 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2469 | return switch (tree.nodeTag(node)) { | |
| 2530 | 2470 | .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node), |
| 2531 | 2471 | .switch_case, .switch_case_inline => tree.switchCase(node), |
| 2532 | 2472 | else => null, |
| ... | ... | @@ -2534,7 +2474,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase { |
| 2534 | 2474 | } |
| 2535 | 2475 | |
| 2536 | 2476 | pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { |
| 2537 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2477 | return switch (tree.nodeTag(node)) { | |
| 2538 | 2478 | .asm_simple => tree.asmSimple(node), |
| 2539 | 2479 | .@"asm" => tree.asmFull(node), |
| 2540 | 2480 | else => null, |
| ... | ... | @@ -2542,13 +2482,29 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { |
| 2542 | 2482 | } |
| 2543 | 2483 | |
| 2544 | 2484 | pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { |
| 2545 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2485 | return switch (tree.nodeTag(node)) { | |
| 2546 | 2486 | .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node), |
| 2547 | 2487 | .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node), |
| 2548 | 2488 | else => null, |
| 2549 | 2489 | }; |
| 2550 | 2490 | } |
| 2551 | 2491 | |
| 2492 | pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index { | |
| 2493 | return switch (tree.nodeTag(node)) { | |
| 2494 | .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node), | |
| 2495 | .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index), | |
| 2496 | else => null, | |
| 2497 | }; | |
| 2498 | } | |
| 2499 | ||
| 2500 | pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index { | |
| 2501 | return switch (tree.nodeTag(node)) { | |
| 2502 | .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node), | |
| 2503 | .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index), | |
| 2504 | else => null, | |
| 2505 | }; | |
| 2506 | } | |
| 2507 | ||
| 2552 | 2508 | /// Fully assembled AST node information. |
| 2553 | 2509 | pub const full = struct { |
| 2554 | 2510 | pub const VarDecl = struct { |
| ... | ... | @@ -2561,11 +2517,11 @@ pub const full = struct { |
| 2561 | 2517 | |
| 2562 | 2518 | pub const Components = struct { |
| 2563 | 2519 | mut_token: TokenIndex, |
| 2564 | type_node: Node.Index, | |
| 2565 | align_node: Node.Index, | |
| 2566 | addrspace_node: Node.Index, | |
| 2567 | section_node: Node.Index, | |
| 2568 | init_node: Node.Index, | |
| 2520 | type_node: Node.OptionalIndex, | |
| 2521 | align_node: Node.OptionalIndex, | |
| 2522 | addrspace_node: Node.OptionalIndex, | |
| 2523 | section_node: Node.OptionalIndex, | |
| 2524 | init_node: Node.OptionalIndex, | |
| 2569 | 2525 | }; |
| 2570 | 2526 | |
| 2571 | 2527 | pub fn firstToken(var_decl: VarDecl) TokenIndex { |
| ... | ... | @@ -2594,7 +2550,7 @@ pub const full = struct { |
| 2594 | 2550 | payload_token: ?TokenIndex, |
| 2595 | 2551 | /// Points to the identifier after the `|`. |
| 2596 | 2552 | error_token: ?TokenIndex, |
| 2597 | /// Populated only if else_expr != 0. | |
| 2553 | /// Populated only if else_expr != .none. | |
| 2598 | 2554 | else_token: TokenIndex, |
| 2599 | 2555 | ast: Components, |
| 2600 | 2556 | |
| ... | ... | @@ -2602,7 +2558,7 @@ pub const full = struct { |
| 2602 | 2558 | if_token: TokenIndex, |
| 2603 | 2559 | cond_expr: Node.Index, |
| 2604 | 2560 | then_expr: Node.Index, |
| 2605 | else_expr: Node.Index, | |
| 2561 | else_expr: Node.OptionalIndex, | |
| 2606 | 2562 | }; |
| 2607 | 2563 | }; |
| 2608 | 2564 | |
| ... | ... | @@ -2612,15 +2568,15 @@ pub const full = struct { |
| 2612 | 2568 | label_token: ?TokenIndex, |
| 2613 | 2569 | payload_token: ?TokenIndex, |
| 2614 | 2570 | error_token: ?TokenIndex, |
| 2615 | /// Populated only if else_expr != 0. | |
| 2571 | /// Populated only if else_expr != none. | |
| 2616 | 2572 | else_token: TokenIndex, |
| 2617 | 2573 | |
| 2618 | 2574 | pub const Components = struct { |
| 2619 | 2575 | while_token: TokenIndex, |
| 2620 | 2576 | cond_expr: Node.Index, |
| 2621 | cont_expr: Node.Index, | |
| 2577 | cont_expr: Node.OptionalIndex, | |
| 2622 | 2578 | then_expr: Node.Index, |
| 2623 | else_expr: Node.Index, | |
| 2579 | else_expr: Node.OptionalIndex, | |
| 2624 | 2580 | }; |
| 2625 | 2581 | }; |
| 2626 | 2582 | |
| ... | ... | @@ -2629,14 +2585,14 @@ pub const full = struct { |
| 2629 | 2585 | inline_token: ?TokenIndex, |
| 2630 | 2586 | label_token: ?TokenIndex, |
| 2631 | 2587 | payload_token: TokenIndex, |
| 2632 | /// Populated only if else_expr != 0. | |
| 2633 | else_token: TokenIndex, | |
| 2588 | /// Populated only if else_expr != .none. | |
| 2589 | else_token: ?TokenIndex, | |
| 2634 | 2590 | |
| 2635 | 2591 | pub const Components = struct { |
| 2636 | 2592 | for_token: TokenIndex, |
| 2637 | 2593 | inputs: []const Node.Index, |
| 2638 | 2594 | then_expr: Node.Index, |
| 2639 | else_expr: Node.Index, | |
| 2595 | else_expr: Node.OptionalIndex, | |
| 2640 | 2596 | }; |
| 2641 | 2597 | }; |
| 2642 | 2598 | |
| ... | ... | @@ -2646,9 +2602,10 @@ pub const full = struct { |
| 2646 | 2602 | |
| 2647 | 2603 | pub const Components = struct { |
| 2648 | 2604 | main_token: TokenIndex, |
| 2649 | type_expr: Node.Index, | |
| 2650 | align_expr: Node.Index, | |
| 2651 | value_expr: Node.Index, | |
| 2605 | /// Can only be `.none` after calling `convertToNonTupleLike`. | |
| 2606 | type_expr: Node.OptionalIndex, | |
| 2607 | align_expr: Node.OptionalIndex, | |
| 2608 | value_expr: Node.OptionalIndex, | |
| 2652 | 2609 | tuple_like: bool, |
| 2653 | 2610 | }; |
| 2654 | 2611 | |
| ... | ... | @@ -2656,11 +2613,11 @@ pub const full = struct { |
| 2656 | 2613 | return cf.comptime_token orelse cf.ast.main_token; |
| 2657 | 2614 | } |
| 2658 | 2615 | |
| 2659 | pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void { | |
| 2616 | pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void { | |
| 2660 | 2617 | if (!cf.ast.tuple_like) return; |
| 2661 | if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return; | |
| 2618 | if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return; | |
| 2662 | 2619 | |
| 2663 | cf.ast.type_expr = 0; | |
| 2620 | cf.ast.type_expr = .none; | |
| 2664 | 2621 | cf.ast.tuple_like = false; |
| 2665 | 2622 | } |
| 2666 | 2623 | }; |
| ... | ... | @@ -2676,12 +2633,12 @@ pub const full = struct { |
| 2676 | 2633 | pub const Components = struct { |
| 2677 | 2634 | proto_node: Node.Index, |
| 2678 | 2635 | fn_token: TokenIndex, |
| 2679 | return_type: Node.Index, | |
| 2636 | return_type: Node.OptionalIndex, | |
| 2680 | 2637 | params: []const Node.Index, |
| 2681 | align_expr: Node.Index, | |
| 2682 | addrspace_expr: Node.Index, | |
| 2683 | section_expr: Node.Index, | |
| 2684 | callconv_expr: Node.Index, | |
| 2638 | align_expr: Node.OptionalIndex, | |
| 2639 | addrspace_expr: Node.OptionalIndex, | |
| 2640 | section_expr: Node.OptionalIndex, | |
| 2641 | callconv_expr: Node.OptionalIndex, | |
| 2685 | 2642 | }; |
| 2686 | 2643 | |
| 2687 | 2644 | pub const Param = struct { |
| ... | ... | @@ -2689,7 +2646,7 @@ pub const full = struct { |
| 2689 | 2646 | name_token: ?TokenIndex, |
| 2690 | 2647 | comptime_noalias: ?TokenIndex, |
| 2691 | 2648 | anytype_ellipsis3: ?TokenIndex, |
| 2692 | type_expr: Node.Index, | |
| 2649 | type_expr: ?Node.Index, | |
| 2693 | 2650 | }; |
| 2694 | 2651 | |
| 2695 | 2652 | pub fn firstToken(fn_proto: FnProto) TokenIndex { |
| ... | ... | @@ -2709,7 +2666,7 @@ pub const full = struct { |
| 2709 | 2666 | tok_flag: bool, |
| 2710 | 2667 | |
| 2711 | 2668 | pub fn next(it: *Iterator) ?Param { |
| 2712 | const token_tags = it.tree.tokens.items(.tag); | |
| 2669 | const tree = it.tree; | |
| 2713 | 2670 | while (true) { |
| 2714 | 2671 | var first_doc_comment: ?TokenIndex = null; |
| 2715 | 2672 | var comptime_noalias: ?TokenIndex = null; |
| ... | ... | @@ -2719,8 +2676,8 @@ pub const full = struct { |
| 2719 | 2676 | return null; |
| 2720 | 2677 | } |
| 2721 | 2678 | const param_type = it.fn_proto.ast.params[it.param_i]; |
| 2722 | var tok_i = it.tree.firstToken(param_type) - 1; | |
| 2723 | while (true) : (tok_i -= 1) switch (token_tags[tok_i]) { | |
| 2679 | var tok_i = tree.firstToken(param_type) - 1; | |
| 2680 | while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) { | |
| 2724 | 2681 | .colon => continue, |
| 2725 | 2682 | .identifier => name_token = tok_i, |
| 2726 | 2683 | .doc_comment => first_doc_comment = tok_i, |
| ... | ... | @@ -2728,9 +2685,9 @@ pub const full = struct { |
| 2728 | 2685 | else => break, |
| 2729 | 2686 | }; |
| 2730 | 2687 | it.param_i += 1; |
| 2731 | it.tok_i = it.tree.lastToken(param_type) + 1; | |
| 2688 | it.tok_i = tree.lastToken(param_type) + 1; | |
| 2732 | 2689 | // Look for anytype and ... params afterwards. |
| 2733 | if (token_tags[it.tok_i] == .comma) { | |
| 2690 | if (tree.tokenTag(it.tok_i) == .comma) { | |
| 2734 | 2691 | it.tok_i += 1; |
| 2735 | 2692 | } |
| 2736 | 2693 | it.tok_flag = true; |
| ... | ... | @@ -2742,19 +2699,19 @@ pub const full = struct { |
| 2742 | 2699 | .type_expr = param_type, |
| 2743 | 2700 | }; |
| 2744 | 2701 | } |
| 2745 | if (token_tags[it.tok_i] == .comma) { | |
| 2702 | if (tree.tokenTag(it.tok_i) == .comma) { | |
| 2746 | 2703 | it.tok_i += 1; |
| 2747 | 2704 | } |
| 2748 | if (token_tags[it.tok_i] == .r_paren) { | |
| 2705 | if (tree.tokenTag(it.tok_i) == .r_paren) { | |
| 2749 | 2706 | return null; |
| 2750 | 2707 | } |
| 2751 | if (token_tags[it.tok_i] == .doc_comment) { | |
| 2708 | if (tree.tokenTag(it.tok_i) == .doc_comment) { | |
| 2752 | 2709 | first_doc_comment = it.tok_i; |
| 2753 | while (token_tags[it.tok_i] == .doc_comment) { | |
| 2710 | while (tree.tokenTag(it.tok_i) == .doc_comment) { | |
| 2754 | 2711 | it.tok_i += 1; |
| 2755 | 2712 | } |
| 2756 | 2713 | } |
| 2757 | switch (token_tags[it.tok_i]) { | |
| 2714 | switch (tree.tokenTag(it.tok_i)) { | |
| 2758 | 2715 | .ellipsis3 => { |
| 2759 | 2716 | it.tok_flag = false; // Next iteration should return null. |
| 2760 | 2717 | return Param{ |
| ... | ... | @@ -2762,7 +2719,7 @@ pub const full = struct { |
| 2762 | 2719 | .comptime_noalias = null, |
| 2763 | 2720 | .name_token = null, |
| 2764 | 2721 | .anytype_ellipsis3 = it.tok_i, |
| 2765 | .type_expr = 0, | |
| 2722 | .type_expr = null, | |
| 2766 | 2723 | }; |
| 2767 | 2724 | }, |
| 2768 | 2725 | .keyword_noalias, .keyword_comptime => { |
| ... | ... | @@ -2771,20 +2728,20 @@ pub const full = struct { |
| 2771 | 2728 | }, |
| 2772 | 2729 | else => {}, |
| 2773 | 2730 | } |
| 2774 | if (token_tags[it.tok_i] == .identifier and | |
| 2775 | token_tags[it.tok_i + 1] == .colon) | |
| 2731 | if (tree.tokenTag(it.tok_i) == .identifier and | |
| 2732 | tree.tokenTag(it.tok_i + 1) == .colon) | |
| 2776 | 2733 | { |
| 2777 | 2734 | name_token = it.tok_i; |
| 2778 | 2735 | it.tok_i += 2; |
| 2779 | 2736 | } |
| 2780 | if (token_tags[it.tok_i] == .keyword_anytype) { | |
| 2737 | if (tree.tokenTag(it.tok_i) == .keyword_anytype) { | |
| 2781 | 2738 | it.tok_i += 1; |
| 2782 | 2739 | return Param{ |
| 2783 | 2740 | .first_doc_comment = first_doc_comment, |
| 2784 | 2741 | .comptime_noalias = comptime_noalias, |
| 2785 | 2742 | .name_token = name_token, |
| 2786 | 2743 | .anytype_ellipsis3 = it.tok_i - 1, |
| 2787 | .type_expr = 0, | |
| 2744 | .type_expr = null, | |
| 2788 | 2745 | }; |
| 2789 | 2746 | } |
| 2790 | 2747 | it.tok_flag = false; |
| ... | ... | @@ -2809,7 +2766,7 @@ pub const full = struct { |
| 2809 | 2766 | pub const Components = struct { |
| 2810 | 2767 | lbrace: TokenIndex, |
| 2811 | 2768 | fields: []const Node.Index, |
| 2812 | type_expr: Node.Index, | |
| 2769 | type_expr: Node.OptionalIndex, | |
| 2813 | 2770 | }; |
| 2814 | 2771 | }; |
| 2815 | 2772 | |
| ... | ... | @@ -2819,7 +2776,7 @@ pub const full = struct { |
| 2819 | 2776 | pub const Components = struct { |
| 2820 | 2777 | lbrace: TokenIndex, |
| 2821 | 2778 | elements: []const Node.Index, |
| 2822 | type_expr: Node.Index, | |
| 2779 | type_expr: Node.OptionalIndex, | |
| 2823 | 2780 | }; |
| 2824 | 2781 | }; |
| 2825 | 2782 | |
| ... | ... | @@ -2829,7 +2786,7 @@ pub const full = struct { |
| 2829 | 2786 | pub const Components = struct { |
| 2830 | 2787 | lbracket: TokenIndex, |
| 2831 | 2788 | elem_count: Node.Index, |
| 2832 | sentinel: Node.Index, | |
| 2789 | sentinel: Node.OptionalIndex, | |
| 2833 | 2790 | elem_type: Node.Index, |
| 2834 | 2791 | }; |
| 2835 | 2792 | }; |
| ... | ... | @@ -2843,11 +2800,11 @@ pub const full = struct { |
| 2843 | 2800 | |
| 2844 | 2801 | pub const Components = struct { |
| 2845 | 2802 | main_token: TokenIndex, |
| 2846 | align_node: Node.Index, | |
| 2847 | addrspace_node: Node.Index, | |
| 2848 | sentinel: Node.Index, | |
| 2849 | bit_range_start: Node.Index, | |
| 2850 | bit_range_end: Node.Index, | |
| 2803 | align_node: Node.OptionalIndex, | |
| 2804 | addrspace_node: Node.OptionalIndex, | |
| 2805 | sentinel: Node.OptionalIndex, | |
| 2806 | bit_range_start: Node.OptionalIndex, | |
| 2807 | bit_range_end: Node.OptionalIndex, | |
| 2851 | 2808 | child_type: Node.Index, |
| 2852 | 2809 | }; |
| 2853 | 2810 | }; |
| ... | ... | @@ -2859,8 +2816,8 @@ pub const full = struct { |
| 2859 | 2816 | sliced: Node.Index, |
| 2860 | 2817 | lbracket: TokenIndex, |
| 2861 | 2818 | start: Node.Index, |
| 2862 | end: Node.Index, | |
| 2863 | sentinel: Node.Index, | |
| 2819 | end: Node.OptionalIndex, | |
| 2820 | sentinel: Node.OptionalIndex, | |
| 2864 | 2821 | }; |
| 2865 | 2822 | }; |
| 2866 | 2823 | |
| ... | ... | @@ -2873,7 +2830,7 @@ pub const full = struct { |
| 2873 | 2830 | /// Populated when main_token is Keyword_union. |
| 2874 | 2831 | enum_token: ?TokenIndex, |
| 2875 | 2832 | members: []const Node.Index, |
| 2876 | arg: Node.Index, | |
| 2833 | arg: Node.OptionalIndex, | |
| 2877 | 2834 | }; |
| 2878 | 2835 | }; |
| 2879 | 2836 | |
| ... | ... | @@ -3016,492 +2973,971 @@ pub const Error = struct { |
| 3016 | 2973 | }; |
| 3017 | 2974 | }; |
| 3018 | 2975 | |
| 2976 | /// Index into `extra_data`. | |
| 2977 | pub const ExtraIndex = enum(u32) { | |
| 2978 | _, | |
| 2979 | }; | |
| 2980 | ||
| 3019 | 2981 | pub const Node = struct { |
| 3020 | 2982 | tag: Tag, |
| 3021 | 2983 | main_token: TokenIndex, |
| 3022 | 2984 | data: Data, |
| 3023 | 2985 | |
| 3024 | pub const Index = u32; | |
| 2986 | /// Index into `nodes`. | |
| 2987 | pub const Index = enum(u32) { | |
| 2988 | root = 0, | |
| 2989 | _, | |
| 2990 | ||
| 2991 | pub fn toOptional(i: Index) OptionalIndex { | |
| 2992 | const result: OptionalIndex = @enumFromInt(@intFromEnum(i)); | |
| 2993 | assert(result != .none); | |
| 2994 | return result; | |
| 2995 | } | |
| 2996 | ||
| 2997 | pub fn toOffset(base: Index, destination: Index) Offset { | |
| 2998 | const base_i64: i64 = @intFromEnum(base); | |
| 2999 | const destination_i64: i64 = @intFromEnum(destination); | |
| 3000 | return @enumFromInt(destination_i64 - base_i64); | |
| 3001 | } | |
| 3002 | }; | |
| 3003 | ||
| 3004 | /// Index into `nodes`, or null. | |
| 3005 | pub const OptionalIndex = enum(u32) { | |
| 3006 | root = 0, | |
| 3007 | none = std.math.maxInt(u32), | |
| 3008 | _, | |
| 3009 | ||
| 3010 | pub fn unwrap(oi: OptionalIndex) ?Index { | |
| 3011 | return if (oi == .none) null else @enumFromInt(@intFromEnum(oi)); | |
| 3012 | } | |
| 3013 | ||
| 3014 | pub fn fromOptional(oi: ?Index) OptionalIndex { | |
| 3015 | return if (oi) |i| i.toOptional() else .none; | |
| 3016 | } | |
| 3017 | }; | |
| 3018 | ||
| 3019 | /// A relative node index. | |
| 3020 | pub const Offset = enum(i32) { | |
| 3021 | zero = 0, | |
| 3022 | _, | |
| 3023 | ||
| 3024 | pub fn toOptional(o: Offset) OptionalOffset { | |
| 3025 | const result: OptionalOffset = @enumFromInt(@intFromEnum(o)); | |
| 3026 | assert(result != .none); | |
| 3027 | return result; | |
| 3028 | } | |
| 3029 | ||
| 3030 | pub fn toAbsolute(offset: Offset, base: Index) Index { | |
| 3031 | return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset)); | |
| 3032 | } | |
| 3033 | }; | |
| 3034 | ||
| 3035 | /// A relative node index, or null. | |
| 3036 | pub const OptionalOffset = enum(i32) { | |
| 3037 | none = std.math.maxInt(i32), | |
| 3038 | _, | |
| 3039 | ||
| 3040 | pub fn unwrap(oo: OptionalOffset) ?Offset { | |
| 3041 | return if (oo == .none) null else @enumFromInt(@intFromEnum(oo)); | |
| 3042 | } | |
| 3043 | }; | |
| 3025 | 3044 | |
| 3026 | 3045 | comptime { |
| 3027 | 3046 | // Goal is to keep this under one byte for efficiency. |
| 3028 | 3047 | assert(@sizeOf(Tag) == 1); |
| 3048 | ||
| 3049 | if (!std.debug.runtime_safety) { | |
| 3050 | assert(@sizeOf(Data) == 8); | |
| 3051 | } | |
| 3029 | 3052 | } |
| 3030 | 3053 | |
| 3031 | /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of | |
| 3032 | /// Ast.lastToken() | |
| 3054 | /// The FooComma/FooSemicolon variants exist to ease the implementation of | |
| 3055 | /// `Ast.lastToken()` | |
| 3033 | 3056 | pub const Tag = enum { |
| 3034 | /// sub_list[lhs...rhs] | |
| 3057 | /// The root node which is guaranteed to be at `Node.Index.root`. | |
| 3058 | /// The meaning of the `data` field depends on whether it is a `.zig` or | |
| 3059 | /// `.zon` file. | |
| 3060 | /// | |
| 3061 | /// The `main_token` field is the first token for the source file. | |
| 3035 | 3062 | root, |
| 3036 | /// `usingnamespace lhs;`. rhs unused. main_token is `usingnamespace`. | |
| 3063 | /// `usingnamespace expr;`. | |
| 3064 | /// | |
| 3065 | /// The `data` field is a `.node` to expr. | |
| 3066 | /// | |
| 3067 | /// The `main_token` field is the `usingnamespace` token. | |
| 3037 | 3068 | @"usingnamespace", |
| 3038 | /// lhs is test name token (must be string literal or identifier), if any. | |
| 3039 | /// rhs is the body node. | |
| 3069 | /// `test {}`, | |
| 3070 | /// `test "name" {}`, | |
| 3071 | /// `test identifier {}`. | |
| 3072 | /// | |
| 3073 | /// The `data` field is a `.opt_token_and_node`: | |
| 3074 | /// 1. a `OptionalTokenIndex` to the test name token (must be string literal or identifier), if any. | |
| 3075 | /// 2. a `Node.Index` to the block. | |
| 3076 | /// | |
| 3077 | /// The `main_token` field is the `test` token. | |
| 3040 | 3078 | test_decl, |
| 3041 | /// lhs is the index into extra_data. | |
| 3042 | /// rhs is the initialization expression, if any. | |
| 3043 | /// main_token is `var` or `const`. | |
| 3079 | /// The `data` field is a `.extra_and_opt_node`: | |
| 3080 | /// 1. a `ExtraIndex` to `GlobalVarDecl`. | |
| 3081 | /// 2. a `Node.OptionalIndex` to the initialization expression. | |
| 3082 | /// | |
| 3083 | /// The `main_token` field is the `var` or `const` token. | |
| 3084 | /// | |
| 3085 | /// The initialization expression can't be `.none` unless it is part of | |
| 3086 | /// a `assign_destructure` node or a parsing error occured. | |
| 3044 | 3087 | global_var_decl, |
| 3045 | /// `var a: x align(y) = rhs` | |
| 3046 | /// lhs is the index into extra_data. | |
| 3047 | /// main_token is `var` or `const`. | |
| 3088 | /// `var a: b align(c) = d`. | |
| 3089 | /// `const main_token: type_node align(align_node) = init_expr`. | |
| 3090 | /// | |
| 3091 | /// The `data` field is a `.extra_and_opt_node`: | |
| 3092 | /// 1. a `ExtraIndex` to `LocalVarDecl`. | |
| 3093 | /// 2. a `Node.OptionalIndex` to the initialization expression- | |
| 3094 | /// | |
| 3095 | /// The `main_token` field is the `var` or `const` token. | |
| 3096 | /// | |
| 3097 | /// The initialization expression can't be `.none` unless it is part of | |
| 3098 | /// a `assign_destructure` node or a parsing error occured. | |
| 3048 | 3099 | local_var_decl, |
| 3049 | /// `var a: lhs = rhs`. lhs and rhs may be unused. | |
| 3100 | /// `var a: b = c`. | |
| 3101 | /// `const name_token: type_expr = init_expr`. | |
| 3050 | 3102 | /// Can be local or global. |
| 3051 | /// main_token is `var` or `const`. | |
| 3103 | /// | |
| 3104 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3105 | /// 1. a `Node.OptionalIndex` to the type expression, if any. | |
| 3106 | /// 2. a `Node.OptionalIndex` to the initialization expression. | |
| 3107 | /// | |
| 3108 | /// The `main_token` field is the `var` or `const` token. | |
| 3109 | /// | |
| 3110 | /// The initialization expression can't be `.none` unless it is part of | |
| 3111 | /// a `assign_destructure` node or a parsing error occured. | |
| 3052 | 3112 | simple_var_decl, |
| 3053 | /// `var a align(lhs) = rhs`. lhs and rhs may be unused. | |
| 3113 | /// `var a align(b) = c`. | |
| 3114 | /// `const name_token align(align_expr) = init_expr`. | |
| 3054 | 3115 | /// Can be local or global. |
| 3055 | /// main_token is `var` or `const`. | |
| 3116 | /// | |
| 3117 | /// The `data` field is a `.node_and_opt_node`: | |
| 3118 | /// 1. a `Node.Index` to the alignment expression. | |
| 3119 | /// 2. a `Node.OptionalIndex` to the initialization expression. | |
| 3120 | /// | |
| 3121 | /// The `main_token` field is the `var` or `const` token. | |
| 3122 | /// | |
| 3123 | /// The initialization expression can't be `.none` unless it is part of | |
| 3124 | /// a `assign_destructure` node or a parsing error occured. | |
| 3056 | 3125 | aligned_var_decl, |
| 3057 | /// lhs is the identifier token payload if any, | |
| 3058 | /// rhs is the deferred expression. | |
| 3126 | /// `errdefer expr`, | |
| 3127 | /// `errdefer |payload| expr`. | |
| 3128 | /// | |
| 3129 | /// The `data` field is a `.opt_token_and_node`: | |
| 3130 | /// 1. a `OptionalTokenIndex` to the payload identifier, if any. | |
| 3131 | /// 2. a `Node.Index` to the deferred expression. | |
| 3132 | /// | |
| 3133 | /// The `main_token` field is the `errdefer` token. | |
| 3059 | 3134 | @"errdefer", |
| 3060 | /// lhs is unused. | |
| 3061 | /// rhs is the deferred expression. | |
| 3135 | /// `defer expr`. | |
| 3136 | /// | |
| 3137 | /// The `data` field is a `.node` to the deferred expression. | |
| 3138 | /// | |
| 3139 | /// The `main_token` field is the `defer`. | |
| 3062 | 3140 | @"defer", |
| 3063 | /// lhs catch rhs | |
| 3064 | /// lhs catch |err| rhs | |
| 3065 | /// main_token is the `catch` keyword. | |
| 3066 | /// payload is determined by looking at the next token after the `catch` keyword. | |
| 3141 | /// `lhs catch rhs`, | |
| 3142 | /// `lhs catch |err| rhs`. | |
| 3143 | /// | |
| 3144 | /// The `main_token` field is the `catch` token. | |
| 3145 | /// | |
| 3146 | /// The error payload is determined by looking at the next token after | |
| 3147 | /// the `catch` token. | |
| 3067 | 3148 | @"catch", |
| 3068 | /// `lhs.a`. main_token is the dot. rhs is the identifier token index. | |
| 3149 | /// `lhs.a`. | |
| 3150 | /// | |
| 3151 | /// The `data` field is a `.node_and_token`: | |
| 3152 | /// 1. a `Node.Index` to the left side of the field access. | |
| 3153 | /// 2. a `TokenIndex` to the field name identifier. | |
| 3154 | /// | |
| 3155 | /// The `main_token` field is the `.` token. | |
| 3069 | 3156 | field_access, |
| 3070 | /// `lhs.?`. main_token is the dot. rhs is the `?` token index. | |
| 3157 | /// `lhs.?`. | |
| 3158 | /// | |
| 3159 | /// The `data` field is a `.node_and_token`: | |
| 3160 | /// 1. a `Node.Index` to the left side of the optional unwrap. | |
| 3161 | /// 2. a `TokenIndex` to the `?` token. | |
| 3162 | /// | |
| 3163 | /// The `main_token` field is the `.` token. | |
| 3071 | 3164 | unwrap_optional, |
| 3072 | /// `lhs == rhs`. main_token is op. | |
| 3165 | /// `lhs == rhs`. The `main_token` field is the `==` token. | |
| 3073 | 3166 | equal_equal, |
| 3074 | /// `lhs != rhs`. main_token is op. | |
| 3167 | /// `lhs != rhs`. The `main_token` field is the `!=` token. | |
| 3075 | 3168 | bang_equal, |
| 3076 | /// `lhs < rhs`. main_token is op. | |
| 3169 | /// `lhs < rhs`. The `main_token` field is the `<` token. | |
| 3077 | 3170 | less_than, |
| 3078 | /// `lhs > rhs`. main_token is op. | |
| 3171 | /// `lhs > rhs`. The `main_token` field is the `>` token. | |
| 3079 | 3172 | greater_than, |
| 3080 | /// `lhs <= rhs`. main_token is op. | |
| 3173 | /// `lhs <= rhs`. The `main_token` field is the `<=` token. | |
| 3081 | 3174 | less_or_equal, |
| 3082 | /// `lhs >= rhs`. main_token is op. | |
| 3175 | /// `lhs >= rhs`. The `main_token` field is the `>=` token. | |
| 3083 | 3176 | greater_or_equal, |
| 3084 | /// `lhs *= rhs`. main_token is op. | |
| 3177 | /// `lhs *= rhs`. The `main_token` field is the `*=` token. | |
| 3085 | 3178 | assign_mul, |
| 3086 | /// `lhs /= rhs`. main_token is op. | |
| 3179 | /// `lhs /= rhs`. The `main_token` field is the `/=` token. | |
| 3087 | 3180 | assign_div, |
| 3088 | /// `lhs %= rhs`. main_token is op. | |
| 3181 | /// `lhs %= rhs`. The `main_token` field is the `%=` token. | |
| 3089 | 3182 | assign_mod, |
| 3090 | /// `lhs += rhs`. main_token is op. | |
| 3183 | /// `lhs += rhs`. The `main_token` field is the `+=` token. | |
| 3091 | 3184 | assign_add, |
| 3092 | /// `lhs -= rhs`. main_token is op. | |
| 3185 | /// `lhs -= rhs`. The `main_token` field is the `-=` token. | |
| 3093 | 3186 | assign_sub, |
| 3094 | /// `lhs <<= rhs`. main_token is op. | |
| 3187 | /// `lhs <<= rhs`. The `main_token` field is the `<<=` token. | |
| 3095 | 3188 | assign_shl, |
| 3096 | /// `lhs <<|= rhs`. main_token is op. | |
| 3189 | /// `lhs <<|= rhs`. The `main_token` field is the `<<|=` token. | |
| 3097 | 3190 | assign_shl_sat, |
| 3098 | /// `lhs >>= rhs`. main_token is op. | |
| 3191 | /// `lhs >>= rhs`. The `main_token` field is the `>>=` token. | |
| 3099 | 3192 | assign_shr, |
| 3100 | /// `lhs &= rhs`. main_token is op. | |
| 3193 | /// `lhs &= rhs`. The `main_token` field is the `&=` token. | |
| 3101 | 3194 | assign_bit_and, |
| 3102 | /// `lhs ^= rhs`. main_token is op. | |
| 3195 | /// `lhs ^= rhs`. The `main_token` field is the `^=` token. | |
| 3103 | 3196 | assign_bit_xor, |
| 3104 | /// `lhs |= rhs`. main_token is op. | |
| 3197 | /// `lhs |= rhs`. The `main_token` field is the `|=` token. | |
| 3105 | 3198 | assign_bit_or, |
| 3106 | /// `lhs *%= rhs`. main_token is op. | |
| 3199 | /// `lhs *%= rhs`. The `main_token` field is the `*%=` token. | |
| 3107 | 3200 | assign_mul_wrap, |
| 3108 | /// `lhs +%= rhs`. main_token is op. | |
| 3201 | /// `lhs +%= rhs`. The `main_token` field is the `+%=` token. | |
| 3109 | 3202 | assign_add_wrap, |
| 3110 | /// `lhs -%= rhs`. main_token is op. | |
| 3203 | /// `lhs -%= rhs`. The `main_token` field is the `-%=` token. | |
| 3111 | 3204 | assign_sub_wrap, |
| 3112 | /// `lhs *|= rhs`. main_token is op. | |
| 3205 | /// `lhs *|= rhs`. The `main_token` field is the `*%=` token. | |
| 3113 | 3206 | assign_mul_sat, |
| 3114 | /// `lhs +|= rhs`. main_token is op. | |
| 3207 | /// `lhs +|= rhs`. The `main_token` field is the `+|=` token. | |
| 3115 | 3208 | assign_add_sat, |
| 3116 | /// `lhs -|= rhs`. main_token is op. | |
| 3209 | /// `lhs -|= rhs`. The `main_token` field is the `-|=` token. | |
| 3117 | 3210 | assign_sub_sat, |
| 3118 | /// `lhs = rhs`. main_token is op. | |
| 3211 | /// `lhs = rhs`. The `main_token` field is the `=` token. | |
| 3119 | 3212 | assign, |
| 3120 | /// `a, b, ... = rhs`. main_token is op. lhs is index into `extra_data` | |
| 3121 | /// of an lhs elem count followed by an array of that many `Node.Index`, | |
| 3122 | /// with each node having one of the following types: | |
| 3123 | /// * `global_var_decl` | |
| 3124 | /// * `local_var_decl` | |
| 3125 | /// * `simple_var_decl` | |
| 3126 | /// * `aligned_var_decl` | |
| 3127 | /// * Any expression node | |
| 3128 | /// The first 3 types correspond to a `var` or `const` lhs node (note | |
| 3129 | /// that their `rhs` is always 0). An expression node corresponds to a | |
| 3130 | /// standard assignment LHS (which must be evaluated as an lvalue). | |
| 3131 | /// There may be a preceding `comptime` token, which does not create a | |
| 3132 | /// corresponding `comptime` node so must be manually detected. | |
| 3213 | /// `a, b, ... = rhs`. | |
| 3214 | /// | |
| 3215 | /// The `data` field is a `.extra_and_node`: | |
| 3216 | /// 1. a `ExtraIndex`. Further explained below. | |
| 3217 | /// 2. a `Node.Index` to the initialization expression. | |
| 3218 | /// | |
| 3219 | /// The `main_token` field is the `=` token. | |
| 3220 | /// | |
| 3221 | /// The `ExtraIndex` stores the following data: | |
| 3222 | /// ``` | |
| 3223 | /// elem_count: u32, | |
| 3224 | /// variables: [elem_count]Node.Index, | |
| 3225 | /// ``` | |
| 3226 | /// | |
| 3227 | /// Each node in `variables` has one of the following tags: | |
| 3228 | /// - `global_var_decl` | |
| 3229 | /// - `local_var_decl` | |
| 3230 | /// - `simple_var_decl` | |
| 3231 | /// - `aligned_var_decl` | |
| 3232 | /// - Any expression node | |
| 3233 | /// | |
| 3234 | /// The first 4 tags correspond to a `var` or `const` lhs node (note | |
| 3235 | /// that their initialization expression is always `.none`). | |
| 3236 | /// An expression node corresponds to a standard assignment LHS (which | |
| 3237 | /// must be evaluated as an lvalue). There may be a preceding | |
| 3238 | /// `comptime` token, which does not create a corresponding `comptime` | |
| 3239 | /// node so must be manually detected. | |
| 3133 | 3240 | assign_destructure, |
| 3134 | /// `lhs || rhs`. main_token is the `||`. | |
| 3241 | /// `lhs || rhs`. The `main_token` field is the `||` token. | |
| 3135 | 3242 | merge_error_sets, |
| 3136 | /// `lhs * rhs`. main_token is the `*`. | |
| 3243 | /// `lhs * rhs`. The `main_token` field is the `*` token. | |
| 3137 | 3244 | mul, |
| 3138 | /// `lhs / rhs`. main_token is the `/`. | |
| 3245 | /// `lhs / rhs`. The `main_token` field is the `/` token. | |
| 3139 | 3246 | div, |
| 3140 | /// `lhs % rhs`. main_token is the `%`. | |
| 3247 | /// `lhs % rhs`. The `main_token` field is the `%` token. | |
| 3141 | 3248 | mod, |
| 3142 | /// `lhs ** rhs`. main_token is the `**`. | |
| 3249 | /// `lhs ** rhs`. The `main_token` field is the `**` token. | |
| 3143 | 3250 | array_mult, |
| 3144 | /// `lhs *% rhs`. main_token is the `*%`. | |
| 3251 | /// `lhs *% rhs`. The `main_token` field is the `*%` token. | |
| 3145 | 3252 | mul_wrap, |
| 3146 | /// `lhs *| rhs`. main_token is the `*|`. | |
| 3253 | /// `lhs *| rhs`. The `main_token` field is the `*|` token. | |
| 3147 | 3254 | mul_sat, |
| 3148 | /// `lhs + rhs`. main_token is the `+`. | |
| 3255 | /// `lhs + rhs`. The `main_token` field is the `+` token. | |
| 3149 | 3256 | add, |
| 3150 | /// `lhs - rhs`. main_token is the `-`. | |
| 3257 | /// `lhs - rhs`. The `main_token` field is the `-` token. | |
| 3151 | 3258 | sub, |
| 3152 | /// `lhs ++ rhs`. main_token is the `++`. | |
| 3259 | /// `lhs ++ rhs`. The `main_token` field is the `++` token. | |
| 3153 | 3260 | array_cat, |
| 3154 | /// `lhs +% rhs`. main_token is the `+%`. | |
| 3261 | /// `lhs +% rhs`. The `main_token` field is the `+%` token. | |
| 3155 | 3262 | add_wrap, |
| 3156 | /// `lhs -% rhs`. main_token is the `-%`. | |
| 3263 | /// `lhs -% rhs`. The `main_token` field is the `-%` token. | |
| 3157 | 3264 | sub_wrap, |
| 3158 | /// `lhs +| rhs`. main_token is the `+|`. | |
| 3265 | /// `lhs +| rhs`. The `main_token` field is the `+|` token. | |
| 3159 | 3266 | add_sat, |
| 3160 | /// `lhs -| rhs`. main_token is the `-|`. | |
| 3267 | /// `lhs -| rhs`. The `main_token` field is the `-|` token. | |
| 3161 | 3268 | sub_sat, |
| 3162 | /// `lhs << rhs`. main_token is the `<<`. | |
| 3269 | /// `lhs << rhs`. The `main_token` field is the `<<` token. | |
| 3163 | 3270 | shl, |
| 3164 | /// `lhs <<| rhs`. main_token is the `<<|`. | |
| 3271 | /// `lhs <<| rhs`. The `main_token` field is the `<<|` token. | |
| 3165 | 3272 | shl_sat, |
| 3166 | /// `lhs >> rhs`. main_token is the `>>`. | |
| 3273 | /// `lhs >> rhs`. The `main_token` field is the `>>` token. | |
| 3167 | 3274 | shr, |
| 3168 | /// `lhs & rhs`. main_token is the `&`. | |
| 3275 | /// `lhs & rhs`. The `main_token` field is the `&` token. | |
| 3169 | 3276 | bit_and, |
| 3170 | /// `lhs ^ rhs`. main_token is the `^`. | |
| 3277 | /// `lhs ^ rhs`. The `main_token` field is the `^` token. | |
| 3171 | 3278 | bit_xor, |
| 3172 | /// `lhs | rhs`. main_token is the `|`. | |
| 3279 | /// `lhs | rhs`. The `main_token` field is the `|` token. | |
| 3173 | 3280 | bit_or, |
| 3174 | /// `lhs orelse rhs`. main_token is the `orelse`. | |
| 3281 | /// `lhs orelse rhs`. The `main_token` field is the `orelse` token. | |
| 3175 | 3282 | @"orelse", |
| 3176 | /// `lhs and rhs`. main_token is the `and`. | |
| 3283 | /// `lhs and rhs`. The `main_token` field is the `and` token. | |
| 3177 | 3284 | bool_and, |
| 3178 | /// `lhs or rhs`. main_token is the `or`. | |
| 3285 | /// `lhs or rhs`. The `main_token` field is the `or` token. | |
| 3179 | 3286 | bool_or, |
| 3180 | /// `op lhs`. rhs unused. main_token is op. | |
| 3287 | /// `!expr`. The `main_token` field is the `!` token. | |
| 3181 | 3288 | bool_not, |
| 3182 | /// `op lhs`. rhs unused. main_token is op. | |
| 3289 | /// `-expr`. The `main_token` field is the `-` token. | |
| 3183 | 3290 | negation, |
| 3184 | /// `op lhs`. rhs unused. main_token is op. | |
| 3291 | /// `~expr`. The `main_token` field is the `~` token. | |
| 3185 | 3292 | bit_not, |
| 3186 | /// `op lhs`. rhs unused. main_token is op. | |
| 3293 | /// `-%expr`. The `main_token` field is the `-%` token. | |
| 3187 | 3294 | negation_wrap, |
| 3188 | /// `op lhs`. rhs unused. main_token is op. | |
| 3295 | /// `&expr`. The `main_token` field is the `&` token. | |
| 3189 | 3296 | address_of, |
| 3190 | /// `op lhs`. rhs unused. main_token is op. | |
| 3297 | /// `try expr`. The `main_token` field is the `try` token. | |
| 3191 | 3298 | @"try", |
| 3192 | /// `op lhs`. rhs unused. main_token is op. | |
| 3299 | /// `await expr`. The `main_token` field is the `await` token. | |
| 3193 | 3300 | @"await", |
| 3194 | /// `?lhs`. rhs unused. main_token is the `?`. | |
| 3301 | /// `?expr`. The `main_token` field is the `?` token. | |
| 3195 | 3302 | optional_type, |
| 3196 | /// `[lhs]rhs`. | |
| 3303 | /// `[lhs]rhs`. The `main_token` field is the `[` token. | |
| 3197 | 3304 | array_type, |
| 3198 | /// `[lhs:a]b`. `ArrayTypeSentinel[rhs]`. | |
| 3305 | /// `[lhs:a]b`. | |
| 3306 | /// | |
| 3307 | /// The `data` field is a `.node_and_extra`: | |
| 3308 | /// 1. a `Node.Index` to the length expression. | |
| 3309 | /// 2. a `ExtraIndex` to `ArrayTypeSentinel`. | |
| 3310 | /// | |
| 3311 | /// The `main_token` field is the `[` token. | |
| 3199 | 3312 | array_type_sentinel, |
| 3200 | /// `[*]align(lhs) rhs`. lhs can be omitted. | |
| 3201 | /// `*align(lhs) rhs`. lhs can be omitted. | |
| 3313 | /// `[*]align(lhs) rhs`, | |
| 3314 | /// `*align(lhs) rhs`, | |
| 3202 | 3315 | /// `[]rhs`. |
| 3203 | /// main_token is the asterisk if a single item pointer or the lbracket | |
| 3204 | /// if a slice, many-item pointer, or C-pointer | |
| 3205 | /// main_token might be a ** token, which is shared with a parent/child | |
| 3206 | /// pointer type and may require special handling. | |
| 3316 | /// | |
| 3317 | /// The `data` field is a `.opt_node_and_node`: | |
| 3318 | /// 1. a `Node.OptionalIndex` to the alignment expression, if any. | |
| 3319 | /// 2. a `Node.Index` to the element type expression. | |
| 3320 | /// | |
| 3321 | /// The `main_token` is the asterisk if a single item pointer or the | |
| 3322 | /// lbracket if a slice, many-item pointer, or C-pointer. | |
| 3323 | /// The `main_token` might be a ** token, which is shared with a | |
| 3324 | /// parent/child pointer type and may require special handling. | |
| 3207 | 3325 | ptr_type_aligned, |
| 3208 | /// `[*:lhs]rhs`. lhs can be omitted. | |
| 3209 | /// `*rhs`. | |
| 3326 | /// `[*:lhs]rhs`, | |
| 3327 | /// `*rhs`, | |
| 3210 | 3328 | /// `[:lhs]rhs`. |
| 3211 | /// main_token is the asterisk if a single item pointer or the lbracket | |
| 3212 | /// if a slice, many-item pointer, or C-pointer | |
| 3213 | /// main_token might be a ** token, which is shared with a parent/child | |
| 3214 | /// pointer type and may require special handling. | |
| 3329 | /// | |
| 3330 | /// The `data` field is a `.opt_node_and_node`: | |
| 3331 | /// 1. a `Node.OptionalIndex` to the sentinel expression, if any. | |
| 3332 | /// 2. a `Node.Index` to the element type expression. | |
| 3333 | /// | |
| 3334 | /// The `main_token` is the asterisk if a single item pointer or the | |
| 3335 | /// lbracket if a slice, many-item pointer, or C-pointer. | |
| 3336 | /// The `main_token` might be a ** token, which is shared with a | |
| 3337 | /// parent/child pointer type and may require special handling. | |
| 3215 | 3338 | ptr_type_sentinel, |
| 3216 | /// lhs is index into ptr_type. rhs is the element type expression. | |
| 3217 | /// main_token is the asterisk if a single item pointer or the lbracket | |
| 3218 | /// if a slice, many-item pointer, or C-pointer | |
| 3219 | /// main_token might be a ** token, which is shared with a parent/child | |
| 3220 | /// pointer type and may require special handling. | |
| 3339 | /// The `data` field is a `.opt_node_and_node`: | |
| 3340 | /// 1. a `ExtraIndex` to `PtrType`. | |
| 3341 | /// 2. a `Node.Index` to the element type expression. | |
| 3342 | /// | |
| 3343 | /// The `main_token` is the asterisk if a single item pointer or the | |
| 3344 | /// lbracket if a slice, many-item pointer, or C-pointer. | |
| 3345 | /// The `main_token` might be a ** token, which is shared with a | |
| 3346 | /// parent/child pointer type and may require special handling. | |
| 3221 | 3347 | ptr_type, |
| 3222 | /// lhs is index into ptr_type_bit_range. rhs is the element type expression. | |
| 3223 | /// main_token is the asterisk if a single item pointer or the lbracket | |
| 3224 | /// if a slice, many-item pointer, or C-pointer | |
| 3225 | /// main_token might be a ** token, which is shared with a parent/child | |
| 3226 | /// pointer type and may require special handling. | |
| 3348 | /// The `data` field is a `.opt_node_and_node`: | |
| 3349 | /// 1. a `ExtraIndex` to `PtrTypeBitRange`. | |
| 3350 | /// 2. a `Node.Index` to the element type expression. | |
| 3351 | /// | |
| 3352 | /// The `main_token` is the asterisk if a single item pointer or the | |
| 3353 | /// lbracket if a slice, many-item pointer, or C-pointer. | |
| 3354 | /// The `main_token` might be a ** token, which is shared with a | |
| 3355 | /// parent/child pointer type and may require special handling. | |
| 3227 | 3356 | ptr_type_bit_range, |
| 3228 | 3357 | /// `lhs[rhs..]` |
| 3229 | /// main_token is the lbracket. | |
| 3358 | /// | |
| 3359 | /// The `main_token` field is the `[` token. | |
| 3230 | 3360 | slice_open, |
| 3231 | /// `lhs[b..c]`. rhs is index into Slice | |
| 3232 | /// main_token is the lbracket. | |
| 3361 | /// `sliced[start..end]`. | |
| 3362 | /// | |
| 3363 | /// The `data` field is a `.node_and_extra`: | |
| 3364 | /// 1. a `Node.Index` to the sliced expression. | |
| 3365 | /// 2. a `ExtraIndex` to `Slice`. | |
| 3366 | /// | |
| 3367 | /// The `main_token` field is the `[` token. | |
| 3233 | 3368 | slice, |
| 3234 | /// `lhs[b..c :d]`. rhs is index into SliceSentinel. Slice end "c" can be omitted. | |
| 3235 | /// main_token is the lbracket. | |
| 3369 | /// `sliced[start..end :sentinel]`, | |
| 3370 | /// `sliced[start.. :sentinel]`. | |
| 3371 | /// | |
| 3372 | /// The `data` field is a `.node_and_extra`: | |
| 3373 | /// 1. a `Node.Index` to the sliced expression. | |
| 3374 | /// 2. a `ExtraIndex` to `SliceSentinel`. | |
| 3375 | /// | |
| 3376 | /// The `main_token` field is the `[` token. | |
| 3236 | 3377 | slice_sentinel, |
| 3237 | /// `lhs.*`. rhs is unused. | |
| 3378 | /// `expr.*`. | |
| 3379 | /// | |
| 3380 | /// The `data` field is a `.node` to expr. | |
| 3381 | /// | |
| 3382 | /// The `main_token` field is the `*` token. | |
| 3238 | 3383 | deref, |
| 3239 | 3384 | /// `lhs[rhs]`. |
| 3385 | /// | |
| 3386 | /// The `main_token` field is the `[` token. | |
| 3240 | 3387 | array_access, |
| 3241 | /// `lhs{rhs}`. rhs can be omitted. | |
| 3388 | /// `lhs{rhs}`. | |
| 3389 | /// | |
| 3390 | /// The `main_token` field is the `{` token. | |
| 3242 | 3391 | array_init_one, |
| 3243 | /// `lhs{rhs,}`. rhs can *not* be omitted | |
| 3392 | /// Same as `array_init_one` except there is known to be a trailing | |
| 3393 | /// comma before the final rbrace. | |
| 3244 | 3394 | array_init_one_comma, |
| 3245 | /// `.{lhs, rhs}`. lhs and rhs can be omitted. | |
| 3395 | /// `.{a}`, | |
| 3396 | /// `.{a, b}`. | |
| 3397 | /// | |
| 3398 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3399 | /// 1. a `Node.OptionalIndex` to the first element. Never `.none` | |
| 3400 | /// 2. a `Node.OptionalIndex` to the second element, if any. | |
| 3401 | /// | |
| 3402 | /// The `main_token` field is the `{` token. | |
| 3246 | 3403 | array_init_dot_two, |
| 3247 | /// Same as `array_init_dot_two` except there is known to be a trailing comma | |
| 3248 | /// before the final rbrace. | |
| 3404 | /// Same as `array_init_dot_two` except there is known to be a trailing | |
| 3405 | /// comma before the final rbrace. | |
| 3249 | 3406 | array_init_dot_two_comma, |
| 3250 | /// `.{a, b}`. `sub_list[lhs..rhs]`. | |
| 3407 | /// `.{a, b, c}`. | |
| 3408 | /// | |
| 3409 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3410 | /// each element. | |
| 3411 | /// | |
| 3412 | /// The `main_token` field is the `{` token. | |
| 3251 | 3413 | array_init_dot, |
| 3252 | /// Same as `array_init_dot` except there is known to be a trailing comma | |
| 3253 | /// before the final rbrace. | |
| 3414 | /// Same as `array_init_dot` except there is known to be a trailing | |
| 3415 | /// comma before the final rbrace. | |
| 3254 | 3416 | array_init_dot_comma, |
| 3255 | /// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`. | |
| 3417 | /// `a{b, c}`. | |
| 3418 | /// | |
| 3419 | /// The `data` field is a `.node_and_extra`: | |
| 3420 | /// 1. a `Node.Index` to the type expression. | |
| 3421 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3422 | /// each element. | |
| 3423 | /// | |
| 3424 | /// The `main_token` field is the `{` token. | |
| 3256 | 3425 | array_init, |
| 3257 | 3426 | /// Same as `array_init` except there is known to be a trailing comma |
| 3258 | 3427 | /// before the final rbrace. |
| 3259 | 3428 | array_init_comma, |
| 3260 | /// `lhs{.a = rhs}`. rhs can be omitted making it empty. | |
| 3261 | /// main_token is the lbrace. | |
| 3429 | /// `a{.x = b}`, `a{}`. | |
| 3430 | /// | |
| 3431 | /// The `data` field is a `.node_and_opt_node`: | |
| 3432 | /// 1. a `Node.Index` to the type expression. | |
| 3433 | /// 2. a `Node.OptionalIndex` to the first field initialization, if any. | |
| 3434 | /// | |
| 3435 | /// The `main_token` field is the `{` token. | |
| 3436 | /// | |
| 3437 | /// The field name is determined by looking at the tokens preceding the | |
| 3438 | /// field initialization. | |
| 3262 | 3439 | struct_init_one, |
| 3263 | /// `lhs{.a = rhs,}`. rhs can *not* be omitted. | |
| 3264 | /// main_token is the lbrace. | |
| 3440 | /// Same as `struct_init_one` except there is known to be a trailing comma | |
| 3441 | /// before the final rbrace. | |
| 3265 | 3442 | struct_init_one_comma, |
| 3266 | /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted. | |
| 3267 | /// main_token is the lbrace. | |
| 3268 | /// No trailing comma before the rbrace. | |
| 3443 | /// `.{.x = a, .y = b}`. | |
| 3444 | /// | |
| 3445 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3446 | /// 1. a `Node.OptionalIndex` to the first field initialization. Never `.none` | |
| 3447 | /// 2. a `Node.OptionalIndex` to the second field initialization, if any. | |
| 3448 | /// | |
| 3449 | /// The `main_token` field is the '{' token. | |
| 3450 | /// | |
| 3451 | /// The field name is determined by looking at the tokens preceding the | |
| 3452 | /// field initialization. | |
| 3269 | 3453 | struct_init_dot_two, |
| 3270 | /// Same as `struct_init_dot_two` except there is known to be a trailing comma | |
| 3271 | /// before the final rbrace. | |
| 3454 | /// Same as `struct_init_dot_two` except there is known to be a trailing | |
| 3455 | /// comma before the final rbrace. | |
| 3272 | 3456 | struct_init_dot_two_comma, |
| 3273 | /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`. | |
| 3274 | /// main_token is the lbrace. | |
| 3457 | /// `.{.x = a, .y = b, .z = c}`. | |
| 3458 | /// | |
| 3459 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3460 | /// each field initialization. | |
| 3461 | /// | |
| 3462 | /// The `main_token` field is the `{` token. | |
| 3463 | /// | |
| 3464 | /// The field name is determined by looking at the tokens preceding the | |
| 3465 | /// field initialization. | |
| 3275 | 3466 | struct_init_dot, |
| 3276 | /// Same as `struct_init_dot` except there is known to be a trailing comma | |
| 3277 | /// before the final rbrace. | |
| 3467 | /// Same as `struct_init_dot` except there is known to be a trailing | |
| 3468 | /// comma before the final rbrace. | |
| 3278 | 3469 | struct_init_dot_comma, |
| 3279 | /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`. | |
| 3280 | /// lhs can be omitted which means `.{.a = b, .c = d}`. | |
| 3281 | /// main_token is the lbrace. | |
| 3470 | /// `a{.x = b, .y = c}`. | |
| 3471 | /// | |
| 3472 | /// The `data` field is a `.node_and_extra`: | |
| 3473 | /// 1. a `Node.Index` to the type expression. | |
| 3474 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3475 | /// each field initialization. | |
| 3476 | /// | |
| 3477 | /// The `main_token` field is the `{` token. | |
| 3478 | /// | |
| 3479 | /// The field name is determined by looking at the tokens preceding the | |
| 3480 | /// field initialization. | |
| 3282 | 3481 | struct_init, |
| 3283 | 3482 | /// Same as `struct_init` except there is known to be a trailing comma |
| 3284 | 3483 | /// before the final rbrace. |
| 3285 | 3484 | struct_init_comma, |
| 3286 | /// `lhs(rhs)`. rhs can be omitted. | |
| 3287 | /// main_token is the lparen. | |
| 3485 | /// `a(b)`, `a()`. | |
| 3486 | /// | |
| 3487 | /// The `data` field is a `.node_and_opt_node`: | |
| 3488 | /// 1. a `Node.Index` to the function expression. | |
| 3489 | /// 2. a `Node.OptionalIndex` to the first argument, if any. | |
| 3490 | /// | |
| 3491 | /// The `main_token` field is the `(` token. | |
| 3288 | 3492 | call_one, |
| 3289 | /// `lhs(rhs,)`. rhs can be omitted. | |
| 3290 | /// main_token is the lparen. | |
| 3493 | /// Same as `call_one` except there is known to be a trailing comma | |
| 3494 | /// before the final rparen. | |
| 3291 | 3495 | call_one_comma, |
| 3292 | /// `async lhs(rhs)`. rhs can be omitted. | |
| 3496 | /// `async a(b)`, `async a()`. | |
| 3497 | /// | |
| 3498 | /// The `data` field is a `.node_and_opt_node`: | |
| 3499 | /// 1. a `Node.Index` to the function expression. | |
| 3500 | /// 2. a `Node.OptionalIndex` to the first argument, if any. | |
| 3501 | /// | |
| 3502 | /// The `main_token` field is the `(` token. | |
| 3293 | 3503 | async_call_one, |
| 3294 | /// `async lhs(rhs,)`. | |
| 3504 | /// Same as `async_call_one` except there is known to be a trailing | |
| 3505 | /// comma before the final rparen. | |
| 3295 | 3506 | async_call_one_comma, |
| 3296 | /// `lhs(a, b, c)`. `SubRange[rhs]`. | |
| 3297 | /// main_token is the `(`. | |
| 3507 | /// `a(b, c, d)`. | |
| 3508 | /// | |
| 3509 | /// The `data` field is a `.node_and_extra`: | |
| 3510 | /// 1. a `Node.Index` to the function expression. | |
| 3511 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3512 | /// each argument. | |
| 3513 | /// | |
| 3514 | /// The `main_token` field is the `(` token. | |
| 3298 | 3515 | call, |
| 3299 | /// `lhs(a, b, c,)`. `SubRange[rhs]`. | |
| 3300 | /// main_token is the `(`. | |
| 3516 | /// Same as `call` except there is known to be a trailing comma before | |
| 3517 | /// the final rparen. | |
| 3301 | 3518 | call_comma, |
| 3302 | /// `async lhs(a, b, c)`. `SubRange[rhs]`. | |
| 3303 | /// main_token is the `(`. | |
| 3519 | /// `async a(b, c, d)`. | |
| 3520 | /// | |
| 3521 | /// The `data` field is a `.node_and_extra`: | |
| 3522 | /// 1. a `Node.Index` to the function expression. | |
| 3523 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3524 | /// each argument. | |
| 3525 | /// | |
| 3526 | /// The `main_token` field is the `(` token. | |
| 3304 | 3527 | async_call, |
| 3305 | /// `async lhs(a, b, c,)`. `SubRange[rhs]`. | |
| 3306 | /// main_token is the `(`. | |
| 3528 | /// Same as `async_call` except there is known to be a trailing comma | |
| 3529 | /// before the final rparen. | |
| 3307 | 3530 | async_call_comma, |
| 3308 | /// `switch(lhs) {}`. `SubRange[rhs]`. | |
| 3309 | /// `main_token` is the identifier of a preceding label, if any; otherwise `switch`. | |
| 3531 | /// `switch(a) {}`. | |
| 3532 | /// | |
| 3533 | /// The `data` field is a `.node_and_extra`: | |
| 3534 | /// 1. a `Node.Index` to the switch operand. | |
| 3535 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3536 | /// each switch case. | |
| 3537 | /// | |
| 3538 | /// `The `main_token` field` is the identifier of a preceding label, if any; otherwise `switch`. | |
| 3310 | 3539 | @"switch", |
| 3311 | /// Same as switch except there is known to be a trailing comma | |
| 3312 | /// before the final rbrace | |
| 3540 | /// Same as `switch` except there is known to be a trailing comma before | |
| 3541 | /// the final rbrace. | |
| 3313 | 3542 | switch_comma, |
| 3314 | /// `lhs => rhs`. If lhs is omitted it means `else`. | |
| 3315 | /// main_token is the `=>` | |
| 3543 | /// `a => b`, | |
| 3544 | /// `else => b`. | |
| 3545 | /// | |
| 3546 | /// The `data` field is a `.opt_node_and_node`: | |
| 3547 | /// 1. a `Node.OptionalIndex` where `.none` means `else`. | |
| 3548 | /// 2. a `Node.Index` to the target expression. | |
| 3549 | /// | |
| 3550 | /// The `main_token` field is the `=>` token. | |
| 3316 | 3551 | switch_case_one, |
| 3317 | /// Same ast `switch_case_one` but the case is inline | |
| 3552 | /// Same as `switch_case_one` but the case is inline. | |
| 3318 | 3553 | switch_case_inline_one, |
| 3319 | /// `a, b, c => rhs`. `SubRange[lhs]`. | |
| 3320 | /// main_token is the `=>` | |
| 3554 | /// `a, b, c => d`. | |
| 3555 | /// | |
| 3556 | /// The `data` field is a `.extra_and_node`: | |
| 3557 | /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3558 | /// each switch item. | |
| 3559 | /// 2. a `Node.Index` to the target expression. | |
| 3560 | /// | |
| 3561 | /// The `main_token` field is the `=>` token. | |
| 3321 | 3562 | switch_case, |
| 3322 | /// Same ast `switch_case` but the case is inline | |
| 3563 | /// Same as `switch_case` but the case is inline. | |
| 3323 | 3564 | switch_case_inline, |
| 3324 | 3565 | /// `lhs...rhs`. |
| 3566 | /// | |
| 3567 | /// The `main_token` field is the `...` token. | |
| 3325 | 3568 | switch_range, |
| 3326 | /// `while (lhs) rhs`. | |
| 3327 | /// `while (lhs) |x| rhs`. | |
| 3569 | /// `while (a) b`, | |
| 3570 | /// `while (a) |x| b`. | |
| 3328 | 3571 | while_simple, |
| 3329 | /// `while (lhs) : (a) b`. `WhileCont[rhs]`. | |
| 3330 | /// `while (lhs) : (a) b`. `WhileCont[rhs]`. | |
| 3572 | /// `while (a) : (b) c`, | |
| 3573 | /// `while (a) |x| : (b) c`. | |
| 3331 | 3574 | while_cont, |
| 3332 | /// `while (lhs) : (a) b else c`. `While[rhs]`. | |
| 3333 | /// `while (lhs) |x| : (a) b else c`. `While[rhs]`. | |
| 3334 | /// `while (lhs) |x| : (a) b else |y| c`. `While[rhs]`. | |
| 3335 | /// The cont expression part `: (a)` may be omitted. | |
| 3575 | /// `while (a) : (b) c else d`, | |
| 3576 | /// `while (a) |x| : (b) c else d`, | |
| 3577 | /// `while (a) |x| : (b) c else |y| d`. | |
| 3578 | /// The continue expression part `: (b)` may be omitted. | |
| 3336 | 3579 | @"while", |
| 3337 | /// `for (lhs) rhs`. | |
| 3580 | /// `for (a) b`. | |
| 3338 | 3581 | for_simple, |
| 3339 | 3582 | /// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`. |
| 3340 | 3583 | @"for", |
| 3341 | /// `lhs..rhs`. rhs can be omitted. | |
| 3584 | /// `lhs..rhs`, `lhs..`. | |
| 3342 | 3585 | for_range, |
| 3343 | /// `if (lhs) rhs`. | |
| 3344 | /// `if (lhs) |a| rhs`. | |
| 3586 | /// `if (a) b`. | |
| 3587 | /// `if (b) |x| b`. | |
| 3345 | 3588 | if_simple, |
| 3346 | /// `if (lhs) a else b`. `If[rhs]`. | |
| 3347 | /// `if (lhs) |x| a else b`. `If[rhs]`. | |
| 3348 | /// `if (lhs) |x| a else |y| b`. `If[rhs]`. | |
| 3589 | /// `if (a) b else c`. | |
| 3590 | /// `if (a) |x| b else c`. | |
| 3591 | /// `if (a) |x| b else |y| d`. | |
| 3349 | 3592 | @"if", |
| 3350 | /// `suspend lhs`. lhs can be omitted. rhs is unused. | |
| 3593 | /// `suspend expr`. | |
| 3594 | /// | |
| 3595 | /// The `data` field is a `.node` to expr. | |
| 3596 | /// | |
| 3597 | /// The `main_token` field is the `suspend` token. | |
| 3351 | 3598 | @"suspend", |
| 3352 | /// `resume lhs`. rhs is unused. | |
| 3599 | /// `resume expr`. | |
| 3600 | /// | |
| 3601 | /// The `data` field is a `.node` to expr. | |
| 3602 | /// | |
| 3603 | /// The `main_token` field is the `resume` token. | |
| 3353 | 3604 | @"resume", |
| 3354 | /// `continue :lhs rhs` | |
| 3355 | /// both lhs and rhs may be omitted. | |
| 3605 | /// `continue :label expr`, | |
| 3606 | /// `continue expr`, | |
| 3607 | /// `continue :label`, | |
| 3608 | /// `continue`. | |
| 3609 | /// | |
| 3610 | /// The `data` field is a `.opt_token_and_opt_node`: | |
| 3611 | /// 1. a `OptionalTokenIndex` to the label identifier, if any. | |
| 3612 | /// 2. a `Node.OptionalIndex` to the target expression, if any. | |
| 3613 | /// | |
| 3614 | /// The `main_token` field is the `continue` token. | |
| 3356 | 3615 | @"continue", |
| 3357 | /// `break :lhs rhs` | |
| 3358 | /// both lhs and rhs may be omitted. | |
| 3616 | /// `break :label expr`, | |
| 3617 | /// `break expr`, | |
| 3618 | /// `break :label`, | |
| 3619 | /// `break`. | |
| 3620 | /// | |
| 3621 | /// The `data` field is a `.opt_token_and_opt_node`: | |
| 3622 | /// 1. a `OptionalTokenIndex` to the label identifier, if any. | |
| 3623 | /// 2. a `Node.OptionalIndex` to the target expression, if any. | |
| 3624 | /// | |
| 3625 | /// The `main_token` field is the `break` token. | |
| 3359 | 3626 | @"break", |
| 3360 | /// `return lhs`. lhs can be omitted. rhs is unused. | |
| 3627 | /// `return expr`, `return`. | |
| 3628 | /// | |
| 3629 | /// The `data` field is a `.opt_node` to the return value, if any. | |
| 3630 | /// | |
| 3631 | /// The `main_token` field is the `return` token. | |
| 3361 | 3632 | @"return", |
| 3362 | /// `fn (a: lhs) rhs`. lhs can be omitted. | |
| 3363 | /// anytype and ... parameters are omitted from the AST tree. | |
| 3364 | /// main_token is the `fn` keyword. | |
| 3365 | /// extern function declarations use this tag. | |
| 3633 | /// `fn (a: type_expr) return_type`. | |
| 3634 | /// | |
| 3635 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3636 | /// 1. a `Node.OptionalIndex` to the first parameter type expression, if any. | |
| 3637 | /// 2. a `Node.OptionalIndex` to the return type expression. Can't be | |
| 3638 | /// `.none` unless a parsing error occured. | |
| 3639 | /// | |
| 3640 | /// The `main_token` field is the `fn` token. | |
| 3641 | /// | |
| 3642 | /// `anytype` and `...` parameters are omitted from the AST tree. | |
| 3643 | /// Extern function declarations use this tag. | |
| 3366 | 3644 | fn_proto_simple, |
| 3367 | /// `fn (a: b, c: d) rhs`. `sub_range_list[lhs]`. | |
| 3368 | /// anytype and ... parameters are omitted from the AST tree. | |
| 3369 | /// main_token is the `fn` keyword. | |
| 3370 | /// extern function declarations use this tag. | |
| 3645 | /// `fn (a: b, c: d) return_type`. | |
| 3646 | /// | |
| 3647 | /// The `data` field is a `.extra_and_opt_node`: | |
| 3648 | /// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3649 | /// each parameter type expression. | |
| 3650 | /// 2. a `Node.OptionalIndex` to the return type expression. Can't be | |
| 3651 | /// `.none` unless a parsing error occured. | |
| 3652 | /// | |
| 3653 | /// The `main_token` field is the `fn` token. | |
| 3654 | /// | |
| 3655 | /// `anytype` and `...` parameters are omitted from the AST tree. | |
| 3656 | /// Extern function declarations use this tag. | |
| 3371 | 3657 | fn_proto_multi, |
| 3372 | /// `fn (a: b) addrspace(e) linksection(f) callconv(g) rhs`. `FnProtoOne[lhs]`. | |
| 3658 | /// `fn (a: b) addrspace(e) linksection(f) callconv(g) return_type`. | |
| 3373 | 3659 | /// zero or one parameters. |
| 3374 | /// anytype and ... parameters are omitted from the AST tree. | |
| 3375 | /// main_token is the `fn` keyword. | |
| 3376 | /// extern function declarations use this tag. | |
| 3660 | /// | |
| 3661 | /// The `data` field is a `.extra_and_opt_node`: | |
| 3662 | /// 1. a `Node.ExtraIndex` to `FnProtoOne`. | |
| 3663 | /// 2. a `Node.OptionalIndex` to the return type expression. Can't be | |
| 3664 | /// `.none` unless a parsing error occured. | |
| 3665 | /// | |
| 3666 | /// The `main_token` field is the `fn` token. | |
| 3667 | /// | |
| 3668 | /// `anytype` and `...` parameters are omitted from the AST tree. | |
| 3669 | /// Extern function declarations use this tag. | |
| 3377 | 3670 | fn_proto_one, |
| 3378 | /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) rhs`. `FnProto[lhs]`. | |
| 3379 | /// anytype and ... parameters are omitted from the AST tree. | |
| 3380 | /// main_token is the `fn` keyword. | |
| 3381 | /// extern function declarations use this tag. | |
| 3671 | /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) return_type`. | |
| 3672 | /// | |
| 3673 | /// The `data` field is a `.extra_and_opt_node`: | |
| 3674 | /// 1. a `Node.ExtraIndex` to `FnProto`. | |
| 3675 | /// 2. a `Node.OptionalIndex` to the return type expression. Can't be | |
| 3676 | /// `.none` unless a parsing error occured. | |
| 3677 | /// | |
| 3678 | /// The `main_token` field is the `fn` token. | |
| 3679 | /// | |
| 3680 | /// `anytype` and `...` parameters are omitted from the AST tree. | |
| 3681 | /// Extern function declarations use this tag. | |
| 3382 | 3682 | fn_proto, |
| 3383 | /// lhs is the fn_proto. | |
| 3384 | /// rhs is the function body block. | |
| 3385 | /// Note that extern function declarations use the fn_proto tags rather | |
| 3386 | /// than this one. | |
| 3683 | /// Extern function declarations use the fn_proto tags rather than this one. | |
| 3684 | /// | |
| 3685 | /// The `data` field is a `.node_and_node`: | |
| 3686 | /// 1. a `Node.Index` to `fn_proto_*`. | |
| 3687 | /// 2. a `Node.Index` to function body block. | |
| 3688 | /// | |
| 3689 | /// The `main_token` field is the `fn` token. | |
| 3387 | 3690 | fn_decl, |
| 3388 | /// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index. | |
| 3691 | /// `anyframe->return_type`. | |
| 3692 | /// | |
| 3693 | /// The `data` field is a `.token_and_node`: | |
| 3694 | /// 1. a `TokenIndex` to the `->` token. | |
| 3695 | /// 2. a `Node.Index` to the function frame return type expression. | |
| 3696 | /// | |
| 3697 | /// The `main_token` field is the `anyframe` token. | |
| 3389 | 3698 | anyframe_type, |
| 3390 | /// Both lhs and rhs unused. | |
| 3699 | /// The `data` field is unused. | |
| 3391 | 3700 | anyframe_literal, |
| 3392 | /// Both lhs and rhs unused. | |
| 3701 | /// The `data` field is unused. | |
| 3393 | 3702 | char_literal, |
| 3394 | /// Both lhs and rhs unused. | |
| 3703 | /// The `data` field is unused. | |
| 3395 | 3704 | number_literal, |
| 3396 | /// Both lhs and rhs unused. | |
| 3705 | /// The `data` field is unused. | |
| 3397 | 3706 | unreachable_literal, |
| 3398 | /// Both lhs and rhs unused. | |
| 3399 | /// Most identifiers will not have explicit AST nodes, however for expressions | |
| 3400 | /// which could be one of many different kinds of AST nodes, there will be an | |
| 3401 | /// identifier AST node for it. | |
| 3707 | /// The `data` field is unused. | |
| 3708 | /// | |
| 3709 | /// Most identifiers will not have explicit AST nodes, however for | |
| 3710 | /// expressions which could be one of many different kinds of AST nodes, | |
| 3711 | /// there will be an identifier AST node for it. | |
| 3402 | 3712 | identifier, |
| 3403 | /// lhs is the dot token index, rhs unused, main_token is the identifier. | |
| 3713 | /// `.foo`. | |
| 3714 | /// | |
| 3715 | /// The `data` field is unused. | |
| 3716 | /// | |
| 3717 | /// The `main_token` field is the identifier. | |
| 3404 | 3718 | enum_literal, |
| 3405 | /// main_token is the string literal token | |
| 3406 | /// Both lhs and rhs unused. | |
| 3719 | /// The `data` field is unused. | |
| 3720 | /// | |
| 3721 | /// The `main_token` field is the string literal token. | |
| 3407 | 3722 | string_literal, |
| 3408 | /// main_token is the first token index (redundant with lhs) | |
| 3409 | /// lhs is the first token index; rhs is the last token index. | |
| 3410 | /// Could be a series of multiline_string_literal_line tokens, or a single | |
| 3411 | /// string_literal token. | |
| 3723 | /// The `data` field is a `.token_and_token`: | |
| 3724 | /// 1. a `TokenIndex` to the first `.multiline_string_literal_line` token. | |
| 3725 | /// 2. a `TokenIndex` to the last `.multiline_string_literal_line` token. | |
| 3726 | /// | |
| 3727 | /// The `main_token` field is the first token index (redundant with `data`). | |
| 3412 | 3728 | multiline_string_literal, |
| 3413 | /// `(lhs)`. main_token is the `(`; rhs is the token index of the `)`. | |
| 3729 | /// `(expr)`. | |
| 3730 | /// | |
| 3731 | /// The `data` field is a `.node_and_token`: | |
| 3732 | /// 1. a `Node.Index` to the sub-expression | |
| 3733 | /// 2. a `TokenIndex` to the `)` token. | |
| 3734 | /// | |
| 3735 | /// The `main_token` field is the `(` token. | |
| 3414 | 3736 | grouped_expression, |
| 3415 | /// `@a(lhs, rhs)`. lhs and rhs may be omitted. | |
| 3416 | /// main_token is the builtin token. | |
| 3737 | /// `@a(b, c)`. | |
| 3738 | /// | |
| 3739 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3740 | /// 1. a `Node.OptionalIndex` to the first argument, if any. | |
| 3741 | /// 2. a `Node.OptionalIndex` to the second argument, if any. | |
| 3742 | /// | |
| 3743 | /// The `main_token` field is the builtin token. | |
| 3417 | 3744 | builtin_call_two, |
| 3418 | /// Same as builtin_call_two but there is known to be a trailing comma before the rparen. | |
| 3745 | /// Same as `builtin_call_two` except there is known to be a trailing comma | |
| 3746 | /// before the final rparen. | |
| 3419 | 3747 | builtin_call_two_comma, |
| 3420 | /// `@a(b, c)`. `sub_list[lhs..rhs]`. | |
| 3421 | /// main_token is the builtin token. | |
| 3748 | /// `@a(b, c, d)`. | |
| 3749 | /// | |
| 3750 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3751 | /// each argument. | |
| 3752 | /// | |
| 3753 | /// The `main_token` field is the builtin token. | |
| 3422 | 3754 | builtin_call, |
| 3423 | /// Same as builtin_call but there is known to be a trailing comma before the rparen. | |
| 3755 | /// Same as `builtin_call` except there is known to be a trailing comma | |
| 3756 | /// before the final rparen. | |
| 3424 | 3757 | builtin_call_comma, |
| 3425 | 3758 | /// `error{a, b}`. |
| 3426 | /// rhs is the rbrace, lhs is unused. | |
| 3759 | /// | |
| 3760 | /// The `data` field is a `.token_and_token`: | |
| 3761 | /// 1. a `TokenIndex` to the `{` token. | |
| 3762 | /// 2. a `TokenIndex` to the `}` token. | |
| 3763 | /// | |
| 3764 | /// The `main_token` field is the `error`. | |
| 3427 | 3765 | error_set_decl, |
| 3428 | /// `struct {}`, `union {}`, `opaque {}`, `enum {}`. `extra_data[lhs..rhs]`. | |
| 3429 | /// main_token is `struct`, `union`, `opaque`, `enum` keyword. | |
| 3766 | /// `struct {}`, `union {}`, `opaque {}`, `enum {}`. | |
| 3767 | /// | |
| 3768 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3769 | /// each container member. | |
| 3770 | /// | |
| 3771 | /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token. | |
| 3430 | 3772 | container_decl, |
| 3431 | /// Same as ContainerDecl but there is known to be a trailing comma | |
| 3432 | /// or semicolon before the rbrace. | |
| 3773 | /// Same as `container_decl` except there is known to be a trailing | |
| 3774 | /// comma before the final rbrace. | |
| 3433 | 3775 | container_decl_trailing, |
| 3434 | 3776 | /// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`. |
| 3435 | /// lhs or rhs can be omitted. | |
| 3436 | /// main_token is `struct`, `union`, `opaque`, `enum` keyword. | |
| 3777 | /// | |
| 3778 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3779 | /// 1. a `Node.OptionalIndex` to the first container member, if any. | |
| 3780 | /// 2. a `Node.OptionalIndex` to the second container member, if any. | |
| 3781 | /// | |
| 3782 | /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token. | |
| 3437 | 3783 | container_decl_two, |
| 3438 | /// Same as ContainerDeclTwo except there is known to be a trailing comma | |
| 3439 | /// or semicolon before the rbrace. | |
| 3784 | /// Same as `container_decl_two` except there is known to be a trailing | |
| 3785 | /// comma before the final rbrace. | |
| 3440 | 3786 | container_decl_two_trailing, |
| 3441 | /// `struct(lhs)` / `union(lhs)` / `enum(lhs)`. `SubRange[rhs]`. | |
| 3787 | /// `struct(arg)`, `union(arg)`, `enum(arg)`. | |
| 3788 | /// | |
| 3789 | /// The `data` field is a `.node_and_extra`: | |
| 3790 | /// 1. a `Node.Index` to arg. | |
| 3791 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3792 | /// each container member. | |
| 3793 | /// | |
| 3794 | /// The `main_token` field is the `struct`, `union` or `enum` token. | |
| 3442 | 3795 | container_decl_arg, |
| 3443 | /// Same as container_decl_arg but there is known to be a trailing | |
| 3444 | /// comma or semicolon before the rbrace. | |
| 3796 | /// Same as `container_decl_arg` except there is known to be a trailing | |
| 3797 | /// comma before the final rbrace. | |
| 3445 | 3798 | container_decl_arg_trailing, |
| 3446 | /// `union(enum) {}`. `sub_list[lhs..rhs]`. | |
| 3447 | /// Note that tagged unions with explicitly provided enums are represented | |
| 3448 | /// by `container_decl_arg`. | |
| 3799 | /// `union(enum) {}`. | |
| 3800 | /// | |
| 3801 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3802 | /// each container member. | |
| 3803 | /// | |
| 3804 | /// The `main_token` field is the `union` token. | |
| 3805 | /// | |
| 3806 | /// A tagged union with explicitly provided enums will instead be | |
| 3807 | /// represented by `container_decl_arg`. | |
| 3449 | 3808 | tagged_union, |
| 3450 | /// Same as tagged_union but there is known to be a trailing comma | |
| 3451 | /// or semicolon before the rbrace. | |
| 3809 | /// Same as `tagged_union` except there is known to be a trailing comma | |
| 3810 | /// before the final rbrace. | |
| 3452 | 3811 | tagged_union_trailing, |
| 3453 | /// `union(enum) {lhs, rhs}`. lhs or rhs may be omitted. | |
| 3454 | /// Note that tagged unions with explicitly provided enums are represented | |
| 3455 | /// by `container_decl_arg`. | |
| 3812 | /// `union(enum) {lhs, rhs}`. | |
| 3813 | /// | |
| 3814 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3815 | /// 1. a `Node.OptionalIndex` to the first container member, if any. | |
| 3816 | /// 2. a `Node.OptionalIndex` to the second container member, if any. | |
| 3817 | /// | |
| 3818 | /// The `main_token` field is the `union` token. | |
| 3819 | /// | |
| 3820 | /// A tagged union with explicitly provided enums will instead be | |
| 3821 | /// represented by `container_decl_arg`. | |
| 3456 | 3822 | tagged_union_two, |
| 3457 | /// Same as tagged_union_two but there is known to be a trailing comma | |
| 3458 | /// or semicolon before the rbrace. | |
| 3823 | /// Same as `tagged_union_two` except there is known to be a trailing | |
| 3824 | /// comma before the final rbrace. | |
| 3459 | 3825 | tagged_union_two_trailing, |
| 3460 | /// `union(enum(lhs)) {}`. `SubRange[rhs]`. | |
| 3826 | /// `union(enum(arg)) {}`. | |
| 3827 | /// | |
| 3828 | /// The `data` field is a `.node_and_extra`: | |
| 3829 | /// 1. a `Node.Index` to arg. | |
| 3830 | /// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for | |
| 3831 | /// each container member. | |
| 3832 | /// | |
| 3833 | /// The `main_token` field is the `union` token. | |
| 3461 | 3834 | tagged_union_enum_tag, |
| 3462 | /// Same as tagged_union_enum_tag but there is known to be a trailing comma | |
| 3463 | /// or semicolon before the rbrace. | |
| 3835 | /// Same as `tagged_union_enum_tag` except there is known to be a | |
| 3836 | /// trailing comma before the final rbrace. | |
| 3464 | 3837 | tagged_union_enum_tag_trailing, |
| 3465 | /// `a: lhs = rhs,`. lhs and rhs can be omitted. | |
| 3466 | /// main_token is the field name identifier. | |
| 3467 | /// lastToken() does not include the possible trailing comma. | |
| 3838 | /// `a: lhs = rhs,`, | |
| 3839 | /// `a: lhs,`. | |
| 3840 | /// | |
| 3841 | /// The `data` field is a `.node_and_opt_node`: | |
| 3842 | /// 1. a `Node.Index` to the field type expression. | |
| 3843 | /// 2. a `Node.OptionalIndex` to the default value expression, if any. | |
| 3844 | /// | |
| 3845 | /// The `main_token` field is the field name identifier. | |
| 3846 | /// | |
| 3847 | /// `lastToken()` does not include the possible trailing comma. | |
| 3468 | 3848 | container_field_init, |
| 3469 | /// `a: lhs align(rhs),`. rhs can be omitted. | |
| 3470 | /// main_token is the field name identifier. | |
| 3471 | /// lastToken() does not include the possible trailing comma. | |
| 3849 | /// `a: lhs align(rhs),`. | |
| 3850 | /// | |
| 3851 | /// The `data` field is a `.node_and_node`: | |
| 3852 | /// 1. a `Node.Index` to the field type expression. | |
| 3853 | /// 2. a `Node.Index` to the alignment expression. | |
| 3854 | /// | |
| 3855 | /// The `main_token` field is the field name identifier. | |
| 3856 | /// | |
| 3857 | /// `lastToken()` does not include the possible trailing comma. | |
| 3472 | 3858 | container_field_align, |
| 3473 | /// `a: lhs align(c) = d,`. `container_field_list[rhs]`. | |
| 3474 | /// main_token is the field name identifier. | |
| 3475 | /// lastToken() does not include the possible trailing comma. | |
| 3859 | /// `a: lhs align(c) = d,`. | |
| 3860 | /// | |
| 3861 | /// The `data` field is a `.node_and_extra`: | |
| 3862 | /// 1. a `Node.Index` to the field type expression. | |
| 3863 | /// 2. a `ExtraIndex` to `ContainerField`. | |
| 3864 | /// | |
| 3865 | /// The `main_token` field is the field name identifier. | |
| 3866 | /// | |
| 3867 | /// `lastToken()` does not include the possible trailing comma. | |
| 3476 | 3868 | container_field, |
| 3477 | /// `comptime lhs`. rhs unused. | |
| 3869 | /// `comptime expr`. | |
| 3870 | /// | |
| 3871 | /// The `data` field is a `.node` to expr. | |
| 3872 | /// | |
| 3873 | /// The `main_token` field is the `comptime` token. | |
| 3478 | 3874 | @"comptime", |
| 3479 | /// `nosuspend lhs`. rhs unused. | |
| 3875 | /// `nosuspend expr`. | |
| 3876 | /// | |
| 3877 | /// The `data` field is a `.node` to expr. | |
| 3878 | /// | |
| 3879 | /// The `main_token` field is the `nosuspend` token. | |
| 3480 | 3880 | @"nosuspend", |
| 3481 | /// `{lhs rhs}`. rhs or lhs can be omitted. | |
| 3482 | /// main_token points at the lbrace. | |
| 3881 | /// `{lhs rhs}`. | |
| 3882 | /// | |
| 3883 | /// The `data` field is a `.opt_node_and_opt_node`: | |
| 3884 | /// 1. a `Node.OptionalIndex` to the first statement, if any. | |
| 3885 | /// 2. a `Node.OptionalIndex` to the second statement, if any. | |
| 3886 | /// | |
| 3887 | /// The `main_token` field is the `{` token. | |
| 3483 | 3888 | block_two, |
| 3484 | /// Same as block_two but there is known to be a semicolon before the rbrace. | |
| 3889 | /// Same as `block_two_semicolon` except there is known to be a trailing | |
| 3890 | /// comma before the final rbrace. | |
| 3485 | 3891 | block_two_semicolon, |
| 3486 | /// `{}`. `sub_list[lhs..rhs]`. | |
| 3487 | /// main_token points at the lbrace. | |
| 3892 | /// `{a b}`. | |
| 3893 | /// | |
| 3894 | /// The `data` field is a `.extra_range` that stores a `Node.Index` for | |
| 3895 | /// each statement. | |
| 3896 | /// | |
| 3897 | /// The `main_token` field is the `{` token. | |
| 3488 | 3898 | block, |
| 3489 | /// Same as block but there is known to be a semicolon before the rbrace. | |
| 3899 | /// Same as `block` except there is known to be a trailing comma before | |
| 3900 | /// the final rbrace. | |
| 3490 | 3901 | block_semicolon, |
| 3491 | /// `asm(lhs)`. rhs is the token index of the rparen. | |
| 3902 | /// `asm(lhs)`. | |
| 3903 | /// | |
| 3904 | /// rhs is a `Token.Index` to the `)` token. | |
| 3905 | /// The `main_token` field is the `asm` token. | |
| 3492 | 3906 | asm_simple, |
| 3493 | /// `asm(lhs, a)`. `Asm[rhs]`. | |
| 3907 | /// `asm(lhs, a)`. | |
| 3908 | /// | |
| 3909 | /// The `data` field is a `.node_and_extra`: | |
| 3910 | /// 1. a `Node.Index` to lhs. | |
| 3911 | /// 2. a `ExtraIndex` to `Asm`. | |
| 3912 | /// | |
| 3913 | /// The `main_token` field is the `asm` token. | |
| 3494 | 3914 | @"asm", |
| 3495 | /// `[a] "b" (c)`. lhs is 0, rhs is token index of the rparen. | |
| 3496 | /// `[a] "b" (-> lhs)`. rhs is token index of the rparen. | |
| 3497 | /// main_token is `a`. | |
| 3915 | /// `[a] "b" (c)`. | |
| 3916 | /// `[a] "b" (-> lhs)`. | |
| 3917 | /// | |
| 3918 | /// The `data` field is a `.opt_node_and_token`: | |
| 3919 | /// 1. a `Node.OptionalIndex` to lhs, if any. | |
| 3920 | /// 2. a `TokenIndex` to the `)` token. | |
| 3921 | /// | |
| 3922 | /// The `main_token` field is `a`. | |
| 3498 | 3923 | asm_output, |
| 3499 | /// `[a] "b" (lhs)`. rhs is token index of the rparen. | |
| 3500 | /// main_token is `a`. | |
| 3924 | /// `[a] "b" (lhs)`. | |
| 3925 | /// | |
| 3926 | /// The `data` field is a `.node_and_token`: | |
| 3927 | /// 1. a `Node.Index` to lhs. | |
| 3928 | /// 2. a `TokenIndex` to the `)` token. | |
| 3929 | /// | |
| 3930 | /// The `main_token` field is `a`. | |
| 3501 | 3931 | asm_input, |
| 3502 | /// `error.a`. lhs is token index of `.`. rhs is token index of `a`. | |
| 3932 | /// `error.a`. | |
| 3933 | /// | |
| 3934 | /// The `data` field is unused. | |
| 3935 | /// | |
| 3936 | /// The `main_token` field is `error` token. | |
| 3503 | 3937 | error_value, |
| 3504 | /// `lhs!rhs`. main_token is the `!`. | |
| 3938 | /// `lhs!rhs`. | |
| 3939 | /// | |
| 3940 | /// The `main_token` field is the `!` token. | |
| 3505 | 3941 | error_union, |
| 3506 | 3942 | |
| 3507 | 3943 | pub fn isContainerField(tag: Tag) bool { |
| ... | ... | @@ -3516,9 +3952,26 @@ pub const Node = struct { |
| 3516 | 3952 | } |
| 3517 | 3953 | }; |
| 3518 | 3954 | |
| 3519 | pub const Data = struct { | |
| 3520 | lhs: Index, | |
| 3521 | rhs: Index, | |
| 3955 | pub const Data = union { | |
| 3956 | node: Index, | |
| 3957 | opt_node: OptionalIndex, | |
| 3958 | token: TokenIndex, | |
| 3959 | node_and_node: struct { Index, Index }, | |
| 3960 | opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex }, | |
| 3961 | node_and_opt_node: struct { Index, OptionalIndex }, | |
| 3962 | opt_node_and_node: struct { OptionalIndex, Index }, | |
| 3963 | node_and_extra: struct { Index, ExtraIndex }, | |
| 3964 | extra_and_node: struct { ExtraIndex, Index }, | |
| 3965 | extra_and_opt_node: struct { ExtraIndex, OptionalIndex }, | |
| 3966 | node_and_token: struct { Index, TokenIndex }, | |
| 3967 | token_and_node: struct { TokenIndex, Index }, | |
| 3968 | token_and_token: struct { TokenIndex, TokenIndex }, | |
| 3969 | opt_node_and_token: struct { OptionalIndex, TokenIndex }, | |
| 3970 | opt_token_and_node: struct { OptionalTokenIndex, Index }, | |
| 3971 | opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex }, | |
| 3972 | opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex }, | |
| 3973 | @"for": struct { ExtraIndex, For }, | |
| 3974 | extra_range: SubRange, | |
| 3522 | 3975 | }; |
| 3523 | 3976 | |
| 3524 | 3977 | pub const LocalVarDecl = struct { |
| ... | ... | @@ -3532,24 +3985,24 @@ pub const Node = struct { |
| 3532 | 3985 | }; |
| 3533 | 3986 | |
| 3534 | 3987 | pub const PtrType = struct { |
| 3535 | sentinel: Index, | |
| 3536 | align_node: Index, | |
| 3537 | addrspace_node: Index, | |
| 3988 | sentinel: OptionalIndex, | |
| 3989 | align_node: OptionalIndex, | |
| 3990 | addrspace_node: OptionalIndex, | |
| 3538 | 3991 | }; |
| 3539 | 3992 | |
| 3540 | 3993 | pub const PtrTypeBitRange = struct { |
| 3541 | sentinel: Index, | |
| 3994 | sentinel: OptionalIndex, | |
| 3542 | 3995 | align_node: Index, |
| 3543 | addrspace_node: Index, | |
| 3996 | addrspace_node: OptionalIndex, | |
| 3544 | 3997 | bit_range_start: Index, |
| 3545 | 3998 | bit_range_end: Index, |
| 3546 | 3999 | }; |
| 3547 | 4000 | |
| 3548 | 4001 | pub const SubRange = struct { |
| 3549 | /// Index into sub_list. | |
| 3550 | start: Index, | |
| 3551 | /// Index into sub_list. | |
| 3552 | end: Index, | |
| 4002 | /// Index into extra_data. | |
| 4003 | start: ExtraIndex, | |
| 4004 | /// Index into extra_data. | |
| 4005 | end: ExtraIndex, | |
| 3553 | 4006 | }; |
| 3554 | 4007 | |
| 3555 | 4008 | pub const If = struct { |
| ... | ... | @@ -3564,13 +4017,13 @@ pub const Node = struct { |
| 3564 | 4017 | |
| 3565 | 4018 | pub const GlobalVarDecl = struct { |
| 3566 | 4019 | /// Populated if there is an explicit type ascription. |
| 3567 | type_node: Index, | |
| 4020 | type_node: OptionalIndex, | |
| 3568 | 4021 | /// Populated if align(A) is present. |
| 3569 | align_node: Index, | |
| 4022 | align_node: OptionalIndex, | |
| 3570 | 4023 | /// Populated if addrspace(A) is present. |
| 3571 | addrspace_node: Index, | |
| 4024 | addrspace_node: OptionalIndex, | |
| 3572 | 4025 | /// Populated if linksection(A) is present. |
| 3573 | section_node: Index, | |
| 4026 | section_node: OptionalIndex, | |
| 3574 | 4027 | }; |
| 3575 | 4028 | |
| 3576 | 4029 | pub const Slice = struct { |
| ... | ... | @@ -3580,13 +4033,13 @@ pub const Node = struct { |
| 3580 | 4033 | |
| 3581 | 4034 | pub const SliceSentinel = struct { |
| 3582 | 4035 | start: Index, |
| 3583 | /// May be 0 if the slice is "open" | |
| 3584 | end: Index, | |
| 4036 | /// May be .none if the slice is "open" | |
| 4037 | end: OptionalIndex, | |
| 3585 | 4038 | sentinel: Index, |
| 3586 | 4039 | }; |
| 3587 | 4040 | |
| 3588 | 4041 | pub const While = struct { |
| 3589 | cont_expr: Index, | |
| 4042 | cont_expr: OptionalIndex, | |
| 3590 | 4043 | then_expr: Index, |
| 3591 | 4044 | else_expr: Index, |
| 3592 | 4045 | }; |
| ... | ... | @@ -3603,44 +4056,44 @@ pub const Node = struct { |
| 3603 | 4056 | |
| 3604 | 4057 | pub const FnProtoOne = struct { |
| 3605 | 4058 | /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters. |
| 3606 | param: Index, | |
| 4059 | param: OptionalIndex, | |
| 3607 | 4060 | /// Populated if align(A) is present. |
| 3608 | align_expr: Index, | |
| 4061 | align_expr: OptionalIndex, | |
| 3609 | 4062 | /// Populated if addrspace(A) is present. |
| 3610 | addrspace_expr: Index, | |
| 4063 | addrspace_expr: OptionalIndex, | |
| 3611 | 4064 | /// Populated if linksection(A) is present. |
| 3612 | section_expr: Index, | |
| 4065 | section_expr: OptionalIndex, | |
| 3613 | 4066 | /// Populated if callconv(A) is present. |
| 3614 | callconv_expr: Index, | |
| 4067 | callconv_expr: OptionalIndex, | |
| 3615 | 4068 | }; |
| 3616 | 4069 | |
| 3617 | 4070 | pub const FnProto = struct { |
| 3618 | params_start: Index, | |
| 3619 | params_end: Index, | |
| 4071 | params_start: ExtraIndex, | |
| 4072 | params_end: ExtraIndex, | |
| 3620 | 4073 | /// Populated if align(A) is present. |
| 3621 | align_expr: Index, | |
| 4074 | align_expr: OptionalIndex, | |
| 3622 | 4075 | /// Populated if addrspace(A) is present. |
| 3623 | addrspace_expr: Index, | |
| 4076 | addrspace_expr: OptionalIndex, | |
| 3624 | 4077 | /// Populated if linksection(A) is present. |
| 3625 | section_expr: Index, | |
| 4078 | section_expr: OptionalIndex, | |
| 3626 | 4079 | /// Populated if callconv(A) is present. |
| 3627 | callconv_expr: Index, | |
| 4080 | callconv_expr: OptionalIndex, | |
| 3628 | 4081 | }; |
| 3629 | 4082 | |
| 3630 | 4083 | pub const Asm = struct { |
| 3631 | items_start: Index, | |
| 3632 | items_end: Index, | |
| 4084 | items_start: ExtraIndex, | |
| 4085 | items_end: ExtraIndex, | |
| 3633 | 4086 | /// Needed to make lastToken() work. |
| 3634 | 4087 | rparen: TokenIndex, |
| 3635 | 4088 | }; |
| 3636 | 4089 | }; |
| 3637 | 4090 | |
| 3638 | pub fn nodeToSpan(tree: *const Ast, node: u32) Span { | |
| 4091 | pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span { | |
| 3639 | 4092 | return tokensToSpan( |
| 3640 | 4093 | tree, |
| 3641 | 4094 | tree.firstToken(node), |
| 3642 | 4095 | tree.lastToken(node), |
| 3643 | tree.nodes.items(.main_token)[node], | |
| 4096 | tree.nodeMainToken(node), | |
| 3644 | 4097 | ); |
| 3645 | 4098 | } |
| 3646 | 4099 | |
| ... | ... | @@ -3649,7 +4102,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { |
| 3649 | 4102 | } |
| 3650 | 4103 | |
| 3651 | 4104 | pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { |
| 3652 | const token_starts = tree.tokens.items(.start); | |
| 3653 | 4105 | var start_tok = start; |
| 3654 | 4106 | var end_tok = end; |
| 3655 | 4107 | |
| ... | ... | @@ -3663,9 +4115,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex |
| 3663 | 4115 | start_tok = main; |
| 3664 | 4116 | end_tok = main; |
| 3665 | 4117 | } |
| 3666 | const start_off = token_starts[start_tok]; | |
| 3667 | const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | |
| 3668 | return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; | |
| 4118 | const start_off = tree.tokenStart(start_tok); | |
| 4119 | const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | |
| 4120 | return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) }; | |
| 3669 | 4121 | } |
| 3670 | 4122 | |
| 3671 | 4123 | const std = @import("../std.zig"); |
lib/std/zig/AstGen.zig+650-835| ... | ... | @@ -99,8 +99,18 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 99 | 99 | Zir.Inst.Declaration.Name, |
| 100 | 100 | std.zig.SimpleComptimeReason, |
| 101 | 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 | 106 | => @intFromEnum(@field(extra, field.name)), |
| 103 | 107 | |
| 108 | Ast.TokenOffset, | |
| 109 | Ast.OptionalTokenOffset, | |
| 110 | Ast.Node.Offset, | |
| 111 | Ast.Node.OptionalOffset, | |
| 112 | => @bitCast(@intFromEnum(@field(extra, field.name))), | |
| 113 | ||
| 104 | 114 | i32, |
| 105 | 115 | Zir.Inst.Call.Flags, |
| 106 | 116 | Zir.Inst.BuiltinCall.Flags, |
| ... | ... | @@ -168,7 +178,7 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 168 | 178 | .is_comptime = true, |
| 169 | 179 | .parent = &top_scope.base, |
| 170 | 180 | .anon_name_strategy = .parent, |
| 171 | .decl_node_index = 0, | |
| 181 | .decl_node_index = .root, | |
| 172 | 182 | .decl_line = 0, |
| 173 | 183 | .astgen = &astgen, |
| 174 | 184 | .instructions = &gz_instructions, |
| ... | ... | @@ -182,10 +192,10 @@ pub fn generate(gpa: Allocator, tree: Ast) Allocator.Error!Zir { |
| 182 | 192 | if (AstGen.structDeclInner( |
| 183 | 193 | &gen_scope, |
| 184 | 194 | &gen_scope.base, |
| 185 | 0, | |
| 195 | .root, | |
| 186 | 196 | tree.containerDeclRoot(), |
| 187 | 197 | .auto, |
| 188 | 0, | |
| 198 | .none, | |
| 189 | 199 | )) |struct_decl_ref| { |
| 190 | 200 | assert(struct_decl_ref.toIndex().? == .main_struct_inst); |
| 191 | 201 | break :fatal false; |
| ... | ... | @@ -430,9 +440,7 @@ fn reachableExprComptime( |
| 430 | 440 | fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 431 | 441 | const astgen = gz.astgen; |
| 432 | 442 | const tree = astgen.tree; |
| 433 | const node_tags = tree.nodes.items(.tag); | |
| 434 | const main_tokens = tree.nodes.items(.main_token); | |
| 435 | switch (node_tags[node]) { | |
| 443 | switch (tree.nodeTag(node)) { | |
| 436 | 444 | .root => unreachable, |
| 437 | 445 | .@"usingnamespace" => unreachable, |
| 438 | 446 | .test_decl => unreachable, |
| ... | ... | @@ -600,7 +608,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins |
| 600 | 608 | .builtin_call_two, |
| 601 | 609 | .builtin_call_two_comma, |
| 602 | 610 | => { |
| 603 | const builtin_token = main_tokens[node]; | |
| 611 | const builtin_token = tree.nodeMainToken(node); | |
| 604 | 612 | const builtin_name = tree.tokenSlice(builtin_token); |
| 605 | 613 | // If the builtin is an invalid name, we don't cause an error here; instead |
| 606 | 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 | 639 | fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 632 | 640 | const astgen = gz.astgen; |
| 633 | 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); | |
| 638 | 642 | |
| 639 | 643 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 640 | 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 | 646 | gz.anon_name_strategy = .anon; |
| 643 | 647 | } |
| 644 | 648 | |
| 645 | switch (node_tags[node]) { | |
| 649 | switch (tree.nodeTag(node)) { | |
| 646 | 650 | .root => unreachable, // Top-level declaration. |
| 647 | 651 | .@"usingnamespace" => unreachable, // Top-level declaration. |
| 648 | 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 | 756 | }, |
| 753 | 757 | |
| 754 | 758 | // zig fmt: off |
| 755 | .shl => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shl), | |
| 756 | .shr => return shiftOp(gz, scope, ri, node, node_datas[node].lhs, node_datas[node].rhs, .shr), | |
| 759 | .shl => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shl), | |
| 760 | .shr => return shiftOp(gz, scope, ri, node, tree.nodeData(node).node_and_node[0], tree.nodeData(node).node_and_node[1], .shr), | |
| 757 | 761 | |
| 758 | 762 | .add => return simpleBinOp(gz, scope, ri, node, .add), |
| 759 | 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 | 787 | // This syntax form does not currently use the result type in the language specification. |
| 784 | 788 | // However, the result type can be used to emit more optimal code for large multiplications by |
| 785 | 789 | // having Sema perform a coercion before the multiplication operation. |
| 790 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 786 | 791 | const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{ |
| 787 | 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), | |
| 789 | .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs, .array_mul_factor), | |
| 793 | .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node), | |
| 794 | .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node, .array_mul_factor), | |
| 790 | 795 | }); |
| 791 | 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 | 802 | .merge_error_sets => .merge_error_sets, |
| 798 | 803 | else => unreachable, |
| 799 | 804 | }; |
| 800 | const lhs = try reachableTypeExpr(gz, scope, node_datas[node].lhs, node); | |
| 801 | const rhs = try reachableTypeExpr(gz, scope, node_datas[node].rhs, node); | |
| 805 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 806 | const lhs = try reachableTypeExpr(gz, scope, lhs_node, node); | |
| 807 | const rhs = try reachableTypeExpr(gz, scope, rhs_node, node); | |
| 802 | 808 | const result = try gz.addPlNode(inst_tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); |
| 803 | 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 | 812 | .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and), |
| 807 | 813 | .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or), |
| 808 | 814 | |
| 809 | .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, node_datas[node].lhs, .bool_not), | |
| 810 | .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not), | |
| 815 | .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, tree.nodeData(node).node, .bool_not), | |
| 816 | .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, tree.nodeData(node).node, .bit_not), | |
| 811 | 817 | |
| 812 | 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), | |
| 814 | 820 | |
| 815 | 821 | .identifier => return identifier(gz, scope, ri, node, null), |
| 816 | 822 | |
| ... | ... | @@ -824,20 +830,13 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 824 | 830 | .number_literal => return numberLiteral(gz, ri, node, node, .positive), |
| 825 | 831 | // zig fmt: on |
| 826 | 832 | |
| 827 | .builtin_call_two, .builtin_call_two_comma => { | |
| 828 | if (node_datas[node].lhs == 0) { | |
| 829 | const params = [_]Ast.Node.Index{}; | |
| 830 | return builtinCall(gz, scope, ri, node, &params, false); | |
| 831 | } else if (node_datas[node].rhs == 0) { | |
| 832 | const params = [_]Ast.Node.Index{node_datas[node].lhs}; | |
| 833 | return builtinCall(gz, scope, ri, node, &params, false); | |
| 834 | } else { | |
| 835 | const params = [_]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 836 | return builtinCall(gz, scope, ri, node, &params, false); | |
| 837 | } | |
| 838 | }, | |
| 839 | .builtin_call, .builtin_call_comma => { | |
| 840 | const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 833 | .builtin_call_two, | |
| 834 | .builtin_call_two_comma, | |
| 835 | .builtin_call, | |
| 836 | .builtin_call_comma, | |
| 837 | => { | |
| 838 | var buf: [2]Ast.Node.Index = undefined; | |
| 839 | const params = tree.builtinCallParams(&buf, node).?; | |
| 841 | 840 | return builtinCall(gz, scope, ri, node, params, false); |
| 842 | 841 | }, |
| 843 | 842 | |
| ... | ... | @@ -873,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 873 | 872 | const if_full = tree.fullIf(node).?; |
| 874 | 873 | no_switch_on_err: { |
| 875 | 874 | const error_token = if_full.error_token orelse break :no_switch_on_err; |
| 876 | const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err; | |
| 875 | const else_node = if_full.ast.else_expr.unwrap() orelse break :no_switch_on_err; | |
| 876 | const full_switch = tree.fullSwitch(else_node) orelse break :no_switch_on_err; | |
| 877 | 877 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 878 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; | |
| 879 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; | |
| 878 | if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err; | |
| 879 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err; | |
| 880 | 880 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"if"); |
| 881 | 881 | } |
| 882 | 882 | return ifExpr(gz, scope, ri.br(), node, if_full); |
| ... | ... | @@ -894,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 894 | 894 | .slice_sentinel, |
| 895 | 895 | => { |
| 896 | 896 | const full = tree.fullSlice(node).?; |
| 897 | if (full.ast.end != 0 and | |
| 898 | node_tags[full.ast.sliced] == .slice_open and | |
| 897 | if (full.ast.end != .none and | |
| 898 | tree.nodeTag(full.ast.sliced) == .slice_open and | |
| 899 | 899 | nodeIsTriviallyZero(tree, full.ast.start)) |
| 900 | 900 | { |
| 901 | 901 | const lhs_extra = tree.sliceOpen(full.ast.sliced).ast; |
| ... | ... | @@ -903,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 903 | 903 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced); |
| 904 | 904 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start); |
| 905 | 905 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 906 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end); | |
| 907 | const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none; | |
| 906 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end.unwrap().?); | |
| 907 | const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| try expr(gz, scope, .{ .rl = .none }, sentinel) else .none; | |
| 908 | 908 | try emitDbgStmt(gz, cursor); |
| 909 | 909 | const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{ |
| 910 | 910 | .lhs = lhs, |
| ... | ... | @@ -919,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 919 | 919 | |
| 920 | 920 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 921 | 921 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start); |
| 922 | const end = if (full.ast.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end) else .none; | |
| 923 | const sentinel = if (full.ast.sentinel != 0) s: { | |
| 922 | const end = if (full.ast.end.unwrap()) |end| try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, end) else .none; | |
| 923 | const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| s: { | |
| 924 | 924 | const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node); |
| 925 | break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, full.ast.sentinel); | |
| 925 | break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, sentinel); | |
| 926 | 926 | } else .none; |
| 927 | 927 | try emitDbgStmt(gz, cursor); |
| 928 | 928 | if (sentinel != .none) { |
| ... | ... | @@ -950,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 950 | 950 | }, |
| 951 | 951 | |
| 952 | 952 | .deref => { |
| 953 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 953 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node); | |
| 954 | 954 | _ = try gz.addUnNode(.validate_deref, lhs, node); |
| 955 | 955 | switch (ri.rl) { |
| 956 | 956 | .ref, .ref_coerced_ty => return lhs, |
| ... | ... | @@ -965,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 965 | 965 | _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node)); |
| 966 | 966 | break :rl .{ .ref_coerced_ty = res_ty_inst }; |
| 967 | 967 | } else .ref; |
| 968 | const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs); | |
| 968 | const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node); | |
| 969 | 969 | return rvalue(gz, ri, result, node); |
| 970 | 970 | }, |
| 971 | 971 | .optional_type => { |
| 972 | const operand = try typeExpr(gz, scope, node_datas[node].lhs); | |
| 972 | const operand = try typeExpr(gz, scope, tree.nodeData(node).node); | |
| 973 | 973 | const result = try gz.addUnNode(.optional_type, operand, node); |
| 974 | 974 | return rvalue(gz, ri, result, node); |
| 975 | 975 | }, |
| 976 | 976 | .unwrap_optional => switch (ri.rl) { |
| 977 | 977 | .ref, .ref_coerced_ty => { |
| 978 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | |
| 978 | const lhs = try expr(gz, scope, .{ .rl = .ref }, tree.nodeData(node).node_and_token[0]); | |
| 979 | 979 | |
| 980 | 980 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 981 | 981 | try emitDbgStmt(gz, cursor); |
| ... | ... | @@ -983,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 983 | 983 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); |
| 984 | 984 | }, |
| 985 | 985 | else => { |
| 986 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 986 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]); | |
| 987 | 987 | |
| 988 | 988 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 989 | 989 | try emitDbgStmt(gz, cursor); |
| ... | ... | @@ -991,22 +991,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 991 | 991 | return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node); |
| 992 | 992 | }, |
| 993 | 993 | }, |
| 994 | .block_two, .block_two_semicolon => { | |
| 995 | const statements = [2]Ast.Node.Index{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 996 | if (node_datas[node].lhs == 0) { | |
| 997 | return blockExpr(gz, scope, ri, node, statements[0..0], .normal); | |
| 998 | } else if (node_datas[node].rhs == 0) { | |
| 999 | return blockExpr(gz, scope, ri, node, statements[0..1], .normal); | |
| 1000 | } else { | |
| 1001 | return blockExpr(gz, scope, ri, node, statements[0..2], .normal); | |
| 1002 | } | |
| 1003 | }, | |
| 1004 | .block, .block_semicolon => { | |
| 1005 | const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 994 | .block_two, | |
| 995 | .block_two_semicolon, | |
| 996 | .block, | |
| 997 | .block_semicolon, | |
| 998 | => { | |
| 999 | var buf: [2]Ast.Node.Index = undefined; | |
| 1000 | const statements = tree.blockStatements(&buf, node).?; | |
| 1006 | 1001 | return blockExpr(gz, scope, ri, node, statements, .normal); |
| 1007 | 1002 | }, |
| 1008 | 1003 | .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| { |
| 1009 | const str_index = try astgen.identAsString(main_tokens[node]); | |
| 1004 | const str_index = try astgen.identAsString(tree.nodeMainToken(node)); | |
| 1010 | 1005 | const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{ |
| 1011 | 1006 | .lhs = res_ty, |
| 1012 | 1007 | .field_name_start = str_index, |
| ... | ... | @@ -1016,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1016 | 1011 | .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us |
| 1017 | 1012 | .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node), |
| 1018 | 1013 | } |
| 1019 | } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal), | |
| 1020 | .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value), | |
| 1014 | } else return simpleStrTok(gz, ri, tree.nodeMainToken(node), node, .enum_literal), | |
| 1015 | .error_value => return simpleStrTok(gz, ri, tree.nodeMainToken(node) + 2, node, .error_value), | |
| 1021 | 1016 | // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025 |
| 1022 | 1017 | // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node), |
| 1023 | 1018 | .anyframe_literal => { |
| ... | ... | @@ -1025,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1025 | 1020 | return rvalue(gz, ri, result, node); |
| 1026 | 1021 | }, |
| 1027 | 1022 | .anyframe_type => { |
| 1028 | const return_type = try typeExpr(gz, scope, node_datas[node].rhs); | |
| 1023 | const return_type = try typeExpr(gz, scope, tree.nodeData(node).token_and_node[1]); | |
| 1029 | 1024 | const result = try gz.addUnNode(.anyframe_type, return_type, node); |
| 1030 | 1025 | return rvalue(gz, ri, result, node); |
| 1031 | 1026 | }, |
| 1032 | 1027 | .@"catch" => { |
| 1033 | const catch_token = main_tokens[node]; | |
| 1034 | const payload_token: ?Ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe) | |
| 1028 | const catch_token = tree.nodeMainToken(node); | |
| 1029 | const payload_token: ?Ast.TokenIndex = if (tree.tokenTag(catch_token + 1) == .pipe) | |
| 1035 | 1030 | catch_token + 2 |
| 1036 | 1031 | else |
| 1037 | 1032 | null; |
| 1038 | 1033 | no_switch_on_err: { |
| 1039 | 1034 | const capture_token = payload_token orelse break :no_switch_on_err; |
| 1040 | const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err; | |
| 1035 | const full_switch = tree.fullSwitch(tree.nodeData(node).node_and_node[1]) orelse break :no_switch_on_err; | |
| 1041 | 1036 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 1042 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; | |
| 1043 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; | |
| 1037 | if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err; | |
| 1038 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err; | |
| 1044 | 1039 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch"); |
| 1045 | 1040 | } |
| 1046 | 1041 | switch (ri.rl) { |
| ... | ... | @@ -1049,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1049 | 1044 | scope, |
| 1050 | 1045 | ri, |
| 1051 | 1046 | node, |
| 1052 | node_datas[node].lhs, | |
| 1053 | 1047 | .is_non_err_ptr, |
| 1054 | 1048 | .err_union_payload_unsafe_ptr, |
| 1055 | 1049 | .err_union_code_ptr, |
| 1056 | node_datas[node].rhs, | |
| 1057 | 1050 | payload_token, |
| 1058 | 1051 | ), |
| 1059 | 1052 | else => return orelseCatchExpr( |
| ... | ... | @@ -1061,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1061 | 1054 | scope, |
| 1062 | 1055 | ri, |
| 1063 | 1056 | node, |
| 1064 | node_datas[node].lhs, | |
| 1065 | 1057 | .is_non_err, |
| 1066 | 1058 | .err_union_payload_unsafe, |
| 1067 | 1059 | .err_union_code, |
| 1068 | node_datas[node].rhs, | |
| 1069 | 1060 | payload_token, |
| 1070 | 1061 | ), |
| 1071 | 1062 | } |
| ... | ... | @@ -1076,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1076 | 1067 | scope, |
| 1077 | 1068 | ri, |
| 1078 | 1069 | node, |
| 1079 | node_datas[node].lhs, | |
| 1080 | 1070 | .is_non_null_ptr, |
| 1081 | 1071 | .optional_payload_unsafe_ptr, |
| 1082 | 1072 | undefined, |
| 1083 | node_datas[node].rhs, | |
| 1084 | 1073 | null, |
| 1085 | 1074 | ), |
| 1086 | 1075 | else => return orelseCatchExpr( |
| ... | ... | @@ -1088,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1088 | 1077 | scope, |
| 1089 | 1078 | ri, |
| 1090 | 1079 | node, |
| 1091 | node_datas[node].lhs, | |
| 1092 | 1080 | .is_non_null, |
| 1093 | 1081 | .optional_payload_unsafe, |
| 1094 | 1082 | undefined, |
| 1095 | node_datas[node].rhs, | |
| 1096 | 1083 | null, |
| 1097 | 1084 | ), |
| 1098 | 1085 | }, |
| ... | ... | @@ -1122,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1122 | 1109 | |
| 1123 | 1110 | .@"break" => return breakExpr(gz, scope, node), |
| 1124 | 1111 | .@"continue" => return continueExpr(gz, scope, node), |
| 1125 | .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs), | |
| 1112 | .grouped_expression => return expr(gz, scope, ri, tree.nodeData(node).node_and_token[0]), | |
| 1126 | 1113 | .array_type => return arrayType(gz, scope, ri, node), |
| 1127 | 1114 | .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node), |
| 1128 | 1115 | .char_literal => return charLiteral(gz, ri, node), |
| ... | ... | @@ -1136,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1136 | 1123 | .@"await" => return awaitExpr(gz, scope, ri, node), |
| 1137 | 1124 | .@"resume" => return resumeExpr(gz, scope, ri, node), |
| 1138 | 1125 | |
| 1139 | .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs), | |
| 1126 | .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node), | |
| 1140 | 1127 | |
| 1141 | 1128 | .array_init_one, |
| 1142 | 1129 | .array_init_one_comma, |
| ... | ... | @@ -1183,16 +1170,14 @@ fn nosuspendExpr( |
| 1183 | 1170 | ) InnerError!Zir.Inst.Ref { |
| 1184 | 1171 | const astgen = gz.astgen; |
| 1185 | 1172 | const tree = astgen.tree; |
| 1186 | const node_datas = tree.nodes.items(.data); | |
| 1187 | const body_node = node_datas[node].lhs; | |
| 1188 | assert(body_node != 0); | |
| 1189 | if (gz.nosuspend_node != 0) { | |
| 1173 | const body_node = tree.nodeData(node).node; | |
| 1174 | if (gz.nosuspend_node.unwrap()) |nosuspend_node| { | |
| 1190 | 1175 | try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{ |
| 1191 | try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}), | |
| 1176 | try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}), | |
| 1192 | 1177 | }); |
| 1193 | 1178 | } |
| 1194 | gz.nosuspend_node = node; | |
| 1195 | defer gz.nosuspend_node = 0; | |
| 1179 | gz.nosuspend_node = node.toOptional(); | |
| 1180 | defer gz.nosuspend_node = .none; | |
| 1196 | 1181 | return expr(gz, scope, ri, body_node); |
| 1197 | 1182 | } |
| 1198 | 1183 | |
| ... | ... | @@ -1204,26 +1189,24 @@ fn suspendExpr( |
| 1204 | 1189 | const astgen = gz.astgen; |
| 1205 | 1190 | const gpa = astgen.gpa; |
| 1206 | 1191 | const tree = astgen.tree; |
| 1207 | const node_datas = tree.nodes.items(.data); | |
| 1208 | const body_node = node_datas[node].lhs; | |
| 1192 | const body_node = tree.nodeData(node).node; | |
| 1209 | 1193 | |
| 1210 | if (gz.nosuspend_node != 0) { | |
| 1194 | if (gz.nosuspend_node.unwrap()) |nosuspend_node| { | |
| 1211 | 1195 | return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{ |
| 1212 | try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}), | |
| 1196 | try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}), | |
| 1213 | 1197 | }); |
| 1214 | 1198 | } |
| 1215 | if (gz.suspend_node != 0) { | |
| 1199 | if (gz.suspend_node.unwrap()) |suspend_node| { | |
| 1216 | 1200 | return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{ |
| 1217 | try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}), | |
| 1201 | try astgen.errNoteNode(suspend_node, "other suspend block here", .{}), | |
| 1218 | 1202 | }); |
| 1219 | 1203 | } |
| 1220 | assert(body_node != 0); | |
| 1221 | 1204 | |
| 1222 | 1205 | const suspend_inst = try gz.makeBlockInst(.suspend_block, node); |
| 1223 | 1206 | try gz.instructions.append(gpa, suspend_inst); |
| 1224 | 1207 | |
| 1225 | 1208 | var suspend_scope = gz.makeSubBlock(scope); |
| 1226 | suspend_scope.suspend_node = node; | |
| 1209 | suspend_scope.suspend_node = node.toOptional(); | |
| 1227 | 1210 | defer suspend_scope.unstack(); |
| 1228 | 1211 | |
| 1229 | 1212 | const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal); |
| ... | ... | @@ -1243,16 +1226,15 @@ fn awaitExpr( |
| 1243 | 1226 | ) InnerError!Zir.Inst.Ref { |
| 1244 | 1227 | const astgen = gz.astgen; |
| 1245 | 1228 | const tree = astgen.tree; |
| 1246 | const node_datas = tree.nodes.items(.data); | |
| 1247 | const rhs_node = node_datas[node].lhs; | |
| 1229 | const rhs_node = tree.nodeData(node).node; | |
| 1248 | 1230 | |
| 1249 | if (gz.suspend_node != 0) { | |
| 1231 | if (gz.suspend_node.unwrap()) |suspend_node| { | |
| 1250 | 1232 | return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{ |
| 1251 | try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}), | |
| 1233 | try astgen.errNoteNode(suspend_node, "suspend block here", .{}), | |
| 1252 | 1234 | }); |
| 1253 | 1235 | } |
| 1254 | 1236 | const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node); |
| 1255 | const result = if (gz.nosuspend_node != 0) | |
| 1237 | const result = if (gz.nosuspend_node != .none) | |
| 1256 | 1238 | try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{ |
| 1257 | 1239 | .node = gz.nodeIndexToRelative(node), |
| 1258 | 1240 | .operand = operand, |
| ... | ... | @@ -1271,8 +1253,7 @@ fn resumeExpr( |
| 1271 | 1253 | ) InnerError!Zir.Inst.Ref { |
| 1272 | 1254 | const astgen = gz.astgen; |
| 1273 | 1255 | const tree = astgen.tree; |
| 1274 | const node_datas = tree.nodes.items(.data); | |
| 1275 | const rhs_node = node_datas[node].lhs; | |
| 1256 | const rhs_node = tree.nodeData(node).node; | |
| 1276 | 1257 | const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node); |
| 1277 | 1258 | const result = try gz.addUnNode(.@"resume", operand, node); |
| 1278 | 1259 | return rvalue(gz, ri, result, node); |
| ... | ... | @@ -1287,33 +1268,33 @@ fn fnProtoExpr( |
| 1287 | 1268 | ) InnerError!Zir.Inst.Ref { |
| 1288 | 1269 | const astgen = gz.astgen; |
| 1289 | 1270 | const tree = astgen.tree; |
| 1290 | const token_tags = tree.tokens.items(.tag); | |
| 1291 | 1271 | |
| 1292 | 1272 | if (fn_proto.name_token) |some| { |
| 1293 | 1273 | return astgen.failTok(some, "function type cannot have a name", .{}); |
| 1294 | 1274 | } |
| 1295 | 1275 | |
| 1296 | if (fn_proto.ast.align_expr != 0) { | |
| 1297 | return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{}); | |
| 1276 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1277 | return astgen.failNode(align_expr, "function type cannot have an alignment", .{}); | |
| 1298 | 1278 | } |
| 1299 | 1279 | |
| 1300 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1301 | return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{}); | |
| 1280 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1281 | return astgen.failNode(addrspace_expr, "function type cannot have an addrspace", .{}); | |
| 1302 | 1282 | } |
| 1303 | 1283 | |
| 1304 | if (fn_proto.ast.section_expr != 0) { | |
| 1305 | return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{}); | |
| 1284 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1285 | return astgen.failNode(section_expr, "function type cannot have a linksection", .{}); | |
| 1306 | 1286 | } |
| 1307 | 1287 | |
| 1308 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 1309 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 1288 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 1289 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 1290 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 1310 | 1291 | if (is_inferred_error) { |
| 1311 | 1292 | return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{}); |
| 1312 | 1293 | } |
| 1313 | 1294 | |
| 1314 | 1295 | const is_extern = blk: { |
| 1315 | 1296 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 1316 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 1297 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 1317 | 1298 | }; |
| 1318 | 1299 | assert(!is_extern); |
| 1319 | 1300 | |
| ... | ... | @@ -1330,7 +1311,6 @@ fn fnProtoExprInner( |
| 1330 | 1311 | ) InnerError!Zir.Inst.Ref { |
| 1331 | 1312 | const astgen = gz.astgen; |
| 1332 | 1313 | const tree = astgen.tree; |
| 1333 | const token_tags = tree.tokens.items(.tag); | |
| 1334 | 1314 | |
| 1335 | 1315 | var block_scope = gz.makeSubBlock(scope); |
| 1336 | 1316 | defer block_scope.unstack(); |
| ... | ... | @@ -1342,7 +1322,7 @@ fn fnProtoExprInner( |
| 1342 | 1322 | var param_type_i: usize = 0; |
| 1343 | 1323 | var it = fn_proto.iterate(tree); |
| 1344 | 1324 | while (it.next()) |param| : (param_type_i += 1) { |
| 1345 | const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) { | |
| 1325 | const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) { | |
| 1346 | 1326 | .keyword_noalias => is_comptime: { |
| 1347 | 1327 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse |
| 1348 | 1328 | return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); |
| ... | ... | @@ -1353,7 +1333,7 @@ fn fnProtoExprInner( |
| 1353 | 1333 | } else false; |
| 1354 | 1334 | |
| 1355 | 1335 | const is_anytype = if (param.anytype_ellipsis3) |token| blk: { |
| 1356 | switch (token_tags[token]) { | |
| 1336 | switch (tree.tokenTag(token)) { | |
| 1357 | 1337 | .keyword_anytype => break :blk true, |
| 1358 | 1338 | .ellipsis3 => break :is_var_args true, |
| 1359 | 1339 | else => unreachable, |
| ... | ... | @@ -1376,16 +1356,14 @@ fn fnProtoExprInner( |
| 1376 | 1356 | .param_anytype; |
| 1377 | 1357 | _ = try block_scope.addStrTok(tag, param_name, name_token); |
| 1378 | 1358 | } else { |
| 1379 | const param_type_node = param.type_expr; | |
| 1380 | assert(param_type_node != 0); | |
| 1359 | const param_type_node = param.type_expr.?; | |
| 1381 | 1360 | var param_gz = block_scope.makeSubBlock(scope); |
| 1382 | 1361 | defer param_gz.unstack(); |
| 1383 | 1362 | param_gz.is_comptime = true; |
| 1384 | 1363 | const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal); |
| 1385 | 1364 | const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1); |
| 1386 | 1365 | _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); |
| 1387 | const main_tokens = tree.nodes.items(.main_token); | |
| 1388 | const name_token = param.name_token orelse main_tokens[param_type_node]; | |
| 1366 | const name_token = param.name_token orelse tree.nodeMainToken(param_type_node); | |
| 1389 | 1367 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 1390 | 1368 | // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous |
| 1391 | 1369 | // arguments (we haven't set up scopes here). |
| ... | ... | @@ -1396,12 +1374,12 @@ fn fnProtoExprInner( |
| 1396 | 1374 | break :is_var_args false; |
| 1397 | 1375 | }; |
| 1398 | 1376 | |
| 1399 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) | |
| 1377 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| | |
| 1400 | 1378 | try comptimeExpr( |
| 1401 | 1379 | &block_scope, |
| 1402 | 1380 | scope, |
| 1403 | .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, | |
| 1404 | fn_proto.ast.callconv_expr, | |
| 1381 | .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(callconv_expr, .calling_convention) } }, | |
| 1382 | callconv_expr, | |
| 1405 | 1383 | .@"callconv", |
| 1406 | 1384 | ) |
| 1407 | 1385 | else if (implicit_ccc) |
| ... | ... | @@ -1409,7 +1387,8 @@ fn fnProtoExprInner( |
| 1409 | 1387 | else |
| 1410 | 1388 | .none; |
| 1411 | 1389 | |
| 1412 | const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty); | |
| 1390 | const ret_ty_node = fn_proto.ast.return_type.unwrap().?; | |
| 1391 | const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty); | |
| 1413 | 1392 | |
| 1414 | 1393 | const result = try block_scope.addFunc(.{ |
| 1415 | 1394 | .src_node = fn_proto.ast.proto_node, |
| ... | ... | @@ -1449,33 +1428,32 @@ fn arrayInitExpr( |
| 1449 | 1428 | ) InnerError!Zir.Inst.Ref { |
| 1450 | 1429 | const astgen = gz.astgen; |
| 1451 | 1430 | const tree = astgen.tree; |
| 1452 | const node_tags = tree.nodes.items(.tag); | |
| 1453 | const main_tokens = tree.nodes.items(.main_token); | |
| 1454 | 1431 | |
| 1455 | 1432 | assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init. |
| 1456 | 1433 | |
| 1457 | 1434 | const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: { |
| 1458 | if (array_init.ast.type_expr == 0) break :inst .{ .none, .none }; | |
| 1435 | const type_expr = array_init.ast.type_expr.unwrap() orelse break :inst .{ .none, .none }; | |
| 1459 | 1436 | |
| 1460 | 1437 | infer: { |
| 1461 | const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer; | |
| 1438 | const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse break :infer; | |
| 1462 | 1439 | // This intentionally does not support `@"_"` syntax. |
| 1463 | if (node_tags[array_type.ast.elem_count] == .identifier and | |
| 1464 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_")) | |
| 1440 | if (tree.nodeTag(array_type.ast.elem_count) == .identifier and | |
| 1441 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_")) | |
| 1465 | 1442 | { |
| 1466 | 1443 | const len_inst = try gz.addInt(array_init.ast.elements.len); |
| 1467 | 1444 | const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type); |
| 1468 | if (array_type.ast.sentinel == 0) { | |
| 1469 | const array_type_inst = try gz.addPlNode(.array_type, array_init.ast.type_expr, Zir.Inst.Bin{ | |
| 1445 | if (array_type.ast.sentinel == .none) { | |
| 1446 | const array_type_inst = try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{ | |
| 1470 | 1447 | .lhs = len_inst, |
| 1471 | 1448 | .rhs = elem_type, |
| 1472 | 1449 | }); |
| 1473 | 1450 | break :inst .{ array_type_inst, elem_type }; |
| 1474 | 1451 | } else { |
| 1475 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel); | |
| 1452 | const sentinel_node = array_type.ast.sentinel.unwrap().?; | |
| 1453 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel); | |
| 1476 | 1454 | const array_type_inst = try gz.addPlNode( |
| 1477 | 1455 | .array_type_sentinel, |
| 1478 | array_init.ast.type_expr, | |
| 1456 | type_expr, | |
| 1479 | 1457 | Zir.Inst.ArrayTypeSentinel{ |
| 1480 | 1458 | .len = len_inst, |
| 1481 | 1459 | .elem_type = elem_type, |
| ... | ... | @@ -1486,7 +1464,7 @@ fn arrayInitExpr( |
| 1486 | 1464 | } |
| 1487 | 1465 | } |
| 1488 | 1466 | } |
| 1489 | const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr); | |
| 1467 | const array_type_inst = try typeExpr(gz, scope, type_expr); | |
| 1490 | 1468 | _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{ |
| 1491 | 1469 | .ty = array_type_inst, |
| 1492 | 1470 | .init_count = @intCast(array_init.ast.elements.len), |
| ... | ... | @@ -1694,7 +1672,7 @@ fn structInitExpr( |
| 1694 | 1672 | const astgen = gz.astgen; |
| 1695 | 1673 | const tree = astgen.tree; |
| 1696 | 1674 | |
| 1697 | if (struct_init.ast.type_expr == 0) { | |
| 1675 | if (struct_init.ast.type_expr == .none) { | |
| 1698 | 1676 | if (struct_init.ast.fields.len == 0) { |
| 1699 | 1677 | // Anonymous init with no fields. |
| 1700 | 1678 | switch (ri.rl) { |
| ... | ... | @@ -1718,32 +1696,32 @@ fn structInitExpr( |
| 1718 | 1696 | } |
| 1719 | 1697 | } |
| 1720 | 1698 | } else array: { |
| 1721 | const node_tags = tree.nodes.items(.tag); | |
| 1722 | const main_tokens = tree.nodes.items(.main_token); | |
| 1723 | const array_type: Ast.full.ArrayType = tree.fullArrayType(struct_init.ast.type_expr) orelse { | |
| 1699 | const type_expr = struct_init.ast.type_expr.unwrap().?; | |
| 1700 | const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse { | |
| 1724 | 1701 | if (struct_init.ast.fields.len == 0) { |
| 1725 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1702 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1726 | 1703 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1727 | 1704 | return rvalue(gz, ri, result, node); |
| 1728 | 1705 | } |
| 1729 | 1706 | break :array; |
| 1730 | 1707 | }; |
| 1731 | const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and | |
| 1708 | const is_inferred_array_len = tree.nodeTag(array_type.ast.elem_count) == .identifier and | |
| 1732 | 1709 | // This intentionally does not support `@"_"` syntax. |
| 1733 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"); | |
| 1710 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_"); | |
| 1734 | 1711 | if (struct_init.ast.fields.len == 0) { |
| 1735 | 1712 | if (is_inferred_array_len) { |
| 1736 | 1713 | const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type); |
| 1737 | const array_type_inst = if (array_type.ast.sentinel == 0) blk: { | |
| 1738 | break :blk try gz.addPlNode(.array_type, struct_init.ast.type_expr, Zir.Inst.Bin{ | |
| 1714 | const array_type_inst = if (array_type.ast.sentinel == .none) blk: { | |
| 1715 | break :blk try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{ | |
| 1739 | 1716 | .lhs = .zero_usize, |
| 1740 | 1717 | .rhs = elem_type, |
| 1741 | 1718 | }); |
| 1742 | 1719 | } else blk: { |
| 1743 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel); | |
| 1720 | const sentinel_node = array_type.ast.sentinel.unwrap().?; | |
| 1721 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel); | |
| 1744 | 1722 | break :blk try gz.addPlNode( |
| 1745 | 1723 | .array_type_sentinel, |
| 1746 | struct_init.ast.type_expr, | |
| 1724 | type_expr, | |
| 1747 | 1725 | Zir.Inst.ArrayTypeSentinel{ |
| 1748 | 1726 | .len = .zero_usize, |
| 1749 | 1727 | .elem_type = elem_type, |
| ... | ... | @@ -1754,12 +1732,12 @@ fn structInitExpr( |
| 1754 | 1732 | const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node); |
| 1755 | 1733 | return rvalue(gz, ri, result, node); |
| 1756 | 1734 | } |
| 1757 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1735 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1758 | 1736 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1759 | 1737 | return rvalue(gz, ri, result, node); |
| 1760 | 1738 | } else { |
| 1761 | 1739 | return astgen.failNode( |
| 1762 | struct_init.ast.type_expr, | |
| 1740 | type_expr, | |
| 1763 | 1741 | "initializing array with struct syntax", |
| 1764 | 1742 | .{}, |
| 1765 | 1743 | ); |
| ... | ... | @@ -1818,9 +1796,9 @@ fn structInitExpr( |
| 1818 | 1796 | } |
| 1819 | 1797 | } |
| 1820 | 1798 | |
| 1821 | if (struct_init.ast.type_expr != 0) { | |
| 1799 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 1822 | 1800 | // Typed inits do not use RLS for language simplicity. |
| 1823 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1801 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1824 | 1802 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); |
| 1825 | 1803 | switch (ri.rl) { |
| 1826 | 1804 | .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true), |
| ... | ... | @@ -2009,9 +1987,7 @@ fn comptimeExpr2( |
| 2009 | 1987 | // no need to wrap it in a block. This is hard to determine in general, but we can identify a |
| 2010 | 1988 | // common subset of trivially comptime expressions to take down the size of the ZIR a bit. |
| 2011 | 1989 | const tree = gz.astgen.tree; |
| 2012 | const main_tokens = tree.nodes.items(.main_token); | |
| 2013 | const node_tags = tree.nodes.items(.tag); | |
| 2014 | switch (node_tags[node]) { | |
| 1990 | switch (tree.nodeTag(node)) { | |
| 2015 | 1991 | .identifier => { |
| 2016 | 1992 | // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has |
| 2017 | 1993 | // special handling for this case. |
| ... | ... | @@ -2064,8 +2040,7 @@ fn comptimeExpr2( |
| 2064 | 2040 | // comptime block, because that would be silly! Note that we don't bother doing this for |
| 2065 | 2041 | // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`). |
| 2066 | 2042 | .block_two, .block_two_semicolon, .block, .block_semicolon => { |
| 2067 | const token_tags = tree.tokens.items(.tag); | |
| 2068 | const lbrace = main_tokens[node]; | |
| 2043 | const lbrace = tree.nodeMainToken(node); | |
| 2069 | 2044 | // Careful! We can't pass in the real result location here, since it may |
| 2070 | 2045 | // refer to runtime memory. A runtime-to-comptime boundary has to remove |
| 2071 | 2046 | // result location information, compute the result, and copy it to the true |
| ... | ... | @@ -2077,31 +2052,13 @@ fn comptimeExpr2( |
| 2077 | 2052 | else |
| 2078 | 2053 | .none, |
| 2079 | 2054 | }; |
| 2080 | if (token_tags[lbrace - 1] == .colon and | |
| 2081 | token_tags[lbrace - 2] == .identifier) | |
| 2082 | { | |
| 2083 | const node_datas = tree.nodes.items(.data); | |
| 2084 | switch (node_tags[node]) { | |
| 2085 | .block_two, .block_two_semicolon => { | |
| 2086 | const stmts: [2]Ast.Node.Index = .{ node_datas[node].lhs, node_datas[node].rhs }; | |
| 2087 | const stmt_slice = if (stmts[0] == 0) | |
| 2088 | stmts[0..0] | |
| 2089 | else if (stmts[1] == 0) | |
| 2090 | stmts[0..1] | |
| 2091 | else | |
| 2092 | stmts[0..2]; | |
| 2055 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2056 | var buf: [2]Ast.Node.Index = undefined; | |
| 2057 | const stmts = tree.blockStatements(&buf, node).?; | |
| 2093 | 2058 | |
| 2094 | const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmt_slice, true, .normal); | |
| 2095 | return rvalue(gz, ri, block_ref, node); | |
| 2096 | }, | |
| 2097 | .block, .block_semicolon => { | |
| 2098 | const stmts = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 2099 | // Replace result location and copy back later - see above. | |
| 2100 | const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal); | |
| 2101 | return rvalue(gz, ri, block_ref, node); | |
| 2102 | }, | |
| 2103 | else => unreachable, | |
| 2104 | } | |
| 2059 | // Replace result location and copy back later - see above. | |
| 2060 | const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal); | |
| 2061 | return rvalue(gz, ri, block_ref, node); | |
| 2105 | 2062 | } |
| 2106 | 2063 | }, |
| 2107 | 2064 | |
| ... | ... | @@ -2146,8 +2103,7 @@ fn comptimeExprAst( |
| 2146 | 2103 | try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{}); |
| 2147 | 2104 | } |
| 2148 | 2105 | const tree = astgen.tree; |
| 2149 | const node_datas = tree.nodes.items(.data); | |
| 2150 | const body_node = node_datas[node].lhs; | |
| 2106 | const body_node = tree.nodeData(node).node; | |
| 2151 | 2107 | return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword); |
| 2152 | 2108 | } |
| 2153 | 2109 | |
| ... | ... | @@ -2185,9 +2141,7 @@ fn restoreErrRetIndex( |
| 2185 | 2141 | fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2186 | 2142 | const astgen = parent_gz.astgen; |
| 2187 | 2143 | const tree = astgen.tree; |
| 2188 | const node_datas = tree.nodes.items(.data); | |
| 2189 | const break_label = node_datas[node].lhs; | |
| 2190 | const rhs = node_datas[node].rhs; | |
| 2144 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 2191 | 2145 | |
| 2192 | 2146 | // Look for the label in the scope. |
| 2193 | 2147 | var scope = parent_scope; |
| ... | ... | @@ -2196,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2196 | 2150 | .gen_zir => { |
| 2197 | 2151 | const block_gz = scope.cast(GenZir).?; |
| 2198 | 2152 | |
| 2199 | if (block_gz.cur_defer_node != 0) { | |
| 2153 | if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| { | |
| 2200 | 2154 | // We are breaking out of a `defer` block. |
| 2201 | 2155 | return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ |
| 2202 | 2156 | try astgen.errNoteNode( |
| 2203 | block_gz.cur_defer_node, | |
| 2157 | cur_defer_node, | |
| 2204 | 2158 | "defer expression here", |
| 2205 | 2159 | .{}, |
| 2206 | 2160 | ), |
| ... | ... | @@ -2208,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2208 | 2162 | } |
| 2209 | 2163 | |
| 2210 | 2164 | const block_inst = blk: { |
| 2211 | if (break_label != 0) { | |
| 2165 | if (opt_break_label.unwrap()) |break_label| { | |
| 2212 | 2166 | if (block_gz.label) |*label| { |
| 2213 | 2167 | if (try astgen.tokenIdentEql(label.token, break_label)) { |
| 2214 | 2168 | label.used = true; |
| ... | ... | @@ -2229,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2229 | 2183 | else |
| 2230 | 2184 | .@"break"; |
| 2231 | 2185 | |
| 2232 | if (rhs == 0) { | |
| 2186 | const rhs = opt_rhs.unwrap() orelse { | |
| 2233 | 2187 | _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node); |
| 2234 | 2188 | |
| 2235 | 2189 | try genDefers(parent_gz, scope, parent_scope, .normal_only); |
| ... | ... | @@ -2240,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2240 | 2194 | |
| 2241 | 2195 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); |
| 2242 | 2196 | return Zir.Inst.Ref.unreachable_value; |
| 2243 | } | |
| 2197 | }; | |
| 2244 | 2198 | |
| 2245 | 2199 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node); |
| 2246 | 2200 | |
| ... | ... | @@ -2272,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2272 | 2226 | .top => unreachable, |
| 2273 | 2227 | } |
| 2274 | 2228 | } |
| 2275 | if (break_label != 0) { | |
| 2229 | if (opt_break_label.unwrap()) |break_label| { | |
| 2276 | 2230 | const label_name = try astgen.identifierTokenString(break_label); |
| 2277 | 2231 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 2278 | 2232 | } else { |
| ... | ... | @@ -2283,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2283 | 2237 | fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2284 | 2238 | const astgen = parent_gz.astgen; |
| 2285 | 2239 | const tree = astgen.tree; |
| 2286 | const node_datas = tree.nodes.items(.data); | |
| 2287 | const break_label = node_datas[node].lhs; | |
| 2288 | const rhs = node_datas[node].rhs; | |
| 2240 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 2289 | 2241 | |
| 2290 | if (break_label == 0 and rhs != 0) { | |
| 2242 | if (opt_break_label == .none and opt_rhs != .none) { | |
| 2291 | 2243 | return astgen.failNode(node, "cannot continue with operand without label", .{}); |
| 2292 | 2244 | } |
| 2293 | 2245 | |
| ... | ... | @@ -2298,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2298 | 2250 | .gen_zir => { |
| 2299 | 2251 | const gen_zir = scope.cast(GenZir).?; |
| 2300 | 2252 | |
| 2301 | if (gen_zir.cur_defer_node != 0) { | |
| 2253 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { | |
| 2302 | 2254 | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ |
| 2303 | 2255 | try astgen.errNoteNode( |
| 2304 | gen_zir.cur_defer_node, | |
| 2256 | cur_defer_node, | |
| 2305 | 2257 | "defer expression here", |
| 2306 | 2258 | .{}, |
| 2307 | 2259 | ), |
| ... | ... | @@ -2311,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2311 | 2263 | scope = gen_zir.parent; |
| 2312 | 2264 | continue; |
| 2313 | 2265 | }; |
| 2314 | if (break_label != 0) blk: { | |
| 2266 | if (opt_break_label.unwrap()) |break_label| blk: { | |
| 2315 | 2267 | if (gen_zir.label) |*label| { |
| 2316 | 2268 | if (try astgen.tokenIdentEql(label.token, break_label)) { |
| 2317 | 2269 | const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)]; |
| 2318 | if (rhs != 0) switch (maybe_switch_tag) { | |
| 2270 | if (opt_rhs != .none) switch (maybe_switch_tag) { | |
| 2319 | 2271 | .switch_block, .switch_block_ref => {}, |
| 2320 | 2272 | else => return astgen.failNode(node, "cannot continue loop with operand", .{}), |
| 2321 | 2273 | } else switch (maybe_switch_tag) { |
| ... | ... | @@ -2343,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2343 | 2295 | } |
| 2344 | 2296 | } |
| 2345 | 2297 | |
| 2346 | if (rhs != 0) { | |
| 2298 | if (opt_rhs.unwrap()) |rhs| { | |
| 2347 | 2299 | // We need to figure out the result info to use. |
| 2348 | 2300 | // The type should match |
| 2349 | 2301 | const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node); |
| ... | ... | @@ -2382,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2382 | 2334 | .top => unreachable, |
| 2383 | 2335 | } |
| 2384 | 2336 | } |
| 2385 | if (break_label != 0) { | |
| 2337 | if (opt_break_label.unwrap()) |break_label| { | |
| 2386 | 2338 | const label_name = try astgen.identifierTokenString(break_label); |
| 2387 | 2339 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 2388 | 2340 | } else { |
| ... | ... | @@ -2402,30 +2354,14 @@ fn fullBodyExpr( |
| 2402 | 2354 | block_kind: BlockKind, |
| 2403 | 2355 | ) InnerError!Zir.Inst.Ref { |
| 2404 | 2356 | const tree = gz.astgen.tree; |
| 2405 | const node_tags = tree.nodes.items(.tag); | |
| 2406 | const node_datas = tree.nodes.items(.data); | |
| 2407 | const main_tokens = tree.nodes.items(.main_token); | |
| 2408 | const token_tags = tree.tokens.items(.tag); | |
| 2357 | ||
| 2409 | 2358 | var stmt_buf: [2]Ast.Node.Index = undefined; |
| 2410 | const statements: []const Ast.Node.Index = switch (node_tags[node]) { | |
| 2411 | else => return expr(gz, scope, ri, node), | |
| 2412 | .block_two, .block_two_semicolon => if (node_datas[node].lhs == 0) s: { | |
| 2413 | break :s &.{}; | |
| 2414 | } else if (node_datas[node].rhs == 0) s: { | |
| 2415 | stmt_buf[0] = node_datas[node].lhs; | |
| 2416 | break :s stmt_buf[0..1]; | |
| 2417 | } else s: { | |
| 2418 | stmt_buf[0] = node_datas[node].lhs; | |
| 2419 | stmt_buf[1] = node_datas[node].rhs; | |
| 2420 | break :s stmt_buf[0..2]; | |
| 2421 | }, | |
| 2422 | .block, .block_semicolon => tree.extra_data[node_datas[node].lhs..node_datas[node].rhs], | |
| 2423 | }; | |
| 2359 | const statements = tree.blockStatements(&stmt_buf, node) orelse | |
| 2360 | return expr(gz, scope, ri, node); | |
| 2424 | 2361 | |
| 2425 | const lbrace = main_tokens[node]; | |
| 2426 | if (token_tags[lbrace - 1] == .colon and | |
| 2427 | token_tags[lbrace - 2] == .identifier) | |
| 2428 | { | |
| 2362 | const lbrace = tree.nodeMainToken(node); | |
| 2363 | ||
| 2364 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2429 | 2365 | // Labeled blocks are tricky - forwarding result location information properly is non-trivial, |
| 2430 | 2366 | // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This |
| 2431 | 2367 | // case is rare, so just treat it as a normal expression and create a nested block. |
| ... | ... | @@ -2450,13 +2386,9 @@ fn blockExpr( |
| 2450 | 2386 | ) InnerError!Zir.Inst.Ref { |
| 2451 | 2387 | const astgen = gz.astgen; |
| 2452 | 2388 | const tree = astgen.tree; |
| 2453 | const main_tokens = tree.nodes.items(.main_token); | |
| 2454 | const token_tags = tree.tokens.items(.tag); | |
| 2455 | 2389 | |
| 2456 | const lbrace = main_tokens[block_node]; | |
| 2457 | if (token_tags[lbrace - 1] == .colon and | |
| 2458 | token_tags[lbrace - 2] == .identifier) | |
| 2459 | { | |
| 2390 | const lbrace = tree.nodeMainToken(block_node); | |
| 2391 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2460 | 2392 | return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind); |
| 2461 | 2393 | } |
| 2462 | 2394 | |
| ... | ... | @@ -2533,12 +2465,10 @@ fn labeledBlockExpr( |
| 2533 | 2465 | ) InnerError!Zir.Inst.Ref { |
| 2534 | 2466 | const astgen = gz.astgen; |
| 2535 | 2467 | const tree = astgen.tree; |
| 2536 | const main_tokens = tree.nodes.items(.main_token); | |
| 2537 | const token_tags = tree.tokens.items(.tag); | |
| 2538 | 2468 | |
| 2539 | const lbrace = main_tokens[block_node]; | |
| 2469 | const lbrace = tree.nodeMainToken(block_node); | |
| 2540 | 2470 | const label_token = lbrace - 2; |
| 2541 | assert(token_tags[label_token] == .identifier); | |
| 2471 | assert(tree.tokenTag(label_token) == .identifier); | |
| 2542 | 2472 | |
| 2543 | 2473 | try astgen.checkLabelRedefinition(parent_scope, label_token); |
| 2544 | 2474 | |
| ... | ... | @@ -2599,8 +2529,6 @@ fn labeledBlockExpr( |
| 2599 | 2529 | fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void { |
| 2600 | 2530 | const astgen = gz.astgen; |
| 2601 | 2531 | const tree = astgen.tree; |
| 2602 | const node_tags = tree.nodes.items(.tag); | |
| 2603 | const node_data = tree.nodes.items(.data); | |
| 2604 | 2532 | |
| 2605 | 2533 | if (statements.len == 0) return; |
| 2606 | 2534 | |
| ... | ... | @@ -2608,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2608 | 2536 | defer block_arena.deinit(); |
| 2609 | 2537 | const block_arena_allocator = block_arena.allocator(); |
| 2610 | 2538 | |
| 2611 | var noreturn_src_node: Ast.Node.Index = 0; | |
| 2539 | var noreturn_src_node: Ast.Node.OptionalIndex = .none; | |
| 2612 | 2540 | var scope = parent_scope; |
| 2613 | 2541 | for (statements, 0..) |statement, stmt_idx| { |
| 2614 | if (noreturn_src_node != 0) { | |
| 2542 | if (noreturn_src_node.unwrap()) |src_node| { | |
| 2615 | 2543 | try astgen.appendErrorNodeNotes( |
| 2616 | 2544 | statement, |
| 2617 | 2545 | "unreachable code", |
| 2618 | 2546 | .{}, |
| 2619 | 2547 | &[_]u32{ |
| 2620 | 2548 | try astgen.errNoteNode( |
| 2621 | noreturn_src_node, | |
| 2549 | src_node, | |
| 2622 | 2550 | "control flow is diverted here", |
| 2623 | 2551 | .{}, |
| 2624 | 2552 | ), |
| ... | ... | @@ -2631,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2631 | 2559 | }; |
| 2632 | 2560 | var inner_node = statement; |
| 2633 | 2561 | while (true) { |
| 2634 | switch (node_tags[inner_node]) { | |
| 2562 | switch (tree.nodeTag(inner_node)) { | |
| 2635 | 2563 | // zig fmt: off |
| 2636 | 2564 | .global_var_decl, |
| 2637 | 2565 | .local_var_decl, |
| ... | ... | @@ -2661,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2661 | 2589 | .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap), |
| 2662 | 2590 | |
| 2663 | 2591 | .grouped_expression => { |
| 2664 | inner_node = node_data[statement].lhs; | |
| 2592 | inner_node = tree.nodeData(statement).node_and_token[0]; | |
| 2665 | 2593 | continue; |
| 2666 | 2594 | }, |
| 2667 | 2595 | |
| ... | ... | @@ -2671,47 +2599,37 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2671 | 2599 | |
| 2672 | 2600 | .for_simple, |
| 2673 | 2601 | .@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true), |
| 2602 | // zig fmt: on | |
| 2674 | 2603 | |
| 2675 | 2604 | // These cases are here to allow branch hints. |
| 2676 | .builtin_call_two, .builtin_call_two_comma => { | |
| 2677 | try emitDbgNode(gz, inner_node); | |
| 2678 | const ri: ResultInfo = .{ .rl = .none }; | |
| 2679 | const result = if (node_data[inner_node].lhs == 0) r: { | |
| 2680 | break :r try builtinCall(gz, scope, ri, inner_node, &.{}, allow_branch_hint); | |
| 2681 | } else if (node_data[inner_node].rhs == 0) r: { | |
| 2682 | break :r try builtinCall(gz, scope, ri, inner_node, &.{node_data[inner_node].lhs}, allow_branch_hint); | |
| 2683 | } else r: { | |
| 2684 | break :r try builtinCall(gz, scope, ri, inner_node, &.{ | |
| 2685 | node_data[inner_node].lhs, | |
| 2686 | node_data[inner_node].rhs, | |
| 2687 | }, allow_branch_hint); | |
| 2688 | }; | |
| 2689 | noreturn_src_node = try addEnsureResult(gz, result, inner_node); | |
| 2690 | }, | |
| 2691 | .builtin_call, .builtin_call_comma => { | |
| 2605 | .builtin_call_two, | |
| 2606 | .builtin_call_two_comma, | |
| 2607 | .builtin_call, | |
| 2608 | .builtin_call_comma, | |
| 2609 | => { | |
| 2610 | var buf: [2]Ast.Node.Index = undefined; | |
| 2611 | const params = tree.builtinCallParams(&buf, inner_node).?; | |
| 2612 | ||
| 2692 | 2613 | try emitDbgNode(gz, inner_node); |
| 2693 | const ri: ResultInfo = .{ .rl = .none }; | |
| 2694 | const params = tree.extra_data[node_data[inner_node].lhs..node_data[inner_node].rhs]; | |
| 2695 | const result = try builtinCall(gz, scope, ri, inner_node, params, allow_branch_hint); | |
| 2614 | const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint); | |
| 2696 | 2615 | noreturn_src_node = try addEnsureResult(gz, result, inner_node); |
| 2697 | 2616 | }, |
| 2698 | 2617 | |
| 2699 | 2618 | else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node), |
| 2700 | // zig fmt: on | |
| 2701 | 2619 | } |
| 2702 | 2620 | break; |
| 2703 | 2621 | } |
| 2704 | 2622 | } |
| 2705 | 2623 | |
| 2706 | if (noreturn_src_node == 0) { | |
| 2624 | if (noreturn_src_node == .none) { | |
| 2707 | 2625 | try genDefers(gz, parent_scope, scope, .normal_only); |
| 2708 | 2626 | } |
| 2709 | 2627 | try checkUsed(gz, parent_scope, scope); |
| 2710 | 2628 | } |
| 2711 | 2629 | |
| 2712 | 2630 | /// Returns AST source node of the thing that is noreturn if the statement is |
| 2713 | /// definitely `noreturn`. Otherwise returns 0. | |
| 2714 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { | |
| 2631 | /// definitely `noreturn`. Otherwise returns .none. | |
| 2632 | fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex { | |
| 2715 | 2633 | try emitDbgNode(gz, statement); |
| 2716 | 2634 | // We need to emit an error if the result is not `noreturn` or `void`, but |
| 2717 | 2635 | // we want to avoid adding the ZIR instruction if possible for performance. |
| ... | ... | @@ -2719,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2719 | 2637 | return addEnsureResult(gz, maybe_unused_result, statement); |
| 2720 | 2638 | } |
| 2721 | 2639 | |
| 2722 | fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index { | |
| 2723 | var noreturn_src_node: Ast.Node.Index = 0; | |
| 2640 | fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex { | |
| 2641 | var noreturn_src_node: Ast.Node.OptionalIndex = .none; | |
| 2724 | 2642 | const elide_check = if (maybe_unused_result.toIndex()) |inst| b: { |
| 2725 | 2643 | // Note that this array becomes invalid after appending more items to it |
| 2726 | 2644 | // in the above while loop. |
| ... | ... | @@ -2981,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2981 | 2899 | .check_comptime_control_flow, |
| 2982 | 2900 | .switch_continue, |
| 2983 | 2901 | => { |
| 2984 | noreturn_src_node = statement; | |
| 2902 | noreturn_src_node = statement.toOptional(); | |
| 2985 | 2903 | break :b true; |
| 2986 | 2904 | }, |
| 2987 | 2905 | |
| ... | ... | @@ -3023,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 3023 | 2941 | .none => unreachable, |
| 3024 | 2942 | |
| 3025 | 2943 | .unreachable_value => b: { |
| 3026 | noreturn_src_node = statement; | |
| 2944 | noreturn_src_node = statement.toOptional(); | |
| 3027 | 2945 | break :b true; |
| 3028 | 2946 | }, |
| 3029 | 2947 | |
| ... | ... | @@ -3152,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3152 | 3070 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 3153 | 3071 | .local_val => { |
| 3154 | 3072 | const s = scope.cast(Scope.LocalVal).?; |
| 3155 | if (s.used == 0 and s.discarded == 0) { | |
| 3073 | if (s.used == .none and s.discarded == .none) { | |
| 3156 | 3074 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3157 | } else if (s.used != 0 and s.discarded != 0) { | |
| 3158 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3159 | try gz.astgen.errNoteTok(s.used, "used here", .{}), | |
| 3075 | } else if (s.used != .none and s.discarded != .none) { | |
| 3076 | try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3077 | try gz.astgen.errNoteTok(s.used.unwrap().?, "used here", .{}), | |
| 3160 | 3078 | }); |
| 3161 | 3079 | } |
| 3162 | 3080 | scope = s.parent; |
| 3163 | 3081 | }, |
| 3164 | 3082 | .local_ptr => { |
| 3165 | 3083 | const s = scope.cast(Scope.LocalPtr).?; |
| 3166 | if (s.used == 0 and s.discarded == 0) { | |
| 3084 | if (s.used == .none and s.discarded == .none) { | |
| 3167 | 3085 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3168 | 3086 | } else { |
| 3169 | if (s.used != 0 and s.discarded != 0) { | |
| 3170 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3171 | try astgen.errNoteTok(s.used, "used here", .{}), | |
| 3087 | if (s.used != .none and s.discarded != .none) { | |
| 3088 | try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3089 | try astgen.errNoteTok(s.used.unwrap().?, "used here", .{}), | |
| 3172 | 3090 | }); |
| 3173 | 3091 | } |
| 3174 | 3092 | if (s.id_cat == .@"local variable" and !s.used_as_lvalue) { |
| ... | ... | @@ -3195,19 +3113,15 @@ fn deferStmt( |
| 3195 | 3113 | scope_tag: Scope.Tag, |
| 3196 | 3114 | ) InnerError!*Scope { |
| 3197 | 3115 | var defer_gen = gz.makeSubBlock(scope); |
| 3198 | defer_gen.cur_defer_node = node; | |
| 3199 | defer_gen.any_defer_node = node; | |
| 3116 | defer_gen.cur_defer_node = node.toOptional(); | |
| 3117 | defer_gen.any_defer_node = node.toOptional(); | |
| 3200 | 3118 | defer defer_gen.unstack(); |
| 3201 | 3119 | |
| 3202 | 3120 | const tree = gz.astgen.tree; |
| 3203 | const node_datas = tree.nodes.items(.data); | |
| 3204 | const expr_node = node_datas[node].rhs; | |
| 3205 | ||
| 3206 | const payload_token = node_datas[node].lhs; | |
| 3207 | 3121 | var local_val_scope: Scope.LocalVal = undefined; |
| 3208 | 3122 | var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none; |
| 3209 | const have_err_code = scope_tag == .defer_error and payload_token != 0; | |
| 3210 | const sub_scope = if (!have_err_code) &defer_gen.base else blk: { | |
| 3123 | const sub_scope = if (scope_tag != .defer_error) &defer_gen.base else blk: { | |
| 3124 | const payload_token = tree.nodeData(node).opt_token_and_node[0].unwrap() orelse break :blk &defer_gen.base; | |
| 3211 | 3125 | const ident_name = try gz.astgen.identAsString(payload_token); |
| 3212 | 3126 | if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) { |
| 3213 | 3127 | try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{}); |
| ... | ... | @@ -3235,6 +3149,11 @@ fn deferStmt( |
| 3235 | 3149 | try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref); |
| 3236 | 3150 | break :blk &local_val_scope.base; |
| 3237 | 3151 | }; |
| 3152 | const expr_node = switch (scope_tag) { | |
| 3153 | .defer_normal => tree.nodeData(node).node, | |
| 3154 | .defer_error => tree.nodeData(node).opt_token_and_node[1], | |
| 3155 | else => unreachable, | |
| 3156 | }; | |
| 3238 | 3157 | _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node); |
| 3239 | 3158 | try checkUsed(gz, scope, sub_scope); |
| 3240 | 3159 | _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value); |
| ... | ... | @@ -3269,8 +3188,6 @@ fn varDecl( |
| 3269 | 3188 | try emitDbgNode(gz, node); |
| 3270 | 3189 | const astgen = gz.astgen; |
| 3271 | 3190 | const tree = astgen.tree; |
| 3272 | const token_tags = tree.tokens.items(.tag); | |
| 3273 | const main_tokens = tree.nodes.items(.main_token); | |
| 3274 | 3191 | |
| 3275 | 3192 | const name_token = var_decl.ast.mut_token + 1; |
| 3276 | 3193 | const ident_name_raw = tree.tokenSlice(name_token); |
| ... | ... | @@ -3284,27 +3201,27 @@ fn varDecl( |
| 3284 | 3201 | ident_name, |
| 3285 | 3202 | name_token, |
| 3286 | 3203 | ident_name_raw, |
| 3287 | if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable", | |
| 3204 | if (tree.tokenTag(var_decl.ast.mut_token) == .keyword_const) .@"local constant" else .@"local variable", | |
| 3288 | 3205 | ); |
| 3289 | 3206 | |
| 3290 | if (var_decl.ast.init_node == 0) { | |
| 3207 | const init_node = var_decl.ast.init_node.unwrap() orelse { | |
| 3291 | 3208 | return astgen.failNode(node, "variables must be initialized", .{}); |
| 3292 | } | |
| 3209 | }; | |
| 3293 | 3210 | |
| 3294 | if (var_decl.ast.addrspace_node != 0) { | |
| 3295 | return astgen.failTok(main_tokens[var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3211 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3212 | return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3296 | 3213 | } |
| 3297 | 3214 | |
| 3298 | if (var_decl.ast.section_node != 0) { | |
| 3299 | return astgen.failTok(main_tokens[var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3215 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 3216 | return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3300 | 3217 | } |
| 3301 | 3218 | |
| 3302 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) | |
| 3303 | try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node) | |
| 3219 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node| | |
| 3220 | try expr(gz, scope, coerced_align_ri, align_node) | |
| 3304 | 3221 | else |
| 3305 | 3222 | .none; |
| 3306 | 3223 | |
| 3307 | switch (token_tags[var_decl.ast.mut_token]) { | |
| 3224 | switch (tree.tokenTag(var_decl.ast.mut_token)) { | |
| 3308 | 3225 | .keyword_const => { |
| 3309 | 3226 | if (var_decl.comptime_token) |comptime_token| { |
| 3310 | 3227 | try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{}); |
| ... | ... | @@ -3316,25 +3233,24 @@ fn varDecl( |
| 3316 | 3233 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 3317 | 3234 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 3318 | 3235 | // the variable, no memory location needed. |
| 3319 | const type_node = var_decl.ast.type_node; | |
| 3320 | 3236 | if (align_inst == .none and |
| 3321 | 3237 | !astgen.nodes_need_rl.contains(node)) |
| 3322 | 3238 | { |
| 3323 | const result_info: ResultInfo = if (type_node != 0) .{ | |
| 3239 | const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{ | |
| 3324 | 3240 | .rl = .{ .ty = try typeExpr(gz, scope, type_node) }, |
| 3325 | 3241 | .ctx = .const_init, |
| 3326 | 3242 | } else .{ .rl = .none, .ctx = .const_init }; |
| 3327 | 3243 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 3328 | 3244 | gz.anon_name_strategy = .dbg_var; |
| 3329 | const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3245 | const init_inst = try reachableExprComptime(gz, scope, result_info, init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3330 | 3246 | gz.anon_name_strategy = prev_anon_name_strategy; |
| 3331 | 3247 | |
| 3332 | _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node); | |
| 3248 | _ = try gz.addUnNode(.validate_const, init_inst, init_node); | |
| 3333 | 3249 | try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); |
| 3334 | 3250 | |
| 3335 | 3251 | // The const init expression may have modified the error return trace, so signal |
| 3336 | 3252 | // to Sema that it should save the new index for restoring later. |
| 3337 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) | |
| 3253 | if (nodeMayAppendToErrorTrace(tree, init_node)) | |
| 3338 | 3254 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 3339 | 3255 | |
| 3340 | 3256 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| ... | ... | @@ -3350,9 +3266,9 @@ fn varDecl( |
| 3350 | 3266 | } |
| 3351 | 3267 | |
| 3352 | 3268 | const is_comptime = gz.is_comptime or |
| 3353 | tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime"; | |
| 3269 | tree.nodeTag(init_node) == .@"comptime"; | |
| 3354 | 3270 | |
| 3355 | const init_rl: ResultInfo.Loc = if (type_node != 0) init_rl: { | |
| 3271 | const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: { | |
| 3356 | 3272 | const type_inst = try typeExpr(gz, scope, type_node); |
| 3357 | 3273 | if (align_inst == .none) { |
| 3358 | 3274 | break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } }; |
| ... | ... | @@ -3393,11 +3309,11 @@ fn varDecl( |
| 3393 | 3309 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 3394 | 3310 | gz.anon_name_strategy = .dbg_var; |
| 3395 | 3311 | defer gz.anon_name_strategy = prev_anon_name_strategy; |
| 3396 | const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3312 | const init_inst = try reachableExprComptime(gz, scope, init_result_info, init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3397 | 3313 | |
| 3398 | 3314 | // The const init expression may have modified the error return trace, so signal |
| 3399 | 3315 | // to Sema that it should save the new index for restoring later. |
| 3400 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) | |
| 3316 | if (nodeMayAppendToErrorTrace(tree, init_node)) | |
| 3401 | 3317 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 3402 | 3318 | |
| 3403 | 3319 | const const_ptr = if (resolve_inferred) |
| ... | ... | @@ -3423,8 +3339,8 @@ fn varDecl( |
| 3423 | 3339 | if (var_decl.comptime_token != null and gz.is_comptime) |
| 3424 | 3340 | return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{}); |
| 3425 | 3341 | const is_comptime = var_decl.comptime_token != null or gz.is_comptime; |
| 3426 | const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: { | |
| 3427 | const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); | |
| 3342 | const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| a: { | |
| 3343 | const type_inst = try typeExpr(gz, scope, type_node); | |
| 3428 | 3344 | const alloc = alloc: { |
| 3429 | 3345 | if (align_inst == .none) { |
| 3430 | 3346 | const tag: Zir.Inst.Tag = if (is_comptime) |
| ... | ... | @@ -3469,7 +3385,7 @@ fn varDecl( |
| 3469 | 3385 | gz, |
| 3470 | 3386 | scope, |
| 3471 | 3387 | result_info, |
| 3472 | var_decl.ast.init_node, | |
| 3388 | init_node, | |
| 3473 | 3389 | node, |
| 3474 | 3390 | if (var_decl.comptime_token != null) .comptime_keyword else null, |
| 3475 | 3391 | ); |
| ... | ... | @@ -3512,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3512 | 3428 | try emitDbgNode(gz, infix_node); |
| 3513 | 3429 | const astgen = gz.astgen; |
| 3514 | 3430 | const tree = astgen.tree; |
| 3515 | const node_datas = tree.nodes.items(.data); | |
| 3516 | const main_tokens = tree.nodes.items(.main_token); | |
| 3517 | const node_tags = tree.nodes.items(.tag); | |
| 3518 | 3431 | |
| 3519 | const lhs = node_datas[infix_node].lhs; | |
| 3520 | const rhs = node_datas[infix_node].rhs; | |
| 3521 | if (node_tags[lhs] == .identifier) { | |
| 3432 | const lhs, const rhs = tree.nodeData(infix_node).node_and_node; | |
| 3433 | if (tree.nodeTag(lhs) == .identifier) { | |
| 3522 | 3434 | // This intentionally does not support `@"_"` syntax. |
| 3523 | const ident_name = tree.tokenSlice(main_tokens[lhs]); | |
| 3435 | const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs)); | |
| 3524 | 3436 | if (mem.eql(u8, ident_name, "_")) { |
| 3525 | 3437 | _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs); |
| 3526 | 3438 | return; |
| ... | ... | @@ -3538,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro |
| 3538 | 3450 | try emitDbgNode(gz, node); |
| 3539 | 3451 | const astgen = gz.astgen; |
| 3540 | 3452 | const tree = astgen.tree; |
| 3541 | const main_tokens = tree.nodes.items(.main_token); | |
| 3542 | const node_tags = tree.nodes.items(.tag); | |
| 3543 | 3453 | |
| 3544 | 3454 | const full = tree.assignDestructure(node); |
| 3545 | 3455 | if (full.comptime_token != null and gz.is_comptime) { |
| ... | ... | @@ -3557,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro |
| 3557 | 3467 | |
| 3558 | 3468 | const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len); |
| 3559 | 3469 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3560 | if (node_tags[variable_node] == .identifier) { | |
| 3470 | if (tree.nodeTag(variable_node) == .identifier) { | |
| 3561 | 3471 | // This intentionally does not support `@"_"` syntax. |
| 3562 | const ident_name = tree.tokenSlice(main_tokens[variable_node]); | |
| 3472 | const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node)); | |
| 3563 | 3473 | if (mem.eql(u8, ident_name, "_")) { |
| 3564 | 3474 | variable_rl.* = .discard; |
| 3565 | 3475 | continue; |
| ... | ... | @@ -3596,9 +3506,6 @@ fn assignDestructureMaybeDecls( |
| 3596 | 3506 | try emitDbgNode(gz, node); |
| 3597 | 3507 | const astgen = gz.astgen; |
| 3598 | 3508 | const tree = astgen.tree; |
| 3599 | const token_tags = tree.tokens.items(.tag); | |
| 3600 | const main_tokens = tree.nodes.items(.main_token); | |
| 3601 | const node_tags = tree.nodes.items(.tag); | |
| 3602 | 3509 | |
| 3603 | 3510 | const full = tree.assignDestructure(node); |
| 3604 | 3511 | if (full.comptime_token != null and gz.is_comptime) { |
| ... | ... | @@ -3606,7 +3513,7 @@ fn assignDestructureMaybeDecls( |
| 3606 | 3513 | } |
| 3607 | 3514 | |
| 3608 | 3515 | const is_comptime = full.comptime_token != null or gz.is_comptime; |
| 3609 | const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime"; | |
| 3516 | const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime"; | |
| 3610 | 3517 | |
| 3611 | 3518 | // When declaring consts via a destructure, we always use a result pointer. |
| 3612 | 3519 | // This avoids the need to create tuple types, and is also likely easier to |
| ... | ... | @@ -3619,10 +3526,10 @@ fn assignDestructureMaybeDecls( |
| 3619 | 3526 | var any_non_const_variables = false; |
| 3620 | 3527 | var any_lvalue_expr = false; |
| 3621 | 3528 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3622 | switch (node_tags[variable_node]) { | |
| 3529 | switch (tree.nodeTag(variable_node)) { | |
| 3623 | 3530 | .identifier => { |
| 3624 | 3531 | // This intentionally does not support `@"_"` syntax. |
| 3625 | const ident_name = tree.tokenSlice(main_tokens[variable_node]); | |
| 3532 | const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node)); | |
| 3626 | 3533 | if (mem.eql(u8, ident_name, "_")) { |
| 3627 | 3534 | any_non_const_variables = true; |
| 3628 | 3535 | variable_rl.* = .discard; |
| ... | ... | @@ -3640,14 +3547,14 @@ fn assignDestructureMaybeDecls( |
| 3640 | 3547 | |
| 3641 | 3548 | // We detect shadowing in the second pass over these, while we're creating scopes. |
| 3642 | 3549 | |
| 3643 | if (full_var_decl.ast.addrspace_node != 0) { | |
| 3644 | return astgen.failTok(main_tokens[full_var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3550 | if (full_var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3551 | return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3645 | 3552 | } |
| 3646 | if (full_var_decl.ast.section_node != 0) { | |
| 3647 | return astgen.failTok(main_tokens[full_var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3553 | if (full_var_decl.ast.section_node.unwrap()) |section_node| { | |
| 3554 | return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3648 | 3555 | } |
| 3649 | 3556 | |
| 3650 | const is_const = switch (token_tags[full_var_decl.ast.mut_token]) { | |
| 3557 | const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) { | |
| 3651 | 3558 | .keyword_var => false, |
| 3652 | 3559 | .keyword_const => true, |
| 3653 | 3560 | else => unreachable, |
| ... | ... | @@ -3657,14 +3564,14 @@ fn assignDestructureMaybeDecls( |
| 3657 | 3564 | // We also mark `const`s as comptime if the RHS is definitely comptime-known. |
| 3658 | 3565 | const this_variable_comptime = is_comptime or (is_const and value_is_comptime); |
| 3659 | 3566 | |
| 3660 | const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node != 0) | |
| 3661 | try expr(gz, scope, coerced_align_ri, full_var_decl.ast.align_node) | |
| 3567 | const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node| | |
| 3568 | try expr(gz, scope, coerced_align_ri, align_node) | |
| 3662 | 3569 | else |
| 3663 | 3570 | .none; |
| 3664 | 3571 | |
| 3665 | if (full_var_decl.ast.type_node != 0) { | |
| 3572 | if (full_var_decl.ast.type_node.unwrap()) |type_node| { | |
| 3666 | 3573 | // Typed alloc |
| 3667 | const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node); | |
| 3574 | const type_inst = try typeExpr(gz, scope, type_node); | |
| 3668 | 3575 | const ptr = if (align_inst == .none) ptr: { |
| 3669 | 3576 | const tag: Zir.Inst.Tag = if (is_const) |
| 3670 | 3577 | .alloc |
| ... | ... | @@ -3733,7 +3640,7 @@ fn assignDestructureMaybeDecls( |
| 3733 | 3640 | // evaluate the lvalues from within the possible block_comptime. |
| 3734 | 3641 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3735 | 3642 | if (variable_rl.* != .typed_ptr) continue; |
| 3736 | switch (node_tags[variable_node]) { | |
| 3643 | switch (tree.nodeTag(variable_node)) { | |
| 3737 | 3644 | .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue, |
| 3738 | 3645 | else => {}, |
| 3739 | 3646 | } |
| ... | ... | @@ -3762,7 +3669,7 @@ fn assignDestructureMaybeDecls( |
| 3762 | 3669 | // If there were any `const` decls, make the pointer constant. |
| 3763 | 3670 | var cur_scope = scope; |
| 3764 | 3671 | for (rl_components, full.ast.variables) |variable_rl, variable_node| { |
| 3765 | switch (node_tags[variable_node]) { | |
| 3672 | switch (tree.nodeTag(variable_node)) { | |
| 3766 | 3673 | .local_var_decl, .simple_var_decl, .aligned_var_decl => {}, |
| 3767 | 3674 | else => continue, // We were mutating an existing lvalue - nothing to do |
| 3768 | 3675 | } |
| ... | ... | @@ -3772,7 +3679,7 @@ fn assignDestructureMaybeDecls( |
| 3772 | 3679 | .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false }, |
| 3773 | 3680 | .inferred_ptr => |ptr_inst| .{ ptr_inst, true }, |
| 3774 | 3681 | }; |
| 3775 | const is_const = switch (token_tags[full_var_decl.ast.mut_token]) { | |
| 3682 | const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) { | |
| 3776 | 3683 | .keyword_var => false, |
| 3777 | 3684 | .keyword_const => true, |
| 3778 | 3685 | else => unreachable, |
| ... | ... | @@ -3823,9 +3730,9 @@ fn assignOp( |
| 3823 | 3730 | try emitDbgNode(gz, infix_node); |
| 3824 | 3731 | const astgen = gz.astgen; |
| 3825 | 3732 | const tree = astgen.tree; |
| 3826 | const node_datas = tree.nodes.items(.data); | |
| 3827 | 3733 | |
| 3828 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3734 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3735 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3829 | 3736 | |
| 3830 | 3737 | const cursor = switch (op_inst_tag) { |
| 3831 | 3738 | .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node), |
| ... | ... | @@ -3851,7 +3758,7 @@ fn assignOp( |
| 3851 | 3758 | else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type |
| 3852 | 3759 | }; |
| 3853 | 3760 | // Not `coerced_ty` since `add`/etc won't coerce to this type. |
| 3854 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, node_datas[infix_node].rhs); | |
| 3761 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, rhs_node); | |
| 3855 | 3762 | |
| 3856 | 3763 | switch (op_inst_tag) { |
| 3857 | 3764 | .add, .sub, .mul, .div, .mod_rem => { |
| ... | ... | @@ -3878,12 +3785,12 @@ fn assignShift( |
| 3878 | 3785 | try emitDbgNode(gz, infix_node); |
| 3879 | 3786 | const astgen = gz.astgen; |
| 3880 | 3787 | const tree = astgen.tree; |
| 3881 | const node_datas = tree.nodes.items(.data); | |
| 3882 | 3788 | |
| 3883 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3789 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3790 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3884 | 3791 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3885 | 3792 | const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node); |
| 3886 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs); | |
| 3793 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, rhs_node); | |
| 3887 | 3794 | |
| 3888 | 3795 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3889 | 3796 | .lhs = lhs, |
| ... | ... | @@ -3899,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE |
| 3899 | 3806 | try emitDbgNode(gz, infix_node); |
| 3900 | 3807 | const astgen = gz.astgen; |
| 3901 | 3808 | const tree = astgen.tree; |
| 3902 | const node_datas = tree.nodes.items(.data); | |
| 3903 | 3809 | |
| 3904 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3810 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3811 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3905 | 3812 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3906 | 3813 | // Saturating shift-left allows any integer type for both the LHS and RHS. |
| 3907 | const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs); | |
| 3814 | const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node); | |
| 3908 | 3815 | |
| 3909 | 3816 | const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{ |
| 3910 | 3817 | .lhs = lhs, |
| ... | ... | @@ -3939,7 +3846,7 @@ fn ptrType( |
| 3939 | 3846 | var bit_end_ref: Zir.Inst.Ref = .none; |
| 3940 | 3847 | var trailing_count: u32 = 0; |
| 3941 | 3848 | |
| 3942 | if (ptr_info.ast.sentinel != 0) { | |
| 3849 | if (ptr_info.ast.sentinel.unwrap()) |sentinel| { | |
| 3943 | 3850 | // These attributes can appear in any order and they all come before the |
| 3944 | 3851 | // element type so we need to reset the source cursor before generating them. |
| 3945 | 3852 | gz.astgen.source_offset = source_offset; |
| ... | ... | @@ -3950,7 +3857,7 @@ fn ptrType( |
| 3950 | 3857 | gz, |
| 3951 | 3858 | scope, |
| 3952 | 3859 | .{ .rl = .{ .ty = elem_type } }, |
| 3953 | ptr_info.ast.sentinel, | |
| 3860 | sentinel, | |
| 3954 | 3861 | switch (ptr_info.size) { |
| 3955 | 3862 | .slice => .slice_sentinel, |
| 3956 | 3863 | else => .pointer_sentinel, |
| ... | ... | @@ -3958,27 +3865,27 @@ fn ptrType( |
| 3958 | 3865 | ); |
| 3959 | 3866 | trailing_count += 1; |
| 3960 | 3867 | } |
| 3961 | if (ptr_info.ast.addrspace_node != 0) { | |
| 3868 | if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3962 | 3869 | gz.astgen.source_offset = source_offset; |
| 3963 | 3870 | gz.astgen.source_line = source_line; |
| 3964 | 3871 | gz.astgen.source_column = source_column; |
| 3965 | 3872 | |
| 3966 | const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space); | |
| 3967 | addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node, .@"addrspace"); | |
| 3873 | const addrspace_ty = try gz.addBuiltinValue(addrspace_node, .address_space); | |
| 3874 | addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node, .@"addrspace"); | |
| 3968 | 3875 | trailing_count += 1; |
| 3969 | 3876 | } |
| 3970 | if (ptr_info.ast.align_node != 0) { | |
| 3877 | if (ptr_info.ast.align_node.unwrap()) |align_node| { | |
| 3971 | 3878 | gz.astgen.source_offset = source_offset; |
| 3972 | 3879 | gz.astgen.source_line = source_line; |
| 3973 | 3880 | gz.astgen.source_column = source_column; |
| 3974 | 3881 | |
| 3975 | align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align"); | |
| 3882 | align_ref = try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align"); | |
| 3976 | 3883 | trailing_count += 1; |
| 3977 | 3884 | } |
| 3978 | if (ptr_info.ast.bit_range_start != 0) { | |
| 3979 | assert(ptr_info.ast.bit_range_end != 0); | |
| 3980 | bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type); | |
| 3981 | bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end, .type); | |
| 3885 | if (ptr_info.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 3886 | const bit_range_end = ptr_info.ast.bit_range_end.unwrap().?; | |
| 3887 | bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_start, .type); | |
| 3888 | bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_end, .type); | |
| 3982 | 3889 | trailing_count += 2; |
| 3983 | 3890 | } |
| 3984 | 3891 | |
| ... | ... | @@ -4031,18 +3938,15 @@ fn ptrType( |
| 4031 | 3938 | fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 4032 | 3939 | const astgen = gz.astgen; |
| 4033 | 3940 | const tree = astgen.tree; |
| 4034 | const node_datas = tree.nodes.items(.data); | |
| 4035 | const node_tags = tree.nodes.items(.tag); | |
| 4036 | const main_tokens = tree.nodes.items(.main_token); | |
| 4037 | 3941 | |
| 4038 | const len_node = node_datas[node].lhs; | |
| 4039 | if (node_tags[len_node] == .identifier and | |
| 4040 | mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_")) | |
| 3942 | const len_node, const elem_type_node = tree.nodeData(node).node_and_node; | |
| 3943 | if (tree.nodeTag(len_node) == .identifier and | |
| 3944 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_")) | |
| 4041 | 3945 | { |
| 4042 | 3946 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 4043 | 3947 | } |
| 4044 | 3948 | const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type); |
| 4045 | const elem_type = try typeExpr(gz, scope, node_datas[node].rhs); | |
| 3949 | const elem_type = try typeExpr(gz, scope, elem_type_node); | |
| 4046 | 3950 | |
| 4047 | 3951 | const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{ |
| 4048 | 3952 | .lhs = len, |
| ... | ... | @@ -4054,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) ! |
| 4054 | 3958 | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 4055 | 3959 | const astgen = gz.astgen; |
| 4056 | 3960 | const tree = astgen.tree; |
| 4057 | const node_datas = tree.nodes.items(.data); | |
| 4058 | const node_tags = tree.nodes.items(.tag); | |
| 4059 | const main_tokens = tree.nodes.items(.main_token); | |
| 4060 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 4061 | ||
| 4062 | const len_node = node_datas[node].lhs; | |
| 4063 | if (node_tags[len_node] == .identifier and | |
| 4064 | mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_")) | |
| 3961 | ||
| 3962 | const len_node, const extra_index = tree.nodeData(node).node_and_extra; | |
| 3963 | const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 3964 | ||
| 3965 | if (tree.nodeTag(len_node) == .identifier and | |
| 3966 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_")) | |
| 4065 | 3967 | { |
| 4066 | 3968 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 4067 | 3969 | } |
| ... | ... | @@ -4161,11 +4063,10 @@ fn fnDecl( |
| 4161 | 4063 | scope: *Scope, |
| 4162 | 4064 | wip_members: *WipMembers, |
| 4163 | 4065 | decl_node: Ast.Node.Index, |
| 4164 | body_node: Ast.Node.Index, | |
| 4066 | body_node: Ast.Node.OptionalIndex, | |
| 4165 | 4067 | fn_proto: Ast.full.FnProto, |
| 4166 | 4068 | ) InnerError!void { |
| 4167 | 4069 | const tree = astgen.tree; |
| 4168 | const token_tags = tree.tokens.items(.tag); | |
| 4169 | 4070 | |
| 4170 | 4071 | const old_hasher = astgen.src_hasher; |
| 4171 | 4072 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4194,15 +4095,15 @@ fn fnDecl( |
| 4194 | 4095 | const is_pub = fn_proto.visib_token != null; |
| 4195 | 4096 | const is_export = blk: { |
| 4196 | 4097 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4197 | break :blk token_tags[maybe_export_token] == .keyword_export; | |
| 4098 | break :blk tree.tokenTag(maybe_export_token) == .keyword_export; | |
| 4198 | 4099 | }; |
| 4199 | 4100 | const is_extern = blk: { |
| 4200 | 4101 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4201 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 4102 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 4202 | 4103 | }; |
| 4203 | 4104 | const has_inline_keyword = blk: { |
| 4204 | 4105 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4205 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | |
| 4106 | break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline; | |
| 4206 | 4107 | }; |
| 4207 | 4108 | const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: { |
| 4208 | 4109 | const lib_name_str = try astgen.strLitAsString(lib_name_token); |
| ... | ... | @@ -4214,16 +4115,18 @@ fn fnDecl( |
| 4214 | 4115 | } |
| 4215 | 4116 | break :blk lib_name_str.index; |
| 4216 | 4117 | } else .empty; |
| 4217 | if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) { | |
| 4118 | if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) { | |
| 4218 | 4119 | return astgen.failNode( |
| 4219 | fn_proto.ast.callconv_expr, | |
| 4120 | fn_proto.ast.callconv_expr.unwrap().?, | |
| 4220 | 4121 | "explicit callconv incompatible with inline keyword", |
| 4221 | 4122 | .{}, |
| 4222 | 4123 | ); |
| 4223 | 4124 | } |
| 4224 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 4225 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 4226 | if (body_node == 0) { | |
| 4125 | ||
| 4126 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 4127 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 4128 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 4129 | if (body_node == .none) { | |
| 4227 | 4130 | if (!is_extern) { |
| 4228 | 4131 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); |
| 4229 | 4132 | } |
| ... | ... | @@ -4256,28 +4159,28 @@ fn fnDecl( |
| 4256 | 4159 | var align_gz = type_gz.makeSubBlock(scope); |
| 4257 | 4160 | defer align_gz.unstack(); |
| 4258 | 4161 | |
| 4259 | if (fn_proto.ast.align_expr != 0) { | |
| 4162 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 4260 | 4163 | astgen.restoreSourceCursor(saved_cursor); |
| 4261 | const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr); | |
| 4164 | const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr); | |
| 4262 | 4165 | _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4263 | 4166 | } |
| 4264 | 4167 | |
| 4265 | 4168 | var linksection_gz = align_gz.makeSubBlock(scope); |
| 4266 | 4169 | defer linksection_gz.unstack(); |
| 4267 | 4170 | |
| 4268 | if (fn_proto.ast.section_expr != 0) { | |
| 4171 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 4269 | 4172 | astgen.restoreSourceCursor(saved_cursor); |
| 4270 | const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr); | |
| 4173 | const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr); | |
| 4271 | 4174 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4272 | 4175 | } |
| 4273 | 4176 | |
| 4274 | 4177 | var addrspace_gz = linksection_gz.makeSubBlock(scope); |
| 4275 | 4178 | defer addrspace_gz.unstack(); |
| 4276 | 4179 | |
| 4277 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 4180 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 4278 | 4181 | astgen.restoreSourceCursor(saved_cursor); |
| 4279 | const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space); | |
| 4280 | const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr); | |
| 4182 | const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_expr, .address_space); | |
| 4183 | const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr); | |
| 4281 | 4184 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4282 | 4185 | } |
| 4283 | 4186 | |
| ... | ... | @@ -4287,7 +4190,7 @@ fn fnDecl( |
| 4287 | 4190 | if (!is_extern) { |
| 4288 | 4191 | // We include a function *value*, not a type. |
| 4289 | 4192 | astgen.restoreSourceCursor(saved_cursor); |
| 4290 | try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto); | |
| 4193 | try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto); | |
| 4291 | 4194 | } |
| 4292 | 4195 | |
| 4293 | 4196 | // *Now* we can incorporate the full source code into the hasher. |
| ... | ... | @@ -4326,18 +4229,19 @@ fn fnDeclInner( |
| 4326 | 4229 | fn_proto: Ast.full.FnProto, |
| 4327 | 4230 | ) InnerError!void { |
| 4328 | 4231 | const tree = astgen.tree; |
| 4329 | const token_tags = tree.tokens.items(.tag); | |
| 4330 | 4232 | |
| 4331 | 4233 | const is_noinline = blk: { |
| 4332 | 4234 | const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4333 | break :blk token_tags[maybe_noinline_token] == .keyword_noinline; | |
| 4235 | break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline; | |
| 4334 | 4236 | }; |
| 4335 | 4237 | const has_inline_keyword = blk: { |
| 4336 | 4238 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4337 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | |
| 4239 | break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline; | |
| 4338 | 4240 | }; |
| 4339 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 4340 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 4241 | ||
| 4242 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 4243 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 4244 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 4341 | 4245 | |
| 4342 | 4246 | // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters. |
| 4343 | 4247 | var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len); |
| ... | ... | @@ -4351,7 +4255,7 @@ fn fnDeclInner( |
| 4351 | 4255 | var param_type_i: usize = 0; |
| 4352 | 4256 | var it = fn_proto.iterate(tree); |
| 4353 | 4257 | while (it.next()) |param| : (param_type_i += 1) { |
| 4354 | const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) { | |
| 4258 | const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) { | |
| 4355 | 4259 | .keyword_noalias => is_comptime: { |
| 4356 | 4260 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse |
| 4357 | 4261 | return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); |
| ... | ... | @@ -4362,7 +4266,7 @@ fn fnDeclInner( |
| 4362 | 4266 | } else false; |
| 4363 | 4267 | |
| 4364 | 4268 | const is_anytype = if (param.anytype_ellipsis3) |token| blk: { |
| 4365 | switch (token_tags[token]) { | |
| 4269 | switch (tree.tokenTag(token)) { | |
| 4366 | 4270 | .keyword_anytype => break :blk true, |
| 4367 | 4271 | .ellipsis3 => break :is_var_args true, |
| 4368 | 4272 | else => unreachable, |
| ... | ... | @@ -4381,30 +4285,31 @@ fn fnDeclInner( |
| 4381 | 4285 | if (param.anytype_ellipsis3) |tok| { |
| 4382 | 4286 | return astgen.failTok(tok, "missing parameter name", .{}); |
| 4383 | 4287 | } else { |
| 4288 | const type_expr = param.type_expr.?; | |
| 4384 | 4289 | ambiguous: { |
| 4385 | if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous; | |
| 4386 | const main_token = tree.nodes.items(.main_token)[param.type_expr]; | |
| 4290 | if (tree.nodeTag(type_expr) != .identifier) break :ambiguous; | |
| 4291 | const main_token = tree.nodeMainToken(type_expr); | |
| 4387 | 4292 | const identifier_str = tree.tokenSlice(main_token); |
| 4388 | 4293 | if (isPrimitive(identifier_str)) break :ambiguous; |
| 4389 | 4294 | return astgen.failNodeNotes( |
| 4390 | param.type_expr, | |
| 4295 | type_expr, | |
| 4391 | 4296 | "missing parameter name or type", |
| 4392 | 4297 | .{}, |
| 4393 | 4298 | &[_]u32{ |
| 4394 | 4299 | try astgen.errNoteNode( |
| 4395 | param.type_expr, | |
| 4300 | type_expr, | |
| 4396 | 4301 | "if this is a name, annotate its type '{s}: T'", |
| 4397 | 4302 | .{identifier_str}, |
| 4398 | 4303 | ), |
| 4399 | 4304 | try astgen.errNoteNode( |
| 4400 | param.type_expr, | |
| 4305 | type_expr, | |
| 4401 | 4306 | "if this is a type, give it a name '<name>: {s}'", |
| 4402 | 4307 | .{identifier_str}, |
| 4403 | 4308 | ), |
| 4404 | 4309 | }, |
| 4405 | 4310 | ); |
| 4406 | 4311 | } |
| 4407 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); | |
| 4312 | return astgen.failNode(type_expr, "missing parameter name", .{}); | |
| 4408 | 4313 | } |
| 4409 | 4314 | }; |
| 4410 | 4315 | |
| ... | ... | @@ -4416,8 +4321,7 @@ fn fnDeclInner( |
| 4416 | 4321 | .param_anytype; |
| 4417 | 4322 | break :param try decl_gz.addStrTok(tag, param_name, name_token); |
| 4418 | 4323 | } else param: { |
| 4419 | const param_type_node = param.type_expr; | |
| 4420 | assert(param_type_node != 0); | |
| 4324 | const param_type_node = param.type_expr.?; | |
| 4421 | 4325 | any_param_used = false; // we will check this later |
| 4422 | 4326 | var param_gz = decl_gz.makeSubBlock(scope); |
| 4423 | 4327 | defer param_gz.unstack(); |
| ... | ... | @@ -4426,8 +4330,7 @@ fn fnDeclInner( |
| 4426 | 4330 | _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); |
| 4427 | 4331 | const param_type_is_generic = any_param_used; |
| 4428 | 4332 | |
| 4429 | const main_tokens = tree.nodes.items(.main_token); | |
| 4430 | const name_token = param.name_token orelse main_tokens[param_type_node]; | |
| 4333 | const name_token = param.name_token orelse tree.nodeMainToken(param_type_node); | |
| 4431 | 4334 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 4432 | 4335 | const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name); |
| 4433 | 4336 | assert(param_inst_expected == param_inst); |
| ... | ... | @@ -4463,7 +4366,7 @@ fn fnDeclInner( |
| 4463 | 4366 | // Parameters are in scope for the return type, so we use `params_scope` here. |
| 4464 | 4367 | // The calling convention will not have parameters in scope, so we'll just use `scope`. |
| 4465 | 4368 | // See #22263 for a proposal to solve the inconsistency here. |
| 4466 | const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal); | |
| 4369 | const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal); | |
| 4467 | 4370 | if (ret_gz.instructionsSlice().len == 0) { |
| 4468 | 4371 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 4469 | 4372 | break :inst inst; |
| ... | ... | @@ -4480,12 +4383,12 @@ fn fnDeclInner( |
| 4480 | 4383 | var cc_gz = decl_gz.makeSubBlock(scope); |
| 4481 | 4384 | defer cc_gz.unstack(); |
| 4482 | 4385 | const cc_ref: Zir.Inst.Ref = blk: { |
| 4483 | if (fn_proto.ast.callconv_expr != 0) { | |
| 4386 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 4484 | 4387 | const inst = try expr( |
| 4485 | 4388 | &cc_gz, |
| 4486 | 4389 | scope, |
| 4487 | .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, | |
| 4488 | fn_proto.ast.callconv_expr, | |
| 4390 | .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(callconv_expr, .calling_convention) } }, | |
| 4391 | callconv_expr, | |
| 4489 | 4392 | ); |
| 4490 | 4393 | if (cc_gz.instructionsSlice().len == 0) { |
| 4491 | 4394 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| ... | ... | @@ -4524,7 +4427,7 @@ fn fnDeclInner( |
| 4524 | 4427 | // Leave `astgen.src_hasher` unmodified; this will be used for hashing |
| 4525 | 4428 | // the *whole* function declaration, including its body. |
| 4526 | 4429 | var proto_hasher = astgen.src_hasher; |
| 4527 | const proto_node = tree.nodes.items(.data)[decl_node].lhs; | |
| 4430 | const proto_node = tree.nodeData(decl_node).node_and_node[0]; | |
| 4528 | 4431 | proto_hasher.update(tree.getNodeSource(proto_node)); |
| 4529 | 4432 | var proto_hash: std.zig.SrcHash = undefined; |
| 4530 | 4433 | proto_hasher.final(&proto_hash); |
| ... | ... | @@ -4594,7 +4497,6 @@ fn globalVarDecl( |
| 4594 | 4497 | var_decl: Ast.full.VarDecl, |
| 4595 | 4498 | ) InnerError!void { |
| 4596 | 4499 | const tree = astgen.tree; |
| 4597 | const token_tags = tree.tokens.items(.tag); | |
| 4598 | 4500 | |
| 4599 | 4501 | const old_hasher = astgen.src_hasher; |
| 4600 | 4502 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4602,16 +4504,16 @@ fn globalVarDecl( |
| 4602 | 4504 | astgen.src_hasher.update(tree.getNodeSource(node)); |
| 4603 | 4505 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); |
| 4604 | 4506 | |
| 4605 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; | |
| 4507 | const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var; | |
| 4606 | 4508 | const name_token = var_decl.ast.mut_token + 1; |
| 4607 | 4509 | const is_pub = var_decl.visib_token != null; |
| 4608 | 4510 | const is_export = blk: { |
| 4609 | 4511 | const maybe_export_token = var_decl.extern_export_token orelse break :blk false; |
| 4610 | break :blk token_tags[maybe_export_token] == .keyword_export; | |
| 4512 | break :blk tree.tokenTag(maybe_export_token) == .keyword_export; | |
| 4611 | 4513 | }; |
| 4612 | 4514 | const is_extern = blk: { |
| 4613 | 4515 | const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; |
| 4614 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 4516 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 4615 | 4517 | }; |
| 4616 | 4518 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 4617 | 4519 | if (!is_mutable) { |
| ... | ... | @@ -4637,10 +4539,10 @@ fn globalVarDecl( |
| 4637 | 4539 | const decl_inst = try gz.makeDeclaration(node); |
| 4638 | 4540 | wip_members.nextDecl(decl_inst); |
| 4639 | 4541 | |
| 4640 | if (var_decl.ast.init_node != 0) { | |
| 4542 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 4641 | 4543 | if (is_extern) { |
| 4642 | 4544 | return astgen.failNode( |
| 4643 | var_decl.ast.init_node, | |
| 4545 | init_node, | |
| 4644 | 4546 | "extern variables have no initializers", |
| 4645 | 4547 | .{}, |
| 4646 | 4548 | ); |
| ... | ... | @@ -4651,7 +4553,7 @@ fn globalVarDecl( |
| 4651 | 4553 | } |
| 4652 | 4554 | } |
| 4653 | 4555 | |
| 4654 | if (is_extern and var_decl.ast.type_node == 0) { | |
| 4556 | if (is_extern and var_decl.ast.type_node == .none) { | |
| 4655 | 4557 | return astgen.failNode(node, "unable to infer variable type", .{}); |
| 4656 | 4558 | } |
| 4657 | 4559 | |
| ... | ... | @@ -4668,45 +4570,45 @@ fn globalVarDecl( |
| 4668 | 4570 | }; |
| 4669 | 4571 | defer type_gz.unstack(); |
| 4670 | 4572 | |
| 4671 | if (var_decl.ast.type_node != 0) { | |
| 4672 | const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, var_decl.ast.type_node); | |
| 4573 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 4574 | const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, type_node); | |
| 4673 | 4575 | _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node); |
| 4674 | 4576 | } |
| 4675 | 4577 | |
| 4676 | 4578 | var align_gz = type_gz.makeSubBlock(scope); |
| 4677 | 4579 | defer align_gz.unstack(); |
| 4678 | 4580 | |
| 4679 | if (var_decl.ast.align_node != 0) { | |
| 4680 | const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node); | |
| 4581 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 4582 | const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_node); | |
| 4681 | 4583 | _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node); |
| 4682 | 4584 | } |
| 4683 | 4585 | |
| 4684 | 4586 | var linksection_gz = type_gz.makeSubBlock(scope); |
| 4685 | 4587 | defer linksection_gz.unstack(); |
| 4686 | 4588 | |
| 4687 | if (var_decl.ast.section_node != 0) { | |
| 4688 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node); | |
| 4589 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 4590 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node); | |
| 4689 | 4591 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node); |
| 4690 | 4592 | } |
| 4691 | 4593 | |
| 4692 | 4594 | var addrspace_gz = type_gz.makeSubBlock(scope); |
| 4693 | 4595 | defer addrspace_gz.unstack(); |
| 4694 | 4596 | |
| 4695 | if (var_decl.ast.addrspace_node != 0) { | |
| 4696 | const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space); | |
| 4697 | const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node); | |
| 4597 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 4598 | const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_node, .address_space); | |
| 4599 | const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node); | |
| 4698 | 4600 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node); |
| 4699 | 4601 | } |
| 4700 | 4602 | |
| 4701 | 4603 | var init_gz = type_gz.makeSubBlock(scope); |
| 4702 | 4604 | defer init_gz.unstack(); |
| 4703 | 4605 | |
| 4704 | if (var_decl.ast.init_node != 0) { | |
| 4606 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 4705 | 4607 | init_gz.anon_name_strategy = .parent; |
| 4706 | const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{ | |
| 4608 | const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{ | |
| 4707 | 4609 | .rl = .{ .coerced_ty = decl_inst.toRef() }, |
| 4708 | 4610 | } else .{ .rl = .none }; |
| 4709 | const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node); | |
| 4611 | const init_inst = try expr(&init_gz, &init_gz.base, init_ri, init_node); | |
| 4710 | 4612 | _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node); |
| 4711 | 4613 | } |
| 4712 | 4614 | |
| ... | ... | @@ -4740,8 +4642,7 @@ fn comptimeDecl( |
| 4740 | 4642 | node: Ast.Node.Index, |
| 4741 | 4643 | ) InnerError!void { |
| 4742 | 4644 | const tree = astgen.tree; |
| 4743 | const node_datas = tree.nodes.items(.data); | |
| 4744 | const body_node = node_datas[node].lhs; | |
| 4645 | const body_node = tree.nodeData(node).node; | |
| 4745 | 4646 | |
| 4746 | 4647 | const old_hasher = astgen.src_hasher; |
| 4747 | 4648 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4804,7 +4705,6 @@ fn usingnamespaceDecl( |
| 4804 | 4705 | node: Ast.Node.Index, |
| 4805 | 4706 | ) InnerError!void { |
| 4806 | 4707 | const tree = astgen.tree; |
| 4807 | const node_datas = tree.nodes.items(.data); | |
| 4808 | 4708 | |
| 4809 | 4709 | const old_hasher = astgen.src_hasher; |
| 4810 | 4710 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4812,13 +4712,9 @@ fn usingnamespaceDecl( |
| 4812 | 4712 | astgen.src_hasher.update(tree.getNodeSource(node)); |
| 4813 | 4713 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); |
| 4814 | 4714 | |
| 4815 | const type_expr = node_datas[node].lhs; | |
| 4816 | const is_pub = blk: { | |
| 4817 | const main_tokens = tree.nodes.items(.main_token); | |
| 4818 | const token_tags = tree.tokens.items(.tag); | |
| 4819 | const main_token = main_tokens[node]; | |
| 4820 | break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub); | |
| 4821 | }; | |
| 4715 | const type_expr = tree.nodeData(node).node; | |
| 4716 | const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub}); | |
| 4717 | ||
| 4822 | 4718 | // Up top so the ZIR instruction index marks the start range of this |
| 4823 | 4719 | // top-level declaration. |
| 4824 | 4720 | const decl_inst = try gz.makeDeclaration(node); |
| ... | ... | @@ -4872,8 +4768,7 @@ fn testDecl( |
| 4872 | 4768 | node: Ast.Node.Index, |
| 4873 | 4769 | ) InnerError!void { |
| 4874 | 4770 | const tree = astgen.tree; |
| 4875 | const node_datas = tree.nodes.items(.data); | |
| 4876 | const body_node = node_datas[node].rhs; | |
| 4771 | _, const body_node = tree.nodeData(node).opt_token_and_node; | |
| 4877 | 4772 | |
| 4878 | 4773 | const old_hasher = astgen.src_hasher; |
| 4879 | 4774 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4905,12 +4800,10 @@ fn testDecl( |
| 4905 | 4800 | |
| 4906 | 4801 | const decl_column = astgen.source_column; |
| 4907 | 4802 | |
| 4908 | const main_tokens = tree.nodes.items(.main_token); | |
| 4909 | const token_tags = tree.tokens.items(.tag); | |
| 4910 | const test_token = main_tokens[node]; | |
| 4803 | const test_token = tree.nodeMainToken(node); | |
| 4911 | 4804 | |
| 4912 | 4805 | const test_name_token = test_token + 1; |
| 4913 | const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) { | |
| 4806 | const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) { | |
| 4914 | 4807 | else => .empty, |
| 4915 | 4808 | .string_literal => name: { |
| 4916 | 4809 | const name = try astgen.strLitAsString(test_name_token); |
| ... | ... | @@ -4942,7 +4835,7 @@ fn testDecl( |
| 4942 | 4835 | .local_val => { |
| 4943 | 4836 | const local_val = s.cast(Scope.LocalVal).?; |
| 4944 | 4837 | if (local_val.name == name_str_index) { |
| 4945 | local_val.used = test_name_token; | |
| 4838 | local_val.used = .fromToken(test_name_token); | |
| 4946 | 4839 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| 4947 | 4840 | @tagName(local_val.id_cat), |
| 4948 | 4841 | }, &[_]u32{ |
| ... | ... | @@ -4956,7 +4849,7 @@ fn testDecl( |
| 4956 | 4849 | .local_ptr => { |
| 4957 | 4850 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 4958 | 4851 | if (local_ptr.name == name_str_index) { |
| 4959 | local_ptr.used = test_name_token; | |
| 4852 | local_ptr.used = .fromToken(test_name_token); | |
| 4960 | 4853 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| 4961 | 4854 | @tagName(local_ptr.id_cat), |
| 4962 | 4855 | }, &[_]u32{ |
| ... | ... | @@ -5067,7 +4960,7 @@ fn testDecl( |
| 5067 | 4960 | .src_line = decl_block.decl_line, |
| 5068 | 4961 | .src_column = decl_column, |
| 5069 | 4962 | |
| 5070 | .kind = switch (token_tags[test_name_token]) { | |
| 4963 | .kind = switch (tree.tokenTag(test_name_token)) { | |
| 5071 | 4964 | .string_literal => .@"test", |
| 5072 | 4965 | .identifier => .decltest, |
| 5073 | 4966 | else => .unnamed_test, |
| ... | ... | @@ -5091,7 +4984,7 @@ fn structDeclInner( |
| 5091 | 4984 | node: Ast.Node.Index, |
| 5092 | 4985 | container_decl: Ast.full.ContainerDecl, |
| 5093 | 4986 | layout: std.builtin.Type.ContainerLayout, |
| 5094 | backing_int_node: Ast.Node.Index, | |
| 4987 | backing_int_node: Ast.Node.OptionalIndex, | |
| 5095 | 4988 | ) InnerError!Zir.Inst.Ref { |
| 5096 | 4989 | const astgen = gz.astgen; |
| 5097 | 4990 | const gpa = astgen.gpa; |
| ... | ... | @@ -5103,7 +4996,7 @@ fn structDeclInner( |
| 5103 | 4996 | if (container_field.ast.tuple_like) break member_node; |
| 5104 | 4997 | } else break :is_tuple; |
| 5105 | 4998 | |
| 5106 | if (node == 0) { | |
| 4999 | if (node == .root) { | |
| 5107 | 5000 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); |
| 5108 | 5001 | } else { |
| 5109 | 5002 | return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node); |
| ... | ... | @@ -5112,7 +5005,7 @@ fn structDeclInner( |
| 5112 | 5005 | |
| 5113 | 5006 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5114 | 5007 | |
| 5115 | if (container_decl.ast.members.len == 0 and backing_int_node == 0) { | |
| 5008 | if (container_decl.ast.members.len == 0 and backing_int_node == .none) { | |
| 5116 | 5009 | try gz.setStruct(decl_inst, .{ |
| 5117 | 5010 | .src_node = node, |
| 5118 | 5011 | .layout = layout, |
| ... | ... | @@ -5159,11 +5052,11 @@ fn structDeclInner( |
| 5159 | 5052 | |
| 5160 | 5053 | var backing_int_body_len: usize = 0; |
| 5161 | 5054 | const backing_int_ref: Zir.Inst.Ref = blk: { |
| 5162 | if (backing_int_node != 0) { | |
| 5055 | if (backing_int_node.unwrap()) |arg| { | |
| 5163 | 5056 | if (layout != .@"packed") { |
| 5164 | return astgen.failNode(backing_int_node, "non-packed struct does not support backing integer type", .{}); | |
| 5057 | return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{}); | |
| 5165 | 5058 | } else { |
| 5166 | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node); | |
| 5059 | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg); | |
| 5167 | 5060 | if (!block_scope.isEmpty()) { |
| 5168 | 5061 | if (!block_scope.endsWithNoReturn()) { |
| 5169 | 5062 | _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref); |
| ... | ... | @@ -5208,8 +5101,8 @@ fn structDeclInner( |
| 5208 | 5101 | defer astgen.src_hasher = old_hasher; |
| 5209 | 5102 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5210 | 5103 | astgen.src_hasher.update(@tagName(layout)); |
| 5211 | if (backing_int_node != 0) { | |
| 5212 | astgen.src_hasher.update(tree.getNodeSource(backing_int_node)); | |
| 5104 | if (backing_int_node.unwrap()) |arg| { | |
| 5105 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5213 | 5106 | } |
| 5214 | 5107 | |
| 5215 | 5108 | var known_non_opv = false; |
| ... | ... | @@ -5226,18 +5119,18 @@ fn structDeclInner( |
| 5226 | 5119 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5227 | 5120 | |
| 5228 | 5121 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5229 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5122 | member.convertToNonTupleLike(astgen.tree); | |
| 5230 | 5123 | assert(!member.ast.tuple_like); |
| 5231 | 5124 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5232 | 5125 | |
| 5233 | if (member.ast.type_expr == 0) { | |
| 5126 | const type_expr = member.ast.type_expr.unwrap() orelse { | |
| 5234 | 5127 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); |
| 5235 | } | |
| 5128 | }; | |
| 5236 | 5129 | |
| 5237 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 5130 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5238 | 5131 | const have_type_body = !block_scope.isEmpty(); |
| 5239 | const have_align = member.ast.align_expr != 0; | |
| 5240 | const have_value = member.ast.value_expr != 0; | |
| 5132 | const have_align = member.ast.align_expr != .none; | |
| 5133 | const have_value = member.ast.value_expr != .none; | |
| 5241 | 5134 | const is_comptime = member.comptime_token != null; |
| 5242 | 5135 | |
| 5243 | 5136 | if (is_comptime) { |
| ... | ... | @@ -5247,9 +5140,9 @@ fn structDeclInner( |
| 5247 | 5140 | } |
| 5248 | 5141 | } else { |
| 5249 | 5142 | known_non_opv = known_non_opv or |
| 5250 | nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr); | |
| 5143 | nodeImpliesMoreThanOnePossibleValue(tree, type_expr); | |
| 5251 | 5144 | known_comptime_only = known_comptime_only or |
| 5252 | nodeImpliesComptimeOnly(tree, member.ast.type_expr); | |
| 5145 | nodeImpliesComptimeOnly(tree, type_expr); | |
| 5253 | 5146 | } |
| 5254 | 5147 | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body }); |
| 5255 | 5148 | |
| ... | ... | @@ -5267,12 +5160,12 @@ fn structDeclInner( |
| 5267 | 5160 | wip_members.appendToField(@intFromEnum(field_type)); |
| 5268 | 5161 | } |
| 5269 | 5162 | |
| 5270 | if (have_align) { | |
| 5163 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5271 | 5164 | if (layout == .@"packed") { |
| 5272 | return astgen.failNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{}); | |
| 5165 | return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{}); | |
| 5273 | 5166 | } |
| 5274 | 5167 | any_aligned_fields = true; |
| 5275 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr); | |
| 5168 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); | |
| 5276 | 5169 | if (!block_scope.endsWithNoReturn()) { |
| 5277 | 5170 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5278 | 5171 | } |
| ... | ... | @@ -5284,14 +5177,14 @@ fn structDeclInner( |
| 5284 | 5177 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5285 | 5178 | } |
| 5286 | 5179 | |
| 5287 | if (have_value) { | |
| 5180 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5288 | 5181 | any_default_inits = true; |
| 5289 | 5182 | |
| 5290 | 5183 | // The decl_inst is used as here so that we can easily reconstruct a mapping |
| 5291 | 5184 | // between it and the field type when the fields inits are analyzed. |
| 5292 | 5185 | const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } }; |
| 5293 | 5186 | |
| 5294 | const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr); | |
| 5187 | const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr); | |
| 5295 | 5188 | if (!block_scope.endsWithNoReturn()) { |
| 5296 | 5189 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); |
| 5297 | 5190 | } |
| ... | ... | @@ -5354,21 +5247,19 @@ fn tupleDecl( |
| 5354 | 5247 | node: Ast.Node.Index, |
| 5355 | 5248 | container_decl: Ast.full.ContainerDecl, |
| 5356 | 5249 | layout: std.builtin.Type.ContainerLayout, |
| 5357 | backing_int_node: Ast.Node.Index, | |
| 5250 | backing_int_node: Ast.Node.OptionalIndex, | |
| 5358 | 5251 | ) InnerError!Zir.Inst.Ref { |
| 5359 | 5252 | const astgen = gz.astgen; |
| 5360 | 5253 | const gpa = astgen.gpa; |
| 5361 | 5254 | const tree = astgen.tree; |
| 5362 | 5255 | |
| 5363 | const node_tags = tree.nodes.items(.tag); | |
| 5364 | ||
| 5365 | 5256 | switch (layout) { |
| 5366 | 5257 | .auto => {}, |
| 5367 | 5258 | .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}), |
| 5368 | 5259 | } |
| 5369 | 5260 | |
| 5370 | if (backing_int_node != 0) { | |
| 5371 | return astgen.failNode(backing_int_node, "tuple does not support backing integer type", .{}); | |
| 5261 | if (backing_int_node.unwrap()) |arg| { | |
| 5262 | return astgen.failNode(arg, "tuple does not support backing integer type", .{}); | |
| 5372 | 5263 | } |
| 5373 | 5264 | |
| 5374 | 5265 | // We will use the scratch buffer, starting here, for the field data: |
| ... | ... | @@ -5383,7 +5274,7 @@ fn tupleDecl( |
| 5383 | 5274 | |
| 5384 | 5275 | for (container_decl.ast.members) |member_node| { |
| 5385 | 5276 | const field = tree.fullContainerField(member_node) orelse { |
| 5386 | const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) { | |
| 5277 | const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) { | |
| 5387 | 5278 | .container_field_init, |
| 5388 | 5279 | .container_field_align, |
| 5389 | 5280 | .container_field, |
| ... | ... | @@ -5402,23 +5293,23 @@ fn tupleDecl( |
| 5402 | 5293 | return astgen.failTok(field.ast.main_token, "tuple field has a name", .{}); |
| 5403 | 5294 | } |
| 5404 | 5295 | |
| 5405 | if (field.ast.align_expr != 0) { | |
| 5296 | if (field.ast.align_expr != .none) { | |
| 5406 | 5297 | return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{}); |
| 5407 | 5298 | } |
| 5408 | 5299 | |
| 5409 | if (field.ast.value_expr != 0 and field.comptime_token == null) { | |
| 5300 | if (field.ast.value_expr != .none and field.comptime_token == null) { | |
| 5410 | 5301 | return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{}); |
| 5411 | 5302 | } |
| 5412 | 5303 | |
| 5413 | if (field.ast.value_expr == 0 and field.comptime_token != null) { | |
| 5304 | if (field.ast.value_expr == .none and field.comptime_token != null) { | |
| 5414 | 5305 | return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{}); |
| 5415 | 5306 | } |
| 5416 | 5307 | |
| 5417 | const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr); | |
| 5308 | const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?); | |
| 5418 | 5309 | astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref)); |
| 5419 | 5310 | |
| 5420 | if (field.ast.value_expr != 0) { | |
| 5421 | const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value); | |
| 5311 | if (field.ast.value_expr.unwrap()) |value_expr| { | |
| 5312 | const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, value_expr, .tuple_field_default_value); | |
| 5422 | 5313 | astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref)); |
| 5423 | 5314 | } else { |
| 5424 | 5315 | astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none)); |
| ... | ... | @@ -5453,7 +5344,7 @@ fn unionDeclInner( |
| 5453 | 5344 | node: Ast.Node.Index, |
| 5454 | 5345 | members: []const Ast.Node.Index, |
| 5455 | 5346 | layout: std.builtin.Type.ContainerLayout, |
| 5456 | arg_node: Ast.Node.Index, | |
| 5347 | opt_arg_node: Ast.Node.OptionalIndex, | |
| 5457 | 5348 | auto_enum_tok: ?Ast.TokenIndex, |
| 5458 | 5349 | ) InnerError!Zir.Inst.Ref { |
| 5459 | 5350 | const decl_inst = try gz.reserveInstructionIndex(); |
| ... | ... | @@ -5488,15 +5379,15 @@ fn unionDeclInner( |
| 5488 | 5379 | const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); |
| 5489 | 5380 | const field_count: u32 = @intCast(members.len - decl_count); |
| 5490 | 5381 | |
| 5491 | if (layout != .auto and (auto_enum_tok != null or arg_node != 0)) { | |
| 5492 | if (arg_node != 0) { | |
| 5382 | if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) { | |
| 5383 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5493 | 5384 | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5494 | 5385 | } else { |
| 5495 | 5386 | return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5496 | 5387 | } |
| 5497 | 5388 | } |
| 5498 | 5389 | |
| 5499 | const arg_inst: Zir.Inst.Ref = if (arg_node != 0) | |
| 5390 | const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| | |
| 5500 | 5391 | try typeExpr(&block_scope, &namespace.base, arg_node) |
| 5501 | 5392 | else |
| 5502 | 5393 | .none; |
| ... | ... | @@ -5512,7 +5403,7 @@ fn unionDeclInner( |
| 5512 | 5403 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5513 | 5404 | astgen.src_hasher.update(@tagName(layout)); |
| 5514 | 5405 | astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); |
| 5515 | if (arg_node != 0) { | |
| 5406 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5516 | 5407 | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); |
| 5517 | 5408 | } |
| 5518 | 5409 | |
| ... | ... | @@ -5522,7 +5413,7 @@ fn unionDeclInner( |
| 5522 | 5413 | .field => |field| field, |
| 5523 | 5414 | }; |
| 5524 | 5415 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); |
| 5525 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5416 | member.convertToNonTupleLike(astgen.tree); | |
| 5526 | 5417 | if (member.ast.tuple_like) { |
| 5527 | 5418 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); |
| 5528 | 5419 | } |
| ... | ... | @@ -5533,24 +5424,24 @@ fn unionDeclInner( |
| 5533 | 5424 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5534 | 5425 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5535 | 5426 | |
| 5536 | const have_type = member.ast.type_expr != 0; | |
| 5537 | const have_align = member.ast.align_expr != 0; | |
| 5538 | const have_value = member.ast.value_expr != 0; | |
| 5427 | const have_type = member.ast.type_expr != .none; | |
| 5428 | const have_align = member.ast.align_expr != .none; | |
| 5429 | const have_value = member.ast.value_expr != .none; | |
| 5539 | 5430 | const unused = false; |
| 5540 | 5431 | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); |
| 5541 | 5432 | |
| 5542 | if (have_type) { | |
| 5543 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 5433 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5434 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5544 | 5435 | wip_members.appendToField(@intFromEnum(field_type)); |
| 5545 | 5436 | } else if (arg_inst == .none and auto_enum_tok == null) { |
| 5546 | 5437 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 5547 | 5438 | } |
| 5548 | if (have_align) { | |
| 5549 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, member.ast.align_expr); | |
| 5439 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5440 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); | |
| 5550 | 5441 | wip_members.appendToField(@intFromEnum(align_inst)); |
| 5551 | 5442 | any_aligned_fields = true; |
| 5552 | 5443 | } |
| 5553 | if (have_value) { | |
| 5444 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5554 | 5445 | if (arg_inst == .none) { |
| 5555 | 5446 | return astgen.failNodeNotes( |
| 5556 | 5447 | node, |
| ... | ... | @@ -5558,7 +5449,7 @@ fn unionDeclInner( |
| 5558 | 5449 | .{}, |
| 5559 | 5450 | &[_]u32{ |
| 5560 | 5451 | try astgen.errNoteNode( |
| 5561 | member.ast.value_expr, | |
| 5452 | value_expr, | |
| 5562 | 5453 | "tag value specified here", |
| 5563 | 5454 | .{}, |
| 5564 | 5455 | ), |
| ... | ... | @@ -5572,14 +5463,14 @@ fn unionDeclInner( |
| 5572 | 5463 | .{}, |
| 5573 | 5464 | &[_]u32{ |
| 5574 | 5465 | try astgen.errNoteNode( |
| 5575 | member.ast.value_expr, | |
| 5466 | value_expr, | |
| 5576 | 5467 | "tag value specified here", |
| 5577 | 5468 | .{}, |
| 5578 | 5469 | ), |
| 5579 | 5470 | }, |
| 5580 | 5471 | ); |
| 5581 | 5472 | } |
| 5582 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | |
| 5473 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5583 | 5474 | wip_members.appendToField(@intFromEnum(tag_value)); |
| 5584 | 5475 | } |
| 5585 | 5476 | } |
| ... | ... | @@ -5631,7 +5522,6 @@ fn containerDecl( |
| 5631 | 5522 | const astgen = gz.astgen; |
| 5632 | 5523 | const gpa = astgen.gpa; |
| 5633 | 5524 | const tree = astgen.tree; |
| 5634 | const token_tags = tree.tokens.items(.tag); | |
| 5635 | 5525 | |
| 5636 | 5526 | const prev_fn_block = astgen.fn_block; |
| 5637 | 5527 | astgen.fn_block = null; |
| ... | ... | @@ -5640,9 +5530,9 @@ fn containerDecl( |
| 5640 | 5530 | // We must not create any types until Sema. Here the goal is only to generate |
| 5641 | 5531 | // ZIR for all the field types, alignments, and default value expressions. |
| 5642 | 5532 | |
| 5643 | switch (token_tags[container_decl.ast.main_token]) { | |
| 5533 | switch (tree.tokenTag(container_decl.ast.main_token)) { | |
| 5644 | 5534 | .keyword_struct => { |
| 5645 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) { | |
| 5535 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) { | |
| 5646 | 5536 | .keyword_packed => .@"packed", |
| 5647 | 5537 | .keyword_extern => .@"extern", |
| 5648 | 5538 | else => unreachable, |
| ... | ... | @@ -5652,7 +5542,7 @@ fn containerDecl( |
| 5652 | 5542 | return rvalue(gz, ri, result, node); |
| 5653 | 5543 | }, |
| 5654 | 5544 | .keyword_union => { |
| 5655 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) { | |
| 5545 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) { | |
| 5656 | 5546 | .keyword_packed => .@"packed", |
| 5657 | 5547 | .keyword_extern => .@"extern", |
| 5658 | 5548 | else => unreachable, |
| ... | ... | @@ -5670,23 +5560,23 @@ fn containerDecl( |
| 5670 | 5560 | var values: usize = 0; |
| 5671 | 5561 | var total_fields: usize = 0; |
| 5672 | 5562 | var decls: usize = 0; |
| 5673 | var nonexhaustive_node: Ast.Node.Index = 0; | |
| 5563 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; | |
| 5674 | 5564 | var nonfinal_nonexhaustive = false; |
| 5675 | 5565 | for (container_decl.ast.members) |member_node| { |
| 5676 | 5566 | var member = tree.fullContainerField(member_node) orelse { |
| 5677 | 5567 | decls += 1; |
| 5678 | 5568 | continue; |
| 5679 | 5569 | }; |
| 5680 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5570 | member.convertToNonTupleLike(astgen.tree); | |
| 5681 | 5571 | if (member.ast.tuple_like) { |
| 5682 | 5572 | return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 5683 | 5573 | } |
| 5684 | 5574 | if (member.comptime_token) |comptime_token| { |
| 5685 | 5575 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); |
| 5686 | 5576 | } |
| 5687 | if (member.ast.type_expr != 0) { | |
| 5577 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5688 | 5578 | return astgen.failNodeNotes( |
| 5689 | member.ast.type_expr, | |
| 5579 | type_expr, | |
| 5690 | 5580 | "enum fields do not have types", |
| 5691 | 5581 | .{}, |
| 5692 | 5582 | &[_]u32{ |
| ... | ... | @@ -5698,13 +5588,13 @@ fn containerDecl( |
| 5698 | 5588 | }, |
| 5699 | 5589 | ); |
| 5700 | 5590 | } |
| 5701 | if (member.ast.align_expr != 0) { | |
| 5702 | return astgen.failNode(member.ast.align_expr, "enum fields cannot be aligned", .{}); | |
| 5591 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5592 | return astgen.failNode(align_expr, "enum fields cannot be aligned", .{}); | |
| 5703 | 5593 | } |
| 5704 | 5594 | |
| 5705 | 5595 | const name_token = member.ast.main_token; |
| 5706 | 5596 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { |
| 5707 | if (nonexhaustive_node != 0) { | |
| 5597 | if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { | |
| 5708 | 5598 | return astgen.failNodeNotes( |
| 5709 | 5599 | member_node, |
| 5710 | 5600 | "redundant non-exhaustive enum mark", |
| ... | ... | @@ -5718,40 +5608,41 @@ fn containerDecl( |
| 5718 | 5608 | }, |
| 5719 | 5609 | ); |
| 5720 | 5610 | } |
| 5721 | nonexhaustive_node = member_node; | |
| 5722 | if (member.ast.value_expr != 0) { | |
| 5723 | return astgen.failNode(member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5611 | opt_nonexhaustive_node = member_node.toOptional(); | |
| 5612 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5613 | return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5724 | 5614 | } |
| 5725 | 5615 | continue; |
| 5726 | } else if (nonexhaustive_node != 0) { | |
| 5616 | } else if (opt_nonexhaustive_node != .none) { | |
| 5727 | 5617 | nonfinal_nonexhaustive = true; |
| 5728 | 5618 | } |
| 5729 | 5619 | total_fields += 1; |
| 5730 | if (member.ast.value_expr != 0) { | |
| 5731 | if (container_decl.ast.arg == 0) { | |
| 5732 | return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{}); | |
| 5620 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5621 | if (container_decl.ast.arg == .none) { | |
| 5622 | return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{}); | |
| 5733 | 5623 | } |
| 5734 | 5624 | values += 1; |
| 5735 | 5625 | } |
| 5736 | 5626 | } |
| 5737 | 5627 | if (nonfinal_nonexhaustive) { |
| 5738 | return astgen.failNode(nonexhaustive_node, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5628 | return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5739 | 5629 | } |
| 5740 | 5630 | break :blk .{ |
| 5741 | 5631 | .total_fields = total_fields, |
| 5742 | 5632 | .values = values, |
| 5743 | 5633 | .decls = decls, |
| 5744 | .nonexhaustive_node = nonexhaustive_node, | |
| 5634 | .nonexhaustive_node = opt_nonexhaustive_node, | |
| 5745 | 5635 | }; |
| 5746 | 5636 | }; |
| 5747 | if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) { | |
| 5637 | if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) { | |
| 5638 | const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?; | |
| 5748 | 5639 | return astgen.failNodeNotes( |
| 5749 | 5640 | node, |
| 5750 | 5641 | "non-exhaustive enum missing integer tag type", |
| 5751 | 5642 | .{}, |
| 5752 | 5643 | &[_]u32{ |
| 5753 | 5644 | try astgen.errNoteNode( |
| 5754 | counts.nonexhaustive_node, | |
| 5645 | nonexhaustive_node, | |
| 5755 | 5646 | "marked non-exhaustive here", |
| 5756 | 5647 | .{}, |
| 5757 | 5648 | ), |
| ... | ... | @@ -5760,7 +5651,7 @@ fn containerDecl( |
| 5760 | 5651 | } |
| 5761 | 5652 | // In this case we must generate ZIR code for the tag values, similar to |
| 5762 | 5653 | // how structs are handled above. |
| 5763 | const nonexhaustive = counts.nonexhaustive_node != 0; | |
| 5654 | const nonexhaustive = counts.nonexhaustive_node != .none; | |
| 5764 | 5655 | |
| 5765 | 5656 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5766 | 5657 | |
| ... | ... | @@ -5790,8 +5681,8 @@ fn containerDecl( |
| 5790 | 5681 | _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); |
| 5791 | 5682 | namespace.base.tag = .namespace; |
| 5792 | 5683 | |
| 5793 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) | |
| 5794 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type) | |
| 5684 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| | |
| 5685 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) | |
| 5795 | 5686 | else |
| 5796 | 5687 | .none; |
| 5797 | 5688 | |
| ... | ... | @@ -5803,31 +5694,31 @@ fn containerDecl( |
| 5803 | 5694 | const old_hasher = astgen.src_hasher; |
| 5804 | 5695 | defer astgen.src_hasher = old_hasher; |
| 5805 | 5696 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5806 | if (container_decl.ast.arg != 0) { | |
| 5807 | astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg)); | |
| 5697 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 5698 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5808 | 5699 | } |
| 5809 | 5700 | astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); |
| 5810 | 5701 | |
| 5811 | 5702 | for (container_decl.ast.members) |member_node| { |
| 5812 | if (member_node == counts.nonexhaustive_node) | |
| 5703 | if (member_node.toOptional() == counts.nonexhaustive_node) | |
| 5813 | 5704 | continue; |
| 5814 | 5705 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5815 | 5706 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5816 | 5707 | .decl => continue, |
| 5817 | 5708 | .field => |field| field, |
| 5818 | 5709 | }; |
| 5819 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5710 | member.convertToNonTupleLike(astgen.tree); | |
| 5820 | 5711 | assert(member.comptime_token == null); |
| 5821 | assert(member.ast.type_expr == 0); | |
| 5822 | assert(member.ast.align_expr == 0); | |
| 5712 | assert(member.ast.type_expr == .none); | |
| 5713 | assert(member.ast.align_expr == .none); | |
| 5823 | 5714 | |
| 5824 | 5715 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5825 | 5716 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5826 | 5717 | |
| 5827 | const have_value = member.ast.value_expr != 0; | |
| 5718 | const have_value = member.ast.value_expr != .none; | |
| 5828 | 5719 | wip_members.nextField(bits_per_field, .{have_value}); |
| 5829 | 5720 | |
| 5830 | if (have_value) { | |
| 5721 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5831 | 5722 | if (arg_inst == .none) { |
| 5832 | 5723 | return astgen.failNodeNotes( |
| 5833 | 5724 | node, |
| ... | ... | @@ -5835,14 +5726,14 @@ fn containerDecl( |
| 5835 | 5726 | .{}, |
| 5836 | 5727 | &[_]u32{ |
| 5837 | 5728 | try astgen.errNoteNode( |
| 5838 | member.ast.value_expr, | |
| 5729 | value_expr, | |
| 5839 | 5730 | "tag value specified here", |
| 5840 | 5731 | .{}, |
| 5841 | 5732 | ), |
| 5842 | 5733 | }, |
| 5843 | 5734 | ); |
| 5844 | 5735 | } |
| 5845 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | |
| 5736 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5846 | 5737 | wip_members.appendToField(@intFromEnum(tag_value_inst)); |
| 5847 | 5738 | } |
| 5848 | 5739 | } |
| ... | ... | @@ -5882,7 +5773,7 @@ fn containerDecl( |
| 5882 | 5773 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5883 | 5774 | }, |
| 5884 | 5775 | .keyword_opaque => { |
| 5885 | assert(container_decl.ast.arg == 0); | |
| 5776 | assert(container_decl.ast.arg == .none); | |
| 5886 | 5777 | |
| 5887 | 5778 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5888 | 5779 | |
| ... | ... | @@ -5953,9 +5844,7 @@ fn containerMember( |
| 5953 | 5844 | ) InnerError!ContainerMemberResult { |
| 5954 | 5845 | const astgen = gz.astgen; |
| 5955 | 5846 | const tree = astgen.tree; |
| 5956 | const node_tags = tree.nodes.items(.tag); | |
| 5957 | const node_datas = tree.nodes.items(.data); | |
| 5958 | switch (node_tags[member_node]) { | |
| 5847 | switch (tree.nodeTag(member_node)) { | |
| 5959 | 5848 | .container_field_init, |
| 5960 | 5849 | .container_field_align, |
| 5961 | 5850 | .container_field, |
| ... | ... | @@ -5969,7 +5858,11 @@ fn containerMember( |
| 5969 | 5858 | => { |
| 5970 | 5859 | var buf: [1]Ast.Node.Index = undefined; |
| 5971 | 5860 | const full = tree.fullFnProto(&buf, member_node).?; |
| 5972 | const body = if (node_tags[member_node] == .fn_decl) node_datas[member_node].rhs else 0; | |
| 5861 | ||
| 5862 | const body: Ast.Node.OptionalIndex = if (tree.nodeTag(member_node) == .fn_decl) | |
| 5863 | tree.nodeData(member_node).node_and_node[1].toOptional() | |
| 5864 | else | |
| 5865 | .none; | |
| 5973 | 5866 | |
| 5974 | 5867 | const prev_decl_index = wip_members.decl_index; |
| 5975 | 5868 | astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { |
| ... | ... | @@ -6040,12 +5933,7 @@ fn containerMember( |
| 6040 | 5933 | .@"usingnamespace", |
| 6041 | 5934 | .empty, |
| 6042 | 5935 | member_node, |
| 6043 | is_pub: { | |
| 6044 | const main_tokens = tree.nodes.items(.main_token); | |
| 6045 | const token_tags = tree.tokens.items(.tag); | |
| 6046 | const main_token = main_tokens[member_node]; | |
| 6047 | break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub; | |
| 6048 | }, | |
| 5936 | tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}), | |
| 6049 | 5937 | ); |
| 6050 | 5938 | }, |
| 6051 | 5939 | }; |
| ... | ... | @@ -6079,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi |
| 6079 | 5967 | const astgen = gz.astgen; |
| 6080 | 5968 | const gpa = astgen.gpa; |
| 6081 | 5969 | const tree = astgen.tree; |
| 6082 | const main_tokens = tree.nodes.items(.main_token); | |
| 6083 | const token_tags = tree.tokens.items(.tag); | |
| 6084 | 5970 | |
| 6085 | 5971 | const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len); |
| 6086 | 5972 | var fields_len: usize = 0; |
| ... | ... | @@ -6088,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi |
| 6088 | 5974 | var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty; |
| 6089 | 5975 | defer idents.deinit(gpa); |
| 6090 | 5976 | |
| 6091 | const error_token = main_tokens[node]; | |
| 6092 | var tok_i = error_token + 2; | |
| 6093 | while (true) : (tok_i += 1) { | |
| 6094 | switch (token_tags[tok_i]) { | |
| 5977 | const lbrace, const rbrace = tree.nodeData(node).token_and_token; | |
| 5978 | for (lbrace + 1..rbrace) |i| { | |
| 5979 | const tok_i: Ast.TokenIndex = @intCast(i); | |
| 5980 | switch (tree.tokenTag(tok_i)) { | |
| 6095 | 5981 | .doc_comment, .comma => {}, |
| 6096 | 5982 | .identifier => { |
| 6097 | 5983 | const str_index = try astgen.identAsString(tok_i); |
| ... | ... | @@ -6117,7 +6003,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi |
| 6117 | 6003 | try astgen.extra.append(gpa, @intFromEnum(str_index)); |
| 6118 | 6004 | fields_len += 1; |
| 6119 | 6005 | }, |
| 6120 | .r_brace => break, | |
| 6121 | 6006 | else => unreachable, |
| 6122 | 6007 | } |
| 6123 | 6008 | } |
| ... | ... | @@ -6143,10 +6028,10 @@ fn tryExpr( |
| 6143 | 6028 | return astgen.failNode(node, "'try' outside function scope", .{}); |
| 6144 | 6029 | }; |
| 6145 | 6030 | |
| 6146 | if (parent_gz.any_defer_node != 0) { | |
| 6031 | if (parent_gz.any_defer_node.unwrap()) |any_defer_node| { | |
| 6147 | 6032 | return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{ |
| 6148 | 6033 | try astgen.errNoteNode( |
| 6149 | parent_gz.any_defer_node, | |
| 6034 | any_defer_node, | |
| 6150 | 6035 | "defer expression here", |
| 6151 | 6036 | .{}, |
| 6152 | 6037 | ), |
| ... | ... | @@ -6209,16 +6094,16 @@ fn orelseCatchExpr( |
| 6209 | 6094 | scope: *Scope, |
| 6210 | 6095 | ri: ResultInfo, |
| 6211 | 6096 | node: Ast.Node.Index, |
| 6212 | lhs: Ast.Node.Index, | |
| 6213 | 6097 | cond_op: Zir.Inst.Tag, |
| 6214 | 6098 | unwrap_op: Zir.Inst.Tag, |
| 6215 | 6099 | unwrap_code_op: Zir.Inst.Tag, |
| 6216 | rhs: Ast.Node.Index, | |
| 6217 | 6100 | payload_token: ?Ast.TokenIndex, |
| 6218 | 6101 | ) InnerError!Zir.Inst.Ref { |
| 6219 | 6102 | const astgen = parent_gz.astgen; |
| 6220 | 6103 | const tree = astgen.tree; |
| 6221 | 6104 | |
| 6105 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 6106 | ||
| 6222 | 6107 | const need_rl = astgen.nodes_need_rl.contains(node); |
| 6223 | 6108 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| 6224 | 6109 | .rl = switch (ri.rl) { |
| ... | ... | @@ -6351,12 +6236,8 @@ fn addFieldAccess( |
| 6351 | 6236 | ) InnerError!Zir.Inst.Ref { |
| 6352 | 6237 | const astgen = gz.astgen; |
| 6353 | 6238 | const tree = astgen.tree; |
| 6354 | const main_tokens = tree.nodes.items(.main_token); | |
| 6355 | const node_datas = tree.nodes.items(.data); | |
| 6356 | 6239 | |
| 6357 | const object_node = node_datas[node].lhs; | |
| 6358 | const dot_token = main_tokens[node]; | |
| 6359 | const field_ident = dot_token + 1; | |
| 6240 | const object_node, const field_ident = tree.nodeData(node).node_and_token; | |
| 6360 | 6241 | const str_index = try astgen.identAsString(field_ident); |
| 6361 | 6242 | const lhs = try expr(gz, scope, lhs_ri, object_node); |
| 6362 | 6243 | |
| ... | ... | @@ -6376,24 +6257,25 @@ fn arrayAccess( |
| 6376 | 6257 | node: Ast.Node.Index, |
| 6377 | 6258 | ) InnerError!Zir.Inst.Ref { |
| 6378 | 6259 | const tree = gz.astgen.tree; |
| 6379 | const node_datas = tree.nodes.items(.data); | |
| 6380 | 6260 | switch (ri.rl) { |
| 6381 | 6261 | .ref, .ref_coerced_ty => { |
| 6382 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | |
| 6262 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6263 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node); | |
| 6383 | 6264 | |
| 6384 | 6265 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 6385 | 6266 | |
| 6386 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); | |
| 6267 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node); | |
| 6387 | 6268 | try emitDbgStmt(gz, cursor); |
| 6388 | 6269 | |
| 6389 | 6270 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); |
| 6390 | 6271 | }, |
| 6391 | 6272 | else => { |
| 6392 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 6273 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6274 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); | |
| 6393 | 6275 | |
| 6394 | 6276 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 6395 | 6277 | |
| 6396 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); | |
| 6278 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node); | |
| 6397 | 6279 | try emitDbgStmt(gz, cursor); |
| 6398 | 6280 | |
| 6399 | 6281 | return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node); |
| ... | ... | @@ -6410,22 +6292,22 @@ fn simpleBinOp( |
| 6410 | 6292 | ) InnerError!Zir.Inst.Ref { |
| 6411 | 6293 | const astgen = gz.astgen; |
| 6412 | 6294 | const tree = astgen.tree; |
| 6413 | const node_datas = tree.nodes.items(.data); | |
| 6295 | ||
| 6296 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6414 | 6297 | |
| 6415 | 6298 | if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) { |
| 6416 | const node_tags = tree.nodes.items(.tag); | |
| 6417 | 6299 | const str = if (op_inst_tag == .cmp_eq) "==" else "!="; |
| 6418 | if (node_tags[node_datas[node].lhs] == .string_literal or | |
| 6419 | node_tags[node_datas[node].rhs] == .string_literal) | |
| 6300 | if (tree.nodeTag(lhs_node) == .string_literal or | |
| 6301 | tree.nodeTag(rhs_node) == .string_literal) | |
| 6420 | 6302 | return astgen.failNode(node, "cannot compare strings with {s}", .{str}); |
| 6421 | 6303 | } |
| 6422 | 6304 | |
| 6423 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); | |
| 6305 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node); | |
| 6424 | 6306 | const cursor = switch (op_inst_tag) { |
| 6425 | 6307 | .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node), |
| 6426 | 6308 | else => undefined, |
| 6427 | 6309 | }; |
| 6428 | const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node); | |
| 6310 | const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node); | |
| 6429 | 6311 | |
| 6430 | 6312 | switch (op_inst_tag) { |
| 6431 | 6313 | .add, .sub, .mul, .div, .mod_rem => { |
| ... | ... | @@ -6459,16 +6341,16 @@ fn boolBinOp( |
| 6459 | 6341 | ) InnerError!Zir.Inst.Ref { |
| 6460 | 6342 | const astgen = gz.astgen; |
| 6461 | 6343 | const tree = astgen.tree; |
| 6462 | const node_datas = tree.nodes.items(.data); | |
| 6463 | 6344 | |
| 6464 | const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs); | |
| 6345 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6346 | const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node); | |
| 6465 | 6347 | const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?; |
| 6466 | 6348 | |
| 6467 | 6349 | var rhs_scope = gz.makeSubBlock(scope); |
| 6468 | 6350 | defer rhs_scope.unstack(); |
| 6469 | const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint); | |
| 6351 | const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint); | |
| 6470 | 6352 | if (!gz.refIsNoReturn(rhs)) { |
| 6471 | _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs); | |
| 6353 | _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node); | |
| 6472 | 6354 | } |
| 6473 | 6355 | try rhs_scope.setBoolBrBody(bool_br, lhs); |
| 6474 | 6356 | |
| ... | ... | @@ -6485,7 +6367,6 @@ fn ifExpr( |
| 6485 | 6367 | ) InnerError!Zir.Inst.Ref { |
| 6486 | 6368 | const astgen = parent_gz.astgen; |
| 6487 | 6369 | const tree = astgen.tree; |
| 6488 | const token_tags = tree.tokens.items(.tag); | |
| 6489 | 6370 | |
| 6490 | 6371 | const do_err_trace = astgen.fn_block != null and if_full.error_token != null; |
| 6491 | 6372 | |
| ... | ... | @@ -6508,7 +6389,7 @@ fn ifExpr( |
| 6508 | 6389 | defer block_scope.unstack(); |
| 6509 | 6390 | |
| 6510 | 6391 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 6511 | token_tags[payload_token] == .asterisk | |
| 6392 | tree.tokenTag(payload_token) == .asterisk | |
| 6512 | 6393 | else |
| 6513 | 6394 | false; |
| 6514 | 6395 | |
| ... | ... | @@ -6586,7 +6467,7 @@ fn ifExpr( |
| 6586 | 6467 | break :s &then_scope.base; |
| 6587 | 6468 | } |
| 6588 | 6469 | } else if (if_full.payload_token) |payload_token| { |
| 6589 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | |
| 6470 | const ident_token = payload_token + @intFromBool(payload_is_ref); | |
| 6590 | 6471 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 6591 | 6472 | .optional_payload_unsafe_ptr |
| 6592 | 6473 | else |
| ... | ... | @@ -6628,8 +6509,7 @@ fn ifExpr( |
| 6628 | 6509 | if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr)) |
| 6629 | 6510 | _ = try else_scope.addSaveErrRetIndex(.always); |
| 6630 | 6511 | |
| 6631 | const else_node = if_full.ast.else_expr; | |
| 6632 | if (else_node != 0) { | |
| 6512 | if (if_full.ast.else_expr.unwrap()) |else_node| { | |
| 6633 | 6513 | const sub_scope = s: { |
| 6634 | 6514 | if (if_full.error_token) |error_token| { |
| 6635 | 6515 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -6717,8 +6597,6 @@ fn whileExpr( |
| 6717 | 6597 | ) InnerError!Zir.Inst.Ref { |
| 6718 | 6598 | const astgen = parent_gz.astgen; |
| 6719 | 6599 | const tree = astgen.tree; |
| 6720 | const token_tags = tree.tokens.items(.tag); | |
| 6721 | const token_starts = tree.tokens.items(.start); | |
| 6722 | 6600 | |
| 6723 | 6601 | const need_rl = astgen.nodes_need_rl.contains(node); |
| 6724 | 6602 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| ... | ... | @@ -6755,7 +6633,7 @@ fn whileExpr( |
| 6755 | 6633 | defer cond_scope.unstack(); |
| 6756 | 6634 | |
| 6757 | 6635 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 6758 | token_tags[payload_token] == .asterisk | |
| 6636 | tree.tokenTag(payload_token) == .asterisk | |
| 6759 | 6637 | else |
| 6760 | 6638 | false; |
| 6761 | 6639 | |
| ... | ... | @@ -6841,7 +6719,6 @@ fn whileExpr( |
| 6841 | 6719 | break :s &then_scope.base; |
| 6842 | 6720 | } |
| 6843 | 6721 | } else if (while_full.payload_token) |payload_token| { |
| 6844 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | |
| 6845 | 6722 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 6846 | 6723 | .optional_payload_unsafe_ptr |
| 6847 | 6724 | else |
| ... | ... | @@ -6849,6 +6726,7 @@ fn whileExpr( |
| 6849 | 6726 | // will add this instruction to then_scope.instructions below |
| 6850 | 6727 | const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr); |
| 6851 | 6728 | opt_payload_inst = payload_inst.toOptional(); |
| 6729 | const ident_token = payload_token + @intFromBool(payload_is_ref); | |
| 6852 | 6730 | const ident_name = try astgen.identAsString(ident_token); |
| 6853 | 6731 | const ident_bytes = tree.tokenSlice(ident_token); |
| 6854 | 6732 | if (mem.eql(u8, "_", ident_bytes)) { |
| ... | ... | @@ -6903,8 +6781,8 @@ fn whileExpr( |
| 6903 | 6781 | // are no jumps to it. This happens when the last statement of a while body is noreturn |
| 6904 | 6782 | // and there are no `continue` statements. |
| 6905 | 6783 | // Tracking issue: https://github.com/ziglang/zig/issues/9185 |
| 6906 | if (while_full.ast.cont_expr != 0) { | |
| 6907 | _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr); | |
| 6784 | if (while_full.ast.cont_expr.unwrap()) |cont_expr| { | |
| 6785 | _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr); | |
| 6908 | 6786 | } |
| 6909 | 6787 | |
| 6910 | 6788 | continue_scope.instructions_top = continue_scope.instructions.items.len; |
| ... | ... | @@ -6916,7 +6794,7 @@ fn whileExpr( |
| 6916 | 6794 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 6917 | 6795 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6918 | 6796 | if (!continue_scope.endsWithNoReturn()) { |
| 6919 | astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); | |
| 6797 | astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node))); | |
| 6920 | 6798 | try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); |
| 6921 | 6799 | _ = try parent_gz.add(.{ |
| 6922 | 6800 | .tag = .extended, |
| ... | ... | @@ -6934,8 +6812,7 @@ fn whileExpr( |
| 6934 | 6812 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 6935 | 6813 | defer else_scope.unstack(); |
| 6936 | 6814 | |
| 6937 | const else_node = while_full.ast.else_expr; | |
| 6938 | if (else_node != 0) { | |
| 6815 | if (while_full.ast.else_expr.unwrap()) |else_node| { | |
| 6939 | 6816 | const sub_scope = s: { |
| 6940 | 6817 | if (while_full.error_token) |error_token| { |
| 6941 | 6818 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -7033,10 +6910,6 @@ fn forExpr( |
| 7033 | 6910 | try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{}); |
| 7034 | 6911 | } |
| 7035 | 6912 | const tree = astgen.tree; |
| 7036 | const token_tags = tree.tokens.items(.tag); | |
| 7037 | const token_starts = tree.tokens.items(.start); | |
| 7038 | const node_tags = tree.nodes.items(.tag); | |
| 7039 | const node_data = tree.nodes.items(.data); | |
| 7040 | 6913 | const gpa = astgen.gpa; |
| 7041 | 6914 | |
| 7042 | 6915 | // For counters, this is the start value; for indexables, this is the base |
| ... | ... | @@ -7066,7 +6939,7 @@ fn forExpr( |
| 7066 | 6939 | { |
| 7067 | 6940 | var capture_token = for_full.payload_token; |
| 7068 | 6941 | for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| { |
| 7069 | const capture_is_ref = token_tags[capture_token] == .asterisk; | |
| 6942 | const capture_is_ref = tree.tokenTag(capture_token) == .asterisk; | |
| 7070 | 6943 | const ident_tok = capture_token + @intFromBool(capture_is_ref); |
| 7071 | 6944 | const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_"); |
| 7072 | 6945 | |
| ... | ... | @@ -7077,16 +6950,15 @@ fn forExpr( |
| 7077 | 6950 | capture_token = ident_tok + 2; |
| 7078 | 6951 | |
| 7079 | 6952 | try emitDbgNode(parent_gz, input); |
| 7080 | if (node_tags[input] == .for_range) { | |
| 6953 | if (tree.nodeTag(input) == .for_range) { | |
| 7081 | 6954 | if (capture_is_ref) { |
| 7082 | 6955 | return astgen.failTok(ident_tok, "cannot capture reference to range", .{}); |
| 7083 | 6956 | } |
| 7084 | const start_node = node_data[input].lhs; | |
| 6957 | const start_node, const end_node = tree.nodeData(input).node_and_opt_node; | |
| 7085 | 6958 | const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node); |
| 7086 | 6959 | |
| 7087 | const end_node = node_data[input].rhs; | |
| 7088 | const end_val = if (end_node != 0) | |
| 7089 | try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs) | |
| 6960 | const end_val = if (end_node.unwrap()) |end| | |
| 6961 | try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end) | |
| 7090 | 6962 | else |
| 7091 | 6963 | .none; |
| 7092 | 6964 | |
| ... | ... | @@ -7179,7 +7051,7 @@ fn forExpr( |
| 7179 | 7051 | var capture_token = for_full.payload_token; |
| 7180 | 7052 | var capture_sub_scope: *Scope = &then_scope.base; |
| 7181 | 7053 | for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| { |
| 7182 | const capture_is_ref = token_tags[capture_token] == .asterisk; | |
| 7054 | const capture_is_ref = tree.tokenTag(capture_token) == .asterisk; | |
| 7183 | 7055 | const ident_tok = capture_token + @intFromBool(capture_is_ref); |
| 7184 | 7056 | const capture_name = tree.tokenSlice(ident_tok); |
| 7185 | 7057 | // Skip over the comma, and on to the next capture (or the ending pipe character). |
| ... | ... | @@ -7191,7 +7063,7 @@ fn forExpr( |
| 7191 | 7063 | try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture); |
| 7192 | 7064 | |
| 7193 | 7065 | const capture_inst = inst: { |
| 7194 | const is_counter = node_tags[input] == .for_range; | |
| 7066 | const is_counter = tree.nodeTag(input) == .for_range; | |
| 7195 | 7067 | |
| 7196 | 7068 | if (indexable_ref == .none) { |
| 7197 | 7069 | // Special case: the main index can be used directly. |
| ... | ... | @@ -7238,7 +7110,7 @@ fn forExpr( |
| 7238 | 7110 | |
| 7239 | 7111 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 7240 | 7112 | |
| 7241 | astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); | |
| 7113 | astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node))); | |
| 7242 | 7114 | try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); |
| 7243 | 7115 | _ = try parent_gz.add(.{ |
| 7244 | 7116 | .tag = .extended, |
| ... | ... | @@ -7255,8 +7127,7 @@ fn forExpr( |
| 7255 | 7127 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 7256 | 7128 | defer else_scope.unstack(); |
| 7257 | 7129 | |
| 7258 | const else_node = for_full.ast.else_expr; | |
| 7259 | if (else_node != 0) { | |
| 7130 | if (for_full.ast.else_expr.unwrap()) |else_node| { | |
| 7260 | 7131 | const sub_scope = &else_scope.base; |
| 7261 | 7132 | // Remove the continue block and break block so that `continue` and `break` |
| 7262 | 7133 | // control flow apply to outer loops; not this one. |
| ... | ... | @@ -7324,10 +7195,6 @@ fn switchExprErrUnion( |
| 7324 | 7195 | const astgen = parent_gz.astgen; |
| 7325 | 7196 | const gpa = astgen.gpa; |
| 7326 | 7197 | const tree = astgen.tree; |
| 7327 | const node_datas = tree.nodes.items(.data); | |
| 7328 | const node_tags = tree.nodes.items(.tag); | |
| 7329 | const main_tokens = tree.nodes.items(.main_token); | |
| 7330 | const token_tags = tree.tokens.items(.tag); | |
| 7331 | 7198 | |
| 7332 | 7199 | const if_full = switch (node_ty) { |
| 7333 | 7200 | .@"catch" => undefined, |
| ... | ... | @@ -7336,23 +7203,19 @@ fn switchExprErrUnion( |
| 7336 | 7203 | |
| 7337 | 7204 | const switch_node, const operand_node, const error_payload = switch (node_ty) { |
| 7338 | 7205 | .@"catch" => .{ |
| 7339 | node_datas[catch_or_if_node].rhs, | |
| 7340 | node_datas[catch_or_if_node].lhs, | |
| 7341 | main_tokens[catch_or_if_node] + 2, | |
| 7206 | tree.nodeData(catch_or_if_node).node_and_node[1], | |
| 7207 | tree.nodeData(catch_or_if_node).node_and_node[0], | |
| 7208 | tree.nodeMainToken(catch_or_if_node) + 2, | |
| 7342 | 7209 | }, |
| 7343 | 7210 | .@"if" => .{ |
| 7344 | if_full.ast.else_expr, | |
| 7211 | if_full.ast.else_expr.unwrap().?, | |
| 7345 | 7212 | if_full.ast.cond_expr, |
| 7346 | 7213 | if_full.error_token.?, |
| 7347 | 7214 | }, |
| 7348 | 7215 | }; |
| 7349 | assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma); | |
| 7216 | const switch_full = tree.fullSwitch(switch_node).?; | |
| 7350 | 7217 | |
| 7351 | 7218 | const do_err_trace = astgen.fn_block != null; |
| 7352 | ||
| 7353 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 7354 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 7355 | ||
| 7356 | 7219 | const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node); |
| 7357 | 7220 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| 7358 | 7221 | .rl = switch (ri.rl) { |
| ... | ... | @@ -7364,7 +7227,7 @@ fn switchExprErrUnion( |
| 7364 | 7227 | }; |
| 7365 | 7228 | |
| 7366 | 7229 | const payload_is_ref = switch (node_ty) { |
| 7367 | .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk, | |
| 7230 | .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk, | |
| 7368 | 7231 | .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty, |
| 7369 | 7232 | }; |
| 7370 | 7233 | |
| ... | ... | @@ -7376,9 +7239,9 @@ fn switchExprErrUnion( |
| 7376 | 7239 | var multi_cases_len: u32 = 0; |
| 7377 | 7240 | var inline_cases_len: u32 = 0; |
| 7378 | 7241 | var has_else = false; |
| 7379 | var else_node: Ast.Node.Index = 0; | |
| 7242 | var else_node: Ast.Node.OptionalIndex = .none; | |
| 7380 | 7243 | var else_src: ?Ast.TokenIndex = null; |
| 7381 | for (case_nodes) |case_node| { | |
| 7244 | for (switch_full.ast.cases) |case_node| { | |
| 7382 | 7245 | const case = tree.fullSwitchCase(case_node).?; |
| 7383 | 7246 | |
| 7384 | 7247 | if (case.ast.values.len == 0) { |
| ... | ... | @@ -7398,12 +7261,12 @@ fn switchExprErrUnion( |
| 7398 | 7261 | ); |
| 7399 | 7262 | } |
| 7400 | 7263 | has_else = true; |
| 7401 | else_node = case_node; | |
| 7264 | else_node = case_node.toOptional(); | |
| 7402 | 7265 | else_src = case_src; |
| 7403 | 7266 | continue; |
| 7404 | 7267 | } else if (case.ast.values.len == 1 and |
| 7405 | node_tags[case.ast.values[0]] == .identifier and | |
| 7406 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) | |
| 7268 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 7269 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")) | |
| 7407 | 7270 | { |
| 7408 | 7271 | const case_src = case.ast.arrow_token - 1; |
| 7409 | 7272 | return astgen.failTokNotes( |
| ... | ... | @@ -7421,11 +7284,11 @@ fn switchExprErrUnion( |
| 7421 | 7284 | } |
| 7422 | 7285 | |
| 7423 | 7286 | for (case.ast.values) |val| { |
| 7424 | if (node_tags[val] == .string_literal) | |
| 7287 | if (tree.nodeTag(val) == .string_literal) | |
| 7425 | 7288 | return astgen.failNode(val, "cannot switch on strings", .{}); |
| 7426 | 7289 | } |
| 7427 | 7290 | |
| 7428 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { | |
| 7291 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) { | |
| 7429 | 7292 | scalar_cases_len += 1; |
| 7430 | 7293 | } else { |
| 7431 | 7294 | multi_cases_len += 1; |
| ... | ... | @@ -7618,11 +7481,11 @@ fn switchExprErrUnion( |
| 7618 | 7481 | var multi_case_index: u32 = 0; |
| 7619 | 7482 | var scalar_case_index: u32 = 0; |
| 7620 | 7483 | var any_uses_err_capture = false; |
| 7621 | for (case_nodes) |case_node| { | |
| 7484 | for (switch_full.ast.cases) |case_node| { | |
| 7622 | 7485 | const case = tree.fullSwitchCase(case_node).?; |
| 7623 | 7486 | |
| 7624 | 7487 | const is_multi_case = case.ast.values.len > 1 or |
| 7625 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | |
| 7488 | (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range); | |
| 7626 | 7489 | |
| 7627 | 7490 | var dbg_var_name: Zir.NullTerminatedString = .empty; |
| 7628 | 7491 | var dbg_var_inst: Zir.Inst.Ref = undefined; |
| ... | ... | @@ -7640,7 +7503,7 @@ fn switchExprErrUnion( |
| 7640 | 7503 | }; |
| 7641 | 7504 | |
| 7642 | 7505 | const capture_token = case.payload_token orelse break :blk &err_scope.base; |
| 7643 | if (token_tags[capture_token] != .identifier) { | |
| 7506 | if (tree.tokenTag(capture_token) != .identifier) { | |
| 7644 | 7507 | return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{}); |
| 7645 | 7508 | } |
| 7646 | 7509 | |
| ... | ... | @@ -7676,7 +7539,7 @@ fn switchExprErrUnion( |
| 7676 | 7539 | // items |
| 7677 | 7540 | var items_len: u32 = 0; |
| 7678 | 7541 | for (case.ast.values) |item_node| { |
| 7679 | if (node_tags[item_node] == .switch_range) continue; | |
| 7542 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 7680 | 7543 | items_len += 1; |
| 7681 | 7544 | |
| 7682 | 7545 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item); |
| ... | ... | @@ -7686,11 +7549,12 @@ fn switchExprErrUnion( |
| 7686 | 7549 | // ranges |
| 7687 | 7550 | var ranges_len: u32 = 0; |
| 7688 | 7551 | for (case.ast.values) |range| { |
| 7689 | if (node_tags[range] != .switch_range) continue; | |
| 7552 | if (tree.nodeTag(range) != .switch_range) continue; | |
| 7690 | 7553 | ranges_len += 1; |
| 7691 | 7554 | |
| 7692 | const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item); | |
| 7693 | const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item); | |
| 7555 | const first_node, const last_node = tree.nodeData(range).node_and_node; | |
| 7556 | const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item); | |
| 7557 | const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item); | |
| 7694 | 7558 | try payloads.appendSlice(gpa, &[_]u32{ |
| 7695 | 7559 | @intFromEnum(first), @intFromEnum(last), |
| 7696 | 7560 | }); |
| ... | ... | @@ -7699,7 +7563,7 @@ fn switchExprErrUnion( |
| 7699 | 7563 | payloads.items[header_index] = items_len; |
| 7700 | 7564 | payloads.items[header_index + 1] = ranges_len; |
| 7701 | 7565 | break :blk header_index + 2; |
| 7702 | } else if (case_node == else_node) blk: { | |
| 7566 | } else if (case_node.toOptional() == else_node) blk: { | |
| 7703 | 7567 | payloads.items[case_table_start + 1] = header_index; |
| 7704 | 7568 | try payloads.resize(gpa, header_index + 1); // body_len |
| 7705 | 7569 | break :blk header_index; |
| ... | ... | @@ -7729,7 +7593,7 @@ fn switchExprErrUnion( |
| 7729 | 7593 | const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint); |
| 7730 | 7594 | // check capture_scope, not err_scope to avoid false positive unused error capture |
| 7731 | 7595 | try checkUsed(parent_gz, &case_scope.base, err_scope.parent); |
| 7732 | const uses_err = err_scope.used != 0 or err_scope.discarded != 0; | |
| 7596 | const uses_err = err_scope.used != .none or err_scope.discarded != .none; | |
| 7733 | 7597 | if (uses_err) { |
| 7734 | 7598 | try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef()); |
| 7735 | 7599 | any_uses_err_capture = true; |
| ... | ... | @@ -7829,10 +7693,6 @@ fn switchExpr( |
| 7829 | 7693 | const astgen = parent_gz.astgen; |
| 7830 | 7694 | const gpa = astgen.gpa; |
| 7831 | 7695 | const tree = astgen.tree; |
| 7832 | const node_datas = tree.nodes.items(.data); | |
| 7833 | const node_tags = tree.nodes.items(.tag); | |
| 7834 | const main_tokens = tree.nodes.items(.main_token); | |
| 7835 | const token_tags = tree.tokens.items(.tag); | |
| 7836 | 7696 | const operand_node = switch_full.ast.condition; |
| 7837 | 7697 | const case_nodes = switch_full.ast.cases; |
| 7838 | 7698 | |
| ... | ... | @@ -7864,17 +7724,17 @@ fn switchExpr( |
| 7864 | 7724 | var multi_cases_len: u32 = 0; |
| 7865 | 7725 | var inline_cases_len: u32 = 0; |
| 7866 | 7726 | var special_prong: Zir.SpecialProng = .none; |
| 7867 | var special_node: Ast.Node.Index = 0; | |
| 7727 | var special_node: Ast.Node.OptionalIndex = .none; | |
| 7868 | 7728 | var else_src: ?Ast.TokenIndex = null; |
| 7869 | 7729 | var underscore_src: ?Ast.TokenIndex = null; |
| 7870 | 7730 | for (case_nodes) |case_node| { |
| 7871 | 7731 | const case = tree.fullSwitchCase(case_node).?; |
| 7872 | 7732 | if (case.payload_token) |payload_token| { |
| 7873 | const ident = if (token_tags[payload_token] == .asterisk) blk: { | |
| 7733 | const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: { | |
| 7874 | 7734 | any_payload_is_ref = true; |
| 7875 | 7735 | break :blk payload_token + 1; |
| 7876 | 7736 | } else payload_token; |
| 7877 | if (token_tags[ident + 1] == .comma) { | |
| 7737 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 7878 | 7738 | any_has_tag_capture = true; |
| 7879 | 7739 | } |
| 7880 | 7740 | |
| ... | ... | @@ -7922,13 +7782,13 @@ fn switchExpr( |
| 7922 | 7782 | }, |
| 7923 | 7783 | ); |
| 7924 | 7784 | } |
| 7925 | special_node = case_node; | |
| 7785 | special_node = case_node.toOptional(); | |
| 7926 | 7786 | special_prong = .@"else"; |
| 7927 | 7787 | else_src = case_src; |
| 7928 | 7788 | continue; |
| 7929 | 7789 | } else if (case.ast.values.len == 1 and |
| 7930 | node_tags[case.ast.values[0]] == .identifier and | |
| 7931 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) | |
| 7790 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 7791 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")) | |
| 7932 | 7792 | { |
| 7933 | 7793 | const case_src = case.ast.arrow_token - 1; |
| 7934 | 7794 | if (underscore_src) |src| { |
| ... | ... | @@ -7966,18 +7826,18 @@ fn switchExpr( |
| 7966 | 7826 | if (case.inline_token != null) { |
| 7967 | 7827 | return astgen.failTok(case_src, "cannot inline '_' prong", .{}); |
| 7968 | 7828 | } |
| 7969 | special_node = case_node; | |
| 7829 | special_node = case_node.toOptional(); | |
| 7970 | 7830 | special_prong = .under; |
| 7971 | 7831 | underscore_src = case_src; |
| 7972 | 7832 | continue; |
| 7973 | 7833 | } |
| 7974 | 7834 | |
| 7975 | 7835 | for (case.ast.values) |val| { |
| 7976 | if (node_tags[val] == .string_literal) | |
| 7836 | if (tree.nodeTag(val) == .string_literal) | |
| 7977 | 7837 | return astgen.failNode(val, "cannot switch on strings", .{}); |
| 7978 | 7838 | } |
| 7979 | 7839 | |
| 7980 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { | |
| 7840 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) { | |
| 7981 | 7841 | scalar_cases_len += 1; |
| 7982 | 7842 | } else { |
| 7983 | 7843 | multi_cases_len += 1; |
| ... | ... | @@ -8066,7 +7926,7 @@ fn switchExpr( |
| 8066 | 7926 | const case = tree.fullSwitchCase(case_node).?; |
| 8067 | 7927 | |
| 8068 | 7928 | const is_multi_case = case.ast.values.len > 1 or |
| 8069 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | |
| 7929 | (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range); | |
| 8070 | 7930 | |
| 8071 | 7931 | var dbg_var_name: Zir.NullTerminatedString = .empty; |
| 8072 | 7932 | var dbg_var_inst: Zir.Inst.Ref = undefined; |
| ... | ... | @@ -8080,18 +7940,15 @@ fn switchExpr( |
| 8080 | 7940 | |
| 8081 | 7941 | const sub_scope = blk: { |
| 8082 | 7942 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 8083 | const ident = if (token_tags[payload_token] == .asterisk) | |
| 8084 | payload_token + 1 | |
| 8085 | else | |
| 8086 | payload_token; | |
| 7943 | const capture_is_ref = tree.tokenTag(payload_token) == .asterisk; | |
| 7944 | const ident = payload_token + @intFromBool(capture_is_ref); | |
| 8087 | 7945 | |
| 8088 | const is_ptr = ident != payload_token; | |
| 8089 | capture = if (is_ptr) .by_ref else .by_val; | |
| 7946 | capture = if (capture_is_ref) .by_ref else .by_val; | |
| 8090 | 7947 | |
| 8091 | 7948 | const ident_slice = tree.tokenSlice(ident); |
| 8092 | 7949 | var payload_sub_scope: *Scope = undefined; |
| 8093 | 7950 | if (mem.eql(u8, ident_slice, "_")) { |
| 8094 | if (is_ptr) { | |
| 7951 | if (capture_is_ref) { | |
| 8095 | 7952 | return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{}); |
| 8096 | 7953 | } |
| 8097 | 7954 | payload_sub_scope = &case_scope.base; |
| ... | ... | @@ -8111,7 +7968,7 @@ fn switchExpr( |
| 8111 | 7968 | payload_sub_scope = &capture_val_scope.base; |
| 8112 | 7969 | } |
| 8113 | 7970 | |
| 8114 | const tag_token = if (token_tags[ident + 1] == .comma) | |
| 7971 | const tag_token = if (tree.tokenTag(ident + 1) == .comma) | |
| 8115 | 7972 | ident + 2 |
| 8116 | 7973 | else |
| 8117 | 7974 | break :blk payload_sub_scope; |
| ... | ... | @@ -8149,7 +8006,7 @@ fn switchExpr( |
| 8149 | 8006 | // items |
| 8150 | 8007 | var items_len: u32 = 0; |
| 8151 | 8008 | for (case.ast.values) |item_node| { |
| 8152 | if (node_tags[item_node] == .switch_range) continue; | |
| 8009 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 8153 | 8010 | items_len += 1; |
| 8154 | 8011 | |
| 8155 | 8012 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item); |
| ... | ... | @@ -8159,11 +8016,12 @@ fn switchExpr( |
| 8159 | 8016 | // ranges |
| 8160 | 8017 | var ranges_len: u32 = 0; |
| 8161 | 8018 | for (case.ast.values) |range| { |
| 8162 | if (node_tags[range] != .switch_range) continue; | |
| 8019 | if (tree.nodeTag(range) != .switch_range) continue; | |
| 8163 | 8020 | ranges_len += 1; |
| 8164 | 8021 | |
| 8165 | const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item); | |
| 8166 | const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item); | |
| 8022 | const first_node, const last_node = tree.nodeData(range).node_and_node; | |
| 8023 | const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item); | |
| 8024 | const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item); | |
| 8167 | 8025 | try payloads.appendSlice(gpa, &[_]u32{ |
| 8168 | 8026 | @intFromEnum(first), @intFromEnum(last), |
| 8169 | 8027 | }); |
| ... | ... | @@ -8172,7 +8030,7 @@ fn switchExpr( |
| 8172 | 8030 | payloads.items[header_index] = items_len; |
| 8173 | 8031 | payloads.items[header_index + 1] = ranges_len; |
| 8174 | 8032 | break :blk header_index + 2; |
| 8175 | } else if (case_node == special_node) blk: { | |
| 8033 | } else if (case_node.toOptional() == special_node) blk: { | |
| 8176 | 8034 | payloads.items[case_table_start] = header_index; |
| 8177 | 8035 | try payloads.resize(gpa, header_index + 1); // body_len |
| 8178 | 8036 | break :blk header_index; |
| ... | ... | @@ -8285,17 +8143,15 @@ fn switchExpr( |
| 8285 | 8143 | fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 8286 | 8144 | const astgen = gz.astgen; |
| 8287 | 8145 | const tree = astgen.tree; |
| 8288 | const node_datas = tree.nodes.items(.data); | |
| 8289 | const node_tags = tree.nodes.items(.tag); | |
| 8290 | 8146 | |
| 8291 | 8147 | if (astgen.fn_block == null) { |
| 8292 | 8148 | return astgen.failNode(node, "'return' outside function scope", .{}); |
| 8293 | 8149 | } |
| 8294 | 8150 | |
| 8295 | if (gz.any_defer_node != 0) { | |
| 8151 | if (gz.any_defer_node.unwrap()) |any_defer_node| { | |
| 8296 | 8152 | return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{ |
| 8297 | 8153 | try astgen.errNoteNode( |
| 8298 | gz.any_defer_node, | |
| 8154 | any_defer_node, | |
| 8299 | 8155 | "defer expression here", |
| 8300 | 8156 | .{}, |
| 8301 | 8157 | ), |
| ... | ... | @@ -8313,8 +8169,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 8313 | 8169 | |
| 8314 | 8170 | const defer_outer = &astgen.fn_block.?.base; |
| 8315 | 8171 | |
| 8316 | const operand_node = node_datas[node].lhs; | |
| 8317 | if (operand_node == 0) { | |
| 8172 | const operand_node = tree.nodeData(node).opt_node.unwrap() orelse { | |
| 8318 | 8173 | // Returning a void value; skip error defers. |
| 8319 | 8174 | try genDefers(gz, defer_outer, scope, .normal_only); |
| 8320 | 8175 | |
| ... | ... | @@ -8323,12 +8178,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 8323 | 8178 | |
| 8324 | 8179 | _ = try gz.addUnNode(.ret_node, .void_value, node); |
| 8325 | 8180 | return Zir.Inst.Ref.unreachable_value; |
| 8326 | } | |
| 8181 | }; | |
| 8327 | 8182 | |
| 8328 | if (node_tags[operand_node] == .error_value) { | |
| 8183 | if (tree.nodeTag(operand_node) == .error_value) { | |
| 8329 | 8184 | // Hot path for `return error.Foo`. This bypasses result location logic as well as logic |
| 8330 | 8185 | // for detecting whether to add something to the function's inferred error set. |
| 8331 | const ident_token = node_datas[operand_node].rhs; | |
| 8186 | const ident_token = tree.nodeMainToken(operand_node) + 2; | |
| 8332 | 8187 | const err_name_str_index = try astgen.identAsString(ident_token); |
| 8333 | 8188 | const defer_counts = countDefers(defer_outer, scope); |
| 8334 | 8189 | if (!defer_counts.need_err_code) { |
| ... | ... | @@ -8459,9 +8314,8 @@ fn identifier( |
| 8459 | 8314 | ) InnerError!Zir.Inst.Ref { |
| 8460 | 8315 | const astgen = gz.astgen; |
| 8461 | 8316 | const tree = astgen.tree; |
| 8462 | const main_tokens = tree.nodes.items(.main_token); | |
| 8463 | 8317 | |
| 8464 | const ident_token = main_tokens[ident]; | |
| 8318 | const ident_token = tree.nodeMainToken(ident); | |
| 8465 | 8319 | const ident_name_raw = tree.tokenSlice(ident_token); |
| 8466 | 8320 | if (mem.eql(u8, ident_name_raw, "_")) { |
| 8467 | 8321 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); |
| ... | ... | @@ -8563,9 +8417,9 @@ fn localVarRef( |
| 8563 | 8417 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 8564 | 8418 | // references in this case. |
| 8565 | 8419 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 8566 | local_val.discarded = ident_token; | |
| 8420 | local_val.discarded = .fromToken(ident_token); | |
| 8567 | 8421 | } else { |
| 8568 | local_val.used = ident_token; | |
| 8422 | local_val.used = .fromToken(ident_token); | |
| 8569 | 8423 | } |
| 8570 | 8424 | |
| 8571 | 8425 | if (local_val.is_used_or_discarded) |ptr| ptr.* = true; |
| ... | ... | @@ -8587,9 +8441,9 @@ fn localVarRef( |
| 8587 | 8441 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 8588 | 8442 | if (local_ptr.name == name_str_index) { |
| 8589 | 8443 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 8590 | local_ptr.discarded = ident_token; | |
| 8444 | local_ptr.discarded = .fromToken(ident_token); | |
| 8591 | 8445 | } else { |
| 8592 | local_ptr.used = ident_token; | |
| 8446 | local_ptr.used = .fromToken(ident_token); | |
| 8593 | 8447 | } |
| 8594 | 8448 | |
| 8595 | 8449 | // Can't close over a runtime variable |
| ... | ... | @@ -8802,8 +8656,7 @@ fn stringLiteral( |
| 8802 | 8656 | ) InnerError!Zir.Inst.Ref { |
| 8803 | 8657 | const astgen = gz.astgen; |
| 8804 | 8658 | const tree = astgen.tree; |
| 8805 | const main_tokens = tree.nodes.items(.main_token); | |
| 8806 | const str_lit_token = main_tokens[node]; | |
| 8659 | const str_lit_token = tree.nodeMainToken(node); | |
| 8807 | 8660 | const str = try astgen.strLitAsString(str_lit_token); |
| 8808 | 8661 | const result = try gz.add(.{ |
| 8809 | 8662 | .tag = .str, |
| ... | ... | @@ -8835,8 +8688,7 @@ fn multilineStringLiteral( |
| 8835 | 8688 | fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 8836 | 8689 | const astgen = gz.astgen; |
| 8837 | 8690 | const tree = astgen.tree; |
| 8838 | const main_tokens = tree.nodes.items(.main_token); | |
| 8839 | const main_token = main_tokens[node]; | |
| 8691 | const main_token = tree.nodeMainToken(node); | |
| 8840 | 8692 | const slice = tree.tokenSlice(main_token); |
| 8841 | 8693 | |
| 8842 | 8694 | switch (std.zig.parseCharLiteral(slice)) { |
| ... | ... | @@ -8853,8 +8705,7 @@ const Sign = enum { negative, positive }; |
| 8853 | 8705 | fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { |
| 8854 | 8706 | const astgen = gz.astgen; |
| 8855 | 8707 | const tree = astgen.tree; |
| 8856 | const main_tokens = tree.nodes.items(.main_token); | |
| 8857 | const num_token = main_tokens[node]; | |
| 8708 | const num_token = tree.nodeMainToken(node); | |
| 8858 | 8709 | const bytes = tree.tokenSlice(num_token); |
| 8859 | 8710 | |
| 8860 | 8711 | const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) { |
| ... | ... | @@ -8972,16 +8823,12 @@ fn asmExpr( |
| 8972 | 8823 | ) InnerError!Zir.Inst.Ref { |
| 8973 | 8824 | const astgen = gz.astgen; |
| 8974 | 8825 | const tree = astgen.tree; |
| 8975 | const main_tokens = tree.nodes.items(.main_token); | |
| 8976 | const node_datas = tree.nodes.items(.data); | |
| 8977 | const node_tags = tree.nodes.items(.tag); | |
| 8978 | const token_tags = tree.tokens.items(.tag); | |
| 8979 | 8826 | |
| 8980 | 8827 | const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString }; |
| 8981 | const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) { | |
| 8828 | const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) { | |
| 8982 | 8829 | .string_literal => .{ |
| 8983 | 8830 | .tag = .@"asm", |
| 8984 | .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index, | |
| 8831 | .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index, | |
| 8985 | 8832 | }, |
| 8986 | 8833 | .multiline_string_literal => .{ |
| 8987 | 8834 | .tag = .@"asm", |
| ... | ... | @@ -9016,17 +8863,17 @@ fn asmExpr( |
| 9016 | 8863 | var output_type_bits: u32 = 0; |
| 9017 | 8864 | |
| 9018 | 8865 | for (full.outputs, 0..) |output_node, i| { |
| 9019 | const symbolic_name = main_tokens[output_node]; | |
| 8866 | const symbolic_name = tree.nodeMainToken(output_node); | |
| 9020 | 8867 | const name = try astgen.identAsString(symbolic_name); |
| 9021 | 8868 | const constraint_token = symbolic_name + 2; |
| 9022 | 8869 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 9023 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; | |
| 8870 | const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow; | |
| 9024 | 8871 | if (has_arrow) { |
| 9025 | 8872 | if (output_type_bits != 0) { |
| 9026 | 8873 | return astgen.failNode(output_node, "inline assembly allows up to one output value", .{}); |
| 9027 | 8874 | } |
| 9028 | 8875 | output_type_bits |= @as(u32, 1) << @intCast(i); |
| 9029 | const out_type_node = node_datas[output_node].lhs; | |
| 8876 | const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?; | |
| 9030 | 8877 | const out_type_inst = try typeExpr(gz, scope, out_type_node); |
| 9031 | 8878 | outputs[i] = .{ |
| 9032 | 8879 | .name = name, |
| ... | ... | @@ -9053,11 +8900,11 @@ fn asmExpr( |
| 9053 | 8900 | const inputs = inputs_buffer[0..full.inputs.len]; |
| 9054 | 8901 | |
| 9055 | 8902 | for (full.inputs, 0..) |input_node, i| { |
| 9056 | const symbolic_name = main_tokens[input_node]; | |
| 8903 | const symbolic_name = tree.nodeMainToken(input_node); | |
| 9057 | 8904 | const name = try astgen.identAsString(symbolic_name); |
| 9058 | 8905 | const constraint_token = symbolic_name + 2; |
| 9059 | 8906 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 9060 | const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs); | |
| 8907 | const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]); | |
| 9061 | 8908 | inputs[i] = .{ |
| 9062 | 8909 | .name = name, |
| 9063 | 8910 | .constraint = constraint, |
| ... | ... | @@ -9078,10 +8925,10 @@ fn asmExpr( |
| 9078 | 8925 | clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index); |
| 9079 | 8926 | clobber_i += 1; |
| 9080 | 8927 | tok_i += 1; |
| 9081 | switch (token_tags[tok_i]) { | |
| 8928 | switch (tree.tokenTag(tok_i)) { | |
| 9082 | 8929 | .r_paren => break :clobbers, |
| 9083 | 8930 | .comma => { |
| 9084 | if (token_tags[tok_i + 1] == .r_paren) { | |
| 8931 | if (tree.tokenTag(tok_i + 1) == .r_paren) { | |
| 9085 | 8932 | break :clobbers; |
| 9086 | 8933 | } else { |
| 9087 | 8934 | continue; |
| ... | ... | @@ -9173,9 +9020,6 @@ fn ptrCast( |
| 9173 | 9020 | ) InnerError!Zir.Inst.Ref { |
| 9174 | 9021 | const astgen = gz.astgen; |
| 9175 | 9022 | const tree = astgen.tree; |
| 9176 | const main_tokens = tree.nodes.items(.main_token); | |
| 9177 | const node_datas = tree.nodes.items(.data); | |
| 9178 | const node_tags = tree.nodes.items(.tag); | |
| 9179 | 9023 | |
| 9180 | 9024 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; |
| 9181 | 9025 | var flags: Zir.Inst.FullPtrCastFlags = .{}; |
| ... | ... | @@ -9184,23 +9028,26 @@ fn ptrCast( |
| 9184 | 9028 | // to handle `builtin_call_two`. |
| 9185 | 9029 | var node = root_node; |
| 9186 | 9030 | while (true) { |
| 9187 | switch (node_tags[node]) { | |
| 9031 | switch (tree.nodeTag(node)) { | |
| 9188 | 9032 | .builtin_call_two, .builtin_call_two_comma => {}, |
| 9189 | 9033 | .grouped_expression => { |
| 9190 | 9034 | // Handle the chaining even with redundant parentheses |
| 9191 | node = node_datas[node].lhs; | |
| 9035 | node = tree.nodeData(node).node_and_token[0]; | |
| 9192 | 9036 | continue; |
| 9193 | 9037 | }, |
| 9194 | 9038 | else => break, |
| 9195 | 9039 | } |
| 9196 | 9040 | |
| 9197 | if (node_datas[node].lhs == 0) break; // 0 args | |
| 9041 | var buf: [2]Ast.Node.Index = undefined; | |
| 9042 | const args = tree.builtinCallParams(&buf, node).?; | |
| 9043 | std.debug.assert(args.len <= 2); | |
| 9044 | ||
| 9045 | if (args.len == 0) break; // 0 args | |
| 9198 | 9046 | |
| 9199 | const builtin_token = main_tokens[node]; | |
| 9047 | const builtin_token = tree.nodeMainToken(node); | |
| 9200 | 9048 | const builtin_name = tree.tokenSlice(builtin_token); |
| 9201 | 9049 | const info = BuiltinFn.list.get(builtin_name) orelse break; |
| 9202 | if (node_datas[node].rhs == 0) { | |
| 9203 | // 1 arg | |
| 9050 | if (args.len == 1) { | |
| 9204 | 9051 | if (info.param_count != 1) break; |
| 9205 | 9052 | |
| 9206 | 9053 | switch (info.tag) { |
| ... | ... | @@ -9218,9 +9065,9 @@ fn ptrCast( |
| 9218 | 9065 | }, |
| 9219 | 9066 | } |
| 9220 | 9067 | |
| 9221 | node = node_datas[node].lhs; | |
| 9068 | node = args[0]; | |
| 9222 | 9069 | } else { |
| 9223 | // 2 args | |
| 9070 | std.debug.assert(args.len == 2); | |
| 9224 | 9071 | if (info.param_count != 2) break; |
| 9225 | 9072 | |
| 9226 | 9073 | switch (info.tag) { |
| ... | ... | @@ -9231,8 +9078,8 @@ fn ptrCast( |
| 9231 | 9078 | const flags_int: FlagsInt = @bitCast(flags); |
| 9232 | 9079 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node); |
| 9233 | 9080 | const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast"); |
| 9234 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs, .field_name); | |
| 9235 | const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs); | |
| 9081 | const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, args[0], .field_name); | |
| 9082 | const field_ptr = try expr(gz, scope, .{ .rl = .none }, args[1]); | |
| 9236 | 9083 | try emitDbgStmt(gz, cursor); |
| 9237 | 9084 | const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{ |
| 9238 | 9085 | .src_node = gz.nodeIndexToRelative(node), |
| ... | ... | @@ -9397,9 +9244,8 @@ fn builtinCall( |
| 9397 | 9244 | ) InnerError!Zir.Inst.Ref { |
| 9398 | 9245 | const astgen = gz.astgen; |
| 9399 | 9246 | const tree = astgen.tree; |
| 9400 | const main_tokens = tree.nodes.items(.main_token); | |
| 9401 | 9247 | |
| 9402 | const builtin_token = main_tokens[node]; | |
| 9248 | const builtin_token = tree.nodeMainToken(node); | |
| 9403 | 9249 | const builtin_name = tree.tokenSlice(builtin_token); |
| 9404 | 9250 | |
| 9405 | 9251 | // We handle the different builtins manually because they have different semantics depending |
| ... | ... | @@ -9440,14 +9286,13 @@ fn builtinCall( |
| 9440 | 9286 | return rvalue(gz, ri, .void_value, node); |
| 9441 | 9287 | }, |
| 9442 | 9288 | .import => { |
| 9443 | const node_tags = tree.nodes.items(.tag); | |
| 9444 | 9289 | const operand_node = params[0]; |
| 9445 | 9290 | |
| 9446 | if (node_tags[operand_node] != .string_literal) { | |
| 9291 | if (tree.nodeTag(operand_node) != .string_literal) { | |
| 9447 | 9292 | // Spec reference: https://github.com/ziglang/zig/issues/2206 |
| 9448 | 9293 | return astgen.failNode(operand_node, "@import operand must be a string literal", .{}); |
| 9449 | 9294 | } |
| 9450 | const str_lit_token = main_tokens[operand_node]; | |
| 9295 | const str_lit_token = tree.nodeMainToken(operand_node); | |
| 9451 | 9296 | const str = try astgen.strLitAsString(str_lit_token); |
| 9452 | 9297 | const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len]; |
| 9453 | 9298 | if (mem.indexOfScalar(u8, str_slice, 0) != null) { |
| ... | ... | @@ -9558,8 +9403,7 @@ fn builtinCall( |
| 9558 | 9403 | std.mem.asBytes(&astgen.source_column), |
| 9559 | 9404 | ); |
| 9560 | 9405 | |
| 9561 | const token_starts = tree.tokens.items(.start); | |
| 9562 | const node_start = token_starts[tree.firstToken(node)]; | |
| 9406 | const node_start = tree.tokenStart(tree.firstToken(node)); | |
| 9563 | 9407 | astgen.advanceSourceCursor(node_start); |
| 9564 | 9408 | const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{ |
| 9565 | 9409 | .node = gz.nodeIndexToRelative(node), |
| ... | ... | @@ -9839,7 +9683,7 @@ fn builtinCall( |
| 9839 | 9683 | .callee = callee, |
| 9840 | 9684 | .args = args, |
| 9841 | 9685 | .flags = .{ |
| 9842 | .is_nosuspend = gz.nosuspend_node != 0, | |
| 9686 | .is_nosuspend = gz.nosuspend_node != .none, | |
| 9843 | 9687 | .ensure_result_used = false, |
| 9844 | 9688 | }, |
| 9845 | 9689 | }); |
| ... | ... | @@ -10064,13 +9908,11 @@ fn negation( |
| 10064 | 9908 | ) InnerError!Zir.Inst.Ref { |
| 10065 | 9909 | const astgen = gz.astgen; |
| 10066 | 9910 | const tree = astgen.tree; |
| 10067 | const node_tags = tree.nodes.items(.tag); | |
| 10068 | const node_datas = tree.nodes.items(.data); | |
| 10069 | 9911 | |
| 10070 | 9912 | // Check for float literal as the sub-expression because we want to preserve |
| 10071 | 9913 | // its negativity rather than having it go through comptime subtraction. |
| 10072 | const operand_node = node_datas[node].lhs; | |
| 10073 | if (node_tags[operand_node] == .number_literal) { | |
| 9914 | const operand_node = tree.nodeData(node).node; | |
| 9915 | if (tree.nodeTag(operand_node) == .number_literal) { | |
| 10074 | 9916 | return numberLiteral(gz, ri, operand_node, node, .negative); |
| 10075 | 9917 | } |
| 10076 | 9918 | |
| ... | ... | @@ -10186,7 +10028,7 @@ fn shiftOp( |
| 10186 | 10028 | ) InnerError!Zir.Inst.Ref { |
| 10187 | 10029 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); |
| 10188 | 10030 | |
| 10189 | const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) { | |
| 10031 | const cursor = switch (gz.astgen.tree.nodeTag(node)) { | |
| 10190 | 10032 | .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node), |
| 10191 | 10033 | else => undefined, |
| 10192 | 10034 | }; |
| ... | ... | @@ -10194,7 +10036,7 @@ fn shiftOp( |
| 10194 | 10036 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); |
| 10195 | 10037 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); |
| 10196 | 10038 | |
| 10197 | switch (gz.astgen.tree.nodes.items(.tag)[node]) { | |
| 10039 | switch (gz.astgen.tree.nodeTag(node)) { | |
| 10198 | 10040 | .shl, .shr => try emitDbgStmt(gz, cursor), |
| 10199 | 10041 | else => undefined, |
| 10200 | 10042 | } |
| ... | ... | @@ -10270,14 +10112,14 @@ fn callExpr( |
| 10270 | 10112 | if (call.async_token != null) { |
| 10271 | 10113 | break :blk .async_kw; |
| 10272 | 10114 | } |
| 10273 | if (gz.nosuspend_node != 0) { | |
| 10115 | if (gz.nosuspend_node != .none) { | |
| 10274 | 10116 | break :blk .no_async; |
| 10275 | 10117 | } |
| 10276 | 10118 | break :blk .auto; |
| 10277 | 10119 | }; |
| 10278 | 10120 | |
| 10279 | 10121 | { |
| 10280 | astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); | |
| 10122 | astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen)); | |
| 10281 | 10123 | const line = astgen.source_line - gz.decl_line; |
| 10282 | 10124 | const column = astgen.source_column; |
| 10283 | 10125 | // Sema expects a dbg_stmt immediately before call, |
| ... | ... | @@ -10288,7 +10130,6 @@ fn callExpr( |
| 10288 | 10130 | .direct => |obj| assert(obj != .none), |
| 10289 | 10131 | .field => |field| assert(field.obj_ptr != .none), |
| 10290 | 10132 | } |
| 10291 | assert(node != 0); | |
| 10292 | 10133 | |
| 10293 | 10134 | const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); |
| 10294 | 10135 | const call_inst = call_index.toRef(); |
| ... | ... | @@ -10399,14 +10240,10 @@ fn calleeExpr( |
| 10399 | 10240 | const astgen = gz.astgen; |
| 10400 | 10241 | const tree = astgen.tree; |
| 10401 | 10242 | |
| 10402 | const tag = tree.nodes.items(.tag)[node]; | |
| 10243 | const tag = tree.nodeTag(node); | |
| 10403 | 10244 | switch (tag) { |
| 10404 | 10245 | .field_access => { |
| 10405 | const main_tokens = tree.nodes.items(.main_token); | |
| 10406 | const node_datas = tree.nodes.items(.data); | |
| 10407 | const object_node = node_datas[node].lhs; | |
| 10408 | const dot_token = main_tokens[node]; | |
| 10409 | const field_ident = dot_token + 1; | |
| 10246 | const object_node, const field_ident = tree.nodeData(node).node_and_token; | |
| 10410 | 10247 | const str_index = try astgen.identAsString(field_ident); |
| 10411 | 10248 | // Capture the object by reference so we can promote it to an |
| 10412 | 10249 | // address in Sema if needed. |
| ... | ... | @@ -10431,7 +10268,7 @@ fn calleeExpr( |
| 10431 | 10268 | // Decl literal call syntax, e.g. |
| 10432 | 10269 | // `const foo: T = .init();` |
| 10433 | 10270 | // Look up `init` in `T`, but don't try and coerce it. |
| 10434 | const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]); | |
| 10271 | const str_index = try astgen.identAsString(tree.nodeMainToken(node)); | |
| 10435 | 10272 | const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{ |
| 10436 | 10273 | .lhs = res_ty, |
| 10437 | 10274 | .field_name_start = str_index, |
| ... | ... | @@ -10503,12 +10340,9 @@ comptime { |
| 10503 | 10340 | } |
| 10504 | 10341 | |
| 10505 | 10342 | fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool { |
| 10506 | const node_tags = tree.nodes.items(.tag); | |
| 10507 | const main_tokens = tree.nodes.items(.main_token); | |
| 10508 | ||
| 10509 | switch (node_tags[node]) { | |
| 10343 | switch (tree.nodeTag(node)) { | |
| 10510 | 10344 | .number_literal => { |
| 10511 | const ident = main_tokens[node]; | |
| 10345 | const ident = tree.nodeMainToken(node); | |
| 10512 | 10346 | return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) { |
| 10513 | 10347 | .int => |number| switch (number) { |
| 10514 | 10348 | 0 => true, |
| ... | ... | @@ -10522,12 +10356,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool { |
| 10522 | 10356 | } |
| 10523 | 10357 | |
| 10524 | 10358 | fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10525 | const node_tags = tree.nodes.items(.tag); | |
| 10526 | const node_datas = tree.nodes.items(.data); | |
| 10527 | ||
| 10528 | 10359 | var node = start_node; |
| 10529 | 10360 | while (true) { |
| 10530 | switch (node_tags[node]) { | |
| 10361 | switch (tree.nodeTag(node)) { | |
| 10531 | 10362 | // These don't have the opportunity to call any runtime functions. |
| 10532 | 10363 | .error_value, |
| 10533 | 10364 | .identifier, |
| ... | ... | @@ -10535,11 +10366,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool |
| 10535 | 10366 | => return false, |
| 10536 | 10367 | |
| 10537 | 10368 | // Forward the question to the LHS sub-expression. |
| 10538 | .grouped_expression, | |
| 10539 | 10369 | .@"try", |
| 10540 | 10370 | .@"nosuspend", |
| 10371 | => node = tree.nodeData(node).node, | |
| 10372 | .grouped_expression, | |
| 10541 | 10373 | .unwrap_optional, |
| 10542 | => node = node_datas[node].lhs, | |
| 10374 | => node = tree.nodeData(node).node_and_token[0], | |
| 10543 | 10375 | |
| 10544 | 10376 | // Anything that does not eval to an error is guaranteed to pop any |
| 10545 | 10377 | // additions to the error trace, so it effectively does not append. |
| ... | ... | @@ -10549,14 +10381,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool |
| 10549 | 10381 | } |
| 10550 | 10382 | |
| 10551 | 10383 | fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError { |
| 10552 | const node_tags = tree.nodes.items(.tag); | |
| 10553 | const node_datas = tree.nodes.items(.data); | |
| 10554 | const main_tokens = tree.nodes.items(.main_token); | |
| 10555 | const token_tags = tree.tokens.items(.tag); | |
| 10556 | ||
| 10557 | 10384 | var node = start_node; |
| 10558 | 10385 | while (true) { |
| 10559 | switch (node_tags[node]) { | |
| 10386 | switch (tree.nodeTag(node)) { | |
| 10560 | 10387 | .root, |
| 10561 | 10388 | .@"usingnamespace", |
| 10562 | 10389 | .test_decl, |
| ... | ... | @@ -10719,13 +10546,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10719 | 10546 | => return .never, |
| 10720 | 10547 | |
| 10721 | 10548 | // Forward the question to the LHS sub-expression. |
| 10722 | .grouped_expression, | |
| 10723 | 10549 | .@"try", |
| 10724 | 10550 | .@"await", |
| 10725 | 10551 | .@"comptime", |
| 10726 | 10552 | .@"nosuspend", |
| 10553 | => node = tree.nodeData(node).node, | |
| 10554 | .grouped_expression, | |
| 10727 | 10555 | .unwrap_optional, |
| 10728 | => node = node_datas[node].lhs, | |
| 10556 | => node = tree.nodeData(node).node_and_token[0], | |
| 10729 | 10557 | |
| 10730 | 10558 | // LHS sub-expression may still be an error under the outer optional or error union |
| 10731 | 10559 | .@"catch", |
| ... | ... | @@ -10737,8 +10565,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10737 | 10565 | .block, |
| 10738 | 10566 | .block_semicolon, |
| 10739 | 10567 | => { |
| 10740 | const lbrace = main_tokens[node]; | |
| 10741 | if (token_tags[lbrace - 1] == .colon) { | |
| 10568 | const lbrace = tree.nodeMainToken(node); | |
| 10569 | if (tree.tokenTag(lbrace - 1) == .colon) { | |
| 10742 | 10570 | // Labeled blocks may need a memory location to forward |
| 10743 | 10571 | // to their break statements. |
| 10744 | 10572 | return .maybe; |
| ... | ... | @@ -10752,7 +10580,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10752 | 10580 | .builtin_call_two, |
| 10753 | 10581 | .builtin_call_two_comma, |
| 10754 | 10582 | => { |
| 10755 | const builtin_token = main_tokens[node]; | |
| 10583 | const builtin_token = tree.nodeMainToken(node); | |
| 10756 | 10584 | const builtin_name = tree.tokenSlice(builtin_token); |
| 10757 | 10585 | // If the builtin is an invalid name, we don't cause an error here; instead |
| 10758 | 10586 | // let it pass, and the error will be "invalid builtin function" later. |
| ... | ... | @@ -10766,12 +10594,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10766 | 10594 | /// Returns `true` if it is known the type expression has more than one possible value; |
| 10767 | 10595 | /// `false` otherwise. |
| 10768 | 10596 | fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10769 | const node_tags = tree.nodes.items(.tag); | |
| 10770 | const node_datas = tree.nodes.items(.data); | |
| 10771 | ||
| 10772 | 10597 | var node = start_node; |
| 10773 | 10598 | while (true) { |
| 10774 | switch (node_tags[node]) { | |
| 10599 | switch (tree.nodeTag(node)) { | |
| 10775 | 10600 | .root, |
| 10776 | 10601 | .@"usingnamespace", |
| 10777 | 10602 | .test_decl, |
| ... | ... | @@ -10934,13 +10759,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10934 | 10759 | => return false, |
| 10935 | 10760 | |
| 10936 | 10761 | // Forward the question to the LHS sub-expression. |
| 10937 | .grouped_expression, | |
| 10938 | 10762 | .@"try", |
| 10939 | 10763 | .@"await", |
| 10940 | 10764 | .@"comptime", |
| 10941 | 10765 | .@"nosuspend", |
| 10766 | => node = tree.nodeData(node).node, | |
| 10767 | .grouped_expression, | |
| 10942 | 10768 | .unwrap_optional, |
| 10943 | => node = node_datas[node].lhs, | |
| 10769 | => node = tree.nodeData(node).node_and_token[0], | |
| 10944 | 10770 | |
| 10945 | 10771 | .ptr_type_aligned, |
| 10946 | 10772 | .ptr_type_sentinel, |
| ... | ... | @@ -10952,8 +10778,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10952 | 10778 | => return true, |
| 10953 | 10779 | |
| 10954 | 10780 | .identifier => { |
| 10955 | const main_tokens = tree.nodes.items(.main_token); | |
| 10956 | const ident_bytes = tree.tokenSlice(main_tokens[node]); | |
| 10781 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 10957 | 10782 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 10958 | 10783 | .anyerror_type, |
| 10959 | 10784 | .anyframe_type, |
| ... | ... | @@ -11013,12 +10838,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 11013 | 10838 | /// Returns `true` if it is known the expression is a type that cannot be used at runtime; |
| 11014 | 10839 | /// `false` otherwise. |
| 11015 | 10840 | fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 11016 | const node_tags = tree.nodes.items(.tag); | |
| 11017 | const node_datas = tree.nodes.items(.data); | |
| 11018 | ||
| 11019 | 10841 | var node = start_node; |
| 11020 | 10842 | while (true) { |
| 11021 | switch (node_tags[node]) { | |
| 10843 | switch (tree.nodeTag(node)) { | |
| 11022 | 10844 | .root, |
| 11023 | 10845 | .@"usingnamespace", |
| 11024 | 10846 | .test_decl, |
| ... | ... | @@ -11190,17 +11012,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 11190 | 11012 | => return true, |
| 11191 | 11013 | |
| 11192 | 11014 | // Forward the question to the LHS sub-expression. |
| 11193 | .grouped_expression, | |
| 11194 | 11015 | .@"try", |
| 11195 | 11016 | .@"await", |
| 11196 | 11017 | .@"comptime", |
| 11197 | 11018 | .@"nosuspend", |
| 11019 | => node = tree.nodeData(node).node, | |
| 11020 | .grouped_expression, | |
| 11198 | 11021 | .unwrap_optional, |
| 11199 | => node = node_datas[node].lhs, | |
| 11022 | => node = tree.nodeData(node).node_and_token[0], | |
| 11200 | 11023 | |
| 11201 | 11024 | .identifier => { |
| 11202 | const main_tokens = tree.nodes.items(.main_token); | |
| 11203 | const ident_bytes = tree.tokenSlice(main_tokens[node]); | |
| 11025 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 11204 | 11026 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 11205 | 11027 | .anyerror_type, |
| 11206 | 11028 | .anyframe_type, |
| ... | ... | @@ -11259,8 +11081,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 11259 | 11081 | |
| 11260 | 11082 | /// Returns `true` if the node uses `gz.anon_name_strategy`. |
| 11261 | 11083 | fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 11262 | const node_tags = tree.nodes.items(.tag); | |
| 11263 | switch (node_tags[node]) { | |
| 11084 | switch (tree.nodeTag(node)) { | |
| 11264 | 11085 | .container_decl, |
| 11265 | 11086 | .container_decl_trailing, |
| 11266 | 11087 | .container_decl_two, |
| ... | ... | @@ -11275,7 +11096,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 11275 | 11096 | .tagged_union_enum_tag_trailing, |
| 11276 | 11097 | => return true, |
| 11277 | 11098 | .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => { |
| 11278 | const builtin_token = tree.nodes.items(.main_token)[node]; | |
| 11099 | const builtin_token = tree.nodeMainToken(node); | |
| 11279 | 11100 | const builtin_name = tree.tokenSlice(builtin_token); |
| 11280 | 11101 | return std.mem.eql(u8, builtin_name, "@Type"); |
| 11281 | 11102 | }, |
| ... | ... | @@ -11508,8 +11329,7 @@ fn rvalueInner( |
| 11508 | 11329 | /// See also `appendIdentStr` and `parseStrLit`. |
| 11509 | 11330 | fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 { |
| 11510 | 11331 | const tree = astgen.tree; |
| 11511 | const token_tags = tree.tokens.items(.tag); | |
| 11512 | assert(token_tags[token] == .identifier); | |
| 11332 | assert(tree.tokenTag(token) == .identifier); | |
| 11513 | 11333 | const ident_name = tree.tokenSlice(token); |
| 11514 | 11334 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 11515 | 11335 | return ident_name; |
| ... | ... | @@ -11535,8 +11355,7 @@ fn appendIdentStr( |
| 11535 | 11355 | buf: *ArrayListUnmanaged(u8), |
| 11536 | 11356 | ) InnerError!void { |
| 11537 | 11357 | const tree = astgen.tree; |
| 11538 | const token_tags = tree.tokens.items(.tag); | |
| 11539 | assert(token_tags[token] == .identifier); | |
| 11358 | assert(tree.tokenTag(token) == .identifier); | |
| 11540 | 11359 | const ident_name = tree.tokenSlice(token); |
| 11541 | 11360 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 11542 | 11361 | return buf.appendSlice(astgen.gpa, ident_name); |
| ... | ... | @@ -11625,8 +11444,8 @@ fn appendErrorNodeNotes( |
| 11625 | 11444 | } else 0; |
| 11626 | 11445 | try astgen.compile_errors.append(astgen.gpa, .{ |
| 11627 | 11446 | .msg = msg, |
| 11628 | .node = node, | |
| 11629 | .token = 0, | |
| 11447 | .node = node.toOptional(), | |
| 11448 | .token = .none, | |
| 11630 | 11449 | .byte_offset = 0, |
| 11631 | 11450 | .notes = notes_index, |
| 11632 | 11451 | }); |
| ... | ... | @@ -11717,8 +11536,8 @@ fn appendErrorTokNotesOff( |
| 11717 | 11536 | } else 0; |
| 11718 | 11537 | try astgen.compile_errors.append(gpa, .{ |
| 11719 | 11538 | .msg = msg, |
| 11720 | .node = 0, | |
| 11721 | .token = token, | |
| 11539 | .node = .none, | |
| 11540 | .token = .fromToken(token), | |
| 11722 | 11541 | .byte_offset = byte_offset, |
| 11723 | 11542 | .notes = notes_index, |
| 11724 | 11543 | }); |
| ... | ... | @@ -11746,8 +11565,8 @@ fn errNoteTokOff( |
| 11746 | 11565 | try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); |
| 11747 | 11566 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 11748 | 11567 | .msg = msg, |
| 11749 | .node = 0, | |
| 11750 | .token = token, | |
| 11568 | .node = .none, | |
| 11569 | .token = .fromToken(token), | |
| 11751 | 11570 | .byte_offset = byte_offset, |
| 11752 | 11571 | .notes = 0, |
| 11753 | 11572 | }); |
| ... | ... | @@ -11765,8 +11584,8 @@ fn errNoteNode( |
| 11765 | 11584 | try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); |
| 11766 | 11585 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 11767 | 11586 | .msg = msg, |
| 11768 | .node = node, | |
| 11769 | .token = 0, | |
| 11587 | .node = node.toOptional(), | |
| 11588 | .token = .none, | |
| 11770 | 11589 | .byte_offset = 0, |
| 11771 | 11590 | .notes = 0, |
| 11772 | 11591 | }); |
| ... | ... | @@ -11832,10 +11651,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice { |
| 11832 | 11651 | |
| 11833 | 11652 | fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice { |
| 11834 | 11653 | const tree = astgen.tree; |
| 11835 | const node_datas = tree.nodes.items(.data); | |
| 11836 | 11654 | |
| 11837 | const start = node_datas[node].lhs; | |
| 11838 | const end = node_datas[node].rhs; | |
| 11655 | const start, const end = tree.nodeData(node).token_and_token; | |
| 11839 | 11656 | |
| 11840 | 11657 | const gpa = astgen.gpa; |
| 11841 | 11658 | const string_bytes = &astgen.string_bytes; |
| ... | ... | @@ -11930,11 +11747,11 @@ const Scope = struct { |
| 11930 | 11747 | /// Source location of the corresponding variable declaration. |
| 11931 | 11748 | token_src: Ast.TokenIndex, |
| 11932 | 11749 | /// Track the first identifier where it is referenced. |
| 11933 | /// 0 means never referenced. | |
| 11934 | used: Ast.TokenIndex = 0, | |
| 11750 | /// .none means never referenced. | |
| 11751 | used: Ast.OptionalTokenIndex = .none, | |
| 11935 | 11752 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 11936 | /// 0 means never discarded. | |
| 11937 | discarded: Ast.TokenIndex = 0, | |
| 11753 | /// .none means never discarded. | |
| 11754 | discarded: Ast.OptionalTokenIndex = .none, | |
| 11938 | 11755 | is_used_or_discarded: ?*bool = null, |
| 11939 | 11756 | /// String table index. |
| 11940 | 11757 | name: Zir.NullTerminatedString, |
| ... | ... | @@ -11954,11 +11771,11 @@ const Scope = struct { |
| 11954 | 11771 | /// Source location of the corresponding variable declaration. |
| 11955 | 11772 | token_src: Ast.TokenIndex, |
| 11956 | 11773 | /// Track the first identifier where it is referenced. |
| 11957 | /// 0 means never referenced. | |
| 11958 | used: Ast.TokenIndex = 0, | |
| 11774 | /// .none means never referenced. | |
| 11775 | used: Ast.OptionalTokenIndex = .none, | |
| 11959 | 11776 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 11960 | /// 0 means never discarded. | |
| 11961 | discarded: Ast.TokenIndex = 0, | |
| 11777 | /// .none means never discarded. | |
| 11778 | discarded: Ast.OptionalTokenIndex = .none, | |
| 11962 | 11779 | /// Whether this value is used as an lvalue after initialization. |
| 11963 | 11780 | /// If not, we know it can be `const`, so will emit a compile error if it is `var`. |
| 11964 | 11781 | used_as_lvalue: bool = false, |
| ... | ... | @@ -12053,12 +11870,12 @@ const GenZir = struct { |
| 12053 | 11870 | break_result_info: AstGen.ResultInfo = undefined, |
| 12054 | 11871 | continue_result_info: AstGen.ResultInfo = undefined, |
| 12055 | 11872 | |
| 12056 | suspend_node: Ast.Node.Index = 0, | |
| 12057 | nosuspend_node: Ast.Node.Index = 0, | |
| 11873 | suspend_node: Ast.Node.OptionalIndex = .none, | |
| 11874 | nosuspend_node: Ast.Node.OptionalIndex = .none, | |
| 12058 | 11875 | /// Set if this GenZir is a defer. |
| 12059 | cur_defer_node: Ast.Node.Index = 0, | |
| 11876 | cur_defer_node: Ast.Node.OptionalIndex = .none, | |
| 12060 | 11877 | // Set if this GenZir is a defer or it is inside a defer. |
| 12061 | any_defer_node: Ast.Node.Index = 0, | |
| 11878 | any_defer_node: Ast.Node.OptionalIndex = .none, | |
| 12062 | 11879 | |
| 12063 | 11880 | const unstacked_top = std.math.maxInt(usize); |
| 12064 | 11881 | /// Call unstack before adding any new instructions to containing GenZir. |
| ... | ... | @@ -12139,12 +11956,12 @@ const GenZir = struct { |
| 12139 | 11956 | return false; |
| 12140 | 11957 | } |
| 12141 | 11958 | |
| 12142 | fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 { | |
| 12143 | return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index)); | |
| 11959 | fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset { | |
| 11960 | return gz.decl_node_index.toOffset(node_index); | |
| 12144 | 11961 | } |
| 12145 | 11962 | |
| 12146 | fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 { | |
| 12147 | return token - gz.srcToken(); | |
| 11963 | fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset { | |
| 11964 | return .init(gz.srcToken(), token); | |
| 12148 | 11965 | } |
| 12149 | 11966 | |
| 12150 | 11967 | fn srcToken(gz: GenZir) Ast.TokenIndex { |
| ... | ... | @@ -12297,7 +12114,7 @@ const GenZir = struct { |
| 12297 | 12114 | proto_hash: std.zig.SrcHash, |
| 12298 | 12115 | }, |
| 12299 | 12116 | ) !Zir.Inst.Ref { |
| 12300 | assert(args.src_node != 0); | |
| 12117 | assert(args.src_node != .root); | |
| 12301 | 12118 | const astgen = gz.astgen; |
| 12302 | 12119 | const gpa = astgen.gpa; |
| 12303 | 12120 | const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref; |
| ... | ... | @@ -12329,13 +12146,13 @@ const GenZir = struct { |
| 12329 | 12146 | var src_locs_and_hash_buffer: [7]u32 = undefined; |
| 12330 | 12147 | const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: { |
| 12331 | 12148 | const tree = astgen.tree; |
| 12332 | const node_tags = tree.nodes.items(.tag); | |
| 12333 | const node_datas = tree.nodes.items(.data); | |
| 12334 | const token_starts = tree.tokens.items(.start); | |
| 12335 | 12149 | const fn_decl = args.src_node; |
| 12336 | assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl); | |
| 12337 | const block = node_datas[fn_decl].rhs; | |
| 12338 | const rbrace_start = token_starts[tree.lastToken(block)]; | |
| 12150 | const block = switch (tree.nodeTag(fn_decl)) { | |
| 12151 | .fn_decl => tree.nodeData(fn_decl).node_and_node[1], | |
| 12152 | .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1], | |
| 12153 | else => unreachable, | |
| 12154 | }; | |
| 12155 | const rbrace_start = tree.tokenStart(tree.lastToken(block)); | |
| 12339 | 12156 | astgen.advanceSourceCursor(rbrace_start); |
| 12340 | 12157 | const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line); |
| 12341 | 12158 | const rbrace_column: u32 = @intCast(astgen.source_column); |
| ... | ... | @@ -12742,7 +12559,7 @@ const GenZir = struct { |
| 12742 | 12559 | .data = .{ .extended = .{ |
| 12743 | 12560 | .opcode = opcode, |
| 12744 | 12561 | .small = small, |
| 12745 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | |
| 12562 | .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))), | |
| 12746 | 12563 | } }, |
| 12747 | 12564 | }); |
| 12748 | 12565 | gz.instructions.appendAssumeCapacity(new_index); |
| ... | ... | @@ -12931,9 +12748,9 @@ const GenZir = struct { |
| 12931 | 12748 | .operand = operand, |
| 12932 | 12749 | .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{ |
| 12933 | 12750 | .operand_src_node = if (operand_src_node) |src_node| |
| 12934 | gz.nodeIndexToRelative(src_node) | |
| 12751 | gz.nodeIndexToRelative(src_node).toOptional() | |
| 12935 | 12752 | else |
| 12936 | Zir.Inst.Break.no_src_node, | |
| 12753 | .none, | |
| 12937 | 12754 | .block_inst = block_inst, |
| 12938 | 12755 | }), |
| 12939 | 12756 | } }, |
| ... | ... | @@ -13022,7 +12839,7 @@ const GenZir = struct { |
| 13022 | 12839 | .data = .{ .extended = .{ |
| 13023 | 12840 | .opcode = opcode, |
| 13024 | 12841 | .small = undefined, |
| 13025 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | |
| 12842 | .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))), | |
| 13026 | 12843 | } }, |
| 13027 | 12844 | }); |
| 13028 | 12845 | } |
| ... | ... | @@ -13202,8 +13019,8 @@ const GenZir = struct { |
| 13202 | 13019 | const astgen = gz.astgen; |
| 13203 | 13020 | const gpa = astgen.gpa; |
| 13204 | 13021 | |
| 13205 | // Node 0 is valid for the root `struct_decl` of a file! | |
| 13206 | assert(args.src_node != 0 or gz.parent.tag == .top); | |
| 13022 | // Node .root is valid for the root `struct_decl` of a file! | |
| 13023 | assert(args.src_node != .root or gz.parent.tag == .top); | |
| 13207 | 13024 | |
| 13208 | 13025 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13209 | 13026 | |
| ... | ... | @@ -13263,7 +13080,7 @@ const GenZir = struct { |
| 13263 | 13080 | const astgen = gz.astgen; |
| 13264 | 13081 | const gpa = astgen.gpa; |
| 13265 | 13082 | |
| 13266 | assert(args.src_node != 0); | |
| 13083 | assert(args.src_node != .root); | |
| 13267 | 13084 | |
| 13268 | 13085 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13269 | 13086 | |
| ... | ... | @@ -13325,7 +13142,7 @@ const GenZir = struct { |
| 13325 | 13142 | const astgen = gz.astgen; |
| 13326 | 13143 | const gpa = astgen.gpa; |
| 13327 | 13144 | |
| 13328 | assert(args.src_node != 0); | |
| 13145 | assert(args.src_node != .root); | |
| 13329 | 13146 | |
| 13330 | 13147 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13331 | 13148 | |
| ... | ... | @@ -13380,7 +13197,7 @@ const GenZir = struct { |
| 13380 | 13197 | const astgen = gz.astgen; |
| 13381 | 13198 | const gpa = astgen.gpa; |
| 13382 | 13199 | |
| 13383 | assert(args.src_node != 0); | |
| 13200 | assert(args.src_node != .root); | |
| 13384 | 13201 | |
| 13385 | 13202 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2); |
| 13386 | 13203 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| ... | ... | @@ -13574,9 +13391,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo |
| 13574 | 13391 | if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column }; |
| 13575 | 13392 | |
| 13576 | 13393 | const tree = gz.astgen.tree; |
| 13577 | const token_starts = tree.tokens.items(.start); | |
| 13578 | const main_tokens = tree.nodes.items(.main_token); | |
| 13579 | const node_start = token_starts[main_tokens[node]]; | |
| 13394 | const node_start = tree.tokenStart(tree.nodeMainToken(node)); | |
| 13580 | 13395 | gz.astgen.advanceSourceCursor(node_start); |
| 13581 | 13396 | |
| 13582 | 13397 | return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column }; |
| ... | ... | @@ -13585,8 +13400,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo |
| 13585 | 13400 | /// Advances the source cursor to the beginning of `node`. |
| 13586 | 13401 | fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void { |
| 13587 | 13402 | const tree = astgen.tree; |
| 13588 | const token_starts = tree.tokens.items(.start); | |
| 13589 | const node_start = token_starts[tree.firstToken(node)]; | |
| 13403 | const node_start = tree.tokenStart(tree.firstToken(node)); | |
| 13590 | 13404 | astgen.advanceSourceCursor(node_start); |
| 13591 | 13405 | } |
| 13592 | 13406 | |
| ... | ... | @@ -13641,9 +13455,6 @@ fn scanContainer( |
| 13641 | 13455 | ) !u32 { |
| 13642 | 13456 | const gpa = astgen.gpa; |
| 13643 | 13457 | const tree = astgen.tree; |
| 13644 | const node_tags = tree.nodes.items(.tag); | |
| 13645 | const main_tokens = tree.nodes.items(.main_token); | |
| 13646 | const token_tags = tree.tokens.items(.tag); | |
| 13647 | 13458 | |
| 13648 | 13459 | var any_invalid_declarations = false; |
| 13649 | 13460 | |
| ... | ... | @@ -13673,7 +13484,7 @@ fn scanContainer( |
| 13673 | 13484 | var decl_count: u32 = 0; |
| 13674 | 13485 | for (members) |member_node| { |
| 13675 | 13486 | const Kind = enum { decl, field }; |
| 13676 | const kind: Kind, const name_token = switch (node_tags[member_node]) { | |
| 13487 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { | |
| 13677 | 13488 | .container_field_init, |
| 13678 | 13489 | .container_field_align, |
| 13679 | 13490 | .container_field, |
| ... | ... | @@ -13681,7 +13492,7 @@ fn scanContainer( |
| 13681 | 13492 | var full = tree.fullContainerField(member_node).?; |
| 13682 | 13493 | switch (container_kind) { |
| 13683 | 13494 | .@"struct", .@"opaque" => {}, |
| 13684 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes), | |
| 13495 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), | |
| 13685 | 13496 | } |
| 13686 | 13497 | if (full.ast.tuple_like) continue; |
| 13687 | 13498 | break :blk .{ .field, full.ast.main_token }; |
| ... | ... | @@ -13693,7 +13504,7 @@ fn scanContainer( |
| 13693 | 13504 | .aligned_var_decl, |
| 13694 | 13505 | => blk: { |
| 13695 | 13506 | decl_count += 1; |
| 13696 | break :blk .{ .decl, main_tokens[member_node] + 1 }; | |
| 13507 | break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 }; | |
| 13697 | 13508 | }, |
| 13698 | 13509 | |
| 13699 | 13510 | .fn_proto_simple, |
| ... | ... | @@ -13703,8 +13514,8 @@ fn scanContainer( |
| 13703 | 13514 | .fn_decl, |
| 13704 | 13515 | => blk: { |
| 13705 | 13516 | decl_count += 1; |
| 13706 | const ident = main_tokens[member_node] + 1; | |
| 13707 | if (token_tags[ident] != .identifier) { | |
| 13517 | const ident = tree.nodeMainToken(member_node) + 1; | |
| 13518 | if (tree.tokenTag(ident) != .identifier) { | |
| 13708 | 13519 | try astgen.appendErrorNode(member_node, "missing function name", .{}); |
| 13709 | 13520 | any_invalid_declarations = true; |
| 13710 | 13521 | continue; |
| ... | ... | @@ -13721,12 +13532,12 @@ fn scanContainer( |
| 13721 | 13532 | decl_count += 1; |
| 13722 | 13533 | // We don't want shadowing detection here, and test names work a bit differently, so |
| 13723 | 13534 | // we must do the redeclaration detection ourselves. |
| 13724 | const test_name_token = main_tokens[member_node] + 1; | |
| 13535 | const test_name_token = tree.nodeMainToken(member_node) + 1; | |
| 13725 | 13536 | const new_ent: NameEntry = .{ |
| 13726 | 13537 | .tok = test_name_token, |
| 13727 | 13538 | .next = null, |
| 13728 | 13539 | }; |
| 13729 | switch (token_tags[test_name_token]) { | |
| 13540 | switch (tree.tokenTag(test_name_token)) { | |
| 13730 | 13541 | else => {}, // unnamed test |
| 13731 | 13542 | .string_literal => { |
| 13732 | 13543 | const name = try astgen.strLitAsString(test_name_token); |
| ... | ... | @@ -14328,3 +14139,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) ! |
| 14328 | 14139 | } |
| 14329 | 14140 | return refs.items; |
| 14330 | 14141 | } |
| 14142 | ||
| 14143 | test { | |
| 14144 | _ = &generate; | |
| 14145 | } |
lib/std/zig/AstRlAnnotate.zig+173-164| ... | ... | @@ -92,27 +92,26 @@ fn containerDecl( |
| 92 | 92 | full: Ast.full.ContainerDecl, |
| 93 | 93 | ) !void { |
| 94 | 94 | const tree = astrl.tree; |
| 95 | const token_tags = tree.tokens.items(.tag); | |
| 96 | switch (token_tags[full.ast.main_token]) { | |
| 95 | switch (tree.tokenTag(full.ast.main_token)) { | |
| 97 | 96 | .keyword_struct => { |
| 98 | if (full.ast.arg != 0) { | |
| 99 | _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only); | |
| 97 | if (full.ast.arg.unwrap()) |arg| { | |
| 98 | _ = try astrl.expr(arg, block, ResultInfo.type_only); | |
| 100 | 99 | } |
| 101 | 100 | for (full.ast.members) |member_node| { |
| 102 | 101 | _ = try astrl.expr(member_node, block, ResultInfo.none); |
| 103 | 102 | } |
| 104 | 103 | }, |
| 105 | 104 | .keyword_union => { |
| 106 | if (full.ast.arg != 0) { | |
| 107 | _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only); | |
| 105 | if (full.ast.arg.unwrap()) |arg| { | |
| 106 | _ = try astrl.expr(arg, block, ResultInfo.type_only); | |
| 108 | 107 | } |
| 109 | 108 | for (full.ast.members) |member_node| { |
| 110 | 109 | _ = try astrl.expr(member_node, block, ResultInfo.none); |
| 111 | 110 | } |
| 112 | 111 | }, |
| 113 | 112 | .keyword_enum => { |
| 114 | if (full.ast.arg != 0) { | |
| 115 | _ = try astrl.expr(full.ast.arg, block, ResultInfo.type_only); | |
| 113 | if (full.ast.arg.unwrap()) |arg| { | |
| 114 | _ = try astrl.expr(arg, block, ResultInfo.type_only); | |
| 116 | 115 | } |
| 117 | 116 | for (full.ast.members) |member_node| { |
| 118 | 117 | _ = try astrl.expr(member_node, block, ResultInfo.none); |
| ... | ... | @@ -130,10 +129,7 @@ fn containerDecl( |
| 130 | 129 | /// Returns true if `rl` provides a result pointer and the expression consumes it. |
| 131 | 130 | fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultInfo) Allocator.Error!bool { |
| 132 | 131 | const tree = astrl.tree; |
| 133 | const token_tags = tree.tokens.items(.tag); | |
| 134 | const node_datas = tree.nodes.items(.data); | |
| 135 | const node_tags = tree.nodes.items(.tag); | |
| 136 | switch (node_tags[node]) { | |
| 132 | switch (tree.nodeTag(node)) { | |
| 137 | 133 | .root, |
| 138 | 134 | .switch_case_one, |
| 139 | 135 | .switch_case_inline_one, |
| ... | ... | @@ -145,8 +141,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 145 | 141 | .asm_input, |
| 146 | 142 | => unreachable, |
| 147 | 143 | |
| 148 | .@"errdefer", .@"defer" => { | |
| 149 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 144 | .@"errdefer" => { | |
| 145 | _ = try astrl.expr(tree.nodeData(node).opt_token_and_node[1], block, ResultInfo.none); | |
| 146 | return false; | |
| 147 | }, | |
| 148 | .@"defer" => { | |
| 149 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 150 | 150 | return false; |
| 151 | 151 | }, |
| 152 | 152 | |
| ... | ... | @@ -155,21 +155,22 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 155 | 155 | .container_field, |
| 156 | 156 | => { |
| 157 | 157 | const full = tree.fullContainerField(node).?; |
| 158 | _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.type_only); | |
| 159 | if (full.ast.align_expr != 0) { | |
| 160 | _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only); | |
| 158 | const type_expr = full.ast.type_expr.unwrap().?; | |
| 159 | _ = try astrl.expr(type_expr, block, ResultInfo.type_only); | |
| 160 | if (full.ast.align_expr.unwrap()) |align_expr| { | |
| 161 | _ = try astrl.expr(align_expr, block, ResultInfo.type_only); | |
| 161 | 162 | } |
| 162 | if (full.ast.value_expr != 0) { | |
| 163 | _ = try astrl.expr(full.ast.value_expr, block, ResultInfo.type_only); | |
| 163 | if (full.ast.value_expr.unwrap()) |value_expr| { | |
| 164 | _ = try astrl.expr(value_expr, block, ResultInfo.type_only); | |
| 164 | 165 | } |
| 165 | 166 | return false; |
| 166 | 167 | }, |
| 167 | 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 | 170 | return false; |
| 170 | 171 | }, |
| 171 | 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 | 174 | return false; |
| 174 | 175 | }, |
| 175 | 176 | .global_var_decl, |
| ... | ... | @@ -178,17 +179,17 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 178 | 179 | .aligned_var_decl, |
| 179 | 180 | => { |
| 180 | 181 | const full = tree.fullVarDecl(node).?; |
| 181 | const init_ri = if (full.ast.type_node != 0) init_ri: { | |
| 182 | _ = try astrl.expr(full.ast.type_node, block, ResultInfo.type_only); | |
| 182 | const init_ri = if (full.ast.type_node.unwrap()) |type_node| init_ri: { | |
| 183 | _ = try astrl.expr(type_node, block, ResultInfo.type_only); | |
| 183 | 184 | break :init_ri ResultInfo.typed_ptr; |
| 184 | 185 | } else ResultInfo.inferred_ptr; |
| 185 | if (full.ast.init_node == 0) { | |
| 186 | const init_node = full.ast.init_node.unwrap() orelse { | |
| 186 | 187 | // No init node, so we're done. |
| 187 | 188 | return false; |
| 188 | } | |
| 189 | switch (token_tags[full.ast.mut_token]) { | |
| 189 | }; | |
| 190 | switch (tree.tokenTag(full.ast.mut_token)) { | |
| 190 | 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 | 193 | if (init_consumes_rl) { |
| 193 | 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 | 198 | .keyword_var => { |
| 198 | 199 | // We'll create an alloc either way, so don't care if the |
| 199 | 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 | 202 | return false; |
| 202 | 203 | }, |
| 203 | 204 | else => unreachable, |
| ... | ... | @@ -213,8 +214,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 213 | 214 | return false; |
| 214 | 215 | }, |
| 215 | 216 | .assign => { |
| 216 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 217 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.typed_ptr); | |
| 217 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 218 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 219 | _ = try astrl.expr(rhs, block, ResultInfo.typed_ptr); | |
| 218 | 220 | return false; |
| 219 | 221 | }, |
| 220 | 222 | .assign_shl, |
| ... | ... | @@ -235,13 +237,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 235 | 237 | .assign_mul_wrap, |
| 236 | 238 | .assign_mul_sat, |
| 237 | 239 | => { |
| 238 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 239 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 240 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 241 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 242 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 240 | 243 | return false; |
| 241 | 244 | }, |
| 242 | 245 | .shl, .shr => { |
| 243 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 244 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 246 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 247 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 248 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 245 | 249 | return false; |
| 246 | 250 | }, |
| 247 | 251 | .add, |
| ... | ... | @@ -267,33 +271,38 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 267 | 271 | .less_or_equal, |
| 268 | 272 | .array_cat, |
| 269 | 273 | => { |
| 270 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 271 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 274 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 275 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 276 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 272 | 277 | return false; |
| 273 | 278 | }, |
| 279 | ||
| 274 | 280 | .array_mult => { |
| 275 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 276 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 281 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 282 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 283 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 277 | 284 | return false; |
| 278 | 285 | }, |
| 279 | 286 | .error_union, .merge_error_sets => { |
| 280 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 281 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 287 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 288 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 289 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 282 | 290 | return false; |
| 283 | 291 | }, |
| 284 | 292 | .bool_and, |
| 285 | 293 | .bool_or, |
| 286 | 294 | => { |
| 287 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 288 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 295 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 296 | _ = try astrl.expr(lhs, block, ResultInfo.type_only); | |
| 297 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 289 | 298 | return false; |
| 290 | 299 | }, |
| 291 | 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 | 302 | return false; |
| 294 | 303 | }, |
| 295 | 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 | 306 | return false; |
| 298 | 307 | }, |
| 299 | 308 | |
| ... | ... | @@ -313,17 +322,13 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 313 | 322 | .error_set_decl, |
| 314 | 323 | => return false, |
| 315 | 324 | |
| 316 | .builtin_call_two, .builtin_call_two_comma => { | |
| 317 | if (node_datas[node].lhs == 0) { | |
| 318 | return astrl.builtinCall(block, ri, node, &.{}); | |
| 319 | } else if (node_datas[node].rhs == 0) { | |
| 320 | return astrl.builtinCall(block, ri, node, &.{node_datas[node].lhs}); | |
| 321 | } else { | |
| 322 | return astrl.builtinCall(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs }); | |
| 323 | } | |
| 324 | }, | |
| 325 | .builtin_call, .builtin_call_comma => { | |
| 326 | const params = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 325 | .builtin_call_two, | |
| 326 | .builtin_call_two_comma, | |
| 327 | .builtin_call, | |
| 328 | .builtin_call_comma, | |
| 329 | => { | |
| 330 | var buf: [2]Ast.Node.Index = undefined; | |
| 331 | const params = tree.builtinCallParams(&buf, node).?; | |
| 327 | 332 | return astrl.builtinCall(block, ri, node, params); |
| 328 | 333 | }, |
| 329 | 334 | |
| ... | ... | @@ -342,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 342 | 347 | for (full.ast.params) |param_node| { |
| 343 | 348 | _ = try astrl.expr(param_node, block, ResultInfo.type_only); |
| 344 | 349 | } |
| 345 | return switch (node_tags[node]) { | |
| 350 | return switch (tree.nodeTag(node)) { | |
| 346 | 351 | .call_one, |
| 347 | 352 | .call_one_comma, |
| 348 | 353 | .call, |
| ... | ... | @@ -358,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 358 | 363 | }, |
| 359 | 364 | |
| 360 | 365 | .@"return" => { |
| 361 | if (node_datas[node].lhs != 0) { | |
| 362 | const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr); | |
| 366 | if (tree.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 367 | const ret_val_consumes_rl = try astrl.expr(lhs, block, ResultInfo.typed_ptr); | |
| 363 | 368 | if (ret_val_consumes_rl) { |
| 364 | 369 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 365 | 370 | } |
| ... | ... | @@ -368,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 368 | 373 | }, |
| 369 | 374 | |
| 370 | 375 | .field_access => { |
| 371 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 376 | const lhs, _ = tree.nodeData(node).node_and_token; | |
| 377 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 372 | 378 | return false; |
| 373 | 379 | }, |
| 374 | 380 | |
| ... | ... | @@ -380,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 380 | 386 | _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool |
| 381 | 387 | } |
| 382 | 388 | |
| 383 | if (full.ast.else_expr == 0) { | |
| 384 | _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none); | |
| 385 | return false; | |
| 386 | } else { | |
| 389 | if (full.ast.else_expr.unwrap()) |else_expr| { | |
| 387 | 390 | const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri); |
| 388 | const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri); | |
| 391 | const else_uses_rl = try astrl.expr(else_expr, block, ri); | |
| 389 | 392 | const uses_rl = then_uses_rl or else_uses_rl; |
| 390 | 393 | if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 391 | 394 | return uses_rl; |
| 395 | } else { | |
| 396 | _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none); | |
| 397 | return false; | |
| 392 | 398 | } |
| 393 | 399 | }, |
| 394 | 400 | |
| ... | ... | @@ -409,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 409 | 415 | .ri = ri, |
| 410 | 416 | .consumes_res_ptr = false, |
| 411 | 417 | }; |
| 412 | if (full.ast.cont_expr != 0) { | |
| 413 | _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none); | |
| 418 | if (full.ast.cont_expr.unwrap()) |cont_expr| { | |
| 419 | _ = try astrl.expr(cont_expr, &new_block, ResultInfo.none); | |
| 414 | 420 | } |
| 415 | 421 | _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none); |
| 416 | const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: { | |
| 417 | break :else_rl try astrl.expr(full.ast.else_expr, block, ri); | |
| 422 | const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: { | |
| 423 | break :else_rl try astrl.expr(else_expr, block, ri); | |
| 418 | 424 | } else false; |
| 419 | 425 | if (new_block.consumes_res_ptr or else_consumes_rl) { |
| 420 | 426 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| ... | ... | @@ -430,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 430 | 436 | break :label try astrl.identString(label_token); |
| 431 | 437 | } else null; |
| 432 | 438 | for (full.ast.inputs) |input| { |
| 433 | if (node_tags[input] == .for_range) { | |
| 434 | _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only); | |
| 435 | if (node_datas[input].rhs != 0) { | |
| 436 | _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only); | |
| 439 | if (tree.nodeTag(input) == .for_range) { | |
| 440 | const lhs, const opt_rhs = tree.nodeData(input).node_and_opt_node; | |
| 441 | _ = try astrl.expr(lhs, block, ResultInfo.type_only); | |
| 442 | if (opt_rhs.unwrap()) |rhs| { | |
| 443 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 437 | 444 | } |
| 438 | 445 | } else { |
| 439 | 446 | _ = try astrl.expr(input, block, ResultInfo.none); |
| ... | ... | @@ -447,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 447 | 454 | .consumes_res_ptr = false, |
| 448 | 455 | }; |
| 449 | 456 | _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none); |
| 450 | const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: { | |
| 451 | break :else_rl try astrl.expr(full.ast.else_expr, block, ri); | |
| 457 | const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: { | |
| 458 | break :else_rl try astrl.expr(else_expr, block, ri); | |
| 452 | 459 | } else false; |
| 453 | 460 | if (new_block.consumes_res_ptr or else_consumes_rl) { |
| 454 | 461 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| ... | ... | @@ -459,66 +466,68 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 459 | 466 | }, |
| 460 | 467 | |
| 461 | 468 | .slice_open => { |
| 462 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 463 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 469 | const sliced, const start = tree.nodeData(node).node_and_node; | |
| 470 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 471 | _ = try astrl.expr(start, block, ResultInfo.type_only); | |
| 464 | 472 | return false; |
| 465 | 473 | }, |
| 466 | 474 | .slice => { |
| 467 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); | |
| 468 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 475 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 476 | const extra = tree.extraData(extra_index, Ast.Node.Slice); | |
| 477 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 469 | 478 | _ = try astrl.expr(extra.start, block, ResultInfo.type_only); |
| 470 | 479 | _ = try astrl.expr(extra.end, block, ResultInfo.type_only); |
| 471 | 480 | return false; |
| 472 | 481 | }, |
| 473 | 482 | .slice_sentinel => { |
| 474 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); | |
| 475 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 483 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 484 | const extra = tree.extraData(extra_index, Ast.Node.SliceSentinel); | |
| 485 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 476 | 486 | _ = try astrl.expr(extra.start, block, ResultInfo.type_only); |
| 477 | if (extra.end != 0) { | |
| 478 | _ = try astrl.expr(extra.end, block, ResultInfo.type_only); | |
| 487 | if (extra.end.unwrap()) |end| { | |
| 488 | _ = try astrl.expr(end, block, ResultInfo.type_only); | |
| 479 | 489 | } |
| 480 | 490 | _ = try astrl.expr(extra.sentinel, block, ResultInfo.none); |
| 481 | 491 | return false; |
| 482 | 492 | }, |
| 483 | 493 | .deref => { |
| 484 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 494 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 485 | 495 | return false; |
| 486 | 496 | }, |
| 487 | 497 | .address_of => { |
| 488 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 498 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 489 | 499 | return false; |
| 490 | 500 | }, |
| 491 | 501 | .optional_type => { |
| 492 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 502 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only); | |
| 493 | 503 | return false; |
| 494 | 504 | }, |
| 495 | .grouped_expression, | |
| 496 | 505 | .@"try", |
| 497 | 506 | .@"await", |
| 498 | 507 | .@"nosuspend", |
| 508 | => return astrl.expr(tree.nodeData(node).node, block, ri), | |
| 509 | .grouped_expression, | |
| 499 | 510 | .unwrap_optional, |
| 500 | => return astrl.expr(node_datas[node].lhs, block, ri), | |
| 511 | => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri), | |
| 501 | 512 | |
| 502 | .block_two, .block_two_semicolon => { | |
| 503 | if (node_datas[node].lhs == 0) { | |
| 504 | return astrl.blockExpr(block, ri, node, &.{}); | |
| 505 | } else if (node_datas[node].rhs == 0) { | |
| 506 | return astrl.blockExpr(block, ri, node, &.{node_datas[node].lhs}); | |
| 507 | } else { | |
| 508 | return astrl.blockExpr(block, ri, node, &.{ node_datas[node].lhs, node_datas[node].rhs }); | |
| 509 | } | |
| 510 | }, | |
| 511 | .block, .block_semicolon => { | |
| 512 | const statements = tree.extra_data[node_datas[node].lhs..node_datas[node].rhs]; | |
| 513 | .block_two, | |
| 514 | .block_two_semicolon, | |
| 515 | .block, | |
| 516 | .block_semicolon, | |
| 517 | => { | |
| 518 | var buf: [2]Ast.Node.Index = undefined; | |
| 519 | const statements = tree.blockStatements(&buf, node).?; | |
| 513 | 520 | return astrl.blockExpr(block, ri, node, statements); |
| 514 | 521 | }, |
| 515 | 522 | .anyframe_type => { |
| 516 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 523 | _, const child_type = tree.nodeData(node).token_and_node; | |
| 524 | _ = try astrl.expr(child_type, block, ResultInfo.type_only); | |
| 517 | 525 | return false; |
| 518 | 526 | }, |
| 519 | 527 | .@"catch", .@"orelse" => { |
| 520 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 521 | const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri); | |
| 528 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 529 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 530 | const rhs_consumes_rl = try astrl.expr(rhs, block, ri); | |
| 522 | 531 | if (rhs_consumes_rl) { |
| 523 | 532 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 524 | 533 | } |
| ... | ... | @@ -532,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 532 | 541 | => { |
| 533 | 542 | const full = tree.fullPtrType(node).?; |
| 534 | 543 | _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only); |
| 535 | if (full.ast.sentinel != 0) { | |
| 536 | _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only); | |
| 544 | if (full.ast.sentinel.unwrap()) |sentinel| { | |
| 545 | _ = try astrl.expr(sentinel, block, ResultInfo.type_only); | |
| 537 | 546 | } |
| 538 | if (full.ast.addrspace_node != 0) { | |
| 539 | _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only); | |
| 547 | if (full.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 548 | _ = try astrl.expr(addrspace_node, block, ResultInfo.type_only); | |
| 540 | 549 | } |
| 541 | if (full.ast.align_node != 0) { | |
| 542 | _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only); | |
| 550 | if (full.ast.align_node.unwrap()) |align_node| { | |
| 551 | _ = try astrl.expr(align_node, block, ResultInfo.type_only); | |
| 543 | 552 | } |
| 544 | if (full.ast.bit_range_start != 0) { | |
| 545 | assert(full.ast.bit_range_end != 0); | |
| 546 | _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only); | |
| 547 | _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only); | |
| 553 | if (full.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 554 | const bit_range_end = full.ast.bit_range_end.unwrap().?; | |
| 555 | _ = try astrl.expr(bit_range_start, block, ResultInfo.type_only); | |
| 556 | _ = try astrl.expr(bit_range_end, block, ResultInfo.type_only); | |
| 548 | 557 | } |
| 549 | 558 | return false; |
| 550 | 559 | }, |
| ... | ... | @@ -568,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 568 | 577 | }, |
| 569 | 578 | |
| 570 | 579 | .@"break" => { |
| 571 | if (node_datas[node].rhs == 0) { | |
| 580 | const opt_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 581 | const rhs = opt_rhs.unwrap() orelse { | |
| 572 | 582 | // Breaks with void are not interesting |
| 573 | 583 | return false; |
| 574 | } | |
| 584 | }; | |
| 575 | 585 | |
| 576 | 586 | var opt_cur_block = block; |
| 577 | if (node_datas[node].lhs == 0) { | |
| 578 | // No label - we're breaking from a loop. | |
| 587 | if (opt_label.unwrap()) |label_token| { | |
| 588 | const break_label = try astrl.identString(label_token); | |
| 579 | 589 | while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) { |
| 580 | if (cur_block.is_loop) break; | |
| 590 | const block_label = cur_block.label orelse continue; | |
| 591 | if (std.mem.eql(u8, block_label, break_label)) break; | |
| 581 | 592 | } |
| 582 | 593 | } else { |
| 583 | const break_label = try astrl.identString(node_datas[node].lhs); | |
| 594 | // No label - we're breaking from a loop. | |
| 584 | 595 | while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) { |
| 585 | const block_label = cur_block.label orelse continue; | |
| 586 | if (std.mem.eql(u8, block_label, break_label)) break; | |
| 596 | if (cur_block.is_loop) break; | |
| 587 | 597 | } |
| 588 | 598 | } |
| 589 | 599 | |
| 590 | 600 | if (opt_cur_block) |target_block| { |
| 591 | const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri); | |
| 601 | const consumes_break_rl = try astrl.expr(rhs, block, target_block.ri); | |
| 592 | 602 | if (consumes_break_rl) target_block.consumes_res_ptr = true; |
| 593 | 603 | } else { |
| 594 | 604 | // No corresponding scope to break from - AstGen will emit an error. |
| 595 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 605 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 596 | 606 | } |
| 597 | 607 | |
| 598 | 608 | return false; |
| 599 | 609 | }, |
| 600 | 610 | |
| 601 | 611 | .array_type => { |
| 602 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 603 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 612 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 613 | _ = try astrl.expr(lhs, block, ResultInfo.type_only); | |
| 614 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 604 | 615 | return false; |
| 605 | 616 | }, |
| 606 | 617 | .array_type_sentinel => { |
| 607 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 608 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 618 | const len_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 619 | const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 620 | _ = try astrl.expr(len_expr, block, ResultInfo.type_only); | |
| 609 | 621 | _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only); |
| 610 | 622 | _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only); |
| 611 | 623 | return false; |
| 612 | 624 | }, |
| 613 | 625 | .array_access => { |
| 614 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 615 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 626 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 627 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 628 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 616 | 629 | return false; |
| 617 | 630 | }, |
| 618 | 631 | .@"comptime" => { |
| 619 | 632 | // AstGen will emit an error if the scope is already comptime, so we can assume it is |
| 620 | 633 | // not. This means the result location is not forwarded. |
| 621 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 634 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 622 | 635 | return false; |
| 623 | 636 | }, |
| 624 | 637 | .@"switch", .switch_comma => { |
| 625 | const operand_node = node_datas[node].lhs; | |
| 626 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 627 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 638 | const operand_node, const extra_index = tree.nodeData(node).node_and_extra; | |
| 639 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 628 | 640 | |
| 629 | 641 | _ = try astrl.expr(operand_node, block, ResultInfo.none); |
| 630 | 642 | |
| ... | ... | @@ -632,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 632 | 644 | for (case_nodes) |case_node| { |
| 633 | 645 | const case = tree.fullSwitchCase(case_node).?; |
| 634 | 646 | for (case.ast.values) |item_node| { |
| 635 | if (node_tags[item_node] == .switch_range) { | |
| 636 | _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none); | |
| 637 | _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none); | |
| 647 | if (tree.nodeTag(item_node) == .switch_range) { | |
| 648 | const lhs, const rhs = tree.nodeData(item_node).node_and_node; | |
| 649 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 650 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 638 | 651 | } else { |
| 639 | 652 | _ = try astrl.expr(item_node, block, ResultInfo.none); |
| 640 | 653 | } |
| ... | ... | @@ -649,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 649 | 662 | return any_prong_consumed_rl; |
| 650 | 663 | }, |
| 651 | 664 | .@"suspend" => { |
| 652 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 665 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 653 | 666 | return false; |
| 654 | 667 | }, |
| 655 | 668 | .@"resume" => { |
| 656 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 669 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 657 | 670 | return false; |
| 658 | 671 | }, |
| 659 | 672 | |
| ... | ... | @@ -669,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 669 | 682 | var buf: [2]Ast.Node.Index = undefined; |
| 670 | 683 | const full = tree.fullArrayInit(&buf, node).?; |
| 671 | 684 | |
| 672 | if (full.ast.type_expr != 0) { | |
| 685 | if (full.ast.type_expr.unwrap()) |type_expr| { | |
| 673 | 686 | // Explicitly typed init does not participate in RLS |
| 674 | _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none); | |
| 687 | _ = try astrl.expr(type_expr, block, ResultInfo.none); | |
| 675 | 688 | for (full.ast.elements) |elem_init| { |
| 676 | 689 | _ = try astrl.expr(elem_init, block, ResultInfo.type_only); |
| 677 | 690 | } |
| ... | ... | @@ -706,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 706 | 719 | var buf: [2]Ast.Node.Index = undefined; |
| 707 | 720 | const full = tree.fullStructInit(&buf, node).?; |
| 708 | 721 | |
| 709 | if (full.ast.type_expr != 0) { | |
| 722 | if (full.ast.type_expr.unwrap()) |type_expr| { | |
| 710 | 723 | // Explicitly typed init does not participate in RLS |
| 711 | _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none); | |
| 724 | _ = try astrl.expr(type_expr, block, ResultInfo.none); | |
| 712 | 725 | for (full.ast.fields) |field_init| { |
| 713 | 726 | _ = try astrl.expr(field_init, block, ResultInfo.type_only); |
| 714 | 727 | } |
| ... | ... | @@ -736,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 736 | 749 | .fn_proto_one, |
| 737 | 750 | .fn_proto, |
| 738 | 751 | .fn_decl, |
| 739 | => { | |
| 752 | => |tag| { | |
| 740 | 753 | var buf: [1]Ast.Node.Index = undefined; |
| 741 | 754 | const full = tree.fullFnProto(&buf, node).?; |
| 742 | const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0; | |
| 755 | const body_node = if (tag == .fn_decl) tree.nodeData(node).node_and_node[1].toOptional() else .none; | |
| 743 | 756 | { |
| 744 | 757 | var it = full.iterate(tree); |
| 745 | 758 | while (it.next()) |param| { |
| 746 | 759 | if (param.anytype_ellipsis3 == null) { |
| 747 | _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only); | |
| 760 | const type_expr = param.type_expr.?; | |
| 761 | _ = try astrl.expr(type_expr, block, ResultInfo.type_only); | |
| 748 | 762 | } |
| 749 | 763 | } |
| 750 | 764 | } |
| 751 | if (full.ast.align_expr != 0) { | |
| 752 | _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only); | |
| 765 | if (full.ast.align_expr.unwrap()) |align_expr| { | |
| 766 | _ = try astrl.expr(align_expr, block, ResultInfo.type_only); | |
| 753 | 767 | } |
| 754 | if (full.ast.addrspace_expr != 0) { | |
| 755 | _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only); | |
| 768 | if (full.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 769 | _ = try astrl.expr(addrspace_expr, block, ResultInfo.type_only); | |
| 756 | 770 | } |
| 757 | if (full.ast.section_expr != 0) { | |
| 758 | _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only); | |
| 771 | if (full.ast.section_expr.unwrap()) |section_expr| { | |
| 772 | _ = try astrl.expr(section_expr, block, ResultInfo.type_only); | |
| 759 | 773 | } |
| 760 | if (full.ast.callconv_expr != 0) { | |
| 761 | _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only); | |
| 774 | if (full.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 775 | _ = try astrl.expr(callconv_expr, block, ResultInfo.type_only); | |
| 762 | 776 | } |
| 763 | _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only); | |
| 764 | if (body_node != 0) { | |
| 765 | _ = try astrl.expr(body_node, block, ResultInfo.none); | |
| 777 | const return_type = full.ast.return_type.unwrap().?; | |
| 778 | _ = try astrl.expr(return_type, block, ResultInfo.type_only); | |
| 779 | if (body_node.unwrap()) |body| { | |
| 780 | _ = try astrl.expr(body, block, ResultInfo.none); | |
| 766 | 781 | } |
| 767 | 782 | return false; |
| 768 | 783 | }, |
| ... | ... | @@ -771,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 771 | 786 | |
| 772 | 787 | fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 { |
| 773 | 788 | const tree = astrl.tree; |
| 774 | const token_tags = tree.tokens.items(.tag); | |
| 775 | assert(token_tags[token] == .identifier); | |
| 789 | assert(tree.tokenTag(token) == .identifier); | |
| 776 | 790 | const ident_name = tree.tokenSlice(token); |
| 777 | 791 | if (!std.mem.startsWith(u8, ident_name, "@")) { |
| 778 | 792 | return ident_name; |
| ... | ... | @@ -785,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 { |
| 785 | 799 | |
| 786 | 800 | fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool { |
| 787 | 801 | const tree = astrl.tree; |
| 788 | const token_tags = tree.tokens.items(.tag); | |
| 789 | const main_tokens = tree.nodes.items(.main_token); | |
| 790 | 802 | |
| 791 | const lbrace = main_tokens[node]; | |
| 792 | if (token_tags[lbrace - 1] == .colon and | |
| 793 | token_tags[lbrace - 2] == .identifier) | |
| 794 | { | |
| 803 | const lbrace = tree.nodeMainToken(node); | |
| 804 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 795 | 805 | // Labeled block |
| 796 | 806 | var new_block: Block = .{ |
| 797 | 807 | .parent = parent_block, |
| ... | ... | @@ -820,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 820 | 830 | _ = ri; // Currently, no builtin consumes its result location. |
| 821 | 831 | |
| 822 | 832 | const tree = astrl.tree; |
| 823 | const main_tokens = tree.nodes.items(.main_token); | |
| 824 | const builtin_token = main_tokens[node]; | |
| 833 | const builtin_token = tree.nodeMainToken(node); | |
| 825 | 834 | const builtin_name = tree.tokenSlice(builtin_token); |
| 826 | 835 | const info = BuiltinFn.list.get(builtin_name) orelse return false; |
| 827 | 836 | if (info.param_count) |expected| { |
lib/std/zig/ErrorBundle.zig+28-26| ... | ... | @@ -481,13 +481,13 @@ pub const Wip = struct { |
| 481 | 481 | const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); |
| 482 | 482 | extra_index = item.end; |
| 483 | 483 | const err_span = blk: { |
| 484 | if (item.data.node != 0) { | |
| 485 | break :blk tree.nodeToSpan(item.data.node); | |
| 486 | } | |
| 487 | const token_starts = tree.tokens.items(.start); | |
| 488 | const start = token_starts[item.data.token] + item.data.byte_offset; | |
| 489 | const end = start + @as(u32, @intCast(tree.tokenSlice(item.data.token).len)) - item.data.byte_offset; | |
| 490 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | |
| 484 | if (item.data.node.unwrap()) |node| { | |
| 485 | break :blk tree.nodeToSpan(node); | |
| 486 | } else if (item.data.token.unwrap()) |token| { | |
| 487 | const start = tree.tokenStart(token) + item.data.byte_offset; | |
| 488 | const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset; | |
| 489 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | |
| 490 | } else unreachable; | |
| 491 | 491 | }; |
| 492 | 492 | const err_loc = std.zig.findLineColumn(source, err_span.main); |
| 493 | 493 | |
| ... | ... | @@ -516,13 +516,13 @@ pub const Wip = struct { |
| 516 | 516 | const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); |
| 517 | 517 | const msg = zir.nullTerminatedString(note_item.data.msg); |
| 518 | 518 | const span = blk: { |
| 519 | if (note_item.data.node != 0) { | |
| 520 | break :blk tree.nodeToSpan(note_item.data.node); | |
| 521 | } | |
| 522 | const token_starts = tree.tokens.items(.start); | |
| 523 | const start = token_starts[note_item.data.token] + note_item.data.byte_offset; | |
| 524 | const end = start + @as(u32, @intCast(tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset; | |
| 525 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | |
| 519 | if (note_item.data.node.unwrap()) |node| { | |
| 520 | break :blk tree.nodeToSpan(node); | |
| 521 | } else if (note_item.data.token.unwrap()) |token| { | |
| 522 | const start = tree.tokenStart(token) + note_item.data.byte_offset; | |
| 523 | const end = start + @as(u32, @intCast(tree.tokenSlice(token).len)) - item.data.byte_offset; | |
| 524 | break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; | |
| 525 | } else unreachable; | |
| 526 | 526 | }; |
| 527 | 527 | const loc = std.zig.findLineColumn(source, span.main); |
| 528 | 528 | |
| ... | ... | @@ -560,13 +560,14 @@ pub const Wip = struct { |
| 560 | 560 | |
| 561 | 561 | for (zoir.compile_errors) |err| { |
| 562 | 562 | const err_span: std.zig.Ast.Span = span: { |
| 563 | if (err.token == std.zig.Zoir.CompileError.invalid_token) { | |
| 564 | break :span tree.nodeToSpan(err.node_or_offset); | |
| 563 | if (err.token.unwrap()) |token| { | |
| 564 | const token_start = tree.tokenStart(token); | |
| 565 | const start = token_start + err.node_or_offset; | |
| 566 | const end = token_start + @as(u32, @intCast(tree.tokenSlice(token).len)); | |
| 567 | break :span .{ .start = start, .end = end, .main = start }; | |
| 568 | } else { | |
| 569 | break :span tree.nodeToSpan(@enumFromInt(err.node_or_offset)); | |
| 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 | 572 | const err_loc = std.zig.findLineColumn(source, err_span.main); |
| 572 | 573 | |
| ... | ... | @@ -588,13 +589,14 @@ pub const Wip = struct { |
| 588 | 589 | for (notes_start.., err.first_note.., 0..err.note_count) |eb_note_idx, zoir_note_idx, _| { |
| 589 | 590 | const note = zoir.error_notes[zoir_note_idx]; |
| 590 | 591 | const note_span: std.zig.Ast.Span = span: { |
| 591 | if (note.token == std.zig.Zoir.CompileError.invalid_token) { | |
| 592 | break :span tree.nodeToSpan(note.node_or_offset); | |
| 592 | if (note.token.unwrap()) |token| { | |
| 593 | const token_start = tree.tokenStart(token); | |
| 594 | const start = token_start + note.node_or_offset; | |
| 595 | const end = token_start + @as(u32, @intCast(tree.tokenSlice(token).len)); | |
| 596 | break :span .{ .start = start, .end = end, .main = start }; | |
| 597 | } else { | |
| 598 | break :span tree.nodeToSpan(@enumFromInt(note.node_or_offset)); | |
| 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 | 601 | const note_loc = std.zig.findLineColumn(source, note_span.main); |
| 600 | 602 |
lib/std/zig/Parse.zig+1076-1328| ... | ... | @@ -4,52 +4,71 @@ pub const Error = error{ParseError} || Allocator.Error; |
| 4 | 4 | |
| 5 | 5 | gpa: Allocator, |
| 6 | 6 | source: []const u8, |
| 7 | token_tags: []const Token.Tag, | |
| 8 | token_starts: []const Ast.ByteOffset, | |
| 7 | tokens: Ast.TokenList.Slice, | |
| 9 | 8 | tok_i: TokenIndex, |
| 10 | 9 | errors: std.ArrayListUnmanaged(AstError), |
| 11 | 10 | nodes: Ast.NodeList, |
| 12 | extra_data: std.ArrayListUnmanaged(Node.Index), | |
| 11 | extra_data: std.ArrayListUnmanaged(u32), | |
| 13 | 12 | scratch: std.ArrayListUnmanaged(Node.Index), |
| 14 | 13 | |
| 14 | fn tokenTag(p: *const Parse, token_index: TokenIndex) Token.Tag { | |
| 15 | return p.tokens.items(.tag)[token_index]; | |
| 16 | } | |
| 17 | ||
| 18 | fn tokenStart(p: *const Parse, token_index: TokenIndex) Ast.ByteOffset { | |
| 19 | return p.tokens.items(.start)[token_index]; | |
| 20 | } | |
| 21 | ||
| 22 | fn nodeTag(p: *const Parse, node: Node.Index) Node.Tag { | |
| 23 | return p.nodes.items(.tag)[@intFromEnum(node)]; | |
| 24 | } | |
| 25 | ||
| 26 | fn nodeMainToken(p: *const Parse, node: Node.Index) TokenIndex { | |
| 27 | return p.nodes.items(.main_token)[@intFromEnum(node)]; | |
| 28 | } | |
| 29 | ||
| 30 | fn nodeData(p: *const Parse, node: Node.Index) Node.Data { | |
| 31 | return p.nodes.items(.data)[@intFromEnum(node)]; | |
| 32 | } | |
| 33 | ||
| 15 | 34 | const SmallSpan = union(enum) { |
| 16 | zero_or_one: Node.Index, | |
| 35 | zero_or_one: Node.OptionalIndex, | |
| 17 | 36 | multi: Node.SubRange, |
| 18 | 37 | }; |
| 19 | 38 | |
| 20 | 39 | const Members = struct { |
| 21 | 40 | len: usize, |
| 22 | lhs: Node.Index, | |
| 23 | rhs: Node.Index, | |
| 41 | /// Must be either `.opt_node_and_opt_node` if `len <= 2` or `.extra_range` otherwise. | |
| 42 | data: Node.Data, | |
| 24 | 43 | trailing: bool, |
| 25 | 44 | |
| 26 | 45 | fn toSpan(self: Members, p: *Parse) !Node.SubRange { |
| 27 | if (self.len <= 2) { | |
| 28 | const nodes = [2]Node.Index{ self.lhs, self.rhs }; | |
| 29 | return p.listToSpan(nodes[0..self.len]); | |
| 30 | } else { | |
| 31 | return Node.SubRange{ .start = self.lhs, .end = self.rhs }; | |
| 32 | } | |
| 46 | return switch (self.len) { | |
| 47 | 0 => p.listToSpan(&.{}), | |
| 48 | 1 => p.listToSpan(&.{self.data.opt_node_and_opt_node[0].unwrap().?}), | |
| 49 | 2 => p.listToSpan(&.{ self.data.opt_node_and_opt_node[0].unwrap().?, self.data.opt_node_and_opt_node[1].unwrap().? }), | |
| 50 | else => self.data.extra_range, | |
| 51 | }; | |
| 33 | 52 | } |
| 34 | 53 | }; |
| 35 | 54 | |
| 36 | fn listToSpan(p: *Parse, list: []const Node.Index) !Node.SubRange { | |
| 37 | try p.extra_data.appendSlice(p.gpa, list); | |
| 38 | return Node.SubRange{ | |
| 39 | .start = @as(Node.Index, @intCast(p.extra_data.items.len - list.len)), | |
| 40 | .end = @as(Node.Index, @intCast(p.extra_data.items.len)), | |
| 55 | fn listToSpan(p: *Parse, list: []const Node.Index) Allocator.Error!Node.SubRange { | |
| 56 | try p.extra_data.appendSlice(p.gpa, @ptrCast(list)); | |
| 57 | return .{ | |
| 58 | .start = @enumFromInt(p.extra_data.items.len - list.len), | |
| 59 | .end = @enumFromInt(p.extra_data.items.len), | |
| 41 | 60 | }; |
| 42 | 61 | } |
| 43 | 62 | |
| 44 | 63 | fn 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 | 65 | try p.nodes.append(p.gpa, elem); |
| 47 | 66 | return result; |
| 48 | 67 | } |
| 49 | 68 | |
| 50 | 69 | fn setNode(p: *Parse, i: usize, elem: Ast.Node) Node.Index { |
| 51 | 70 | p.nodes.set(i, elem); |
| 52 | return @as(Node.Index, @intCast(i)); | |
| 71 | return @enumFromInt(i); | |
| 53 | 72 | } |
| 54 | 73 | |
| 55 | 74 | fn reserveNode(p: *Parse, tag: Ast.Node.Tag) !usize { |
| ... | ... | @@ -69,13 +88,22 @@ fn unreserveNode(p: *Parse, node_index: usize) void { |
| 69 | 88 | } |
| 70 | 89 | } |
| 71 | 90 | |
| 72 | fn addExtra(p: *Parse, extra: anytype) Allocator.Error!Node.Index { | |
| 91 | fn addExtra(p: *Parse, extra: anytype) Allocator.Error!ExtraIndex { | |
| 73 | 92 | const fields = std.meta.fields(@TypeOf(extra)); |
| 74 | 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 | 95 | inline for (fields) |field| { |
| 77 | comptime assert(field.type == Node.Index); | |
| 78 | p.extra_data.appendAssumeCapacity(@field(extra, field.name)); | |
| 96 | const data: u32 = switch (field.type) { | |
| 97 | Node.Index, | |
| 98 | Node.OptionalIndex, | |
| 99 | OptionalTokenIndex, | |
| 100 | ExtraIndex, | |
| 101 | => @intFromEnum(@field(extra, field.name)), | |
| 102 | TokenIndex, | |
| 103 | => @field(extra, field.name), | |
| 104 | else => @compileError("unexpected field type"), | |
| 105 | }; | |
| 106 | p.extra_data.appendAssumeCapacity(data); | |
| 79 | 107 | } |
| 80 | 108 | return result; |
| 81 | 109 | } |
| ... | ... | @@ -170,13 +198,10 @@ pub fn parseRoot(p: *Parse) !void { |
| 170 | 198 | }); |
| 171 | 199 | const root_members = try p.parseContainerMembers(); |
| 172 | 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 | 202 | try p.warnExpected(.eof); |
| 175 | 203 | } |
| 176 | p.nodes.items(.data)[0] = .{ | |
| 177 | .lhs = root_decls.start, | |
| 178 | .rhs = root_decls.end, | |
| 179 | }; | |
| 204 | p.nodes.items(.data)[0] = .{ .extra_range = root_decls }; | |
| 180 | 205 | } |
| 181 | 206 | |
| 182 | 207 | /// Parse in ZON mode. Subset of the language. |
| ... | ... | @@ -196,13 +221,10 @@ pub fn parseZon(p: *Parse) !void { |
| 196 | 221 | }, |
| 197 | 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 | 225 | try p.warnExpected(.eof); |
| 201 | 226 | } |
| 202 | p.nodes.items(.data)[0] = .{ | |
| 203 | .lhs = node_index, | |
| 204 | .rhs = undefined, | |
| 205 | }; | |
| 227 | p.nodes.items(.data)[0] = .{ .node = node_index }; | |
| 206 | 228 | } |
| 207 | 229 | |
| 208 | 230 | /// ContainerMembers <- ContainerDeclaration* (ContainerField COMMA)* (ContainerField / ContainerDeclaration*) |
| ... | ... | @@ -235,13 +257,13 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 235 | 257 | while (true) { |
| 236 | 258 | const doc_comment = try p.eatDocComments(); |
| 237 | 259 | |
| 238 | switch (p.token_tags[p.tok_i]) { | |
| 260 | switch (p.tokenTag(p.tok_i)) { | |
| 239 | 261 | .keyword_test => { |
| 240 | 262 | if (doc_comment) |some| { |
| 241 | 263 | try p.warnMsg(.{ .tag = .test_doc_comment, .token = some }); |
| 242 | 264 | } |
| 243 | const test_decl_node = try p.expectTestDeclRecoverable(); | |
| 244 | if (test_decl_node != 0) { | |
| 265 | const maybe_test_decl_node = try p.expectTestDeclRecoverable(); | |
| 266 | if (maybe_test_decl_node) |test_decl_node| { | |
| 245 | 267 | if (field_state == .seen) { |
| 246 | 268 | field_state = .{ .end = test_decl_node }; |
| 247 | 269 | } |
| ... | ... | @@ -249,27 +271,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 249 | 271 | } |
| 250 | 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 | 275 | .l_brace => { |
| 254 | 276 | if (doc_comment) |some| { |
| 255 | 277 | try p.warnMsg(.{ .tag = .comptime_doc_comment, .token = some }); |
| 256 | 278 | } |
| 257 | 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 | 281 | error.OutOfMemory => return error.OutOfMemory, |
| 260 | 282 | error.ParseError => blk: { |
| 261 | 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 | 288 | const comptime_node = try p.addNode(.{ |
| 267 | 289 | .tag = .@"comptime", |
| 268 | 290 | .main_token = comptime_token, |
| 269 | .data = .{ | |
| 270 | .lhs = block, | |
| 271 | .rhs = undefined, | |
| 272 | }, | |
| 291 | .data = .{ .node = block }, | |
| 273 | 292 | }); |
| 274 | 293 | if (field_state == .seen) { |
| 275 | 294 | field_state = .{ .end = comptime_node }; |
| ... | ... | @@ -294,7 +313,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 294 | 313 | .end => |node| { |
| 295 | 314 | try p.warnMsg(.{ |
| 296 | 315 | .tag = .decl_between_fields, |
| 297 | .token = p.nodes.items(.main_token)[node], | |
| 316 | .token = p.nodeMainToken(node), | |
| 298 | 317 | }); |
| 299 | 318 | try p.warnMsg(.{ |
| 300 | 319 | .tag = .previous_field, |
| ... | ... | @@ -311,7 +330,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 311 | 330 | }, |
| 312 | 331 | } |
| 313 | 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 | 334 | .comma => { |
| 316 | 335 | p.tok_i += 1; |
| 317 | 336 | trailing = true; |
| ... | ... | @@ -331,24 +350,24 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 331 | 350 | }, |
| 332 | 351 | .keyword_pub => { |
| 333 | 352 | p.tok_i += 1; |
| 334 | const top_level_decl = try p.expectTopLevelDeclRecoverable(); | |
| 335 | if (top_level_decl != 0) { | |
| 353 | const opt_top_level_decl = try p.expectTopLevelDeclRecoverable(); | |
| 354 | if (opt_top_level_decl) |top_level_decl| { | |
| 336 | 355 | if (field_state == .seen) { |
| 337 | 356 | field_state = .{ .end = top_level_decl }; |
| 338 | 357 | } |
| 339 | 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 | 362 | .keyword_usingnamespace => { |
| 344 | const node = try p.expectUsingNamespaceRecoverable(); | |
| 345 | if (node != 0) { | |
| 363 | const opt_node = try p.expectUsingNamespaceRecoverable(); | |
| 364 | if (opt_node) |node| { | |
| 346 | 365 | if (field_state == .seen) { |
| 347 | 366 | field_state = .{ .end = node }; |
| 348 | 367 | } |
| 349 | 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 | 372 | .keyword_const, |
| 354 | 373 | .keyword_var, |
| ... | ... | @@ -359,14 +378,14 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 359 | 378 | .keyword_noinline, |
| 360 | 379 | .keyword_fn, |
| 361 | 380 | => { |
| 362 | const top_level_decl = try p.expectTopLevelDeclRecoverable(); | |
| 363 | if (top_level_decl != 0) { | |
| 381 | const opt_top_level_decl = try p.expectTopLevelDeclRecoverable(); | |
| 382 | if (opt_top_level_decl) |top_level_decl| { | |
| 364 | 383 | if (field_state == .seen) { |
| 365 | 384 | field_state = .{ .end = top_level_decl }; |
| 366 | 385 | } |
| 367 | 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 | 390 | .eof, .r_brace => { |
| 372 | 391 | if (doc_comment) |tok| { |
| ... | ... | @@ -399,7 +418,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 399 | 418 | .end => |node| { |
| 400 | 419 | try p.warnMsg(.{ |
| 401 | 420 | .tag = .decl_between_fields, |
| 402 | .token = p.nodes.items(.main_token)[node], | |
| 421 | .token = p.nodeMainToken(node), | |
| 403 | 422 | }); |
| 404 | 423 | try p.warnMsg(.{ |
| 405 | 424 | .tag = .previous_field, |
| ... | ... | @@ -416,7 +435,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 416 | 435 | }, |
| 417 | 436 | } |
| 418 | 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 | 439 | .comma => { |
| 421 | 440 | p.tok_i += 1; |
| 422 | 441 | trailing = true; |
| ... | ... | @@ -431,7 +450,7 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 431 | 450 | // There is not allowed to be a decl after a field with no comma. |
| 432 | 451 | // Report error but recover parser. |
| 433 | 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 | 454 | try p.warnMsg(.{ |
| 436 | 455 | .tag = .var_const_decl, |
| 437 | 456 | .is_note = true, |
| ... | ... | @@ -445,34 +464,21 @@ fn parseContainerMembers(p: *Parse) Allocator.Error!Members { |
| 445 | 464 | } |
| 446 | 465 | |
| 447 | 466 | const items = p.scratch.items[scratch_top..]; |
| 448 | switch (items.len) { | |
| 449 | 0 => return Members{ | |
| 450 | .len = 0, | |
| 451 | .lhs = 0, | |
| 452 | .rhs = 0, | |
| 453 | .trailing = trailing, | |
| 454 | }, | |
| 455 | 1 => return Members{ | |
| 456 | .len = 1, | |
| 457 | .lhs = items[0], | |
| 458 | .rhs = 0, | |
| 467 | if (items.len <= 2) { | |
| 468 | return Members{ | |
| 469 | .len = items.len, | |
| 470 | .data = .{ .opt_node_and_opt_node = .{ | |
| 471 | if (items.len >= 1) items[0].toOptional() else .none, | |
| 472 | if (items.len >= 2) items[1].toOptional() else .none, | |
| 473 | } }, | |
| 459 | 474 | .trailing = trailing, |
| 460 | }, | |
| 461 | 2 => return Members{ | |
| 462 | .len = 2, | |
| 463 | .lhs = items[0], | |
| 464 | .rhs = items[1], | |
| 475 | }; | |
| 476 | } else { | |
| 477 | return Members{ | |
| 478 | .len = items.len, | |
| 479 | .data = .{ .extra_range = try p.listToSpan(items) }, | |
| 465 | 480 | .trailing = trailing, |
| 466 | }, | |
| 467 | else => { | |
| 468 | const span = try p.listToSpan(items); | |
| 469 | return Members{ | |
| 470 | .len = items.len, | |
| 471 | .lhs = span.start, | |
| 472 | .rhs = span.end, | |
| 473 | .trailing = trailing, | |
| 474 | }; | |
| 475 | }, | |
| 481 | }; | |
| 476 | 482 | } |
| 477 | 483 | } |
| 478 | 484 | |
| ... | ... | @@ -481,7 +487,7 @@ fn findNextContainerMember(p: *Parse) void { |
| 481 | 487 | var level: u32 = 0; |
| 482 | 488 | while (true) { |
| 483 | 489 | const tok = p.nextToken(); |
| 484 | switch (p.token_tags[tok]) { | |
| 490 | switch (p.tokenTag(tok)) { | |
| 485 | 491 | // Any of these can start a new top level declaration. |
| 486 | 492 | .keyword_test, |
| 487 | 493 | .keyword_comptime, |
| ... | ... | @@ -502,7 +508,7 @@ fn findNextContainerMember(p: *Parse) void { |
| 502 | 508 | } |
| 503 | 509 | }, |
| 504 | 510 | .identifier => { |
| 505 | if (p.token_tags[tok + 1] == .comma and level == 0) { | |
| 511 | if (p.tokenTag(tok + 1) == .comma and level == 0) { | |
| 506 | 512 | p.tok_i -= 1; |
| 507 | 513 | return; |
| 508 | 514 | } |
| ... | ... | @@ -539,7 +545,7 @@ fn findNextStmt(p: *Parse) void { |
| 539 | 545 | var level: u32 = 0; |
| 540 | 546 | while (true) { |
| 541 | 547 | const tok = p.nextToken(); |
| 542 | switch (p.token_tags[tok]) { | |
| 548 | switch (p.tokenTag(tok)) { | |
| 543 | 549 | .l_brace => level += 1, |
| 544 | 550 | .r_brace => { |
| 545 | 551 | if (level == 0) { |
| ... | ... | @@ -563,44 +569,45 @@ fn findNextStmt(p: *Parse) void { |
| 563 | 569 | } |
| 564 | 570 | |
| 565 | 571 | /// TestDecl <- KEYWORD_test (STRINGLITERALSINGLE / IDENTIFIER)? Block |
| 566 | fn expectTestDecl(p: *Parse) !Node.Index { | |
| 572 | fn expectTestDecl(p: *Parse) Error!Node.Index { | |
| 567 | 573 | const test_token = p.assertToken(.keyword_test); |
| 568 | const name_token = switch (p.token_tags[p.tok_i]) { | |
| 569 | .string_literal, .identifier => p.nextToken(), | |
| 570 | else => null, | |
| 574 | const name_token: OptionalTokenIndex = switch (p.tokenTag(p.tok_i)) { | |
| 575 | .string_literal, .identifier => .fromToken(p.nextToken()), | |
| 576 | else => .none, | |
| 571 | 577 | }; |
| 572 | const block_node = try p.parseBlock(); | |
| 573 | if (block_node == 0) return p.fail(.expected_block); | |
| 578 | const block_node = try p.parseBlock() orelse return p.fail(.expected_block); | |
| 574 | 579 | return p.addNode(.{ |
| 575 | 580 | .tag = .test_decl, |
| 576 | 581 | .main_token = test_token, |
| 577 | .data = .{ | |
| 578 | .lhs = name_token orelse 0, | |
| 579 | .rhs = block_node, | |
| 580 | }, | |
| 582 | .data = .{ .opt_token_and_node = .{ | |
| 583 | name_token, | |
| 584 | block_node, | |
| 585 | } }, | |
| 581 | 586 | }); |
| 582 | 587 | } |
| 583 | 588 | |
| 584 | fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index { | |
| 585 | return p.expectTestDecl() catch |err| switch (err) { | |
| 589 | fn expectTestDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index { | |
| 590 | if (p.expectTestDecl()) |node| { | |
| 591 | return node; | |
| 592 | } else |err| switch (err) { | |
| 586 | 593 | error.OutOfMemory => return error.OutOfMemory, |
| 587 | 594 | error.ParseError => { |
| 588 | 595 | p.findNextContainerMember(); |
| 589 | return null_node; | |
| 596 | return null; | |
| 590 | 597 | }, |
| 591 | }; | |
| 598 | } | |
| 592 | 599 | } |
| 593 | 600 | |
| 594 | 601 | /// Decl |
| 595 | 602 | /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / KEYWORD_inline / KEYWORD_noinline)? FnProto (SEMICOLON / Block) |
| 596 | 603 | /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl |
| 597 | 604 | /// / KEYWORD_usingnamespace Expr SEMICOLON |
| 598 | fn expectTopLevelDecl(p: *Parse) !Node.Index { | |
| 605 | fn expectTopLevelDecl(p: *Parse) !?Node.Index { | |
| 599 | 606 | const extern_export_inline_token = p.nextToken(); |
| 600 | 607 | var is_extern: bool = false; |
| 601 | 608 | var expect_fn: bool = false; |
| 602 | 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 | 611 | .keyword_extern => { |
| 605 | 612 | _ = p.eatToken(.string_literal); |
| 606 | 613 | is_extern = true; |
| ... | ... | @@ -610,9 +617,9 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index { |
| 610 | 617 | .keyword_inline, .keyword_noinline => expect_fn = true, |
| 611 | 618 | else => p.tok_i -= 1, |
| 612 | 619 | } |
| 613 | const fn_proto = try p.parseFnProto(); | |
| 614 | if (fn_proto != 0) { | |
| 615 | switch (p.token_tags[p.tok_i]) { | |
| 620 | const opt_fn_proto = try p.parseFnProto(); | |
| 621 | if (opt_fn_proto) |fn_proto| { | |
| 622 | switch (p.tokenTag(p.tok_i)) { | |
| 616 | 623 | .semicolon => { |
| 617 | 624 | p.tok_i += 1; |
| 618 | 625 | return fn_proto; |
| ... | ... | @@ -620,20 +627,19 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index { |
| 620 | 627 | .l_brace => { |
| 621 | 628 | if (is_extern) { |
| 622 | 629 | try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token }); |
| 623 | return null_node; | |
| 630 | return null; | |
| 624 | 631 | } |
| 625 | 632 | const fn_decl_index = try p.reserveNode(.fn_decl); |
| 626 | 633 | errdefer p.unreserveNode(fn_decl_index); |
| 627 | 634 | |
| 628 | 635 | const body_block = try p.parseBlock(); |
| 629 | assert(body_block != 0); | |
| 630 | 636 | return p.setNode(fn_decl_index, .{ |
| 631 | 637 | .tag = .fn_decl, |
| 632 | .main_token = p.nodes.items(.main_token)[fn_proto], | |
| 633 | .data = .{ | |
| 634 | .lhs = fn_proto, | |
| 635 | .rhs = body_block, | |
| 636 | }, | |
| 638 | .main_token = p.nodeMainToken(fn_proto), | |
| 639 | .data = .{ .node_and_node = .{ | |
| 640 | fn_proto, | |
| 641 | body_block.?, | |
| 642 | } }, | |
| 637 | 643 | }); |
| 638 | 644 | }, |
| 639 | 645 | else => { |
| ... | ... | @@ -641,7 +647,7 @@ fn expectTopLevelDecl(p: *Parse) !Node.Index { |
| 641 | 647 | // a missing '}' we can assume this function was |
| 642 | 648 | // supposed to end here. |
| 643 | 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 | 657 | } |
| 652 | 658 | |
| 653 | 659 | const thread_local_token = p.eatToken(.keyword_threadlocal); |
| 654 | const var_decl = try p.parseGlobalVarDecl(); | |
| 655 | if (var_decl != 0) { | |
| 656 | return var_decl; | |
| 657 | } | |
| 660 | if (try p.parseGlobalVarDecl()) |var_decl| return var_decl; | |
| 658 | 661 | if (thread_local_token != null) { |
| 659 | 662 | return p.fail(.expected_var_decl); |
| 660 | 663 | } |
| 661 | 664 | if (expect_var_or_fn) { |
| 662 | 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 | 668 | return p.fail(.expected_pub_item); |
| 666 | 669 | } |
| 667 | return p.expectUsingNamespace(); | |
| 670 | return try p.expectUsingNamespace(); | |
| 668 | 671 | } |
| 669 | 672 | |
| 670 | fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!Node.Index { | |
| 673 | fn expectTopLevelDeclRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index { | |
| 671 | 674 | return p.expectTopLevelDecl() catch |err| switch (err) { |
| 672 | 675 | error.OutOfMemory => return error.OutOfMemory, |
| 673 | 676 | error.ParseError => { |
| 674 | 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 | 687 | return p.addNode(.{ |
| 685 | 688 | .tag = .@"usingnamespace", |
| 686 | 689 | .main_token = usingnamespace_token, |
| 687 | .data = .{ | |
| 688 | .lhs = expr, | |
| 689 | .rhs = undefined, | |
| 690 | }, | |
| 690 | .data = .{ .node = expr }, | |
| 691 | 691 | }); |
| 692 | 692 | } |
| 693 | 693 | |
| 694 | fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!Node.Index { | |
| 694 | fn expectUsingNamespaceRecoverable(p: *Parse) error{OutOfMemory}!?Node.Index { | |
| 695 | 695 | return p.expectUsingNamespace() catch |err| switch (err) { |
| 696 | 696 | error.OutOfMemory => return error.OutOfMemory, |
| 697 | 697 | error.ParseError => { |
| 698 | 698 | p.findNextContainerMember(); |
| 699 | return null_node; | |
| 699 | return null; | |
| 700 | 700 | }, |
| 701 | 701 | }; |
| 702 | 702 | } |
| 703 | 703 | |
| 704 | 704 | /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr |
| 705 | fn parseFnProto(p: *Parse) !Node.Index { | |
| 706 | const fn_token = p.eatToken(.keyword_fn) orelse return null_node; | |
| 705 | fn parseFnProto(p: *Parse) !?Node.Index { | |
| 706 | const fn_token = p.eatToken(.keyword_fn) orelse return null; | |
| 707 | 707 | |
| 708 | 708 | // We want the fn proto node to be before its children in the array. |
| 709 | 709 | const fn_proto_index = try p.reserveNode(.fn_proto); |
| ... | ... | @@ -718,33 +718,33 @@ fn parseFnProto(p: *Parse) !Node.Index { |
| 718 | 718 | _ = p.eatToken(.bang); |
| 719 | 719 | |
| 720 | 720 | const return_type_expr = try p.parseTypeExpr(); |
| 721 | if (return_type_expr == 0) { | |
| 721 | if (return_type_expr == null) { | |
| 722 | 722 | // most likely the user forgot to specify the return type. |
| 723 | 723 | // Mark return type as invalid and try to continue. |
| 724 | 724 | try p.warn(.expected_return_type); |
| 725 | 725 | } |
| 726 | 726 | |
| 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 | 728 | switch (params) { |
| 729 | 729 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ |
| 730 | 730 | .tag = .fn_proto_simple, |
| 731 | 731 | .main_token = fn_token, |
| 732 | .data = .{ | |
| 733 | .lhs = param, | |
| 734 | .rhs = return_type_expr, | |
| 735 | }, | |
| 732 | .data = .{ .opt_node_and_opt_node = .{ | |
| 733 | param, | |
| 734 | .fromOptional(return_type_expr), | |
| 735 | } }, | |
| 736 | 736 | }), |
| 737 | 737 | .multi => |span| { |
| 738 | 738 | return p.setNode(fn_proto_index, .{ |
| 739 | 739 | .tag = .fn_proto_multi, |
| 740 | 740 | .main_token = fn_token, |
| 741 | .data = .{ | |
| 742 | .lhs = try p.addExtra(Node.SubRange{ | |
| 741 | .data = .{ .extra_and_opt_node = .{ | |
| 742 | try p.addExtra(Node.SubRange{ | |
| 743 | 743 | .start = span.start, |
| 744 | 744 | .end = span.end, |
| 745 | 745 | }), |
| 746 | .rhs = return_type_expr, | |
| 747 | }, | |
| 746 | .fromOptional(return_type_expr), | |
| 747 | } }, | |
| 748 | 748 | }); |
| 749 | 749 | }, |
| 750 | 750 | } |
| ... | ... | @@ -753,109 +753,124 @@ fn parseFnProto(p: *Parse) !Node.Index { |
| 753 | 753 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ |
| 754 | 754 | .tag = .fn_proto_one, |
| 755 | 755 | .main_token = fn_token, |
| 756 | .data = .{ | |
| 757 | .lhs = try p.addExtra(Node.FnProtoOne{ | |
| 756 | .data = .{ .extra_and_opt_node = .{ | |
| 757 | try p.addExtra(Node.FnProtoOne{ | |
| 758 | 758 | .param = param, |
| 759 | .align_expr = align_expr, | |
| 760 | .addrspace_expr = addrspace_expr, | |
| 761 | .section_expr = section_expr, | |
| 762 | .callconv_expr = callconv_expr, | |
| 759 | .align_expr = .fromOptional(align_expr), | |
| 760 | .addrspace_expr = .fromOptional(addrspace_expr), | |
| 761 | .section_expr = .fromOptional(section_expr), | |
| 762 | .callconv_expr = .fromOptional(callconv_expr), | |
| 763 | 763 | }), |
| 764 | .rhs = return_type_expr, | |
| 765 | }, | |
| 764 | .fromOptional(return_type_expr), | |
| 765 | } }, | |
| 766 | 766 | }), |
| 767 | 767 | .multi => |span| { |
| 768 | 768 | return p.setNode(fn_proto_index, .{ |
| 769 | 769 | .tag = .fn_proto, |
| 770 | 770 | .main_token = fn_token, |
| 771 | .data = .{ | |
| 772 | .lhs = try p.addExtra(Node.FnProto{ | |
| 771 | .data = .{ .extra_and_opt_node = .{ | |
| 772 | try p.addExtra(Node.FnProto{ | |
| 773 | 773 | .params_start = span.start, |
| 774 | 774 | .params_end = span.end, |
| 775 | .align_expr = align_expr, | |
| 776 | .addrspace_expr = addrspace_expr, | |
| 777 | .section_expr = section_expr, | |
| 778 | .callconv_expr = callconv_expr, | |
| 775 | .align_expr = .fromOptional(align_expr), | |
| 776 | .addrspace_expr = .fromOptional(addrspace_expr), | |
| 777 | .section_expr = .fromOptional(section_expr), | |
| 778 | .callconv_expr = .fromOptional(callconv_expr), | |
| 779 | 779 | }), |
| 780 | .rhs = return_type_expr, | |
| 781 | }, | |
| 780 | .fromOptional(return_type_expr), | |
| 781 | } }, | |
| 782 | 782 | }); |
| 783 | 783 | }, |
| 784 | 784 | } |
| 785 | 785 | } |
| 786 | 786 | |
| 787 | fn 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 | 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. | |
| 789 | fn parseVarDeclProto(p: *Parse) !Node.Index { | |
| 798 | /// Returns a `*_var_decl` node with its rhs (init expression) initialized to .none. | |
| 799 | fn parseVarDeclProto(p: *Parse) !?Node.Index { | |
| 790 | 800 | const mut_token = p.eatToken(.keyword_const) orelse |
| 791 | 801 | p.eatToken(.keyword_var) orelse |
| 792 | return null_node; | |
| 802 | return null; | |
| 793 | 803 | |
| 794 | 804 | _ = try p.expectToken(.identifier); |
| 795 | const type_node: Node.Index = if (p.eatToken(.colon) == null) 0 else try p.expectTypeExpr(); | |
| 796 | const align_node = try p.parseByteAlign(); | |
| 797 | const addrspace_node = try p.parseAddrSpace(); | |
| 798 | const section_node = try p.parseLinkSection(); | |
| 799 | ||
| 800 | if (section_node == 0 and addrspace_node == 0) { | |
| 801 | if (align_node == 0) { | |
| 802 | return p.addNode(.{ | |
| 805 | const opt_type_node = if (p.eatToken(.colon) == null) null else try p.expectTypeExpr(); | |
| 806 | const opt_align_node = try p.parseByteAlign(); | |
| 807 | const opt_addrspace_node = try p.parseAddrSpace(); | |
| 808 | const opt_section_node = try p.parseLinkSection(); | |
| 809 | ||
| 810 | if (opt_section_node == null and opt_addrspace_node == null) { | |
| 811 | const align_node = opt_align_node orelse { | |
| 812 | return try p.addNode(.{ | |
| 803 | 813 | .tag = .simple_var_decl, |
| 804 | 814 | .main_token = mut_token, |
| 805 | 815 | .data = .{ |
| 806 | .lhs = type_node, | |
| 807 | .rhs = 0, | |
| 816 | .opt_node_and_opt_node = .{ | |
| 817 | .fromOptional(opt_type_node), | |
| 818 | .none, // set later with `setVarDeclInitExpr | |
| 819 | }, | |
| 808 | 820 | }, |
| 809 | 821 | }); |
| 810 | } | |
| 822 | }; | |
| 811 | 823 | |
| 812 | if (type_node == 0) { | |
| 813 | return p.addNode(.{ | |
| 824 | const type_node = opt_type_node orelse { | |
| 825 | return try p.addNode(.{ | |
| 814 | 826 | .tag = .aligned_var_decl, |
| 815 | 827 | .main_token = mut_token, |
| 816 | 828 | .data = .{ |
| 817 | .lhs = align_node, | |
| 818 | .rhs = 0, | |
| 829 | .node_and_opt_node = .{ | |
| 830 | align_node, | |
| 831 | .none, // set later with `setVarDeclInitExpr | |
| 832 | }, | |
| 819 | 833 | }, |
| 820 | 834 | }); |
| 821 | } | |
| 835 | }; | |
| 822 | 836 | |
| 823 | return p.addNode(.{ | |
| 837 | return try p.addNode(.{ | |
| 824 | 838 | .tag = .local_var_decl, |
| 825 | 839 | .main_token = mut_token, |
| 826 | 840 | .data = .{ |
| 827 | .lhs = try p.addExtra(Node.LocalVarDecl{ | |
| 828 | .type_node = type_node, | |
| 829 | .align_node = align_node, | |
| 830 | }), | |
| 831 | .rhs = 0, | |
| 841 | .extra_and_opt_node = .{ | |
| 842 | try p.addExtra(Node.LocalVarDecl{ | |
| 843 | .type_node = type_node, | |
| 844 | .align_node = align_node, | |
| 845 | }), | |
| 846 | .none, // set later with `setVarDeclInitExpr | |
| 847 | }, | |
| 832 | 848 | }, |
| 833 | 849 | }); |
| 834 | 850 | } else { |
| 835 | return p.addNode(.{ | |
| 851 | return try p.addNode(.{ | |
| 836 | 852 | .tag = .global_var_decl, |
| 837 | 853 | .main_token = mut_token, |
| 838 | 854 | .data = .{ |
| 839 | .lhs = try p.addExtra(Node.GlobalVarDecl{ | |
| 840 | .type_node = type_node, | |
| 841 | .align_node = align_node, | |
| 842 | .addrspace_node = addrspace_node, | |
| 843 | .section_node = section_node, | |
| 844 | }), | |
| 845 | .rhs = 0, | |
| 855 | .extra_and_opt_node = .{ | |
| 856 | try p.addExtra(Node.GlobalVarDecl{ | |
| 857 | .type_node = .fromOptional(opt_type_node), | |
| 858 | .align_node = .fromOptional(opt_align_node), | |
| 859 | .addrspace_node = .fromOptional(opt_addrspace_node), | |
| 860 | .section_node = .fromOptional(opt_section_node), | |
| 861 | }), | |
| 862 | .none, // set later with `setVarDeclInitExpr | |
| 863 | }, | |
| 846 | 864 | }, |
| 847 | 865 | }); |
| 848 | 866 | } |
| 849 | 867 | } |
| 850 | 868 | |
| 851 | 869 | /// GlobalVarDecl <- VarDeclProto (EQUAL Expr?) SEMICOLON |
| 852 | fn parseGlobalVarDecl(p: *Parse) !Node.Index { | |
| 853 | const var_decl = try p.parseVarDeclProto(); | |
| 854 | if (var_decl == 0) { | |
| 855 | return null_node; | |
| 856 | } | |
| 870 | fn parseGlobalVarDecl(p: *Parse) !?Node.Index { | |
| 871 | const var_decl = try p.parseVarDeclProto() orelse return null; | |
| 857 | 872 | |
| 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 | 874 | .equal_equal => blk: { |
| 860 | 875 | try p.warn(.wrong_equal_var_decl); |
| 861 | 876 | p.tok_i += 1; |
| ... | ... | @@ -865,10 +880,10 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index { |
| 865 | 880 | p.tok_i += 1; |
| 866 | 881 | break :blk try p.expectExpr(); |
| 867 | 882 | }, |
| 868 | else => 0, | |
| 883 | else => null, | |
| 869 | 884 | }; |
| 870 | 885 | |
| 871 | p.nodes.items(.data)[var_decl].rhs = init_node; | |
| 886 | p.setVarDeclInitExpr(var_decl, .fromOptional(init_node)); | |
| 872 | 887 | |
| 873 | 888 | try p.expectSemicolon(.expected_semi_after_decl, false); |
| 874 | 889 | return var_decl; |
| ... | ... | @@ -878,40 +893,39 @@ fn parseGlobalVarDecl(p: *Parse) !Node.Index { |
| 878 | 893 | fn expectContainerField(p: *Parse) !Node.Index { |
| 879 | 894 | _ = p.eatToken(.keyword_comptime); |
| 880 | 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 | 897 | const type_expr = try p.expectTypeExpr(); |
| 883 | 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(); | |
| 885 | 900 | |
| 886 | if (align_expr == 0) { | |
| 901 | if (align_expr == null) { | |
| 887 | 902 | return p.addNode(.{ |
| 888 | 903 | .tag = .container_field_init, |
| 889 | 904 | .main_token = main_token, |
| 890 | .data = .{ | |
| 891 | .lhs = type_expr, | |
| 892 | .rhs = value_expr, | |
| 893 | }, | |
| 905 | .data = .{ .node_and_opt_node = .{ | |
| 906 | type_expr, | |
| 907 | .fromOptional(value_expr), | |
| 908 | } }, | |
| 894 | 909 | }); |
| 895 | } else if (value_expr == 0) { | |
| 910 | } else if (value_expr == null) { | |
| 896 | 911 | return p.addNode(.{ |
| 897 | 912 | .tag = .container_field_align, |
| 898 | 913 | .main_token = main_token, |
| 899 | .data = .{ | |
| 900 | .lhs = type_expr, | |
| 901 | .rhs = align_expr, | |
| 902 | }, | |
| 914 | .data = .{ .node_and_node = .{ | |
| 915 | type_expr, | |
| 916 | align_expr.?, | |
| 917 | } }, | |
| 903 | 918 | }); |
| 904 | 919 | } else { |
| 905 | 920 | return p.addNode(.{ |
| 906 | 921 | .tag = .container_field, |
| 907 | 922 | .main_token = main_token, |
| 908 | .data = .{ | |
| 909 | .lhs = type_expr, | |
| 910 | .rhs = try p.addExtra(Node.ContainerField{ | |
| 911 | .align_expr = align_expr, | |
| 912 | .value_expr = value_expr, | |
| 923 | .data = .{ .node_and_extra = .{ | |
| 924 | type_expr, try p.addExtra(Node.ContainerField{ | |
| 925 | .align_expr = align_expr.?, | |
| 926 | .value_expr = value_expr.?, | |
| 913 | 927 | }), |
| 914 | }, | |
| 928 | } }, | |
| 915 | 929 | }); |
| 916 | 930 | } |
| 917 | 931 | } |
| ... | ... | @@ -927,15 +941,12 @@ fn expectContainerField(p: *Parse) !Node.Index { |
| 927 | 941 | /// / VarDeclExprStatement |
| 928 | 942 | fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index { |
| 929 | 943 | if (p.eatToken(.keyword_comptime)) |comptime_token| { |
| 930 | const block_expr = try p.parseBlockExpr(); | |
| 931 | if (block_expr != 0) { | |
| 944 | const opt_block_expr = try p.parseBlockExpr(); | |
| 945 | if (opt_block_expr) |block_expr| { | |
| 932 | 946 | return p.addNode(.{ |
| 933 | 947 | .tag = .@"comptime", |
| 934 | 948 | .main_token = comptime_token, |
| 935 | .data = .{ | |
| 936 | .lhs = block_expr, | |
| 937 | .rhs = undefined, | |
| 938 | }, | |
| 949 | .data = .{ .node = block_expr }, | |
| 939 | 950 | }); |
| 940 | 951 | } |
| 941 | 952 | |
| ... | ... | @@ -947,23 +958,17 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index { |
| 947 | 958 | return p.addNode(.{ |
| 948 | 959 | .tag = .@"comptime", |
| 949 | 960 | .main_token = comptime_token, |
| 950 | .data = .{ | |
| 951 | .lhs = assign, | |
| 952 | .rhs = undefined, | |
| 953 | }, | |
| 961 | .data = .{ .node = assign }, | |
| 954 | 962 | }); |
| 955 | 963 | } |
| 956 | 964 | } |
| 957 | 965 | |
| 958 | switch (p.token_tags[p.tok_i]) { | |
| 966 | switch (p.tokenTag(p.tok_i)) { | |
| 959 | 967 | .keyword_nosuspend => { |
| 960 | 968 | return p.addNode(.{ |
| 961 | 969 | .tag = .@"nosuspend", |
| 962 | 970 | .main_token = p.nextToken(), |
| 963 | .data = .{ | |
| 964 | .lhs = try p.expectBlockExprStatement(), | |
| 965 | .rhs = undefined, | |
| 966 | }, | |
| 971 | .data = .{ .node = try p.expectBlockExprStatement() }, | |
| 967 | 972 | }); |
| 968 | 973 | }, |
| 969 | 974 | .keyword_suspend => { |
| ... | ... | @@ -972,27 +977,21 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index { |
| 972 | 977 | return p.addNode(.{ |
| 973 | 978 | .tag = .@"suspend", |
| 974 | 979 | .main_token = token, |
| 975 | .data = .{ | |
| 976 | .lhs = block_expr, | |
| 977 | .rhs = undefined, | |
| 978 | }, | |
| 980 | .data = .{ .node = block_expr }, | |
| 979 | 981 | }); |
| 980 | 982 | }, |
| 981 | 983 | .keyword_defer => if (allow_defer_var) return p.addNode(.{ |
| 982 | 984 | .tag = .@"defer", |
| 983 | 985 | .main_token = p.nextToken(), |
| 984 | .data = .{ | |
| 985 | .lhs = undefined, | |
| 986 | .rhs = try p.expectBlockExprStatement(), | |
| 987 | }, | |
| 986 | .data = .{ .node = try p.expectBlockExprStatement() }, | |
| 988 | 987 | }), |
| 989 | 988 | .keyword_errdefer => if (allow_defer_var) return p.addNode(.{ |
| 990 | 989 | .tag = .@"errdefer", |
| 991 | 990 | .main_token = p.nextToken(), |
| 992 | .data = .{ | |
| 993 | .lhs = try p.parsePayload(), | |
| 994 | .rhs = try p.expectBlockExprStatement(), | |
| 995 | }, | |
| 991 | .data = .{ .opt_token_and_node = .{ | |
| 992 | try p.parsePayload(), | |
| 993 | try p.expectBlockExprStatement(), | |
| 994 | } }, | |
| 996 | 995 | }), |
| 997 | 996 | .keyword_if => return p.expectIfStatement(), |
| 998 | 997 | .keyword_enum, .keyword_struct, .keyword_union => { |
| ... | ... | @@ -1002,18 +1001,14 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index { |
| 1002 | 1001 | return p.addNode(.{ |
| 1003 | 1002 | .tag = .identifier, |
| 1004 | 1003 | .main_token = identifier, |
| 1005 | .data = .{ | |
| 1006 | .lhs = undefined, | |
| 1007 | .rhs = undefined, | |
| 1008 | }, | |
| 1004 | .data = undefined, | |
| 1009 | 1005 | }); |
| 1010 | 1006 | } |
| 1011 | 1007 | }, |
| 1012 | 1008 | else => {}, |
| 1013 | 1009 | } |
| 1014 | 1010 | |
| 1015 | const labeled_statement = try p.parseLabeledStatement(); | |
| 1016 | if (labeled_statement != 0) return labeled_statement; | |
| 1011 | if (try p.parseLabeledStatement()) |labeled_statement| return labeled_statement; | |
| 1017 | 1012 | |
| 1018 | 1013 | if (allow_defer_var) { |
| 1019 | 1014 | return p.expectVarDeclExprStatement(null); |
| ... | ... | @@ -1028,12 +1023,15 @@ fn expectStatement(p: *Parse, allow_defer_var: bool) Error!Node.Index { |
| 1028 | 1023 | /// <- BlockExpr |
| 1029 | 1024 | /// / VarDeclExprStatement |
| 1030 | 1025 | fn expectComptimeStatement(p: *Parse, comptime_token: TokenIndex) !Node.Index { |
| 1031 | const block_expr = try p.parseBlockExpr(); | |
| 1032 | if (block_expr != 0) { | |
| 1026 | const maybe_block_expr = try p.parseBlockExpr(); | |
| 1027 | if (maybe_block_expr) |block_expr| { | |
| 1033 | 1028 | return p.addNode(.{ |
| 1034 | 1029 | .tag = .@"comptime", |
| 1035 | 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 | 1037 | return p.expectVarDeclExprStatement(comptime_token); |
| ... | ... | @@ -1047,12 +1045,11 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1047 | 1045 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 1048 | 1046 | |
| 1049 | 1047 | while (true) { |
| 1050 | const var_decl_proto = try p.parseVarDeclProto(); | |
| 1051 | if (var_decl_proto != 0) { | |
| 1052 | try p.scratch.append(p.gpa, var_decl_proto); | |
| 1048 | const opt_var_decl_proto = try p.parseVarDeclProto(); | |
| 1049 | if (opt_var_decl_proto) |var_decl| { | |
| 1050 | try p.scratch.append(p.gpa, var_decl); | |
| 1053 | 1051 | } else { |
| 1054 | const expr = try p.parseExpr(); | |
| 1055 | if (expr == 0) { | |
| 1052 | const expr = try p.parseExpr() orelse { | |
| 1056 | 1053 | if (p.scratch.items.len == scratch_top) { |
| 1057 | 1054 | // We parsed nothing |
| 1058 | 1055 | return p.fail(.expected_statement); |
| ... | ... | @@ -1060,7 +1057,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1060 | 1057 | // We've had at least one LHS, but had a bad comma |
| 1061 | 1058 | return p.fail(.expected_expr_or_var_decl); |
| 1062 | 1059 | } |
| 1063 | } | |
| 1060 | }; | |
| 1064 | 1061 | try p.scratch.append(p.gpa, expr); |
| 1065 | 1062 | } |
| 1066 | 1063 | _ = p.eatToken(.comma) orelse break; |
| ... | ... | @@ -1079,7 +1076,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1079 | 1076 | return p.failExpected(.equal); |
| 1080 | 1077 | } |
| 1081 | 1078 | const lhs = p.scratch.items[scratch_top]; |
| 1082 | switch (p.nodes.items(.tag)[lhs]) { | |
| 1079 | switch (p.nodeTag(lhs)) { | |
| 1083 | 1080 | .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => { |
| 1084 | 1081 | // Definitely a var decl, so allow recovering from == |
| 1085 | 1082 | if (p.eatToken(.equal_equal)) |tok| { |
| ... | ... | @@ -1097,10 +1094,7 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1097 | 1094 | return p.addNode(.{ |
| 1098 | 1095 | .tag = .@"comptime", |
| 1099 | 1096 | .main_token = t, |
| 1100 | .data = .{ | |
| 1101 | .lhs = expr, | |
| 1102 | .rhs = undefined, | |
| 1103 | }, | |
| 1097 | .data = .{ .node = expr }, | |
| 1104 | 1098 | }); |
| 1105 | 1099 | } else { |
| 1106 | 1100 | return expr; |
| ... | ... | @@ -1112,9 +1106,9 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1112 | 1106 | |
| 1113 | 1107 | if (lhs_count == 1) { |
| 1114 | 1108 | const lhs = p.scratch.items[scratch_top]; |
| 1115 | switch (p.nodes.items(.tag)[lhs]) { | |
| 1116 | .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => { | |
| 1117 | p.nodes.items(.data)[lhs].rhs = rhs; | |
| 1109 | switch (p.nodeTag(lhs)) { | |
| 1110 | .simple_var_decl, .aligned_var_decl, .local_var_decl, .global_var_decl => { | |
| 1111 | p.setVarDeclInitExpr(lhs, rhs.toOptional()); | |
| 1118 | 1112 | // Don't need to wrap in comptime |
| 1119 | 1113 | return lhs; |
| 1120 | 1114 | }, |
| ... | ... | @@ -1123,16 +1117,16 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1123 | 1117 | const expr = try p.addNode(.{ |
| 1124 | 1118 | .tag = .assign, |
| 1125 | 1119 | .main_token = equal_token, |
| 1126 | .data = .{ .lhs = lhs, .rhs = rhs }, | |
| 1120 | .data = .{ .node_and_node = .{ | |
| 1121 | lhs, | |
| 1122 | rhs, | |
| 1123 | } }, | |
| 1127 | 1124 | }); |
| 1128 | 1125 | if (comptime_token) |t| { |
| 1129 | 1126 | return p.addNode(.{ |
| 1130 | 1127 | .tag = .@"comptime", |
| 1131 | 1128 | .main_token = t, |
| 1132 | .data = .{ | |
| 1133 | .lhs = expr, | |
| 1134 | .rhs = undefined, | |
| 1135 | }, | |
| 1129 | .data = .{ .node = expr }, | |
| 1136 | 1130 | }); |
| 1137 | 1131 | } else { |
| 1138 | 1132 | return expr; |
| ... | ... | @@ -1141,32 +1135,32 @@ fn expectVarDeclExprStatement(p: *Parse, comptime_token: ?TokenIndex) !Node.Inde |
| 1141 | 1135 | |
| 1142 | 1136 | // An actual destructure! No need for any `comptime` wrapper here. |
| 1143 | 1137 | |
| 1144 | const extra_start = p.extra_data.items.len; | |
| 1138 | const extra_start: ExtraIndex = @enumFromInt(p.extra_data.items.len); | |
| 1145 | 1139 | try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1); |
| 1146 | 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..])); | |
| 1148 | 1142 | |
| 1149 | 1143 | return p.addNode(.{ |
| 1150 | 1144 | .tag = .assign_destructure, |
| 1151 | 1145 | .main_token = equal_token, |
| 1152 | .data = .{ | |
| 1153 | .lhs = @intCast(extra_start), | |
| 1154 | .rhs = rhs, | |
| 1155 | }, | |
| 1146 | .data = .{ .extra_and_node = .{ | |
| 1147 | extra_start, | |
| 1148 | rhs, | |
| 1149 | } }, | |
| 1156 | 1150 | }); |
| 1157 | 1151 | } |
| 1158 | 1152 | |
| 1159 | 1153 | /// If a parse error occurs, reports an error, but then finds the next statement |
| 1160 | 1154 | /// and returns that one instead. If a parse error occurs but there is no following |
| 1161 | 1155 | /// statement, returns 0. |
| 1162 | fn expectStatementRecoverable(p: *Parse) Error!Node.Index { | |
| 1156 | fn expectStatementRecoverable(p: *Parse) Error!?Node.Index { | |
| 1163 | 1157 | while (true) { |
| 1164 | 1158 | return p.expectStatement(true) catch |err| switch (err) { |
| 1165 | 1159 | error.OutOfMemory => return error.OutOfMemory, |
| 1166 | 1160 | error.ParseError => { |
| 1167 | 1161 | p.findNextStmt(); // Try to skip to the next statement. |
| 1168 | switch (p.token_tags[p.tok_i]) { | |
| 1169 | .r_brace => return null_node, | |
| 1162 | switch (p.tokenTag(p.tok_i)) { | |
| 1163 | .r_brace => return null, | |
| 1170 | 1164 | .eof => return error.ParseError, |
| 1171 | 1165 | else => continue, |
| 1172 | 1166 | } |
| ... | ... | @@ -1190,19 +1184,18 @@ fn expectIfStatement(p: *Parse) !Node.Index { |
| 1190 | 1184 | var else_required = false; |
| 1191 | 1185 | const then_expr = blk: { |
| 1192 | 1186 | const block_expr = try p.parseBlockExpr(); |
| 1193 | if (block_expr != 0) break :blk block_expr; | |
| 1194 | const assign_expr = try p.parseAssignExpr(); | |
| 1195 | if (assign_expr == 0) { | |
| 1187 | if (block_expr) |block| break :blk block; | |
| 1188 | const assign_expr = try p.parseAssignExpr() orelse { | |
| 1196 | 1189 | return p.fail(.expected_block_or_assignment); |
| 1197 | } | |
| 1190 | }; | |
| 1198 | 1191 | if (p.eatToken(.semicolon)) |_| { |
| 1199 | 1192 | return p.addNode(.{ |
| 1200 | 1193 | .tag = .if_simple, |
| 1201 | 1194 | .main_token = if_token, |
| 1202 | .data = .{ | |
| 1203 | .lhs = condition, | |
| 1204 | .rhs = assign_expr, | |
| 1205 | }, | |
| 1195 | .data = .{ .node_and_node = .{ | |
| 1196 | condition, | |
| 1197 | assign_expr, | |
| 1198 | } }, | |
| 1206 | 1199 | }); |
| 1207 | 1200 | } |
| 1208 | 1201 | else_required = true; |
| ... | ... | @@ -1215,10 +1208,10 @@ fn expectIfStatement(p: *Parse) !Node.Index { |
| 1215 | 1208 | return p.addNode(.{ |
| 1216 | 1209 | .tag = .if_simple, |
| 1217 | 1210 | .main_token = if_token, |
| 1218 | .data = .{ | |
| 1219 | .lhs = condition, | |
| 1220 | .rhs = then_expr, | |
| 1221 | }, | |
| 1211 | .data = .{ .node_and_node = .{ | |
| 1212 | condition, | |
| 1213 | then_expr, | |
| 1214 | } }, | |
| 1222 | 1215 | }); |
| 1223 | 1216 | }; |
| 1224 | 1217 | _ = try p.parsePayload(); |
| ... | ... | @@ -1226,57 +1219,46 @@ fn expectIfStatement(p: *Parse) !Node.Index { |
| 1226 | 1219 | return p.addNode(.{ |
| 1227 | 1220 | .tag = .@"if", |
| 1228 | 1221 | .main_token = if_token, |
| 1229 | .data = .{ | |
| 1230 | .lhs = condition, | |
| 1231 | .rhs = try p.addExtra(Node.If{ | |
| 1222 | .data = .{ .node_and_extra = .{ | |
| 1223 | condition, try p.addExtra(Node.If{ | |
| 1232 | 1224 | .then_expr = then_expr, |
| 1233 | 1225 | .else_expr = else_expr, |
| 1234 | 1226 | }), |
| 1235 | }, | |
| 1227 | } }, | |
| 1236 | 1228 | }); |
| 1237 | 1229 | } |
| 1238 | 1230 | |
| 1239 | 1231 | /// LabeledStatement <- BlockLabel? (Block / LoopStatement / SwitchExpr) |
| 1240 | fn parseLabeledStatement(p: *Parse) !Node.Index { | |
| 1241 | const label_token = p.parseBlockLabel(); | |
| 1242 | const block = try p.parseBlock(); | |
| 1243 | if (block != 0) return block; | |
| 1244 | ||
| 1245 | const loop_stmt = try p.parseLoopStatement(); | |
| 1246 | if (loop_stmt != 0) return loop_stmt; | |
| 1247 | ||
| 1248 | const switch_expr = try p.parseSwitchExpr(label_token != 0); | |
| 1249 | if (switch_expr != 0) return switch_expr; | |
| 1250 | ||
| 1251 | if (label_token != 0) { | |
| 1252 | const after_colon = p.tok_i; | |
| 1253 | const node = try p.parseTypeExpr(); | |
| 1254 | if (node != 0) { | |
| 1255 | const a = try p.parseByteAlign(); | |
| 1256 | const b = try p.parseAddrSpace(); | |
| 1257 | const c = try p.parseLinkSection(); | |
| 1258 | const d = if (p.eatToken(.equal) == null) 0 else try p.expectExpr(); | |
| 1259 | if (a != 0 or b != 0 or c != 0 or d != 0) { | |
| 1260 | return p.failMsg(.{ .tag = .expected_var_const, .token = label_token }); | |
| 1261 | } | |
| 1232 | fn parseLabeledStatement(p: *Parse) !?Node.Index { | |
| 1233 | const opt_label_token = p.parseBlockLabel(); | |
| 1234 | ||
| 1235 | if (try p.parseBlock()) |block| return block; | |
| 1236 | if (try p.parseLoopStatement()) |loop_stmt| return loop_stmt; | |
| 1237 | if (try p.parseSwitchExpr(opt_label_token != null)) |switch_expr| return switch_expr; | |
| 1238 | ||
| 1239 | const label_token = opt_label_token orelse return null; | |
| 1240 | ||
| 1241 | const after_colon = p.tok_i; | |
| 1242 | if (try p.parseTypeExpr()) |_| { | |
| 1243 | const a = try p.parseByteAlign(); | |
| 1244 | const b = try p.parseAddrSpace(); | |
| 1245 | const c = try p.parseLinkSection(); | |
| 1246 | const d = if (p.eatToken(.equal) == null) null else try p.expectExpr(); | |
| 1247 | if (a != null or b != null or c != null or d != null) { | |
| 1248 | return p.failMsg(.{ .tag = .expected_var_const, .token = label_token }); | |
| 1262 | 1249 | } |
| 1263 | return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon }); | |
| 1264 | 1250 | } |
| 1265 | ||
| 1266 | return null_node; | |
| 1251 | return p.failMsg(.{ .tag = .expected_labelable, .token = after_colon }); | |
| 1267 | 1252 | } |
| 1268 | 1253 | |
| 1269 | 1254 | /// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement) |
| 1270 | fn parseLoopStatement(p: *Parse) !Node.Index { | |
| 1255 | fn parseLoopStatement(p: *Parse) !?Node.Index { | |
| 1271 | 1256 | const inline_token = p.eatToken(.keyword_inline); |
| 1272 | 1257 | |
| 1273 | const for_statement = try p.parseForStatement(); | |
| 1274 | if (for_statement != 0) return for_statement; | |
| 1258 | if (try p.parseForStatement()) |for_statement| return for_statement; | |
| 1259 | if (try p.parseWhileStatement()) |while_statement| return while_statement; | |
| 1275 | 1260 | |
| 1276 | const while_statement = try p.parseWhileStatement(); | |
| 1277 | if (while_statement != 0) return while_statement; | |
| 1278 | ||
| 1279 | if (inline_token == null) return null_node; | |
| 1261 | if (inline_token == null) return null; | |
| 1280 | 1262 | |
| 1281 | 1263 | // If we've seen "inline", there should have been a "for" or "while" |
| 1282 | 1264 | return p.fail(.expected_inlinable); |
| ... | ... | @@ -1285,8 +1267,8 @@ fn parseLoopStatement(p: *Parse) !Node.Index { |
| 1285 | 1267 | /// ForStatement |
| 1286 | 1268 | /// <- ForPrefix BlockExpr ( KEYWORD_else Statement )? |
| 1287 | 1269 | /// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement ) |
| 1288 | fn parseForStatement(p: *Parse) !Node.Index { | |
| 1289 | const for_token = p.eatToken(.keyword_for) orelse return null_node; | |
| 1270 | fn parseForStatement(p: *Parse) !?Node.Index { | |
| 1271 | const for_token = p.eatToken(.keyword_for) orelse return null; | |
| 1290 | 1272 | |
| 1291 | 1273 | const scratch_top = p.scratch.items.len; |
| 1292 | 1274 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| ... | ... | @@ -1296,11 +1278,10 @@ fn parseForStatement(p: *Parse) !Node.Index { |
| 1296 | 1278 | var seen_semicolon = false; |
| 1297 | 1279 | const then_expr = blk: { |
| 1298 | 1280 | const block_expr = try p.parseBlockExpr(); |
| 1299 | if (block_expr != 0) break :blk block_expr; | |
| 1300 | const assign_expr = try p.parseAssignExpr(); | |
| 1301 | if (assign_expr == 0) { | |
| 1281 | if (block_expr) |block| break :blk block; | |
| 1282 | const assign_expr = try p.parseAssignExpr() orelse { | |
| 1302 | 1283 | return p.fail(.expected_block_or_assignment); |
| 1303 | } | |
| 1284 | }; | |
| 1304 | 1285 | if (p.eatToken(.semicolon)) |_| { |
| 1305 | 1286 | seen_semicolon = true; |
| 1306 | 1287 | break :blk assign_expr; |
| ... | ... | @@ -1316,28 +1297,25 @@ fn parseForStatement(p: *Parse) !Node.Index { |
| 1316 | 1297 | has_else = true; |
| 1317 | 1298 | } else if (inputs == 1) { |
| 1318 | 1299 | if (else_required) try p.warn(.expected_semi_or_else); |
| 1319 | return p.addNode(.{ | |
| 1300 | return try p.addNode(.{ | |
| 1320 | 1301 | .tag = .for_simple, |
| 1321 | 1302 | .main_token = for_token, |
| 1322 | .data = .{ | |
| 1323 | .lhs = p.scratch.items[scratch_top], | |
| 1324 | .rhs = then_expr, | |
| 1325 | }, | |
| 1303 | .data = .{ .node_and_node = .{ | |
| 1304 | p.scratch.items[scratch_top], | |
| 1305 | then_expr, | |
| 1306 | } }, | |
| 1326 | 1307 | }); |
| 1327 | 1308 | } else { |
| 1328 | 1309 | if (else_required) try p.warn(.expected_semi_or_else); |
| 1329 | 1310 | try p.scratch.append(p.gpa, then_expr); |
| 1330 | 1311 | } |
| 1331 | return p.addNode(.{ | |
| 1312 | return try p.addNode(.{ | |
| 1332 | 1313 | .tag = .@"for", |
| 1333 | 1314 | .main_token = for_token, |
| 1334 | .data = .{ | |
| 1335 | .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 1336 | .rhs = @as(u32, @bitCast(Node.For{ | |
| 1337 | .inputs = @as(u31, @intCast(inputs)), | |
| 1338 | .has_else = has_else, | |
| 1339 | })), | |
| 1340 | }, | |
| 1315 | .data = .{ .@"for" = .{ | |
| 1316 | (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 1317 | .{ .inputs = @intCast(inputs), .has_else = has_else }, | |
| 1318 | } }, | |
| 1341 | 1319 | }); |
| 1342 | 1320 | } |
| 1343 | 1321 | |
| ... | ... | @@ -1346,8 +1324,8 @@ fn parseForStatement(p: *Parse) !Node.Index { |
| 1346 | 1324 | /// WhileStatement |
| 1347 | 1325 | /// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )? |
| 1348 | 1326 | /// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement ) |
| 1349 | fn parseWhileStatement(p: *Parse) !Node.Index { | |
| 1350 | const while_token = p.eatToken(.keyword_while) orelse return null_node; | |
| 1327 | fn parseWhileStatement(p: *Parse) !?Node.Index { | |
| 1328 | const while_token = p.eatToken(.keyword_while) orelse return null; | |
| 1351 | 1329 | _ = try p.expectToken(.l_paren); |
| 1352 | 1330 | const condition = try p.expectExpr(); |
| 1353 | 1331 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -1359,32 +1337,31 @@ fn parseWhileStatement(p: *Parse) !Node.Index { |
| 1359 | 1337 | var else_required = false; |
| 1360 | 1338 | const then_expr = blk: { |
| 1361 | 1339 | const block_expr = try p.parseBlockExpr(); |
| 1362 | if (block_expr != 0) break :blk block_expr; | |
| 1363 | const assign_expr = try p.parseAssignExpr(); | |
| 1364 | if (assign_expr == 0) { | |
| 1340 | if (block_expr) |block| break :blk block; | |
| 1341 | const assign_expr = try p.parseAssignExpr() orelse { | |
| 1365 | 1342 | return p.fail(.expected_block_or_assignment); |
| 1366 | } | |
| 1343 | }; | |
| 1367 | 1344 | if (p.eatToken(.semicolon)) |_| { |
| 1368 | if (cont_expr == 0) { | |
| 1369 | return p.addNode(.{ | |
| 1345 | if (cont_expr == null) { | |
| 1346 | return try p.addNode(.{ | |
| 1370 | 1347 | .tag = .while_simple, |
| 1371 | 1348 | .main_token = while_token, |
| 1372 | .data = .{ | |
| 1373 | .lhs = condition, | |
| 1374 | .rhs = assign_expr, | |
| 1375 | }, | |
| 1349 | .data = .{ .node_and_node = .{ | |
| 1350 | condition, | |
| 1351 | assign_expr, | |
| 1352 | } }, | |
| 1376 | 1353 | }); |
| 1377 | 1354 | } else { |
| 1378 | return p.addNode(.{ | |
| 1355 | return try p.addNode(.{ | |
| 1379 | 1356 | .tag = .while_cont, |
| 1380 | 1357 | .main_token = while_token, |
| 1381 | .data = .{ | |
| 1382 | .lhs = condition, | |
| 1383 | .rhs = try p.addExtra(Node.WhileCont{ | |
| 1384 | .cont_expr = cont_expr, | |
| 1358 | .data = .{ .node_and_extra = .{ | |
| 1359 | condition, | |
| 1360 | try p.addExtra(Node.WhileCont{ | |
| 1361 | .cont_expr = cont_expr.?, | |
| 1385 | 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 | 1372 | if (else_required) { |
| 1396 | 1373 | try p.warn(.expected_semi_or_else); |
| 1397 | 1374 | } |
| 1398 | if (cont_expr == 0) { | |
| 1399 | return p.addNode(.{ | |
| 1375 | if (cont_expr == null) { | |
| 1376 | return try p.addNode(.{ | |
| 1400 | 1377 | .tag = .while_simple, |
| 1401 | 1378 | .main_token = while_token, |
| 1402 | .data = .{ | |
| 1403 | .lhs = condition, | |
| 1404 | .rhs = then_expr, | |
| 1405 | }, | |
| 1379 | .data = .{ .node_and_node = .{ | |
| 1380 | condition, | |
| 1381 | then_expr, | |
| 1382 | } }, | |
| 1406 | 1383 | }); |
| 1407 | 1384 | } else { |
| 1408 | return p.addNode(.{ | |
| 1385 | return try p.addNode(.{ | |
| 1409 | 1386 | .tag = .while_cont, |
| 1410 | 1387 | .main_token = while_token, |
| 1411 | .data = .{ | |
| 1412 | .lhs = condition, | |
| 1413 | .rhs = try p.addExtra(Node.WhileCont{ | |
| 1414 | .cont_expr = cont_expr, | |
| 1388 | .data = .{ .node_and_extra = .{ | |
| 1389 | condition, | |
| 1390 | try p.addExtra(Node.WhileCont{ | |
| 1391 | .cont_expr = cont_expr.?, | |
| 1415 | 1392 | .then_expr = then_expr, |
| 1416 | 1393 | }), |
| 1417 | }, | |
| 1394 | } }, | |
| 1418 | 1395 | }); |
| 1419 | 1396 | } |
| 1420 | 1397 | }; |
| 1421 | 1398 | _ = try p.parsePayload(); |
| 1422 | 1399 | const else_expr = try p.expectStatement(false); |
| 1423 | return p.addNode(.{ | |
| 1400 | return try p.addNode(.{ | |
| 1424 | 1401 | .tag = .@"while", |
| 1425 | 1402 | .main_token = while_token, |
| 1426 | .data = .{ | |
| 1427 | .lhs = condition, | |
| 1428 | .rhs = try p.addExtra(Node.While{ | |
| 1429 | .cont_expr = cont_expr, | |
| 1403 | .data = .{ .node_and_extra = .{ | |
| 1404 | condition, try p.addExtra(Node.While{ | |
| 1405 | .cont_expr = .fromOptional(cont_expr), | |
| 1430 | 1406 | .then_expr = then_expr, |
| 1431 | 1407 | .else_expr = else_expr, |
| 1432 | 1408 | }), |
| 1433 | }, | |
| 1409 | } }, | |
| 1434 | 1410 | }); |
| 1435 | 1411 | } |
| 1436 | 1412 | |
| 1437 | 1413 | /// BlockExprStatement |
| 1438 | 1414 | /// <- BlockExpr |
| 1439 | 1415 | /// / AssignExpr SEMICOLON |
| 1440 | fn parseBlockExprStatement(p: *Parse) !Node.Index { | |
| 1416 | fn parseBlockExprStatement(p: *Parse) !?Node.Index { | |
| 1441 | 1417 | const block_expr = try p.parseBlockExpr(); |
| 1442 | if (block_expr != 0) { | |
| 1443 | return block_expr; | |
| 1444 | } | |
| 1418 | if (block_expr) |expr| return expr; | |
| 1445 | 1419 | const assign_expr = try p.parseAssignExpr(); |
| 1446 | if (assign_expr != 0) { | |
| 1420 | if (assign_expr) |expr| { | |
| 1447 | 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 | } |
| 1452 | 1426 | |
| 1453 | 1427 | fn expectBlockExprStatement(p: *Parse) !Node.Index { |
| 1454 | const node = try p.parseBlockExprStatement(); | |
| 1455 | if (node == 0) { | |
| 1456 | return p.fail(.expected_block_or_expr); | |
| 1457 | } | |
| 1458 | return node; | |
| 1428 | return try p.parseBlockExprStatement() orelse return p.fail(.expected_block_or_expr); | |
| 1459 | 1429 | } |
| 1460 | 1430 | |
| 1461 | 1431 | /// BlockExpr <- BlockLabel? Block |
| 1462 | fn parseBlockExpr(p: *Parse) Error!Node.Index { | |
| 1463 | switch (p.token_tags[p.tok_i]) { | |
| 1432 | fn parseBlockExpr(p: *Parse) Error!?Node.Index { | |
| 1433 | switch (p.tokenTag(p.tok_i)) { | |
| 1464 | 1434 | .identifier => { |
| 1465 | if (p.token_tags[p.tok_i + 1] == .colon and | |
| 1466 | p.token_tags[p.tok_i + 2] == .l_brace) | |
| 1435 | if (p.tokenTag(p.tok_i + 1) == .colon and | |
| 1436 | p.tokenTag(p.tok_i + 2) == .l_brace) | |
| 1467 | 1437 | { |
| 1468 | 1438 | p.tok_i += 2; |
| 1469 | 1439 | return p.parseBlock(); |
| 1470 | 1440 | } else { |
| 1471 | return null_node; | |
| 1441 | return null; | |
| 1472 | 1442 | } |
| 1473 | 1443 | }, |
| 1474 | 1444 | .l_brace => return p.parseBlock(), |
| 1475 | else => return null_node, | |
| 1445 | else => return null, | |
| 1476 | 1446 | } |
| 1477 | 1447 | } |
| 1478 | 1448 | |
| ... | ... | @@ -1497,38 +1467,36 @@ fn parseBlockExpr(p: *Parse) Error!Node.Index { |
| 1497 | 1467 | /// / PLUSPERCENTEQUAL |
| 1498 | 1468 | /// / MINUSPERCENTEQUAL |
| 1499 | 1469 | /// / EQUAL |
| 1500 | fn parseAssignExpr(p: *Parse) !Node.Index { | |
| 1501 | const expr = try p.parseExpr(); | |
| 1502 | if (expr == 0) return null_node; | |
| 1503 | return p.finishAssignExpr(expr); | |
| 1470 | fn parseAssignExpr(p: *Parse) !?Node.Index { | |
| 1471 | const expr = try p.parseExpr() orelse return null; | |
| 1472 | return try p.finishAssignExpr(expr); | |
| 1504 | 1473 | } |
| 1505 | 1474 | |
| 1506 | 1475 | /// SingleAssignExpr <- Expr (AssignOp Expr)? |
| 1507 | fn parseSingleAssignExpr(p: *Parse) !Node.Index { | |
| 1508 | const lhs = try p.parseExpr(); | |
| 1509 | if (lhs == 0) return null_node; | |
| 1510 | const tag = assignOpNode(p.token_tags[p.tok_i]) orelse return lhs; | |
| 1511 | return p.addNode(.{ | |
| 1476 | fn parseSingleAssignExpr(p: *Parse) !?Node.Index { | |
| 1477 | const lhs = try p.parseExpr() orelse return null; | |
| 1478 | const tag = assignOpNode(p.tokenTag(p.tok_i)) orelse return lhs; | |
| 1479 | return try p.addNode(.{ | |
| 1512 | 1480 | .tag = tag, |
| 1513 | 1481 | .main_token = p.nextToken(), |
| 1514 | .data = .{ | |
| 1515 | .lhs = lhs, | |
| 1516 | .rhs = try p.expectExpr(), | |
| 1517 | }, | |
| 1482 | .data = .{ .node_and_node = .{ | |
| 1483 | lhs, | |
| 1484 | try p.expectExpr(), | |
| 1485 | } }, | |
| 1518 | 1486 | }); |
| 1519 | 1487 | } |
| 1520 | 1488 | |
| 1521 | 1489 | fn 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 | 1491 | if (tok == .comma) return p.finishAssignDestructureExpr(lhs); |
| 1524 | 1492 | const tag = assignOpNode(tok) orelse return lhs; |
| 1525 | 1493 | return p.addNode(.{ |
| 1526 | 1494 | .tag = tag, |
| 1527 | 1495 | .main_token = p.nextToken(), |
| 1528 | .data = .{ | |
| 1529 | .lhs = lhs, | |
| 1530 | .rhs = try p.expectExpr(), | |
| 1531 | }, | |
| 1496 | .data = .{ .node_and_node = .{ | |
| 1497 | lhs, | |
| 1498 | try p.expectExpr(), | |
| 1499 | } }, | |
| 1532 | 1500 | }); |
| 1533 | 1501 | } |
| 1534 | 1502 | |
| ... | ... | @@ -1574,48 +1542,35 @@ fn finishAssignDestructureExpr(p: *Parse, first_lhs: Node.Index) !Node.Index { |
| 1574 | 1542 | const lhs_count = p.scratch.items.len - scratch_top; |
| 1575 | 1543 | assert(lhs_count > 1); // we already had first_lhs, and must have at least one more lvalue |
| 1576 | 1544 | |
| 1577 | const extra_start = p.extra_data.items.len; | |
| 1545 | const extra_start: ExtraIndex = @enumFromInt(p.extra_data.items.len); | |
| 1578 | 1546 | try p.extra_data.ensureUnusedCapacity(p.gpa, lhs_count + 1); |
| 1579 | 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..])); | |
| 1581 | 1549 | |
| 1582 | 1550 | return p.addNode(.{ |
| 1583 | 1551 | .tag = .assign_destructure, |
| 1584 | 1552 | .main_token = equal_token, |
| 1585 | .data = .{ | |
| 1586 | .lhs = @intCast(extra_start), | |
| 1587 | .rhs = rhs, | |
| 1588 | }, | |
| 1553 | .data = .{ .extra_and_node = .{ | |
| 1554 | extra_start, | |
| 1555 | rhs, | |
| 1556 | } }, | |
| 1589 | 1557 | }); |
| 1590 | 1558 | } |
| 1591 | 1559 | |
| 1592 | 1560 | fn expectSingleAssignExpr(p: *Parse) !Node.Index { |
| 1593 | const expr = try p.parseSingleAssignExpr(); | |
| 1594 | if (expr == 0) { | |
| 1595 | return p.fail(.expected_expr_or_assignment); | |
| 1596 | } | |
| 1597 | return expr; | |
| 1561 | return try p.parseSingleAssignExpr() orelse return p.fail(.expected_expr_or_assignment); | |
| 1598 | 1562 | } |
| 1599 | 1563 | |
| 1600 | 1564 | fn expectAssignExpr(p: *Parse) !Node.Index { |
| 1601 | const expr = try p.parseAssignExpr(); | |
| 1602 | if (expr == 0) { | |
| 1603 | return p.fail(.expected_expr_or_assignment); | |
| 1604 | } | |
| 1605 | return expr; | |
| 1565 | return try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment); | |
| 1606 | 1566 | } |
| 1607 | 1567 | |
| 1608 | fn parseExpr(p: *Parse) Error!Node.Index { | |
| 1568 | fn parseExpr(p: *Parse) Error!?Node.Index { | |
| 1609 | 1569 | return p.parseExprPrecedence(0); |
| 1610 | 1570 | } |
| 1611 | 1571 | |
| 1612 | 1572 | fn expectExpr(p: *Parse) Error!Node.Index { |
| 1613 | const node = try p.parseExpr(); | |
| 1614 | if (node == 0) { | |
| 1615 | return p.fail(.expected_expr); | |
| 1616 | } else { | |
| 1617 | return node; | |
| 1618 | } | |
| 1573 | return try p.parseExpr() orelse return p.fail(.expected_expr); | |
| 1619 | 1574 | } |
| 1620 | 1575 | |
| 1621 | 1576 | const Assoc = enum { |
| ... | ... | @@ -1671,17 +1626,14 @@ const operTable = std.enums.directEnumArrayDefault(Token.Tag, OperInfo, .{ .prec |
| 1671 | 1626 | .asterisk_pipe = .{ .prec = 70, .tag = .mul_sat }, |
| 1672 | 1627 | }); |
| 1673 | 1628 | |
| 1674 | fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index { | |
| 1629 | fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!?Node.Index { | |
| 1675 | 1630 | assert(min_prec >= 0); |
| 1676 | var node = try p.parsePrefixExpr(); | |
| 1677 | if (node == 0) { | |
| 1678 | return null_node; | |
| 1679 | } | |
| 1631 | var node = try p.parsePrefixExpr() orelse return null; | |
| 1680 | 1632 | |
| 1681 | 1633 | var banned_prec: i8 = -1; |
| 1682 | 1634 | |
| 1683 | 1635 | while (true) { |
| 1684 | const tok_tag = p.token_tags[p.tok_i]; | |
| 1636 | const tok_tag = p.tokenTag(p.tok_i); | |
| 1685 | 1637 | const info = operTable[@as(usize, @intCast(@intFromEnum(tok_tag)))]; |
| 1686 | 1638 | if (info.prec < min_prec) { |
| 1687 | 1639 | break; |
| ... | ... | @@ -1695,16 +1647,15 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index { |
| 1695 | 1647 | if (tok_tag == .keyword_catch) { |
| 1696 | 1648 | _ = try p.parsePayload(); |
| 1697 | 1649 | } |
| 1698 | const rhs = try p.parseExprPrecedence(info.prec + 1); | |
| 1699 | if (rhs == 0) { | |
| 1650 | const rhs = try p.parseExprPrecedence(info.prec + 1) orelse { | |
| 1700 | 1651 | try p.warn(.expected_expr); |
| 1701 | 1652 | return node; |
| 1702 | } | |
| 1653 | }; | |
| 1703 | 1654 | |
| 1704 | 1655 | { |
| 1705 | 1656 | const tok_len = tok_tag.lexeme().?.len; |
| 1706 | const char_before = p.source[p.token_starts[oper_token] - 1]; | |
| 1707 | const char_after = p.source[p.token_starts[oper_token] + tok_len]; | |
| 1657 | const char_before = p.source[p.tokenStart(oper_token) - 1]; | |
| 1658 | const char_after = p.source[p.tokenStart(oper_token) + tok_len]; | |
| 1708 | 1659 | if (tok_tag == .ampersand and char_after == '&') { |
| 1709 | 1660 | // without types we don't know if '&&' was intended as 'bitwise_and address_of', or a c-style logical_and |
| 1710 | 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 | 1668 | node = try p.addNode(.{ |
| 1718 | 1669 | .tag = info.tag, |
| 1719 | 1670 | .main_token = oper_token, |
| 1720 | .data = .{ | |
| 1721 | .lhs = node, | |
| 1722 | .rhs = rhs, | |
| 1723 | }, | |
| 1671 | .data = .{ .node_and_node = .{ node, rhs } }, | |
| 1724 | 1672 | }); |
| 1725 | 1673 | |
| 1726 | 1674 | if (info.assoc == Assoc.none) { |
| ... | ... | @@ -1741,8 +1689,8 @@ fn parseExprPrecedence(p: *Parse, min_prec: i32) Error!Node.Index { |
| 1741 | 1689 | /// / AMPERSAND |
| 1742 | 1690 | /// / KEYWORD_try |
| 1743 | 1691 | /// / KEYWORD_await |
| 1744 | fn parsePrefixExpr(p: *Parse) Error!Node.Index { | |
| 1745 | const tag: Node.Tag = switch (p.token_tags[p.tok_i]) { | |
| 1692 | fn parsePrefixExpr(p: *Parse) Error!?Node.Index { | |
| 1693 | const tag: Node.Tag = switch (p.tokenTag(p.tok_i)) { | |
| 1746 | 1694 | .bang => .bool_not, |
| 1747 | 1695 | .minus => .negation, |
| 1748 | 1696 | .tilde => .bit_not, |
| ... | ... | @@ -1752,22 +1700,15 @@ fn parsePrefixExpr(p: *Parse) Error!Node.Index { |
| 1752 | 1700 | .keyword_await => .@"await", |
| 1753 | 1701 | else => return p.parsePrimaryExpr(), |
| 1754 | 1702 | }; |
| 1755 | return p.addNode(.{ | |
| 1703 | return try p.addNode(.{ | |
| 1756 | 1704 | .tag = tag, |
| 1757 | 1705 | .main_token = p.nextToken(), |
| 1758 | .data = .{ | |
| 1759 | .lhs = try p.expectPrefixExpr(), | |
| 1760 | .rhs = undefined, | |
| 1761 | }, | |
| 1706 | .data = .{ .node = try p.expectPrefixExpr() }, | |
| 1762 | 1707 | }); |
| 1763 | 1708 | } |
| 1764 | 1709 | |
| 1765 | 1710 | fn expectPrefixExpr(p: *Parse) Error!Node.Index { |
| 1766 | const node = try p.parsePrefixExpr(); | |
| 1767 | if (node == 0) { | |
| 1768 | return p.fail(.expected_prefix_expr); | |
| 1769 | } | |
| 1770 | return node; | |
| 1711 | return try p.parsePrefixExpr() orelse return p.fail(.expected_prefix_expr); | |
| 1771 | 1712 | } |
| 1772 | 1713 | |
| 1773 | 1714 | /// TypeExpr <- PrefixTypeOp* ErrorUnionExpr |
| ... | ... | @@ -1787,67 +1728,64 @@ fn expectPrefixExpr(p: *Parse) Error!Node.Index { |
| 1787 | 1728 | /// / LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET |
| 1788 | 1729 | /// |
| 1789 | 1730 | /// ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET |
| 1790 | fn parseTypeExpr(p: *Parse) Error!Node.Index { | |
| 1791 | switch (p.token_tags[p.tok_i]) { | |
| 1792 | .question_mark => return p.addNode(.{ | |
| 1731 | fn parseTypeExpr(p: *Parse) Error!?Node.Index { | |
| 1732 | switch (p.tokenTag(p.tok_i)) { | |
| 1733 | .question_mark => return try p.addNode(.{ | |
| 1793 | 1734 | .tag = .optional_type, |
| 1794 | 1735 | .main_token = p.nextToken(), |
| 1795 | .data = .{ | |
| 1796 | .lhs = try p.expectTypeExpr(), | |
| 1797 | .rhs = undefined, | |
| 1798 | }, | |
| 1736 | .data = .{ .node = try p.expectTypeExpr() }, | |
| 1799 | 1737 | }), |
| 1800 | .keyword_anyframe => switch (p.token_tags[p.tok_i + 1]) { | |
| 1801 | .arrow => return p.addNode(.{ | |
| 1738 | .keyword_anyframe => switch (p.tokenTag(p.tok_i + 1)) { | |
| 1739 | .arrow => return try p.addNode(.{ | |
| 1802 | 1740 | .tag = .anyframe_type, |
| 1803 | 1741 | .main_token = p.nextToken(), |
| 1804 | .data = .{ | |
| 1805 | .lhs = p.nextToken(), | |
| 1806 | .rhs = try p.expectTypeExpr(), | |
| 1807 | }, | |
| 1742 | .data = .{ .token_and_node = .{ | |
| 1743 | p.nextToken(), | |
| 1744 | try p.expectTypeExpr(), | |
| 1745 | } }, | |
| 1808 | 1746 | }), |
| 1809 | else => return p.parseErrorUnionExpr(), | |
| 1747 | else => return try p.parseErrorUnionExpr(), | |
| 1810 | 1748 | }, |
| 1811 | 1749 | .asterisk => { |
| 1812 | 1750 | const asterisk = p.nextToken(); |
| 1813 | 1751 | const mods = try p.parsePtrModifiers(); |
| 1814 | 1752 | const elem_type = try p.expectTypeExpr(); |
| 1815 | if (mods.bit_range_start != 0) { | |
| 1816 | return p.addNode(.{ | |
| 1753 | if (mods.bit_range_start != .none) { | |
| 1754 | return try p.addNode(.{ | |
| 1817 | 1755 | .tag = .ptr_type_bit_range, |
| 1818 | 1756 | .main_token = asterisk, |
| 1819 | .data = .{ | |
| 1820 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1821 | .sentinel = 0, | |
| 1822 | .align_node = mods.align_node, | |
| 1757 | .data = .{ .extra_and_node = .{ | |
| 1758 | try p.addExtra(Node.PtrTypeBitRange{ | |
| 1759 | .sentinel = .none, | |
| 1760 | .align_node = mods.align_node.unwrap().?, | |
| 1823 | 1761 | .addrspace_node = mods.addrspace_node, |
| 1824 | .bit_range_start = mods.bit_range_start, | |
| 1825 | .bit_range_end = mods.bit_range_end, | |
| 1762 | .bit_range_start = mods.bit_range_start.unwrap().?, | |
| 1763 | .bit_range_end = mods.bit_range_end.unwrap().?, | |
| 1826 | 1764 | }), |
| 1827 | .rhs = elem_type, | |
| 1828 | }, | |
| 1765 | elem_type, | |
| 1766 | } }, | |
| 1829 | 1767 | }); |
| 1830 | } else if (mods.addrspace_node != 0) { | |
| 1831 | return p.addNode(.{ | |
| 1768 | } else if (mods.addrspace_node != .none) { | |
| 1769 | return try p.addNode(.{ | |
| 1832 | 1770 | .tag = .ptr_type, |
| 1833 | 1771 | .main_token = asterisk, |
| 1834 | .data = .{ | |
| 1835 | .lhs = try p.addExtra(Node.PtrType{ | |
| 1836 | .sentinel = 0, | |
| 1772 | .data = .{ .extra_and_node = .{ | |
| 1773 | try p.addExtra(Node.PtrType{ | |
| 1774 | .sentinel = .none, | |
| 1837 | 1775 | .align_node = mods.align_node, |
| 1838 | 1776 | .addrspace_node = mods.addrspace_node, |
| 1839 | 1777 | }), |
| 1840 | .rhs = elem_type, | |
| 1841 | }, | |
| 1778 | elem_type, | |
| 1779 | } }, | |
| 1842 | 1780 | }); |
| 1843 | 1781 | } else { |
| 1844 | return p.addNode(.{ | |
| 1782 | return try p.addNode(.{ | |
| 1845 | 1783 | .tag = .ptr_type_aligned, |
| 1846 | 1784 | .main_token = asterisk, |
| 1847 | .data = .{ | |
| 1848 | .lhs = mods.align_node, | |
| 1849 | .rhs = elem_type, | |
| 1850 | }, | |
| 1785 | .data = .{ .opt_node_and_node = .{ | |
| 1786 | mods.align_node, | |
| 1787 | elem_type, | |
| 1788 | } }, | |
| 1851 | 1789 | }); |
| 1852 | 1790 | } |
| 1853 | 1791 | }, |
| ... | ... | @@ -1856,61 +1794,61 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index { |
| 1856 | 1794 | const mods = try p.parsePtrModifiers(); |
| 1857 | 1795 | const elem_type = try p.expectTypeExpr(); |
| 1858 | 1796 | const inner: Node.Index = inner: { |
| 1859 | if (mods.bit_range_start != 0) { | |
| 1797 | if (mods.bit_range_start != .none) { | |
| 1860 | 1798 | break :inner try p.addNode(.{ |
| 1861 | 1799 | .tag = .ptr_type_bit_range, |
| 1862 | 1800 | .main_token = asterisk, |
| 1863 | .data = .{ | |
| 1864 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1865 | .sentinel = 0, | |
| 1866 | .align_node = mods.align_node, | |
| 1801 | .data = .{ .extra_and_node = .{ | |
| 1802 | try p.addExtra(Node.PtrTypeBitRange{ | |
| 1803 | .sentinel = .none, | |
| 1804 | .align_node = mods.align_node.unwrap().?, | |
| 1867 | 1805 | .addrspace_node = mods.addrspace_node, |
| 1868 | .bit_range_start = mods.bit_range_start, | |
| 1869 | .bit_range_end = mods.bit_range_end, | |
| 1806 | .bit_range_start = mods.bit_range_start.unwrap().?, | |
| 1807 | .bit_range_end = mods.bit_range_end.unwrap().?, | |
| 1870 | 1808 | }), |
| 1871 | .rhs = elem_type, | |
| 1872 | }, | |
| 1809 | elem_type, | |
| 1810 | } }, | |
| 1873 | 1811 | }); |
| 1874 | } else if (mods.addrspace_node != 0) { | |
| 1812 | } else if (mods.addrspace_node != .none) { | |
| 1875 | 1813 | break :inner try p.addNode(.{ |
| 1876 | 1814 | .tag = .ptr_type, |
| 1877 | 1815 | .main_token = asterisk, |
| 1878 | .data = .{ | |
| 1879 | .lhs = try p.addExtra(Node.PtrType{ | |
| 1880 | .sentinel = 0, | |
| 1816 | .data = .{ .extra_and_node = .{ | |
| 1817 | try p.addExtra(Node.PtrType{ | |
| 1818 | .sentinel = .none, | |
| 1881 | 1819 | .align_node = mods.align_node, |
| 1882 | 1820 | .addrspace_node = mods.addrspace_node, |
| 1883 | 1821 | }), |
| 1884 | .rhs = elem_type, | |
| 1885 | }, | |
| 1822 | elem_type, | |
| 1823 | } }, | |
| 1886 | 1824 | }); |
| 1887 | 1825 | } else { |
| 1888 | 1826 | break :inner try p.addNode(.{ |
| 1889 | 1827 | .tag = .ptr_type_aligned, |
| 1890 | 1828 | .main_token = asterisk, |
| 1891 | .data = .{ | |
| 1892 | .lhs = mods.align_node, | |
| 1893 | .rhs = elem_type, | |
| 1894 | }, | |
| 1829 | .data = .{ .opt_node_and_node = .{ | |
| 1830 | mods.align_node, | |
| 1831 | elem_type, | |
| 1832 | } }, | |
| 1895 | 1833 | }); |
| 1896 | 1834 | } |
| 1897 | 1835 | }; |
| 1898 | return p.addNode(.{ | |
| 1836 | return try p.addNode(.{ | |
| 1899 | 1837 | .tag = .ptr_type_aligned, |
| 1900 | 1838 | .main_token = asterisk, |
| 1901 | .data = .{ | |
| 1902 | .lhs = 0, | |
| 1903 | .rhs = inner, | |
| 1904 | }, | |
| 1839 | .data = .{ .opt_node_and_node = .{ | |
| 1840 | .none, | |
| 1841 | inner, | |
| 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 | 1846 | .asterisk => { |
| 1909 | 1847 | const l_bracket = p.nextToken(); |
| 1910 | 1848 | _ = p.nextToken(); |
| 1911 | var sentinel: Node.Index = 0; | |
| 1849 | var sentinel: ?Node.Index = null; | |
| 1912 | 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 | 1852 | if (!std.mem.eql(u8, std.mem.trimRight(u8, ident_slice, &std.ascii.whitespace), "c")) { |
| 1915 | 1853 | p.tok_i -= 1; |
| 1916 | 1854 | } |
| ... | ... | @@ -1920,107 +1858,107 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index { |
| 1920 | 1858 | _ = try p.expectToken(.r_bracket); |
| 1921 | 1859 | const mods = try p.parsePtrModifiers(); |
| 1922 | 1860 | const elem_type = try p.expectTypeExpr(); |
| 1923 | if (mods.bit_range_start == 0) { | |
| 1924 | if (sentinel == 0 and mods.addrspace_node == 0) { | |
| 1925 | return p.addNode(.{ | |
| 1861 | if (mods.bit_range_start == .none) { | |
| 1862 | if (sentinel == null and mods.addrspace_node == .none) { | |
| 1863 | return try p.addNode(.{ | |
| 1926 | 1864 | .tag = .ptr_type_aligned, |
| 1927 | 1865 | .main_token = l_bracket, |
| 1928 | .data = .{ | |
| 1929 | .lhs = mods.align_node, | |
| 1930 | .rhs = elem_type, | |
| 1931 | }, | |
| 1866 | .data = .{ .opt_node_and_node = .{ | |
| 1867 | mods.align_node, | |
| 1868 | elem_type, | |
| 1869 | } }, | |
| 1932 | 1870 | }); |
| 1933 | } else if (mods.align_node == 0 and mods.addrspace_node == 0) { | |
| 1934 | return p.addNode(.{ | |
| 1871 | } else if (mods.align_node == .none and mods.addrspace_node == .none) { | |
| 1872 | return try p.addNode(.{ | |
| 1935 | 1873 | .tag = .ptr_type_sentinel, |
| 1936 | 1874 | .main_token = l_bracket, |
| 1937 | .data = .{ | |
| 1938 | .lhs = sentinel, | |
| 1939 | .rhs = elem_type, | |
| 1940 | }, | |
| 1875 | .data = .{ .opt_node_and_node = .{ | |
| 1876 | .fromOptional(sentinel), | |
| 1877 | elem_type, | |
| 1878 | } }, | |
| 1941 | 1879 | }); |
| 1942 | 1880 | } else { |
| 1943 | return p.addNode(.{ | |
| 1881 | return try p.addNode(.{ | |
| 1944 | 1882 | .tag = .ptr_type, |
| 1945 | 1883 | .main_token = l_bracket, |
| 1946 | .data = .{ | |
| 1947 | .lhs = try p.addExtra(Node.PtrType{ | |
| 1948 | .sentinel = sentinel, | |
| 1884 | .data = .{ .extra_and_node = .{ | |
| 1885 | try p.addExtra(Node.PtrType{ | |
| 1886 | .sentinel = .fromOptional(sentinel), | |
| 1949 | 1887 | .align_node = mods.align_node, |
| 1950 | 1888 | .addrspace_node = mods.addrspace_node, |
| 1951 | 1889 | }), |
| 1952 | .rhs = elem_type, | |
| 1953 | }, | |
| 1890 | elem_type, | |
| 1891 | } }, | |
| 1954 | 1892 | }); |
| 1955 | 1893 | } |
| 1956 | 1894 | } else { |
| 1957 | return p.addNode(.{ | |
| 1895 | return try p.addNode(.{ | |
| 1958 | 1896 | .tag = .ptr_type_bit_range, |
| 1959 | 1897 | .main_token = l_bracket, |
| 1960 | .data = .{ | |
| 1961 | .lhs = try p.addExtra(Node.PtrTypeBitRange{ | |
| 1962 | .sentinel = sentinel, | |
| 1963 | .align_node = mods.align_node, | |
| 1898 | .data = .{ .extra_and_node = .{ | |
| 1899 | try p.addExtra(Node.PtrTypeBitRange{ | |
| 1900 | .sentinel = .fromOptional(sentinel), | |
| 1901 | .align_node = mods.align_node.unwrap().?, | |
| 1964 | 1902 | .addrspace_node = mods.addrspace_node, |
| 1965 | .bit_range_start = mods.bit_range_start, | |
| 1966 | .bit_range_end = mods.bit_range_end, | |
| 1903 | .bit_range_start = mods.bit_range_start.unwrap().?, | |
| 1904 | .bit_range_end = mods.bit_range_end.unwrap().?, | |
| 1967 | 1905 | }), |
| 1968 | .rhs = elem_type, | |
| 1969 | }, | |
| 1906 | elem_type, | |
| 1907 | } }, | |
| 1970 | 1908 | }); |
| 1971 | 1909 | } |
| 1972 | 1910 | }, |
| 1973 | 1911 | else => { |
| 1974 | 1912 | const lbracket = p.nextToken(); |
| 1975 | 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 | 1915 | try p.expectExpr() |
| 1978 | 1916 | else |
| 1979 | 0; | |
| 1917 | null; | |
| 1980 | 1918 | _ = try p.expectToken(.r_bracket); |
| 1981 | if (len_expr == 0) { | |
| 1919 | if (len_expr == null) { | |
| 1982 | 1920 | const mods = try p.parsePtrModifiers(); |
| 1983 | 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 | 1923 | try p.warnMsg(.{ |
| 1986 | 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) { | |
| 1991 | return p.addNode(.{ | |
| 1928 | if (sentinel == null and mods.addrspace_node == .none) { | |
| 1929 | return try p.addNode(.{ | |
| 1992 | 1930 | .tag = .ptr_type_aligned, |
| 1993 | 1931 | .main_token = lbracket, |
| 1994 | .data = .{ | |
| 1995 | .lhs = mods.align_node, | |
| 1996 | .rhs = elem_type, | |
| 1997 | }, | |
| 1932 | .data = .{ .opt_node_and_node = .{ | |
| 1933 | mods.align_node, | |
| 1934 | elem_type, | |
| 1935 | } }, | |
| 1998 | 1936 | }); |
| 1999 | } else if (mods.align_node == 0 and mods.addrspace_node == 0) { | |
| 2000 | return p.addNode(.{ | |
| 1937 | } else if (mods.align_node == .none and mods.addrspace_node == .none) { | |
| 1938 | return try p.addNode(.{ | |
| 2001 | 1939 | .tag = .ptr_type_sentinel, |
| 2002 | 1940 | .main_token = lbracket, |
| 2003 | .data = .{ | |
| 2004 | .lhs = sentinel, | |
| 2005 | .rhs = elem_type, | |
| 2006 | }, | |
| 1941 | .data = .{ .opt_node_and_node = .{ | |
| 1942 | .fromOptional(sentinel), | |
| 1943 | elem_type, | |
| 1944 | } }, | |
| 2007 | 1945 | }); |
| 2008 | 1946 | } else { |
| 2009 | return p.addNode(.{ | |
| 1947 | return try p.addNode(.{ | |
| 2010 | 1948 | .tag = .ptr_type, |
| 2011 | 1949 | .main_token = lbracket, |
| 2012 | .data = .{ | |
| 2013 | .lhs = try p.addExtra(Node.PtrType{ | |
| 2014 | .sentinel = sentinel, | |
| 1950 | .data = .{ .extra_and_node = .{ | |
| 1951 | try p.addExtra(Node.PtrType{ | |
| 1952 | .sentinel = .fromOptional(sentinel), | |
| 2015 | 1953 | .align_node = mods.align_node, |
| 2016 | 1954 | .addrspace_node = mods.addrspace_node, |
| 2017 | 1955 | }), |
| 2018 | .rhs = elem_type, | |
| 2019 | }, | |
| 1956 | elem_type, | |
| 1957 | } }, | |
| 2020 | 1958 | }); |
| 2021 | 1959 | } |
| 2022 | 1960 | } else { |
| 2023 | switch (p.token_tags[p.tok_i]) { | |
| 1961 | switch (p.tokenTag(p.tok_i)) { | |
| 2024 | 1962 | .keyword_align, |
| 2025 | 1963 | .keyword_const, |
| 2026 | 1964 | .keyword_volatile, |
| ... | ... | @@ -2030,26 +1968,25 @@ fn parseTypeExpr(p: *Parse) Error!Node.Index { |
| 2030 | 1968 | else => {}, |
| 2031 | 1969 | } |
| 2032 | 1970 | const elem_type = try p.expectTypeExpr(); |
| 2033 | if (sentinel == 0) { | |
| 2034 | return p.addNode(.{ | |
| 1971 | if (sentinel == null) { | |
| 1972 | return try p.addNode(.{ | |
| 2035 | 1973 | .tag = .array_type, |
| 2036 | 1974 | .main_token = lbracket, |
| 2037 | .data = .{ | |
| 2038 | .lhs = len_expr, | |
| 2039 | .rhs = elem_type, | |
| 2040 | }, | |
| 1975 | .data = .{ .node_and_node = .{ | |
| 1976 | len_expr.?, | |
| 1977 | elem_type, | |
| 1978 | } }, | |
| 2041 | 1979 | }); |
| 2042 | 1980 | } else { |
| 2043 | return p.addNode(.{ | |
| 1981 | return try p.addNode(.{ | |
| 2044 | 1982 | .tag = .array_type_sentinel, |
| 2045 | 1983 | .main_token = lbracket, |
| 2046 | .data = .{ | |
| 2047 | .lhs = len_expr, | |
| 2048 | .rhs = try p.addExtra(Node.ArrayTypeSentinel{ | |
| 2049 | .sentinel = sentinel, | |
| 1984 | .data = .{ .node_and_extra = .{ | |
| 1985 | len_expr.?, try p.addExtra(Node.ArrayTypeSentinel{ | |
| 1986 | .sentinel = sentinel.?, | |
| 2050 | 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 | 1997 | } |
| 2061 | 1998 | |
| 2062 | 1999 | fn expectTypeExpr(p: *Parse) Error!Node.Index { |
| 2063 | const node = try p.parseTypeExpr(); | |
| 2064 | if (node == 0) { | |
| 2065 | return p.fail(.expected_type_expr); | |
| 2066 | } | |
| 2067 | return node; | |
| 2000 | return try p.parseTypeExpr() orelse return p.fail(.expected_type_expr); | |
| 2068 | 2001 | } |
| 2069 | 2002 | |
| 2070 | 2003 | /// PrimaryExpr |
| ... | ... | @@ -2079,169 +2012,135 @@ fn expectTypeExpr(p: *Parse) Error!Node.Index { |
| 2079 | 2012 | /// / BlockLabel? LoopExpr |
| 2080 | 2013 | /// / Block |
| 2081 | 2014 | /// / CurlySuffixExpr |
| 2082 | fn parsePrimaryExpr(p: *Parse) !Node.Index { | |
| 2083 | switch (p.token_tags[p.tok_i]) { | |
| 2084 | .keyword_asm => return p.expectAsmExpr(), | |
| 2085 | .keyword_if => return p.parseIfExpr(), | |
| 2015 | fn parsePrimaryExpr(p: *Parse) !?Node.Index { | |
| 2016 | switch (p.tokenTag(p.tok_i)) { | |
| 2017 | .keyword_asm => return try p.expectAsmExpr(), | |
| 2018 | .keyword_if => return try p.parseIfExpr(), | |
| 2086 | 2019 | .keyword_break => { |
| 2087 | return p.addNode(.{ | |
| 2020 | return try p.addNode(.{ | |
| 2088 | 2021 | .tag = .@"break", |
| 2089 | 2022 | .main_token = p.nextToken(), |
| 2090 | .data = .{ | |
| 2091 | .lhs = try p.parseBreakLabel(), | |
| 2092 | .rhs = try p.parseExpr(), | |
| 2093 | }, | |
| 2023 | .data = .{ .opt_token_and_opt_node = .{ | |
| 2024 | try p.parseBreakLabel(), | |
| 2025 | .fromOptional(try p.parseExpr()), | |
| 2026 | } }, | |
| 2094 | 2027 | }); |
| 2095 | 2028 | }, |
| 2096 | 2029 | .keyword_continue => { |
| 2097 | return p.addNode(.{ | |
| 2030 | return try p.addNode(.{ | |
| 2098 | 2031 | .tag = .@"continue", |
| 2099 | 2032 | .main_token = p.nextToken(), |
| 2100 | .data = .{ | |
| 2101 | .lhs = try p.parseBreakLabel(), | |
| 2102 | .rhs = try p.parseExpr(), | |
| 2103 | }, | |
| 2033 | .data = .{ .opt_token_and_opt_node = .{ | |
| 2034 | try p.parseBreakLabel(), | |
| 2035 | .fromOptional(try p.parseExpr()), | |
| 2036 | } }, | |
| 2104 | 2037 | }); |
| 2105 | 2038 | }, |
| 2106 | 2039 | .keyword_comptime => { |
| 2107 | return p.addNode(.{ | |
| 2040 | return try p.addNode(.{ | |
| 2108 | 2041 | .tag = .@"comptime", |
| 2109 | 2042 | .main_token = p.nextToken(), |
| 2110 | .data = .{ | |
| 2111 | .lhs = try p.expectExpr(), | |
| 2112 | .rhs = undefined, | |
| 2113 | }, | |
| 2043 | .data = .{ .node = try p.expectExpr() }, | |
| 2114 | 2044 | }); |
| 2115 | 2045 | }, |
| 2116 | 2046 | .keyword_nosuspend => { |
| 2117 | return p.addNode(.{ | |
| 2047 | return try p.addNode(.{ | |
| 2118 | 2048 | .tag = .@"nosuspend", |
| 2119 | 2049 | .main_token = p.nextToken(), |
| 2120 | .data = .{ | |
| 2121 | .lhs = try p.expectExpr(), | |
| 2122 | .rhs = undefined, | |
| 2123 | }, | |
| 2050 | .data = .{ .node = try p.expectExpr() }, | |
| 2124 | 2051 | }); |
| 2125 | 2052 | }, |
| 2126 | 2053 | .keyword_resume => { |
| 2127 | return p.addNode(.{ | |
| 2054 | return try p.addNode(.{ | |
| 2128 | 2055 | .tag = .@"resume", |
| 2129 | 2056 | .main_token = p.nextToken(), |
| 2130 | .data = .{ | |
| 2131 | .lhs = try p.expectExpr(), | |
| 2132 | .rhs = undefined, | |
| 2133 | }, | |
| 2057 | .data = .{ .node = try p.expectExpr() }, | |
| 2134 | 2058 | }); |
| 2135 | 2059 | }, |
| 2136 | 2060 | .keyword_return => { |
| 2137 | return p.addNode(.{ | |
| 2061 | return try p.addNode(.{ | |
| 2138 | 2062 | .tag = .@"return", |
| 2139 | 2063 | .main_token = p.nextToken(), |
| 2140 | .data = .{ | |
| 2141 | .lhs = try p.parseExpr(), | |
| 2142 | .rhs = undefined, | |
| 2143 | }, | |
| 2064 | .data = .{ .opt_node = .fromOptional(try p.parseExpr()) }, | |
| 2144 | 2065 | }); |
| 2145 | 2066 | }, |
| 2146 | 2067 | .identifier => { |
| 2147 | if (p.token_tags[p.tok_i + 1] == .colon) { | |
| 2148 | switch (p.token_tags[p.tok_i + 2]) { | |
| 2068 | if (p.tokenTag(p.tok_i + 1) == .colon) { | |
| 2069 | switch (p.tokenTag(p.tok_i + 2)) { | |
| 2149 | 2070 | .keyword_inline => { |
| 2150 | 2071 | p.tok_i += 3; |
| 2151 | switch (p.token_tags[p.tok_i]) { | |
| 2152 | .keyword_for => return p.parseFor(expectExpr), | |
| 2153 | .keyword_while => return p.parseWhileExpr(), | |
| 2072 | switch (p.tokenTag(p.tok_i)) { | |
| 2073 | .keyword_for => return try p.parseFor(expectExpr), | |
| 2074 | .keyword_while => return try p.parseWhileExpr(), | |
| 2154 | 2075 | else => return p.fail(.expected_inlinable), |
| 2155 | 2076 | } |
| 2156 | 2077 | }, |
| 2157 | 2078 | .keyword_for => { |
| 2158 | 2079 | p.tok_i += 2; |
| 2159 | return p.parseFor(expectExpr); | |
| 2080 | return try p.parseFor(expectExpr); | |
| 2160 | 2081 | }, |
| 2161 | 2082 | .keyword_while => { |
| 2162 | 2083 | p.tok_i += 2; |
| 2163 | return p.parseWhileExpr(); | |
| 2084 | return try p.parseWhileExpr(); | |
| 2164 | 2085 | }, |
| 2165 | 2086 | .l_brace => { |
| 2166 | 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 | 2092 | } else { |
| 2172 | return p.parseCurlySuffixExpr(); | |
| 2093 | return try p.parseCurlySuffixExpr(); | |
| 2173 | 2094 | } |
| 2174 | 2095 | }, |
| 2175 | 2096 | .keyword_inline => { |
| 2176 | 2097 | p.tok_i += 1; |
| 2177 | switch (p.token_tags[p.tok_i]) { | |
| 2178 | .keyword_for => return p.parseFor(expectExpr), | |
| 2179 | .keyword_while => return p.parseWhileExpr(), | |
| 2098 | switch (p.tokenTag(p.tok_i)) { | |
| 2099 | .keyword_for => return try p.parseFor(expectExpr), | |
| 2100 | .keyword_while => return try p.parseWhileExpr(), | |
| 2180 | 2101 | else => return p.fail(.expected_inlinable), |
| 2181 | 2102 | } |
| 2182 | 2103 | }, |
| 2183 | .keyword_for => return p.parseFor(expectExpr), | |
| 2184 | .keyword_while => return p.parseWhileExpr(), | |
| 2185 | .l_brace => return p.parseBlock(), | |
| 2186 | else => return p.parseCurlySuffixExpr(), | |
| 2104 | .keyword_for => return try p.parseFor(expectExpr), | |
| 2105 | .keyword_while => return try p.parseWhileExpr(), | |
| 2106 | .l_brace => return try p.parseBlock(), | |
| 2107 | else => return try p.parseCurlySuffixExpr(), | |
| 2187 | 2108 | } |
| 2188 | 2109 | } |
| 2189 | 2110 | |
| 2190 | 2111 | /// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)? |
| 2191 | fn parseIfExpr(p: *Parse) !Node.Index { | |
| 2192 | return p.parseIf(expectExpr); | |
| 2112 | fn parseIfExpr(p: *Parse) !?Node.Index { | |
| 2113 | return try p.parseIf(expectExpr); | |
| 2193 | 2114 | } |
| 2194 | 2115 | |
| 2195 | 2116 | /// Block <- LBRACE Statement* RBRACE |
| 2196 | fn parseBlock(p: *Parse) !Node.Index { | |
| 2197 | const lbrace = p.eatToken(.l_brace) orelse return null_node; | |
| 2117 | fn parseBlock(p: *Parse) !?Node.Index { | |
| 2118 | const lbrace = p.eatToken(.l_brace) orelse return null; | |
| 2198 | 2119 | const scratch_top = p.scratch.items.len; |
| 2199 | 2120 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2200 | 2121 | while (true) { |
| 2201 | if (p.token_tags[p.tok_i] == .r_brace) break; | |
| 2202 | const statement = try p.expectStatementRecoverable(); | |
| 2203 | if (statement == 0) break; | |
| 2122 | if (p.tokenTag(p.tok_i) == .r_brace) break; | |
| 2123 | const statement = try p.expectStatementRecoverable() orelse break; | |
| 2204 | 2124 | try p.scratch.append(p.gpa, statement); |
| 2205 | 2125 | } |
| 2206 | 2126 | _ = try p.expectToken(.r_brace); |
| 2207 | const semicolon = (p.token_tags[p.tok_i - 2] == .semicolon); | |
| 2208 | 2127 | const statements = p.scratch.items[scratch_top..]; |
| 2209 | switch (statements.len) { | |
| 2210 | 0 => return p.addNode(.{ | |
| 2211 | .tag = .block_two, | |
| 2212 | .main_token = lbrace, | |
| 2213 | .data = .{ | |
| 2214 | .lhs = 0, | |
| 2215 | .rhs = 0, | |
| 2216 | }, | |
| 2217 | }), | |
| 2218 | 1 => return p.addNode(.{ | |
| 2128 | const semicolon = statements.len != 0 and (p.tokenTag(p.tok_i - 2)) == .semicolon; | |
| 2129 | if (statements.len <= 2) { | |
| 2130 | return try p.addNode(.{ | |
| 2219 | 2131 | .tag = if (semicolon) .block_two_semicolon else .block_two, |
| 2220 | 2132 | .main_token = lbrace, |
| 2221 | .data = .{ | |
| 2222 | .lhs = statements[0], | |
| 2223 | .rhs = 0, | |
| 2224 | }, | |
| 2225 | }), | |
| 2226 | 2 => return p.addNode(.{ | |
| 2227 | .tag = if (semicolon) .block_two_semicolon else .block_two, | |
| 2133 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2134 | if (statements.len >= 1) statements[0].toOptional() else .none, | |
| 2135 | if (statements.len >= 2) statements[1].toOptional() else .none, | |
| 2136 | } }, | |
| 2137 | }); | |
| 2138 | } else { | |
| 2139 | return try p.addNode(.{ | |
| 2140 | .tag = if (semicolon) .block_semicolon else .block, | |
| 2228 | 2141 | .main_token = lbrace, |
| 2229 | .data = .{ | |
| 2230 | .lhs = statements[0], | |
| 2231 | .rhs = statements[1], | |
| 2232 | }, | |
| 2233 | }), | |
| 2234 | else => { | |
| 2235 | const span = try p.listToSpan(statements); | |
| 2236 | return p.addNode(.{ | |
| 2237 | .tag = if (semicolon) .block_semicolon else .block, | |
| 2238 | .main_token = lbrace, | |
| 2239 | .data = .{ | |
| 2240 | .lhs = span.start, | |
| 2241 | .rhs = span.end, | |
| 2242 | }, | |
| 2243 | }); | |
| 2244 | }, | |
| 2142 | .data = .{ .extra_range = try p.listToSpan(statements) }, | |
| 2143 | }); | |
| 2245 | 2144 | } |
| 2246 | 2145 | } |
| 2247 | 2146 | |
| ... | ... | @@ -2260,15 +2159,15 @@ fn forPrefix(p: *Parse) Error!usize { |
| 2260 | 2159 | input = try p.addNode(.{ |
| 2261 | 2160 | .tag = .for_range, |
| 2262 | 2161 | .main_token = ellipsis, |
| 2263 | .data = .{ | |
| 2264 | .lhs = input, | |
| 2265 | .rhs = try p.parseExpr(), | |
| 2266 | }, | |
| 2162 | .data = .{ .node_and_opt_node = .{ | |
| 2163 | input, | |
| 2164 | .fromOptional(try p.parseExpr()), | |
| 2165 | } }, | |
| 2267 | 2166 | }); |
| 2268 | 2167 | } |
| 2269 | 2168 | |
| 2270 | 2169 | try p.scratch.append(p.gpa, input); |
| 2271 | switch (p.token_tags[p.tok_i]) { | |
| 2170 | switch (p.tokenTag(p.tok_i)) { | |
| 2272 | 2171 | .comma => p.tok_i += 1, |
| 2273 | 2172 | .r_paren => { |
| 2274 | 2173 | p.tok_i += 1; |
| ... | ... | @@ -2297,7 +2196,7 @@ fn forPrefix(p: *Parse) Error!usize { |
| 2297 | 2196 | try p.warnMsg(.{ .tag = .extra_for_capture, .token = identifier }); |
| 2298 | 2197 | warned_excess = true; |
| 2299 | 2198 | } |
| 2300 | switch (p.token_tags[p.tok_i]) { | |
| 2199 | switch (p.tokenTag(p.tok_i)) { | |
| 2301 | 2200 | .comma => p.tok_i += 1, |
| 2302 | 2201 | .pipe => { |
| 2303 | 2202 | p.tok_i += 1; |
| ... | ... | @@ -2311,7 +2210,7 @@ fn forPrefix(p: *Parse) Error!usize { |
| 2311 | 2210 | |
| 2312 | 2211 | if (captures < inputs) { |
| 2313 | 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 | 2214 | try p.warnMsg(.{ .tag = .for_input_not_captured, .token = input }); |
| 2316 | 2215 | } |
| 2317 | 2216 | return inputs; |
| ... | ... | @@ -2320,8 +2219,8 @@ fn forPrefix(p: *Parse) Error!usize { |
| 2320 | 2219 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2321 | 2220 | /// |
| 2322 | 2221 | /// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)? |
| 2323 | fn parseWhileExpr(p: *Parse) !Node.Index { | |
| 2324 | const while_token = p.eatToken(.keyword_while) orelse return null_node; | |
| 2222 | fn parseWhileExpr(p: *Parse) !?Node.Index { | |
| 2223 | const while_token = p.eatToken(.keyword_while) orelse return null; | |
| 2325 | 2224 | _ = try p.expectToken(.l_paren); |
| 2326 | 2225 | const condition = try p.expectExpr(); |
| 2327 | 2226 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -2330,42 +2229,42 @@ fn parseWhileExpr(p: *Parse) !Node.Index { |
| 2330 | 2229 | |
| 2331 | 2230 | const then_expr = try p.expectExpr(); |
| 2332 | 2231 | _ = p.eatToken(.keyword_else) orelse { |
| 2333 | if (cont_expr == 0) { | |
| 2334 | return p.addNode(.{ | |
| 2232 | if (cont_expr == null) { | |
| 2233 | return try p.addNode(.{ | |
| 2335 | 2234 | .tag = .while_simple, |
| 2336 | 2235 | .main_token = while_token, |
| 2337 | .data = .{ | |
| 2338 | .lhs = condition, | |
| 2339 | .rhs = then_expr, | |
| 2340 | }, | |
| 2236 | .data = .{ .node_and_node = .{ | |
| 2237 | condition, | |
| 2238 | then_expr, | |
| 2239 | } }, | |
| 2341 | 2240 | }); |
| 2342 | 2241 | } else { |
| 2343 | return p.addNode(.{ | |
| 2242 | return try p.addNode(.{ | |
| 2344 | 2243 | .tag = .while_cont, |
| 2345 | 2244 | .main_token = while_token, |
| 2346 | .data = .{ | |
| 2347 | .lhs = condition, | |
| 2348 | .rhs = try p.addExtra(Node.WhileCont{ | |
| 2349 | .cont_expr = cont_expr, | |
| 2245 | .data = .{ .node_and_extra = .{ | |
| 2246 | condition, | |
| 2247 | try p.addExtra(Node.WhileCont{ | |
| 2248 | .cont_expr = cont_expr.?, | |
| 2350 | 2249 | .then_expr = then_expr, |
| 2351 | 2250 | }), |
| 2352 | }, | |
| 2251 | } }, | |
| 2353 | 2252 | }); |
| 2354 | 2253 | } |
| 2355 | 2254 | }; |
| 2356 | 2255 | _ = try p.parsePayload(); |
| 2357 | 2256 | const else_expr = try p.expectExpr(); |
| 2358 | return p.addNode(.{ | |
| 2257 | return try p.addNode(.{ | |
| 2359 | 2258 | .tag = .@"while", |
| 2360 | 2259 | .main_token = while_token, |
| 2361 | .data = .{ | |
| 2362 | .lhs = condition, | |
| 2363 | .rhs = try p.addExtra(Node.While{ | |
| 2364 | .cont_expr = cont_expr, | |
| 2260 | .data = .{ .node_and_extra = .{ | |
| 2261 | condition, | |
| 2262 | try p.addExtra(Node.While{ | |
| 2263 | .cont_expr = .fromOptional(cont_expr), | |
| 2365 | 2264 | .then_expr = then_expr, |
| 2366 | 2265 | .else_expr = else_expr, |
| 2367 | 2266 | }), |
| 2368 | }, | |
| 2267 | } }, | |
| 2369 | 2268 | }); |
| 2370 | 2269 | } |
| 2371 | 2270 | |
| ... | ... | @@ -2375,9 +2274,8 @@ fn parseWhileExpr(p: *Parse) !Node.Index { |
| 2375 | 2274 | /// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE |
| 2376 | 2275 | /// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE |
| 2377 | 2276 | /// / LBRACE RBRACE |
| 2378 | fn parseCurlySuffixExpr(p: *Parse) !Node.Index { | |
| 2379 | const lhs = try p.parseTypeExpr(); | |
| 2380 | if (lhs == 0) return null_node; | |
| 2277 | fn parseCurlySuffixExpr(p: *Parse) !?Node.Index { | |
| 2278 | const lhs = try p.parseTypeExpr() orelse return null; | |
| 2381 | 2279 | const lbrace = p.eatToken(.l_brace) orelse return lhs; |
| 2382 | 2280 | |
| 2383 | 2281 | // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne; |
| ... | ... | @@ -2385,11 +2283,11 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index { |
| 2385 | 2283 | |
| 2386 | 2284 | const scratch_top = p.scratch.items.len; |
| 2387 | 2285 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2388 | const field_init = try p.parseFieldInit(); | |
| 2389 | if (field_init != 0) { | |
| 2286 | const opt_field_init = try p.parseFieldInit(); | |
| 2287 | if (opt_field_init) |field_init| { | |
| 2390 | 2288 | try p.scratch.append(p.gpa, field_init); |
| 2391 | 2289 | while (true) { |
| 2392 | switch (p.token_tags[p.tok_i]) { | |
| 2290 | switch (p.tokenTag(p.tok_i)) { | |
| 2393 | 2291 | .comma => p.tok_i += 1, |
| 2394 | 2292 | .r_brace => { |
| 2395 | 2293 | p.tok_i += 1; |
| ... | ... | @@ -2403,26 +2301,27 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index { |
| 2403 | 2301 | const next = try p.expectFieldInit(); |
| 2404 | 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 | 2305 | const inits = p.scratch.items[scratch_top..]; |
| 2408 | switch (inits.len) { | |
| 2409 | 0 => unreachable, | |
| 2410 | 1 => return p.addNode(.{ | |
| 2306 | std.debug.assert(inits.len != 0); | |
| 2307 | if (inits.len <= 1) { | |
| 2308 | return try p.addNode(.{ | |
| 2411 | 2309 | .tag = if (comma) .struct_init_one_comma else .struct_init_one, |
| 2412 | 2310 | .main_token = lbrace, |
| 2413 | .data = .{ | |
| 2414 | .lhs = lhs, | |
| 2415 | .rhs = inits[0], | |
| 2416 | }, | |
| 2417 | }), | |
| 2418 | else => return p.addNode(.{ | |
| 2311 | .data = .{ .node_and_opt_node = .{ | |
| 2312 | lhs, | |
| 2313 | inits[0].toOptional(), | |
| 2314 | } }, | |
| 2315 | }); | |
| 2316 | } else { | |
| 2317 | return try p.addNode(.{ | |
| 2419 | 2318 | .tag = if (comma) .struct_init_comma else .struct_init, |
| 2420 | 2319 | .main_token = lbrace, |
| 2421 | .data = .{ | |
| 2422 | .lhs = lhs, | |
| 2423 | .rhs = try p.addExtra(try p.listToSpan(inits)), | |
| 2424 | }, | |
| 2425 | }), | |
| 2320 | .data = .{ .node_and_extra = .{ | |
| 2321 | lhs, | |
| 2322 | try p.addExtra(try p.listToSpan(inits)), | |
| 2323 | } }, | |
| 2324 | }); | |
| 2426 | 2325 | } |
| 2427 | 2326 | } |
| 2428 | 2327 | |
| ... | ... | @@ -2430,7 +2329,7 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index { |
| 2430 | 2329 | if (p.eatToken(.r_brace)) |_| break; |
| 2431 | 2330 | const elem_init = try p.expectExpr(); |
| 2432 | 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 | 2333 | .comma => p.tok_i += 1, |
| 2435 | 2334 | .r_brace => { |
| 2436 | 2335 | p.tok_i += 1; |
| ... | ... | @@ -2441,48 +2340,47 @@ fn parseCurlySuffixExpr(p: *Parse) !Node.Index { |
| 2441 | 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 | 2344 | const inits = p.scratch.items[scratch_top..]; |
| 2446 | 2345 | switch (inits.len) { |
| 2447 | 0 => return p.addNode(.{ | |
| 2346 | 0 => return try p.addNode(.{ | |
| 2448 | 2347 | .tag = .struct_init_one, |
| 2449 | 2348 | .main_token = lbrace, |
| 2450 | .data = .{ | |
| 2451 | .lhs = lhs, | |
| 2452 | .rhs = 0, | |
| 2453 | }, | |
| 2349 | .data = .{ .node_and_opt_node = .{ | |
| 2350 | lhs, | |
| 2351 | .none, | |
| 2352 | } }, | |
| 2454 | 2353 | }), |
| 2455 | 1 => return p.addNode(.{ | |
| 2354 | 1 => return try p.addNode(.{ | |
| 2456 | 2355 | .tag = if (comma) .array_init_one_comma else .array_init_one, |
| 2457 | 2356 | .main_token = lbrace, |
| 2458 | .data = .{ | |
| 2459 | .lhs = lhs, | |
| 2460 | .rhs = inits[0], | |
| 2461 | }, | |
| 2357 | .data = .{ .node_and_node = .{ | |
| 2358 | lhs, | |
| 2359 | inits[0], | |
| 2360 | } }, | |
| 2462 | 2361 | }), |
| 2463 | else => return p.addNode(.{ | |
| 2362 | else => return try p.addNode(.{ | |
| 2464 | 2363 | .tag = if (comma) .array_init_comma else .array_init, |
| 2465 | 2364 | .main_token = lbrace, |
| 2466 | .data = .{ | |
| 2467 | .lhs = lhs, | |
| 2468 | .rhs = try p.addExtra(try p.listToSpan(inits)), | |
| 2469 | }, | |
| 2365 | .data = .{ .node_and_extra = .{ | |
| 2366 | lhs, | |
| 2367 | try p.addExtra(try p.listToSpan(inits)), | |
| 2368 | } }, | |
| 2470 | 2369 | }), |
| 2471 | 2370 | } |
| 2472 | 2371 | } |
| 2473 | 2372 | |
| 2474 | 2373 | /// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)? |
| 2475 | fn parseErrorUnionExpr(p: *Parse) !Node.Index { | |
| 2476 | const suffix_expr = try p.parseSuffixExpr(); | |
| 2477 | if (suffix_expr == 0) return null_node; | |
| 2374 | fn parseErrorUnionExpr(p: *Parse) !?Node.Index { | |
| 2375 | const suffix_expr = try p.parseSuffixExpr() orelse return null; | |
| 2478 | 2376 | const bang = p.eatToken(.bang) orelse return suffix_expr; |
| 2479 | return p.addNode(.{ | |
| 2377 | return try p.addNode(.{ | |
| 2480 | 2378 | .tag = .error_union, |
| 2481 | 2379 | .main_token = bang, |
| 2482 | .data = .{ | |
| 2483 | .lhs = suffix_expr, | |
| 2484 | .rhs = try p.expectTypeExpr(), | |
| 2485 | }, | |
| 2380 | .data = .{ .node_and_node = .{ | |
| 2381 | suffix_expr, | |
| 2382 | try p.expectTypeExpr(), | |
| 2383 | } }, | |
| 2486 | 2384 | }); |
| 2487 | 2385 | } |
| 2488 | 2386 | |
| ... | ... | @@ -2493,13 +2391,11 @@ fn parseErrorUnionExpr(p: *Parse) !Node.Index { |
| 2493 | 2391 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 2494 | 2392 | /// |
| 2495 | 2393 | /// ExprList <- (Expr COMMA)* Expr? |
| 2496 | fn parseSuffixExpr(p: *Parse) !Node.Index { | |
| 2394 | fn parseSuffixExpr(p: *Parse) !?Node.Index { | |
| 2497 | 2395 | if (p.eatToken(.keyword_async)) |_| { |
| 2498 | 2396 | var res = try p.expectPrimaryTypeExpr(); |
| 2499 | 2397 | while (true) { |
| 2500 | const node = try p.parseSuffixOp(res); | |
| 2501 | if (node == 0) break; | |
| 2502 | res = node; | |
| 2398 | res = try p.parseSuffixOp(res) orelse break; | |
| 2503 | 2399 | } |
| 2504 | 2400 | const lparen = p.eatToken(.l_paren) orelse { |
| 2505 | 2401 | try p.warn(.expected_param_list); |
| ... | ... | @@ -2511,7 +2407,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index { |
| 2511 | 2407 | if (p.eatToken(.r_paren)) |_| break; |
| 2512 | 2408 | const param = try p.expectExpr(); |
| 2513 | 2409 | try p.scratch.append(p.gpa, param); |
| 2514 | switch (p.token_tags[p.tok_i]) { | |
| 2410 | switch (p.tokenTag(p.tok_i)) { | |
| 2515 | 2411 | .comma => p.tok_i += 1, |
| 2516 | 2412 | .r_paren => { |
| 2517 | 2413 | p.tok_i += 1; |
| ... | ... | @@ -2522,41 +2418,33 @@ fn parseSuffixExpr(p: *Parse) !Node.Index { |
| 2522 | 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 | 2422 | const params = p.scratch.items[scratch_top..]; |
| 2527 | switch (params.len) { | |
| 2528 | 0 => return p.addNode(.{ | |
| 2529 | .tag = if (comma) .async_call_one_comma else .async_call_one, | |
| 2530 | .main_token = lparen, | |
| 2531 | .data = .{ | |
| 2532 | .lhs = res, | |
| 2533 | .rhs = 0, | |
| 2534 | }, | |
| 2535 | }), | |
| 2536 | 1 => return p.addNode(.{ | |
| 2423 | if (params.len <= 1) { | |
| 2424 | return try p.addNode(.{ | |
| 2537 | 2425 | .tag = if (comma) .async_call_one_comma else .async_call_one, |
| 2538 | 2426 | .main_token = lparen, |
| 2539 | .data = .{ | |
| 2540 | .lhs = res, | |
| 2541 | .rhs = params[0], | |
| 2542 | }, | |
| 2543 | }), | |
| 2544 | else => return p.addNode(.{ | |
| 2427 | .data = .{ .node_and_opt_node = .{ | |
| 2428 | res, | |
| 2429 | if (params.len >= 1) params[0].toOptional() else .none, | |
| 2430 | } }, | |
| 2431 | }); | |
| 2432 | } else { | |
| 2433 | return try p.addNode(.{ | |
| 2545 | 2434 | .tag = if (comma) .async_call_comma else .async_call, |
| 2546 | 2435 | .main_token = lparen, |
| 2547 | .data = .{ | |
| 2548 | .lhs = res, | |
| 2549 | .rhs = try p.addExtra(try p.listToSpan(params)), | |
| 2550 | }, | |
| 2551 | }), | |
| 2436 | .data = .{ .node_and_extra = .{ | |
| 2437 | res, | |
| 2438 | try p.addExtra(try p.listToSpan(params)), | |
| 2439 | } }, | |
| 2440 | }); | |
| 2552 | 2441 | } |
| 2553 | 2442 | } |
| 2554 | 2443 | |
| 2555 | var res = try p.parsePrimaryTypeExpr(); | |
| 2556 | if (res == 0) return res; | |
| 2444 | var res = try p.parsePrimaryTypeExpr() orelse return null; | |
| 2557 | 2445 | while (true) { |
| 2558 | const suffix_op = try p.parseSuffixOp(res); | |
| 2559 | if (suffix_op != 0) { | |
| 2446 | const opt_suffix_op = try p.parseSuffixOp(res); | |
| 2447 | if (opt_suffix_op) |suffix_op| { | |
| 2560 | 2448 | res = suffix_op; |
| 2561 | 2449 | continue; |
| 2562 | 2450 | } |
| ... | ... | @@ -2567,7 +2455,7 @@ fn parseSuffixExpr(p: *Parse) !Node.Index { |
| 2567 | 2455 | if (p.eatToken(.r_paren)) |_| break; |
| 2568 | 2456 | const param = try p.expectExpr(); |
| 2569 | 2457 | try p.scratch.append(p.gpa, param); |
| 2570 | switch (p.token_tags[p.tok_i]) { | |
| 2458 | switch (p.tokenTag(p.tok_i)) { | |
| 2571 | 2459 | .comma => p.tok_i += 1, |
| 2572 | 2460 | .r_paren => { |
| 2573 | 2461 | p.tok_i += 1; |
| ... | ... | @@ -2578,32 +2466,24 @@ fn parseSuffixExpr(p: *Parse) !Node.Index { |
| 2578 | 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 | 2470 | const params = p.scratch.items[scratch_top..]; |
| 2583 | 2471 | res = switch (params.len) { |
| 2584 | 0 => try p.addNode(.{ | |
| 2472 | 0, 1 => try p.addNode(.{ | |
| 2585 | 2473 | .tag = if (comma) .call_one_comma else .call_one, |
| 2586 | 2474 | .main_token = lparen, |
| 2587 | .data = .{ | |
| 2588 | .lhs = res, | |
| 2589 | .rhs = 0, | |
| 2590 | }, | |
| 2591 | }), | |
| 2592 | 1 => try p.addNode(.{ | |
| 2593 | .tag = if (comma) .call_one_comma else .call_one, | |
| 2594 | .main_token = lparen, | |
| 2595 | .data = .{ | |
| 2596 | .lhs = res, | |
| 2597 | .rhs = params[0], | |
| 2598 | }, | |
| 2475 | .data = .{ .node_and_opt_node = .{ | |
| 2476 | res, | |
| 2477 | if (params.len >= 1) .fromOptional(params[0]) else .none, | |
| 2478 | } }, | |
| 2599 | 2479 | }), |
| 2600 | 2480 | else => try p.addNode(.{ |
| 2601 | 2481 | .tag = if (comma) .call_comma else .call, |
| 2602 | 2482 | .main_token = lparen, |
| 2603 | .data = .{ | |
| 2604 | .lhs = res, | |
| 2605 | .rhs = try p.addExtra(try p.listToSpan(params)), | |
| 2606 | }, | |
| 2483 | .data = .{ .node_and_extra = .{ | |
| 2484 | res, | |
| 2485 | try p.addExtra(try p.listToSpan(params)), | |
| 2486 | } }, | |
| 2607 | 2487 | }), |
| 2608 | 2488 | }; |
| 2609 | 2489 | } |
| ... | ... | @@ -2650,155 +2530,131 @@ fn parseSuffixExpr(p: *Parse) !Node.Index { |
| 2650 | 2530 | /// / BlockLabel? SwitchExpr |
| 2651 | 2531 | /// |
| 2652 | 2532 | /// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr) |
| 2653 | fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { | |
| 2654 | switch (p.token_tags[p.tok_i]) { | |
| 2655 | .char_literal => return p.addNode(.{ | |
| 2533 | fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index { | |
| 2534 | switch (p.tokenTag(p.tok_i)) { | |
| 2535 | .char_literal => return try p.addNode(.{ | |
| 2656 | 2536 | .tag = .char_literal, |
| 2657 | 2537 | .main_token = p.nextToken(), |
| 2658 | .data = .{ | |
| 2659 | .lhs = undefined, | |
| 2660 | .rhs = undefined, | |
| 2661 | }, | |
| 2538 | .data = undefined, | |
| 2662 | 2539 | }), |
| 2663 | .number_literal => return p.addNode(.{ | |
| 2540 | .number_literal => return try p.addNode(.{ | |
| 2664 | 2541 | .tag = .number_literal, |
| 2665 | 2542 | .main_token = p.nextToken(), |
| 2666 | .data = .{ | |
| 2667 | .lhs = undefined, | |
| 2668 | .rhs = undefined, | |
| 2669 | }, | |
| 2543 | .data = undefined, | |
| 2670 | 2544 | }), |
| 2671 | .keyword_unreachable => return p.addNode(.{ | |
| 2545 | .keyword_unreachable => return try p.addNode(.{ | |
| 2672 | 2546 | .tag = .unreachable_literal, |
| 2673 | 2547 | .main_token = p.nextToken(), |
| 2674 | .data = .{ | |
| 2675 | .lhs = undefined, | |
| 2676 | .rhs = undefined, | |
| 2677 | }, | |
| 2548 | .data = undefined, | |
| 2678 | 2549 | }), |
| 2679 | .keyword_anyframe => return p.addNode(.{ | |
| 2550 | .keyword_anyframe => return try p.addNode(.{ | |
| 2680 | 2551 | .tag = .anyframe_literal, |
| 2681 | 2552 | .main_token = p.nextToken(), |
| 2682 | .data = .{ | |
| 2683 | .lhs = undefined, | |
| 2684 | .rhs = undefined, | |
| 2685 | }, | |
| 2553 | .data = undefined, | |
| 2686 | 2554 | }), |
| 2687 | 2555 | .string_literal => { |
| 2688 | 2556 | const main_token = p.nextToken(); |
| 2689 | return p.addNode(.{ | |
| 2557 | return try p.addNode(.{ | |
| 2690 | 2558 | .tag = .string_literal, |
| 2691 | 2559 | .main_token = main_token, |
| 2692 | .data = .{ | |
| 2693 | .lhs = undefined, | |
| 2694 | .rhs = undefined, | |
| 2695 | }, | |
| 2560 | .data = undefined, | |
| 2696 | 2561 | }); |
| 2697 | 2562 | }, |
| 2698 | 2563 | |
| 2699 | .builtin => return p.parseBuiltinCall(), | |
| 2700 | .keyword_fn => return p.parseFnProto(), | |
| 2701 | .keyword_if => return p.parseIf(expectTypeExpr), | |
| 2702 | .keyword_switch => return p.expectSwitchExpr(false), | |
| 2564 | .builtin => return try p.parseBuiltinCall(), | |
| 2565 | .keyword_fn => return try p.parseFnProto(), | |
| 2566 | .keyword_if => return try p.parseIf(expectTypeExpr), | |
| 2567 | .keyword_switch => return try p.expectSwitchExpr(false), | |
| 2703 | 2568 | |
| 2704 | 2569 | .keyword_extern, |
| 2705 | 2570 | .keyword_packed, |
| 2706 | 2571 | => { |
| 2707 | 2572 | p.tok_i += 1; |
| 2708 | return p.parseContainerDeclAuto(); | |
| 2573 | return try p.parseContainerDeclAuto(); | |
| 2709 | 2574 | }, |
| 2710 | 2575 | |
| 2711 | 2576 | .keyword_struct, |
| 2712 | 2577 | .keyword_opaque, |
| 2713 | 2578 | .keyword_enum, |
| 2714 | 2579 | .keyword_union, |
| 2715 | => return p.parseContainerDeclAuto(), | |
| 2580 | => return try p.parseContainerDeclAuto(), | |
| 2716 | 2581 | |
| 2717 | .keyword_comptime => return p.addNode(.{ | |
| 2582 | .keyword_comptime => return try p.addNode(.{ | |
| 2718 | 2583 | .tag = .@"comptime", |
| 2719 | 2584 | .main_token = p.nextToken(), |
| 2720 | .data = .{ | |
| 2721 | .lhs = try p.expectTypeExpr(), | |
| 2722 | .rhs = undefined, | |
| 2723 | }, | |
| 2585 | .data = .{ .node = try p.expectTypeExpr() }, | |
| 2724 | 2586 | }), |
| 2725 | 2587 | .multiline_string_literal_line => { |
| 2726 | 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 | 2590 | p.tok_i += 1; |
| 2729 | 2591 | } |
| 2730 | return p.addNode(.{ | |
| 2592 | return try p.addNode(.{ | |
| 2731 | 2593 | .tag = .multiline_string_literal, |
| 2732 | 2594 | .main_token = first_line, |
| 2733 | .data = .{ | |
| 2734 | .lhs = first_line, | |
| 2735 | .rhs = p.tok_i - 1, | |
| 2736 | }, | |
| 2595 | .data = .{ .token_and_token = .{ | |
| 2596 | first_line, | |
| 2597 | p.tok_i - 1, | |
| 2598 | } }, | |
| 2737 | 2599 | }); |
| 2738 | 2600 | }, |
| 2739 | .identifier => switch (p.token_tags[p.tok_i + 1]) { | |
| 2740 | .colon => switch (p.token_tags[p.tok_i + 2]) { | |
| 2601 | .identifier => switch (p.tokenTag(p.tok_i + 1)) { | |
| 2602 | .colon => switch (p.tokenTag(p.tok_i + 2)) { | |
| 2741 | 2603 | .keyword_inline => { |
| 2742 | 2604 | p.tok_i += 3; |
| 2743 | switch (p.token_tags[p.tok_i]) { | |
| 2744 | .keyword_for => return p.parseFor(expectTypeExpr), | |
| 2745 | .keyword_while => return p.parseWhileTypeExpr(), | |
| 2605 | switch (p.tokenTag(p.tok_i)) { | |
| 2606 | .keyword_for => return try p.parseFor(expectTypeExpr), | |
| 2607 | .keyword_while => return try p.parseWhileTypeExpr(), | |
| 2746 | 2608 | else => return p.fail(.expected_inlinable), |
| 2747 | 2609 | } |
| 2748 | 2610 | }, |
| 2749 | 2611 | .keyword_for => { |
| 2750 | 2612 | p.tok_i += 2; |
| 2751 | return p.parseFor(expectTypeExpr); | |
| 2613 | return try p.parseFor(expectTypeExpr); | |
| 2752 | 2614 | }, |
| 2753 | 2615 | .keyword_while => { |
| 2754 | 2616 | p.tok_i += 2; |
| 2755 | return p.parseWhileTypeExpr(); | |
| 2617 | return try p.parseWhileTypeExpr(); | |
| 2756 | 2618 | }, |
| 2757 | 2619 | .keyword_switch => { |
| 2758 | 2620 | p.tok_i += 2; |
| 2759 | return p.expectSwitchExpr(true); | |
| 2621 | return try p.expectSwitchExpr(true); | |
| 2760 | 2622 | }, |
| 2761 | 2623 | .l_brace => { |
| 2762 | 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 | 2628 | .tag = .identifier, |
| 2767 | 2629 | .main_token = p.nextToken(), |
| 2768 | .data = .{ | |
| 2769 | .lhs = undefined, | |
| 2770 | .rhs = undefined, | |
| 2771 | }, | |
| 2630 | .data = undefined, | |
| 2772 | 2631 | }), |
| 2773 | 2632 | }, |
| 2774 | else => return p.addNode(.{ | |
| 2633 | else => return try p.addNode(.{ | |
| 2775 | 2634 | .tag = .identifier, |
| 2776 | 2635 | .main_token = p.nextToken(), |
| 2777 | .data = .{ | |
| 2778 | .lhs = undefined, | |
| 2779 | .rhs = undefined, | |
| 2780 | }, | |
| 2636 | .data = undefined, | |
| 2781 | 2637 | }), |
| 2782 | 2638 | }, |
| 2783 | 2639 | .keyword_inline => { |
| 2784 | 2640 | p.tok_i += 1; |
| 2785 | switch (p.token_tags[p.tok_i]) { | |
| 2786 | .keyword_for => return p.parseFor(expectTypeExpr), | |
| 2787 | .keyword_while => return p.parseWhileTypeExpr(), | |
| 2641 | switch (p.tokenTag(p.tok_i)) { | |
| 2642 | .keyword_for => return try p.parseFor(expectTypeExpr), | |
| 2643 | .keyword_while => return try p.parseWhileTypeExpr(), | |
| 2788 | 2644 | else => return p.fail(.expected_inlinable), |
| 2789 | 2645 | } |
| 2790 | 2646 | }, |
| 2791 | .keyword_for => return p.parseFor(expectTypeExpr), | |
| 2792 | .keyword_while => return p.parseWhileTypeExpr(), | |
| 2793 | .period => switch (p.token_tags[p.tok_i + 1]) { | |
| 2794 | .identifier => return p.addNode(.{ | |
| 2795 | .tag = .enum_literal, | |
| 2796 | .data = .{ | |
| 2797 | .lhs = p.nextToken(), // dot | |
| 2798 | .rhs = undefined, | |
| 2799 | }, | |
| 2800 | .main_token = p.nextToken(), // identifier | |
| 2801 | }), | |
| 2647 | .keyword_for => return try p.parseFor(expectTypeExpr), | |
| 2648 | .keyword_while => return try p.parseWhileTypeExpr(), | |
| 2649 | .period => switch (p.tokenTag(p.tok_i + 1)) { | |
| 2650 | .identifier => { | |
| 2651 | p.tok_i += 1; | |
| 2652 | return try p.addNode(.{ | |
| 2653 | .tag = .enum_literal, | |
| 2654 | .main_token = p.nextToken(), // identifier | |
| 2655 | .data = undefined, | |
| 2656 | }); | |
| 2657 | }, | |
| 2802 | 2658 | .l_brace => { |
| 2803 | 2659 | const lbrace = p.tok_i + 1; |
| 2804 | 2660 | p.tok_i = lbrace + 1; |
| ... | ... | @@ -2808,11 +2664,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2808 | 2664 | |
| 2809 | 2665 | const scratch_top = p.scratch.items.len; |
| 2810 | 2666 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2811 | const field_init = try p.parseFieldInit(); | |
| 2812 | if (field_init != 0) { | |
| 2667 | const opt_field_init = try p.parseFieldInit(); | |
| 2668 | if (opt_field_init) |field_init| { | |
| 2813 | 2669 | try p.scratch.append(p.gpa, field_init); |
| 2814 | 2670 | while (true) { |
| 2815 | switch (p.token_tags[p.tok_i]) { | |
| 2671 | switch (p.tokenTag(p.tok_i)) { | |
| 2816 | 2672 | .comma => p.tok_i += 1, |
| 2817 | 2673 | .r_brace => { |
| 2818 | 2674 | p.tok_i += 1; |
| ... | ... | @@ -2826,37 +2682,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2826 | 2682 | const next = try p.expectFieldInit(); |
| 2827 | 2683 | try p.scratch.append(p.gpa, next); |
| 2828 | 2684 | } |
| 2829 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 2685 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 2830 | 2686 | const inits = p.scratch.items[scratch_top..]; |
| 2831 | switch (inits.len) { | |
| 2832 | 0 => unreachable, | |
| 2833 | 1 => return p.addNode(.{ | |
| 2687 | std.debug.assert(inits.len != 0); | |
| 2688 | if (inits.len <= 2) { | |
| 2689 | return try p.addNode(.{ | |
| 2834 | 2690 | .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, |
| 2835 | 2691 | .main_token = lbrace, |
| 2836 | .data = .{ | |
| 2837 | .lhs = inits[0], | |
| 2838 | .rhs = 0, | |
| 2839 | }, | |
| 2840 | }), | |
| 2841 | 2 => return p.addNode(.{ | |
| 2842 | .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, | |
| 2692 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2693 | if (inits.len >= 1) .fromOptional(inits[0]) else .none, | |
| 2694 | if (inits.len >= 2) .fromOptional(inits[1]) else .none, | |
| 2695 | } }, | |
| 2696 | }); | |
| 2697 | } else { | |
| 2698 | return try p.addNode(.{ | |
| 2699 | .tag = if (comma) .struct_init_dot_comma else .struct_init_dot, | |
| 2843 | 2700 | .main_token = lbrace, |
| 2844 | .data = .{ | |
| 2845 | .lhs = inits[0], | |
| 2846 | .rhs = inits[1], | |
| 2847 | }, | |
| 2848 | }), | |
| 2849 | else => { | |
| 2850 | const span = try p.listToSpan(inits); | |
| 2851 | return p.addNode(.{ | |
| 2852 | .tag = if (comma) .struct_init_dot_comma else .struct_init_dot, | |
| 2853 | .main_token = lbrace, | |
| 2854 | .data = .{ | |
| 2855 | .lhs = span.start, | |
| 2856 | .rhs = span.end, | |
| 2857 | }, | |
| 2858 | }); | |
| 2859 | }, | |
| 2701 | .data = .{ .extra_range = try p.listToSpan(inits) }, | |
| 2702 | }); | |
| 2860 | 2703 | } |
| 2861 | 2704 | } |
| 2862 | 2705 | |
| ... | ... | @@ -2864,7 +2707,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2864 | 2707 | if (p.eatToken(.r_brace)) |_| break; |
| 2865 | 2708 | const elem_init = try p.expectExpr(); |
| 2866 | 2709 | try p.scratch.append(p.gpa, elem_init); |
| 2867 | switch (p.token_tags[p.tok_i]) { | |
| 2710 | switch (p.tokenTag(p.tok_i)) { | |
| 2868 | 2711 | .comma => p.tok_i += 1, |
| 2869 | 2712 | .r_brace => { |
| 2870 | 2713 | p.tok_i += 1; |
| ... | ... | @@ -2875,49 +2718,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2875 | 2718 | else => try p.warn(.expected_comma_after_initializer), |
| 2876 | 2719 | } |
| 2877 | 2720 | } |
| 2878 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 2721 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 2879 | 2722 | const inits = p.scratch.items[scratch_top..]; |
| 2880 | switch (inits.len) { | |
| 2881 | 0 => return p.addNode(.{ | |
| 2882 | .tag = .struct_init_dot_two, | |
| 2723 | if (inits.len <= 2) { | |
| 2724 | return try p.addNode(.{ | |
| 2725 | .tag = if (inits.len == 0) | |
| 2726 | .struct_init_dot_two | |
| 2727 | else if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2883 | 2728 | .main_token = lbrace, |
| 2884 | .data = .{ | |
| 2885 | .lhs = 0, | |
| 2886 | .rhs = 0, | |
| 2887 | }, | |
| 2888 | }), | |
| 2889 | 1 => return p.addNode(.{ | |
| 2890 | .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2891 | .main_token = lbrace, | |
| 2892 | .data = .{ | |
| 2893 | .lhs = inits[0], | |
| 2894 | .rhs = 0, | |
| 2895 | }, | |
| 2896 | }), | |
| 2897 | 2 => return p.addNode(.{ | |
| 2898 | .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2729 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2730 | if (inits.len >= 1) inits[0].toOptional() else .none, | |
| 2731 | if (inits.len >= 2) inits[1].toOptional() else .none, | |
| 2732 | } }, | |
| 2733 | }); | |
| 2734 | } else { | |
| 2735 | return try p.addNode(.{ | |
| 2736 | .tag = if (comma) .array_init_dot_comma else .array_init_dot, | |
| 2899 | 2737 | .main_token = lbrace, |
| 2900 | .data = .{ | |
| 2901 | .lhs = inits[0], | |
| 2902 | .rhs = inits[1], | |
| 2903 | }, | |
| 2904 | }), | |
| 2905 | else => { | |
| 2906 | const span = try p.listToSpan(inits); | |
| 2907 | return p.addNode(.{ | |
| 2908 | .tag = if (comma) .array_init_dot_comma else .array_init_dot, | |
| 2909 | .main_token = lbrace, | |
| 2910 | .data = .{ | |
| 2911 | .lhs = span.start, | |
| 2912 | .rhs = span.end, | |
| 2913 | }, | |
| 2914 | }); | |
| 2915 | }, | |
| 2738 | .data = .{ .extra_range = try p.listToSpan(inits) }, | |
| 2739 | }); | |
| 2916 | 2740 | } |
| 2917 | 2741 | }, |
| 2918 | else => return null_node, | |
| 2742 | else => return null, | |
| 2919 | 2743 | }, |
| 2920 | .keyword_error => switch (p.token_tags[p.tok_i + 1]) { | |
| 2744 | .keyword_error => switch (p.tokenTag(p.tok_i + 1)) { | |
| 2921 | 2745 | .l_brace => { |
| 2922 | 2746 | const error_token = p.tok_i; |
| 2923 | 2747 | p.tok_i += 2; |
| ... | ... | @@ -2925,7 +2749,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2925 | 2749 | if (p.eatToken(.r_brace)) |_| break; |
| 2926 | 2750 | _ = try p.eatDocComments(); |
| 2927 | 2751 | _ = try p.expectToken(.identifier); |
| 2928 | switch (p.token_tags[p.tok_i]) { | |
| 2752 | switch (p.tokenTag(p.tok_i)) { | |
| 2929 | 2753 | .comma => p.tok_i += 1, |
| 2930 | 2754 | .r_brace => { |
| 2931 | 2755 | p.tok_i += 1; |
| ... | ... | @@ -2936,12 +2760,14 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2936 | 2760 | else => try p.warn(.expected_comma_after_field), |
| 2937 | 2761 | } |
| 2938 | 2762 | } |
| 2939 | return p.addNode(.{ | |
| 2763 | return try p.addNode(.{ | |
| 2940 | 2764 | .tag = .error_set_decl, |
| 2941 | 2765 | .main_token = error_token, |
| 2942 | 2766 | .data = .{ |
| 2943 | .lhs = undefined, | |
| 2944 | .rhs = p.tok_i - 1, // rbrace | |
| 2767 | .token_and_token = .{ | |
| 2768 | error_token + 1, // lbrace | |
| 2769 | p.tok_i - 1, // rbrace | |
| 2770 | }, | |
| 2945 | 2771 | }, |
| 2946 | 2772 | }); |
| 2947 | 2773 | }, |
| ... | ... | @@ -2951,41 +2777,34 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2951 | 2777 | if (period == null) try p.warnExpected(.period); |
| 2952 | 2778 | const identifier = p.eatToken(.identifier); |
| 2953 | 2779 | if (identifier == null) try p.warnExpected(.identifier); |
| 2954 | return p.addNode(.{ | |
| 2780 | return try p.addNode(.{ | |
| 2955 | 2781 | .tag = .error_value, |
| 2956 | 2782 | .main_token = main_token, |
| 2957 | .data = .{ | |
| 2958 | .lhs = period orelse 0, | |
| 2959 | .rhs = identifier orelse 0, | |
| 2960 | }, | |
| 2783 | .data = undefined, | |
| 2961 | 2784 | }); |
| 2962 | 2785 | }, |
| 2963 | 2786 | }, |
| 2964 | .l_paren => return p.addNode(.{ | |
| 2787 | .l_paren => return try p.addNode(.{ | |
| 2965 | 2788 | .tag = .grouped_expression, |
| 2966 | 2789 | .main_token = p.nextToken(), |
| 2967 | .data = .{ | |
| 2968 | .lhs = try p.expectExpr(), | |
| 2969 | .rhs = try p.expectToken(.r_paren), | |
| 2970 | }, | |
| 2790 | .data = .{ .node_and_token = .{ | |
| 2791 | try p.expectExpr(), | |
| 2792 | try p.expectToken(.r_paren), | |
| 2793 | } }, | |
| 2971 | 2794 | }), |
| 2972 | else => return null_node, | |
| 2795 | else => return null, | |
| 2973 | 2796 | } |
| 2974 | 2797 | } |
| 2975 | 2798 | |
| 2976 | 2799 | fn expectPrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2977 | const node = try p.parsePrimaryTypeExpr(); | |
| 2978 | if (node == 0) { | |
| 2979 | return p.fail(.expected_primary_type_expr); | |
| 2980 | } | |
| 2981 | return node; | |
| 2800 | return try p.parsePrimaryTypeExpr() orelse return p.fail(.expected_primary_type_expr); | |
| 2982 | 2801 | } |
| 2983 | 2802 | |
| 2984 | 2803 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2985 | 2804 | /// |
| 2986 | 2805 | /// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)? |
| 2987 | fn parseWhileTypeExpr(p: *Parse) !Node.Index { | |
| 2988 | const while_token = p.eatToken(.keyword_while) orelse return null_node; | |
| 2806 | fn parseWhileTypeExpr(p: *Parse) !?Node.Index { | |
| 2807 | const while_token = p.eatToken(.keyword_while) orelse return null; | |
| 2989 | 2808 | _ = try p.expectToken(.l_paren); |
| 2990 | 2809 | const condition = try p.expectExpr(); |
| 2991 | 2810 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -2994,54 +2813,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index { |
| 2994 | 2813 | |
| 2995 | 2814 | const then_expr = try p.expectTypeExpr(); |
| 2996 | 2815 | _ = p.eatToken(.keyword_else) orelse { |
| 2997 | if (cont_expr == 0) { | |
| 2998 | return p.addNode(.{ | |
| 2816 | if (cont_expr == null) { | |
| 2817 | return try p.addNode(.{ | |
| 2999 | 2818 | .tag = .while_simple, |
| 3000 | 2819 | .main_token = while_token, |
| 3001 | .data = .{ | |
| 3002 | .lhs = condition, | |
| 3003 | .rhs = then_expr, | |
| 3004 | }, | |
| 2820 | .data = .{ .node_and_node = .{ | |
| 2821 | condition, | |
| 2822 | then_expr, | |
| 2823 | } }, | |
| 3005 | 2824 | }); |
| 3006 | 2825 | } else { |
| 3007 | return p.addNode(.{ | |
| 2826 | return try p.addNode(.{ | |
| 3008 | 2827 | .tag = .while_cont, |
| 3009 | 2828 | .main_token = while_token, |
| 3010 | .data = .{ | |
| 3011 | .lhs = condition, | |
| 3012 | .rhs = try p.addExtra(Node.WhileCont{ | |
| 3013 | .cont_expr = cont_expr, | |
| 2829 | .data = .{ .node_and_extra = .{ | |
| 2830 | condition, try p.addExtra(Node.WhileCont{ | |
| 2831 | .cont_expr = cont_expr.?, | |
| 3014 | 2832 | .then_expr = then_expr, |
| 3015 | 2833 | }), |
| 3016 | }, | |
| 2834 | } }, | |
| 3017 | 2835 | }); |
| 3018 | 2836 | } |
| 3019 | 2837 | }; |
| 3020 | 2838 | _ = try p.parsePayload(); |
| 3021 | 2839 | const else_expr = try p.expectTypeExpr(); |
| 3022 | return p.addNode(.{ | |
| 2840 | return try p.addNode(.{ | |
| 3023 | 2841 | .tag = .@"while", |
| 3024 | 2842 | .main_token = while_token, |
| 3025 | .data = .{ | |
| 3026 | .lhs = condition, | |
| 3027 | .rhs = try p.addExtra(Node.While{ | |
| 3028 | .cont_expr = cont_expr, | |
| 2843 | .data = .{ .node_and_extra = .{ | |
| 2844 | condition, try p.addExtra(Node.While{ | |
| 2845 | .cont_expr = .fromOptional(cont_expr), | |
| 3029 | 2846 | .then_expr = then_expr, |
| 3030 | 2847 | .else_expr = else_expr, |
| 3031 | 2848 | }), |
| 3032 | }, | |
| 2849 | } }, | |
| 3033 | 2850 | }); |
| 3034 | 2851 | } |
| 3035 | 2852 | |
| 3036 | 2853 | /// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE |
| 3037 | fn parseSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index { | |
| 3038 | const switch_token = p.eatToken(.keyword_switch) orelse return null_node; | |
| 3039 | return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 2854 | fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index { | |
| 2855 | const switch_token = p.eatToken(.keyword_switch) orelse return null; | |
| 2856 | return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 3040 | 2857 | } |
| 3041 | 2858 | |
| 3042 | 2859 | fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index { |
| 3043 | 2860 | const switch_token = p.assertToken(.keyword_switch); |
| 3044 | return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 2861 | return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 3045 | 2862 | } |
| 3046 | 2863 | |
| 3047 | 2864 | fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { |
| ... | ... | @@ -3050,19 +2867,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { |
| 3050 | 2867 | _ = try p.expectToken(.r_paren); |
| 3051 | 2868 | _ = try p.expectToken(.l_brace); |
| 3052 | 2869 | const cases = try p.parseSwitchProngList(); |
| 3053 | const trailing_comma = p.token_tags[p.tok_i - 1] == .comma; | |
| 2870 | const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma; | |
| 3054 | 2871 | _ = try p.expectToken(.r_brace); |
| 3055 | 2872 | |
| 3056 | 2873 | return p.addNode(.{ |
| 3057 | 2874 | .tag = if (trailing_comma) .switch_comma else .@"switch", |
| 3058 | 2875 | .main_token = main_token, |
| 3059 | .data = .{ | |
| 3060 | .lhs = expr_node, | |
| 3061 | .rhs = try p.addExtra(Node.SubRange{ | |
| 2876 | .data = .{ .node_and_extra = .{ | |
| 2877 | expr_node, | |
| 2878 | try p.addExtra(Node.SubRange{ | |
| 3062 | 2879 | .start = cases.start, |
| 3063 | 2880 | .end = cases.end, |
| 3064 | 2881 | }), |
| 3065 | }, | |
| 2882 | } }, | |
| 3066 | 2883 | }); |
| 3067 | 2884 | } |
| 3068 | 2885 | |
| ... | ... | @@ -3089,10 +2906,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3089 | 2906 | return p.addNode(.{ |
| 3090 | 2907 | .tag = .asm_simple, |
| 3091 | 2908 | .main_token = asm_token, |
| 3092 | .data = .{ | |
| 3093 | .lhs = template, | |
| 3094 | .rhs = rparen, | |
| 3095 | }, | |
| 2909 | .data = .{ .node_and_token = .{ | |
| 2910 | template, | |
| 2911 | rparen, | |
| 2912 | } }, | |
| 3096 | 2913 | }); |
| 3097 | 2914 | } |
| 3098 | 2915 | |
| ... | ... | @@ -3102,10 +2919,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3102 | 2919 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3103 | 2920 | |
| 3104 | 2921 | while (true) { |
| 3105 | const output_item = try p.parseAsmOutputItem(); | |
| 3106 | if (output_item == 0) break; | |
| 2922 | const output_item = try p.parseAsmOutputItem() orelse break; | |
| 3107 | 2923 | try p.scratch.append(p.gpa, output_item); |
| 3108 | switch (p.token_tags[p.tok_i]) { | |
| 2924 | switch (p.tokenTag(p.tok_i)) { | |
| 3109 | 2925 | .comma => p.tok_i += 1, |
| 3110 | 2926 | // All possible delimiters. |
| 3111 | 2927 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3115,10 +2931,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3115 | 2931 | } |
| 3116 | 2932 | if (p.eatToken(.colon)) |_| { |
| 3117 | 2933 | while (true) { |
| 3118 | const input_item = try p.parseAsmInputItem(); | |
| 3119 | if (input_item == 0) break; | |
| 2934 | const input_item = try p.parseAsmInputItem() orelse break; | |
| 3120 | 2935 | try p.scratch.append(p.gpa, input_item); |
| 3121 | switch (p.token_tags[p.tok_i]) { | |
| 2936 | switch (p.tokenTag(p.tok_i)) { | |
| 3122 | 2937 | .comma => p.tok_i += 1, |
| 3123 | 2938 | // All possible delimiters. |
| 3124 | 2939 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3128,7 +2943,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3128 | 2943 | } |
| 3129 | 2944 | if (p.eatToken(.colon)) |_| { |
| 3130 | 2945 | while (p.eatToken(.string_literal)) |_| { |
| 3131 | switch (p.token_tags[p.tok_i]) { | |
| 2946 | switch (p.tokenTag(p.tok_i)) { | |
| 3132 | 2947 | .comma => p.tok_i += 1, |
| 3133 | 2948 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| 3134 | 2949 | // Likely just a missing comma; give error but continue parsing. |
| ... | ... | @@ -3142,121 +2957,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3142 | 2957 | return p.addNode(.{ |
| 3143 | 2958 | .tag = .@"asm", |
| 3144 | 2959 | .main_token = asm_token, |
| 3145 | .data = .{ | |
| 3146 | .lhs = template, | |
| 3147 | .rhs = try p.addExtra(Node.Asm{ | |
| 2960 | .data = .{ .node_and_extra = .{ | |
| 2961 | template, | |
| 2962 | try p.addExtra(Node.Asm{ | |
| 3148 | 2963 | .items_start = span.start, |
| 3149 | 2964 | .items_end = span.end, |
| 3150 | 2965 | .rparen = rparen, |
| 3151 | 2966 | }), |
| 3152 | }, | |
| 2967 | } }, | |
| 3153 | 2968 | }); |
| 3154 | 2969 | } |
| 3155 | 2970 | |
| 3156 | 2971 | /// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN |
| 3157 | fn parseAsmOutputItem(p: *Parse) !Node.Index { | |
| 3158 | _ = p.eatToken(.l_bracket) orelse return null_node; | |
| 2972 | fn parseAsmOutputItem(p: *Parse) !?Node.Index { | |
| 2973 | _ = p.eatToken(.l_bracket) orelse return null; | |
| 3159 | 2974 | const identifier = try p.expectToken(.identifier); |
| 3160 | 2975 | _ = try p.expectToken(.r_bracket); |
| 3161 | 2976 | _ = try p.expectToken(.string_literal); |
| 3162 | 2977 | _ = try p.expectToken(.l_paren); |
| 3163 | const type_expr: Node.Index = blk: { | |
| 2978 | const type_expr: Node.OptionalIndex = blk: { | |
| 3164 | 2979 | if (p.eatToken(.arrow)) |_| { |
| 3165 | break :blk try p.expectTypeExpr(); | |
| 2980 | break :blk .fromOptional(try p.expectTypeExpr()); | |
| 3166 | 2981 | } else { |
| 3167 | 2982 | _ = try p.expectToken(.identifier); |
| 3168 | break :blk null_node; | |
| 2983 | break :blk .none; | |
| 3169 | 2984 | } |
| 3170 | 2985 | }; |
| 3171 | 2986 | const rparen = try p.expectToken(.r_paren); |
| 3172 | return p.addNode(.{ | |
| 2987 | return try p.addNode(.{ | |
| 3173 | 2988 | .tag = .asm_output, |
| 3174 | 2989 | .main_token = identifier, |
| 3175 | .data = .{ | |
| 3176 | .lhs = type_expr, | |
| 3177 | .rhs = rparen, | |
| 3178 | }, | |
| 2990 | .data = .{ .opt_node_and_token = .{ | |
| 2991 | type_expr, | |
| 2992 | rparen, | |
| 2993 | } }, | |
| 3179 | 2994 | }); |
| 3180 | 2995 | } |
| 3181 | 2996 | |
| 3182 | 2997 | /// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN |
| 3183 | fn parseAsmInputItem(p: *Parse) !Node.Index { | |
| 3184 | _ = p.eatToken(.l_bracket) orelse return null_node; | |
| 2998 | fn parseAsmInputItem(p: *Parse) !?Node.Index { | |
| 2999 | _ = p.eatToken(.l_bracket) orelse return null; | |
| 3185 | 3000 | const identifier = try p.expectToken(.identifier); |
| 3186 | 3001 | _ = try p.expectToken(.r_bracket); |
| 3187 | 3002 | _ = try p.expectToken(.string_literal); |
| 3188 | 3003 | _ = try p.expectToken(.l_paren); |
| 3189 | 3004 | const expr = try p.expectExpr(); |
| 3190 | 3005 | const rparen = try p.expectToken(.r_paren); |
| 3191 | return p.addNode(.{ | |
| 3006 | return try p.addNode(.{ | |
| 3192 | 3007 | .tag = .asm_input, |
| 3193 | 3008 | .main_token = identifier, |
| 3194 | .data = .{ | |
| 3195 | .lhs = expr, | |
| 3196 | .rhs = rparen, | |
| 3197 | }, | |
| 3009 | .data = .{ .node_and_token = .{ | |
| 3010 | expr, | |
| 3011 | rparen, | |
| 3012 | } }, | |
| 3198 | 3013 | }); |
| 3199 | 3014 | } |
| 3200 | 3015 | |
| 3201 | 3016 | /// BreakLabel <- COLON IDENTIFIER |
| 3202 | fn parseBreakLabel(p: *Parse) !TokenIndex { | |
| 3203 | _ = p.eatToken(.colon) orelse return null_node; | |
| 3204 | return p.expectToken(.identifier); | |
| 3017 | fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex { | |
| 3018 | _ = p.eatToken(.colon) orelse return .none; | |
| 3019 | const next_token = try p.expectToken(.identifier); | |
| 3020 | return .fromToken(next_token); | |
| 3205 | 3021 | } |
| 3206 | 3022 | |
| 3207 | 3023 | /// BlockLabel <- IDENTIFIER COLON |
| 3208 | fn parseBlockLabel(p: *Parse) TokenIndex { | |
| 3209 | if (p.token_tags[p.tok_i] == .identifier and | |
| 3210 | p.token_tags[p.tok_i + 1] == .colon) | |
| 3211 | { | |
| 3212 | const identifier = p.tok_i; | |
| 3213 | p.tok_i += 2; | |
| 3214 | return identifier; | |
| 3215 | } | |
| 3216 | return null_node; | |
| 3024 | fn parseBlockLabel(p: *Parse) ?TokenIndex { | |
| 3025 | return p.eatTokens(&.{ .identifier, .colon }); | |
| 3217 | 3026 | } |
| 3218 | 3027 | |
| 3219 | 3028 | /// FieldInit <- DOT IDENTIFIER EQUAL Expr |
| 3220 | fn parseFieldInit(p: *Parse) !Node.Index { | |
| 3221 | if (p.token_tags[p.tok_i + 0] == .period and | |
| 3222 | p.token_tags[p.tok_i + 1] == .identifier and | |
| 3223 | p.token_tags[p.tok_i + 2] == .equal) | |
| 3224 | { | |
| 3225 | p.tok_i += 3; | |
| 3226 | return p.expectExpr(); | |
| 3227 | } else { | |
| 3228 | return null_node; | |
| 3029 | fn parseFieldInit(p: *Parse) !?Node.Index { | |
| 3030 | if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| { | |
| 3031 | return try p.expectExpr(); | |
| 3229 | 3032 | } |
| 3033 | return null; | |
| 3230 | 3034 | } |
| 3231 | 3035 | |
| 3232 | 3036 | fn expectFieldInit(p: *Parse) !Node.Index { |
| 3233 | if (p.token_tags[p.tok_i] != .period or | |
| 3234 | p.token_tags[p.tok_i + 1] != .identifier or | |
| 3235 | p.token_tags[p.tok_i + 2] != .equal) | |
| 3236 | return p.fail(.expected_initializer); | |
| 3237 | ||
| 3238 | p.tok_i += 3; | |
| 3239 | return p.expectExpr(); | |
| 3037 | if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| { | |
| 3038 | return try p.expectExpr(); | |
| 3039 | } | |
| 3040 | return p.fail(.expected_initializer); | |
| 3240 | 3041 | } |
| 3241 | 3042 | |
| 3242 | 3043 | /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN |
| 3243 | fn parseWhileContinueExpr(p: *Parse) !Node.Index { | |
| 3044 | fn parseWhileContinueExpr(p: *Parse) !?Node.Index { | |
| 3244 | 3045 | _ = p.eatToken(.colon) orelse { |
| 3245 | if (p.token_tags[p.tok_i] == .l_paren and | |
| 3046 | if (p.tokenTag(p.tok_i) == .l_paren and | |
| 3246 | 3047 | p.tokensOnSameLine(p.tok_i - 1, p.tok_i)) |
| 3247 | 3048 | return p.fail(.expected_continue_expr); |
| 3248 | return null_node; | |
| 3049 | return null; | |
| 3249 | 3050 | }; |
| 3250 | 3051 | _ = try p.expectToken(.l_paren); |
| 3251 | const node = try p.parseAssignExpr(); | |
| 3252 | if (node == 0) return p.fail(.expected_expr_or_assignment); | |
| 3052 | const node = try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment); | |
| 3253 | 3053 | _ = try p.expectToken(.r_paren); |
| 3254 | 3054 | return node; |
| 3255 | 3055 | } |
| 3256 | 3056 | |
| 3257 | 3057 | /// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN |
| 3258 | fn parseLinkSection(p: *Parse) !Node.Index { | |
| 3259 | _ = p.eatToken(.keyword_linksection) orelse return null_node; | |
| 3058 | fn parseLinkSection(p: *Parse) !?Node.Index { | |
| 3059 | _ = p.eatToken(.keyword_linksection) orelse return null; | |
| 3260 | 3060 | _ = try p.expectToken(.l_paren); |
| 3261 | 3061 | const expr_node = try p.expectExpr(); |
| 3262 | 3062 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3264,8 +3064,8 @@ fn parseLinkSection(p: *Parse) !Node.Index { |
| 3264 | 3064 | } |
| 3265 | 3065 | |
| 3266 | 3066 | /// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN |
| 3267 | fn parseCallconv(p: *Parse) !Node.Index { | |
| 3268 | _ = p.eatToken(.keyword_callconv) orelse return null_node; | |
| 3067 | fn parseCallconv(p: *Parse) !?Node.Index { | |
| 3068 | _ = p.eatToken(.keyword_callconv) orelse return null; | |
| 3269 | 3069 | _ = try p.expectToken(.l_paren); |
| 3270 | 3070 | const expr_node = try p.expectExpr(); |
| 3271 | 3071 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3273,8 +3073,8 @@ fn parseCallconv(p: *Parse) !Node.Index { |
| 3273 | 3073 | } |
| 3274 | 3074 | |
| 3275 | 3075 | /// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN |
| 3276 | fn parseAddrSpace(p: *Parse) !Node.Index { | |
| 3277 | _ = p.eatToken(.keyword_addrspace) orelse return null_node; | |
| 3076 | fn parseAddrSpace(p: *Parse) !?Node.Index { | |
| 3077 | _ = p.eatToken(.keyword_addrspace) orelse return null; | |
| 3278 | 3078 | _ = try p.expectToken(.l_paren); |
| 3279 | 3079 | const expr_node = try p.expectExpr(); |
| 3280 | 3080 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3292,59 +3092,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index { |
| 3292 | 3092 | /// ParamType |
| 3293 | 3093 | /// <- KEYWORD_anytype |
| 3294 | 3094 | /// / TypeExpr |
| 3295 | fn expectParamDecl(p: *Parse) !Node.Index { | |
| 3095 | fn expectParamDecl(p: *Parse) !?Node.Index { | |
| 3296 | 3096 | _ = try p.eatDocComments(); |
| 3297 | switch (p.token_tags[p.tok_i]) { | |
| 3097 | switch (p.tokenTag(p.tok_i)) { | |
| 3298 | 3098 | .keyword_noalias, .keyword_comptime => p.tok_i += 1, |
| 3299 | 3099 | .ellipsis3 => { |
| 3300 | 3100 | p.tok_i += 1; |
| 3301 | return null_node; | |
| 3101 | return null; | |
| 3302 | 3102 | }, |
| 3303 | 3103 | else => {}, |
| 3304 | 3104 | } |
| 3305 | if (p.token_tags[p.tok_i] == .identifier and | |
| 3306 | p.token_tags[p.tok_i + 1] == .colon) | |
| 3307 | { | |
| 3308 | p.tok_i += 2; | |
| 3309 | } | |
| 3310 | switch (p.token_tags[p.tok_i]) { | |
| 3311 | .keyword_anytype => { | |
| 3312 | p.tok_i += 1; | |
| 3313 | return null_node; | |
| 3314 | }, | |
| 3315 | else => return p.expectTypeExpr(), | |
| 3105 | _ = p.eatTokens(&.{ .identifier, .colon }); | |
| 3106 | if (p.eatToken(.keyword_anytype)) |_| { | |
| 3107 | return null; | |
| 3108 | } else { | |
| 3109 | return try p.expectTypeExpr(); | |
| 3316 | 3110 | } |
| 3317 | 3111 | } |
| 3318 | 3112 | |
| 3319 | 3113 | /// Payload <- PIPE IDENTIFIER PIPE |
| 3320 | fn parsePayload(p: *Parse) !TokenIndex { | |
| 3321 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3114 | fn parsePayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3115 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3322 | 3116 | const identifier = try p.expectToken(.identifier); |
| 3323 | 3117 | _ = try p.expectToken(.pipe); |
| 3324 | return identifier; | |
| 3118 | return .fromToken(identifier); | |
| 3325 | 3119 | } |
| 3326 | 3120 | |
| 3327 | 3121 | /// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE |
| 3328 | fn parsePtrPayload(p: *Parse) !TokenIndex { | |
| 3329 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3122 | fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3123 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3330 | 3124 | _ = p.eatToken(.asterisk); |
| 3331 | 3125 | const identifier = try p.expectToken(.identifier); |
| 3332 | 3126 | _ = try p.expectToken(.pipe); |
| 3333 | return identifier; | |
| 3127 | return .fromToken(identifier); | |
| 3334 | 3128 | } |
| 3335 | 3129 | |
| 3336 | 3130 | /// Returns the first identifier token, if any. |
| 3337 | 3131 | /// |
| 3338 | 3132 | /// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 3339 | fn parsePtrIndexPayload(p: *Parse) !TokenIndex { | |
| 3340 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3133 | fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3134 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3341 | 3135 | _ = p.eatToken(.asterisk); |
| 3342 | 3136 | const identifier = try p.expectToken(.identifier); |
| 3343 | 3137 | if (p.eatToken(.comma) != null) { |
| 3344 | 3138 | _ = try p.expectToken(.identifier); |
| 3345 | 3139 | } |
| 3346 | 3140 | _ = try p.expectToken(.pipe); |
| 3347 | return identifier; | |
| 3141 | return .fromToken(identifier); | |
| 3348 | 3142 | } |
| 3349 | 3143 | |
| 3350 | 3144 | /// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr |
| ... | ... | @@ -3352,7 +3146,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex { |
| 3352 | 3146 | /// SwitchCase |
| 3353 | 3147 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 3354 | 3148 | /// / KEYWORD_else |
| 3355 | fn parseSwitchProng(p: *Parse) !Node.Index { | |
| 3149 | fn parseSwitchProng(p: *Parse) !?Node.Index { | |
| 3356 | 3150 | const scratch_top = p.scratch.items.len; |
| 3357 | 3151 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3358 | 3152 | |
| ... | ... | @@ -3360,97 +3154,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index { |
| 3360 | 3154 | |
| 3361 | 3155 | if (p.eatToken(.keyword_else) == null) { |
| 3362 | 3156 | while (true) { |
| 3363 | const item = try p.parseSwitchItem(); | |
| 3364 | if (item == 0) break; | |
| 3157 | const item = try p.parseSwitchItem() orelse break; | |
| 3365 | 3158 | try p.scratch.append(p.gpa, item); |
| 3366 | 3159 | if (p.eatToken(.comma) == null) break; |
| 3367 | 3160 | } |
| 3368 | 3161 | if (scratch_top == p.scratch.items.len) { |
| 3369 | 3162 | if (is_inline) p.tok_i -= 1; |
| 3370 | return null_node; | |
| 3163 | return null; | |
| 3371 | 3164 | } |
| 3372 | 3165 | } |
| 3373 | 3166 | const arrow_token = try p.expectToken(.equal_angle_bracket_right); |
| 3374 | 3167 | _ = try p.parsePtrIndexPayload(); |
| 3375 | 3168 | |
| 3376 | 3169 | const items = p.scratch.items[scratch_top..]; |
| 3377 | switch (items.len) { | |
| 3378 | 0 => return p.addNode(.{ | |
| 3170 | if (items.len <= 1) { | |
| 3171 | return try p.addNode(.{ | |
| 3379 | 3172 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, |
| 3380 | 3173 | .main_token = arrow_token, |
| 3381 | .data = .{ | |
| 3382 | .lhs = 0, | |
| 3383 | .rhs = try p.expectSingleAssignExpr(), | |
| 3384 | }, | |
| 3385 | }), | |
| 3386 | 1 => return p.addNode(.{ | |
| 3387 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, | |
| 3388 | .main_token = arrow_token, | |
| 3389 | .data = .{ | |
| 3390 | .lhs = items[0], | |
| 3391 | .rhs = try p.expectSingleAssignExpr(), | |
| 3392 | }, | |
| 3393 | }), | |
| 3394 | else => return p.addNode(.{ | |
| 3174 | .data = .{ .opt_node_and_node = .{ | |
| 3175 | if (items.len >= 1) items[0].toOptional() else .none, | |
| 3176 | try p.expectSingleAssignExpr(), | |
| 3177 | } }, | |
| 3178 | }); | |
| 3179 | } else { | |
| 3180 | return try p.addNode(.{ | |
| 3395 | 3181 | .tag = if (is_inline) .switch_case_inline else .switch_case, |
| 3396 | 3182 | .main_token = arrow_token, |
| 3397 | .data = .{ | |
| 3398 | .lhs = try p.addExtra(try p.listToSpan(items)), | |
| 3399 | .rhs = try p.expectSingleAssignExpr(), | |
| 3400 | }, | |
| 3401 | }), | |
| 3183 | .data = .{ .extra_and_node = .{ | |
| 3184 | try p.addExtra(try p.listToSpan(items)), | |
| 3185 | try p.expectSingleAssignExpr(), | |
| 3186 | } }, | |
| 3187 | }); | |
| 3402 | 3188 | } |
| 3403 | 3189 | } |
| 3404 | 3190 | |
| 3405 | 3191 | /// SwitchItem <- Expr (DOT3 Expr)? |
| 3406 | fn parseSwitchItem(p: *Parse) !Node.Index { | |
| 3407 | const expr = try p.parseExpr(); | |
| 3408 | if (expr == 0) return null_node; | |
| 3192 | fn parseSwitchItem(p: *Parse) !?Node.Index { | |
| 3193 | const expr = try p.parseExpr() orelse return null; | |
| 3409 | 3194 | |
| 3410 | 3195 | if (p.eatToken(.ellipsis3)) |token| { |
| 3411 | return p.addNode(.{ | |
| 3196 | return try p.addNode(.{ | |
| 3412 | 3197 | .tag = .switch_range, |
| 3413 | 3198 | .main_token = token, |
| 3414 | .data = .{ | |
| 3415 | .lhs = expr, | |
| 3416 | .rhs = try p.expectExpr(), | |
| 3417 | }, | |
| 3199 | .data = .{ .node_and_node = .{ | |
| 3200 | expr, | |
| 3201 | try p.expectExpr(), | |
| 3202 | } }, | |
| 3418 | 3203 | }); |
| 3419 | 3204 | } |
| 3420 | 3205 | return expr; |
| 3421 | 3206 | } |
| 3422 | 3207 | |
| 3208 | /// The following invariant will hold: | |
| 3209 | /// - `(bit_range_start == .none) == (bit_range_end == .none)` | |
| 3210 | /// - `bit_range_start != .none` implies `align_node != .none` | |
| 3211 | /// - `bit_range_end != .none` implies `align_node != .none` | |
| 3423 | 3212 | const PtrModifiers = struct { |
| 3424 | align_node: Node.Index, | |
| 3425 | addrspace_node: Node.Index, | |
| 3426 | bit_range_start: Node.Index, | |
| 3427 | bit_range_end: Node.Index, | |
| 3213 | align_node: Node.OptionalIndex, | |
| 3214 | addrspace_node: Node.OptionalIndex, | |
| 3215 | bit_range_start: Node.OptionalIndex, | |
| 3216 | bit_range_end: Node.OptionalIndex, | |
| 3428 | 3217 | }; |
| 3429 | 3218 | |
| 3430 | 3219 | fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3431 | 3220 | var result: PtrModifiers = .{ |
| 3432 | .align_node = 0, | |
| 3433 | .addrspace_node = 0, | |
| 3434 | .bit_range_start = 0, | |
| 3435 | .bit_range_end = 0, | |
| 3221 | .align_node = .none, | |
| 3222 | .addrspace_node = .none, | |
| 3223 | .bit_range_start = .none, | |
| 3224 | .bit_range_end = .none, | |
| 3436 | 3225 | }; |
| 3437 | 3226 | var saw_const = false; |
| 3438 | 3227 | var saw_volatile = false; |
| 3439 | 3228 | var saw_allowzero = false; |
| 3440 | 3229 | while (true) { |
| 3441 | switch (p.token_tags[p.tok_i]) { | |
| 3230 | switch (p.tokenTag(p.tok_i)) { | |
| 3442 | 3231 | .keyword_align => { |
| 3443 | if (result.align_node != 0) { | |
| 3232 | if (result.align_node != .none) { | |
| 3444 | 3233 | try p.warn(.extra_align_qualifier); |
| 3445 | 3234 | } |
| 3446 | 3235 | p.tok_i += 1; |
| 3447 | 3236 | _ = try p.expectToken(.l_paren); |
| 3448 | result.align_node = try p.expectExpr(); | |
| 3237 | result.align_node = (try p.expectExpr()).toOptional(); | |
| 3449 | 3238 | |
| 3450 | 3239 | if (p.eatToken(.colon)) |_| { |
| 3451 | result.bit_range_start = try p.expectExpr(); | |
| 3240 | result.bit_range_start = (try p.expectExpr()).toOptional(); | |
| 3452 | 3241 | _ = try p.expectToken(.colon); |
| 3453 | result.bit_range_end = try p.expectExpr(); | |
| 3242 | result.bit_range_end = (try p.expectExpr()).toOptional(); | |
| 3454 | 3243 | } |
| 3455 | 3244 | |
| 3456 | 3245 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3477,10 +3266,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3477 | 3266 | saw_allowzero = true; |
| 3478 | 3267 | }, |
| 3479 | 3268 | .keyword_addrspace => { |
| 3480 | if (result.addrspace_node != 0) { | |
| 3269 | if (result.addrspace_node != .none) { | |
| 3481 | 3270 | try p.warn(.extra_addrspace_qualifier); |
| 3482 | 3271 | } |
| 3483 | result.addrspace_node = try p.parseAddrSpace(); | |
| 3272 | result.addrspace_node = .fromOptional(try p.parseAddrSpace()); | |
| 3484 | 3273 | }, |
| 3485 | 3274 | else => return result, |
| 3486 | 3275 | } |
| ... | ... | @@ -3492,110 +3281,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3492 | 3281 | /// / DOT IDENTIFIER |
| 3493 | 3282 | /// / DOTASTERISK |
| 3494 | 3283 | /// / DOTQUESTIONMARK |
| 3495 | fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index { | |
| 3496 | switch (p.token_tags[p.tok_i]) { | |
| 3284 | fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index { | |
| 3285 | switch (p.tokenTag(p.tok_i)) { | |
| 3497 | 3286 | .l_bracket => { |
| 3498 | 3287 | const lbracket = p.nextToken(); |
| 3499 | 3288 | const index_expr = try p.expectExpr(); |
| 3500 | 3289 | |
| 3501 | 3290 | if (p.eatToken(.ellipsis2)) |_| { |
| 3502 | const end_expr = try p.parseExpr(); | |
| 3291 | const opt_end_expr = try p.parseExpr(); | |
| 3503 | 3292 | if (p.eatToken(.colon)) |_| { |
| 3504 | 3293 | const sentinel = try p.expectExpr(); |
| 3505 | 3294 | _ = try p.expectToken(.r_bracket); |
| 3506 | return p.addNode(.{ | |
| 3295 | return try p.addNode(.{ | |
| 3507 | 3296 | .tag = .slice_sentinel, |
| 3508 | 3297 | .main_token = lbracket, |
| 3509 | .data = .{ | |
| 3510 | .lhs = lhs, | |
| 3511 | .rhs = try p.addExtra(Node.SliceSentinel{ | |
| 3298 | .data = .{ .node_and_extra = .{ | |
| 3299 | lhs, try p.addExtra(Node.SliceSentinel{ | |
| 3512 | 3300 | .start = index_expr, |
| 3513 | .end = end_expr, | |
| 3301 | .end = .fromOptional(opt_end_expr), | |
| 3514 | 3302 | .sentinel = sentinel, |
| 3515 | 3303 | }), |
| 3516 | }, | |
| 3304 | } }, | |
| 3517 | 3305 | }); |
| 3518 | 3306 | } |
| 3519 | 3307 | _ = try p.expectToken(.r_bracket); |
| 3520 | if (end_expr == 0) { | |
| 3521 | return p.addNode(.{ | |
| 3308 | const end_expr = opt_end_expr orelse { | |
| 3309 | return try p.addNode(.{ | |
| 3522 | 3310 | .tag = .slice_open, |
| 3523 | 3311 | .main_token = lbracket, |
| 3524 | .data = .{ | |
| 3525 | .lhs = lhs, | |
| 3526 | .rhs = index_expr, | |
| 3527 | }, | |
| 3312 | .data = .{ .node_and_node = .{ | |
| 3313 | lhs, | |
| 3314 | index_expr, | |
| 3315 | } }, | |
| 3528 | 3316 | }); |
| 3529 | } | |
| 3530 | return p.addNode(.{ | |
| 3317 | }; | |
| 3318 | return try p.addNode(.{ | |
| 3531 | 3319 | .tag = .slice, |
| 3532 | 3320 | .main_token = lbracket, |
| 3533 | .data = .{ | |
| 3534 | .lhs = lhs, | |
| 3535 | .rhs = try p.addExtra(Node.Slice{ | |
| 3321 | .data = .{ .node_and_extra = .{ | |
| 3322 | lhs, try p.addExtra(Node.Slice{ | |
| 3536 | 3323 | .start = index_expr, |
| 3537 | 3324 | .end = end_expr, |
| 3538 | 3325 | }), |
| 3539 | }, | |
| 3326 | } }, | |
| 3540 | 3327 | }); |
| 3541 | 3328 | } |
| 3542 | 3329 | _ = try p.expectToken(.r_bracket); |
| 3543 | return p.addNode(.{ | |
| 3330 | return try p.addNode(.{ | |
| 3544 | 3331 | .tag = .array_access, |
| 3545 | 3332 | .main_token = lbracket, |
| 3546 | .data = .{ | |
| 3547 | .lhs = lhs, | |
| 3548 | .rhs = index_expr, | |
| 3549 | }, | |
| 3333 | .data = .{ .node_and_node = .{ | |
| 3334 | lhs, | |
| 3335 | index_expr, | |
| 3336 | } }, | |
| 3550 | 3337 | }); |
| 3551 | 3338 | }, |
| 3552 | .period_asterisk => return p.addNode(.{ | |
| 3339 | .period_asterisk => return try p.addNode(.{ | |
| 3553 | 3340 | .tag = .deref, |
| 3554 | 3341 | .main_token = p.nextToken(), |
| 3555 | .data = .{ | |
| 3556 | .lhs = lhs, | |
| 3557 | .rhs = undefined, | |
| 3558 | }, | |
| 3342 | .data = .{ .node = lhs }, | |
| 3559 | 3343 | }), |
| 3560 | 3344 | .invalid_periodasterisks => { |
| 3561 | 3345 | try p.warn(.asterisk_after_ptr_deref); |
| 3562 | return p.addNode(.{ | |
| 3346 | return try p.addNode(.{ | |
| 3563 | 3347 | .tag = .deref, |
| 3564 | 3348 | .main_token = p.nextToken(), |
| 3565 | .data = .{ | |
| 3566 | .lhs = lhs, | |
| 3567 | .rhs = undefined, | |
| 3568 | }, | |
| 3349 | .data = .{ .node = lhs }, | |
| 3569 | 3350 | }); |
| 3570 | 3351 | }, |
| 3571 | .period => switch (p.token_tags[p.tok_i + 1]) { | |
| 3572 | .identifier => return p.addNode(.{ | |
| 3352 | .period => switch (p.tokenTag(p.tok_i + 1)) { | |
| 3353 | .identifier => return try p.addNode(.{ | |
| 3573 | 3354 | .tag = .field_access, |
| 3574 | 3355 | .main_token = p.nextToken(), |
| 3575 | .data = .{ | |
| 3576 | .lhs = lhs, | |
| 3577 | .rhs = p.nextToken(), | |
| 3578 | }, | |
| 3356 | .data = .{ .node_and_token = .{ | |
| 3357 | lhs, | |
| 3358 | p.nextToken(), | |
| 3359 | } }, | |
| 3579 | 3360 | }), |
| 3580 | .question_mark => return p.addNode(.{ | |
| 3361 | .question_mark => return try p.addNode(.{ | |
| 3581 | 3362 | .tag = .unwrap_optional, |
| 3582 | 3363 | .main_token = p.nextToken(), |
| 3583 | .data = .{ | |
| 3584 | .lhs = lhs, | |
| 3585 | .rhs = p.nextToken(), | |
| 3586 | }, | |
| 3364 | .data = .{ .node_and_token = .{ | |
| 3365 | lhs, | |
| 3366 | p.nextToken(), | |
| 3367 | } }, | |
| 3587 | 3368 | }), |
| 3588 | 3369 | .l_brace => { |
| 3589 | 3370 | // this a misplaced `.{`, handle the error somewhere else |
| 3590 | return null_node; | |
| 3371 | return null; | |
| 3591 | 3372 | }, |
| 3592 | 3373 | else => { |
| 3593 | 3374 | p.tok_i += 1; |
| 3594 | 3375 | try p.warn(.expected_suffix_op); |
| 3595 | return null_node; | |
| 3376 | return null; | |
| 3596 | 3377 | }, |
| 3597 | 3378 | }, |
| 3598 | else => return null_node, | |
| 3379 | else => return null, | |
| 3599 | 3380 | } |
| 3600 | 3381 | } |
| 3601 | 3382 | |
| ... | ... | @@ -3608,17 +3389,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index { |
| 3608 | 3389 | /// / KEYWORD_opaque |
| 3609 | 3390 | /// / KEYWORD_enum (LPAREN Expr RPAREN)? |
| 3610 | 3391 | /// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 3611 | fn parseContainerDeclAuto(p: *Parse) !Node.Index { | |
| 3392 | fn parseContainerDeclAuto(p: *Parse) !?Node.Index { | |
| 3612 | 3393 | const main_token = p.nextToken(); |
| 3613 | const arg_expr = switch (p.token_tags[main_token]) { | |
| 3614 | .keyword_opaque => null_node, | |
| 3394 | const arg_expr = switch (p.tokenTag(main_token)) { | |
| 3395 | .keyword_opaque => null, | |
| 3615 | 3396 | .keyword_struct, .keyword_enum => blk: { |
| 3616 | 3397 | if (p.eatToken(.l_paren)) |_| { |
| 3617 | 3398 | const expr = try p.expectExpr(); |
| 3618 | 3399 | _ = try p.expectToken(.r_paren); |
| 3619 | 3400 | break :blk expr; |
| 3620 | 3401 | } else { |
| 3621 | break :blk null_node; | |
| 3402 | break :blk null; | |
| 3622 | 3403 | } |
| 3623 | 3404 | }, |
| 3624 | 3405 | .keyword_union => blk: { |
| ... | ... | @@ -3633,16 +3414,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3633 | 3414 | const members = try p.parseContainerMembers(); |
| 3634 | 3415 | const members_span = try members.toSpan(p); |
| 3635 | 3416 | _ = try p.expectToken(.r_brace); |
| 3636 | return p.addNode(.{ | |
| 3417 | return try p.addNode(.{ | |
| 3637 | 3418 | .tag = switch (members.trailing) { |
| 3638 | 3419 | true => .tagged_union_enum_tag_trailing, |
| 3639 | 3420 | false => .tagged_union_enum_tag, |
| 3640 | 3421 | }, |
| 3641 | 3422 | .main_token = main_token, |
| 3642 | .data = .{ | |
| 3643 | .lhs = enum_tag_expr, | |
| 3644 | .rhs = try p.addExtra(members_span), | |
| 3645 | }, | |
| 3423 | .data = .{ .node_and_extra = .{ | |
| 3424 | enum_tag_expr, | |
| 3425 | try p.addExtra(members_span), | |
| 3426 | } }, | |
| 3646 | 3427 | }); |
| 3647 | 3428 | } else { |
| 3648 | 3429 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3651,29 +3432,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3651 | 3432 | const members = try p.parseContainerMembers(); |
| 3652 | 3433 | _ = try p.expectToken(.r_brace); |
| 3653 | 3434 | if (members.len <= 2) { |
| 3654 | return p.addNode(.{ | |
| 3435 | return try p.addNode(.{ | |
| 3655 | 3436 | .tag = switch (members.trailing) { |
| 3656 | 3437 | true => .tagged_union_two_trailing, |
| 3657 | 3438 | false => .tagged_union_two, |
| 3658 | 3439 | }, |
| 3659 | 3440 | .main_token = main_token, |
| 3660 | .data = .{ | |
| 3661 | .lhs = members.lhs, | |
| 3662 | .rhs = members.rhs, | |
| 3663 | }, | |
| 3441 | .data = members.data, | |
| 3664 | 3442 | }); |
| 3665 | 3443 | } else { |
| 3666 | 3444 | const span = try members.toSpan(p); |
| 3667 | return p.addNode(.{ | |
| 3445 | return try p.addNode(.{ | |
| 3668 | 3446 | .tag = switch (members.trailing) { |
| 3669 | 3447 | true => .tagged_union_trailing, |
| 3670 | 3448 | false => .tagged_union, |
| 3671 | 3449 | }, |
| 3672 | 3450 | .main_token = main_token, |
| 3673 | .data = .{ | |
| 3674 | .lhs = span.start, | |
| 3675 | .rhs = span.end, | |
| 3676 | }, | |
| 3451 | .data = .{ .extra_range = span }, | |
| 3677 | 3452 | }); |
| 3678 | 3453 | } |
| 3679 | 3454 | } |
| ... | ... | @@ -3683,7 +3458,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3683 | 3458 | break :blk expr; |
| 3684 | 3459 | } |
| 3685 | 3460 | } else { |
| 3686 | break :blk null_node; | |
| 3461 | break :blk null; | |
| 3687 | 3462 | } |
| 3688 | 3463 | }, |
| 3689 | 3464 | else => { |
| ... | ... | @@ -3694,48 +3469,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3694 | 3469 | _ = try p.expectToken(.l_brace); |
| 3695 | 3470 | const members = try p.parseContainerMembers(); |
| 3696 | 3471 | _ = try p.expectToken(.r_brace); |
| 3697 | if (arg_expr == 0) { | |
| 3472 | if (arg_expr == null) { | |
| 3698 | 3473 | if (members.len <= 2) { |
| 3699 | return p.addNode(.{ | |
| 3474 | return try p.addNode(.{ | |
| 3700 | 3475 | .tag = switch (members.trailing) { |
| 3701 | 3476 | true => .container_decl_two_trailing, |
| 3702 | 3477 | false => .container_decl_two, |
| 3703 | 3478 | }, |
| 3704 | 3479 | .main_token = main_token, |
| 3705 | .data = .{ | |
| 3706 | .lhs = members.lhs, | |
| 3707 | .rhs = members.rhs, | |
| 3708 | }, | |
| 3480 | .data = members.data, | |
| 3709 | 3481 | }); |
| 3710 | 3482 | } else { |
| 3711 | 3483 | const span = try members.toSpan(p); |
| 3712 | return p.addNode(.{ | |
| 3484 | return try p.addNode(.{ | |
| 3713 | 3485 | .tag = switch (members.trailing) { |
| 3714 | 3486 | true => .container_decl_trailing, |
| 3715 | 3487 | false => .container_decl, |
| 3716 | 3488 | }, |
| 3717 | 3489 | .main_token = main_token, |
| 3718 | .data = .{ | |
| 3719 | .lhs = span.start, | |
| 3720 | .rhs = span.end, | |
| 3721 | }, | |
| 3490 | .data = .{ .extra_range = span }, | |
| 3722 | 3491 | }); |
| 3723 | 3492 | } |
| 3724 | 3493 | } else { |
| 3725 | 3494 | const span = try members.toSpan(p); |
| 3726 | return p.addNode(.{ | |
| 3495 | return try p.addNode(.{ | |
| 3727 | 3496 | .tag = switch (members.trailing) { |
| 3728 | 3497 | true => .container_decl_arg_trailing, |
| 3729 | 3498 | false => .container_decl_arg, |
| 3730 | 3499 | }, |
| 3731 | 3500 | .main_token = main_token, |
| 3732 | .data = .{ | |
| 3733 | .lhs = arg_expr, | |
| 3734 | .rhs = try p.addExtra(Node.SubRange{ | |
| 3501 | .data = .{ .node_and_extra = .{ | |
| 3502 | arg_expr.?, | |
| 3503 | try p.addExtra(Node.SubRange{ | |
| 3735 | 3504 | .start = span.start, |
| 3736 | 3505 | .end = span.end, |
| 3737 | 3506 | }), |
| 3738 | }, | |
| 3507 | } }, | |
| 3739 | 3508 | }); |
| 3740 | 3509 | } |
| 3741 | 3510 | } |
| ... | ... | @@ -3744,24 +3513,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3744 | 3513 | /// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'. |
| 3745 | 3514 | fn parseCStyleContainer(p: *Parse) Error!bool { |
| 3746 | 3515 | const main_token = p.tok_i; |
| 3747 | switch (p.token_tags[p.tok_i]) { | |
| 3516 | switch (p.tokenTag(p.tok_i)) { | |
| 3748 | 3517 | .keyword_enum, .keyword_union, .keyword_struct => {}, |
| 3749 | 3518 | else => return false, |
| 3750 | 3519 | } |
| 3751 | 3520 | const identifier = p.tok_i + 1; |
| 3752 | if (p.token_tags[identifier] != .identifier) return false; | |
| 3521 | if (p.tokenTag(identifier) != .identifier) return false; | |
| 3753 | 3522 | p.tok_i += 2; |
| 3754 | 3523 | |
| 3755 | 3524 | try p.warnMsg(.{ |
| 3756 | 3525 | .tag = .c_style_container, |
| 3757 | 3526 | .token = identifier, |
| 3758 | .extra = .{ .expected_tag = p.token_tags[main_token] }, | |
| 3527 | .extra = .{ .expected_tag = p.tokenTag(main_token) }, | |
| 3759 | 3528 | }); |
| 3760 | 3529 | try p.warnMsg(.{ |
| 3761 | 3530 | .tag = .zig_style_container, |
| 3762 | 3531 | .is_note = true, |
| 3763 | 3532 | .token = identifier, |
| 3764 | .extra = .{ .expected_tag = p.token_tags[main_token] }, | |
| 3533 | .extra = .{ .expected_tag = p.tokenTag(main_token) }, | |
| 3765 | 3534 | }); |
| 3766 | 3535 | |
| 3767 | 3536 | _ = try p.expectToken(.l_brace); |
| ... | ... | @@ -3774,8 +3543,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool { |
| 3774 | 3543 | /// Holds temporary data until we are ready to construct the full ContainerDecl AST node. |
| 3775 | 3544 | /// |
| 3776 | 3545 | /// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN |
| 3777 | fn parseByteAlign(p: *Parse) !Node.Index { | |
| 3778 | _ = p.eatToken(.keyword_align) orelse return null_node; | |
| 3546 | fn parseByteAlign(p: *Parse) !?Node.Index { | |
| 3547 | _ = p.eatToken(.keyword_align) orelse return null; | |
| 3779 | 3548 | _ = try p.expectToken(.l_paren); |
| 3780 | 3549 | const expr = try p.expectExpr(); |
| 3781 | 3550 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3788,12 +3557,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange { |
| 3788 | 3557 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3789 | 3558 | |
| 3790 | 3559 | while (true) { |
| 3791 | const item = try parseSwitchProng(p); | |
| 3792 | if (item == 0) break; | |
| 3560 | const item = try parseSwitchProng(p) orelse break; | |
| 3793 | 3561 | |
| 3794 | 3562 | try p.scratch.append(p.gpa, item); |
| 3795 | 3563 | |
| 3796 | switch (p.token_tags[p.tok_i]) { | |
| 3564 | switch (p.tokenTag(p.tok_i)) { | |
| 3797 | 3565 | .comma => p.tok_i += 1, |
| 3798 | 3566 | // All possible delimiters. |
| 3799 | 3567 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3813,13 +3581,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan { |
| 3813 | 3581 | while (true) { |
| 3814 | 3582 | if (p.eatToken(.r_paren)) |_| break; |
| 3815 | 3583 | if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i }; |
| 3816 | const param = try p.expectParamDecl(); | |
| 3817 | if (param != 0) { | |
| 3584 | const opt_param = try p.expectParamDecl(); | |
| 3585 | if (opt_param) |param| { | |
| 3818 | 3586 | try p.scratch.append(p.gpa, param); |
| 3819 | } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) { | |
| 3587 | } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) { | |
| 3820 | 3588 | if (varargs == .none) varargs = .seen; |
| 3821 | 3589 | } |
| 3822 | switch (p.token_tags[p.tok_i]) { | |
| 3590 | switch (p.tokenTag(p.tok_i)) { | |
| 3823 | 3591 | .comma => p.tok_i += 1, |
| 3824 | 3592 | .r_paren => { |
| 3825 | 3593 | p.tok_i += 1; |
| ... | ... | @@ -3835,9 +3603,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan { |
| 3835 | 3603 | } |
| 3836 | 3604 | const params = p.scratch.items[scratch_top..]; |
| 3837 | 3605 | return switch (params.len) { |
| 3838 | 0 => SmallSpan{ .zero_or_one = 0 }, | |
| 3839 | 1 => SmallSpan{ .zero_or_one = params[0] }, | |
| 3840 | else => SmallSpan{ .multi = try p.listToSpan(params) }, | |
| 3606 | 0 => .{ .zero_or_one = .none }, | |
| 3607 | 1 => .{ .zero_or_one = params[0].toOptional() }, | |
| 3608 | else => .{ .multi = try p.listToSpan(params) }, | |
| 3841 | 3609 | }; |
| 3842 | 3610 | } |
| 3843 | 3611 | |
| ... | ... | @@ -3852,10 +3620,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3852 | 3620 | return p.addNode(.{ |
| 3853 | 3621 | .tag = .identifier, |
| 3854 | 3622 | .main_token = builtin_token, |
| 3855 | .data = .{ | |
| 3856 | .lhs = undefined, | |
| 3857 | .rhs = undefined, | |
| 3858 | }, | |
| 3623 | .data = undefined, | |
| 3859 | 3624 | }); |
| 3860 | 3625 | }; |
| 3861 | 3626 | const scratch_top = p.scratch.items.len; |
| ... | ... | @@ -3864,7 +3629,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3864 | 3629 | if (p.eatToken(.r_paren)) |_| break; |
| 3865 | 3630 | const param = try p.expectExpr(); |
| 3866 | 3631 | try p.scratch.append(p.gpa, param); |
| 3867 | switch (p.token_tags[p.tok_i]) { | |
| 3632 | switch (p.tokenTag(p.tok_i)) { | |
| 3868 | 3633 | .comma => p.tok_i += 1, |
| 3869 | 3634 | .r_paren => { |
| 3870 | 3635 | p.tok_i += 1; |
| ... | ... | @@ -3874,88 +3639,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3874 | 3639 | else => try p.warn(.expected_comma_after_arg), |
| 3875 | 3640 | } |
| 3876 | 3641 | } |
| 3877 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 3642 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 3878 | 3643 | const params = p.scratch.items[scratch_top..]; |
| 3879 | switch (params.len) { | |
| 3880 | 0 => return p.addNode(.{ | |
| 3881 | .tag = .builtin_call_two, | |
| 3882 | .main_token = builtin_token, | |
| 3883 | .data = .{ | |
| 3884 | .lhs = 0, | |
| 3885 | .rhs = 0, | |
| 3886 | }, | |
| 3887 | }), | |
| 3888 | 1 => return p.addNode(.{ | |
| 3644 | if (params.len <= 2) { | |
| 3645 | return p.addNode(.{ | |
| 3889 | 3646 | .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, |
| 3890 | 3647 | .main_token = builtin_token, |
| 3891 | .data = .{ | |
| 3892 | .lhs = params[0], | |
| 3893 | .rhs = 0, | |
| 3894 | }, | |
| 3895 | }), | |
| 3896 | 2 => return p.addNode(.{ | |
| 3897 | .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, | |
| 3648 | .data = .{ .opt_node_and_opt_node = .{ | |
| 3649 | if (params.len >= 1) .fromOptional(params[0]) else .none, | |
| 3650 | if (params.len >= 2) .fromOptional(params[1]) else .none, | |
| 3651 | } }, | |
| 3652 | }); | |
| 3653 | } else { | |
| 3654 | const span = try p.listToSpan(params); | |
| 3655 | return p.addNode(.{ | |
| 3656 | .tag = if (comma) .builtin_call_comma else .builtin_call, | |
| 3898 | 3657 | .main_token = builtin_token, |
| 3899 | .data = .{ | |
| 3900 | .lhs = params[0], | |
| 3901 | .rhs = params[1], | |
| 3902 | }, | |
| 3903 | }), | |
| 3904 | else => { | |
| 3905 | const span = try p.listToSpan(params); | |
| 3906 | return p.addNode(.{ | |
| 3907 | .tag = if (comma) .builtin_call_comma else .builtin_call, | |
| 3908 | .main_token = builtin_token, | |
| 3909 | .data = .{ | |
| 3910 | .lhs = span.start, | |
| 3911 | .rhs = span.end, | |
| 3912 | }, | |
| 3913 | }); | |
| 3914 | }, | |
| 3658 | .data = .{ .extra_range = span }, | |
| 3659 | }); | |
| 3915 | 3660 | } |
| 3916 | 3661 | } |
| 3917 | 3662 | |
| 3918 | 3663 | /// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload? |
| 3919 | fn 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; | |
| 3664 | fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index { | |
| 3665 | const if_token = p.eatToken(.keyword_if) orelse return null; | |
| 3921 | 3666 | _ = try p.expectToken(.l_paren); |
| 3922 | 3667 | const condition = try p.expectExpr(); |
| 3923 | 3668 | _ = try p.expectToken(.r_paren); |
| 3924 | 3669 | _ = try p.parsePtrPayload(); |
| 3925 | 3670 | |
| 3926 | 3671 | const then_expr = try bodyParseFn(p); |
| 3927 | assert(then_expr != 0); | |
| 3928 | 3672 | |
| 3929 | _ = p.eatToken(.keyword_else) orelse return p.addNode(.{ | |
| 3673 | _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{ | |
| 3930 | 3674 | .tag = .if_simple, |
| 3931 | 3675 | .main_token = if_token, |
| 3932 | .data = .{ | |
| 3933 | .lhs = condition, | |
| 3934 | .rhs = then_expr, | |
| 3935 | }, | |
| 3676 | .data = .{ .node_and_node = .{ | |
| 3677 | condition, | |
| 3678 | then_expr, | |
| 3679 | } }, | |
| 3936 | 3680 | }); |
| 3937 | 3681 | _ = try p.parsePayload(); |
| 3938 | 3682 | const else_expr = try bodyParseFn(p); |
| 3939 | assert(else_expr != 0); | |
| 3940 | 3683 | |
| 3941 | return p.addNode(.{ | |
| 3684 | return try p.addNode(.{ | |
| 3942 | 3685 | .tag = .@"if", |
| 3943 | 3686 | .main_token = if_token, |
| 3944 | .data = .{ | |
| 3945 | .lhs = condition, | |
| 3946 | .rhs = try p.addExtra(Node.If{ | |
| 3687 | .data = .{ .node_and_extra = .{ | |
| 3688 | condition, | |
| 3689 | try p.addExtra(Node.If{ | |
| 3947 | 3690 | .then_expr = then_expr, |
| 3948 | 3691 | .else_expr = else_expr, |
| 3949 | 3692 | }), |
| 3950 | }, | |
| 3693 | } }, | |
| 3951 | 3694 | }); |
| 3952 | 3695 | } |
| 3953 | 3696 | |
| 3954 | 3697 | /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? |
| 3955 | 3698 | /// |
| 3956 | 3699 | /// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)? |
| 3957 | fn 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; | |
| 3700 | fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index { | |
| 3701 | const for_token = p.eatToken(.keyword_for) orelse return null; | |
| 3959 | 3702 | |
| 3960 | 3703 | const scratch_top = p.scratch.items.len; |
| 3961 | 3704 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| ... | ... | @@ -3969,27 +3712,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N |
| 3969 | 3712 | try p.scratch.append(p.gpa, else_expr); |
| 3970 | 3713 | has_else = true; |
| 3971 | 3714 | } else if (inputs == 1) { |
| 3972 | return p.addNode(.{ | |
| 3715 | return try p.addNode(.{ | |
| 3973 | 3716 | .tag = .for_simple, |
| 3974 | 3717 | .main_token = for_token, |
| 3975 | .data = .{ | |
| 3976 | .lhs = p.scratch.items[scratch_top], | |
| 3977 | .rhs = then_expr, | |
| 3978 | }, | |
| 3718 | .data = .{ .node_and_node = .{ | |
| 3719 | p.scratch.items[scratch_top], | |
| 3720 | then_expr, | |
| 3721 | } }, | |
| 3979 | 3722 | }); |
| 3980 | 3723 | } else { |
| 3981 | 3724 | try p.scratch.append(p.gpa, then_expr); |
| 3982 | 3725 | } |
| 3983 | return p.addNode(.{ | |
| 3726 | return try p.addNode(.{ | |
| 3984 | 3727 | .tag = .@"for", |
| 3985 | 3728 | .main_token = for_token, |
| 3986 | .data = .{ | |
| 3987 | .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 3988 | .rhs = @as(u32, @bitCast(Node.For{ | |
| 3989 | .inputs = @as(u31, @intCast(inputs)), | |
| 3990 | .has_else = has_else, | |
| 3991 | })), | |
| 3992 | }, | |
| 3729 | .data = .{ .@"for" = .{ | |
| 3730 | (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 3731 | .{ .inputs = @intCast(inputs), .has_else = has_else }, | |
| 3732 | } }, | |
| 3993 | 3733 | }); |
| 3994 | 3734 | } |
| 3995 | 3735 | |
| ... | ... | @@ -4011,21 +3751,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { |
| 4011 | 3751 | } |
| 4012 | 3752 | |
| 4013 | 3753 | fn tokensOnSameLine(p: *Parse, token1: TokenIndex, token2: TokenIndex) bool { |
| 4014 | return std.mem.indexOfScalar(u8, p.source[p.token_starts[token1]..p.token_starts[token2]], '\n') == null; | |
| 3754 | return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null; | |
| 4015 | 3755 | } |
| 4016 | 3756 | |
| 4017 | 3757 | fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex { |
| 4018 | return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null; | |
| 3758 | return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null; | |
| 3759 | } | |
| 3760 | ||
| 3761 | fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex { | |
| 3762 | const available_tags = p.tokens.items(.tag)[p.tok_i..]; | |
| 3763 | if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null; | |
| 3764 | const result = p.tok_i; | |
| 3765 | p.tok_i += @intCast(tags.len); | |
| 3766 | return result; | |
| 4019 | 3767 | } |
| 4020 | 3768 | |
| 4021 | 3769 | fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex { |
| 4022 | 3770 | const token = p.nextToken(); |
| 4023 | assert(p.token_tags[token] == tag); | |
| 3771 | assert(p.tokenTag(token) == tag); | |
| 4024 | 3772 | return token; |
| 4025 | 3773 | } |
| 4026 | 3774 | |
| 4027 | 3775 | fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex { |
| 4028 | if (p.token_tags[p.tok_i] != tag) { | |
| 3776 | if (p.tokenTag(p.tok_i) != tag) { | |
| 4029 | 3777 | return p.failMsg(.{ |
| 4030 | 3778 | .tag = .expected_token, |
| 4031 | 3779 | .token = p.tok_i, |
| ... | ... | @@ -4036,7 +3784,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex { |
| 4036 | 3784 | } |
| 4037 | 3785 | |
| 4038 | 3786 | fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void { |
| 4039 | if (p.token_tags[p.tok_i] == .semicolon) { | |
| 3787 | if (p.tokenTag(p.tok_i) == .semicolon) { | |
| 4040 | 3788 | _ = p.nextToken(); |
| 4041 | 3789 | return; |
| 4042 | 3790 | } |
| ... | ... | @@ -4050,8 +3798,6 @@ fn nextToken(p: *Parse) TokenIndex { |
| 4050 | 3798 | return result; |
| 4051 | 3799 | } |
| 4052 | 3800 | |
| 4053 | const null_node: Node.Index = 0; | |
| 4054 | ||
| 4055 | 3801 | const Parse = @This(); |
| 4056 | 3802 | const std = @import("../std.zig"); |
| 4057 | 3803 | const assert = std.debug.assert; |
| ... | ... | @@ -4060,6 +3806,8 @@ const Ast = std.zig.Ast; |
| 4060 | 3806 | const Node = Ast.Node; |
| 4061 | 3807 | const AstError = Ast.Error; |
| 4062 | 3808 | const TokenIndex = Ast.TokenIndex; |
| 3809 | const OptionalTokenIndex = Ast.OptionalTokenIndex; | |
| 3810 | const ExtraIndex = Ast.ExtraIndex; | |
| 4063 | 3811 | const Token = std.zig.Token; |
| 4064 | 3812 | |
| 4065 | 3813 | test { |
lib/std/zig/Zir.zig+52-45| ... | ... | @@ -80,9 +80,18 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) { |
| 80 | 80 | Inst.Declaration.Name, |
| 81 | 81 | std.zig.SimpleComptimeReason, |
| 82 | 82 | NullTerminatedString, |
| 83 | // Ast.TokenIndex is missing because it is a u32. | |
| 84 | Ast.OptionalTokenIndex, | |
| 85 | Ast.Node.Index, | |
| 86 | Ast.Node.OptionalIndex, | |
| 83 | 87 | => @enumFromInt(code.extra[i]), |
| 84 | 88 | |
| 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 | 95 | Inst.Call.Flags, |
| 87 | 96 | Inst.BuiltinCall.Flags, |
| 88 | 97 | Inst.SwitchBlock.Bits, |
| ... | ... | @@ -1904,22 +1913,22 @@ pub const Inst = struct { |
| 1904 | 1913 | /// `small` is `fields_len: u16`. |
| 1905 | 1914 | tuple_decl, |
| 1906 | 1915 | /// Implements the `@This` builtin. |
| 1907 | /// `operand` is `src_node: i32`. | |
| 1916 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 1908 | 1917 | this, |
| 1909 | 1918 | /// Implements the `@returnAddress` builtin. |
| 1910 | /// `operand` is `src_node: i32`. | |
| 1919 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 1911 | 1920 | ret_addr, |
| 1912 | 1921 | /// Implements the `@src` builtin. |
| 1913 | 1922 | /// `operand` is payload index to `LineColumn`. |
| 1914 | 1923 | builtin_src, |
| 1915 | 1924 | /// Implements the `@errorReturnTrace` builtin. |
| 1916 | /// `operand` is `src_node: i32`. | |
| 1925 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 1917 | 1926 | error_return_trace, |
| 1918 | 1927 | /// Implements the `@frame` builtin. |
| 1919 | /// `operand` is `src_node: i32`. | |
| 1928 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 1920 | 1929 | frame, |
| 1921 | 1930 | /// Implements the `@frameAddress` builtin. |
| 1922 | /// `operand` is `src_node: i32`. | |
| 1931 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 1923 | 1932 | frame_address, |
| 1924 | 1933 | /// Same as `alloc` from `Tag` but may contain an alignment instruction. |
| 1925 | 1934 | /// `operand` is payload index to `AllocExtended`. |
| ... | ... | @@ -2004,9 +2013,9 @@ pub const Inst = struct { |
| 2004 | 2013 | /// `operand` is payload index to `UnNode`. |
| 2005 | 2014 | await_nosuspend, |
| 2006 | 2015 | /// Implements `@breakpoint`. |
| 2007 | /// `operand` is `src_node: i32`. | |
| 2016 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 2008 | 2017 | breakpoint, |
| 2009 | /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: i32`. | |
| 2018 | /// Implement builtin `@disableInstrumentation`. `operand` is `src_node: Ast.Node.Offset`. | |
| 2010 | 2019 | disable_instrumentation, |
| 2011 | 2020 | /// Implement builtin `@disableIntrinsics`. `operand` is `src_node: i32`. |
| 2012 | 2021 | disable_intrinsics, |
| ... | ... | @@ -2040,7 +2049,7 @@ pub const Inst = struct { |
| 2040 | 2049 | /// `operand` is payload index to `UnNode`. |
| 2041 | 2050 | c_va_end, |
| 2042 | 2051 | /// Implement builtin `@cVaStart`. |
| 2043 | /// `operand` is `src_node: i32`. | |
| 2052 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 2044 | 2053 | c_va_start, |
| 2045 | 2054 | /// Implements the following builtins: |
| 2046 | 2055 | /// `@ptrCast`, `@alignCast`, `@addrSpaceCast`, `@constCast`, `@volatileCast`. |
| ... | ... | @@ -2067,7 +2076,7 @@ pub const Inst = struct { |
| 2067 | 2076 | /// `operand` is payload index to `UnNode`. |
| 2068 | 2077 | work_group_id, |
| 2069 | 2078 | /// Implements the `@inComptime` builtin. |
| 2070 | /// `operand` is `src_node: i32`. | |
| 2079 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 2071 | 2080 | in_comptime, |
| 2072 | 2081 | /// Restores the error return index to its last saved state in a given |
| 2073 | 2082 | /// block. If the block is `.none`, restores to the state from the point |
| ... | ... | @@ -2077,7 +2086,7 @@ pub const Inst = struct { |
| 2077 | 2086 | /// `small` is undefined. |
| 2078 | 2087 | restore_err_ret_index, |
| 2079 | 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 | 2090 | /// `small` is closure index. |
| 2082 | 2091 | closure_get, |
| 2083 | 2092 | /// Used as a placeholder instruction which is just a dummy index for Sema to replace |
| ... | ... | @@ -2091,7 +2100,7 @@ pub const Inst = struct { |
| 2091 | 2100 | /// Uses the `pl_node` union field with payload `FieldParentPtr`. |
| 2092 | 2101 | field_parent_ptr, |
| 2093 | 2102 | /// Get a type or value from `std.builtin`. |
| 2094 | /// `operand` is `src_node: i32`. | |
| 2103 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 2095 | 2104 | /// `small` is an `Inst.BuiltinValue`. |
| 2096 | 2105 | builtin_value, |
| 2097 | 2106 | /// Provide a `@branchHint` for the current block. |
| ... | ... | @@ -2286,28 +2295,28 @@ pub const Inst = struct { |
| 2286 | 2295 | /// Used for unary operators, with an AST node source location. |
| 2287 | 2296 | un_node: struct { |
| 2288 | 2297 | /// Offset from Decl AST node index. |
| 2289 | src_node: i32, | |
| 2298 | src_node: Ast.Node.Offset, | |
| 2290 | 2299 | /// The meaning of this operand depends on the corresponding `Tag`. |
| 2291 | 2300 | operand: Ref, |
| 2292 | 2301 | }, |
| 2293 | 2302 | /// Used for unary operators, with a token source location. |
| 2294 | 2303 | un_tok: struct { |
| 2295 | 2304 | /// Offset from Decl AST token index. |
| 2296 | src_tok: Ast.TokenIndex, | |
| 2305 | src_tok: Ast.TokenOffset, | |
| 2297 | 2306 | /// The meaning of this operand depends on the corresponding `Tag`. |
| 2298 | 2307 | operand: Ref, |
| 2299 | 2308 | }, |
| 2300 | 2309 | pl_node: struct { |
| 2301 | 2310 | /// Offset from Decl AST node index. |
| 2302 | 2311 | /// `Tag` determines which kind of AST node this points to. |
| 2303 | src_node: i32, | |
| 2312 | src_node: Ast.Node.Offset, | |
| 2304 | 2313 | /// index into extra. |
| 2305 | 2314 | /// `Tag` determines what lives there. |
| 2306 | 2315 | payload_index: u32, |
| 2307 | 2316 | }, |
| 2308 | 2317 | pl_tok: struct { |
| 2309 | 2318 | /// Offset from Decl AST token index. |
| 2310 | src_tok: Ast.TokenIndex, | |
| 2319 | src_tok: Ast.TokenOffset, | |
| 2311 | 2320 | /// index into extra. |
| 2312 | 2321 | /// `Tag` determines what lives there. |
| 2313 | 2322 | payload_index: u32, |
| ... | ... | @@ -2328,16 +2337,16 @@ pub const Inst = struct { |
| 2328 | 2337 | /// Offset into `string_bytes`. Null-terminated. |
| 2329 | 2338 | start: NullTerminatedString, |
| 2330 | 2339 | /// Offset from Decl AST token index. |
| 2331 | src_tok: u32, | |
| 2340 | src_tok: Ast.TokenOffset, | |
| 2332 | 2341 | |
| 2333 | 2342 | pub fn get(self: @This(), code: Zir) [:0]const u8 { |
| 2334 | 2343 | return code.nullTerminatedString(self.start); |
| 2335 | 2344 | } |
| 2336 | 2345 | }, |
| 2337 | 2346 | /// Offset from Decl AST token index. |
| 2338 | tok: Ast.TokenIndex, | |
| 2347 | tok: Ast.TokenOffset, | |
| 2339 | 2348 | /// Offset from Decl AST node index. |
| 2340 | node: i32, | |
| 2349 | node: Ast.Node.Offset, | |
| 2341 | 2350 | int: u64, |
| 2342 | 2351 | float: f64, |
| 2343 | 2352 | ptr_type: struct { |
| ... | ... | @@ -2358,14 +2367,14 @@ pub const Inst = struct { |
| 2358 | 2367 | int_type: struct { |
| 2359 | 2368 | /// Offset from Decl AST node index. |
| 2360 | 2369 | /// `Tag` determines which kind of AST node this points to. |
| 2361 | src_node: i32, | |
| 2370 | src_node: Ast.Node.Offset, | |
| 2362 | 2371 | signedness: std.builtin.Signedness, |
| 2363 | 2372 | bit_count: u16, |
| 2364 | 2373 | }, |
| 2365 | 2374 | @"unreachable": struct { |
| 2366 | 2375 | /// Offset from Decl AST node index. |
| 2367 | 2376 | /// `Tag` determines which kind of AST node this points to. |
| 2368 | src_node: i32, | |
| 2377 | src_node: Ast.Node.Offset, | |
| 2369 | 2378 | }, |
| 2370 | 2379 | @"break": struct { |
| 2371 | 2380 | operand: Ref, |
| ... | ... | @@ -2377,7 +2386,7 @@ pub const Inst = struct { |
| 2377 | 2386 | /// with an AST node source location. |
| 2378 | 2387 | inst_node: struct { |
| 2379 | 2388 | /// Offset from Decl AST node index. |
| 2380 | src_node: i32, | |
| 2389 | src_node: Ast.Node.Offset, | |
| 2381 | 2390 | /// The meaning of this operand depends on the corresponding `Tag`. |
| 2382 | 2391 | inst: Index, |
| 2383 | 2392 | }, |
| ... | ... | @@ -2456,9 +2465,7 @@ pub const Inst = struct { |
| 2456 | 2465 | }; |
| 2457 | 2466 | |
| 2458 | 2467 | pub const Break = struct { |
| 2459 | pub const no_src_node = std.math.maxInt(i32); | |
| 2460 | ||
| 2461 | operand_src_node: i32, | |
| 2468 | operand_src_node: Ast.Node.OptionalOffset, | |
| 2462 | 2469 | block_inst: Index, |
| 2463 | 2470 | }; |
| 2464 | 2471 | |
| ... | ... | @@ -2467,7 +2474,7 @@ pub const Inst = struct { |
| 2467 | 2474 | /// 1. Input for every inputs_len |
| 2468 | 2475 | /// 2. clobber: NullTerminatedString // index into string_bytes (null terminated) for every clobbers_len. |
| 2469 | 2476 | pub const Asm = struct { |
| 2470 | src_node: i32, | |
| 2477 | src_node: Ast.Node.Offset, | |
| 2471 | 2478 | // null-terminated string index |
| 2472 | 2479 | asm_source: NullTerminatedString, |
| 2473 | 2480 | /// 1 bit for each outputs_len: whether it uses `-> T` or not. |
| ... | ... | @@ -2582,7 +2589,7 @@ pub const Inst = struct { |
| 2582 | 2589 | |
| 2583 | 2590 | /// Trailing: operand: Ref, // for each `operands_len` (stored in `small`). |
| 2584 | 2591 | pub const NodeMultiOp = struct { |
| 2585 | src_node: i32, | |
| 2592 | src_node: Ast.Node.Offset, | |
| 2586 | 2593 | }; |
| 2587 | 2594 | |
| 2588 | 2595 | /// This data is stored inside extra, with trailing operands according to `body_len`. |
| ... | ... | @@ -3033,7 +3040,7 @@ pub const Inst = struct { |
| 3033 | 3040 | /// Trailing: |
| 3034 | 3041 | /// 0. operand: Ref // for each `operands_len` |
| 3035 | 3042 | pub const TypeOfPeer = struct { |
| 3036 | src_node: i32, | |
| 3043 | src_node: Ast.Node.Offset, | |
| 3037 | 3044 | body_len: u32, |
| 3038 | 3045 | body_index: u32, |
| 3039 | 3046 | }; |
| ... | ... | @@ -3084,7 +3091,7 @@ pub const Inst = struct { |
| 3084 | 3091 | /// 4. host_size: Ref // if `has_bit_range` flag is set |
| 3085 | 3092 | pub const PtrType = struct { |
| 3086 | 3093 | elem_type: Ref, |
| 3087 | src_node: i32, | |
| 3094 | src_node: Ast.Node.Offset, | |
| 3088 | 3095 | }; |
| 3089 | 3096 | |
| 3090 | 3097 | pub const ArrayTypeSentinel = struct { |
| ... | ... | @@ -3116,7 +3123,7 @@ pub const Inst = struct { |
| 3116 | 3123 | start: Ref, |
| 3117 | 3124 | len: Ref, |
| 3118 | 3125 | sentinel: Ref, |
| 3119 | start_src_node_offset: i32, | |
| 3126 | start_src_node_offset: Ast.Node.Offset, | |
| 3120 | 3127 | }; |
| 3121 | 3128 | |
| 3122 | 3129 | /// The meaning of these operands depends on the corresponding `Tag`. |
| ... | ... | @@ -3126,13 +3133,13 @@ pub const Inst = struct { |
| 3126 | 3133 | }; |
| 3127 | 3134 | |
| 3128 | 3135 | pub const BinNode = struct { |
| 3129 | node: i32, | |
| 3136 | node: Ast.Node.Offset, | |
| 3130 | 3137 | lhs: Ref, |
| 3131 | 3138 | rhs: Ref, |
| 3132 | 3139 | }; |
| 3133 | 3140 | |
| 3134 | 3141 | pub const UnNode = struct { |
| 3135 | node: i32, | |
| 3142 | node: Ast.Node.Offset, | |
| 3136 | 3143 | operand: Ref, |
| 3137 | 3144 | }; |
| 3138 | 3145 | |
| ... | ... | @@ -3186,7 +3193,7 @@ pub const Inst = struct { |
| 3186 | 3193 | pub const SwitchBlockErrUnion = struct { |
| 3187 | 3194 | operand: Ref, |
| 3188 | 3195 | bits: Bits, |
| 3189 | main_src_node_offset: i32, | |
| 3196 | main_src_node_offset: Ast.Node.Offset, | |
| 3190 | 3197 | |
| 3191 | 3198 | pub const Bits = packed struct(u32) { |
| 3192 | 3199 | /// If true, one or more prongs have multiple items. |
| ... | ... | @@ -3592,7 +3599,7 @@ pub const Inst = struct { |
| 3592 | 3599 | /// init: Inst.Ref, // `.none` for non-`comptime` fields |
| 3593 | 3600 | /// } |
| 3594 | 3601 | pub const TupleDecl = struct { |
| 3595 | src_node: i32, // relative | |
| 3602 | src_node: Ast.Node.Offset, | |
| 3596 | 3603 | }; |
| 3597 | 3604 | |
| 3598 | 3605 | /// Trailing: |
| ... | ... | @@ -3666,7 +3673,7 @@ pub const Inst = struct { |
| 3666 | 3673 | }; |
| 3667 | 3674 | |
| 3668 | 3675 | pub const Cmpxchg = struct { |
| 3669 | node: i32, | |
| 3676 | node: Ast.Node.Offset, | |
| 3670 | 3677 | ptr: Ref, |
| 3671 | 3678 | expected_value: Ref, |
| 3672 | 3679 | new_value: Ref, |
| ... | ... | @@ -3706,7 +3713,7 @@ pub const Inst = struct { |
| 3706 | 3713 | }; |
| 3707 | 3714 | |
| 3708 | 3715 | pub const FieldParentPtr = struct { |
| 3709 | src_node: i32, | |
| 3716 | src_node: Ast.Node.Offset, | |
| 3710 | 3717 | parent_ptr_type: Ref, |
| 3711 | 3718 | field_name: Ref, |
| 3712 | 3719 | field_ptr: Ref, |
| ... | ... | @@ -3720,7 +3727,7 @@ pub const Inst = struct { |
| 3720 | 3727 | }; |
| 3721 | 3728 | |
| 3722 | 3729 | pub const Select = struct { |
| 3723 | node: i32, | |
| 3730 | node: Ast.Node.Offset, | |
| 3724 | 3731 | elem_type: Ref, |
| 3725 | 3732 | pred: Ref, |
| 3726 | 3733 | a: Ref, |
| ... | ... | @@ -3728,7 +3735,7 @@ pub const Inst = struct { |
| 3728 | 3735 | }; |
| 3729 | 3736 | |
| 3730 | 3737 | pub const AsyncCall = struct { |
| 3731 | node: i32, | |
| 3738 | node: Ast.Node.Offset, | |
| 3732 | 3739 | frame_buffer: Ref, |
| 3733 | 3740 | result_ptr: Ref, |
| 3734 | 3741 | fn_ptr: Ref, |
| ... | ... | @@ -3753,7 +3760,7 @@ pub const Inst = struct { |
| 3753 | 3760 | /// 0. type_inst: Ref, // if small 0b000X is set |
| 3754 | 3761 | /// 1. align_inst: Ref, // if small 0b00X0 is set |
| 3755 | 3762 | pub const AllocExtended = struct { |
| 3756 | src_node: i32, | |
| 3763 | src_node: Ast.Node.Offset, | |
| 3757 | 3764 | |
| 3758 | 3765 | pub const Small = packed struct { |
| 3759 | 3766 | has_type: bool, |
| ... | ... | @@ -3778,9 +3785,9 @@ pub const Inst = struct { |
| 3778 | 3785 | pub const Item = struct { |
| 3779 | 3786 | /// null terminated string index |
| 3780 | 3787 | msg: NullTerminatedString, |
| 3781 | node: Ast.Node.Index, | |
| 3782 | /// If node is 0 then this will be populated. | |
| 3783 | token: Ast.TokenIndex, | |
| 3788 | node: Ast.Node.OptionalIndex, | |
| 3789 | /// If node is .none then this will be populated. | |
| 3790 | token: Ast.OptionalTokenIndex, | |
| 3784 | 3791 | /// Can be used in combination with `token`. |
| 3785 | 3792 | byte_offset: u32, |
| 3786 | 3793 | /// 0 or a payload index of a `Block`, each is a payload |
| ... | ... | @@ -3818,7 +3825,7 @@ pub const Inst = struct { |
| 3818 | 3825 | }; |
| 3819 | 3826 | |
| 3820 | 3827 | pub const Src = struct { |
| 3821 | node: i32, | |
| 3828 | node: Ast.Node.Offset, | |
| 3822 | 3829 | line: u32, |
| 3823 | 3830 | column: u32, |
| 3824 | 3831 | }; |
| ... | ... | @@ -3833,7 +3840,7 @@ pub const Inst = struct { |
| 3833 | 3840 | /// The value being destructured. |
| 3834 | 3841 | operand: Ref, |
| 3835 | 3842 | /// The `destructure_assign` node. |
| 3836 | destructure_node: i32, | |
| 3843 | destructure_node: Ast.Node.Offset, | |
| 3837 | 3844 | /// The expected field count. |
| 3838 | 3845 | expect_len: u32, |
| 3839 | 3846 | }; |
| ... | ... | @@ -3848,7 +3855,7 @@ pub const Inst = struct { |
| 3848 | 3855 | }; |
| 3849 | 3856 | |
| 3850 | 3857 | pub const RestoreErrRetIndex = struct { |
| 3851 | src_node: i32, | |
| 3858 | src_node: Ast.Node.Offset, | |
| 3852 | 3859 | /// If `.none`, restore the trace to its state upon function entry. |
| 3853 | 3860 | block: Ref, |
| 3854 | 3861 | /// If `.none`, restore unconditionally. |
lib/std/zig/Zoir.zig+4-6| ... | ... | @@ -228,8 +228,8 @@ pub const NullTerminatedString = enum(u32) { |
| 228 | 228 | |
| 229 | 229 | pub const CompileError = extern struct { |
| 230 | 230 | msg: NullTerminatedString, |
| 231 | token: Ast.TokenIndex, | |
| 232 | /// If `token == invalid_token`, this is an `Ast.Node.Index`. | |
| 231 | token: Ast.OptionalTokenIndex, | |
| 232 | /// If `token == .none`, this is an `Ast.Node.Index`. | |
| 233 | 233 | /// Otherwise, this is a byte offset into `token`. |
| 234 | 234 | node_or_offset: u32, |
| 235 | 235 | |
| ... | ... | @@ -243,14 +243,12 @@ pub const CompileError = extern struct { |
| 243 | 243 | |
| 244 | 244 | pub const Note = extern struct { |
| 245 | 245 | msg: NullTerminatedString, |
| 246 | token: Ast.TokenIndex, | |
| 247 | /// If `token == invalid_token`, this is an `Ast.Node.Index`. | |
| 246 | token: Ast.OptionalTokenIndex, | |
| 247 | /// If `token == .none`, this is an `Ast.Node.Index`. | |
| 248 | 248 | /// Otherwise, this is a byte offset into `token`. |
| 249 | 249 | node_or_offset: u32, |
| 250 | 250 | }; |
| 251 | 251 | |
| 252 | pub const invalid_token: Ast.TokenIndex = std.math.maxInt(Ast.TokenIndex); | |
| 253 | ||
| 254 | 252 | comptime { |
| 255 | 253 | assert(std.meta.hasUniqueRepresentation(CompileError)); |
| 256 | 254 | assert(std.meta.hasUniqueRepresentation(Note)); |
lib/std/zig/ZonGen.zig+44-56| ... | ... | @@ -48,7 +48,7 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 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 | 52 | try zg.nodes.append(gpa, undefined); // index 0; root node |
| 53 | 53 | try zg.expr(root_ast_node, .root); |
| 54 | 54 | } else { |
| ... | ... | @@ -97,11 +97,8 @@ pub fn generate(gpa: Allocator, tree: Ast, options: Options) Allocator.Error!Zoi |
| 97 | 97 | fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator.Error!void { |
| 98 | 98 | const gpa = zg.gpa; |
| 99 | 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); | |
| 103 | 100 | |
| 104 | switch (node_tags[node]) { | |
| 101 | switch (tree.nodeTag(node)) { | |
| 105 | 102 | .root => unreachable, |
| 106 | 103 | .@"usingnamespace" => unreachable, |
| 107 | 104 | .test_decl => unreachable, |
| ... | ... | @@ -173,7 +170,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 173 | 170 | .bool_not, |
| 174 | 171 | .bit_not, |
| 175 | 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))}), | |
| 177 | 174 | |
| 178 | 175 | .error_union, |
| 179 | 176 | .merge_error_sets, |
| ... | ... | @@ -251,23 +248,20 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 251 | 248 | .slice_sentinel, |
| 252 | 249 | => try zg.addErrorNode(node, "slice operator is not allowed in ZON", .{}), |
| 253 | 250 | |
| 254 | .deref, .address_of => try zg.addErrorTok(main_tokens[node], "pointers are not available in ZON", .{}), | |
| 255 | .unwrap_optional => try zg.addErrorTok(main_tokens[node], "optionals are not available in ZON", .{}), | |
| 251 | .deref, .address_of => try zg.addErrorTok(tree.nodeMainToken(node), "pointers are not available in ZON", .{}), | |
| 252 | .unwrap_optional => try zg.addErrorTok(tree.nodeMainToken(node), "optionals are not available in ZON", .{}), | |
| 256 | 253 | .error_value => try zg.addErrorNode(node, "errors are not available in ZON", .{}), |
| 257 | 254 | |
| 258 | .array_access => try zg.addErrorTok(node, "array indexing is not allowed in ZON", .{}), | |
| 255 | .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}), | |
| 259 | 256 | |
| 260 | 257 | .block_two, |
| 261 | 258 | .block_two_semicolon, |
| 262 | 259 | .block, |
| 263 | 260 | .block_semicolon, |
| 264 | 261 | => { |
| 265 | const size = switch (node_tags[node]) { | |
| 266 | .block_two, .block_two_semicolon => @intFromBool(node_datas[node].lhs != 0) + @intFromBool(node_datas[node].rhs != 0), | |
| 267 | .block, .block_semicolon => node_datas[node].rhs - node_datas[node].lhs, | |
| 268 | else => unreachable, | |
| 269 | }; | |
| 270 | if (size == 0) { | |
| 262 | var buffer: [2]Ast.Node.Index = undefined; | |
| 263 | const statements = tree.blockStatements(&buffer, node).?; | |
| 264 | if (statements.len == 0) { | |
| 271 | 265 | try zg.addErrorNodeNotes(node, "void literals are not available in ZON", .{}, &.{ |
| 272 | 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 | 282 | var buf: [2]Ast.Node.Index = undefined; |
| 289 | 283 | |
| 290 | 284 | const type_node = if (tree.fullArrayInit(&buf, node)) |full| |
| 291 | full.ast.type_expr | |
| 285 | full.ast.type_expr.unwrap().? | |
| 292 | 286 | else if (tree.fullStructInit(&buf, node)) |full| |
| 293 | full.ast.type_expr | |
| 287 | full.ast.type_expr.unwrap().? | |
| 294 | 288 | else |
| 295 | 289 | unreachable; |
| 296 | 290 | |
| ... | ... | @@ -300,18 +294,18 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 300 | 294 | }, |
| 301 | 295 | |
| 302 | 296 | .grouped_expression => { |
| 303 | try zg.addErrorTokNotes(main_tokens[node], "expression grouping is not allowed in ZON", .{}, &.{ | |
| 304 | try zg.errNoteTok(main_tokens[node], "these parentheses are always redundant", .{}), | |
| 297 | try zg.addErrorTokNotes(tree.nodeMainToken(node), "expression grouping is not allowed in ZON", .{}, &.{ | |
| 298 | try zg.errNoteTok(tree.nodeMainToken(node), "these parentheses are always redundant", .{}), | |
| 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 | }, |
| 308 | 302 | |
| 309 | 303 | .negation => { |
| 310 | const child_node = node_datas[node].lhs; | |
| 311 | switch (node_tags[child_node]) { | |
| 304 | const child_node = tree.nodeData(node).node; | |
| 305 | switch (tree.nodeTag(child_node)) { | |
| 312 | 306 | .number_literal => return zg.numberLiteral(child_node, node, dest_node, .negative), |
| 313 | 307 | .identifier => { |
| 314 | const child_ident = tree.tokenSlice(main_tokens[child_node]); | |
| 308 | const child_ident = tree.tokenSlice(tree.nodeMainToken(child_node)); | |
| 315 | 309 | if (mem.eql(u8, child_ident, "inf")) { |
| 316 | 310 | zg.setNode(dest_node, .{ |
| 317 | 311 | .tag = .neg_inf, |
| ... | ... | @@ -323,7 +317,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 323 | 317 | }, |
| 324 | 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 | 322 | .number_literal => try zg.numberLiteral(node, node, dest_node, .positive), |
| 329 | 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 | 325 | .identifier => try zg.identifier(node, dest_node), |
| 332 | 326 | |
| 333 | 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 | 329 | error.BadString => undefined, // doesn't matter, there's an error |
| 336 | 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 | 363 | var buf: [2]Ast.Node.Index = undefined; |
| 370 | 364 | const full = tree.fullArrayInit(&buf, node).?; |
| 371 | 365 | 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_*` | |
| 373 | 367 | |
| 374 | 368 | const first_elem: u32 = @intCast(zg.nodes.len); |
| 375 | 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 | 392 | => { |
| 399 | 393 | var buf: [2]Ast.Node.Index = undefined; |
| 400 | 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_*` | |
| 402 | 396 | |
| 403 | 397 | if (full.ast.fields.len == 0) { |
| 404 | 398 | zg.setNode(dest_node, .{ |
| ... | ... | @@ -460,7 +454,7 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 460 | 454 | |
| 461 | 455 | fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 { |
| 462 | 456 | const tree = zg.tree; |
| 463 | assert(tree.tokens.items(.tag)[ident_token] == .identifier); | |
| 457 | assert(tree.tokenTag(ident_token) == .identifier); | |
| 464 | 458 | const ident_name = tree.tokenSlice(ident_token); |
| 465 | 459 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 466 | 460 | const start = zg.string_bytes.items.len; |
| ... | ... | @@ -493,19 +487,16 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 { |
| 493 | 487 | |
| 494 | 488 | /// Estimates the size of a string node without parsing it. |
| 495 | 489 | pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize { |
| 496 | switch (tree.nodes.items(.tag)[node]) { | |
| 490 | switch (tree.nodeTag(node)) { | |
| 497 | 491 | // Parsed string literals are typically around the size of the raw strings. |
| 498 | 492 | .string_literal => { |
| 499 | const token = tree.nodes.items(.main_token)[node]; | |
| 493 | const token = tree.nodeMainToken(node); | |
| 500 | 494 | const raw_string = tree.tokenSlice(token); |
| 501 | 495 | return raw_string.len; |
| 502 | 496 | }, |
| 503 | 497 | // Multiline string literal lengths can be computed exactly. |
| 504 | 498 | .multiline_string_literal => { |
| 505 | const first_tok, const last_tok = bounds: { | |
| 506 | const node_data = tree.nodes.items(.data)[node]; | |
| 507 | break :bounds .{ node_data.lhs, node_data.rhs }; | |
| 508 | }; | |
| 499 | const first_tok, const last_tok = tree.nodeData(node).token_and_token; | |
| 509 | 500 | |
| 510 | 501 | var size = tree.tokenSlice(first_tok)[2..].len; |
| 511 | 502 | for (first_tok + 1..last_tok + 1) |tok_idx| { |
| ... | ... | @@ -524,17 +515,14 @@ pub fn parseStrLit( |
| 524 | 515 | node: Ast.Node.Index, |
| 525 | 516 | writer: anytype, |
| 526 | 517 | ) error{OutOfMemory}!std.zig.string_literal.Result { |
| 527 | switch (tree.nodes.items(.tag)[node]) { | |
| 518 | switch (tree.nodeTag(node)) { | |
| 528 | 519 | .string_literal => { |
| 529 | const token = tree.nodes.items(.main_token)[node]; | |
| 520 | const token = tree.nodeMainToken(node); | |
| 530 | 521 | const raw_string = tree.tokenSlice(token); |
| 531 | 522 | return std.zig.string_literal.parseWrite(writer, raw_string); |
| 532 | 523 | }, |
| 533 | 524 | .multiline_string_literal => { |
| 534 | const first_tok, const last_tok = bounds: { | |
| 535 | const node_data = tree.nodes.items(.data)[node]; | |
| 536 | break :bounds .{ node_data.lhs, node_data.rhs }; | |
| 537 | }; | |
| 525 | const first_tok, const last_tok = tree.nodeData(node).token_and_token; | |
| 538 | 526 | |
| 539 | 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 | 560 | switch (try parseStrLit(zg.tree, str_node, zg.string_bytes.writer(zg.gpa))) { |
| 573 | 561 | .success => {}, |
| 574 | 562 | .failure => |err| { |
| 575 | const token = zg.tree.nodes.items(.main_token)[str_node]; | |
| 563 | const token = zg.tree.nodeMainToken(str_node); | |
| 576 | 564 | const raw_string = zg.tree.tokenSlice(token); |
| 577 | 565 | try zg.lowerStrLitError(err, token, raw_string, 0); |
| 578 | 566 | return error.BadString; |
| ... | ... | @@ -620,7 +608,7 @@ fn identAsString(zg: *ZonGen, ident_token: Ast.TokenIndex) !Zoir.NullTerminatedS |
| 620 | 608 | |
| 621 | 609 | fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum { negative, positive }) !void { |
| 622 | 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 | 612 | const num_bytes = tree.tokenSlice(num_token); |
| 625 | 613 | |
| 626 | 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 | 712 | |
| 725 | 713 | fn charLiteral(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void { |
| 726 | 714 | const tree = zg.tree; |
| 727 | assert(tree.nodes.items(.tag)[node] == .char_literal); | |
| 728 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 715 | assert(tree.nodeTag(node) == .char_literal); | |
| 716 | const main_token = tree.nodeMainToken(node); | |
| 729 | 717 | const slice = tree.tokenSlice(main_token); |
| 730 | 718 | switch (std.zig.parseCharLiteral(slice)) { |
| 731 | 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 | 727 | |
| 740 | 728 | fn identifier(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) !void { |
| 741 | 729 | const tree = zg.tree; |
| 742 | assert(tree.nodes.items(.tag)[node] == .identifier); | |
| 743 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 730 | assert(tree.nodeTag(node) == .identifier); | |
| 731 | const main_token = tree.nodeMainToken(node); | |
| 744 | 732 | const ident = tree.tokenSlice(main_token); |
| 745 | 733 | |
| 746 | 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 | 811 | |
| 824 | 812 | return .{ |
| 825 | 813 | .msg = @enumFromInt(message_idx), |
| 826 | .token = Zoir.CompileError.invalid_token, | |
| 827 | .node_or_offset = node, | |
| 814 | .token = .none, | |
| 815 | .node_or_offset = @intFromEnum(node), | |
| 828 | 816 | }; |
| 829 | 817 | } |
| 830 | 818 | |
| ... | ... | @@ -836,33 +824,33 @@ fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, arg |
| 836 | 824 | |
| 837 | 825 | return .{ |
| 838 | 826 | .msg = @enumFromInt(message_idx), |
| 839 | .token = tok, | |
| 827 | .token = .fromToken(tok), | |
| 840 | 828 | .node_or_offset = 0, |
| 841 | 829 | }; |
| 842 | 830 | } |
| 843 | 831 | |
| 844 | 832 | fn 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 | } |
| 847 | 835 | fn 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 | } |
| 850 | 838 | fn 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 | } |
| 853 | 841 | fn 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 | } |
| 856 | 844 | fn 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 | } |
| 859 | 847 | fn 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 | } |
| 862 | 850 | |
| 863 | 851 | fn addErrorInner( |
| 864 | 852 | zg: *ZonGen, |
| 865 | token: Ast.TokenIndex, | |
| 853 | token: Ast.OptionalTokenIndex, | |
| 866 | 854 | node_or_offset: u32, |
| 867 | 855 | comptime format: []const u8, |
| 868 | 856 | args: anytype, |
lib/std/zig/render.zig+469-530| ... | ... | @@ -91,21 +91,22 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v |
| 91 | 91 | }; |
| 92 | 92 | |
| 93 | 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 | 95 | _ = try renderComments(&r, 0, comment_end_loc); |
| 96 | 96 | |
| 97 | if (tree.tokens.items(.tag)[0] == .container_doc_comment) { | |
| 97 | if (tree.tokenTag(0) == .container_doc_comment) { | |
| 98 | 98 | try renderContainerDocComments(&r, 0); |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | if (tree.mode == .zon) { | |
| 102 | try renderExpression( | |
| 103 | &r, | |
| 104 | tree.nodes.items(.data)[0].lhs, | |
| 105 | .newline, | |
| 106 | ); | |
| 107 | } else { | |
| 108 | try renderMembers(&r, tree.rootDecls()); | |
| 101 | switch (tree.mode) { | |
| 102 | .zig => try renderMembers(&r, tree.rootDecls()), | |
| 103 | .zon => { | |
| 104 | try renderExpression( | |
| 105 | &r, | |
| 106 | tree.rootDecls()[0], | |
| 107 | .newline, | |
| 108 | ); | |
| 109 | }, | |
| 109 | 110 | } |
| 110 | 111 | |
| 111 | 112 | if (auto_indenting_stream.disabled_offset) |disabled_offset| { |
| ... | ... | @@ -141,24 +142,20 @@ fn renderMember( |
| 141 | 142 | ) Error!void { |
| 142 | 143 | const tree = r.tree; |
| 143 | 144 | const ais = r.ais; |
| 144 | const node_tags = tree.nodes.items(.tag); | |
| 145 | const token_tags = tree.tokens.items(.tag); | |
| 146 | const main_tokens = tree.nodes.items(.main_token); | |
| 147 | const datas = tree.nodes.items(.data); | |
| 148 | 145 | if (r.fixups.omit_nodes.contains(decl)) return; |
| 149 | 146 | try renderDocComments(r, tree.firstToken(decl)); |
| 150 | switch (tree.nodes.items(.tag)[decl]) { | |
| 147 | switch (tree.nodeTag(decl)) { | |
| 151 | 148 | .fn_decl => { |
| 152 | 149 | // Some examples: |
| 153 | 150 | // pub extern "foo" fn ... |
| 154 | 151 | // export fn ... |
| 155 | const fn_proto = datas[decl].lhs; | |
| 156 | const fn_token = main_tokens[fn_proto]; | |
| 152 | const fn_proto, const body_node = tree.nodeData(decl).node_and_node; | |
| 153 | const fn_token = tree.nodeMainToken(fn_proto); | |
| 157 | 154 | // Go back to the first token we should render here. |
| 158 | 155 | var i = fn_token; |
| 159 | 156 | while (i > 0) { |
| 160 | 157 | i -= 1; |
| 161 | switch (token_tags[i]) { | |
| 158 | switch (tree.tokenTag(i)) { | |
| 162 | 159 | .keyword_extern, |
| 163 | 160 | .keyword_export, |
| 164 | 161 | .keyword_pub, |
| ... | ... | @@ -173,31 +170,34 @@ fn renderMember( |
| 173 | 170 | }, |
| 174 | 171 | } |
| 175 | 172 | } |
| 173 | ||
| 176 | 174 | while (i < fn_token) : (i += 1) { |
| 177 | 175 | try renderToken(r, i, .space); |
| 178 | 176 | } |
| 179 | switch (tree.nodes.items(.tag)[fn_proto]) { | |
| 177 | switch (tree.nodeTag(fn_proto)) { | |
| 180 | 178 | .fn_proto_one, .fn_proto => { |
| 181 | const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one) | |
| 182 | tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr | |
| 179 | var buf: [1]Ast.Node.Index = undefined; | |
| 180 | const opt_callconv_expr = if (tree.nodeTag(fn_proto) == .fn_proto_one) | |
| 181 | tree.fnProtoOne(&buf, fn_proto).ast.callconv_expr | |
| 183 | 182 | else |
| 184 | tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr; | |
| 183 | tree.fnProto(fn_proto).ast.callconv_expr; | |
| 184 | ||
| 185 | 185 | // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE |
| 186 | if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) { | |
| 187 | if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) { | |
| 188 | try ais.writer().writeAll("inline "); | |
| 186 | if (opt_callconv_expr.unwrap()) |callconv_expr| { | |
| 187 | if (tree.nodeTag(callconv_expr) == .enum_literal) { | |
| 188 | if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) { | |
| 189 | try ais.writer().writeAll("inline "); | |
| 190 | } | |
| 189 | 191 | } |
| 190 | 192 | } |
| 191 | 193 | }, |
| 192 | 194 | .fn_proto_simple, .fn_proto_multi => {}, |
| 193 | 195 | else => unreachable, |
| 194 | 196 | } |
| 195 | assert(datas[decl].rhs != 0); | |
| 196 | 197 | try renderExpression(r, fn_proto, .space); |
| 197 | const body_node = datas[decl].rhs; | |
| 198 | 198 | if (r.fixups.gut_functions.contains(decl)) { |
| 199 | 199 | try ais.pushIndent(.normal); |
| 200 | const lbrace = tree.nodes.items(.main_token)[body_node]; | |
| 200 | const lbrace = tree.nodeMainToken(body_node); | |
| 201 | 201 | try renderToken(r, lbrace, .newline); |
| 202 | 202 | try discardAllParams(r, fn_proto); |
| 203 | 203 | try ais.writer().writeAll("@trap();"); |
| ... | ... | @@ -206,7 +206,7 @@ fn renderMember( |
| 206 | 206 | try renderToken(r, tree.lastToken(body_node), space); // rbrace |
| 207 | 207 | } else if (r.fixups.unused_var_decls.count() != 0) { |
| 208 | 208 | try ais.pushIndent(.normal); |
| 209 | const lbrace = tree.nodes.items(.main_token)[body_node]; | |
| 209 | const lbrace = tree.nodeMainToken(body_node); | |
| 210 | 210 | try renderToken(r, lbrace, .newline); |
| 211 | 211 | |
| 212 | 212 | var fn_proto_buf: [1]Ast.Node.Index = undefined; |
| ... | ... | @@ -214,7 +214,7 @@ fn renderMember( |
| 214 | 214 | var it = full_fn_proto.iterate(&tree); |
| 215 | 215 | while (it.next()) |param| { |
| 216 | 216 | const name_ident = param.name_token.?; |
| 217 | assert(token_tags[name_ident] == .identifier); | |
| 217 | assert(tree.tokenTag(name_ident) == .identifier); | |
| 218 | 218 | if (r.fixups.unused_var_decls.contains(name_ident)) { |
| 219 | 219 | const w = ais.writer(); |
| 220 | 220 | try w.writeAll("_ = "); |
| ... | ... | @@ -223,25 +223,7 @@ fn renderMember( |
| 223 | 223 | } |
| 224 | 224 | } |
| 225 | 225 | var statements_buf: [2]Ast.Node.Index = undefined; |
| 226 | const statements = switch (node_tags[body_node]) { | |
| 227 | .block_two, | |
| 228 | .block_two_semicolon, | |
| 229 | => b: { | |
| 230 | statements_buf = .{ datas[body_node].lhs, datas[body_node].rhs }; | |
| 231 | if (datas[body_node].lhs == 0) { | |
| 232 | break :b statements_buf[0..0]; | |
| 233 | } else if (datas[body_node].rhs == 0) { | |
| 234 | break :b statements_buf[0..1]; | |
| 235 | } else { | |
| 236 | break :b statements_buf[0..2]; | |
| 237 | } | |
| 238 | }, | |
| 239 | .block, | |
| 240 | .block_semicolon, | |
| 241 | => tree.extra_data[datas[body_node].lhs..datas[body_node].rhs], | |
| 242 | ||
| 243 | else => unreachable, | |
| 244 | }; | |
| 226 | const statements = tree.blockStatements(&statements_buf, body_node).?; | |
| 245 | 227 | return finishRenderBlock(r, body_node, statements, space); |
| 246 | 228 | } else { |
| 247 | 229 | return renderExpression(r, body_node, space); |
| ... | ... | @@ -254,11 +236,11 @@ fn renderMember( |
| 254 | 236 | => { |
| 255 | 237 | // Extern function prototypes are parsed as these tags. |
| 256 | 238 | // Go back to the first token we should render here. |
| 257 | const fn_token = main_tokens[decl]; | |
| 239 | const fn_token = tree.nodeMainToken(decl); | |
| 258 | 240 | var i = fn_token; |
| 259 | 241 | while (i > 0) { |
| 260 | 242 | i -= 1; |
| 261 | switch (token_tags[i]) { | |
| 243 | switch (tree.tokenTag(i)) { | |
| 262 | 244 | .keyword_extern, |
| 263 | 245 | .keyword_export, |
| 264 | 246 | .keyword_pub, |
| ... | ... | @@ -281,9 +263,9 @@ fn renderMember( |
| 281 | 263 | }, |
| 282 | 264 | |
| 283 | 265 | .@"usingnamespace" => { |
| 284 | const main_token = main_tokens[decl]; | |
| 285 | const expr = datas[decl].lhs; | |
| 286 | if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) { | |
| 266 | const main_token = tree.nodeMainToken(decl); | |
| 267 | const expr = tree.nodeData(decl).node; | |
| 268 | if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) { | |
| 287 | 269 | try renderToken(r, main_token - 1, .space); // pub |
| 288 | 270 | } |
| 289 | 271 | try renderToken(r, main_token, .space); // usingnamespace |
| ... | ... | @@ -302,15 +284,17 @@ fn renderMember( |
| 302 | 284 | }, |
| 303 | 285 | |
| 304 | 286 | .test_decl => { |
| 305 | const test_token = main_tokens[decl]; | |
| 287 | const test_token = tree.nodeMainToken(decl); | |
| 288 | const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node; | |
| 306 | 289 | try renderToken(r, test_token, .space); |
| 307 | const test_name_tag = token_tags[test_token + 1]; | |
| 308 | switch (test_name_tag) { | |
| 309 | .string_literal => try renderToken(r, test_token + 1, .space), | |
| 310 | .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing), | |
| 311 | else => {}, | |
| 290 | if (opt_name_token.unwrap()) |name_token| { | |
| 291 | switch (tree.tokenTag(name_token)) { | |
| 292 | .string_literal => try renderToken(r, name_token, .space), | |
| 293 | .identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing), | |
| 294 | else => unreachable, | |
| 295 | } | |
| 312 | 296 | } |
| 313 | try renderExpression(r, datas[decl].rhs, space); | |
| 297 | try renderExpression(r, block_node, space); | |
| 314 | 298 | }, |
| 315 | 299 | |
| 316 | 300 | .container_field_init, |
| ... | ... | @@ -338,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa |
| 338 | 322 | fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 339 | 323 | const tree = r.tree; |
| 340 | 324 | const ais = r.ais; |
| 341 | const token_tags = tree.tokens.items(.tag); | |
| 342 | const main_tokens = tree.nodes.items(.main_token); | |
| 343 | const node_tags = tree.nodes.items(.tag); | |
| 344 | const datas = tree.nodes.items(.data); | |
| 345 | 325 | if (r.fixups.replace_nodes_with_string.get(node)) |replacement| { |
| 346 | 326 | try ais.writer().writeAll(replacement); |
| 347 | 327 | try renderOnlySpace(r, space); |
| ... | ... | @@ -349,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 349 | 329 | } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| { |
| 350 | 330 | return renderExpression(r, replacement, space); |
| 351 | 331 | } |
| 352 | switch (node_tags[node]) { | |
| 332 | switch (tree.nodeTag(node)) { | |
| 353 | 333 | .identifier => { |
| 354 | const token_index = main_tokens[node]; | |
| 334 | const token_index = tree.nodeMainToken(node); | |
| 355 | 335 | return renderIdentifier(r, token_index, space, .preserve_when_shadowing); |
| 356 | 336 | }, |
| 357 | 337 | |
| ... | ... | @@ -360,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 360 | 340 | .unreachable_literal, |
| 361 | 341 | .anyframe_literal, |
| 362 | 342 | .string_literal, |
| 363 | => return renderToken(r, main_tokens[node], space), | |
| 343 | => return renderToken(r, tree.nodeMainToken(node), space), | |
| 364 | 344 | |
| 365 | 345 | .multiline_string_literal => { |
| 366 | 346 | try ais.maybeInsertNewline(); |
| 367 | 347 | |
| 368 | var i = datas[node].lhs; | |
| 369 | while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline); | |
| 348 | const first_tok, const last_tok = tree.nodeData(node).token_and_token; | |
| 349 | for (first_tok..last_tok + 1) |i| { | |
| 350 | try renderToken(r, @intCast(i), .newline); | |
| 351 | } | |
| 352 | ||
| 353 | const next_token = last_tok + 1; | |
| 354 | const next_token_tag = tree.tokenTag(next_token); | |
| 370 | 355 | |
| 371 | 356 | // dedent the next thing that comes after a multiline string literal |
| 372 | 357 | if (!ais.indentStackEmpty() and |
| 373 | token_tags[i] != .colon and | |
| 374 | ((token_tags[i] != .semicolon and token_tags[i] != .comma) or | |
| 358 | next_token_tag != .colon and | |
| 359 | ((next_token_tag != .semicolon and next_token_tag != .comma) or | |
| 375 | 360 | ais.lastSpaceModeIndent() < ais.currentIndent())) |
| 376 | 361 | { |
| 377 | 362 | ais.popIndent(); |
| ... | ... | @@ -380,44 +365,35 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 380 | 365 | |
| 381 | 366 | switch (space) { |
| 382 | 367 | .none, .space, .newline, .skip => {}, |
| 383 | .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon), | |
| 384 | .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma), | |
| 385 | .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space), | |
| 368 | .semicolon => if (next_token_tag == .semicolon) try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon), | |
| 369 | .comma => if (next_token_tag == .comma) try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma), | |
| 370 | .comma_space => if (next_token_tag == .comma) try renderToken(r, next_token, .space), | |
| 386 | 371 | } |
| 387 | 372 | }, |
| 388 | 373 | |
| 389 | 374 | .error_value => { |
| 390 | try renderToken(r, main_tokens[node], .none); | |
| 391 | try renderToken(r, main_tokens[node] + 1, .none); | |
| 392 | return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote); | |
| 375 | const main_token = tree.nodeMainToken(node); | |
| 376 | try renderToken(r, main_token, .none); | |
| 377 | try renderToken(r, main_token + 1, .none); | |
| 378 | return renderIdentifier(r, main_token + 2, space, .eagerly_unquote); | |
| 393 | 379 | }, |
| 394 | 380 | |
| 395 | 381 | .block_two, |
| 396 | 382 | .block_two_semicolon, |
| 397 | => { | |
| 398 | const statements = [2]Ast.Node.Index{ datas[node].lhs, datas[node].rhs }; | |
| 399 | if (datas[node].lhs == 0) { | |
| 400 | return renderBlock(r, node, statements[0..0], space); | |
| 401 | } else if (datas[node].rhs == 0) { | |
| 402 | return renderBlock(r, node, statements[0..1], space); | |
| 403 | } else { | |
| 404 | return renderBlock(r, node, statements[0..2], space); | |
| 405 | } | |
| 406 | }, | |
| 407 | 383 | .block, |
| 408 | 384 | .block_semicolon, |
| 409 | 385 | => { |
| 410 | const statements = tree.extra_data[datas[node].lhs..datas[node].rhs]; | |
| 386 | var buf: [2]Ast.Node.Index = undefined; | |
| 387 | const statements = tree.blockStatements(&buf, node).?; | |
| 411 | 388 | return renderBlock(r, node, statements, space); |
| 412 | 389 | }, |
| 413 | 390 | |
| 414 | 391 | .@"errdefer" => { |
| 415 | const defer_token = main_tokens[node]; | |
| 416 | const payload_token = datas[node].lhs; | |
| 417 | const expr = datas[node].rhs; | |
| 392 | const defer_token = tree.nodeMainToken(node); | |
| 393 | const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node; | |
| 418 | 394 | |
| 419 | 395 | try renderToken(r, defer_token, .space); |
| 420 | if (payload_token != 0) { | |
| 396 | if (maybe_payload_token.unwrap()) |payload_token| { | |
| 421 | 397 | try renderToken(r, payload_token - 1, .none); // | |
| 422 | 398 | try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier |
| 423 | 399 | try renderToken(r, payload_token + 1, .space); // | |
| ... | ... | @@ -425,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 425 | 401 | return renderExpression(r, expr, space); |
| 426 | 402 | }, |
| 427 | 403 | |
| 428 | .@"defer" => { | |
| 429 | const defer_token = main_tokens[node]; | |
| 430 | const expr = datas[node].rhs; | |
| 431 | try renderToken(r, defer_token, .space); | |
| 432 | return renderExpression(r, expr, space); | |
| 433 | }, | |
| 434 | .@"comptime", .@"nosuspend" => { | |
| 435 | const comptime_token = main_tokens[node]; | |
| 436 | const block = datas[node].lhs; | |
| 437 | try renderToken(r, comptime_token, .space); | |
| 438 | return renderExpression(r, block, space); | |
| 439 | }, | |
| 440 | ||
| 441 | .@"suspend" => { | |
| 442 | const suspend_token = main_tokens[node]; | |
| 443 | const body = datas[node].lhs; | |
| 444 | try renderToken(r, suspend_token, .space); | |
| 445 | return renderExpression(r, body, space); | |
| 404 | .@"defer", | |
| 405 | .@"comptime", | |
| 406 | .@"nosuspend", | |
| 407 | .@"suspend", | |
| 408 | => { | |
| 409 | const main_token = tree.nodeMainToken(node); | |
| 410 | const item = tree.nodeData(node).node; | |
| 411 | try renderToken(r, main_token, .space); | |
| 412 | return renderExpression(r, item, space); | |
| 446 | 413 | }, |
| 447 | 414 | |
| 448 | 415 | .@"catch" => { |
| 449 | const main_token = main_tokens[node]; | |
| 450 | const fallback_first = tree.firstToken(datas[node].rhs); | |
| 416 | const main_token = tree.nodeMainToken(node); | |
| 417 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 418 | const fallback_first = tree.firstToken(rhs); | |
| 451 | 419 | |
| 452 | 420 | const same_line = tree.tokensOnSameLine(main_token, fallback_first); |
| 453 | 421 | const after_op_space = if (same_line) Space.space else Space.newline; |
| 454 | 422 | |
| 455 | try renderExpression(r, datas[node].lhs, .space); // target | |
| 423 | try renderExpression(r, lhs, .space); // target | |
| 456 | 424 | |
| 457 | 425 | try ais.pushIndent(.normal); |
| 458 | if (token_tags[fallback_first - 1] == .pipe) { | |
| 426 | if (tree.tokenTag(fallback_first - 1) == .pipe) { | |
| 459 | 427 | try renderToken(r, main_token, .space); // catch keyword |
| 460 | 428 | try renderToken(r, main_token + 1, .none); // pipe |
| 461 | 429 | try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier |
| 462 | 430 | try renderToken(r, main_token + 3, after_op_space); // pipe |
| 463 | 431 | } else { |
| 464 | assert(token_tags[fallback_first - 1] == .keyword_catch); | |
| 432 | assert(tree.tokenTag(fallback_first - 1) == .keyword_catch); | |
| 465 | 433 | try renderToken(r, main_token, after_op_space); // catch keyword |
| 466 | 434 | } |
| 467 | try renderExpression(r, datas[node].rhs, space); // fallback | |
| 435 | try renderExpression(r, rhs, space); // fallback | |
| 468 | 436 | ais.popIndent(); |
| 469 | 437 | }, |
| 470 | 438 | |
| 471 | 439 | .field_access => { |
| 472 | const main_token = main_tokens[node]; | |
| 473 | const field_access = datas[node]; | |
| 440 | const lhs, const name_token = tree.nodeData(node).node_and_token; | |
| 441 | const dot_token = name_token - 1; | |
| 474 | 442 | |
| 475 | 443 | try ais.pushIndent(.field_access); |
| 476 | try renderExpression(r, field_access.lhs, .none); | |
| 444 | try renderExpression(r, lhs, .none); | |
| 477 | 445 | |
| 478 | 446 | // Allow a line break between the lhs and the dot if the lhs and rhs |
| 479 | 447 | // are on different lines. |
| 480 | const lhs_last_token = tree.lastToken(field_access.lhs); | |
| 481 | const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1); | |
| 482 | if (!same_line and !hasComment(tree, lhs_last_token, main_token)) try ais.insertNewline(); | |
| 448 | const lhs_last_token = tree.lastToken(lhs); | |
| 449 | const same_line = tree.tokensOnSameLine(lhs_last_token, name_token); | |
| 450 | if (!same_line and !hasComment(tree, lhs_last_token, dot_token)) try ais.insertNewline(); | |
| 483 | 451 | |
| 484 | try renderToken(r, main_token, .none); // . | |
| 452 | try renderToken(r, dot_token, .none); | |
| 485 | 453 | |
| 486 | try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field | |
| 454 | try renderIdentifier(r, name_token, space, .eagerly_unquote); // field | |
| 487 | 455 | ais.popIndent(); |
| 488 | 456 | }, |
| 489 | 457 | |
| 490 | 458 | .error_union, |
| 491 | 459 | .switch_range, |
| 492 | 460 | => { |
| 493 | const infix = datas[node]; | |
| 494 | try renderExpression(r, infix.lhs, .none); | |
| 495 | try renderToken(r, main_tokens[node], .none); | |
| 496 | return renderExpression(r, infix.rhs, space); | |
| 461 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 462 | try renderExpression(r, lhs, .none); | |
| 463 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 464 | return renderExpression(r, rhs, space); | |
| 497 | 465 | }, |
| 498 | 466 | .for_range => { |
| 499 | const infix = datas[node]; | |
| 500 | try renderExpression(r, infix.lhs, .none); | |
| 501 | if (infix.rhs != 0) { | |
| 502 | try renderToken(r, main_tokens[node], .none); | |
| 503 | return renderExpression(r, infix.rhs, space); | |
| 467 | const start, const opt_end = tree.nodeData(node).node_and_opt_node; | |
| 468 | try renderExpression(r, start, .none); | |
| 469 | if (opt_end.unwrap()) |end| { | |
| 470 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 471 | return renderExpression(r, end, space); | |
| 504 | 472 | } else { |
| 505 | return renderToken(r, main_tokens[node], space); | |
| 473 | return renderToken(r, tree.nodeMainToken(node), space); | |
| 506 | 474 | } |
| 507 | 475 | }, |
| 508 | 476 | |
| ... | ... | @@ -525,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 525 | 493 | .assign_mul_wrap, |
| 526 | 494 | .assign_mul_sat, |
| 527 | 495 | => { |
| 528 | const infix = datas[node]; | |
| 529 | try renderExpression(r, infix.lhs, .space); | |
| 530 | const op_token = main_tokens[node]; | |
| 496 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 497 | try renderExpression(r, lhs, .space); | |
| 498 | const op_token = tree.nodeMainToken(node); | |
| 531 | 499 | try ais.pushIndent(.after_equals); |
| 532 | 500 | if (tree.tokensOnSameLine(op_token, op_token + 1)) { |
| 533 | 501 | try renderToken(r, op_token, .space); |
| 534 | 502 | } else { |
| 535 | 503 | try renderToken(r, op_token, .newline); |
| 536 | 504 | } |
| 537 | try renderExpression(r, infix.rhs, space); | |
| 505 | try renderExpression(r, rhs, space); | |
| 538 | 506 | ais.popIndent(); |
| 539 | 507 | }, |
| 540 | 508 | |
| ... | ... | @@ -568,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 568 | 536 | .sub_sat, |
| 569 | 537 | .@"orelse", |
| 570 | 538 | => { |
| 571 | const infix = datas[node]; | |
| 572 | try renderExpression(r, infix.lhs, .space); | |
| 573 | const op_token = main_tokens[node]; | |
| 539 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 540 | try renderExpression(r, lhs, .space); | |
| 541 | const op_token = tree.nodeMainToken(node); | |
| 574 | 542 | try ais.pushIndent(.binop); |
| 575 | 543 | if (tree.tokensOnSameLine(op_token, op_token + 1)) { |
| 576 | 544 | try renderToken(r, op_token, .space); |
| 577 | 545 | } else { |
| 578 | 546 | try renderToken(r, op_token, .newline); |
| 579 | 547 | } |
| 580 | try renderExpression(r, infix.rhs, space); | |
| 548 | try renderExpression(r, rhs, space); | |
| 581 | 549 | ais.popIndent(); |
| 582 | 550 | }, |
| 583 | 551 | |
| ... | ... | @@ -589,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 589 | 557 | |
| 590 | 558 | for (full.ast.variables, 0..) |variable_node, i| { |
| 591 | 559 | const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space; |
| 592 | switch (node_tags[variable_node]) { | |
| 560 | switch (tree.nodeTag(variable_node)) { | |
| 593 | 561 | .global_var_decl, |
| 594 | 562 | .local_var_decl, |
| 595 | 563 | .simple_var_decl, |
| ... | ... | @@ -617,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 617 | 585 | .optional_type, |
| 618 | 586 | .address_of, |
| 619 | 587 | => { |
| 620 | try renderToken(r, main_tokens[node], .none); | |
| 621 | return renderExpression(r, datas[node].lhs, space); | |
| 588 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 589 | return renderExpression(r, tree.nodeData(node).node, space); | |
| 622 | 590 | }, |
| 623 | 591 | |
| 624 | 592 | .@"try", |
| 625 | 593 | .@"resume", |
| 626 | 594 | .@"await", |
| 627 | 595 | => { |
| 628 | try renderToken(r, main_tokens[node], .space); | |
| 629 | return renderExpression(r, datas[node].lhs, space); | |
| 596 | try renderToken(r, tree.nodeMainToken(node), .space); | |
| 597 | return renderExpression(r, tree.nodeData(node).node, space); | |
| 630 | 598 | }, |
| 631 | 599 | |
| 632 | 600 | .array_type, |
| ... | ... | @@ -679,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 679 | 647 | }, |
| 680 | 648 | |
| 681 | 649 | .array_access => { |
| 682 | const suffix = datas[node]; | |
| 683 | const lbracket = tree.firstToken(suffix.rhs) - 1; | |
| 684 | const rbracket = tree.lastToken(suffix.rhs) + 1; | |
| 650 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 651 | const lbracket = tree.firstToken(rhs) - 1; | |
| 652 | const rbracket = tree.lastToken(rhs) + 1; | |
| 685 | 653 | const one_line = tree.tokensOnSameLine(lbracket, rbracket); |
| 686 | 654 | const inner_space = if (one_line) Space.none else Space.newline; |
| 687 | try renderExpression(r, suffix.lhs, .none); | |
| 655 | try renderExpression(r, lhs, .none); | |
| 688 | 656 | try ais.pushIndent(.normal); |
| 689 | 657 | try renderToken(r, lbracket, inner_space); // [ |
| 690 | try renderExpression(r, suffix.rhs, inner_space); | |
| 658 | try renderExpression(r, rhs, inner_space); | |
| 691 | 659 | ais.popIndent(); |
| 692 | 660 | return renderToken(r, rbracket, space); // ] |
| 693 | 661 | }, |
| 694 | 662 | |
| 695 | .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space), | |
| 663 | .slice_open, | |
| 664 | .slice, | |
| 665 | .slice_sentinel, | |
| 666 | => return renderSlice(r, node, tree.fullSlice(node).?, space), | |
| 696 | 667 | |
| 697 | 668 | .deref => { |
| 698 | try renderExpression(r, datas[node].lhs, .none); | |
| 699 | return renderToken(r, main_tokens[node], space); | |
| 669 | try renderExpression(r, tree.nodeData(node).node, .none); | |
| 670 | return renderToken(r, tree.nodeMainToken(node), space); | |
| 700 | 671 | }, |
| 701 | 672 | |
| 702 | 673 | .unwrap_optional => { |
| 703 | try renderExpression(r, datas[node].lhs, .none); | |
| 704 | try renderToken(r, main_tokens[node], .none); | |
| 705 | return renderToken(r, datas[node].rhs, space); | |
| 674 | const lhs, const question_mark = tree.nodeData(node).node_and_token; | |
| 675 | const dot_token = question_mark - 1; | |
| 676 | try renderExpression(r, lhs, .none); | |
| 677 | try renderToken(r, dot_token, .none); | |
| 678 | return renderToken(r, question_mark, space); | |
| 706 | 679 | }, |
| 707 | 680 | |
| 708 | 681 | .@"break", .@"continue" => { |
| 709 | const main_token = main_tokens[node]; | |
| 710 | const label_token = datas[node].lhs; | |
| 711 | const target = datas[node].rhs; | |
| 712 | if (label_token == 0 and target == 0) { | |
| 682 | const main_token = tree.nodeMainToken(node); | |
| 683 | const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node; | |
| 684 | if (opt_label_token == .none and opt_target == .none) { | |
| 713 | 685 | try renderToken(r, main_token, space); // break/continue |
| 714 | } else if (label_token == 0 and target != 0) { | |
| 686 | } else if (opt_label_token == .none and opt_target != .none) { | |
| 687 | const target = opt_target.unwrap().?; | |
| 715 | 688 | try renderToken(r, main_token, .space); // break/continue |
| 716 | 689 | try renderExpression(r, target, space); |
| 717 | } else if (label_token != 0 and target == 0) { | |
| 690 | } else if (opt_label_token != .none and opt_target == .none) { | |
| 691 | const label_token = opt_label_token.unwrap().?; | |
| 718 | 692 | try renderToken(r, main_token, .space); // break/continue |
| 719 | 693 | try renderToken(r, label_token - 1, .none); // : |
| 720 | 694 | try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier |
| 721 | } else if (label_token != 0 and target != 0) { | |
| 695 | } else if (opt_label_token != .none and opt_target != .none) { | |
| 696 | const label_token = opt_label_token.unwrap().?; | |
| 697 | const target = opt_target.unwrap().?; | |
| 722 | 698 | try renderToken(r, main_token, .space); // break/continue |
| 723 | 699 | try renderToken(r, label_token - 1, .none); // : |
| 724 | 700 | try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier |
| 725 | 701 | try renderExpression(r, target, space); |
| 726 | } | |
| 702 | } else unreachable; | |
| 727 | 703 | }, |
| 728 | 704 | |
| 729 | 705 | .@"return" => { |
| 730 | if (datas[node].lhs != 0) { | |
| 731 | try renderToken(r, main_tokens[node], .space); | |
| 732 | try renderExpression(r, datas[node].lhs, space); | |
| 706 | if (tree.nodeData(node).opt_node.unwrap()) |expr| { | |
| 707 | try renderToken(r, tree.nodeMainToken(node), .space); | |
| 708 | try renderExpression(r, expr, space); | |
| 733 | 709 | } else { |
| 734 | try renderToken(r, main_tokens[node], space); | |
| 710 | try renderToken(r, tree.nodeMainToken(node), space); | |
| 735 | 711 | } |
| 736 | 712 | }, |
| 737 | 713 | |
| 738 | 714 | .grouped_expression => { |
| 715 | const expr, const rparen = tree.nodeData(node).node_and_token; | |
| 739 | 716 | try ais.pushIndent(.normal); |
| 740 | try renderToken(r, main_tokens[node], .none); // lparen | |
| 741 | try renderExpression(r, datas[node].lhs, .none); | |
| 717 | try renderToken(r, tree.nodeMainToken(node), .none); // lparen | |
| 718 | try renderExpression(r, expr, .none); | |
| 742 | 719 | ais.popIndent(); |
| 743 | return renderToken(r, datas[node].rhs, space); // rparen | |
| 720 | return renderToken(r, rparen, space); | |
| 744 | 721 | }, |
| 745 | 722 | |
| 746 | 723 | .container_decl, |
| ... | ... | @@ -761,9 +738,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 761 | 738 | }, |
| 762 | 739 | |
| 763 | 740 | .error_set_decl => { |
| 764 | const error_token = main_tokens[node]; | |
| 765 | const lbrace = error_token + 1; | |
| 766 | const rbrace = datas[node].rhs; | |
| 741 | const error_token = tree.nodeMainToken(node); | |
| 742 | const lbrace, const rbrace = tree.nodeData(node).token_and_token; | |
| 767 | 743 | |
| 768 | 744 | try renderToken(r, error_token, .none); |
| 769 | 745 | |
| ... | ... | @@ -771,20 +747,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 771 | 747 | // There is nothing between the braces so render condensed: `error{}` |
| 772 | 748 | try renderToken(r, lbrace, .none); |
| 773 | 749 | return renderToken(r, rbrace, space); |
| 774 | } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) { | |
| 750 | } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) { | |
| 775 | 751 | // There is exactly one member and no trailing comma or |
| 776 | 752 | // comments, so render without surrounding spaces: `error{Foo}` |
| 777 | 753 | try renderToken(r, lbrace, .none); |
| 778 | 754 | try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier |
| 779 | 755 | return renderToken(r, rbrace, space); |
| 780 | } else if (token_tags[rbrace - 1] == .comma) { | |
| 756 | } else if (tree.tokenTag(rbrace - 1) == .comma) { | |
| 781 | 757 | // There is a trailing comma so render each member on a new line. |
| 782 | 758 | try ais.pushIndent(.normal); |
| 783 | 759 | try renderToken(r, lbrace, .newline); |
| 784 | 760 | var i = lbrace + 1; |
| 785 | 761 | while (i < rbrace) : (i += 1) { |
| 786 | 762 | if (i > lbrace + 1) try renderExtraNewlineToken(r, i); |
| 787 | switch (token_tags[i]) { | |
| 763 | switch (tree.tokenTag(i)) { | |
| 788 | 764 | .doc_comment => try renderToken(r, i, .newline), |
| 789 | 765 | .identifier => { |
| 790 | 766 | try ais.pushSpace(.comma); |
| ... | ... | @@ -802,7 +778,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 802 | 778 | try renderToken(r, lbrace, .space); |
| 803 | 779 | var i = lbrace + 1; |
| 804 | 780 | while (i < rbrace) : (i += 1) { |
| 805 | switch (token_tags[i]) { | |
| 781 | switch (tree.tokenTag(i)) { | |
| 806 | 782 | .doc_comment => unreachable, // TODO |
| 807 | 783 | .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote), |
| 808 | 784 | .comma => {}, |
| ... | ... | @@ -813,18 +789,14 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 813 | 789 | } |
| 814 | 790 | }, |
| 815 | 791 | |
| 816 | .builtin_call_two, .builtin_call_two_comma => { | |
| 817 | if (datas[node].lhs == 0) { | |
| 818 | return renderBuiltinCall(r, main_tokens[node], &.{}, space); | |
| 819 | } else if (datas[node].rhs == 0) { | |
| 820 | return renderBuiltinCall(r, main_tokens[node], &.{datas[node].lhs}, space); | |
| 821 | } else { | |
| 822 | return renderBuiltinCall(r, main_tokens[node], &.{ datas[node].lhs, datas[node].rhs }, space); | |
| 823 | } | |
| 824 | }, | |
| 825 | .builtin_call, .builtin_call_comma => { | |
| 826 | const params = tree.extra_data[datas[node].lhs..datas[node].rhs]; | |
| 827 | return renderBuiltinCall(r, main_tokens[node], params, space); | |
| 792 | .builtin_call_two, | |
| 793 | .builtin_call_two_comma, | |
| 794 | .builtin_call, | |
| 795 | .builtin_call_comma, | |
| 796 | => { | |
| 797 | var buf: [2]Ast.Node.Index = undefined; | |
| 798 | const params = tree.builtinCallParams(&buf, node).?; | |
| 799 | return renderBuiltinCall(r, tree.nodeMainToken(node), params, space); | |
| 828 | 800 | }, |
| 829 | 801 | |
| 830 | 802 | .fn_proto_simple, |
| ... | ... | @@ -837,14 +809,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 837 | 809 | }, |
| 838 | 810 | |
| 839 | 811 | .anyframe_type => { |
| 840 | const main_token = main_tokens[node]; | |
| 841 | if (datas[node].rhs != 0) { | |
| 842 | try renderToken(r, main_token, .none); // anyframe | |
| 843 | try renderToken(r, main_token + 1, .none); // -> | |
| 844 | return renderExpression(r, datas[node].rhs, space); | |
| 845 | } else { | |
| 846 | return renderToken(r, main_token, space); // anyframe | |
| 847 | } | |
| 812 | const main_token = tree.nodeMainToken(node); | |
| 813 | try renderToken(r, main_token, .none); // anyframe | |
| 814 | try renderToken(r, main_token + 1, .none); // -> | |
| 815 | return renderExpression(r, tree.nodeData(node).token_and_node[1], space); | |
| 848 | 816 | }, |
| 849 | 817 | |
| 850 | 818 | .@"switch", |
| ... | ... | @@ -901,8 +869,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 901 | 869 | => return renderAsm(r, tree.fullAsm(node).?, space), |
| 902 | 870 | |
| 903 | 871 | .enum_literal => { |
| 904 | try renderToken(r, main_tokens[node] - 1, .none); // . | |
| 905 | return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name | |
| 872 | try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . | |
| 873 | return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name | |
| 906 | 874 | }, |
| 907 | 875 | |
| 908 | 876 | .fn_decl => unreachable, |
| ... | ... | @@ -944,9 +912,9 @@ fn renderArrayType( |
| 944 | 912 | try ais.pushIndent(.normal); |
| 945 | 913 | try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket |
| 946 | 914 | try renderExpression(r, array_type.ast.elem_count, inner_space); |
| 947 | if (array_type.ast.sentinel != 0) { | |
| 948 | try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon | |
| 949 | try renderExpression(r, array_type.ast.sentinel, inner_space); | |
| 915 | if (array_type.ast.sentinel.unwrap()) |sentinel| { | |
| 916 | try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon | |
| 917 | try renderExpression(r, sentinel, inner_space); | |
| 950 | 918 | } |
| 951 | 919 | ais.popIndent(); |
| 952 | 920 | try renderToken(r, rbracket, .none); // rbracket |
| ... | ... | @@ -955,6 +923,7 @@ fn renderArrayType( |
| 955 | 923 | |
| 956 | 924 | fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void { |
| 957 | 925 | const tree = r.tree; |
| 926 | const main_token = ptr_type.ast.main_token; | |
| 958 | 927 | switch (ptr_type.size) { |
| 959 | 928 | .one => { |
| 960 | 929 | // Since ** tokens exist and the same token is shared by two |
| ... | ... | @@ -962,41 +931,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi |
| 962 | 931 | // in such a relationship. If so, skip rendering anything for |
| 963 | 932 | // this pointer type and rely on the child to render our asterisk |
| 964 | 933 | // as well when it renders the ** token. |
| 965 | if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and | |
| 966 | ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type]) | |
| 934 | if (tree.tokenTag(main_token) == .asterisk_asterisk and | |
| 935 | main_token == tree.nodeMainToken(ptr_type.ast.child_type)) | |
| 967 | 936 | { |
| 968 | 937 | return renderExpression(r, ptr_type.ast.child_type, space); |
| 969 | 938 | } |
| 970 | try renderToken(r, ptr_type.ast.main_token, .none); // asterisk | |
| 939 | try renderToken(r, main_token, .none); // asterisk | |
| 971 | 940 | }, |
| 972 | 941 | .many => { |
| 973 | if (ptr_type.ast.sentinel == 0) { | |
| 974 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 975 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 976 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket | |
| 942 | if (ptr_type.ast.sentinel.unwrap()) |sentinel| { | |
| 943 | try renderToken(r, main_token, .none); // lbracket | |
| 944 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 945 | try renderToken(r, main_token + 2, .none); // colon | |
| 946 | try renderExpression(r, sentinel, .none); | |
| 947 | try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket | |
| 977 | 948 | } else { |
| 978 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 979 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 980 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon | |
| 981 | try renderExpression(r, ptr_type.ast.sentinel, .none); | |
| 982 | try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket | |
| 949 | try renderToken(r, main_token, .none); // lbracket | |
| 950 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 951 | try renderToken(r, main_token + 2, .none); // rbracket | |
| 983 | 952 | } |
| 984 | 953 | }, |
| 985 | 954 | .c => { |
| 986 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 987 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 988 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // c | |
| 989 | try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket | |
| 955 | try renderToken(r, main_token, .none); // lbracket | |
| 956 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 957 | try renderToken(r, main_token + 2, .none); // c | |
| 958 | try renderToken(r, main_token + 3, .none); // rbracket | |
| 990 | 959 | }, |
| 991 | 960 | .slice => { |
| 992 | if (ptr_type.ast.sentinel == 0) { | |
| 993 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 994 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket | |
| 961 | if (ptr_type.ast.sentinel.unwrap()) |sentinel| { | |
| 962 | try renderToken(r, main_token, .none); // lbracket | |
| 963 | try renderToken(r, main_token + 1, .none); // colon | |
| 964 | try renderExpression(r, sentinel, .none); | |
| 965 | try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket | |
| 995 | 966 | } else { |
| 996 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 997 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon | |
| 998 | try renderExpression(r, ptr_type.ast.sentinel, .none); | |
| 999 | try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket | |
| 967 | try renderToken(r, main_token, .none); // lbracket | |
| 968 | try renderToken(r, main_token + 1, .none); // rbracket | |
| 1000 | 969 | } |
| 1001 | 970 | }, |
| 1002 | 971 | } |
| ... | ... | @@ -1005,29 +974,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi |
| 1005 | 974 | try renderToken(r, allowzero_token, .space); |
| 1006 | 975 | } |
| 1007 | 976 | |
| 1008 | if (ptr_type.ast.align_node != 0) { | |
| 1009 | const align_first = tree.firstToken(ptr_type.ast.align_node); | |
| 977 | if (ptr_type.ast.align_node.unwrap()) |align_node| { | |
| 978 | const align_first = tree.firstToken(align_node); | |
| 1010 | 979 | try renderToken(r, align_first - 2, .none); // align |
| 1011 | 980 | try renderToken(r, align_first - 1, .none); // lparen |
| 1012 | try renderExpression(r, ptr_type.ast.align_node, .none); | |
| 1013 | if (ptr_type.ast.bit_range_start != 0) { | |
| 1014 | assert(ptr_type.ast.bit_range_end != 0); | |
| 1015 | try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon | |
| 1016 | try renderExpression(r, ptr_type.ast.bit_range_start, .none); | |
| 1017 | try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon | |
| 1018 | try renderExpression(r, ptr_type.ast.bit_range_end, .none); | |
| 1019 | try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen | |
| 981 | try renderExpression(r, align_node, .none); | |
| 982 | if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 983 | const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?; | |
| 984 | try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon | |
| 985 | try renderExpression(r, bit_range_start, .none); | |
| 986 | try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon | |
| 987 | try renderExpression(r, bit_range_end, .none); | |
| 988 | try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen | |
| 1020 | 989 | } else { |
| 1021 | try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen | |
| 990 | try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen | |
| 1022 | 991 | } |
| 1023 | 992 | } |
| 1024 | 993 | |
| 1025 | if (ptr_type.ast.addrspace_node != 0) { | |
| 1026 | const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node); | |
| 994 | if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 995 | const addrspace_first = tree.firstToken(addrspace_node); | |
| 1027 | 996 | try renderToken(r, addrspace_first - 2, .none); // addrspace |
| 1028 | 997 | try renderToken(r, addrspace_first - 1, .none); // lparen |
| 1029 | try renderExpression(r, ptr_type.ast.addrspace_node, .none); | |
| 1030 | try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen | |
| 998 | try renderExpression(r, addrspace_node, .none); | |
| 999 | try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen | |
| 1031 | 1000 | } |
| 1032 | 1001 | |
| 1033 | 1002 | if (ptr_type.const_token) |const_token| { |
| ... | ... | @@ -1048,13 +1017,12 @@ fn renderSlice( |
| 1048 | 1017 | space: Space, |
| 1049 | 1018 | ) Error!void { |
| 1050 | 1019 | const tree = r.tree; |
| 1051 | const node_tags = tree.nodes.items(.tag); | |
| 1052 | const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or | |
| 1053 | if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false; | |
| 1020 | const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or | |
| 1021 | if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false; | |
| 1054 | 1022 | const after_start_space = if (after_start_space_bool) Space.space else Space.none; |
| 1055 | const after_dots_space = if (slice.ast.end != 0) | |
| 1023 | const after_dots_space = if (slice.ast.end != .none) | |
| 1056 | 1024 | after_start_space |
| 1057 | else if (slice.ast.sentinel != 0) Space.space else Space.none; | |
| 1025 | else if (slice.ast.sentinel != .none) Space.space else Space.none; | |
| 1058 | 1026 | |
| 1059 | 1027 | try renderExpression(r, slice.ast.sliced, .none); |
| 1060 | 1028 | try renderToken(r, slice.ast.lbracket, .none); // lbracket |
| ... | ... | @@ -1063,14 +1031,14 @@ fn renderSlice( |
| 1063 | 1031 | try renderExpression(r, slice.ast.start, after_start_space); |
| 1064 | 1032 | try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..") |
| 1065 | 1033 | |
| 1066 | if (slice.ast.end != 0) { | |
| 1067 | const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none; | |
| 1068 | try renderExpression(r, slice.ast.end, after_end_space); | |
| 1034 | if (slice.ast.end.unwrap()) |end| { | |
| 1035 | const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none; | |
| 1036 | try renderExpression(r, end, after_end_space); | |
| 1069 | 1037 | } |
| 1070 | 1038 | |
| 1071 | if (slice.ast.sentinel != 0) { | |
| 1072 | try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon | |
| 1073 | try renderExpression(r, slice.ast.sentinel, .none); | |
| 1039 | if (slice.ast.sentinel.unwrap()) |sentinel| { | |
| 1040 | try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon | |
| 1041 | try renderExpression(r, sentinel, .none); | |
| 1074 | 1042 | } |
| 1075 | 1043 | |
| 1076 | 1044 | try renderToken(r, tree.lastToken(slice_node), space); // rbracket |
| ... | ... | @@ -1082,12 +1050,8 @@ fn renderAsmOutput( |
| 1082 | 1050 | space: Space, |
| 1083 | 1051 | ) Error!void { |
| 1084 | 1052 | const tree = r.tree; |
| 1085 | const token_tags = tree.tokens.items(.tag); | |
| 1086 | const node_tags = tree.nodes.items(.tag); | |
| 1087 | const main_tokens = tree.nodes.items(.main_token); | |
| 1088 | const datas = tree.nodes.items(.data); | |
| 1089 | assert(node_tags[asm_output] == .asm_output); | |
| 1090 | const symbolic_name = main_tokens[asm_output]; | |
| 1053 | assert(tree.nodeTag(asm_output) == .asm_output); | |
| 1054 | const symbolic_name = tree.nodeMainToken(asm_output); | |
| 1091 | 1055 | |
| 1092 | 1056 | try renderToken(r, symbolic_name - 1, .none); // lbracket |
| 1093 | 1057 | try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident |
| ... | ... | @@ -1095,10 +1059,11 @@ fn renderAsmOutput( |
| 1095 | 1059 | try renderToken(r, symbolic_name + 2, .space); // "constraint" |
| 1096 | 1060 | try renderToken(r, symbolic_name + 3, .none); // lparen |
| 1097 | 1061 | |
| 1098 | if (token_tags[symbolic_name + 4] == .arrow) { | |
| 1062 | if (tree.tokenTag(symbolic_name + 4) == .arrow) { | |
| 1063 | const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token; | |
| 1099 | 1064 | try renderToken(r, symbolic_name + 4, .space); // -> |
| 1100 | try renderExpression(r, datas[asm_output].lhs, Space.none); | |
| 1101 | return renderToken(r, datas[asm_output].rhs, space); // rparen | |
| 1065 | try renderExpression(r, type_expr.unwrap().?, Space.none); | |
| 1066 | return renderToken(r, rparen, space); | |
| 1102 | 1067 | } else { |
| 1103 | 1068 | try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident |
| 1104 | 1069 | return renderToken(r, symbolic_name + 5, space); // rparen |
| ... | ... | @@ -1111,19 +1076,17 @@ fn renderAsmInput( |
| 1111 | 1076 | space: Space, |
| 1112 | 1077 | ) Error!void { |
| 1113 | 1078 | const tree = r.tree; |
| 1114 | const node_tags = tree.nodes.items(.tag); | |
| 1115 | const main_tokens = tree.nodes.items(.main_token); | |
| 1116 | const datas = tree.nodes.items(.data); | |
| 1117 | assert(node_tags[asm_input] == .asm_input); | |
| 1118 | const symbolic_name = main_tokens[asm_input]; | |
| 1079 | assert(tree.nodeTag(asm_input) == .asm_input); | |
| 1080 | const symbolic_name = tree.nodeMainToken(asm_input); | |
| 1081 | const expr, const rparen = tree.nodeData(asm_input).node_and_token; | |
| 1119 | 1082 | |
| 1120 | 1083 | try renderToken(r, symbolic_name - 1, .none); // lbracket |
| 1121 | 1084 | try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident |
| 1122 | 1085 | try renderToken(r, symbolic_name + 1, .space); // rbracket |
| 1123 | 1086 | try renderToken(r, symbolic_name + 2, .space); // "constraint" |
| 1124 | 1087 | try renderToken(r, symbolic_name + 3, .none); // lparen |
| 1125 | try renderExpression(r, datas[asm_input].lhs, Space.none); | |
| 1126 | return renderToken(r, datas[asm_input].rhs, space); // rparen | |
| 1088 | try renderExpression(r, expr, Space.none); | |
| 1089 | return renderToken(r, rparen, space); | |
| 1127 | 1090 | } |
| 1128 | 1091 | |
| 1129 | 1092 | fn renderVarDecl( |
| ... | ... | @@ -1179,15 +1142,15 @@ fn renderVarDeclWithoutFixups( |
| 1179 | 1142 | |
| 1180 | 1143 | try renderToken(r, var_decl.ast.mut_token, .space); // var |
| 1181 | 1144 | |
| 1182 | if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or | |
| 1183 | var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or | |
| 1184 | var_decl.ast.init_node != 0) | |
| 1145 | if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or | |
| 1146 | var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or | |
| 1147 | var_decl.ast.init_node != .none) | |
| 1185 | 1148 | { |
| 1186 | const name_space = if (var_decl.ast.type_node == 0 and | |
| 1187 | (var_decl.ast.align_node != 0 or | |
| 1188 | var_decl.ast.addrspace_node != 0 or | |
| 1189 | var_decl.ast.section_node != 0 or | |
| 1190 | var_decl.ast.init_node != 0)) | |
| 1149 | const name_space = if (var_decl.ast.type_node == .none and | |
| 1150 | (var_decl.ast.align_node != .none or | |
| 1151 | var_decl.ast.addrspace_node != .none or | |
| 1152 | var_decl.ast.section_node != .none or | |
| 1153 | var_decl.ast.init_node != .none)) | |
| 1191 | 1154 | Space.space |
| 1192 | 1155 | else |
| 1193 | 1156 | Space.none; |
| ... | ... | @@ -1197,26 +1160,26 @@ fn renderVarDeclWithoutFixups( |
| 1197 | 1160 | return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name |
| 1198 | 1161 | } |
| 1199 | 1162 | |
| 1200 | if (var_decl.ast.type_node != 0) { | |
| 1163 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 1201 | 1164 | try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // : |
| 1202 | if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or | |
| 1203 | var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) | |
| 1165 | if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or | |
| 1166 | var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) | |
| 1204 | 1167 | { |
| 1205 | try renderExpression(r, var_decl.ast.type_node, .space); | |
| 1168 | try renderExpression(r, type_node, .space); | |
| 1206 | 1169 | } else { |
| 1207 | return renderExpression(r, var_decl.ast.type_node, space); | |
| 1170 | return renderExpression(r, type_node, space); | |
| 1208 | 1171 | } |
| 1209 | 1172 | } |
| 1210 | 1173 | |
| 1211 | if (var_decl.ast.align_node != 0) { | |
| 1212 | const lparen = tree.firstToken(var_decl.ast.align_node) - 1; | |
| 1174 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 1175 | const lparen = tree.firstToken(align_node) - 1; | |
| 1213 | 1176 | const align_kw = lparen - 1; |
| 1214 | const rparen = tree.lastToken(var_decl.ast.align_node) + 1; | |
| 1177 | const rparen = tree.lastToken(align_node) + 1; | |
| 1215 | 1178 | try renderToken(r, align_kw, Space.none); // align |
| 1216 | 1179 | try renderToken(r, lparen, Space.none); // ( |
| 1217 | try renderExpression(r, var_decl.ast.align_node, Space.none); | |
| 1218 | if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or | |
| 1219 | var_decl.ast.init_node != 0) | |
| 1180 | try renderExpression(r, align_node, Space.none); | |
| 1181 | if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or | |
| 1182 | var_decl.ast.init_node != .none) | |
| 1220 | 1183 | { |
| 1221 | 1184 | try renderToken(r, rparen, .space); // ) |
| 1222 | 1185 | } else { |
| ... | ... | @@ -1224,14 +1187,14 @@ fn renderVarDeclWithoutFixups( |
| 1224 | 1187 | } |
| 1225 | 1188 | } |
| 1226 | 1189 | |
| 1227 | if (var_decl.ast.addrspace_node != 0) { | |
| 1228 | const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1; | |
| 1190 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 1191 | const lparen = tree.firstToken(addrspace_node) - 1; | |
| 1229 | 1192 | const addrspace_kw = lparen - 1; |
| 1230 | const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1; | |
| 1193 | const rparen = tree.lastToken(addrspace_node) + 1; | |
| 1231 | 1194 | try renderToken(r, addrspace_kw, Space.none); // addrspace |
| 1232 | 1195 | try renderToken(r, lparen, Space.none); // ( |
| 1233 | try renderExpression(r, var_decl.ast.addrspace_node, Space.none); | |
| 1234 | if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) { | |
| 1196 | try renderExpression(r, addrspace_node, Space.none); | |
| 1197 | if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) { | |
| 1235 | 1198 | try renderToken(r, rparen, .space); // ) |
| 1236 | 1199 | } else { |
| 1237 | 1200 | try renderToken(r, rparen, .none); // ) |
| ... | ... | @@ -1239,27 +1202,27 @@ fn renderVarDeclWithoutFixups( |
| 1239 | 1202 | } |
| 1240 | 1203 | } |
| 1241 | 1204 | |
| 1242 | if (var_decl.ast.section_node != 0) { | |
| 1243 | const lparen = tree.firstToken(var_decl.ast.section_node) - 1; | |
| 1205 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 1206 | const lparen = tree.firstToken(section_node) - 1; | |
| 1244 | 1207 | const section_kw = lparen - 1; |
| 1245 | const rparen = tree.lastToken(var_decl.ast.section_node) + 1; | |
| 1208 | const rparen = tree.lastToken(section_node) + 1; | |
| 1246 | 1209 | try renderToken(r, section_kw, Space.none); // linksection |
| 1247 | 1210 | try renderToken(r, lparen, Space.none); // ( |
| 1248 | try renderExpression(r, var_decl.ast.section_node, Space.none); | |
| 1249 | if (var_decl.ast.init_node != 0) { | |
| 1211 | try renderExpression(r, section_node, Space.none); | |
| 1212 | if (var_decl.ast.init_node != .none) { | |
| 1250 | 1213 | try renderToken(r, rparen, .space); // ) |
| 1251 | 1214 | } else { |
| 1252 | 1215 | return renderToken(r, rparen, space); // ) |
| 1253 | 1216 | } |
| 1254 | 1217 | } |
| 1255 | 1218 | |
| 1256 | assert(var_decl.ast.init_node != 0); | |
| 1219 | const init_node = var_decl.ast.init_node.unwrap().?; | |
| 1257 | 1220 | |
| 1258 | const eq_token = tree.firstToken(var_decl.ast.init_node) - 1; | |
| 1221 | const eq_token = tree.firstToken(init_node) - 1; | |
| 1259 | 1222 | const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline; |
| 1260 | 1223 | try ais.pushIndent(.after_equals); |
| 1261 | 1224 | try renderToken(r, eq_token, eq_space); // = |
| 1262 | try renderExpression(r, var_decl.ast.init_node, space); // ; | |
| 1225 | try renderExpression(r, init_node, space); // ; | |
| 1263 | 1226 | ais.popIndent(); |
| 1264 | 1227 | } |
| 1265 | 1228 | |
| ... | ... | @@ -1268,7 +1231,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void { |
| 1268 | 1231 | .ast = .{ |
| 1269 | 1232 | .while_token = if_node.ast.if_token, |
| 1270 | 1233 | .cond_expr = if_node.ast.cond_expr, |
| 1271 | .cont_expr = 0, | |
| 1234 | .cont_expr = .none, | |
| 1272 | 1235 | .then_expr = if_node.ast.then_expr, |
| 1273 | 1236 | .else_expr = if_node.ast.else_expr, |
| 1274 | 1237 | }, |
| ... | ... | @@ -1284,7 +1247,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void { |
| 1284 | 1247 | /// respective values set to null. |
| 1285 | 1248 | fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void { |
| 1286 | 1249 | const tree = r.tree; |
| 1287 | const token_tags = tree.tokens.items(.tag); | |
| 1288 | 1250 | |
| 1289 | 1251 | if (while_node.label_token) |label| { |
| 1290 | 1252 | try renderIdentifier(r, label, .none, .eagerly_unquote); // label |
| ... | ... | @@ -1305,7 +1267,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1305 | 1267 | try renderToken(r, last_prefix_token, .space); |
| 1306 | 1268 | try renderToken(r, payload_token - 1, .none); // | |
| 1307 | 1269 | const ident = blk: { |
| 1308 | if (token_tags[payload_token] == .asterisk) { | |
| 1270 | if (tree.tokenTag(payload_token) == .asterisk) { | |
| 1309 | 1271 | try renderToken(r, payload_token, .none); // * |
| 1310 | 1272 | break :blk payload_token + 1; |
| 1311 | 1273 | } else { |
| ... | ... | @@ -1314,7 +1276,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1314 | 1276 | }; |
| 1315 | 1277 | try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier |
| 1316 | 1278 | const pipe = blk: { |
| 1317 | if (token_tags[ident + 1] == .comma) { | |
| 1279 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 1318 | 1280 | try renderToken(r, ident + 1, .space); // , |
| 1319 | 1281 | try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index |
| 1320 | 1282 | break :blk ident + 3; |
| ... | ... | @@ -1325,13 +1287,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1325 | 1287 | last_prefix_token = pipe; |
| 1326 | 1288 | } |
| 1327 | 1289 | |
| 1328 | if (while_node.ast.cont_expr != 0) { | |
| 1290 | if (while_node.ast.cont_expr.unwrap()) |cont_expr| { | |
| 1329 | 1291 | try renderToken(r, last_prefix_token, .space); |
| 1330 | const lparen = tree.firstToken(while_node.ast.cont_expr) - 1; | |
| 1292 | const lparen = tree.firstToken(cont_expr) - 1; | |
| 1331 | 1293 | try renderToken(r, lparen - 1, .space); // : |
| 1332 | 1294 | try renderToken(r, lparen, .none); // lparen |
| 1333 | try renderExpression(r, while_node.ast.cont_expr, .none); | |
| 1334 | last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen | |
| 1295 | try renderExpression(r, cont_expr, .none); | |
| 1296 | last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen | |
| 1335 | 1297 | } |
| 1336 | 1298 | |
| 1337 | 1299 | try renderThenElse( |
| ... | ... | @@ -1349,15 +1311,14 @@ fn renderThenElse( |
| 1349 | 1311 | r: *Render, |
| 1350 | 1312 | last_prefix_token: Ast.TokenIndex, |
| 1351 | 1313 | then_expr: Ast.Node.Index, |
| 1352 | else_token: Ast.TokenIndex, | |
| 1314 | else_token: ?Ast.TokenIndex, | |
| 1353 | 1315 | maybe_error_token: ?Ast.TokenIndex, |
| 1354 | else_expr: Ast.Node.Index, | |
| 1316 | opt_else_expr: Ast.Node.OptionalIndex, | |
| 1355 | 1317 | space: Space, |
| 1356 | 1318 | ) Error!void { |
| 1357 | 1319 | const tree = r.tree; |
| 1358 | 1320 | const ais = r.ais; |
| 1359 | const node_tags = tree.nodes.items(.tag); | |
| 1360 | const then_expr_is_block = nodeIsBlock(node_tags[then_expr]); | |
| 1321 | const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr)); | |
| 1361 | 1322 | const indent_then_expr = !then_expr_is_block and |
| 1362 | 1323 | !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr)); |
| 1363 | 1324 | |
| ... | ... | @@ -1373,7 +1334,7 @@ fn renderThenElse( |
| 1373 | 1334 | try renderToken(r, last_prefix_token, .space); |
| 1374 | 1335 | } |
| 1375 | 1336 | |
| 1376 | if (else_expr != 0) { | |
| 1337 | if (opt_else_expr.unwrap()) |else_expr| { | |
| 1377 | 1338 | if (indent_then_expr) { |
| 1378 | 1339 | try renderExpression(r, then_expr, .newline); |
| 1379 | 1340 | } else { |
| ... | ... | @@ -1382,18 +1343,18 @@ fn renderThenElse( |
| 1382 | 1343 | |
| 1383 | 1344 | if (indent_then_expr) ais.popIndent(); |
| 1384 | 1345 | |
| 1385 | var last_else_token = else_token; | |
| 1346 | var last_else_token = else_token.?; | |
| 1386 | 1347 | |
| 1387 | 1348 | if (maybe_error_token) |error_token| { |
| 1388 | try renderToken(r, else_token, .space); // else | |
| 1349 | try renderToken(r, last_else_token, .space); // else | |
| 1389 | 1350 | try renderToken(r, error_token - 1, .none); // | |
| 1390 | 1351 | try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier |
| 1391 | 1352 | last_else_token = error_token + 1; // | |
| 1392 | 1353 | } |
| 1393 | 1354 | |
| 1394 | 1355 | const indent_else_expr = indent_then_expr and |
| 1395 | !nodeIsBlock(node_tags[else_expr]) and | |
| 1396 | !nodeIsIfForWhileSwitch(node_tags[else_expr]); | |
| 1356 | !nodeIsBlock(tree.nodeTag(else_expr)) and | |
| 1357 | !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr)); | |
| 1397 | 1358 | if (indent_else_expr) { |
| 1398 | 1359 | try ais.pushIndent(.normal); |
| 1399 | 1360 | try renderToken(r, last_else_token, .newline); |
| ... | ... | @@ -1430,21 +1391,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void { |
| 1430 | 1391 | |
| 1431 | 1392 | var cur = for_node.payload_token; |
| 1432 | 1393 | const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?; |
| 1433 | if (token_tags[pipe - 1] == .comma) { | |
| 1394 | if (tree.tokenTag(@intCast(pipe - 1)) == .comma) { | |
| 1434 | 1395 | try ais.pushIndent(.normal); |
| 1435 | 1396 | try renderToken(r, cur - 1, .newline); // | |
| 1436 | 1397 | while (true) { |
| 1437 | if (token_tags[cur] == .asterisk) { | |
| 1398 | if (tree.tokenTag(cur) == .asterisk) { | |
| 1438 | 1399 | try renderToken(r, cur, .none); // * |
| 1439 | 1400 | cur += 1; |
| 1440 | 1401 | } |
| 1441 | 1402 | try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier |
| 1442 | 1403 | cur += 1; |
| 1443 | if (token_tags[cur] == .comma) { | |
| 1404 | if (tree.tokenTag(cur) == .comma) { | |
| 1444 | 1405 | try renderToken(r, cur, .newline); // , |
| 1445 | 1406 | cur += 1; |
| 1446 | 1407 | } |
| 1447 | if (token_tags[cur] == .pipe) { | |
| 1408 | if (tree.tokenTag(cur) == .pipe) { | |
| 1448 | 1409 | break; |
| 1449 | 1410 | } |
| 1450 | 1411 | } |
| ... | ... | @@ -1452,17 +1413,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void { |
| 1452 | 1413 | } else { |
| 1453 | 1414 | try renderToken(r, cur - 1, .none); // | |
| 1454 | 1415 | while (true) { |
| 1455 | if (token_tags[cur] == .asterisk) { | |
| 1416 | if (tree.tokenTag(cur) == .asterisk) { | |
| 1456 | 1417 | try renderToken(r, cur, .none); // * |
| 1457 | 1418 | cur += 1; |
| 1458 | 1419 | } |
| 1459 | 1420 | try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier |
| 1460 | 1421 | cur += 1; |
| 1461 | if (token_tags[cur] == .comma) { | |
| 1422 | if (tree.tokenTag(cur) == .comma) { | |
| 1462 | 1423 | try renderToken(r, cur, .space); // , |
| 1463 | 1424 | cur += 1; |
| 1464 | 1425 | } |
| 1465 | if (token_tags[cur] == .pipe) { | |
| 1426 | if (tree.tokenTag(cur) == .pipe) { | |
| 1466 | 1427 | break; |
| 1467 | 1428 | } |
| 1468 | 1429 | } |
| ... | ... | @@ -1488,7 +1449,7 @@ fn renderContainerField( |
| 1488 | 1449 | const tree = r.tree; |
| 1489 | 1450 | const ais = r.ais; |
| 1490 | 1451 | var field = field_param; |
| 1491 | if (container != .tuple) field.convertToNonTupleLike(tree.nodes); | |
| 1452 | if (container != .tuple) field.convertToNonTupleLike(&tree); | |
| 1492 | 1453 | const quote: QuoteBehavior = switch (container) { |
| 1493 | 1454 | .@"enum" => .eagerly_unquote_except_underscore, |
| 1494 | 1455 | .tuple, .other => .eagerly_unquote, |
| ... | ... | @@ -1497,67 +1458,74 @@ fn renderContainerField( |
| 1497 | 1458 | if (field.comptime_token) |t| { |
| 1498 | 1459 | try renderToken(r, t, .space); // comptime |
| 1499 | 1460 | } |
| 1500 | if (field.ast.type_expr == 0 and field.ast.value_expr == 0) { | |
| 1501 | if (field.ast.align_expr != 0) { | |
| 1461 | if (field.ast.type_expr == .none and field.ast.value_expr == .none) { | |
| 1462 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1502 | 1463 | try renderIdentifier(r, field.ast.main_token, .space, quote); // name |
| 1503 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1464 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1504 | 1465 | const align_kw = lparen_token - 1; |
| 1505 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1466 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1506 | 1467 | try renderToken(r, align_kw, .none); // align |
| 1507 | 1468 | try renderToken(r, lparen_token, .none); // ( |
| 1508 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1469 | try renderExpression(r, align_expr, .none); // alignment | |
| 1509 | 1470 | return renderToken(r, rparen_token, .space); // ) |
| 1510 | 1471 | } |
| 1511 | 1472 | return renderIdentifierComma(r, field.ast.main_token, space, quote); // name |
| 1512 | 1473 | } |
| 1513 | if (field.ast.type_expr != 0 and field.ast.value_expr == 0) { | |
| 1474 | if (field.ast.type_expr != .none and field.ast.value_expr == .none) { | |
| 1475 | const type_expr = field.ast.type_expr.unwrap().?; | |
| 1514 | 1476 | if (!field.ast.tuple_like) { |
| 1515 | 1477 | try renderIdentifier(r, field.ast.main_token, .none, quote); // name |
| 1516 | 1478 | try renderToken(r, field.ast.main_token + 1, .space); // : |
| 1517 | 1479 | } |
| 1518 | 1480 | |
| 1519 | if (field.ast.align_expr != 0) { | |
| 1520 | try renderExpression(r, field.ast.type_expr, .space); // type | |
| 1521 | const align_token = tree.firstToken(field.ast.align_expr) - 2; | |
| 1481 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1482 | try renderExpression(r, type_expr, .space); // type | |
| 1483 | const align_token = tree.firstToken(align_expr) - 2; | |
| 1522 | 1484 | try renderToken(r, align_token, .none); // align |
| 1523 | 1485 | try renderToken(r, align_token + 1, .none); // ( |
| 1524 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1525 | const rparen = tree.lastToken(field.ast.align_expr) + 1; | |
| 1486 | try renderExpression(r, align_expr, .none); // alignment | |
| 1487 | const rparen = tree.lastToken(align_expr) + 1; | |
| 1526 | 1488 | return renderTokenComma(r, rparen, space); // ) |
| 1527 | 1489 | } else { |
| 1528 | return renderExpressionComma(r, field.ast.type_expr, space); // type | |
| 1490 | return renderExpressionComma(r, type_expr, space); // type | |
| 1529 | 1491 | } |
| 1530 | 1492 | } |
| 1531 | if (field.ast.type_expr == 0 and field.ast.value_expr != 0) { | |
| 1493 | if (field.ast.type_expr == .none and field.ast.value_expr != .none) { | |
| 1494 | const value_expr = field.ast.value_expr.unwrap().?; | |
| 1495 | ||
| 1532 | 1496 | try renderIdentifier(r, field.ast.main_token, .space, quote); // name |
| 1533 | if (field.ast.align_expr != 0) { | |
| 1534 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1497 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1498 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1535 | 1499 | const align_kw = lparen_token - 1; |
| 1536 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1500 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1537 | 1501 | try renderToken(r, align_kw, .none); // align |
| 1538 | 1502 | try renderToken(r, lparen_token, .none); // ( |
| 1539 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1503 | try renderExpression(r, align_expr, .none); // alignment | |
| 1540 | 1504 | try renderToken(r, rparen_token, .space); // ) |
| 1541 | 1505 | } |
| 1542 | 1506 | try renderToken(r, field.ast.main_token + 1, .space); // = |
| 1543 | return renderExpressionComma(r, field.ast.value_expr, space); // value | |
| 1507 | return renderExpressionComma(r, value_expr, space); // value | |
| 1544 | 1508 | } |
| 1545 | 1509 | if (!field.ast.tuple_like) { |
| 1546 | 1510 | try renderIdentifier(r, field.ast.main_token, .none, quote); // name |
| 1547 | 1511 | try renderToken(r, field.ast.main_token + 1, .space); // : |
| 1548 | 1512 | } |
| 1549 | try renderExpression(r, field.ast.type_expr, .space); // type | |
| 1550 | 1513 | |
| 1551 | if (field.ast.align_expr != 0) { | |
| 1552 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1514 | const type_expr = field.ast.type_expr.unwrap().?; | |
| 1515 | const value_expr = field.ast.value_expr.unwrap().?; | |
| 1516 | ||
| 1517 | try renderExpression(r, type_expr, .space); // type | |
| 1518 | ||
| 1519 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1520 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1553 | 1521 | const align_kw = lparen_token - 1; |
| 1554 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1522 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1555 | 1523 | try renderToken(r, align_kw, .none); // align |
| 1556 | 1524 | try renderToken(r, lparen_token, .none); // ( |
| 1557 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1525 | try renderExpression(r, align_expr, .none); // alignment | |
| 1558 | 1526 | try renderToken(r, rparen_token, .space); // ) |
| 1559 | 1527 | } |
| 1560 | const eq_token = tree.firstToken(field.ast.value_expr) - 1; | |
| 1528 | const eq_token = tree.firstToken(value_expr) - 1; | |
| 1561 | 1529 | const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline; |
| 1562 | 1530 | |
| 1563 | 1531 | try ais.pushIndent(.after_equals); |
| ... | ... | @@ -1565,19 +1533,18 @@ fn renderContainerField( |
| 1565 | 1533 | |
| 1566 | 1534 | if (eq_space == .space) { |
| 1567 | 1535 | ais.popIndent(); |
| 1568 | try renderExpressionComma(r, field.ast.value_expr, space); // value | |
| 1536 | try renderExpressionComma(r, value_expr, space); // value | |
| 1569 | 1537 | return; |
| 1570 | 1538 | } |
| 1571 | 1539 | |
| 1572 | const token_tags = tree.tokens.items(.tag); | |
| 1573 | const maybe_comma = tree.lastToken(field.ast.value_expr) + 1; | |
| 1540 | const maybe_comma = tree.lastToken(value_expr) + 1; | |
| 1574 | 1541 | |
| 1575 | if (token_tags[maybe_comma] == .comma) { | |
| 1576 | try renderExpression(r, field.ast.value_expr, .none); // value | |
| 1542 | if (tree.tokenTag(maybe_comma) == .comma) { | |
| 1543 | try renderExpression(r, value_expr, .none); // value | |
| 1577 | 1544 | ais.popIndent(); |
| 1578 | 1545 | try renderToken(r, maybe_comma, .newline); |
| 1579 | 1546 | } else { |
| 1580 | try renderExpression(r, field.ast.value_expr, space); // value | |
| 1547 | try renderExpression(r, value_expr, space); // value | |
| 1581 | 1548 | ais.popIndent(); |
| 1582 | 1549 | } |
| 1583 | 1550 | } |
| ... | ... | @@ -1590,8 +1557,6 @@ fn renderBuiltinCall( |
| 1590 | 1557 | ) Error!void { |
| 1591 | 1558 | const tree = r.tree; |
| 1592 | 1559 | const ais = r.ais; |
| 1593 | const token_tags = tree.tokens.items(.tag); | |
| 1594 | const main_tokens = tree.nodes.items(.main_token); | |
| 1595 | 1560 | |
| 1596 | 1561 | try renderToken(r, builtin_token, .none); // @name |
| 1597 | 1562 | |
| ... | ... | @@ -1604,8 +1569,8 @@ fn renderBuiltinCall( |
| 1604 | 1569 | const slice = tree.tokenSlice(builtin_token); |
| 1605 | 1570 | if (mem.eql(u8, slice, "@import")) f: { |
| 1606 | 1571 | const param = params[0]; |
| 1607 | const str_lit_token = main_tokens[param]; | |
| 1608 | assert(token_tags[str_lit_token] == .string_literal); | |
| 1572 | const str_lit_token = tree.nodeMainToken(param); | |
| 1573 | assert(tree.tokenTag(str_lit_token) == .string_literal); | |
| 1609 | 1574 | const token_bytes = tree.tokenSlice(str_lit_token); |
| 1610 | 1575 | const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) { |
| 1611 | 1576 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -1624,13 +1589,13 @@ fn renderBuiltinCall( |
| 1624 | 1589 | const last_param = params[params.len - 1]; |
| 1625 | 1590 | const after_last_param_token = tree.lastToken(last_param) + 1; |
| 1626 | 1591 | |
| 1627 | if (token_tags[after_last_param_token] != .comma) { | |
| 1592 | if (tree.tokenTag(after_last_param_token) != .comma) { | |
| 1628 | 1593 | // Render all on one line, no trailing comma. |
| 1629 | 1594 | try renderToken(r, builtin_token + 1, .none); // ( |
| 1630 | 1595 | |
| 1631 | 1596 | for (params, 0..) |param_node, i| { |
| 1632 | 1597 | const first_param_token = tree.firstToken(param_node); |
| 1633 | if (token_tags[first_param_token] == .multiline_string_literal_line or | |
| 1598 | if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or | |
| 1634 | 1599 | hasSameLineComment(tree, first_param_token - 1)) |
| 1635 | 1600 | { |
| 1636 | 1601 | try ais.pushIndent(.normal); |
| ... | ... | @@ -1665,11 +1630,9 @@ fn renderBuiltinCall( |
| 1665 | 1630 | fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void { |
| 1666 | 1631 | const tree = r.tree; |
| 1667 | 1632 | const ais = r.ais; |
| 1668 | const token_tags = tree.tokens.items(.tag); | |
| 1669 | const token_starts = tree.tokens.items(.start); | |
| 1670 | 1633 | |
| 1671 | 1634 | const after_fn_token = fn_proto.ast.fn_token + 1; |
| 1672 | const lparen = if (token_tags[after_fn_token] == .identifier) blk: { | |
| 1635 | const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: { | |
| 1673 | 1636 | try renderToken(r, fn_proto.ast.fn_token, .space); // fn |
| 1674 | 1637 | try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name |
| 1675 | 1638 | break :blk after_fn_token + 1; |
| ... | ... | @@ -1677,41 +1640,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1677 | 1640 | try renderToken(r, fn_proto.ast.fn_token, .space); // fn |
| 1678 | 1641 | break :blk fn_proto.ast.fn_token + 1; |
| 1679 | 1642 | }; |
| 1680 | assert(token_tags[lparen] == .l_paren); | |
| 1643 | assert(tree.tokenTag(lparen) == .l_paren); | |
| 1681 | 1644 | |
| 1682 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 1645 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 1646 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 1683 | 1647 | const rparen = blk: { |
| 1684 | 1648 | // These may appear in any order, so we have to check the token_starts array |
| 1685 | 1649 | // to find out which is first. |
| 1686 | var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang; | |
| 1687 | var smallest_start = token_starts[maybe_bang]; | |
| 1688 | if (fn_proto.ast.align_expr != 0) { | |
| 1689 | const tok = tree.firstToken(fn_proto.ast.align_expr) - 3; | |
| 1690 | const start = token_starts[tok]; | |
| 1650 | var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang; | |
| 1651 | var smallest_start = tree.tokenStart(maybe_bang); | |
| 1652 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1653 | const tok = tree.firstToken(align_expr) - 3; | |
| 1654 | const start = tree.tokenStart(tok); | |
| 1691 | 1655 | if (start < smallest_start) { |
| 1692 | 1656 | rparen = tok; |
| 1693 | 1657 | smallest_start = start; |
| 1694 | 1658 | } |
| 1695 | 1659 | } |
| 1696 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1697 | const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3; | |
| 1698 | const start = token_starts[tok]; | |
| 1660 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1661 | const tok = tree.firstToken(addrspace_expr) - 3; | |
| 1662 | const start = tree.tokenStart(tok); | |
| 1699 | 1663 | if (start < smallest_start) { |
| 1700 | 1664 | rparen = tok; |
| 1701 | 1665 | smallest_start = start; |
| 1702 | 1666 | } |
| 1703 | 1667 | } |
| 1704 | if (fn_proto.ast.section_expr != 0) { | |
| 1705 | const tok = tree.firstToken(fn_proto.ast.section_expr) - 3; | |
| 1706 | const start = token_starts[tok]; | |
| 1668 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1669 | const tok = tree.firstToken(section_expr) - 3; | |
| 1670 | const start = tree.tokenStart(tok); | |
| 1707 | 1671 | if (start < smallest_start) { |
| 1708 | 1672 | rparen = tok; |
| 1709 | 1673 | smallest_start = start; |
| 1710 | 1674 | } |
| 1711 | 1675 | } |
| 1712 | if (fn_proto.ast.callconv_expr != 0) { | |
| 1713 | const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3; | |
| 1714 | const start = token_starts[tok]; | |
| 1676 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 1677 | const tok = tree.firstToken(callconv_expr) - 3; | |
| 1678 | const start = tree.tokenStart(tok); | |
| 1715 | 1679 | if (start < smallest_start) { |
| 1716 | 1680 | rparen = tok; |
| 1717 | 1681 | smallest_start = start; |
| ... | ... | @@ -1719,11 +1683,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1719 | 1683 | } |
| 1720 | 1684 | break :blk rparen; |
| 1721 | 1685 | }; |
| 1722 | assert(token_tags[rparen] == .r_paren); | |
| 1686 | assert(tree.tokenTag(rparen) == .r_paren); | |
| 1723 | 1687 | |
| 1724 | 1688 | // The params list is a sparse set that does *not* include anytype or ... parameters. |
| 1725 | 1689 | |
| 1726 | const trailing_comma = token_tags[rparen - 1] == .comma; | |
| 1690 | const trailing_comma = tree.tokenTag(rparen - 1) == .comma; | |
| 1727 | 1691 | if (!trailing_comma and !hasComment(tree, lparen, rparen)) { |
| 1728 | 1692 | // Render all on one line, no trailing comma. |
| 1729 | 1693 | try renderToken(r, lparen, .none); // ( |
| ... | ... | @@ -1732,7 +1696,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1732 | 1696 | var last_param_token = lparen; |
| 1733 | 1697 | while (true) { |
| 1734 | 1698 | last_param_token += 1; |
| 1735 | switch (token_tags[last_param_token]) { | |
| 1699 | switch (tree.tokenTag(last_param_token)) { | |
| 1736 | 1700 | .doc_comment => { |
| 1737 | 1701 | try renderToken(r, last_param_token, .newline); |
| 1738 | 1702 | continue; |
| ... | ... | @@ -1757,15 +1721,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1757 | 1721 | }, |
| 1758 | 1722 | else => {}, // Parameter type without a name. |
| 1759 | 1723 | } |
| 1760 | if (token_tags[last_param_token] == .identifier and | |
| 1761 | token_tags[last_param_token + 1] == .colon) | |
| 1724 | if (tree.tokenTag(last_param_token) == .identifier and | |
| 1725 | tree.tokenTag(last_param_token + 1) == .colon) | |
| 1762 | 1726 | { |
| 1763 | 1727 | try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name |
| 1764 | last_param_token += 1; | |
| 1728 | last_param_token = last_param_token + 1; | |
| 1765 | 1729 | try renderToken(r, last_param_token, .space); // : |
| 1766 | 1730 | last_param_token += 1; |
| 1767 | 1731 | } |
| 1768 | if (token_tags[last_param_token] == .keyword_anytype) { | |
| 1732 | if (tree.tokenTag(last_param_token) == .keyword_anytype) { | |
| 1769 | 1733 | try renderToken(r, last_param_token, .none); // anytype |
| 1770 | 1734 | continue; |
| 1771 | 1735 | } |
| ... | ... | @@ -1783,7 +1747,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1783 | 1747 | var last_param_token = lparen; |
| 1784 | 1748 | while (true) { |
| 1785 | 1749 | last_param_token += 1; |
| 1786 | switch (token_tags[last_param_token]) { | |
| 1750 | switch (tree.tokenTag(last_param_token)) { | |
| 1787 | 1751 | .doc_comment => { |
| 1788 | 1752 | try renderToken(r, last_param_token, .newline); |
| 1789 | 1753 | continue; |
| ... | ... | @@ -1799,24 +1763,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1799 | 1763 | .identifier => {}, |
| 1800 | 1764 | .keyword_anytype => { |
| 1801 | 1765 | try renderToken(r, last_param_token, .comma); // anytype |
| 1802 | if (token_tags[last_param_token + 1] == .comma) | |
| 1766 | if (tree.tokenTag(last_param_token + 1) == .comma) | |
| 1803 | 1767 | last_param_token += 1; |
| 1804 | 1768 | continue; |
| 1805 | 1769 | }, |
| 1806 | 1770 | .r_paren => break, |
| 1807 | 1771 | else => {}, // Parameter type without a name. |
| 1808 | 1772 | } |
| 1809 | if (token_tags[last_param_token] == .identifier and | |
| 1810 | token_tags[last_param_token + 1] == .colon) | |
| 1773 | if (tree.tokenTag(last_param_token) == .identifier and | |
| 1774 | tree.tokenTag(last_param_token + 1) == .colon) | |
| 1811 | 1775 | { |
| 1812 | 1776 | try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name |
| 1813 | 1777 | last_param_token += 1; |
| 1814 | 1778 | try renderToken(r, last_param_token, .space); // : |
| 1815 | 1779 | last_param_token += 1; |
| 1816 | 1780 | } |
| 1817 | if (token_tags[last_param_token] == .keyword_anytype) { | |
| 1781 | if (tree.tokenTag(last_param_token) == .keyword_anytype) { | |
| 1818 | 1782 | try renderToken(r, last_param_token, .comma); // anytype |
| 1819 | if (token_tags[last_param_token + 1] == .comma) | |
| 1783 | if (tree.tokenTag(last_param_token + 1) == .comma) | |
| 1820 | 1784 | last_param_token += 1; |
| 1821 | 1785 | continue; |
| 1822 | 1786 | } |
| ... | ... | @@ -1826,60 +1790,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1826 | 1790 | try renderExpression(r, param, .comma); |
| 1827 | 1791 | ais.popSpace(); |
| 1828 | 1792 | last_param_token = tree.lastToken(param); |
| 1829 | if (token_tags[last_param_token + 1] == .comma) last_param_token += 1; | |
| 1793 | if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1; | |
| 1830 | 1794 | } |
| 1831 | 1795 | ais.popIndent(); |
| 1832 | 1796 | } |
| 1833 | 1797 | |
| 1834 | 1798 | try renderToken(r, rparen, .space); // ) |
| 1835 | 1799 | |
| 1836 | if (fn_proto.ast.align_expr != 0) { | |
| 1837 | const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1; | |
| 1838 | const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1; | |
| 1800 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1801 | const align_lparen = tree.firstToken(align_expr) - 1; | |
| 1802 | const align_rparen = tree.lastToken(align_expr) + 1; | |
| 1839 | 1803 | |
| 1840 | 1804 | try renderToken(r, align_lparen - 1, .none); // align |
| 1841 | 1805 | try renderToken(r, align_lparen, .none); // ( |
| 1842 | try renderExpression(r, fn_proto.ast.align_expr, .none); | |
| 1806 | try renderExpression(r, align_expr, .none); | |
| 1843 | 1807 | try renderToken(r, align_rparen, .space); // ) |
| 1844 | 1808 | } |
| 1845 | 1809 | |
| 1846 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1847 | const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1; | |
| 1848 | const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1; | |
| 1810 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1811 | const align_lparen = tree.firstToken(addrspace_expr) - 1; | |
| 1812 | const align_rparen = tree.lastToken(addrspace_expr) + 1; | |
| 1849 | 1813 | |
| 1850 | 1814 | try renderToken(r, align_lparen - 1, .none); // addrspace |
| 1851 | 1815 | try renderToken(r, align_lparen, .none); // ( |
| 1852 | try renderExpression(r, fn_proto.ast.addrspace_expr, .none); | |
| 1816 | try renderExpression(r, addrspace_expr, .none); | |
| 1853 | 1817 | try renderToken(r, align_rparen, .space); // ) |
| 1854 | 1818 | } |
| 1855 | 1819 | |
| 1856 | if (fn_proto.ast.section_expr != 0) { | |
| 1857 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; | |
| 1858 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; | |
| 1820 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1821 | const section_lparen = tree.firstToken(section_expr) - 1; | |
| 1822 | const section_rparen = tree.lastToken(section_expr) + 1; | |
| 1859 | 1823 | |
| 1860 | 1824 | try renderToken(r, section_lparen - 1, .none); // section |
| 1861 | 1825 | try renderToken(r, section_lparen, .none); // ( |
| 1862 | try renderExpression(r, fn_proto.ast.section_expr, .none); | |
| 1826 | try renderExpression(r, section_expr, .none); | |
| 1863 | 1827 | try renderToken(r, section_rparen, .space); // ) |
| 1864 | 1828 | } |
| 1865 | 1829 | |
| 1866 | // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE | |
| 1867 | const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr])); | |
| 1868 | const is_declaration = fn_proto.name_token != null; | |
| 1869 | if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) { | |
| 1870 | const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1; | |
| 1871 | const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1; | |
| 1830 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 1831 | // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE | |
| 1832 | const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr))); | |
| 1833 | const is_declaration = fn_proto.name_token != null; | |
| 1834 | if (!(is_declaration and is_callconv_inline)) { | |
| 1835 | const callconv_lparen = tree.firstToken(callconv_expr) - 1; | |
| 1836 | const callconv_rparen = tree.lastToken(callconv_expr) + 1; | |
| 1872 | 1837 | |
| 1873 | try renderToken(r, callconv_lparen - 1, .none); // callconv | |
| 1874 | try renderToken(r, callconv_lparen, .none); // ( | |
| 1875 | try renderExpression(r, fn_proto.ast.callconv_expr, .none); | |
| 1876 | try renderToken(r, callconv_rparen, .space); // ) | |
| 1838 | try renderToken(r, callconv_lparen - 1, .none); // callconv | |
| 1839 | try renderToken(r, callconv_lparen, .none); // ( | |
| 1840 | try renderExpression(r, callconv_expr, .none); | |
| 1841 | try renderToken(r, callconv_rparen, .space); // ) | |
| 1842 | } | |
| 1877 | 1843 | } |
| 1878 | 1844 | |
| 1879 | if (token_tags[maybe_bang] == .bang) { | |
| 1845 | if (tree.tokenTag(maybe_bang) == .bang) { | |
| 1880 | 1846 | try renderToken(r, maybe_bang, .none); // ! |
| 1881 | 1847 | } |
| 1882 | return renderExpression(r, fn_proto.ast.return_type, space); | |
| 1848 | return renderExpression(r, return_type, space); | |
| 1883 | 1849 | } |
| 1884 | 1850 | |
| 1885 | 1851 | fn renderSwitchCase( |
| ... | ... | @@ -1889,9 +1855,7 @@ fn renderSwitchCase( |
| 1889 | 1855 | ) Error!void { |
| 1890 | 1856 | const ais = r.ais; |
| 1891 | 1857 | const tree = r.tree; |
| 1892 | const node_tags = tree.nodes.items(.tag); | |
| 1893 | const token_tags = tree.tokens.items(.tag); | |
| 1894 | const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma; | |
| 1858 | const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma; | |
| 1895 | 1859 | const has_comment_before_arrow = blk: { |
| 1896 | 1860 | if (switch_case.ast.values.len == 0) break :blk false; |
| 1897 | 1861 | break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token); |
| ... | ... | @@ -1918,7 +1882,7 @@ fn renderSwitchCase( |
| 1918 | 1882 | } |
| 1919 | 1883 | |
| 1920 | 1884 | // Render the arrow and everything after it |
| 1921 | const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal) | |
| 1885 | const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal) | |
| 1922 | 1886 | // Newline gets inserted when rendering the target expr. |
| 1923 | 1887 | Space.none |
| 1924 | 1888 | else |
| ... | ... | @@ -1928,12 +1892,12 @@ fn renderSwitchCase( |
| 1928 | 1892 | |
| 1929 | 1893 | if (switch_case.payload_token) |payload_token| { |
| 1930 | 1894 | try renderToken(r, payload_token - 1, .none); // pipe |
| 1931 | const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk); | |
| 1932 | if (token_tags[payload_token] == .asterisk) { | |
| 1895 | const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk); | |
| 1896 | if (tree.tokenTag(payload_token) == .asterisk) { | |
| 1933 | 1897 | try renderToken(r, payload_token, .none); // asterisk |
| 1934 | 1898 | } |
| 1935 | 1899 | try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier |
| 1936 | if (token_tags[ident + 1] == .comma) { | |
| 1900 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 1937 | 1901 | try renderToken(r, ident + 1, .space); // , |
| 1938 | 1902 | try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier |
| 1939 | 1903 | try renderToken(r, ident + 3, pre_target_space); // pipe |
| ... | ... | @@ -1953,12 +1917,9 @@ fn renderBlock( |
| 1953 | 1917 | ) Error!void { |
| 1954 | 1918 | const tree = r.tree; |
| 1955 | 1919 | const ais = r.ais; |
| 1956 | const token_tags = tree.tokens.items(.tag); | |
| 1957 | const lbrace = tree.nodes.items(.main_token)[block_node]; | |
| 1920 | const lbrace = tree.nodeMainToken(block_node); | |
| 1958 | 1921 | |
| 1959 | if (token_tags[lbrace - 1] == .colon and | |
| 1960 | token_tags[lbrace - 2] == .identifier) | |
| 1961 | { | |
| 1922 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 1962 | 1923 | try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier |
| 1963 | 1924 | try renderToken(r, lbrace - 1, .space); // : |
| 1964 | 1925 | } |
| ... | ... | @@ -1980,13 +1941,12 @@ fn finishRenderBlock( |
| 1980 | 1941 | space: Space, |
| 1981 | 1942 | ) Error!void { |
| 1982 | 1943 | const tree = r.tree; |
| 1983 | const node_tags = tree.nodes.items(.tag); | |
| 1984 | 1944 | const ais = r.ais; |
| 1985 | 1945 | for (statements, 0..) |stmt, i| { |
| 1986 | 1946 | if (i != 0) try renderExtraNewline(r, stmt); |
| 1987 | 1947 | if (r.fixups.omit_nodes.contains(stmt)) continue; |
| 1988 | 1948 | try ais.pushSpace(.semicolon); |
| 1989 | switch (node_tags[stmt]) { | |
| 1949 | switch (tree.nodeTag(stmt)) { | |
| 1990 | 1950 | .global_var_decl, |
| 1991 | 1951 | .local_var_decl, |
| 1992 | 1952 | .simple_var_decl, |
| ... | ... | @@ -2010,12 +1970,13 @@ fn renderStructInit( |
| 2010 | 1970 | ) Error!void { |
| 2011 | 1971 | const tree = r.tree; |
| 2012 | 1972 | const ais = r.ais; |
| 2013 | const token_tags = tree.tokens.items(.tag); | |
| 2014 | if (struct_init.ast.type_expr == 0) { | |
| 2015 | try renderToken(r, struct_init.ast.lbrace - 1, .none); // . | |
| 1973 | ||
| 1974 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 1975 | try renderExpression(r, type_expr, .none); // T | |
| 2016 | 1976 | } else { |
| 2017 | try renderExpression(r, struct_init.ast.type_expr, .none); // T | |
| 1977 | try renderToken(r, struct_init.ast.lbrace - 1, .none); // . | |
| 2018 | 1978 | } |
| 1979 | ||
| 2019 | 1980 | if (struct_init.ast.fields.len == 0) { |
| 2020 | 1981 | try ais.pushIndent(.normal); |
| 2021 | 1982 | try renderToken(r, struct_init.ast.lbrace, .none); // lbrace |
| ... | ... | @@ -2024,7 +1985,7 @@ fn renderStructInit( |
| 2024 | 1985 | } |
| 2025 | 1986 | |
| 2026 | 1987 | const rbrace = tree.lastToken(struct_node); |
| 2027 | const trailing_comma = token_tags[rbrace - 1] == .comma; | |
| 1988 | const trailing_comma = tree.tokenTag(rbrace - 1) == .comma; | |
| 2028 | 1989 | if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) { |
| 2029 | 1990 | // Render one field init per line. |
| 2030 | 1991 | try ais.pushIndent(.normal); |
| ... | ... | @@ -2034,9 +1995,8 @@ fn renderStructInit( |
| 2034 | 1995 | try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name |
| 2035 | 1996 | // Don't output a space after the = if expression is a multiline string, |
| 2036 | 1997 | // since then it will start on the next line. |
| 2037 | const nodes = tree.nodes.items(.tag); | |
| 2038 | 1998 | const field_node = struct_init.ast.fields[0]; |
| 2039 | const expr = nodes[field_node]; | |
| 1999 | const expr = tree.nodeTag(field_node); | |
| 2040 | 2000 | var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space; |
| 2041 | 2001 | try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // = |
| 2042 | 2002 | |
| ... | ... | @@ -2049,7 +2009,7 @@ fn renderStructInit( |
| 2049 | 2009 | try renderExtraNewlineToken(r, init_token - 3); |
| 2050 | 2010 | try renderToken(r, init_token - 3, .none); // . |
| 2051 | 2011 | try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name |
| 2052 | space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space; | |
| 2012 | space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space; | |
| 2053 | 2013 | try renderToken(r, init_token - 1, space_after_equal); // = |
| 2054 | 2014 | |
| 2055 | 2015 | try ais.pushSpace(.comma); |
| ... | ... | @@ -2082,12 +2042,11 @@ fn renderArrayInit( |
| 2082 | 2042 | const tree = r.tree; |
| 2083 | 2043 | const ais = r.ais; |
| 2084 | 2044 | const gpa = r.gpa; |
| 2085 | const token_tags = tree.tokens.items(.tag); | |
| 2086 | 2045 | |
| 2087 | if (array_init.ast.type_expr == 0) { | |
| 2088 | try renderToken(r, array_init.ast.lbrace - 1, .none); // . | |
| 2046 | if (array_init.ast.type_expr.unwrap()) |type_expr| { | |
| 2047 | try renderExpression(r, type_expr, .none); // T | |
| 2089 | 2048 | } else { |
| 2090 | try renderExpression(r, array_init.ast.type_expr, .none); // T | |
| 2049 | try renderToken(r, array_init.ast.lbrace - 1, .none); // . | |
| 2091 | 2050 | } |
| 2092 | 2051 | |
| 2093 | 2052 | if (array_init.ast.elements.len == 0) { |
| ... | ... | @@ -2099,14 +2058,14 @@ fn renderArrayInit( |
| 2099 | 2058 | |
| 2100 | 2059 | const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1]; |
| 2101 | 2060 | const last_elem_token = tree.lastToken(last_elem); |
| 2102 | const trailing_comma = token_tags[last_elem_token + 1] == .comma; | |
| 2061 | const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma; | |
| 2103 | 2062 | const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1; |
| 2104 | assert(token_tags[rbrace] == .r_brace); | |
| 2063 | assert(tree.tokenTag(rbrace) == .r_brace); | |
| 2105 | 2064 | |
| 2106 | 2065 | if (array_init.ast.elements.len == 1) { |
| 2107 | 2066 | const only_elem = array_init.ast.elements[0]; |
| 2108 | 2067 | const first_token = tree.firstToken(only_elem); |
| 2109 | if (token_tags[first_token] != .multiline_string_literal_line and | |
| 2068 | if (tree.tokenTag(first_token) != .multiline_string_literal_line and | |
| 2110 | 2069 | !anythingBetween(tree, last_elem_token, rbrace)) |
| 2111 | 2070 | { |
| 2112 | 2071 | try renderToken(r, array_init.ast.lbrace, .none); |
| ... | ... | @@ -2169,7 +2128,7 @@ fn renderArrayInit( |
| 2169 | 2128 | } |
| 2170 | 2129 | |
| 2171 | 2130 | const maybe_comma = expr_last_token + 1; |
| 2172 | if (token_tags[maybe_comma] == .comma) { | |
| 2131 | if (tree.tokenTag(maybe_comma) == .comma) { | |
| 2173 | 2132 | if (hasSameLineComment(tree, maybe_comma)) |
| 2174 | 2133 | break :sec_end i - this_line_size + 1; |
| 2175 | 2134 | } |
| ... | ... | @@ -2309,13 +2268,12 @@ fn renderContainerDecl( |
| 2309 | 2268 | ) Error!void { |
| 2310 | 2269 | const tree = r.tree; |
| 2311 | 2270 | const ais = r.ais; |
| 2312 | const token_tags = tree.tokens.items(.tag); | |
| 2313 | 2271 | |
| 2314 | 2272 | if (container_decl.layout_token) |layout_token| { |
| 2315 | 2273 | try renderToken(r, layout_token, .space); |
| 2316 | 2274 | } |
| 2317 | 2275 | |
| 2318 | const container: Container = switch (token_tags[container_decl.ast.main_token]) { | |
| 2276 | const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) { | |
| 2319 | 2277 | .keyword_enum => .@"enum", |
| 2320 | 2278 | .keyword_struct => for (container_decl.ast.members) |member| { |
| 2321 | 2279 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| ... | ... | @@ -2328,10 +2286,10 @@ fn renderContainerDecl( |
| 2328 | 2286 | try renderToken(r, container_decl.ast.main_token, .none); // union |
| 2329 | 2287 | try renderToken(r, enum_token - 1, .none); // lparen |
| 2330 | 2288 | try renderToken(r, enum_token, .none); // enum |
| 2331 | if (container_decl.ast.arg != 0) { | |
| 2289 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 2332 | 2290 | try renderToken(r, enum_token + 1, .none); // lparen |
| 2333 | try renderExpression(r, container_decl.ast.arg, .none); | |
| 2334 | const rparen = tree.lastToken(container_decl.ast.arg) + 1; | |
| 2291 | try renderExpression(r, arg, .none); | |
| 2292 | const rparen = tree.lastToken(arg) + 1; | |
| 2335 | 2293 | try renderToken(r, rparen, .none); // rparen |
| 2336 | 2294 | try renderToken(r, rparen + 1, .space); // rparen |
| 2337 | 2295 | lbrace = rparen + 2; |
| ... | ... | @@ -2339,11 +2297,11 @@ fn renderContainerDecl( |
| 2339 | 2297 | try renderToken(r, enum_token + 1, .space); // rparen |
| 2340 | 2298 | lbrace = enum_token + 2; |
| 2341 | 2299 | } |
| 2342 | } else if (container_decl.ast.arg != 0) { | |
| 2300 | } else if (container_decl.ast.arg.unwrap()) |arg| { | |
| 2343 | 2301 | try renderToken(r, container_decl.ast.main_token, .none); // union |
| 2344 | 2302 | try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen |
| 2345 | try renderExpression(r, container_decl.ast.arg, .none); | |
| 2346 | const rparen = tree.lastToken(container_decl.ast.arg) + 1; | |
| 2303 | try renderExpression(r, arg, .none); | |
| 2304 | const rparen = tree.lastToken(arg) + 1; | |
| 2347 | 2305 | try renderToken(r, rparen, .space); // rparen |
| 2348 | 2306 | lbrace = rparen + 1; |
| 2349 | 2307 | } else { |
| ... | ... | @@ -2352,9 +2310,10 @@ fn renderContainerDecl( |
| 2352 | 2310 | } |
| 2353 | 2311 | |
| 2354 | 2312 | const rbrace = tree.lastToken(container_decl_node); |
| 2313 | ||
| 2355 | 2314 | if (container_decl.ast.members.len == 0) { |
| 2356 | 2315 | try ais.pushIndent(.normal); |
| 2357 | if (token_tags[lbrace + 1] == .container_doc_comment) { | |
| 2316 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) { | |
| 2358 | 2317 | try renderToken(r, lbrace, .newline); // lbrace |
| 2359 | 2318 | try renderContainerDocComments(r, lbrace + 1); |
| 2360 | 2319 | } else { |
| ... | ... | @@ -2364,7 +2323,7 @@ fn renderContainerDecl( |
| 2364 | 2323 | return renderToken(r, rbrace, space); // rbrace |
| 2365 | 2324 | } |
| 2366 | 2325 | |
| 2367 | const src_has_trailing_comma = token_tags[rbrace - 1] == .comma; | |
| 2326 | const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma; | |
| 2368 | 2327 | if (!src_has_trailing_comma) one_line: { |
| 2369 | 2328 | // We print all the members in-line unless one of the following conditions are true: |
| 2370 | 2329 | |
| ... | ... | @@ -2374,10 +2333,10 @@ fn renderContainerDecl( |
| 2374 | 2333 | } |
| 2375 | 2334 | |
| 2376 | 2335 | // 2. The container has a container comment. |
| 2377 | if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line; | |
| 2336 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line; | |
| 2378 | 2337 | |
| 2379 | 2338 | // 3. A member of the container has a doc comment. |
| 2380 | for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| { | |
| 2339 | for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| { | |
| 2381 | 2340 | if (tag == .doc_comment) break :one_line; |
| 2382 | 2341 | } |
| 2383 | 2342 | |
| ... | ... | @@ -2397,12 +2356,12 @@ fn renderContainerDecl( |
| 2397 | 2356 | // One member per line. |
| 2398 | 2357 | try ais.pushIndent(.normal); |
| 2399 | 2358 | try renderToken(r, lbrace, .newline); // lbrace |
| 2400 | if (token_tags[lbrace + 1] == .container_doc_comment) { | |
| 2359 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) { | |
| 2401 | 2360 | try renderContainerDocComments(r, lbrace + 1); |
| 2402 | 2361 | } |
| 2403 | 2362 | for (container_decl.ast.members, 0..) |member, i| { |
| 2404 | 2363 | if (i != 0) try renderExtraNewline(r, member); |
| 2405 | switch (tree.nodes.items(.tag)[member]) { | |
| 2364 | switch (tree.nodeTag(member)) { | |
| 2406 | 2365 | // For container fields, ensure a trailing comma is added if necessary. |
| 2407 | 2366 | .container_field_init, |
| 2408 | 2367 | .container_field_align, |
| ... | ... | @@ -2428,7 +2387,6 @@ fn renderAsm( |
| 2428 | 2387 | ) Error!void { |
| 2429 | 2388 | const tree = r.tree; |
| 2430 | 2389 | const ais = r.ais; |
| 2431 | const token_tags = tree.tokens.items(.tag); | |
| 2432 | 2390 | |
| 2433 | 2391 | try renderToken(r, asm_node.ast.asm_token, .space); // asm |
| 2434 | 2392 | |
| ... | ... | @@ -2454,13 +2412,13 @@ fn renderAsm( |
| 2454 | 2412 | while (true) : (tok_i += 1) { |
| 2455 | 2413 | try renderToken(r, tok_i, .none); |
| 2456 | 2414 | tok_i += 1; |
| 2457 | switch (token_tags[tok_i]) { | |
| 2415 | switch (tree.tokenTag(tok_i)) { | |
| 2458 | 2416 | .r_paren => { |
| 2459 | 2417 | ais.popIndent(); |
| 2460 | 2418 | return renderToken(r, tok_i, space); |
| 2461 | 2419 | }, |
| 2462 | 2420 | .comma => { |
| 2463 | if (token_tags[tok_i + 1] == .r_paren) { | |
| 2421 | if (tree.tokenTag(tok_i + 1) == .r_paren) { | |
| 2464 | 2422 | ais.popIndent(); |
| 2465 | 2423 | return renderToken(r, tok_i + 1, space); |
| 2466 | 2424 | } else { |
| ... | ... | @@ -2512,7 +2470,7 @@ fn renderAsm( |
| 2512 | 2470 | ais.popSpace(); |
| 2513 | 2471 | const comma_or_colon = tree.lastToken(asm_output) + 1; |
| 2514 | 2472 | ais.popIndent(); |
| 2515 | break :colon2 switch (token_tags[comma_or_colon]) { | |
| 2473 | break :colon2 switch (tree.tokenTag(comma_or_colon)) { | |
| 2516 | 2474 | .comma => comma_or_colon + 1, |
| 2517 | 2475 | else => comma_or_colon, |
| 2518 | 2476 | }; |
| ... | ... | @@ -2548,7 +2506,7 @@ fn renderAsm( |
| 2548 | 2506 | ais.popSpace(); |
| 2549 | 2507 | const comma_or_colon = tree.lastToken(asm_input) + 1; |
| 2550 | 2508 | ais.popIndent(); |
| 2551 | break :colon3 switch (token_tags[comma_or_colon]) { | |
| 2509 | break :colon3 switch (tree.tokenTag(comma_or_colon)) { | |
| 2552 | 2510 | .comma => comma_or_colon + 1, |
| 2553 | 2511 | else => comma_or_colon, |
| 2554 | 2512 | }; |
| ... | ... | @@ -2561,7 +2519,7 @@ fn renderAsm( |
| 2561 | 2519 | const first_clobber = asm_node.first_clobber.?; |
| 2562 | 2520 | var tok_i = first_clobber; |
| 2563 | 2521 | while (true) { |
| 2564 | switch (token_tags[tok_i + 1]) { | |
| 2522 | switch (tree.tokenTag(tok_i + 1)) { | |
| 2565 | 2523 | .r_paren => { |
| 2566 | 2524 | ais.setIndentDelta(indent_delta); |
| 2567 | 2525 | try renderToken(r, tok_i, .newline); |
| ... | ... | @@ -2569,7 +2527,7 @@ fn renderAsm( |
| 2569 | 2527 | return renderToken(r, tok_i + 1, space); |
| 2570 | 2528 | }, |
| 2571 | 2529 | .comma => { |
| 2572 | switch (token_tags[tok_i + 2]) { | |
| 2530 | switch (tree.tokenTag(tok_i + 2)) { | |
| 2573 | 2531 | .r_paren => { |
| 2574 | 2532 | ais.setIndentDelta(indent_delta); |
| 2575 | 2533 | try renderToken(r, tok_i, .newline); |
| ... | ... | @@ -2608,7 +2566,6 @@ fn renderParamList( |
| 2608 | 2566 | ) Error!void { |
| 2609 | 2567 | const tree = r.tree; |
| 2610 | 2568 | const ais = r.ais; |
| 2611 | const token_tags = tree.tokens.items(.tag); | |
| 2612 | 2569 | |
| 2613 | 2570 | if (params.len == 0) { |
| 2614 | 2571 | try ais.pushIndent(.normal); |
| ... | ... | @@ -2619,7 +2576,7 @@ fn renderParamList( |
| 2619 | 2576 | |
| 2620 | 2577 | const last_param = params[params.len - 1]; |
| 2621 | 2578 | const after_last_param_tok = tree.lastToken(last_param) + 1; |
| 2622 | if (token_tags[after_last_param_tok] == .comma) { | |
| 2579 | if (tree.tokenTag(after_last_param_tok) == .comma) { | |
| 2623 | 2580 | try ais.pushIndent(.normal); |
| 2624 | 2581 | try renderToken(r, lparen, .newline); // ( |
| 2625 | 2582 | for (params, 0..) |param_node, i| { |
| ... | ... | @@ -2648,7 +2605,7 @@ fn renderParamList( |
| 2648 | 2605 | if (i + 1 < params.len) { |
| 2649 | 2606 | const comma = tree.lastToken(param_node) + 1; |
| 2650 | 2607 | const next_multiline_string = |
| 2651 | token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line; | |
| 2608 | tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line; | |
| 2652 | 2609 | const comma_space: Space = if (next_multiline_string) .none else .space; |
| 2653 | 2610 | try renderToken(r, comma, comma_space); |
| 2654 | 2611 | } |
| ... | ... | @@ -2661,9 +2618,8 @@ fn renderParamList( |
| 2661 | 2618 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2662 | 2619 | fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 2663 | 2620 | const tree = r.tree; |
| 2664 | const token_tags = tree.tokens.items(.tag); | |
| 2665 | 2621 | const maybe_comma = tree.lastToken(node) + 1; |
| 2666 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2622 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2667 | 2623 | try renderExpression(r, node, .none); |
| 2668 | 2624 | return renderToken(r, maybe_comma, space); |
| 2669 | 2625 | } else { |
| ... | ... | @@ -2675,9 +2631,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v |
| 2675 | 2631 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2676 | 2632 | fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void { |
| 2677 | 2633 | const tree = r.tree; |
| 2678 | const token_tags = tree.tokens.items(.tag); | |
| 2679 | 2634 | const maybe_comma = token + 1; |
| 2680 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2635 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2681 | 2636 | try renderToken(r, token, .none); |
| 2682 | 2637 | return renderToken(r, maybe_comma, space); |
| 2683 | 2638 | } else { |
| ... | ... | @@ -2689,9 +2644,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void |
| 2689 | 2644 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2690 | 2645 | fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { |
| 2691 | 2646 | const tree = r.tree; |
| 2692 | const token_tags = tree.tokens.items(.tag); | |
| 2693 | 2647 | const maybe_comma = token + 1; |
| 2694 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2648 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2695 | 2649 | try renderIdentifier(r, token, .none, quote); |
| 2696 | 2650 | return renderToken(r, maybe_comma, space); |
| 2697 | 2651 | } else { |
| ... | ... | @@ -2741,37 +2695,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: |
| 2741 | 2695 | fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void { |
| 2742 | 2696 | const tree = r.tree; |
| 2743 | 2697 | const ais = r.ais; |
| 2744 | const token_tags = tree.tokens.items(.tag); | |
| 2745 | const token_starts = tree.tokens.items(.start); | |
| 2746 | 2698 | |
| 2747 | const token_start = token_starts[token_index]; | |
| 2699 | const next_token_tag = tree.tokenTag(token_index + 1); | |
| 2748 | 2700 | |
| 2749 | 2701 | if (space == .skip) return; |
| 2750 | 2702 | |
| 2751 | if (space == .comma and token_tags[token_index + 1] != .comma) { | |
| 2703 | if (space == .comma and next_token_tag != .comma) { | |
| 2752 | 2704 | try ais.writer().writeByte(','); |
| 2753 | 2705 | } |
| 2754 | 2706 | if (space == .semicolon or space == .comma) ais.enableSpaceMode(space); |
| 2755 | 2707 | defer ais.disableSpaceMode(); |
| 2756 | const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]); | |
| 2708 | const comment = try renderComments( | |
| 2709 | r, | |
| 2710 | tree.tokenStart(token_index) + lexeme_len, | |
| 2711 | tree.tokenStart(token_index + 1), | |
| 2712 | ); | |
| 2757 | 2713 | switch (space) { |
| 2758 | 2714 | .none => {}, |
| 2759 | 2715 | .space => if (!comment) try ais.writer().writeByte(' '), |
| 2760 | 2716 | .newline => if (!comment) try ais.insertNewline(), |
| 2761 | 2717 | |
| 2762 | .comma => if (token_tags[token_index + 1] == .comma) { | |
| 2718 | .comma => if (next_token_tag == .comma) { | |
| 2763 | 2719 | try renderToken(r, token_index + 1, .newline); |
| 2764 | 2720 | } else if (!comment) { |
| 2765 | 2721 | try ais.insertNewline(); |
| 2766 | 2722 | }, |
| 2767 | 2723 | |
| 2768 | .comma_space => if (token_tags[token_index + 1] == .comma) { | |
| 2724 | .comma_space => if (next_token_tag == .comma) { | |
| 2769 | 2725 | try renderToken(r, token_index + 1, .space); |
| 2770 | 2726 | } else if (!comment) { |
| 2771 | 2727 | try ais.writer().writeByte(' '); |
| 2772 | 2728 | }, |
| 2773 | 2729 | |
| 2774 | .semicolon => if (token_tags[token_index + 1] == .semicolon) { | |
| 2730 | .semicolon => if (next_token_tag == .semicolon) { | |
| 2775 | 2731 | try renderToken(r, token_index + 1, .newline); |
| 2776 | 2732 | } else if (!comment) { |
| 2777 | 2733 | try ais.insertNewline(); |
| ... | ... | @@ -2802,8 +2758,7 @@ const QuoteBehavior = enum { |
| 2802 | 2758 | |
| 2803 | 2759 | fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { |
| 2804 | 2760 | const tree = r.tree; |
| 2805 | const token_tags = tree.tokens.items(.tag); | |
| 2806 | assert(token_tags[token_index] == .identifier); | |
| 2761 | assert(tree.tokenTag(token_index) == .identifier); | |
| 2807 | 2762 | const lexeme = tokenSliceForRender(tree, token_index); |
| 2808 | 2763 | |
| 2809 | 2764 | if (r.fixups.rename_identifiers.get(lexeme)) |mangled| { |
| ... | ... | @@ -2912,8 +2867,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote |
| 2912 | 2867 | fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void { |
| 2913 | 2868 | const tree = r.tree; |
| 2914 | 2869 | const ais = r.ais; |
| 2915 | const token_tags = tree.tokens.items(.tag); | |
| 2916 | assert(token_tags[token_index] == .identifier); | |
| 2870 | assert(tree.tokenTag(token_index) == .identifier); | |
| 2917 | 2871 | const lexeme = tokenSliceForRender(tree, token_index); |
| 2918 | 2872 | assert(lexeme.len >= 3 and lexeme[0] == '@'); |
| 2919 | 2873 | |
| ... | ... | @@ -2966,12 +2920,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void { |
| 2966 | 2920 | /// fn_proto should be wrapped and have a trailing comma inserted even if |
| 2967 | 2921 | /// there is none in the source. |
| 2968 | 2922 | fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 2969 | const token_starts = tree.tokens.items(.start); | |
| 2970 | ||
| 2971 | var i = start_token; | |
| 2972 | while (i < end_token) : (i += 1) { | |
| 2973 | const start = token_starts[i] + tree.tokenSlice(i).len; | |
| 2974 | const end = token_starts[i + 1]; | |
| 2923 | for (start_token..end_token) |i| { | |
| 2924 | const token: Ast.TokenIndex = @intCast(i); | |
| 2925 | const start = tree.tokenStart(token) + tree.tokenSlice(token).len; | |
| 2926 | const end = tree.tokenStart(token + 1); | |
| 2975 | 2927 | if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true; |
| 2976 | 2928 | } |
| 2977 | 2929 | |
| ... | ... | @@ -2981,16 +2933,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) |
| 2981 | 2933 | /// Returns true if there exists a multiline string literal between the start |
| 2982 | 2934 | /// of token `start_token` and the start of token `end_token`. |
| 2983 | 2935 | fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 2984 | const token_tags = tree.tokens.items(.tag); | |
| 2985 | ||
| 2986 | for (token_tags[start_token..end_token]) |tag| { | |
| 2987 | switch (tag) { | |
| 2988 | .multiline_string_literal_line => return true, | |
| 2989 | else => continue, | |
| 2990 | } | |
| 2991 | } | |
| 2992 | ||
| 2993 | return false; | |
| 2936 | return std.mem.indexOfScalar( | |
| 2937 | Token.Tag, | |
| 2938 | tree.tokens.items(.tag)[start_token..end_token], | |
| 2939 | .multiline_string_literal_line, | |
| 2940 | ) != null; | |
| 2994 | 2941 | } |
| 2995 | 2942 | |
| 2996 | 2943 | /// Assumes that start is the first byte past the previous token and |
| ... | ... | @@ -3066,18 +3013,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void { |
| 3066 | 3013 | fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void { |
| 3067 | 3014 | const tree = r.tree; |
| 3068 | 3015 | const ais = r.ais; |
| 3069 | const token_starts = tree.tokens.items(.start); | |
| 3070 | const token_start = token_starts[token_index]; | |
| 3016 | const token_start = tree.tokenStart(token_index); | |
| 3071 | 3017 | if (token_start == 0) return; |
| 3072 | 3018 | const prev_token_end = if (token_index == 0) |
| 3073 | 3019 | 0 |
| 3074 | 3020 | else |
| 3075 | token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len; | |
| 3021 | tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len; | |
| 3076 | 3022 | |
| 3077 | 3023 | // If there is a immediately preceding comment or doc_comment, |
| 3078 | 3024 | // skip it because required extra newline has already been rendered. |
| 3079 | 3025 | if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return; |
| 3080 | if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return; | |
| 3026 | if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return; | |
| 3081 | 3027 | |
| 3082 | 3028 | // Iterate backwards to the end of the previous token, stopping if a |
| 3083 | 3029 | // non-whitespace character is encountered or two newlines have been found. |
| ... | ... | @@ -3095,10 +3041,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void { |
| 3095 | 3041 | fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3096 | 3042 | const tree = r.tree; |
| 3097 | 3043 | // Search backwards for the first doc comment. |
| 3098 | const token_tags = tree.tokens.items(.tag); | |
| 3099 | 3044 | if (end_token == 0) return; |
| 3100 | 3045 | var tok = end_token - 1; |
| 3101 | while (token_tags[tok] == .doc_comment) { | |
| 3046 | while (tree.tokenTag(tok) == .doc_comment) { | |
| 3102 | 3047 | if (tok == 0) break; |
| 3103 | 3048 | tok -= 1; |
| 3104 | 3049 | } else { |
| ... | ... | @@ -3108,7 +3053,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3108 | 3053 | if (first_tok == end_token) return; |
| 3109 | 3054 | |
| 3110 | 3055 | if (first_tok != 0) { |
| 3111 | const prev_token_tag = token_tags[first_tok - 1]; | |
| 3056 | const prev_token_tag = tree.tokenTag(first_tok - 1); | |
| 3112 | 3057 | |
| 3113 | 3058 | // Prevent accidental use of `renderDocComments` for a function argument doc comment |
| 3114 | 3059 | assert(prev_token_tag != .l_paren); |
| ... | ... | @@ -3118,7 +3063,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3118 | 3063 | } |
| 3119 | 3064 | } |
| 3120 | 3065 | |
| 3121 | while (token_tags[tok] == .doc_comment) : (tok += 1) { | |
| 3066 | while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) { | |
| 3122 | 3067 | try renderToken(r, tok, .newline); |
| 3123 | 3068 | } |
| 3124 | 3069 | } |
| ... | ... | @@ -3126,15 +3071,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3126 | 3071 | /// start_token is first container doc comment token. |
| 3127 | 3072 | fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void { |
| 3128 | 3073 | const tree = r.tree; |
| 3129 | const token_tags = tree.tokens.items(.tag); | |
| 3130 | 3074 | var tok = start_token; |
| 3131 | while (token_tags[tok] == .container_doc_comment) : (tok += 1) { | |
| 3075 | while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) { | |
| 3132 | 3076 | try renderToken(r, tok, .newline); |
| 3133 | 3077 | } |
| 3134 | 3078 | // Render extra newline if there is one between final container doc comment and |
| 3135 | 3079 | // the next token. If the next token is a doc comment, that code path |
| 3136 | 3080 | // will have its own logic to insert a newline. |
| 3137 | if (token_tags[tok] != .doc_comment) { | |
| 3081 | if (tree.tokenTag(tok) != .doc_comment) { | |
| 3138 | 3082 | try renderExtraNewlineToken(r, tok); |
| 3139 | 3083 | } |
| 3140 | 3084 | } |
| ... | ... | @@ -3144,11 +3088,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void { |
| 3144 | 3088 | const ais = r.ais; |
| 3145 | 3089 | var buf: [1]Ast.Node.Index = undefined; |
| 3146 | 3090 | const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?; |
| 3147 | const token_tags = tree.tokens.items(.tag); | |
| 3148 | 3091 | var it = fn_proto.iterate(tree); |
| 3149 | 3092 | while (it.next()) |param| { |
| 3150 | 3093 | const name_ident = param.name_token.?; |
| 3151 | assert(token_tags[name_ident] == .identifier); | |
| 3094 | assert(tree.tokenTag(name_ident) == .identifier); | |
| 3152 | 3095 | const w = ais.writer(); |
| 3153 | 3096 | try w.writeAll("_ = "); |
| 3154 | 3097 | try w.writeAll(tokenSliceForRender(r.tree, name_ident)); |
| ... | ... | @@ -3158,7 +3101,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void { |
| 3158 | 3101 | |
| 3159 | 3102 | fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 { |
| 3160 | 3103 | var ret = tree.tokenSlice(token_index); |
| 3161 | switch (tree.tokens.items(.tag)[token_index]) { | |
| 3104 | switch (tree.tokenTag(token_index)) { | |
| 3162 | 3105 | .container_doc_comment, .doc_comment => { |
| 3163 | 3106 | ret = mem.trimRight(u8, ret, &std.ascii.whitespace); |
| 3164 | 3107 | }, |
| ... | ... | @@ -3168,8 +3111,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 { |
| 3168 | 3111 | } |
| 3169 | 3112 | |
| 3170 | 3113 | fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool { |
| 3171 | const token_starts = tree.tokens.items(.start); | |
| 3172 | const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]]; | |
| 3114 | const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)]; | |
| 3173 | 3115 | for (between_source) |byte| switch (byte) { |
| 3174 | 3116 | '\n' => return false, |
| 3175 | 3117 | '/' => return true, |
| ... | ... | @@ -3182,8 +3124,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool { |
| 3182 | 3124 | /// start_token and end_token. |
| 3183 | 3125 | fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 3184 | 3126 | if (start_token + 1 != end_token) return true; |
| 3185 | const token_starts = tree.tokens.items(.start); | |
| 3186 | const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]]; | |
| 3127 | const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)]; | |
| 3187 | 3128 | for (between_source) |byte| switch (byte) { |
| 3188 | 3129 | '/' => return true, |
| 3189 | 3130 | else => continue, |
| ... | ... | @@ -3277,12 +3218,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool { |
| 3277 | 3218 | |
| 3278 | 3219 | // Returns the number of nodes in `exprs` that are on the same line as `rtoken`. |
| 3279 | 3220 | fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize { |
| 3280 | const token_tags = tree.tokens.items(.tag); | |
| 3281 | ||
| 3282 | 3221 | const first_token = tree.firstToken(exprs[0]); |
| 3283 | 3222 | if (tree.tokensOnSameLine(first_token, rtoken)) { |
| 3284 | 3223 | const maybe_comma = rtoken - 1; |
| 3285 | if (token_tags[maybe_comma] == .comma) | |
| 3224 | if (tree.tokenTag(maybe_comma) == .comma) | |
| 3286 | 3225 | return 1; |
| 3287 | 3226 | return exprs.len; // no newlines |
| 3288 | 3227 | } |
lib/std/zon/parse.zig+11-17| ... | ... | @@ -196,16 +196,15 @@ pub const Error = union(enum) { |
| 196 | 196 | return .{ .err = self, .status = status }; |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | fn zoirErrorLocation(ast: Ast, maybe_token: Ast.TokenIndex, node_or_offset: u32) Ast.Location { | |
| 200 | if (maybe_token == Zoir.CompileError.invalid_token) { | |
| 201 | const main_tokens = ast.nodes.items(.main_token); | |
| 202 | const ast_node = node_or_offset; | |
| 203 | const token = main_tokens[ast_node]; | |
| 204 | return ast.tokenLocation(0, token); | |
| 205 | } else { | |
| 206 | var location = ast.tokenLocation(0, maybe_token); | |
| 199 | fn zoirErrorLocation(ast: Ast, maybe_token: Ast.OptionalTokenIndex, node_or_offset: u32) Ast.Location { | |
| 200 | if (maybe_token.unwrap()) |token| { | |
| 201 | var location = ast.tokenLocation(0, token); | |
| 207 | 202 | location.column += node_or_offset; |
| 208 | 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 | 631 | switch (try ZonGen.parseStrLit(self.ast, ast_node, buf.writer(self.gpa))) { |
| 633 | 632 | .success => {}, |
| 634 | 633 | .failure => |err| { |
| 635 | const token = self.ast.nodes.items(.main_token)[ast_node]; | |
| 634 | const token = self.ast.nodeMainToken(ast_node); | |
| 636 | 635 | const raw_string = self.ast.tokenSlice(token); |
| 637 | 636 | return self.failTokenFmt(token, @intCast(err.offset()), "{s}", .{err.fmt(raw_string)}); |
| 638 | 637 | }, |
| ... | ... | @@ -1005,8 +1004,7 @@ const Parser = struct { |
| 1005 | 1004 | args: anytype, |
| 1006 | 1005 | ) error{ OutOfMemory, ParseZon } { |
| 1007 | 1006 | @branchHint(.cold); |
| 1008 | const main_tokens = self.ast.nodes.items(.main_token); | |
| 1009 | const token = main_tokens[node.getAstNode(self.zoir)]; | |
| 1007 | const token = self.ast.nodeMainToken(node.getAstNode(self.zoir)); | |
| 1010 | 1008 | return self.failTokenFmt(token, 0, fmt, args); |
| 1011 | 1009 | } |
| 1012 | 1010 | |
| ... | ... | @@ -1025,8 +1023,7 @@ const Parser = struct { |
| 1025 | 1023 | message: []const u8, |
| 1026 | 1024 | ) error{ParseZon} { |
| 1027 | 1025 | @branchHint(.cold); |
| 1028 | const main_tokens = self.ast.nodes.items(.main_token); | |
| 1029 | const token = main_tokens[node.getAstNode(self.zoir)]; | |
| 1026 | const token = self.ast.nodeMainToken(node.getAstNode(self.zoir)); | |
| 1030 | 1027 | return self.failToken(.{ |
| 1031 | 1028 | .token = token, |
| 1032 | 1029 | .offset = 0, |
| ... | ... | @@ -1059,10 +1056,7 @@ const Parser = struct { |
| 1059 | 1056 | const struct_init = self.ast.fullStructInit(&buf, node.getAstNode(self.zoir)).?; |
| 1060 | 1057 | const field_node = struct_init.ast.fields[f]; |
| 1061 | 1058 | break :b self.ast.firstToken(field_node) - 2; |
| 1062 | } else b: { | |
| 1063 | const main_tokens = self.ast.nodes.items(.main_token); | |
| 1064 | break :b main_tokens[node.getAstNode(self.zoir)]; | |
| 1065 | }; | |
| 1059 | } else self.ast.nodeMainToken(node.getAstNode(self.zoir)); | |
| 1066 | 1060 | switch (@typeInfo(T)) { |
| 1067 | 1061 | inline .@"struct", .@"union", .@"enum" => |info| { |
| 1068 | 1062 | const note: Error.TypeCheckFailure.Note = if (info.fields.len == 0) b: { |
src/Package/Fetch.zig+10-10| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | arena: std.heap.ArenaAllocator, |
| 31 | 31 | location: Location, |
| 32 | 32 | location_tok: std.zig.Ast.TokenIndex, |
| 33 | hash_tok: std.zig.Ast.TokenIndex, | |
| 33 | hash_tok: std.zig.Ast.OptionalTokenIndex, | |
| 34 | 34 | name_tok: std.zig.Ast.TokenIndex, |
| 35 | 35 | lazy_status: LazyStatus, |
| 36 | 36 | parent_package_root: Cache.Path, |
| ... | ... | @@ -317,8 +317,8 @@ pub fn run(f: *Fetch) RunError!void { |
| 317 | 317 | f.location_tok, |
| 318 | 318 | try eb.addString("expected path relative to build root; found absolute path"), |
| 319 | 319 | ); |
| 320 | if (f.hash_tok != 0) return f.fail( | |
| 321 | f.hash_tok, | |
| 320 | if (f.hash_tok.unwrap()) |hash_tok| return f.fail( | |
| 321 | hash_tok, | |
| 322 | 322 | try eb.addString("path-based dependencies are not hashed"), |
| 323 | 323 | ); |
| 324 | 324 | // Packages fetched by URL may not use relative paths to escape outside the |
| ... | ... | @@ -555,17 +555,18 @@ fn runResource( |
| 555 | 555 | // job is done. |
| 556 | 556 | |
| 557 | 557 | if (remote_hash) |declared_hash| { |
| 558 | const hash_tok = f.hash_tok.unwrap().?; | |
| 558 | 559 | if (declared_hash.isOld()) { |
| 559 | 560 | const actual_hex = Package.multiHashHexDigest(f.computed_hash.digest); |
| 560 | 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 | 563 | "hash mismatch: manifest declares {s} but the fetched package has {s}", |
| 563 | 564 | .{ declared_hash.toSlice(), actual_hex }, |
| 564 | 565 | )); |
| 565 | 566 | } |
| 566 | 567 | } else { |
| 567 | 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 | 570 | "hash mismatch: manifest declares {s} but the fetched package has {s}", |
| 570 | 571 | .{ declared_hash.toSlice(), computed_package_hash.toSlice() }, |
| 571 | 572 | )); |
| ... | ... | @@ -813,15 +814,14 @@ fn srcLoc( |
| 813 | 814 | ) Allocator.Error!ErrorBundle.SourceLocationIndex { |
| 814 | 815 | const ast = f.parent_manifest_ast orelse return .none; |
| 815 | 816 | const eb = &f.error_bundle; |
| 816 | const token_starts = ast.tokens.items(.start); | |
| 817 | 817 | const start_loc = ast.tokenLocation(0, tok); |
| 818 | 818 | const src_path = try eb.printString("{}" ++ fs.path.sep_str ++ Manifest.basename, .{f.parent_package_root}); |
| 819 | 819 | const msg_off = 0; |
| 820 | 820 | return eb.addSourceLocation(.{ |
| 821 | 821 | .src_path = src_path, |
| 822 | .span_start = token_starts[tok], | |
| 823 | .span_end = @intCast(token_starts[tok] + ast.tokenSlice(tok).len), | |
| 824 | .span_main = token_starts[tok] + msg_off, | |
| 822 | .span_start = ast.tokenStart(tok), | |
| 823 | .span_end = @intCast(ast.tokenStart(tok) + ast.tokenSlice(tok).len), | |
| 824 | .span_main = ast.tokenStart(tok) + msg_off, | |
| 825 | 825 | .line = @intCast(start_loc.line), |
| 826 | 826 | .column = @intCast(start_loc.column), |
| 827 | 827 | .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]), |
| ... | ... | @@ -2331,7 +2331,7 @@ const TestFetchBuilder = struct { |
| 2331 | 2331 | .arena = std.heap.ArenaAllocator.init(allocator), |
| 2332 | 2332 | .location = .{ .path_or_url = path_or_url }, |
| 2333 | 2333 | .location_tok = 0, |
| 2334 | .hash_tok = 0, | |
| 2334 | .hash_tok = .none, | |
| 2335 | 2335 | .name_tok = 0, |
| 2336 | 2336 | .lazy_status = .eager, |
| 2337 | 2337 | .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } }, |
src/Package/Manifest.zig+42-61| ... | ... | @@ -17,8 +17,8 @@ pub const Dependency = struct { |
| 17 | 17 | location_tok: Ast.TokenIndex, |
| 18 | 18 | location_node: Ast.Node.Index, |
| 19 | 19 | hash: ?[]const u8, |
| 20 | hash_tok: Ast.TokenIndex, | |
| 21 | hash_node: Ast.Node.Index, | |
| 20 | hash_tok: Ast.OptionalTokenIndex, | |
| 21 | hash_node: Ast.Node.OptionalIndex, | |
| 22 | 22 | node: Ast.Node.Index, |
| 23 | 23 | name_tok: Ast.TokenIndex, |
| 24 | 24 | lazy: bool, |
| ... | ... | @@ -40,7 +40,7 @@ id: u32, |
| 40 | 40 | version: std.SemanticVersion, |
| 41 | 41 | version_node: Ast.Node.Index, |
| 42 | 42 | dependencies: std.StringArrayHashMapUnmanaged(Dependency), |
| 43 | dependencies_node: Ast.Node.Index, | |
| 43 | dependencies_node: Ast.Node.OptionalIndex, | |
| 44 | 44 | paths: std.StringArrayHashMapUnmanaged(void), |
| 45 | 45 | minimum_zig_version: ?std.SemanticVersion, |
| 46 | 46 | |
| ... | ... | @@ -58,10 +58,7 @@ pub const ParseOptions = struct { |
| 58 | 58 | pub const Error = Allocator.Error; |
| 59 | 59 | |
| 60 | 60 | pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { |
| 61 | const node_tags = ast.nodes.items(.tag); | |
| 62 | const node_datas = ast.nodes.items(.data); | |
| 63 | assert(node_tags[0] == .root); | |
| 64 | const main_node_index = node_datas[0].lhs; | |
| 61 | const main_node_index = ast.nodeData(.root).node; | |
| 65 | 62 | |
| 66 | 63 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| 67 | 64 | errdefer arena_instance.deinit(); |
| ... | ... | @@ -75,9 +72,9 @@ pub fn parse(gpa: Allocator, ast: Ast, options: ParseOptions) Error!Manifest { |
| 75 | 72 | .name = undefined, |
| 76 | 73 | .id = 0, |
| 77 | 74 | .version = undefined, |
| 78 | .version_node = 0, | |
| 75 | .version_node = undefined, | |
| 79 | 76 | .dependencies = .{}, |
| 80 | .dependencies_node = 0, | |
| 77 | .dependencies_node = .none, | |
| 81 | 78 | .paths = .{}, |
| 82 | 79 | .allow_missing_paths_field = options.allow_missing_paths_field, |
| 83 | 80 | .allow_name_string = options.allow_name_string, |
| ... | ... | @@ -121,8 +118,6 @@ pub fn copyErrorsIntoBundle( |
| 121 | 118 | src_path: u32, |
| 122 | 119 | eb: *std.zig.ErrorBundle.Wip, |
| 123 | 120 | ) Allocator.Error!void { |
| 124 | const token_starts = ast.tokens.items(.start); | |
| 125 | ||
| 126 | 121 | for (man.errors) |msg| { |
| 127 | 122 | const start_loc = ast.tokenLocation(0, msg.tok); |
| 128 | 123 | |
| ... | ... | @@ -130,9 +125,9 @@ pub fn copyErrorsIntoBundle( |
| 130 | 125 | .msg = try eb.addString(msg.msg), |
| 131 | 126 | .src_loc = try eb.addSourceLocation(.{ |
| 132 | 127 | .src_path = src_path, |
| 133 | .span_start = token_starts[msg.tok], | |
| 134 | .span_end = @intCast(token_starts[msg.tok] + ast.tokenSlice(msg.tok).len), | |
| 135 | .span_main = token_starts[msg.tok] + msg.off, | |
| 128 | .span_start = ast.tokenStart(msg.tok), | |
| 129 | .span_end = @intCast(ast.tokenStart(msg.tok) + ast.tokenSlice(msg.tok).len), | |
| 130 | .span_main = ast.tokenStart(msg.tok) + msg.off, | |
| 136 | 131 | .line = @intCast(start_loc.line), |
| 137 | 132 | .column = @intCast(start_loc.column), |
| 138 | 133 | .source_line = try eb.addString(ast.source[start_loc.line_start..start_loc.line_end]), |
| ... | ... | @@ -153,7 +148,7 @@ const Parse = struct { |
| 153 | 148 | version: std.SemanticVersion, |
| 154 | 149 | version_node: Ast.Node.Index, |
| 155 | 150 | dependencies: std.StringArrayHashMapUnmanaged(Dependency), |
| 156 | dependencies_node: Ast.Node.Index, | |
| 151 | dependencies_node: Ast.Node.OptionalIndex, | |
| 157 | 152 | paths: std.StringArrayHashMapUnmanaged(void), |
| 158 | 153 | allow_missing_paths_field: bool, |
| 159 | 154 | allow_name_string: bool, |
| ... | ... | @@ -164,8 +159,7 @@ const Parse = struct { |
| 164 | 159 | |
| 165 | 160 | fn parseRoot(p: *Parse, node: Ast.Node.Index) !void { |
| 166 | 161 | const ast = p.ast; |
| 167 | const main_tokens = ast.nodes.items(.main_token); | |
| 168 | const main_token = main_tokens[node]; | |
| 162 | const main_token = ast.nodeMainToken(node); | |
| 169 | 163 | |
| 170 | 164 | var buf: [2]Ast.Node.Index = undefined; |
| 171 | 165 | const struct_init = ast.fullStructInit(&buf, node) orelse { |
| ... | ... | @@ -184,7 +178,7 @@ const Parse = struct { |
| 184 | 178 | // things manually provides an opportunity to do any additional verification |
| 185 | 179 | // that is desirable on a per-field basis. |
| 186 | 180 | if (mem.eql(u8, field_name, "dependencies")) { |
| 187 | p.dependencies_node = field_init; | |
| 181 | p.dependencies_node = field_init.toOptional(); | |
| 188 | 182 | try parseDependencies(p, field_init); |
| 189 | 183 | } else if (mem.eql(u8, field_name, "paths")) { |
| 190 | 184 | have_included_paths = true; |
| ... | ... | @@ -198,17 +192,17 @@ const Parse = struct { |
| 198 | 192 | p.version_node = field_init; |
| 199 | 193 | const version_text = try parseString(p, field_init); |
| 200 | 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 | 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 | 199 | break :v undefined; |
| 206 | 200 | }; |
| 207 | 201 | have_version = true; |
| 208 | 202 | } else if (mem.eql(u8, field_name, "minimum_zig_version")) { |
| 209 | 203 | const version_text = try parseString(p, field_init); |
| 210 | 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 | 206 | break :v null; |
| 213 | 207 | }; |
| 214 | 208 | } else { |
| ... | ... | @@ -251,11 +245,10 @@ const Parse = struct { |
| 251 | 245 | |
| 252 | 246 | fn parseDependencies(p: *Parse, node: Ast.Node.Index) !void { |
| 253 | 247 | const ast = p.ast; |
| 254 | const main_tokens = ast.nodes.items(.main_token); | |
| 255 | 248 | |
| 256 | 249 | var buf: [2]Ast.Node.Index = undefined; |
| 257 | 250 | const struct_init = ast.fullStructInit(&buf, node) orelse { |
| 258 | const tok = main_tokens[node]; | |
| 251 | const tok = ast.nodeMainToken(node); | |
| 259 | 252 | return fail(p, tok, "expected dependencies expression to be a struct", .{}); |
| 260 | 253 | }; |
| 261 | 254 | |
| ... | ... | @@ -269,23 +262,22 @@ const Parse = struct { |
| 269 | 262 | |
| 270 | 263 | fn parseDependency(p: *Parse, node: Ast.Node.Index) !Dependency { |
| 271 | 264 | const ast = p.ast; |
| 272 | const main_tokens = ast.nodes.items(.main_token); | |
| 273 | 265 | |
| 274 | 266 | var buf: [2]Ast.Node.Index = undefined; |
| 275 | 267 | const struct_init = ast.fullStructInit(&buf, node) orelse { |
| 276 | const tok = main_tokens[node]; | |
| 268 | const tok = ast.nodeMainToken(node); | |
| 277 | 269 | return fail(p, tok, "expected dependency expression to be a struct", .{}); |
| 278 | 270 | }; |
| 279 | 271 | |
| 280 | 272 | var dep: Dependency = .{ |
| 281 | 273 | .location = undefined, |
| 282 | .location_tok = 0, | |
| 274 | .location_tok = undefined, | |
| 283 | 275 | .location_node = undefined, |
| 284 | 276 | .hash = null, |
| 285 | .hash_tok = 0, | |
| 286 | .hash_node = undefined, | |
| 277 | .hash_tok = .none, | |
| 278 | .hash_node = .none, | |
| 287 | 279 | .node = node, |
| 288 | .name_tok = 0, | |
| 280 | .name_tok = undefined, | |
| 289 | 281 | .lazy = false, |
| 290 | 282 | }; |
| 291 | 283 | var has_location = false; |
| ... | ... | @@ -299,7 +291,7 @@ const Parse = struct { |
| 299 | 291 | // that is desirable on a per-field basis. |
| 300 | 292 | if (mem.eql(u8, field_name, "url")) { |
| 301 | 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 | 296 | dep.location = .{ |
| 305 | 297 | .url = parseString(p, field_init) catch |err| switch (err) { |
| ... | ... | @@ -308,11 +300,11 @@ const Parse = struct { |
| 308 | 300 | }, |
| 309 | 301 | }; |
| 310 | 302 | has_location = true; |
| 311 | dep.location_tok = main_tokens[field_init]; | |
| 303 | dep.location_tok = ast.nodeMainToken(field_init); | |
| 312 | 304 | dep.location_node = field_init; |
| 313 | 305 | } else if (mem.eql(u8, field_name, "path")) { |
| 314 | 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 | 309 | dep.location = .{ |
| 318 | 310 | .path = parseString(p, field_init) catch |err| switch (err) { |
| ... | ... | @@ -321,15 +313,15 @@ const Parse = struct { |
| 321 | 313 | }, |
| 322 | 314 | }; |
| 323 | 315 | has_location = true; |
| 324 | dep.location_tok = main_tokens[field_init]; | |
| 316 | dep.location_tok = ast.nodeMainToken(field_init); | |
| 325 | 317 | dep.location_node = field_init; |
| 326 | 318 | } else if (mem.eql(u8, field_name, "hash")) { |
| 327 | 319 | dep.hash = parseHash(p, field_init) catch |err| switch (err) { |
| 328 | 320 | error.ParseFailure => continue, |
| 329 | 321 | else => |e| return e, |
| 330 | 322 | }; |
| 331 | dep.hash_tok = main_tokens[field_init]; | |
| 332 | dep.hash_node = field_init; | |
| 323 | dep.hash_tok = .fromToken(ast.nodeMainToken(field_init)); | |
| 324 | dep.hash_node = field_init.toOptional(); | |
| 333 | 325 | } else if (mem.eql(u8, field_name, "lazy")) { |
| 334 | 326 | dep.lazy = parseBool(p, field_init) catch |err| switch (err) { |
| 335 | 327 | error.ParseFailure => continue, |
| ... | ... | @@ -342,7 +334,7 @@ const Parse = struct { |
| 342 | 334 | } |
| 343 | 335 | |
| 344 | 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 | } |
| 347 | 339 | |
| 348 | 340 | return dep; |
| ... | ... | @@ -350,11 +342,10 @@ const Parse = struct { |
| 350 | 342 | |
| 351 | 343 | fn parseIncludedPaths(p: *Parse, node: Ast.Node.Index) !void { |
| 352 | 344 | const ast = p.ast; |
| 353 | const main_tokens = ast.nodes.items(.main_token); | |
| 354 | 345 | |
| 355 | 346 | var buf: [2]Ast.Node.Index = undefined; |
| 356 | 347 | const array_init = ast.fullArrayInit(&buf, node) orelse { |
| 357 | const tok = main_tokens[node]; | |
| 348 | const tok = ast.nodeMainToken(node); | |
| 358 | 349 | return fail(p, tok, "expected paths expression to be a list of strings", .{}); |
| 359 | 350 | }; |
| 360 | 351 | |
| ... | ... | @@ -369,12 +360,10 @@ const Parse = struct { |
| 369 | 360 | |
| 370 | 361 | fn parseBool(p: *Parse, node: Ast.Node.Index) !bool { |
| 371 | 362 | const ast = p.ast; |
| 372 | const node_tags = ast.nodes.items(.tag); | |
| 373 | const main_tokens = ast.nodes.items(.main_token); | |
| 374 | if (node_tags[node] != .identifier) { | |
| 375 | return fail(p, main_tokens[node], "expected identifier", .{}); | |
| 363 | if (ast.nodeTag(node) != .identifier) { | |
| 364 | return fail(p, ast.nodeMainToken(node), "expected identifier", .{}); | |
| 376 | 365 | } |
| 377 | const ident_token = main_tokens[node]; | |
| 366 | const ident_token = ast.nodeMainToken(node); | |
| 378 | 367 | const token_bytes = ast.tokenSlice(ident_token); |
| 379 | 368 | if (mem.eql(u8, token_bytes, "true")) { |
| 380 | 369 | return true; |
| ... | ... | @@ -387,10 +376,8 @@ const Parse = struct { |
| 387 | 376 | |
| 388 | 377 | fn parseFingerprint(p: *Parse, node: Ast.Node.Index) !Package.Fingerprint { |
| 389 | 378 | const ast = p.ast; |
| 390 | const node_tags = ast.nodes.items(.tag); | |
| 391 | const main_tokens = ast.nodes.items(.main_token); | |
| 392 | const main_token = main_tokens[node]; | |
| 393 | if (node_tags[node] != .number_literal) { | |
| 379 | const main_token = ast.nodeMainToken(node); | |
| 380 | if (ast.nodeTag(node) != .number_literal) { | |
| 394 | 381 | return fail(p, main_token, "expected integer literal", .{}); |
| 395 | 382 | } |
| 396 | 383 | const token_bytes = ast.tokenSlice(main_token); |
| ... | ... | @@ -406,11 +393,9 @@ const Parse = struct { |
| 406 | 393 | |
| 407 | 394 | fn parseName(p: *Parse, node: Ast.Node.Index) ![]const u8 { |
| 408 | 395 | const ast = p.ast; |
| 409 | const node_tags = ast.nodes.items(.tag); | |
| 410 | const main_tokens = ast.nodes.items(.main_token); | |
| 411 | const main_token = main_tokens[node]; | |
| 396 | const main_token = ast.nodeMainToken(node); | |
| 412 | 397 | |
| 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 | 399 | const name = try parseString(p, node); |
| 415 | 400 | if (!std.zig.isValidId(name)) |
| 416 | 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 | 408 | return name; |
| 424 | 409 | } |
| 425 | 410 | |
| 426 | if (node_tags[node] != .enum_literal) | |
| 411 | if (ast.nodeTag(node) != .enum_literal) | |
| 427 | 412 | return fail(p, main_token, "expected enum literal", .{}); |
| 428 | 413 | |
| 429 | 414 | const ident_name = ast.tokenSlice(main_token); |
| ... | ... | @@ -440,12 +425,10 @@ const Parse = struct { |
| 440 | 425 | |
| 441 | 426 | fn parseString(p: *Parse, node: Ast.Node.Index) ![]const u8 { |
| 442 | 427 | const ast = p.ast; |
| 443 | const node_tags = ast.nodes.items(.tag); | |
| 444 | const main_tokens = ast.nodes.items(.main_token); | |
| 445 | if (node_tags[node] != .string_literal) { | |
| 446 | return fail(p, main_tokens[node], "expected string literal", .{}); | |
| 428 | if (ast.nodeTag(node) != .string_literal) { | |
| 429 | return fail(p, ast.nodeMainToken(node), "expected string literal", .{}); | |
| 447 | 430 | } |
| 448 | const str_lit_token = main_tokens[node]; | |
| 431 | const str_lit_token = ast.nodeMainToken(node); | |
| 449 | 432 | const token_bytes = ast.tokenSlice(str_lit_token); |
| 450 | 433 | p.buf.clearRetainingCapacity(); |
| 451 | 434 | try parseStrLit(p, str_lit_token, &p.buf, token_bytes, 0); |
| ... | ... | @@ -455,8 +438,7 @@ const Parse = struct { |
| 455 | 438 | |
| 456 | 439 | fn parseHash(p: *Parse, node: Ast.Node.Index) ![]const u8 { |
| 457 | 440 | const ast = p.ast; |
| 458 | const main_tokens = ast.nodes.items(.main_token); | |
| 459 | const tok = main_tokens[node]; | |
| 441 | const tok = ast.nodeMainToken(node); | |
| 460 | 442 | const h = try parseString(p, node); |
| 461 | 443 | |
| 462 | 444 | if (h.len > Package.Hash.max_len) { |
| ... | ... | @@ -469,8 +451,7 @@ const Parse = struct { |
| 469 | 451 | /// TODO: try to DRY this with AstGen.identifierTokenString |
| 470 | 452 | fn identifierTokenString(p: *Parse, token: Ast.TokenIndex) InnerError![]const u8 { |
| 471 | 453 | const ast = p.ast; |
| 472 | const token_tags = ast.tokens.items(.tag); | |
| 473 | assert(token_tags[token] == .identifier); | |
| 454 | assert(ast.tokenTag(token) == .identifier); | |
| 474 | 455 | const ident_name = ast.tokenSlice(token); |
| 475 | 456 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 476 | 457 | return ident_name; |
src/Sema.zig+110-87| ... | ... | @@ -407,18 +407,18 @@ pub const Block = struct { |
| 407 | 407 | return block.comptime_reason != null; |
| 408 | 408 | } |
| 409 | 409 | |
| 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 | 411 | return block.src(.{ .node_offset_builtin_call_arg = .{ |
| 412 | 412 | .builtin_call_node = builtin_call_node, |
| 413 | 413 | .arg_index = arg_index, |
| 414 | 414 | } }); |
| 415 | 415 | } |
| 416 | 416 | |
| 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 | 418 | return block.src(LazySrcLoc.Offset.nodeOffset(node_offset)); |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | fn tokenOffset(block: Block, tok_offset: u32) LazySrcLoc { | |
| 421 | fn tokenOffset(block: Block, tok_offset: std.zig.Ast.TokenOffset) LazySrcLoc { | |
| 422 | 422 | return block.src(.{ .token_offset = tok_offset }); |
| 423 | 423 | } |
| 424 | 424 | |
| ... | ... | @@ -1860,7 +1860,7 @@ fn analyzeBodyInner( |
| 1860 | 1860 | if (!block.isComptime()) break :blk try sema.zirTry(block, inst); |
| 1861 | 1861 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1862 | 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 | 1864 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 1865 | 1865 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1866 | 1866 | const err_union = try sema.resolveInst(extra.data.operand); |
| ... | ... | @@ -1883,7 +1883,7 @@ fn analyzeBodyInner( |
| 1883 | 1883 | if (!block.isComptime()) break :blk try sema.zirTryPtr(block, inst); |
| 1884 | 1884 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 1885 | 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 | 1887 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 1888 | 1888 | const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 1889 | 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 | 2166 | const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty)); |
| 2167 | 2167 | |
| 2168 | 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 | 2170 | try stack_trace_ty.resolveFields(pt); |
| 2171 | 2171 | const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); |
| 2172 | 2172 | |
| ... | ... | @@ -2901,7 +2901,7 @@ fn zirStructDecl( |
| 2901 | 2901 | const tracked_inst = try block.trackZir(inst); |
| 2902 | 2902 | const src: LazySrcLoc = .{ |
| 2903 | 2903 | .base_node_inst = tracked_inst, |
| 2904 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 2904 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 2905 | 2905 | }; |
| 2906 | 2906 | |
| 2907 | 2907 | var extra_index = extra.end; |
| ... | ... | @@ -3114,7 +3114,7 @@ fn zirEnumDecl( |
| 3114 | 3114 | var extra_index: usize = extra.end; |
| 3115 | 3115 | |
| 3116 | 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) }; | |
| 3118 | 3118 | |
| 3119 | 3119 | const tag_type_ref = if (small.has_tag_type) blk: { |
| 3120 | 3120 | const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| ... | ... | @@ -3277,7 +3277,7 @@ fn zirUnionDecl( |
| 3277 | 3277 | var extra_index: usize = extra.end; |
| 3278 | 3278 | |
| 3279 | 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) }; | |
| 3281 | 3281 | |
| 3282 | 3282 | extra_index += @intFromBool(small.has_tag_type); |
| 3283 | 3283 | const captures_len = if (small.has_captures_len) blk: { |
| ... | ... | @@ -3402,7 +3402,7 @@ fn zirOpaqueDecl( |
| 3402 | 3402 | var extra_index: usize = extra.end; |
| 3403 | 3403 | |
| 3404 | 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) }; | |
| 3406 | 3406 | |
| 3407 | 3407 | const captures_len = if (small.has_captures_len) blk: { |
| 3408 | 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 | 3835 | if (try elem_ty.comptimeOnlySema(pt)) { |
| 3836 | 3836 | // The value was initialized through RLS, so we didn't detect the runtime condition earlier. |
| 3837 | 3837 | // 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 | 3839 | return sema.fail(block, init_src, "value with comptime-only type '{}' depends on runtime control flow", .{elem_ty.fmt(pt)}); |
| 3840 | 3840 | } |
| 3841 | 3841 | |
| ... | ... | @@ -6690,8 +6690,8 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError |
| 6690 | 6690 | if (block.label) |label| { |
| 6691 | 6691 | if (label.zir_block == zir_block) { |
| 6692 | 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) | |
| 6694 | start_block.nodeOffset(extra.operand_src_node) | |
| 6693 | const src_loc = if (extra.operand_src_node.unwrap()) |operand_src_node| | |
| 6694 | start_block.nodeOffset(operand_src_node) | |
| 6695 | 6695 | else |
| 6696 | 6696 | null; |
| 6697 | 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 | 6715 | |
| 6716 | 6716 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; |
| 6717 | 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); | |
| 6719 | const operand_src = start_block.nodeOffset(extra.operand_src_node); | |
| 6718 | const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?); | |
| 6720 | 6719 | const uncoerced_operand = try sema.resolveInst(inst_data.operand); |
| 6721 | 6720 | const switch_inst = extra.block_inst; |
| 6722 | 6721 | |
| ... | ... | @@ -7048,7 +7047,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref |
| 7048 | 7047 | |
| 7049 | 7048 | if (!block.ownerModule().error_tracing) return .none; |
| 7050 | 7049 | |
| 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 | 7051 | try stack_trace_ty.resolveFields(pt); |
| 7053 | 7052 | const field_name = try zcu.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls); |
| 7054 | 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 | 7345 | if (maybe_func_inst) |func_inst| { |
| 7347 | 7346 | try sema.errNote(.{ |
| 7348 | 7347 | .base_node_inst = func_inst, |
| 7349 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 7348 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 7350 | 7349 | }, msg, "function declared here", .{}); |
| 7351 | 7350 | } |
| 7352 | 7351 | break :msg msg; |
| ... | ... | @@ -7418,7 +7417,7 @@ const CallArgsInfo = union(enum) { |
| 7418 | 7417 | /// The list of resolved (but uncoerced) arguments is known ahead of time, but |
| 7419 | 7418 | /// originated from a usage of the @call builtin at the given node offset. |
| 7420 | 7419 | call_builtin: struct { |
| 7421 | call_node_offset: i32, | |
| 7420 | call_node_offset: std.zig.Ast.Node.Offset, | |
| 7422 | 7421 | args: []const Air.Inst.Ref, |
| 7423 | 7422 | }, |
| 7424 | 7423 | |
| ... | ... | @@ -7436,7 +7435,7 @@ const CallArgsInfo = union(enum) { |
| 7436 | 7435 | /// analyzing arguments. |
| 7437 | 7436 | call_inst: Zir.Inst.Index, |
| 7438 | 7437 | /// The node offset of `call_inst`. |
| 7439 | call_node_offset: i32, | |
| 7438 | call_node_offset: std.zig.Ast.Node.Offset, | |
| 7440 | 7439 | /// The number of arguments to this call, not including `bound_arg`. |
| 7441 | 7440 | num_args: u32, |
| 7442 | 7441 | /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it |
| ... | ... | @@ -7599,7 +7598,7 @@ fn analyzeCall( |
| 7599 | 7598 | const maybe_func_inst = try sema.funcDeclSrcInst(callee); |
| 7600 | 7599 | const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{ |
| 7601 | 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 | 7602 | } else func_src; |
| 7604 | 7603 | |
| 7605 | 7604 | const func_ty_info = zcu.typeToFunc(func_ty).?; |
| ... | ... | @@ -7613,7 +7612,7 @@ fn analyzeCall( |
| 7613 | 7612 | errdefer msg.destroy(gpa); |
| 7614 | 7613 | if (maybe_func_inst) |func_inst| try sema.errNote(.{ |
| 7615 | 7614 | .base_node_inst = func_inst, |
| 7616 | .offset = .nodeOffset(0), | |
| 7615 | .offset = .nodeOffset(.zero), | |
| 7617 | 7616 | }, msg, "function declared here", .{}); |
| 7618 | 7617 | break :msg msg; |
| 7619 | 7618 | }); |
| ... | ... | @@ -9574,7 +9573,7 @@ const Section = union(enum) { |
| 9574 | 9573 | fn funcCommon( |
| 9575 | 9574 | sema: *Sema, |
| 9576 | 9575 | block: *Block, |
| 9577 | src_node_offset: i32, | |
| 9576 | src_node_offset: std.zig.Ast.Node.Offset, | |
| 9578 | 9577 | func_inst: Zir.Inst.Index, |
| 9579 | 9578 | cc: std.builtin.CallingConvention, |
| 9580 | 9579 | /// this might be Type.generic_poison |
| ... | ... | @@ -9948,7 +9947,7 @@ fn finishFunc( |
| 9948 | 9947 | if (!is_generic and sema.wantErrorReturnTracing(return_type)) { |
| 9949 | 9948 | // Make sure that StackTrace's fields are resolved so that the backend can |
| 9950 | 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 | 9951 | try unresolved_stack_trace_ty.resolveFields(pt); |
| 9953 | 9952 | } |
| 9954 | 9953 | |
| ... | ... | @@ -12599,7 +12598,7 @@ fn analyzeSwitchRuntimeBlock( |
| 12599 | 12598 | union_originally: bool, |
| 12600 | 12599 | maybe_union_ty: Type, |
| 12601 | 12600 | err_set: bool, |
| 12602 | switch_node_offset: i32, | |
| 12601 | switch_node_offset: std.zig.Ast.Node.Offset, | |
| 12603 | 12602 | special_prong_src: LazySrcLoc, |
| 12604 | 12603 | seen_enum_fields: []?LazySrcLoc, |
| 12605 | 12604 | seen_errors: SwitchErrorSet, |
| ... | ... | @@ -13219,7 +13218,7 @@ fn resolveSwitchComptimeLoop( |
| 13219 | 13218 | maybe_ptr_operand_ty: Type, |
| 13220 | 13219 | cond_ty: Type, |
| 13221 | 13220 | init_cond_val: Value, |
| 13222 | switch_node_offset: i32, | |
| 13221 | switch_node_offset: std.zig.Ast.Node.Offset, | |
| 13223 | 13222 | special: SpecialProng, |
| 13224 | 13223 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 13225 | 13224 | scalar_cases_len: u32, |
| ... | ... | @@ -13255,7 +13254,7 @@ fn resolveSwitchComptimeLoop( |
| 13255 | 13254 | const extra = sema.code.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data; |
| 13256 | 13255 | if (extra.block_inst != spa.switch_block_inst) return error.ComptimeBreak; |
| 13257 | 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 | 13258 | const new_operand_uncoerced = try sema.resolveInst(break_inst.data.@"break".operand); |
| 13260 | 13259 | const new_operand = try sema.coerce(child_block, maybe_ptr_operand_ty, new_operand_uncoerced, src); |
| 13261 | 13260 | |
| ... | ... | @@ -13287,7 +13286,7 @@ fn resolveSwitchComptime( |
| 13287 | 13286 | cond_operand: Air.Inst.Ref, |
| 13288 | 13287 | operand_val: Value, |
| 13289 | 13288 | operand_ty: Type, |
| 13290 | switch_node_offset: i32, | |
| 13289 | switch_node_offset: std.zig.Ast.Node.Offset, | |
| 13291 | 13290 | special: SpecialProng, |
| 13292 | 13291 | case_vals: std.ArrayListUnmanaged(Air.Inst.Ref), |
| 13293 | 13292 | scalar_cases_len: u32, |
| ... | ... | @@ -13837,7 +13836,7 @@ fn validateSwitchNoRange( |
| 13837 | 13836 | block: *Block, |
| 13838 | 13837 | ranges_len: u32, |
| 13839 | 13838 | operand_ty: Type, |
| 13840 | src_node_offset: i32, | |
| 13839 | src_node_offset: std.zig.Ast.Node.Offset, | |
| 13841 | 13840 | ) CompileError!void { |
| 13842 | 13841 | if (ranges_len == 0) |
| 13843 | 13842 | return; |
| ... | ... | @@ -14158,14 +14157,24 @@ fn zirShl( |
| 14158 | 14157 | const pt = sema.pt; |
| 14159 | 14158 | const zcu = pt.zcu; |
| 14160 | 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 | 14160 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14165 | 14161 | const lhs = try sema.resolveInst(extra.lhs); |
| 14166 | 14162 | const rhs = try sema.resolveInst(extra.rhs); |
| 14167 | 14163 | const lhs_ty = sema.typeOf(lhs); |
| 14168 | 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 | 14178 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 14170 | 14179 | |
| 14171 | 14180 | const scalar_ty = lhs_ty.scalarType(zcu); |
| ... | ... | @@ -14329,14 +14338,24 @@ fn zirShr( |
| 14329 | 14338 | const pt = sema.pt; |
| 14330 | 14339 | const zcu = pt.zcu; |
| 14331 | 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 | 14341 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 14336 | 14342 | const lhs = try sema.resolveInst(extra.lhs); |
| 14337 | 14343 | const rhs = try sema.resolveInst(extra.rhs); |
| 14338 | 14344 | const lhs_ty = sema.typeOf(lhs); |
| 14339 | 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 | 14359 | try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src); |
| 14341 | 14360 | const scalar_ty = lhs_ty.scalarType(zcu); |
| 14342 | 14361 | |
| ... | ... | @@ -14560,7 +14579,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 14560 | 14579 | fn analyzeTupleCat( |
| 14561 | 14580 | sema: *Sema, |
| 14562 | 14581 | block: *Block, |
| 14563 | src_node: i32, | |
| 14582 | src_node: std.zig.Ast.Node.Offset, | |
| 14564 | 14583 | lhs: Air.Inst.Ref, |
| 14565 | 14584 | rhs: Air.Inst.Ref, |
| 14566 | 14585 | ) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -15005,7 +15024,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 15005 | 15024 | fn analyzeTupleMul( |
| 15006 | 15025 | sema: *Sema, |
| 15007 | 15026 | block: *Block, |
| 15008 | src_node: i32, | |
| 15027 | src_node: std.zig.Ast.Node.Offset, | |
| 15009 | 15028 | operand: Air.Inst.Ref, |
| 15010 | 15029 | factor: usize, |
| 15011 | 15030 | ) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -15494,8 +15513,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15494 | 15513 | const zcu = pt.zcu; |
| 15495 | 15514 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 15496 | 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 }); | |
| 15498 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 15516 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 15517 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 15499 | 15518 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15500 | 15519 | const lhs = try sema.resolveInst(extra.lhs); |
| 15501 | 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 | 15679 | const zcu = pt.zcu; |
| 15661 | 15680 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 15662 | 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 }); | |
| 15664 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 15682 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 15683 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 15665 | 15684 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15666 | 15685 | const lhs = try sema.resolveInst(extra.lhs); |
| 15667 | 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 | 15790 | const zcu = pt.zcu; |
| 15772 | 15791 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 15773 | 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 }); | |
| 15775 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 15793 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 15794 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 15776 | 15795 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 15777 | 15796 | const lhs = try sema.resolveInst(extra.lhs); |
| 15778 | 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 | 16220 | const zcu = pt.zcu; |
| 16202 | 16221 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 16203 | 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 }); | |
| 16205 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 16223 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 16224 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 16206 | 16225 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 16207 | 16226 | const lhs = try sema.resolveInst(extra.lhs); |
| 16208 | 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 | 16316 | const zcu = pt.zcu; |
| 16298 | 16317 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 16299 | 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 }); | |
| 16301 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 16319 | const lhs_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 16320 | const rhs_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 16302 | 16321 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 16303 | 16322 | const lhs = try sema.resolveInst(extra.lhs); |
| 16304 | 16323 | const rhs = try sema.resolveInst(extra.rhs); |
| ... | ... | @@ -17873,7 +17892,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17873 | 17892 | const ip = &zcu.intern_pool; |
| 17874 | 17893 | const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu); |
| 17875 | 17894 | |
| 17876 | const src_node: i32 = @bitCast(extended.operand); | |
| 17895 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 17877 | 17896 | const src = block.nodeOffset(src_node); |
| 17878 | 17897 | |
| 17879 | 17898 | const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) { |
| ... | ... | @@ -17897,8 +17916,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17897 | 17916 | }); |
| 17898 | 17917 | break :name null; |
| 17899 | 17918 | }; |
| 17900 | const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); | |
| 17901 | const token = tree.nodes.items(.main_token)[node]; | |
| 17919 | const node = src_node.toAbsolute(src_base_node); | |
| 17920 | const token = tree.nodeMainToken(node); | |
| 17902 | 17921 | break :name tree.tokenSlice(token); |
| 17903 | 17922 | }; |
| 17904 | 17923 | |
| ... | ... | @@ -17925,8 +17944,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17925 | 17944 | }); |
| 17926 | 17945 | break :name null; |
| 17927 | 17946 | }; |
| 17928 | const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); | |
| 17929 | const token = tree.nodes.items(.main_token)[node]; | |
| 17947 | const node = src_node.toAbsolute(src_base_node); | |
| 17948 | const token = tree.nodeMainToken(node); | |
| 17930 | 17949 | break :name tree.tokenSlice(token); |
| 17931 | 17950 | }; |
| 17932 | 17951 | |
| ... | ... | @@ -17936,7 +17955,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17936 | 17955 | try sema.errMsg(src, "variable not accessible from inner function", .{}); |
| 17937 | 17956 | errdefer msg.destroy(sema.gpa); |
| 17938 | 17957 | |
| 17939 | try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{}); | |
| 17958 | try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{}); | |
| 17940 | 17959 | |
| 17941 | 17960 | // TODO add "declared here" note |
| 17942 | 17961 | break :msg msg; |
| ... | ... | @@ -17968,7 +17987,8 @@ fn zirFrameAddress( |
| 17968 | 17987 | block: *Block, |
| 17969 | 17988 | extended: Zir.Inst.Extended.InstData, |
| 17970 | 17989 | ) CompileError!Air.Inst.Ref { |
| 17971 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 17990 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 17991 | const src = block.nodeOffset(src_node); | |
| 17972 | 17992 | try sema.requireRuntimeBlock(block, src, null); |
| 17973 | 17993 | return try block.addNoOp(.frame_addr); |
| 17974 | 17994 | } |
| ... | ... | @@ -18065,7 +18085,7 @@ fn zirBuiltinSrc( |
| 18065 | 18085 | } }); |
| 18066 | 18086 | }; |
| 18067 | 18087 | |
| 18068 | const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation); | |
| 18088 | const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation); | |
| 18069 | 18089 | const fields = .{ |
| 18070 | 18090 | // module: [:0]const u8, |
| 18071 | 18091 | module_name_val, |
| ... | ... | @@ -19534,7 +19554,7 @@ fn zirCondbr( |
| 19534 | 19554 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19535 | 19555 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19536 | 19556 | const src = parent_block.nodeOffset(inst_data.src_node); |
| 19537 | const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 19557 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); | |
| 19538 | 19558 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 19539 | 19559 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 19540 | 19560 | const err_union = try sema.resolveInst(extra.data.operand); |
| ... | ... | @@ -19593,7 +19613,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19593 | 19613 | fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19594 | 19614 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19595 | 19615 | const src = parent_block.nodeOffset(inst_data.src_node); |
| 19596 | const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 19616 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); | |
| 19597 | 19617 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 19598 | 19618 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 19599 | 19619 | const operand = try sema.resolveInst(extra.data.operand); |
| ... | ... | @@ -19796,7 +19816,7 @@ fn zirRetImplicit( |
| 19796 | 19816 | } |
| 19797 | 19817 | |
| 19798 | 19818 | const operand = try sema.resolveInst(inst_data.operand); |
| 19799 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 }); | |
| 19819 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero }); | |
| 19800 | 19820 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu); |
| 19801 | 19821 | if (base_tag == .noreturn) { |
| 19802 | 19822 | const msg = msg: { |
| ... | ... | @@ -21283,7 +21303,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 21283 | 21303 | const pt = sema.pt; |
| 21284 | 21304 | const zcu = pt.zcu; |
| 21285 | 21305 | const ip = &zcu.intern_pool; |
| 21286 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace); | |
| 21306 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); | |
| 21287 | 21307 | try stack_trace_ty.resolveFields(pt); |
| 21288 | 21308 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 21289 | 21309 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| ... | ... | @@ -21305,7 +21325,8 @@ fn zirFrame( |
| 21305 | 21325 | block: *Block, |
| 21306 | 21326 | extended: Zir.Inst.Extended.InstData, |
| 21307 | 21327 | ) CompileError!Air.Inst.Ref { |
| 21308 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 21328 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 21329 | const src = block.nodeOffset(src_node); | |
| 21309 | 21330 | return sema.failWithUseOfAsync(block, src); |
| 21310 | 21331 | } |
| 21311 | 21332 | |
| ... | ... | @@ -21559,13 +21580,13 @@ fn zirReify( |
| 21559 | 21580 | const tracked_inst = try block.trackZir(inst); |
| 21560 | 21581 | const src: LazySrcLoc = .{ |
| 21561 | 21582 | .base_node_inst = tracked_inst, |
| 21562 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 21583 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 21563 | 21584 | }; |
| 21564 | 21585 | const operand_src: LazySrcLoc = .{ |
| 21565 | 21586 | .base_node_inst = tracked_inst, |
| 21566 | 21587 | .offset = .{ |
| 21567 | 21588 | .node_offset_builtin_call_arg = .{ |
| 21568 | .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 | |
| 21589 | .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 | |
| 21569 | 21590 | .arg_index = 0, |
| 21570 | 21591 | }, |
| 21571 | 21592 | }, |
| ... | ... | @@ -22873,7 +22894,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 22873 | 22894 | } |
| 22874 | 22895 | |
| 22875 | 22896 | fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 22876 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 22897 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 22898 | const src = block.nodeOffset(src_node); | |
| 22877 | 22899 | |
| 22878 | 22900 | const va_list_ty = try sema.getBuiltinType(src, .VaList); |
| 22879 | 22901 | try sema.requireRuntimeBlock(block, src, null); |
| ... | ... | @@ -24278,12 +24300,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 24278 | 24300 | fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 { |
| 24279 | 24301 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 24280 | 24302 | const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); |
| 24281 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 24282 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 24303 | const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 24304 | const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 24283 | 24305 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 24284 | 24306 | |
| 24285 | const ty = try sema.resolveType(block, lhs_src, extra.lhs); | |
| 24286 | const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name }); | |
| 24307 | const ty = try sema.resolveType(block, ty_src, extra.lhs); | |
| 24308 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); | |
| 24287 | 24309 | |
| 24288 | 24310 | const pt = sema.pt; |
| 24289 | 24311 | const zcu = pt.zcu; |
| ... | ... | @@ -24291,15 +24313,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 24291 | 24313 | try ty.resolveLayout(pt); |
| 24292 | 24314 | switch (ty.zigTypeTag(zcu)) { |
| 24293 | 24315 | .@"struct" => {}, |
| 24294 | else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}), | |
| 24316 | else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}), | |
| 24295 | 24317 | } |
| 24296 | 24318 | |
| 24297 | 24319 | const field_index = if (ty.isTuple(zcu)) blk: { |
| 24298 | 24320 | if (field_name.eqlSlice("len", ip)) { |
| 24299 | 24321 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); |
| 24300 | 24322 | } |
| 24301 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); | |
| 24302 | } else try sema.structFieldIndex(block, ty, field_name, rhs_src); | |
| 24323 | break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src); | |
| 24324 | } else try sema.structFieldIndex(block, ty, field_name, field_name_src); | |
| 24303 | 24325 | |
| 24304 | 24326 | if (ty.structFieldIsComptime(field_index, zcu)) { |
| 24305 | 24327 | return sema.fail(block, src, "no offset available for comptime field", .{}); |
| ... | ... | @@ -25083,7 +25105,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 25083 | 25105 | fn analyzeShuffle( |
| 25084 | 25106 | sema: *Sema, |
| 25085 | 25107 | block: *Block, |
| 25086 | src_node: i32, | |
| 25108 | src_node: std.zig.Ast.Node.Offset, | |
| 25087 | 25109 | elem_ty: Type, |
| 25088 | 25110 | a_arg: Air.Inst.Ref, |
| 25089 | 25111 | b_arg: Air.Inst.Ref, |
| ... | ... | @@ -27010,7 +27032,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 27010 | 27032 | const gpa = zcu.gpa; |
| 27011 | 27033 | const ip = &zcu.intern_pool; |
| 27012 | 27034 | |
| 27013 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 27035 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 27036 | const src = block.nodeOffset(src_node); | |
| 27014 | 27037 | const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); |
| 27015 | 27038 | |
| 27016 | 27039 | const ty = switch (value) { |
| ... | ... | @@ -29485,7 +29508,7 @@ const CoerceOpts = struct { |
| 29485 | 29508 | return .{ |
| 29486 | 29509 | .base_node_inst = func_inst, |
| 29487 | 29510 | .offset = .{ .fn_proto_param_type = .{ |
| 29488 | .fn_proto_node_offset = 0, | |
| 29511 | .fn_proto_node_offset = .zero, | |
| 29489 | 29512 | .param_index = info.param_i, |
| 29490 | 29513 | } }, |
| 29491 | 29514 | }; |
| ... | ... | @@ -30090,7 +30113,7 @@ fn coerceExtra( |
| 30090 | 30113 | |
| 30091 | 30114 | const ret_ty_src: LazySrcLoc = .{ |
| 30092 | 30115 | .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip), |
| 30093 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, | |
| 30116 | .offset = .{ .node_offset_fn_type_ret_ty = .zero }, | |
| 30094 | 30117 | }; |
| 30095 | 30118 | try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{}); |
| 30096 | 30119 | break :msg msg; |
| ... | ... | @@ -30130,7 +30153,7 @@ fn coerceExtra( |
| 30130 | 30153 | { |
| 30131 | 30154 | const ret_ty_src: LazySrcLoc = .{ |
| 30132 | 30155 | .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip), |
| 30133 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, | |
| 30156 | .offset = .{ .node_offset_fn_type_ret_ty = .zero }, | |
| 30134 | 30157 | }; |
| 30135 | 30158 | if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) { |
| 30136 | 30159 | try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{}); |
| ... | ... | @@ -32331,7 +32354,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav |
| 32331 | 32354 | if (zcu.analysis_in_progress.contains(anal_unit)) { |
| 32332 | 32355 | return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ |
| 32333 | 32356 | .base_node_inst = nav.analysis.?.zir_index, |
| 32334 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 32357 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 32335 | 32358 | }, "dependency loop detected", .{})); |
| 32336 | 32359 | } |
| 32337 | 32360 | |
| ... | ... | @@ -33948,7 +33971,7 @@ const PeerTypeCandidateSrc = union(enum) { |
| 33948 | 33971 | /// index i in this slice |
| 33949 | 33972 | override: []const ?LazySrcLoc, |
| 33950 | 33973 | /// resolvePeerTypes originates from a @TypeOf(...) call |
| 33951 | typeof_builtin_call_node_offset: i32, | |
| 33974 | typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset, | |
| 33952 | 33975 | |
| 33953 | 33976 | pub fn resolve( |
| 33954 | 33977 | self: PeerTypeCandidateSrc, |
| ... | ... | @@ -35551,7 +35574,7 @@ fn backingIntType( |
| 35551 | 35574 | |
| 35552 | 35575 | const backing_int_src: LazySrcLoc = .{ |
| 35553 | 35576 | .base_node_inst = struct_type.zir_index, |
| 35554 | .offset = .{ .node_offset_container_tag = 0 }, | |
| 35577 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 35555 | 35578 | }; |
| 35556 | 35579 | block.comptime_reason = .{ .reason = .{ |
| 35557 | 35580 | .src = backing_int_src, |
| ... | ... | @@ -35572,7 +35595,7 @@ fn backingIntType( |
| 35572 | 35595 | struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); |
| 35573 | 35596 | } else { |
| 35574 | 35597 | if (fields_bit_sum > std.math.maxInt(u16)) { |
| 35575 | return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | |
| 35598 | return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | |
| 35576 | 35599 | } |
| 35577 | 35600 | const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); |
| 35578 | 35601 | struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); |
| ... | ... | @@ -36173,7 +36196,7 @@ fn structFields( |
| 36173 | 36196 | .comptime_reason = .{ .reason = .{ |
| 36174 | 36197 | .src = .{ |
| 36175 | 36198 | .base_node_inst = struct_type.zir_index, |
| 36176 | .offset = .nodeOffset(0), | |
| 36199 | .offset = .nodeOffset(.zero), | |
| 36177 | 36200 | }, |
| 36178 | 36201 | .r = .{ .simple = .struct_fields }, |
| 36179 | 36202 | } }, |
| ... | ... | @@ -36514,7 +36537,7 @@ fn unionFields( |
| 36514 | 36537 | |
| 36515 | 36538 | const src: LazySrcLoc = .{ |
| 36516 | 36539 | .base_node_inst = union_type.zir_index, |
| 36517 | .offset = .nodeOffset(0), | |
| 36540 | .offset = .nodeOffset(.zero), | |
| 36518 | 36541 | }; |
| 36519 | 36542 | |
| 36520 | 36543 | var block_scope: Block = .{ |
| ... | ... | @@ -36543,7 +36566,7 @@ fn unionFields( |
| 36543 | 36566 | if (tag_type_ref != .none) { |
| 36544 | 36567 | const tag_ty_src: LazySrcLoc = .{ |
| 36545 | 36568 | .base_node_inst = union_type.zir_index, |
| 36546 | .offset = .{ .node_offset_container_tag = 0 }, | |
| 36569 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 36547 | 36570 | }; |
| 36548 | 36571 | const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); |
| 36549 | 36572 | if (small.auto_enum_tag) { |
| ... | ... | @@ -38523,7 +38546,7 @@ pub fn resolveDeclaredEnum( |
| 38523 | 38546 | const zcu = pt.zcu; |
| 38524 | 38547 | const gpa = zcu.gpa; |
| 38525 | 38548 | |
| 38526 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) }; | |
| 38549 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 38527 | 38550 | |
| 38528 | 38551 | var arena: std.heap.ArenaAllocator = .init(gpa); |
| 38529 | 38552 | defer arena.deinit(); |
| ... | ... | @@ -38610,7 +38633,7 @@ fn resolveDeclaredEnumInner( |
| 38610 | 38633 | |
| 38611 | 38634 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| 38612 | 38635 | |
| 38613 | const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } }; | |
| 38636 | const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } }; | |
| 38614 | 38637 | |
| 38615 | 38638 | const int_tag_ty = ty: { |
| 38616 | 38639 | if (body.len != 0) { |
| ... | ... | @@ -38763,9 +38786,9 @@ pub fn resolveNavPtrModifiers( |
| 38763 | 38786 | const gpa = zcu.gpa; |
| 38764 | 38787 | const ip = &zcu.intern_pool; |
| 38765 | 38788 | |
| 38766 | const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); | |
| 38767 | const section_src = block.src(.{ .node_offset_var_decl_section = 0 }); | |
| 38768 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 38789 | const align_src = block.src(.{ .node_offset_var_decl_align = .zero }); | |
| 38790 | const section_src = block.src(.{ .node_offset_var_decl_section = .zero }); | |
| 38791 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero }); | |
| 38769 | 38792 | |
| 38770 | 38793 | const alignment: InternPool.Alignment = a: { |
| 38771 | 38794 | const align_body = zir_decl.align_body orelse break :a .none; |
| ... | ... | @@ -38838,7 +38861,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38838 | 38861 | |
| 38839 | 38862 | const src: LazySrcLoc = .{ |
| 38840 | 38863 | .base_node_inst = ip.getNav(nav).srcInst(ip), |
| 38841 | .offset = .nodeOffset(0), | |
| 38864 | .offset = .nodeOffset(.zero), | |
| 38842 | 38865 | }; |
| 38843 | 38866 | |
| 38844 | 38867 | const result = try sema.analyzeNavVal(block, src, nav); |
src/Type.zig+1-1| ... | ... | @@ -3505,7 +3505,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc { |
| 3505 | 3505 | }, |
| 3506 | 3506 | else => return null, |
| 3507 | 3507 | }, |
| 3508 | .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0), | |
| 3508 | .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero), | |
| 3509 | 3509 | }; |
| 3510 | 3510 | } |
| 3511 | 3511 |
src/Zcu.zig+284-314| ... | ... | @@ -134,7 +134,7 @@ failed_types: std.AutoArrayHashMapUnmanaged(InternPool.Index, *ErrorMsg) = .empt |
| 134 | 134 | /// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`. |
| 135 | 135 | compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct { |
| 136 | 136 | base_node_inst: InternPool.TrackedInst.Index, |
| 137 | node_offset: i32, | |
| 137 | node_offset: Ast.Node.Offset, | |
| 138 | 138 | pub fn src(self: @This()) LazySrcLoc { |
| 139 | 139 | return .{ |
| 140 | 140 | .base_node_inst = self.base_node_inst, |
| ... | ... | @@ -1034,10 +1034,6 @@ pub const SrcLoc = struct { |
| 1034 | 1034 | return tree.firstToken(src_loc.base_node); |
| 1035 | 1035 | } |
| 1036 | 1036 | |
| 1037 | pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index { | |
| 1038 | return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node))); | |
| 1039 | } | |
| 1040 | ||
| 1041 | 1037 | pub const Span = Ast.Span; |
| 1042 | 1038 | |
| 1043 | 1039 | pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { |
| ... | ... | @@ -1049,7 +1045,7 @@ pub const SrcLoc = struct { |
| 1049 | 1045 | |
| 1050 | 1046 | .token_abs => |tok_index| { |
| 1051 | 1047 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1052 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1048 | const start = tree.tokenStart(tok_index); | |
| 1053 | 1049 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1054 | 1050 | return Span{ .start = start, .end = end, .main = start }; |
| 1055 | 1051 | }, |
| ... | ... | @@ -1060,142 +1056,137 @@ pub const SrcLoc = struct { |
| 1060 | 1056 | .byte_offset => |byte_off| { |
| 1061 | 1057 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1062 | 1058 | const tok_index = src_loc.baseSrcToken(); |
| 1063 | const start = tree.tokens.items(.start)[tok_index] + byte_off; | |
| 1059 | const start = tree.tokenStart(tok_index) + byte_off; | |
| 1064 | 1060 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1065 | 1061 | return Span{ .start = start, .end = end, .main = start }; |
| 1066 | 1062 | }, |
| 1067 | 1063 | .token_offset => |tok_off| { |
| 1068 | 1064 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1069 | const tok_index = src_loc.baseSrcToken() + tok_off; | |
| 1070 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1065 | const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken()); | |
| 1066 | const start = tree.tokenStart(tok_index); | |
| 1071 | 1067 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1072 | 1068 | return Span{ .start = start, .end = end, .main = start }; |
| 1073 | 1069 | }, |
| 1074 | 1070 | .node_offset => |traced_off| { |
| 1075 | 1071 | const node_off = traced_off.x; |
| 1076 | 1072 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1077 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1073 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1078 | 1074 | return tree.nodeToSpan(node); |
| 1079 | 1075 | }, |
| 1080 | 1076 | .node_offset_main_token => |node_off| { |
| 1081 | 1077 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1082 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1083 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1078 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1079 | const main_token = tree.nodeMainToken(node); | |
| 1084 | 1080 | return tree.tokensToSpan(main_token, main_token, main_token); |
| 1085 | 1081 | }, |
| 1086 | 1082 | .node_offset_bin_op => |node_off| { |
| 1087 | 1083 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1088 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1084 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1089 | 1085 | return tree.nodeToSpan(node); |
| 1090 | 1086 | }, |
| 1091 | 1087 | .node_offset_initializer => |node_off| { |
| 1092 | 1088 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1093 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1089 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1094 | 1090 | return tree.tokensToSpan( |
| 1095 | 1091 | tree.firstToken(node) - 3, |
| 1096 | 1092 | tree.lastToken(node), |
| 1097 | tree.nodes.items(.main_token)[node] - 2, | |
| 1093 | tree.nodeMainToken(node) - 2, | |
| 1098 | 1094 | ); |
| 1099 | 1095 | }, |
| 1100 | 1096 | .node_offset_var_decl_ty => |node_off| { |
| 1101 | 1097 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1102 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1103 | const node_tags = tree.nodes.items(.tag); | |
| 1104 | const full = switch (node_tags[node]) { | |
| 1098 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1099 | const full = switch (tree.nodeTag(node)) { | |
| 1105 | 1100 | .global_var_decl, |
| 1106 | 1101 | .local_var_decl, |
| 1107 | 1102 | .simple_var_decl, |
| 1108 | 1103 | .aligned_var_decl, |
| 1109 | 1104 | => tree.fullVarDecl(node).?, |
| 1110 | 1105 | .@"usingnamespace" => { |
| 1111 | const node_data = tree.nodes.items(.data); | |
| 1112 | return tree.nodeToSpan(node_data[node].lhs); | |
| 1106 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1113 | 1107 | }, |
| 1114 | 1108 | else => unreachable, |
| 1115 | 1109 | }; |
| 1116 | if (full.ast.type_node != 0) { | |
| 1117 | return tree.nodeToSpan(full.ast.type_node); | |
| 1110 | if (full.ast.type_node.unwrap()) |type_node| { | |
| 1111 | return tree.nodeToSpan(type_node); | |
| 1118 | 1112 | } |
| 1119 | 1113 | const tok_index = full.ast.mut_token + 1; // the name token |
| 1120 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1114 | const start = tree.tokenStart(tok_index); | |
| 1121 | 1115 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1122 | 1116 | return Span{ .start = start, .end = end, .main = start }; |
| 1123 | 1117 | }, |
| 1124 | 1118 | .node_offset_var_decl_align => |node_off| { |
| 1125 | 1119 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1126 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1120 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1127 | 1121 | var buf: [1]Ast.Node.Index = undefined; |
| 1128 | 1122 | const align_node = if (tree.fullVarDecl(node)) |v| |
| 1129 | v.ast.align_node | |
| 1123 | v.ast.align_node.unwrap().? | |
| 1130 | 1124 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1131 | f.ast.align_expr | |
| 1125 | f.ast.align_expr.unwrap().? | |
| 1132 | 1126 | else |
| 1133 | 1127 | unreachable; |
| 1134 | 1128 | return tree.nodeToSpan(align_node); |
| 1135 | 1129 | }, |
| 1136 | 1130 | .node_offset_var_decl_section => |node_off| { |
| 1137 | 1131 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1138 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1132 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1139 | 1133 | var buf: [1]Ast.Node.Index = undefined; |
| 1140 | 1134 | const section_node = if (tree.fullVarDecl(node)) |v| |
| 1141 | v.ast.section_node | |
| 1135 | v.ast.section_node.unwrap().? | |
| 1142 | 1136 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1143 | f.ast.section_expr | |
| 1137 | f.ast.section_expr.unwrap().? | |
| 1144 | 1138 | else |
| 1145 | 1139 | unreachable; |
| 1146 | 1140 | return tree.nodeToSpan(section_node); |
| 1147 | 1141 | }, |
| 1148 | 1142 | .node_offset_var_decl_addrspace => |node_off| { |
| 1149 | 1143 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1150 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1144 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1151 | 1145 | var buf: [1]Ast.Node.Index = undefined; |
| 1152 | 1146 | const addrspace_node = if (tree.fullVarDecl(node)) |v| |
| 1153 | v.ast.addrspace_node | |
| 1147 | v.ast.addrspace_node.unwrap().? | |
| 1154 | 1148 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1155 | f.ast.addrspace_expr | |
| 1149 | f.ast.addrspace_expr.unwrap().? | |
| 1156 | 1150 | else |
| 1157 | 1151 | unreachable; |
| 1158 | 1152 | return tree.nodeToSpan(addrspace_node); |
| 1159 | 1153 | }, |
| 1160 | 1154 | .node_offset_var_decl_init => |node_off| { |
| 1161 | 1155 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1162 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1163 | const full = tree.fullVarDecl(node).?; | |
| 1164 | return tree.nodeToSpan(full.ast.init_node); | |
| 1156 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1157 | const init_node = switch (tree.nodeTag(node)) { | |
| 1158 | .global_var_decl, | |
| 1159 | .local_var_decl, | |
| 1160 | .aligned_var_decl, | |
| 1161 | .simple_var_decl, | |
| 1162 | => tree.fullVarDecl(node).?.ast.init_node.unwrap().?, | |
| 1163 | .assign_destructure => tree.assignDestructure(node).ast.value_expr, | |
| 1164 | else => unreachable, | |
| 1165 | }; | |
| 1166 | return tree.nodeToSpan(init_node); | |
| 1165 | 1167 | }, |
| 1166 | 1168 | .node_offset_builtin_call_arg => |builtin_arg| { |
| 1167 | 1169 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1168 | const node_datas = tree.nodes.items(.data); | |
| 1169 | const node_tags = tree.nodes.items(.tag); | |
| 1170 | const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node); | |
| 1171 | const param = switch (node_tags[node]) { | |
| 1172 | .builtin_call_two, .builtin_call_two_comma => switch (builtin_arg.arg_index) { | |
| 1173 | 0 => node_datas[node].lhs, | |
| 1174 | 1 => node_datas[node].rhs, | |
| 1175 | else => unreachable, | |
| 1176 | }, | |
| 1177 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + builtin_arg.arg_index], | |
| 1178 | else => unreachable, | |
| 1179 | }; | |
| 1180 | return tree.nodeToSpan(param); | |
| 1170 | const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node); | |
| 1171 | var buf: [2]Ast.Node.Index = undefined; | |
| 1172 | const params = tree.builtinCallParams(&buf, node).?; | |
| 1173 | return tree.nodeToSpan(params[builtin_arg.arg_index]); | |
| 1181 | 1174 | }, |
| 1182 | 1175 | .node_offset_ptrcast_operand => |node_off| { |
| 1183 | 1176 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1184 | const main_tokens = tree.nodes.items(.main_token); | |
| 1185 | const node_datas = tree.nodes.items(.data); | |
| 1186 | const node_tags = tree.nodes.items(.tag); | |
| 1187 | 1177 | |
| 1188 | var node = src_loc.relativeToNodeIndex(node_off); | |
| 1178 | var node = node_off.toAbsolute(src_loc.base_node); | |
| 1189 | 1179 | while (true) { |
| 1190 | switch (node_tags[node]) { | |
| 1180 | switch (tree.nodeTag(node)) { | |
| 1191 | 1181 | .builtin_call_two, .builtin_call_two_comma => {}, |
| 1192 | 1182 | else => break, |
| 1193 | 1183 | } |
| 1194 | 1184 | |
| 1195 | if (node_datas[node].lhs == 0) break; // 0 args | |
| 1196 | if (node_datas[node].rhs != 0) break; // 2 args | |
| 1185 | const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node; | |
| 1186 | if (first_arg == .none) break; // 0 args | |
| 1187 | if (second_arg != .none) break; // 2 args | |
| 1197 | 1188 | |
| 1198 | const builtin_token = main_tokens[node]; | |
| 1189 | const builtin_token = tree.nodeMainToken(node); | |
| 1199 | 1190 | const builtin_name = tree.tokenSlice(builtin_token); |
| 1200 | 1191 | const info = BuiltinFn.list.get(builtin_name) orelse break; |
| 1201 | 1192 | |
| ... | ... | @@ -1209,16 +1200,15 @@ pub const SrcLoc = struct { |
| 1209 | 1200 | => {}, |
| 1210 | 1201 | } |
| 1211 | 1202 | |
| 1212 | node = node_datas[node].lhs; | |
| 1203 | node = first_arg.unwrap().?; | |
| 1213 | 1204 | } |
| 1214 | 1205 | |
| 1215 | 1206 | return tree.nodeToSpan(node); |
| 1216 | 1207 | }, |
| 1217 | 1208 | .node_offset_array_access_index => |node_off| { |
| 1218 | 1209 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1219 | const node_datas = tree.nodes.items(.data); | |
| 1220 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1221 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1210 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1211 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1222 | 1212 | }, |
| 1223 | 1213 | .node_offset_slice_ptr, |
| 1224 | 1214 | .node_offset_slice_start, |
| ... | ... | @@ -1226,32 +1216,30 @@ pub const SrcLoc = struct { |
| 1226 | 1216 | .node_offset_slice_sentinel, |
| 1227 | 1217 | => |node_off| { |
| 1228 | 1218 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1229 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1219 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1230 | 1220 | const full = tree.fullSlice(node).?; |
| 1231 | 1221 | const part_node = switch (src_loc.lazy) { |
| 1232 | 1222 | .node_offset_slice_ptr => full.ast.sliced, |
| 1233 | 1223 | .node_offset_slice_start => full.ast.start, |
| 1234 | .node_offset_slice_end => full.ast.end, | |
| 1235 | .node_offset_slice_sentinel => full.ast.sentinel, | |
| 1224 | .node_offset_slice_end => full.ast.end.unwrap().?, | |
| 1225 | .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?, | |
| 1236 | 1226 | else => unreachable, |
| 1237 | 1227 | }; |
| 1238 | 1228 | return tree.nodeToSpan(part_node); |
| 1239 | 1229 | }, |
| 1240 | 1230 | .node_offset_call_func => |node_off| { |
| 1241 | 1231 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1242 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1232 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1243 | 1233 | var buf: [1]Ast.Node.Index = undefined; |
| 1244 | 1234 | const full = tree.fullCall(&buf, node).?; |
| 1245 | 1235 | return tree.nodeToSpan(full.ast.fn_expr); |
| 1246 | 1236 | }, |
| 1247 | 1237 | .node_offset_field_name => |node_off| { |
| 1248 | 1238 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1249 | const node_datas = tree.nodes.items(.data); | |
| 1250 | const node_tags = tree.nodes.items(.tag); | |
| 1251 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1239 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1252 | 1240 | var buf: [1]Ast.Node.Index = undefined; |
| 1253 | const tok_index = switch (node_tags[node]) { | |
| 1254 | .field_access => node_datas[node].rhs, | |
| 1241 | const tok_index = switch (tree.nodeTag(node)) { | |
| 1242 | .field_access => tree.nodeData(node).node_and_token[1], | |
| 1255 | 1243 | .call_one, |
| 1256 | 1244 | .call_one_comma, |
| 1257 | 1245 | .async_call_one, |
| ... | ... | @@ -1266,43 +1254,41 @@ pub const SrcLoc = struct { |
| 1266 | 1254 | }, |
| 1267 | 1255 | else => tree.firstToken(node) - 2, |
| 1268 | 1256 | }; |
| 1269 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1257 | const start = tree.tokenStart(tok_index); | |
| 1270 | 1258 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1271 | 1259 | return Span{ .start = start, .end = end, .main = start }; |
| 1272 | 1260 | }, |
| 1273 | 1261 | .node_offset_field_name_init => |node_off| { |
| 1274 | 1262 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1275 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1263 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1276 | 1264 | const tok_index = tree.firstToken(node) - 2; |
| 1277 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1265 | const start = tree.tokenStart(tok_index); | |
| 1278 | 1266 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1279 | 1267 | return Span{ .start = start, .end = end, .main = start }; |
| 1280 | 1268 | }, |
| 1281 | 1269 | .node_offset_deref_ptr => |node_off| { |
| 1282 | 1270 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1283 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1271 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1284 | 1272 | return tree.nodeToSpan(node); |
| 1285 | 1273 | }, |
| 1286 | 1274 | .node_offset_asm_source => |node_off| { |
| 1287 | 1275 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1288 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1276 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1289 | 1277 | const full = tree.fullAsm(node).?; |
| 1290 | 1278 | return tree.nodeToSpan(full.ast.template); |
| 1291 | 1279 | }, |
| 1292 | 1280 | .node_offset_asm_ret_ty => |node_off| { |
| 1293 | 1281 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1294 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1282 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1295 | 1283 | const full = tree.fullAsm(node).?; |
| 1296 | 1284 | const asm_output = full.outputs[0]; |
| 1297 | const node_datas = tree.nodes.items(.data); | |
| 1298 | return tree.nodeToSpan(node_datas[asm_output].lhs); | |
| 1285 | return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?); | |
| 1299 | 1286 | }, |
| 1300 | 1287 | |
| 1301 | 1288 | .node_offset_if_cond => |node_off| { |
| 1302 | 1289 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1303 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1304 | const node_tags = tree.nodes.items(.tag); | |
| 1305 | const src_node = switch (node_tags[node]) { | |
| 1290 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1291 | const src_node = switch (tree.nodeTag(node)) { | |
| 1306 | 1292 | .if_simple, |
| 1307 | 1293 | .@"if", |
| 1308 | 1294 | => tree.fullIf(node).?.ast.cond_expr, |
| ... | ... | @@ -1329,20 +1315,19 @@ pub const SrcLoc = struct { |
| 1329 | 1315 | }, |
| 1330 | 1316 | .for_input => |for_input| { |
| 1331 | 1317 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1332 | const node = src_loc.relativeToNodeIndex(for_input.for_node_offset); | |
| 1318 | const node = for_input.for_node_offset.toAbsolute(src_loc.base_node); | |
| 1333 | 1319 | const for_full = tree.fullFor(node).?; |
| 1334 | 1320 | const src_node = for_full.ast.inputs[for_input.input_index]; |
| 1335 | 1321 | return tree.nodeToSpan(src_node); |
| 1336 | 1322 | }, |
| 1337 | 1323 | .for_capture_from_input => |node_off| { |
| 1338 | 1324 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1339 | const token_tags = tree.tokens.items(.tag); | |
| 1340 | const input_node = src_loc.relativeToNodeIndex(node_off); | |
| 1325 | const input_node = node_off.toAbsolute(src_loc.base_node); | |
| 1341 | 1326 | // We have to actually linear scan the whole AST to find the for loop |
| 1342 | 1327 | // that contains this input. |
| 1343 | 1328 | const node_tags = tree.nodes.items(.tag); |
| 1344 | 1329 | for (node_tags, 0..) |node_tag, node_usize| { |
| 1345 | const node = @as(Ast.Node.Index, @intCast(node_usize)); | |
| 1330 | const node: Ast.Node.Index = @enumFromInt(node_usize); | |
| 1346 | 1331 | switch (node_tag) { |
| 1347 | 1332 | .for_simple, .@"for" => { |
| 1348 | 1333 | const for_full = tree.fullFor(node).?; |
| ... | ... | @@ -1351,7 +1336,7 @@ pub const SrcLoc = struct { |
| 1351 | 1336 | var count = input_index; |
| 1352 | 1337 | var tok = for_full.payload_token; |
| 1353 | 1338 | while (true) { |
| 1354 | switch (token_tags[tok]) { | |
| 1339 | switch (tree.tokenTag(tok)) { | |
| 1355 | 1340 | .comma => { |
| 1356 | 1341 | count -= 1; |
| 1357 | 1342 | tok += 1; |
| ... | ... | @@ -1378,13 +1363,12 @@ pub const SrcLoc = struct { |
| 1378 | 1363 | }, |
| 1379 | 1364 | .call_arg => |call_arg| { |
| 1380 | 1365 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1381 | const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset); | |
| 1366 | const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node); | |
| 1382 | 1367 | var buf: [2]Ast.Node.Index = undefined; |
| 1383 | 1368 | const call_full = tree.fullCall(buf[0..1], node) orelse { |
| 1384 | const node_tags = tree.nodes.items(.tag); | |
| 1385 | assert(node_tags[node] == .builtin_call); | |
| 1386 | const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1]; | |
| 1387 | switch (node_tags[call_args_node]) { | |
| 1369 | assert(tree.nodeTag(node) == .builtin_call); | |
| 1370 | const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]); | |
| 1371 | switch (tree.nodeTag(call_args_node)) { | |
| 1388 | 1372 | .array_init_one, |
| 1389 | 1373 | .array_init_one_comma, |
| 1390 | 1374 | .array_init_dot_two, |
| ... | ... | @@ -1416,7 +1400,7 @@ pub const SrcLoc = struct { |
| 1416 | 1400 | }, |
| 1417 | 1401 | .fn_proto_param, .fn_proto_param_type => |fn_proto_param| { |
| 1418 | 1402 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1419 | const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset); | |
| 1403 | const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node); | |
| 1420 | 1404 | var buf: [1]Ast.Node.Index = undefined; |
| 1421 | 1405 | const full = tree.fullFnProto(&buf, node).?; |
| 1422 | 1406 | var it = full.iterate(tree); |
| ... | ... | @@ -1428,14 +1412,14 @@ pub const SrcLoc = struct { |
| 1428 | 1412 | .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| { |
| 1429 | 1413 | return tree.tokenToSpan(tok); |
| 1430 | 1414 | } else { |
| 1431 | return tree.nodeToSpan(param.type_expr); | |
| 1415 | return tree.nodeToSpan(param.type_expr.?); | |
| 1432 | 1416 | }, |
| 1433 | 1417 | .fn_proto_param => if (param.anytype_ellipsis3) |tok| { |
| 1434 | 1418 | const first = param.comptime_noalias orelse param.name_token orelse tok; |
| 1435 | 1419 | return tree.tokensToSpan(first, tok, first); |
| 1436 | 1420 | } else { |
| 1437 | const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr); | |
| 1438 | return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first); | |
| 1421 | const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?); | |
| 1422 | return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first); | |
| 1439 | 1423 | }, |
| 1440 | 1424 | else => unreachable, |
| 1441 | 1425 | } |
| ... | ... | @@ -1444,28 +1428,24 @@ pub const SrcLoc = struct { |
| 1444 | 1428 | }, |
| 1445 | 1429 | .node_offset_bin_lhs => |node_off| { |
| 1446 | 1430 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1447 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1448 | const node_datas = tree.nodes.items(.data); | |
| 1449 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1431 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1432 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]); | |
| 1450 | 1433 | }, |
| 1451 | 1434 | .node_offset_bin_rhs => |node_off| { |
| 1452 | 1435 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1453 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1454 | const node_datas = tree.nodes.items(.data); | |
| 1455 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1436 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1437 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1456 | 1438 | }, |
| 1457 | 1439 | .array_cat_lhs, .array_cat_rhs => |cat| { |
| 1458 | 1440 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1459 | const node = src_loc.relativeToNodeIndex(cat.array_cat_offset); | |
| 1460 | const node_datas = tree.nodes.items(.data); | |
| 1441 | const node = cat.array_cat_offset.toAbsolute(src_loc.base_node); | |
| 1461 | 1442 | const arr_node = if (src_loc.lazy == .array_cat_lhs) |
| 1462 | node_datas[node].lhs | |
| 1443 | tree.nodeData(node).node_and_node[0] | |
| 1463 | 1444 | else |
| 1464 | node_datas[node].rhs; | |
| 1445 | tree.nodeData(node).node_and_node[1]; | |
| 1465 | 1446 | |
| 1466 | const node_tags = tree.nodes.items(.tag); | |
| 1467 | 1447 | var buf: [2]Ast.Node.Index = undefined; |
| 1468 | switch (node_tags[arr_node]) { | |
| 1448 | switch (tree.nodeTag(arr_node)) { | |
| 1469 | 1449 | .array_init_one, |
| 1470 | 1450 | .array_init_one_comma, |
| 1471 | 1451 | .array_init_dot_two, |
| ... | ... | @@ -1482,27 +1462,30 @@ pub const SrcLoc = struct { |
| 1482 | 1462 | } |
| 1483 | 1463 | }, |
| 1484 | 1464 | |
| 1465 | .node_offset_try_operand => |node_off| { | |
| 1466 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 1467 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1468 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1469 | }, | |
| 1470 | ||
| 1485 | 1471 | .node_offset_switch_operand => |node_off| { |
| 1486 | 1472 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1487 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1488 | const node_datas = tree.nodes.items(.data); | |
| 1489 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1473 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1474 | const condition, _ = tree.nodeData(node).node_and_extra; | |
| 1475 | return tree.nodeToSpan(condition); | |
| 1490 | 1476 | }, |
| 1491 | 1477 | |
| 1492 | 1478 | .node_offset_switch_special_prong => |node_off| { |
| 1493 | 1479 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1494 | const switch_node = src_loc.relativeToNodeIndex(node_off); | |
| 1495 | const node_datas = tree.nodes.items(.data); | |
| 1496 | const node_tags = tree.nodes.items(.tag); | |
| 1497 | const main_tokens = tree.nodes.items(.main_token); | |
| 1498 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1499 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1480 | const switch_node = node_off.toAbsolute(src_loc.base_node); | |
| 1481 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1482 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1500 | 1483 | for (case_nodes) |case_node| { |
| 1501 | 1484 | const case = tree.fullSwitchCase(case_node).?; |
| 1502 | 1485 | const is_special = (case.ast.values.len == 0) or |
| 1503 | 1486 | (case.ast.values.len == 1 and |
| 1504 | node_tags[case.ast.values[0]] == .identifier and | |
| 1505 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); | |
| 1487 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 1488 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")); | |
| 1506 | 1489 | if (!is_special) continue; |
| 1507 | 1490 | |
| 1508 | 1491 | return tree.nodeToSpan(case_node); |
| ... | ... | @@ -1511,22 +1494,19 @@ pub const SrcLoc = struct { |
| 1511 | 1494 | |
| 1512 | 1495 | .node_offset_switch_range => |node_off| { |
| 1513 | 1496 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1514 | const switch_node = src_loc.relativeToNodeIndex(node_off); | |
| 1515 | const node_datas = tree.nodes.items(.data); | |
| 1516 | const node_tags = tree.nodes.items(.tag); | |
| 1517 | const main_tokens = tree.nodes.items(.main_token); | |
| 1518 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1519 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1497 | const switch_node = node_off.toAbsolute(src_loc.base_node); | |
| 1498 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1499 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1520 | 1500 | for (case_nodes) |case_node| { |
| 1521 | 1501 | const case = tree.fullSwitchCase(case_node).?; |
| 1522 | 1502 | const is_special = (case.ast.values.len == 0) or |
| 1523 | 1503 | (case.ast.values.len == 1 and |
| 1524 | node_tags[case.ast.values[0]] == .identifier and | |
| 1525 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); | |
| 1504 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 1505 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")); | |
| 1526 | 1506 | if (is_special) continue; |
| 1527 | 1507 | |
| 1528 | 1508 | for (case.ast.values) |item_node| { |
| 1529 | if (node_tags[item_node] == .switch_range) { | |
| 1509 | if (tree.nodeTag(item_node) == .switch_range) { | |
| 1530 | 1510 | return tree.nodeToSpan(item_node); |
| 1531 | 1511 | } |
| 1532 | 1512 | } |
| ... | ... | @@ -1534,47 +1514,46 @@ pub const SrcLoc = struct { |
| 1534 | 1514 | }, |
| 1535 | 1515 | .node_offset_fn_type_align => |node_off| { |
| 1536 | 1516 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1537 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1517 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1538 | 1518 | var buf: [1]Ast.Node.Index = undefined; |
| 1539 | 1519 | const full = tree.fullFnProto(&buf, node).?; |
| 1540 | return tree.nodeToSpan(full.ast.align_expr); | |
| 1520 | return tree.nodeToSpan(full.ast.align_expr.unwrap().?); | |
| 1541 | 1521 | }, |
| 1542 | 1522 | .node_offset_fn_type_addrspace => |node_off| { |
| 1543 | 1523 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1544 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1524 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1545 | 1525 | var buf: [1]Ast.Node.Index = undefined; |
| 1546 | 1526 | const full = tree.fullFnProto(&buf, node).?; |
| 1547 | return tree.nodeToSpan(full.ast.addrspace_expr); | |
| 1527 | return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?); | |
| 1548 | 1528 | }, |
| 1549 | 1529 | .node_offset_fn_type_section => |node_off| { |
| 1550 | 1530 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1551 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1531 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1552 | 1532 | var buf: [1]Ast.Node.Index = undefined; |
| 1553 | 1533 | const full = tree.fullFnProto(&buf, node).?; |
| 1554 | return tree.nodeToSpan(full.ast.section_expr); | |
| 1534 | return tree.nodeToSpan(full.ast.section_expr.unwrap().?); | |
| 1555 | 1535 | }, |
| 1556 | 1536 | .node_offset_fn_type_cc => |node_off| { |
| 1557 | 1537 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1558 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1538 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1559 | 1539 | var buf: [1]Ast.Node.Index = undefined; |
| 1560 | 1540 | const full = tree.fullFnProto(&buf, node).?; |
| 1561 | return tree.nodeToSpan(full.ast.callconv_expr); | |
| 1541 | return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?); | |
| 1562 | 1542 | }, |
| 1563 | 1543 | |
| 1564 | 1544 | .node_offset_fn_type_ret_ty => |node_off| { |
| 1565 | 1545 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1566 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1546 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1567 | 1547 | var buf: [1]Ast.Node.Index = undefined; |
| 1568 | 1548 | const full = tree.fullFnProto(&buf, node).?; |
| 1569 | return tree.nodeToSpan(full.ast.return_type); | |
| 1549 | return tree.nodeToSpan(full.ast.return_type.unwrap().?); | |
| 1570 | 1550 | }, |
| 1571 | 1551 | .node_offset_param => |node_off| { |
| 1572 | 1552 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1573 | const token_tags = tree.tokens.items(.tag); | |
| 1574 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1553 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1575 | 1554 | |
| 1576 | 1555 | var first_tok = tree.firstToken(node); |
| 1577 | while (true) switch (token_tags[first_tok - 1]) { | |
| 1556 | while (true) switch (tree.tokenTag(first_tok - 1)) { | |
| 1578 | 1557 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1579 | 1558 | else => break, |
| 1580 | 1559 | }; |
| ... | ... | @@ -1586,12 +1565,11 @@ pub const SrcLoc = struct { |
| 1586 | 1565 | }, |
| 1587 | 1566 | .token_offset_param => |token_off| { |
| 1588 | 1567 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1589 | const token_tags = tree.tokens.items(.tag); | |
| 1590 | const main_token = tree.nodes.items(.main_token)[src_loc.base_node]; | |
| 1591 | const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token)))); | |
| 1568 | const main_token = tree.nodeMainToken(src_loc.base_node); | |
| 1569 | const tok_index = token_off.toAbsolute(main_token); | |
| 1592 | 1570 | |
| 1593 | 1571 | var first_tok = tok_index; |
| 1594 | while (true) switch (token_tags[first_tok - 1]) { | |
| 1572 | while (true) switch (tree.tokenTag(first_tok - 1)) { | |
| 1595 | 1573 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1596 | 1574 | else => break, |
| 1597 | 1575 | }; |
| ... | ... | @@ -1604,109 +1582,108 @@ pub const SrcLoc = struct { |
| 1604 | 1582 | |
| 1605 | 1583 | .node_offset_anyframe_type => |node_off| { |
| 1606 | 1584 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1607 | const node_datas = tree.nodes.items(.data); | |
| 1608 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1609 | return tree.nodeToSpan(node_datas[parent_node].rhs); | |
| 1585 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1586 | _, const child_type = tree.nodeData(parent_node).token_and_node; | |
| 1587 | return tree.nodeToSpan(child_type); | |
| 1610 | 1588 | }, |
| 1611 | 1589 | |
| 1612 | 1590 | .node_offset_lib_name => |node_off| { |
| 1613 | 1591 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1614 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1592 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1615 | 1593 | var buf: [1]Ast.Node.Index = undefined; |
| 1616 | 1594 | const full = tree.fullFnProto(&buf, parent_node).?; |
| 1617 | 1595 | const tok_index = full.lib_name.?; |
| 1618 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1596 | const start = tree.tokenStart(tok_index); | |
| 1619 | 1597 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1620 | 1598 | return Span{ .start = start, .end = end, .main = start }; |
| 1621 | 1599 | }, |
| 1622 | 1600 | |
| 1623 | 1601 | .node_offset_array_type_len => |node_off| { |
| 1624 | 1602 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1625 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1603 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1626 | 1604 | |
| 1627 | 1605 | const full = tree.fullArrayType(parent_node).?; |
| 1628 | 1606 | return tree.nodeToSpan(full.ast.elem_count); |
| 1629 | 1607 | }, |
| 1630 | 1608 | .node_offset_array_type_sentinel => |node_off| { |
| 1631 | 1609 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1632 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1610 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1633 | 1611 | |
| 1634 | 1612 | const full = tree.fullArrayType(parent_node).?; |
| 1635 | return tree.nodeToSpan(full.ast.sentinel); | |
| 1613 | return tree.nodeToSpan(full.ast.sentinel.unwrap().?); | |
| 1636 | 1614 | }, |
| 1637 | 1615 | .node_offset_array_type_elem => |node_off| { |
| 1638 | 1616 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1639 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1617 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1640 | 1618 | |
| 1641 | 1619 | const full = tree.fullArrayType(parent_node).?; |
| 1642 | 1620 | return tree.nodeToSpan(full.ast.elem_type); |
| 1643 | 1621 | }, |
| 1644 | 1622 | .node_offset_un_op => |node_off| { |
| 1645 | 1623 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1646 | const node_datas = tree.nodes.items(.data); | |
| 1647 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1648 | ||
| 1649 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1624 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1625 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1650 | 1626 | }, |
| 1651 | 1627 | .node_offset_ptr_elem => |node_off| { |
| 1652 | 1628 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1653 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1629 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1654 | 1630 | |
| 1655 | 1631 | const full = tree.fullPtrType(parent_node).?; |
| 1656 | 1632 | return tree.nodeToSpan(full.ast.child_type); |
| 1657 | 1633 | }, |
| 1658 | 1634 | .node_offset_ptr_sentinel => |node_off| { |
| 1659 | 1635 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1660 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1636 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1661 | 1637 | |
| 1662 | 1638 | const full = tree.fullPtrType(parent_node).?; |
| 1663 | return tree.nodeToSpan(full.ast.sentinel); | |
| 1639 | return tree.nodeToSpan(full.ast.sentinel.unwrap().?); | |
| 1664 | 1640 | }, |
| 1665 | 1641 | .node_offset_ptr_align => |node_off| { |
| 1666 | 1642 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1667 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1643 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1668 | 1644 | |
| 1669 | 1645 | const full = tree.fullPtrType(parent_node).?; |
| 1670 | return tree.nodeToSpan(full.ast.align_node); | |
| 1646 | return tree.nodeToSpan(full.ast.align_node.unwrap().?); | |
| 1671 | 1647 | }, |
| 1672 | 1648 | .node_offset_ptr_addrspace => |node_off| { |
| 1673 | 1649 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1674 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1650 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1675 | 1651 | |
| 1676 | 1652 | const full = tree.fullPtrType(parent_node).?; |
| 1677 | return tree.nodeToSpan(full.ast.addrspace_node); | |
| 1653 | return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?); | |
| 1678 | 1654 | }, |
| 1679 | 1655 | .node_offset_ptr_bitoffset => |node_off| { |
| 1680 | 1656 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1681 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1657 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1682 | 1658 | |
| 1683 | 1659 | const full = tree.fullPtrType(parent_node).?; |
| 1684 | return tree.nodeToSpan(full.ast.bit_range_start); | |
| 1660 | return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?); | |
| 1685 | 1661 | }, |
| 1686 | 1662 | .node_offset_ptr_hostsize => |node_off| { |
| 1687 | 1663 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1688 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1664 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1689 | 1665 | |
| 1690 | 1666 | const full = tree.fullPtrType(parent_node).?; |
| 1691 | return tree.nodeToSpan(full.ast.bit_range_end); | |
| 1667 | return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?); | |
| 1692 | 1668 | }, |
| 1693 | 1669 | .node_offset_container_tag => |node_off| { |
| 1694 | 1670 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1695 | const node_tags = tree.nodes.items(.tag); | |
| 1696 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1671 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1697 | 1672 | |
| 1698 | switch (node_tags[parent_node]) { | |
| 1673 | switch (tree.nodeTag(parent_node)) { | |
| 1699 | 1674 | .container_decl_arg, .container_decl_arg_trailing => { |
| 1700 | 1675 | const full = tree.containerDeclArg(parent_node); |
| 1701 | return tree.nodeToSpan(full.ast.arg); | |
| 1676 | const arg_node = full.ast.arg.unwrap().?; | |
| 1677 | return tree.nodeToSpan(arg_node); | |
| 1702 | 1678 | }, |
| 1703 | 1679 | .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { |
| 1704 | 1680 | const full = tree.taggedUnionEnumTag(parent_node); |
| 1681 | const arg_node = full.ast.arg.unwrap().?; | |
| 1705 | 1682 | |
| 1706 | 1683 | return tree.tokensToSpan( |
| 1707 | tree.firstToken(full.ast.arg) - 2, | |
| 1708 | tree.lastToken(full.ast.arg) + 1, | |
| 1709 | tree.nodes.items(.main_token)[full.ast.arg], | |
| 1684 | tree.firstToken(arg_node) - 2, | |
| 1685 | tree.lastToken(arg_node) + 1, | |
| 1686 | tree.nodeMainToken(arg_node), | |
| 1710 | 1687 | ); |
| 1711 | 1688 | }, |
| 1712 | 1689 | else => unreachable, |
| ... | ... | @@ -1714,60 +1691,55 @@ pub const SrcLoc = struct { |
| 1714 | 1691 | }, |
| 1715 | 1692 | .node_offset_field_default => |node_off| { |
| 1716 | 1693 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1717 | const node_tags = tree.nodes.items(.tag); | |
| 1718 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1694 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1719 | 1695 | |
| 1720 | const full: Ast.full.ContainerField = switch (node_tags[parent_node]) { | |
| 1696 | const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) { | |
| 1721 | 1697 | .container_field => tree.containerField(parent_node), |
| 1722 | 1698 | .container_field_init => tree.containerFieldInit(parent_node), |
| 1723 | 1699 | else => unreachable, |
| 1724 | 1700 | }; |
| 1725 | return tree.nodeToSpan(full.ast.value_expr); | |
| 1701 | return tree.nodeToSpan(full.ast.value_expr.unwrap().?); | |
| 1726 | 1702 | }, |
| 1727 | 1703 | .node_offset_init_ty => |node_off| { |
| 1728 | 1704 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1729 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1705 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1730 | 1706 | |
| 1731 | 1707 | var buf: [2]Ast.Node.Index = undefined; |
| 1732 | 1708 | const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init| |
| 1733 | array_init.ast.type_expr | |
| 1709 | array_init.ast.type_expr.unwrap().? | |
| 1734 | 1710 | else |
| 1735 | tree.fullStructInit(&buf, parent_node).?.ast.type_expr; | |
| 1711 | tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?; | |
| 1736 | 1712 | return tree.nodeToSpan(type_expr); |
| 1737 | 1713 | }, |
| 1738 | 1714 | .node_offset_store_ptr => |node_off| { |
| 1739 | 1715 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1740 | const node_tags = tree.nodes.items(.tag); | |
| 1741 | const node_datas = tree.nodes.items(.data); | |
| 1742 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1716 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1743 | 1717 | |
| 1744 | switch (node_tags[node]) { | |
| 1718 | switch (tree.nodeTag(node)) { | |
| 1745 | 1719 | .assign => { |
| 1746 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1720 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]); | |
| 1747 | 1721 | }, |
| 1748 | 1722 | else => return tree.nodeToSpan(node), |
| 1749 | 1723 | } |
| 1750 | 1724 | }, |
| 1751 | 1725 | .node_offset_store_operand => |node_off| { |
| 1752 | 1726 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1753 | const node_tags = tree.nodes.items(.tag); | |
| 1754 | const node_datas = tree.nodes.items(.data); | |
| 1755 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1727 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1756 | 1728 | |
| 1757 | switch (node_tags[node]) { | |
| 1729 | switch (tree.nodeTag(node)) { | |
| 1758 | 1730 | .assign => { |
| 1759 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1731 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1760 | 1732 | }, |
| 1761 | 1733 | else => return tree.nodeToSpan(node), |
| 1762 | 1734 | } |
| 1763 | 1735 | }, |
| 1764 | 1736 | .node_offset_return_operand => |node_off| { |
| 1765 | 1737 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1766 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1767 | const node_tags = tree.nodes.items(.tag); | |
| 1768 | const node_datas = tree.nodes.items(.data); | |
| 1769 | if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { | |
| 1770 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1738 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1739 | if (tree.nodeTag(node) == .@"return") { | |
| 1740 | if (tree.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 1741 | return tree.nodeToSpan(lhs); | |
| 1742 | } | |
| 1771 | 1743 | } |
| 1772 | 1744 | return tree.nodeToSpan(node); |
| 1773 | 1745 | }, |
| ... | ... | @@ -1777,7 +1749,7 @@ pub const SrcLoc = struct { |
| 1777 | 1749 | .container_field_align, |
| 1778 | 1750 | => |field_idx| { |
| 1779 | 1751 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1780 | const node = src_loc.relativeToNodeIndex(0); | |
| 1752 | const node = src_loc.base_node; | |
| 1781 | 1753 | var buf: [2]Ast.Node.Index = undefined; |
| 1782 | 1754 | const container_decl = tree.fullContainerDecl(&buf, node) orelse |
| 1783 | 1755 | return tree.nodeToSpan(node); |
| ... | ... | @@ -1790,36 +1762,36 @@ pub const SrcLoc = struct { |
| 1790 | 1762 | continue; |
| 1791 | 1763 | } |
| 1792 | 1764 | const field_component_node = switch (src_loc.lazy) { |
| 1793 | .container_field_name => 0, | |
| 1765 | .container_field_name => .none, | |
| 1794 | 1766 | .container_field_value => field.ast.value_expr, |
| 1795 | 1767 | .container_field_type => field.ast.type_expr, |
| 1796 | 1768 | .container_field_align => field.ast.align_expr, |
| 1797 | 1769 | else => unreachable, |
| 1798 | 1770 | }; |
| 1799 | if (field_component_node == 0) { | |
| 1800 | return tree.tokenToSpan(field.ast.main_token); | |
| 1771 | if (field_component_node.unwrap()) |component_node| { | |
| 1772 | return tree.nodeToSpan(component_node); | |
| 1801 | 1773 | } else { |
| 1802 | return tree.nodeToSpan(field_component_node); | |
| 1774 | return tree.tokenToSpan(field.ast.main_token); | |
| 1803 | 1775 | } |
| 1804 | 1776 | } else unreachable; |
| 1805 | 1777 | }, |
| 1806 | 1778 | .tuple_field_type, .tuple_field_init => |field_info| { |
| 1807 | 1779 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1808 | const node = src_loc.relativeToNodeIndex(0); | |
| 1780 | const node = src_loc.base_node; | |
| 1809 | 1781 | var buf: [2]Ast.Node.Index = undefined; |
| 1810 | 1782 | const container_decl = tree.fullContainerDecl(&buf, node) orelse |
| 1811 | 1783 | return tree.nodeToSpan(node); |
| 1812 | 1784 | |
| 1813 | 1785 | const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?; |
| 1814 | 1786 | return tree.nodeToSpan(switch (src_loc.lazy) { |
| 1815 | .tuple_field_type => field.ast.type_expr, | |
| 1816 | .tuple_field_init => field.ast.value_expr, | |
| 1787 | .tuple_field_type => field.ast.type_expr.unwrap().?, | |
| 1788 | .tuple_field_init => field.ast.value_expr.unwrap().?, | |
| 1817 | 1789 | else => unreachable, |
| 1818 | 1790 | }); |
| 1819 | 1791 | }, |
| 1820 | 1792 | .init_elem => |init_elem| { |
| 1821 | 1793 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1822 | const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset); | |
| 1794 | const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node); | |
| 1823 | 1795 | var buf: [2]Ast.Node.Index = undefined; |
| 1824 | 1796 | if (tree.fullArrayInit(&buf, init_node)) |full| { |
| 1825 | 1797 | const elem_node = full.ast.elements[init_elem.elem_index]; |
| ... | ... | @@ -1829,7 +1801,7 @@ pub const SrcLoc = struct { |
| 1829 | 1801 | return tree.tokensToSpan( |
| 1830 | 1802 | tree.firstToken(field_node) - 3, |
| 1831 | 1803 | tree.lastToken(field_node), |
| 1832 | tree.nodes.items(.main_token)[field_node] - 2, | |
| 1804 | tree.nodeMainToken(field_node) - 2, | |
| 1833 | 1805 | ); |
| 1834 | 1806 | } else unreachable; |
| 1835 | 1807 | }, |
| ... | ... | @@ -1858,14 +1830,10 @@ pub const SrcLoc = struct { |
| 1858 | 1830 | else => unreachable, |
| 1859 | 1831 | }; |
| 1860 | 1832 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1861 | const node_datas = tree.nodes.items(.data); | |
| 1862 | const node_tags = tree.nodes.items(.tag); | |
| 1863 | const node = src_loc.relativeToNodeIndex(builtin_call_node); | |
| 1864 | const arg_node = switch (node_tags[node]) { | |
| 1865 | .builtin_call_two, .builtin_call_two_comma => node_datas[node].rhs, | |
| 1866 | .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + 1], | |
| 1867 | else => unreachable, | |
| 1868 | }; | |
| 1833 | const node = builtin_call_node.toAbsolute(src_loc.base_node); | |
| 1834 | var builtin_buf: [2]Ast.Node.Index = undefined; | |
| 1835 | const args = tree.builtinCallParams(&builtin_buf, node).?; | |
| 1836 | const arg_node = args[1]; | |
| 1869 | 1837 | var buf: [2]Ast.Node.Index = undefined; |
| 1870 | 1838 | const full = tree.fullStructInit(&buf, arg_node) orelse |
| 1871 | 1839 | return tree.nodeToSpan(arg_node); |
| ... | ... | @@ -1877,7 +1845,7 @@ pub const SrcLoc = struct { |
| 1877 | 1845 | return tree.tokensToSpan( |
| 1878 | 1846 | name_token - 1, |
| 1879 | 1847 | tree.lastToken(field_node), |
| 1880 | tree.nodes.items(.main_token)[field_node] - 2, | |
| 1848 | tree.nodeMainToken(field_node) - 2, | |
| 1881 | 1849 | ); |
| 1882 | 1850 | } |
| 1883 | 1851 | } |
| ... | ... | @@ -1901,12 +1869,9 @@ pub const SrcLoc = struct { |
| 1901 | 1869 | }; |
| 1902 | 1870 | |
| 1903 | 1871 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1904 | const node_datas = tree.nodes.items(.data); | |
| 1905 | const node_tags = tree.nodes.items(.tag); | |
| 1906 | const main_tokens = tree.nodes.items(.main_token); | |
| 1907 | const switch_node = src_loc.relativeToNodeIndex(switch_node_offset); | |
| 1908 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1909 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1872 | const switch_node = switch_node_offset.toAbsolute(src_loc.base_node); | |
| 1873 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1874 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1910 | 1875 | |
| 1911 | 1876 | var multi_i: u32 = 0; |
| 1912 | 1877 | var scalar_i: u32 = 0; |
| ... | ... | @@ -1914,8 +1879,8 @@ pub const SrcLoc = struct { |
| 1914 | 1879 | const case = tree.fullSwitchCase(case_node).?; |
| 1915 | 1880 | const is_special = special: { |
| 1916 | 1881 | if (case.ast.values.len == 0) break :special true; |
| 1917 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) { | |
| 1918 | break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"); | |
| 1882 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) { | |
| 1883 | break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"); | |
| 1919 | 1884 | } |
| 1920 | 1885 | break :special false; |
| 1921 | 1886 | }; |
| ... | ... | @@ -1927,7 +1892,7 @@ pub const SrcLoc = struct { |
| 1927 | 1892 | } |
| 1928 | 1893 | |
| 1929 | 1894 | const is_multi = case.ast.values.len != 1 or |
| 1930 | node_tags[case.ast.values[0]] == .switch_range; | |
| 1895 | tree.nodeTag(case.ast.values[0]) == .switch_range; | |
| 1931 | 1896 | |
| 1932 | 1897 | switch (want_case_idx.kind) { |
| 1933 | 1898 | .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case, |
| ... | ... | @@ -1947,18 +1912,17 @@ pub const SrcLoc = struct { |
| 1947 | 1912 | .switch_case_item_range_last, |
| 1948 | 1913 | => |x| x.item_idx, |
| 1949 | 1914 | .switch_capture, .switch_tag_capture => { |
| 1950 | const token_tags = tree.tokens.items(.tag); | |
| 1951 | 1915 | const start = switch (src_loc.lazy) { |
| 1952 | 1916 | .switch_capture => case.payload_token.?, |
| 1953 | 1917 | .switch_tag_capture => tok: { |
| 1954 | 1918 | var tok = case.payload_token.?; |
| 1955 | if (token_tags[tok] == .asterisk) tok += 1; | |
| 1956 | tok += 2; // skip over comma | |
| 1919 | if (tree.tokenTag(tok) == .asterisk) tok += 1; | |
| 1920 | tok = tok + 2; // skip over comma | |
| 1957 | 1921 | break :tok tok; |
| 1958 | 1922 | }, |
| 1959 | 1923 | else => unreachable, |
| 1960 | 1924 | }; |
| 1961 | const end = switch (token_tags[start]) { | |
| 1925 | const end = switch (tree.tokenTag(start)) { | |
| 1962 | 1926 | .asterisk => start + 1, |
| 1963 | 1927 | else => start, |
| 1964 | 1928 | }; |
| ... | ... | @@ -1971,7 +1935,7 @@ pub const SrcLoc = struct { |
| 1971 | 1935 | .single => { |
| 1972 | 1936 | var item_i: u32 = 0; |
| 1973 | 1937 | for (case.ast.values) |item_node| { |
| 1974 | if (node_tags[item_node] == .switch_range) continue; | |
| 1938 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 1975 | 1939 | if (item_i != want_item.index) { |
| 1976 | 1940 | item_i += 1; |
| 1977 | 1941 | continue; |
| ... | ... | @@ -1982,15 +1946,16 @@ pub const SrcLoc = struct { |
| 1982 | 1946 | .range => { |
| 1983 | 1947 | var range_i: u32 = 0; |
| 1984 | 1948 | for (case.ast.values) |item_node| { |
| 1985 | if (node_tags[item_node] != .switch_range) continue; | |
| 1949 | if (tree.nodeTag(item_node) != .switch_range) continue; | |
| 1986 | 1950 | if (range_i != want_item.index) { |
| 1987 | 1951 | range_i += 1; |
| 1988 | 1952 | continue; |
| 1989 | 1953 | } |
| 1954 | const first, const last = tree.nodeData(item_node).node_and_node; | |
| 1990 | 1955 | return switch (src_loc.lazy) { |
| 1991 | 1956 | .switch_case_item => tree.nodeToSpan(item_node), |
| 1992 | .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs), | |
| 1993 | .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs), | |
| 1957 | .switch_case_item_range_first => tree.nodeToSpan(first), | |
| 1958 | .switch_case_item_range_last => tree.nodeToSpan(last), | |
| 1994 | 1959 | else => unreachable, |
| 1995 | 1960 | }; |
| 1996 | 1961 | } else unreachable; |
| ... | ... | @@ -2013,7 +1978,7 @@ pub const SrcLoc = struct { |
| 2013 | 1978 | var param_it = full.iterate(tree); |
| 2014 | 1979 | for (0..param_idx) |_| assert(param_it.next() != null); |
| 2015 | 1980 | const param = param_it.next().?; |
| 2016 | return tree.nodeToSpan(param.type_expr); | |
| 1981 | return tree.nodeToSpan(param.type_expr.?); | |
| 2017 | 1982 | }, |
| 2018 | 1983 | } |
| 2019 | 1984 | } |
| ... | ... | @@ -2044,212 +2009,217 @@ pub const LazySrcLoc = struct { |
| 2044 | 2009 | byte_abs: u32, |
| 2045 | 2010 | /// The source location points to a token within a source file, |
| 2046 | 2011 | /// offset from 0. The source file is determined contextually. |
| 2047 | token_abs: u32, | |
| 2012 | token_abs: Ast.TokenIndex, | |
| 2048 | 2013 | /// The source location points to an AST node within a source file, |
| 2049 | 2014 | /// offset from 0. The source file is determined contextually. |
| 2050 | node_abs: u32, | |
| 2015 | node_abs: Ast.Node.Index, | |
| 2051 | 2016 | /// The source location points to a byte offset within a source file, |
| 2052 | 2017 | /// offset from the byte offset of the base node within the file. |
| 2053 | 2018 | byte_offset: u32, |
| 2054 | 2019 | /// This data is the offset into the token list from the base node's first token. |
| 2055 | token_offset: u32, | |
| 2020 | token_offset: Ast.TokenOffset, | |
| 2056 | 2021 | /// The source location points to an AST node, which is this value offset |
| 2057 | 2022 | /// from its containing base node AST index. |
| 2058 | 2023 | node_offset: TracedOffset, |
| 2059 | 2024 | /// The source location points to the main token of an AST node, found |
| 2060 | 2025 | /// by taking this AST node index offset from the containing base node. |
| 2061 | node_offset_main_token: i32, | |
| 2026 | node_offset_main_token: Ast.Node.Offset, | |
| 2062 | 2027 | /// The source location points to the beginning of a struct initializer. |
| 2063 | node_offset_initializer: i32, | |
| 2028 | node_offset_initializer: Ast.Node.Offset, | |
| 2064 | 2029 | /// The source location points to a variable declaration type expression, |
| 2065 | 2030 | /// found by taking this AST node index offset from the containing |
| 2066 | 2031 | /// base node, which points to a variable declaration AST node. Next, navigate |
| 2067 | 2032 | /// to the type expression. |
| 2068 | node_offset_var_decl_ty: i32, | |
| 2033 | node_offset_var_decl_ty: Ast.Node.Offset, | |
| 2069 | 2034 | /// The source location points to the alignment expression of a var decl. |
| 2070 | node_offset_var_decl_align: i32, | |
| 2035 | node_offset_var_decl_align: Ast.Node.Offset, | |
| 2071 | 2036 | /// The source location points to the linksection expression of a var decl. |
| 2072 | node_offset_var_decl_section: i32, | |
| 2037 | node_offset_var_decl_section: Ast.Node.Offset, | |
| 2073 | 2038 | /// The source location points to the addrspace expression of a var decl. |
| 2074 | node_offset_var_decl_addrspace: i32, | |
| 2039 | node_offset_var_decl_addrspace: Ast.Node.Offset, | |
| 2075 | 2040 | /// The source location points to the initializer of a var decl. |
| 2076 | node_offset_var_decl_init: i32, | |
| 2041 | node_offset_var_decl_init: Ast.Node.Offset, | |
| 2077 | 2042 | /// The source location points to the given argument of a builtin function call. |
| 2078 | 2043 | /// `builtin_call_node` points to the builtin call. |
| 2079 | 2044 | /// `arg_index` is the index of the argument which hte source location refers to. |
| 2080 | 2045 | node_offset_builtin_call_arg: struct { |
| 2081 | builtin_call_node: i32, | |
| 2046 | builtin_call_node: Ast.Node.Offset, | |
| 2082 | 2047 | arg_index: u32, |
| 2083 | 2048 | }, |
| 2084 | 2049 | /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls |
| 2085 | 2050 | /// to pointer cast builtins (taking the first argument of the most nested). |
| 2086 | node_offset_ptrcast_operand: i32, | |
| 2051 | node_offset_ptrcast_operand: Ast.Node.Offset, | |
| 2087 | 2052 | /// The source location points to the index expression of an array access |
| 2088 | 2053 | /// expression, found by taking this AST node index offset from the containing |
| 2089 | 2054 | /// base node, which points to an array access AST node. Next, navigate |
| 2090 | 2055 | /// to the index expression. |
| 2091 | node_offset_array_access_index: i32, | |
| 2056 | node_offset_array_access_index: Ast.Node.Offset, | |
| 2092 | 2057 | /// The source location points to the LHS of a slice expression |
| 2093 | 2058 | /// expression, found by taking this AST node index offset from the containing |
| 2094 | 2059 | /// base node, which points to a slice AST node. Next, navigate |
| 2095 | 2060 | /// to the sentinel expression. |
| 2096 | node_offset_slice_ptr: i32, | |
| 2061 | node_offset_slice_ptr: Ast.Node.Offset, | |
| 2097 | 2062 | /// The source location points to start expression of a slice expression |
| 2098 | 2063 | /// expression, found by taking this AST node index offset from the containing |
| 2099 | 2064 | /// base node, which points to a slice AST node. Next, navigate |
| 2100 | 2065 | /// to the sentinel expression. |
| 2101 | node_offset_slice_start: i32, | |
| 2066 | node_offset_slice_start: Ast.Node.Offset, | |
| 2102 | 2067 | /// The source location points to the end expression of a slice |
| 2103 | 2068 | /// expression, found by taking this AST node index offset from the containing |
| 2104 | 2069 | /// base node, which points to a slice AST node. Next, navigate |
| 2105 | 2070 | /// to the sentinel expression. |
| 2106 | node_offset_slice_end: i32, | |
| 2071 | node_offset_slice_end: Ast.Node.Offset, | |
| 2107 | 2072 | /// The source location points to the sentinel expression of a slice |
| 2108 | 2073 | /// expression, found by taking this AST node index offset from the containing |
| 2109 | 2074 | /// base node, which points to a slice AST node. Next, navigate |
| 2110 | 2075 | /// to the sentinel expression. |
| 2111 | node_offset_slice_sentinel: i32, | |
| 2076 | node_offset_slice_sentinel: Ast.Node.Offset, | |
| 2112 | 2077 | /// The source location points to the callee expression of a function |
| 2113 | 2078 | /// call expression, found by taking this AST node index offset from the containing |
| 2114 | 2079 | /// base node, which points to a function call AST node. Next, navigate |
| 2115 | 2080 | /// to the callee expression. |
| 2116 | node_offset_call_func: i32, | |
| 2081 | node_offset_call_func: Ast.Node.Offset, | |
| 2117 | 2082 | /// The payload is offset from the containing base node. |
| 2118 | 2083 | /// The source location points to the field name of: |
| 2119 | 2084 | /// * a field access expression (`a.b`), or |
| 2120 | 2085 | /// * the callee of a method call (`a.b()`) |
| 2121 | node_offset_field_name: i32, | |
| 2086 | node_offset_field_name: Ast.Node.Offset, | |
| 2122 | 2087 | /// The payload is offset from the containing base node. |
| 2123 | 2088 | /// The source location points to the field name of the operand ("b" node) |
| 2124 | 2089 | /// of a field initialization expression (`.a = b`) |
| 2125 | node_offset_field_name_init: i32, | |
| 2090 | node_offset_field_name_init: Ast.Node.Offset, | |
| 2126 | 2091 | /// The source location points to the pointer of a pointer deref expression, |
| 2127 | 2092 | /// found by taking this AST node index offset from the containing |
| 2128 | 2093 | /// base node, which points to a pointer deref AST node. Next, navigate |
| 2129 | 2094 | /// to the pointer expression. |
| 2130 | node_offset_deref_ptr: i32, | |
| 2095 | node_offset_deref_ptr: Ast.Node.Offset, | |
| 2131 | 2096 | /// The source location points to the assembly source code of an inline assembly |
| 2132 | 2097 | /// expression, found by taking this AST node index offset from the containing |
| 2133 | 2098 | /// base node, which points to inline assembly AST node. Next, navigate |
| 2134 | 2099 | /// to the asm template source code. |
| 2135 | node_offset_asm_source: i32, | |
| 2100 | node_offset_asm_source: Ast.Node.Offset, | |
| 2136 | 2101 | /// The source location points to the return type of an inline assembly |
| 2137 | 2102 | /// expression, found by taking this AST node index offset from the containing |
| 2138 | 2103 | /// base node, which points to inline assembly AST node. Next, navigate |
| 2139 | 2104 | /// to the return type expression. |
| 2140 | node_offset_asm_ret_ty: i32, | |
| 2105 | node_offset_asm_ret_ty: Ast.Node.Offset, | |
| 2141 | 2106 | /// The source location points to the condition expression of an if |
| 2142 | 2107 | /// expression, found by taking this AST node index offset from the containing |
| 2143 | 2108 | /// base node, which points to an if expression AST node. Next, navigate |
| 2144 | 2109 | /// to the condition expression. |
| 2145 | node_offset_if_cond: i32, | |
| 2110 | node_offset_if_cond: Ast.Node.Offset, | |
| 2146 | 2111 | /// The source location points to a binary expression, such as `a + b`, found |
| 2147 | 2112 | /// by taking this AST node index offset from the containing base node. |
| 2148 | node_offset_bin_op: i32, | |
| 2113 | node_offset_bin_op: Ast.Node.Offset, | |
| 2149 | 2114 | /// The source location points to the LHS of a binary expression, found |
| 2150 | 2115 | /// by taking this AST node index offset from the containing base node, |
| 2151 | 2116 | /// which points to a binary expression AST node. Next, navigate to the LHS. |
| 2152 | node_offset_bin_lhs: i32, | |
| 2117 | node_offset_bin_lhs: Ast.Node.Offset, | |
| 2153 | 2118 | /// The source location points to the RHS of a binary expression, found |
| 2154 | 2119 | /// by taking this AST node index offset from the containing base node, |
| 2155 | 2120 | /// which points to a binary expression AST node. Next, navigate to the RHS. |
| 2156 | node_offset_bin_rhs: i32, | |
| 2121 | node_offset_bin_rhs: Ast.Node.Offset, | |
| 2122 | /// The source location points to the operand of a try expression, found | |
| 2123 | /// by taking this AST node index offset from the containing base node, | |
| 2124 | /// which points to a try expression AST node. Next, navigate to the | |
| 2125 | /// operand expression. | |
| 2126 | node_offset_try_operand: Ast.Node.Offset, | |
| 2157 | 2127 | /// The source location points to the operand of a switch expression, found |
| 2158 | 2128 | /// by taking this AST node index offset from the containing base node, |
| 2159 | 2129 | /// which points to a switch expression AST node. Next, navigate to the operand. |
| 2160 | node_offset_switch_operand: i32, | |
| 2130 | node_offset_switch_operand: Ast.Node.Offset, | |
| 2161 | 2131 | /// The source location points to the else/`_` prong of a switch expression, found |
| 2162 | 2132 | /// by taking this AST node index offset from the containing base node, |
| 2163 | 2133 | /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. |
| 2164 | node_offset_switch_special_prong: i32, | |
| 2134 | node_offset_switch_special_prong: Ast.Node.Offset, | |
| 2165 | 2135 | /// The source location points to all the ranges of a switch expression, found |
| 2166 | 2136 | /// by taking this AST node index offset from the containing base node, |
| 2167 | 2137 | /// which points to a switch expression AST node. Next, navigate to any of the |
| 2168 | 2138 | /// range nodes. The error applies to all of them. |
| 2169 | node_offset_switch_range: i32, | |
| 2139 | node_offset_switch_range: Ast.Node.Offset, | |
| 2170 | 2140 | /// The source location points to the align expr of a function type |
| 2171 | 2141 | /// expression, found by taking this AST node index offset from the containing |
| 2172 | 2142 | /// base node, which points to a function type AST node. Next, navigate to |
| 2173 | 2143 | /// the calling convention node. |
| 2174 | node_offset_fn_type_align: i32, | |
| 2144 | node_offset_fn_type_align: Ast.Node.Offset, | |
| 2175 | 2145 | /// The source location points to the addrspace expr of a function type |
| 2176 | 2146 | /// expression, found by taking this AST node index offset from the containing |
| 2177 | 2147 | /// base node, which points to a function type AST node. Next, navigate to |
| 2178 | 2148 | /// the calling convention node. |
| 2179 | node_offset_fn_type_addrspace: i32, | |
| 2149 | node_offset_fn_type_addrspace: Ast.Node.Offset, | |
| 2180 | 2150 | /// The source location points to the linksection expr of a function type |
| 2181 | 2151 | /// expression, found by taking this AST node index offset from the containing |
| 2182 | 2152 | /// base node, which points to a function type AST node. Next, navigate to |
| 2183 | 2153 | /// the calling convention node. |
| 2184 | node_offset_fn_type_section: i32, | |
| 2154 | node_offset_fn_type_section: Ast.Node.Offset, | |
| 2185 | 2155 | /// The source location points to the calling convention of a function type |
| 2186 | 2156 | /// expression, found by taking this AST node index offset from the containing |
| 2187 | 2157 | /// base node, which points to a function type AST node. Next, navigate to |
| 2188 | 2158 | /// the calling convention node. |
| 2189 | node_offset_fn_type_cc: i32, | |
| 2159 | node_offset_fn_type_cc: Ast.Node.Offset, | |
| 2190 | 2160 | /// The source location points to the return type of a function type |
| 2191 | 2161 | /// expression, found by taking this AST node index offset from the containing |
| 2192 | 2162 | /// base node, which points to a function type AST node. Next, navigate to |
| 2193 | 2163 | /// the return type node. |
| 2194 | node_offset_fn_type_ret_ty: i32, | |
| 2195 | node_offset_param: i32, | |
| 2196 | token_offset_param: i32, | |
| 2164 | node_offset_fn_type_ret_ty: Ast.Node.Offset, | |
| 2165 | node_offset_param: Ast.Node.Offset, | |
| 2166 | token_offset_param: Ast.TokenOffset, | |
| 2197 | 2167 | /// The source location points to the type expression of an `anyframe->T` |
| 2198 | 2168 | /// expression, found by taking this AST node index offset from the containing |
| 2199 | 2169 | /// base node, which points to a `anyframe->T` expression AST node. Next, navigate |
| 2200 | 2170 | /// to the type expression. |
| 2201 | node_offset_anyframe_type: i32, | |
| 2171 | node_offset_anyframe_type: Ast.Node.Offset, | |
| 2202 | 2172 | /// The source location points to the string literal of `extern "foo"`, found |
| 2203 | 2173 | /// by taking this AST node index offset from the containing |
| 2204 | 2174 | /// base node, which points to a function prototype or variable declaration |
| 2205 | 2175 | /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. |
| 2206 | node_offset_lib_name: i32, | |
| 2176 | node_offset_lib_name: Ast.Node.Offset, | |
| 2207 | 2177 | /// The source location points to the len expression of an `[N:S]T` |
| 2208 | 2178 | /// expression, found by taking this AST node index offset from the containing |
| 2209 | 2179 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2210 | 2180 | /// to the len expression. |
| 2211 | node_offset_array_type_len: i32, | |
| 2181 | node_offset_array_type_len: Ast.Node.Offset, | |
| 2212 | 2182 | /// The source location points to the sentinel expression of an `[N:S]T` |
| 2213 | 2183 | /// expression, found by taking this AST node index offset from the containing |
| 2214 | 2184 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2215 | 2185 | /// to the sentinel expression. |
| 2216 | node_offset_array_type_sentinel: i32, | |
| 2186 | node_offset_array_type_sentinel: Ast.Node.Offset, | |
| 2217 | 2187 | /// The source location points to the elem expression of an `[N:S]T` |
| 2218 | 2188 | /// expression, found by taking this AST node index offset from the containing |
| 2219 | 2189 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2220 | 2190 | /// to the elem expression. |
| 2221 | node_offset_array_type_elem: i32, | |
| 2191 | node_offset_array_type_elem: Ast.Node.Offset, | |
| 2222 | 2192 | /// The source location points to the operand of an unary expression. |
| 2223 | node_offset_un_op: i32, | |
| 2193 | node_offset_un_op: Ast.Node.Offset, | |
| 2224 | 2194 | /// The source location points to the elem type of a pointer. |
| 2225 | node_offset_ptr_elem: i32, | |
| 2195 | node_offset_ptr_elem: Ast.Node.Offset, | |
| 2226 | 2196 | /// The source location points to the sentinel of a pointer. |
| 2227 | node_offset_ptr_sentinel: i32, | |
| 2197 | node_offset_ptr_sentinel: Ast.Node.Offset, | |
| 2228 | 2198 | /// The source location points to the align expr of a pointer. |
| 2229 | node_offset_ptr_align: i32, | |
| 2199 | node_offset_ptr_align: Ast.Node.Offset, | |
| 2230 | 2200 | /// The source location points to the addrspace expr of a pointer. |
| 2231 | node_offset_ptr_addrspace: i32, | |
| 2201 | node_offset_ptr_addrspace: Ast.Node.Offset, | |
| 2232 | 2202 | /// The source location points to the bit-offset of a pointer. |
| 2233 | node_offset_ptr_bitoffset: i32, | |
| 2203 | node_offset_ptr_bitoffset: Ast.Node.Offset, | |
| 2234 | 2204 | /// The source location points to the host size of a pointer. |
| 2235 | node_offset_ptr_hostsize: i32, | |
| 2205 | node_offset_ptr_hostsize: Ast.Node.Offset, | |
| 2236 | 2206 | /// The source location points to the tag type of an union or an enum. |
| 2237 | node_offset_container_tag: i32, | |
| 2207 | node_offset_container_tag: Ast.Node.Offset, | |
| 2238 | 2208 | /// The source location points to the default value of a field. |
| 2239 | node_offset_field_default: i32, | |
| 2209 | node_offset_field_default: Ast.Node.Offset, | |
| 2240 | 2210 | /// The source location points to the type of an array or struct initializer. |
| 2241 | node_offset_init_ty: i32, | |
| 2211 | node_offset_init_ty: Ast.Node.Offset, | |
| 2242 | 2212 | /// The source location points to the LHS of an assignment. |
| 2243 | node_offset_store_ptr: i32, | |
| 2213 | node_offset_store_ptr: Ast.Node.Offset, | |
| 2244 | 2214 | /// The source location points to the RHS of an assignment. |
| 2245 | node_offset_store_operand: i32, | |
| 2215 | node_offset_store_operand: Ast.Node.Offset, | |
| 2246 | 2216 | /// The source location points to the operand of a `return` statement, or |
| 2247 | 2217 | /// the `return` itself if there is no explicit operand. |
| 2248 | node_offset_return_operand: i32, | |
| 2218 | node_offset_return_operand: Ast.Node.Offset, | |
| 2249 | 2219 | /// The source location points to a for loop input. |
| 2250 | 2220 | for_input: struct { |
| 2251 | 2221 | /// Points to the for loop AST node. |
| 2252 | for_node_offset: i32, | |
| 2222 | for_node_offset: Ast.Node.Offset, | |
| 2253 | 2223 | /// Picks one of the inputs from the condition. |
| 2254 | 2224 | input_index: u32, |
| 2255 | 2225 | }, |
| ... | ... | @@ -2257,11 +2227,11 @@ pub const LazySrcLoc = struct { |
| 2257 | 2227 | /// by taking this AST node index offset from the containing |
| 2258 | 2228 | /// base node, which points to one of the input nodes of a for loop. |
| 2259 | 2229 | /// Next, navigate to the corresponding capture. |
| 2260 | for_capture_from_input: i32, | |
| 2230 | for_capture_from_input: Ast.Node.Offset, | |
| 2261 | 2231 | /// The source location points to the argument node of a function call. |
| 2262 | 2232 | call_arg: struct { |
| 2263 | 2233 | /// Points to the function call AST node. |
| 2264 | call_node_offset: i32, | |
| 2234 | call_node_offset: Ast.Node.Offset, | |
| 2265 | 2235 | /// The index of the argument the source location points to. |
| 2266 | 2236 | arg_index: u32, |
| 2267 | 2237 | }, |
| ... | ... | @@ -2288,25 +2258,25 @@ pub const LazySrcLoc = struct { |
| 2288 | 2258 | /// array initialization expression. |
| 2289 | 2259 | init_elem: struct { |
| 2290 | 2260 | /// Points to the AST node of the initialization expression. |
| 2291 | init_node_offset: i32, | |
| 2261 | init_node_offset: Ast.Node.Offset, | |
| 2292 | 2262 | /// The index of the field/element the source location points to. |
| 2293 | 2263 | elem_index: u32, |
| 2294 | 2264 | }, |
| 2295 | 2265 | // The following source locations are like `init_elem`, but refer to a |
| 2296 | 2266 | // field with a specific name. If such a field is not given, the entire |
| 2297 | 2267 | // initialization expression is used instead. |
| 2298 | // The `i32` points to the AST node of a builtin call, whose *second* | |
| 2268 | // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second* | |
| 2299 | 2269 | // argument is the init expression. |
| 2300 | init_field_name: i32, | |
| 2301 | init_field_linkage: i32, | |
| 2302 | init_field_section: i32, | |
| 2303 | init_field_visibility: i32, | |
| 2304 | init_field_rw: i32, | |
| 2305 | init_field_locality: i32, | |
| 2306 | init_field_cache: i32, | |
| 2307 | init_field_library: i32, | |
| 2308 | init_field_thread_local: i32, | |
| 2309 | init_field_dll_import: i32, | |
| 2270 | init_field_name: Ast.Node.Offset, | |
| 2271 | init_field_linkage: Ast.Node.Offset, | |
| 2272 | init_field_section: Ast.Node.Offset, | |
| 2273 | init_field_visibility: Ast.Node.Offset, | |
| 2274 | init_field_rw: Ast.Node.Offset, | |
| 2275 | init_field_locality: Ast.Node.Offset, | |
| 2276 | init_field_cache: Ast.Node.Offset, | |
| 2277 | init_field_library: Ast.Node.Offset, | |
| 2278 | init_field_thread_local: Ast.Node.Offset, | |
| 2279 | init_field_dll_import: Ast.Node.Offset, | |
| 2310 | 2280 | /// The source location points to the value of an item in a specific |
| 2311 | 2281 | /// case of a `switch`. |
| 2312 | 2282 | switch_case_item: SwitchItem, |
| ... | ... | @@ -2331,14 +2301,14 @@ pub const LazySrcLoc = struct { |
| 2331 | 2301 | |
| 2332 | 2302 | pub const FnProtoParam = struct { |
| 2333 | 2303 | /// The offset of the function prototype AST node. |
| 2334 | fn_proto_node_offset: i32, | |
| 2304 | fn_proto_node_offset: Ast.Node.Offset, | |
| 2335 | 2305 | /// The index of the parameter the source location points to. |
| 2336 | 2306 | param_index: u32, |
| 2337 | 2307 | }; |
| 2338 | 2308 | |
| 2339 | 2309 | pub const SwitchItem = struct { |
| 2340 | 2310 | /// The offset of the switch AST node. |
| 2341 | switch_node_offset: i32, | |
| 2311 | switch_node_offset: Ast.Node.Offset, | |
| 2342 | 2312 | /// The index of the case to point to within this switch. |
| 2343 | 2313 | case_idx: SwitchCaseIndex, |
| 2344 | 2314 | /// The index of the item to point to within this case. |
| ... | ... | @@ -2347,7 +2317,7 @@ pub const LazySrcLoc = struct { |
| 2347 | 2317 | |
| 2348 | 2318 | pub const SwitchCapture = struct { |
| 2349 | 2319 | /// The offset of the switch AST node. |
| 2350 | switch_node_offset: i32, | |
| 2320 | switch_node_offset: Ast.Node.Offset, | |
| 2351 | 2321 | /// The index of the case whose capture to point to. |
| 2352 | 2322 | case_idx: SwitchCaseIndex, |
| 2353 | 2323 | }; |
| ... | ... | @@ -2369,34 +2339,34 @@ pub const LazySrcLoc = struct { |
| 2369 | 2339 | |
| 2370 | 2340 | pub const ArrayCat = struct { |
| 2371 | 2341 | /// Points to the array concat AST node. |
| 2372 | array_cat_offset: i32, | |
| 2342 | array_cat_offset: Ast.Node.Offset, | |
| 2373 | 2343 | /// The index of the element the source location points to. |
| 2374 | 2344 | elem_index: u32, |
| 2375 | 2345 | }; |
| 2376 | 2346 | |
| 2377 | 2347 | pub const TupleField = struct { |
| 2378 | 2348 | /// Points to the AST node of the tuple type decaration. |
| 2379 | tuple_decl_node_offset: i32, | |
| 2349 | tuple_decl_node_offset: Ast.Node.Offset, | |
| 2380 | 2350 | /// The index of the tuple field the source location points to. |
| 2381 | 2351 | elem_index: u32, |
| 2382 | 2352 | }; |
| 2383 | 2353 | |
| 2384 | 2354 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 2385 | 2355 | |
| 2386 | noinline fn nodeOffsetDebug(node_offset: i32) Offset { | |
| 2356 | noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset { | |
| 2387 | 2357 | var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; |
| 2388 | 2358 | result.node_offset.trace.addAddr(@returnAddress(), "init"); |
| 2389 | 2359 | return result; |
| 2390 | 2360 | } |
| 2391 | 2361 | |
| 2392 | fn nodeOffsetRelease(node_offset: i32) Offset { | |
| 2362 | fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset { | |
| 2393 | 2363 | return .{ .node_offset = .{ .x = node_offset } }; |
| 2394 | 2364 | } |
| 2395 | 2365 | |
| 2396 | 2366 | /// This wraps a simple integer in debug builds so that later on we can find out |
| 2397 | 2367 | /// where in semantic analysis the value got set. |
| 2398 | 2368 | pub const TracedOffset = struct { |
| 2399 | x: i32, | |
| 2369 | x: Ast.Node.Offset, | |
| 2400 | 2370 | trace: std.debug.Trace = std.debug.Trace.init, |
| 2401 | 2371 | |
| 2402 | 2372 | const want_tracing = false; |
| ... | ... | @@ -2421,7 +2391,7 @@ pub const LazySrcLoc = struct { |
| 2421 | 2391 | |
| 2422 | 2392 | // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR, |
| 2423 | 2393 | // which may not exist e.g. in the case of errors in ZON files. |
| 2424 | if (zir_inst == .main_struct_inst) return .{ file, 0 }; | |
| 2394 | if (zir_inst == .main_struct_inst) return .{ file, .root }; | |
| 2425 | 2395 | |
| 2426 | 2396 | // Otherwise, make sure ZIR is loaded. |
| 2427 | 2397 | const zir = file.zir.?; |
| ... | ... | @@ -2454,7 +2424,7 @@ pub const LazySrcLoc = struct { |
| 2454 | 2424 | pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc { |
| 2455 | 2425 | const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{ |
| 2456 | 2426 | zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)), |
| 2457 | 0, | |
| 2427 | .root, | |
| 2458 | 2428 | } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null; |
| 2459 | 2429 | return .{ |
| 2460 | 2430 | .file_scope = file, |
| ... | ... | @@ -4023,7 +3993,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc { |
| 4023 | 3993 | const ip = &zcu.intern_pool; |
| 4024 | 3994 | return .{ |
| 4025 | 3995 | .base_node_inst = ip.getNav(nav_index).srcInst(ip), |
| 4026 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 3996 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 4027 | 3997 | }; |
| 4028 | 3998 | } |
| 4029 | 3999 |
src/Zcu/PerThread.zig+11-11| ... | ... | @@ -841,7 +841,7 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 841 | 841 | .comptime_reason = .{ .reason = .{ |
| 842 | 842 | .src = .{ |
| 843 | 843 | .base_node_inst = comptime_unit.zir_index, |
| 844 | .offset = .{ .token_offset = 0 }, | |
| 844 | .offset = .{ .token_offset = .zero }, | |
| 845 | 845 | }, |
| 846 | 846 | .r = .{ .simple = .comptime_keyword }, |
| 847 | 847 | } }, |
| ... | ... | @@ -1042,11 +1042,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1042 | 1042 | const zir_decl = zir.getDeclaration(inst_resolved.inst); |
| 1043 | 1043 | assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace")); |
| 1044 | 1044 | |
| 1045 | const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 }); | |
| 1046 | const init_src = block.src(.{ .node_offset_var_decl_init = 0 }); | |
| 1047 | const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); | |
| 1048 | const section_src = block.src(.{ .node_offset_var_decl_section = 0 }); | |
| 1049 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 1045 | const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero }); | |
| 1046 | const init_src = block.src(.{ .node_offset_var_decl_init = .zero }); | |
| 1047 | const align_src = block.src(.{ .node_offset_var_decl_align = .zero }); | |
| 1048 | const section_src = block.src(.{ .node_offset_var_decl_section = .zero }); | |
| 1049 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero }); | |
| 1050 | 1050 | |
| 1051 | 1051 | block.comptime_reason = .{ .reason = .{ |
| 1052 | 1052 | .src = init_src, |
| ... | ... | @@ -1135,7 +1135,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1135 | 1135 | break :l zir.nullTerminatedString(zir_decl.lib_name); |
| 1136 | 1136 | } else null; |
| 1137 | 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 | 1139 | try sema.handleExternLibName(&block, lib_name_src, l); |
| 1140 | 1140 | } |
| 1141 | 1141 | break :val .fromInterned(try pt.getExtern(.{ |
| ... | ... | @@ -1233,7 +1233,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr |
| 1233 | 1233 | } |
| 1234 | 1234 | |
| 1235 | 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 | 1237 | const name_slice = zir.nullTerminatedString(zir_decl.name); |
| 1238 | 1238 | const name_ip = try ip.getOrPutString(gpa, pt.tid, name_slice, .no_embedded_nulls); |
| 1239 | 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 | 1414 | const zir_decl = zir.getDeclaration(inst_resolved.inst); |
| 1415 | 1415 | assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace")); |
| 1416 | 1416 | |
| 1417 | const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 }); | |
| 1417 | const ty_src = block.src(.{ .node_offset_var_decl_ty = .zero }); | |
| 1418 | 1418 | |
| 1419 | 1419 | block.comptime_reason = .{ .reason = .{ |
| 1420 | 1420 | .src = ty_src, |
| ... | ... | @@ -2743,7 +2743,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2743 | 2743 | if (sema.fn_ret_ty_ies) |ies| { |
| 2744 | 2744 | sema.resolveInferredErrorSetPtr(&inner_block, .{ |
| 2745 | 2745 | .base_node_inst = inner_block.src_base_inst, |
| 2746 | .offset = Zcu.LazySrcLoc.Offset.nodeOffset(0), | |
| 2746 | .offset = Zcu.LazySrcLoc.Offset.nodeOffset(.zero), | |
| 2747 | 2747 | }, ies) catch |err| switch (err) { |
| 2748 | 2748 | error.ComptimeReturn => unreachable, |
| 2749 | 2749 | error.ComptimeBreak => unreachable, |
| ... | ... | @@ -2762,7 +2762,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 2762 | 2762 | // result in circular dependency errors. |
| 2763 | 2763 | // TODO: this can go away once we fix backends having to resolve `StackTrace`. |
| 2764 | 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 | 2766 | error.ComptimeReturn => unreachable, |
| 2767 | 2767 | error.ComptimeBreak => unreachable, |
| 2768 | 2768 | else => |e| return e, |
src/main.zig+13-7| ... | ... | @@ -5224,7 +5224,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 5224 | 5224 | .arena = std.heap.ArenaAllocator.init(gpa), |
| 5225 | 5225 | .location = .{ .relative_path = build_mod.root }, |
| 5226 | 5226 | .location_tok = 0, |
| 5227 | .hash_tok = 0, | |
| 5227 | .hash_tok = .none, | |
| 5228 | 5228 | .name_tok = 0, |
| 5229 | 5229 | .lazy_status = .eager, |
| 5230 | 5230 | .parent_package_root = build_mod.root, |
| ... | ... | @@ -6285,8 +6285,10 @@ fn cmdAstCheck( |
| 6285 | 6285 | file.tree.?.tokens.len * (@sizeOf(std.zig.Token.Tag) + @sizeOf(Ast.ByteOffset)); |
| 6286 | 6286 | const tree_bytes = @sizeOf(Ast) + file.tree.?.nodes.len * |
| 6287 | 6287 | (@sizeOf(Ast.Node.Tag) + |
| 6288 | @sizeOf(Ast.Node.Data) + | |
| 6289 | @sizeOf(Ast.TokenIndex)); | |
| 6288 | @sizeOf(Ast.TokenIndex) + | |
| 6289 | // Here we don't use @sizeOf(Ast.Node.Data) because it would include | |
| 6290 | // the debug safety tag but we want to measure release size. | |
| 6291 | 8); | |
| 6290 | 6292 | const instruction_bytes = file.zir.?.instructions.len * |
| 6291 | 6293 | // Here we don't use @sizeOf(Zir.Inst.Data) because it would include |
| 6292 | 6294 | // the debug safety tag but we want to measure release size. |
| ... | ... | @@ -7126,7 +7128,7 @@ fn cmdFetch( |
| 7126 | 7128 | .arena = std.heap.ArenaAllocator.init(gpa), |
| 7127 | 7129 | .location = .{ .path_or_url = path_or_url }, |
| 7128 | 7130 | .location_tok = 0, |
| 7129 | .hash_tok = 0, | |
| 7131 | .hash_tok = .none, | |
| 7130 | 7132 | .name_tok = 0, |
| 7131 | 7133 | .lazy_status = .eager, |
| 7132 | 7134 | .parent_package_root = undefined, |
| ... | ... | @@ -7282,15 +7284,19 @@ fn cmdFetch( |
| 7282 | 7284 | |
| 7283 | 7285 | warn("overwriting existing dependency named '{s}'", .{name}); |
| 7284 | 7286 | try fixups.replace_nodes_with_string.put(gpa, dep.location_node, location_replace); |
| 7285 | try fixups.replace_nodes_with_string.put(gpa, dep.hash_node, hash_replace); | |
| 7287 | if (dep.hash_node.unwrap()) |hash_node| { | |
| 7288 | try fixups.replace_nodes_with_string.put(gpa, hash_node, hash_replace); | |
| 7289 | } else { | |
| 7290 | // https://github.com/ziglang/zig/issues/21690 | |
| 7291 | } | |
| 7286 | 7292 | } else if (manifest.dependencies.count() > 0) { |
| 7287 | 7293 | // Add fixup for adding another dependency. |
| 7288 | 7294 | const deps = manifest.dependencies.values(); |
| 7289 | 7295 | const last_dep_node = deps[deps.len - 1].node; |
| 7290 | 7296 | try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text); |
| 7291 | } else if (manifest.dependencies_node != 0) { | |
| 7297 | } else if (manifest.dependencies_node.unwrap()) |dependencies_node| { | |
| 7292 | 7298 | // Add fixup for replacing the entire dependencies struct. |
| 7293 | try fixups.replace_nodes_with_string.put(gpa, manifest.dependencies_node, dependencies_init); | |
| 7299 | try fixups.replace_nodes_with_string.put(gpa, dependencies_node, dependencies_init); | |
| 7294 | 7300 | } else { |
| 7295 | 7301 | // Add fixup for adding dependencies struct. |
| 7296 | 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 | 24 | .file = scope_file, |
| 25 | 25 | .code = scope_file.zir.?, |
| 26 | 26 | .indent = 0, |
| 27 | .parent_decl_node = 0, | |
| 27 | .parent_decl_node = .root, | |
| 28 | 28 | .recurse_decls = true, |
| 29 | 29 | .recurse_blocks = true, |
| 30 | 30 | }; |
| ... | ... | @@ -185,10 +185,6 @@ const Writer = struct { |
| 185 | 185 | } |
| 186 | 186 | } = .{}, |
| 187 | 187 | |
| 188 | fn relativeToNodeIndex(self: *Writer, offset: i32) Ast.Node.Index { | |
| 189 | return @bitCast(offset + @as(i32, @bitCast(self.parent_decl_node))); | |
| 190 | } | |
| 191 | ||
| 192 | 188 | fn writeInstToStream( |
| 193 | 189 | self: *Writer, |
| 194 | 190 | stream: anytype, |
| ... | ... | @@ -595,7 +591,7 @@ const Writer = struct { |
| 595 | 591 | const prev_parent_decl_node = self.parent_decl_node; |
| 596 | 592 | self.parent_decl_node = inst_data.node; |
| 597 | 593 | defer self.parent_decl_node = prev_parent_decl_node; |
| 598 | try self.writeSrcNode(stream, 0); | |
| 594 | try self.writeSrcNode(stream, .zero); | |
| 599 | 595 | }, |
| 600 | 596 | |
| 601 | 597 | .builtin_extern, |
| ... | ... | @@ -631,7 +627,8 @@ const Writer = struct { |
| 631 | 627 | |
| 632 | 628 | fn writeExtNode(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 633 | 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 | } |
| 636 | 633 | |
| 637 | 634 | fn writeArrayInitElemType(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void { |
| ... | ... | @@ -1579,7 +1576,7 @@ const Writer = struct { |
| 1579 | 1576 | try stream.writeByteNTimes(' ', self.indent); |
| 1580 | 1577 | try stream.writeAll("}) "); |
| 1581 | 1578 | } |
| 1582 | try self.writeSrcNode(stream, 0); | |
| 1579 | try self.writeSrcNode(stream, .zero); | |
| 1583 | 1580 | } |
| 1584 | 1581 | |
| 1585 | 1582 | fn writeUnionDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| ... | ... | @@ -1659,7 +1656,7 @@ const Writer = struct { |
| 1659 | 1656 | |
| 1660 | 1657 | if (fields_len == 0) { |
| 1661 | 1658 | try stream.writeAll("}) "); |
| 1662 | try self.writeSrcNode(stream, 0); | |
| 1659 | try self.writeSrcNode(stream, .zero); | |
| 1663 | 1660 | return; |
| 1664 | 1661 | } |
| 1665 | 1662 | try stream.writeAll(", "); |
| ... | ... | @@ -1730,7 +1727,7 @@ const Writer = struct { |
| 1730 | 1727 | self.indent -= 2; |
| 1731 | 1728 | try stream.writeByteNTimes(' ', self.indent); |
| 1732 | 1729 | try stream.writeAll("}) "); |
| 1733 | try self.writeSrcNode(stream, 0); | |
| 1730 | try self.writeSrcNode(stream, .zero); | |
| 1734 | 1731 | } |
| 1735 | 1732 | |
| 1736 | 1733 | fn writeEnumDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| ... | ... | @@ -1849,7 +1846,7 @@ const Writer = struct { |
| 1849 | 1846 | try stream.writeByteNTimes(' ', self.indent); |
| 1850 | 1847 | try stream.writeAll("}) "); |
| 1851 | 1848 | } |
| 1852 | try self.writeSrcNode(stream, 0); | |
| 1849 | try self.writeSrcNode(stream, .zero); | |
| 1853 | 1850 | } |
| 1854 | 1851 | |
| 1855 | 1852 | fn writeOpaqueDecl( |
| ... | ... | @@ -1893,7 +1890,7 @@ const Writer = struct { |
| 1893 | 1890 | try stream.writeByteNTimes(' ', self.indent); |
| 1894 | 1891 | try stream.writeAll("}) "); |
| 1895 | 1892 | } |
| 1896 | try self.writeSrcNode(stream, 0); | |
| 1893 | try self.writeSrcNode(stream, .zero); | |
| 1897 | 1894 | } |
| 1898 | 1895 | |
| 1899 | 1896 | fn writeTupleDecl(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| ... | ... | @@ -2539,7 +2536,7 @@ const Writer = struct { |
| 2539 | 2536 | ret_ty_body: []const Zir.Inst.Index, |
| 2540 | 2537 | ret_ty_is_generic: bool, |
| 2541 | 2538 | body: []const Zir.Inst.Index, |
| 2542 | src_node: i32, | |
| 2539 | src_node: Ast.Node.Offset, | |
| 2543 | 2540 | src_locs: Zir.Inst.Func.SrcLocs, |
| 2544 | 2541 | noalias_bits: u32, |
| 2545 | 2542 | ) !void { |
| ... | ... | @@ -2647,18 +2644,20 @@ const Writer = struct { |
| 2647 | 2644 | } |
| 2648 | 2645 | |
| 2649 | 2646 | try stream.writeAll(") "); |
| 2650 | try self.writeSrcNode(stream, 0); | |
| 2647 | try self.writeSrcNode(stream, .zero); | |
| 2651 | 2648 | } |
| 2652 | 2649 | |
| 2653 | 2650 | fn writeClosureGet(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 2654 | 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 | } |
| 2657 | 2655 | |
| 2658 | 2656 | fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| 2659 | 2657 | const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); |
| 2660 | 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 | } |
| 2663 | 2662 | |
| 2664 | 2663 | fn writeInplaceArithResultTy(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void { |
| ... | ... | @@ -2760,9 +2759,9 @@ const Writer = struct { |
| 2760 | 2759 | try stream.writeAll(name); |
| 2761 | 2760 | } |
| 2762 | 2761 | |
| 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 | 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 | 2765 | const src_span = tree.nodeToSpan(abs_node); |
| 2767 | 2766 | const start = self.line_col_cursor.find(tree.source, src_span.start); |
| 2768 | 2767 | const end = self.line_col_cursor.find(tree.source, src_span.end); |
| ... | ... | @@ -2772,10 +2771,10 @@ const Writer = struct { |
| 2772 | 2771 | }); |
| 2773 | 2772 | } |
| 2774 | 2773 | |
| 2775 | fn writeSrcTok(self: *Writer, stream: anytype, src_tok: u32) !void { | |
| 2774 | fn writeSrcTok(self: *Writer, stream: anytype, src_tok: Ast.TokenOffset) !void { | |
| 2776 | 2775 | const tree = self.file.tree orelse return; |
| 2777 | const abs_tok = tree.firstToken(self.parent_decl_node) + src_tok; | |
| 2778 | const span_start = tree.tokens.items(.start)[abs_tok]; | |
| 2776 | const abs_tok = src_tok.toAbsolute(tree.firstToken(self.parent_decl_node)); | |
| 2777 | const span_start = tree.tokenStart(abs_tok); | |
| 2779 | 2778 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(abs_tok).len)); |
| 2780 | 2779 | const start = self.line_col_cursor.find(tree.source, span_start); |
| 2781 | 2780 | const end = self.line_col_cursor.find(tree.source, span_end); |
| ... | ... | @@ -2785,9 +2784,9 @@ const Writer = struct { |
| 2785 | 2784 | }); |
| 2786 | 2785 | } |
| 2787 | 2786 | |
| 2788 | fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: u32) !void { | |
| 2787 | fn writeSrcTokAbs(self: *Writer, stream: anytype, src_tok: Ast.TokenIndex) !void { | |
| 2789 | 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 | 2790 | const span_end = span_start + @as(u32, @intCast(tree.tokenSlice(src_tok).len)); |
| 2792 | 2791 | const start = self.line_col_cursor.find(tree.source, span_start); |
| 2793 | 2792 | const end = self.line_col_cursor.find(tree.source, span_end); |
test/cases/translate_c/continue_from_while.c created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | void foo() { | |
| 2 | for (;;) { | |
| 3 | continue; | |
| 4 | } | |
| 5 | } | |
| 6 | ||
| 7 | // translate-c | |
| 8 | // c_frontend=clang | |
| 9 | // | |
| 10 | // pub export fn foo() void { | |
| 11 | // while (true) { | |
| 12 | // continue; | |
| 13 | // } | |
| 14 | // } |