| author | |
| committer | |
| log | ca6fb30e992fd86ee41a6510ef731e86f5de77c9 |
| tree | 72fc291a37d62fb3eee341ae1203c559968c0856 |
| parent | 6dcd8f4f75098c716ed617a388c96238c70aff17 |
| signature |
This commits adds the following distinct integer types to std.zig.Ast:
- OptionalTokenIndex
- TokenOffset
- OptionalTokenOffset
- Node.OptionalIndex
- Node.Offset
- Node.OptionalOffset
The `Node.Index` type has also been converted to a distinct type while
`TokenIndex` remains unchanged.
`Ast.Node.Data` has also been changed to a (untagged) union to provide
safety checks.25 files changed, 4559 insertions(+), 5056 deletions(-)
lib/compiler/aro_translate_c/ast.zig+383-440| ... | ... | @@ -775,10 +775,7 @@ pub fn render(gpa: Allocator, nodes: []const Node) !std.zig.Ast { |
| 775 | 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 = 0, | |
| 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+144-207| ... | ... | @@ -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| { |
| ... | ... | @@ -239,46 +230,27 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 239 | 230 | }, |
| 240 | 231 | |
| 241 | 232 | .@"errdefer" => { |
| 242 | const expr = datas[node].rhs; | |
| 233 | const expr = ast.nodeData(node).opt_token_and_node[1]; | |
| 243 | 234 | return walkExpression(w, expr); |
| 244 | 235 | }, |
| 245 | 236 | |
| 246 | .@"defer" => { | |
| 247 | const expr = datas[node].rhs; | |
| 248 | return walkExpression(w, expr); | |
| 249 | }, | |
| 250 | .@"comptime", .@"nosuspend" => { | |
| 251 | const block = datas[node].lhs; | |
| 252 | return walkExpression(w, block); | |
| 253 | }, | |
| 254 | ||
| 255 | .@"suspend" => { | |
| 256 | const body = datas[node].lhs; | |
| 257 | return walkExpression(w, body); | |
| 258 | }, | |
| 259 | ||
| 260 | .@"catch" => { | |
| 261 | try walkExpression(w, datas[node].lhs); // target | |
| 262 | try walkExpression(w, datas[node].rhs); // fallback | |
| 237 | .@"defer", | |
| 238 | .@"comptime", | |
| 239 | .@"nosuspend", | |
| 240 | .@"suspend", | |
| 241 | => { | |
| 242 | return walkExpression(w, ast.nodeData(node).node); | |
| 263 | 243 | }, |
| 264 | 244 | |
| 265 | 245 | .field_access => { |
| 266 | const field_access = datas[node]; | |
| 267 | try walkExpression(w, field_access.lhs); | |
| 246 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 268 | 247 | }, |
| 269 | 248 | |
| 270 | .error_union, | |
| 271 | .switch_range, | |
| 272 | => { | |
| 273 | const infix = datas[node]; | |
| 274 | try walkExpression(w, infix.lhs); | |
| 275 | return walkExpression(w, infix.rhs); | |
| 276 | }, | |
| 277 | 249 | .for_range => { |
| 278 | const infix = datas[node]; | |
| 279 | try walkExpression(w, infix.lhs); | |
| 280 | if (infix.rhs != 0) { | |
| 281 | return walkExpression(w, infix.rhs); | |
| 250 | const start, const opt_end = ast.nodeData(node).node_and_opt_node; | |
| 251 | try walkExpression(w, start); | |
| 252 | if (opt_end.unwrap()) |end| { | |
| 253 | return walkExpression(w, end); | |
| 282 | 254 | } |
| 283 | 255 | }, |
| 284 | 256 | |
| ... | ... | @@ -328,17 +300,21 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 328 | 300 | .sub, |
| 329 | 301 | .sub_wrap, |
| 330 | 302 | .sub_sat, |
| 303 | .@"catch", | |
| 304 | .error_union, | |
| 305 | .switch_range, | |
| 331 | 306 | .@"orelse", |
| 307 | .array_access, | |
| 332 | 308 | => { |
| 333 | const infix = datas[node]; | |
| 334 | try walkExpression(w, infix.lhs); | |
| 335 | try walkExpression(w, infix.rhs); | |
| 309 | const lhs, const rhs = ast.nodeData(node).node_and_node; | |
| 310 | try walkExpression(w, lhs); | |
| 311 | try walkExpression(w, rhs); | |
| 336 | 312 | }, |
| 337 | 313 | |
| 338 | 314 | .assign_destructure => { |
| 339 | 315 | const full = ast.assignDestructure(node); |
| 340 | 316 | for (full.ast.variables) |variable_node| { |
| 341 | switch (node_tags[variable_node]) { | |
| 317 | switch (ast.nodeTag(variable_node)) { | |
| 342 | 318 | .global_var_decl, |
| 343 | 319 | .local_var_decl, |
| 344 | 320 | .simple_var_decl, |
| ... | ... | @@ -357,15 +333,12 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 357 | 333 | .negation_wrap, |
| 358 | 334 | .optional_type, |
| 359 | 335 | .address_of, |
| 360 | => { | |
| 361 | return walkExpression(w, datas[node].lhs); | |
| 362 | }, | |
| 363 | ||
| 364 | 336 | .@"try", |
| 365 | 337 | .@"resume", |
| 366 | 338 | .@"await", |
| 339 | .deref, | |
| 367 | 340 | => { |
| 368 | return walkExpression(w, datas[node].lhs); | |
| 341 | return walkExpression(w, ast.nodeData(node).node); | |
| 369 | 342 | }, |
| 370 | 343 | |
| 371 | 344 | .array_type, |
| ... | ... | @@ -417,51 +390,40 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 417 | 390 | return walkCall(w, ast.fullCall(&buf, node).?); |
| 418 | 391 | }, |
| 419 | 392 | |
| 420 | .array_access => { | |
| 421 | const suffix = datas[node]; | |
| 422 | try walkExpression(w, suffix.lhs); | |
| 423 | try walkExpression(w, suffix.rhs); | |
| 424 | }, | |
| 425 | ||
| 426 | 393 | .slice_open, .slice, .slice_sentinel => return walkSlice(w, node, ast.fullSlice(node).?), |
| 427 | 394 | |
| 428 | .deref => { | |
| 429 | try walkExpression(w, datas[node].lhs); | |
| 430 | }, | |
| 431 | ||
| 432 | 395 | .unwrap_optional => { |
| 433 | try walkExpression(w, datas[node].lhs); | |
| 396 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 434 | 397 | }, |
| 435 | 398 | |
| 436 | 399 | .@"break" => { |
| 437 | const label_token = datas[node].lhs; | |
| 438 | const target = datas[node].rhs; | |
| 439 | if (label_token == 0 and target == 0) { | |
| 400 | const label_token, const target = ast.nodeData(node).opt_token_and_opt_node; | |
| 401 | if (label_token == .none and target == .none) { | |
| 440 | 402 | // no expressions |
| 441 | } else if (label_token == 0 and target != 0) { | |
| 442 | try walkExpression(w, target); | |
| 443 | } else if (label_token != 0 and target == 0) { | |
| 444 | try walkIdentifier(w, label_token); | |
| 445 | } else if (label_token != 0 and target != 0) { | |
| 446 | try walkExpression(w, target); | |
| 403 | } else if (label_token == .none and target != .none) { | |
| 404 | try walkExpression(w, target.unwrap().?); | |
| 405 | } else if (label_token != .none and target == .none) { | |
| 406 | try walkIdentifier(w, label_token.unwrap().?); | |
| 407 | } else if (label_token != .none and target != .none) { | |
| 408 | try walkExpression(w, target.unwrap().?); | |
| 447 | 409 | } |
| 448 | 410 | }, |
| 449 | 411 | |
| 450 | 412 | .@"continue" => { |
| 451 | const label = datas[node].lhs; | |
| 452 | if (label != 0) { | |
| 453 | return walkIdentifier(w, label); // label | |
| 413 | const opt_label = ast.nodeData(node).opt_token_and_opt_node[0]; | |
| 414 | if (opt_label.unwrap()) |label| { | |
| 415 | return walkIdentifier(w, label); | |
| 454 | 416 | } |
| 455 | 417 | }, |
| 456 | 418 | |
| 457 | 419 | .@"return" => { |
| 458 | if (datas[node].lhs != 0) { | |
| 459 | try walkExpression(w, datas[node].lhs); | |
| 420 | if (ast.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 421 | try walkExpression(w, lhs); | |
| 460 | 422 | } |
| 461 | 423 | }, |
| 462 | 424 | |
| 463 | 425 | .grouped_expression => { |
| 464 | try walkExpression(w, datas[node].lhs); | |
| 426 | try walkExpression(w, ast.nodeData(node).node_and_token[0]); | |
| 465 | 427 | }, |
| 466 | 428 | |
| 467 | 429 | .container_decl, |
| ... | ... | @@ -482,13 +444,13 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 482 | 444 | }, |
| 483 | 445 | |
| 484 | 446 | .error_set_decl => { |
| 485 | const error_token = main_tokens[node]; | |
| 447 | const error_token = ast.nodeMainToken(node); | |
| 486 | 448 | const lbrace = error_token + 1; |
| 487 | const rbrace = datas[node].rhs; | |
| 449 | const rbrace = ast.nodeData(node).token; | |
| 488 | 450 | |
| 489 | 451 | var i = lbrace + 1; |
| 490 | 452 | while (i < rbrace) : (i += 1) { |
| 491 | switch (token_tags[i]) { | |
| 453 | switch (ast.tokenTag(i)) { | |
| 492 | 454 | .doc_comment => unreachable, // TODO |
| 493 | 455 | .identifier => try walkIdentifier(w, i), |
| 494 | 456 | .comma => {}, |
| ... | ... | @@ -517,20 +479,16 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 517 | 479 | }, |
| 518 | 480 | |
| 519 | 481 | .anyframe_type => { |
| 520 | if (datas[node].rhs != 0) { | |
| 521 | return walkExpression(w, datas[node].rhs); | |
| 522 | } | |
| 482 | _, const child_type = ast.nodeData(node).token_and_node; | |
| 483 | return walkExpression(w, child_type); | |
| 523 | 484 | }, |
| 524 | 485 | |
| 525 | 486 | .@"switch", |
| 526 | 487 | .switch_comma, |
| 527 | 488 | => { |
| 528 | const condition = datas[node].lhs; | |
| 529 | const extra = ast.extraData(datas[node].rhs, Ast.Node.SubRange); | |
| 530 | const cases = ast.extra_data[extra.start..extra.end]; | |
| 531 | ||
| 532 | try walkExpression(w, condition); // condition expression | |
| 533 | try walkExpressions(w, cases); | |
| 489 | const full = ast.fullSwitch(node).?; | |
| 490 | try walkExpression(w, full.ast.condition); // condition expression | |
| 491 | try walkExpressions(w, full.ast.cases); | |
| 534 | 492 | }, |
| 535 | 493 | |
| 536 | 494 | .switch_case_one, |
| ... | ... | @@ -557,7 +515,7 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 557 | 515 | => return walkAsm(w, ast.fullAsm(node).?), |
| 558 | 516 | |
| 559 | 517 | .enum_literal => { |
| 560 | return walkIdentifier(w, main_tokens[node]); // name | |
| 518 | return walkIdentifier(w, ast.nodeMainToken(node)); // name | |
| 561 | 519 | }, |
| 562 | 520 | |
| 563 | 521 | .fn_decl => unreachable, |
| ... | ... | @@ -579,66 +537,66 @@ fn walkExpression(w: *Walk, node: Ast.Node.Index) Error!void { |
| 579 | 537 | fn walkGlobalVarDecl(w: *Walk, decl_node: Ast.Node.Index, var_decl: Ast.full.VarDecl) Error!void { |
| 580 | 538 | _ = decl_node; |
| 581 | 539 | |
| 582 | if (var_decl.ast.type_node != 0) { | |
| 583 | try walkExpression(w, var_decl.ast.type_node); | |
| 540 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 541 | try walkExpression(w, type_node); | |
| 584 | 542 | } |
| 585 | 543 | |
| 586 | if (var_decl.ast.align_node != 0) { | |
| 587 | try walkExpression(w, var_decl.ast.align_node); | |
| 544 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 545 | try walkExpression(w, align_node); | |
| 588 | 546 | } |
| 589 | 547 | |
| 590 | if (var_decl.ast.addrspace_node != 0) { | |
| 591 | try walkExpression(w, var_decl.ast.addrspace_node); | |
| 548 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 549 | try walkExpression(w, addrspace_node); | |
| 592 | 550 | } |
| 593 | 551 | |
| 594 | if (var_decl.ast.section_node != 0) { | |
| 595 | try walkExpression(w, var_decl.ast.section_node); | |
| 552 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 553 | try walkExpression(w, section_node); | |
| 596 | 554 | } |
| 597 | 555 | |
| 598 | if (var_decl.ast.init_node != 0) { | |
| 599 | if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) { | |
| 600 | try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node }); | |
| 556 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 557 | if (!isUndefinedIdent(w.ast, init_node)) { | |
| 558 | try w.transformations.append(.{ .replace_with_undef = init_node }); | |
| 601 | 559 | } |
| 602 | try walkExpression(w, var_decl.ast.init_node); | |
| 560 | try walkExpression(w, init_node); | |
| 603 | 561 | } |
| 604 | 562 | } |
| 605 | 563 | |
| 606 | 564 | fn walkLocalVarDecl(w: *Walk, var_decl: Ast.full.VarDecl) Error!void { |
| 607 | 565 | try walkIdentifierNew(w, var_decl.ast.mut_token + 1); // name |
| 608 | 566 | |
| 609 | if (var_decl.ast.type_node != 0) { | |
| 610 | try walkExpression(w, var_decl.ast.type_node); | |
| 567 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 568 | try walkExpression(w, type_node); | |
| 611 | 569 | } |
| 612 | 570 | |
| 613 | if (var_decl.ast.align_node != 0) { | |
| 614 | try walkExpression(w, var_decl.ast.align_node); | |
| 571 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 572 | try walkExpression(w, align_node); | |
| 615 | 573 | } |
| 616 | 574 | |
| 617 | if (var_decl.ast.addrspace_node != 0) { | |
| 618 | try walkExpression(w, var_decl.ast.addrspace_node); | |
| 575 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 576 | try walkExpression(w, addrspace_node); | |
| 619 | 577 | } |
| 620 | 578 | |
| 621 | if (var_decl.ast.section_node != 0) { | |
| 622 | try walkExpression(w, var_decl.ast.section_node); | |
| 579 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 580 | try walkExpression(w, section_node); | |
| 623 | 581 | } |
| 624 | 582 | |
| 625 | if (var_decl.ast.init_node != 0) { | |
| 626 | if (!isUndefinedIdent(w.ast, var_decl.ast.init_node)) { | |
| 627 | try w.transformations.append(.{ .replace_with_undef = var_decl.ast.init_node }); | |
| 583 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 584 | if (!isUndefinedIdent(w.ast, init_node)) { | |
| 585 | try w.transformations.append(.{ .replace_with_undef = init_node }); | |
| 628 | 586 | } |
| 629 | try walkExpression(w, var_decl.ast.init_node); | |
| 587 | try walkExpression(w, init_node); | |
| 630 | 588 | } |
| 631 | 589 | } |
| 632 | 590 | |
| 633 | 591 | fn walkContainerField(w: *Walk, field: Ast.full.ContainerField) Error!void { |
| 634 | if (field.ast.type_expr != 0) { | |
| 635 | try walkExpression(w, field.ast.type_expr); // type | |
| 592 | if (field.ast.type_expr.unwrap()) |type_expr| { | |
| 593 | try walkExpression(w, type_expr); // type | |
| 636 | 594 | } |
| 637 | if (field.ast.align_expr != 0) { | |
| 638 | try walkExpression(w, field.ast.align_expr); // alignment | |
| 595 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 596 | try walkExpression(w, align_expr); // alignment | |
| 639 | 597 | } |
| 640 | if (field.ast.value_expr != 0) { | |
| 641 | try walkExpression(w, field.ast.value_expr); // value | |
| 598 | if (field.ast.value_expr.unwrap()) |value_expr| { | |
| 599 | try walkExpression(w, value_expr); // value | |
| 642 | 600 | } |
| 643 | 601 | } |
| 644 | 602 | |
| ... | ... | @@ -649,18 +607,17 @@ fn walkBlock( |
| 649 | 607 | ) Error!void { |
| 650 | 608 | _ = block_node; |
| 651 | 609 | const ast = w.ast; |
| 652 | const node_tags = ast.nodes.items(.tag); | |
| 653 | 610 | |
| 654 | 611 | for (statements) |stmt| { |
| 655 | switch (node_tags[stmt]) { | |
| 612 | switch (ast.nodeTag(stmt)) { | |
| 656 | 613 | .global_var_decl, |
| 657 | 614 | .local_var_decl, |
| 658 | 615 | .simple_var_decl, |
| 659 | 616 | .aligned_var_decl, |
| 660 | 617 | => { |
| 661 | 618 | const var_decl = ast.fullVarDecl(stmt).?; |
| 662 | if (var_decl.ast.init_node != 0 and | |
| 663 | isUndefinedIdent(w.ast, var_decl.ast.init_node)) | |
| 619 | if (var_decl.ast.init_node != .none and | |
| 620 | isUndefinedIdent(w.ast, var_decl.ast.init_node.unwrap().?)) | |
| 664 | 621 | { |
| 665 | 622 | try w.transformations.append(.{ .delete_var_decl = .{ |
| 666 | 623 | .var_decl_node = stmt, |
| ... | ... | @@ -691,15 +648,15 @@ fn walkBlock( |
| 691 | 648 | |
| 692 | 649 | fn walkArrayType(w: *Walk, array_type: Ast.full.ArrayType) Error!void { |
| 693 | 650 | try walkExpression(w, array_type.ast.elem_count); |
| 694 | if (array_type.ast.sentinel != 0) { | |
| 695 | try walkExpression(w, array_type.ast.sentinel); | |
| 651 | if (array_type.ast.sentinel.unwrap()) |sentinel| { | |
| 652 | try walkExpression(w, sentinel); | |
| 696 | 653 | } |
| 697 | 654 | return walkExpression(w, array_type.ast.elem_type); |
| 698 | 655 | } |
| 699 | 656 | |
| 700 | 657 | fn walkArrayInit(w: *Walk, array_init: Ast.full.ArrayInit) Error!void { |
| 701 | if (array_init.ast.type_expr != 0) { | |
| 702 | try walkExpression(w, array_init.ast.type_expr); // T | |
| 658 | if (array_init.ast.type_expr.unwrap()) |type_expr| { | |
| 659 | try walkExpression(w, type_expr); // T | |
| 703 | 660 | } |
| 704 | 661 | for (array_init.ast.elements) |elem_init| { |
| 705 | 662 | try walkExpression(w, elem_init); |
| ... | ... | @@ -712,8 +669,8 @@ fn walkStructInit( |
| 712 | 669 | struct_init: Ast.full.StructInit, |
| 713 | 670 | ) Error!void { |
| 714 | 671 | _ = struct_node; |
| 715 | if (struct_init.ast.type_expr != 0) { | |
| 716 | try walkExpression(w, struct_init.ast.type_expr); // T | |
| 672 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 673 | try walkExpression(w, type_expr); // T | |
| 717 | 674 | } |
| 718 | 675 | for (struct_init.ast.fields) |field_init| { |
| 719 | 676 | try walkExpression(w, field_init); |
| ... | ... | @@ -733,18 +690,17 @@ fn walkSlice( |
| 733 | 690 | _ = slice_node; |
| 734 | 691 | try walkExpression(w, slice.ast.sliced); |
| 735 | 692 | try walkExpression(w, slice.ast.start); |
| 736 | if (slice.ast.end != 0) { | |
| 737 | try walkExpression(w, slice.ast.end); | |
| 693 | if (slice.ast.end.unwrap()) |end| { | |
| 694 | try walkExpression(w, end); | |
| 738 | 695 | } |
| 739 | if (slice.ast.sentinel != 0) { | |
| 740 | try walkExpression(w, slice.ast.sentinel); | |
| 696 | if (slice.ast.sentinel.unwrap()) |sentinel| { | |
| 697 | try walkExpression(w, sentinel); | |
| 741 | 698 | } |
| 742 | 699 | } |
| 743 | 700 | |
| 744 | 701 | fn walkIdentifier(w: *Walk, name_ident: Ast.TokenIndex) Error!void { |
| 745 | 702 | const ast = w.ast; |
| 746 | const token_tags = ast.tokens.items(.tag); | |
| 747 | assert(token_tags[name_ident] == .identifier); | |
| 703 | assert(ast.tokenTag(name_ident) == .identifier); | |
| 748 | 704 | const name_bytes = ast.tokenSlice(name_ident); |
| 749 | 705 | _ = w.unreferenced_globals.swapRemove(name_bytes); |
| 750 | 706 | } |
| ... | ... | @@ -760,8 +716,8 @@ fn walkContainerDecl( |
| 760 | 716 | container_decl: Ast.full.ContainerDecl, |
| 761 | 717 | ) Error!void { |
| 762 | 718 | _ = container_decl_node; |
| 763 | if (container_decl.ast.arg != 0) { | |
| 764 | try walkExpression(w, container_decl.ast.arg); | |
| 719 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 720 | try walkExpression(w, arg); | |
| 765 | 721 | } |
| 766 | 722 | try walkMembers(w, container_decl.ast.members); |
| 767 | 723 | } |
| ... | ... | @@ -772,14 +728,13 @@ fn walkBuiltinCall( |
| 772 | 728 | params: []const Ast.Node.Index, |
| 773 | 729 | ) Error!void { |
| 774 | 730 | const ast = w.ast; |
| 775 | const main_tokens = ast.nodes.items(.main_token); | |
| 776 | const builtin_token = main_tokens[call_node]; | |
| 731 | const builtin_token = ast.nodeMainToken(call_node); | |
| 777 | 732 | const builtin_name = ast.tokenSlice(builtin_token); |
| 778 | 733 | const info = BuiltinFn.list.get(builtin_name).?; |
| 779 | 734 | switch (info.tag) { |
| 780 | 735 | .import => { |
| 781 | 736 | const operand_node = params[0]; |
| 782 | const str_lit_token = main_tokens[operand_node]; | |
| 737 | const str_lit_token = ast.nodeMainToken(operand_node); | |
| 783 | 738 | const token_bytes = ast.tokenSlice(str_lit_token); |
| 784 | 739 | if (std.mem.endsWith(u8, token_bytes, ".zig\"")) { |
| 785 | 740 | const imported_string = std.zig.string_literal.parseAlloc(w.arena, token_bytes) catch |
| ... | ... | @@ -808,29 +763,30 @@ fn walkFnProto(w: *Walk, fn_proto: Ast.full.FnProto) Error!void { |
| 808 | 763 | { |
| 809 | 764 | var it = fn_proto.iterate(ast); |
| 810 | 765 | while (it.next()) |param| { |
| 811 | if (param.type_expr != 0) { | |
| 812 | try walkExpression(w, param.type_expr); | |
| 766 | if (param.type_expr) |type_expr| { | |
| 767 | try walkExpression(w, type_expr); | |
| 813 | 768 | } |
| 814 | 769 | } |
| 815 | 770 | } |
| 816 | 771 | |
| 817 | if (fn_proto.ast.align_expr != 0) { | |
| 818 | try walkExpression(w, fn_proto.ast.align_expr); | |
| 772 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 773 | try walkExpression(w, align_expr); | |
| 819 | 774 | } |
| 820 | 775 | |
| 821 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 822 | try walkExpression(w, fn_proto.ast.addrspace_expr); | |
| 776 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 777 | try walkExpression(w, addrspace_expr); | |
| 823 | 778 | } |
| 824 | 779 | |
| 825 | if (fn_proto.ast.section_expr != 0) { | |
| 826 | try walkExpression(w, fn_proto.ast.section_expr); | |
| 780 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 781 | try walkExpression(w, section_expr); | |
| 827 | 782 | } |
| 828 | 783 | |
| 829 | if (fn_proto.ast.callconv_expr != 0) { | |
| 830 | try walkExpression(w, fn_proto.ast.callconv_expr); | |
| 784 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 785 | try walkExpression(w, callconv_expr); | |
| 831 | 786 | } |
| 832 | 787 | |
| 833 | try walkExpression(w, fn_proto.ast.return_type); | |
| 788 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 789 | try walkExpression(w, return_type); | |
| 834 | 790 | } |
| 835 | 791 | |
| 836 | 792 | fn walkExpressions(w: *Walk, expressions: []const Ast.Node.Index) Error!void { |
| ... | ... | @@ -847,16 +803,13 @@ fn walkSwitchCase(w: *Walk, switch_case: Ast.full.SwitchCase) Error!void { |
| 847 | 803 | } |
| 848 | 804 | |
| 849 | 805 | fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) Error!void { |
| 850 | assert(while_node.ast.cond_expr != 0); | |
| 851 | assert(while_node.ast.then_expr != 0); | |
| 852 | ||
| 853 | 806 | // Perform these transformations in this priority order: |
| 854 | 807 | // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already. |
| 855 | 808 | // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already. |
| 856 | 809 | // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression. |
| 857 | 810 | // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression. |
| 858 | 811 | if (!isTrueIdent(w.ast, while_node.ast.cond_expr) and |
| 859 | (while_node.ast.else_expr == 0 or isEmptyBlock(w.ast, while_node.ast.else_expr))) | |
| 812 | (while_node.ast.else_expr == .none or isEmptyBlock(w.ast, while_node.ast.else_expr.unwrap().?))) | |
| 860 | 813 | { |
| 861 | 814 | try w.transformations.ensureUnusedCapacity(1); |
| 862 | 815 | w.transformations.appendAssumeCapacity(.{ .replace_with_true = while_node.ast.cond_expr }); |
| ... | ... | @@ -873,45 +826,39 @@ fn walkWhile(w: *Walk, node_index: Ast.Node.Index, while_node: Ast.full.While) E |
| 873 | 826 | try w.transformations.ensureUnusedCapacity(1); |
| 874 | 827 | w.transformations.appendAssumeCapacity(.{ .replace_node = .{ |
| 875 | 828 | .to_replace = node_index, |
| 876 | .replacement = while_node.ast.else_expr, | |
| 829 | .replacement = while_node.ast.else_expr.unwrap().?, | |
| 877 | 830 | } }); |
| 878 | 831 | } |
| 879 | 832 | |
| 880 | 833 | try walkExpression(w, while_node.ast.cond_expr); // condition |
| 881 | 834 | |
| 882 | if (while_node.ast.cont_expr != 0) { | |
| 883 | try walkExpression(w, while_node.ast.cont_expr); | |
| 835 | if (while_node.ast.cont_expr.unwrap()) |cont_expr| { | |
| 836 | try walkExpression(w, cont_expr); | |
| 884 | 837 | } |
| 885 | 838 | |
| 886 | if (while_node.ast.then_expr != 0) { | |
| 887 | try walkExpression(w, while_node.ast.then_expr); | |
| 888 | } | |
| 889 | if (while_node.ast.else_expr != 0) { | |
| 890 | try walkExpression(w, while_node.ast.else_expr); | |
| 839 | try walkExpression(w, while_node.ast.then_expr); | |
| 840 | ||
| 841 | if (while_node.ast.else_expr.unwrap()) |else_expr| { | |
| 842 | try walkExpression(w, else_expr); | |
| 891 | 843 | } |
| 892 | 844 | } |
| 893 | 845 | |
| 894 | 846 | fn walkFor(w: *Walk, for_node: Ast.full.For) Error!void { |
| 895 | 847 | try walkParamList(w, for_node.ast.inputs); |
| 896 | if (for_node.ast.then_expr != 0) { | |
| 897 | try walkExpression(w, for_node.ast.then_expr); | |
| 898 | } | |
| 899 | if (for_node.ast.else_expr != 0) { | |
| 900 | try walkExpression(w, for_node.ast.else_expr); | |
| 848 | try walkExpression(w, for_node.ast.then_expr); | |
| 849 | if (for_node.ast.else_expr.unwrap()) |else_expr| { | |
| 850 | try walkExpression(w, else_expr); | |
| 901 | 851 | } |
| 902 | 852 | } |
| 903 | 853 | |
| 904 | 854 | fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void { |
| 905 | assert(if_node.ast.cond_expr != 0); | |
| 906 | assert(if_node.ast.then_expr != 0); | |
| 907 | ||
| 908 | 855 | // Perform these transformations in this priority order: |
| 909 | 856 | // 1. If the `else` expression is missing or an empty block, replace the condition with `if (true)` if it is not already. |
| 910 | 857 | // 2. If the `then` block is empty, replace the condition with `if (false)` if it is not already. |
| 911 | 858 | // 3. If the condition is `if (true)`, replace the `if` expression with the contents of the `then` expression. |
| 912 | 859 | // 4. If the condition is `if (false)`, replace the `if` expression with the contents of the `else` expression. |
| 913 | 860 | if (!isTrueIdent(w.ast, if_node.ast.cond_expr) and |
| 914 | (if_node.ast.else_expr == 0 or isEmptyBlock(w.ast, if_node.ast.else_expr))) | |
| 861 | (if_node.ast.else_expr == .none or isEmptyBlock(w.ast, if_node.ast.else_expr.unwrap().?))) | |
| 915 | 862 | { |
| 916 | 863 | try w.transformations.ensureUnusedCapacity(1); |
| 917 | 864 | w.transformations.appendAssumeCapacity(.{ .replace_with_true = if_node.ast.cond_expr }); |
| ... | ... | @@ -928,17 +875,14 @@ fn walkIf(w: *Walk, node_index: Ast.Node.Index, if_node: Ast.full.If) Error!void |
| 928 | 875 | try w.transformations.ensureUnusedCapacity(1); |
| 929 | 876 | w.transformations.appendAssumeCapacity(.{ .replace_node = .{ |
| 930 | 877 | .to_replace = node_index, |
| 931 | .replacement = if_node.ast.else_expr, | |
| 878 | .replacement = if_node.ast.else_expr.unwrap().?, | |
| 932 | 879 | } }); |
| 933 | 880 | } |
| 934 | 881 | |
| 935 | 882 | try walkExpression(w, if_node.ast.cond_expr); // condition |
| 936 | ||
| 937 | if (if_node.ast.then_expr != 0) { | |
| 938 | try walkExpression(w, if_node.ast.then_expr); | |
| 939 | } | |
| 940 | if (if_node.ast.else_expr != 0) { | |
| 941 | try walkExpression(w, if_node.ast.else_expr); | |
| 883 | try walkExpression(w, if_node.ast.then_expr); | |
| 884 | if (if_node.ast.else_expr.unwrap()) |else_expr| { | |
| 885 | try walkExpression(w, else_expr); | |
| 942 | 886 | } |
| 943 | 887 | } |
| 944 | 888 | |
| ... | ... | @@ -958,9 +902,8 @@ fn walkParamList(w: *Walk, params: []const Ast.Node.Index) Error!void { |
| 958 | 902 | /// Check if it is already gutted (i.e. its body replaced with `@trap()`). |
| 959 | 903 | fn isFnBodyGutted(ast: *const Ast, body_node: Ast.Node.Index) bool { |
| 960 | 904 | // skip over discards |
| 961 | const node_tags = ast.nodes.items(.tag); | |
| 962 | 905 | var statements_buf: [2]Ast.Node.Index = undefined; |
| 963 | const statements = switch (node_tags[body_node]) { | |
| 906 | const statements = switch (ast.nodeTag(body_node)) { | |
| 964 | 907 | .block_two, |
| 965 | 908 | .block_two_semicolon, |
| 966 | 909 | .block, |
| ... | ... | @@ -988,10 +931,7 @@ const StmtCategory = enum { |
| 988 | 931 | }; |
| 989 | 932 | |
| 990 | 933 | fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory { |
| 991 | const node_tags = ast.nodes.items(.tag); | |
| 992 | const datas = ast.nodes.items(.data); | |
| 993 | const main_tokens = ast.nodes.items(.main_token); | |
| 994 | switch (node_tags[stmt]) { | |
| 934 | switch (ast.nodeTag(stmt)) { | |
| 995 | 935 | .builtin_call_two, |
| 996 | 936 | .builtin_call_two_comma, |
| 997 | 937 | .builtin_call, |
| ... | ... | @@ -999,12 +939,12 @@ fn categorizeStmt(ast: *const Ast, stmt: Ast.Node.Index) StmtCategory { |
| 999 | 939 | => { |
| 1000 | 940 | var buf: [2]Ast.Node.Index = undefined; |
| 1001 | 941 | const params = ast.builtinCallParams(&buf, stmt).?; |
| 1002 | return categorizeBuiltinCall(ast, main_tokens[stmt], params); | |
| 942 | return categorizeBuiltinCall(ast, ast.nodeMainToken(stmt), params); | |
| 1003 | 943 | }, |
| 1004 | 944 | .assign => { |
| 1005 | const infix = datas[stmt]; | |
| 1006 | if (isDiscardIdent(ast, infix.lhs) and node_tags[infix.rhs] == .identifier) { | |
| 1007 | const name_bytes = ast.tokenSlice(main_tokens[infix.rhs]); | |
| 945 | const lhs, const rhs = ast.nodeData(stmt).node_and_node; | |
| 946 | if (isDiscardIdent(ast, lhs) and ast.nodeTag(rhs) == .identifier) { | |
| 947 | const name_bytes = ast.tokenSlice(ast.nodeMainToken(rhs)); | |
| 1008 | 948 | if (std.mem.eql(u8, name_bytes, "undefined")) { |
| 1009 | 949 | return .discard_undefined; |
| 1010 | 950 | } else { |
| ... | ... | @@ -1046,11 +986,9 @@ fn isFalseIdent(ast: *const Ast, node: Ast.Node.Index) bool { |
| 1046 | 986 | } |
| 1047 | 987 | |
| 1048 | 988 | fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bool { |
| 1049 | const node_tags = ast.nodes.items(.tag); | |
| 1050 | const main_tokens = ast.nodes.items(.main_token); | |
| 1051 | switch (node_tags[node]) { | |
| 989 | switch (ast.nodeTag(node)) { | |
| 1052 | 990 | .identifier => { |
| 1053 | const token_index = main_tokens[node]; | |
| 991 | const token_index = ast.nodeMainToken(node); | |
| 1054 | 992 | const name_bytes = ast.tokenSlice(token_index); |
| 1055 | 993 | return std.mem.eql(u8, name_bytes, string); |
| 1056 | 994 | }, |
| ... | ... | @@ -1059,11 +997,10 @@ fn isMatchingIdent(ast: *const Ast, node: Ast.Node.Index, string: []const u8) bo |
| 1059 | 997 | } |
| 1060 | 998 | |
| 1061 | 999 | fn isEmptyBlock(ast: *const Ast, node: Ast.Node.Index) bool { |
| 1062 | const node_tags = ast.nodes.items(.tag); | |
| 1063 | const node_data = ast.nodes.items(.data); | |
| 1064 | switch (node_tags[node]) { | |
| 1000 | switch (ast.nodeTag(node)) { | |
| 1065 | 1001 | .block_two => { |
| 1066 | return node_data[node].lhs == 0 and node_data[node].rhs == 0; | |
| 1002 | const opt_lhs, const opt_rhs = ast.nodeData(node).opt_node_and_opt_node; | |
| 1003 | return opt_lhs == .none and opt_rhs == .none; | |
| 1067 | 1004 | }, |
| 1068 | 1005 | else => return false, |
| 1069 | 1006 | } |
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+71-94| ... | ... | @@ -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)) { |
| ... | ... | @@ -259,9 +253,9 @@ pub const File = struct { |
| 259 | 253 | .@"if", |
| 260 | 254 | => { |
| 261 | 255 | const if_full = ast.fullIf(node).?; |
| 262 | if (if_full.ast.else_expr != 0) { | |
| 256 | if (if_full.ast.else_expr.unwrap()) |else_expr| { | |
| 263 | 257 | const then_cat = categorize_expr_deep(file_index, if_full.ast.then_expr); |
| 264 | const else_cat = categorize_expr_deep(file_index, if_full.ast.else_expr); | |
| 258 | const else_cat = categorize_expr_deep(file_index, else_expr); | |
| 265 | 259 | if (then_cat == .type_type and else_cat == .type_type) { |
| 266 | 260 | return .type_type; |
| 267 | 261 | } else if (then_cat == .error_set and else_cat == .error_set) { |
| ... | ... | @@ -320,11 +314,10 @@ pub const File = struct { |
| 320 | 314 | params: []const Ast.Node.Index, |
| 321 | 315 | ) Category { |
| 322 | 316 | const ast = file_index.get_ast(); |
| 323 | const main_tokens = ast.nodes.items(.main_token); | |
| 324 | const builtin_token = main_tokens[node]; | |
| 317 | const builtin_token = ast.nodeMainToken(node); | |
| 325 | 318 | const builtin_name = ast.tokenSlice(builtin_token); |
| 326 | 319 | if (std.mem.eql(u8, builtin_name, "@import")) { |
| 327 | const str_lit_token = main_tokens[params[0]]; | |
| 320 | const str_lit_token = ast.nodeMainToken(params[0]); | |
| 328 | 321 | const str_bytes = ast.tokenSlice(str_lit_token); |
| 329 | 322 | const file_path = std.zig.string_literal.parseAlloc(gpa, str_bytes) catch @panic("OOM"); |
| 330 | 323 | defer gpa.free(file_path); |
| ... | ... | @@ -357,14 +350,12 @@ pub const File = struct { |
| 357 | 350 | |
| 358 | 351 | fn categorize_switch(file_index: File.Index, node: Ast.Node.Index) Category { |
| 359 | 352 | const ast = file_index.get_ast(); |
| 360 | const node_datas = ast.nodes.items(.data); | |
| 361 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 362 | const case_nodes = ast.extra_data[extra.start..extra.end]; | |
| 353 | const full = ast.fullSwitch(node).?; | |
| 363 | 354 | var all_type_type = true; |
| 364 | 355 | var all_error_set = true; |
| 365 | 356 | var any_type = false; |
| 366 | if (case_nodes.len == 0) return .{ .global_const = node }; | |
| 367 | for (case_nodes) |case_node| { | |
| 357 | if (full.ast.cases.len == 0) return .{ .global_const = node }; | |
| 358 | for (full.ast.cases) |case_node| { | |
| 368 | 359 | const case = ast.fullSwitchCase(case_node).?; |
| 369 | 360 | switch (categorize_expr_deep(file_index, case.ast.target_expr)) { |
| 370 | 361 | .type_type => { |
| ... | ... | @@ -410,8 +401,8 @@ pub fn add_file(file_name: []const u8, bytes: []u8) !File.Index { |
| 410 | 401 | const scope = try gpa.create(Scope); |
| 411 | 402 | scope.* = .{ .tag = .top }; |
| 412 | 403 | |
| 413 | const decl_index = try file_index.add_decl(0, .none); | |
| 414 | try struct_decl(&w, scope, decl_index, 0, ast.containerDeclRoot()); | |
| 404 | const decl_index = try file_index.add_decl(.root, .none); | |
| 405 | try struct_decl(&w, scope, decl_index, .root, ast.containerDeclRoot()); | |
| 415 | 406 | |
| 416 | 407 | const file = file_index.get(); |
| 417 | 408 | shrinkToFit(&file.ident_decls); |
| ... | ... | @@ -505,13 +496,12 @@ pub const Scope = struct { |
| 505 | 496 | } |
| 506 | 497 | |
| 507 | 498 | pub fn lookup(start_scope: *Scope, ast: *const Ast, name: []const u8) ?Ast.Node.Index { |
| 508 | const main_tokens = ast.nodes.items(.main_token); | |
| 509 | 499 | var it: *Scope = start_scope; |
| 510 | 500 | while (true) switch (it.tag) { |
| 511 | 501 | .top => break, |
| 512 | 502 | .local => { |
| 513 | 503 | const local: *Local = @alignCast(@fieldParentPtr("base", it)); |
| 514 | const name_token = main_tokens[local.var_node] + 1; | |
| 504 | const name_token = ast.nodeMainToken(local.var_node) + 1; | |
| 515 | 505 | const ident_name = ast.tokenSlice(name_token); |
| 516 | 506 | if (std.mem.eql(u8, ident_name, name)) { |
| 517 | 507 | return local.var_node; |
| ... | ... | @@ -538,8 +528,6 @@ fn struct_decl( |
| 538 | 528 | container_decl: Ast.full.ContainerDecl, |
| 539 | 529 | ) Oom!void { |
| 540 | 530 | const ast = w.file.get_ast(); |
| 541 | const node_tags = ast.nodes.items(.tag); | |
| 542 | const node_datas = ast.nodes.items(.data); | |
| 543 | 531 | |
| 544 | 532 | const namespace = try gpa.create(Scope.Namespace); |
| 545 | 533 | namespace.* = .{ |
| ... | ... | @@ -549,7 +537,7 @@ fn struct_decl( |
| 549 | 537 | try w.file.get().scopes.putNoClobber(gpa, node, &namespace.base); |
| 550 | 538 | try w.scanDecls(namespace, container_decl.ast.members); |
| 551 | 539 | |
| 552 | for (container_decl.ast.members) |member| switch (node_tags[member]) { | |
| 540 | for (container_decl.ast.members) |member| switch (ast.nodeTag(member)) { | |
| 553 | 541 | .container_field_init, |
| 554 | 542 | .container_field_align, |
| 555 | 543 | .container_field, |
| ... | ... | @@ -569,7 +557,7 @@ fn struct_decl( |
| 569 | 557 | try w.file.get().doctests.put(gpa, member, doctest_node); |
| 570 | 558 | } |
| 571 | 559 | const decl_index = try w.file.add_decl(member, parent_decl); |
| 572 | const body = if (node_tags[member] == .fn_decl) node_datas[member].rhs else 0; | |
| 560 | const body = if (ast.nodeTag(member) == .fn_decl) ast.nodeData(member).node_and_node[1].toOptional() else .none; | |
| 573 | 561 | try w.fn_decl(&namespace.base, decl_index, body, full); |
| 574 | 562 | }, |
| 575 | 563 | |
| ... | ... | @@ -584,9 +572,9 @@ fn struct_decl( |
| 584 | 572 | |
| 585 | 573 | .@"comptime", |
| 586 | 574 | .@"usingnamespace", |
| 587 | => try w.expr(&namespace.base, parent_decl, node_datas[member].lhs), | |
| 575 | => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).node), | |
| 588 | 576 | |
| 589 | .test_decl => try w.expr(&namespace.base, parent_decl, node_datas[member].rhs), | |
| 577 | .test_decl => try w.expr(&namespace.base, parent_decl, ast.nodeData(member).opt_token_and_node[1]), | |
| 590 | 578 | |
| 591 | 579 | else => unreachable, |
| 592 | 580 | }; |
| ... | ... | @@ -633,13 +621,13 @@ fn fn_decl( |
| 633 | 621 | w: *Walk, |
| 634 | 622 | scope: *Scope, |
| 635 | 623 | parent_decl: Decl.Index, |
| 636 | body: Ast.Node.Index, | |
| 624 | body: Ast.Node.OptionalIndex, | |
| 637 | 625 | full: Ast.full.FnProto, |
| 638 | 626 | ) Oom!void { |
| 639 | 627 | for (full.ast.params) |param| { |
| 640 | 628 | try expr(w, scope, parent_decl, param); |
| 641 | 629 | } |
| 642 | try expr(w, scope, parent_decl, full.ast.return_type); | |
| 630 | try expr(w, scope, parent_decl, full.ast.return_type.unwrap().?); | |
| 643 | 631 | try maybe_expr(w, scope, parent_decl, full.ast.align_expr); |
| 644 | 632 | try maybe_expr(w, scope, parent_decl, full.ast.addrspace_expr); |
| 645 | 633 | try maybe_expr(w, scope, parent_decl, full.ast.section_expr); |
| ... | ... | @@ -647,17 +635,13 @@ fn fn_decl( |
| 647 | 635 | try maybe_expr(w, scope, parent_decl, body); |
| 648 | 636 | } |
| 649 | 637 | |
| 650 | fn maybe_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void { | |
| 651 | if (node != 0) return expr(w, scope, parent_decl, node); | |
| 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); | |
| 652 | 640 | } |
| 653 | 641 | |
| 654 | 642 | fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) Oom!void { |
| 655 | assert(node != 0); | |
| 656 | 643 | const ast = w.file.get_ast(); |
| 657 | const node_tags = ast.nodes.items(.tag); | |
| 658 | const node_datas = ast.nodes.items(.data); | |
| 659 | const main_tokens = ast.nodes.items(.main_token); | |
| 660 | switch (node_tags[node]) { | |
| 644 | switch (ast.nodeTag(node)) { | |
| 661 | 645 | .root => unreachable, // Top-level declaration. |
| 662 | 646 | .@"usingnamespace" => unreachable, // Top-level declaration. |
| 663 | 647 | .test_decl => unreachable, // Top-level declaration. |
| ... | ... | @@ -738,8 +722,9 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 738 | 722 | .array_access, |
| 739 | 723 | .switch_range, |
| 740 | 724 | => { |
| 741 | try expr(w, scope, parent_decl, node_datas[node].lhs); | |
| 742 | try expr(w, scope, parent_decl, node_datas[node].rhs); | |
| 725 | const lhs, const rhs = ast.nodeData(node).node_and_node; | |
| 726 | try expr(w, scope, parent_decl, lhs); | |
| 727 | try expr(w, scope, parent_decl, rhs); | |
| 743 | 728 | }, |
| 744 | 729 | |
| 745 | 730 | .assign_destructure => { |
| ... | ... | @@ -752,35 +737,33 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 752 | 737 | .bit_not, |
| 753 | 738 | .negation, |
| 754 | 739 | .negation_wrap, |
| 755 | .@"return", | |
| 756 | 740 | .deref, |
| 757 | 741 | .address_of, |
| 758 | 742 | .optional_type, |
| 759 | .unwrap_optional, | |
| 760 | .grouped_expression, | |
| 761 | 743 | .@"comptime", |
| 762 | 744 | .@"nosuspend", |
| 763 | 745 | .@"suspend", |
| 764 | 746 | .@"await", |
| 765 | 747 | .@"resume", |
| 766 | 748 | .@"try", |
| 767 | => try maybe_expr(w, scope, parent_decl, node_datas[node].lhs), | |
| 749 | => try expr(w, scope, parent_decl, ast.nodeData(node).node), | |
| 750 | .unwrap_optional, | |
| 751 | .grouped_expression, | |
| 752 | => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]), | |
| 753 | .@"return" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_node), | |
| 768 | 754 | |
| 769 | .anyframe_type, | |
| 770 | .@"break", | |
| 771 | => try maybe_expr(w, scope, parent_decl, node_datas[node].rhs), | |
| 755 | .anyframe_type => try expr(w, scope, parent_decl, ast.nodeData(node).token_and_node[1]), | |
| 756 | .@"break" => try maybe_expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_opt_node[1]), | |
| 772 | 757 | |
| 773 | 758 | .identifier => { |
| 774 | const ident_token = main_tokens[node]; | |
| 759 | const ident_token = ast.nodeMainToken(node); | |
| 775 | 760 | const ident_name = ast.tokenSlice(ident_token); |
| 776 | 761 | if (scope.lookup(ast, ident_name)) |var_node| { |
| 777 | 762 | try w.file.get().ident_decls.put(gpa, ident_token, var_node); |
| 778 | 763 | } |
| 779 | 764 | }, |
| 780 | 765 | .field_access => { |
| 781 | const object_node = node_datas[node].lhs; | |
| 782 | const dot_token = main_tokens[node]; | |
| 783 | const field_ident = dot_token + 1; | |
| 766 | const object_node, const field_ident = ast.nodeData(node).node_and_token; | |
| 784 | 767 | try w.file.get().token_parents.put(gpa, field_ident, node); |
| 785 | 768 | // This will populate the left-most field object if it is an |
| 786 | 769 | // identifier, allowing rendering code to piece together the link. |
| ... | ... | @@ -857,9 +840,10 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 857 | 840 | .for_simple, .@"for" => { |
| 858 | 841 | const full = ast.fullFor(node).?; |
| 859 | 842 | for (full.ast.inputs) |input| { |
| 860 | if (node_tags[input] == .for_range) { | |
| 861 | try expr(w, scope, parent_decl, node_datas[input].lhs); | |
| 862 | try maybe_expr(w, scope, parent_decl, node_datas[input].rhs); | |
| 843 | if (ast.nodeTag(input) == .for_range) { | |
| 844 | const start, const end = ast.nodeData(input).node_and_opt_node; | |
| 845 | try expr(w, scope, parent_decl, start); | |
| 846 | try maybe_expr(w, scope, parent_decl, end); | |
| 863 | 847 | } else { |
| 864 | 848 | try expr(w, scope, parent_decl, input); |
| 865 | 849 | } |
| ... | ... | @@ -914,17 +898,16 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 914 | 898 | }, |
| 915 | 899 | |
| 916 | 900 | .array_type_sentinel => { |
| 917 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 918 | try expr(w, scope, parent_decl, node_datas[node].lhs); | |
| 901 | const len_expr, const extra_index = ast.nodeData(node).node_and_extra; | |
| 902 | const extra = ast.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 903 | try expr(w, scope, parent_decl, len_expr); | |
| 919 | 904 | try expr(w, scope, parent_decl, extra.elem_type); |
| 920 | 905 | try expr(w, scope, parent_decl, extra.sentinel); |
| 921 | 906 | }, |
| 922 | 907 | .@"switch", .switch_comma => { |
| 923 | const operand_node = node_datas[node].lhs; | |
| 924 | try expr(w, scope, parent_decl, operand_node); | |
| 925 | const extra = ast.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 926 | const case_nodes = ast.extra_data[extra.start..extra.end]; | |
| 927 | for (case_nodes) |case_node| { | |
| 908 | const full = ast.fullSwitch(node).?; | |
| 909 | try expr(w, scope, parent_decl, full.ast.condition); | |
| 910 | for (full.ast.cases) |case_node| { | |
| 928 | 911 | const case = ast.fullSwitchCase(case_node).?; |
| 929 | 912 | for (case.ast.values) |value_node| { |
| 930 | 913 | try expr(w, scope, parent_decl, value_node); |
| ... | ... | @@ -973,7 +956,7 @@ fn expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, node: Ast.Node.Index) |
| 973 | 956 | .fn_proto, |
| 974 | 957 | => { |
| 975 | 958 | var buf: [1]Ast.Node.Index = undefined; |
| 976 | return fn_decl(w, scope, parent_decl, 0, ast.fullFnProto(&buf, node).?); | |
| 959 | return fn_decl(w, scope, parent_decl, .none, ast.fullFnProto(&buf, node).?); | |
| 977 | 960 | }, |
| 978 | 961 | } |
| 979 | 962 | } |
| ... | ... | @@ -993,8 +976,7 @@ fn builtin_call( |
| 993 | 976 | params: []const Ast.Node.Index, |
| 994 | 977 | ) Oom!void { |
| 995 | 978 | const ast = w.file.get_ast(); |
| 996 | const main_tokens = ast.nodes.items(.main_token); | |
| 997 | const builtin_token = main_tokens[node]; | |
| 979 | const builtin_token = ast.nodeMainToken(node); | |
| 998 | 980 | const builtin_name = ast.tokenSlice(builtin_token); |
| 999 | 981 | if (std.mem.eql(u8, builtin_name, "@This")) { |
| 1000 | 982 | try w.file.get().node_decls.put(gpa, node, scope.getNamespaceDecl()); |
| ... | ... | @@ -1012,13 +994,11 @@ fn block( |
| 1012 | 994 | statements: []const Ast.Node.Index, |
| 1013 | 995 | ) Oom!void { |
| 1014 | 996 | const ast = w.file.get_ast(); |
| 1015 | const node_tags = ast.nodes.items(.tag); | |
| 1016 | const node_datas = ast.nodes.items(.data); | |
| 1017 | 997 | |
| 1018 | 998 | var scope = parent_scope; |
| 1019 | 999 | |
| 1020 | 1000 | for (statements) |node| { |
| 1021 | switch (node_tags[node]) { | |
| 1001 | switch (ast.nodeTag(node)) { | |
| 1022 | 1002 | .global_var_decl, |
| 1023 | 1003 | .local_var_decl, |
| 1024 | 1004 | .simple_var_decl, |
| ... | ... | @@ -1039,11 +1019,10 @@ fn block( |
| 1039 | 1019 | log.debug("walk assign_destructure not implemented yet", .{}); |
| 1040 | 1020 | }, |
| 1041 | 1021 | |
| 1042 | .grouped_expression => try expr(w, scope, parent_decl, node_datas[node].lhs), | |
| 1022 | .grouped_expression => try expr(w, scope, parent_decl, ast.nodeData(node).node_and_token[0]), | |
| 1043 | 1023 | |
| 1044 | .@"defer", | |
| 1045 | .@"errdefer", | |
| 1046 | => try expr(w, scope, parent_decl, node_datas[node].rhs), | |
| 1024 | .@"defer" => try expr(w, scope, parent_decl, ast.nodeData(node).node), | |
| 1025 | .@"errdefer" => try expr(w, scope, parent_decl, ast.nodeData(node).opt_token_and_node[1]), | |
| 1047 | 1026 | |
| 1048 | 1027 | else => try expr(w, scope, parent_decl, node), |
| 1049 | 1028 | } |
| ... | ... | @@ -1059,18 +1038,14 @@ fn while_expr(w: *Walk, scope: *Scope, parent_decl: Decl.Index, full: Ast.full.W |
| 1059 | 1038 | |
| 1060 | 1039 | fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.Index) Oom!void { |
| 1061 | 1040 | const ast = w.file.get_ast(); |
| 1062 | const node_tags = ast.nodes.items(.tag); | |
| 1063 | const main_tokens = ast.nodes.items(.main_token); | |
| 1064 | const token_tags = ast.tokens.items(.tag); | |
| 1065 | const node_datas = ast.nodes.items(.data); | |
| 1066 | 1041 | |
| 1067 | 1042 | for (members) |member_node| { |
| 1068 | const name_token = switch (node_tags[member_node]) { | |
| 1043 | const name_token = switch (ast.nodeTag(member_node)) { | |
| 1069 | 1044 | .global_var_decl, |
| 1070 | 1045 | .local_var_decl, |
| 1071 | 1046 | .simple_var_decl, |
| 1072 | 1047 | .aligned_var_decl, |
| 1073 | => main_tokens[member_node] + 1, | |
| 1048 | => ast.nodeMainToken(member_node) + 1, | |
| 1074 | 1049 | |
| 1075 | 1050 | .fn_proto_simple, |
| 1076 | 1051 | .fn_proto_multi, |
| ... | ... | @@ -1078,17 +1053,19 @@ fn scanDecls(w: *Walk, namespace: *Scope.Namespace, members: []const Ast.Node.In |
| 1078 | 1053 | .fn_proto, |
| 1079 | 1054 | .fn_decl, |
| 1080 | 1055 | => blk: { |
| 1081 | const ident = main_tokens[member_node] + 1; | |
| 1082 | if (token_tags[ident] != .identifier) continue; | |
| 1056 | const ident = ast.nodeMainToken(member_node) + 1; | |
| 1057 | if (ast.tokenTag(ident) != .identifier) continue; | |
| 1083 | 1058 | break :blk ident; |
| 1084 | 1059 | }, |
| 1085 | 1060 | |
| 1086 | 1061 | .test_decl => { |
| 1087 | const ident_token = node_datas[member_node].lhs; | |
| 1088 | const is_doctest = token_tags[ident_token] == .identifier; | |
| 1089 | if (is_doctest) { | |
| 1090 | const token_bytes = ast.tokenSlice(ident_token); | |
| 1091 | try namespace.doctests.put(gpa, token_bytes, member_node); | |
| 1062 | const opt_ident_token = ast.nodeData(member_node).opt_token_and_node[0]; | |
| 1063 | if (opt_ident_token.unwrap()) |ident_token| { | |
| 1064 | const is_doctest = ast.tokenTag(ident_token) == .identifier; | |
| 1065 | if (is_doctest) { | |
| 1066 | const token_bytes = ast.tokenSlice(ident_token); | |
| 1067 | try namespace.doctests.put(gpa, token_bytes, member_node); | |
| 1068 | } | |
| 1092 | 1069 | } |
| 1093 | 1070 | continue; |
| 1094 | 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+965-844| ... | ... | @@ -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,14 +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_tags = tree.tokens.items(.tag); | |
| 804 | 889 | var n = node; |
| 805 | var end_offset: TokenIndex = 0; | |
| 806 | while (true) switch (tags[n]) { | |
| 807 | .root => return @as(TokenIndex, @intCast(tree.tokens.len - 1)), | |
| 890 | var end_offset: u32 = 0; | |
| 891 | while (true) switch (tree.nodeTag(n)) { | |
| 892 | .root => return @intCast(tree.tokens.len - 1), | |
| 808 | 893 | |
| 809 | 894 | .@"usingnamespace", |
| 810 | 895 | .bool_not, |
| ... | ... | @@ -819,11 +904,8 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 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,44 +954,53 @@ 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, | |
| 883 | .fn_proto_one, | |
| 884 | .fn_proto, | |
| 885 | 961 | .fn_decl, |
| 962 | .array_type, | |
| 963 | .switch_range, | |
| 964 | => n = tree.nodeData(n).node_and_node[1], | |
| 965 | ||
| 966 | .test_decl, .@"errdefer" => n = tree.nodeData(n).opt_token_and_node[1], | |
| 967 | .@"defer" => n = tree.nodeData(n).node, | |
| 968 | .anyframe_type => n = tree.nodeData(n).token_and_node[1], | |
| 969 | ||
| 970 | .switch_case_one, | |
| 971 | .switch_case_inline_one, | |
| 886 | 972 | .ptr_type_aligned, |
| 887 | 973 | .ptr_type_sentinel, |
| 974 | => n = tree.nodeData(n).opt_node_and_node[1], | |
| 975 | ||
| 976 | .assign_destructure, | |
| 888 | 977 | .ptr_type, |
| 889 | 978 | .ptr_type_bit_range, |
| 890 | .array_type, | |
| 891 | .switch_case_one, | |
| 892 | .switch_case_inline_one, | |
| 893 | 979 | .switch_case, |
| 894 | 980 | .switch_case_inline, |
| 895 | .switch_range, | |
| 896 | => n = datas[n].rhs, | |
| 981 | => n = tree.nodeData(n).extra_and_node[1], | |
| 897 | 982 | |
| 898 | .for_range => if (datas[n].rhs != 0) { | |
| 899 | n = datas[n].rhs; | |
| 900 | } else { | |
| 901 | return main_tokens[n] + end_offset; | |
| 983 | .fn_proto_simple => n = tree.nodeData(n).opt_node_and_opt_node[1].unwrap().?, | |
| 984 | .fn_proto_multi, | |
| 985 | .fn_proto_one, | |
| 986 | .fn_proto, | |
| 987 | => n = tree.nodeData(n).extra_and_opt_node[1].unwrap().?, | |
| 988 | ||
| 989 | .for_range => { | |
| 990 | n = tree.nodeData(n).node_and_opt_node[1].unwrap() orelse { | |
| 991 | return tree.nodeMainToken(n) + end_offset; | |
| 992 | }; | |
| 902 | 993 | }, |
| 903 | 994 | |
| 904 | 995 | .field_access, |
| 905 | 996 | .unwrap_optional, |
| 906 | .grouped_expression, | |
| 907 | .multiline_string_literal, | |
| 908 | .error_set_decl, | |
| 909 | 997 | .asm_simple, |
| 910 | .asm_output, | |
| 911 | .asm_input, | |
| 912 | .error_value, | |
| 913 | => return datas[n].rhs + end_offset, | |
| 998 | => return tree.nodeData(n).node_and_token[1] + end_offset, | |
| 999 | .error_set_decl => return tree.nodeData(n).token + end_offset, | |
| 1000 | .grouped_expression, .asm_input => return tree.nodeData(n).node_and_token[1] + end_offset, | |
| 1001 | .multiline_string_literal => return tree.nodeData(n).token_and_token[1] + end_offset, | |
| 1002 | .asm_output => return tree.nodeData(n).opt_node_and_token[1] + end_offset, | |
| 1003 | .error_value => return tree.nodeData(n).opt_token_and_opt_token[1].unwrap().? + end_offset, | |
| 914 | 1004 | |
| 915 | 1005 | .anyframe_literal, |
| 916 | 1006 | .char_literal, |
| ... | ... | @@ -920,80 +1010,88 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 920 | 1010 | .deref, |
| 921 | 1011 | .enum_literal, |
| 922 | 1012 | .string_literal, |
| 923 | => return main_tokens[n] + end_offset, | |
| 1013 | => return tree.nodeMainToken(n) + end_offset, | |
| 924 | 1014 | |
| 925 | .@"return" => if (datas[n].lhs != 0) { | |
| 926 | n = datas[n].lhs; | |
| 927 | } else { | |
| 928 | return main_tokens[n] + end_offset; | |
| 1015 | .@"return" => { | |
| 1016 | n = tree.nodeData(n).opt_node.unwrap() orelse { | |
| 1017 | return tree.nodeMainToken(n) + end_offset; | |
| 1018 | }; | |
| 929 | 1019 | }, |
| 930 | 1020 | |
| 931 | 1021 | .call, .async_call => { |
| 1022 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1023 | const params = tree.extraData(extra_index, Node.SubRange); | |
| 1024 | assert(params.start != params.end); | |
| 932 | 1025 | end_offset += 1; // for the rparen |
| 933 | const params = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 934 | assert(params.end - params.start > 0); | |
| 935 | n = tree.extra_data[params.end - 1]; // last parameter | |
| 1026 | n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter | |
| 936 | 1027 | }, |
| 937 | 1028 | .tagged_union_enum_tag => { |
| 938 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 939 | if (members.end - members.start == 0) { | |
| 1029 | const arg, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1030 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1031 | if (members.start == members.end) { | |
| 940 | 1032 | end_offset += 4; // for the rparen + rparen + lbrace + rbrace |
| 941 | n = datas[n].lhs; | |
| 1033 | n = arg; | |
| 942 | 1034 | } else { |
| 943 | 1035 | end_offset += 1; // for the rbrace |
| 944 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1036 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 945 | 1037 | } |
| 946 | 1038 | }, |
| 947 | 1039 | .call_comma, |
| 948 | 1040 | .async_call_comma, |
| 949 | 1041 | .tagged_union_enum_tag_trailing, |
| 950 | 1042 | => { |
| 1043 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1044 | const params = tree.extraData(extra_index, Node.SubRange); | |
| 1045 | assert(params.start != params.end); | |
| 951 | 1046 | end_offset += 2; // for the comma/semicolon + rparen/rbrace |
| 952 | const params = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 953 | assert(params.end > params.start); | |
| 954 | n = tree.extra_data[params.end - 1]; // last parameter | |
| 1047 | n = @enumFromInt(tree.extra_data[@intFromEnum(params.end) - 1]); // last parameter | |
| 955 | 1048 | }, |
| 956 | 1049 | .@"switch" => { |
| 957 | const cases = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 958 | if (cases.end - cases.start == 0) { | |
| 1050 | const condition, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1051 | const cases = tree.extraData(extra_index, Node.SubRange); | |
| 1052 | if (cases.start == cases.end) { | |
| 959 | 1053 | end_offset += 3; // rparen, lbrace, rbrace |
| 960 | n = datas[n].lhs; // condition expression | |
| 1054 | n = condition; | |
| 961 | 1055 | } else { |
| 962 | 1056 | end_offset += 1; // for the rbrace |
| 963 | n = tree.extra_data[cases.end - 1]; // last case | |
| 1057 | n = @enumFromInt(tree.extra_data[@intFromEnum(cases.end) - 1]); // last case | |
| 964 | 1058 | } |
| 965 | 1059 | }, |
| 966 | 1060 | .container_decl_arg => { |
| 967 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 968 | if (members.end - members.start == 0) { | |
| 1061 | const arg, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1062 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1063 | if (members.end == members.start) { | |
| 969 | 1064 | end_offset += 3; // for the rparen + lbrace + rbrace |
| 970 | n = datas[n].lhs; | |
| 1065 | n = arg; | |
| 971 | 1066 | } else { |
| 972 | 1067 | end_offset += 1; // for the rbrace |
| 973 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1068 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 974 | 1069 | } |
| 975 | 1070 | }, |
| 976 | 1071 | .@"asm" => { |
| 977 | const extra = tree.extraData(datas[n].rhs, Node.Asm); | |
| 1072 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1073 | const extra = tree.extraData(extra_index, Node.Asm); | |
| 978 | 1074 | return extra.rparen + end_offset; |
| 979 | 1075 | }, |
| 980 | 1076 | .array_init, |
| 981 | 1077 | .struct_init, |
| 982 | 1078 | => { |
| 983 | const elements = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 984 | assert(elements.end - elements.start > 0); | |
| 1079 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1080 | const elements = tree.extraData(extra_index, Node.SubRange); | |
| 1081 | assert(elements.start != elements.end); | |
| 985 | 1082 | end_offset += 1; // for the rbrace |
| 986 | n = tree.extra_data[elements.end - 1]; // last element | |
| 1083 | n = @enumFromInt(tree.extra_data[@intFromEnum(elements.end) - 1]); // last element | |
| 987 | 1084 | }, |
| 988 | 1085 | .array_init_comma, |
| 989 | 1086 | .struct_init_comma, |
| 990 | 1087 | .container_decl_arg_trailing, |
| 991 | 1088 | .switch_comma, |
| 992 | 1089 | => { |
| 993 | const members = tree.extraData(datas[n].rhs, Node.SubRange); | |
| 994 | assert(members.end - members.start > 0); | |
| 1090 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1091 | const members = tree.extraData(extra_index, Node.SubRange); | |
| 1092 | assert(members.start != members.end); | |
| 995 | 1093 | end_offset += 2; // for the comma + rbrace |
| 996 | n = tree.extra_data[members.end - 1]; // last parameter | |
| 1094 | n = @enumFromInt(tree.extra_data[@intFromEnum(members.end) - 1]); // last parameter | |
| 997 | 1095 | }, |
| 998 | 1096 | .array_init_dot, |
| 999 | 1097 | .struct_init_dot, |
| ... | ... | @@ -1002,9 +1100,10 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1002 | 1100 | .tagged_union, |
| 1003 | 1101 | .builtin_call, |
| 1004 | 1102 | => { |
| 1005 | assert(datas[n].rhs - datas[n].lhs > 0); | |
| 1103 | const range = tree.nodeData(n).extra_range; | |
| 1104 | assert(range.start != range.end); | |
| 1006 | 1105 | end_offset += 1; // for the rbrace |
| 1007 | n = tree.extra_data[datas[n].rhs - 1]; // last statement | |
| 1106 | n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last statement | |
| 1008 | 1107 | }, |
| 1009 | 1108 | .array_init_dot_comma, |
| 1010 | 1109 | .struct_init_dot_comma, |
| ... | ... | @@ -1013,20 +1112,21 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1013 | 1112 | .tagged_union_trailing, |
| 1014 | 1113 | .builtin_call_comma, |
| 1015 | 1114 | => { |
| 1016 | assert(datas[n].rhs - datas[n].lhs > 0); | |
| 1115 | const range = tree.nodeData(n).extra_range; | |
| 1116 | assert(range.start != range.end); | |
| 1017 | 1117 | end_offset += 2; // for the comma/semicolon + rbrace/rparen |
| 1018 | n = tree.extra_data[datas[n].rhs - 1]; // last member | |
| 1118 | n = @enumFromInt(tree.extra_data[@intFromEnum(range.end) - 1]); // last member | |
| 1019 | 1119 | }, |
| 1020 | 1120 | .call_one, |
| 1021 | 1121 | .async_call_one, |
| 1022 | .array_access, | |
| 1023 | 1122 | => { |
| 1024 | end_offset += 1; // for the rparen/rbracket | |
| 1025 | if (datas[n].rhs == 0) { | |
| 1026 | return main_tokens[n] + end_offset; | |
| 1027 | } | |
| 1028 | n = datas[n].rhs; | |
| 1123 | _, const first_param = tree.nodeData(n).node_and_opt_node; | |
| 1124 | end_offset += 1; // for the rparen | |
| 1125 | n = first_param.unwrap() orelse { | |
| 1126 | return tree.nodeMainToken(n) + end_offset; | |
| 1127 | }; | |
| 1029 | 1128 | }, |
| 1129 | ||
| 1030 | 1130 | .array_init_dot_two, |
| 1031 | 1131 | .block_two, |
| 1032 | 1132 | .builtin_call_two, |
| ... | ... | @@ -1034,14 +1134,15 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1034 | 1134 | .container_decl_two, |
| 1035 | 1135 | .tagged_union_two, |
| 1036 | 1136 | => { |
| 1037 | if (datas[n].rhs != 0) { | |
| 1137 | const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; | |
| 1138 | if (opt_rhs.unwrap()) |rhs| { | |
| 1038 | 1139 | end_offset += 1; // for the rparen/rbrace |
| 1039 | n = datas[n].rhs; | |
| 1040 | } else if (datas[n].lhs != 0) { | |
| 1140 | n = rhs; | |
| 1141 | } else if (opt_lhs.unwrap()) |lhs| { | |
| 1041 | 1142 | end_offset += 1; // for the rparen/rbrace |
| 1042 | n = datas[n].lhs; | |
| 1143 | n = lhs; | |
| 1043 | 1144 | } else { |
| 1044 | switch (tags[n]) { | |
| 1145 | switch (tree.nodeTag(n)) { | |
| 1045 | 1146 | .array_init_dot_two, |
| 1046 | 1147 | .block_two, |
| 1047 | 1148 | .struct_init_dot_two, |
| ... | ... | @@ -1049,17 +1150,17 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1049 | 1150 | .builtin_call_two => end_offset += 2, // lparen/lbrace + rparen/rbrace |
| 1050 | 1151 | .container_decl_two => { |
| 1051 | 1152 | var i: u32 = 2; // lbrace + rbrace |
| 1052 | while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1; | |
| 1153 | while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; | |
| 1053 | 1154 | end_offset += i; |
| 1054 | 1155 | }, |
| 1055 | 1156 | .tagged_union_two => { |
| 1056 | 1157 | var i: u32 = 5; // (enum) {} |
| 1057 | while (token_tags[main_tokens[n] + i] == .container_doc_comment) i += 1; | |
| 1158 | while (tree.tokenTag(tree.nodeMainToken(n) + i) == .container_doc_comment) i += 1; | |
| 1058 | 1159 | end_offset += i; |
| 1059 | 1160 | }, |
| 1060 | 1161 | else => unreachable, |
| 1061 | 1162 | } |
| 1062 | return main_tokens[n] + end_offset; | |
| 1163 | return tree.nodeMainToken(n) + end_offset; | |
| 1063 | 1164 | } |
| 1064 | 1165 | }, |
| 1065 | 1166 | .array_init_dot_two_comma, |
| ... | ... | @@ -1069,341 +1170,345 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 1069 | 1170 | .container_decl_two_trailing, |
| 1070 | 1171 | .tagged_union_two_trailing, |
| 1071 | 1172 | => { |
| 1173 | const opt_lhs, const opt_rhs = tree.nodeData(n).opt_node_and_opt_node; | |
| 1072 | 1174 | end_offset += 2; // for the comma/semicolon + rbrace/rparen |
| 1073 | if (datas[n].rhs != 0) { | |
| 1074 | n = datas[n].rhs; | |
| 1075 | } else if (datas[n].lhs != 0) { | |
| 1076 | n = datas[n].lhs; | |
| 1175 | if (opt_rhs.unwrap()) |rhs| { | |
| 1176 | n = rhs; | |
| 1177 | } else if (opt_lhs.unwrap()) |lhs| { | |
| 1178 | n = lhs; | |
| 1077 | 1179 | } else { |
| 1078 | 1180 | unreachable; |
| 1079 | 1181 | } |
| 1080 | 1182 | }, |
| 1081 | 1183 | .simple_var_decl => { |
| 1082 | if (datas[n].rhs != 0) { | |
| 1083 | n = datas[n].rhs; | |
| 1084 | } else if (datas[n].lhs != 0) { | |
| 1085 | n = datas[n].lhs; | |
| 1184 | const type_node, const init_node = tree.nodeData(n).opt_node_and_opt_node; | |
| 1185 | if (init_node.unwrap()) |rhs| { | |
| 1186 | n = rhs; | |
| 1187 | } else if (type_node.unwrap()) |lhs| { | |
| 1188 | n = lhs; | |
| 1086 | 1189 | } else { |
| 1087 | 1190 | end_offset += 1; // from mut token to name |
| 1088 | return main_tokens[n] + end_offset; | |
| 1191 | return tree.nodeMainToken(n) + end_offset; | |
| 1089 | 1192 | } |
| 1090 | 1193 | }, |
| 1091 | 1194 | .aligned_var_decl => { |
| 1092 | if (datas[n].rhs != 0) { | |
| 1093 | n = datas[n].rhs; | |
| 1094 | } else if (datas[n].lhs != 0) { | |
| 1095 | end_offset += 1; // for the rparen | |
| 1096 | n = datas[n].lhs; | |
| 1195 | const align_node, const init_node = tree.nodeData(n).node_and_opt_node; | |
| 1196 | if (init_node.unwrap()) |rhs| { | |
| 1197 | n = rhs; | |
| 1097 | 1198 | } else { |
| 1098 | end_offset += 1; // from mut token to name | |
| 1099 | return main_tokens[n] + end_offset; | |
| 1199 | end_offset += 1; // for the rparen | |
| 1200 | n = align_node; | |
| 1100 | 1201 | } |
| 1101 | 1202 | }, |
| 1102 | 1203 | .global_var_decl => { |
| 1103 | if (datas[n].rhs != 0) { | |
| 1104 | n = datas[n].rhs; | |
| 1204 | const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; | |
| 1205 | if (init_node.unwrap()) |rhs| { | |
| 1206 | n = rhs; | |
| 1105 | 1207 | } else { |
| 1106 | const extra = tree.extraData(datas[n].lhs, Node.GlobalVarDecl); | |
| 1107 | if (extra.section_node != 0) { | |
| 1208 | const extra = tree.extraData(extra_index, Node.GlobalVarDecl); | |
| 1209 | if (extra.section_node.unwrap()) |section_node| { | |
| 1108 | 1210 | end_offset += 1; // for the rparen |
| 1109 | n = extra.section_node; | |
| 1110 | } else if (extra.align_node != 0) { | |
| 1211 | n = section_node; | |
| 1212 | } else if (extra.align_node.unwrap()) |align_node| { | |
| 1111 | 1213 | end_offset += 1; // for the rparen |
| 1112 | n = extra.align_node; | |
| 1113 | } else if (extra.type_node != 0) { | |
| 1114 | n = extra.type_node; | |
| 1214 | n = align_node; | |
| 1215 | } else if (extra.type_node.unwrap()) |type_node| { | |
| 1216 | n = type_node; | |
| 1115 | 1217 | } else { |
| 1116 | 1218 | end_offset += 1; // from mut token to name |
| 1117 | return main_tokens[n] + end_offset; | |
| 1219 | return tree.nodeMainToken(n) + end_offset; | |
| 1118 | 1220 | } |
| 1119 | 1221 | } |
| 1120 | 1222 | }, |
| 1121 | 1223 | .local_var_decl => { |
| 1122 | if (datas[n].rhs != 0) { | |
| 1123 | n = datas[n].rhs; | |
| 1224 | const extra_index, const init_node = tree.nodeData(n).extra_and_opt_node; | |
| 1225 | if (init_node.unwrap()) |rhs| { | |
| 1226 | n = rhs; | |
| 1124 | 1227 | } else { |
| 1125 | const extra = tree.extraData(datas[n].lhs, Node.LocalVarDecl); | |
| 1126 | assert(extra.align_node != 0); | |
| 1228 | const extra = tree.extraData(extra_index, Node.LocalVarDecl); | |
| 1127 | 1229 | end_offset += 1; // for the rparen |
| 1128 | 1230 | n = extra.align_node; |
| 1129 | 1231 | } |
| 1130 | 1232 | }, |
| 1131 | 1233 | .container_field_init => { |
| 1132 | if (datas[n].rhs != 0) { | |
| 1133 | n = datas[n].rhs; | |
| 1134 | } else { | |
| 1135 | assert(datas[n].lhs != 0); | |
| 1136 | n = datas[n].lhs; | |
| 1137 | } | |
| 1234 | const type_expr, const value_expr = tree.nodeData(n).node_and_opt_node; | |
| 1235 | n = value_expr.unwrap() orelse type_expr; | |
| 1138 | 1236 | }, |
| 1139 | .container_field_align => { | |
| 1140 | assert(datas[n].rhs != 0); | |
| 1141 | end_offset += 1; // for the rparen | |
| 1142 | n = datas[n].rhs; | |
| 1237 | ||
| 1238 | .array_access, | |
| 1239 | .array_init_one, | |
| 1240 | .container_field_align, | |
| 1241 | => { | |
| 1242 | _, const rhs = tree.nodeData(n).node_and_node; | |
| 1243 | end_offset += 1; // for the rbracket/rbrace/rparen | |
| 1244 | n = rhs; | |
| 1143 | 1245 | }, |
| 1144 | 1246 | .container_field => { |
| 1145 | const extra = tree.extraData(datas[n].rhs, Node.ContainerField); | |
| 1146 | assert(extra.value_expr != 0); | |
| 1247 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1248 | const extra = tree.extraData(extra_index, Node.ContainerField); | |
| 1147 | 1249 | n = extra.value_expr; |
| 1148 | 1250 | }, |
| 1149 | 1251 | |
| 1150 | .array_init_one, | |
| 1151 | .struct_init_one, | |
| 1152 | => { | |
| 1252 | .struct_init_one => { | |
| 1253 | _, const first_field = tree.nodeData(n).node_and_opt_node; | |
| 1153 | 1254 | end_offset += 1; // rbrace |
| 1154 | if (datas[n].rhs == 0) { | |
| 1155 | return main_tokens[n] + end_offset; | |
| 1156 | } else { | |
| 1157 | n = datas[n].rhs; | |
| 1158 | } | |
| 1255 | n = first_field.unwrap() orelse { | |
| 1256 | return tree.nodeMainToken(n) + end_offset; | |
| 1257 | }; | |
| 1258 | }, | |
| 1259 | .slice_open => { | |
| 1260 | _, const start_node = tree.nodeData(n).node_and_node; | |
| 1261 | end_offset += 2; // ellipsis2 + rbracket, or comma + rparen | |
| 1262 | n = start_node; | |
| 1263 | }, | |
| 1264 | .array_init_one_comma => { | |
| 1265 | _, const first_element = tree.nodeData(n).node_and_node; | |
| 1266 | end_offset += 2; // comma + rbrace | |
| 1267 | n = first_element; | |
| 1159 | 1268 | }, |
| 1160 | .slice_open, | |
| 1161 | 1269 | .call_one_comma, |
| 1162 | 1270 | .async_call_one_comma, |
| 1163 | .array_init_one_comma, | |
| 1164 | 1271 | .struct_init_one_comma, |
| 1165 | 1272 | => { |
| 1273 | _, const first_field = tree.nodeData(n).node_and_opt_node; | |
| 1166 | 1274 | end_offset += 2; // ellipsis2 + rbracket, or comma + rparen |
| 1167 | n = datas[n].rhs; | |
| 1168 | assert(n != 0); | |
| 1275 | n = first_field.unwrap().?; | |
| 1169 | 1276 | }, |
| 1170 | 1277 | .slice => { |
| 1171 | const extra = tree.extraData(datas[n].rhs, Node.Slice); | |
| 1172 | assert(extra.end != 0); // should have used slice_open | |
| 1278 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1279 | const extra = tree.extraData(extra_index, Node.Slice); | |
| 1173 | 1280 | end_offset += 1; // rbracket |
| 1174 | 1281 | n = extra.end; |
| 1175 | 1282 | }, |
| 1176 | 1283 | .slice_sentinel => { |
| 1177 | const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel); | |
| 1178 | assert(extra.sentinel != 0); // should have used slice | |
| 1284 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1285 | const extra = tree.extraData(extra_index, Node.SliceSentinel); | |
| 1179 | 1286 | end_offset += 1; // rbracket |
| 1180 | 1287 | n = extra.sentinel; |
| 1181 | 1288 | }, |
| 1182 | 1289 | |
| 1183 | 1290 | .@"continue", .@"break" => { |
| 1184 | if (datas[n].rhs != 0) { | |
| 1185 | n = datas[n].rhs; | |
| 1186 | } else if (datas[n].lhs != 0) { | |
| 1187 | return datas[n].lhs + end_offset; | |
| 1291 | const opt_label, const opt_rhs = tree.nodeData(n).opt_token_and_opt_node; | |
| 1292 | if (opt_rhs.unwrap()) |rhs| { | |
| 1293 | n = rhs; | |
| 1294 | } else if (opt_label.unwrap()) |lhs| { | |
| 1295 | return lhs + end_offset; | |
| 1188 | 1296 | } else { |
| 1189 | return main_tokens[n] + end_offset; | |
| 1297 | return tree.nodeMainToken(n) + end_offset; | |
| 1190 | 1298 | } |
| 1191 | 1299 | }, |
| 1192 | 1300 | .while_cont => { |
| 1193 | const extra = tree.extraData(datas[n].rhs, Node.WhileCont); | |
| 1194 | assert(extra.then_expr != 0); | |
| 1301 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1302 | const extra = tree.extraData(extra_index, Node.WhileCont); | |
| 1195 | 1303 | n = extra.then_expr; |
| 1196 | 1304 | }, |
| 1197 | 1305 | .@"while" => { |
| 1198 | const extra = tree.extraData(datas[n].rhs, Node.While); | |
| 1199 | assert(extra.else_expr != 0); | |
| 1306 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1307 | const extra = tree.extraData(extra_index, Node.While); | |
| 1200 | 1308 | n = extra.else_expr; |
| 1201 | 1309 | }, |
| 1202 | 1310 | .@"if" => { |
| 1203 | const extra = tree.extraData(datas[n].rhs, Node.If); | |
| 1204 | assert(extra.else_expr != 0); | |
| 1311 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1312 | const extra = tree.extraData(extra_index, Node.If); | |
| 1205 | 1313 | n = extra.else_expr; |
| 1206 | 1314 | }, |
| 1207 | 1315 | .@"for" => { |
| 1208 | const extra = @as(Node.For, @bitCast(datas[n].rhs)); | |
| 1209 | n = tree.extra_data[datas[n].lhs + extra.inputs + @intFromBool(extra.has_else)]; | |
| 1316 | const extra_index, const extra = tree.nodeData(n).@"for"; | |
| 1317 | const index = @intFromEnum(extra_index) + extra.inputs + @intFromBool(extra.has_else); | |
| 1318 | n = @enumFromInt(tree.extra_data[index]); | |
| 1210 | 1319 | }, |
| 1211 | 1320 | .array_type_sentinel => { |
| 1212 | const extra = tree.extraData(datas[n].rhs, Node.ArrayTypeSentinel); | |
| 1321 | _, const extra_index = tree.nodeData(n).node_and_extra; | |
| 1322 | const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel); | |
| 1213 | 1323 | n = extra.elem_type; |
| 1214 | 1324 | }, |
| 1215 | 1325 | }; |
| 1216 | 1326 | } |
| 1217 | 1327 | |
| 1218 | 1328 | pub fn tokensOnSameLine(tree: Ast, token1: TokenIndex, token2: TokenIndex) bool { |
| 1219 | const token_starts = tree.tokens.items(.start); | |
| 1220 | const source = tree.source[token_starts[token1]..token_starts[token2]]; | |
| 1329 | const source = tree.source[tree.tokenStart(token1)..tree.tokenStart(token2)]; | |
| 1221 | 1330 | return mem.indexOfScalar(u8, source, '\n') == null; |
| 1222 | 1331 | } |
| 1223 | 1332 | |
| 1224 | 1333 | pub fn getNodeSource(tree: Ast, node: Node.Index) []const u8 { |
| 1225 | const token_starts = tree.tokens.items(.start); | |
| 1226 | 1334 | const first_token = tree.firstToken(node); |
| 1227 | 1335 | const last_token = tree.lastToken(node); |
| 1228 | const start = token_starts[first_token]; | |
| 1229 | const end = token_starts[last_token] + tree.tokenSlice(last_token).len; | |
| 1336 | const start = tree.tokenStart(first_token); | |
| 1337 | const end = tree.tokenStart(last_token) + tree.tokenSlice(last_token).len; | |
| 1230 | 1338 | return tree.source[start..end]; |
| 1231 | 1339 | } |
| 1232 | 1340 | |
| 1233 | 1341 | pub fn globalVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1234 | assert(tree.nodes.items(.tag)[node] == .global_var_decl); | |
| 1235 | const data = tree.nodes.items(.data)[node]; | |
| 1236 | const extra = tree.extraData(data.lhs, Node.GlobalVarDecl); | |
| 1342 | assert(tree.nodeTag(node) == .global_var_decl); | |
| 1343 | const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node; | |
| 1344 | const extra = tree.extraData(extra_index, Node.GlobalVarDecl); | |
| 1237 | 1345 | return tree.fullVarDeclComponents(.{ |
| 1238 | 1346 | .type_node = extra.type_node, |
| 1239 | 1347 | .align_node = extra.align_node, |
| 1240 | 1348 | .addrspace_node = extra.addrspace_node, |
| 1241 | 1349 | .section_node = extra.section_node, |
| 1242 | .init_node = data.rhs, | |
| 1243 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1350 | .init_node = init_node, | |
| 1351 | .mut_token = tree.nodeMainToken(node), | |
| 1244 | 1352 | }); |
| 1245 | 1353 | } |
| 1246 | 1354 | |
| 1247 | 1355 | pub fn localVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1248 | assert(tree.nodes.items(.tag)[node] == .local_var_decl); | |
| 1249 | const data = tree.nodes.items(.data)[node]; | |
| 1250 | const extra = tree.extraData(data.lhs, Node.LocalVarDecl); | |
| 1356 | assert(tree.nodeTag(node) == .local_var_decl); | |
| 1357 | const extra_index, const init_node = tree.nodeData(node).extra_and_opt_node; | |
| 1358 | const extra = tree.extraData(extra_index, Node.LocalVarDecl); | |
| 1251 | 1359 | return tree.fullVarDeclComponents(.{ |
| 1252 | .type_node = extra.type_node, | |
| 1253 | .align_node = extra.align_node, | |
| 1254 | .addrspace_node = 0, | |
| 1255 | .section_node = 0, | |
| 1256 | .init_node = data.rhs, | |
| 1257 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1360 | .type_node = extra.type_node.toOptional(), | |
| 1361 | .align_node = extra.align_node.toOptional(), | |
| 1362 | .addrspace_node = .none, | |
| 1363 | .section_node = .none, | |
| 1364 | .init_node = init_node, | |
| 1365 | .mut_token = tree.nodeMainToken(node), | |
| 1258 | 1366 | }); |
| 1259 | 1367 | } |
| 1260 | 1368 | |
| 1261 | 1369 | pub fn simpleVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1262 | assert(tree.nodes.items(.tag)[node] == .simple_var_decl); | |
| 1263 | const data = tree.nodes.items(.data)[node]; | |
| 1370 | assert(tree.nodeTag(node) == .simple_var_decl); | |
| 1371 | const type_node, const init_node = tree.nodeData(node).opt_node_and_opt_node; | |
| 1264 | 1372 | return tree.fullVarDeclComponents(.{ |
| 1265 | .type_node = data.lhs, | |
| 1266 | .align_node = 0, | |
| 1267 | .addrspace_node = 0, | |
| 1268 | .section_node = 0, | |
| 1269 | .init_node = data.rhs, | |
| 1270 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1373 | .type_node = type_node, | |
| 1374 | .align_node = .none, | |
| 1375 | .addrspace_node = .none, | |
| 1376 | .section_node = .none, | |
| 1377 | .init_node = init_node, | |
| 1378 | .mut_token = tree.nodeMainToken(node), | |
| 1271 | 1379 | }); |
| 1272 | 1380 | } |
| 1273 | 1381 | |
| 1274 | 1382 | pub fn alignedVarDecl(tree: Ast, node: Node.Index) full.VarDecl { |
| 1275 | assert(tree.nodes.items(.tag)[node] == .aligned_var_decl); | |
| 1276 | const data = tree.nodes.items(.data)[node]; | |
| 1383 | assert(tree.nodeTag(node) == .aligned_var_decl); | |
| 1384 | const align_node, const init_node = tree.nodeData(node).node_and_opt_node; | |
| 1277 | 1385 | return tree.fullVarDeclComponents(.{ |
| 1278 | .type_node = 0, | |
| 1279 | .align_node = data.lhs, | |
| 1280 | .addrspace_node = 0, | |
| 1281 | .section_node = 0, | |
| 1282 | .init_node = data.rhs, | |
| 1283 | .mut_token = tree.nodes.items(.main_token)[node], | |
| 1386 | .type_node = .none, | |
| 1387 | .align_node = align_node.toOptional(), | |
| 1388 | .addrspace_node = .none, | |
| 1389 | .section_node = .none, | |
| 1390 | .init_node = init_node, | |
| 1391 | .mut_token = tree.nodeMainToken(node), | |
| 1284 | 1392 | }); |
| 1285 | 1393 | } |
| 1286 | 1394 | |
| 1287 | 1395 | pub fn assignDestructure(tree: Ast, node: Node.Index) full.AssignDestructure { |
| 1288 | const data = tree.nodes.items(.data)[node]; | |
| 1289 | const variable_count = tree.extra_data[data.lhs]; | |
| 1396 | const extra_index, const value_expr = tree.nodeData(node).extra_and_node; | |
| 1397 | const variable_count = tree.extra_data[@intFromEnum(extra_index)]; | |
| 1290 | 1398 | return tree.fullAssignDestructureComponents(.{ |
| 1291 | .variables = tree.extra_data[data.lhs + 1 ..][0..variable_count], | |
| 1292 | .equal_token = tree.nodes.items(.main_token)[node], | |
| 1293 | .value_expr = data.rhs, | |
| 1399 | .variables = tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(extra_index) + 1), variable_count, Node.Index), | |
| 1400 | .equal_token = tree.nodeMainToken(node), | |
| 1401 | .value_expr = value_expr, | |
| 1294 | 1402 | }); |
| 1295 | 1403 | } |
| 1296 | 1404 | |
| 1297 | 1405 | pub fn ifSimple(tree: Ast, node: Node.Index) full.If { |
| 1298 | assert(tree.nodes.items(.tag)[node] == .if_simple); | |
| 1299 | const data = tree.nodes.items(.data)[node]; | |
| 1406 | assert(tree.nodeTag(node) == .if_simple); | |
| 1407 | const cond_expr, const then_expr = tree.nodeData(node).node_and_node; | |
| 1300 | 1408 | return tree.fullIfComponents(.{ |
| 1301 | .cond_expr = data.lhs, | |
| 1302 | .then_expr = data.rhs, | |
| 1303 | .else_expr = 0, | |
| 1304 | .if_token = tree.nodes.items(.main_token)[node], | |
| 1409 | .cond_expr = cond_expr, | |
| 1410 | .then_expr = then_expr, | |
| 1411 | .else_expr = .none, | |
| 1412 | .if_token = tree.nodeMainToken(node), | |
| 1305 | 1413 | }); |
| 1306 | 1414 | } |
| 1307 | 1415 | |
| 1308 | 1416 | pub fn ifFull(tree: Ast, node: Node.Index) full.If { |
| 1309 | assert(tree.nodes.items(.tag)[node] == .@"if"); | |
| 1310 | const data = tree.nodes.items(.data)[node]; | |
| 1311 | const extra = tree.extraData(data.rhs, Node.If); | |
| 1417 | assert(tree.nodeTag(node) == .@"if"); | |
| 1418 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1419 | const extra = tree.extraData(extra_index, Node.If); | |
| 1312 | 1420 | return tree.fullIfComponents(.{ |
| 1313 | .cond_expr = data.lhs, | |
| 1421 | .cond_expr = cond_expr, | |
| 1314 | 1422 | .then_expr = extra.then_expr, |
| 1315 | .else_expr = extra.else_expr, | |
| 1316 | .if_token = tree.nodes.items(.main_token)[node], | |
| 1423 | .else_expr = extra.else_expr.toOptional(), | |
| 1424 | .if_token = tree.nodeMainToken(node), | |
| 1317 | 1425 | }); |
| 1318 | 1426 | } |
| 1319 | 1427 | |
| 1320 | 1428 | pub fn containerField(tree: Ast, node: Node.Index) full.ContainerField { |
| 1321 | assert(tree.nodes.items(.tag)[node] == .container_field); | |
| 1322 | const data = tree.nodes.items(.data)[node]; | |
| 1323 | const extra = tree.extraData(data.rhs, Node.ContainerField); | |
| 1324 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1429 | assert(tree.nodeTag(node) == .container_field); | |
| 1430 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1431 | const extra = tree.extraData(extra_index, Node.ContainerField); | |
| 1432 | const main_token = tree.nodeMainToken(node); | |
| 1325 | 1433 | return tree.fullContainerFieldComponents(.{ |
| 1326 | 1434 | .main_token = main_token, |
| 1327 | .type_expr = data.lhs, | |
| 1328 | .align_expr = extra.align_expr, | |
| 1329 | .value_expr = extra.value_expr, | |
| 1330 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1331 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1435 | .type_expr = type_expr.toOptional(), | |
| 1436 | .align_expr = extra.align_expr.toOptional(), | |
| 1437 | .value_expr = extra.value_expr.toOptional(), | |
| 1438 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1439 | tree.tokenTag(main_token + 1) != .colon, | |
| 1332 | 1440 | }); |
| 1333 | 1441 | } |
| 1334 | 1442 | |
| 1335 | 1443 | pub fn containerFieldInit(tree: Ast, node: Node.Index) full.ContainerField { |
| 1336 | assert(tree.nodes.items(.tag)[node] == .container_field_init); | |
| 1337 | const data = tree.nodes.items(.data)[node]; | |
| 1338 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1444 | assert(tree.nodeTag(node) == .container_field_init); | |
| 1445 | const type_expr, const value_expr = tree.nodeData(node).node_and_opt_node; | |
| 1446 | const main_token = tree.nodeMainToken(node); | |
| 1339 | 1447 | return tree.fullContainerFieldComponents(.{ |
| 1340 | 1448 | .main_token = main_token, |
| 1341 | .type_expr = data.lhs, | |
| 1342 | .align_expr = 0, | |
| 1343 | .value_expr = data.rhs, | |
| 1344 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1345 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1449 | .type_expr = type_expr.toOptional(), | |
| 1450 | .align_expr = .none, | |
| 1451 | .value_expr = value_expr, | |
| 1452 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1453 | tree.tokenTag(main_token + 1) != .colon, | |
| 1346 | 1454 | }); |
| 1347 | 1455 | } |
| 1348 | 1456 | |
| 1349 | 1457 | pub fn containerFieldAlign(tree: Ast, node: Node.Index) full.ContainerField { |
| 1350 | assert(tree.nodes.items(.tag)[node] == .container_field_align); | |
| 1351 | const data = tree.nodes.items(.data)[node]; | |
| 1352 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1458 | assert(tree.nodeTag(node) == .container_field_align); | |
| 1459 | const type_expr, const align_expr = tree.nodeData(node).node_and_node; | |
| 1460 | const main_token = tree.nodeMainToken(node); | |
| 1353 | 1461 | return tree.fullContainerFieldComponents(.{ |
| 1354 | 1462 | .main_token = main_token, |
| 1355 | .type_expr = data.lhs, | |
| 1356 | .align_expr = data.rhs, | |
| 1357 | .value_expr = 0, | |
| 1358 | .tuple_like = tree.tokens.items(.tag)[main_token] != .identifier or | |
| 1359 | tree.tokens.items(.tag)[main_token + 1] != .colon, | |
| 1463 | .type_expr = type_expr.toOptional(), | |
| 1464 | .align_expr = align_expr.toOptional(), | |
| 1465 | .value_expr = .none, | |
| 1466 | .tuple_like = tree.tokenTag(main_token) != .identifier or | |
| 1467 | tree.tokenTag(main_token + 1) != .colon, | |
| 1360 | 1468 | }); |
| 1361 | 1469 | } |
| 1362 | 1470 | |
| 1363 | 1471 | pub fn fnProtoSimple(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { |
| 1364 | assert(tree.nodes.items(.tag)[node] == .fn_proto_simple); | |
| 1365 | const data = tree.nodes.items(.data)[node]; | |
| 1366 | buffer[0] = data.lhs; | |
| 1367 | const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1472 | assert(tree.nodeTag(node) == .fn_proto_simple); | |
| 1473 | const first_param, const return_type = tree.nodeData(node).opt_node_and_opt_node; | |
| 1474 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param}); | |
| 1368 | 1475 | return tree.fullFnProtoComponents(.{ |
| 1369 | 1476 | .proto_node = node, |
| 1370 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1371 | .return_type = data.rhs, | |
| 1477 | .fn_token = tree.nodeMainToken(node), | |
| 1478 | .return_type = return_type, | |
| 1372 | 1479 | .params = params, |
| 1373 | .align_expr = 0, | |
| 1374 | .addrspace_expr = 0, | |
| 1375 | .section_expr = 0, | |
| 1376 | .callconv_expr = 0, | |
| 1480 | .align_expr = .none, | |
| 1481 | .addrspace_expr = .none, | |
| 1482 | .section_expr = .none, | |
| 1483 | .callconv_expr = .none, | |
| 1377 | 1484 | }); |
| 1378 | 1485 | } |
| 1379 | 1486 | |
| 1380 | 1487 | pub fn fnProtoMulti(tree: Ast, node: Node.Index) full.FnProto { |
| 1381 | assert(tree.nodes.items(.tag)[node] == .fn_proto_multi); | |
| 1382 | const data = tree.nodes.items(.data)[node]; | |
| 1383 | const params_range = tree.extraData(data.lhs, Node.SubRange); | |
| 1384 | const params = tree.extra_data[params_range.start..params_range.end]; | |
| 1488 | assert(tree.nodeTag(node) == .fn_proto_multi); | |
| 1489 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1490 | const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1385 | 1491 | return tree.fullFnProtoComponents(.{ |
| 1386 | 1492 | .proto_node = node, |
| 1387 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1388 | .return_type = data.rhs, | |
| 1493 | .fn_token = tree.nodeMainToken(node), | |
| 1494 | .return_type = return_type, | |
| 1389 | 1495 | .params = params, |
| 1390 | .align_expr = 0, | |
| 1391 | .addrspace_expr = 0, | |
| 1392 | .section_expr = 0, | |
| 1393 | .callconv_expr = 0, | |
| 1496 | .align_expr = .none, | |
| 1497 | .addrspace_expr = .none, | |
| 1498 | .section_expr = .none, | |
| 1499 | .callconv_expr = .none, | |
| 1394 | 1500 | }); |
| 1395 | 1501 | } |
| 1396 | 1502 | |
| 1397 | 1503 | pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnProto { |
| 1398 | assert(tree.nodes.items(.tag)[node] == .fn_proto_one); | |
| 1399 | const data = tree.nodes.items(.data)[node]; | |
| 1400 | const extra = tree.extraData(data.lhs, Node.FnProtoOne); | |
| 1401 | buffer[0] = extra.param; | |
| 1402 | const params = if (extra.param == 0) buffer[0..0] else buffer[0..1]; | |
| 1504 | assert(tree.nodeTag(node) == .fn_proto_one); | |
| 1505 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1506 | const extra = tree.extraData(extra_index, Node.FnProtoOne); | |
| 1507 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{extra.param}); | |
| 1403 | 1508 | return tree.fullFnProtoComponents(.{ |
| 1404 | 1509 | .proto_node = node, |
| 1405 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1406 | .return_type = data.rhs, | |
| 1510 | .fn_token = tree.nodeMainToken(node), | |
| 1511 | .return_type = return_type, | |
| 1407 | 1512 | .params = params, |
| 1408 | 1513 | .align_expr = extra.align_expr, |
| 1409 | 1514 | .addrspace_expr = extra.addrspace_expr, |
| ... | ... | @@ -1413,14 +1518,14 @@ pub fn fnProtoOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.FnPr |
| 1413 | 1518 | } |
| 1414 | 1519 | |
| 1415 | 1520 | pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto { |
| 1416 | assert(tree.nodes.items(.tag)[node] == .fn_proto); | |
| 1417 | const data = tree.nodes.items(.data)[node]; | |
| 1418 | const extra = tree.extraData(data.lhs, Node.FnProto); | |
| 1419 | const params = tree.extra_data[extra.params_start..extra.params_end]; | |
| 1521 | assert(tree.nodeTag(node) == .fn_proto); | |
| 1522 | const extra_index, const return_type = tree.nodeData(node).extra_and_opt_node; | |
| 1523 | const extra = tree.extraData(extra_index, Node.FnProto); | |
| 1524 | const params = tree.extraDataSlice(.{ .start = extra.params_start, .end = extra.params_end }, Node.Index); | |
| 1420 | 1525 | return tree.fullFnProtoComponents(.{ |
| 1421 | 1526 | .proto_node = node, |
| 1422 | .fn_token = tree.nodes.items(.main_token)[node], | |
| 1423 | .return_type = data.rhs, | |
| 1527 | .fn_token = tree.nodeMainToken(node), | |
| 1528 | .return_type = return_type, | |
| 1424 | 1529 | .params = params, |
| 1425 | 1530 | .align_expr = extra.align_expr, |
| 1426 | 1531 | .addrspace_expr = extra.addrspace_expr, |
| ... | ... | @@ -1430,300 +1535,275 @@ pub fn fnProto(tree: Ast, node: Node.Index) full.FnProto { |
| 1430 | 1535 | } |
| 1431 | 1536 | |
| 1432 | 1537 | pub fn structInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.StructInit { |
| 1433 | assert(tree.nodes.items(.tag)[node] == .struct_init_one or | |
| 1434 | tree.nodes.items(.tag)[node] == .struct_init_one_comma); | |
| 1435 | const data = tree.nodes.items(.data)[node]; | |
| 1436 | buffer[0] = data.rhs; | |
| 1437 | const fields = if (data.rhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1538 | assert(tree.nodeTag(node) == .struct_init_one or | |
| 1539 | tree.nodeTag(node) == .struct_init_one_comma); | |
| 1540 | const type_expr, const first_field = tree.nodeData(node).node_and_opt_node; | |
| 1541 | const fields = loadOptionalNodesIntoBuffer(1, buffer, .{first_field}); | |
| 1438 | 1542 | return .{ |
| 1439 | 1543 | .ast = .{ |
| 1440 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1544 | .lbrace = tree.nodeMainToken(node), | |
| 1441 | 1545 | .fields = fields, |
| 1442 | .type_expr = data.lhs, | |
| 1546 | .type_expr = type_expr.toOptional(), | |
| 1443 | 1547 | }, |
| 1444 | 1548 | }; |
| 1445 | 1549 | } |
| 1446 | 1550 | |
| 1447 | 1551 | pub fn structInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.StructInit { |
| 1448 | assert(tree.nodes.items(.tag)[node] == .struct_init_dot_two or | |
| 1449 | tree.nodes.items(.tag)[node] == .struct_init_dot_two_comma); | |
| 1450 | const data = tree.nodes.items(.data)[node]; | |
| 1451 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1452 | const fields = if (data.rhs != 0) | |
| 1453 | buffer[0..2] | |
| 1454 | else if (data.lhs != 0) | |
| 1455 | buffer[0..1] | |
| 1456 | else | |
| 1457 | buffer[0..0]; | |
| 1552 | assert(tree.nodeTag(node) == .struct_init_dot_two or | |
| 1553 | tree.nodeTag(node) == .struct_init_dot_two_comma); | |
| 1554 | const fields = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1458 | 1555 | return .{ |
| 1459 | 1556 | .ast = .{ |
| 1460 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1557 | .lbrace = tree.nodeMainToken(node), | |
| 1461 | 1558 | .fields = fields, |
| 1462 | .type_expr = 0, | |
| 1559 | .type_expr = .none, | |
| 1463 | 1560 | }, |
| 1464 | 1561 | }; |
| 1465 | 1562 | } |
| 1466 | 1563 | |
| 1467 | 1564 | pub fn structInitDot(tree: Ast, node: Node.Index) full.StructInit { |
| 1468 | assert(tree.nodes.items(.tag)[node] == .struct_init_dot or | |
| 1469 | tree.nodes.items(.tag)[node] == .struct_init_dot_comma); | |
| 1470 | const data = tree.nodes.items(.data)[node]; | |
| 1565 | assert(tree.nodeTag(node) == .struct_init_dot or | |
| 1566 | tree.nodeTag(node) == .struct_init_dot_comma); | |
| 1567 | const fields = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1471 | 1568 | return .{ |
| 1472 | 1569 | .ast = .{ |
| 1473 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1474 | .fields = tree.extra_data[data.lhs..data.rhs], | |
| 1475 | .type_expr = 0, | |
| 1570 | .lbrace = tree.nodeMainToken(node), | |
| 1571 | .fields = fields, | |
| 1572 | .type_expr = .none, | |
| 1476 | 1573 | }, |
| 1477 | 1574 | }; |
| 1478 | 1575 | } |
| 1479 | 1576 | |
| 1480 | 1577 | pub fn structInit(tree: Ast, node: Node.Index) full.StructInit { |
| 1481 | assert(tree.nodes.items(.tag)[node] == .struct_init or | |
| 1482 | tree.nodes.items(.tag)[node] == .struct_init_comma); | |
| 1483 | const data = tree.nodes.items(.data)[node]; | |
| 1484 | const fields_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1578 | assert(tree.nodeTag(node) == .struct_init or | |
| 1579 | tree.nodeTag(node) == .struct_init_comma); | |
| 1580 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1581 | const fields = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1485 | 1582 | return .{ |
| 1486 | 1583 | .ast = .{ |
| 1487 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1488 | .fields = tree.extra_data[fields_range.start..fields_range.end], | |
| 1489 | .type_expr = data.lhs, | |
| 1584 | .lbrace = tree.nodeMainToken(node), | |
| 1585 | .fields = fields, | |
| 1586 | .type_expr = type_expr.toOptional(), | |
| 1490 | 1587 | }, |
| 1491 | 1588 | }; |
| 1492 | 1589 | } |
| 1493 | 1590 | |
| 1494 | 1591 | pub fn arrayInitOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.ArrayInit { |
| 1495 | assert(tree.nodes.items(.tag)[node] == .array_init_one or | |
| 1496 | tree.nodes.items(.tag)[node] == .array_init_one_comma); | |
| 1497 | const data = tree.nodes.items(.data)[node]; | |
| 1498 | buffer[0] = data.rhs; | |
| 1499 | const elements = if (data.rhs == 0) buffer[0..0] else buffer[0..1]; | |
| 1592 | assert(tree.nodeTag(node) == .array_init_one or | |
| 1593 | tree.nodeTag(node) == .array_init_one_comma); | |
| 1594 | const type_expr, buffer[0] = tree.nodeData(node).node_and_node; | |
| 1500 | 1595 | return .{ |
| 1501 | 1596 | .ast = .{ |
| 1502 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1503 | .elements = elements, | |
| 1504 | .type_expr = data.lhs, | |
| 1597 | .lbrace = tree.nodeMainToken(node), | |
| 1598 | .elements = buffer[0..1], | |
| 1599 | .type_expr = type_expr.toOptional(), | |
| 1505 | 1600 | }, |
| 1506 | 1601 | }; |
| 1507 | 1602 | } |
| 1508 | 1603 | |
| 1509 | 1604 | pub fn arrayInitDotTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ArrayInit { |
| 1510 | assert(tree.nodes.items(.tag)[node] == .array_init_dot_two or | |
| 1511 | tree.nodes.items(.tag)[node] == .array_init_dot_two_comma); | |
| 1512 | const data = tree.nodes.items(.data)[node]; | |
| 1513 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1514 | const elements = if (data.rhs != 0) | |
| 1515 | buffer[0..2] | |
| 1516 | else if (data.lhs != 0) | |
| 1517 | buffer[0..1] | |
| 1518 | else | |
| 1519 | buffer[0..0]; | |
| 1605 | assert(tree.nodeTag(node) == .array_init_dot_two or | |
| 1606 | tree.nodeTag(node) == .array_init_dot_two_comma); | |
| 1607 | const elements = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1520 | 1608 | return .{ |
| 1521 | 1609 | .ast = .{ |
| 1522 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1610 | .lbrace = tree.nodeMainToken(node), | |
| 1523 | 1611 | .elements = elements, |
| 1524 | .type_expr = 0, | |
| 1612 | .type_expr = .none, | |
| 1525 | 1613 | }, |
| 1526 | 1614 | }; |
| 1527 | 1615 | } |
| 1528 | 1616 | |
| 1529 | 1617 | pub fn arrayInitDot(tree: Ast, node: Node.Index) full.ArrayInit { |
| 1530 | assert(tree.nodes.items(.tag)[node] == .array_init_dot or | |
| 1531 | tree.nodes.items(.tag)[node] == .array_init_dot_comma); | |
| 1532 | const data = tree.nodes.items(.data)[node]; | |
| 1618 | assert(tree.nodeTag(node) == .array_init_dot or | |
| 1619 | tree.nodeTag(node) == .array_init_dot_comma); | |
| 1620 | const elements = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1533 | 1621 | return .{ |
| 1534 | 1622 | .ast = .{ |
| 1535 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1536 | .elements = tree.extra_data[data.lhs..data.rhs], | |
| 1537 | .type_expr = 0, | |
| 1623 | .lbrace = tree.nodeMainToken(node), | |
| 1624 | .elements = elements, | |
| 1625 | .type_expr = .none, | |
| 1538 | 1626 | }, |
| 1539 | 1627 | }; |
| 1540 | 1628 | } |
| 1541 | 1629 | |
| 1542 | 1630 | pub fn arrayInit(tree: Ast, node: Node.Index) full.ArrayInit { |
| 1543 | assert(tree.nodes.items(.tag)[node] == .array_init or | |
| 1544 | tree.nodes.items(.tag)[node] == .array_init_comma); | |
| 1545 | const data = tree.nodes.items(.data)[node]; | |
| 1546 | const elem_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1631 | assert(tree.nodeTag(node) == .array_init or | |
| 1632 | tree.nodeTag(node) == .array_init_comma); | |
| 1633 | const type_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1634 | const elements = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1547 | 1635 | return .{ |
| 1548 | 1636 | .ast = .{ |
| 1549 | .lbrace = tree.nodes.items(.main_token)[node], | |
| 1550 | .elements = tree.extra_data[elem_range.start..elem_range.end], | |
| 1551 | .type_expr = data.lhs, | |
| 1637 | .lbrace = tree.nodeMainToken(node), | |
| 1638 | .elements = elements, | |
| 1639 | .type_expr = type_expr.toOptional(), | |
| 1552 | 1640 | }, |
| 1553 | 1641 | }; |
| 1554 | 1642 | } |
| 1555 | 1643 | |
| 1556 | 1644 | pub fn arrayType(tree: Ast, node: Node.Index) full.ArrayType { |
| 1557 | assert(tree.nodes.items(.tag)[node] == .array_type); | |
| 1558 | const data = tree.nodes.items(.data)[node]; | |
| 1645 | assert(tree.nodeTag(node) == .array_type); | |
| 1646 | const elem_count, const elem_type = tree.nodeData(node).node_and_node; | |
| 1559 | 1647 | return .{ |
| 1560 | 1648 | .ast = .{ |
| 1561 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1562 | .elem_count = data.lhs, | |
| 1563 | .sentinel = 0, | |
| 1564 | .elem_type = data.rhs, | |
| 1649 | .lbracket = tree.nodeMainToken(node), | |
| 1650 | .elem_count = elem_count, | |
| 1651 | .sentinel = .none, | |
| 1652 | .elem_type = elem_type, | |
| 1565 | 1653 | }, |
| 1566 | 1654 | }; |
| 1567 | 1655 | } |
| 1568 | 1656 | |
| 1569 | 1657 | pub fn arrayTypeSentinel(tree: Ast, node: Node.Index) full.ArrayType { |
| 1570 | assert(tree.nodes.items(.tag)[node] == .array_type_sentinel); | |
| 1571 | const data = tree.nodes.items(.data)[node]; | |
| 1572 | const extra = tree.extraData(data.rhs, Node.ArrayTypeSentinel); | |
| 1573 | assert(extra.sentinel != 0); | |
| 1658 | assert(tree.nodeTag(node) == .array_type_sentinel); | |
| 1659 | const elem_count, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1660 | const extra = tree.extraData(extra_index, Node.ArrayTypeSentinel); | |
| 1574 | 1661 | return .{ |
| 1575 | 1662 | .ast = .{ |
| 1576 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1577 | .elem_count = data.lhs, | |
| 1578 | .sentinel = extra.sentinel, | |
| 1663 | .lbracket = tree.nodeMainToken(node), | |
| 1664 | .elem_count = elem_count, | |
| 1665 | .sentinel = extra.sentinel.toOptional(), | |
| 1579 | 1666 | .elem_type = extra.elem_type, |
| 1580 | 1667 | }, |
| 1581 | 1668 | }; |
| 1582 | 1669 | } |
| 1583 | 1670 | |
| 1584 | 1671 | pub fn ptrTypeAligned(tree: Ast, node: Node.Index) full.PtrType { |
| 1585 | assert(tree.nodes.items(.tag)[node] == .ptr_type_aligned); | |
| 1586 | const data = tree.nodes.items(.data)[node]; | |
| 1672 | assert(tree.nodeTag(node) == .ptr_type_aligned); | |
| 1673 | const align_node, const child_type = tree.nodeData(node).opt_node_and_node; | |
| 1587 | 1674 | return tree.fullPtrTypeComponents(.{ |
| 1588 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1589 | .align_node = data.lhs, | |
| 1590 | .addrspace_node = 0, | |
| 1591 | .sentinel = 0, | |
| 1592 | .bit_range_start = 0, | |
| 1593 | .bit_range_end = 0, | |
| 1594 | .child_type = data.rhs, | |
| 1675 | .main_token = tree.nodeMainToken(node), | |
| 1676 | .align_node = align_node, | |
| 1677 | .addrspace_node = .none, | |
| 1678 | .sentinel = .none, | |
| 1679 | .bit_range_start = .none, | |
| 1680 | .bit_range_end = .none, | |
| 1681 | .child_type = child_type, | |
| 1595 | 1682 | }); |
| 1596 | 1683 | } |
| 1597 | 1684 | |
| 1598 | 1685 | pub fn ptrTypeSentinel(tree: Ast, node: Node.Index) full.PtrType { |
| 1599 | assert(tree.nodes.items(.tag)[node] == .ptr_type_sentinel); | |
| 1600 | const data = tree.nodes.items(.data)[node]; | |
| 1686 | assert(tree.nodeTag(node) == .ptr_type_sentinel); | |
| 1687 | const sentinel, const child_type = tree.nodeData(node).opt_node_and_node; | |
| 1601 | 1688 | return tree.fullPtrTypeComponents(.{ |
| 1602 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1603 | .align_node = 0, | |
| 1604 | .addrspace_node = 0, | |
| 1605 | .sentinel = data.lhs, | |
| 1606 | .bit_range_start = 0, | |
| 1607 | .bit_range_end = 0, | |
| 1608 | .child_type = data.rhs, | |
| 1689 | .main_token = tree.nodeMainToken(node), | |
| 1690 | .align_node = .none, | |
| 1691 | .addrspace_node = .none, | |
| 1692 | .sentinel = sentinel, | |
| 1693 | .bit_range_start = .none, | |
| 1694 | .bit_range_end = .none, | |
| 1695 | .child_type = child_type, | |
| 1609 | 1696 | }); |
| 1610 | 1697 | } |
| 1611 | 1698 | |
| 1612 | 1699 | pub fn ptrType(tree: Ast, node: Node.Index) full.PtrType { |
| 1613 | assert(tree.nodes.items(.tag)[node] == .ptr_type); | |
| 1614 | const data = tree.nodes.items(.data)[node]; | |
| 1615 | const extra = tree.extraData(data.lhs, Node.PtrType); | |
| 1700 | assert(tree.nodeTag(node) == .ptr_type); | |
| 1701 | const extra_index, const child_type = tree.nodeData(node).extra_and_node; | |
| 1702 | const extra = tree.extraData(extra_index, Node.PtrType); | |
| 1616 | 1703 | return tree.fullPtrTypeComponents(.{ |
| 1617 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1704 | .main_token = tree.nodeMainToken(node), | |
| 1618 | 1705 | .align_node = extra.align_node, |
| 1619 | 1706 | .addrspace_node = extra.addrspace_node, |
| 1620 | 1707 | .sentinel = extra.sentinel, |
| 1621 | .bit_range_start = 0, | |
| 1622 | .bit_range_end = 0, | |
| 1623 | .child_type = data.rhs, | |
| 1708 | .bit_range_start = .none, | |
| 1709 | .bit_range_end = .none, | |
| 1710 | .child_type = child_type, | |
| 1624 | 1711 | }); |
| 1625 | 1712 | } |
| 1626 | 1713 | |
| 1627 | 1714 | pub fn ptrTypeBitRange(tree: Ast, node: Node.Index) full.PtrType { |
| 1628 | assert(tree.nodes.items(.tag)[node] == .ptr_type_bit_range); | |
| 1629 | const data = tree.nodes.items(.data)[node]; | |
| 1630 | const extra = tree.extraData(data.lhs, Node.PtrTypeBitRange); | |
| 1715 | assert(tree.nodeTag(node) == .ptr_type_bit_range); | |
| 1716 | const extra_index, const child_type = tree.nodeData(node).extra_and_node; | |
| 1717 | const extra = tree.extraData(extra_index, Node.PtrTypeBitRange); | |
| 1631 | 1718 | return tree.fullPtrTypeComponents(.{ |
| 1632 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1633 | .align_node = extra.align_node, | |
| 1719 | .main_token = tree.nodeMainToken(node), | |
| 1720 | .align_node = extra.align_node.toOptional(), | |
| 1634 | 1721 | .addrspace_node = extra.addrspace_node, |
| 1635 | 1722 | .sentinel = extra.sentinel, |
| 1636 | .bit_range_start = extra.bit_range_start, | |
| 1637 | .bit_range_end = extra.bit_range_end, | |
| 1638 | .child_type = data.rhs, | |
| 1723 | .bit_range_start = extra.bit_range_start.toOptional(), | |
| 1724 | .bit_range_end = extra.bit_range_end.toOptional(), | |
| 1725 | .child_type = child_type, | |
| 1639 | 1726 | }); |
| 1640 | 1727 | } |
| 1641 | 1728 | |
| 1642 | 1729 | pub fn sliceOpen(tree: Ast, node: Node.Index) full.Slice { |
| 1643 | assert(tree.nodes.items(.tag)[node] == .slice_open); | |
| 1644 | const data = tree.nodes.items(.data)[node]; | |
| 1730 | assert(tree.nodeTag(node) == .slice_open); | |
| 1731 | const sliced, const start = tree.nodeData(node).node_and_node; | |
| 1645 | 1732 | return .{ |
| 1646 | 1733 | .ast = .{ |
| 1647 | .sliced = data.lhs, | |
| 1648 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1649 | .start = data.rhs, | |
| 1650 | .end = 0, | |
| 1651 | .sentinel = 0, | |
| 1734 | .sliced = sliced, | |
| 1735 | .lbracket = tree.nodeMainToken(node), | |
| 1736 | .start = start, | |
| 1737 | .end = .none, | |
| 1738 | .sentinel = .none, | |
| 1652 | 1739 | }, |
| 1653 | 1740 | }; |
| 1654 | 1741 | } |
| 1655 | 1742 | |
| 1656 | 1743 | pub fn slice(tree: Ast, node: Node.Index) full.Slice { |
| 1657 | assert(tree.nodes.items(.tag)[node] == .slice); | |
| 1658 | const data = tree.nodes.items(.data)[node]; | |
| 1659 | const extra = tree.extraData(data.rhs, Node.Slice); | |
| 1744 | assert(tree.nodeTag(node) == .slice); | |
| 1745 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1746 | const extra = tree.extraData(extra_index, Node.Slice); | |
| 1660 | 1747 | return .{ |
| 1661 | 1748 | .ast = .{ |
| 1662 | .sliced = data.lhs, | |
| 1663 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1749 | .sliced = sliced, | |
| 1750 | .lbracket = tree.nodeMainToken(node), | |
| 1664 | 1751 | .start = extra.start, |
| 1665 | .end = extra.end, | |
| 1666 | .sentinel = 0, | |
| 1752 | .end = extra.end.toOptional(), | |
| 1753 | .sentinel = .none, | |
| 1667 | 1754 | }, |
| 1668 | 1755 | }; |
| 1669 | 1756 | } |
| 1670 | 1757 | |
| 1671 | 1758 | pub fn sliceSentinel(tree: Ast, node: Node.Index) full.Slice { |
| 1672 | assert(tree.nodes.items(.tag)[node] == .slice_sentinel); | |
| 1673 | const data = tree.nodes.items(.data)[node]; | |
| 1674 | const extra = tree.extraData(data.rhs, Node.SliceSentinel); | |
| 1759 | assert(tree.nodeTag(node) == .slice_sentinel); | |
| 1760 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1761 | const extra = tree.extraData(extra_index, Node.SliceSentinel); | |
| 1675 | 1762 | return .{ |
| 1676 | 1763 | .ast = .{ |
| 1677 | .sliced = data.lhs, | |
| 1678 | .lbracket = tree.nodes.items(.main_token)[node], | |
| 1764 | .sliced = sliced, | |
| 1765 | .lbracket = tree.nodeMainToken(node), | |
| 1679 | 1766 | .start = extra.start, |
| 1680 | 1767 | .end = extra.end, |
| 1681 | .sentinel = extra.sentinel, | |
| 1768 | .sentinel = extra.sentinel.toOptional(), | |
| 1682 | 1769 | }, |
| 1683 | 1770 | }; |
| 1684 | 1771 | } |
| 1685 | 1772 | |
| 1686 | 1773 | pub fn containerDeclTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { |
| 1687 | assert(tree.nodes.items(.tag)[node] == .container_decl_two or | |
| 1688 | tree.nodes.items(.tag)[node] == .container_decl_two_trailing); | |
| 1689 | const data = tree.nodes.items(.data)[node]; | |
| 1690 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1691 | const members = if (data.rhs != 0) | |
| 1692 | buffer[0..2] | |
| 1693 | else if (data.lhs != 0) | |
| 1694 | buffer[0..1] | |
| 1695 | else | |
| 1696 | buffer[0..0]; | |
| 1774 | assert(tree.nodeTag(node) == .container_decl_two or | |
| 1775 | tree.nodeTag(node) == .container_decl_two_trailing); | |
| 1776 | const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1697 | 1777 | return tree.fullContainerDeclComponents(.{ |
| 1698 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1778 | .main_token = tree.nodeMainToken(node), | |
| 1699 | 1779 | .enum_token = null, |
| 1700 | 1780 | .members = members, |
| 1701 | .arg = 0, | |
| 1781 | .arg = .none, | |
| 1702 | 1782 | }); |
| 1703 | 1783 | } |
| 1704 | 1784 | |
| 1705 | 1785 | pub fn containerDecl(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1706 | assert(tree.nodes.items(.tag)[node] == .container_decl or | |
| 1707 | tree.nodes.items(.tag)[node] == .container_decl_trailing); | |
| 1708 | const data = tree.nodes.items(.data)[node]; | |
| 1786 | assert(tree.nodeTag(node) == .container_decl or | |
| 1787 | tree.nodeTag(node) == .container_decl_trailing); | |
| 1788 | const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1709 | 1789 | return tree.fullContainerDeclComponents(.{ |
| 1710 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1790 | .main_token = tree.nodeMainToken(node), | |
| 1711 | 1791 | .enum_token = null, |
| 1712 | .members = tree.extra_data[data.lhs..data.rhs], | |
| 1713 | .arg = 0, | |
| 1792 | .members = members, | |
| 1793 | .arg = .none, | |
| 1714 | 1794 | }); |
| 1715 | 1795 | } |
| 1716 | 1796 | |
| 1717 | 1797 | pub fn containerDeclArg(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1718 | assert(tree.nodes.items(.tag)[node] == .container_decl_arg or | |
| 1719 | tree.nodes.items(.tag)[node] == .container_decl_arg_trailing); | |
| 1720 | const data = tree.nodes.items(.data)[node]; | |
| 1721 | const members_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1798 | assert(tree.nodeTag(node) == .container_decl_arg or | |
| 1799 | tree.nodeTag(node) == .container_decl_arg_trailing); | |
| 1800 | const arg, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1801 | const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1722 | 1802 | return tree.fullContainerDeclComponents(.{ |
| 1723 | .main_token = tree.nodes.items(.main_token)[node], | |
| 1803 | .main_token = tree.nodeMainToken(node), | |
| 1724 | 1804 | .enum_token = null, |
| 1725 | .members = tree.extra_data[members_range.start..members_range.end], | |
| 1726 | .arg = data.lhs, | |
| 1805 | .members = members, | |
| 1806 | .arg = arg.toOptional(), | |
| 1727 | 1807 | }); |
| 1728 | 1808 | } |
| 1729 | 1809 | |
| ... | ... | @@ -1731,175 +1811,170 @@ pub fn containerDeclRoot(tree: Ast) full.ContainerDecl { |
| 1731 | 1811 | return .{ |
| 1732 | 1812 | .layout_token = null, |
| 1733 | 1813 | .ast = .{ |
| 1734 | .main_token = undefined, | |
| 1814 | .main_token = 0, | |
| 1735 | 1815 | .enum_token = null, |
| 1736 | 1816 | .members = tree.rootDecls(), |
| 1737 | .arg = 0, | |
| 1817 | .arg = .none, | |
| 1738 | 1818 | }, |
| 1739 | 1819 | }; |
| 1740 | 1820 | } |
| 1741 | 1821 | |
| 1742 | 1822 | pub fn taggedUnionTwo(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) full.ContainerDecl { |
| 1743 | assert(tree.nodes.items(.tag)[node] == .tagged_union_two or | |
| 1744 | tree.nodes.items(.tag)[node] == .tagged_union_two_trailing); | |
| 1745 | const data = tree.nodes.items(.data)[node]; | |
| 1746 | buffer.* = .{ data.lhs, data.rhs }; | |
| 1747 | const members = if (data.rhs != 0) | |
| 1748 | buffer[0..2] | |
| 1749 | else if (data.lhs != 0) | |
| 1750 | buffer[0..1] | |
| 1751 | else | |
| 1752 | buffer[0..0]; | |
| 1753 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1823 | assert(tree.nodeTag(node) == .tagged_union_two or | |
| 1824 | tree.nodeTag(node) == .tagged_union_two_trailing); | |
| 1825 | const members = loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node); | |
| 1826 | const main_token = tree.nodeMainToken(node); | |
| 1754 | 1827 | return tree.fullContainerDeclComponents(.{ |
| 1755 | 1828 | .main_token = main_token, |
| 1756 | 1829 | .enum_token = main_token + 2, // union lparen enum |
| 1757 | 1830 | .members = members, |
| 1758 | .arg = 0, | |
| 1831 | .arg = .none, | |
| 1759 | 1832 | }); |
| 1760 | 1833 | } |
| 1761 | 1834 | |
| 1762 | 1835 | pub fn taggedUnion(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1763 | assert(tree.nodes.items(.tag)[node] == .tagged_union or | |
| 1764 | tree.nodes.items(.tag)[node] == .tagged_union_trailing); | |
| 1765 | const data = tree.nodes.items(.data)[node]; | |
| 1766 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1836 | assert(tree.nodeTag(node) == .tagged_union or | |
| 1837 | tree.nodeTag(node) == .tagged_union_trailing); | |
| 1838 | const members = tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index); | |
| 1839 | const main_token = tree.nodeMainToken(node); | |
| 1767 | 1840 | return tree.fullContainerDeclComponents(.{ |
| 1768 | 1841 | .main_token = main_token, |
| 1769 | 1842 | .enum_token = main_token + 2, // union lparen enum |
| 1770 | .members = tree.extra_data[data.lhs..data.rhs], | |
| 1771 | .arg = 0, | |
| 1843 | .members = members, | |
| 1844 | .arg = .none, | |
| 1772 | 1845 | }); |
| 1773 | 1846 | } |
| 1774 | 1847 | |
| 1775 | 1848 | pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl { |
| 1776 | assert(tree.nodes.items(.tag)[node] == .tagged_union_enum_tag or | |
| 1777 | tree.nodes.items(.tag)[node] == .tagged_union_enum_tag_trailing); | |
| 1778 | const data = tree.nodes.items(.data)[node]; | |
| 1779 | const members_range = tree.extraData(data.rhs, Node.SubRange); | |
| 1780 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1849 | assert(tree.nodeTag(node) == .tagged_union_enum_tag or | |
| 1850 | tree.nodeTag(node) == .tagged_union_enum_tag_trailing); | |
| 1851 | const arg, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1852 | const members = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1853 | const main_token = tree.nodeMainToken(node); | |
| 1781 | 1854 | return tree.fullContainerDeclComponents(.{ |
| 1782 | 1855 | .main_token = main_token, |
| 1783 | 1856 | .enum_token = main_token + 2, // union lparen enum |
| 1784 | .members = tree.extra_data[members_range.start..members_range.end], | |
| 1785 | .arg = data.lhs, | |
| 1857 | .members = members, | |
| 1858 | .arg = arg.toOptional(), | |
| 1786 | 1859 | }); |
| 1787 | 1860 | } |
| 1788 | 1861 | |
| 1789 | 1862 | pub fn switchFull(tree: Ast, node: Node.Index) full.Switch { |
| 1790 | const data = &tree.nodes.items(.data)[node]; | |
| 1791 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1792 | const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) { | |
| 1863 | const main_token = tree.nodeMainToken(node); | |
| 1864 | const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokenTag(main_token)) { | |
| 1793 | 1865 | .identifier => .{ main_token + 2, main_token }, |
| 1794 | 1866 | .keyword_switch => .{ main_token, null }, |
| 1795 | 1867 | else => unreachable, |
| 1796 | 1868 | }; |
| 1797 | const extra = tree.extraData(data.rhs, Ast.Node.SubRange); | |
| 1869 | const condition, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1870 | const cases = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Node.Index); | |
| 1798 | 1871 | return .{ |
| 1799 | 1872 | .ast = .{ |
| 1800 | 1873 | .switch_token = switch_token, |
| 1801 | .condition = data.lhs, | |
| 1802 | .cases = tree.extra_data[extra.start..extra.end], | |
| 1874 | .condition = condition, | |
| 1875 | .cases = cases, | |
| 1803 | 1876 | }, |
| 1804 | 1877 | .label_token = label_token, |
| 1805 | 1878 | }; |
| 1806 | 1879 | } |
| 1807 | 1880 | |
| 1808 | 1881 | pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1809 | const data = &tree.nodes.items(.data)[node]; | |
| 1810 | const values: *[1]Node.Index = &data.lhs; | |
| 1882 | const first_value, const target_expr = tree.nodeData(node).opt_node_and_node; | |
| 1811 | 1883 | return tree.fullSwitchCaseComponents(.{ |
| 1812 | .values = if (data.lhs == 0) values[0..0] else values[0..1], | |
| 1813 | .arrow_token = tree.nodes.items(.main_token)[node], | |
| 1814 | .target_expr = data.rhs, | |
| 1884 | .values = if (first_value == .none) | |
| 1885 | &.{} | |
| 1886 | else | |
| 1887 | // Ensure that the returned slice points into the existing memory of the Ast | |
| 1888 | (@as(*const Node.Index, @ptrCast(&tree.nodes.items(.data)[@intFromEnum(node)].opt_node_and_node[0])))[0..1], | |
| 1889 | .arrow_token = tree.nodeMainToken(node), | |
| 1890 | .target_expr = target_expr, | |
| 1815 | 1891 | }, node); |
| 1816 | 1892 | } |
| 1817 | 1893 | |
| 1818 | 1894 | pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1819 | const data = tree.nodes.items(.data)[node]; | |
| 1820 | const extra = tree.extraData(data.lhs, Node.SubRange); | |
| 1895 | const extra_index, const target_expr = tree.nodeData(node).extra_and_node; | |
| 1896 | const values = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1821 | 1897 | return tree.fullSwitchCaseComponents(.{ |
| 1822 | .values = tree.extra_data[extra.start..extra.end], | |
| 1823 | .arrow_token = tree.nodes.items(.main_token)[node], | |
| 1824 | .target_expr = data.rhs, | |
| 1898 | .values = values, | |
| 1899 | .arrow_token = tree.nodeMainToken(node), | |
| 1900 | .target_expr = target_expr, | |
| 1825 | 1901 | }, node); |
| 1826 | 1902 | } |
| 1827 | 1903 | |
| 1828 | 1904 | pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { |
| 1829 | const data = tree.nodes.items(.data)[node]; | |
| 1905 | const template, const rparen = tree.nodeData(node).node_and_token; | |
| 1830 | 1906 | return tree.fullAsmComponents(.{ |
| 1831 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1832 | .template = data.lhs, | |
| 1907 | .asm_token = tree.nodeMainToken(node), | |
| 1908 | .template = template, | |
| 1833 | 1909 | .items = &.{}, |
| 1834 | .rparen = data.rhs, | |
| 1910 | .rparen = rparen, | |
| 1835 | 1911 | }); |
| 1836 | 1912 | } |
| 1837 | 1913 | |
| 1838 | 1914 | pub fn asmFull(tree: Ast, node: Node.Index) full.Asm { |
| 1839 | const data = tree.nodes.items(.data)[node]; | |
| 1840 | const extra = tree.extraData(data.rhs, Node.Asm); | |
| 1915 | const template, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1916 | const extra = tree.extraData(extra_index, Node.Asm); | |
| 1917 | const items = tree.extraDataSlice(.{ .start = extra.items_start, .end = extra.items_end }, Node.Index); | |
| 1841 | 1918 | return tree.fullAsmComponents(.{ |
| 1842 | .asm_token = tree.nodes.items(.main_token)[node], | |
| 1843 | .template = data.lhs, | |
| 1844 | .items = tree.extra_data[extra.items_start..extra.items_end], | |
| 1919 | .asm_token = tree.nodeMainToken(node), | |
| 1920 | .template = template, | |
| 1921 | .items = items, | |
| 1845 | 1922 | .rparen = extra.rparen, |
| 1846 | 1923 | }); |
| 1847 | 1924 | } |
| 1848 | 1925 | |
| 1849 | 1926 | pub fn whileSimple(tree: Ast, node: Node.Index) full.While { |
| 1850 | const data = tree.nodes.items(.data)[node]; | |
| 1927 | const cond_expr, const then_expr = tree.nodeData(node).node_and_node; | |
| 1851 | 1928 | return tree.fullWhileComponents(.{ |
| 1852 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1853 | .cond_expr = data.lhs, | |
| 1854 | .cont_expr = 0, | |
| 1855 | .then_expr = data.rhs, | |
| 1856 | .else_expr = 0, | |
| 1929 | .while_token = tree.nodeMainToken(node), | |
| 1930 | .cond_expr = cond_expr, | |
| 1931 | .cont_expr = .none, | |
| 1932 | .then_expr = then_expr, | |
| 1933 | .else_expr = .none, | |
| 1857 | 1934 | }); |
| 1858 | 1935 | } |
| 1859 | 1936 | |
| 1860 | 1937 | pub fn whileCont(tree: Ast, node: Node.Index) full.While { |
| 1861 | const data = tree.nodes.items(.data)[node]; | |
| 1862 | const extra = tree.extraData(data.rhs, Node.WhileCont); | |
| 1938 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1939 | const extra = tree.extraData(extra_index, Node.WhileCont); | |
| 1863 | 1940 | return tree.fullWhileComponents(.{ |
| 1864 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1865 | .cond_expr = data.lhs, | |
| 1866 | .cont_expr = extra.cont_expr, | |
| 1941 | .while_token = tree.nodeMainToken(node), | |
| 1942 | .cond_expr = cond_expr, | |
| 1943 | .cont_expr = extra.cont_expr.toOptional(), | |
| 1867 | 1944 | .then_expr = extra.then_expr, |
| 1868 | .else_expr = 0, | |
| 1945 | .else_expr = .none, | |
| 1869 | 1946 | }); |
| 1870 | 1947 | } |
| 1871 | 1948 | |
| 1872 | 1949 | pub fn whileFull(tree: Ast, node: Node.Index) full.While { |
| 1873 | const data = tree.nodes.items(.data)[node]; | |
| 1874 | const extra = tree.extraData(data.rhs, Node.While); | |
| 1950 | const cond_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1951 | const extra = tree.extraData(extra_index, Node.While); | |
| 1875 | 1952 | return tree.fullWhileComponents(.{ |
| 1876 | .while_token = tree.nodes.items(.main_token)[node], | |
| 1877 | .cond_expr = data.lhs, | |
| 1953 | .while_token = tree.nodeMainToken(node), | |
| 1954 | .cond_expr = cond_expr, | |
| 1878 | 1955 | .cont_expr = extra.cont_expr, |
| 1879 | 1956 | .then_expr = extra.then_expr, |
| 1880 | .else_expr = extra.else_expr, | |
| 1957 | .else_expr = extra.else_expr.toOptional(), | |
| 1881 | 1958 | }); |
| 1882 | 1959 | } |
| 1883 | 1960 | |
| 1884 | 1961 | pub fn forSimple(tree: Ast, node: Node.Index) full.For { |
| 1885 | const data = &tree.nodes.items(.data)[node]; | |
| 1886 | const inputs: *[1]Node.Index = &data.lhs; | |
| 1962 | const data = &tree.nodes.items(.data)[@intFromEnum(node)].node_and_node; | |
| 1887 | 1963 | return tree.fullForComponents(.{ |
| 1888 | .for_token = tree.nodes.items(.main_token)[node], | |
| 1889 | .inputs = inputs[0..1], | |
| 1890 | .then_expr = data.rhs, | |
| 1891 | .else_expr = 0, | |
| 1964 | .for_token = tree.nodeMainToken(node), | |
| 1965 | .inputs = (&data[0])[0..1], | |
| 1966 | .then_expr = data[1], | |
| 1967 | .else_expr = .none, | |
| 1892 | 1968 | }); |
| 1893 | 1969 | } |
| 1894 | 1970 | |
| 1895 | 1971 | pub fn forFull(tree: Ast, node: Node.Index) full.For { |
| 1896 | const data = tree.nodes.items(.data)[node]; | |
| 1897 | const extra = @as(Node.For, @bitCast(data.rhs)); | |
| 1898 | const inputs = tree.extra_data[data.lhs..][0..extra.inputs]; | |
| 1899 | const then_expr = tree.extra_data[data.lhs + extra.inputs]; | |
| 1900 | const else_expr = if (extra.has_else) tree.extra_data[data.lhs + extra.inputs + 1] else 0; | |
| 1972 | const extra_index, const extra = tree.nodeData(node).@"for"; | |
| 1973 | const inputs = tree.extraDataSliceWithLen(extra_index, extra.inputs, Node.Index); | |
| 1974 | const then_expr: Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs]); | |
| 1975 | const else_expr: Node.OptionalIndex = if (extra.has_else) @enumFromInt(tree.extra_data[@intFromEnum(extra_index) + extra.inputs + 1]) else .none; | |
| 1901 | 1976 | return tree.fullForComponents(.{ |
| 1902 | .for_token = tree.nodes.items(.main_token)[node], | |
| 1977 | .for_token = tree.nodeMainToken(node), | |
| 1903 | 1978 | .inputs = inputs, |
| 1904 | 1979 | .then_expr = then_expr, |
| 1905 | 1980 | .else_expr = else_expr, |
| ... | ... | @@ -1907,28 +1982,26 @@ pub fn forFull(tree: Ast, node: Node.Index) full.For { |
| 1907 | 1982 | } |
| 1908 | 1983 | |
| 1909 | 1984 | pub fn callOne(tree: Ast, buffer: *[1]Node.Index, node: Node.Index) full.Call { |
| 1910 | const data = tree.nodes.items(.data)[node]; | |
| 1911 | buffer.* = .{data.rhs}; | |
| 1912 | const params = if (data.rhs != 0) buffer[0..1] else buffer[0..0]; | |
| 1985 | const fn_expr, const first_param = tree.nodeData(node).node_and_opt_node; | |
| 1986 | const params = loadOptionalNodesIntoBuffer(1, buffer, .{first_param}); | |
| 1913 | 1987 | return tree.fullCallComponents(.{ |
| 1914 | .lparen = tree.nodes.items(.main_token)[node], | |
| 1915 | .fn_expr = data.lhs, | |
| 1988 | .lparen = tree.nodeMainToken(node), | |
| 1989 | .fn_expr = fn_expr, | |
| 1916 | 1990 | .params = params, |
| 1917 | 1991 | }); |
| 1918 | 1992 | } |
| 1919 | 1993 | |
| 1920 | 1994 | pub fn callFull(tree: Ast, node: Node.Index) full.Call { |
| 1921 | const data = tree.nodes.items(.data)[node]; | |
| 1922 | const extra = tree.extraData(data.rhs, Node.SubRange); | |
| 1995 | const fn_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 1996 | const params = tree.extraDataSlice(tree.extraData(extra_index, Node.SubRange), Node.Index); | |
| 1923 | 1997 | return tree.fullCallComponents(.{ |
| 1924 | .lparen = tree.nodes.items(.main_token)[node], | |
| 1925 | .fn_expr = data.lhs, | |
| 1926 | .params = tree.extra_data[extra.start..extra.end], | |
| 1998 | .lparen = tree.nodeMainToken(node), | |
| 1999 | .fn_expr = fn_expr, | |
| 2000 | .params = params, | |
| 1927 | 2001 | }); |
| 1928 | 2002 | } |
| 1929 | 2003 | |
| 1930 | 2004 | fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl { |
| 1931 | const token_tags = tree.tokens.items(.tag); | |
| 1932 | 2005 | var result: full.VarDecl = .{ |
| 1933 | 2006 | .ast = info, |
| 1934 | 2007 | .visib_token = null, |
| ... | ... | @@ -1940,7 +2013,7 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl |
| 1940 | 2013 | var i = info.mut_token; |
| 1941 | 2014 | while (i > 0) { |
| 1942 | 2015 | i -= 1; |
| 1943 | switch (token_tags[i]) { | |
| 2016 | switch (tree.tokenTag(i)) { | |
| 1944 | 2017 | .keyword_extern, .keyword_export => result.extern_export_token = i, |
| 1945 | 2018 | .keyword_comptime => result.comptime_token = i, |
| 1946 | 2019 | .keyword_pub => result.visib_token = i, |
| ... | ... | @@ -1953,14 +2026,12 @@ fn fullVarDeclComponents(tree: Ast, info: full.VarDecl.Components) full.VarDecl |
| 1953 | 2026 | } |
| 1954 | 2027 | |
| 1955 | 2028 | fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Components) full.AssignDestructure { |
| 1956 | const token_tags = tree.tokens.items(.tag); | |
| 1957 | const node_tags = tree.nodes.items(.tag); | |
| 1958 | 2029 | var result: full.AssignDestructure = .{ |
| 1959 | 2030 | .comptime_token = null, |
| 1960 | 2031 | .ast = info, |
| 1961 | 2032 | }; |
| 1962 | 2033 | const first_variable_token = tree.firstToken(info.variables[0]); |
| 1963 | const maybe_comptime_token = switch (node_tags[info.variables[0]]) { | |
| 2034 | const maybe_comptime_token = switch (tree.nodeTag(info.variables[0])) { | |
| 1964 | 2035 | .global_var_decl, |
| 1965 | 2036 | .local_var_decl, |
| 1966 | 2037 | .aligned_var_decl, |
| ... | ... | @@ -1968,14 +2039,13 @@ fn fullAssignDestructureComponents(tree: Ast, info: full.AssignDestructure.Compo |
| 1968 | 2039 | => first_variable_token, |
| 1969 | 2040 | else => first_variable_token - 1, |
| 1970 | 2041 | }; |
| 1971 | if (token_tags[maybe_comptime_token] == .keyword_comptime) { | |
| 2042 | if (tree.tokenTag(maybe_comptime_token) == .keyword_comptime) { | |
| 1972 | 2043 | result.comptime_token = maybe_comptime_token; |
| 1973 | 2044 | } |
| 1974 | 2045 | return result; |
| 1975 | 2046 | } |
| 1976 | 2047 | |
| 1977 | 2048 | fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 1978 | const token_tags = tree.tokens.items(.tag); | |
| 1979 | 2049 | var result: full.If = .{ |
| 1980 | 2050 | .ast = info, |
| 1981 | 2051 | .payload_token = null, |
| ... | ... | @@ -1985,14 +2055,14 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 1985 | 2055 | // if (cond_expr) |x| |
| 1986 | 2056 | // ^ ^ |
| 1987 | 2057 | const payload_pipe = tree.lastToken(info.cond_expr) + 2; |
| 1988 | if (token_tags[payload_pipe] == .pipe) { | |
| 2058 | if (tree.tokenTag(payload_pipe) == .pipe) { | |
| 1989 | 2059 | result.payload_token = payload_pipe + 1; |
| 1990 | 2060 | } |
| 1991 | if (info.else_expr != 0) { | |
| 2061 | if (info.else_expr != .none) { | |
| 1992 | 2062 | // then_expr else |x| |
| 1993 | 2063 | // ^ ^ |
| 1994 | 2064 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 1995 | if (token_tags[result.else_token + 1] == .pipe) { | |
| 2065 | if (tree.tokenTag(result.else_token + 1) == .pipe) { | |
| 1996 | 2066 | result.error_token = result.else_token + 2; |
| 1997 | 2067 | } |
| 1998 | 2068 | } |
| ... | ... | @@ -2000,12 +2070,11 @@ fn fullIfComponents(tree: Ast, info: full.If.Components) full.If { |
| 2000 | 2070 | } |
| 2001 | 2071 | |
| 2002 | 2072 | fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) full.ContainerField { |
| 2003 | const token_tags = tree.tokens.items(.tag); | |
| 2004 | 2073 | var result: full.ContainerField = .{ |
| 2005 | 2074 | .ast = info, |
| 2006 | 2075 | .comptime_token = null, |
| 2007 | 2076 | }; |
| 2008 | if (info.main_token > 0 and token_tags[info.main_token - 1] == .keyword_comptime) { | |
| 2077 | if (tree.isTokenPrecededByTags(info.main_token, &.{.keyword_comptime})) { | |
| 2009 | 2078 | // comptime type = init, |
| 2010 | 2079 | // ^ ^ |
| 2011 | 2080 | // comptime name: type = init, |
| ... | ... | @@ -2016,7 +2085,6 @@ fn fullContainerFieldComponents(tree: Ast, info: full.ContainerField.Components) |
| 2016 | 2085 | } |
| 2017 | 2086 | |
| 2018 | 2087 | fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto { |
| 2019 | const token_tags = tree.tokens.items(.tag); | |
| 2020 | 2088 | var result: full.FnProto = .{ |
| 2021 | 2089 | .ast = info, |
| 2022 | 2090 | .visib_token = null, |
| ... | ... | @@ -2028,7 +2096,7 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto |
| 2028 | 2096 | var i = info.fn_token; |
| 2029 | 2097 | while (i > 0) { |
| 2030 | 2098 | i -= 1; |
| 2031 | switch (token_tags[i]) { | |
| 2099 | switch (tree.tokenTag(i)) { | |
| 2032 | 2100 | .keyword_extern, |
| 2033 | 2101 | .keyword_export, |
| 2034 | 2102 | .keyword_inline, |
| ... | ... | @@ -2040,25 +2108,24 @@ fn fullFnProtoComponents(tree: Ast, info: full.FnProto.Components) full.FnProto |
| 2040 | 2108 | } |
| 2041 | 2109 | } |
| 2042 | 2110 | const after_fn_token = info.fn_token + 1; |
| 2043 | if (token_tags[after_fn_token] == .identifier) { | |
| 2111 | if (tree.tokenTag(after_fn_token) == .identifier) { | |
| 2044 | 2112 | result.name_token = after_fn_token; |
| 2045 | 2113 | result.lparen = after_fn_token + 1; |
| 2046 | 2114 | } else { |
| 2047 | 2115 | result.lparen = after_fn_token; |
| 2048 | 2116 | } |
| 2049 | assert(token_tags[result.lparen] == .l_paren); | |
| 2117 | assert(tree.tokenTag(result.lparen) == .l_paren); | |
| 2050 | 2118 | |
| 2051 | 2119 | return result; |
| 2052 | 2120 | } |
| 2053 | 2121 | |
| 2054 | 2122 | fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType { |
| 2055 | const token_tags = tree.tokens.items(.tag); | |
| 2056 | const size: std.builtin.Type.Pointer.Size = switch (token_tags[info.main_token]) { | |
| 2123 | const size: std.builtin.Type.Pointer.Size = switch (tree.tokenTag(info.main_token)) { | |
| 2057 | 2124 | .asterisk, |
| 2058 | 2125 | .asterisk_asterisk, |
| 2059 | 2126 | => .one, |
| 2060 | .l_bracket => switch (token_tags[info.main_token + 1]) { | |
| 2061 | .asterisk => if (token_tags[info.main_token + 2] == .identifier) .c else .many, | |
| 2127 | .l_bracket => switch (tree.tokenTag(info.main_token + 1)) { | |
| 2128 | .asterisk => if (tree.tokenTag(info.main_token + 2) == .identifier) .c else .many, | |
| 2062 | 2129 | else => .slice, |
| 2063 | 2130 | }, |
| 2064 | 2131 | else => unreachable, |
| ... | ... | @@ -2074,23 +2141,23 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType |
| 2074 | 2141 | // here while looking for modifiers as that could result in false |
| 2075 | 2142 | // positives. Therefore, start after a sentinel if there is one and |
| 2076 | 2143 | // skip over any align node and bit range nodes. |
| 2077 | var i = if (info.sentinel != 0) tree.lastToken(info.sentinel) + 1 else switch (size) { | |
| 2144 | var i = if (info.sentinel.unwrap()) |sentinel| tree.lastToken(sentinel) + 1 else switch (size) { | |
| 2078 | 2145 | .many, .c => info.main_token + 1, |
| 2079 | 2146 | else => info.main_token, |
| 2080 | 2147 | }; |
| 2081 | 2148 | const end = tree.firstToken(info.child_type); |
| 2082 | 2149 | while (i < end) : (i += 1) { |
| 2083 | switch (token_tags[i]) { | |
| 2150 | switch (tree.tokenTag(i)) { | |
| 2084 | 2151 | .keyword_allowzero => result.allowzero_token = i, |
| 2085 | 2152 | .keyword_const => result.const_token = i, |
| 2086 | 2153 | .keyword_volatile => result.volatile_token = i, |
| 2087 | 2154 | .keyword_align => { |
| 2088 | assert(info.align_node != 0); | |
| 2089 | if (info.bit_range_end != 0) { | |
| 2090 | assert(info.bit_range_start != 0); | |
| 2091 | i = tree.lastToken(info.bit_range_end) + 1; | |
| 2155 | const align_node = info.align_node.unwrap().?; | |
| 2156 | if (info.bit_range_end.unwrap()) |bit_range_end| { | |
| 2157 | assert(info.bit_range_start != .none); | |
| 2158 | i = tree.lastToken(bit_range_end) + 1; | |
| 2092 | 2159 | } else { |
| 2093 | i = tree.lastToken(info.align_node) + 1; | |
| 2160 | i = tree.lastToken(align_node) + 1; | |
| 2094 | 2161 | } |
| 2095 | 2162 | }, |
| 2096 | 2163 | else => {}, |
| ... | ... | @@ -2100,30 +2167,29 @@ fn fullPtrTypeComponents(tree: Ast, info: full.PtrType.Components) full.PtrType |
| 2100 | 2167 | } |
| 2101 | 2168 | |
| 2102 | 2169 | fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) full.ContainerDecl { |
| 2103 | const token_tags = tree.tokens.items(.tag); | |
| 2104 | 2170 | var result: full.ContainerDecl = .{ |
| 2105 | 2171 | .ast = info, |
| 2106 | 2172 | .layout_token = null, |
| 2107 | 2173 | }; |
| 2108 | 2174 | |
| 2109 | if (info.main_token == 0) return result; | |
| 2175 | if (info.main_token == 0) return result; // .root | |
| 2176 | const previous_token = info.main_token - 1; | |
| 2110 | 2177 | |
| 2111 | switch (token_tags[info.main_token - 1]) { | |
| 2112 | .keyword_extern, .keyword_packed => result.layout_token = info.main_token - 1, | |
| 2178 | switch (tree.tokenTag(previous_token)) { | |
| 2179 | .keyword_extern, .keyword_packed => result.layout_token = previous_token, | |
| 2113 | 2180 | else => {}, |
| 2114 | 2181 | } |
| 2115 | 2182 | return result; |
| 2116 | 2183 | } |
| 2117 | 2184 | |
| 2118 | 2185 | fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch { |
| 2119 | const token_tags = tree.tokens.items(.tag); | |
| 2120 | 2186 | const tok_i = info.switch_token -| 1; |
| 2121 | 2187 | var result: full.Switch = .{ |
| 2122 | 2188 | .ast = info, |
| 2123 | 2189 | .label_token = null, |
| 2124 | 2190 | }; |
| 2125 | if (token_tags[tok_i] == .colon and | |
| 2126 | token_tags[tok_i -| 1] == .identifier) | |
| 2191 | if (tree.tokenTag(tok_i) == .colon and | |
| 2192 | tree.tokenTag(tok_i -| 1) == .identifier) | |
| 2127 | 2193 | { |
| 2128 | 2194 | result.label_token = tok_i - 1; |
| 2129 | 2195 | } |
| ... | ... | @@ -2131,26 +2197,25 @@ fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch { |
| 2131 | 2197 | } |
| 2132 | 2198 | |
| 2133 | 2199 | fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase { |
| 2134 | const token_tags = tree.tokens.items(.tag); | |
| 2135 | const node_tags = tree.nodes.items(.tag); | |
| 2136 | 2200 | var result: full.SwitchCase = .{ |
| 2137 | 2201 | .ast = info, |
| 2138 | 2202 | .payload_token = null, |
| 2139 | 2203 | .inline_token = null, |
| 2140 | 2204 | }; |
| 2141 | if (token_tags[info.arrow_token + 1] == .pipe) { | |
| 2205 | if (tree.tokenTag(info.arrow_token + 1) == .pipe) { | |
| 2142 | 2206 | result.payload_token = info.arrow_token + 2; |
| 2143 | 2207 | } |
| 2144 | switch (node_tags[node]) { | |
| 2145 | .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node), | |
| 2146 | else => {}, | |
| 2147 | } | |
| 2208 | result.inline_token = switch (tree.nodeTag(node)) { | |
| 2209 | .switch_case_inline, .switch_case_inline_one => if (result.ast.values.len == 0) | |
| 2210 | info.arrow_token - 2 | |
| 2211 | else | |
| 2212 | tree.firstToken(result.ast.values[0]) - 1, | |
| 2213 | else => null, | |
| 2214 | }; | |
| 2148 | 2215 | return result; |
| 2149 | 2216 | } |
| 2150 | 2217 | |
| 2151 | 2218 | fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2152 | const token_tags = tree.tokens.items(.tag); | |
| 2153 | const node_tags = tree.nodes.items(.tag); | |
| 2154 | 2219 | var result: full.Asm = .{ |
| 2155 | 2220 | .ast = info, |
| 2156 | 2221 | .volatile_token = null, |
| ... | ... | @@ -2158,11 +2223,11 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2158 | 2223 | .outputs = &.{}, |
| 2159 | 2224 | .first_clobber = null, |
| 2160 | 2225 | }; |
| 2161 | if (token_tags[info.asm_token + 1] == .keyword_volatile) { | |
| 2226 | if (tree.tokenTag(info.asm_token + 1) == .keyword_volatile) { | |
| 2162 | 2227 | result.volatile_token = info.asm_token + 1; |
| 2163 | 2228 | } |
| 2164 | 2229 | const outputs_end: usize = for (info.items, 0..) |item, i| { |
| 2165 | switch (node_tags[item]) { | |
| 2230 | switch (tree.nodeTag(item)) { | |
| 2166 | 2231 | .asm_output => continue, |
| 2167 | 2232 | else => break i, |
| 2168 | 2233 | } |
| ... | ... | @@ -2174,10 +2239,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2174 | 2239 | if (info.items.len == 0) { |
| 2175 | 2240 | // asm ("foo" ::: "a", "b"); |
| 2176 | 2241 | const template_token = tree.lastToken(info.template); |
| 2177 | if (token_tags[template_token + 1] == .colon and | |
| 2178 | token_tags[template_token + 2] == .colon and | |
| 2179 | token_tags[template_token + 3] == .colon and | |
| 2180 | token_tags[template_token + 4] == .string_literal) | |
| 2242 | if (tree.tokenTag(template_token + 1) == .colon and | |
| 2243 | tree.tokenTag(template_token + 2) == .colon and | |
| 2244 | tree.tokenTag(template_token + 3) == .colon and | |
| 2245 | tree.tokenTag(template_token + 4) == .string_literal) | |
| 2181 | 2246 | { |
| 2182 | 2247 | result.first_clobber = template_token + 4; |
| 2183 | 2248 | } |
| ... | ... | @@ -2187,9 +2252,9 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2187 | 2252 | const rparen = tree.lastToken(last_input); |
| 2188 | 2253 | var i = rparen + 1; |
| 2189 | 2254 | // Allow a (useless) comma right after the closing parenthesis. |
| 2190 | if (token_tags[i] == .comma) i += 1; | |
| 2191 | if (token_tags[i] == .colon and | |
| 2192 | token_tags[i + 1] == .string_literal) | |
| 2255 | if (tree.tokenTag(i) == .comma) i = i + 1; | |
| 2256 | if (tree.tokenTag(i) == .colon and | |
| 2257 | tree.tokenTag(i + 1) == .string_literal) | |
| 2193 | 2258 | { |
| 2194 | 2259 | result.first_clobber = i + 1; |
| 2195 | 2260 | } |
| ... | ... | @@ -2199,10 +2264,10 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2199 | 2264 | const rparen = tree.lastToken(last_output); |
| 2200 | 2265 | var i = rparen + 1; |
| 2201 | 2266 | // Allow a (useless) comma right after the closing parenthesis. |
| 2202 | if (token_tags[i] == .comma) i += 1; | |
| 2203 | if (token_tags[i] == .colon and | |
| 2204 | token_tags[i + 1] == .colon and | |
| 2205 | token_tags[i + 2] == .string_literal) | |
| 2267 | if (tree.tokenTag(i) == .comma) i = i + 1; | |
| 2268 | if (tree.tokenTag(i) == .colon and | |
| 2269 | tree.tokenTag(i + 1) == .colon and | |
| 2270 | tree.tokenTag(i + 2) == .string_literal) | |
| 2206 | 2271 | { |
| 2207 | 2272 | result.first_clobber = i + 2; |
| 2208 | 2273 | } |
| ... | ... | @@ -2212,7 +2277,6 @@ fn fullAsmComponents(tree: Ast, info: full.Asm.Components) full.Asm { |
| 2212 | 2277 | } |
| 2213 | 2278 | |
| 2214 | 2279 | fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2215 | const token_tags = tree.tokens.items(.tag); | |
| 2216 | 2280 | var result: full.While = .{ |
| 2217 | 2281 | .ast = info, |
| 2218 | 2282 | .inline_token = null, |
| ... | ... | @@ -2221,25 +2285,23 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2221 | 2285 | .else_token = undefined, |
| 2222 | 2286 | .error_token = null, |
| 2223 | 2287 | }; |
| 2224 | var tok_i = info.while_token -| 1; | |
| 2225 | if (token_tags[tok_i] == .keyword_inline) { | |
| 2226 | result.inline_token = tok_i; | |
| 2227 | tok_i -|= 1; | |
| 2288 | var tok_i = info.while_token; | |
| 2289 | if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) { | |
| 2290 | result.inline_token = tok_i - 1; | |
| 2291 | tok_i = tok_i - 1; | |
| 2228 | 2292 | } |
| 2229 | if (token_tags[tok_i] == .colon and | |
| 2230 | token_tags[tok_i -| 1] == .identifier) | |
| 2231 | { | |
| 2232 | result.label_token = tok_i - 1; | |
| 2293 | if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) { | |
| 2294 | result.label_token = tok_i - 2; | |
| 2233 | 2295 | } |
| 2234 | 2296 | const last_cond_token = tree.lastToken(info.cond_expr); |
| 2235 | if (token_tags[last_cond_token + 2] == .pipe) { | |
| 2297 | if (tree.tokenTag(last_cond_token + 2) == .pipe) { | |
| 2236 | 2298 | result.payload_token = last_cond_token + 3; |
| 2237 | 2299 | } |
| 2238 | if (info.else_expr != 0) { | |
| 2300 | if (info.else_expr != .none) { | |
| 2239 | 2301 | // then_expr else |x| |
| 2240 | 2302 | // ^ ^ |
| 2241 | 2303 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 2242 | if (token_tags[result.else_token + 1] == .pipe) { | |
| 2304 | if (tree.tokenTag(result.else_token + 1) == .pipe) { | |
| 2243 | 2305 | result.error_token = result.else_token + 2; |
| 2244 | 2306 | } |
| 2245 | 2307 | } |
| ... | ... | @@ -2247,7 +2309,6 @@ fn fullWhileComponents(tree: Ast, info: full.While.Components) full.While { |
| 2247 | 2309 | } |
| 2248 | 2310 | |
| 2249 | 2311 | fn fullForComponents(tree: Ast, info: full.For.Components) full.For { |
| 2250 | const token_tags = tree.tokens.items(.tag); | |
| 2251 | 2312 | var result: full.For = .{ |
| 2252 | 2313 | .ast = info, |
| 2253 | 2314 | .inline_token = null, |
| ... | ... | @@ -2255,39 +2316,36 @@ fn fullForComponents(tree: Ast, info: full.For.Components) full.For { |
| 2255 | 2316 | .payload_token = undefined, |
| 2256 | 2317 | .else_token = undefined, |
| 2257 | 2318 | }; |
| 2258 | var tok_i = info.for_token -| 1; | |
| 2259 | if (token_tags[tok_i] == .keyword_inline) { | |
| 2260 | result.inline_token = tok_i; | |
| 2261 | tok_i -|= 1; | |
| 2319 | var tok_i = info.for_token; | |
| 2320 | if (tree.isTokenPrecededByTags(tok_i, &.{.keyword_inline})) { | |
| 2321 | result.inline_token = tok_i - 1; | |
| 2322 | tok_i = tok_i - 1; | |
| 2262 | 2323 | } |
| 2263 | if (token_tags[tok_i] == .colon and | |
| 2264 | token_tags[tok_i -| 1] == .identifier) | |
| 2265 | { | |
| 2266 | result.label_token = tok_i - 1; | |
| 2324 | if (tree.isTokenPrecededByTags(tok_i, &.{ .identifier, .colon })) { | |
| 2325 | result.label_token = tok_i - 2; | |
| 2267 | 2326 | } |
| 2268 | 2327 | const last_cond_token = tree.lastToken(info.inputs[info.inputs.len - 1]); |
| 2269 | result.payload_token = last_cond_token + 3 + @intFromBool(token_tags[last_cond_token + 1] == .comma); | |
| 2270 | if (info.else_expr != 0) { | |
| 2328 | result.payload_token = last_cond_token + @as(u32, 3) + @intFromBool(tree.tokenTag(last_cond_token + 1) == .comma); | |
| 2329 | if (info.else_expr != .none) { | |
| 2271 | 2330 | result.else_token = tree.lastToken(info.then_expr) + 1; |
| 2272 | 2331 | } |
| 2273 | 2332 | return result; |
| 2274 | 2333 | } |
| 2275 | 2334 | |
| 2276 | 2335 | fn fullCallComponents(tree: Ast, info: full.Call.Components) full.Call { |
| 2277 | const token_tags = tree.tokens.items(.tag); | |
| 2278 | 2336 | var result: full.Call = .{ |
| 2279 | 2337 | .ast = info, |
| 2280 | 2338 | .async_token = null, |
| 2281 | 2339 | }; |
| 2282 | 2340 | const first_token = tree.firstToken(info.fn_expr); |
| 2283 | if (first_token != 0 and token_tags[first_token - 1] == .keyword_async) { | |
| 2341 | if (tree.isTokenPrecededByTags(first_token, &.{.keyword_async})) { | |
| 2284 | 2342 | result.async_token = first_token - 1; |
| 2285 | 2343 | } |
| 2286 | 2344 | return result; |
| 2287 | 2345 | } |
| 2288 | 2346 | |
| 2289 | 2347 | pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl { |
| 2290 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2348 | return switch (tree.nodeTag(node)) { | |
| 2291 | 2349 | .global_var_decl => tree.globalVarDecl(node), |
| 2292 | 2350 | .local_var_decl => tree.localVarDecl(node), |
| 2293 | 2351 | .aligned_var_decl => tree.alignedVarDecl(node), |
| ... | ... | @@ -2297,7 +2355,7 @@ pub fn fullVarDecl(tree: Ast, node: Node.Index) ?full.VarDecl { |
| 2297 | 2355 | } |
| 2298 | 2356 | |
| 2299 | 2357 | pub fn fullIf(tree: Ast, node: Node.Index) ?full.If { |
| 2300 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2358 | return switch (tree.nodeTag(node)) { | |
| 2301 | 2359 | .if_simple => tree.ifSimple(node), |
| 2302 | 2360 | .@"if" => tree.ifFull(node), |
| 2303 | 2361 | else => null, |
| ... | ... | @@ -2305,7 +2363,7 @@ pub fn fullIf(tree: Ast, node: Node.Index) ?full.If { |
| 2305 | 2363 | } |
| 2306 | 2364 | |
| 2307 | 2365 | pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While { |
| 2308 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2366 | return switch (tree.nodeTag(node)) { | |
| 2309 | 2367 | .while_simple => tree.whileSimple(node), |
| 2310 | 2368 | .while_cont => tree.whileCont(node), |
| 2311 | 2369 | .@"while" => tree.whileFull(node), |
| ... | ... | @@ -2314,7 +2372,7 @@ pub fn fullWhile(tree: Ast, node: Node.Index) ?full.While { |
| 2314 | 2372 | } |
| 2315 | 2373 | |
| 2316 | 2374 | pub fn fullFor(tree: Ast, node: Node.Index) ?full.For { |
| 2317 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2375 | return switch (tree.nodeTag(node)) { | |
| 2318 | 2376 | .for_simple => tree.forSimple(node), |
| 2319 | 2377 | .@"for" => tree.forFull(node), |
| 2320 | 2378 | else => null, |
| ... | ... | @@ -2322,7 +2380,7 @@ pub fn fullFor(tree: Ast, node: Node.Index) ?full.For { |
| 2322 | 2380 | } |
| 2323 | 2381 | |
| 2324 | 2382 | pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField { |
| 2325 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2383 | return switch (tree.nodeTag(node)) { | |
| 2326 | 2384 | .container_field_init => tree.containerFieldInit(node), |
| 2327 | 2385 | .container_field_align => tree.containerFieldAlign(node), |
| 2328 | 2386 | .container_field => tree.containerField(node), |
| ... | ... | @@ -2331,18 +2389,18 @@ pub fn fullContainerField(tree: Ast, node: Node.Index) ?full.ContainerField { |
| 2331 | 2389 | } |
| 2332 | 2390 | |
| 2333 | 2391 | pub fn fullFnProto(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.FnProto { |
| 2334 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2392 | return switch (tree.nodeTag(node)) { | |
| 2335 | 2393 | .fn_proto => tree.fnProto(node), |
| 2336 | 2394 | .fn_proto_multi => tree.fnProtoMulti(node), |
| 2337 | 2395 | .fn_proto_one => tree.fnProtoOne(buffer, node), |
| 2338 | 2396 | .fn_proto_simple => tree.fnProtoSimple(buffer, node), |
| 2339 | .fn_decl => tree.fullFnProto(buffer, tree.nodes.items(.data)[node].lhs), | |
| 2397 | .fn_decl => tree.fullFnProto(buffer, tree.nodeData(node).node_and_node[0]), | |
| 2340 | 2398 | else => null, |
| 2341 | 2399 | }; |
| 2342 | 2400 | } |
| 2343 | 2401 | |
| 2344 | 2402 | pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.StructInit { |
| 2345 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2403 | return switch (tree.nodeTag(node)) { | |
| 2346 | 2404 | .struct_init_one, .struct_init_one_comma => tree.structInitOne(buffer[0..1], node), |
| 2347 | 2405 | .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(buffer, node), |
| 2348 | 2406 | .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node), |
| ... | ... | @@ -2352,7 +2410,7 @@ pub fn fullStructInit(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ? |
| 2352 | 2410 | } |
| 2353 | 2411 | |
| 2354 | 2412 | pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full.ArrayInit { |
| 2355 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2413 | return switch (tree.nodeTag(node)) { | |
| 2356 | 2414 | .array_init_one, .array_init_one_comma => tree.arrayInitOne(buffer[0..1], node), |
| 2357 | 2415 | .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(buffer, node), |
| 2358 | 2416 | .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(node), |
| ... | ... | @@ -2362,7 +2420,7 @@ pub fn fullArrayInit(tree: Ast, buffer: *[2]Node.Index, node: Node.Index) ?full. |
| 2362 | 2420 | } |
| 2363 | 2421 | |
| 2364 | 2422 | pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType { |
| 2365 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2423 | return switch (tree.nodeTag(node)) { | |
| 2366 | 2424 | .array_type => tree.arrayType(node), |
| 2367 | 2425 | .array_type_sentinel => tree.arrayTypeSentinel(node), |
| 2368 | 2426 | else => null, |
| ... | ... | @@ -2370,7 +2428,7 @@ pub fn fullArrayType(tree: Ast, node: Node.Index) ?full.ArrayType { |
| 2370 | 2428 | } |
| 2371 | 2429 | |
| 2372 | 2430 | pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType { |
| 2373 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2431 | return switch (tree.nodeTag(node)) { | |
| 2374 | 2432 | .ptr_type_aligned => tree.ptrTypeAligned(node), |
| 2375 | 2433 | .ptr_type_sentinel => tree.ptrTypeSentinel(node), |
| 2376 | 2434 | .ptr_type => tree.ptrType(node), |
| ... | ... | @@ -2380,7 +2438,7 @@ pub fn fullPtrType(tree: Ast, node: Node.Index) ?full.PtrType { |
| 2380 | 2438 | } |
| 2381 | 2439 | |
| 2382 | 2440 | pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice { |
| 2383 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2441 | return switch (tree.nodeTag(node)) { | |
| 2384 | 2442 | .slice_open => tree.sliceOpen(node), |
| 2385 | 2443 | .slice => tree.slice(node), |
| 2386 | 2444 | .slice_sentinel => tree.sliceSentinel(node), |
| ... | ... | @@ -2389,7 +2447,7 @@ pub fn fullSlice(tree: Ast, node: Node.Index) ?full.Slice { |
| 2389 | 2447 | } |
| 2390 | 2448 | |
| 2391 | 2449 | pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index) ?full.ContainerDecl { |
| 2392 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2450 | return switch (tree.nodeTag(node)) { | |
| 2393 | 2451 | .root => tree.containerDeclRoot(), |
| 2394 | 2452 | .container_decl, .container_decl_trailing => tree.containerDecl(node), |
| 2395 | 2453 | .container_decl_arg, .container_decl_arg_trailing => tree.containerDeclArg(node), |
| ... | ... | @@ -2402,14 +2460,14 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index |
| 2402 | 2460 | } |
| 2403 | 2461 | |
| 2404 | 2462 | pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch { |
| 2405 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2463 | return switch (tree.nodeTag(node)) { | |
| 2406 | 2464 | .@"switch", .switch_comma => tree.switchFull(node), |
| 2407 | 2465 | else => null, |
| 2408 | 2466 | }; |
| 2409 | 2467 | } |
| 2410 | 2468 | |
| 2411 | 2469 | pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase { |
| 2412 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2470 | return switch (tree.nodeTag(node)) { | |
| 2413 | 2471 | .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node), |
| 2414 | 2472 | .switch_case, .switch_case_inline => tree.switchCase(node), |
| 2415 | 2473 | else => null, |
| ... | ... | @@ -2417,7 +2475,7 @@ pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase { |
| 2417 | 2475 | } |
| 2418 | 2476 | |
| 2419 | 2477 | pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { |
| 2420 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2478 | return switch (tree.nodeTag(node)) { | |
| 2421 | 2479 | .asm_simple => tree.asmSimple(node), |
| 2422 | 2480 | .@"asm" => tree.asmFull(node), |
| 2423 | 2481 | else => null, |
| ... | ... | @@ -2425,7 +2483,7 @@ pub fn fullAsm(tree: Ast, node: Node.Index) ?full.Asm { |
| 2425 | 2483 | } |
| 2426 | 2484 | |
| 2427 | 2485 | pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.Call { |
| 2428 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2486 | return switch (tree.nodeTag(node)) { | |
| 2429 | 2487 | .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node), |
| 2430 | 2488 | .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(buffer, node), |
| 2431 | 2489 | else => null, |
| ... | ... | @@ -2433,37 +2491,17 @@ pub fn fullCall(tree: Ast, buffer: *[1]Ast.Node.Index, node: Node.Index) ?full.C |
| 2433 | 2491 | } |
| 2434 | 2492 | |
| 2435 | 2493 | pub fn builtinCallParams(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index { |
| 2436 | const data = tree.nodes.items(.data)[node]; | |
| 2437 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2438 | .builtin_call_two, .builtin_call_two_comma => { | |
| 2439 | buffer.* = .{ data.lhs, data.rhs }; | |
| 2440 | if (data.rhs != 0) { | |
| 2441 | return buffer[0..2]; | |
| 2442 | } else if (data.lhs != 0) { | |
| 2443 | return buffer[0..1]; | |
| 2444 | } else { | |
| 2445 | return buffer[0..0]; | |
| 2446 | } | |
| 2447 | }, | |
| 2448 | .builtin_call, .builtin_call_comma => tree.extra_data[data.lhs..data.rhs], | |
| 2494 | return switch (tree.nodeTag(node)) { | |
| 2495 | .builtin_call_two, .builtin_call_two_comma => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node), | |
| 2496 | .builtin_call, .builtin_call_comma => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index), | |
| 2449 | 2497 | else => null, |
| 2450 | 2498 | }; |
| 2451 | 2499 | } |
| 2452 | 2500 | |
| 2453 | 2501 | pub fn blockStatements(tree: Ast, buffer: *[2]Ast.Node.Index, node: Ast.Node.Index) ?[]const Node.Index { |
| 2454 | const data = tree.nodes.items(.data)[node]; | |
| 2455 | return switch (tree.nodes.items(.tag)[node]) { | |
| 2456 | .block_two, .block_two_semicolon => { | |
| 2457 | buffer.* = .{ data.lhs, data.rhs }; | |
| 2458 | if (data.rhs != 0) { | |
| 2459 | return buffer[0..2]; | |
| 2460 | } else if (data.lhs != 0) { | |
| 2461 | return buffer[0..1]; | |
| 2462 | } else { | |
| 2463 | return buffer[0..0]; | |
| 2464 | } | |
| 2465 | }, | |
| 2466 | .block, .block_semicolon => tree.extra_data[data.lhs..data.rhs], | |
| 2502 | return switch (tree.nodeTag(node)) { | |
| 2503 | .block_two, .block_two_semicolon => loadOptionalNodesIntoBuffer(2, buffer, tree.nodeData(node).opt_node_and_opt_node), | |
| 2504 | .block, .block_semicolon => tree.extraDataSlice(tree.nodeData(node).extra_range, Node.Index), | |
| 2467 | 2505 | else => null, |
| 2468 | 2506 | }; |
| 2469 | 2507 | } |
| ... | ... | @@ -2480,11 +2518,11 @@ pub const full = struct { |
| 2480 | 2518 | |
| 2481 | 2519 | pub const Components = struct { |
| 2482 | 2520 | mut_token: TokenIndex, |
| 2483 | type_node: Node.Index, | |
| 2484 | align_node: Node.Index, | |
| 2485 | addrspace_node: Node.Index, | |
| 2486 | section_node: Node.Index, | |
| 2487 | init_node: Node.Index, | |
| 2521 | type_node: Node.OptionalIndex, | |
| 2522 | align_node: Node.OptionalIndex, | |
| 2523 | addrspace_node: Node.OptionalIndex, | |
| 2524 | section_node: Node.OptionalIndex, | |
| 2525 | init_node: Node.OptionalIndex, | |
| 2488 | 2526 | }; |
| 2489 | 2527 | |
| 2490 | 2528 | pub fn firstToken(var_decl: VarDecl) TokenIndex { |
| ... | ... | @@ -2513,7 +2551,7 @@ pub const full = struct { |
| 2513 | 2551 | payload_token: ?TokenIndex, |
| 2514 | 2552 | /// Points to the identifier after the `|`. |
| 2515 | 2553 | error_token: ?TokenIndex, |
| 2516 | /// Populated only if else_expr != 0. | |
| 2554 | /// Populated only if else_expr != .none. | |
| 2517 | 2555 | else_token: TokenIndex, |
| 2518 | 2556 | ast: Components, |
| 2519 | 2557 | |
| ... | ... | @@ -2521,7 +2559,7 @@ pub const full = struct { |
| 2521 | 2559 | if_token: TokenIndex, |
| 2522 | 2560 | cond_expr: Node.Index, |
| 2523 | 2561 | then_expr: Node.Index, |
| 2524 | else_expr: Node.Index, | |
| 2562 | else_expr: Node.OptionalIndex, | |
| 2525 | 2563 | }; |
| 2526 | 2564 | }; |
| 2527 | 2565 | |
| ... | ... | @@ -2531,15 +2569,15 @@ pub const full = struct { |
| 2531 | 2569 | label_token: ?TokenIndex, |
| 2532 | 2570 | payload_token: ?TokenIndex, |
| 2533 | 2571 | error_token: ?TokenIndex, |
| 2534 | /// Populated only if else_expr != 0. | |
| 2572 | /// Populated only if else_expr != none. | |
| 2535 | 2573 | else_token: TokenIndex, |
| 2536 | 2574 | |
| 2537 | 2575 | pub const Components = struct { |
| 2538 | 2576 | while_token: TokenIndex, |
| 2539 | 2577 | cond_expr: Node.Index, |
| 2540 | cont_expr: Node.Index, | |
| 2578 | cont_expr: Node.OptionalIndex, | |
| 2541 | 2579 | then_expr: Node.Index, |
| 2542 | else_expr: Node.Index, | |
| 2580 | else_expr: Node.OptionalIndex, | |
| 2543 | 2581 | }; |
| 2544 | 2582 | }; |
| 2545 | 2583 | |
| ... | ... | @@ -2548,14 +2586,14 @@ pub const full = struct { |
| 2548 | 2586 | inline_token: ?TokenIndex, |
| 2549 | 2587 | label_token: ?TokenIndex, |
| 2550 | 2588 | payload_token: TokenIndex, |
| 2551 | /// Populated only if else_expr != 0. | |
| 2552 | else_token: TokenIndex, | |
| 2589 | /// Populated only if else_expr != .none. | |
| 2590 | else_token: ?TokenIndex, | |
| 2553 | 2591 | |
| 2554 | 2592 | pub const Components = struct { |
| 2555 | 2593 | for_token: TokenIndex, |
| 2556 | 2594 | inputs: []const Node.Index, |
| 2557 | 2595 | then_expr: Node.Index, |
| 2558 | else_expr: Node.Index, | |
| 2596 | else_expr: Node.OptionalIndex, | |
| 2559 | 2597 | }; |
| 2560 | 2598 | }; |
| 2561 | 2599 | |
| ... | ... | @@ -2565,9 +2603,10 @@ pub const full = struct { |
| 2565 | 2603 | |
| 2566 | 2604 | pub const Components = struct { |
| 2567 | 2605 | main_token: TokenIndex, |
| 2568 | type_expr: Node.Index, | |
| 2569 | align_expr: Node.Index, | |
| 2570 | value_expr: Node.Index, | |
| 2606 | /// Can only be `.none` after calling `convertToNonTupleLike`. | |
| 2607 | type_expr: Node.OptionalIndex, | |
| 2608 | align_expr: Node.OptionalIndex, | |
| 2609 | value_expr: Node.OptionalIndex, | |
| 2571 | 2610 | tuple_like: bool, |
| 2572 | 2611 | }; |
| 2573 | 2612 | |
| ... | ... | @@ -2575,11 +2614,11 @@ pub const full = struct { |
| 2575 | 2614 | return cf.comptime_token orelse cf.ast.main_token; |
| 2576 | 2615 | } |
| 2577 | 2616 | |
| 2578 | pub fn convertToNonTupleLike(cf: *ContainerField, nodes: NodeList.Slice) void { | |
| 2617 | pub fn convertToNonTupleLike(cf: *ContainerField, tree: *const Ast) void { | |
| 2579 | 2618 | if (!cf.ast.tuple_like) return; |
| 2580 | if (nodes.items(.tag)[cf.ast.type_expr] != .identifier) return; | |
| 2619 | if (tree.nodeTag(cf.ast.type_expr.unwrap().?) != .identifier) return; | |
| 2581 | 2620 | |
| 2582 | cf.ast.type_expr = 0; | |
| 2621 | cf.ast.type_expr = .none; | |
| 2583 | 2622 | cf.ast.tuple_like = false; |
| 2584 | 2623 | } |
| 2585 | 2624 | }; |
| ... | ... | @@ -2595,12 +2634,12 @@ pub const full = struct { |
| 2595 | 2634 | pub const Components = struct { |
| 2596 | 2635 | proto_node: Node.Index, |
| 2597 | 2636 | fn_token: TokenIndex, |
| 2598 | return_type: Node.Index, | |
| 2637 | return_type: Node.OptionalIndex, | |
| 2599 | 2638 | params: []const Node.Index, |
| 2600 | align_expr: Node.Index, | |
| 2601 | addrspace_expr: Node.Index, | |
| 2602 | section_expr: Node.Index, | |
| 2603 | callconv_expr: Node.Index, | |
| 2639 | align_expr: Node.OptionalIndex, | |
| 2640 | addrspace_expr: Node.OptionalIndex, | |
| 2641 | section_expr: Node.OptionalIndex, | |
| 2642 | callconv_expr: Node.OptionalIndex, | |
| 2604 | 2643 | }; |
| 2605 | 2644 | |
| 2606 | 2645 | pub const Param = struct { |
| ... | ... | @@ -2608,7 +2647,7 @@ pub const full = struct { |
| 2608 | 2647 | name_token: ?TokenIndex, |
| 2609 | 2648 | comptime_noalias: ?TokenIndex, |
| 2610 | 2649 | anytype_ellipsis3: ?TokenIndex, |
| 2611 | type_expr: Node.Index, | |
| 2650 | type_expr: ?Node.Index, | |
| 2612 | 2651 | }; |
| 2613 | 2652 | |
| 2614 | 2653 | pub fn firstToken(fn_proto: FnProto) TokenIndex { |
| ... | ... | @@ -2628,7 +2667,7 @@ pub const full = struct { |
| 2628 | 2667 | tok_flag: bool, |
| 2629 | 2668 | |
| 2630 | 2669 | pub fn next(it: *Iterator) ?Param { |
| 2631 | const token_tags = it.tree.tokens.items(.tag); | |
| 2670 | const tree = it.tree; | |
| 2632 | 2671 | while (true) { |
| 2633 | 2672 | var first_doc_comment: ?TokenIndex = null; |
| 2634 | 2673 | var comptime_noalias: ?TokenIndex = null; |
| ... | ... | @@ -2638,8 +2677,8 @@ pub const full = struct { |
| 2638 | 2677 | return null; |
| 2639 | 2678 | } |
| 2640 | 2679 | const param_type = it.fn_proto.ast.params[it.param_i]; |
| 2641 | var tok_i = it.tree.firstToken(param_type) - 1; | |
| 2642 | while (true) : (tok_i -= 1) switch (token_tags[tok_i]) { | |
| 2680 | var tok_i = tree.firstToken(param_type) - 1; | |
| 2681 | while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) { | |
| 2643 | 2682 | .colon => continue, |
| 2644 | 2683 | .identifier => name_token = tok_i, |
| 2645 | 2684 | .doc_comment => first_doc_comment = tok_i, |
| ... | ... | @@ -2647,9 +2686,9 @@ pub const full = struct { |
| 2647 | 2686 | else => break, |
| 2648 | 2687 | }; |
| 2649 | 2688 | it.param_i += 1; |
| 2650 | it.tok_i = it.tree.lastToken(param_type) + 1; | |
| 2689 | it.tok_i = tree.lastToken(param_type) + 1; | |
| 2651 | 2690 | // Look for anytype and ... params afterwards. |
| 2652 | if (token_tags[it.tok_i] == .comma) { | |
| 2691 | if (tree.tokenTag(it.tok_i) == .comma) { | |
| 2653 | 2692 | it.tok_i += 1; |
| 2654 | 2693 | } |
| 2655 | 2694 | it.tok_flag = true; |
| ... | ... | @@ -2661,19 +2700,19 @@ pub const full = struct { |
| 2661 | 2700 | .type_expr = param_type, |
| 2662 | 2701 | }; |
| 2663 | 2702 | } |
| 2664 | if (token_tags[it.tok_i] == .comma) { | |
| 2703 | if (tree.tokenTag(it.tok_i) == .comma) { | |
| 2665 | 2704 | it.tok_i += 1; |
| 2666 | 2705 | } |
| 2667 | if (token_tags[it.tok_i] == .r_paren) { | |
| 2706 | if (tree.tokenTag(it.tok_i) == .r_paren) { | |
| 2668 | 2707 | return null; |
| 2669 | 2708 | } |
| 2670 | if (token_tags[it.tok_i] == .doc_comment) { | |
| 2709 | if (tree.tokenTag(it.tok_i) == .doc_comment) { | |
| 2671 | 2710 | first_doc_comment = it.tok_i; |
| 2672 | while (token_tags[it.tok_i] == .doc_comment) { | |
| 2711 | while (tree.tokenTag(it.tok_i) == .doc_comment) { | |
| 2673 | 2712 | it.tok_i += 1; |
| 2674 | 2713 | } |
| 2675 | 2714 | } |
| 2676 | switch (token_tags[it.tok_i]) { | |
| 2715 | switch (tree.tokenTag(it.tok_i)) { | |
| 2677 | 2716 | .ellipsis3 => { |
| 2678 | 2717 | it.tok_flag = false; // Next iteration should return null. |
| 2679 | 2718 | return Param{ |
| ... | ... | @@ -2681,7 +2720,7 @@ pub const full = struct { |
| 2681 | 2720 | .comptime_noalias = null, |
| 2682 | 2721 | .name_token = null, |
| 2683 | 2722 | .anytype_ellipsis3 = it.tok_i, |
| 2684 | .type_expr = 0, | |
| 2723 | .type_expr = null, | |
| 2685 | 2724 | }; |
| 2686 | 2725 | }, |
| 2687 | 2726 | .keyword_noalias, .keyword_comptime => { |
| ... | ... | @@ -2690,20 +2729,20 @@ pub const full = struct { |
| 2690 | 2729 | }, |
| 2691 | 2730 | else => {}, |
| 2692 | 2731 | } |
| 2693 | if (token_tags[it.tok_i] == .identifier and | |
| 2694 | token_tags[it.tok_i + 1] == .colon) | |
| 2732 | if (tree.tokenTag(it.tok_i) == .identifier and | |
| 2733 | tree.tokenTag(it.tok_i + 1) == .colon) | |
| 2695 | 2734 | { |
| 2696 | 2735 | name_token = it.tok_i; |
| 2697 | 2736 | it.tok_i += 2; |
| 2698 | 2737 | } |
| 2699 | if (token_tags[it.tok_i] == .keyword_anytype) { | |
| 2738 | if (tree.tokenTag(it.tok_i) == .keyword_anytype) { | |
| 2700 | 2739 | it.tok_i += 1; |
| 2701 | 2740 | return Param{ |
| 2702 | 2741 | .first_doc_comment = first_doc_comment, |
| 2703 | 2742 | .comptime_noalias = comptime_noalias, |
| 2704 | 2743 | .name_token = name_token, |
| 2705 | 2744 | .anytype_ellipsis3 = it.tok_i - 1, |
| 2706 | .type_expr = 0, | |
| 2745 | .type_expr = null, | |
| 2707 | 2746 | }; |
| 2708 | 2747 | } |
| 2709 | 2748 | it.tok_flag = false; |
| ... | ... | @@ -2728,7 +2767,7 @@ pub const full = struct { |
| 2728 | 2767 | pub const Components = struct { |
| 2729 | 2768 | lbrace: TokenIndex, |
| 2730 | 2769 | fields: []const Node.Index, |
| 2731 | type_expr: Node.Index, | |
| 2770 | type_expr: Node.OptionalIndex, | |
| 2732 | 2771 | }; |
| 2733 | 2772 | }; |
| 2734 | 2773 | |
| ... | ... | @@ -2738,7 +2777,7 @@ pub const full = struct { |
| 2738 | 2777 | pub const Components = struct { |
| 2739 | 2778 | lbrace: TokenIndex, |
| 2740 | 2779 | elements: []const Node.Index, |
| 2741 | type_expr: Node.Index, | |
| 2780 | type_expr: Node.OptionalIndex, | |
| 2742 | 2781 | }; |
| 2743 | 2782 | }; |
| 2744 | 2783 | |
| ... | ... | @@ -2748,7 +2787,7 @@ pub const full = struct { |
| 2748 | 2787 | pub const Components = struct { |
| 2749 | 2788 | lbracket: TokenIndex, |
| 2750 | 2789 | elem_count: Node.Index, |
| 2751 | sentinel: Node.Index, | |
| 2790 | sentinel: Node.OptionalIndex, | |
| 2752 | 2791 | elem_type: Node.Index, |
| 2753 | 2792 | }; |
| 2754 | 2793 | }; |
| ... | ... | @@ -2762,11 +2801,11 @@ pub const full = struct { |
| 2762 | 2801 | |
| 2763 | 2802 | pub const Components = struct { |
| 2764 | 2803 | main_token: TokenIndex, |
| 2765 | align_node: Node.Index, | |
| 2766 | addrspace_node: Node.Index, | |
| 2767 | sentinel: Node.Index, | |
| 2768 | bit_range_start: Node.Index, | |
| 2769 | bit_range_end: Node.Index, | |
| 2804 | align_node: Node.OptionalIndex, | |
| 2805 | addrspace_node: Node.OptionalIndex, | |
| 2806 | sentinel: Node.OptionalIndex, | |
| 2807 | bit_range_start: Node.OptionalIndex, | |
| 2808 | bit_range_end: Node.OptionalIndex, | |
| 2770 | 2809 | child_type: Node.Index, |
| 2771 | 2810 | }; |
| 2772 | 2811 | }; |
| ... | ... | @@ -2778,8 +2817,8 @@ pub const full = struct { |
| 2778 | 2817 | sliced: Node.Index, |
| 2779 | 2818 | lbracket: TokenIndex, |
| 2780 | 2819 | start: Node.Index, |
| 2781 | end: Node.Index, | |
| 2782 | sentinel: Node.Index, | |
| 2820 | end: Node.OptionalIndex, | |
| 2821 | sentinel: Node.OptionalIndex, | |
| 2783 | 2822 | }; |
| 2784 | 2823 | }; |
| 2785 | 2824 | |
| ... | ... | @@ -2792,7 +2831,7 @@ pub const full = struct { |
| 2792 | 2831 | /// Populated when main_token is Keyword_union. |
| 2793 | 2832 | enum_token: ?TokenIndex, |
| 2794 | 2833 | members: []const Node.Index, |
| 2795 | arg: Node.Index, | |
| 2834 | arg: Node.OptionalIndex, | |
| 2796 | 2835 | }; |
| 2797 | 2836 | }; |
| 2798 | 2837 | |
| ... | ... | @@ -2935,16 +2974,82 @@ pub const Error = struct { |
| 2935 | 2974 | }; |
| 2936 | 2975 | }; |
| 2937 | 2976 | |
| 2977 | /// Index into `extra_data`. | |
| 2978 | pub const ExtraIndex = enum(u32) { | |
| 2979 | _, | |
| 2980 | }; | |
| 2981 | ||
| 2938 | 2982 | pub const Node = struct { |
| 2939 | 2983 | tag: Tag, |
| 2940 | 2984 | main_token: TokenIndex, |
| 2941 | 2985 | data: Data, |
| 2942 | 2986 | |
| 2943 | pub const Index = u32; | |
| 2987 | /// Index into `nodes`. | |
| 2988 | pub const Index = enum(u32) { | |
| 2989 | root = 0, | |
| 2990 | _, | |
| 2991 | ||
| 2992 | pub fn toOptional(i: Index) OptionalIndex { | |
| 2993 | const result: OptionalIndex = @enumFromInt(@intFromEnum(i)); | |
| 2994 | assert(result != .none); | |
| 2995 | return result; | |
| 2996 | } | |
| 2997 | ||
| 2998 | pub fn toOffset(base: Index, destination: Index) Offset { | |
| 2999 | const base_i64: i64 = @intFromEnum(base); | |
| 3000 | const destination_i64: i64 = @intFromEnum(destination); | |
| 3001 | return @enumFromInt(destination_i64 - base_i64); | |
| 3002 | } | |
| 3003 | }; | |
| 3004 | ||
| 3005 | /// Index into `nodes`, or null. | |
| 3006 | pub const OptionalIndex = enum(u32) { | |
| 3007 | root = 0, | |
| 3008 | none = std.math.maxInt(u32), | |
| 3009 | _, | |
| 3010 | ||
| 3011 | pub fn unwrap(oi: OptionalIndex) ?Index { | |
| 3012 | return if (oi == .none) null else @enumFromInt(@intFromEnum(oi)); | |
| 3013 | } | |
| 3014 | ||
| 3015 | pub fn fromOptional(oi: ?Index) OptionalIndex { | |
| 3016 | return if (oi) |i| i.toOptional() else .none; | |
| 3017 | } | |
| 3018 | }; | |
| 3019 | ||
| 3020 | /// A relative node index. | |
| 3021 | pub const Offset = enum(i32) { | |
| 3022 | zero = 0, | |
| 3023 | _, | |
| 3024 | ||
| 3025 | pub fn toOptional(o: Offset) OptionalOffset { | |
| 3026 | const result: OptionalOffset = @enumFromInt(@intFromEnum(o)); | |
| 3027 | assert(result != .none); | |
| 3028 | return result; | |
| 3029 | } | |
| 3030 | ||
| 3031 | pub fn toAbsolute(offset: Offset, base: Index) Index { | |
| 3032 | return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset)); | |
| 3033 | } | |
| 3034 | }; | |
| 3035 | ||
| 3036 | /// A relative node index, or null. | |
| 3037 | pub const OptionalOffset = enum(i32) { | |
| 3038 | none = std.math.maxInt(i32), | |
| 3039 | _, | |
| 3040 | ||
| 3041 | pub fn unwrap(oo: OptionalOffset) ?Offset { | |
| 3042 | return if (oo == .none) null else @enumFromInt(@intFromEnum(oo)); | |
| 3043 | } | |
| 3044 | }; | |
| 2944 | 3045 | |
| 2945 | 3046 | comptime { |
| 2946 | 3047 | // Goal is to keep this under one byte for efficiency. |
| 2947 | 3048 | assert(@sizeOf(Tag) == 1); |
| 3049 | ||
| 3050 | if (!std.debug.runtime_safety) { | |
| 3051 | assert(@sizeOf(Data) == 8); | |
| 3052 | } | |
| 2948 | 3053 | } |
| 2949 | 3054 | |
| 2950 | 3055 | /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of |
| ... | ... | @@ -3435,9 +3540,26 @@ pub const Node = struct { |
| 3435 | 3540 | } |
| 3436 | 3541 | }; |
| 3437 | 3542 | |
| 3438 | pub const Data = struct { | |
| 3439 | lhs: Index, | |
| 3440 | rhs: Index, | |
| 3543 | pub const Data = union { | |
| 3544 | node: Index, | |
| 3545 | opt_node: OptionalIndex, | |
| 3546 | token: TokenIndex, | |
| 3547 | node_and_node: struct { Index, Index }, | |
| 3548 | opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex }, | |
| 3549 | node_and_opt_node: struct { Index, OptionalIndex }, | |
| 3550 | opt_node_and_node: struct { OptionalIndex, Index }, | |
| 3551 | node_and_extra: struct { Index, ExtraIndex }, | |
| 3552 | extra_and_node: struct { ExtraIndex, Index }, | |
| 3553 | extra_and_opt_node: struct { ExtraIndex, OptionalIndex }, | |
| 3554 | node_and_token: struct { Index, TokenIndex }, | |
| 3555 | token_and_node: struct { TokenIndex, Index }, | |
| 3556 | token_and_token: struct { TokenIndex, TokenIndex }, | |
| 3557 | opt_node_and_token: struct { OptionalIndex, TokenIndex }, | |
| 3558 | opt_token_and_node: struct { OptionalTokenIndex, Index }, | |
| 3559 | opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex }, | |
| 3560 | opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex }, | |
| 3561 | @"for": struct { ExtraIndex, For }, | |
| 3562 | extra_range: SubRange, | |
| 3441 | 3563 | }; |
| 3442 | 3564 | |
| 3443 | 3565 | pub const LocalVarDecl = struct { |
| ... | ... | @@ -3451,24 +3573,24 @@ pub const Node = struct { |
| 3451 | 3573 | }; |
| 3452 | 3574 | |
| 3453 | 3575 | pub const PtrType = struct { |
| 3454 | sentinel: Index, | |
| 3455 | align_node: Index, | |
| 3456 | addrspace_node: Index, | |
| 3576 | sentinel: OptionalIndex, | |
| 3577 | align_node: OptionalIndex, | |
| 3578 | addrspace_node: OptionalIndex, | |
| 3457 | 3579 | }; |
| 3458 | 3580 | |
| 3459 | 3581 | pub const PtrTypeBitRange = struct { |
| 3460 | sentinel: Index, | |
| 3582 | sentinel: OptionalIndex, | |
| 3461 | 3583 | align_node: Index, |
| 3462 | addrspace_node: Index, | |
| 3584 | addrspace_node: OptionalIndex, | |
| 3463 | 3585 | bit_range_start: Index, |
| 3464 | 3586 | bit_range_end: Index, |
| 3465 | 3587 | }; |
| 3466 | 3588 | |
| 3467 | 3589 | pub const SubRange = struct { |
| 3468 | /// Index into sub_list. | |
| 3469 | start: Index, | |
| 3470 | /// Index into sub_list. | |
| 3471 | end: Index, | |
| 3590 | /// Index into extra_data. | |
| 3591 | start: ExtraIndex, | |
| 3592 | /// Index into extra_data. | |
| 3593 | end: ExtraIndex, | |
| 3472 | 3594 | }; |
| 3473 | 3595 | |
| 3474 | 3596 | pub const If = struct { |
| ... | ... | @@ -3483,13 +3605,13 @@ pub const Node = struct { |
| 3483 | 3605 | |
| 3484 | 3606 | pub const GlobalVarDecl = struct { |
| 3485 | 3607 | /// Populated if there is an explicit type ascription. |
| 3486 | type_node: Index, | |
| 3608 | type_node: OptionalIndex, | |
| 3487 | 3609 | /// Populated if align(A) is present. |
| 3488 | align_node: Index, | |
| 3610 | align_node: OptionalIndex, | |
| 3489 | 3611 | /// Populated if addrspace(A) is present. |
| 3490 | addrspace_node: Index, | |
| 3612 | addrspace_node: OptionalIndex, | |
| 3491 | 3613 | /// Populated if linksection(A) is present. |
| 3492 | section_node: Index, | |
| 3614 | section_node: OptionalIndex, | |
| 3493 | 3615 | }; |
| 3494 | 3616 | |
| 3495 | 3617 | pub const Slice = struct { |
| ... | ... | @@ -3499,13 +3621,13 @@ pub const Node = struct { |
| 3499 | 3621 | |
| 3500 | 3622 | pub const SliceSentinel = struct { |
| 3501 | 3623 | start: Index, |
| 3502 | /// May be 0 if the slice is "open" | |
| 3503 | end: Index, | |
| 3624 | /// May be .none if the slice is "open" | |
| 3625 | end: OptionalIndex, | |
| 3504 | 3626 | sentinel: Index, |
| 3505 | 3627 | }; |
| 3506 | 3628 | |
| 3507 | 3629 | pub const While = struct { |
| 3508 | cont_expr: Index, | |
| 3630 | cont_expr: OptionalIndex, | |
| 3509 | 3631 | then_expr: Index, |
| 3510 | 3632 | else_expr: Index, |
| 3511 | 3633 | }; |
| ... | ... | @@ -3522,44 +3644,44 @@ pub const Node = struct { |
| 3522 | 3644 | |
| 3523 | 3645 | pub const FnProtoOne = struct { |
| 3524 | 3646 | /// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters. |
| 3525 | param: Index, | |
| 3647 | param: OptionalIndex, | |
| 3526 | 3648 | /// Populated if align(A) is present. |
| 3527 | align_expr: Index, | |
| 3649 | align_expr: OptionalIndex, | |
| 3528 | 3650 | /// Populated if addrspace(A) is present. |
| 3529 | addrspace_expr: Index, | |
| 3651 | addrspace_expr: OptionalIndex, | |
| 3530 | 3652 | /// Populated if linksection(A) is present. |
| 3531 | section_expr: Index, | |
| 3653 | section_expr: OptionalIndex, | |
| 3532 | 3654 | /// Populated if callconv(A) is present. |
| 3533 | callconv_expr: Index, | |
| 3655 | callconv_expr: OptionalIndex, | |
| 3534 | 3656 | }; |
| 3535 | 3657 | |
| 3536 | 3658 | pub const FnProto = struct { |
| 3537 | params_start: Index, | |
| 3538 | params_end: Index, | |
| 3659 | params_start: ExtraIndex, | |
| 3660 | params_end: ExtraIndex, | |
| 3539 | 3661 | /// Populated if align(A) is present. |
| 3540 | align_expr: Index, | |
| 3662 | align_expr: OptionalIndex, | |
| 3541 | 3663 | /// Populated if addrspace(A) is present. |
| 3542 | addrspace_expr: Index, | |
| 3664 | addrspace_expr: OptionalIndex, | |
| 3543 | 3665 | /// Populated if linksection(A) is present. |
| 3544 | section_expr: Index, | |
| 3666 | section_expr: OptionalIndex, | |
| 3545 | 3667 | /// Populated if callconv(A) is present. |
| 3546 | callconv_expr: Index, | |
| 3668 | callconv_expr: OptionalIndex, | |
| 3547 | 3669 | }; |
| 3548 | 3670 | |
| 3549 | 3671 | pub const Asm = struct { |
| 3550 | items_start: Index, | |
| 3551 | items_end: Index, | |
| 3672 | items_start: ExtraIndex, | |
| 3673 | items_end: ExtraIndex, | |
| 3552 | 3674 | /// Needed to make lastToken() work. |
| 3553 | 3675 | rparen: TokenIndex, |
| 3554 | 3676 | }; |
| 3555 | 3677 | }; |
| 3556 | 3678 | |
| 3557 | pub fn nodeToSpan(tree: *const Ast, node: u32) Span { | |
| 3679 | pub fn nodeToSpan(tree: *const Ast, node: Ast.Node.Index) Span { | |
| 3558 | 3680 | return tokensToSpan( |
| 3559 | 3681 | tree, |
| 3560 | 3682 | tree.firstToken(node), |
| 3561 | 3683 | tree.lastToken(node), |
| 3562 | tree.nodes.items(.main_token)[node], | |
| 3684 | tree.nodeMainToken(node), | |
| 3563 | 3685 | ); |
| 3564 | 3686 | } |
| 3565 | 3687 | |
| ... | ... | @@ -3568,7 +3690,6 @@ pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { |
| 3568 | 3690 | } |
| 3569 | 3691 | |
| 3570 | 3692 | pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { |
| 3571 | const token_starts = tree.tokens.items(.start); | |
| 3572 | 3693 | var start_tok = start; |
| 3573 | 3694 | var end_tok = end; |
| 3574 | 3695 | |
| ... | ... | @@ -3582,9 +3703,9 @@ pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex |
| 3582 | 3703 | start_tok = main; |
| 3583 | 3704 | end_tok = main; |
| 3584 | 3705 | } |
| 3585 | const start_off = token_starts[start_tok]; | |
| 3586 | const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | |
| 3587 | return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; | |
| 3706 | const start_off = tree.tokenStart(start_tok); | |
| 3707 | const end_off = tree.tokenStart(end_tok) + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); | |
| 3708 | return Span{ .start = start_off, .end = end_off, .main = tree.tokenStart(main) }; | |
| 3588 | 3709 | } |
| 3589 | 3710 | |
| 3590 | 3711 | const std = @import("../std.zig"); |
lib/std/zig/AstGen.zig+612-743| ... | ... | @@ -99,8 +99,18 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 99 | 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 | |
| ... | ... | @@ -866,10 +872,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 866 | 872 | const if_full = tree.fullIf(node).?; |
| 867 | 873 | no_switch_on_err: { |
| 868 | 874 | const error_token = if_full.error_token orelse break :no_switch_on_err; |
| 869 | const full_switch = tree.fullSwitch(if_full.ast.else_expr) orelse break :no_switch_on_err; | |
| 875 | const else_node = if_full.ast.else_expr.unwrap() orelse break :no_switch_on_err; | |
| 876 | const full_switch = tree.fullSwitch(else_node) orelse break :no_switch_on_err; | |
| 870 | 877 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 871 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; | |
| 872 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; | |
| 878 | if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err; | |
| 879 | if (!mem.eql(u8, tree.tokenSlice(error_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err; | |
| 873 | 880 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"if"); |
| 874 | 881 | } |
| 875 | 882 | return ifExpr(gz, scope, ri.br(), node, if_full); |
| ... | ... | @@ -887,8 +894,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 887 | 894 | .slice_sentinel, |
| 888 | 895 | => { |
| 889 | 896 | const full = tree.fullSlice(node).?; |
| 890 | if (full.ast.end != 0 and | |
| 891 | node_tags[full.ast.sliced] == .slice_open and | |
| 897 | if (full.ast.end != .none and | |
| 898 | tree.nodeTag(full.ast.sliced) == .slice_open and | |
| 892 | 899 | nodeIsTriviallyZero(tree, full.ast.start)) |
| 893 | 900 | { |
| 894 | 901 | const lhs_extra = tree.sliceOpen(full.ast.sliced).ast; |
| ... | ... | @@ -896,8 +903,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 896 | 903 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_extra.sliced); |
| 897 | 904 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, lhs_extra.start); |
| 898 | 905 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 899 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end); | |
| 900 | const sentinel = if (full.ast.sentinel != 0) try expr(gz, scope, .{ .rl = .none }, full.ast.sentinel) else .none; | |
| 906 | const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end.unwrap().?); | |
| 907 | const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| try expr(gz, scope, .{ .rl = .none }, sentinel) else .none; | |
| 901 | 908 | try emitDbgStmt(gz, cursor); |
| 902 | 909 | const result = try gz.addPlNode(.slice_length, node, Zir.Inst.SliceLength{ |
| 903 | 910 | .lhs = lhs, |
| ... | ... | @@ -912,10 +919,10 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 912 | 919 | |
| 913 | 920 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 914 | 921 | const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.start); |
| 915 | const end = if (full.ast.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, full.ast.end) else .none; | |
| 916 | const sentinel = if (full.ast.sentinel != 0) s: { | |
| 922 | const end = if (full.ast.end.unwrap()) |end| try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, end) else .none; | |
| 923 | const sentinel = if (full.ast.sentinel.unwrap()) |sentinel| s: { | |
| 917 | 924 | const sentinel_ty = try gz.addUnNode(.slice_sentinel_ty, lhs, node); |
| 918 | break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, full.ast.sentinel); | |
| 925 | break :s try expr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, sentinel); | |
| 919 | 926 | } else .none; |
| 920 | 927 | try emitDbgStmt(gz, cursor); |
| 921 | 928 | if (sentinel != .none) { |
| ... | ... | @@ -943,7 +950,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 943 | 950 | }, |
| 944 | 951 | |
| 945 | 952 | .deref => { |
| 946 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 953 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node); | |
| 947 | 954 | _ = try gz.addUnNode(.validate_deref, lhs, node); |
| 948 | 955 | switch (ri.rl) { |
| 949 | 956 | .ref, .ref_coerced_ty => return lhs, |
| ... | ... | @@ -958,17 +965,17 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 958 | 965 | _ = try gz.addUnTok(.validate_ref_ty, res_ty_inst, tree.firstToken(node)); |
| 959 | 966 | break :rl .{ .ref_coerced_ty = res_ty_inst }; |
| 960 | 967 | } else .ref; |
| 961 | const result = try expr(gz, scope, .{ .rl = operand_rl }, node_datas[node].lhs); | |
| 968 | const result = try expr(gz, scope, .{ .rl = operand_rl }, tree.nodeData(node).node); | |
| 962 | 969 | return rvalue(gz, ri, result, node); |
| 963 | 970 | }, |
| 964 | 971 | .optional_type => { |
| 965 | const operand = try typeExpr(gz, scope, node_datas[node].lhs); | |
| 972 | const operand = try typeExpr(gz, scope, tree.nodeData(node).node); | |
| 966 | 973 | const result = try gz.addUnNode(.optional_type, operand, node); |
| 967 | 974 | return rvalue(gz, ri, result, node); |
| 968 | 975 | }, |
| 969 | 976 | .unwrap_optional => switch (ri.rl) { |
| 970 | 977 | .ref, .ref_coerced_ty => { |
| 971 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | |
| 978 | const lhs = try expr(gz, scope, .{ .rl = .ref }, tree.nodeData(node).node_and_token[0]); | |
| 972 | 979 | |
| 973 | 980 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 974 | 981 | try emitDbgStmt(gz, cursor); |
| ... | ... | @@ -976,7 +983,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 976 | 983 | return gz.addUnNode(.optional_payload_safe_ptr, lhs, node); |
| 977 | 984 | }, |
| 978 | 985 | else => { |
| 979 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 986 | const lhs = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(node).node_and_token[0]); | |
| 980 | 987 | |
| 981 | 988 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 982 | 989 | try emitDbgStmt(gz, cursor); |
| ... | ... | @@ -994,7 +1001,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 994 | 1001 | return blockExpr(gz, scope, ri, node, statements, .normal); |
| 995 | 1002 | }, |
| 996 | 1003 | .enum_literal => if (try ri.rl.resultType(gz, node)) |res_ty| { |
| 997 | const str_index = try astgen.identAsString(main_tokens[node]); | |
| 1004 | const str_index = try astgen.identAsString(tree.nodeMainToken(node)); | |
| 998 | 1005 | const res = try gz.addPlNode(.decl_literal, node, Zir.Inst.Field{ |
| 999 | 1006 | .lhs = res_ty, |
| 1000 | 1007 | .field_name_start = str_index, |
| ... | ... | @@ -1004,8 +1011,8 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1004 | 1011 | .ty, .coerced_ty => return res, // `decl_literal` does the coercion for us |
| 1005 | 1012 | .ref_coerced_ty, .ptr, .inferred_ptr, .destructure => return rvalue(gz, ri, res, node), |
| 1006 | 1013 | } |
| 1007 | } else return simpleStrTok(gz, ri, main_tokens[node], node, .enum_literal), | |
| 1008 | .error_value => return simpleStrTok(gz, ri, node_datas[node].rhs, node, .error_value), | |
| 1014 | } else return simpleStrTok(gz, ri, tree.nodeMainToken(node), node, .enum_literal), | |
| 1015 | .error_value => return simpleStrTok(gz, ri, tree.nodeData(node).opt_token_and_opt_token[1].unwrap().?, node, .error_value), | |
| 1009 | 1016 | // TODO restore this when implementing https://github.com/ziglang/zig/issues/6025 |
| 1010 | 1017 | // .anyframe_literal => return rvalue(gz, ri, .anyframe_type, node), |
| 1011 | 1018 | .anyframe_literal => { |
| ... | ... | @@ -1013,22 +1020,22 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1013 | 1020 | return rvalue(gz, ri, result, node); |
| 1014 | 1021 | }, |
| 1015 | 1022 | .anyframe_type => { |
| 1016 | const return_type = try typeExpr(gz, scope, node_datas[node].rhs); | |
| 1023 | const return_type = try typeExpr(gz, scope, tree.nodeData(node).token_and_node[1]); | |
| 1017 | 1024 | const result = try gz.addUnNode(.anyframe_type, return_type, node); |
| 1018 | 1025 | return rvalue(gz, ri, result, node); |
| 1019 | 1026 | }, |
| 1020 | 1027 | .@"catch" => { |
| 1021 | const catch_token = main_tokens[node]; | |
| 1022 | const payload_token: ?Ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe) | |
| 1028 | const catch_token = tree.nodeMainToken(node); | |
| 1029 | const payload_token: ?Ast.TokenIndex = if (tree.tokenTag(catch_token + 1) == .pipe) | |
| 1023 | 1030 | catch_token + 2 |
| 1024 | 1031 | else |
| 1025 | 1032 | null; |
| 1026 | 1033 | no_switch_on_err: { |
| 1027 | 1034 | const capture_token = payload_token orelse break :no_switch_on_err; |
| 1028 | const full_switch = tree.fullSwitch(node_datas[node].rhs) orelse break :no_switch_on_err; | |
| 1035 | const full_switch = tree.fullSwitch(tree.nodeData(node).node_and_node[1]) orelse break :no_switch_on_err; | |
| 1029 | 1036 | if (full_switch.label_token != null) break :no_switch_on_err; |
| 1030 | if (node_tags[full_switch.ast.condition] != .identifier) break :no_switch_on_err; | |
| 1031 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(main_tokens[full_switch.ast.condition]))) break :no_switch_on_err; | |
| 1037 | if (tree.nodeTag(full_switch.ast.condition) != .identifier) break :no_switch_on_err; | |
| 1038 | if (!mem.eql(u8, tree.tokenSlice(capture_token), tree.tokenSlice(tree.nodeMainToken(full_switch.ast.condition)))) break :no_switch_on_err; | |
| 1032 | 1039 | return switchExprErrUnion(gz, scope, ri.br(), node, .@"catch"); |
| 1033 | 1040 | } |
| 1034 | 1041 | switch (ri.rl) { |
| ... | ... | @@ -1037,11 +1044,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1037 | 1044 | scope, |
| 1038 | 1045 | ri, |
| 1039 | 1046 | node, |
| 1040 | node_datas[node].lhs, | |
| 1041 | 1047 | .is_non_err_ptr, |
| 1042 | 1048 | .err_union_payload_unsafe_ptr, |
| 1043 | 1049 | .err_union_code_ptr, |
| 1044 | node_datas[node].rhs, | |
| 1045 | 1050 | payload_token, |
| 1046 | 1051 | ), |
| 1047 | 1052 | else => return orelseCatchExpr( |
| ... | ... | @@ -1049,11 +1054,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1049 | 1054 | scope, |
| 1050 | 1055 | ri, |
| 1051 | 1056 | node, |
| 1052 | node_datas[node].lhs, | |
| 1053 | 1057 | .is_non_err, |
| 1054 | 1058 | .err_union_payload_unsafe, |
| 1055 | 1059 | .err_union_code, |
| 1056 | node_datas[node].rhs, | |
| 1057 | 1060 | payload_token, |
| 1058 | 1061 | ), |
| 1059 | 1062 | } |
| ... | ... | @@ -1064,11 +1067,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1064 | 1067 | scope, |
| 1065 | 1068 | ri, |
| 1066 | 1069 | node, |
| 1067 | node_datas[node].lhs, | |
| 1068 | 1070 | .is_non_null_ptr, |
| 1069 | 1071 | .optional_payload_unsafe_ptr, |
| 1070 | 1072 | undefined, |
| 1071 | node_datas[node].rhs, | |
| 1072 | 1073 | null, |
| 1073 | 1074 | ), |
| 1074 | 1075 | else => return orelseCatchExpr( |
| ... | ... | @@ -1076,11 +1077,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1076 | 1077 | scope, |
| 1077 | 1078 | ri, |
| 1078 | 1079 | node, |
| 1079 | node_datas[node].lhs, | |
| 1080 | 1080 | .is_non_null, |
| 1081 | 1081 | .optional_payload_unsafe, |
| 1082 | 1082 | undefined, |
| 1083 | node_datas[node].rhs, | |
| 1084 | 1083 | null, |
| 1085 | 1084 | ), |
| 1086 | 1085 | }, |
| ... | ... | @@ -1110,7 +1109,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1110 | 1109 | |
| 1111 | 1110 | .@"break" => return breakExpr(gz, scope, node), |
| 1112 | 1111 | .@"continue" => return continueExpr(gz, scope, node), |
| 1113 | .grouped_expression => return expr(gz, scope, ri, node_datas[node].lhs), | |
| 1112 | .grouped_expression => return expr(gz, scope, ri, tree.nodeData(node).node_and_token[0]), | |
| 1114 | 1113 | .array_type => return arrayType(gz, scope, ri, node), |
| 1115 | 1114 | .array_type_sentinel => return arrayTypeSentinel(gz, scope, ri, node), |
| 1116 | 1115 | .char_literal => return charLiteral(gz, ri, node), |
| ... | ... | @@ -1124,7 +1123,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE |
| 1124 | 1123 | .@"await" => return awaitExpr(gz, scope, ri, node), |
| 1125 | 1124 | .@"resume" => return resumeExpr(gz, scope, ri, node), |
| 1126 | 1125 | |
| 1127 | .@"try" => return tryExpr(gz, scope, ri, node, node_datas[node].lhs), | |
| 1126 | .@"try" => return tryExpr(gz, scope, ri, node, tree.nodeData(node).node), | |
| 1128 | 1127 | |
| 1129 | 1128 | .array_init_one, |
| 1130 | 1129 | .array_init_one_comma, |
| ... | ... | @@ -1171,16 +1170,14 @@ fn nosuspendExpr( |
| 1171 | 1170 | ) InnerError!Zir.Inst.Ref { |
| 1172 | 1171 | const astgen = gz.astgen; |
| 1173 | 1172 | const tree = astgen.tree; |
| 1174 | const node_datas = tree.nodes.items(.data); | |
| 1175 | const body_node = node_datas[node].lhs; | |
| 1176 | assert(body_node != 0); | |
| 1177 | if (gz.nosuspend_node != 0) { | |
| 1173 | const body_node = tree.nodeData(node).node; | |
| 1174 | if (gz.nosuspend_node.unwrap()) |nosuspend_node| { | |
| 1178 | 1175 | try astgen.appendErrorNodeNotes(node, "redundant nosuspend block", .{}, &[_]u32{ |
| 1179 | try astgen.errNoteNode(gz.nosuspend_node, "other nosuspend block here", .{}), | |
| 1176 | try astgen.errNoteNode(nosuspend_node, "other nosuspend block here", .{}), | |
| 1180 | 1177 | }); |
| 1181 | 1178 | } |
| 1182 | gz.nosuspend_node = node; | |
| 1183 | defer gz.nosuspend_node = 0; | |
| 1179 | gz.nosuspend_node = node.toOptional(); | |
| 1180 | defer gz.nosuspend_node = .none; | |
| 1184 | 1181 | return expr(gz, scope, ri, body_node); |
| 1185 | 1182 | } |
| 1186 | 1183 | |
| ... | ... | @@ -1192,26 +1189,24 @@ fn suspendExpr( |
| 1192 | 1189 | const astgen = gz.astgen; |
| 1193 | 1190 | const gpa = astgen.gpa; |
| 1194 | 1191 | const tree = astgen.tree; |
| 1195 | const node_datas = tree.nodes.items(.data); | |
| 1196 | const body_node = node_datas[node].lhs; | |
| 1192 | const body_node = tree.nodeData(node).node; | |
| 1197 | 1193 | |
| 1198 | if (gz.nosuspend_node != 0) { | |
| 1194 | if (gz.nosuspend_node.unwrap()) |nosuspend_node| { | |
| 1199 | 1195 | return astgen.failNodeNotes(node, "suspend inside nosuspend block", .{}, &[_]u32{ |
| 1200 | try astgen.errNoteNode(gz.nosuspend_node, "nosuspend block here", .{}), | |
| 1196 | try astgen.errNoteNode(nosuspend_node, "nosuspend block here", .{}), | |
| 1201 | 1197 | }); |
| 1202 | 1198 | } |
| 1203 | if (gz.suspend_node != 0) { | |
| 1199 | if (gz.suspend_node.unwrap()) |suspend_node| { | |
| 1204 | 1200 | return astgen.failNodeNotes(node, "cannot suspend inside suspend block", .{}, &[_]u32{ |
| 1205 | try astgen.errNoteNode(gz.suspend_node, "other suspend block here", .{}), | |
| 1201 | try astgen.errNoteNode(suspend_node, "other suspend block here", .{}), | |
| 1206 | 1202 | }); |
| 1207 | 1203 | } |
| 1208 | assert(body_node != 0); | |
| 1209 | 1204 | |
| 1210 | 1205 | const suspend_inst = try gz.makeBlockInst(.suspend_block, node); |
| 1211 | 1206 | try gz.instructions.append(gpa, suspend_inst); |
| 1212 | 1207 | |
| 1213 | 1208 | var suspend_scope = gz.makeSubBlock(scope); |
| 1214 | suspend_scope.suspend_node = node; | |
| 1209 | suspend_scope.suspend_node = node.toOptional(); | |
| 1215 | 1210 | defer suspend_scope.unstack(); |
| 1216 | 1211 | |
| 1217 | 1212 | const body_result = try fullBodyExpr(&suspend_scope, &suspend_scope.base, .{ .rl = .none }, body_node, .normal); |
| ... | ... | @@ -1231,16 +1226,15 @@ fn awaitExpr( |
| 1231 | 1226 | ) InnerError!Zir.Inst.Ref { |
| 1232 | 1227 | const astgen = gz.astgen; |
| 1233 | 1228 | const tree = astgen.tree; |
| 1234 | const node_datas = tree.nodes.items(.data); | |
| 1235 | const rhs_node = node_datas[node].lhs; | |
| 1229 | const rhs_node = tree.nodeData(node).node; | |
| 1236 | 1230 | |
| 1237 | if (gz.suspend_node != 0) { | |
| 1231 | if (gz.suspend_node.unwrap()) |suspend_node| { | |
| 1238 | 1232 | return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{ |
| 1239 | try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}), | |
| 1233 | try astgen.errNoteNode(suspend_node, "suspend block here", .{}), | |
| 1240 | 1234 | }); |
| 1241 | 1235 | } |
| 1242 | 1236 | const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node); |
| 1243 | const result = if (gz.nosuspend_node != 0) | |
| 1237 | const result = if (gz.nosuspend_node != .none) | |
| 1244 | 1238 | try gz.addExtendedPayload(.await_nosuspend, Zir.Inst.UnNode{ |
| 1245 | 1239 | .node = gz.nodeIndexToRelative(node), |
| 1246 | 1240 | .operand = operand, |
| ... | ... | @@ -1259,8 +1253,7 @@ fn resumeExpr( |
| 1259 | 1253 | ) InnerError!Zir.Inst.Ref { |
| 1260 | 1254 | const astgen = gz.astgen; |
| 1261 | 1255 | const tree = astgen.tree; |
| 1262 | const node_datas = tree.nodes.items(.data); | |
| 1263 | const rhs_node = node_datas[node].lhs; | |
| 1256 | const rhs_node = tree.nodeData(node).node; | |
| 1264 | 1257 | const operand = try expr(gz, scope, .{ .rl = .ref }, rhs_node); |
| 1265 | 1258 | const result = try gz.addUnNode(.@"resume", operand, node); |
| 1266 | 1259 | return rvalue(gz, ri, result, node); |
| ... | ... | @@ -1275,33 +1268,33 @@ fn fnProtoExpr( |
| 1275 | 1268 | ) InnerError!Zir.Inst.Ref { |
| 1276 | 1269 | const astgen = gz.astgen; |
| 1277 | 1270 | const tree = astgen.tree; |
| 1278 | const token_tags = tree.tokens.items(.tag); | |
| 1279 | 1271 | |
| 1280 | 1272 | if (fn_proto.name_token) |some| { |
| 1281 | 1273 | return astgen.failTok(some, "function type cannot have a name", .{}); |
| 1282 | 1274 | } |
| 1283 | 1275 | |
| 1284 | if (fn_proto.ast.align_expr != 0) { | |
| 1285 | return astgen.failNode(fn_proto.ast.align_expr, "function type cannot have an alignment", .{}); | |
| 1276 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1277 | return astgen.failNode(align_expr, "function type cannot have an alignment", .{}); | |
| 1286 | 1278 | } |
| 1287 | 1279 | |
| 1288 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1289 | return astgen.failNode(fn_proto.ast.addrspace_expr, "function type cannot have an addrspace", .{}); | |
| 1280 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1281 | return astgen.failNode(addrspace_expr, "function type cannot have an addrspace", .{}); | |
| 1290 | 1282 | } |
| 1291 | 1283 | |
| 1292 | if (fn_proto.ast.section_expr != 0) { | |
| 1293 | return astgen.failNode(fn_proto.ast.section_expr, "function type cannot have a linksection", .{}); | |
| 1284 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1285 | return astgen.failNode(section_expr, "function type cannot have a linksection", .{}); | |
| 1294 | 1286 | } |
| 1295 | 1287 | |
| 1296 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 1297 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 1288 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 1289 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 1290 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 1298 | 1291 | if (is_inferred_error) { |
| 1299 | 1292 | return astgen.failTok(maybe_bang, "function type cannot have an inferred error set", .{}); |
| 1300 | 1293 | } |
| 1301 | 1294 | |
| 1302 | 1295 | const is_extern = blk: { |
| 1303 | 1296 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 1304 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 1297 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 1305 | 1298 | }; |
| 1306 | 1299 | assert(!is_extern); |
| 1307 | 1300 | |
| ... | ... | @@ -1318,7 +1311,6 @@ fn fnProtoExprInner( |
| 1318 | 1311 | ) InnerError!Zir.Inst.Ref { |
| 1319 | 1312 | const astgen = gz.astgen; |
| 1320 | 1313 | const tree = astgen.tree; |
| 1321 | const token_tags = tree.tokens.items(.tag); | |
| 1322 | 1314 | |
| 1323 | 1315 | var block_scope = gz.makeSubBlock(scope); |
| 1324 | 1316 | defer block_scope.unstack(); |
| ... | ... | @@ -1330,7 +1322,7 @@ fn fnProtoExprInner( |
| 1330 | 1322 | var param_type_i: usize = 0; |
| 1331 | 1323 | var it = fn_proto.iterate(tree); |
| 1332 | 1324 | while (it.next()) |param| : (param_type_i += 1) { |
| 1333 | const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) { | |
| 1325 | const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) { | |
| 1334 | 1326 | .keyword_noalias => is_comptime: { |
| 1335 | 1327 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse |
| 1336 | 1328 | return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); |
| ... | ... | @@ -1341,7 +1333,7 @@ fn fnProtoExprInner( |
| 1341 | 1333 | } else false; |
| 1342 | 1334 | |
| 1343 | 1335 | const is_anytype = if (param.anytype_ellipsis3) |token| blk: { |
| 1344 | switch (token_tags[token]) { | |
| 1336 | switch (tree.tokenTag(token)) { | |
| 1345 | 1337 | .keyword_anytype => break :blk true, |
| 1346 | 1338 | .ellipsis3 => break :is_var_args true, |
| 1347 | 1339 | else => unreachable, |
| ... | ... | @@ -1364,16 +1356,14 @@ fn fnProtoExprInner( |
| 1364 | 1356 | .param_anytype; |
| 1365 | 1357 | _ = try block_scope.addStrTok(tag, param_name, name_token); |
| 1366 | 1358 | } else { |
| 1367 | const param_type_node = param.type_expr; | |
| 1368 | assert(param_type_node != 0); | |
| 1359 | const param_type_node = param.type_expr.?; | |
| 1369 | 1360 | var param_gz = block_scope.makeSubBlock(scope); |
| 1370 | 1361 | defer param_gz.unstack(); |
| 1371 | 1362 | param_gz.is_comptime = true; |
| 1372 | 1363 | const param_type = try fullBodyExpr(&param_gz, scope, coerced_type_ri, param_type_node, .normal); |
| 1373 | 1364 | const param_inst_expected: Zir.Inst.Index = @enumFromInt(astgen.instructions.len + 1); |
| 1374 | 1365 | _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); |
| 1375 | const main_tokens = tree.nodes.items(.main_token); | |
| 1376 | const name_token = param.name_token orelse main_tokens[param_type_node]; | |
| 1366 | const name_token = param.name_token orelse tree.nodeMainToken(param_type_node); | |
| 1377 | 1367 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 1378 | 1368 | // We pass `prev_param_insts` as `&.{}` here because a function prototype can't refer to previous |
| 1379 | 1369 | // arguments (we haven't set up scopes here). |
| ... | ... | @@ -1384,12 +1374,12 @@ fn fnProtoExprInner( |
| 1384 | 1374 | break :is_var_args false; |
| 1385 | 1375 | }; |
| 1386 | 1376 | |
| 1387 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) | |
| 1377 | const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| | |
| 1388 | 1378 | try comptimeExpr( |
| 1389 | 1379 | &block_scope, |
| 1390 | 1380 | scope, |
| 1391 | .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, | |
| 1392 | fn_proto.ast.callconv_expr, | |
| 1381 | .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(callconv_expr, .calling_convention) } }, | |
| 1382 | callconv_expr, | |
| 1393 | 1383 | .@"callconv", |
| 1394 | 1384 | ) |
| 1395 | 1385 | else if (implicit_ccc) |
| ... | ... | @@ -1397,7 +1387,8 @@ fn fnProtoExprInner( |
| 1397 | 1387 | else |
| 1398 | 1388 | .none; |
| 1399 | 1389 | |
| 1400 | const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, fn_proto.ast.return_type, .function_ret_ty); | |
| 1390 | const ret_ty_node = fn_proto.ast.return_type.unwrap().?; | |
| 1391 | const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty); | |
| 1401 | 1392 | |
| 1402 | 1393 | const result = try block_scope.addFunc(.{ |
| 1403 | 1394 | .src_node = fn_proto.ast.proto_node, |
| ... | ... | @@ -1437,33 +1428,32 @@ fn arrayInitExpr( |
| 1437 | 1428 | ) InnerError!Zir.Inst.Ref { |
| 1438 | 1429 | const astgen = gz.astgen; |
| 1439 | 1430 | const tree = astgen.tree; |
| 1440 | const node_tags = tree.nodes.items(.tag); | |
| 1441 | const main_tokens = tree.nodes.items(.main_token); | |
| 1442 | 1431 | |
| 1443 | 1432 | assert(array_init.ast.elements.len != 0); // Otherwise it would be struct init. |
| 1444 | 1433 | |
| 1445 | 1434 | const array_ty: Zir.Inst.Ref, const elem_ty: Zir.Inst.Ref = inst: { |
| 1446 | if (array_init.ast.type_expr == 0) break :inst .{ .none, .none }; | |
| 1435 | const type_expr = array_init.ast.type_expr.unwrap() orelse break :inst .{ .none, .none }; | |
| 1447 | 1436 | |
| 1448 | 1437 | infer: { |
| 1449 | const array_type: Ast.full.ArrayType = tree.fullArrayType(array_init.ast.type_expr) orelse break :infer; | |
| 1438 | const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse break :infer; | |
| 1450 | 1439 | // This intentionally does not support `@"_"` syntax. |
| 1451 | if (node_tags[array_type.ast.elem_count] == .identifier and | |
| 1452 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_")) | |
| 1440 | if (tree.nodeTag(array_type.ast.elem_count) == .identifier and | |
| 1441 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_")) | |
| 1453 | 1442 | { |
| 1454 | 1443 | const len_inst = try gz.addInt(array_init.ast.elements.len); |
| 1455 | 1444 | const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type); |
| 1456 | if (array_type.ast.sentinel == 0) { | |
| 1457 | const array_type_inst = try gz.addPlNode(.array_type, array_init.ast.type_expr, Zir.Inst.Bin{ | |
| 1445 | if (array_type.ast.sentinel == .none) { | |
| 1446 | const array_type_inst = try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{ | |
| 1458 | 1447 | .lhs = len_inst, |
| 1459 | 1448 | .rhs = elem_type, |
| 1460 | 1449 | }); |
| 1461 | 1450 | break :inst .{ array_type_inst, elem_type }; |
| 1462 | 1451 | } else { |
| 1463 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel); | |
| 1452 | const sentinel_node = array_type.ast.sentinel.unwrap().?; | |
| 1453 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel); | |
| 1464 | 1454 | const array_type_inst = try gz.addPlNode( |
| 1465 | 1455 | .array_type_sentinel, |
| 1466 | array_init.ast.type_expr, | |
| 1456 | type_expr, | |
| 1467 | 1457 | Zir.Inst.ArrayTypeSentinel{ |
| 1468 | 1458 | .len = len_inst, |
| 1469 | 1459 | .elem_type = elem_type, |
| ... | ... | @@ -1474,7 +1464,7 @@ fn arrayInitExpr( |
| 1474 | 1464 | } |
| 1475 | 1465 | } |
| 1476 | 1466 | } |
| 1477 | const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr); | |
| 1467 | const array_type_inst = try typeExpr(gz, scope, type_expr); | |
| 1478 | 1468 | _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{ |
| 1479 | 1469 | .ty = array_type_inst, |
| 1480 | 1470 | .init_count = @intCast(array_init.ast.elements.len), |
| ... | ... | @@ -1682,7 +1672,7 @@ fn structInitExpr( |
| 1682 | 1672 | const astgen = gz.astgen; |
| 1683 | 1673 | const tree = astgen.tree; |
| 1684 | 1674 | |
| 1685 | if (struct_init.ast.type_expr == 0) { | |
| 1675 | if (struct_init.ast.type_expr == .none) { | |
| 1686 | 1676 | if (struct_init.ast.fields.len == 0) { |
| 1687 | 1677 | // Anonymous init with no fields. |
| 1688 | 1678 | switch (ri.rl) { |
| ... | ... | @@ -1706,32 +1696,32 @@ fn structInitExpr( |
| 1706 | 1696 | } |
| 1707 | 1697 | } |
| 1708 | 1698 | } else array: { |
| 1709 | const node_tags = tree.nodes.items(.tag); | |
| 1710 | const main_tokens = tree.nodes.items(.main_token); | |
| 1711 | const array_type: Ast.full.ArrayType = tree.fullArrayType(struct_init.ast.type_expr) orelse { | |
| 1699 | const type_expr = struct_init.ast.type_expr.unwrap().?; | |
| 1700 | const array_type: Ast.full.ArrayType = tree.fullArrayType(type_expr) orelse { | |
| 1712 | 1701 | if (struct_init.ast.fields.len == 0) { |
| 1713 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1702 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1714 | 1703 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1715 | 1704 | return rvalue(gz, ri, result, node); |
| 1716 | 1705 | } |
| 1717 | 1706 | break :array; |
| 1718 | 1707 | }; |
| 1719 | const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and | |
| 1708 | const is_inferred_array_len = tree.nodeTag(array_type.ast.elem_count) == .identifier and | |
| 1720 | 1709 | // This intentionally does not support `@"_"` syntax. |
| 1721 | mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"); | |
| 1710 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(array_type.ast.elem_count)), "_"); | |
| 1722 | 1711 | if (struct_init.ast.fields.len == 0) { |
| 1723 | 1712 | if (is_inferred_array_len) { |
| 1724 | 1713 | const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type); |
| 1725 | const array_type_inst = if (array_type.ast.sentinel == 0) blk: { | |
| 1726 | break :blk try gz.addPlNode(.array_type, struct_init.ast.type_expr, Zir.Inst.Bin{ | |
| 1714 | const array_type_inst = if (array_type.ast.sentinel == .none) blk: { | |
| 1715 | break :blk try gz.addPlNode(.array_type, type_expr, Zir.Inst.Bin{ | |
| 1727 | 1716 | .lhs = .zero_usize, |
| 1728 | 1717 | .rhs = elem_type, |
| 1729 | 1718 | }); |
| 1730 | 1719 | } else blk: { |
| 1731 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel); | |
| 1720 | const sentinel_node = array_type.ast.sentinel.unwrap().?; | |
| 1721 | const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, sentinel_node, .array_sentinel); | |
| 1732 | 1722 | break :blk try gz.addPlNode( |
| 1733 | 1723 | .array_type_sentinel, |
| 1734 | struct_init.ast.type_expr, | |
| 1724 | type_expr, | |
| 1735 | 1725 | Zir.Inst.ArrayTypeSentinel{ |
| 1736 | 1726 | .len = .zero_usize, |
| 1737 | 1727 | .elem_type = elem_type, |
| ... | ... | @@ -1742,12 +1732,12 @@ fn structInitExpr( |
| 1742 | 1732 | const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node); |
| 1743 | 1733 | return rvalue(gz, ri, result, node); |
| 1744 | 1734 | } |
| 1745 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1735 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1746 | 1736 | const result = try gz.addUnNode(.struct_init_empty, ty_inst, node); |
| 1747 | 1737 | return rvalue(gz, ri, result, node); |
| 1748 | 1738 | } else { |
| 1749 | 1739 | return astgen.failNode( |
| 1750 | struct_init.ast.type_expr, | |
| 1740 | type_expr, | |
| 1751 | 1741 | "initializing array with struct syntax", |
| 1752 | 1742 | .{}, |
| 1753 | 1743 | ); |
| ... | ... | @@ -1806,9 +1796,9 @@ fn structInitExpr( |
| 1806 | 1796 | } |
| 1807 | 1797 | } |
| 1808 | 1798 | |
| 1809 | if (struct_init.ast.type_expr != 0) { | |
| 1799 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 1810 | 1800 | // Typed inits do not use RLS for language simplicity. |
| 1811 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | |
| 1801 | const ty_inst = try typeExpr(gz, scope, type_expr); | |
| 1812 | 1802 | _ = try gz.addUnNode(.validate_struct_init_ty, ty_inst, node); |
| 1813 | 1803 | switch (ri.rl) { |
| 1814 | 1804 | .ref => return structInitExprTyped(gz, scope, node, struct_init, ty_inst, true), |
| ... | ... | @@ -1997,9 +1987,7 @@ fn comptimeExpr2( |
| 1997 | 1987 | // no need to wrap it in a block. This is hard to determine in general, but we can identify a |
| 1998 | 1988 | // common subset of trivially comptime expressions to take down the size of the ZIR a bit. |
| 1999 | 1989 | const tree = gz.astgen.tree; |
| 2000 | const main_tokens = tree.nodes.items(.main_token); | |
| 2001 | const node_tags = tree.nodes.items(.tag); | |
| 2002 | switch (node_tags[node]) { | |
| 1990 | switch (tree.nodeTag(node)) { | |
| 2003 | 1991 | .identifier => { |
| 2004 | 1992 | // Many identifiers can be handled without a `block_comptime`, so `AstGen.identifier` has |
| 2005 | 1993 | // special handling for this case. |
| ... | ... | @@ -2052,8 +2040,7 @@ fn comptimeExpr2( |
| 2052 | 2040 | // comptime block, because that would be silly! Note that we don't bother doing this for |
| 2053 | 2041 | // unlabelled blocks, since they don't generate blocks at comptime anyway (see `blockExpr`). |
| 2054 | 2042 | .block_two, .block_two_semicolon, .block, .block_semicolon => { |
| 2055 | const token_tags = tree.tokens.items(.tag); | |
| 2056 | const lbrace = main_tokens[node]; | |
| 2043 | const lbrace = tree.nodeMainToken(node); | |
| 2057 | 2044 | // Careful! We can't pass in the real result location here, since it may |
| 2058 | 2045 | // refer to runtime memory. A runtime-to-comptime boundary has to remove |
| 2059 | 2046 | // result location information, compute the result, and copy it to the true |
| ... | ... | @@ -2065,11 +2052,10 @@ fn comptimeExpr2( |
| 2065 | 2052 | else |
| 2066 | 2053 | .none, |
| 2067 | 2054 | }; |
| 2068 | if (token_tags[lbrace - 1] == .colon and | |
| 2069 | token_tags[lbrace - 2] == .identifier) | |
| 2070 | { | |
| 2055 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2071 | 2056 | var buf: [2]Ast.Node.Index = undefined; |
| 2072 | 2057 | const stmts = tree.blockStatements(&buf, node).?; |
| 2058 | ||
| 2073 | 2059 | // Replace result location and copy back later - see above. |
| 2074 | 2060 | const block_ref = try labeledBlockExpr(gz, scope, ty_only_ri, node, stmts, true, .normal); |
| 2075 | 2061 | return rvalue(gz, ri, block_ref, node); |
| ... | ... | @@ -2117,8 +2103,7 @@ fn comptimeExprAst( |
| 2117 | 2103 | try astgen.appendErrorNode(node, "redundant comptime keyword in already comptime scope", .{}); |
| 2118 | 2104 | } |
| 2119 | 2105 | const tree = astgen.tree; |
| 2120 | const node_datas = tree.nodes.items(.data); | |
| 2121 | const body_node = node_datas[node].lhs; | |
| 2106 | const body_node = tree.nodeData(node).node; | |
| 2122 | 2107 | return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword); |
| 2123 | 2108 | } |
| 2124 | 2109 | |
| ... | ... | @@ -2156,9 +2141,7 @@ fn restoreErrRetIndex( |
| 2156 | 2141 | fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2157 | 2142 | const astgen = parent_gz.astgen; |
| 2158 | 2143 | const tree = astgen.tree; |
| 2159 | const node_datas = tree.nodes.items(.data); | |
| 2160 | const break_label = node_datas[node].lhs; | |
| 2161 | const rhs = node_datas[node].rhs; | |
| 2144 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 2162 | 2145 | |
| 2163 | 2146 | // Look for the label in the scope. |
| 2164 | 2147 | var scope = parent_scope; |
| ... | ... | @@ -2167,11 +2150,11 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2167 | 2150 | .gen_zir => { |
| 2168 | 2151 | const block_gz = scope.cast(GenZir).?; |
| 2169 | 2152 | |
| 2170 | if (block_gz.cur_defer_node != 0) { | |
| 2153 | if (block_gz.cur_defer_node.unwrap()) |cur_defer_node| { | |
| 2171 | 2154 | // We are breaking out of a `defer` block. |
| 2172 | 2155 | return astgen.failNodeNotes(node, "cannot break out of defer expression", .{}, &.{ |
| 2173 | 2156 | try astgen.errNoteNode( |
| 2174 | block_gz.cur_defer_node, | |
| 2157 | cur_defer_node, | |
| 2175 | 2158 | "defer expression here", |
| 2176 | 2159 | .{}, |
| 2177 | 2160 | ), |
| ... | ... | @@ -2179,7 +2162,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2179 | 2162 | } |
| 2180 | 2163 | |
| 2181 | 2164 | const block_inst = blk: { |
| 2182 | if (break_label != 0) { | |
| 2165 | if (opt_break_label.unwrap()) |break_label| { | |
| 2183 | 2166 | if (block_gz.label) |*label| { |
| 2184 | 2167 | if (try astgen.tokenIdentEql(label.token, break_label)) { |
| 2185 | 2168 | label.used = true; |
| ... | ... | @@ -2200,7 +2183,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2200 | 2183 | else |
| 2201 | 2184 | .@"break"; |
| 2202 | 2185 | |
| 2203 | if (rhs == 0) { | |
| 2186 | const rhs = opt_rhs.unwrap() orelse { | |
| 2204 | 2187 | _ = try rvalue(parent_gz, block_gz.break_result_info, .void_value, node); |
| 2205 | 2188 | |
| 2206 | 2189 | try genDefers(parent_gz, scope, parent_scope, .normal_only); |
| ... | ... | @@ -2211,7 +2194,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2211 | 2194 | |
| 2212 | 2195 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); |
| 2213 | 2196 | return Zir.Inst.Ref.unreachable_value; |
| 2214 | } | |
| 2197 | }; | |
| 2215 | 2198 | |
| 2216 | 2199 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_info, rhs, node); |
| 2217 | 2200 | |
| ... | ... | @@ -2243,7 +2226,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2243 | 2226 | .top => unreachable, |
| 2244 | 2227 | } |
| 2245 | 2228 | } |
| 2246 | if (break_label != 0) { | |
| 2229 | if (opt_break_label.unwrap()) |break_label| { | |
| 2247 | 2230 | const label_name = try astgen.identifierTokenString(break_label); |
| 2248 | 2231 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 2249 | 2232 | } else { |
| ... | ... | @@ -2254,11 +2237,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 2254 | 2237 | fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 2255 | 2238 | const astgen = parent_gz.astgen; |
| 2256 | 2239 | const tree = astgen.tree; |
| 2257 | const node_datas = tree.nodes.items(.data); | |
| 2258 | const break_label = node_datas[node].lhs; | |
| 2259 | const rhs = node_datas[node].rhs; | |
| 2240 | const opt_break_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 2260 | 2241 | |
| 2261 | if (break_label == 0 and rhs != 0) { | |
| 2242 | if (opt_break_label == .none and opt_rhs != .none) { | |
| 2262 | 2243 | return astgen.failNode(node, "cannot continue with operand without label", .{}); |
| 2263 | 2244 | } |
| 2264 | 2245 | |
| ... | ... | @@ -2269,10 +2250,10 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2269 | 2250 | .gen_zir => { |
| 2270 | 2251 | const gen_zir = scope.cast(GenZir).?; |
| 2271 | 2252 | |
| 2272 | if (gen_zir.cur_defer_node != 0) { | |
| 2253 | if (gen_zir.cur_defer_node.unwrap()) |cur_defer_node| { | |
| 2273 | 2254 | return astgen.failNodeNotes(node, "cannot continue out of defer expression", .{}, &.{ |
| 2274 | 2255 | try astgen.errNoteNode( |
| 2275 | gen_zir.cur_defer_node, | |
| 2256 | cur_defer_node, | |
| 2276 | 2257 | "defer expression here", |
| 2277 | 2258 | .{}, |
| 2278 | 2259 | ), |
| ... | ... | @@ -2282,11 +2263,11 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2282 | 2263 | scope = gen_zir.parent; |
| 2283 | 2264 | continue; |
| 2284 | 2265 | }; |
| 2285 | if (break_label != 0) blk: { | |
| 2266 | if (opt_break_label.unwrap()) |break_label| blk: { | |
| 2286 | 2267 | if (gen_zir.label) |*label| { |
| 2287 | 2268 | if (try astgen.tokenIdentEql(label.token, break_label)) { |
| 2288 | 2269 | const maybe_switch_tag = astgen.instructions.items(.tag)[@intFromEnum(label.block_inst)]; |
| 2289 | if (rhs != 0) switch (maybe_switch_tag) { | |
| 2270 | if (opt_rhs != .none) switch (maybe_switch_tag) { | |
| 2290 | 2271 | .switch_block, .switch_block_ref => {}, |
| 2291 | 2272 | else => return astgen.failNode(node, "cannot continue loop with operand", .{}), |
| 2292 | 2273 | } else switch (maybe_switch_tag) { |
| ... | ... | @@ -2314,7 +2295,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2314 | 2295 | } |
| 2315 | 2296 | } |
| 2316 | 2297 | |
| 2317 | if (rhs != 0) { | |
| 2298 | if (opt_rhs.unwrap()) |rhs| { | |
| 2318 | 2299 | // We need to figure out the result info to use. |
| 2319 | 2300 | // The type should match |
| 2320 | 2301 | const operand = try reachableExpr(parent_gz, parent_scope, gen_zir.continue_result_info, rhs, node); |
| ... | ... | @@ -2353,7 +2334,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) |
| 2353 | 2334 | .top => unreachable, |
| 2354 | 2335 | } |
| 2355 | 2336 | } |
| 2356 | if (break_label != 0) { | |
| 2337 | if (opt_break_label.unwrap()) |break_label| { | |
| 2357 | 2338 | const label_name = try astgen.identifierTokenString(break_label); |
| 2358 | 2339 | return astgen.failTok(break_label, "label not found: '{s}'", .{label_name}); |
| 2359 | 2340 | } else { |
| ... | ... | @@ -2373,15 +2354,14 @@ fn fullBodyExpr( |
| 2373 | 2354 | block_kind: BlockKind, |
| 2374 | 2355 | ) InnerError!Zir.Inst.Ref { |
| 2375 | 2356 | const tree = gz.astgen.tree; |
| 2376 | const main_tokens = tree.nodes.items(.main_token); | |
| 2377 | const token_tags = tree.tokens.items(.tag); | |
| 2357 | ||
| 2378 | 2358 | var stmt_buf: [2]Ast.Node.Index = undefined; |
| 2379 | const statements = tree.blockStatements(&stmt_buf, node).?; | |
| 2359 | const statements = tree.blockStatements(&stmt_buf, node) orelse | |
| 2360 | return expr(gz, scope, ri, node); | |
| 2380 | 2361 | |
| 2381 | const lbrace = main_tokens[node]; | |
| 2382 | if (token_tags[lbrace - 1] == .colon and | |
| 2383 | token_tags[lbrace - 2] == .identifier) | |
| 2384 | { | |
| 2362 | const lbrace = tree.nodeMainToken(node); | |
| 2363 | ||
| 2364 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2385 | 2365 | // Labeled blocks are tricky - forwarding result location information properly is non-trivial, |
| 2386 | 2366 | // plus if this block is exited with a `break_inline` we aren't allowed multiple breaks. This |
| 2387 | 2367 | // case is rare, so just treat it as a normal expression and create a nested block. |
| ... | ... | @@ -2406,13 +2386,9 @@ fn blockExpr( |
| 2406 | 2386 | ) InnerError!Zir.Inst.Ref { |
| 2407 | 2387 | const astgen = gz.astgen; |
| 2408 | 2388 | const tree = astgen.tree; |
| 2409 | const main_tokens = tree.nodes.items(.main_token); | |
| 2410 | const token_tags = tree.tokens.items(.tag); | |
| 2411 | 2389 | |
| 2412 | const lbrace = main_tokens[block_node]; | |
| 2413 | if (token_tags[lbrace - 1] == .colon and | |
| 2414 | token_tags[lbrace - 2] == .identifier) | |
| 2415 | { | |
| 2390 | const lbrace = tree.nodeMainToken(block_node); | |
| 2391 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 2416 | 2392 | return labeledBlockExpr(gz, scope, ri, block_node, statements, false, kind); |
| 2417 | 2393 | } |
| 2418 | 2394 | |
| ... | ... | @@ -2489,12 +2465,10 @@ fn labeledBlockExpr( |
| 2489 | 2465 | ) InnerError!Zir.Inst.Ref { |
| 2490 | 2466 | const astgen = gz.astgen; |
| 2491 | 2467 | const tree = astgen.tree; |
| 2492 | const main_tokens = tree.nodes.items(.main_token); | |
| 2493 | const token_tags = tree.tokens.items(.tag); | |
| 2494 | 2468 | |
| 2495 | const lbrace = main_tokens[block_node]; | |
| 2469 | const lbrace = tree.nodeMainToken(block_node); | |
| 2496 | 2470 | const label_token = lbrace - 2; |
| 2497 | assert(token_tags[label_token] == .identifier); | |
| 2471 | assert(tree.tokenTag(label_token) == .identifier); | |
| 2498 | 2472 | |
| 2499 | 2473 | try astgen.checkLabelRedefinition(parent_scope, label_token); |
| 2500 | 2474 | |
| ... | ... | @@ -2555,8 +2529,6 @@ fn labeledBlockExpr( |
| 2555 | 2529 | fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Node.Index, block_kind: BlockKind) !void { |
| 2556 | 2530 | const astgen = gz.astgen; |
| 2557 | 2531 | const tree = astgen.tree; |
| 2558 | const node_tags = tree.nodes.items(.tag); | |
| 2559 | const node_data = tree.nodes.items(.data); | |
| 2560 | 2532 | |
| 2561 | 2533 | if (statements.len == 0) return; |
| 2562 | 2534 | |
| ... | ... | @@ -2564,17 +2536,17 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2564 | 2536 | defer block_arena.deinit(); |
| 2565 | 2537 | const block_arena_allocator = block_arena.allocator(); |
| 2566 | 2538 | |
| 2567 | var noreturn_src_node: Ast.Node.Index = 0; | |
| 2539 | var noreturn_src_node: Ast.Node.OptionalIndex = .none; | |
| 2568 | 2540 | var scope = parent_scope; |
| 2569 | 2541 | for (statements, 0..) |statement, stmt_idx| { |
| 2570 | if (noreturn_src_node != 0) { | |
| 2542 | if (noreturn_src_node.unwrap()) |src_node| { | |
| 2571 | 2543 | try astgen.appendErrorNodeNotes( |
| 2572 | 2544 | statement, |
| 2573 | 2545 | "unreachable code", |
| 2574 | 2546 | .{}, |
| 2575 | 2547 | &[_]u32{ |
| 2576 | 2548 | try astgen.errNoteNode( |
| 2577 | noreturn_src_node, | |
| 2549 | src_node, | |
| 2578 | 2550 | "control flow is diverted here", |
| 2579 | 2551 | .{}, |
| 2580 | 2552 | ), |
| ... | ... | @@ -2587,7 +2559,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2587 | 2559 | }; |
| 2588 | 2560 | var inner_node = statement; |
| 2589 | 2561 | while (true) { |
| 2590 | switch (node_tags[inner_node]) { | |
| 2562 | switch (tree.nodeTag(inner_node)) { | |
| 2591 | 2563 | // zig fmt: off |
| 2592 | 2564 | .global_var_decl, |
| 2593 | 2565 | .local_var_decl, |
| ... | ... | @@ -2617,7 +2589,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2617 | 2589 | .assign_mul_wrap => try assignOp(gz, scope, statement, .mulwrap), |
| 2618 | 2590 | |
| 2619 | 2591 | .grouped_expression => { |
| 2620 | inner_node = node_data[statement].lhs; | |
| 2592 | inner_node = tree.nodeData(statement).node_and_token[0]; | |
| 2621 | 2593 | continue; |
| 2622 | 2594 | }, |
| 2623 | 2595 | |
| ... | ... | @@ -2649,15 +2621,15 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod |
| 2649 | 2621 | } |
| 2650 | 2622 | } |
| 2651 | 2623 | |
| 2652 | if (noreturn_src_node == 0) { | |
| 2624 | if (noreturn_src_node == .none) { | |
| 2653 | 2625 | try genDefers(gz, parent_scope, scope, .normal_only); |
| 2654 | 2626 | } |
| 2655 | 2627 | try checkUsed(gz, parent_scope, scope); |
| 2656 | 2628 | } |
| 2657 | 2629 | |
| 2658 | 2630 | /// Returns AST source node of the thing that is noreturn if the statement is |
| 2659 | /// definitely `noreturn`. Otherwise returns 0. | |
| 2660 | 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 { | |
| 2661 | 2633 | try emitDbgNode(gz, statement); |
| 2662 | 2634 | // We need to emit an error if the result is not `noreturn` or `void`, but |
| 2663 | 2635 | // we want to avoid adding the ZIR instruction if possible for performance. |
| ... | ... | @@ -2665,8 +2637,8 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner |
| 2665 | 2637 | return addEnsureResult(gz, maybe_unused_result, statement); |
| 2666 | 2638 | } |
| 2667 | 2639 | |
| 2668 | fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.Index { | |
| 2669 | var noreturn_src_node: Ast.Node.Index = 0; | |
| 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; | |
| 2670 | 2642 | const elide_check = if (maybe_unused_result.toIndex()) |inst| b: { |
| 2671 | 2643 | // Note that this array becomes invalid after appending more items to it |
| 2672 | 2644 | // in the above while loop. |
| ... | ... | @@ -2927,7 +2899,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2927 | 2899 | .check_comptime_control_flow, |
| 2928 | 2900 | .switch_continue, |
| 2929 | 2901 | => { |
| 2930 | noreturn_src_node = statement; | |
| 2902 | noreturn_src_node = statement.toOptional(); | |
| 2931 | 2903 | break :b true; |
| 2932 | 2904 | }, |
| 2933 | 2905 | |
| ... | ... | @@ -2969,7 +2941,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As |
| 2969 | 2941 | .none => unreachable, |
| 2970 | 2942 | |
| 2971 | 2943 | .unreachable_value => b: { |
| 2972 | noreturn_src_node = statement; | |
| 2944 | noreturn_src_node = statement.toOptional(); | |
| 2973 | 2945 | break :b true; |
| 2974 | 2946 | }, |
| 2975 | 2947 | |
| ... | ... | @@ -3098,23 +3070,23 @@ fn checkUsed(gz: *GenZir, outer_scope: *Scope, inner_scope: *Scope) InnerError!v |
| 3098 | 3070 | .gen_zir => scope = scope.cast(GenZir).?.parent, |
| 3099 | 3071 | .local_val => { |
| 3100 | 3072 | const s = scope.cast(Scope.LocalVal).?; |
| 3101 | if (s.used == 0 and s.discarded == 0) { | |
| 3073 | if (s.used == .none and s.discarded == .none) { | |
| 3102 | 3074 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3103 | } else if (s.used != 0 and s.discarded != 0) { | |
| 3104 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3105 | try gz.astgen.errNoteTok(s.used, "used here", .{}), | |
| 3075 | } else if (s.used != .none and s.discarded != .none) { | |
| 3076 | try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3077 | try gz.astgen.errNoteTok(s.used.unwrap().?, "used here", .{}), | |
| 3106 | 3078 | }); |
| 3107 | 3079 | } |
| 3108 | 3080 | scope = s.parent; |
| 3109 | 3081 | }, |
| 3110 | 3082 | .local_ptr => { |
| 3111 | 3083 | const s = scope.cast(Scope.LocalPtr).?; |
| 3112 | if (s.used == 0 and s.discarded == 0) { | |
| 3084 | if (s.used == .none and s.discarded == .none) { | |
| 3113 | 3085 | try astgen.appendErrorTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)}); |
| 3114 | 3086 | } else { |
| 3115 | if (s.used != 0 and s.discarded != 0) { | |
| 3116 | try astgen.appendErrorTokNotes(s.discarded, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3117 | try astgen.errNoteTok(s.used, "used here", .{}), | |
| 3087 | if (s.used != .none and s.discarded != .none) { | |
| 3088 | try astgen.appendErrorTokNotes(s.discarded.unwrap().?, "pointless discard of {s}", .{@tagName(s.id_cat)}, &[_]u32{ | |
| 3089 | try astgen.errNoteTok(s.used.unwrap().?, "used here", .{}), | |
| 3118 | 3090 | }); |
| 3119 | 3091 | } |
| 3120 | 3092 | if (s.id_cat == .@"local variable" and !s.used_as_lvalue) { |
| ... | ... | @@ -3141,19 +3113,15 @@ fn deferStmt( |
| 3141 | 3113 | scope_tag: Scope.Tag, |
| 3142 | 3114 | ) InnerError!*Scope { |
| 3143 | 3115 | var defer_gen = gz.makeSubBlock(scope); |
| 3144 | defer_gen.cur_defer_node = node; | |
| 3145 | defer_gen.any_defer_node = node; | |
| 3116 | defer_gen.cur_defer_node = node.toOptional(); | |
| 3117 | defer_gen.any_defer_node = node.toOptional(); | |
| 3146 | 3118 | defer defer_gen.unstack(); |
| 3147 | 3119 | |
| 3148 | 3120 | const tree = gz.astgen.tree; |
| 3149 | const node_datas = tree.nodes.items(.data); | |
| 3150 | const expr_node = node_datas[node].rhs; | |
| 3151 | ||
| 3152 | const payload_token = node_datas[node].lhs; | |
| 3153 | 3121 | var local_val_scope: Scope.LocalVal = undefined; |
| 3154 | 3122 | var opt_remapped_err_code: Zir.Inst.OptionalIndex = .none; |
| 3155 | const have_err_code = scope_tag == .defer_error and payload_token != 0; | |
| 3156 | const sub_scope = if (!have_err_code) &defer_gen.base else blk: { | |
| 3123 | const sub_scope = if (scope_tag != .defer_error) &defer_gen.base else blk: { | |
| 3124 | const payload_token = tree.nodeData(node).opt_token_and_node[0].unwrap() orelse break :blk &defer_gen.base; | |
| 3157 | 3125 | const ident_name = try gz.astgen.identAsString(payload_token); |
| 3158 | 3126 | if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) { |
| 3159 | 3127 | try gz.astgen.appendErrorTok(payload_token, "discard of error capture; omit it instead", .{}); |
| ... | ... | @@ -3181,6 +3149,11 @@ fn deferStmt( |
| 3181 | 3149 | try gz.addDbgVar(.dbg_var_val, ident_name, remapped_err_code_ref); |
| 3182 | 3150 | break :blk &local_val_scope.base; |
| 3183 | 3151 | }; |
| 3152 | const expr_node = switch (scope_tag) { | |
| 3153 | .defer_normal => tree.nodeData(node).node, | |
| 3154 | .defer_error => tree.nodeData(node).opt_token_and_node[1], | |
| 3155 | else => unreachable, | |
| 3156 | }; | |
| 3184 | 3157 | _ = try unusedResultExpr(&defer_gen, sub_scope, expr_node); |
| 3185 | 3158 | try checkUsed(gz, scope, sub_scope); |
| 3186 | 3159 | _ = try defer_gen.addBreak(.break_inline, @enumFromInt(0), .void_value); |
| ... | ... | @@ -3215,8 +3188,6 @@ fn varDecl( |
| 3215 | 3188 | try emitDbgNode(gz, node); |
| 3216 | 3189 | const astgen = gz.astgen; |
| 3217 | 3190 | const tree = astgen.tree; |
| 3218 | const token_tags = tree.tokens.items(.tag); | |
| 3219 | const main_tokens = tree.nodes.items(.main_token); | |
| 3220 | 3191 | |
| 3221 | 3192 | const name_token = var_decl.ast.mut_token + 1; |
| 3222 | 3193 | const ident_name_raw = tree.tokenSlice(name_token); |
| ... | ... | @@ -3230,27 +3201,27 @@ fn varDecl( |
| 3230 | 3201 | ident_name, |
| 3231 | 3202 | name_token, |
| 3232 | 3203 | ident_name_raw, |
| 3233 | if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable", | |
| 3204 | if (tree.tokenTag(var_decl.ast.mut_token) == .keyword_const) .@"local constant" else .@"local variable", | |
| 3234 | 3205 | ); |
| 3235 | 3206 | |
| 3236 | if (var_decl.ast.init_node == 0) { | |
| 3207 | const init_node = var_decl.ast.init_node.unwrap() orelse { | |
| 3237 | 3208 | return astgen.failNode(node, "variables must be initialized", .{}); |
| 3238 | } | |
| 3209 | }; | |
| 3239 | 3210 | |
| 3240 | if (var_decl.ast.addrspace_node != 0) { | |
| 3241 | return astgen.failTok(main_tokens[var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3211 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3212 | return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3242 | 3213 | } |
| 3243 | 3214 | |
| 3244 | if (var_decl.ast.section_node != 0) { | |
| 3245 | return astgen.failTok(main_tokens[var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3215 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 3216 | return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3246 | 3217 | } |
| 3247 | 3218 | |
| 3248 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) | |
| 3249 | try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node) | |
| 3219 | const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node| | |
| 3220 | try expr(gz, scope, coerced_align_ri, align_node) | |
| 3250 | 3221 | else |
| 3251 | 3222 | .none; |
| 3252 | 3223 | |
| 3253 | switch (token_tags[var_decl.ast.mut_token]) { | |
| 3224 | switch (tree.tokenTag(var_decl.ast.mut_token)) { | |
| 3254 | 3225 | .keyword_const => { |
| 3255 | 3226 | if (var_decl.comptime_token) |comptime_token| { |
| 3256 | 3227 | try astgen.appendErrorTok(comptime_token, "'comptime const' is redundant; instead wrap the initialization expression with 'comptime'", .{}); |
| ... | ... | @@ -3262,25 +3233,24 @@ fn varDecl( |
| 3262 | 3233 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 3263 | 3234 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 3264 | 3235 | // the variable, no memory location needed. |
| 3265 | const type_node = var_decl.ast.type_node; | |
| 3266 | 3236 | if (align_inst == .none and |
| 3267 | 3237 | !astgen.nodes_need_rl.contains(node)) |
| 3268 | 3238 | { |
| 3269 | const result_info: ResultInfo = if (type_node != 0) .{ | |
| 3239 | const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{ | |
| 3270 | 3240 | .rl = .{ .ty = try typeExpr(gz, scope, type_node) }, |
| 3271 | 3241 | .ctx = .const_init, |
| 3272 | 3242 | } else .{ .rl = .none, .ctx = .const_init }; |
| 3273 | 3243 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 3274 | 3244 | gz.anon_name_strategy = .dbg_var; |
| 3275 | const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3245 | const init_inst = try reachableExprComptime(gz, scope, result_info, init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3276 | 3246 | gz.anon_name_strategy = prev_anon_name_strategy; |
| 3277 | 3247 | |
| 3278 | _ = try gz.addUnNode(.validate_const, init_inst, var_decl.ast.init_node); | |
| 3248 | _ = try gz.addUnNode(.validate_const, init_inst, init_node); | |
| 3279 | 3249 | try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); |
| 3280 | 3250 | |
| 3281 | 3251 | // The const init expression may have modified the error return trace, so signal |
| 3282 | 3252 | // to Sema that it should save the new index for restoring later. |
| 3283 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) | |
| 3253 | if (nodeMayAppendToErrorTrace(tree, init_node)) | |
| 3284 | 3254 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 3285 | 3255 | |
| 3286 | 3256 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| ... | ... | @@ -3296,9 +3266,9 @@ fn varDecl( |
| 3296 | 3266 | } |
| 3297 | 3267 | |
| 3298 | 3268 | const is_comptime = gz.is_comptime or |
| 3299 | tree.nodes.items(.tag)[var_decl.ast.init_node] == .@"comptime"; | |
| 3269 | tree.nodeTag(init_node) == .@"comptime"; | |
| 3300 | 3270 | |
| 3301 | const init_rl: ResultInfo.Loc = if (type_node != 0) init_rl: { | |
| 3271 | const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: { | |
| 3302 | 3272 | const type_inst = try typeExpr(gz, scope, type_node); |
| 3303 | 3273 | if (align_inst == .none) { |
| 3304 | 3274 | break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } }; |
| ... | ... | @@ -3339,11 +3309,11 @@ fn varDecl( |
| 3339 | 3309 | const prev_anon_name_strategy = gz.anon_name_strategy; |
| 3340 | 3310 | gz.anon_name_strategy = .dbg_var; |
| 3341 | 3311 | defer gz.anon_name_strategy = prev_anon_name_strategy; |
| 3342 | const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3312 | const init_inst = try reachableExprComptime(gz, scope, init_result_info, init_node, node, if (force_comptime) .comptime_keyword else null); | |
| 3343 | 3313 | |
| 3344 | 3314 | // The const init expression may have modified the error return trace, so signal |
| 3345 | 3315 | // to Sema that it should save the new index for restoring later. |
| 3346 | if (nodeMayAppendToErrorTrace(tree, var_decl.ast.init_node)) | |
| 3316 | if (nodeMayAppendToErrorTrace(tree, init_node)) | |
| 3347 | 3317 | _ = try gz.addSaveErrRetIndex(.{ .if_of_error_type = init_inst }); |
| 3348 | 3318 | |
| 3349 | 3319 | const const_ptr = if (resolve_inferred) |
| ... | ... | @@ -3369,8 +3339,8 @@ fn varDecl( |
| 3369 | 3339 | if (var_decl.comptime_token != null and gz.is_comptime) |
| 3370 | 3340 | return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{}); |
| 3371 | 3341 | const is_comptime = var_decl.comptime_token != null or gz.is_comptime; |
| 3372 | const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node != 0) a: { | |
| 3373 | const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); | |
| 3342 | const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| a: { | |
| 3343 | const type_inst = try typeExpr(gz, scope, type_node); | |
| 3374 | 3344 | const alloc = alloc: { |
| 3375 | 3345 | if (align_inst == .none) { |
| 3376 | 3346 | const tag: Zir.Inst.Tag = if (is_comptime) |
| ... | ... | @@ -3415,7 +3385,7 @@ fn varDecl( |
| 3415 | 3385 | gz, |
| 3416 | 3386 | scope, |
| 3417 | 3387 | result_info, |
| 3418 | var_decl.ast.init_node, | |
| 3388 | init_node, | |
| 3419 | 3389 | node, |
| 3420 | 3390 | if (var_decl.comptime_token != null) .comptime_keyword else null, |
| 3421 | 3391 | ); |
| ... | ... | @@ -3458,15 +3428,11 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3458 | 3428 | try emitDbgNode(gz, infix_node); |
| 3459 | 3429 | const astgen = gz.astgen; |
| 3460 | 3430 | const tree = astgen.tree; |
| 3461 | const node_datas = tree.nodes.items(.data); | |
| 3462 | const main_tokens = tree.nodes.items(.main_token); | |
| 3463 | const node_tags = tree.nodes.items(.tag); | |
| 3464 | 3431 | |
| 3465 | const lhs = node_datas[infix_node].lhs; | |
| 3466 | const rhs = node_datas[infix_node].rhs; | |
| 3467 | if (node_tags[lhs] == .identifier) { | |
| 3432 | const lhs, const rhs = tree.nodeData(infix_node).node_and_node; | |
| 3433 | if (tree.nodeTag(lhs) == .identifier) { | |
| 3468 | 3434 | // This intentionally does not support `@"_"` syntax. |
| 3469 | const ident_name = tree.tokenSlice(main_tokens[lhs]); | |
| 3435 | const ident_name = tree.tokenSlice(tree.nodeMainToken(lhs)); | |
| 3470 | 3436 | if (mem.eql(u8, ident_name, "_")) { |
| 3471 | 3437 | _ = try expr(gz, scope, .{ .rl = .discard, .ctx = .assignment }, rhs); |
| 3472 | 3438 | return; |
| ... | ... | @@ -3484,8 +3450,6 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro |
| 3484 | 3450 | try emitDbgNode(gz, node); |
| 3485 | 3451 | const astgen = gz.astgen; |
| 3486 | 3452 | const tree = astgen.tree; |
| 3487 | const main_tokens = tree.nodes.items(.main_token); | |
| 3488 | const node_tags = tree.nodes.items(.tag); | |
| 3489 | 3453 | |
| 3490 | 3454 | const full = tree.assignDestructure(node); |
| 3491 | 3455 | if (full.comptime_token != null and gz.is_comptime) { |
| ... | ... | @@ -3503,9 +3467,9 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro |
| 3503 | 3467 | |
| 3504 | 3468 | const rl_components = try astgen.arena.alloc(ResultInfo.Loc.DestructureComponent, full.ast.variables.len); |
| 3505 | 3469 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3506 | if (node_tags[variable_node] == .identifier) { | |
| 3470 | if (tree.nodeTag(variable_node) == .identifier) { | |
| 3507 | 3471 | // This intentionally does not support `@"_"` syntax. |
| 3508 | const ident_name = tree.tokenSlice(main_tokens[variable_node]); | |
| 3472 | const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node)); | |
| 3509 | 3473 | if (mem.eql(u8, ident_name, "_")) { |
| 3510 | 3474 | variable_rl.* = .discard; |
| 3511 | 3475 | continue; |
| ... | ... | @@ -3542,9 +3506,6 @@ fn assignDestructureMaybeDecls( |
| 3542 | 3506 | try emitDbgNode(gz, node); |
| 3543 | 3507 | const astgen = gz.astgen; |
| 3544 | 3508 | const tree = astgen.tree; |
| 3545 | const token_tags = tree.tokens.items(.tag); | |
| 3546 | const main_tokens = tree.nodes.items(.main_token); | |
| 3547 | const node_tags = tree.nodes.items(.tag); | |
| 3548 | 3509 | |
| 3549 | 3510 | const full = tree.assignDestructure(node); |
| 3550 | 3511 | if (full.comptime_token != null and gz.is_comptime) { |
| ... | ... | @@ -3552,7 +3513,7 @@ fn assignDestructureMaybeDecls( |
| 3552 | 3513 | } |
| 3553 | 3514 | |
| 3554 | 3515 | const is_comptime = full.comptime_token != null or gz.is_comptime; |
| 3555 | const value_is_comptime = node_tags[full.ast.value_expr] == .@"comptime"; | |
| 3516 | const value_is_comptime = tree.nodeTag(full.ast.value_expr) == .@"comptime"; | |
| 3556 | 3517 | |
| 3557 | 3518 | // When declaring consts via a destructure, we always use a result pointer. |
| 3558 | 3519 | // This avoids the need to create tuple types, and is also likely easier to |
| ... | ... | @@ -3565,10 +3526,10 @@ fn assignDestructureMaybeDecls( |
| 3565 | 3526 | var any_non_const_variables = false; |
| 3566 | 3527 | var any_lvalue_expr = false; |
| 3567 | 3528 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3568 | switch (node_tags[variable_node]) { | |
| 3529 | switch (tree.nodeTag(variable_node)) { | |
| 3569 | 3530 | .identifier => { |
| 3570 | 3531 | // This intentionally does not support `@"_"` syntax. |
| 3571 | const ident_name = tree.tokenSlice(main_tokens[variable_node]); | |
| 3532 | const ident_name = tree.tokenSlice(tree.nodeMainToken(variable_node)); | |
| 3572 | 3533 | if (mem.eql(u8, ident_name, "_")) { |
| 3573 | 3534 | any_non_const_variables = true; |
| 3574 | 3535 | variable_rl.* = .discard; |
| ... | ... | @@ -3586,14 +3547,14 @@ fn assignDestructureMaybeDecls( |
| 3586 | 3547 | |
| 3587 | 3548 | // We detect shadowing in the second pass over these, while we're creating scopes. |
| 3588 | 3549 | |
| 3589 | if (full_var_decl.ast.addrspace_node != 0) { | |
| 3590 | return astgen.failTok(main_tokens[full_var_decl.ast.addrspace_node], "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3550 | if (full_var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3551 | return astgen.failTok(tree.nodeMainToken(addrspace_node), "cannot set address space of local variable '{s}'", .{ident_name_raw}); | |
| 3591 | 3552 | } |
| 3592 | if (full_var_decl.ast.section_node != 0) { | |
| 3593 | return astgen.failTok(main_tokens[full_var_decl.ast.section_node], "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3553 | if (full_var_decl.ast.section_node.unwrap()) |section_node| { | |
| 3554 | return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw}); | |
| 3594 | 3555 | } |
| 3595 | 3556 | |
| 3596 | const is_const = switch (token_tags[full_var_decl.ast.mut_token]) { | |
| 3557 | const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) { | |
| 3597 | 3558 | .keyword_var => false, |
| 3598 | 3559 | .keyword_const => true, |
| 3599 | 3560 | else => unreachable, |
| ... | ... | @@ -3603,14 +3564,14 @@ fn assignDestructureMaybeDecls( |
| 3603 | 3564 | // We also mark `const`s as comptime if the RHS is definitely comptime-known. |
| 3604 | 3565 | const this_variable_comptime = is_comptime or (is_const and value_is_comptime); |
| 3605 | 3566 | |
| 3606 | const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node != 0) | |
| 3607 | try expr(gz, scope, coerced_align_ri, full_var_decl.ast.align_node) | |
| 3567 | const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node| | |
| 3568 | try expr(gz, scope, coerced_align_ri, align_node) | |
| 3608 | 3569 | else |
| 3609 | 3570 | .none; |
| 3610 | 3571 | |
| 3611 | if (full_var_decl.ast.type_node != 0) { | |
| 3572 | if (full_var_decl.ast.type_node.unwrap()) |type_node| { | |
| 3612 | 3573 | // Typed alloc |
| 3613 | const type_inst = try typeExpr(gz, scope, full_var_decl.ast.type_node); | |
| 3574 | const type_inst = try typeExpr(gz, scope, type_node); | |
| 3614 | 3575 | const ptr = if (align_inst == .none) ptr: { |
| 3615 | 3576 | const tag: Zir.Inst.Tag = if (is_const) |
| 3616 | 3577 | .alloc |
| ... | ... | @@ -3679,7 +3640,7 @@ fn assignDestructureMaybeDecls( |
| 3679 | 3640 | // evaluate the lvalues from within the possible block_comptime. |
| 3680 | 3641 | for (rl_components, full.ast.variables) |*variable_rl, variable_node| { |
| 3681 | 3642 | if (variable_rl.* != .typed_ptr) continue; |
| 3682 | switch (node_tags[variable_node]) { | |
| 3643 | switch (tree.nodeTag(variable_node)) { | |
| 3683 | 3644 | .global_var_decl, .local_var_decl, .simple_var_decl, .aligned_var_decl => continue, |
| 3684 | 3645 | else => {}, |
| 3685 | 3646 | } |
| ... | ... | @@ -3708,7 +3669,7 @@ fn assignDestructureMaybeDecls( |
| 3708 | 3669 | // If there were any `const` decls, make the pointer constant. |
| 3709 | 3670 | var cur_scope = scope; |
| 3710 | 3671 | for (rl_components, full.ast.variables) |variable_rl, variable_node| { |
| 3711 | switch (node_tags[variable_node]) { | |
| 3672 | switch (tree.nodeTag(variable_node)) { | |
| 3712 | 3673 | .local_var_decl, .simple_var_decl, .aligned_var_decl => {}, |
| 3713 | 3674 | else => continue, // We were mutating an existing lvalue - nothing to do |
| 3714 | 3675 | } |
| ... | ... | @@ -3718,7 +3679,7 @@ fn assignDestructureMaybeDecls( |
| 3718 | 3679 | .typed_ptr => |typed_ptr| .{ typed_ptr.inst, false }, |
| 3719 | 3680 | .inferred_ptr => |ptr_inst| .{ ptr_inst, true }, |
| 3720 | 3681 | }; |
| 3721 | const is_const = switch (token_tags[full_var_decl.ast.mut_token]) { | |
| 3682 | const is_const = switch (tree.tokenTag(full_var_decl.ast.mut_token)) { | |
| 3722 | 3683 | .keyword_var => false, |
| 3723 | 3684 | .keyword_const => true, |
| 3724 | 3685 | else => unreachable, |
| ... | ... | @@ -3769,9 +3730,9 @@ fn assignOp( |
| 3769 | 3730 | try emitDbgNode(gz, infix_node); |
| 3770 | 3731 | const astgen = gz.astgen; |
| 3771 | 3732 | const tree = astgen.tree; |
| 3772 | const node_datas = tree.nodes.items(.data); | |
| 3773 | 3733 | |
| 3774 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3734 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3735 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3775 | 3736 | |
| 3776 | 3737 | const cursor = switch (op_inst_tag) { |
| 3777 | 3738 | .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node), |
| ... | ... | @@ -3797,7 +3758,7 @@ fn assignOp( |
| 3797 | 3758 | else => try gz.addUnNode(.typeof, lhs, infix_node), // same as LHS type |
| 3798 | 3759 | }; |
| 3799 | 3760 | // Not `coerced_ty` since `add`/etc won't coerce to this type. |
| 3800 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, node_datas[infix_node].rhs); | |
| 3761 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_res_ty } }, rhs_node); | |
| 3801 | 3762 | |
| 3802 | 3763 | switch (op_inst_tag) { |
| 3803 | 3764 | .add, .sub, .mul, .div, .mod_rem => { |
| ... | ... | @@ -3824,12 +3785,12 @@ fn assignShift( |
| 3824 | 3785 | try emitDbgNode(gz, infix_node); |
| 3825 | 3786 | const astgen = gz.astgen; |
| 3826 | 3787 | const tree = astgen.tree; |
| 3827 | const node_datas = tree.nodes.items(.data); | |
| 3828 | 3788 | |
| 3829 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3789 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3790 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3830 | 3791 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3831 | 3792 | const rhs_type = try gz.addUnNode(.typeof_log2_int_type, lhs, infix_node); |
| 3832 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, node_datas[infix_node].rhs); | |
| 3793 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = rhs_type } }, rhs_node); | |
| 3833 | 3794 | |
| 3834 | 3795 | const result = try gz.addPlNode(op_inst_tag, infix_node, Zir.Inst.Bin{ |
| 3835 | 3796 | .lhs = lhs, |
| ... | ... | @@ -3845,12 +3806,12 @@ fn assignShiftSat(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerE |
| 3845 | 3806 | try emitDbgNode(gz, infix_node); |
| 3846 | 3807 | const astgen = gz.astgen; |
| 3847 | 3808 | const tree = astgen.tree; |
| 3848 | const node_datas = tree.nodes.items(.data); | |
| 3849 | 3809 | |
| 3850 | const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs); | |
| 3810 | const lhs_node, const rhs_node = tree.nodeData(infix_node).node_and_node; | |
| 3811 | const lhs_ptr = try lvalExpr(gz, scope, lhs_node); | |
| 3851 | 3812 | const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node); |
| 3852 | 3813 | // Saturating shift-left allows any integer type for both the LHS and RHS. |
| 3853 | const rhs = try expr(gz, scope, .{ .rl = .none }, node_datas[infix_node].rhs); | |
| 3814 | const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node); | |
| 3854 | 3815 | |
| 3855 | 3816 | const result = try gz.addPlNode(.shl_sat, infix_node, Zir.Inst.Bin{ |
| 3856 | 3817 | .lhs = lhs, |
| ... | ... | @@ -3885,7 +3846,7 @@ fn ptrType( |
| 3885 | 3846 | var bit_end_ref: Zir.Inst.Ref = .none; |
| 3886 | 3847 | var trailing_count: u32 = 0; |
| 3887 | 3848 | |
| 3888 | if (ptr_info.ast.sentinel != 0) { | |
| 3849 | if (ptr_info.ast.sentinel.unwrap()) |sentinel| { | |
| 3889 | 3850 | // These attributes can appear in any order and they all come before the |
| 3890 | 3851 | // element type so we need to reset the source cursor before generating them. |
| 3891 | 3852 | gz.astgen.source_offset = source_offset; |
| ... | ... | @@ -3896,7 +3857,7 @@ fn ptrType( |
| 3896 | 3857 | gz, |
| 3897 | 3858 | scope, |
| 3898 | 3859 | .{ .rl = .{ .ty = elem_type } }, |
| 3899 | ptr_info.ast.sentinel, | |
| 3860 | sentinel, | |
| 3900 | 3861 | switch (ptr_info.size) { |
| 3901 | 3862 | .slice => .slice_sentinel, |
| 3902 | 3863 | else => .pointer_sentinel, |
| ... | ... | @@ -3904,27 +3865,27 @@ fn ptrType( |
| 3904 | 3865 | ); |
| 3905 | 3866 | trailing_count += 1; |
| 3906 | 3867 | } |
| 3907 | if (ptr_info.ast.addrspace_node != 0) { | |
| 3868 | if (ptr_info.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 3908 | 3869 | gz.astgen.source_offset = source_offset; |
| 3909 | 3870 | gz.astgen.source_line = source_line; |
| 3910 | 3871 | gz.astgen.source_column = source_column; |
| 3911 | 3872 | |
| 3912 | const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space); | |
| 3913 | addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node, .@"addrspace"); | |
| 3873 | const addrspace_ty = try gz.addBuiltinValue(addrspace_node, .address_space); | |
| 3874 | addrspace_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node, .@"addrspace"); | |
| 3914 | 3875 | trailing_count += 1; |
| 3915 | 3876 | } |
| 3916 | if (ptr_info.ast.align_node != 0) { | |
| 3877 | if (ptr_info.ast.align_node.unwrap()) |align_node| { | |
| 3917 | 3878 | gz.astgen.source_offset = source_offset; |
| 3918 | 3879 | gz.astgen.source_line = source_line; |
| 3919 | 3880 | gz.astgen.source_column = source_column; |
| 3920 | 3881 | |
| 3921 | align_ref = try comptimeExpr(gz, scope, coerced_align_ri, ptr_info.ast.align_node, .@"align"); | |
| 3882 | align_ref = try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align"); | |
| 3922 | 3883 | trailing_count += 1; |
| 3923 | 3884 | } |
| 3924 | if (ptr_info.ast.bit_range_start != 0) { | |
| 3925 | assert(ptr_info.ast.bit_range_end != 0); | |
| 3926 | bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_start, .type); | |
| 3927 | bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, ptr_info.ast.bit_range_end, .type); | |
| 3885 | if (ptr_info.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 3886 | const bit_range_end = ptr_info.ast.bit_range_end.unwrap().?; | |
| 3887 | bit_start_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_start, .type); | |
| 3888 | bit_end_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, bit_range_end, .type); | |
| 3928 | 3889 | trailing_count += 2; |
| 3929 | 3890 | } |
| 3930 | 3891 | |
| ... | ... | @@ -3977,18 +3938,15 @@ fn ptrType( |
| 3977 | 3938 | fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 3978 | 3939 | const astgen = gz.astgen; |
| 3979 | 3940 | const tree = astgen.tree; |
| 3980 | const node_datas = tree.nodes.items(.data); | |
| 3981 | const node_tags = tree.nodes.items(.tag); | |
| 3982 | const main_tokens = tree.nodes.items(.main_token); | |
| 3983 | 3941 | |
| 3984 | const len_node = node_datas[node].lhs; | |
| 3985 | if (node_tags[len_node] == .identifier and | |
| 3986 | mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_")) | |
| 3942 | const len_node, const elem_type_node = tree.nodeData(node).node_and_node; | |
| 3943 | if (tree.nodeTag(len_node) == .identifier and | |
| 3944 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_")) | |
| 3987 | 3945 | { |
| 3988 | 3946 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 3989 | 3947 | } |
| 3990 | 3948 | const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type); |
| 3991 | const elem_type = try typeExpr(gz, scope, node_datas[node].rhs); | |
| 3949 | const elem_type = try typeExpr(gz, scope, elem_type_node); | |
| 3992 | 3950 | |
| 3993 | 3951 | const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{ |
| 3994 | 3952 | .lhs = len, |
| ... | ... | @@ -4000,14 +3958,12 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) ! |
| 4000 | 3958 | fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !Zir.Inst.Ref { |
| 4001 | 3959 | const astgen = gz.astgen; |
| 4002 | 3960 | const tree = astgen.tree; |
| 4003 | const node_datas = tree.nodes.items(.data); | |
| 4004 | const node_tags = tree.nodes.items(.tag); | |
| 4005 | const main_tokens = tree.nodes.items(.main_token); | |
| 4006 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 4007 | ||
| 4008 | const len_node = node_datas[node].lhs; | |
| 4009 | if (node_tags[len_node] == .identifier and | |
| 4010 | mem.eql(u8, tree.tokenSlice(main_tokens[len_node]), "_")) | |
| 3961 | ||
| 3962 | const len_node, const extra_index = tree.nodeData(node).node_and_extra; | |
| 3963 | const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 3964 | ||
| 3965 | if (tree.nodeTag(len_node) == .identifier and | |
| 3966 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(len_node)), "_")) | |
| 4011 | 3967 | { |
| 4012 | 3968 | return astgen.failNode(len_node, "unable to infer array size", .{}); |
| 4013 | 3969 | } |
| ... | ... | @@ -4107,11 +4063,10 @@ fn fnDecl( |
| 4107 | 4063 | scope: *Scope, |
| 4108 | 4064 | wip_members: *WipMembers, |
| 4109 | 4065 | decl_node: Ast.Node.Index, |
| 4110 | body_node: Ast.Node.Index, | |
| 4066 | body_node: Ast.Node.OptionalIndex, | |
| 4111 | 4067 | fn_proto: Ast.full.FnProto, |
| 4112 | 4068 | ) InnerError!void { |
| 4113 | 4069 | const tree = astgen.tree; |
| 4114 | const token_tags = tree.tokens.items(.tag); | |
| 4115 | 4070 | |
| 4116 | 4071 | const old_hasher = astgen.src_hasher; |
| 4117 | 4072 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4140,15 +4095,15 @@ fn fnDecl( |
| 4140 | 4095 | const is_pub = fn_proto.visib_token != null; |
| 4141 | 4096 | const is_export = blk: { |
| 4142 | 4097 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4143 | break :blk token_tags[maybe_export_token] == .keyword_export; | |
| 4098 | break :blk tree.tokenTag(maybe_export_token) == .keyword_export; | |
| 4144 | 4099 | }; |
| 4145 | 4100 | const is_extern = blk: { |
| 4146 | 4101 | const maybe_extern_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4147 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 4102 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 4148 | 4103 | }; |
| 4149 | 4104 | const has_inline_keyword = blk: { |
| 4150 | 4105 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4151 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | |
| 4106 | break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline; | |
| 4152 | 4107 | }; |
| 4153 | 4108 | const lib_name = if (fn_proto.lib_name) |lib_name_token| blk: { |
| 4154 | 4109 | const lib_name_str = try astgen.strLitAsString(lib_name_token); |
| ... | ... | @@ -4160,16 +4115,18 @@ fn fnDecl( |
| 4160 | 4115 | } |
| 4161 | 4116 | break :blk lib_name_str.index; |
| 4162 | 4117 | } else .empty; |
| 4163 | if (fn_proto.ast.callconv_expr != 0 and has_inline_keyword) { | |
| 4118 | if (fn_proto.ast.callconv_expr != .none and has_inline_keyword) { | |
| 4164 | 4119 | return astgen.failNode( |
| 4165 | fn_proto.ast.callconv_expr, | |
| 4120 | fn_proto.ast.callconv_expr.unwrap().?, | |
| 4166 | 4121 | "explicit callconv incompatible with inline keyword", |
| 4167 | 4122 | .{}, |
| 4168 | 4123 | ); |
| 4169 | 4124 | } |
| 4170 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 4171 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 4172 | if (body_node == 0) { | |
| 4125 | ||
| 4126 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 4127 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 4128 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 4129 | if (body_node == .none) { | |
| 4173 | 4130 | if (!is_extern) { |
| 4174 | 4131 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function has no body", .{}); |
| 4175 | 4132 | } |
| ... | ... | @@ -4202,28 +4159,28 @@ fn fnDecl( |
| 4202 | 4159 | var align_gz = type_gz.makeSubBlock(scope); |
| 4203 | 4160 | defer align_gz.unstack(); |
| 4204 | 4161 | |
| 4205 | if (fn_proto.ast.align_expr != 0) { | |
| 4162 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 4206 | 4163 | astgen.restoreSourceCursor(saved_cursor); |
| 4207 | const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, fn_proto.ast.align_expr); | |
| 4164 | const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr); | |
| 4208 | 4165 | _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4209 | 4166 | } |
| 4210 | 4167 | |
| 4211 | 4168 | var linksection_gz = align_gz.makeSubBlock(scope); |
| 4212 | 4169 | defer linksection_gz.unstack(); |
| 4213 | 4170 | |
| 4214 | if (fn_proto.ast.section_expr != 0) { | |
| 4171 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 4215 | 4172 | astgen.restoreSourceCursor(saved_cursor); |
| 4216 | const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, fn_proto.ast.section_expr); | |
| 4173 | const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr); | |
| 4217 | 4174 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4218 | 4175 | } |
| 4219 | 4176 | |
| 4220 | 4177 | var addrspace_gz = linksection_gz.makeSubBlock(scope); |
| 4221 | 4178 | defer addrspace_gz.unstack(); |
| 4222 | 4179 | |
| 4223 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 4180 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 4224 | 4181 | astgen.restoreSourceCursor(saved_cursor); |
| 4225 | const addrspace_ty = try addrspace_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space); | |
| 4226 | const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr); | |
| 4182 | const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_expr, .address_space); | |
| 4183 | const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr); | |
| 4227 | 4184 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node); |
| 4228 | 4185 | } |
| 4229 | 4186 | |
| ... | ... | @@ -4233,7 +4190,7 @@ fn fnDecl( |
| 4233 | 4190 | if (!is_extern) { |
| 4234 | 4191 | // We include a function *value*, not a type. |
| 4235 | 4192 | astgen.restoreSourceCursor(saved_cursor); |
| 4236 | try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node, fn_proto); | |
| 4193 | try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto); | |
| 4237 | 4194 | } |
| 4238 | 4195 | |
| 4239 | 4196 | // *Now* we can incorporate the full source code into the hasher. |
| ... | ... | @@ -4272,18 +4229,19 @@ fn fnDeclInner( |
| 4272 | 4229 | fn_proto: Ast.full.FnProto, |
| 4273 | 4230 | ) InnerError!void { |
| 4274 | 4231 | const tree = astgen.tree; |
| 4275 | const token_tags = tree.tokens.items(.tag); | |
| 4276 | 4232 | |
| 4277 | 4233 | const is_noinline = blk: { |
| 4278 | 4234 | const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4279 | break :blk token_tags[maybe_noinline_token] == .keyword_noinline; | |
| 4235 | break :blk tree.tokenTag(maybe_noinline_token) == .keyword_noinline; | |
| 4280 | 4236 | }; |
| 4281 | 4237 | const has_inline_keyword = blk: { |
| 4282 | 4238 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 4283 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | |
| 4239 | break :blk tree.tokenTag(maybe_inline_token) == .keyword_inline; | |
| 4284 | 4240 | }; |
| 4285 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 4286 | const is_inferred_error = token_tags[maybe_bang] == .bang; | |
| 4241 | ||
| 4242 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 4243 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 4244 | const is_inferred_error = tree.tokenTag(maybe_bang) == .bang; | |
| 4287 | 4245 | |
| 4288 | 4246 | // Note that the capacity here may not be sufficient, as this does not include `anytype` parameters. |
| 4289 | 4247 | var param_insts: std.ArrayListUnmanaged(Zir.Inst.Index) = try .initCapacity(astgen.arena, fn_proto.ast.params.len); |
| ... | ... | @@ -4297,7 +4255,7 @@ fn fnDeclInner( |
| 4297 | 4255 | var param_type_i: usize = 0; |
| 4298 | 4256 | var it = fn_proto.iterate(tree); |
| 4299 | 4257 | while (it.next()) |param| : (param_type_i += 1) { |
| 4300 | const is_comptime = if (param.comptime_noalias) |token| switch (token_tags[token]) { | |
| 4258 | const is_comptime = if (param.comptime_noalias) |token| switch (tree.tokenTag(token)) { | |
| 4301 | 4259 | .keyword_noalias => is_comptime: { |
| 4302 | 4260 | noalias_bits |= @as(u32, 1) << (std.math.cast(u5, param_type_i) orelse |
| 4303 | 4261 | return astgen.failTok(token, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); |
| ... | ... | @@ -4308,7 +4266,7 @@ fn fnDeclInner( |
| 4308 | 4266 | } else false; |
| 4309 | 4267 | |
| 4310 | 4268 | const is_anytype = if (param.anytype_ellipsis3) |token| blk: { |
| 4311 | switch (token_tags[token]) { | |
| 4269 | switch (tree.tokenTag(token)) { | |
| 4312 | 4270 | .keyword_anytype => break :blk true, |
| 4313 | 4271 | .ellipsis3 => break :is_var_args true, |
| 4314 | 4272 | else => unreachable, |
| ... | ... | @@ -4327,30 +4285,31 @@ fn fnDeclInner( |
| 4327 | 4285 | if (param.anytype_ellipsis3) |tok| { |
| 4328 | 4286 | return astgen.failTok(tok, "missing parameter name", .{}); |
| 4329 | 4287 | } else { |
| 4288 | const type_expr = param.type_expr.?; | |
| 4330 | 4289 | ambiguous: { |
| 4331 | if (tree.nodes.items(.tag)[param.type_expr] != .identifier) break :ambiguous; | |
| 4332 | const main_token = tree.nodes.items(.main_token)[param.type_expr]; | |
| 4290 | if (tree.nodeTag(type_expr) != .identifier) break :ambiguous; | |
| 4291 | const main_token = tree.nodeMainToken(type_expr); | |
| 4333 | 4292 | const identifier_str = tree.tokenSlice(main_token); |
| 4334 | 4293 | if (isPrimitive(identifier_str)) break :ambiguous; |
| 4335 | 4294 | return astgen.failNodeNotes( |
| 4336 | param.type_expr, | |
| 4295 | type_expr, | |
| 4337 | 4296 | "missing parameter name or type", |
| 4338 | 4297 | .{}, |
| 4339 | 4298 | &[_]u32{ |
| 4340 | 4299 | try astgen.errNoteNode( |
| 4341 | param.type_expr, | |
| 4300 | type_expr, | |
| 4342 | 4301 | "if this is a name, annotate its type '{s}: T'", |
| 4343 | 4302 | .{identifier_str}, |
| 4344 | 4303 | ), |
| 4345 | 4304 | try astgen.errNoteNode( |
| 4346 | param.type_expr, | |
| 4305 | type_expr, | |
| 4347 | 4306 | "if this is a type, give it a name '<name>: {s}'", |
| 4348 | 4307 | .{identifier_str}, |
| 4349 | 4308 | ), |
| 4350 | 4309 | }, |
| 4351 | 4310 | ); |
| 4352 | 4311 | } |
| 4353 | return astgen.failNode(param.type_expr, "missing parameter name", .{}); | |
| 4312 | return astgen.failNode(type_expr, "missing parameter name", .{}); | |
| 4354 | 4313 | } |
| 4355 | 4314 | }; |
| 4356 | 4315 | |
| ... | ... | @@ -4362,8 +4321,7 @@ fn fnDeclInner( |
| 4362 | 4321 | .param_anytype; |
| 4363 | 4322 | break :param try decl_gz.addStrTok(tag, param_name, name_token); |
| 4364 | 4323 | } else param: { |
| 4365 | const param_type_node = param.type_expr; | |
| 4366 | assert(param_type_node != 0); | |
| 4324 | const param_type_node = param.type_expr.?; | |
| 4367 | 4325 | any_param_used = false; // we will check this later |
| 4368 | 4326 | var param_gz = decl_gz.makeSubBlock(scope); |
| 4369 | 4327 | defer param_gz.unstack(); |
| ... | ... | @@ -4372,8 +4330,7 @@ fn fnDeclInner( |
| 4372 | 4330 | _ = try param_gz.addBreakWithSrcNode(.break_inline, param_inst_expected, param_type, param_type_node); |
| 4373 | 4331 | const param_type_is_generic = any_param_used; |
| 4374 | 4332 | |
| 4375 | const main_tokens = tree.nodes.items(.main_token); | |
| 4376 | const name_token = param.name_token orelse main_tokens[param_type_node]; | |
| 4333 | const name_token = param.name_token orelse tree.nodeMainToken(param_type_node); | |
| 4377 | 4334 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 4378 | 4335 | const param_inst = try decl_gz.addParam(&param_gz, param_insts.items, param_type_is_generic, tag, name_token, param_name); |
| 4379 | 4336 | assert(param_inst_expected == param_inst); |
| ... | ... | @@ -4409,7 +4366,7 @@ fn fnDeclInner( |
| 4409 | 4366 | // Parameters are in scope for the return type, so we use `params_scope` here. |
| 4410 | 4367 | // The calling convention will not have parameters in scope, so we'll just use `scope`. |
| 4411 | 4368 | // See #22263 for a proposal to solve the inconsistency here. |
| 4412 | const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type, .normal); | |
| 4369 | const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal); | |
| 4413 | 4370 | if (ret_gz.instructionsSlice().len == 0) { |
| 4414 | 4371 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| 4415 | 4372 | break :inst inst; |
| ... | ... | @@ -4426,12 +4383,12 @@ fn fnDeclInner( |
| 4426 | 4383 | var cc_gz = decl_gz.makeSubBlock(scope); |
| 4427 | 4384 | defer cc_gz.unstack(); |
| 4428 | 4385 | const cc_ref: Zir.Inst.Ref = blk: { |
| 4429 | if (fn_proto.ast.callconv_expr != 0) { | |
| 4386 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 4430 | 4387 | const inst = try expr( |
| 4431 | 4388 | &cc_gz, |
| 4432 | 4389 | scope, |
| 4433 | .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, | |
| 4434 | fn_proto.ast.callconv_expr, | |
| 4390 | .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(callconv_expr, .calling_convention) } }, | |
| 4391 | callconv_expr, | |
| 4435 | 4392 | ); |
| 4436 | 4393 | if (cc_gz.instructionsSlice().len == 0) { |
| 4437 | 4394 | // In this case we will send a len=0 body which can be encoded more efficiently. |
| ... | ... | @@ -4470,7 +4427,7 @@ fn fnDeclInner( |
| 4470 | 4427 | // Leave `astgen.src_hasher` unmodified; this will be used for hashing |
| 4471 | 4428 | // the *whole* function declaration, including its body. |
| 4472 | 4429 | var proto_hasher = astgen.src_hasher; |
| 4473 | const proto_node = tree.nodes.items(.data)[decl_node].lhs; | |
| 4430 | const proto_node = tree.nodeData(decl_node).node_and_node[0]; | |
| 4474 | 4431 | proto_hasher.update(tree.getNodeSource(proto_node)); |
| 4475 | 4432 | var proto_hash: std.zig.SrcHash = undefined; |
| 4476 | 4433 | proto_hasher.final(&proto_hash); |
| ... | ... | @@ -4540,7 +4497,6 @@ fn globalVarDecl( |
| 4540 | 4497 | var_decl: Ast.full.VarDecl, |
| 4541 | 4498 | ) InnerError!void { |
| 4542 | 4499 | const tree = astgen.tree; |
| 4543 | const token_tags = tree.tokens.items(.tag); | |
| 4544 | 4500 | |
| 4545 | 4501 | const old_hasher = astgen.src_hasher; |
| 4546 | 4502 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4548,16 +4504,16 @@ fn globalVarDecl( |
| 4548 | 4504 | astgen.src_hasher.update(tree.getNodeSource(node)); |
| 4549 | 4505 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); |
| 4550 | 4506 | |
| 4551 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; | |
| 4507 | const is_mutable = tree.tokenTag(var_decl.ast.mut_token) == .keyword_var; | |
| 4552 | 4508 | const name_token = var_decl.ast.mut_token + 1; |
| 4553 | 4509 | const is_pub = var_decl.visib_token != null; |
| 4554 | 4510 | const is_export = blk: { |
| 4555 | 4511 | const maybe_export_token = var_decl.extern_export_token orelse break :blk false; |
| 4556 | break :blk token_tags[maybe_export_token] == .keyword_export; | |
| 4512 | break :blk tree.tokenTag(maybe_export_token) == .keyword_export; | |
| 4557 | 4513 | }; |
| 4558 | 4514 | const is_extern = blk: { |
| 4559 | 4515 | const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; |
| 4560 | break :blk token_tags[maybe_extern_token] == .keyword_extern; | |
| 4516 | break :blk tree.tokenTag(maybe_extern_token) == .keyword_extern; | |
| 4561 | 4517 | }; |
| 4562 | 4518 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 4563 | 4519 | if (!is_mutable) { |
| ... | ... | @@ -4583,10 +4539,10 @@ fn globalVarDecl( |
| 4583 | 4539 | const decl_inst = try gz.makeDeclaration(node); |
| 4584 | 4540 | wip_members.nextDecl(decl_inst); |
| 4585 | 4541 | |
| 4586 | if (var_decl.ast.init_node != 0) { | |
| 4542 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 4587 | 4543 | if (is_extern) { |
| 4588 | 4544 | return astgen.failNode( |
| 4589 | var_decl.ast.init_node, | |
| 4545 | init_node, | |
| 4590 | 4546 | "extern variables have no initializers", |
| 4591 | 4547 | .{}, |
| 4592 | 4548 | ); |
| ... | ... | @@ -4597,7 +4553,7 @@ fn globalVarDecl( |
| 4597 | 4553 | } |
| 4598 | 4554 | } |
| 4599 | 4555 | |
| 4600 | if (is_extern and var_decl.ast.type_node == 0) { | |
| 4556 | if (is_extern and var_decl.ast.type_node == .none) { | |
| 4601 | 4557 | return astgen.failNode(node, "unable to infer variable type", .{}); |
| 4602 | 4558 | } |
| 4603 | 4559 | |
| ... | ... | @@ -4614,45 +4570,45 @@ fn globalVarDecl( |
| 4614 | 4570 | }; |
| 4615 | 4571 | defer type_gz.unstack(); |
| 4616 | 4572 | |
| 4617 | if (var_decl.ast.type_node != 0) { | |
| 4618 | const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, var_decl.ast.type_node); | |
| 4573 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 4574 | const type_inst = try expr(&type_gz, &type_gz.base, coerced_type_ri, type_node); | |
| 4619 | 4575 | _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, node); |
| 4620 | 4576 | } |
| 4621 | 4577 | |
| 4622 | 4578 | var align_gz = type_gz.makeSubBlock(scope); |
| 4623 | 4579 | defer align_gz.unstack(); |
| 4624 | 4580 | |
| 4625 | if (var_decl.ast.align_node != 0) { | |
| 4626 | const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, var_decl.ast.align_node); | |
| 4581 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 4582 | const align_inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_node); | |
| 4627 | 4583 | _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node); |
| 4628 | 4584 | } |
| 4629 | 4585 | |
| 4630 | 4586 | var linksection_gz = type_gz.makeSubBlock(scope); |
| 4631 | 4587 | defer linksection_gz.unstack(); |
| 4632 | 4588 | |
| 4633 | if (var_decl.ast.section_node != 0) { | |
| 4634 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, var_decl.ast.section_node); | |
| 4589 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 4590 | const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node); | |
| 4635 | 4591 | _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node); |
| 4636 | 4592 | } |
| 4637 | 4593 | |
| 4638 | 4594 | var addrspace_gz = type_gz.makeSubBlock(scope); |
| 4639 | 4595 | defer addrspace_gz.unstack(); |
| 4640 | 4596 | |
| 4641 | if (var_decl.ast.addrspace_node != 0) { | |
| 4642 | const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space); | |
| 4643 | const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node); | |
| 4597 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 4598 | const addrspace_ty = try addrspace_gz.addBuiltinValue(addrspace_node, .address_space); | |
| 4599 | const addrspace_inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_node); | |
| 4644 | 4600 | _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node); |
| 4645 | 4601 | } |
| 4646 | 4602 | |
| 4647 | 4603 | var init_gz = type_gz.makeSubBlock(scope); |
| 4648 | 4604 | defer init_gz.unstack(); |
| 4649 | 4605 | |
| 4650 | if (var_decl.ast.init_node != 0) { | |
| 4606 | if (var_decl.ast.init_node.unwrap()) |init_node| { | |
| 4651 | 4607 | init_gz.anon_name_strategy = .parent; |
| 4652 | const init_ri: ResultInfo = if (var_decl.ast.type_node != 0) .{ | |
| 4608 | const init_ri: ResultInfo = if (var_decl.ast.type_node != .none) .{ | |
| 4653 | 4609 | .rl = .{ .coerced_ty = decl_inst.toRef() }, |
| 4654 | 4610 | } else .{ .rl = .none }; |
| 4655 | const init_inst = try expr(&init_gz, &init_gz.base, init_ri, var_decl.ast.init_node); | |
| 4611 | const init_inst = try expr(&init_gz, &init_gz.base, init_ri, init_node); | |
| 4656 | 4612 | _ = try init_gz.addBreakWithSrcNode(.break_inline, decl_inst, init_inst, node); |
| 4657 | 4613 | } |
| 4658 | 4614 | |
| ... | ... | @@ -4686,8 +4642,7 @@ fn comptimeDecl( |
| 4686 | 4642 | node: Ast.Node.Index, |
| 4687 | 4643 | ) InnerError!void { |
| 4688 | 4644 | const tree = astgen.tree; |
| 4689 | const node_datas = tree.nodes.items(.data); | |
| 4690 | const body_node = node_datas[node].lhs; | |
| 4645 | const body_node = tree.nodeData(node).node; | |
| 4691 | 4646 | |
| 4692 | 4647 | const old_hasher = astgen.src_hasher; |
| 4693 | 4648 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4750,7 +4705,6 @@ fn usingnamespaceDecl( |
| 4750 | 4705 | node: Ast.Node.Index, |
| 4751 | 4706 | ) InnerError!void { |
| 4752 | 4707 | const tree = astgen.tree; |
| 4753 | const node_datas = tree.nodes.items(.data); | |
| 4754 | 4708 | |
| 4755 | 4709 | const old_hasher = astgen.src_hasher; |
| 4756 | 4710 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4758,13 +4712,9 @@ fn usingnamespaceDecl( |
| 4758 | 4712 | astgen.src_hasher.update(tree.getNodeSource(node)); |
| 4759 | 4713 | astgen.src_hasher.update(std.mem.asBytes(&astgen.source_column)); |
| 4760 | 4714 | |
| 4761 | const type_expr = node_datas[node].lhs; | |
| 4762 | const is_pub = blk: { | |
| 4763 | const main_tokens = tree.nodes.items(.main_token); | |
| 4764 | const token_tags = tree.tokens.items(.tag); | |
| 4765 | const main_token = main_tokens[node]; | |
| 4766 | break :blk (main_token > 0 and token_tags[main_token - 1] == .keyword_pub); | |
| 4767 | }; | |
| 4715 | const type_expr = tree.nodeData(node).node; | |
| 4716 | const is_pub = tree.isTokenPrecededByTags(tree.nodeMainToken(node), &.{.keyword_pub}); | |
| 4717 | ||
| 4768 | 4718 | // Up top so the ZIR instruction index marks the start range of this |
| 4769 | 4719 | // top-level declaration. |
| 4770 | 4720 | const decl_inst = try gz.makeDeclaration(node); |
| ... | ... | @@ -4818,8 +4768,7 @@ fn testDecl( |
| 4818 | 4768 | node: Ast.Node.Index, |
| 4819 | 4769 | ) InnerError!void { |
| 4820 | 4770 | const tree = astgen.tree; |
| 4821 | const node_datas = tree.nodes.items(.data); | |
| 4822 | const body_node = node_datas[node].rhs; | |
| 4771 | _, const body_node = tree.nodeData(node).opt_token_and_node; | |
| 4823 | 4772 | |
| 4824 | 4773 | const old_hasher = astgen.src_hasher; |
| 4825 | 4774 | defer astgen.src_hasher = old_hasher; |
| ... | ... | @@ -4851,12 +4800,10 @@ fn testDecl( |
| 4851 | 4800 | |
| 4852 | 4801 | const decl_column = astgen.source_column; |
| 4853 | 4802 | |
| 4854 | const main_tokens = tree.nodes.items(.main_token); | |
| 4855 | const token_tags = tree.tokens.items(.tag); | |
| 4856 | const test_token = main_tokens[node]; | |
| 4803 | const test_token = tree.nodeMainToken(node); | |
| 4857 | 4804 | |
| 4858 | 4805 | const test_name_token = test_token + 1; |
| 4859 | const test_name: Zir.NullTerminatedString = switch (token_tags[test_name_token]) { | |
| 4806 | const test_name: Zir.NullTerminatedString = switch (tree.tokenTag(test_name_token)) { | |
| 4860 | 4807 | else => .empty, |
| 4861 | 4808 | .string_literal => name: { |
| 4862 | 4809 | const name = try astgen.strLitAsString(test_name_token); |
| ... | ... | @@ -4888,7 +4835,7 @@ fn testDecl( |
| 4888 | 4835 | .local_val => { |
| 4889 | 4836 | const local_val = s.cast(Scope.LocalVal).?; |
| 4890 | 4837 | if (local_val.name == name_str_index) { |
| 4891 | local_val.used = test_name_token; | |
| 4838 | local_val.used = .fromToken(test_name_token); | |
| 4892 | 4839 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| 4893 | 4840 | @tagName(local_val.id_cat), |
| 4894 | 4841 | }, &[_]u32{ |
| ... | ... | @@ -4902,7 +4849,7 @@ fn testDecl( |
| 4902 | 4849 | .local_ptr => { |
| 4903 | 4850 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 4904 | 4851 | if (local_ptr.name == name_str_index) { |
| 4905 | local_ptr.used = test_name_token; | |
| 4852 | local_ptr.used = .fromToken(test_name_token); | |
| 4906 | 4853 | return astgen.failTokNotes(test_name_token, "cannot test a {s}", .{ |
| 4907 | 4854 | @tagName(local_ptr.id_cat), |
| 4908 | 4855 | }, &[_]u32{ |
| ... | ... | @@ -5013,7 +4960,7 @@ fn testDecl( |
| 5013 | 4960 | .src_line = decl_block.decl_line, |
| 5014 | 4961 | .src_column = decl_column, |
| 5015 | 4962 | |
| 5016 | .kind = switch (token_tags[test_name_token]) { | |
| 4963 | .kind = switch (tree.tokenTag(test_name_token)) { | |
| 5017 | 4964 | .string_literal => .@"test", |
| 5018 | 4965 | .identifier => .decltest, |
| 5019 | 4966 | else => .unnamed_test, |
| ... | ... | @@ -5037,7 +4984,7 @@ fn structDeclInner( |
| 5037 | 4984 | node: Ast.Node.Index, |
| 5038 | 4985 | container_decl: Ast.full.ContainerDecl, |
| 5039 | 4986 | layout: std.builtin.Type.ContainerLayout, |
| 5040 | backing_int_node: Ast.Node.Index, | |
| 4987 | backing_int_node: Ast.Node.OptionalIndex, | |
| 5041 | 4988 | ) InnerError!Zir.Inst.Ref { |
| 5042 | 4989 | const astgen = gz.astgen; |
| 5043 | 4990 | const gpa = astgen.gpa; |
| ... | ... | @@ -5049,7 +4996,7 @@ fn structDeclInner( |
| 5049 | 4996 | if (container_field.ast.tuple_like) break member_node; |
| 5050 | 4997 | } else break :is_tuple; |
| 5051 | 4998 | |
| 5052 | if (node == 0) { | |
| 4999 | if (node == .root) { | |
| 5053 | 5000 | return astgen.failNode(tuple_field_node, "file cannot be a tuple", .{}); |
| 5054 | 5001 | } else { |
| 5055 | 5002 | return tupleDecl(gz, scope, node, container_decl, layout, backing_int_node); |
| ... | ... | @@ -5058,7 +5005,7 @@ fn structDeclInner( |
| 5058 | 5005 | |
| 5059 | 5006 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5060 | 5007 | |
| 5061 | if (container_decl.ast.members.len == 0 and backing_int_node == 0) { | |
| 5008 | if (container_decl.ast.members.len == 0 and backing_int_node == .none) { | |
| 5062 | 5009 | try gz.setStruct(decl_inst, .{ |
| 5063 | 5010 | .src_node = node, |
| 5064 | 5011 | .layout = layout, |
| ... | ... | @@ -5105,11 +5052,11 @@ fn structDeclInner( |
| 5105 | 5052 | |
| 5106 | 5053 | var backing_int_body_len: usize = 0; |
| 5107 | 5054 | const backing_int_ref: Zir.Inst.Ref = blk: { |
| 5108 | if (backing_int_node != 0) { | |
| 5055 | if (backing_int_node.unwrap()) |arg| { | |
| 5109 | 5056 | if (layout != .@"packed") { |
| 5110 | return astgen.failNode(backing_int_node, "non-packed struct does not support backing integer type", .{}); | |
| 5057 | return astgen.failNode(arg, "non-packed struct does not support backing integer type", .{}); | |
| 5111 | 5058 | } else { |
| 5112 | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, backing_int_node); | |
| 5059 | const backing_int_ref = try typeExpr(&block_scope, &namespace.base, arg); | |
| 5113 | 5060 | if (!block_scope.isEmpty()) { |
| 5114 | 5061 | if (!block_scope.endsWithNoReturn()) { |
| 5115 | 5062 | _ = try block_scope.addBreak(.break_inline, decl_inst, backing_int_ref); |
| ... | ... | @@ -5154,8 +5101,8 @@ fn structDeclInner( |
| 5154 | 5101 | defer astgen.src_hasher = old_hasher; |
| 5155 | 5102 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5156 | 5103 | astgen.src_hasher.update(@tagName(layout)); |
| 5157 | if (backing_int_node != 0) { | |
| 5158 | astgen.src_hasher.update(tree.getNodeSource(backing_int_node)); | |
| 5104 | if (backing_int_node.unwrap()) |arg| { | |
| 5105 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5159 | 5106 | } |
| 5160 | 5107 | |
| 5161 | 5108 | var known_non_opv = false; |
| ... | ... | @@ -5172,18 +5119,18 @@ fn structDeclInner( |
| 5172 | 5119 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5173 | 5120 | |
| 5174 | 5121 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5175 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5122 | member.convertToNonTupleLike(astgen.tree); | |
| 5176 | 5123 | assert(!member.ast.tuple_like); |
| 5177 | 5124 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5178 | 5125 | |
| 5179 | if (member.ast.type_expr == 0) { | |
| 5126 | const type_expr = member.ast.type_expr.unwrap() orelse { | |
| 5180 | 5127 | return astgen.failTok(member.ast.main_token, "struct field missing type", .{}); |
| 5181 | } | |
| 5128 | }; | |
| 5182 | 5129 | |
| 5183 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 5130 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5184 | 5131 | const have_type_body = !block_scope.isEmpty(); |
| 5185 | const have_align = member.ast.align_expr != 0; | |
| 5186 | const have_value = member.ast.value_expr != 0; | |
| 5132 | const have_align = member.ast.align_expr != .none; | |
| 5133 | const have_value = member.ast.value_expr != .none; | |
| 5187 | 5134 | const is_comptime = member.comptime_token != null; |
| 5188 | 5135 | |
| 5189 | 5136 | if (is_comptime) { |
| ... | ... | @@ -5193,9 +5140,9 @@ fn structDeclInner( |
| 5193 | 5140 | } |
| 5194 | 5141 | } else { |
| 5195 | 5142 | known_non_opv = known_non_opv or |
| 5196 | nodeImpliesMoreThanOnePossibleValue(tree, member.ast.type_expr); | |
| 5143 | nodeImpliesMoreThanOnePossibleValue(tree, type_expr); | |
| 5197 | 5144 | known_comptime_only = known_comptime_only or |
| 5198 | nodeImpliesComptimeOnly(tree, member.ast.type_expr); | |
| 5145 | nodeImpliesComptimeOnly(tree, type_expr); | |
| 5199 | 5146 | } |
| 5200 | 5147 | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, have_type_body }); |
| 5201 | 5148 | |
| ... | ... | @@ -5213,12 +5160,12 @@ fn structDeclInner( |
| 5213 | 5160 | wip_members.appendToField(@intFromEnum(field_type)); |
| 5214 | 5161 | } |
| 5215 | 5162 | |
| 5216 | if (have_align) { | |
| 5163 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5217 | 5164 | if (layout == .@"packed") { |
| 5218 | return astgen.failNode(member.ast.align_expr, "unable to override alignment of packed struct fields", .{}); | |
| 5165 | return astgen.failNode(align_expr, "unable to override alignment of packed struct fields", .{}); | |
| 5219 | 5166 | } |
| 5220 | 5167 | any_aligned_fields = true; |
| 5221 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, member.ast.align_expr); | |
| 5168 | const align_ref = try expr(&block_scope, &namespace.base, coerced_align_ri, align_expr); | |
| 5222 | 5169 | if (!block_scope.endsWithNoReturn()) { |
| 5223 | 5170 | _ = try block_scope.addBreak(.break_inline, decl_inst, align_ref); |
| 5224 | 5171 | } |
| ... | ... | @@ -5230,14 +5177,14 @@ fn structDeclInner( |
| 5230 | 5177 | block_scope.instructions.items.len = block_scope.instructions_top; |
| 5231 | 5178 | } |
| 5232 | 5179 | |
| 5233 | if (have_value) { | |
| 5180 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5234 | 5181 | any_default_inits = true; |
| 5235 | 5182 | |
| 5236 | 5183 | // The decl_inst is used as here so that we can easily reconstruct a mapping |
| 5237 | 5184 | // between it and the field type when the fields inits are analyzed. |
| 5238 | 5185 | const ri: ResultInfo = .{ .rl = if (field_type == .none) .none else .{ .coerced_ty = decl_inst.toRef() } }; |
| 5239 | 5186 | |
| 5240 | const default_inst = try expr(&block_scope, &namespace.base, ri, member.ast.value_expr); | |
| 5187 | const default_inst = try expr(&block_scope, &namespace.base, ri, value_expr); | |
| 5241 | 5188 | if (!block_scope.endsWithNoReturn()) { |
| 5242 | 5189 | _ = try block_scope.addBreak(.break_inline, decl_inst, default_inst); |
| 5243 | 5190 | } |
| ... | ... | @@ -5300,21 +5247,19 @@ fn tupleDecl( |
| 5300 | 5247 | node: Ast.Node.Index, |
| 5301 | 5248 | container_decl: Ast.full.ContainerDecl, |
| 5302 | 5249 | layout: std.builtin.Type.ContainerLayout, |
| 5303 | backing_int_node: Ast.Node.Index, | |
| 5250 | backing_int_node: Ast.Node.OptionalIndex, | |
| 5304 | 5251 | ) InnerError!Zir.Inst.Ref { |
| 5305 | 5252 | const astgen = gz.astgen; |
| 5306 | 5253 | const gpa = astgen.gpa; |
| 5307 | 5254 | const tree = astgen.tree; |
| 5308 | 5255 | |
| 5309 | const node_tags = tree.nodes.items(.tag); | |
| 5310 | ||
| 5311 | 5256 | switch (layout) { |
| 5312 | 5257 | .auto => {}, |
| 5313 | 5258 | .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}), |
| 5314 | 5259 | } |
| 5315 | 5260 | |
| 5316 | if (backing_int_node != 0) { | |
| 5317 | return astgen.failNode(backing_int_node, "tuple does not support backing integer type", .{}); | |
| 5261 | if (backing_int_node.unwrap()) |arg| { | |
| 5262 | return astgen.failNode(arg, "tuple does not support backing integer type", .{}); | |
| 5318 | 5263 | } |
| 5319 | 5264 | |
| 5320 | 5265 | // We will use the scratch buffer, starting here, for the field data: |
| ... | ... | @@ -5329,7 +5274,7 @@ fn tupleDecl( |
| 5329 | 5274 | |
| 5330 | 5275 | for (container_decl.ast.members) |member_node| { |
| 5331 | 5276 | const field = tree.fullContainerField(member_node) orelse { |
| 5332 | const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (node_tags[maybe_tuple]) { | |
| 5277 | const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) { | |
| 5333 | 5278 | .container_field_init, |
| 5334 | 5279 | .container_field_align, |
| 5335 | 5280 | .container_field, |
| ... | ... | @@ -5348,23 +5293,23 @@ fn tupleDecl( |
| 5348 | 5293 | return astgen.failTok(field.ast.main_token, "tuple field has a name", .{}); |
| 5349 | 5294 | } |
| 5350 | 5295 | |
| 5351 | if (field.ast.align_expr != 0) { | |
| 5296 | if (field.ast.align_expr != .none) { | |
| 5352 | 5297 | return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{}); |
| 5353 | 5298 | } |
| 5354 | 5299 | |
| 5355 | if (field.ast.value_expr != 0 and field.comptime_token == null) { | |
| 5300 | if (field.ast.value_expr != .none and field.comptime_token == null) { | |
| 5356 | 5301 | return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{}); |
| 5357 | 5302 | } |
| 5358 | 5303 | |
| 5359 | if (field.ast.value_expr == 0 and field.comptime_token != null) { | |
| 5304 | if (field.ast.value_expr == .none and field.comptime_token != null) { | |
| 5360 | 5305 | return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{}); |
| 5361 | 5306 | } |
| 5362 | 5307 | |
| 5363 | const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr); | |
| 5308 | const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?); | |
| 5364 | 5309 | astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref)); |
| 5365 | 5310 | |
| 5366 | if (field.ast.value_expr != 0) { | |
| 5367 | const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value); | |
| 5311 | if (field.ast.value_expr.unwrap()) |value_expr| { | |
| 5312 | const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, value_expr, .tuple_field_default_value); | |
| 5368 | 5313 | astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref)); |
| 5369 | 5314 | } else { |
| 5370 | 5315 | astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none)); |
| ... | ... | @@ -5399,7 +5344,7 @@ fn unionDeclInner( |
| 5399 | 5344 | node: Ast.Node.Index, |
| 5400 | 5345 | members: []const Ast.Node.Index, |
| 5401 | 5346 | layout: std.builtin.Type.ContainerLayout, |
| 5402 | arg_node: Ast.Node.Index, | |
| 5347 | opt_arg_node: Ast.Node.OptionalIndex, | |
| 5403 | 5348 | auto_enum_tok: ?Ast.TokenIndex, |
| 5404 | 5349 | ) InnerError!Zir.Inst.Ref { |
| 5405 | 5350 | const decl_inst = try gz.reserveInstructionIndex(); |
| ... | ... | @@ -5434,15 +5379,15 @@ fn unionDeclInner( |
| 5434 | 5379 | const decl_count = try astgen.scanContainer(&namespace, members, .@"union"); |
| 5435 | 5380 | const field_count: u32 = @intCast(members.len - decl_count); |
| 5436 | 5381 | |
| 5437 | if (layout != .auto and (auto_enum_tok != null or arg_node != 0)) { | |
| 5438 | if (arg_node != 0) { | |
| 5382 | if (layout != .auto and (auto_enum_tok != null or opt_arg_node != .none)) { | |
| 5383 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5439 | 5384 | return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5440 | 5385 | } else { |
| 5441 | 5386 | return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{@tagName(layout)}); |
| 5442 | 5387 | } |
| 5443 | 5388 | } |
| 5444 | 5389 | |
| 5445 | const arg_inst: Zir.Inst.Ref = if (arg_node != 0) | |
| 5390 | const arg_inst: Zir.Inst.Ref = if (opt_arg_node.unwrap()) |arg_node| | |
| 5446 | 5391 | try typeExpr(&block_scope, &namespace.base, arg_node) |
| 5447 | 5392 | else |
| 5448 | 5393 | .none; |
| ... | ... | @@ -5458,7 +5403,7 @@ fn unionDeclInner( |
| 5458 | 5403 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5459 | 5404 | astgen.src_hasher.update(@tagName(layout)); |
| 5460 | 5405 | astgen.src_hasher.update(&.{@intFromBool(auto_enum_tok != null)}); |
| 5461 | if (arg_node != 0) { | |
| 5406 | if (opt_arg_node.unwrap()) |arg_node| { | |
| 5462 | 5407 | astgen.src_hasher.update(astgen.tree.getNodeSource(arg_node)); |
| 5463 | 5408 | } |
| 5464 | 5409 | |
| ... | ... | @@ -5468,7 +5413,7 @@ fn unionDeclInner( |
| 5468 | 5413 | .field => |field| field, |
| 5469 | 5414 | }; |
| 5470 | 5415 | astgen.src_hasher.update(astgen.tree.getNodeSource(member_node)); |
| 5471 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5416 | member.convertToNonTupleLike(astgen.tree); | |
| 5472 | 5417 | if (member.ast.tuple_like) { |
| 5473 | 5418 | return astgen.failTok(member.ast.main_token, "union field missing name", .{}); |
| 5474 | 5419 | } |
| ... | ... | @@ -5479,24 +5424,24 @@ fn unionDeclInner( |
| 5479 | 5424 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5480 | 5425 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5481 | 5426 | |
| 5482 | const have_type = member.ast.type_expr != 0; | |
| 5483 | const have_align = member.ast.align_expr != 0; | |
| 5484 | const have_value = member.ast.value_expr != 0; | |
| 5427 | const have_type = member.ast.type_expr != .none; | |
| 5428 | const have_align = member.ast.align_expr != .none; | |
| 5429 | const have_value = member.ast.value_expr != .none; | |
| 5485 | 5430 | const unused = false; |
| 5486 | 5431 | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); |
| 5487 | 5432 | |
| 5488 | if (have_type) { | |
| 5489 | const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | |
| 5433 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5434 | const field_type = try typeExpr(&block_scope, &namespace.base, type_expr); | |
| 5490 | 5435 | wip_members.appendToField(@intFromEnum(field_type)); |
| 5491 | 5436 | } else if (arg_inst == .none and auto_enum_tok == null) { |
| 5492 | 5437 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 5493 | 5438 | } |
| 5494 | if (have_align) { | |
| 5495 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, member.ast.align_expr); | |
| 5439 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5440 | const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, align_expr); | |
| 5496 | 5441 | wip_members.appendToField(@intFromEnum(align_inst)); |
| 5497 | 5442 | any_aligned_fields = true; |
| 5498 | 5443 | } |
| 5499 | if (have_value) { | |
| 5444 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5500 | 5445 | if (arg_inst == .none) { |
| 5501 | 5446 | return astgen.failNodeNotes( |
| 5502 | 5447 | node, |
| ... | ... | @@ -5504,7 +5449,7 @@ fn unionDeclInner( |
| 5504 | 5449 | .{}, |
| 5505 | 5450 | &[_]u32{ |
| 5506 | 5451 | try astgen.errNoteNode( |
| 5507 | member.ast.value_expr, | |
| 5452 | value_expr, | |
| 5508 | 5453 | "tag value specified here", |
| 5509 | 5454 | .{}, |
| 5510 | 5455 | ), |
| ... | ... | @@ -5518,14 +5463,14 @@ fn unionDeclInner( |
| 5518 | 5463 | .{}, |
| 5519 | 5464 | &[_]u32{ |
| 5520 | 5465 | try astgen.errNoteNode( |
| 5521 | member.ast.value_expr, | |
| 5466 | value_expr, | |
| 5522 | 5467 | "tag value specified here", |
| 5523 | 5468 | .{}, |
| 5524 | 5469 | ), |
| 5525 | 5470 | }, |
| 5526 | 5471 | ); |
| 5527 | 5472 | } |
| 5528 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | |
| 5473 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5529 | 5474 | wip_members.appendToField(@intFromEnum(tag_value)); |
| 5530 | 5475 | } |
| 5531 | 5476 | } |
| ... | ... | @@ -5577,7 +5522,6 @@ fn containerDecl( |
| 5577 | 5522 | const astgen = gz.astgen; |
| 5578 | 5523 | const gpa = astgen.gpa; |
| 5579 | 5524 | const tree = astgen.tree; |
| 5580 | const token_tags = tree.tokens.items(.tag); | |
| 5581 | 5525 | |
| 5582 | 5526 | const prev_fn_block = astgen.fn_block; |
| 5583 | 5527 | astgen.fn_block = null; |
| ... | ... | @@ -5586,9 +5530,9 @@ fn containerDecl( |
| 5586 | 5530 | // We must not create any types until Sema. Here the goal is only to generate |
| 5587 | 5531 | // ZIR for all the field types, alignments, and default value expressions. |
| 5588 | 5532 | |
| 5589 | switch (token_tags[container_decl.ast.main_token]) { | |
| 5533 | switch (tree.tokenTag(container_decl.ast.main_token)) { | |
| 5590 | 5534 | .keyword_struct => { |
| 5591 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) { | |
| 5535 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) { | |
| 5592 | 5536 | .keyword_packed => .@"packed", |
| 5593 | 5537 | .keyword_extern => .@"extern", |
| 5594 | 5538 | else => unreachable, |
| ... | ... | @@ -5598,7 +5542,7 @@ fn containerDecl( |
| 5598 | 5542 | return rvalue(gz, ri, result, node); |
| 5599 | 5543 | }, |
| 5600 | 5544 | .keyword_union => { |
| 5601 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (token_tags[t]) { | |
| 5545 | const layout: std.builtin.Type.ContainerLayout = if (container_decl.layout_token) |t| switch (tree.tokenTag(t)) { | |
| 5602 | 5546 | .keyword_packed => .@"packed", |
| 5603 | 5547 | .keyword_extern => .@"extern", |
| 5604 | 5548 | else => unreachable, |
| ... | ... | @@ -5616,23 +5560,23 @@ fn containerDecl( |
| 5616 | 5560 | var values: usize = 0; |
| 5617 | 5561 | var total_fields: usize = 0; |
| 5618 | 5562 | var decls: usize = 0; |
| 5619 | var nonexhaustive_node: Ast.Node.Index = 0; | |
| 5563 | var opt_nonexhaustive_node: Ast.Node.OptionalIndex = .none; | |
| 5620 | 5564 | var nonfinal_nonexhaustive = false; |
| 5621 | 5565 | for (container_decl.ast.members) |member_node| { |
| 5622 | 5566 | var member = tree.fullContainerField(member_node) orelse { |
| 5623 | 5567 | decls += 1; |
| 5624 | 5568 | continue; |
| 5625 | 5569 | }; |
| 5626 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5570 | member.convertToNonTupleLike(astgen.tree); | |
| 5627 | 5571 | if (member.ast.tuple_like) { |
| 5628 | 5572 | return astgen.failTok(member.ast.main_token, "enum field missing name", .{}); |
| 5629 | 5573 | } |
| 5630 | 5574 | if (member.comptime_token) |comptime_token| { |
| 5631 | 5575 | return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{}); |
| 5632 | 5576 | } |
| 5633 | if (member.ast.type_expr != 0) { | |
| 5577 | if (member.ast.type_expr.unwrap()) |type_expr| { | |
| 5634 | 5578 | return astgen.failNodeNotes( |
| 5635 | member.ast.type_expr, | |
| 5579 | type_expr, | |
| 5636 | 5580 | "enum fields do not have types", |
| 5637 | 5581 | .{}, |
| 5638 | 5582 | &[_]u32{ |
| ... | ... | @@ -5644,13 +5588,13 @@ fn containerDecl( |
| 5644 | 5588 | }, |
| 5645 | 5589 | ); |
| 5646 | 5590 | } |
| 5647 | if (member.ast.align_expr != 0) { | |
| 5648 | return astgen.failNode(member.ast.align_expr, "enum fields cannot be aligned", .{}); | |
| 5591 | if (member.ast.align_expr.unwrap()) |align_expr| { | |
| 5592 | return astgen.failNode(align_expr, "enum fields cannot be aligned", .{}); | |
| 5649 | 5593 | } |
| 5650 | 5594 | |
| 5651 | 5595 | const name_token = member.ast.main_token; |
| 5652 | 5596 | if (mem.eql(u8, tree.tokenSlice(name_token), "_")) { |
| 5653 | if (nonexhaustive_node != 0) { | |
| 5597 | if (opt_nonexhaustive_node.unwrap()) |nonexhaustive_node| { | |
| 5654 | 5598 | return astgen.failNodeNotes( |
| 5655 | 5599 | member_node, |
| 5656 | 5600 | "redundant non-exhaustive enum mark", |
| ... | ... | @@ -5664,40 +5608,41 @@ fn containerDecl( |
| 5664 | 5608 | }, |
| 5665 | 5609 | ); |
| 5666 | 5610 | } |
| 5667 | nonexhaustive_node = member_node; | |
| 5668 | if (member.ast.value_expr != 0) { | |
| 5669 | return astgen.failNode(member.ast.value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5611 | opt_nonexhaustive_node = member_node.toOptional(); | |
| 5612 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5613 | return astgen.failNode(value_expr, "'_' is used to mark an enum as non-exhaustive and cannot be assigned a value", .{}); | |
| 5670 | 5614 | } |
| 5671 | 5615 | continue; |
| 5672 | } else if (nonexhaustive_node != 0) { | |
| 5616 | } else if (opt_nonexhaustive_node != .none) { | |
| 5673 | 5617 | nonfinal_nonexhaustive = true; |
| 5674 | 5618 | } |
| 5675 | 5619 | total_fields += 1; |
| 5676 | if (member.ast.value_expr != 0) { | |
| 5677 | if (container_decl.ast.arg == 0) { | |
| 5678 | return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{}); | |
| 5620 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5621 | if (container_decl.ast.arg == .none) { | |
| 5622 | return astgen.failNode(value_expr, "value assigned to enum tag with inferred tag type", .{}); | |
| 5679 | 5623 | } |
| 5680 | 5624 | values += 1; |
| 5681 | 5625 | } |
| 5682 | 5626 | } |
| 5683 | 5627 | if (nonfinal_nonexhaustive) { |
| 5684 | return astgen.failNode(nonexhaustive_node, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5628 | return astgen.failNode(opt_nonexhaustive_node.unwrap().?, "'_' field of non-exhaustive enum must be last", .{}); | |
| 5685 | 5629 | } |
| 5686 | 5630 | break :blk .{ |
| 5687 | 5631 | .total_fields = total_fields, |
| 5688 | 5632 | .values = values, |
| 5689 | 5633 | .decls = decls, |
| 5690 | .nonexhaustive_node = nonexhaustive_node, | |
| 5634 | .nonexhaustive_node = opt_nonexhaustive_node, | |
| 5691 | 5635 | }; |
| 5692 | 5636 | }; |
| 5693 | if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) { | |
| 5637 | if (counts.nonexhaustive_node != .none and container_decl.ast.arg == .none) { | |
| 5638 | const nonexhaustive_node = counts.nonexhaustive_node.unwrap().?; | |
| 5694 | 5639 | return astgen.failNodeNotes( |
| 5695 | 5640 | node, |
| 5696 | 5641 | "non-exhaustive enum missing integer tag type", |
| 5697 | 5642 | .{}, |
| 5698 | 5643 | &[_]u32{ |
| 5699 | 5644 | try astgen.errNoteNode( |
| 5700 | counts.nonexhaustive_node, | |
| 5645 | nonexhaustive_node, | |
| 5701 | 5646 | "marked non-exhaustive here", |
| 5702 | 5647 | .{}, |
| 5703 | 5648 | ), |
| ... | ... | @@ -5706,7 +5651,7 @@ fn containerDecl( |
| 5706 | 5651 | } |
| 5707 | 5652 | // In this case we must generate ZIR code for the tag values, similar to |
| 5708 | 5653 | // how structs are handled above. |
| 5709 | const nonexhaustive = counts.nonexhaustive_node != 0; | |
| 5654 | const nonexhaustive = counts.nonexhaustive_node != .none; | |
| 5710 | 5655 | |
| 5711 | 5656 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5712 | 5657 | |
| ... | ... | @@ -5736,8 +5681,8 @@ fn containerDecl( |
| 5736 | 5681 | _ = try astgen.scanContainer(&namespace, container_decl.ast.members, .@"enum"); |
| 5737 | 5682 | namespace.base.tag = .namespace; |
| 5738 | 5683 | |
| 5739 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) | |
| 5740 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type) | |
| 5684 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg.unwrap()) |arg| | |
| 5685 | try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, arg, .type) | |
| 5741 | 5686 | else |
| 5742 | 5687 | .none; |
| 5743 | 5688 | |
| ... | ... | @@ -5749,31 +5694,31 @@ fn containerDecl( |
| 5749 | 5694 | const old_hasher = astgen.src_hasher; |
| 5750 | 5695 | defer astgen.src_hasher = old_hasher; |
| 5751 | 5696 | astgen.src_hasher = std.zig.SrcHasher.init(.{}); |
| 5752 | if (container_decl.ast.arg != 0) { | |
| 5753 | astgen.src_hasher.update(tree.getNodeSource(container_decl.ast.arg)); | |
| 5697 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 5698 | astgen.src_hasher.update(tree.getNodeSource(arg)); | |
| 5754 | 5699 | } |
| 5755 | 5700 | astgen.src_hasher.update(&.{@intFromBool(nonexhaustive)}); |
| 5756 | 5701 | |
| 5757 | 5702 | for (container_decl.ast.members) |member_node| { |
| 5758 | if (member_node == counts.nonexhaustive_node) | |
| 5703 | if (member_node.toOptional() == counts.nonexhaustive_node) | |
| 5759 | 5704 | continue; |
| 5760 | 5705 | astgen.src_hasher.update(tree.getNodeSource(member_node)); |
| 5761 | 5706 | var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) { |
| 5762 | 5707 | .decl => continue, |
| 5763 | 5708 | .field => |field| field, |
| 5764 | 5709 | }; |
| 5765 | member.convertToNonTupleLike(astgen.tree.nodes); | |
| 5710 | member.convertToNonTupleLike(astgen.tree); | |
| 5766 | 5711 | assert(member.comptime_token == null); |
| 5767 | assert(member.ast.type_expr == 0); | |
| 5768 | assert(member.ast.align_expr == 0); | |
| 5712 | assert(member.ast.type_expr == .none); | |
| 5713 | assert(member.ast.align_expr == .none); | |
| 5769 | 5714 | |
| 5770 | 5715 | const field_name = try astgen.identAsString(member.ast.main_token); |
| 5771 | 5716 | wip_members.appendToField(@intFromEnum(field_name)); |
| 5772 | 5717 | |
| 5773 | const have_value = member.ast.value_expr != 0; | |
| 5718 | const have_value = member.ast.value_expr != .none; | |
| 5774 | 5719 | wip_members.nextField(bits_per_field, .{have_value}); |
| 5775 | 5720 | |
| 5776 | if (have_value) { | |
| 5721 | if (member.ast.value_expr.unwrap()) |value_expr| { | |
| 5777 | 5722 | if (arg_inst == .none) { |
| 5778 | 5723 | return astgen.failNodeNotes( |
| 5779 | 5724 | node, |
| ... | ... | @@ -5781,14 +5726,14 @@ fn containerDecl( |
| 5781 | 5726 | .{}, |
| 5782 | 5727 | &[_]u32{ |
| 5783 | 5728 | try astgen.errNoteNode( |
| 5784 | member.ast.value_expr, | |
| 5729 | value_expr, | |
| 5785 | 5730 | "tag value specified here", |
| 5786 | 5731 | .{}, |
| 5787 | 5732 | ), |
| 5788 | 5733 | }, |
| 5789 | 5734 | ); |
| 5790 | 5735 | } |
| 5791 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, member.ast.value_expr); | |
| 5736 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .rl = .{ .ty = arg_inst } }, value_expr); | |
| 5792 | 5737 | wip_members.appendToField(@intFromEnum(tag_value_inst)); |
| 5793 | 5738 | } |
| 5794 | 5739 | } |
| ... | ... | @@ -5828,7 +5773,7 @@ fn containerDecl( |
| 5828 | 5773 | return rvalue(gz, ri, decl_inst.toRef(), node); |
| 5829 | 5774 | }, |
| 5830 | 5775 | .keyword_opaque => { |
| 5831 | assert(container_decl.ast.arg == 0); | |
| 5776 | assert(container_decl.ast.arg == .none); | |
| 5832 | 5777 | |
| 5833 | 5778 | const decl_inst = try gz.reserveInstructionIndex(); |
| 5834 | 5779 | |
| ... | ... | @@ -5899,9 +5844,7 @@ fn containerMember( |
| 5899 | 5844 | ) InnerError!ContainerMemberResult { |
| 5900 | 5845 | const astgen = gz.astgen; |
| 5901 | 5846 | const tree = astgen.tree; |
| 5902 | const node_tags = tree.nodes.items(.tag); | |
| 5903 | const node_datas = tree.nodes.items(.data); | |
| 5904 | switch (node_tags[member_node]) { | |
| 5847 | switch (tree.nodeTag(member_node)) { | |
| 5905 | 5848 | .container_field_init, |
| 5906 | 5849 | .container_field_align, |
| 5907 | 5850 | .container_field, |
| ... | ... | @@ -5915,7 +5858,11 @@ fn containerMember( |
| 5915 | 5858 | => { |
| 5916 | 5859 | var buf: [1]Ast.Node.Index = undefined; |
| 5917 | 5860 | const full = tree.fullFnProto(&buf, member_node).?; |
| 5918 | const body = if (node_tags[member_node] == .fn_decl) node_datas[member_node].rhs else 0; | |
| 5861 | ||
| 5862 | const body: Ast.Node.OptionalIndex = if (tree.nodeTag(member_node) == .fn_decl) | |
| 5863 | tree.nodeData(member_node).node_and_node[1].toOptional() | |
| 5864 | else | |
| 5865 | .none; | |
| 5919 | 5866 | |
| 5920 | 5867 | const prev_decl_index = wip_members.decl_index; |
| 5921 | 5868 | astgen.fnDecl(gz, scope, wip_members, member_node, body, full) catch |err| switch (err) { |
| ... | ... | @@ -5986,12 +5933,7 @@ fn containerMember( |
| 5986 | 5933 | .@"usingnamespace", |
| 5987 | 5934 | .empty, |
| 5988 | 5935 | member_node, |
| 5989 | is_pub: { | |
| 5990 | const main_tokens = tree.nodes.items(.main_token); | |
| 5991 | const token_tags = tree.tokens.items(.tag); | |
| 5992 | const main_token = main_tokens[member_node]; | |
| 5993 | break :is_pub main_token > 0 and token_tags[main_token - 1] == .keyword_pub; | |
| 5994 | }, | |
| 5936 | tree.isTokenPrecededByTags(tree.nodeMainToken(member_node), &.{.keyword_pub}), | |
| 5995 | 5937 | ); |
| 5996 | 5938 | }, |
| 5997 | 5939 | }; |
| ... | ... | @@ -6025,8 +5967,6 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi |
| 6025 | 5967 | const astgen = gz.astgen; |
| 6026 | 5968 | const gpa = astgen.gpa; |
| 6027 | 5969 | const tree = astgen.tree; |
| 6028 | const main_tokens = tree.nodes.items(.main_token); | |
| 6029 | const token_tags = tree.tokens.items(.tag); | |
| 6030 | 5970 | |
| 6031 | 5971 | const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).@"struct".fields.len); |
| 6032 | 5972 | var fields_len: usize = 0; |
| ... | ... | @@ -6034,10 +5974,10 @@ fn errorSetDecl(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zi |
| 6034 | 5974 | var idents: std.AutoHashMapUnmanaged(Zir.NullTerminatedString, Ast.TokenIndex) = .empty; |
| 6035 | 5975 | defer idents.deinit(gpa); |
| 6036 | 5976 | |
| 6037 | const error_token = main_tokens[node]; | |
| 5977 | const error_token = tree.nodeMainToken(node); | |
| 6038 | 5978 | var tok_i = error_token + 2; |
| 6039 | 5979 | while (true) : (tok_i += 1) { |
| 6040 | switch (token_tags[tok_i]) { | |
| 5980 | switch (tree.tokenTag(tok_i)) { | |
| 6041 | 5981 | .doc_comment, .comma => {}, |
| 6042 | 5982 | .identifier => { |
| 6043 | 5983 | const str_index = try astgen.identAsString(tok_i); |
| ... | ... | @@ -6089,10 +6029,10 @@ fn tryExpr( |
| 6089 | 6029 | return astgen.failNode(node, "'try' outside function scope", .{}); |
| 6090 | 6030 | }; |
| 6091 | 6031 | |
| 6092 | if (parent_gz.any_defer_node != 0) { | |
| 6032 | if (parent_gz.any_defer_node.unwrap()) |any_defer_node| { | |
| 6093 | 6033 | return astgen.failNodeNotes(node, "'try' not allowed inside defer expression", .{}, &.{ |
| 6094 | 6034 | try astgen.errNoteNode( |
| 6095 | parent_gz.any_defer_node, | |
| 6035 | any_defer_node, | |
| 6096 | 6036 | "defer expression here", |
| 6097 | 6037 | .{}, |
| 6098 | 6038 | ), |
| ... | ... | @@ -6155,16 +6095,16 @@ fn orelseCatchExpr( |
| 6155 | 6095 | scope: *Scope, |
| 6156 | 6096 | ri: ResultInfo, |
| 6157 | 6097 | node: Ast.Node.Index, |
| 6158 | lhs: Ast.Node.Index, | |
| 6159 | 6098 | cond_op: Zir.Inst.Tag, |
| 6160 | 6099 | unwrap_op: Zir.Inst.Tag, |
| 6161 | 6100 | unwrap_code_op: Zir.Inst.Tag, |
| 6162 | rhs: Ast.Node.Index, | |
| 6163 | 6101 | payload_token: ?Ast.TokenIndex, |
| 6164 | 6102 | ) InnerError!Zir.Inst.Ref { |
| 6165 | 6103 | const astgen = parent_gz.astgen; |
| 6166 | 6104 | const tree = astgen.tree; |
| 6167 | 6105 | |
| 6106 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 6107 | ||
| 6168 | 6108 | const need_rl = astgen.nodes_need_rl.contains(node); |
| 6169 | 6109 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| 6170 | 6110 | .rl = switch (ri.rl) { |
| ... | ... | @@ -6297,12 +6237,8 @@ fn addFieldAccess( |
| 6297 | 6237 | ) InnerError!Zir.Inst.Ref { |
| 6298 | 6238 | const astgen = gz.astgen; |
| 6299 | 6239 | const tree = astgen.tree; |
| 6300 | const main_tokens = tree.nodes.items(.main_token); | |
| 6301 | const node_datas = tree.nodes.items(.data); | |
| 6302 | 6240 | |
| 6303 | const object_node = node_datas[node].lhs; | |
| 6304 | const dot_token = main_tokens[node]; | |
| 6305 | const field_ident = dot_token + 1; | |
| 6241 | const object_node, const field_ident = tree.nodeData(node).node_and_token; | |
| 6306 | 6242 | const str_index = try astgen.identAsString(field_ident); |
| 6307 | 6243 | const lhs = try expr(gz, scope, lhs_ri, object_node); |
| 6308 | 6244 | |
| ... | ... | @@ -6322,24 +6258,25 @@ fn arrayAccess( |
| 6322 | 6258 | node: Ast.Node.Index, |
| 6323 | 6259 | ) InnerError!Zir.Inst.Ref { |
| 6324 | 6260 | const tree = gz.astgen.tree; |
| 6325 | const node_datas = tree.nodes.items(.data); | |
| 6326 | 6261 | switch (ri.rl) { |
| 6327 | 6262 | .ref, .ref_coerced_ty => { |
| 6328 | const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs); | |
| 6263 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6264 | const lhs = try expr(gz, scope, .{ .rl = .ref }, lhs_node); | |
| 6329 | 6265 | |
| 6330 | 6266 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 6331 | 6267 | |
| 6332 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); | |
| 6268 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node); | |
| 6333 | 6269 | try emitDbgStmt(gz, cursor); |
| 6334 | 6270 | |
| 6335 | 6271 | return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); |
| 6336 | 6272 | }, |
| 6337 | 6273 | else => { |
| 6338 | const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs); | |
| 6274 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6275 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); | |
| 6339 | 6276 | |
| 6340 | 6277 | const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); |
| 6341 | 6278 | |
| 6342 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); | |
| 6279 | const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, rhs_node); | |
| 6343 | 6280 | try emitDbgStmt(gz, cursor); |
| 6344 | 6281 | |
| 6345 | 6282 | return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node); |
| ... | ... | @@ -6356,22 +6293,22 @@ fn simpleBinOp( |
| 6356 | 6293 | ) InnerError!Zir.Inst.Ref { |
| 6357 | 6294 | const astgen = gz.astgen; |
| 6358 | 6295 | const tree = astgen.tree; |
| 6359 | const node_datas = tree.nodes.items(.data); | |
| 6296 | ||
| 6297 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6360 | 6298 | |
| 6361 | 6299 | if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) { |
| 6362 | const node_tags = tree.nodes.items(.tag); | |
| 6363 | 6300 | const str = if (op_inst_tag == .cmp_eq) "==" else "!="; |
| 6364 | if (node_tags[node_datas[node].lhs] == .string_literal or | |
| 6365 | node_tags[node_datas[node].rhs] == .string_literal) | |
| 6301 | if (tree.nodeTag(lhs_node) == .string_literal or | |
| 6302 | tree.nodeTag(rhs_node) == .string_literal) | |
| 6366 | 6303 | return astgen.failNode(node, "cannot compare strings with {s}", .{str}); |
| 6367 | 6304 | } |
| 6368 | 6305 | |
| 6369 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); | |
| 6306 | const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, lhs_node, node); | |
| 6370 | 6307 | const cursor = switch (op_inst_tag) { |
| 6371 | 6308 | .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node), |
| 6372 | 6309 | else => undefined, |
| 6373 | 6310 | }; |
| 6374 | const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node); | |
| 6311 | const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, rhs_node, node); | |
| 6375 | 6312 | |
| 6376 | 6313 | switch (op_inst_tag) { |
| 6377 | 6314 | .add, .sub, .mul, .div, .mod_rem => { |
| ... | ... | @@ -6405,16 +6342,16 @@ fn boolBinOp( |
| 6405 | 6342 | ) InnerError!Zir.Inst.Ref { |
| 6406 | 6343 | const astgen = gz.astgen; |
| 6407 | 6344 | const tree = astgen.tree; |
| 6408 | const node_datas = tree.nodes.items(.data); | |
| 6409 | 6345 | |
| 6410 | const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs); | |
| 6346 | const lhs_node, const rhs_node = tree.nodeData(node).node_and_node; | |
| 6347 | const lhs = try expr(gz, scope, coerced_bool_ri, lhs_node); | |
| 6411 | 6348 | const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?; |
| 6412 | 6349 | |
| 6413 | 6350 | var rhs_scope = gz.makeSubBlock(scope); |
| 6414 | 6351 | defer rhs_scope.unstack(); |
| 6415 | const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs, .allow_branch_hint); | |
| 6352 | const rhs = try fullBodyExpr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, rhs_node, .allow_branch_hint); | |
| 6416 | 6353 | if (!gz.refIsNoReturn(rhs)) { |
| 6417 | _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs); | |
| 6354 | _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, rhs_node); | |
| 6418 | 6355 | } |
| 6419 | 6356 | try rhs_scope.setBoolBrBody(bool_br, lhs); |
| 6420 | 6357 | |
| ... | ... | @@ -6431,7 +6368,6 @@ fn ifExpr( |
| 6431 | 6368 | ) InnerError!Zir.Inst.Ref { |
| 6432 | 6369 | const astgen = parent_gz.astgen; |
| 6433 | 6370 | const tree = astgen.tree; |
| 6434 | const token_tags = tree.tokens.items(.tag); | |
| 6435 | 6371 | |
| 6436 | 6372 | const do_err_trace = astgen.fn_block != null and if_full.error_token != null; |
| 6437 | 6373 | |
| ... | ... | @@ -6454,7 +6390,7 @@ fn ifExpr( |
| 6454 | 6390 | defer block_scope.unstack(); |
| 6455 | 6391 | |
| 6456 | 6392 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 6457 | token_tags[payload_token] == .asterisk | |
| 6393 | tree.tokenTag(payload_token) == .asterisk | |
| 6458 | 6394 | else |
| 6459 | 6395 | false; |
| 6460 | 6396 | |
| ... | ... | @@ -6532,7 +6468,7 @@ fn ifExpr( |
| 6532 | 6468 | break :s &then_scope.base; |
| 6533 | 6469 | } |
| 6534 | 6470 | } else if (if_full.payload_token) |payload_token| { |
| 6535 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | |
| 6471 | const ident_token = payload_token + @intFromBool(payload_is_ref); | |
| 6536 | 6472 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 6537 | 6473 | .optional_payload_unsafe_ptr |
| 6538 | 6474 | else |
| ... | ... | @@ -6574,8 +6510,7 @@ fn ifExpr( |
| 6574 | 6510 | if (do_err_trace and nodeMayAppendToErrorTrace(tree, if_full.ast.cond_expr)) |
| 6575 | 6511 | _ = try else_scope.addSaveErrRetIndex(.always); |
| 6576 | 6512 | |
| 6577 | const else_node = if_full.ast.else_expr; | |
| 6578 | if (else_node != 0) { | |
| 6513 | if (if_full.ast.else_expr.unwrap()) |else_node| { | |
| 6579 | 6514 | const sub_scope = s: { |
| 6580 | 6515 | if (if_full.error_token) |error_token| { |
| 6581 | 6516 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -6663,8 +6598,6 @@ fn whileExpr( |
| 6663 | 6598 | ) InnerError!Zir.Inst.Ref { |
| 6664 | 6599 | const astgen = parent_gz.astgen; |
| 6665 | 6600 | const tree = astgen.tree; |
| 6666 | const token_tags = tree.tokens.items(.tag); | |
| 6667 | const token_starts = tree.tokens.items(.start); | |
| 6668 | 6601 | |
| 6669 | 6602 | const need_rl = astgen.nodes_need_rl.contains(node); |
| 6670 | 6603 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| ... | ... | @@ -6701,7 +6634,7 @@ fn whileExpr( |
| 6701 | 6634 | defer cond_scope.unstack(); |
| 6702 | 6635 | |
| 6703 | 6636 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 6704 | token_tags[payload_token] == .asterisk | |
| 6637 | tree.tokenTag(payload_token) == .asterisk | |
| 6705 | 6638 | else |
| 6706 | 6639 | false; |
| 6707 | 6640 | |
| ... | ... | @@ -6787,7 +6720,6 @@ fn whileExpr( |
| 6787 | 6720 | break :s &then_scope.base; |
| 6788 | 6721 | } |
| 6789 | 6722 | } else if (while_full.payload_token) |payload_token| { |
| 6790 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | |
| 6791 | 6723 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| 6792 | 6724 | .optional_payload_unsafe_ptr |
| 6793 | 6725 | else |
| ... | ... | @@ -6795,6 +6727,7 @@ fn whileExpr( |
| 6795 | 6727 | // will add this instruction to then_scope.instructions below |
| 6796 | 6728 | const payload_inst = try then_scope.makeUnNode(tag, cond.inst, while_full.ast.cond_expr); |
| 6797 | 6729 | opt_payload_inst = payload_inst.toOptional(); |
| 6730 | const ident_token = payload_token + @intFromBool(payload_is_ref); | |
| 6798 | 6731 | const ident_name = try astgen.identAsString(ident_token); |
| 6799 | 6732 | const ident_bytes = tree.tokenSlice(ident_token); |
| 6800 | 6733 | if (mem.eql(u8, "_", ident_bytes)) { |
| ... | ... | @@ -6849,8 +6782,8 @@ fn whileExpr( |
| 6849 | 6782 | // are no jumps to it. This happens when the last statement of a while body is noreturn |
| 6850 | 6783 | // and there are no `continue` statements. |
| 6851 | 6784 | // Tracking issue: https://github.com/ziglang/zig/issues/9185 |
| 6852 | if (while_full.ast.cont_expr != 0) { | |
| 6853 | _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr); | |
| 6785 | if (while_full.ast.cont_expr.unwrap()) |cont_expr| { | |
| 6786 | _ = try unusedResultExpr(&then_scope, then_sub_scope, cont_expr); | |
| 6854 | 6787 | } |
| 6855 | 6788 | |
| 6856 | 6789 | continue_scope.instructions_top = continue_scope.instructions.items.len; |
| ... | ... | @@ -6862,7 +6795,7 @@ fn whileExpr( |
| 6862 | 6795 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 6863 | 6796 | const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break"; |
| 6864 | 6797 | if (!continue_scope.endsWithNoReturn()) { |
| 6865 | astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); | |
| 6798 | astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node))); | |
| 6866 | 6799 | try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); |
| 6867 | 6800 | _ = try parent_gz.add(.{ |
| 6868 | 6801 | .tag = .extended, |
| ... | ... | @@ -6880,8 +6813,7 @@ fn whileExpr( |
| 6880 | 6813 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 6881 | 6814 | defer else_scope.unstack(); |
| 6882 | 6815 | |
| 6883 | const else_node = while_full.ast.else_expr; | |
| 6884 | if (else_node != 0) { | |
| 6816 | if (while_full.ast.else_expr.unwrap()) |else_node| { | |
| 6885 | 6817 | const sub_scope = s: { |
| 6886 | 6818 | if (while_full.error_token) |error_token| { |
| 6887 | 6819 | const tag: Zir.Inst.Tag = if (payload_is_ref) |
| ... | ... | @@ -6979,10 +6911,6 @@ fn forExpr( |
| 6979 | 6911 | try astgen.appendErrorTok(for_full.inline_token.?, "redundant inline keyword in comptime scope", .{}); |
| 6980 | 6912 | } |
| 6981 | 6913 | const tree = astgen.tree; |
| 6982 | const token_tags = tree.tokens.items(.tag); | |
| 6983 | const token_starts = tree.tokens.items(.start); | |
| 6984 | const node_tags = tree.nodes.items(.tag); | |
| 6985 | const node_data = tree.nodes.items(.data); | |
| 6986 | 6914 | const gpa = astgen.gpa; |
| 6987 | 6915 | |
| 6988 | 6916 | // For counters, this is the start value; for indexables, this is the base |
| ... | ... | @@ -7012,7 +6940,7 @@ fn forExpr( |
| 7012 | 6940 | { |
| 7013 | 6941 | var capture_token = for_full.payload_token; |
| 7014 | 6942 | for (for_full.ast.inputs, indexables, lens) |input, *indexable_ref, *len_refs| { |
| 7015 | const capture_is_ref = token_tags[capture_token] == .asterisk; | |
| 6943 | const capture_is_ref = tree.tokenTag(capture_token) == .asterisk; | |
| 7016 | 6944 | const ident_tok = capture_token + @intFromBool(capture_is_ref); |
| 7017 | 6945 | const is_discard = mem.eql(u8, tree.tokenSlice(ident_tok), "_"); |
| 7018 | 6946 | |
| ... | ... | @@ -7023,16 +6951,15 @@ fn forExpr( |
| 7023 | 6951 | capture_token = ident_tok + 2; |
| 7024 | 6952 | |
| 7025 | 6953 | try emitDbgNode(parent_gz, input); |
| 7026 | if (node_tags[input] == .for_range) { | |
| 6954 | if (tree.nodeTag(input) == .for_range) { | |
| 7027 | 6955 | if (capture_is_ref) { |
| 7028 | 6956 | return astgen.failTok(ident_tok, "cannot capture reference to range", .{}); |
| 7029 | 6957 | } |
| 7030 | const start_node = node_data[input].lhs; | |
| 6958 | const start_node, const end_node = tree.nodeData(input).node_and_opt_node; | |
| 7031 | 6959 | const start_val = try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, start_node); |
| 7032 | 6960 | |
| 7033 | const end_node = node_data[input].rhs; | |
| 7034 | const end_val = if (end_node != 0) | |
| 7035 | try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_data[input].rhs) | |
| 6961 | const end_val = if (end_node.unwrap()) |end| | |
| 6962 | try expr(parent_gz, scope, .{ .rl = .{ .ty = .usize_type } }, end) | |
| 7036 | 6963 | else |
| 7037 | 6964 | .none; |
| 7038 | 6965 | |
| ... | ... | @@ -7125,7 +7052,7 @@ fn forExpr( |
| 7125 | 7052 | var capture_token = for_full.payload_token; |
| 7126 | 7053 | var capture_sub_scope: *Scope = &then_scope.base; |
| 7127 | 7054 | for (for_full.ast.inputs, indexables, capture_scopes) |input, indexable_ref, *capture_scope| { |
| 7128 | const capture_is_ref = token_tags[capture_token] == .asterisk; | |
| 7055 | const capture_is_ref = tree.tokenTag(capture_token) == .asterisk; | |
| 7129 | 7056 | const ident_tok = capture_token + @intFromBool(capture_is_ref); |
| 7130 | 7057 | const capture_name = tree.tokenSlice(ident_tok); |
| 7131 | 7058 | // Skip over the comma, and on to the next capture (or the ending pipe character). |
| ... | ... | @@ -7137,7 +7064,7 @@ fn forExpr( |
| 7137 | 7064 | try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture); |
| 7138 | 7065 | |
| 7139 | 7066 | const capture_inst = inst: { |
| 7140 | const is_counter = node_tags[input] == .for_range; | |
| 7067 | const is_counter = tree.nodeTag(input) == .for_range; | |
| 7141 | 7068 | |
| 7142 | 7069 | if (indexable_ref == .none) { |
| 7143 | 7070 | // Special case: the main index can be used directly. |
| ... | ... | @@ -7184,7 +7111,7 @@ fn forExpr( |
| 7184 | 7111 | |
| 7185 | 7112 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 7186 | 7113 | |
| 7187 | astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]); | |
| 7114 | astgen.advanceSourceCursor(tree.tokenStart(tree.lastToken(then_node))); | |
| 7188 | 7115 | try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column }); |
| 7189 | 7116 | _ = try parent_gz.add(.{ |
| 7190 | 7117 | .tag = .extended, |
| ... | ... | @@ -7201,8 +7128,7 @@ fn forExpr( |
| 7201 | 7128 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 7202 | 7129 | defer else_scope.unstack(); |
| 7203 | 7130 | |
| 7204 | const else_node = for_full.ast.else_expr; | |
| 7205 | if (else_node != 0) { | |
| 7131 | if (for_full.ast.else_expr.unwrap()) |else_node| { | |
| 7206 | 7132 | const sub_scope = &else_scope.base; |
| 7207 | 7133 | // Remove the continue block and break block so that `continue` and `break` |
| 7208 | 7134 | // control flow apply to outer loops; not this one. |
| ... | ... | @@ -7270,10 +7196,6 @@ fn switchExprErrUnion( |
| 7270 | 7196 | const astgen = parent_gz.astgen; |
| 7271 | 7197 | const gpa = astgen.gpa; |
| 7272 | 7198 | const tree = astgen.tree; |
| 7273 | const node_datas = tree.nodes.items(.data); | |
| 7274 | const node_tags = tree.nodes.items(.tag); | |
| 7275 | const main_tokens = tree.nodes.items(.main_token); | |
| 7276 | const token_tags = tree.tokens.items(.tag); | |
| 7277 | 7199 | |
| 7278 | 7200 | const if_full = switch (node_ty) { |
| 7279 | 7201 | .@"catch" => undefined, |
| ... | ... | @@ -7282,23 +7204,19 @@ fn switchExprErrUnion( |
| 7282 | 7204 | |
| 7283 | 7205 | const switch_node, const operand_node, const error_payload = switch (node_ty) { |
| 7284 | 7206 | .@"catch" => .{ |
| 7285 | node_datas[catch_or_if_node].rhs, | |
| 7286 | node_datas[catch_or_if_node].lhs, | |
| 7287 | main_tokens[catch_or_if_node] + 2, | |
| 7207 | tree.nodeData(catch_or_if_node).node_and_node[1], | |
| 7208 | tree.nodeData(catch_or_if_node).node_and_node[0], | |
| 7209 | tree.nodeMainToken(catch_or_if_node) + 2, | |
| 7288 | 7210 | }, |
| 7289 | 7211 | .@"if" => .{ |
| 7290 | if_full.ast.else_expr, | |
| 7212 | if_full.ast.else_expr.unwrap().?, | |
| 7291 | 7213 | if_full.ast.cond_expr, |
| 7292 | 7214 | if_full.error_token.?, |
| 7293 | 7215 | }, |
| 7294 | 7216 | }; |
| 7295 | assert(node_tags[switch_node] == .@"switch" or node_tags[switch_node] == .switch_comma); | |
| 7217 | const switch_full = tree.fullSwitch(switch_node).?; | |
| 7296 | 7218 | |
| 7297 | 7219 | const do_err_trace = astgen.fn_block != null; |
| 7298 | ||
| 7299 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 7300 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 7301 | ||
| 7302 | 7220 | const need_rl = astgen.nodes_need_rl.contains(catch_or_if_node); |
| 7303 | 7221 | const block_ri: ResultInfo = if (need_rl) ri else .{ |
| 7304 | 7222 | .rl = switch (ri.rl) { |
| ... | ... | @@ -7310,7 +7228,7 @@ fn switchExprErrUnion( |
| 7310 | 7228 | }; |
| 7311 | 7229 | |
| 7312 | 7230 | const payload_is_ref = switch (node_ty) { |
| 7313 | .@"if" => if_full.payload_token != null and token_tags[if_full.payload_token.?] == .asterisk, | |
| 7231 | .@"if" => if_full.payload_token != null and tree.tokenTag(if_full.payload_token.?) == .asterisk, | |
| 7314 | 7232 | .@"catch" => ri.rl == .ref or ri.rl == .ref_coerced_ty, |
| 7315 | 7233 | }; |
| 7316 | 7234 | |
| ... | ... | @@ -7322,9 +7240,9 @@ fn switchExprErrUnion( |
| 7322 | 7240 | var multi_cases_len: u32 = 0; |
| 7323 | 7241 | var inline_cases_len: u32 = 0; |
| 7324 | 7242 | var has_else = false; |
| 7325 | var else_node: Ast.Node.Index = 0; | |
| 7243 | var else_node: Ast.Node.OptionalIndex = .none; | |
| 7326 | 7244 | var else_src: ?Ast.TokenIndex = null; |
| 7327 | for (case_nodes) |case_node| { | |
| 7245 | for (switch_full.ast.cases) |case_node| { | |
| 7328 | 7246 | const case = tree.fullSwitchCase(case_node).?; |
| 7329 | 7247 | |
| 7330 | 7248 | if (case.ast.values.len == 0) { |
| ... | ... | @@ -7344,12 +7262,12 @@ fn switchExprErrUnion( |
| 7344 | 7262 | ); |
| 7345 | 7263 | } |
| 7346 | 7264 | has_else = true; |
| 7347 | else_node = case_node; | |
| 7265 | else_node = case_node.toOptional(); | |
| 7348 | 7266 | else_src = case_src; |
| 7349 | 7267 | continue; |
| 7350 | 7268 | } else if (case.ast.values.len == 1 and |
| 7351 | node_tags[case.ast.values[0]] == .identifier and | |
| 7352 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) | |
| 7269 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 7270 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")) | |
| 7353 | 7271 | { |
| 7354 | 7272 | const case_src = case.ast.arrow_token - 1; |
| 7355 | 7273 | return astgen.failTokNotes( |
| ... | ... | @@ -7367,11 +7285,11 @@ fn switchExprErrUnion( |
| 7367 | 7285 | } |
| 7368 | 7286 | |
| 7369 | 7287 | for (case.ast.values) |val| { |
| 7370 | if (node_tags[val] == .string_literal) | |
| 7288 | if (tree.nodeTag(val) == .string_literal) | |
| 7371 | 7289 | return astgen.failNode(val, "cannot switch on strings", .{}); |
| 7372 | 7290 | } |
| 7373 | 7291 | |
| 7374 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { | |
| 7292 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) { | |
| 7375 | 7293 | scalar_cases_len += 1; |
| 7376 | 7294 | } else { |
| 7377 | 7295 | multi_cases_len += 1; |
| ... | ... | @@ -7564,11 +7482,11 @@ fn switchExprErrUnion( |
| 7564 | 7482 | var multi_case_index: u32 = 0; |
| 7565 | 7483 | var scalar_case_index: u32 = 0; |
| 7566 | 7484 | var any_uses_err_capture = false; |
| 7567 | for (case_nodes) |case_node| { | |
| 7485 | for (switch_full.ast.cases) |case_node| { | |
| 7568 | 7486 | const case = tree.fullSwitchCase(case_node).?; |
| 7569 | 7487 | |
| 7570 | 7488 | const is_multi_case = case.ast.values.len > 1 or |
| 7571 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | |
| 7489 | (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range); | |
| 7572 | 7490 | |
| 7573 | 7491 | var dbg_var_name: Zir.NullTerminatedString = .empty; |
| 7574 | 7492 | var dbg_var_inst: Zir.Inst.Ref = undefined; |
| ... | ... | @@ -7586,7 +7504,7 @@ fn switchExprErrUnion( |
| 7586 | 7504 | }; |
| 7587 | 7505 | |
| 7588 | 7506 | const capture_token = case.payload_token orelse break :blk &err_scope.base; |
| 7589 | if (token_tags[capture_token] != .identifier) { | |
| 7507 | if (tree.tokenTag(capture_token) != .identifier) { | |
| 7590 | 7508 | return astgen.failTok(capture_token + 1, "error set cannot be captured by reference", .{}); |
| 7591 | 7509 | } |
| 7592 | 7510 | |
| ... | ... | @@ -7622,7 +7540,7 @@ fn switchExprErrUnion( |
| 7622 | 7540 | // items |
| 7623 | 7541 | var items_len: u32 = 0; |
| 7624 | 7542 | for (case.ast.values) |item_node| { |
| 7625 | if (node_tags[item_node] == .switch_range) continue; | |
| 7543 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 7626 | 7544 | items_len += 1; |
| 7627 | 7545 | |
| 7628 | 7546 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item); |
| ... | ... | @@ -7632,11 +7550,12 @@ fn switchExprErrUnion( |
| 7632 | 7550 | // ranges |
| 7633 | 7551 | var ranges_len: u32 = 0; |
| 7634 | 7552 | for (case.ast.values) |range| { |
| 7635 | if (node_tags[range] != .switch_range) continue; | |
| 7553 | if (tree.nodeTag(range) != .switch_range) continue; | |
| 7636 | 7554 | ranges_len += 1; |
| 7637 | 7555 | |
| 7638 | const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item); | |
| 7639 | const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item); | |
| 7556 | const first_node, const last_node = tree.nodeData(range).node_and_node; | |
| 7557 | const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item); | |
| 7558 | const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item); | |
| 7640 | 7559 | try payloads.appendSlice(gpa, &[_]u32{ |
| 7641 | 7560 | @intFromEnum(first), @intFromEnum(last), |
| 7642 | 7561 | }); |
| ... | ... | @@ -7645,7 +7564,7 @@ fn switchExprErrUnion( |
| 7645 | 7564 | payloads.items[header_index] = items_len; |
| 7646 | 7565 | payloads.items[header_index + 1] = ranges_len; |
| 7647 | 7566 | break :blk header_index + 2; |
| 7648 | } else if (case_node == else_node) blk: { | |
| 7567 | } else if (case_node.toOptional() == else_node) blk: { | |
| 7649 | 7568 | payloads.items[case_table_start + 1] = header_index; |
| 7650 | 7569 | try payloads.resize(gpa, header_index + 1); // body_len |
| 7651 | 7570 | break :blk header_index; |
| ... | ... | @@ -7675,7 +7594,7 @@ fn switchExprErrUnion( |
| 7675 | 7594 | const case_result = try fullBodyExpr(&case_scope, sub_scope, block_scope.break_result_info, target_expr_node, .allow_branch_hint); |
| 7676 | 7595 | // check capture_scope, not err_scope to avoid false positive unused error capture |
| 7677 | 7596 | try checkUsed(parent_gz, &case_scope.base, err_scope.parent); |
| 7678 | const uses_err = err_scope.used != 0 or err_scope.discarded != 0; | |
| 7597 | const uses_err = err_scope.used != .none or err_scope.discarded != .none; | |
| 7679 | 7598 | if (uses_err) { |
| 7680 | 7599 | try case_scope.addDbgVar(.dbg_var_val, err_name, err_inst.toRef()); |
| 7681 | 7600 | any_uses_err_capture = true; |
| ... | ... | @@ -7775,10 +7694,6 @@ fn switchExpr( |
| 7775 | 7694 | const astgen = parent_gz.astgen; |
| 7776 | 7695 | const gpa = astgen.gpa; |
| 7777 | 7696 | const tree = astgen.tree; |
| 7778 | const node_datas = tree.nodes.items(.data); | |
| 7779 | const node_tags = tree.nodes.items(.tag); | |
| 7780 | const main_tokens = tree.nodes.items(.main_token); | |
| 7781 | const token_tags = tree.tokens.items(.tag); | |
| 7782 | 7697 | const operand_node = switch_full.ast.condition; |
| 7783 | 7698 | const case_nodes = switch_full.ast.cases; |
| 7784 | 7699 | |
| ... | ... | @@ -7810,17 +7725,17 @@ fn switchExpr( |
| 7810 | 7725 | var multi_cases_len: u32 = 0; |
| 7811 | 7726 | var inline_cases_len: u32 = 0; |
| 7812 | 7727 | var special_prong: Zir.SpecialProng = .none; |
| 7813 | var special_node: Ast.Node.Index = 0; | |
| 7728 | var special_node: Ast.Node.OptionalIndex = .none; | |
| 7814 | 7729 | var else_src: ?Ast.TokenIndex = null; |
| 7815 | 7730 | var underscore_src: ?Ast.TokenIndex = null; |
| 7816 | 7731 | for (case_nodes) |case_node| { |
| 7817 | 7732 | const case = tree.fullSwitchCase(case_node).?; |
| 7818 | 7733 | if (case.payload_token) |payload_token| { |
| 7819 | const ident = if (token_tags[payload_token] == .asterisk) blk: { | |
| 7734 | const ident = if (tree.tokenTag(payload_token) == .asterisk) blk: { | |
| 7820 | 7735 | any_payload_is_ref = true; |
| 7821 | 7736 | break :blk payload_token + 1; |
| 7822 | 7737 | } else payload_token; |
| 7823 | if (token_tags[ident + 1] == .comma) { | |
| 7738 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 7824 | 7739 | any_has_tag_capture = true; |
| 7825 | 7740 | } |
| 7826 | 7741 | |
| ... | ... | @@ -7868,13 +7783,13 @@ fn switchExpr( |
| 7868 | 7783 | }, |
| 7869 | 7784 | ); |
| 7870 | 7785 | } |
| 7871 | special_node = case_node; | |
| 7786 | special_node = case_node.toOptional(); | |
| 7872 | 7787 | special_prong = .@"else"; |
| 7873 | 7788 | else_src = case_src; |
| 7874 | 7789 | continue; |
| 7875 | 7790 | } else if (case.ast.values.len == 1 and |
| 7876 | node_tags[case.ast.values[0]] == .identifier and | |
| 7877 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")) | |
| 7791 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 7792 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")) | |
| 7878 | 7793 | { |
| 7879 | 7794 | const case_src = case.ast.arrow_token - 1; |
| 7880 | 7795 | if (underscore_src) |src| { |
| ... | ... | @@ -7912,18 +7827,18 @@ fn switchExpr( |
| 7912 | 7827 | if (case.inline_token != null) { |
| 7913 | 7828 | return astgen.failTok(case_src, "cannot inline '_' prong", .{}); |
| 7914 | 7829 | } |
| 7915 | special_node = case_node; | |
| 7830 | special_node = case_node.toOptional(); | |
| 7916 | 7831 | special_prong = .under; |
| 7917 | 7832 | underscore_src = case_src; |
| 7918 | 7833 | continue; |
| 7919 | 7834 | } |
| 7920 | 7835 | |
| 7921 | 7836 | for (case.ast.values) |val| { |
| 7922 | if (node_tags[val] == .string_literal) | |
| 7837 | if (tree.nodeTag(val) == .string_literal) | |
| 7923 | 7838 | return astgen.failNode(val, "cannot switch on strings", .{}); |
| 7924 | 7839 | } |
| 7925 | 7840 | |
| 7926 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { | |
| 7841 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) != .switch_range) { | |
| 7927 | 7842 | scalar_cases_len += 1; |
| 7928 | 7843 | } else { |
| 7929 | 7844 | multi_cases_len += 1; |
| ... | ... | @@ -8012,7 +7927,7 @@ fn switchExpr( |
| 8012 | 7927 | const case = tree.fullSwitchCase(case_node).?; |
| 8013 | 7928 | |
| 8014 | 7929 | const is_multi_case = case.ast.values.len > 1 or |
| 8015 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | |
| 7930 | (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .switch_range); | |
| 8016 | 7931 | |
| 8017 | 7932 | var dbg_var_name: Zir.NullTerminatedString = .empty; |
| 8018 | 7933 | var dbg_var_inst: Zir.Inst.Ref = undefined; |
| ... | ... | @@ -8026,18 +7941,15 @@ fn switchExpr( |
| 8026 | 7941 | |
| 8027 | 7942 | const sub_scope = blk: { |
| 8028 | 7943 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 8029 | const ident = if (token_tags[payload_token] == .asterisk) | |
| 8030 | payload_token + 1 | |
| 8031 | else | |
| 8032 | payload_token; | |
| 7944 | const capture_is_ref = tree.tokenTag(payload_token) == .asterisk; | |
| 7945 | const ident = payload_token + @intFromBool(capture_is_ref); | |
| 8033 | 7946 | |
| 8034 | const is_ptr = ident != payload_token; | |
| 8035 | capture = if (is_ptr) .by_ref else .by_val; | |
| 7947 | capture = if (capture_is_ref) .by_ref else .by_val; | |
| 8036 | 7948 | |
| 8037 | 7949 | const ident_slice = tree.tokenSlice(ident); |
| 8038 | 7950 | var payload_sub_scope: *Scope = undefined; |
| 8039 | 7951 | if (mem.eql(u8, ident_slice, "_")) { |
| 8040 | if (is_ptr) { | |
| 7952 | if (capture_is_ref) { | |
| 8041 | 7953 | return astgen.failTok(payload_token, "pointer modifier invalid on discard", .{}); |
| 8042 | 7954 | } |
| 8043 | 7955 | payload_sub_scope = &case_scope.base; |
| ... | ... | @@ -8057,7 +7969,7 @@ fn switchExpr( |
| 8057 | 7969 | payload_sub_scope = &capture_val_scope.base; |
| 8058 | 7970 | } |
| 8059 | 7971 | |
| 8060 | const tag_token = if (token_tags[ident + 1] == .comma) | |
| 7972 | const tag_token = if (tree.tokenTag(ident + 1) == .comma) | |
| 8061 | 7973 | ident + 2 |
| 8062 | 7974 | else |
| 8063 | 7975 | break :blk payload_sub_scope; |
| ... | ... | @@ -8095,7 +8007,7 @@ fn switchExpr( |
| 8095 | 8007 | // items |
| 8096 | 8008 | var items_len: u32 = 0; |
| 8097 | 8009 | for (case.ast.values) |item_node| { |
| 8098 | if (node_tags[item_node] == .switch_range) continue; | |
| 8010 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 8099 | 8011 | items_len += 1; |
| 8100 | 8012 | |
| 8101 | 8013 | const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item); |
| ... | ... | @@ -8105,11 +8017,12 @@ fn switchExpr( |
| 8105 | 8017 | // ranges |
| 8106 | 8018 | var ranges_len: u32 = 0; |
| 8107 | 8019 | for (case.ast.values) |range| { |
| 8108 | if (node_tags[range] != .switch_range) continue; | |
| 8020 | if (tree.nodeTag(range) != .switch_range) continue; | |
| 8109 | 8021 | ranges_len += 1; |
| 8110 | 8022 | |
| 8111 | const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item); | |
| 8112 | const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item); | |
| 8023 | const first_node, const last_node = tree.nodeData(range).node_and_node; | |
| 8024 | const first = try comptimeExpr(parent_gz, scope, item_ri, first_node, .switch_item); | |
| 8025 | const last = try comptimeExpr(parent_gz, scope, item_ri, last_node, .switch_item); | |
| 8113 | 8026 | try payloads.appendSlice(gpa, &[_]u32{ |
| 8114 | 8027 | @intFromEnum(first), @intFromEnum(last), |
| 8115 | 8028 | }); |
| ... | ... | @@ -8118,7 +8031,7 @@ fn switchExpr( |
| 8118 | 8031 | payloads.items[header_index] = items_len; |
| 8119 | 8032 | payloads.items[header_index + 1] = ranges_len; |
| 8120 | 8033 | break :blk header_index + 2; |
| 8121 | } else if (case_node == special_node) blk: { | |
| 8034 | } else if (case_node.toOptional() == special_node) blk: { | |
| 8122 | 8035 | payloads.items[case_table_start] = header_index; |
| 8123 | 8036 | try payloads.resize(gpa, header_index + 1); // body_len |
| 8124 | 8037 | break :blk header_index; |
| ... | ... | @@ -8231,17 +8144,15 @@ fn switchExpr( |
| 8231 | 8144 | fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 8232 | 8145 | const astgen = gz.astgen; |
| 8233 | 8146 | const tree = astgen.tree; |
| 8234 | const node_datas = tree.nodes.items(.data); | |
| 8235 | const node_tags = tree.nodes.items(.tag); | |
| 8236 | 8147 | |
| 8237 | 8148 | if (astgen.fn_block == null) { |
| 8238 | 8149 | return astgen.failNode(node, "'return' outside function scope", .{}); |
| 8239 | 8150 | } |
| 8240 | 8151 | |
| 8241 | if (gz.any_defer_node != 0) { | |
| 8152 | if (gz.any_defer_node.unwrap()) |any_defer_node| { | |
| 8242 | 8153 | return astgen.failNodeNotes(node, "cannot return from defer expression", .{}, &.{ |
| 8243 | 8154 | try astgen.errNoteNode( |
| 8244 | gz.any_defer_node, | |
| 8155 | any_defer_node, | |
| 8245 | 8156 | "defer expression here", |
| 8246 | 8157 | .{}, |
| 8247 | 8158 | ), |
| ... | ... | @@ -8259,8 +8170,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 8259 | 8170 | |
| 8260 | 8171 | const defer_outer = &astgen.fn_block.?.base; |
| 8261 | 8172 | |
| 8262 | const operand_node = node_datas[node].lhs; | |
| 8263 | if (operand_node == 0) { | |
| 8173 | const operand_node = tree.nodeData(node).opt_node.unwrap() orelse { | |
| 8264 | 8174 | // Returning a void value; skip error defers. |
| 8265 | 8175 | try genDefers(gz, defer_outer, scope, .normal_only); |
| 8266 | 8176 | |
| ... | ... | @@ -8269,12 +8179,12 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 8269 | 8179 | |
| 8270 | 8180 | _ = try gz.addUnNode(.ret_node, .void_value, node); |
| 8271 | 8181 | return Zir.Inst.Ref.unreachable_value; |
| 8272 | } | |
| 8182 | }; | |
| 8273 | 8183 | |
| 8274 | if (node_tags[operand_node] == .error_value) { | |
| 8184 | if (tree.nodeTag(operand_node) == .error_value) { | |
| 8275 | 8185 | // Hot path for `return error.Foo`. This bypasses result location logic as well as logic |
| 8276 | 8186 | // for detecting whether to add something to the function's inferred error set. |
| 8277 | const ident_token = node_datas[operand_node].rhs; | |
| 8187 | const ident_token = tree.nodeData(operand_node).opt_token_and_opt_token[1].unwrap().?; | |
| 8278 | 8188 | const err_name_str_index = try astgen.identAsString(ident_token); |
| 8279 | 8189 | const defer_counts = countDefers(defer_outer, scope); |
| 8280 | 8190 | if (!defer_counts.need_err_code) { |
| ... | ... | @@ -8405,9 +8315,8 @@ fn identifier( |
| 8405 | 8315 | ) InnerError!Zir.Inst.Ref { |
| 8406 | 8316 | const astgen = gz.astgen; |
| 8407 | 8317 | const tree = astgen.tree; |
| 8408 | const main_tokens = tree.nodes.items(.main_token); | |
| 8409 | 8318 | |
| 8410 | const ident_token = main_tokens[ident]; | |
| 8319 | const ident_token = tree.nodeMainToken(ident); | |
| 8411 | 8320 | const ident_name_raw = tree.tokenSlice(ident_token); |
| 8412 | 8321 | if (mem.eql(u8, ident_name_raw, "_")) { |
| 8413 | 8322 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); |
| ... | ... | @@ -8509,9 +8418,9 @@ fn localVarRef( |
| 8509 | 8418 | // Locals cannot shadow anything, so we do not need to look for ambiguous |
| 8510 | 8419 | // references in this case. |
| 8511 | 8420 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 8512 | local_val.discarded = ident_token; | |
| 8421 | local_val.discarded = .fromToken(ident_token); | |
| 8513 | 8422 | } else { |
| 8514 | local_val.used = ident_token; | |
| 8423 | local_val.used = .fromToken(ident_token); | |
| 8515 | 8424 | } |
| 8516 | 8425 | |
| 8517 | 8426 | if (local_val.is_used_or_discarded) |ptr| ptr.* = true; |
| ... | ... | @@ -8533,9 +8442,9 @@ fn localVarRef( |
| 8533 | 8442 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 8534 | 8443 | if (local_ptr.name == name_str_index) { |
| 8535 | 8444 | if (ri.rl == .discard and ri.ctx == .assignment) { |
| 8536 | local_ptr.discarded = ident_token; | |
| 8445 | local_ptr.discarded = .fromToken(ident_token); | |
| 8537 | 8446 | } else { |
| 8538 | local_ptr.used = ident_token; | |
| 8447 | local_ptr.used = .fromToken(ident_token); | |
| 8539 | 8448 | } |
| 8540 | 8449 | |
| 8541 | 8450 | // Can't close over a runtime variable |
| ... | ... | @@ -8748,8 +8657,7 @@ fn stringLiteral( |
| 8748 | 8657 | ) InnerError!Zir.Inst.Ref { |
| 8749 | 8658 | const astgen = gz.astgen; |
| 8750 | 8659 | const tree = astgen.tree; |
| 8751 | const main_tokens = tree.nodes.items(.main_token); | |
| 8752 | const str_lit_token = main_tokens[node]; | |
| 8660 | const str_lit_token = tree.nodeMainToken(node); | |
| 8753 | 8661 | const str = try astgen.strLitAsString(str_lit_token); |
| 8754 | 8662 | const result = try gz.add(.{ |
| 8755 | 8663 | .tag = .str, |
| ... | ... | @@ -8781,8 +8689,7 @@ fn multilineStringLiteral( |
| 8781 | 8689 | fn charLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| 8782 | 8690 | const astgen = gz.astgen; |
| 8783 | 8691 | const tree = astgen.tree; |
| 8784 | const main_tokens = tree.nodes.items(.main_token); | |
| 8785 | const main_token = main_tokens[node]; | |
| 8692 | const main_token = tree.nodeMainToken(node); | |
| 8786 | 8693 | const slice = tree.tokenSlice(main_token); |
| 8787 | 8694 | |
| 8788 | 8695 | switch (std.zig.parseCharLiteral(slice)) { |
| ... | ... | @@ -8799,8 +8706,7 @@ const Sign = enum { negative, positive }; |
| 8799 | 8706 | fn numberLiteral(gz: *GenZir, ri: ResultInfo, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref { |
| 8800 | 8707 | const astgen = gz.astgen; |
| 8801 | 8708 | const tree = astgen.tree; |
| 8802 | const main_tokens = tree.nodes.items(.main_token); | |
| 8803 | const num_token = main_tokens[node]; | |
| 8709 | const num_token = tree.nodeMainToken(node); | |
| 8804 | 8710 | const bytes = tree.tokenSlice(num_token); |
| 8805 | 8711 | |
| 8806 | 8712 | const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) { |
| ... | ... | @@ -8918,16 +8824,12 @@ fn asmExpr( |
| 8918 | 8824 | ) InnerError!Zir.Inst.Ref { |
| 8919 | 8825 | const astgen = gz.astgen; |
| 8920 | 8826 | const tree = astgen.tree; |
| 8921 | const main_tokens = tree.nodes.items(.main_token); | |
| 8922 | const node_datas = tree.nodes.items(.data); | |
| 8923 | const node_tags = tree.nodes.items(.tag); | |
| 8924 | const token_tags = tree.tokens.items(.tag); | |
| 8925 | 8827 | |
| 8926 | 8828 | const TagAndTmpl = struct { tag: Zir.Inst.Extended, tmpl: Zir.NullTerminatedString }; |
| 8927 | const tag_and_tmpl: TagAndTmpl = switch (node_tags[full.ast.template]) { | |
| 8829 | const tag_and_tmpl: TagAndTmpl = switch (tree.nodeTag(full.ast.template)) { | |
| 8928 | 8830 | .string_literal => .{ |
| 8929 | 8831 | .tag = .@"asm", |
| 8930 | .tmpl = (try astgen.strLitAsString(main_tokens[full.ast.template])).index, | |
| 8832 | .tmpl = (try astgen.strLitAsString(tree.nodeMainToken(full.ast.template))).index, | |
| 8931 | 8833 | }, |
| 8932 | 8834 | .multiline_string_literal => .{ |
| 8933 | 8835 | .tag = .@"asm", |
| ... | ... | @@ -8962,17 +8864,17 @@ fn asmExpr( |
| 8962 | 8864 | var output_type_bits: u32 = 0; |
| 8963 | 8865 | |
| 8964 | 8866 | for (full.outputs, 0..) |output_node, i| { |
| 8965 | const symbolic_name = main_tokens[output_node]; | |
| 8867 | const symbolic_name = tree.nodeMainToken(output_node); | |
| 8966 | 8868 | const name = try astgen.identAsString(symbolic_name); |
| 8967 | 8869 | const constraint_token = symbolic_name + 2; |
| 8968 | 8870 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 8969 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; | |
| 8871 | const has_arrow = tree.tokenTag(symbolic_name + 4) == .arrow; | |
| 8970 | 8872 | if (has_arrow) { |
| 8971 | 8873 | if (output_type_bits != 0) { |
| 8972 | 8874 | return astgen.failNode(output_node, "inline assembly allows up to one output value", .{}); |
| 8973 | 8875 | } |
| 8974 | 8876 | output_type_bits |= @as(u32, 1) << @intCast(i); |
| 8975 | const out_type_node = node_datas[output_node].lhs; | |
| 8877 | const out_type_node = tree.nodeData(output_node).opt_node_and_token[0].unwrap().?; | |
| 8976 | 8878 | const out_type_inst = try typeExpr(gz, scope, out_type_node); |
| 8977 | 8879 | outputs[i] = .{ |
| 8978 | 8880 | .name = name, |
| ... | ... | @@ -8999,11 +8901,11 @@ fn asmExpr( |
| 8999 | 8901 | const inputs = inputs_buffer[0..full.inputs.len]; |
| 9000 | 8902 | |
| 9001 | 8903 | for (full.inputs, 0..) |input_node, i| { |
| 9002 | const symbolic_name = main_tokens[input_node]; | |
| 8904 | const symbolic_name = tree.nodeMainToken(input_node); | |
| 9003 | 8905 | const name = try astgen.identAsString(symbolic_name); |
| 9004 | 8906 | const constraint_token = symbolic_name + 2; |
| 9005 | 8907 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 9006 | const operand = try expr(gz, scope, .{ .rl = .none }, node_datas[input_node].lhs); | |
| 8908 | const operand = try expr(gz, scope, .{ .rl = .none }, tree.nodeData(input_node).node_and_token[0]); | |
| 9007 | 8909 | inputs[i] = .{ |
| 9008 | 8910 | .name = name, |
| 9009 | 8911 | .constraint = constraint, |
| ... | ... | @@ -9024,10 +8926,10 @@ fn asmExpr( |
| 9024 | 8926 | clobbers_buffer[clobber_i] = @intFromEnum((try astgen.strLitAsString(tok_i)).index); |
| 9025 | 8927 | clobber_i += 1; |
| 9026 | 8928 | tok_i += 1; |
| 9027 | switch (token_tags[tok_i]) { | |
| 8929 | switch (tree.tokenTag(tok_i)) { | |
| 9028 | 8930 | .r_paren => break :clobbers, |
| 9029 | 8931 | .comma => { |
| 9030 | if (token_tags[tok_i + 1] == .r_paren) { | |
| 8932 | if (tree.tokenTag(tok_i + 1) == .r_paren) { | |
| 9031 | 8933 | break :clobbers; |
| 9032 | 8934 | } else { |
| 9033 | 8935 | continue; |
| ... | ... | @@ -9119,9 +9021,6 @@ fn ptrCast( |
| 9119 | 9021 | ) InnerError!Zir.Inst.Ref { |
| 9120 | 9022 | const astgen = gz.astgen; |
| 9121 | 9023 | const tree = astgen.tree; |
| 9122 | const main_tokens = tree.nodes.items(.main_token); | |
| 9123 | const node_datas = tree.nodes.items(.data); | |
| 9124 | const node_tags = tree.nodes.items(.tag); | |
| 9125 | 9024 | |
| 9126 | 9025 | const FlagsInt = @typeInfo(Zir.Inst.FullPtrCastFlags).@"struct".backing_integer.?; |
| 9127 | 9026 | var flags: Zir.Inst.FullPtrCastFlags = .{}; |
| ... | ... | @@ -9130,11 +9029,11 @@ fn ptrCast( |
| 9130 | 9029 | // to handle `builtin_call_two`. |
| 9131 | 9030 | var node = root_node; |
| 9132 | 9031 | while (true) { |
| 9133 | switch (node_tags[node]) { | |
| 9032 | switch (tree.nodeTag(node)) { | |
| 9134 | 9033 | .builtin_call_two, .builtin_call_two_comma => {}, |
| 9135 | 9034 | .grouped_expression => { |
| 9136 | 9035 | // Handle the chaining even with redundant parentheses |
| 9137 | node = node_datas[node].lhs; | |
| 9036 | node = tree.nodeData(node).node_and_token[0]; | |
| 9138 | 9037 | continue; |
| 9139 | 9038 | }, |
| 9140 | 9039 | else => break, |
| ... | ... | @@ -9144,7 +9043,9 @@ fn ptrCast( |
| 9144 | 9043 | const args = tree.builtinCallParams(&buf, node).?; |
| 9145 | 9044 | std.debug.assert(args.len <= 2); |
| 9146 | 9045 | |
| 9147 | const builtin_token = main_tokens[node]; | |
| 9046 | if (args.len == 0) break; // 0 args | |
| 9047 | ||
| 9048 | const builtin_token = tree.nodeMainToken(node); | |
| 9148 | 9049 | const builtin_name = tree.tokenSlice(builtin_token); |
| 9149 | 9050 | const info = BuiltinFn.list.get(builtin_name) orelse break; |
| 9150 | 9051 | if (args.len == 1) { |
| ... | ... | @@ -9344,9 +9245,8 @@ fn builtinCall( |
| 9344 | 9245 | ) InnerError!Zir.Inst.Ref { |
| 9345 | 9246 | const astgen = gz.astgen; |
| 9346 | 9247 | const tree = astgen.tree; |
| 9347 | const main_tokens = tree.nodes.items(.main_token); | |
| 9348 | 9248 | |
| 9349 | const builtin_token = main_tokens[node]; | |
| 9249 | const builtin_token = tree.nodeMainToken(node); | |
| 9350 | 9250 | const builtin_name = tree.tokenSlice(builtin_token); |
| 9351 | 9251 | |
| 9352 | 9252 | // We handle the different builtins manually because they have different semantics depending |
| ... | ... | @@ -9387,14 +9287,13 @@ fn builtinCall( |
| 9387 | 9287 | return rvalue(gz, ri, .void_value, node); |
| 9388 | 9288 | }, |
| 9389 | 9289 | .import => { |
| 9390 | const node_tags = tree.nodes.items(.tag); | |
| 9391 | 9290 | const operand_node = params[0]; |
| 9392 | 9291 | |
| 9393 | if (node_tags[operand_node] != .string_literal) { | |
| 9292 | if (tree.nodeTag(operand_node) != .string_literal) { | |
| 9394 | 9293 | // Spec reference: https://github.com/ziglang/zig/issues/2206 |
| 9395 | 9294 | return astgen.failNode(operand_node, "@import operand must be a string literal", .{}); |
| 9396 | 9295 | } |
| 9397 | const str_lit_token = main_tokens[operand_node]; | |
| 9296 | const str_lit_token = tree.nodeMainToken(operand_node); | |
| 9398 | 9297 | const str = try astgen.strLitAsString(str_lit_token); |
| 9399 | 9298 | const str_slice = astgen.string_bytes.items[@intFromEnum(str.index)..][0..str.len]; |
| 9400 | 9299 | if (mem.indexOfScalar(u8, str_slice, 0) != null) { |
| ... | ... | @@ -9505,8 +9404,7 @@ fn builtinCall( |
| 9505 | 9404 | std.mem.asBytes(&astgen.source_column), |
| 9506 | 9405 | ); |
| 9507 | 9406 | |
| 9508 | const token_starts = tree.tokens.items(.start); | |
| 9509 | const node_start = token_starts[tree.firstToken(node)]; | |
| 9407 | const node_start = tree.tokenStart(tree.firstToken(node)); | |
| 9510 | 9408 | astgen.advanceSourceCursor(node_start); |
| 9511 | 9409 | const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.Src{ |
| 9512 | 9410 | .node = gz.nodeIndexToRelative(node), |
| ... | ... | @@ -9786,7 +9684,7 @@ fn builtinCall( |
| 9786 | 9684 | .callee = callee, |
| 9787 | 9685 | .args = args, |
| 9788 | 9686 | .flags = .{ |
| 9789 | .is_nosuspend = gz.nosuspend_node != 0, | |
| 9687 | .is_nosuspend = gz.nosuspend_node != .none, | |
| 9790 | 9688 | .ensure_result_used = false, |
| 9791 | 9689 | }, |
| 9792 | 9690 | }); |
| ... | ... | @@ -10011,13 +9909,11 @@ fn negation( |
| 10011 | 9909 | ) InnerError!Zir.Inst.Ref { |
| 10012 | 9910 | const astgen = gz.astgen; |
| 10013 | 9911 | const tree = astgen.tree; |
| 10014 | const node_tags = tree.nodes.items(.tag); | |
| 10015 | const node_datas = tree.nodes.items(.data); | |
| 10016 | 9912 | |
| 10017 | 9913 | // Check for float literal as the sub-expression because we want to preserve |
| 10018 | 9914 | // its negativity rather than having it go through comptime subtraction. |
| 10019 | const operand_node = node_datas[node].lhs; | |
| 10020 | if (node_tags[operand_node] == .number_literal) { | |
| 9915 | const operand_node = tree.nodeData(node).node; | |
| 9916 | if (tree.nodeTag(operand_node) == .number_literal) { | |
| 10021 | 9917 | return numberLiteral(gz, ri, operand_node, node, .negative); |
| 10022 | 9918 | } |
| 10023 | 9919 | |
| ... | ... | @@ -10133,7 +10029,7 @@ fn shiftOp( |
| 10133 | 10029 | ) InnerError!Zir.Inst.Ref { |
| 10134 | 10030 | const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node); |
| 10135 | 10031 | |
| 10136 | const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) { | |
| 10032 | const cursor = switch (gz.astgen.tree.nodeTag(node)) { | |
| 10137 | 10033 | .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node), |
| 10138 | 10034 | else => undefined, |
| 10139 | 10035 | }; |
| ... | ... | @@ -10141,7 +10037,7 @@ fn shiftOp( |
| 10141 | 10037 | const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node); |
| 10142 | 10038 | const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node); |
| 10143 | 10039 | |
| 10144 | switch (gz.astgen.tree.nodes.items(.tag)[node]) { | |
| 10040 | switch (gz.astgen.tree.nodeTag(node)) { | |
| 10145 | 10041 | .shl, .shr => try emitDbgStmt(gz, cursor), |
| 10146 | 10042 | else => undefined, |
| 10147 | 10043 | } |
| ... | ... | @@ -10217,14 +10113,14 @@ fn callExpr( |
| 10217 | 10113 | if (call.async_token != null) { |
| 10218 | 10114 | break :blk .async_kw; |
| 10219 | 10115 | } |
| 10220 | if (gz.nosuspend_node != 0) { | |
| 10116 | if (gz.nosuspend_node != .none) { | |
| 10221 | 10117 | break :blk .no_async; |
| 10222 | 10118 | } |
| 10223 | 10119 | break :blk .auto; |
| 10224 | 10120 | }; |
| 10225 | 10121 | |
| 10226 | 10122 | { |
| 10227 | astgen.advanceSourceCursor(astgen.tree.tokens.items(.start)[call.ast.lparen]); | |
| 10123 | astgen.advanceSourceCursor(astgen.tree.tokenStart(call.ast.lparen)); | |
| 10228 | 10124 | const line = astgen.source_line - gz.decl_line; |
| 10229 | 10125 | const column = astgen.source_column; |
| 10230 | 10126 | // Sema expects a dbg_stmt immediately before call, |
| ... | ... | @@ -10235,7 +10131,6 @@ fn callExpr( |
| 10235 | 10131 | .direct => |obj| assert(obj != .none), |
| 10236 | 10132 | .field => |field| assert(field.obj_ptr != .none), |
| 10237 | 10133 | } |
| 10238 | assert(node != 0); | |
| 10239 | 10134 | |
| 10240 | 10135 | const call_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len); |
| 10241 | 10136 | const call_inst = call_index.toRef(); |
| ... | ... | @@ -10346,14 +10241,10 @@ fn calleeExpr( |
| 10346 | 10241 | const astgen = gz.astgen; |
| 10347 | 10242 | const tree = astgen.tree; |
| 10348 | 10243 | |
| 10349 | const tag = tree.nodes.items(.tag)[node]; | |
| 10244 | const tag = tree.nodeTag(node); | |
| 10350 | 10245 | switch (tag) { |
| 10351 | 10246 | .field_access => { |
| 10352 | const main_tokens = tree.nodes.items(.main_token); | |
| 10353 | const node_datas = tree.nodes.items(.data); | |
| 10354 | const object_node = node_datas[node].lhs; | |
| 10355 | const dot_token = main_tokens[node]; | |
| 10356 | const field_ident = dot_token + 1; | |
| 10247 | const object_node, const field_ident = tree.nodeData(node).node_and_token; | |
| 10357 | 10248 | const str_index = try astgen.identAsString(field_ident); |
| 10358 | 10249 | // Capture the object by reference so we can promote it to an |
| 10359 | 10250 | // address in Sema if needed. |
| ... | ... | @@ -10378,7 +10269,7 @@ fn calleeExpr( |
| 10378 | 10269 | // Decl literal call syntax, e.g. |
| 10379 | 10270 | // `const foo: T = .init();` |
| 10380 | 10271 | // Look up `init` in `T`, but don't try and coerce it. |
| 10381 | const str_index = try astgen.identAsString(tree.nodes.items(.main_token)[node]); | |
| 10272 | const str_index = try astgen.identAsString(tree.nodeMainToken(node)); | |
| 10382 | 10273 | const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{ |
| 10383 | 10274 | .lhs = res_ty, |
| 10384 | 10275 | .field_name_start = str_index, |
| ... | ... | @@ -10450,12 +10341,9 @@ comptime { |
| 10450 | 10341 | } |
| 10451 | 10342 | |
| 10452 | 10343 | fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool { |
| 10453 | const node_tags = tree.nodes.items(.tag); | |
| 10454 | const main_tokens = tree.nodes.items(.main_token); | |
| 10455 | ||
| 10456 | switch (node_tags[node]) { | |
| 10344 | switch (tree.nodeTag(node)) { | |
| 10457 | 10345 | .number_literal => { |
| 10458 | const ident = main_tokens[node]; | |
| 10346 | const ident = tree.nodeMainToken(node); | |
| 10459 | 10347 | return switch (std.zig.parseNumberLiteral(tree.tokenSlice(ident))) { |
| 10460 | 10348 | .int => |number| switch (number) { |
| 10461 | 10349 | 0 => true, |
| ... | ... | @@ -10469,12 +10357,9 @@ fn nodeIsTriviallyZero(tree: *const Ast, node: Ast.Node.Index) bool { |
| 10469 | 10357 | } |
| 10470 | 10358 | |
| 10471 | 10359 | fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10472 | const node_tags = tree.nodes.items(.tag); | |
| 10473 | const node_datas = tree.nodes.items(.data); | |
| 10474 | ||
| 10475 | 10360 | var node = start_node; |
| 10476 | 10361 | while (true) { |
| 10477 | switch (node_tags[node]) { | |
| 10362 | switch (tree.nodeTag(node)) { | |
| 10478 | 10363 | // These don't have the opportunity to call any runtime functions. |
| 10479 | 10364 | .error_value, |
| 10480 | 10365 | .identifier, |
| ... | ... | @@ -10482,11 +10367,12 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool |
| 10482 | 10367 | => return false, |
| 10483 | 10368 | |
| 10484 | 10369 | // Forward the question to the LHS sub-expression. |
| 10485 | .grouped_expression, | |
| 10486 | 10370 | .@"try", |
| 10487 | 10371 | .@"nosuspend", |
| 10372 | => node = tree.nodeData(node).node, | |
| 10373 | .grouped_expression, | |
| 10488 | 10374 | .unwrap_optional, |
| 10489 | => node = node_datas[node].lhs, | |
| 10375 | => node = tree.nodeData(node).node_and_token[0], | |
| 10490 | 10376 | |
| 10491 | 10377 | // Anything that does not eval to an error is guaranteed to pop any |
| 10492 | 10378 | // additions to the error trace, so it effectively does not append. |
| ... | ... | @@ -10496,14 +10382,9 @@ fn nodeMayAppendToErrorTrace(tree: *const Ast, start_node: Ast.Node.Index) bool |
| 10496 | 10382 | } |
| 10497 | 10383 | |
| 10498 | 10384 | fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.EvalToError { |
| 10499 | const node_tags = tree.nodes.items(.tag); | |
| 10500 | const node_datas = tree.nodes.items(.data); | |
| 10501 | const main_tokens = tree.nodes.items(.main_token); | |
| 10502 | const token_tags = tree.tokens.items(.tag); | |
| 10503 | ||
| 10504 | 10385 | var node = start_node; |
| 10505 | 10386 | while (true) { |
| 10506 | switch (node_tags[node]) { | |
| 10387 | switch (tree.nodeTag(node)) { | |
| 10507 | 10388 | .root, |
| 10508 | 10389 | .@"usingnamespace", |
| 10509 | 10390 | .test_decl, |
| ... | ... | @@ -10666,13 +10547,14 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10666 | 10547 | => return .never, |
| 10667 | 10548 | |
| 10668 | 10549 | // Forward the question to the LHS sub-expression. |
| 10669 | .grouped_expression, | |
| 10670 | 10550 | .@"try", |
| 10671 | 10551 | .@"await", |
| 10672 | 10552 | .@"comptime", |
| 10673 | 10553 | .@"nosuspend", |
| 10554 | => node = tree.nodeData(node).node, | |
| 10555 | .grouped_expression, | |
| 10674 | 10556 | .unwrap_optional, |
| 10675 | => node = node_datas[node].lhs, | |
| 10557 | => node = tree.nodeData(node).node_and_token[0], | |
| 10676 | 10558 | |
| 10677 | 10559 | // LHS sub-expression may still be an error under the outer optional or error union |
| 10678 | 10560 | .@"catch", |
| ... | ... | @@ -10684,8 +10566,8 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10684 | 10566 | .block, |
| 10685 | 10567 | .block_semicolon, |
| 10686 | 10568 | => { |
| 10687 | const lbrace = main_tokens[node]; | |
| 10688 | if (token_tags[lbrace - 1] == .colon) { | |
| 10569 | const lbrace = tree.nodeMainToken(node); | |
| 10570 | if (tree.tokenTag(lbrace - 1) == .colon) { | |
| 10689 | 10571 | // Labeled blocks may need a memory location to forward |
| 10690 | 10572 | // to their break statements. |
| 10691 | 10573 | return .maybe; |
| ... | ... | @@ -10699,7 +10581,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10699 | 10581 | .builtin_call_two, |
| 10700 | 10582 | .builtin_call_two_comma, |
| 10701 | 10583 | => { |
| 10702 | const builtin_token = main_tokens[node]; | |
| 10584 | const builtin_token = tree.nodeMainToken(node); | |
| 10703 | 10585 | const builtin_name = tree.tokenSlice(builtin_token); |
| 10704 | 10586 | // If the builtin is an invalid name, we don't cause an error here; instead |
| 10705 | 10587 | // let it pass, and the error will be "invalid builtin function" later. |
| ... | ... | @@ -10713,12 +10595,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 10713 | 10595 | /// Returns `true` if it is known the type expression has more than one possible value; |
| 10714 | 10596 | /// `false` otherwise. |
| 10715 | 10597 | fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10716 | const node_tags = tree.nodes.items(.tag); | |
| 10717 | const node_datas = tree.nodes.items(.data); | |
| 10718 | ||
| 10719 | 10598 | var node = start_node; |
| 10720 | 10599 | while (true) { |
| 10721 | switch (node_tags[node]) { | |
| 10600 | switch (tree.nodeTag(node)) { | |
| 10722 | 10601 | .root, |
| 10723 | 10602 | .@"usingnamespace", |
| 10724 | 10603 | .test_decl, |
| ... | ... | @@ -10881,13 +10760,14 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10881 | 10760 | => return false, |
| 10882 | 10761 | |
| 10883 | 10762 | // Forward the question to the LHS sub-expression. |
| 10884 | .grouped_expression, | |
| 10885 | 10763 | .@"try", |
| 10886 | 10764 | .@"await", |
| 10887 | 10765 | .@"comptime", |
| 10888 | 10766 | .@"nosuspend", |
| 10767 | => node = tree.nodeData(node).node, | |
| 10768 | .grouped_expression, | |
| 10889 | 10769 | .unwrap_optional, |
| 10890 | => node = node_datas[node].lhs, | |
| 10770 | => node = tree.nodeData(node).node_and_token[0], | |
| 10891 | 10771 | |
| 10892 | 10772 | .ptr_type_aligned, |
| 10893 | 10773 | .ptr_type_sentinel, |
| ... | ... | @@ -10899,8 +10779,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10899 | 10779 | => return true, |
| 10900 | 10780 | |
| 10901 | 10781 | .identifier => { |
| 10902 | const main_tokens = tree.nodes.items(.main_token); | |
| 10903 | const ident_bytes = tree.tokenSlice(main_tokens[node]); | |
| 10782 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 10904 | 10783 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 10905 | 10784 | .anyerror_type, |
| 10906 | 10785 | .anyframe_type, |
| ... | ... | @@ -10960,12 +10839,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 10960 | 10839 | /// Returns `true` if it is known the expression is a type that cannot be used at runtime; |
| 10961 | 10840 | /// `false` otherwise. |
| 10962 | 10841 | fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 10963 | const node_tags = tree.nodes.items(.tag); | |
| 10964 | const node_datas = tree.nodes.items(.data); | |
| 10965 | ||
| 10966 | 10842 | var node = start_node; |
| 10967 | 10843 | while (true) { |
| 10968 | switch (node_tags[node]) { | |
| 10844 | switch (tree.nodeTag(node)) { | |
| 10969 | 10845 | .root, |
| 10970 | 10846 | .@"usingnamespace", |
| 10971 | 10847 | .test_decl, |
| ... | ... | @@ -11137,17 +11013,17 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 11137 | 11013 | => return true, |
| 11138 | 11014 | |
| 11139 | 11015 | // Forward the question to the LHS sub-expression. |
| 11140 | .grouped_expression, | |
| 11141 | 11016 | .@"try", |
| 11142 | 11017 | .@"await", |
| 11143 | 11018 | .@"comptime", |
| 11144 | 11019 | .@"nosuspend", |
| 11020 | => node = tree.nodeData(node).node, | |
| 11021 | .grouped_expression, | |
| 11145 | 11022 | .unwrap_optional, |
| 11146 | => node = node_datas[node].lhs, | |
| 11023 | => node = tree.nodeData(node).node_and_token[0], | |
| 11147 | 11024 | |
| 11148 | 11025 | .identifier => { |
| 11149 | const main_tokens = tree.nodes.items(.main_token); | |
| 11150 | const ident_bytes = tree.tokenSlice(main_tokens[node]); | |
| 11026 | const ident_bytes = tree.tokenSlice(tree.nodeMainToken(node)); | |
| 11151 | 11027 | if (primitive_instrs.get(ident_bytes)) |primitive| switch (primitive) { |
| 11152 | 11028 | .anyerror_type, |
| 11153 | 11029 | .anyframe_type, |
| ... | ... | @@ -11206,8 +11082,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 11206 | 11082 | |
| 11207 | 11083 | /// Returns `true` if the node uses `gz.anon_name_strategy`. |
| 11208 | 11084 | fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 11209 | const node_tags = tree.nodes.items(.tag); | |
| 11210 | switch (node_tags[node]) { | |
| 11085 | switch (tree.nodeTag(node)) { | |
| 11211 | 11086 | .container_decl, |
| 11212 | 11087 | .container_decl_trailing, |
| 11213 | 11088 | .container_decl_two, |
| ... | ... | @@ -11222,7 +11097,7 @@ fn nodeUsesAnonNameStrategy(tree: *const Ast, node: Ast.Node.Index) bool { |
| 11222 | 11097 | .tagged_union_enum_tag_trailing, |
| 11223 | 11098 | => return true, |
| 11224 | 11099 | .builtin_call_two, .builtin_call_two_comma, .builtin_call, .builtin_call_comma => { |
| 11225 | const builtin_token = tree.nodes.items(.main_token)[node]; | |
| 11100 | const builtin_token = tree.nodeMainToken(node); | |
| 11226 | 11101 | const builtin_name = tree.tokenSlice(builtin_token); |
| 11227 | 11102 | return std.mem.eql(u8, builtin_name, "@Type"); |
| 11228 | 11103 | }, |
| ... | ... | @@ -11455,8 +11330,7 @@ fn rvalueInner( |
| 11455 | 11330 | /// See also `appendIdentStr` and `parseStrLit`. |
| 11456 | 11331 | fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]const u8 { |
| 11457 | 11332 | const tree = astgen.tree; |
| 11458 | const token_tags = tree.tokens.items(.tag); | |
| 11459 | assert(token_tags[token] == .identifier); | |
| 11333 | assert(tree.tokenTag(token) == .identifier); | |
| 11460 | 11334 | const ident_name = tree.tokenSlice(token); |
| 11461 | 11335 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 11462 | 11336 | return ident_name; |
| ... | ... | @@ -11482,8 +11356,7 @@ fn appendIdentStr( |
| 11482 | 11356 | buf: *ArrayListUnmanaged(u8), |
| 11483 | 11357 | ) InnerError!void { |
| 11484 | 11358 | const tree = astgen.tree; |
| 11485 | const token_tags = tree.tokens.items(.tag); | |
| 11486 | assert(token_tags[token] == .identifier); | |
| 11359 | assert(tree.tokenTag(token) == .identifier); | |
| 11487 | 11360 | const ident_name = tree.tokenSlice(token); |
| 11488 | 11361 | if (!mem.startsWith(u8, ident_name, "@")) { |
| 11489 | 11362 | return buf.appendSlice(astgen.gpa, ident_name); |
| ... | ... | @@ -11572,8 +11445,8 @@ fn appendErrorNodeNotes( |
| 11572 | 11445 | } else 0; |
| 11573 | 11446 | try astgen.compile_errors.append(astgen.gpa, .{ |
| 11574 | 11447 | .msg = msg, |
| 11575 | .node = node, | |
| 11576 | .token = 0, | |
| 11448 | .node = node.toOptional(), | |
| 11449 | .token = .none, | |
| 11577 | 11450 | .byte_offset = 0, |
| 11578 | 11451 | .notes = notes_index, |
| 11579 | 11452 | }); |
| ... | ... | @@ -11664,8 +11537,8 @@ fn appendErrorTokNotesOff( |
| 11664 | 11537 | } else 0; |
| 11665 | 11538 | try astgen.compile_errors.append(gpa, .{ |
| 11666 | 11539 | .msg = msg, |
| 11667 | .node = 0, | |
| 11668 | .token = token, | |
| 11540 | .node = .none, | |
| 11541 | .token = .fromToken(token), | |
| 11669 | 11542 | .byte_offset = byte_offset, |
| 11670 | 11543 | .notes = notes_index, |
| 11671 | 11544 | }); |
| ... | ... | @@ -11693,8 +11566,8 @@ fn errNoteTokOff( |
| 11693 | 11566 | try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); |
| 11694 | 11567 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 11695 | 11568 | .msg = msg, |
| 11696 | .node = 0, | |
| 11697 | .token = token, | |
| 11569 | .node = .none, | |
| 11570 | .token = .fromToken(token), | |
| 11698 | 11571 | .byte_offset = byte_offset, |
| 11699 | 11572 | .notes = 0, |
| 11700 | 11573 | }); |
| ... | ... | @@ -11712,8 +11585,8 @@ fn errNoteNode( |
| 11712 | 11585 | try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args); |
| 11713 | 11586 | return astgen.addExtra(Zir.Inst.CompileErrors.Item{ |
| 11714 | 11587 | .msg = msg, |
| 11715 | .node = node, | |
| 11716 | .token = 0, | |
| 11588 | .node = node.toOptional(), | |
| 11589 | .token = .none, | |
| 11717 | 11590 | .byte_offset = 0, |
| 11718 | 11591 | .notes = 0, |
| 11719 | 11592 | }); |
| ... | ... | @@ -11779,10 +11652,8 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !IndexSlice { |
| 11779 | 11652 | |
| 11780 | 11653 | fn strLitNodeAsString(astgen: *AstGen, node: Ast.Node.Index) !IndexSlice { |
| 11781 | 11654 | const tree = astgen.tree; |
| 11782 | const node_datas = tree.nodes.items(.data); | |
| 11783 | 11655 | |
| 11784 | const start = node_datas[node].lhs; | |
| 11785 | const end = node_datas[node].rhs; | |
| 11656 | const start, const end = tree.nodeData(node).token_and_token; | |
| 11786 | 11657 | |
| 11787 | 11658 | const gpa = astgen.gpa; |
| 11788 | 11659 | const string_bytes = &astgen.string_bytes; |
| ... | ... | @@ -11877,11 +11748,11 @@ const Scope = struct { |
| 11877 | 11748 | /// Source location of the corresponding variable declaration. |
| 11878 | 11749 | token_src: Ast.TokenIndex, |
| 11879 | 11750 | /// Track the first identifier where it is referenced. |
| 11880 | /// 0 means never referenced. | |
| 11881 | used: Ast.TokenIndex = 0, | |
| 11751 | /// .none means never referenced. | |
| 11752 | used: Ast.OptionalTokenIndex = .none, | |
| 11882 | 11753 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 11883 | /// 0 means never discarded. | |
| 11884 | discarded: Ast.TokenIndex = 0, | |
| 11754 | /// .none means never discarded. | |
| 11755 | discarded: Ast.OptionalTokenIndex = .none, | |
| 11885 | 11756 | is_used_or_discarded: ?*bool = null, |
| 11886 | 11757 | /// String table index. |
| 11887 | 11758 | name: Zir.NullTerminatedString, |
| ... | ... | @@ -11901,11 +11772,11 @@ const Scope = struct { |
| 11901 | 11772 | /// Source location of the corresponding variable declaration. |
| 11902 | 11773 | token_src: Ast.TokenIndex, |
| 11903 | 11774 | /// Track the first identifier where it is referenced. |
| 11904 | /// 0 means never referenced. | |
| 11905 | used: Ast.TokenIndex = 0, | |
| 11775 | /// .none means never referenced. | |
| 11776 | used: Ast.OptionalTokenIndex = .none, | |
| 11906 | 11777 | /// Track the identifier where it is discarded, like this `_ = foo;`. |
| 11907 | /// 0 means never discarded. | |
| 11908 | discarded: Ast.TokenIndex = 0, | |
| 11778 | /// .none means never discarded. | |
| 11779 | discarded: Ast.OptionalTokenIndex = .none, | |
| 11909 | 11780 | /// Whether this value is used as an lvalue after initialization. |
| 11910 | 11781 | /// If not, we know it can be `const`, so will emit a compile error if it is `var`. |
| 11911 | 11782 | used_as_lvalue: bool = false, |
| ... | ... | @@ -12000,12 +11871,12 @@ const GenZir = struct { |
| 12000 | 11871 | break_result_info: AstGen.ResultInfo = undefined, |
| 12001 | 11872 | continue_result_info: AstGen.ResultInfo = undefined, |
| 12002 | 11873 | |
| 12003 | suspend_node: Ast.Node.Index = 0, | |
| 12004 | nosuspend_node: Ast.Node.Index = 0, | |
| 11874 | suspend_node: Ast.Node.OptionalIndex = .none, | |
| 11875 | nosuspend_node: Ast.Node.OptionalIndex = .none, | |
| 12005 | 11876 | /// Set if this GenZir is a defer. |
| 12006 | cur_defer_node: Ast.Node.Index = 0, | |
| 11877 | cur_defer_node: Ast.Node.OptionalIndex = .none, | |
| 12007 | 11878 | // Set if this GenZir is a defer or it is inside a defer. |
| 12008 | any_defer_node: Ast.Node.Index = 0, | |
| 11879 | any_defer_node: Ast.Node.OptionalIndex = .none, | |
| 12009 | 11880 | |
| 12010 | 11881 | const unstacked_top = std.math.maxInt(usize); |
| 12011 | 11882 | /// Call unstack before adding any new instructions to containing GenZir. |
| ... | ... | @@ -12086,12 +11957,12 @@ const GenZir = struct { |
| 12086 | 11957 | return false; |
| 12087 | 11958 | } |
| 12088 | 11959 | |
| 12089 | fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) i32 { | |
| 12090 | return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(gz.decl_node_index)); | |
| 11960 | fn nodeIndexToRelative(gz: GenZir, node_index: Ast.Node.Index) Ast.Node.Offset { | |
| 11961 | return gz.decl_node_index.toOffset(node_index); | |
| 12091 | 11962 | } |
| 12092 | 11963 | |
| 12093 | fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) u32 { | |
| 12094 | return token - gz.srcToken(); | |
| 11964 | fn tokenIndexToRelative(gz: GenZir, token: Ast.TokenIndex) Ast.TokenOffset { | |
| 11965 | return .init(gz.srcToken(), token); | |
| 12095 | 11966 | } |
| 12096 | 11967 | |
| 12097 | 11968 | fn srcToken(gz: GenZir) Ast.TokenIndex { |
| ... | ... | @@ -12244,7 +12115,7 @@ const GenZir = struct { |
| 12244 | 12115 | proto_hash: std.zig.SrcHash, |
| 12245 | 12116 | }, |
| 12246 | 12117 | ) !Zir.Inst.Ref { |
| 12247 | assert(args.src_node != 0); | |
| 12118 | assert(args.src_node != .root); | |
| 12248 | 12119 | const astgen = gz.astgen; |
| 12249 | 12120 | const gpa = astgen.gpa; |
| 12250 | 12121 | const ret_ref = if (args.ret_ref == .void_type) .none else args.ret_ref; |
| ... | ... | @@ -12276,13 +12147,13 @@ const GenZir = struct { |
| 12276 | 12147 | var src_locs_and_hash_buffer: [7]u32 = undefined; |
| 12277 | 12148 | const src_locs_and_hash: []const u32 = if (args.body_gz != null) src_locs_and_hash: { |
| 12278 | 12149 | const tree = astgen.tree; |
| 12279 | const node_tags = tree.nodes.items(.tag); | |
| 12280 | const node_datas = tree.nodes.items(.data); | |
| 12281 | const token_starts = tree.tokens.items(.start); | |
| 12282 | 12150 | const fn_decl = args.src_node; |
| 12283 | assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl); | |
| 12284 | const block = node_datas[fn_decl].rhs; | |
| 12285 | const rbrace_start = token_starts[tree.lastToken(block)]; | |
| 12151 | const block = switch (tree.nodeTag(fn_decl)) { | |
| 12152 | .fn_decl => tree.nodeData(fn_decl).node_and_node[1], | |
| 12153 | .test_decl => tree.nodeData(fn_decl).opt_token_and_node[1], | |
| 12154 | else => unreachable, | |
| 12155 | }; | |
| 12156 | const rbrace_start = tree.tokenStart(tree.lastToken(block)); | |
| 12286 | 12157 | astgen.advanceSourceCursor(rbrace_start); |
| 12287 | 12158 | const rbrace_line: u32 = @intCast(astgen.source_line - gz.decl_line); |
| 12288 | 12159 | const rbrace_column: u32 = @intCast(astgen.source_column); |
| ... | ... | @@ -12689,7 +12560,7 @@ const GenZir = struct { |
| 12689 | 12560 | .data = .{ .extended = .{ |
| 12690 | 12561 | .opcode = opcode, |
| 12691 | 12562 | .small = small, |
| 12692 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | |
| 12563 | .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))), | |
| 12693 | 12564 | } }, |
| 12694 | 12565 | }); |
| 12695 | 12566 | gz.instructions.appendAssumeCapacity(new_index); |
| ... | ... | @@ -12878,9 +12749,9 @@ const GenZir = struct { |
| 12878 | 12749 | .operand = operand, |
| 12879 | 12750 | .payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Break{ |
| 12880 | 12751 | .operand_src_node = if (operand_src_node) |src_node| |
| 12881 | gz.nodeIndexToRelative(src_node) | |
| 12752 | gz.nodeIndexToRelative(src_node).toOptional() | |
| 12882 | 12753 | else |
| 12883 | Zir.Inst.Break.no_src_node, | |
| 12754 | .none, | |
| 12884 | 12755 | .block_inst = block_inst, |
| 12885 | 12756 | }), |
| 12886 | 12757 | } }, |
| ... | ... | @@ -12969,7 +12840,7 @@ const GenZir = struct { |
| 12969 | 12840 | .data = .{ .extended = .{ |
| 12970 | 12841 | .opcode = opcode, |
| 12971 | 12842 | .small = undefined, |
| 12972 | .operand = @bitCast(gz.nodeIndexToRelative(src_node)), | |
| 12843 | .operand = @bitCast(@intFromEnum(gz.nodeIndexToRelative(src_node))), | |
| 12973 | 12844 | } }, |
| 12974 | 12845 | }); |
| 12975 | 12846 | } |
| ... | ... | @@ -13149,8 +13020,8 @@ const GenZir = struct { |
| 13149 | 13020 | const astgen = gz.astgen; |
| 13150 | 13021 | const gpa = astgen.gpa; |
| 13151 | 13022 | |
| 13152 | // Node 0 is valid for the root `struct_decl` of a file! | |
| 13153 | assert(args.src_node != 0 or gz.parent.tag == .top); | |
| 13023 | // Node .root is valid for the root `struct_decl` of a file! | |
| 13024 | assert(args.src_node != .root or gz.parent.tag == .top); | |
| 13154 | 13025 | |
| 13155 | 13026 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13156 | 13027 | |
| ... | ... | @@ -13210,7 +13081,7 @@ const GenZir = struct { |
| 13210 | 13081 | const astgen = gz.astgen; |
| 13211 | 13082 | const gpa = astgen.gpa; |
| 13212 | 13083 | |
| 13213 | assert(args.src_node != 0); | |
| 13084 | assert(args.src_node != .root); | |
| 13214 | 13085 | |
| 13215 | 13086 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13216 | 13087 | |
| ... | ... | @@ -13272,7 +13143,7 @@ const GenZir = struct { |
| 13272 | 13143 | const astgen = gz.astgen; |
| 13273 | 13144 | const gpa = astgen.gpa; |
| 13274 | 13145 | |
| 13275 | assert(args.src_node != 0); | |
| 13146 | assert(args.src_node != .root); | |
| 13276 | 13147 | |
| 13277 | 13148 | const fields_hash_arr: [4]u32 = @bitCast(args.fields_hash); |
| 13278 | 13149 | |
| ... | ... | @@ -13327,7 +13198,7 @@ const GenZir = struct { |
| 13327 | 13198 | const astgen = gz.astgen; |
| 13328 | 13199 | const gpa = astgen.gpa; |
| 13329 | 13200 | |
| 13330 | assert(args.src_node != 0); | |
| 13201 | assert(args.src_node != .root); | |
| 13331 | 13202 | |
| 13332 | 13203 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).@"struct".fields.len + 2); |
| 13333 | 13204 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{ |
| ... | ... | @@ -13521,9 +13392,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo |
| 13521 | 13392 | if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column }; |
| 13522 | 13393 | |
| 13523 | 13394 | const tree = gz.astgen.tree; |
| 13524 | const token_starts = tree.tokens.items(.start); | |
| 13525 | const main_tokens = tree.nodes.items(.main_token); | |
| 13526 | const node_start = token_starts[main_tokens[node]]; | |
| 13395 | const node_start = tree.tokenStart(tree.nodeMainToken(node)); | |
| 13527 | 13396 | gz.astgen.advanceSourceCursor(node_start); |
| 13528 | 13397 | |
| 13529 | 13398 | return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column }; |
| ... | ... | @@ -13532,8 +13401,7 @@ fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineCo |
| 13532 | 13401 | /// Advances the source cursor to the beginning of `node`. |
| 13533 | 13402 | fn advanceSourceCursorToNode(astgen: *AstGen, node: Ast.Node.Index) void { |
| 13534 | 13403 | const tree = astgen.tree; |
| 13535 | const token_starts = tree.tokens.items(.start); | |
| 13536 | const node_start = token_starts[tree.firstToken(node)]; | |
| 13404 | const node_start = tree.tokenStart(tree.firstToken(node)); | |
| 13537 | 13405 | astgen.advanceSourceCursor(node_start); |
| 13538 | 13406 | } |
| 13539 | 13407 | |
| ... | ... | @@ -13588,9 +13456,6 @@ fn scanContainer( |
| 13588 | 13456 | ) !u32 { |
| 13589 | 13457 | const gpa = astgen.gpa; |
| 13590 | 13458 | const tree = astgen.tree; |
| 13591 | const node_tags = tree.nodes.items(.tag); | |
| 13592 | const main_tokens = tree.nodes.items(.main_token); | |
| 13593 | const token_tags = tree.tokens.items(.tag); | |
| 13594 | 13459 | |
| 13595 | 13460 | var any_invalid_declarations = false; |
| 13596 | 13461 | |
| ... | ... | @@ -13620,7 +13485,7 @@ fn scanContainer( |
| 13620 | 13485 | var decl_count: u32 = 0; |
| 13621 | 13486 | for (members) |member_node| { |
| 13622 | 13487 | const Kind = enum { decl, field }; |
| 13623 | const kind: Kind, const name_token = switch (node_tags[member_node]) { | |
| 13488 | const kind: Kind, const name_token = switch (tree.nodeTag(member_node)) { | |
| 13624 | 13489 | .container_field_init, |
| 13625 | 13490 | .container_field_align, |
| 13626 | 13491 | .container_field, |
| ... | ... | @@ -13628,7 +13493,7 @@ fn scanContainer( |
| 13628 | 13493 | var full = tree.fullContainerField(member_node).?; |
| 13629 | 13494 | switch (container_kind) { |
| 13630 | 13495 | .@"struct", .@"opaque" => {}, |
| 13631 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree.nodes), | |
| 13496 | .@"union", .@"enum" => full.convertToNonTupleLike(astgen.tree), | |
| 13632 | 13497 | } |
| 13633 | 13498 | if (full.ast.tuple_like) continue; |
| 13634 | 13499 | break :blk .{ .field, full.ast.main_token }; |
| ... | ... | @@ -13640,7 +13505,7 @@ fn scanContainer( |
| 13640 | 13505 | .aligned_var_decl, |
| 13641 | 13506 | => blk: { |
| 13642 | 13507 | decl_count += 1; |
| 13643 | break :blk .{ .decl, main_tokens[member_node] + 1 }; | |
| 13508 | break :blk .{ .decl, tree.nodeMainToken(member_node) + 1 }; | |
| 13644 | 13509 | }, |
| 13645 | 13510 | |
| 13646 | 13511 | .fn_proto_simple, |
| ... | ... | @@ -13650,8 +13515,8 @@ fn scanContainer( |
| 13650 | 13515 | .fn_decl, |
| 13651 | 13516 | => blk: { |
| 13652 | 13517 | decl_count += 1; |
| 13653 | const ident = main_tokens[member_node] + 1; | |
| 13654 | if (token_tags[ident] != .identifier) { | |
| 13518 | const ident = tree.nodeMainToken(member_node) + 1; | |
| 13519 | if (tree.tokenTag(ident) != .identifier) { | |
| 13655 | 13520 | try astgen.appendErrorNode(member_node, "missing function name", .{}); |
| 13656 | 13521 | any_invalid_declarations = true; |
| 13657 | 13522 | continue; |
| ... | ... | @@ -13668,12 +13533,12 @@ fn scanContainer( |
| 13668 | 13533 | decl_count += 1; |
| 13669 | 13534 | // We don't want shadowing detection here, and test names work a bit differently, so |
| 13670 | 13535 | // we must do the redeclaration detection ourselves. |
| 13671 | const test_name_token = main_tokens[member_node] + 1; | |
| 13536 | const test_name_token = tree.nodeMainToken(member_node) + 1; | |
| 13672 | 13537 | const new_ent: NameEntry = .{ |
| 13673 | 13538 | .tok = test_name_token, |
| 13674 | 13539 | .next = null, |
| 13675 | 13540 | }; |
| 13676 | switch (token_tags[test_name_token]) { | |
| 13541 | switch (tree.tokenTag(test_name_token)) { | |
| 13677 | 13542 | else => {}, // unnamed test |
| 13678 | 13543 | .string_literal => { |
| 13679 | 13544 | const name = try astgen.strLitAsString(test_name_token); |
| ... | ... | @@ -14275,3 +14140,7 @@ fn fetchRemoveRefEntries(astgen: *AstGen, param_insts: []const Zir.Inst.Index) ! |
| 14275 | 14140 | } |
| 14276 | 14141 | return refs.items; |
| 14277 | 14142 | } |
| 14143 | ||
| 14144 | test { | |
| 14145 | _ = &generate; | |
| 14146 | } |
lib/std/zig/AstRlAnnotate.zig+159-142| ... | ... | @@ -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 | |
| ... | ... | @@ -338,7 +347,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 338 | 347 | for (full.ast.params) |param_node| { |
| 339 | 348 | _ = try astrl.expr(param_node, block, ResultInfo.type_only); |
| 340 | 349 | } |
| 341 | return switch (node_tags[node]) { | |
| 350 | return switch (tree.nodeTag(node)) { | |
| 342 | 351 | .call_one, |
| 343 | 352 | .call_one_comma, |
| 344 | 353 | .call, |
| ... | ... | @@ -354,8 +363,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 354 | 363 | }, |
| 355 | 364 | |
| 356 | 365 | .@"return" => { |
| 357 | if (node_datas[node].lhs != 0) { | |
| 358 | const ret_val_consumes_rl = try astrl.expr(node_datas[node].lhs, block, ResultInfo.typed_ptr); | |
| 366 | if (tree.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 367 | const ret_val_consumes_rl = try astrl.expr(lhs, block, ResultInfo.typed_ptr); | |
| 359 | 368 | if (ret_val_consumes_rl) { |
| 360 | 369 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 361 | 370 | } |
| ... | ... | @@ -364,7 +373,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 364 | 373 | }, |
| 365 | 374 | |
| 366 | 375 | .field_access => { |
| 367 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 376 | const lhs, _ = tree.nodeData(node).node_and_token; | |
| 377 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 368 | 378 | return false; |
| 369 | 379 | }, |
| 370 | 380 | |
| ... | ... | @@ -376,15 +386,15 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 376 | 386 | _ = try astrl.expr(full.ast.cond_expr, block, ResultInfo.type_only); // bool |
| 377 | 387 | } |
| 378 | 388 | |
| 379 | if (full.ast.else_expr == 0) { | |
| 380 | _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none); | |
| 381 | return false; | |
| 382 | } else { | |
| 389 | if (full.ast.else_expr.unwrap()) |else_expr| { | |
| 383 | 390 | const then_uses_rl = try astrl.expr(full.ast.then_expr, block, ri); |
| 384 | const else_uses_rl = try astrl.expr(full.ast.else_expr, block, ri); | |
| 391 | const else_uses_rl = try astrl.expr(else_expr, block, ri); | |
| 385 | 392 | const uses_rl = then_uses_rl or else_uses_rl; |
| 386 | 393 | if (uses_rl) try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 387 | 394 | return uses_rl; |
| 395 | } else { | |
| 396 | _ = try astrl.expr(full.ast.then_expr, block, ResultInfo.none); | |
| 397 | return false; | |
| 388 | 398 | } |
| 389 | 399 | }, |
| 390 | 400 | |
| ... | ... | @@ -405,12 +415,12 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 405 | 415 | .ri = ri, |
| 406 | 416 | .consumes_res_ptr = false, |
| 407 | 417 | }; |
| 408 | if (full.ast.cont_expr != 0) { | |
| 409 | _ = try astrl.expr(full.ast.cont_expr, &new_block, ResultInfo.none); | |
| 418 | if (full.ast.cont_expr.unwrap()) |cont_expr| { | |
| 419 | _ = try astrl.expr(cont_expr, &new_block, ResultInfo.none); | |
| 410 | 420 | } |
| 411 | 421 | _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none); |
| 412 | const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: { | |
| 413 | break :else_rl try astrl.expr(full.ast.else_expr, block, ri); | |
| 422 | const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: { | |
| 423 | break :else_rl try astrl.expr(else_expr, block, ri); | |
| 414 | 424 | } else false; |
| 415 | 425 | if (new_block.consumes_res_ptr or else_consumes_rl) { |
| 416 | 426 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| ... | ... | @@ -426,10 +436,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 426 | 436 | break :label try astrl.identString(label_token); |
| 427 | 437 | } else null; |
| 428 | 438 | for (full.ast.inputs) |input| { |
| 429 | if (node_tags[input] == .for_range) { | |
| 430 | _ = try astrl.expr(node_datas[input].lhs, block, ResultInfo.type_only); | |
| 431 | if (node_datas[input].rhs != 0) { | |
| 432 | _ = try astrl.expr(node_datas[input].rhs, block, ResultInfo.type_only); | |
| 439 | if (tree.nodeTag(input) == .for_range) { | |
| 440 | const lhs, const opt_rhs = tree.nodeData(input).node_and_opt_node; | |
| 441 | _ = try astrl.expr(lhs, block, ResultInfo.type_only); | |
| 442 | if (opt_rhs.unwrap()) |rhs| { | |
| 443 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 433 | 444 | } |
| 434 | 445 | } else { |
| 435 | 446 | _ = try astrl.expr(input, block, ResultInfo.none); |
| ... | ... | @@ -443,8 +454,8 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 443 | 454 | .consumes_res_ptr = false, |
| 444 | 455 | }; |
| 445 | 456 | _ = try astrl.expr(full.ast.then_expr, &new_block, ResultInfo.none); |
| 446 | const else_consumes_rl = if (full.ast.else_expr != 0) else_rl: { | |
| 447 | break :else_rl try astrl.expr(full.ast.else_expr, block, ri); | |
| 457 | const else_consumes_rl = if (full.ast.else_expr.unwrap()) |else_expr| else_rl: { | |
| 458 | break :else_rl try astrl.expr(else_expr, block, ri); | |
| 448 | 459 | } else false; |
| 449 | 460 | if (new_block.consumes_res_ptr or else_consumes_rl) { |
| 450 | 461 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| ... | ... | @@ -455,45 +466,49 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 455 | 466 | }, |
| 456 | 467 | |
| 457 | 468 | .slice_open => { |
| 458 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 459 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 469 | const sliced, const start = tree.nodeData(node).node_and_node; | |
| 470 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 471 | _ = try astrl.expr(start, block, ResultInfo.type_only); | |
| 460 | 472 | return false; |
| 461 | 473 | }, |
| 462 | 474 | .slice => { |
| 463 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice); | |
| 464 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 475 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 476 | const extra = tree.extraData(extra_index, Ast.Node.Slice); | |
| 477 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 465 | 478 | _ = try astrl.expr(extra.start, block, ResultInfo.type_only); |
| 466 | 479 | _ = try astrl.expr(extra.end, block, ResultInfo.type_only); |
| 467 | 480 | return false; |
| 468 | 481 | }, |
| 469 | 482 | .slice_sentinel => { |
| 470 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel); | |
| 471 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 483 | const sliced, const extra_index = tree.nodeData(node).node_and_extra; | |
| 484 | const extra = tree.extraData(extra_index, Ast.Node.SliceSentinel); | |
| 485 | _ = try astrl.expr(sliced, block, ResultInfo.none); | |
| 472 | 486 | _ = try astrl.expr(extra.start, block, ResultInfo.type_only); |
| 473 | if (extra.end != 0) { | |
| 474 | _ = try astrl.expr(extra.end, block, ResultInfo.type_only); | |
| 487 | if (extra.end.unwrap()) |end| { | |
| 488 | _ = try astrl.expr(end, block, ResultInfo.type_only); | |
| 475 | 489 | } |
| 476 | 490 | _ = try astrl.expr(extra.sentinel, block, ResultInfo.none); |
| 477 | 491 | return false; |
| 478 | 492 | }, |
| 479 | 493 | .deref => { |
| 480 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 494 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 481 | 495 | return false; |
| 482 | 496 | }, |
| 483 | 497 | .address_of => { |
| 484 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 498 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 485 | 499 | return false; |
| 486 | 500 | }, |
| 487 | 501 | .optional_type => { |
| 488 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 502 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.type_only); | |
| 489 | 503 | return false; |
| 490 | 504 | }, |
| 491 | .grouped_expression, | |
| 492 | 505 | .@"try", |
| 493 | 506 | .@"await", |
| 494 | 507 | .@"nosuspend", |
| 508 | => return astrl.expr(tree.nodeData(node).node, block, ri), | |
| 509 | .grouped_expression, | |
| 495 | 510 | .unwrap_optional, |
| 496 | => return astrl.expr(node_datas[node].lhs, block, ri), | |
| 511 | => return astrl.expr(tree.nodeData(node).node_and_token[0], block, ri), | |
| 497 | 512 | |
| 498 | 513 | .block_two, |
| 499 | 514 | .block_two_semicolon, |
| ... | ... | @@ -505,12 +520,14 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 505 | 520 | return astrl.blockExpr(block, ri, node, statements); |
| 506 | 521 | }, |
| 507 | 522 | .anyframe_type => { |
| 508 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 523 | _, const child_type = tree.nodeData(node).token_and_node; | |
| 524 | _ = try astrl.expr(child_type, block, ResultInfo.type_only); | |
| 509 | 525 | return false; |
| 510 | 526 | }, |
| 511 | 527 | .@"catch", .@"orelse" => { |
| 512 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 513 | const rhs_consumes_rl = try astrl.expr(node_datas[node].rhs, block, ri); | |
| 528 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 529 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 530 | const rhs_consumes_rl = try astrl.expr(rhs, block, ri); | |
| 514 | 531 | if (rhs_consumes_rl) { |
| 515 | 532 | try astrl.nodes_need_rl.putNoClobber(astrl.gpa, node, {}); |
| 516 | 533 | } |
| ... | ... | @@ -524,19 +541,19 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 524 | 541 | => { |
| 525 | 542 | const full = tree.fullPtrType(node).?; |
| 526 | 543 | _ = try astrl.expr(full.ast.child_type, block, ResultInfo.type_only); |
| 527 | if (full.ast.sentinel != 0) { | |
| 528 | _ = try astrl.expr(full.ast.sentinel, block, ResultInfo.type_only); | |
| 544 | if (full.ast.sentinel.unwrap()) |sentinel| { | |
| 545 | _ = try astrl.expr(sentinel, block, ResultInfo.type_only); | |
| 529 | 546 | } |
| 530 | if (full.ast.addrspace_node != 0) { | |
| 531 | _ = try astrl.expr(full.ast.addrspace_node, block, ResultInfo.type_only); | |
| 547 | if (full.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 548 | _ = try astrl.expr(addrspace_node, block, ResultInfo.type_only); | |
| 532 | 549 | } |
| 533 | if (full.ast.align_node != 0) { | |
| 534 | _ = try astrl.expr(full.ast.align_node, block, ResultInfo.type_only); | |
| 550 | if (full.ast.align_node.unwrap()) |align_node| { | |
| 551 | _ = try astrl.expr(align_node, block, ResultInfo.type_only); | |
| 535 | 552 | } |
| 536 | if (full.ast.bit_range_start != 0) { | |
| 537 | assert(full.ast.bit_range_end != 0); | |
| 538 | _ = try astrl.expr(full.ast.bit_range_start, block, ResultInfo.type_only); | |
| 539 | _ = try astrl.expr(full.ast.bit_range_end, block, ResultInfo.type_only); | |
| 553 | if (full.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 554 | const bit_range_end = full.ast.bit_range_end.unwrap().?; | |
| 555 | _ = try astrl.expr(bit_range_start, block, ResultInfo.type_only); | |
| 556 | _ = try astrl.expr(bit_range_end, block, ResultInfo.type_only); | |
| 540 | 557 | } |
| 541 | 558 | return false; |
| 542 | 559 | }, |
| ... | ... | @@ -560,63 +577,66 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 560 | 577 | }, |
| 561 | 578 | |
| 562 | 579 | .@"break" => { |
| 563 | if (node_datas[node].rhs == 0) { | |
| 580 | const opt_label, const opt_rhs = tree.nodeData(node).opt_token_and_opt_node; | |
| 581 | const rhs = opt_rhs.unwrap() orelse { | |
| 564 | 582 | // Breaks with void are not interesting |
| 565 | 583 | return false; |
| 566 | } | |
| 584 | }; | |
| 567 | 585 | |
| 568 | 586 | var opt_cur_block = block; |
| 569 | if (node_datas[node].lhs == 0) { | |
| 570 | // No label - we're breaking from a loop. | |
| 587 | if (opt_label.unwrap()) |label_token| { | |
| 588 | const break_label = try astrl.identString(label_token); | |
| 571 | 589 | while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) { |
| 572 | if (cur_block.is_loop) break; | |
| 590 | const block_label = cur_block.label orelse continue; | |
| 591 | if (std.mem.eql(u8, block_label, break_label)) break; | |
| 573 | 592 | } |
| 574 | 593 | } else { |
| 575 | const break_label = try astrl.identString(node_datas[node].lhs); | |
| 594 | // No label - we're breaking from a loop. | |
| 576 | 595 | while (opt_cur_block) |cur_block| : (opt_cur_block = cur_block.parent) { |
| 577 | const block_label = cur_block.label orelse continue; | |
| 578 | if (std.mem.eql(u8, block_label, break_label)) break; | |
| 596 | if (cur_block.is_loop) break; | |
| 579 | 597 | } |
| 580 | 598 | } |
| 581 | 599 | |
| 582 | 600 | if (opt_cur_block) |target_block| { |
| 583 | const consumes_break_rl = try astrl.expr(node_datas[node].rhs, block, target_block.ri); | |
| 601 | const consumes_break_rl = try astrl.expr(rhs, block, target_block.ri); | |
| 584 | 602 | if (consumes_break_rl) target_block.consumes_res_ptr = true; |
| 585 | 603 | } else { |
| 586 | 604 | // No corresponding scope to break from - AstGen will emit an error. |
| 587 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.none); | |
| 605 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 588 | 606 | } |
| 589 | 607 | |
| 590 | 608 | return false; |
| 591 | 609 | }, |
| 592 | 610 | |
| 593 | 611 | .array_type => { |
| 594 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 595 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 612 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 613 | _ = try astrl.expr(lhs, block, ResultInfo.type_only); | |
| 614 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 596 | 615 | return false; |
| 597 | 616 | }, |
| 598 | 617 | .array_type_sentinel => { |
| 599 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.ArrayTypeSentinel); | |
| 600 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.type_only); | |
| 618 | const len_expr, const extra_index = tree.nodeData(node).node_and_extra; | |
| 619 | const extra = tree.extraData(extra_index, Ast.Node.ArrayTypeSentinel); | |
| 620 | _ = try astrl.expr(len_expr, block, ResultInfo.type_only); | |
| 601 | 621 | _ = try astrl.expr(extra.elem_type, block, ResultInfo.type_only); |
| 602 | 622 | _ = try astrl.expr(extra.sentinel, block, ResultInfo.type_only); |
| 603 | 623 | return false; |
| 604 | 624 | }, |
| 605 | 625 | .array_access => { |
| 606 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 607 | _ = try astrl.expr(node_datas[node].rhs, block, ResultInfo.type_only); | |
| 626 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 627 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 628 | _ = try astrl.expr(rhs, block, ResultInfo.type_only); | |
| 608 | 629 | return false; |
| 609 | 630 | }, |
| 610 | 631 | .@"comptime" => { |
| 611 | 632 | // AstGen will emit an error if the scope is already comptime, so we can assume it is |
| 612 | 633 | // not. This means the result location is not forwarded. |
| 613 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 634 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 614 | 635 | return false; |
| 615 | 636 | }, |
| 616 | 637 | .@"switch", .switch_comma => { |
| 617 | const operand_node = node_datas[node].lhs; | |
| 618 | const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SubRange); | |
| 619 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 638 | const operand_node, const extra_index = tree.nodeData(node).node_and_extra; | |
| 639 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 620 | 640 | |
| 621 | 641 | _ = try astrl.expr(operand_node, block, ResultInfo.none); |
| 622 | 642 | |
| ... | ... | @@ -624,9 +644,10 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 624 | 644 | for (case_nodes) |case_node| { |
| 625 | 645 | const case = tree.fullSwitchCase(case_node).?; |
| 626 | 646 | for (case.ast.values) |item_node| { |
| 627 | if (node_tags[item_node] == .switch_range) { | |
| 628 | _ = try astrl.expr(node_datas[item_node].lhs, block, ResultInfo.none); | |
| 629 | _ = try astrl.expr(node_datas[item_node].rhs, block, ResultInfo.none); | |
| 647 | if (tree.nodeTag(item_node) == .switch_range) { | |
| 648 | const lhs, const rhs = tree.nodeData(item_node).node_and_node; | |
| 649 | _ = try astrl.expr(lhs, block, ResultInfo.none); | |
| 650 | _ = try astrl.expr(rhs, block, ResultInfo.none); | |
| 630 | 651 | } else { |
| 631 | 652 | _ = try astrl.expr(item_node, block, ResultInfo.none); |
| 632 | 653 | } |
| ... | ... | @@ -641,11 +662,11 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 641 | 662 | return any_prong_consumed_rl; |
| 642 | 663 | }, |
| 643 | 664 | .@"suspend" => { |
| 644 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 665 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 645 | 666 | return false; |
| 646 | 667 | }, |
| 647 | 668 | .@"resume" => { |
| 648 | _ = try astrl.expr(node_datas[node].lhs, block, ResultInfo.none); | |
| 669 | _ = try astrl.expr(tree.nodeData(node).node, block, ResultInfo.none); | |
| 649 | 670 | return false; |
| 650 | 671 | }, |
| 651 | 672 | |
| ... | ... | @@ -661,9 +682,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 661 | 682 | var buf: [2]Ast.Node.Index = undefined; |
| 662 | 683 | const full = tree.fullArrayInit(&buf, node).?; |
| 663 | 684 | |
| 664 | if (full.ast.type_expr != 0) { | |
| 685 | if (full.ast.type_expr.unwrap()) |type_expr| { | |
| 665 | 686 | // Explicitly typed init does not participate in RLS |
| 666 | _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none); | |
| 687 | _ = try astrl.expr(type_expr, block, ResultInfo.none); | |
| 667 | 688 | for (full.ast.elements) |elem_init| { |
| 668 | 689 | _ = try astrl.expr(elem_init, block, ResultInfo.type_only); |
| 669 | 690 | } |
| ... | ... | @@ -698,9 +719,9 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 698 | 719 | var buf: [2]Ast.Node.Index = undefined; |
| 699 | 720 | const full = tree.fullStructInit(&buf, node).?; |
| 700 | 721 | |
| 701 | if (full.ast.type_expr != 0) { | |
| 722 | if (full.ast.type_expr.unwrap()) |type_expr| { | |
| 702 | 723 | // Explicitly typed init does not participate in RLS |
| 703 | _ = try astrl.expr(full.ast.type_expr, block, ResultInfo.none); | |
| 724 | _ = try astrl.expr(type_expr, block, ResultInfo.none); | |
| 704 | 725 | for (full.ast.fields) |field_init| { |
| 705 | 726 | _ = try astrl.expr(field_init, block, ResultInfo.type_only); |
| 706 | 727 | } |
| ... | ... | @@ -728,33 +749,35 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 728 | 749 | .fn_proto_one, |
| 729 | 750 | .fn_proto, |
| 730 | 751 | .fn_decl, |
| 731 | => { | |
| 752 | => |tag| { | |
| 732 | 753 | var buf: [1]Ast.Node.Index = undefined; |
| 733 | 754 | const full = tree.fullFnProto(&buf, node).?; |
| 734 | const body_node = if (node_tags[node] == .fn_decl) node_datas[node].rhs else 0; | |
| 755 | const body_node = if (tag == .fn_decl) tree.nodeData(node).node_and_node[1].toOptional() else .none; | |
| 735 | 756 | { |
| 736 | 757 | var it = full.iterate(tree); |
| 737 | 758 | while (it.next()) |param| { |
| 738 | 759 | if (param.anytype_ellipsis3 == null) { |
| 739 | _ = try astrl.expr(param.type_expr, block, ResultInfo.type_only); | |
| 760 | const type_expr = param.type_expr.?; | |
| 761 | _ = try astrl.expr(type_expr, block, ResultInfo.type_only); | |
| 740 | 762 | } |
| 741 | 763 | } |
| 742 | 764 | } |
| 743 | if (full.ast.align_expr != 0) { | |
| 744 | _ = try astrl.expr(full.ast.align_expr, block, ResultInfo.type_only); | |
| 765 | if (full.ast.align_expr.unwrap()) |align_expr| { | |
| 766 | _ = try astrl.expr(align_expr, block, ResultInfo.type_only); | |
| 745 | 767 | } |
| 746 | if (full.ast.addrspace_expr != 0) { | |
| 747 | _ = try astrl.expr(full.ast.addrspace_expr, block, ResultInfo.type_only); | |
| 768 | if (full.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 769 | _ = try astrl.expr(addrspace_expr, block, ResultInfo.type_only); | |
| 748 | 770 | } |
| 749 | if (full.ast.section_expr != 0) { | |
| 750 | _ = try astrl.expr(full.ast.section_expr, block, ResultInfo.type_only); | |
| 771 | if (full.ast.section_expr.unwrap()) |section_expr| { | |
| 772 | _ = try astrl.expr(section_expr, block, ResultInfo.type_only); | |
| 751 | 773 | } |
| 752 | if (full.ast.callconv_expr != 0) { | |
| 753 | _ = try astrl.expr(full.ast.callconv_expr, block, ResultInfo.type_only); | |
| 774 | if (full.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 775 | _ = try astrl.expr(callconv_expr, block, ResultInfo.type_only); | |
| 754 | 776 | } |
| 755 | _ = try astrl.expr(full.ast.return_type, block, ResultInfo.type_only); | |
| 756 | if (body_node != 0) { | |
| 757 | _ = try astrl.expr(body_node, block, ResultInfo.none); | |
| 777 | const return_type = full.ast.return_type.unwrap().?; | |
| 778 | _ = try astrl.expr(return_type, block, ResultInfo.type_only); | |
| 779 | if (body_node.unwrap()) |body| { | |
| 780 | _ = try astrl.expr(body, block, ResultInfo.none); | |
| 758 | 781 | } |
| 759 | 782 | return false; |
| 760 | 783 | }, |
| ... | ... | @@ -763,8 +786,7 @@ fn expr(astrl: *AstRlAnnotate, node: Ast.Node.Index, block: ?*Block, ri: ResultI |
| 763 | 786 | |
| 764 | 787 | fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 { |
| 765 | 788 | const tree = astrl.tree; |
| 766 | const token_tags = tree.tokens.items(.tag); | |
| 767 | assert(token_tags[token] == .identifier); | |
| 789 | assert(tree.tokenTag(token) == .identifier); | |
| 768 | 790 | const ident_name = tree.tokenSlice(token); |
| 769 | 791 | if (!std.mem.startsWith(u8, ident_name, "@")) { |
| 770 | 792 | return ident_name; |
| ... | ... | @@ -777,13 +799,9 @@ fn identString(astrl: *AstRlAnnotate, token: Ast.TokenIndex) ![]const u8 { |
| 777 | 799 | |
| 778 | 800 | fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, statements: []const Ast.Node.Index) !bool { |
| 779 | 801 | const tree = astrl.tree; |
| 780 | const token_tags = tree.tokens.items(.tag); | |
| 781 | const main_tokens = tree.nodes.items(.main_token); | |
| 782 | 802 | |
| 783 | const lbrace = main_tokens[node]; | |
| 784 | if (token_tags[lbrace - 1] == .colon and | |
| 785 | token_tags[lbrace - 2] == .identifier) | |
| 786 | { | |
| 803 | const lbrace = tree.nodeMainToken(node); | |
| 804 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 787 | 805 | // Labeled block |
| 788 | 806 | var new_block: Block = .{ |
| 789 | 807 | .parent = parent_block, |
| ... | ... | @@ -812,8 +830,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. |
| 812 | 830 | _ = ri; // Currently, no builtin consumes its result location. |
| 813 | 831 | |
| 814 | 832 | const tree = astrl.tree; |
| 815 | const main_tokens = tree.nodes.items(.main_token); | |
| 816 | const builtin_token = main_tokens[node]; | |
| 833 | const builtin_token = tree.nodeMainToken(node); | |
| 817 | 834 | const builtin_name = tree.tokenSlice(builtin_token); |
| 818 | 835 | const info = BuiltinFn.list.get(builtin_name) orelse return false; |
| 819 | 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+1070-1327| ... | ... | @@ -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, | |
| 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 | } }, | |
| 453 | 474 | .trailing = trailing, |
| 454 | }, | |
| 455 | 1 => return Members{ | |
| 456 | .len = 1, | |
| 457 | .lhs = items[0], | |
| 458 | .rhs = 0, | |
| 459 | .trailing = trailing, | |
| 460 | }, | |
| 461 | 2 => return Members{ | |
| 462 | .len = 2, | |
| 463 | .lhs = items[0], | |
| 464 | .rhs = items[1], | |
| 475 | }; | |
| 476 | } else { | |
| 477 | return Members{ | |
| 478 | .len = items.len, | |
| 479 | .data = .{ .extra_range = try p.listToSpan(items) }, | |
| 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(.{ | |
| 2423 | if (params.len <= 1) { | |
| 2424 | return try p.addNode(.{ | |
| 2529 | 2425 | .tag = if (comma) .async_call_one_comma else .async_call_one, |
| 2530 | 2426 | .main_token = lparen, |
| 2531 | .data = .{ | |
| 2532 | .lhs = res, | |
| 2533 | .rhs = 0, | |
| 2534 | }, | |
| 2535 | }), | |
| 2536 | 1 => return p.addNode(.{ | |
| 2537 | .tag = if (comma) .async_call_one_comma else .async_call_one, | |
| 2538 | .main_token = lparen, | |
| 2539 | .data = .{ | |
| 2540 | .lhs = res, | |
| 2541 | .rhs = params[0], | |
| 2542 | }, | |
| 2543 | }), | |
| 2544 | else => return p.addNode(.{ | |
| 2427 | .data = .{ .node_and_opt_node = .{ | |
| 2428 | res, | |
| 2429 | if (params.len >= 1) params[0].toOptional() else .none, | |
| 2430 | } }, | |
| 2431 | }); | |
| 2432 | } else { | |
| 2433 | return try p.addNode(.{ | |
| 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,153 +2530,126 @@ 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(.{ | |
| 2647 | .keyword_for => return try p.parseFor(expectTypeExpr), | |
| 2648 | .keyword_while => return try p.parseWhileTypeExpr(), | |
| 2649 | .period => switch (p.tokenTag(p.tok_i + 1)) { | |
| 2650 | .identifier => return try p.addNode(.{ | |
| 2795 | 2651 | .tag = .enum_literal, |
| 2796 | .data = .{ | |
| 2797 | .lhs = p.nextToken(), // dot | |
| 2798 | .rhs = undefined, | |
| 2799 | }, | |
| 2652 | .data = .{ .token = p.nextToken() }, // dot | |
| 2800 | 2653 | .main_token = p.nextToken(), // identifier |
| 2801 | 2654 | }), |
| 2802 | 2655 | .l_brace => { |
| ... | ... | @@ -2808,11 +2661,11 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2808 | 2661 | |
| 2809 | 2662 | const scratch_top = p.scratch.items.len; |
| 2810 | 2663 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2811 | const field_init = try p.parseFieldInit(); | |
| 2812 | if (field_init != 0) { | |
| 2664 | const opt_field_init = try p.parseFieldInit(); | |
| 2665 | if (opt_field_init) |field_init| { | |
| 2813 | 2666 | try p.scratch.append(p.gpa, field_init); |
| 2814 | 2667 | while (true) { |
| 2815 | switch (p.token_tags[p.tok_i]) { | |
| 2668 | switch (p.tokenTag(p.tok_i)) { | |
| 2816 | 2669 | .comma => p.tok_i += 1, |
| 2817 | 2670 | .r_brace => { |
| 2818 | 2671 | p.tok_i += 1; |
| ... | ... | @@ -2826,37 +2679,24 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2826 | 2679 | const next = try p.expectFieldInit(); |
| 2827 | 2680 | try p.scratch.append(p.gpa, next); |
| 2828 | 2681 | } |
| 2829 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 2682 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 2830 | 2683 | const inits = p.scratch.items[scratch_top..]; |
| 2831 | switch (inits.len) { | |
| 2832 | 0 => unreachable, | |
| 2833 | 1 => return p.addNode(.{ | |
| 2684 | std.debug.assert(inits.len != 0); | |
| 2685 | if (inits.len <= 2) { | |
| 2686 | return try p.addNode(.{ | |
| 2834 | 2687 | .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, |
| 2835 | 2688 | .main_token = lbrace, |
| 2836 | .data = .{ | |
| 2837 | .lhs = inits[0], | |
| 2838 | .rhs = 0, | |
| 2839 | }, | |
| 2840 | }), | |
| 2841 | 2 => return p.addNode(.{ | |
| 2842 | .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two, | |
| 2689 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2690 | if (inits.len >= 1) .fromOptional(inits[0]) else .none, | |
| 2691 | if (inits.len >= 2) .fromOptional(inits[1]) else .none, | |
| 2692 | } }, | |
| 2693 | }); | |
| 2694 | } else { | |
| 2695 | return try p.addNode(.{ | |
| 2696 | .tag = if (comma) .struct_init_dot_comma else .struct_init_dot, | |
| 2843 | 2697 | .main_token = lbrace, |
| 2844 | .data = .{ | |
| 2845 | .lhs = inits[0], | |
| 2846 | .rhs = inits[1], | |
| 2847 | }, | |
| 2848 | }), | |
| 2849 | else => { | |
| 2850 | const span = try p.listToSpan(inits); | |
| 2851 | return p.addNode(.{ | |
| 2852 | .tag = if (comma) .struct_init_dot_comma else .struct_init_dot, | |
| 2853 | .main_token = lbrace, | |
| 2854 | .data = .{ | |
| 2855 | .lhs = span.start, | |
| 2856 | .rhs = span.end, | |
| 2857 | }, | |
| 2858 | }); | |
| 2859 | }, | |
| 2698 | .data = .{ .extra_range = try p.listToSpan(inits) }, | |
| 2699 | }); | |
| 2860 | 2700 | } |
| 2861 | 2701 | } |
| 2862 | 2702 | |
| ... | ... | @@ -2864,7 +2704,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2864 | 2704 | if (p.eatToken(.r_brace)) |_| break; |
| 2865 | 2705 | const elem_init = try p.expectExpr(); |
| 2866 | 2706 | try p.scratch.append(p.gpa, elem_init); |
| 2867 | switch (p.token_tags[p.tok_i]) { | |
| 2707 | switch (p.tokenTag(p.tok_i)) { | |
| 2868 | 2708 | .comma => p.tok_i += 1, |
| 2869 | 2709 | .r_brace => { |
| 2870 | 2710 | p.tok_i += 1; |
| ... | ... | @@ -2875,49 +2715,30 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2875 | 2715 | else => try p.warn(.expected_comma_after_initializer), |
| 2876 | 2716 | } |
| 2877 | 2717 | } |
| 2878 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 2718 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 2879 | 2719 | const inits = p.scratch.items[scratch_top..]; |
| 2880 | switch (inits.len) { | |
| 2881 | 0 => return p.addNode(.{ | |
| 2882 | .tag = .struct_init_dot_two, | |
| 2883 | .main_token = lbrace, | |
| 2884 | .data = .{ | |
| 2885 | .lhs = 0, | |
| 2886 | .rhs = 0, | |
| 2887 | }, | |
| 2888 | }), | |
| 2889 | 1 => return p.addNode(.{ | |
| 2890 | .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2720 | if (inits.len <= 2) { | |
| 2721 | return try p.addNode(.{ | |
| 2722 | .tag = if (inits.len == 0) | |
| 2723 | .struct_init_dot_two | |
| 2724 | else if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2891 | 2725 | .main_token = lbrace, |
| 2892 | .data = .{ | |
| 2893 | .lhs = inits[0], | |
| 2894 | .rhs = 0, | |
| 2895 | }, | |
| 2896 | }), | |
| 2897 | 2 => return p.addNode(.{ | |
| 2898 | .tag = if (comma) .array_init_dot_two_comma else .array_init_dot_two, | |
| 2726 | .data = .{ .opt_node_and_opt_node = .{ | |
| 2727 | if (inits.len >= 1) inits[0].toOptional() else .none, | |
| 2728 | if (inits.len >= 2) inits[1].toOptional() else .none, | |
| 2729 | } }, | |
| 2730 | }); | |
| 2731 | } else { | |
| 2732 | return try p.addNode(.{ | |
| 2733 | .tag = if (comma) .array_init_dot_comma else .array_init_dot, | |
| 2899 | 2734 | .main_token = lbrace, |
| 2900 | .data = .{ | |
| 2901 | .lhs = inits[0], | |
| 2902 | .rhs = inits[1], | |
| 2903 | }, | |
| 2904 | }), | |
| 2905 | else => { | |
| 2906 | const span = try p.listToSpan(inits); | |
| 2907 | return p.addNode(.{ | |
| 2908 | .tag = if (comma) .array_init_dot_comma else .array_init_dot, | |
| 2909 | .main_token = lbrace, | |
| 2910 | .data = .{ | |
| 2911 | .lhs = span.start, | |
| 2912 | .rhs = span.end, | |
| 2913 | }, | |
| 2914 | }); | |
| 2915 | }, | |
| 2735 | .data = .{ .extra_range = try p.listToSpan(inits) }, | |
| 2736 | }); | |
| 2916 | 2737 | } |
| 2917 | 2738 | }, |
| 2918 | else => return null_node, | |
| 2739 | else => return null, | |
| 2919 | 2740 | }, |
| 2920 | .keyword_error => switch (p.token_tags[p.tok_i + 1]) { | |
| 2741 | .keyword_error => switch (p.tokenTag(p.tok_i + 1)) { | |
| 2921 | 2742 | .l_brace => { |
| 2922 | 2743 | const error_token = p.tok_i; |
| 2923 | 2744 | p.tok_i += 2; |
| ... | ... | @@ -2925,7 +2746,7 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2925 | 2746 | if (p.eatToken(.r_brace)) |_| break; |
| 2926 | 2747 | _ = try p.eatDocComments(); |
| 2927 | 2748 | _ = try p.expectToken(.identifier); |
| 2928 | switch (p.token_tags[p.tok_i]) { | |
| 2749 | switch (p.tokenTag(p.tok_i)) { | |
| 2929 | 2750 | .comma => p.tok_i += 1, |
| 2930 | 2751 | .r_brace => { |
| 2931 | 2752 | p.tok_i += 1; |
| ... | ... | @@ -2936,13 +2757,10 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2936 | 2757 | else => try p.warn(.expected_comma_after_field), |
| 2937 | 2758 | } |
| 2938 | 2759 | } |
| 2939 | return p.addNode(.{ | |
| 2760 | return try p.addNode(.{ | |
| 2940 | 2761 | .tag = .error_set_decl, |
| 2941 | 2762 | .main_token = error_token, |
| 2942 | .data = .{ | |
| 2943 | .lhs = undefined, | |
| 2944 | .rhs = p.tok_i - 1, // rbrace | |
| 2945 | }, | |
| 2763 | .data = .{ .token = p.tok_i - 1 }, // rbrace | |
| 2946 | 2764 | }); |
| 2947 | 2765 | }, |
| 2948 | 2766 | else => { |
| ... | ... | @@ -2951,41 +2769,37 @@ fn parsePrimaryTypeExpr(p: *Parse) !Node.Index { |
| 2951 | 2769 | if (period == null) try p.warnExpected(.period); |
| 2952 | 2770 | const identifier = p.eatToken(.identifier); |
| 2953 | 2771 | if (identifier == null) try p.warnExpected(.identifier); |
| 2954 | return p.addNode(.{ | |
| 2772 | return try p.addNode(.{ | |
| 2955 | 2773 | .tag = .error_value, |
| 2956 | 2774 | .main_token = main_token, |
| 2957 | .data = .{ | |
| 2958 | .lhs = period orelse 0, | |
| 2959 | .rhs = identifier orelse 0, | |
| 2960 | }, | |
| 2775 | .data = .{ .opt_token_and_opt_token = .{ | |
| 2776 | .fromOptional(period), | |
| 2777 | .fromOptional(identifier), | |
| 2778 | } }, | |
| 2961 | 2779 | }); |
| 2962 | 2780 | }, |
| 2963 | 2781 | }, |
| 2964 | .l_paren => return p.addNode(.{ | |
| 2782 | .l_paren => return try p.addNode(.{ | |
| 2965 | 2783 | .tag = .grouped_expression, |
| 2966 | 2784 | .main_token = p.nextToken(), |
| 2967 | .data = .{ | |
| 2968 | .lhs = try p.expectExpr(), | |
| 2969 | .rhs = try p.expectToken(.r_paren), | |
| 2970 | }, | |
| 2785 | .data = .{ .node_and_token = .{ | |
| 2786 | try p.expectExpr(), | |
| 2787 | try p.expectToken(.r_paren), | |
| 2788 | } }, | |
| 2971 | 2789 | }), |
| 2972 | else => return null_node, | |
| 2790 | else => return null, | |
| 2973 | 2791 | } |
| 2974 | 2792 | } |
| 2975 | 2793 | |
| 2976 | 2794 | 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; | |
| 2795 | return try p.parsePrimaryTypeExpr() orelse return p.fail(.expected_primary_type_expr); | |
| 2982 | 2796 | } |
| 2983 | 2797 | |
| 2984 | 2798 | /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr? |
| 2985 | 2799 | /// |
| 2986 | 2800 | /// 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; | |
| 2801 | fn parseWhileTypeExpr(p: *Parse) !?Node.Index { | |
| 2802 | const while_token = p.eatToken(.keyword_while) orelse return null; | |
| 2989 | 2803 | _ = try p.expectToken(.l_paren); |
| 2990 | 2804 | const condition = try p.expectExpr(); |
| 2991 | 2805 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -2994,54 +2808,52 @@ fn parseWhileTypeExpr(p: *Parse) !Node.Index { |
| 2994 | 2808 | |
| 2995 | 2809 | const then_expr = try p.expectTypeExpr(); |
| 2996 | 2810 | _ = p.eatToken(.keyword_else) orelse { |
| 2997 | if (cont_expr == 0) { | |
| 2998 | return p.addNode(.{ | |
| 2811 | if (cont_expr == null) { | |
| 2812 | return try p.addNode(.{ | |
| 2999 | 2813 | .tag = .while_simple, |
| 3000 | 2814 | .main_token = while_token, |
| 3001 | .data = .{ | |
| 3002 | .lhs = condition, | |
| 3003 | .rhs = then_expr, | |
| 3004 | }, | |
| 2815 | .data = .{ .node_and_node = .{ | |
| 2816 | condition, | |
| 2817 | then_expr, | |
| 2818 | } }, | |
| 3005 | 2819 | }); |
| 3006 | 2820 | } else { |
| 3007 | return p.addNode(.{ | |
| 2821 | return try p.addNode(.{ | |
| 3008 | 2822 | .tag = .while_cont, |
| 3009 | 2823 | .main_token = while_token, |
| 3010 | .data = .{ | |
| 3011 | .lhs = condition, | |
| 3012 | .rhs = try p.addExtra(Node.WhileCont{ | |
| 3013 | .cont_expr = cont_expr, | |
| 2824 | .data = .{ .node_and_extra = .{ | |
| 2825 | condition, try p.addExtra(Node.WhileCont{ | |
| 2826 | .cont_expr = cont_expr.?, | |
| 3014 | 2827 | .then_expr = then_expr, |
| 3015 | 2828 | }), |
| 3016 | }, | |
| 2829 | } }, | |
| 3017 | 2830 | }); |
| 3018 | 2831 | } |
| 3019 | 2832 | }; |
| 3020 | 2833 | _ = try p.parsePayload(); |
| 3021 | 2834 | const else_expr = try p.expectTypeExpr(); |
| 3022 | return p.addNode(.{ | |
| 2835 | return try p.addNode(.{ | |
| 3023 | 2836 | .tag = .@"while", |
| 3024 | 2837 | .main_token = while_token, |
| 3025 | .data = .{ | |
| 3026 | .lhs = condition, | |
| 3027 | .rhs = try p.addExtra(Node.While{ | |
| 3028 | .cont_expr = cont_expr, | |
| 2838 | .data = .{ .node_and_extra = .{ | |
| 2839 | condition, try p.addExtra(Node.While{ | |
| 2840 | .cont_expr = .fromOptional(cont_expr), | |
| 3029 | 2841 | .then_expr = then_expr, |
| 3030 | 2842 | .else_expr = else_expr, |
| 3031 | 2843 | }), |
| 3032 | }, | |
| 2844 | } }, | |
| 3033 | 2845 | }); |
| 3034 | 2846 | } |
| 3035 | 2847 | |
| 3036 | 2848 | /// 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); | |
| 2849 | fn parseSwitchExpr(p: *Parse, is_labeled: bool) !?Node.Index { | |
| 2850 | const switch_token = p.eatToken(.keyword_switch) orelse return null; | |
| 2851 | return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 3040 | 2852 | } |
| 3041 | 2853 | |
| 3042 | 2854 | fn expectSwitchExpr(p: *Parse, is_labeled: bool) !Node.Index { |
| 3043 | 2855 | const switch_token = p.assertToken(.keyword_switch); |
| 3044 | return p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 2856 | return try p.expectSwitchSuffix(if (is_labeled) switch_token - 2 else switch_token); | |
| 3045 | 2857 | } |
| 3046 | 2858 | |
| 3047 | 2859 | fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { |
| ... | ... | @@ -3050,19 +2862,19 @@ fn expectSwitchSuffix(p: *Parse, main_token: TokenIndex) !Node.Index { |
| 3050 | 2862 | _ = try p.expectToken(.r_paren); |
| 3051 | 2863 | _ = try p.expectToken(.l_brace); |
| 3052 | 2864 | const cases = try p.parseSwitchProngList(); |
| 3053 | const trailing_comma = p.token_tags[p.tok_i - 1] == .comma; | |
| 2865 | const trailing_comma = p.tokenTag(p.tok_i - 1) == .comma; | |
| 3054 | 2866 | _ = try p.expectToken(.r_brace); |
| 3055 | 2867 | |
| 3056 | 2868 | return p.addNode(.{ |
| 3057 | 2869 | .tag = if (trailing_comma) .switch_comma else .@"switch", |
| 3058 | 2870 | .main_token = main_token, |
| 3059 | .data = .{ | |
| 3060 | .lhs = expr_node, | |
| 3061 | .rhs = try p.addExtra(Node.SubRange{ | |
| 2871 | .data = .{ .node_and_extra = .{ | |
| 2872 | expr_node, | |
| 2873 | try p.addExtra(Node.SubRange{ | |
| 3062 | 2874 | .start = cases.start, |
| 3063 | 2875 | .end = cases.end, |
| 3064 | 2876 | }), |
| 3065 | }, | |
| 2877 | } }, | |
| 3066 | 2878 | }); |
| 3067 | 2879 | } |
| 3068 | 2880 | |
| ... | ... | @@ -3089,10 +2901,10 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3089 | 2901 | return p.addNode(.{ |
| 3090 | 2902 | .tag = .asm_simple, |
| 3091 | 2903 | .main_token = asm_token, |
| 3092 | .data = .{ | |
| 3093 | .lhs = template, | |
| 3094 | .rhs = rparen, | |
| 3095 | }, | |
| 2904 | .data = .{ .node_and_token = .{ | |
| 2905 | template, | |
| 2906 | rparen, | |
| 2907 | } }, | |
| 3096 | 2908 | }); |
| 3097 | 2909 | } |
| 3098 | 2910 | |
| ... | ... | @@ -3102,10 +2914,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3102 | 2914 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3103 | 2915 | |
| 3104 | 2916 | while (true) { |
| 3105 | const output_item = try p.parseAsmOutputItem(); | |
| 3106 | if (output_item == 0) break; | |
| 2917 | const output_item = try p.parseAsmOutputItem() orelse break; | |
| 3107 | 2918 | try p.scratch.append(p.gpa, output_item); |
| 3108 | switch (p.token_tags[p.tok_i]) { | |
| 2919 | switch (p.tokenTag(p.tok_i)) { | |
| 3109 | 2920 | .comma => p.tok_i += 1, |
| 3110 | 2921 | // All possible delimiters. |
| 3111 | 2922 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3115,10 +2926,9 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3115 | 2926 | } |
| 3116 | 2927 | if (p.eatToken(.colon)) |_| { |
| 3117 | 2928 | while (true) { |
| 3118 | const input_item = try p.parseAsmInputItem(); | |
| 3119 | if (input_item == 0) break; | |
| 2929 | const input_item = try p.parseAsmInputItem() orelse break; | |
| 3120 | 2930 | try p.scratch.append(p.gpa, input_item); |
| 3121 | switch (p.token_tags[p.tok_i]) { | |
| 2931 | switch (p.tokenTag(p.tok_i)) { | |
| 3122 | 2932 | .comma => p.tok_i += 1, |
| 3123 | 2933 | // All possible delimiters. |
| 3124 | 2934 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3128,7 +2938,7 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3128 | 2938 | } |
| 3129 | 2939 | if (p.eatToken(.colon)) |_| { |
| 3130 | 2940 | while (p.eatToken(.string_literal)) |_| { |
| 3131 | switch (p.token_tags[p.tok_i]) { | |
| 2941 | switch (p.tokenTag(p.tok_i)) { | |
| 3132 | 2942 | .comma => p.tok_i += 1, |
| 3133 | 2943 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| 3134 | 2944 | // Likely just a missing comma; give error but continue parsing. |
| ... | ... | @@ -3142,121 +2952,106 @@ fn expectAsmExpr(p: *Parse) !Node.Index { |
| 3142 | 2952 | return p.addNode(.{ |
| 3143 | 2953 | .tag = .@"asm", |
| 3144 | 2954 | .main_token = asm_token, |
| 3145 | .data = .{ | |
| 3146 | .lhs = template, | |
| 3147 | .rhs = try p.addExtra(Node.Asm{ | |
| 2955 | .data = .{ .node_and_extra = .{ | |
| 2956 | template, | |
| 2957 | try p.addExtra(Node.Asm{ | |
| 3148 | 2958 | .items_start = span.start, |
| 3149 | 2959 | .items_end = span.end, |
| 3150 | 2960 | .rparen = rparen, |
| 3151 | 2961 | }), |
| 3152 | }, | |
| 2962 | } }, | |
| 3153 | 2963 | }); |
| 3154 | 2964 | } |
| 3155 | 2965 | |
| 3156 | 2966 | /// 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; | |
| 2967 | fn parseAsmOutputItem(p: *Parse) !?Node.Index { | |
| 2968 | _ = p.eatToken(.l_bracket) orelse return null; | |
| 3159 | 2969 | const identifier = try p.expectToken(.identifier); |
| 3160 | 2970 | _ = try p.expectToken(.r_bracket); |
| 3161 | 2971 | _ = try p.expectToken(.string_literal); |
| 3162 | 2972 | _ = try p.expectToken(.l_paren); |
| 3163 | const type_expr: Node.Index = blk: { | |
| 2973 | const type_expr: Node.OptionalIndex = blk: { | |
| 3164 | 2974 | if (p.eatToken(.arrow)) |_| { |
| 3165 | break :blk try p.expectTypeExpr(); | |
| 2975 | break :blk .fromOptional(try p.expectTypeExpr()); | |
| 3166 | 2976 | } else { |
| 3167 | 2977 | _ = try p.expectToken(.identifier); |
| 3168 | break :blk null_node; | |
| 2978 | break :blk .none; | |
| 3169 | 2979 | } |
| 3170 | 2980 | }; |
| 3171 | 2981 | const rparen = try p.expectToken(.r_paren); |
| 3172 | return p.addNode(.{ | |
| 2982 | return try p.addNode(.{ | |
| 3173 | 2983 | .tag = .asm_output, |
| 3174 | 2984 | .main_token = identifier, |
| 3175 | .data = .{ | |
| 3176 | .lhs = type_expr, | |
| 3177 | .rhs = rparen, | |
| 3178 | }, | |
| 2985 | .data = .{ .opt_node_and_token = .{ | |
| 2986 | type_expr, | |
| 2987 | rparen, | |
| 2988 | } }, | |
| 3179 | 2989 | }); |
| 3180 | 2990 | } |
| 3181 | 2991 | |
| 3182 | 2992 | /// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN |
| 3183 | fn parseAsmInputItem(p: *Parse) !Node.Index { | |
| 3184 | _ = p.eatToken(.l_bracket) orelse return null_node; | |
| 2993 | fn parseAsmInputItem(p: *Parse) !?Node.Index { | |
| 2994 | _ = p.eatToken(.l_bracket) orelse return null; | |
| 3185 | 2995 | const identifier = try p.expectToken(.identifier); |
| 3186 | 2996 | _ = try p.expectToken(.r_bracket); |
| 3187 | 2997 | _ = try p.expectToken(.string_literal); |
| 3188 | 2998 | _ = try p.expectToken(.l_paren); |
| 3189 | 2999 | const expr = try p.expectExpr(); |
| 3190 | 3000 | const rparen = try p.expectToken(.r_paren); |
| 3191 | return p.addNode(.{ | |
| 3001 | return try p.addNode(.{ | |
| 3192 | 3002 | .tag = .asm_input, |
| 3193 | 3003 | .main_token = identifier, |
| 3194 | .data = .{ | |
| 3195 | .lhs = expr, | |
| 3196 | .rhs = rparen, | |
| 3197 | }, | |
| 3004 | .data = .{ .node_and_token = .{ | |
| 3005 | expr, | |
| 3006 | rparen, | |
| 3007 | } }, | |
| 3198 | 3008 | }); |
| 3199 | 3009 | } |
| 3200 | 3010 | |
| 3201 | 3011 | /// BreakLabel <- COLON IDENTIFIER |
| 3202 | fn parseBreakLabel(p: *Parse) !TokenIndex { | |
| 3203 | _ = p.eatToken(.colon) orelse return null_node; | |
| 3204 | return p.expectToken(.identifier); | |
| 3012 | fn parseBreakLabel(p: *Parse) Error!OptionalTokenIndex { | |
| 3013 | _ = p.eatToken(.colon) orelse return .none; | |
| 3014 | const next_token = try p.expectToken(.identifier); | |
| 3015 | return .fromToken(next_token); | |
| 3205 | 3016 | } |
| 3206 | 3017 | |
| 3207 | 3018 | /// 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; | |
| 3019 | fn parseBlockLabel(p: *Parse) ?TokenIndex { | |
| 3020 | return p.eatTokens(&.{ .identifier, .colon }); | |
| 3217 | 3021 | } |
| 3218 | 3022 | |
| 3219 | 3023 | /// 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; | |
| 3024 | fn parseFieldInit(p: *Parse) !?Node.Index { | |
| 3025 | if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| { | |
| 3026 | return try p.expectExpr(); | |
| 3229 | 3027 | } |
| 3028 | return null; | |
| 3230 | 3029 | } |
| 3231 | 3030 | |
| 3232 | 3031 | 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(); | |
| 3032 | if (p.eatTokens(&.{ .period, .identifier, .equal })) |_| { | |
| 3033 | return try p.expectExpr(); | |
| 3034 | } | |
| 3035 | return p.fail(.expected_initializer); | |
| 3240 | 3036 | } |
| 3241 | 3037 | |
| 3242 | 3038 | /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN |
| 3243 | fn parseWhileContinueExpr(p: *Parse) !Node.Index { | |
| 3039 | fn parseWhileContinueExpr(p: *Parse) !?Node.Index { | |
| 3244 | 3040 | _ = p.eatToken(.colon) orelse { |
| 3245 | if (p.token_tags[p.tok_i] == .l_paren and | |
| 3041 | if (p.tokenTag(p.tok_i) == .l_paren and | |
| 3246 | 3042 | p.tokensOnSameLine(p.tok_i - 1, p.tok_i)) |
| 3247 | 3043 | return p.fail(.expected_continue_expr); |
| 3248 | return null_node; | |
| 3044 | return null; | |
| 3249 | 3045 | }; |
| 3250 | 3046 | _ = try p.expectToken(.l_paren); |
| 3251 | const node = try p.parseAssignExpr(); | |
| 3252 | if (node == 0) return p.fail(.expected_expr_or_assignment); | |
| 3047 | const node = try p.parseAssignExpr() orelse return p.fail(.expected_expr_or_assignment); | |
| 3253 | 3048 | _ = try p.expectToken(.r_paren); |
| 3254 | 3049 | return node; |
| 3255 | 3050 | } |
| 3256 | 3051 | |
| 3257 | 3052 | /// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN |
| 3258 | fn parseLinkSection(p: *Parse) !Node.Index { | |
| 3259 | _ = p.eatToken(.keyword_linksection) orelse return null_node; | |
| 3053 | fn parseLinkSection(p: *Parse) !?Node.Index { | |
| 3054 | _ = p.eatToken(.keyword_linksection) orelse return null; | |
| 3260 | 3055 | _ = try p.expectToken(.l_paren); |
| 3261 | 3056 | const expr_node = try p.expectExpr(); |
| 3262 | 3057 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3264,8 +3059,8 @@ fn parseLinkSection(p: *Parse) !Node.Index { |
| 3264 | 3059 | } |
| 3265 | 3060 | |
| 3266 | 3061 | /// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN |
| 3267 | fn parseCallconv(p: *Parse) !Node.Index { | |
| 3268 | _ = p.eatToken(.keyword_callconv) orelse return null_node; | |
| 3062 | fn parseCallconv(p: *Parse) !?Node.Index { | |
| 3063 | _ = p.eatToken(.keyword_callconv) orelse return null; | |
| 3269 | 3064 | _ = try p.expectToken(.l_paren); |
| 3270 | 3065 | const expr_node = try p.expectExpr(); |
| 3271 | 3066 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3273,8 +3068,8 @@ fn parseCallconv(p: *Parse) !Node.Index { |
| 3273 | 3068 | } |
| 3274 | 3069 | |
| 3275 | 3070 | /// AddrSpace <- KEYWORD_addrspace LPAREN Expr RPAREN |
| 3276 | fn parseAddrSpace(p: *Parse) !Node.Index { | |
| 3277 | _ = p.eatToken(.keyword_addrspace) orelse return null_node; | |
| 3071 | fn parseAddrSpace(p: *Parse) !?Node.Index { | |
| 3072 | _ = p.eatToken(.keyword_addrspace) orelse return null; | |
| 3278 | 3073 | _ = try p.expectToken(.l_paren); |
| 3279 | 3074 | const expr_node = try p.expectExpr(); |
| 3280 | 3075 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3292,59 +3087,53 @@ fn parseAddrSpace(p: *Parse) !Node.Index { |
| 3292 | 3087 | /// ParamType |
| 3293 | 3088 | /// <- KEYWORD_anytype |
| 3294 | 3089 | /// / TypeExpr |
| 3295 | fn expectParamDecl(p: *Parse) !Node.Index { | |
| 3090 | fn expectParamDecl(p: *Parse) !?Node.Index { | |
| 3296 | 3091 | _ = try p.eatDocComments(); |
| 3297 | switch (p.token_tags[p.tok_i]) { | |
| 3092 | switch (p.tokenTag(p.tok_i)) { | |
| 3298 | 3093 | .keyword_noalias, .keyword_comptime => p.tok_i += 1, |
| 3299 | 3094 | .ellipsis3 => { |
| 3300 | 3095 | p.tok_i += 1; |
| 3301 | return null_node; | |
| 3096 | return null; | |
| 3302 | 3097 | }, |
| 3303 | 3098 | else => {}, |
| 3304 | 3099 | } |
| 3305 | if (p.token_tags[p.tok_i] == .identifier and | |
| 3306 | p.token_tags[p.tok_i + 1] == .colon) | |
| 3307 | { | |
| 3308 | p.tok_i += 2; | |
| 3309 | } | |
| 3310 | switch (p.token_tags[p.tok_i]) { | |
| 3311 | .keyword_anytype => { | |
| 3312 | p.tok_i += 1; | |
| 3313 | return null_node; | |
| 3314 | }, | |
| 3315 | else => return p.expectTypeExpr(), | |
| 3100 | _ = p.eatTokens(&.{ .identifier, .colon }); | |
| 3101 | if (p.eatToken(.keyword_anytype)) |_| { | |
| 3102 | return null; | |
| 3103 | } else { | |
| 3104 | return try p.expectTypeExpr(); | |
| 3316 | 3105 | } |
| 3317 | 3106 | } |
| 3318 | 3107 | |
| 3319 | 3108 | /// Payload <- PIPE IDENTIFIER PIPE |
| 3320 | fn parsePayload(p: *Parse) !TokenIndex { | |
| 3321 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3109 | fn parsePayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3110 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3322 | 3111 | const identifier = try p.expectToken(.identifier); |
| 3323 | 3112 | _ = try p.expectToken(.pipe); |
| 3324 | return identifier; | |
| 3113 | return .fromToken(identifier); | |
| 3325 | 3114 | } |
| 3326 | 3115 | |
| 3327 | 3116 | /// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE |
| 3328 | fn parsePtrPayload(p: *Parse) !TokenIndex { | |
| 3329 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3117 | fn parsePtrPayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3118 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3330 | 3119 | _ = p.eatToken(.asterisk); |
| 3331 | 3120 | const identifier = try p.expectToken(.identifier); |
| 3332 | 3121 | _ = try p.expectToken(.pipe); |
| 3333 | return identifier; | |
| 3122 | return .fromToken(identifier); | |
| 3334 | 3123 | } |
| 3335 | 3124 | |
| 3336 | 3125 | /// Returns the first identifier token, if any. |
| 3337 | 3126 | /// |
| 3338 | 3127 | /// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE |
| 3339 | fn parsePtrIndexPayload(p: *Parse) !TokenIndex { | |
| 3340 | _ = p.eatToken(.pipe) orelse return null_node; | |
| 3128 | fn parsePtrIndexPayload(p: *Parse) Error!OptionalTokenIndex { | |
| 3129 | _ = p.eatToken(.pipe) orelse return .none; | |
| 3341 | 3130 | _ = p.eatToken(.asterisk); |
| 3342 | 3131 | const identifier = try p.expectToken(.identifier); |
| 3343 | 3132 | if (p.eatToken(.comma) != null) { |
| 3344 | 3133 | _ = try p.expectToken(.identifier); |
| 3345 | 3134 | } |
| 3346 | 3135 | _ = try p.expectToken(.pipe); |
| 3347 | return identifier; | |
| 3136 | return .fromToken(identifier); | |
| 3348 | 3137 | } |
| 3349 | 3138 | |
| 3350 | 3139 | /// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrIndexPayload? AssignExpr |
| ... | ... | @@ -3352,7 +3141,7 @@ fn parsePtrIndexPayload(p: *Parse) !TokenIndex { |
| 3352 | 3141 | /// SwitchCase |
| 3353 | 3142 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 3354 | 3143 | /// / KEYWORD_else |
| 3355 | fn parseSwitchProng(p: *Parse) !Node.Index { | |
| 3144 | fn parseSwitchProng(p: *Parse) !?Node.Index { | |
| 3356 | 3145 | const scratch_top = p.scratch.items.len; |
| 3357 | 3146 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3358 | 3147 | |
| ... | ... | @@ -3360,97 +3149,92 @@ fn parseSwitchProng(p: *Parse) !Node.Index { |
| 3360 | 3149 | |
| 3361 | 3150 | if (p.eatToken(.keyword_else) == null) { |
| 3362 | 3151 | while (true) { |
| 3363 | const item = try p.parseSwitchItem(); | |
| 3364 | if (item == 0) break; | |
| 3152 | const item = try p.parseSwitchItem() orelse break; | |
| 3365 | 3153 | try p.scratch.append(p.gpa, item); |
| 3366 | 3154 | if (p.eatToken(.comma) == null) break; |
| 3367 | 3155 | } |
| 3368 | 3156 | if (scratch_top == p.scratch.items.len) { |
| 3369 | 3157 | if (is_inline) p.tok_i -= 1; |
| 3370 | return null_node; | |
| 3158 | return null; | |
| 3371 | 3159 | } |
| 3372 | 3160 | } |
| 3373 | 3161 | const arrow_token = try p.expectToken(.equal_angle_bracket_right); |
| 3374 | 3162 | _ = try p.parsePtrIndexPayload(); |
| 3375 | 3163 | |
| 3376 | 3164 | const items = p.scratch.items[scratch_top..]; |
| 3377 | switch (items.len) { | |
| 3378 | 0 => return p.addNode(.{ | |
| 3165 | if (items.len <= 1) { | |
| 3166 | return try p.addNode(.{ | |
| 3379 | 3167 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, |
| 3380 | 3168 | .main_token = arrow_token, |
| 3381 | .data = .{ | |
| 3382 | .lhs = 0, | |
| 3383 | .rhs = try p.expectSingleAssignExpr(), | |
| 3384 | }, | |
| 3385 | }), | |
| 3386 | 1 => return p.addNode(.{ | |
| 3387 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, | |
| 3388 | .main_token = arrow_token, | |
| 3389 | .data = .{ | |
| 3390 | .lhs = items[0], | |
| 3391 | .rhs = try p.expectSingleAssignExpr(), | |
| 3392 | }, | |
| 3393 | }), | |
| 3394 | else => return p.addNode(.{ | |
| 3169 | .data = .{ .opt_node_and_node = .{ | |
| 3170 | if (items.len >= 1) items[0].toOptional() else .none, | |
| 3171 | try p.expectSingleAssignExpr(), | |
| 3172 | } }, | |
| 3173 | }); | |
| 3174 | } else { | |
| 3175 | return try p.addNode(.{ | |
| 3395 | 3176 | .tag = if (is_inline) .switch_case_inline else .switch_case, |
| 3396 | 3177 | .main_token = arrow_token, |
| 3397 | .data = .{ | |
| 3398 | .lhs = try p.addExtra(try p.listToSpan(items)), | |
| 3399 | .rhs = try p.expectSingleAssignExpr(), | |
| 3400 | }, | |
| 3401 | }), | |
| 3178 | .data = .{ .extra_and_node = .{ | |
| 3179 | try p.addExtra(try p.listToSpan(items)), | |
| 3180 | try p.expectSingleAssignExpr(), | |
| 3181 | } }, | |
| 3182 | }); | |
| 3402 | 3183 | } |
| 3403 | 3184 | } |
| 3404 | 3185 | |
| 3405 | 3186 | /// SwitchItem <- Expr (DOT3 Expr)? |
| 3406 | fn parseSwitchItem(p: *Parse) !Node.Index { | |
| 3407 | const expr = try p.parseExpr(); | |
| 3408 | if (expr == 0) return null_node; | |
| 3187 | fn parseSwitchItem(p: *Parse) !?Node.Index { | |
| 3188 | const expr = try p.parseExpr() orelse return null; | |
| 3409 | 3189 | |
| 3410 | 3190 | if (p.eatToken(.ellipsis3)) |token| { |
| 3411 | return p.addNode(.{ | |
| 3191 | return try p.addNode(.{ | |
| 3412 | 3192 | .tag = .switch_range, |
| 3413 | 3193 | .main_token = token, |
| 3414 | .data = .{ | |
| 3415 | .lhs = expr, | |
| 3416 | .rhs = try p.expectExpr(), | |
| 3417 | }, | |
| 3194 | .data = .{ .node_and_node = .{ | |
| 3195 | expr, | |
| 3196 | try p.expectExpr(), | |
| 3197 | } }, | |
| 3418 | 3198 | }); |
| 3419 | 3199 | } |
| 3420 | 3200 | return expr; |
| 3421 | 3201 | } |
| 3422 | 3202 | |
| 3203 | /// The following invariant will hold: | |
| 3204 | /// - `(bit_range_start == .none) == (bit_range_end == .none)` | |
| 3205 | /// - `bit_range_start != .none` implies `align_node != .none` | |
| 3206 | /// - `bit_range_end != .none` implies `align_node != .none` | |
| 3423 | 3207 | 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, | |
| 3208 | align_node: Node.OptionalIndex, | |
| 3209 | addrspace_node: Node.OptionalIndex, | |
| 3210 | bit_range_start: Node.OptionalIndex, | |
| 3211 | bit_range_end: Node.OptionalIndex, | |
| 3428 | 3212 | }; |
| 3429 | 3213 | |
| 3430 | 3214 | fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3431 | 3215 | var result: PtrModifiers = .{ |
| 3432 | .align_node = 0, | |
| 3433 | .addrspace_node = 0, | |
| 3434 | .bit_range_start = 0, | |
| 3435 | .bit_range_end = 0, | |
| 3216 | .align_node = .none, | |
| 3217 | .addrspace_node = .none, | |
| 3218 | .bit_range_start = .none, | |
| 3219 | .bit_range_end = .none, | |
| 3436 | 3220 | }; |
| 3437 | 3221 | var saw_const = false; |
| 3438 | 3222 | var saw_volatile = false; |
| 3439 | 3223 | var saw_allowzero = false; |
| 3440 | 3224 | while (true) { |
| 3441 | switch (p.token_tags[p.tok_i]) { | |
| 3225 | switch (p.tokenTag(p.tok_i)) { | |
| 3442 | 3226 | .keyword_align => { |
| 3443 | if (result.align_node != 0) { | |
| 3227 | if (result.align_node != .none) { | |
| 3444 | 3228 | try p.warn(.extra_align_qualifier); |
| 3445 | 3229 | } |
| 3446 | 3230 | p.tok_i += 1; |
| 3447 | 3231 | _ = try p.expectToken(.l_paren); |
| 3448 | result.align_node = try p.expectExpr(); | |
| 3232 | result.align_node = (try p.expectExpr()).toOptional(); | |
| 3449 | 3233 | |
| 3450 | 3234 | if (p.eatToken(.colon)) |_| { |
| 3451 | result.bit_range_start = try p.expectExpr(); | |
| 3235 | result.bit_range_start = (try p.expectExpr()).toOptional(); | |
| 3452 | 3236 | _ = try p.expectToken(.colon); |
| 3453 | result.bit_range_end = try p.expectExpr(); | |
| 3237 | result.bit_range_end = (try p.expectExpr()).toOptional(); | |
| 3454 | 3238 | } |
| 3455 | 3239 | |
| 3456 | 3240 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3477,10 +3261,10 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3477 | 3261 | saw_allowzero = true; |
| 3478 | 3262 | }, |
| 3479 | 3263 | .keyword_addrspace => { |
| 3480 | if (result.addrspace_node != 0) { | |
| 3264 | if (result.addrspace_node != .none) { | |
| 3481 | 3265 | try p.warn(.extra_addrspace_qualifier); |
| 3482 | 3266 | } |
| 3483 | result.addrspace_node = try p.parseAddrSpace(); | |
| 3267 | result.addrspace_node = .fromOptional(try p.parseAddrSpace()); | |
| 3484 | 3268 | }, |
| 3485 | 3269 | else => return result, |
| 3486 | 3270 | } |
| ... | ... | @@ -3492,110 +3276,102 @@ fn parsePtrModifiers(p: *Parse) !PtrModifiers { |
| 3492 | 3276 | /// / DOT IDENTIFIER |
| 3493 | 3277 | /// / DOTASTERISK |
| 3494 | 3278 | /// / DOTQUESTIONMARK |
| 3495 | fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index { | |
| 3496 | switch (p.token_tags[p.tok_i]) { | |
| 3279 | fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index { | |
| 3280 | switch (p.tokenTag(p.tok_i)) { | |
| 3497 | 3281 | .l_bracket => { |
| 3498 | 3282 | const lbracket = p.nextToken(); |
| 3499 | 3283 | const index_expr = try p.expectExpr(); |
| 3500 | 3284 | |
| 3501 | 3285 | if (p.eatToken(.ellipsis2)) |_| { |
| 3502 | const end_expr = try p.parseExpr(); | |
| 3286 | const opt_end_expr = try p.parseExpr(); | |
| 3503 | 3287 | if (p.eatToken(.colon)) |_| { |
| 3504 | 3288 | const sentinel = try p.expectExpr(); |
| 3505 | 3289 | _ = try p.expectToken(.r_bracket); |
| 3506 | return p.addNode(.{ | |
| 3290 | return try p.addNode(.{ | |
| 3507 | 3291 | .tag = .slice_sentinel, |
| 3508 | 3292 | .main_token = lbracket, |
| 3509 | .data = .{ | |
| 3510 | .lhs = lhs, | |
| 3511 | .rhs = try p.addExtra(Node.SliceSentinel{ | |
| 3293 | .data = .{ .node_and_extra = .{ | |
| 3294 | lhs, try p.addExtra(Node.SliceSentinel{ | |
| 3512 | 3295 | .start = index_expr, |
| 3513 | .end = end_expr, | |
| 3296 | .end = .fromOptional(opt_end_expr), | |
| 3514 | 3297 | .sentinel = sentinel, |
| 3515 | 3298 | }), |
| 3516 | }, | |
| 3299 | } }, | |
| 3517 | 3300 | }); |
| 3518 | 3301 | } |
| 3519 | 3302 | _ = try p.expectToken(.r_bracket); |
| 3520 | if (end_expr == 0) { | |
| 3521 | return p.addNode(.{ | |
| 3303 | const end_expr = opt_end_expr orelse { | |
| 3304 | return try p.addNode(.{ | |
| 3522 | 3305 | .tag = .slice_open, |
| 3523 | 3306 | .main_token = lbracket, |
| 3524 | .data = .{ | |
| 3525 | .lhs = lhs, | |
| 3526 | .rhs = index_expr, | |
| 3527 | }, | |
| 3307 | .data = .{ .node_and_node = .{ | |
| 3308 | lhs, | |
| 3309 | index_expr, | |
| 3310 | } }, | |
| 3528 | 3311 | }); |
| 3529 | } | |
| 3530 | return p.addNode(.{ | |
| 3312 | }; | |
| 3313 | return try p.addNode(.{ | |
| 3531 | 3314 | .tag = .slice, |
| 3532 | 3315 | .main_token = lbracket, |
| 3533 | .data = .{ | |
| 3534 | .lhs = lhs, | |
| 3535 | .rhs = try p.addExtra(Node.Slice{ | |
| 3316 | .data = .{ .node_and_extra = .{ | |
| 3317 | lhs, try p.addExtra(Node.Slice{ | |
| 3536 | 3318 | .start = index_expr, |
| 3537 | 3319 | .end = end_expr, |
| 3538 | 3320 | }), |
| 3539 | }, | |
| 3321 | } }, | |
| 3540 | 3322 | }); |
| 3541 | 3323 | } |
| 3542 | 3324 | _ = try p.expectToken(.r_bracket); |
| 3543 | return p.addNode(.{ | |
| 3325 | return try p.addNode(.{ | |
| 3544 | 3326 | .tag = .array_access, |
| 3545 | 3327 | .main_token = lbracket, |
| 3546 | .data = .{ | |
| 3547 | .lhs = lhs, | |
| 3548 | .rhs = index_expr, | |
| 3549 | }, | |
| 3328 | .data = .{ .node_and_node = .{ | |
| 3329 | lhs, | |
| 3330 | index_expr, | |
| 3331 | } }, | |
| 3550 | 3332 | }); |
| 3551 | 3333 | }, |
| 3552 | .period_asterisk => return p.addNode(.{ | |
| 3334 | .period_asterisk => return try p.addNode(.{ | |
| 3553 | 3335 | .tag = .deref, |
| 3554 | 3336 | .main_token = p.nextToken(), |
| 3555 | .data = .{ | |
| 3556 | .lhs = lhs, | |
| 3557 | .rhs = undefined, | |
| 3558 | }, | |
| 3337 | .data = .{ .node = lhs }, | |
| 3559 | 3338 | }), |
| 3560 | 3339 | .invalid_periodasterisks => { |
| 3561 | 3340 | try p.warn(.asterisk_after_ptr_deref); |
| 3562 | return p.addNode(.{ | |
| 3341 | return try p.addNode(.{ | |
| 3563 | 3342 | .tag = .deref, |
| 3564 | 3343 | .main_token = p.nextToken(), |
| 3565 | .data = .{ | |
| 3566 | .lhs = lhs, | |
| 3567 | .rhs = undefined, | |
| 3568 | }, | |
| 3344 | .data = .{ .node = lhs }, | |
| 3569 | 3345 | }); |
| 3570 | 3346 | }, |
| 3571 | .period => switch (p.token_tags[p.tok_i + 1]) { | |
| 3572 | .identifier => return p.addNode(.{ | |
| 3347 | .period => switch (p.tokenTag(p.tok_i + 1)) { | |
| 3348 | .identifier => return try p.addNode(.{ | |
| 3573 | 3349 | .tag = .field_access, |
| 3574 | 3350 | .main_token = p.nextToken(), |
| 3575 | .data = .{ | |
| 3576 | .lhs = lhs, | |
| 3577 | .rhs = p.nextToken(), | |
| 3578 | }, | |
| 3351 | .data = .{ .node_and_token = .{ | |
| 3352 | lhs, | |
| 3353 | p.nextToken(), | |
| 3354 | } }, | |
| 3579 | 3355 | }), |
| 3580 | .question_mark => return p.addNode(.{ | |
| 3356 | .question_mark => return try p.addNode(.{ | |
| 3581 | 3357 | .tag = .unwrap_optional, |
| 3582 | 3358 | .main_token = p.nextToken(), |
| 3583 | .data = .{ | |
| 3584 | .lhs = lhs, | |
| 3585 | .rhs = p.nextToken(), | |
| 3586 | }, | |
| 3359 | .data = .{ .node_and_token = .{ | |
| 3360 | lhs, | |
| 3361 | p.nextToken(), | |
| 3362 | } }, | |
| 3587 | 3363 | }), |
| 3588 | 3364 | .l_brace => { |
| 3589 | 3365 | // this a misplaced `.{`, handle the error somewhere else |
| 3590 | return null_node; | |
| 3366 | return null; | |
| 3591 | 3367 | }, |
| 3592 | 3368 | else => { |
| 3593 | 3369 | p.tok_i += 1; |
| 3594 | 3370 | try p.warn(.expected_suffix_op); |
| 3595 | return null_node; | |
| 3371 | return null; | |
| 3596 | 3372 | }, |
| 3597 | 3373 | }, |
| 3598 | else => return null_node, | |
| 3374 | else => return null, | |
| 3599 | 3375 | } |
| 3600 | 3376 | } |
| 3601 | 3377 | |
| ... | ... | @@ -3608,17 +3384,17 @@ fn parseSuffixOp(p: *Parse, lhs: Node.Index) !Node.Index { |
| 3608 | 3384 | /// / KEYWORD_opaque |
| 3609 | 3385 | /// / KEYWORD_enum (LPAREN Expr RPAREN)? |
| 3610 | 3386 | /// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)? |
| 3611 | fn parseContainerDeclAuto(p: *Parse) !Node.Index { | |
| 3387 | fn parseContainerDeclAuto(p: *Parse) !?Node.Index { | |
| 3612 | 3388 | const main_token = p.nextToken(); |
| 3613 | const arg_expr = switch (p.token_tags[main_token]) { | |
| 3614 | .keyword_opaque => null_node, | |
| 3389 | const arg_expr = switch (p.tokenTag(main_token)) { | |
| 3390 | .keyword_opaque => null, | |
| 3615 | 3391 | .keyword_struct, .keyword_enum => blk: { |
| 3616 | 3392 | if (p.eatToken(.l_paren)) |_| { |
| 3617 | 3393 | const expr = try p.expectExpr(); |
| 3618 | 3394 | _ = try p.expectToken(.r_paren); |
| 3619 | 3395 | break :blk expr; |
| 3620 | 3396 | } else { |
| 3621 | break :blk null_node; | |
| 3397 | break :blk null; | |
| 3622 | 3398 | } |
| 3623 | 3399 | }, |
| 3624 | 3400 | .keyword_union => blk: { |
| ... | ... | @@ -3633,16 +3409,16 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3633 | 3409 | const members = try p.parseContainerMembers(); |
| 3634 | 3410 | const members_span = try members.toSpan(p); |
| 3635 | 3411 | _ = try p.expectToken(.r_brace); |
| 3636 | return p.addNode(.{ | |
| 3412 | return try p.addNode(.{ | |
| 3637 | 3413 | .tag = switch (members.trailing) { |
| 3638 | 3414 | true => .tagged_union_enum_tag_trailing, |
| 3639 | 3415 | false => .tagged_union_enum_tag, |
| 3640 | 3416 | }, |
| 3641 | 3417 | .main_token = main_token, |
| 3642 | .data = .{ | |
| 3643 | .lhs = enum_tag_expr, | |
| 3644 | .rhs = try p.addExtra(members_span), | |
| 3645 | }, | |
| 3418 | .data = .{ .node_and_extra = .{ | |
| 3419 | enum_tag_expr, | |
| 3420 | try p.addExtra(members_span), | |
| 3421 | } }, | |
| 3646 | 3422 | }); |
| 3647 | 3423 | } else { |
| 3648 | 3424 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3651,29 +3427,23 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3651 | 3427 | const members = try p.parseContainerMembers(); |
| 3652 | 3428 | _ = try p.expectToken(.r_brace); |
| 3653 | 3429 | if (members.len <= 2) { |
| 3654 | return p.addNode(.{ | |
| 3430 | return try p.addNode(.{ | |
| 3655 | 3431 | .tag = switch (members.trailing) { |
| 3656 | 3432 | true => .tagged_union_two_trailing, |
| 3657 | 3433 | false => .tagged_union_two, |
| 3658 | 3434 | }, |
| 3659 | 3435 | .main_token = main_token, |
| 3660 | .data = .{ | |
| 3661 | .lhs = members.lhs, | |
| 3662 | .rhs = members.rhs, | |
| 3663 | }, | |
| 3436 | .data = members.data, | |
| 3664 | 3437 | }); |
| 3665 | 3438 | } else { |
| 3666 | 3439 | const span = try members.toSpan(p); |
| 3667 | return p.addNode(.{ | |
| 3440 | return try p.addNode(.{ | |
| 3668 | 3441 | .tag = switch (members.trailing) { |
| 3669 | 3442 | true => .tagged_union_trailing, |
| 3670 | 3443 | false => .tagged_union, |
| 3671 | 3444 | }, |
| 3672 | 3445 | .main_token = main_token, |
| 3673 | .data = .{ | |
| 3674 | .lhs = span.start, | |
| 3675 | .rhs = span.end, | |
| 3676 | }, | |
| 3446 | .data = .{ .extra_range = span }, | |
| 3677 | 3447 | }); |
| 3678 | 3448 | } |
| 3679 | 3449 | } |
| ... | ... | @@ -3683,7 +3453,7 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3683 | 3453 | break :blk expr; |
| 3684 | 3454 | } |
| 3685 | 3455 | } else { |
| 3686 | break :blk null_node; | |
| 3456 | break :blk null; | |
| 3687 | 3457 | } |
| 3688 | 3458 | }, |
| 3689 | 3459 | else => { |
| ... | ... | @@ -3694,48 +3464,42 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3694 | 3464 | _ = try p.expectToken(.l_brace); |
| 3695 | 3465 | const members = try p.parseContainerMembers(); |
| 3696 | 3466 | _ = try p.expectToken(.r_brace); |
| 3697 | if (arg_expr == 0) { | |
| 3467 | if (arg_expr == null) { | |
| 3698 | 3468 | if (members.len <= 2) { |
| 3699 | return p.addNode(.{ | |
| 3469 | return try p.addNode(.{ | |
| 3700 | 3470 | .tag = switch (members.trailing) { |
| 3701 | 3471 | true => .container_decl_two_trailing, |
| 3702 | 3472 | false => .container_decl_two, |
| 3703 | 3473 | }, |
| 3704 | 3474 | .main_token = main_token, |
| 3705 | .data = .{ | |
| 3706 | .lhs = members.lhs, | |
| 3707 | .rhs = members.rhs, | |
| 3708 | }, | |
| 3475 | .data = members.data, | |
| 3709 | 3476 | }); |
| 3710 | 3477 | } else { |
| 3711 | 3478 | const span = try members.toSpan(p); |
| 3712 | return p.addNode(.{ | |
| 3479 | return try p.addNode(.{ | |
| 3713 | 3480 | .tag = switch (members.trailing) { |
| 3714 | 3481 | true => .container_decl_trailing, |
| 3715 | 3482 | false => .container_decl, |
| 3716 | 3483 | }, |
| 3717 | 3484 | .main_token = main_token, |
| 3718 | .data = .{ | |
| 3719 | .lhs = span.start, | |
| 3720 | .rhs = span.end, | |
| 3721 | }, | |
| 3485 | .data = .{ .extra_range = span }, | |
| 3722 | 3486 | }); |
| 3723 | 3487 | } |
| 3724 | 3488 | } else { |
| 3725 | 3489 | const span = try members.toSpan(p); |
| 3726 | return p.addNode(.{ | |
| 3490 | return try p.addNode(.{ | |
| 3727 | 3491 | .tag = switch (members.trailing) { |
| 3728 | 3492 | true => .container_decl_arg_trailing, |
| 3729 | 3493 | false => .container_decl_arg, |
| 3730 | 3494 | }, |
| 3731 | 3495 | .main_token = main_token, |
| 3732 | .data = .{ | |
| 3733 | .lhs = arg_expr, | |
| 3734 | .rhs = try p.addExtra(Node.SubRange{ | |
| 3496 | .data = .{ .node_and_extra = .{ | |
| 3497 | arg_expr.?, | |
| 3498 | try p.addExtra(Node.SubRange{ | |
| 3735 | 3499 | .start = span.start, |
| 3736 | 3500 | .end = span.end, |
| 3737 | 3501 | }), |
| 3738 | }, | |
| 3502 | } }, | |
| 3739 | 3503 | }); |
| 3740 | 3504 | } |
| 3741 | 3505 | } |
| ... | ... | @@ -3744,24 +3508,24 @@ fn parseContainerDeclAuto(p: *Parse) !Node.Index { |
| 3744 | 3508 | /// C's 'struct Foo {};' to Zig's 'const Foo = struct {};'. |
| 3745 | 3509 | fn parseCStyleContainer(p: *Parse) Error!bool { |
| 3746 | 3510 | const main_token = p.tok_i; |
| 3747 | switch (p.token_tags[p.tok_i]) { | |
| 3511 | switch (p.tokenTag(p.tok_i)) { | |
| 3748 | 3512 | .keyword_enum, .keyword_union, .keyword_struct => {}, |
| 3749 | 3513 | else => return false, |
| 3750 | 3514 | } |
| 3751 | 3515 | const identifier = p.tok_i + 1; |
| 3752 | if (p.token_tags[identifier] != .identifier) return false; | |
| 3516 | if (p.tokenTag(identifier) != .identifier) return false; | |
| 3753 | 3517 | p.tok_i += 2; |
| 3754 | 3518 | |
| 3755 | 3519 | try p.warnMsg(.{ |
| 3756 | 3520 | .tag = .c_style_container, |
| 3757 | 3521 | .token = identifier, |
| 3758 | .extra = .{ .expected_tag = p.token_tags[main_token] }, | |
| 3522 | .extra = .{ .expected_tag = p.tokenTag(main_token) }, | |
| 3759 | 3523 | }); |
| 3760 | 3524 | try p.warnMsg(.{ |
| 3761 | 3525 | .tag = .zig_style_container, |
| 3762 | 3526 | .is_note = true, |
| 3763 | 3527 | .token = identifier, |
| 3764 | .extra = .{ .expected_tag = p.token_tags[main_token] }, | |
| 3528 | .extra = .{ .expected_tag = p.tokenTag(main_token) }, | |
| 3765 | 3529 | }); |
| 3766 | 3530 | |
| 3767 | 3531 | _ = try p.expectToken(.l_brace); |
| ... | ... | @@ -3774,8 +3538,8 @@ fn parseCStyleContainer(p: *Parse) Error!bool { |
| 3774 | 3538 | /// Holds temporary data until we are ready to construct the full ContainerDecl AST node. |
| 3775 | 3539 | /// |
| 3776 | 3540 | /// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN |
| 3777 | fn parseByteAlign(p: *Parse) !Node.Index { | |
| 3778 | _ = p.eatToken(.keyword_align) orelse return null_node; | |
| 3541 | fn parseByteAlign(p: *Parse) !?Node.Index { | |
| 3542 | _ = p.eatToken(.keyword_align) orelse return null; | |
| 3779 | 3543 | _ = try p.expectToken(.l_paren); |
| 3780 | 3544 | const expr = try p.expectExpr(); |
| 3781 | 3545 | _ = try p.expectToken(.r_paren); |
| ... | ... | @@ -3788,12 +3552,11 @@ fn parseSwitchProngList(p: *Parse) !Node.SubRange { |
| 3788 | 3552 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3789 | 3553 | |
| 3790 | 3554 | while (true) { |
| 3791 | const item = try parseSwitchProng(p); | |
| 3792 | if (item == 0) break; | |
| 3555 | const item = try parseSwitchProng(p) orelse break; | |
| 3793 | 3556 | |
| 3794 | 3557 | try p.scratch.append(p.gpa, item); |
| 3795 | 3558 | |
| 3796 | switch (p.token_tags[p.tok_i]) { | |
| 3559 | switch (p.tokenTag(p.tok_i)) { | |
| 3797 | 3560 | .comma => p.tok_i += 1, |
| 3798 | 3561 | // All possible delimiters. |
| 3799 | 3562 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| ... | ... | @@ -3813,13 +3576,13 @@ fn parseParamDeclList(p: *Parse) !SmallSpan { |
| 3813 | 3576 | while (true) { |
| 3814 | 3577 | if (p.eatToken(.r_paren)) |_| break; |
| 3815 | 3578 | if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i }; |
| 3816 | const param = try p.expectParamDecl(); | |
| 3817 | if (param != 0) { | |
| 3579 | const opt_param = try p.expectParamDecl(); | |
| 3580 | if (opt_param) |param| { | |
| 3818 | 3581 | try p.scratch.append(p.gpa, param); |
| 3819 | } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) { | |
| 3582 | } else if (p.tokenTag(p.tok_i - 1) == .ellipsis3) { | |
| 3820 | 3583 | if (varargs == .none) varargs = .seen; |
| 3821 | 3584 | } |
| 3822 | switch (p.token_tags[p.tok_i]) { | |
| 3585 | switch (p.tokenTag(p.tok_i)) { | |
| 3823 | 3586 | .comma => p.tok_i += 1, |
| 3824 | 3587 | .r_paren => { |
| 3825 | 3588 | p.tok_i += 1; |
| ... | ... | @@ -3835,9 +3598,9 @@ fn parseParamDeclList(p: *Parse) !SmallSpan { |
| 3835 | 3598 | } |
| 3836 | 3599 | const params = p.scratch.items[scratch_top..]; |
| 3837 | 3600 | return switch (params.len) { |
| 3838 | 0 => SmallSpan{ .zero_or_one = 0 }, | |
| 3839 | 1 => SmallSpan{ .zero_or_one = params[0] }, | |
| 3840 | else => SmallSpan{ .multi = try p.listToSpan(params) }, | |
| 3601 | 0 => .{ .zero_or_one = .none }, | |
| 3602 | 1 => .{ .zero_or_one = params[0].toOptional() }, | |
| 3603 | else => .{ .multi = try p.listToSpan(params) }, | |
| 3841 | 3604 | }; |
| 3842 | 3605 | } |
| 3843 | 3606 | |
| ... | ... | @@ -3852,10 +3615,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3852 | 3615 | return p.addNode(.{ |
| 3853 | 3616 | .tag = .identifier, |
| 3854 | 3617 | .main_token = builtin_token, |
| 3855 | .data = .{ | |
| 3856 | .lhs = undefined, | |
| 3857 | .rhs = undefined, | |
| 3858 | }, | |
| 3618 | .data = undefined, | |
| 3859 | 3619 | }); |
| 3860 | 3620 | }; |
| 3861 | 3621 | const scratch_top = p.scratch.items.len; |
| ... | ... | @@ -3864,7 +3624,7 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3864 | 3624 | if (p.eatToken(.r_paren)) |_| break; |
| 3865 | 3625 | const param = try p.expectExpr(); |
| 3866 | 3626 | try p.scratch.append(p.gpa, param); |
| 3867 | switch (p.token_tags[p.tok_i]) { | |
| 3627 | switch (p.tokenTag(p.tok_i)) { | |
| 3868 | 3628 | .comma => p.tok_i += 1, |
| 3869 | 3629 | .r_paren => { |
| 3870 | 3630 | p.tok_i += 1; |
| ... | ... | @@ -3874,88 +3634,66 @@ fn parseBuiltinCall(p: *Parse) !Node.Index { |
| 3874 | 3634 | else => try p.warn(.expected_comma_after_arg), |
| 3875 | 3635 | } |
| 3876 | 3636 | } |
| 3877 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | |
| 3637 | const comma = (p.tokenTag(p.tok_i - 2)) == .comma; | |
| 3878 | 3638 | const params = p.scratch.items[scratch_top..]; |
| 3879 | switch (params.len) { | |
| 3880 | 0 => return p.addNode(.{ | |
| 3881 | .tag = .builtin_call_two, | |
| 3882 | .main_token = builtin_token, | |
| 3883 | .data = .{ | |
| 3884 | .lhs = 0, | |
| 3885 | .rhs = 0, | |
| 3886 | }, | |
| 3887 | }), | |
| 3888 | 1 => return p.addNode(.{ | |
| 3639 | if (params.len <= 2) { | |
| 3640 | return p.addNode(.{ | |
| 3889 | 3641 | .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, |
| 3890 | 3642 | .main_token = builtin_token, |
| 3891 | .data = .{ | |
| 3892 | .lhs = params[0], | |
| 3893 | .rhs = 0, | |
| 3894 | }, | |
| 3895 | }), | |
| 3896 | 2 => return p.addNode(.{ | |
| 3897 | .tag = if (comma) .builtin_call_two_comma else .builtin_call_two, | |
| 3643 | .data = .{ .opt_node_and_opt_node = .{ | |
| 3644 | if (params.len >= 1) .fromOptional(params[0]) else .none, | |
| 3645 | if (params.len >= 2) .fromOptional(params[1]) else .none, | |
| 3646 | } }, | |
| 3647 | }); | |
| 3648 | } else { | |
| 3649 | const span = try p.listToSpan(params); | |
| 3650 | return p.addNode(.{ | |
| 3651 | .tag = if (comma) .builtin_call_comma else .builtin_call, | |
| 3898 | 3652 | .main_token = builtin_token, |
| 3899 | .data = .{ | |
| 3900 | .lhs = params[0], | |
| 3901 | .rhs = params[1], | |
| 3902 | }, | |
| 3903 | }), | |
| 3904 | else => { | |
| 3905 | const span = try p.listToSpan(params); | |
| 3906 | return p.addNode(.{ | |
| 3907 | .tag = if (comma) .builtin_call_comma else .builtin_call, | |
| 3908 | .main_token = builtin_token, | |
| 3909 | .data = .{ | |
| 3910 | .lhs = span.start, | |
| 3911 | .rhs = span.end, | |
| 3912 | }, | |
| 3913 | }); | |
| 3914 | }, | |
| 3653 | .data = .{ .extra_range = span }, | |
| 3654 | }); | |
| 3915 | 3655 | } |
| 3916 | 3656 | } |
| 3917 | 3657 | |
| 3918 | 3658 | /// 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; | |
| 3659 | fn parseIf(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index { | |
| 3660 | const if_token = p.eatToken(.keyword_if) orelse return null; | |
| 3921 | 3661 | _ = try p.expectToken(.l_paren); |
| 3922 | 3662 | const condition = try p.expectExpr(); |
| 3923 | 3663 | _ = try p.expectToken(.r_paren); |
| 3924 | 3664 | _ = try p.parsePtrPayload(); |
| 3925 | 3665 | |
| 3926 | 3666 | const then_expr = try bodyParseFn(p); |
| 3927 | assert(then_expr != 0); | |
| 3928 | 3667 | |
| 3929 | _ = p.eatToken(.keyword_else) orelse return p.addNode(.{ | |
| 3668 | _ = p.eatToken(.keyword_else) orelse return try p.addNode(.{ | |
| 3930 | 3669 | .tag = .if_simple, |
| 3931 | 3670 | .main_token = if_token, |
| 3932 | .data = .{ | |
| 3933 | .lhs = condition, | |
| 3934 | .rhs = then_expr, | |
| 3935 | }, | |
| 3671 | .data = .{ .node_and_node = .{ | |
| 3672 | condition, | |
| 3673 | then_expr, | |
| 3674 | } }, | |
| 3936 | 3675 | }); |
| 3937 | 3676 | _ = try p.parsePayload(); |
| 3938 | 3677 | const else_expr = try bodyParseFn(p); |
| 3939 | assert(else_expr != 0); | |
| 3940 | 3678 | |
| 3941 | return p.addNode(.{ | |
| 3679 | return try p.addNode(.{ | |
| 3942 | 3680 | .tag = .@"if", |
| 3943 | 3681 | .main_token = if_token, |
| 3944 | .data = .{ | |
| 3945 | .lhs = condition, | |
| 3946 | .rhs = try p.addExtra(Node.If{ | |
| 3682 | .data = .{ .node_and_extra = .{ | |
| 3683 | condition, | |
| 3684 | try p.addExtra(Node.If{ | |
| 3947 | 3685 | .then_expr = then_expr, |
| 3948 | 3686 | .else_expr = else_expr, |
| 3949 | 3687 | }), |
| 3950 | }, | |
| 3688 | } }, | |
| 3951 | 3689 | }); |
| 3952 | 3690 | } |
| 3953 | 3691 | |
| 3954 | 3692 | /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)? |
| 3955 | 3693 | /// |
| 3956 | 3694 | /// 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; | |
| 3695 | fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !?Node.Index { | |
| 3696 | const for_token = p.eatToken(.keyword_for) orelse return null; | |
| 3959 | 3697 | |
| 3960 | 3698 | const scratch_top = p.scratch.items.len; |
| 3961 | 3699 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| ... | ... | @@ -3969,27 +3707,24 @@ fn parseFor(p: *Parse, comptime bodyParseFn: fn (p: *Parse) Error!Node.Index) !N |
| 3969 | 3707 | try p.scratch.append(p.gpa, else_expr); |
| 3970 | 3708 | has_else = true; |
| 3971 | 3709 | } else if (inputs == 1) { |
| 3972 | return p.addNode(.{ | |
| 3710 | return try p.addNode(.{ | |
| 3973 | 3711 | .tag = .for_simple, |
| 3974 | 3712 | .main_token = for_token, |
| 3975 | .data = .{ | |
| 3976 | .lhs = p.scratch.items[scratch_top], | |
| 3977 | .rhs = then_expr, | |
| 3978 | }, | |
| 3713 | .data = .{ .node_and_node = .{ | |
| 3714 | p.scratch.items[scratch_top], | |
| 3715 | then_expr, | |
| 3716 | } }, | |
| 3979 | 3717 | }); |
| 3980 | 3718 | } else { |
| 3981 | 3719 | try p.scratch.append(p.gpa, then_expr); |
| 3982 | 3720 | } |
| 3983 | return p.addNode(.{ | |
| 3721 | return try p.addNode(.{ | |
| 3984 | 3722 | .tag = .@"for", |
| 3985 | 3723 | .main_token = for_token, |
| 3986 | .data = .{ | |
| 3987 | .lhs = (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 3988 | .rhs = @as(u32, @bitCast(Node.For{ | |
| 3989 | .inputs = @as(u31, @intCast(inputs)), | |
| 3990 | .has_else = has_else, | |
| 3991 | })), | |
| 3992 | }, | |
| 3724 | .data = .{ .@"for" = .{ | |
| 3725 | (try p.listToSpan(p.scratch.items[scratch_top..])).start, | |
| 3726 | .{ .inputs = @intCast(inputs), .has_else = has_else }, | |
| 3727 | } }, | |
| 3993 | 3728 | }); |
| 3994 | 3729 | } |
| 3995 | 3730 | |
| ... | ... | @@ -4011,21 +3746,29 @@ fn eatDocComments(p: *Parse) Allocator.Error!?TokenIndex { |
| 4011 | 3746 | } |
| 4012 | 3747 | |
| 4013 | 3748 | 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; | |
| 3749 | return std.mem.indexOfScalar(u8, p.source[p.tokenStart(token1)..p.tokenStart(token2)], '\n') == null; | |
| 4015 | 3750 | } |
| 4016 | 3751 | |
| 4017 | 3752 | fn eatToken(p: *Parse, tag: Token.Tag) ?TokenIndex { |
| 4018 | return if (p.token_tags[p.tok_i] == tag) p.nextToken() else null; | |
| 3753 | return if (p.tokenTag(p.tok_i) == tag) p.nextToken() else null; | |
| 3754 | } | |
| 3755 | ||
| 3756 | fn eatTokens(p: *Parse, tags: []const Token.Tag) ?TokenIndex { | |
| 3757 | const available_tags = p.tokens.items(.tag)[p.tok_i..]; | |
| 3758 | if (!std.mem.startsWith(Token.Tag, available_tags, tags)) return null; | |
| 3759 | const result = p.tok_i; | |
| 3760 | p.tok_i += @intCast(tags.len); | |
| 3761 | return result; | |
| 4019 | 3762 | } |
| 4020 | 3763 | |
| 4021 | 3764 | fn assertToken(p: *Parse, tag: Token.Tag) TokenIndex { |
| 4022 | 3765 | const token = p.nextToken(); |
| 4023 | assert(p.token_tags[token] == tag); | |
| 3766 | assert(p.tokenTag(token) == tag); | |
| 4024 | 3767 | return token; |
| 4025 | 3768 | } |
| 4026 | 3769 | |
| 4027 | 3770 | fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex { |
| 4028 | if (p.token_tags[p.tok_i] != tag) { | |
| 3771 | if (p.tokenTag(p.tok_i) != tag) { | |
| 4029 | 3772 | return p.failMsg(.{ |
| 4030 | 3773 | .tag = .expected_token, |
| 4031 | 3774 | .token = p.tok_i, |
| ... | ... | @@ -4036,7 +3779,7 @@ fn expectToken(p: *Parse, tag: Token.Tag) Error!TokenIndex { |
| 4036 | 3779 | } |
| 4037 | 3780 | |
| 4038 | 3781 | fn expectSemicolon(p: *Parse, error_tag: AstError.Tag, recoverable: bool) Error!void { |
| 4039 | if (p.token_tags[p.tok_i] == .semicolon) { | |
| 3782 | if (p.tokenTag(p.tok_i) == .semicolon) { | |
| 4040 | 3783 | _ = p.nextToken(); |
| 4041 | 3784 | return; |
| 4042 | 3785 | } |
| ... | ... | @@ -4050,8 +3793,6 @@ fn nextToken(p: *Parse) TokenIndex { |
| 4050 | 3793 | return result; |
| 4051 | 3794 | } |
| 4052 | 3795 | |
| 4053 | const null_node: Node.Index = 0; | |
| 4054 | ||
| 4055 | 3796 | const Parse = @This(); |
| 4056 | 3797 | const std = @import("../std.zig"); |
| 4057 | 3798 | const assert = std.debug.assert; |
| ... | ... | @@ -4060,6 +3801,8 @@ const Ast = std.zig.Ast; |
| 4060 | 3801 | const Node = Ast.Node; |
| 4061 | 3802 | const AstError = Ast.Error; |
| 4062 | 3803 | const TokenIndex = Ast.TokenIndex; |
| 3804 | const OptionalTokenIndex = Ast.OptionalTokenIndex; | |
| 3805 | const ExtraIndex = Ast.ExtraIndex; | |
| 4063 | 3806 | const Token = std.zig.Token; |
| 4064 | 3807 | |
| 4065 | 3808 | 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+43-55| ... | ... | @@ -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,8 +248,8 @@ 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 | 255 | .array_access => try zg.addErrorNode(node, "array indexing is not allowed in ZON", .{}), |
| ... | ... | @@ -262,12 +259,9 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator |
| 262 | 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+459-487| ... | ... | @@ -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,23 +142,20 @@ fn renderMember( |
| 141 | 142 | ) Error!void { |
| 142 | 143 | const tree = r.tree; |
| 143 | 144 | const ais = r.ais; |
| 144 | const token_tags = tree.tokens.items(.tag); | |
| 145 | const main_tokens = tree.nodes.items(.main_token); | |
| 146 | const datas = tree.nodes.items(.data); | |
| 147 | 145 | if (r.fixups.omit_nodes.contains(decl)) return; |
| 148 | 146 | try renderDocComments(r, tree.firstToken(decl)); |
| 149 | switch (tree.nodes.items(.tag)[decl]) { | |
| 147 | switch (tree.nodeTag(decl)) { | |
| 150 | 148 | .fn_decl => { |
| 151 | 149 | // Some examples: |
| 152 | 150 | // pub extern "foo" fn ... |
| 153 | 151 | // export fn ... |
| 154 | const fn_proto = datas[decl].lhs; | |
| 155 | const fn_token = main_tokens[fn_proto]; | |
| 152 | const fn_proto, const body_node = tree.nodeData(decl).node_and_node; | |
| 153 | const fn_token = tree.nodeMainToken(fn_proto); | |
| 156 | 154 | // Go back to the first token we should render here. |
| 157 | 155 | var i = fn_token; |
| 158 | 156 | while (i > 0) { |
| 159 | 157 | i -= 1; |
| 160 | switch (token_tags[i]) { | |
| 158 | switch (tree.tokenTag(i)) { | |
| 161 | 159 | .keyword_extern, |
| 162 | 160 | .keyword_export, |
| 163 | 161 | .keyword_pub, |
| ... | ... | @@ -172,31 +170,34 @@ fn renderMember( |
| 172 | 170 | }, |
| 173 | 171 | } |
| 174 | 172 | } |
| 173 | ||
| 175 | 174 | while (i < fn_token) : (i += 1) { |
| 176 | 175 | try renderToken(r, i, .space); |
| 177 | 176 | } |
| 178 | switch (tree.nodes.items(.tag)[fn_proto]) { | |
| 177 | switch (tree.nodeTag(fn_proto)) { | |
| 179 | 178 | .fn_proto_one, .fn_proto => { |
| 180 | const callconv_expr = if (tree.nodes.items(.tag)[fn_proto] == .fn_proto_one) | |
| 181 | tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProtoOne).callconv_expr | |
| 179 | var buf: [1]Ast.Node.Index = undefined; | |
| 180 | const opt_callconv_expr = if (tree.nodeTag(fn_proto) == .fn_proto_one) | |
| 181 | tree.fnProtoOne(&buf, fn_proto).ast.callconv_expr | |
| 182 | 182 | else |
| 183 | tree.extraData(datas[fn_proto].lhs, Ast.Node.FnProto).callconv_expr; | |
| 183 | tree.fnProto(fn_proto).ast.callconv_expr; | |
| 184 | ||
| 184 | 185 | // Keep in sync with logic in `renderFnProto`. Search this file for the marker PROMOTE_CALLCONV_INLINE |
| 185 | if (callconv_expr != 0 and tree.nodes.items(.tag)[callconv_expr] == .enum_literal) { | |
| 186 | if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(main_tokens[callconv_expr]))) { | |
| 187 | try ais.writer().writeAll("inline "); | |
| 186 | if (opt_callconv_expr.unwrap()) |callconv_expr| { | |
| 187 | if (tree.nodeTag(callconv_expr) == .enum_literal) { | |
| 188 | if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) { | |
| 189 | try ais.writer().writeAll("inline "); | |
| 190 | } | |
| 188 | 191 | } |
| 189 | 192 | } |
| 190 | 193 | }, |
| 191 | 194 | .fn_proto_simple, .fn_proto_multi => {}, |
| 192 | 195 | else => unreachable, |
| 193 | 196 | } |
| 194 | assert(datas[decl].rhs != 0); | |
| 195 | 197 | try renderExpression(r, fn_proto, .space); |
| 196 | const body_node = datas[decl].rhs; | |
| 197 | 198 | if (r.fixups.gut_functions.contains(decl)) { |
| 198 | 199 | try ais.pushIndent(.normal); |
| 199 | const lbrace = tree.nodes.items(.main_token)[body_node]; | |
| 200 | const lbrace = tree.nodeMainToken(body_node); | |
| 200 | 201 | try renderToken(r, lbrace, .newline); |
| 201 | 202 | try discardAllParams(r, fn_proto); |
| 202 | 203 | try ais.writer().writeAll("@trap();"); |
| ... | ... | @@ -205,7 +206,7 @@ fn renderMember( |
| 205 | 206 | try renderToken(r, tree.lastToken(body_node), space); // rbrace |
| 206 | 207 | } else if (r.fixups.unused_var_decls.count() != 0) { |
| 207 | 208 | try ais.pushIndent(.normal); |
| 208 | const lbrace = tree.nodes.items(.main_token)[body_node]; | |
| 209 | const lbrace = tree.nodeMainToken(body_node); | |
| 209 | 210 | try renderToken(r, lbrace, .newline); |
| 210 | 211 | |
| 211 | 212 | var fn_proto_buf: [1]Ast.Node.Index = undefined; |
| ... | ... | @@ -213,7 +214,7 @@ fn renderMember( |
| 213 | 214 | var it = full_fn_proto.iterate(&tree); |
| 214 | 215 | while (it.next()) |param| { |
| 215 | 216 | const name_ident = param.name_token.?; |
| 216 | assert(token_tags[name_ident] == .identifier); | |
| 217 | assert(tree.tokenTag(name_ident) == .identifier); | |
| 217 | 218 | if (r.fixups.unused_var_decls.contains(name_ident)) { |
| 218 | 219 | const w = ais.writer(); |
| 219 | 220 | try w.writeAll("_ = "); |
| ... | ... | @@ -235,11 +236,11 @@ fn renderMember( |
| 235 | 236 | => { |
| 236 | 237 | // Extern function prototypes are parsed as these tags. |
| 237 | 238 | // Go back to the first token we should render here. |
| 238 | const fn_token = main_tokens[decl]; | |
| 239 | const fn_token = tree.nodeMainToken(decl); | |
| 239 | 240 | var i = fn_token; |
| 240 | 241 | while (i > 0) { |
| 241 | 242 | i -= 1; |
| 242 | switch (token_tags[i]) { | |
| 243 | switch (tree.tokenTag(i)) { | |
| 243 | 244 | .keyword_extern, |
| 244 | 245 | .keyword_export, |
| 245 | 246 | .keyword_pub, |
| ... | ... | @@ -262,9 +263,9 @@ fn renderMember( |
| 262 | 263 | }, |
| 263 | 264 | |
| 264 | 265 | .@"usingnamespace" => { |
| 265 | const main_token = main_tokens[decl]; | |
| 266 | const expr = datas[decl].lhs; | |
| 267 | if (main_token > 0 and token_tags[main_token - 1] == .keyword_pub) { | |
| 266 | const main_token = tree.nodeMainToken(decl); | |
| 267 | const expr = tree.nodeData(decl).node; | |
| 268 | if (tree.isTokenPrecededByTags(main_token, &.{.keyword_pub})) { | |
| 268 | 269 | try renderToken(r, main_token - 1, .space); // pub |
| 269 | 270 | } |
| 270 | 271 | try renderToken(r, main_token, .space); // usingnamespace |
| ... | ... | @@ -283,15 +284,17 @@ fn renderMember( |
| 283 | 284 | }, |
| 284 | 285 | |
| 285 | 286 | .test_decl => { |
| 286 | const test_token = main_tokens[decl]; | |
| 287 | const test_token = tree.nodeMainToken(decl); | |
| 288 | const opt_name_token, const block_node = tree.nodeData(decl).opt_token_and_node; | |
| 287 | 289 | try renderToken(r, test_token, .space); |
| 288 | const test_name_tag = token_tags[test_token + 1]; | |
| 289 | switch (test_name_tag) { | |
| 290 | .string_literal => try renderToken(r, test_token + 1, .space), | |
| 291 | .identifier => try renderIdentifier(r, test_token + 1, .space, .preserve_when_shadowing), | |
| 292 | else => {}, | |
| 290 | if (opt_name_token.unwrap()) |name_token| { | |
| 291 | switch (tree.tokenTag(name_token)) { | |
| 292 | .string_literal => try renderToken(r, name_token, .space), | |
| 293 | .identifier => try renderIdentifier(r, name_token, .space, .preserve_when_shadowing), | |
| 294 | else => unreachable, | |
| 295 | } | |
| 293 | 296 | } |
| 294 | try renderExpression(r, datas[decl].rhs, space); | |
| 297 | try renderExpression(r, block_node, space); | |
| 295 | 298 | }, |
| 296 | 299 | |
| 297 | 300 | .container_field_init, |
| ... | ... | @@ -319,10 +322,6 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa |
| 319 | 322 | fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 320 | 323 | const tree = r.tree; |
| 321 | 324 | const ais = r.ais; |
| 322 | const token_tags = tree.tokens.items(.tag); | |
| 323 | const main_tokens = tree.nodes.items(.main_token); | |
| 324 | const node_tags = tree.nodes.items(.tag); | |
| 325 | const datas = tree.nodes.items(.data); | |
| 326 | 325 | if (r.fixups.replace_nodes_with_string.get(node)) |replacement| { |
| 327 | 326 | try ais.writer().writeAll(replacement); |
| 328 | 327 | try renderOnlySpace(r, space); |
| ... | ... | @@ -330,9 +329,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 330 | 329 | } else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| { |
| 331 | 330 | return renderExpression(r, replacement, space); |
| 332 | 331 | } |
| 333 | switch (node_tags[node]) { | |
| 332 | switch (tree.nodeTag(node)) { | |
| 334 | 333 | .identifier => { |
| 335 | const token_index = main_tokens[node]; | |
| 334 | const token_index = tree.nodeMainToken(node); | |
| 336 | 335 | return renderIdentifier(r, token_index, space, .preserve_when_shadowing); |
| 337 | 336 | }, |
| 338 | 337 | |
| ... | ... | @@ -341,18 +340,23 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 341 | 340 | .unreachable_literal, |
| 342 | 341 | .anyframe_literal, |
| 343 | 342 | .string_literal, |
| 344 | => return renderToken(r, main_tokens[node], space), | |
| 343 | => return renderToken(r, tree.nodeMainToken(node), space), | |
| 345 | 344 | |
| 346 | 345 | .multiline_string_literal => { |
| 347 | 346 | try ais.maybeInsertNewline(); |
| 348 | 347 | |
| 349 | var i = datas[node].lhs; | |
| 350 | while (i <= datas[node].rhs) : (i += 1) try renderToken(r, i, .newline); | |
| 348 | const first_tok, const last_tok = tree.nodeData(node).token_and_token; | |
| 349 | for (first_tok..last_tok + 1) |i| { | |
| 350 | try renderToken(r, @intCast(i), .newline); | |
| 351 | } | |
| 352 | ||
| 353 | const next_token = last_tok + 1; | |
| 354 | const next_token_tag = tree.tokenTag(next_token); | |
| 351 | 355 | |
| 352 | 356 | // dedent the next thing that comes after a multiline string literal |
| 353 | 357 | if (!ais.indentStackEmpty() and |
| 354 | token_tags[i] != .colon and | |
| 355 | ((token_tags[i] != .semicolon and token_tags[i] != .comma) or | |
| 358 | next_token_tag != .colon and | |
| 359 | ((next_token_tag != .semicolon and next_token_tag != .comma) or | |
| 356 | 360 | ais.lastSpaceModeIndent() < ais.currentIndent())) |
| 357 | 361 | { |
| 358 | 362 | ais.popIndent(); |
| ... | ... | @@ -361,16 +365,17 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 361 | 365 | |
| 362 | 366 | switch (space) { |
| 363 | 367 | .none, .space, .newline, .skip => {}, |
| 364 | .semicolon => if (token_tags[i] == .semicolon) try renderTokenOverrideSpaceMode(r, i, .newline, .semicolon), | |
| 365 | .comma => if (token_tags[i] == .comma) try renderTokenOverrideSpaceMode(r, i, .newline, .comma), | |
| 366 | .comma_space => if (token_tags[i] == .comma) try renderToken(r, i, .space), | |
| 368 | .semicolon => if (next_token_tag == .semicolon) try renderTokenOverrideSpaceMode(r, next_token, .newline, .semicolon), | |
| 369 | .comma => if (next_token_tag == .comma) try renderTokenOverrideSpaceMode(r, next_token, .newline, .comma), | |
| 370 | .comma_space => if (next_token_tag == .comma) try renderToken(r, next_token, .space), | |
| 367 | 371 | } |
| 368 | 372 | }, |
| 369 | 373 | |
| 370 | 374 | .error_value => { |
| 371 | try renderToken(r, main_tokens[node], .none); | |
| 372 | try renderToken(r, main_tokens[node] + 1, .none); | |
| 373 | return renderIdentifier(r, main_tokens[node] + 2, space, .eagerly_unquote); | |
| 375 | const main_token = tree.nodeMainToken(node); | |
| 376 | try renderToken(r, main_token, .none); | |
| 377 | try renderToken(r, main_token + 1, .none); | |
| 378 | return renderIdentifier(r, main_token + 2, space, .eagerly_unquote); | |
| 374 | 379 | }, |
| 375 | 380 | |
| 376 | 381 | .block_two, |
| ... | ... | @@ -384,12 +389,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 384 | 389 | }, |
| 385 | 390 | |
| 386 | 391 | .@"errdefer" => { |
| 387 | const defer_token = main_tokens[node]; | |
| 388 | const payload_token = datas[node].lhs; | |
| 389 | const expr = datas[node].rhs; | |
| 392 | const defer_token = tree.nodeMainToken(node); | |
| 393 | const maybe_payload_token, const expr = tree.nodeData(node).opt_token_and_node; | |
| 390 | 394 | |
| 391 | 395 | try renderToken(r, defer_token, .space); |
| 392 | if (payload_token != 0) { | |
| 396 | if (maybe_payload_token.unwrap()) |payload_token| { | |
| 393 | 397 | try renderToken(r, payload_token - 1, .none); // | |
| 394 | 398 | try renderIdentifier(r, payload_token, .none, .preserve_when_shadowing); // identifier |
| 395 | 399 | try renderToken(r, payload_token + 1, .space); // | |
| ... | ... | @@ -397,84 +401,76 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 397 | 401 | return renderExpression(r, expr, space); |
| 398 | 402 | }, |
| 399 | 403 | |
| 400 | .@"defer" => { | |
| 401 | const defer_token = main_tokens[node]; | |
| 402 | const expr = datas[node].rhs; | |
| 403 | try renderToken(r, defer_token, .space); | |
| 404 | return renderExpression(r, expr, space); | |
| 405 | }, | |
| 406 | .@"comptime", .@"nosuspend" => { | |
| 407 | const comptime_token = main_tokens[node]; | |
| 408 | const block = datas[node].lhs; | |
| 409 | try renderToken(r, comptime_token, .space); | |
| 410 | return renderExpression(r, block, space); | |
| 411 | }, | |
| 412 | ||
| 413 | .@"suspend" => { | |
| 414 | const suspend_token = main_tokens[node]; | |
| 415 | const body = datas[node].lhs; | |
| 416 | try renderToken(r, suspend_token, .space); | |
| 417 | return renderExpression(r, body, space); | |
| 404 | .@"defer", | |
| 405 | .@"comptime", | |
| 406 | .@"nosuspend", | |
| 407 | .@"suspend", | |
| 408 | => { | |
| 409 | const main_token = tree.nodeMainToken(node); | |
| 410 | const item = tree.nodeData(node).node; | |
| 411 | try renderToken(r, main_token, .space); | |
| 412 | return renderExpression(r, item, space); | |
| 418 | 413 | }, |
| 419 | 414 | |
| 420 | 415 | .@"catch" => { |
| 421 | const main_token = main_tokens[node]; | |
| 422 | const fallback_first = tree.firstToken(datas[node].rhs); | |
| 416 | const main_token = tree.nodeMainToken(node); | |
| 417 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 418 | const fallback_first = tree.firstToken(rhs); | |
| 423 | 419 | |
| 424 | 420 | const same_line = tree.tokensOnSameLine(main_token, fallback_first); |
| 425 | 421 | const after_op_space = if (same_line) Space.space else Space.newline; |
| 426 | 422 | |
| 427 | try renderExpression(r, datas[node].lhs, .space); // target | |
| 423 | try renderExpression(r, lhs, .space); // target | |
| 428 | 424 | |
| 429 | 425 | try ais.pushIndent(.normal); |
| 430 | if (token_tags[fallback_first - 1] == .pipe) { | |
| 426 | if (tree.tokenTag(fallback_first - 1) == .pipe) { | |
| 431 | 427 | try renderToken(r, main_token, .space); // catch keyword |
| 432 | 428 | try renderToken(r, main_token + 1, .none); // pipe |
| 433 | 429 | try renderIdentifier(r, main_token + 2, .none, .preserve_when_shadowing); // payload identifier |
| 434 | 430 | try renderToken(r, main_token + 3, after_op_space); // pipe |
| 435 | 431 | } else { |
| 436 | assert(token_tags[fallback_first - 1] == .keyword_catch); | |
| 432 | assert(tree.tokenTag(fallback_first - 1) == .keyword_catch); | |
| 437 | 433 | try renderToken(r, main_token, after_op_space); // catch keyword |
| 438 | 434 | } |
| 439 | try renderExpression(r, datas[node].rhs, space); // fallback | |
| 435 | try renderExpression(r, rhs, space); // fallback | |
| 440 | 436 | ais.popIndent(); |
| 441 | 437 | }, |
| 442 | 438 | |
| 443 | 439 | .field_access => { |
| 444 | const main_token = main_tokens[node]; | |
| 445 | const field_access = datas[node]; | |
| 440 | const lhs, const name_token = tree.nodeData(node).node_and_token; | |
| 441 | const dot_token = name_token - 1; | |
| 446 | 442 | |
| 447 | 443 | try ais.pushIndent(.field_access); |
| 448 | try renderExpression(r, field_access.lhs, .none); | |
| 444 | try renderExpression(r, lhs, .none); | |
| 449 | 445 | |
| 450 | 446 | // Allow a line break between the lhs and the dot if the lhs and rhs |
| 451 | 447 | // are on different lines. |
| 452 | const lhs_last_token = tree.lastToken(field_access.lhs); | |
| 453 | const same_line = tree.tokensOnSameLine(lhs_last_token, main_token + 1); | |
| 454 | if (!same_line and !hasComment(tree, lhs_last_token, main_token)) try ais.insertNewline(); | |
| 448 | const lhs_last_token = tree.lastToken(lhs); | |
| 449 | const same_line = tree.tokensOnSameLine(lhs_last_token, name_token); | |
| 450 | if (!same_line and !hasComment(tree, lhs_last_token, dot_token)) try ais.insertNewline(); | |
| 455 | 451 | |
| 456 | try renderToken(r, main_token, .none); // . | |
| 452 | try renderToken(r, dot_token, .none); | |
| 457 | 453 | |
| 458 | try renderIdentifier(r, field_access.rhs, space, .eagerly_unquote); // field | |
| 454 | try renderIdentifier(r, name_token, space, .eagerly_unquote); // field | |
| 459 | 455 | ais.popIndent(); |
| 460 | 456 | }, |
| 461 | 457 | |
| 462 | 458 | .error_union, |
| 463 | 459 | .switch_range, |
| 464 | 460 | => { |
| 465 | const infix = datas[node]; | |
| 466 | try renderExpression(r, infix.lhs, .none); | |
| 467 | try renderToken(r, main_tokens[node], .none); | |
| 468 | return renderExpression(r, infix.rhs, space); | |
| 461 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 462 | try renderExpression(r, lhs, .none); | |
| 463 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 464 | return renderExpression(r, rhs, space); | |
| 469 | 465 | }, |
| 470 | 466 | .for_range => { |
| 471 | const infix = datas[node]; | |
| 472 | try renderExpression(r, infix.lhs, .none); | |
| 473 | if (infix.rhs != 0) { | |
| 474 | try renderToken(r, main_tokens[node], .none); | |
| 475 | return renderExpression(r, infix.rhs, space); | |
| 467 | const start, const opt_end = tree.nodeData(node).node_and_opt_node; | |
| 468 | try renderExpression(r, start, .none); | |
| 469 | if (opt_end.unwrap()) |end| { | |
| 470 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 471 | return renderExpression(r, end, space); | |
| 476 | 472 | } else { |
| 477 | return renderToken(r, main_tokens[node], space); | |
| 473 | return renderToken(r, tree.nodeMainToken(node), space); | |
| 478 | 474 | } |
| 479 | 475 | }, |
| 480 | 476 | |
| ... | ... | @@ -497,16 +493,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 497 | 493 | .assign_mul_wrap, |
| 498 | 494 | .assign_mul_sat, |
| 499 | 495 | => { |
| 500 | const infix = datas[node]; | |
| 501 | try renderExpression(r, infix.lhs, .space); | |
| 502 | const op_token = main_tokens[node]; | |
| 496 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 497 | try renderExpression(r, lhs, .space); | |
| 498 | const op_token = tree.nodeMainToken(node); | |
| 503 | 499 | try ais.pushIndent(.after_equals); |
| 504 | 500 | if (tree.tokensOnSameLine(op_token, op_token + 1)) { |
| 505 | 501 | try renderToken(r, op_token, .space); |
| 506 | 502 | } else { |
| 507 | 503 | try renderToken(r, op_token, .newline); |
| 508 | 504 | } |
| 509 | try renderExpression(r, infix.rhs, space); | |
| 505 | try renderExpression(r, rhs, space); | |
| 510 | 506 | ais.popIndent(); |
| 511 | 507 | }, |
| 512 | 508 | |
| ... | ... | @@ -540,16 +536,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 540 | 536 | .sub_sat, |
| 541 | 537 | .@"orelse", |
| 542 | 538 | => { |
| 543 | const infix = datas[node]; | |
| 544 | try renderExpression(r, infix.lhs, .space); | |
| 545 | const op_token = main_tokens[node]; | |
| 539 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 540 | try renderExpression(r, lhs, .space); | |
| 541 | const op_token = tree.nodeMainToken(node); | |
| 546 | 542 | try ais.pushIndent(.binop); |
| 547 | 543 | if (tree.tokensOnSameLine(op_token, op_token + 1)) { |
| 548 | 544 | try renderToken(r, op_token, .space); |
| 549 | 545 | } else { |
| 550 | 546 | try renderToken(r, op_token, .newline); |
| 551 | 547 | } |
| 552 | try renderExpression(r, infix.rhs, space); | |
| 548 | try renderExpression(r, rhs, space); | |
| 553 | 549 | ais.popIndent(); |
| 554 | 550 | }, |
| 555 | 551 | |
| ... | ... | @@ -561,7 +557,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 561 | 557 | |
| 562 | 558 | for (full.ast.variables, 0..) |variable_node, i| { |
| 563 | 559 | const variable_space: Space = if (i == full.ast.variables.len - 1) .space else .comma_space; |
| 564 | switch (node_tags[variable_node]) { | |
| 560 | switch (tree.nodeTag(variable_node)) { | |
| 565 | 561 | .global_var_decl, |
| 566 | 562 | .local_var_decl, |
| 567 | 563 | .simple_var_decl, |
| ... | ... | @@ -589,16 +585,16 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 589 | 585 | .optional_type, |
| 590 | 586 | .address_of, |
| 591 | 587 | => { |
| 592 | try renderToken(r, main_tokens[node], .none); | |
| 593 | return renderExpression(r, datas[node].lhs, space); | |
| 588 | try renderToken(r, tree.nodeMainToken(node), .none); | |
| 589 | return renderExpression(r, tree.nodeData(node).node, space); | |
| 594 | 590 | }, |
| 595 | 591 | |
| 596 | 592 | .@"try", |
| 597 | 593 | .@"resume", |
| 598 | 594 | .@"await", |
| 599 | 595 | => { |
| 600 | try renderToken(r, main_tokens[node], .space); | |
| 601 | return renderExpression(r, datas[node].lhs, space); | |
| 596 | try renderToken(r, tree.nodeMainToken(node), .space); | |
| 597 | return renderExpression(r, tree.nodeData(node).node, space); | |
| 602 | 598 | }, |
| 603 | 599 | |
| 604 | 600 | .array_type, |
| ... | ... | @@ -651,68 +647,77 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 651 | 647 | }, |
| 652 | 648 | |
| 653 | 649 | .array_access => { |
| 654 | const suffix = datas[node]; | |
| 655 | const lbracket = tree.firstToken(suffix.rhs) - 1; | |
| 656 | const rbracket = tree.lastToken(suffix.rhs) + 1; | |
| 650 | const lhs, const rhs = tree.nodeData(node).node_and_node; | |
| 651 | const lbracket = tree.firstToken(rhs) - 1; | |
| 652 | const rbracket = tree.lastToken(rhs) + 1; | |
| 657 | 653 | const one_line = tree.tokensOnSameLine(lbracket, rbracket); |
| 658 | 654 | const inner_space = if (one_line) Space.none else Space.newline; |
| 659 | try renderExpression(r, suffix.lhs, .none); | |
| 655 | try renderExpression(r, lhs, .none); | |
| 660 | 656 | try ais.pushIndent(.normal); |
| 661 | 657 | try renderToken(r, lbracket, inner_space); // [ |
| 662 | try renderExpression(r, suffix.rhs, inner_space); | |
| 658 | try renderExpression(r, rhs, inner_space); | |
| 663 | 659 | ais.popIndent(); |
| 664 | 660 | return renderToken(r, rbracket, space); // ] |
| 665 | 661 | }, |
| 666 | 662 | |
| 667 | .slice_open, .slice, .slice_sentinel => return renderSlice(r, node, tree.fullSlice(node).?, space), | |
| 663 | .slice_open, | |
| 664 | .slice, | |
| 665 | .slice_sentinel, | |
| 666 | => return renderSlice(r, node, tree.fullSlice(node).?, space), | |
| 668 | 667 | |
| 669 | 668 | .deref => { |
| 670 | try renderExpression(r, datas[node].lhs, .none); | |
| 671 | return renderToken(r, main_tokens[node], space); | |
| 669 | try renderExpression(r, tree.nodeData(node).node, .none); | |
| 670 | return renderToken(r, tree.nodeMainToken(node), space); | |
| 672 | 671 | }, |
| 673 | 672 | |
| 674 | 673 | .unwrap_optional => { |
| 675 | try renderExpression(r, datas[node].lhs, .none); | |
| 676 | try renderToken(r, main_tokens[node], .none); | |
| 677 | return renderToken(r, datas[node].rhs, space); | |
| 674 | const lhs, const question_mark = tree.nodeData(node).node_and_token; | |
| 675 | const dot_token = question_mark - 1; | |
| 676 | try renderExpression(r, lhs, .none); | |
| 677 | try renderToken(r, dot_token, .none); | |
| 678 | return renderToken(r, question_mark, space); | |
| 678 | 679 | }, |
| 679 | 680 | |
| 680 | 681 | .@"break", .@"continue" => { |
| 681 | const main_token = main_tokens[node]; | |
| 682 | const label_token = datas[node].lhs; | |
| 683 | const target = datas[node].rhs; | |
| 684 | if (label_token == 0 and target == 0) { | |
| 682 | const main_token = tree.nodeMainToken(node); | |
| 683 | const opt_label_token, const opt_target = tree.nodeData(node).opt_token_and_opt_node; | |
| 684 | if (opt_label_token == .none and opt_target == .none) { | |
| 685 | 685 | try renderToken(r, main_token, space); // break/continue |
| 686 | } else if (label_token == 0 and target != 0) { | |
| 686 | } else if (opt_label_token == .none and opt_target != .none) { | |
| 687 | const target = opt_target.unwrap().?; | |
| 687 | 688 | try renderToken(r, main_token, .space); // break/continue |
| 688 | 689 | try renderExpression(r, target, space); |
| 689 | } else if (label_token != 0 and target == 0) { | |
| 690 | } else if (opt_label_token != .none and opt_target == .none) { | |
| 691 | const label_token = opt_label_token.unwrap().?; | |
| 690 | 692 | try renderToken(r, main_token, .space); // break/continue |
| 691 | 693 | try renderToken(r, label_token - 1, .none); // : |
| 692 | 694 | try renderIdentifier(r, label_token, space, .eagerly_unquote); // identifier |
| 693 | } else if (label_token != 0 and target != 0) { | |
| 695 | } else if (opt_label_token != .none and opt_target != .none) { | |
| 696 | const label_token = opt_label_token.unwrap().?; | |
| 697 | const target = opt_target.unwrap().?; | |
| 694 | 698 | try renderToken(r, main_token, .space); // break/continue |
| 695 | 699 | try renderToken(r, label_token - 1, .none); // : |
| 696 | 700 | try renderIdentifier(r, label_token, .space, .eagerly_unquote); // identifier |
| 697 | 701 | try renderExpression(r, target, space); |
| 698 | } | |
| 702 | } else unreachable; | |
| 699 | 703 | }, |
| 700 | 704 | |
| 701 | 705 | .@"return" => { |
| 702 | if (datas[node].lhs != 0) { | |
| 703 | try renderToken(r, main_tokens[node], .space); | |
| 704 | try renderExpression(r, datas[node].lhs, space); | |
| 706 | if (tree.nodeData(node).opt_node.unwrap()) |expr| { | |
| 707 | try renderToken(r, tree.nodeMainToken(node), .space); | |
| 708 | try renderExpression(r, expr, space); | |
| 705 | 709 | } else { |
| 706 | try renderToken(r, main_tokens[node], space); | |
| 710 | try renderToken(r, tree.nodeMainToken(node), space); | |
| 707 | 711 | } |
| 708 | 712 | }, |
| 709 | 713 | |
| 710 | 714 | .grouped_expression => { |
| 715 | const expr, const rparen = tree.nodeData(node).node_and_token; | |
| 711 | 716 | try ais.pushIndent(.normal); |
| 712 | try renderToken(r, main_tokens[node], .none); // lparen | |
| 713 | try renderExpression(r, datas[node].lhs, .none); | |
| 717 | try renderToken(r, tree.nodeMainToken(node), .none); // lparen | |
| 718 | try renderExpression(r, expr, .none); | |
| 714 | 719 | ais.popIndent(); |
| 715 | return renderToken(r, datas[node].rhs, space); // rparen | |
| 720 | return renderToken(r, rparen, space); | |
| 716 | 721 | }, |
| 717 | 722 | |
| 718 | 723 | .container_decl, |
| ... | ... | @@ -733,9 +738,9 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 733 | 738 | }, |
| 734 | 739 | |
| 735 | 740 | .error_set_decl => { |
| 736 | const error_token = main_tokens[node]; | |
| 741 | const error_token = tree.nodeMainToken(node); | |
| 737 | 742 | const lbrace = error_token + 1; |
| 738 | const rbrace = datas[node].rhs; | |
| 743 | const rbrace = tree.nodeData(node).token; | |
| 739 | 744 | |
| 740 | 745 | try renderToken(r, error_token, .none); |
| 741 | 746 | |
| ... | ... | @@ -743,20 +748,20 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 743 | 748 | // There is nothing between the braces so render condensed: `error{}` |
| 744 | 749 | try renderToken(r, lbrace, .none); |
| 745 | 750 | return renderToken(r, rbrace, space); |
| 746 | } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .identifier) { | |
| 751 | } else if (lbrace + 2 == rbrace and tree.tokenTag(lbrace + 1) == .identifier) { | |
| 747 | 752 | // There is exactly one member and no trailing comma or |
| 748 | 753 | // comments, so render without surrounding spaces: `error{Foo}` |
| 749 | 754 | try renderToken(r, lbrace, .none); |
| 750 | 755 | try renderIdentifier(r, lbrace + 1, .none, .eagerly_unquote); // identifier |
| 751 | 756 | return renderToken(r, rbrace, space); |
| 752 | } else if (token_tags[rbrace - 1] == .comma) { | |
| 757 | } else if (tree.tokenTag(rbrace - 1) == .comma) { | |
| 753 | 758 | // There is a trailing comma so render each member on a new line. |
| 754 | 759 | try ais.pushIndent(.normal); |
| 755 | 760 | try renderToken(r, lbrace, .newline); |
| 756 | 761 | var i = lbrace + 1; |
| 757 | 762 | while (i < rbrace) : (i += 1) { |
| 758 | 763 | if (i > lbrace + 1) try renderExtraNewlineToken(r, i); |
| 759 | switch (token_tags[i]) { | |
| 764 | switch (tree.tokenTag(i)) { | |
| 760 | 765 | .doc_comment => try renderToken(r, i, .newline), |
| 761 | 766 | .identifier => { |
| 762 | 767 | try ais.pushSpace(.comma); |
| ... | ... | @@ -774,7 +779,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 774 | 779 | try renderToken(r, lbrace, .space); |
| 775 | 780 | var i = lbrace + 1; |
| 776 | 781 | while (i < rbrace) : (i += 1) { |
| 777 | switch (token_tags[i]) { | |
| 782 | switch (tree.tokenTag(i)) { | |
| 778 | 783 | .doc_comment => unreachable, // TODO |
| 779 | 784 | .identifier => try renderIdentifier(r, i, .comma_space, .eagerly_unquote), |
| 780 | 785 | .comma => {}, |
| ... | ... | @@ -792,7 +797,7 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 792 | 797 | => { |
| 793 | 798 | var buf: [2]Ast.Node.Index = undefined; |
| 794 | 799 | const params = tree.builtinCallParams(&buf, node).?; |
| 795 | return renderBuiltinCall(r, main_tokens[node], params, space); | |
| 800 | return renderBuiltinCall(r, tree.nodeMainToken(node), params, space); | |
| 796 | 801 | }, |
| 797 | 802 | |
| 798 | 803 | .fn_proto_simple, |
| ... | ... | @@ -805,14 +810,10 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 805 | 810 | }, |
| 806 | 811 | |
| 807 | 812 | .anyframe_type => { |
| 808 | const main_token = main_tokens[node]; | |
| 809 | if (datas[node].rhs != 0) { | |
| 810 | try renderToken(r, main_token, .none); // anyframe | |
| 811 | try renderToken(r, main_token + 1, .none); // -> | |
| 812 | return renderExpression(r, datas[node].rhs, space); | |
| 813 | } else { | |
| 814 | return renderToken(r, main_token, space); // anyframe | |
| 815 | } | |
| 813 | const main_token = tree.nodeMainToken(node); | |
| 814 | try renderToken(r, main_token, .none); // anyframe | |
| 815 | try renderToken(r, main_token + 1, .none); // -> | |
| 816 | return renderExpression(r, tree.nodeData(node).token_and_node[1], space); | |
| 816 | 817 | }, |
| 817 | 818 | |
| 818 | 819 | .@"switch", |
| ... | ... | @@ -869,8 +870,8 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 869 | 870 | => return renderAsm(r, tree.fullAsm(node).?, space), |
| 870 | 871 | |
| 871 | 872 | .enum_literal => { |
| 872 | try renderToken(r, main_tokens[node] - 1, .none); // . | |
| 873 | return renderIdentifier(r, main_tokens[node], space, .eagerly_unquote); // name | |
| 873 | try renderToken(r, tree.nodeMainToken(node) - 1, .none); // . | |
| 874 | return renderIdentifier(r, tree.nodeMainToken(node), space, .eagerly_unquote); // name | |
| 874 | 875 | }, |
| 875 | 876 | |
| 876 | 877 | .fn_decl => unreachable, |
| ... | ... | @@ -912,9 +913,9 @@ fn renderArrayType( |
| 912 | 913 | try ais.pushIndent(.normal); |
| 913 | 914 | try renderToken(r, array_type.ast.lbracket, inner_space); // lbracket |
| 914 | 915 | try renderExpression(r, array_type.ast.elem_count, inner_space); |
| 915 | if (array_type.ast.sentinel != 0) { | |
| 916 | try renderToken(r, tree.firstToken(array_type.ast.sentinel) - 1, inner_space); // colon | |
| 917 | try renderExpression(r, array_type.ast.sentinel, inner_space); | |
| 916 | if (array_type.ast.sentinel.unwrap()) |sentinel| { | |
| 917 | try renderToken(r, tree.firstToken(sentinel) - 1, inner_space); // colon | |
| 918 | try renderExpression(r, sentinel, inner_space); | |
| 918 | 919 | } |
| 919 | 920 | ais.popIndent(); |
| 920 | 921 | try renderToken(r, rbracket, .none); // rbracket |
| ... | ... | @@ -923,6 +924,7 @@ fn renderArrayType( |
| 923 | 924 | |
| 924 | 925 | fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void { |
| 925 | 926 | const tree = r.tree; |
| 927 | const main_token = ptr_type.ast.main_token; | |
| 926 | 928 | switch (ptr_type.size) { |
| 927 | 929 | .one => { |
| 928 | 930 | // Since ** tokens exist and the same token is shared by two |
| ... | ... | @@ -930,41 +932,41 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi |
| 930 | 932 | // in such a relationship. If so, skip rendering anything for |
| 931 | 933 | // this pointer type and rely on the child to render our asterisk |
| 932 | 934 | // as well when it renders the ** token. |
| 933 | if (tree.tokens.items(.tag)[ptr_type.ast.main_token] == .asterisk_asterisk and | |
| 934 | ptr_type.ast.main_token == tree.nodes.items(.main_token)[ptr_type.ast.child_type]) | |
| 935 | if (tree.tokenTag(main_token) == .asterisk_asterisk and | |
| 936 | main_token == tree.nodeMainToken(ptr_type.ast.child_type)) | |
| 935 | 937 | { |
| 936 | 938 | return renderExpression(r, ptr_type.ast.child_type, space); |
| 937 | 939 | } |
| 938 | try renderToken(r, ptr_type.ast.main_token, .none); // asterisk | |
| 940 | try renderToken(r, main_token, .none); // asterisk | |
| 939 | 941 | }, |
| 940 | 942 | .many => { |
| 941 | if (ptr_type.ast.sentinel == 0) { | |
| 942 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 943 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 944 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // rbracket | |
| 943 | if (ptr_type.ast.sentinel.unwrap()) |sentinel| { | |
| 944 | try renderToken(r, main_token, .none); // lbracket | |
| 945 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 946 | try renderToken(r, main_token + 2, .none); // colon | |
| 947 | try renderExpression(r, sentinel, .none); | |
| 948 | try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket | |
| 945 | 949 | } else { |
| 946 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 947 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 948 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // colon | |
| 949 | try renderExpression(r, ptr_type.ast.sentinel, .none); | |
| 950 | try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket | |
| 950 | try renderToken(r, main_token, .none); // lbracket | |
| 951 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 952 | try renderToken(r, main_token + 2, .none); // rbracket | |
| 951 | 953 | } |
| 952 | 954 | }, |
| 953 | 955 | .c => { |
| 954 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 955 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // asterisk | |
| 956 | try renderToken(r, ptr_type.ast.main_token + 2, .none); // c | |
| 957 | try renderToken(r, ptr_type.ast.main_token + 3, .none); // rbracket | |
| 956 | try renderToken(r, main_token, .none); // lbracket | |
| 957 | try renderToken(r, main_token + 1, .none); // asterisk | |
| 958 | try renderToken(r, main_token + 2, .none); // c | |
| 959 | try renderToken(r, main_token + 3, .none); // rbracket | |
| 958 | 960 | }, |
| 959 | 961 | .slice => { |
| 960 | if (ptr_type.ast.sentinel == 0) { | |
| 961 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 962 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // rbracket | |
| 962 | if (ptr_type.ast.sentinel.unwrap()) |sentinel| { | |
| 963 | try renderToken(r, main_token, .none); // lbracket | |
| 964 | try renderToken(r, main_token + 1, .none); // colon | |
| 965 | try renderExpression(r, sentinel, .none); | |
| 966 | try renderToken(r, tree.lastToken(sentinel) + 1, .none); // rbracket | |
| 963 | 967 | } else { |
| 964 | try renderToken(r, ptr_type.ast.main_token, .none); // lbracket | |
| 965 | try renderToken(r, ptr_type.ast.main_token + 1, .none); // colon | |
| 966 | try renderExpression(r, ptr_type.ast.sentinel, .none); | |
| 967 | try renderToken(r, tree.lastToken(ptr_type.ast.sentinel) + 1, .none); // rbracket | |
| 968 | try renderToken(r, main_token, .none); // lbracket | |
| 969 | try renderToken(r, main_token + 1, .none); // rbracket | |
| 968 | 970 | } |
| 969 | 971 | }, |
| 970 | 972 | } |
| ... | ... | @@ -973,29 +975,29 @@ fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!voi |
| 973 | 975 | try renderToken(r, allowzero_token, .space); |
| 974 | 976 | } |
| 975 | 977 | |
| 976 | if (ptr_type.ast.align_node != 0) { | |
| 977 | const align_first = tree.firstToken(ptr_type.ast.align_node); | |
| 978 | if (ptr_type.ast.align_node.unwrap()) |align_node| { | |
| 979 | const align_first = tree.firstToken(align_node); | |
| 978 | 980 | try renderToken(r, align_first - 2, .none); // align |
| 979 | 981 | try renderToken(r, align_first - 1, .none); // lparen |
| 980 | try renderExpression(r, ptr_type.ast.align_node, .none); | |
| 981 | if (ptr_type.ast.bit_range_start != 0) { | |
| 982 | assert(ptr_type.ast.bit_range_end != 0); | |
| 983 | try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_start) - 1, .none); // colon | |
| 984 | try renderExpression(r, ptr_type.ast.bit_range_start, .none); | |
| 985 | try renderToken(r, tree.firstToken(ptr_type.ast.bit_range_end) - 1, .none); // colon | |
| 986 | try renderExpression(r, ptr_type.ast.bit_range_end, .none); | |
| 987 | try renderToken(r, tree.lastToken(ptr_type.ast.bit_range_end) + 1, .space); // rparen | |
| 982 | try renderExpression(r, align_node, .none); | |
| 983 | if (ptr_type.ast.bit_range_start.unwrap()) |bit_range_start| { | |
| 984 | const bit_range_end = ptr_type.ast.bit_range_end.unwrap().?; | |
| 985 | try renderToken(r, tree.firstToken(bit_range_start) - 1, .none); // colon | |
| 986 | try renderExpression(r, bit_range_start, .none); | |
| 987 | try renderToken(r, tree.firstToken(bit_range_end) - 1, .none); // colon | |
| 988 | try renderExpression(r, bit_range_end, .none); | |
| 989 | try renderToken(r, tree.lastToken(bit_range_end) + 1, .space); // rparen | |
| 988 | 990 | } else { |
| 989 | try renderToken(r, tree.lastToken(ptr_type.ast.align_node) + 1, .space); // rparen | |
| 991 | try renderToken(r, tree.lastToken(align_node) + 1, .space); // rparen | |
| 990 | 992 | } |
| 991 | 993 | } |
| 992 | 994 | |
| 993 | if (ptr_type.ast.addrspace_node != 0) { | |
| 994 | const addrspace_first = tree.firstToken(ptr_type.ast.addrspace_node); | |
| 995 | if (ptr_type.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 996 | const addrspace_first = tree.firstToken(addrspace_node); | |
| 995 | 997 | try renderToken(r, addrspace_first - 2, .none); // addrspace |
| 996 | 998 | try renderToken(r, addrspace_first - 1, .none); // lparen |
| 997 | try renderExpression(r, ptr_type.ast.addrspace_node, .none); | |
| 998 | try renderToken(r, tree.lastToken(ptr_type.ast.addrspace_node) + 1, .space); // rparen | |
| 999 | try renderExpression(r, addrspace_node, .none); | |
| 1000 | try renderToken(r, tree.lastToken(addrspace_node) + 1, .space); // rparen | |
| 999 | 1001 | } |
| 1000 | 1002 | |
| 1001 | 1003 | if (ptr_type.const_token) |const_token| { |
| ... | ... | @@ -1016,13 +1018,12 @@ fn renderSlice( |
| 1016 | 1018 | space: Space, |
| 1017 | 1019 | ) Error!void { |
| 1018 | 1020 | const tree = r.tree; |
| 1019 | const node_tags = tree.nodes.items(.tag); | |
| 1020 | const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or | |
| 1021 | if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false; | |
| 1021 | const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or | |
| 1022 | if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false; | |
| 1022 | 1023 | const after_start_space = if (after_start_space_bool) Space.space else Space.none; |
| 1023 | const after_dots_space = if (slice.ast.end != 0) | |
| 1024 | const after_dots_space = if (slice.ast.end != .none) | |
| 1024 | 1025 | after_start_space |
| 1025 | else if (slice.ast.sentinel != 0) Space.space else Space.none; | |
| 1026 | else if (slice.ast.sentinel != .none) Space.space else Space.none; | |
| 1026 | 1027 | |
| 1027 | 1028 | try renderExpression(r, slice.ast.sliced, .none); |
| 1028 | 1029 | try renderToken(r, slice.ast.lbracket, .none); // lbracket |
| ... | ... | @@ -1031,14 +1032,14 @@ fn renderSlice( |
| 1031 | 1032 | try renderExpression(r, slice.ast.start, after_start_space); |
| 1032 | 1033 | try renderToken(r, start_last + 1, after_dots_space); // ellipsis2 ("..") |
| 1033 | 1034 | |
| 1034 | if (slice.ast.end != 0) { | |
| 1035 | const after_end_space = if (slice.ast.sentinel != 0) Space.space else Space.none; | |
| 1036 | try renderExpression(r, slice.ast.end, after_end_space); | |
| 1035 | if (slice.ast.end.unwrap()) |end| { | |
| 1036 | const after_end_space = if (slice.ast.sentinel != .none) Space.space else Space.none; | |
| 1037 | try renderExpression(r, end, after_end_space); | |
| 1037 | 1038 | } |
| 1038 | 1039 | |
| 1039 | if (slice.ast.sentinel != 0) { | |
| 1040 | try renderToken(r, tree.firstToken(slice.ast.sentinel) - 1, .none); // colon | |
| 1041 | try renderExpression(r, slice.ast.sentinel, .none); | |
| 1040 | if (slice.ast.sentinel.unwrap()) |sentinel| { | |
| 1041 | try renderToken(r, tree.firstToken(sentinel) - 1, .none); // colon | |
| 1042 | try renderExpression(r, sentinel, .none); | |
| 1042 | 1043 | } |
| 1043 | 1044 | |
| 1044 | 1045 | try renderToken(r, tree.lastToken(slice_node), space); // rbracket |
| ... | ... | @@ -1050,12 +1051,8 @@ fn renderAsmOutput( |
| 1050 | 1051 | space: Space, |
| 1051 | 1052 | ) Error!void { |
| 1052 | 1053 | const tree = r.tree; |
| 1053 | const token_tags = tree.tokens.items(.tag); | |
| 1054 | const node_tags = tree.nodes.items(.tag); | |
| 1055 | const main_tokens = tree.nodes.items(.main_token); | |
| 1056 | const datas = tree.nodes.items(.data); | |
| 1057 | assert(node_tags[asm_output] == .asm_output); | |
| 1058 | const symbolic_name = main_tokens[asm_output]; | |
| 1054 | assert(tree.nodeTag(asm_output) == .asm_output); | |
| 1055 | const symbolic_name = tree.nodeMainToken(asm_output); | |
| 1059 | 1056 | |
| 1060 | 1057 | try renderToken(r, symbolic_name - 1, .none); // lbracket |
| 1061 | 1058 | try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident |
| ... | ... | @@ -1063,10 +1060,11 @@ fn renderAsmOutput( |
| 1063 | 1060 | try renderToken(r, symbolic_name + 2, .space); // "constraint" |
| 1064 | 1061 | try renderToken(r, symbolic_name + 3, .none); // lparen |
| 1065 | 1062 | |
| 1066 | if (token_tags[symbolic_name + 4] == .arrow) { | |
| 1063 | if (tree.tokenTag(symbolic_name + 4) == .arrow) { | |
| 1064 | const type_expr, const rparen = tree.nodeData(asm_output).opt_node_and_token; | |
| 1067 | 1065 | try renderToken(r, symbolic_name + 4, .space); // -> |
| 1068 | try renderExpression(r, datas[asm_output].lhs, Space.none); | |
| 1069 | return renderToken(r, datas[asm_output].rhs, space); // rparen | |
| 1066 | try renderExpression(r, type_expr.unwrap().?, Space.none); | |
| 1067 | return renderToken(r, rparen, space); | |
| 1070 | 1068 | } else { |
| 1071 | 1069 | try renderIdentifier(r, symbolic_name + 4, .none, .eagerly_unquote); // ident |
| 1072 | 1070 | return renderToken(r, symbolic_name + 5, space); // rparen |
| ... | ... | @@ -1079,19 +1077,17 @@ fn renderAsmInput( |
| 1079 | 1077 | space: Space, |
| 1080 | 1078 | ) Error!void { |
| 1081 | 1079 | const tree = r.tree; |
| 1082 | const node_tags = tree.nodes.items(.tag); | |
| 1083 | const main_tokens = tree.nodes.items(.main_token); | |
| 1084 | const datas = tree.nodes.items(.data); | |
| 1085 | assert(node_tags[asm_input] == .asm_input); | |
| 1086 | const symbolic_name = main_tokens[asm_input]; | |
| 1080 | assert(tree.nodeTag(asm_input) == .asm_input); | |
| 1081 | const symbolic_name = tree.nodeMainToken(asm_input); | |
| 1082 | const expr, const rparen = tree.nodeData(asm_input).node_and_token; | |
| 1087 | 1083 | |
| 1088 | 1084 | try renderToken(r, symbolic_name - 1, .none); // lbracket |
| 1089 | 1085 | try renderIdentifier(r, symbolic_name, .none, .eagerly_unquote); // ident |
| 1090 | 1086 | try renderToken(r, symbolic_name + 1, .space); // rbracket |
| 1091 | 1087 | try renderToken(r, symbolic_name + 2, .space); // "constraint" |
| 1092 | 1088 | try renderToken(r, symbolic_name + 3, .none); // lparen |
| 1093 | try renderExpression(r, datas[asm_input].lhs, Space.none); | |
| 1094 | return renderToken(r, datas[asm_input].rhs, space); // rparen | |
| 1089 | try renderExpression(r, expr, Space.none); | |
| 1090 | return renderToken(r, rparen, space); | |
| 1095 | 1091 | } |
| 1096 | 1092 | |
| 1097 | 1093 | fn renderVarDecl( |
| ... | ... | @@ -1147,15 +1143,15 @@ fn renderVarDeclWithoutFixups( |
| 1147 | 1143 | |
| 1148 | 1144 | try renderToken(r, var_decl.ast.mut_token, .space); // var |
| 1149 | 1145 | |
| 1150 | if (var_decl.ast.type_node != 0 or var_decl.ast.align_node != 0 or | |
| 1151 | var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or | |
| 1152 | var_decl.ast.init_node != 0) | |
| 1146 | if (var_decl.ast.type_node != .none or var_decl.ast.align_node != .none or | |
| 1147 | var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or | |
| 1148 | var_decl.ast.init_node != .none) | |
| 1153 | 1149 | { |
| 1154 | const name_space = if (var_decl.ast.type_node == 0 and | |
| 1155 | (var_decl.ast.align_node != 0 or | |
| 1156 | var_decl.ast.addrspace_node != 0 or | |
| 1157 | var_decl.ast.section_node != 0 or | |
| 1158 | var_decl.ast.init_node != 0)) | |
| 1150 | const name_space = if (var_decl.ast.type_node == .none and | |
| 1151 | (var_decl.ast.align_node != .none or | |
| 1152 | var_decl.ast.addrspace_node != .none or | |
| 1153 | var_decl.ast.section_node != .none or | |
| 1154 | var_decl.ast.init_node != .none)) | |
| 1159 | 1155 | Space.space |
| 1160 | 1156 | else |
| 1161 | 1157 | Space.none; |
| ... | ... | @@ -1165,26 +1161,26 @@ fn renderVarDeclWithoutFixups( |
| 1165 | 1161 | return renderIdentifier(r, var_decl.ast.mut_token + 1, space, .preserve_when_shadowing); // name |
| 1166 | 1162 | } |
| 1167 | 1163 | |
| 1168 | if (var_decl.ast.type_node != 0) { | |
| 1164 | if (var_decl.ast.type_node.unwrap()) |type_node| { | |
| 1169 | 1165 | try renderToken(r, var_decl.ast.mut_token + 2, Space.space); // : |
| 1170 | if (var_decl.ast.align_node != 0 or var_decl.ast.addrspace_node != 0 or | |
| 1171 | var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) | |
| 1166 | if (var_decl.ast.align_node != .none or var_decl.ast.addrspace_node != .none or | |
| 1167 | var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) | |
| 1172 | 1168 | { |
| 1173 | try renderExpression(r, var_decl.ast.type_node, .space); | |
| 1169 | try renderExpression(r, type_node, .space); | |
| 1174 | 1170 | } else { |
| 1175 | return renderExpression(r, var_decl.ast.type_node, space); | |
| 1171 | return renderExpression(r, type_node, space); | |
| 1176 | 1172 | } |
| 1177 | 1173 | } |
| 1178 | 1174 | |
| 1179 | if (var_decl.ast.align_node != 0) { | |
| 1180 | const lparen = tree.firstToken(var_decl.ast.align_node) - 1; | |
| 1175 | if (var_decl.ast.align_node.unwrap()) |align_node| { | |
| 1176 | const lparen = tree.firstToken(align_node) - 1; | |
| 1181 | 1177 | const align_kw = lparen - 1; |
| 1182 | const rparen = tree.lastToken(var_decl.ast.align_node) + 1; | |
| 1178 | const rparen = tree.lastToken(align_node) + 1; | |
| 1183 | 1179 | try renderToken(r, align_kw, Space.none); // align |
| 1184 | 1180 | try renderToken(r, lparen, Space.none); // ( |
| 1185 | try renderExpression(r, var_decl.ast.align_node, Space.none); | |
| 1186 | if (var_decl.ast.addrspace_node != 0 or var_decl.ast.section_node != 0 or | |
| 1187 | var_decl.ast.init_node != 0) | |
| 1181 | try renderExpression(r, align_node, Space.none); | |
| 1182 | if (var_decl.ast.addrspace_node != .none or var_decl.ast.section_node != .none or | |
| 1183 | var_decl.ast.init_node != .none) | |
| 1188 | 1184 | { |
| 1189 | 1185 | try renderToken(r, rparen, .space); // ) |
| 1190 | 1186 | } else { |
| ... | ... | @@ -1192,14 +1188,14 @@ fn renderVarDeclWithoutFixups( |
| 1192 | 1188 | } |
| 1193 | 1189 | } |
| 1194 | 1190 | |
| 1195 | if (var_decl.ast.addrspace_node != 0) { | |
| 1196 | const lparen = tree.firstToken(var_decl.ast.addrspace_node) - 1; | |
| 1191 | if (var_decl.ast.addrspace_node.unwrap()) |addrspace_node| { | |
| 1192 | const lparen = tree.firstToken(addrspace_node) - 1; | |
| 1197 | 1193 | const addrspace_kw = lparen - 1; |
| 1198 | const rparen = tree.lastToken(var_decl.ast.addrspace_node) + 1; | |
| 1194 | const rparen = tree.lastToken(addrspace_node) + 1; | |
| 1199 | 1195 | try renderToken(r, addrspace_kw, Space.none); // addrspace |
| 1200 | 1196 | try renderToken(r, lparen, Space.none); // ( |
| 1201 | try renderExpression(r, var_decl.ast.addrspace_node, Space.none); | |
| 1202 | if (var_decl.ast.section_node != 0 or var_decl.ast.init_node != 0) { | |
| 1197 | try renderExpression(r, addrspace_node, Space.none); | |
| 1198 | if (var_decl.ast.section_node != .none or var_decl.ast.init_node != .none) { | |
| 1203 | 1199 | try renderToken(r, rparen, .space); // ) |
| 1204 | 1200 | } else { |
| 1205 | 1201 | try renderToken(r, rparen, .none); // ) |
| ... | ... | @@ -1207,27 +1203,27 @@ fn renderVarDeclWithoutFixups( |
| 1207 | 1203 | } |
| 1208 | 1204 | } |
| 1209 | 1205 | |
| 1210 | if (var_decl.ast.section_node != 0) { | |
| 1211 | const lparen = tree.firstToken(var_decl.ast.section_node) - 1; | |
| 1206 | if (var_decl.ast.section_node.unwrap()) |section_node| { | |
| 1207 | const lparen = tree.firstToken(section_node) - 1; | |
| 1212 | 1208 | const section_kw = lparen - 1; |
| 1213 | const rparen = tree.lastToken(var_decl.ast.section_node) + 1; | |
| 1209 | const rparen = tree.lastToken(section_node) + 1; | |
| 1214 | 1210 | try renderToken(r, section_kw, Space.none); // linksection |
| 1215 | 1211 | try renderToken(r, lparen, Space.none); // ( |
| 1216 | try renderExpression(r, var_decl.ast.section_node, Space.none); | |
| 1217 | if (var_decl.ast.init_node != 0) { | |
| 1212 | try renderExpression(r, section_node, Space.none); | |
| 1213 | if (var_decl.ast.init_node != .none) { | |
| 1218 | 1214 | try renderToken(r, rparen, .space); // ) |
| 1219 | 1215 | } else { |
| 1220 | 1216 | return renderToken(r, rparen, space); // ) |
| 1221 | 1217 | } |
| 1222 | 1218 | } |
| 1223 | 1219 | |
| 1224 | assert(var_decl.ast.init_node != 0); | |
| 1220 | const init_node = var_decl.ast.init_node.unwrap().?; | |
| 1225 | 1221 | |
| 1226 | const eq_token = tree.firstToken(var_decl.ast.init_node) - 1; | |
| 1222 | const eq_token = tree.firstToken(init_node) - 1; | |
| 1227 | 1223 | const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline; |
| 1228 | 1224 | try ais.pushIndent(.after_equals); |
| 1229 | 1225 | try renderToken(r, eq_token, eq_space); // = |
| 1230 | try renderExpression(r, var_decl.ast.init_node, space); // ; | |
| 1226 | try renderExpression(r, init_node, space); // ; | |
| 1231 | 1227 | ais.popIndent(); |
| 1232 | 1228 | } |
| 1233 | 1229 | |
| ... | ... | @@ -1236,7 +1232,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void { |
| 1236 | 1232 | .ast = .{ |
| 1237 | 1233 | .while_token = if_node.ast.if_token, |
| 1238 | 1234 | .cond_expr = if_node.ast.cond_expr, |
| 1239 | .cont_expr = 0, | |
| 1235 | .cont_expr = .none, | |
| 1240 | 1236 | .then_expr = if_node.ast.then_expr, |
| 1241 | 1237 | .else_expr = if_node.ast.else_expr, |
| 1242 | 1238 | }, |
| ... | ... | @@ -1252,7 +1248,6 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void { |
| 1252 | 1248 | /// respective values set to null. |
| 1253 | 1249 | fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void { |
| 1254 | 1250 | const tree = r.tree; |
| 1255 | const token_tags = tree.tokens.items(.tag); | |
| 1256 | 1251 | |
| 1257 | 1252 | if (while_node.label_token) |label| { |
| 1258 | 1253 | try renderIdentifier(r, label, .none, .eagerly_unquote); // label |
| ... | ... | @@ -1273,7 +1268,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1273 | 1268 | try renderToken(r, last_prefix_token, .space); |
| 1274 | 1269 | try renderToken(r, payload_token - 1, .none); // | |
| 1275 | 1270 | const ident = blk: { |
| 1276 | if (token_tags[payload_token] == .asterisk) { | |
| 1271 | if (tree.tokenTag(payload_token) == .asterisk) { | |
| 1277 | 1272 | try renderToken(r, payload_token, .none); // * |
| 1278 | 1273 | break :blk payload_token + 1; |
| 1279 | 1274 | } else { |
| ... | ... | @@ -1282,7 +1277,7 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1282 | 1277 | }; |
| 1283 | 1278 | try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier |
| 1284 | 1279 | const pipe = blk: { |
| 1285 | if (token_tags[ident + 1] == .comma) { | |
| 1280 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 1286 | 1281 | try renderToken(r, ident + 1, .space); // , |
| 1287 | 1282 | try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // index |
| 1288 | 1283 | break :blk ident + 3; |
| ... | ... | @@ -1293,13 +1288,13 @@ fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void |
| 1293 | 1288 | last_prefix_token = pipe; |
| 1294 | 1289 | } |
| 1295 | 1290 | |
| 1296 | if (while_node.ast.cont_expr != 0) { | |
| 1291 | if (while_node.ast.cont_expr.unwrap()) |cont_expr| { | |
| 1297 | 1292 | try renderToken(r, last_prefix_token, .space); |
| 1298 | const lparen = tree.firstToken(while_node.ast.cont_expr) - 1; | |
| 1293 | const lparen = tree.firstToken(cont_expr) - 1; | |
| 1299 | 1294 | try renderToken(r, lparen - 1, .space); // : |
| 1300 | 1295 | try renderToken(r, lparen, .none); // lparen |
| 1301 | try renderExpression(r, while_node.ast.cont_expr, .none); | |
| 1302 | last_prefix_token = tree.lastToken(while_node.ast.cont_expr) + 1; // rparen | |
| 1296 | try renderExpression(r, cont_expr, .none); | |
| 1297 | last_prefix_token = tree.lastToken(cont_expr) + 1; // rparen | |
| 1303 | 1298 | } |
| 1304 | 1299 | |
| 1305 | 1300 | try renderThenElse( |
| ... | ... | @@ -1317,15 +1312,14 @@ fn renderThenElse( |
| 1317 | 1312 | r: *Render, |
| 1318 | 1313 | last_prefix_token: Ast.TokenIndex, |
| 1319 | 1314 | then_expr: Ast.Node.Index, |
| 1320 | else_token: Ast.TokenIndex, | |
| 1315 | else_token: ?Ast.TokenIndex, | |
| 1321 | 1316 | maybe_error_token: ?Ast.TokenIndex, |
| 1322 | else_expr: Ast.Node.Index, | |
| 1317 | opt_else_expr: Ast.Node.OptionalIndex, | |
| 1323 | 1318 | space: Space, |
| 1324 | 1319 | ) Error!void { |
| 1325 | 1320 | const tree = r.tree; |
| 1326 | 1321 | const ais = r.ais; |
| 1327 | const node_tags = tree.nodes.items(.tag); | |
| 1328 | const then_expr_is_block = nodeIsBlock(node_tags[then_expr]); | |
| 1322 | const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr)); | |
| 1329 | 1323 | const indent_then_expr = !then_expr_is_block and |
| 1330 | 1324 | !tree.tokensOnSameLine(last_prefix_token, tree.firstToken(then_expr)); |
| 1331 | 1325 | |
| ... | ... | @@ -1341,7 +1335,7 @@ fn renderThenElse( |
| 1341 | 1335 | try renderToken(r, last_prefix_token, .space); |
| 1342 | 1336 | } |
| 1343 | 1337 | |
| 1344 | if (else_expr != 0) { | |
| 1338 | if (opt_else_expr.unwrap()) |else_expr| { | |
| 1345 | 1339 | if (indent_then_expr) { |
| 1346 | 1340 | try renderExpression(r, then_expr, .newline); |
| 1347 | 1341 | } else { |
| ... | ... | @@ -1350,18 +1344,18 @@ fn renderThenElse( |
| 1350 | 1344 | |
| 1351 | 1345 | if (indent_then_expr) ais.popIndent(); |
| 1352 | 1346 | |
| 1353 | var last_else_token = else_token; | |
| 1347 | var last_else_token = else_token.?; | |
| 1354 | 1348 | |
| 1355 | 1349 | if (maybe_error_token) |error_token| { |
| 1356 | try renderToken(r, else_token, .space); // else | |
| 1350 | try renderToken(r, last_else_token, .space); // else | |
| 1357 | 1351 | try renderToken(r, error_token - 1, .none); // | |
| 1358 | 1352 | try renderIdentifier(r, error_token, .none, .preserve_when_shadowing); // identifier |
| 1359 | 1353 | last_else_token = error_token + 1; // | |
| 1360 | 1354 | } |
| 1361 | 1355 | |
| 1362 | 1356 | const indent_else_expr = indent_then_expr and |
| 1363 | !nodeIsBlock(node_tags[else_expr]) and | |
| 1364 | !nodeIsIfForWhileSwitch(node_tags[else_expr]); | |
| 1357 | !nodeIsBlock(tree.nodeTag(else_expr)) and | |
| 1358 | !nodeIsIfForWhileSwitch(tree.nodeTag(else_expr)); | |
| 1365 | 1359 | if (indent_else_expr) { |
| 1366 | 1360 | try ais.pushIndent(.normal); |
| 1367 | 1361 | try renderToken(r, last_else_token, .newline); |
| ... | ... | @@ -1398,21 +1392,21 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void { |
| 1398 | 1392 | |
| 1399 | 1393 | var cur = for_node.payload_token; |
| 1400 | 1394 | const pipe = std.mem.indexOfScalarPos(std.zig.Token.Tag, token_tags, cur, .pipe).?; |
| 1401 | if (token_tags[pipe - 1] == .comma) { | |
| 1395 | if (tree.tokenTag(@intCast(pipe - 1)) == .comma) { | |
| 1402 | 1396 | try ais.pushIndent(.normal); |
| 1403 | 1397 | try renderToken(r, cur - 1, .newline); // | |
| 1404 | 1398 | while (true) { |
| 1405 | if (token_tags[cur] == .asterisk) { | |
| 1399 | if (tree.tokenTag(cur) == .asterisk) { | |
| 1406 | 1400 | try renderToken(r, cur, .none); // * |
| 1407 | 1401 | cur += 1; |
| 1408 | 1402 | } |
| 1409 | 1403 | try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier |
| 1410 | 1404 | cur += 1; |
| 1411 | if (token_tags[cur] == .comma) { | |
| 1405 | if (tree.tokenTag(cur) == .comma) { | |
| 1412 | 1406 | try renderToken(r, cur, .newline); // , |
| 1413 | 1407 | cur += 1; |
| 1414 | 1408 | } |
| 1415 | if (token_tags[cur] == .pipe) { | |
| 1409 | if (tree.tokenTag(cur) == .pipe) { | |
| 1416 | 1410 | break; |
| 1417 | 1411 | } |
| 1418 | 1412 | } |
| ... | ... | @@ -1420,17 +1414,17 @@ fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void { |
| 1420 | 1414 | } else { |
| 1421 | 1415 | try renderToken(r, cur - 1, .none); // | |
| 1422 | 1416 | while (true) { |
| 1423 | if (token_tags[cur] == .asterisk) { | |
| 1417 | if (tree.tokenTag(cur) == .asterisk) { | |
| 1424 | 1418 | try renderToken(r, cur, .none); // * |
| 1425 | 1419 | cur += 1; |
| 1426 | 1420 | } |
| 1427 | 1421 | try renderIdentifier(r, cur, .none, .preserve_when_shadowing); // identifier |
| 1428 | 1422 | cur += 1; |
| 1429 | if (token_tags[cur] == .comma) { | |
| 1423 | if (tree.tokenTag(cur) == .comma) { | |
| 1430 | 1424 | try renderToken(r, cur, .space); // , |
| 1431 | 1425 | cur += 1; |
| 1432 | 1426 | } |
| 1433 | if (token_tags[cur] == .pipe) { | |
| 1427 | if (tree.tokenTag(cur) == .pipe) { | |
| 1434 | 1428 | break; |
| 1435 | 1429 | } |
| 1436 | 1430 | } |
| ... | ... | @@ -1456,7 +1450,7 @@ fn renderContainerField( |
| 1456 | 1450 | const tree = r.tree; |
| 1457 | 1451 | const ais = r.ais; |
| 1458 | 1452 | var field = field_param; |
| 1459 | if (container != .tuple) field.convertToNonTupleLike(tree.nodes); | |
| 1453 | if (container != .tuple) field.convertToNonTupleLike(&tree); | |
| 1460 | 1454 | const quote: QuoteBehavior = switch (container) { |
| 1461 | 1455 | .@"enum" => .eagerly_unquote_except_underscore, |
| 1462 | 1456 | .tuple, .other => .eagerly_unquote, |
| ... | ... | @@ -1465,67 +1459,74 @@ fn renderContainerField( |
| 1465 | 1459 | if (field.comptime_token) |t| { |
| 1466 | 1460 | try renderToken(r, t, .space); // comptime |
| 1467 | 1461 | } |
| 1468 | if (field.ast.type_expr == 0 and field.ast.value_expr == 0) { | |
| 1469 | if (field.ast.align_expr != 0) { | |
| 1462 | if (field.ast.type_expr == .none and field.ast.value_expr == .none) { | |
| 1463 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1470 | 1464 | try renderIdentifier(r, field.ast.main_token, .space, quote); // name |
| 1471 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1465 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1472 | 1466 | const align_kw = lparen_token - 1; |
| 1473 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1467 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1474 | 1468 | try renderToken(r, align_kw, .none); // align |
| 1475 | 1469 | try renderToken(r, lparen_token, .none); // ( |
| 1476 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1470 | try renderExpression(r, align_expr, .none); // alignment | |
| 1477 | 1471 | return renderToken(r, rparen_token, .space); // ) |
| 1478 | 1472 | } |
| 1479 | 1473 | return renderIdentifierComma(r, field.ast.main_token, space, quote); // name |
| 1480 | 1474 | } |
| 1481 | if (field.ast.type_expr != 0 and field.ast.value_expr == 0) { | |
| 1475 | if (field.ast.type_expr != .none and field.ast.value_expr == .none) { | |
| 1476 | const type_expr = field.ast.type_expr.unwrap().?; | |
| 1482 | 1477 | if (!field.ast.tuple_like) { |
| 1483 | 1478 | try renderIdentifier(r, field.ast.main_token, .none, quote); // name |
| 1484 | 1479 | try renderToken(r, field.ast.main_token + 1, .space); // : |
| 1485 | 1480 | } |
| 1486 | 1481 | |
| 1487 | if (field.ast.align_expr != 0) { | |
| 1488 | try renderExpression(r, field.ast.type_expr, .space); // type | |
| 1489 | const align_token = tree.firstToken(field.ast.align_expr) - 2; | |
| 1482 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1483 | try renderExpression(r, type_expr, .space); // type | |
| 1484 | const align_token = tree.firstToken(align_expr) - 2; | |
| 1490 | 1485 | try renderToken(r, align_token, .none); // align |
| 1491 | 1486 | try renderToken(r, align_token + 1, .none); // ( |
| 1492 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1493 | const rparen = tree.lastToken(field.ast.align_expr) + 1; | |
| 1487 | try renderExpression(r, align_expr, .none); // alignment | |
| 1488 | const rparen = tree.lastToken(align_expr) + 1; | |
| 1494 | 1489 | return renderTokenComma(r, rparen, space); // ) |
| 1495 | 1490 | } else { |
| 1496 | return renderExpressionComma(r, field.ast.type_expr, space); // type | |
| 1491 | return renderExpressionComma(r, type_expr, space); // type | |
| 1497 | 1492 | } |
| 1498 | 1493 | } |
| 1499 | if (field.ast.type_expr == 0 and field.ast.value_expr != 0) { | |
| 1494 | if (field.ast.type_expr == .none and field.ast.value_expr != .none) { | |
| 1495 | const value_expr = field.ast.value_expr.unwrap().?; | |
| 1496 | ||
| 1500 | 1497 | try renderIdentifier(r, field.ast.main_token, .space, quote); // name |
| 1501 | if (field.ast.align_expr != 0) { | |
| 1502 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1498 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1499 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1503 | 1500 | const align_kw = lparen_token - 1; |
| 1504 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1501 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1505 | 1502 | try renderToken(r, align_kw, .none); // align |
| 1506 | 1503 | try renderToken(r, lparen_token, .none); // ( |
| 1507 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1504 | try renderExpression(r, align_expr, .none); // alignment | |
| 1508 | 1505 | try renderToken(r, rparen_token, .space); // ) |
| 1509 | 1506 | } |
| 1510 | 1507 | try renderToken(r, field.ast.main_token + 1, .space); // = |
| 1511 | return renderExpressionComma(r, field.ast.value_expr, space); // value | |
| 1508 | return renderExpressionComma(r, value_expr, space); // value | |
| 1512 | 1509 | } |
| 1513 | 1510 | if (!field.ast.tuple_like) { |
| 1514 | 1511 | try renderIdentifier(r, field.ast.main_token, .none, quote); // name |
| 1515 | 1512 | try renderToken(r, field.ast.main_token + 1, .space); // : |
| 1516 | 1513 | } |
| 1517 | try renderExpression(r, field.ast.type_expr, .space); // type | |
| 1518 | 1514 | |
| 1519 | if (field.ast.align_expr != 0) { | |
| 1520 | const lparen_token = tree.firstToken(field.ast.align_expr) - 1; | |
| 1515 | const type_expr = field.ast.type_expr.unwrap().?; | |
| 1516 | const value_expr = field.ast.value_expr.unwrap().?; | |
| 1517 | ||
| 1518 | try renderExpression(r, type_expr, .space); // type | |
| 1519 | ||
| 1520 | if (field.ast.align_expr.unwrap()) |align_expr| { | |
| 1521 | const lparen_token = tree.firstToken(align_expr) - 1; | |
| 1521 | 1522 | const align_kw = lparen_token - 1; |
| 1522 | const rparen_token = tree.lastToken(field.ast.align_expr) + 1; | |
| 1523 | const rparen_token = tree.lastToken(align_expr) + 1; | |
| 1523 | 1524 | try renderToken(r, align_kw, .none); // align |
| 1524 | 1525 | try renderToken(r, lparen_token, .none); // ( |
| 1525 | try renderExpression(r, field.ast.align_expr, .none); // alignment | |
| 1526 | try renderExpression(r, align_expr, .none); // alignment | |
| 1526 | 1527 | try renderToken(r, rparen_token, .space); // ) |
| 1527 | 1528 | } |
| 1528 | const eq_token = tree.firstToken(field.ast.value_expr) - 1; | |
| 1529 | const eq_token = tree.firstToken(value_expr) - 1; | |
| 1529 | 1530 | const eq_space: Space = if (tree.tokensOnSameLine(eq_token, eq_token + 1)) .space else .newline; |
| 1530 | 1531 | |
| 1531 | 1532 | try ais.pushIndent(.after_equals); |
| ... | ... | @@ -1533,19 +1534,18 @@ fn renderContainerField( |
| 1533 | 1534 | |
| 1534 | 1535 | if (eq_space == .space) { |
| 1535 | 1536 | ais.popIndent(); |
| 1536 | try renderExpressionComma(r, field.ast.value_expr, space); // value | |
| 1537 | try renderExpressionComma(r, value_expr, space); // value | |
| 1537 | 1538 | return; |
| 1538 | 1539 | } |
| 1539 | 1540 | |
| 1540 | const token_tags = tree.tokens.items(.tag); | |
| 1541 | const maybe_comma = tree.lastToken(field.ast.value_expr) + 1; | |
| 1541 | const maybe_comma = tree.lastToken(value_expr) + 1; | |
| 1542 | 1542 | |
| 1543 | if (token_tags[maybe_comma] == .comma) { | |
| 1544 | try renderExpression(r, field.ast.value_expr, .none); // value | |
| 1543 | if (tree.tokenTag(maybe_comma) == .comma) { | |
| 1544 | try renderExpression(r, value_expr, .none); // value | |
| 1545 | 1545 | ais.popIndent(); |
| 1546 | 1546 | try renderToken(r, maybe_comma, .newline); |
| 1547 | 1547 | } else { |
| 1548 | try renderExpression(r, field.ast.value_expr, space); // value | |
| 1548 | try renderExpression(r, value_expr, space); // value | |
| 1549 | 1549 | ais.popIndent(); |
| 1550 | 1550 | } |
| 1551 | 1551 | } |
| ... | ... | @@ -1558,8 +1558,6 @@ fn renderBuiltinCall( |
| 1558 | 1558 | ) Error!void { |
| 1559 | 1559 | const tree = r.tree; |
| 1560 | 1560 | const ais = r.ais; |
| 1561 | const token_tags = tree.tokens.items(.tag); | |
| 1562 | const main_tokens = tree.nodes.items(.main_token); | |
| 1563 | 1561 | |
| 1564 | 1562 | try renderToken(r, builtin_token, .none); // @name |
| 1565 | 1563 | |
| ... | ... | @@ -1572,8 +1570,8 @@ fn renderBuiltinCall( |
| 1572 | 1570 | const slice = tree.tokenSlice(builtin_token); |
| 1573 | 1571 | if (mem.eql(u8, slice, "@import")) f: { |
| 1574 | 1572 | const param = params[0]; |
| 1575 | const str_lit_token = main_tokens[param]; | |
| 1576 | assert(token_tags[str_lit_token] == .string_literal); | |
| 1573 | const str_lit_token = tree.nodeMainToken(param); | |
| 1574 | assert(tree.tokenTag(str_lit_token) == .string_literal); | |
| 1577 | 1575 | const token_bytes = tree.tokenSlice(str_lit_token); |
| 1578 | 1576 | const imported_string = std.zig.string_literal.parseAlloc(r.gpa, token_bytes) catch |err| switch (err) { |
| 1579 | 1577 | error.OutOfMemory => return error.OutOfMemory, |
| ... | ... | @@ -1592,13 +1590,13 @@ fn renderBuiltinCall( |
| 1592 | 1590 | const last_param = params[params.len - 1]; |
| 1593 | 1591 | const after_last_param_token = tree.lastToken(last_param) + 1; |
| 1594 | 1592 | |
| 1595 | if (token_tags[after_last_param_token] != .comma) { | |
| 1593 | if (tree.tokenTag(after_last_param_token) != .comma) { | |
| 1596 | 1594 | // Render all on one line, no trailing comma. |
| 1597 | 1595 | try renderToken(r, builtin_token + 1, .none); // ( |
| 1598 | 1596 | |
| 1599 | 1597 | for (params, 0..) |param_node, i| { |
| 1600 | 1598 | const first_param_token = tree.firstToken(param_node); |
| 1601 | if (token_tags[first_param_token] == .multiline_string_literal_line or | |
| 1599 | if (tree.tokenTag(first_param_token) == .multiline_string_literal_line or | |
| 1602 | 1600 | hasSameLineComment(tree, first_param_token - 1)) |
| 1603 | 1601 | { |
| 1604 | 1602 | try ais.pushIndent(.normal); |
| ... | ... | @@ -1633,11 +1631,9 @@ fn renderBuiltinCall( |
| 1633 | 1631 | fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void { |
| 1634 | 1632 | const tree = r.tree; |
| 1635 | 1633 | const ais = r.ais; |
| 1636 | const token_tags = tree.tokens.items(.tag); | |
| 1637 | const token_starts = tree.tokens.items(.start); | |
| 1638 | 1634 | |
| 1639 | 1635 | const after_fn_token = fn_proto.ast.fn_token + 1; |
| 1640 | const lparen = if (token_tags[after_fn_token] == .identifier) blk: { | |
| 1636 | const lparen = if (tree.tokenTag(after_fn_token) == .identifier) blk: { | |
| 1641 | 1637 | try renderToken(r, fn_proto.ast.fn_token, .space); // fn |
| 1642 | 1638 | try renderIdentifier(r, after_fn_token, .none, .preserve_when_shadowing); // name |
| 1643 | 1639 | break :blk after_fn_token + 1; |
| ... | ... | @@ -1645,41 +1641,42 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1645 | 1641 | try renderToken(r, fn_proto.ast.fn_token, .space); // fn |
| 1646 | 1642 | break :blk fn_proto.ast.fn_token + 1; |
| 1647 | 1643 | }; |
| 1648 | assert(token_tags[lparen] == .l_paren); | |
| 1644 | assert(tree.tokenTag(lparen) == .l_paren); | |
| 1649 | 1645 | |
| 1650 | const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1; | |
| 1646 | const return_type = fn_proto.ast.return_type.unwrap().?; | |
| 1647 | const maybe_bang = tree.firstToken(return_type) - 1; | |
| 1651 | 1648 | const rparen = blk: { |
| 1652 | 1649 | // These may appear in any order, so we have to check the token_starts array |
| 1653 | 1650 | // to find out which is first. |
| 1654 | var rparen = if (token_tags[maybe_bang] == .bang) maybe_bang - 1 else maybe_bang; | |
| 1655 | var smallest_start = token_starts[maybe_bang]; | |
| 1656 | if (fn_proto.ast.align_expr != 0) { | |
| 1657 | const tok = tree.firstToken(fn_proto.ast.align_expr) - 3; | |
| 1658 | const start = token_starts[tok]; | |
| 1651 | var rparen = if (tree.tokenTag(maybe_bang) == .bang) maybe_bang - 1 else maybe_bang; | |
| 1652 | var smallest_start = tree.tokenStart(maybe_bang); | |
| 1653 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1654 | const tok = tree.firstToken(align_expr) - 3; | |
| 1655 | const start = tree.tokenStart(tok); | |
| 1659 | 1656 | if (start < smallest_start) { |
| 1660 | 1657 | rparen = tok; |
| 1661 | 1658 | smallest_start = start; |
| 1662 | 1659 | } |
| 1663 | 1660 | } |
| 1664 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1665 | const tok = tree.firstToken(fn_proto.ast.addrspace_expr) - 3; | |
| 1666 | const start = token_starts[tok]; | |
| 1661 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1662 | const tok = tree.firstToken(addrspace_expr) - 3; | |
| 1663 | const start = tree.tokenStart(tok); | |
| 1667 | 1664 | if (start < smallest_start) { |
| 1668 | 1665 | rparen = tok; |
| 1669 | 1666 | smallest_start = start; |
| 1670 | 1667 | } |
| 1671 | 1668 | } |
| 1672 | if (fn_proto.ast.section_expr != 0) { | |
| 1673 | const tok = tree.firstToken(fn_proto.ast.section_expr) - 3; | |
| 1674 | const start = token_starts[tok]; | |
| 1669 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1670 | const tok = tree.firstToken(section_expr) - 3; | |
| 1671 | const start = tree.tokenStart(tok); | |
| 1675 | 1672 | if (start < smallest_start) { |
| 1676 | 1673 | rparen = tok; |
| 1677 | 1674 | smallest_start = start; |
| 1678 | 1675 | } |
| 1679 | 1676 | } |
| 1680 | if (fn_proto.ast.callconv_expr != 0) { | |
| 1681 | const tok = tree.firstToken(fn_proto.ast.callconv_expr) - 3; | |
| 1682 | const start = token_starts[tok]; | |
| 1677 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 1678 | const tok = tree.firstToken(callconv_expr) - 3; | |
| 1679 | const start = tree.tokenStart(tok); | |
| 1683 | 1680 | if (start < smallest_start) { |
| 1684 | 1681 | rparen = tok; |
| 1685 | 1682 | smallest_start = start; |
| ... | ... | @@ -1687,11 +1684,11 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1687 | 1684 | } |
| 1688 | 1685 | break :blk rparen; |
| 1689 | 1686 | }; |
| 1690 | assert(token_tags[rparen] == .r_paren); | |
| 1687 | assert(tree.tokenTag(rparen) == .r_paren); | |
| 1691 | 1688 | |
| 1692 | 1689 | // The params list is a sparse set that does *not* include anytype or ... parameters. |
| 1693 | 1690 | |
| 1694 | const trailing_comma = token_tags[rparen - 1] == .comma; | |
| 1691 | const trailing_comma = tree.tokenTag(rparen - 1) == .comma; | |
| 1695 | 1692 | if (!trailing_comma and !hasComment(tree, lparen, rparen)) { |
| 1696 | 1693 | // Render all on one line, no trailing comma. |
| 1697 | 1694 | try renderToken(r, lparen, .none); // ( |
| ... | ... | @@ -1700,7 +1697,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1700 | 1697 | var last_param_token = lparen; |
| 1701 | 1698 | while (true) { |
| 1702 | 1699 | last_param_token += 1; |
| 1703 | switch (token_tags[last_param_token]) { | |
| 1700 | switch (tree.tokenTag(last_param_token)) { | |
| 1704 | 1701 | .doc_comment => { |
| 1705 | 1702 | try renderToken(r, last_param_token, .newline); |
| 1706 | 1703 | continue; |
| ... | ... | @@ -1725,15 +1722,15 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1725 | 1722 | }, |
| 1726 | 1723 | else => {}, // Parameter type without a name. |
| 1727 | 1724 | } |
| 1728 | if (token_tags[last_param_token] == .identifier and | |
| 1729 | token_tags[last_param_token + 1] == .colon) | |
| 1725 | if (tree.tokenTag(last_param_token) == .identifier and | |
| 1726 | tree.tokenTag(last_param_token + 1) == .colon) | |
| 1730 | 1727 | { |
| 1731 | 1728 | try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name |
| 1732 | last_param_token += 1; | |
| 1729 | last_param_token = last_param_token + 1; | |
| 1733 | 1730 | try renderToken(r, last_param_token, .space); // : |
| 1734 | 1731 | last_param_token += 1; |
| 1735 | 1732 | } |
| 1736 | if (token_tags[last_param_token] == .keyword_anytype) { | |
| 1733 | if (tree.tokenTag(last_param_token) == .keyword_anytype) { | |
| 1737 | 1734 | try renderToken(r, last_param_token, .none); // anytype |
| 1738 | 1735 | continue; |
| 1739 | 1736 | } |
| ... | ... | @@ -1751,7 +1748,7 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1751 | 1748 | var last_param_token = lparen; |
| 1752 | 1749 | while (true) { |
| 1753 | 1750 | last_param_token += 1; |
| 1754 | switch (token_tags[last_param_token]) { | |
| 1751 | switch (tree.tokenTag(last_param_token)) { | |
| 1755 | 1752 | .doc_comment => { |
| 1756 | 1753 | try renderToken(r, last_param_token, .newline); |
| 1757 | 1754 | continue; |
| ... | ... | @@ -1767,24 +1764,24 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1767 | 1764 | .identifier => {}, |
| 1768 | 1765 | .keyword_anytype => { |
| 1769 | 1766 | try renderToken(r, last_param_token, .comma); // anytype |
| 1770 | if (token_tags[last_param_token + 1] == .comma) | |
| 1767 | if (tree.tokenTag(last_param_token + 1) == .comma) | |
| 1771 | 1768 | last_param_token += 1; |
| 1772 | 1769 | continue; |
| 1773 | 1770 | }, |
| 1774 | 1771 | .r_paren => break, |
| 1775 | 1772 | else => {}, // Parameter type without a name. |
| 1776 | 1773 | } |
| 1777 | if (token_tags[last_param_token] == .identifier and | |
| 1778 | token_tags[last_param_token + 1] == .colon) | |
| 1774 | if (tree.tokenTag(last_param_token) == .identifier and | |
| 1775 | tree.tokenTag(last_param_token + 1) == .colon) | |
| 1779 | 1776 | { |
| 1780 | 1777 | try renderIdentifier(r, last_param_token, .none, .preserve_when_shadowing); // name |
| 1781 | 1778 | last_param_token += 1; |
| 1782 | 1779 | try renderToken(r, last_param_token, .space); // : |
| 1783 | 1780 | last_param_token += 1; |
| 1784 | 1781 | } |
| 1785 | if (token_tags[last_param_token] == .keyword_anytype) { | |
| 1782 | if (tree.tokenTag(last_param_token) == .keyword_anytype) { | |
| 1786 | 1783 | try renderToken(r, last_param_token, .comma); // anytype |
| 1787 | if (token_tags[last_param_token + 1] == .comma) | |
| 1784 | if (tree.tokenTag(last_param_token + 1) == .comma) | |
| 1788 | 1785 | last_param_token += 1; |
| 1789 | 1786 | continue; |
| 1790 | 1787 | } |
| ... | ... | @@ -1794,60 +1791,62 @@ fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!voi |
| 1794 | 1791 | try renderExpression(r, param, .comma); |
| 1795 | 1792 | ais.popSpace(); |
| 1796 | 1793 | last_param_token = tree.lastToken(param); |
| 1797 | if (token_tags[last_param_token + 1] == .comma) last_param_token += 1; | |
| 1794 | if (tree.tokenTag(last_param_token + 1) == .comma) last_param_token += 1; | |
| 1798 | 1795 | } |
| 1799 | 1796 | ais.popIndent(); |
| 1800 | 1797 | } |
| 1801 | 1798 | |
| 1802 | 1799 | try renderToken(r, rparen, .space); // ) |
| 1803 | 1800 | |
| 1804 | if (fn_proto.ast.align_expr != 0) { | |
| 1805 | const align_lparen = tree.firstToken(fn_proto.ast.align_expr) - 1; | |
| 1806 | const align_rparen = tree.lastToken(fn_proto.ast.align_expr) + 1; | |
| 1801 | if (fn_proto.ast.align_expr.unwrap()) |align_expr| { | |
| 1802 | const align_lparen = tree.firstToken(align_expr) - 1; | |
| 1803 | const align_rparen = tree.lastToken(align_expr) + 1; | |
| 1807 | 1804 | |
| 1808 | 1805 | try renderToken(r, align_lparen - 1, .none); // align |
| 1809 | 1806 | try renderToken(r, align_lparen, .none); // ( |
| 1810 | try renderExpression(r, fn_proto.ast.align_expr, .none); | |
| 1807 | try renderExpression(r, align_expr, .none); | |
| 1811 | 1808 | try renderToken(r, align_rparen, .space); // ) |
| 1812 | 1809 | } |
| 1813 | 1810 | |
| 1814 | if (fn_proto.ast.addrspace_expr != 0) { | |
| 1815 | const align_lparen = tree.firstToken(fn_proto.ast.addrspace_expr) - 1; | |
| 1816 | const align_rparen = tree.lastToken(fn_proto.ast.addrspace_expr) + 1; | |
| 1811 | if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| { | |
| 1812 | const align_lparen = tree.firstToken(addrspace_expr) - 1; | |
| 1813 | const align_rparen = tree.lastToken(addrspace_expr) + 1; | |
| 1817 | 1814 | |
| 1818 | 1815 | try renderToken(r, align_lparen - 1, .none); // addrspace |
| 1819 | 1816 | try renderToken(r, align_lparen, .none); // ( |
| 1820 | try renderExpression(r, fn_proto.ast.addrspace_expr, .none); | |
| 1817 | try renderExpression(r, addrspace_expr, .none); | |
| 1821 | 1818 | try renderToken(r, align_rparen, .space); // ) |
| 1822 | 1819 | } |
| 1823 | 1820 | |
| 1824 | if (fn_proto.ast.section_expr != 0) { | |
| 1825 | const section_lparen = tree.firstToken(fn_proto.ast.section_expr) - 1; | |
| 1826 | const section_rparen = tree.lastToken(fn_proto.ast.section_expr) + 1; | |
| 1821 | if (fn_proto.ast.section_expr.unwrap()) |section_expr| { | |
| 1822 | const section_lparen = tree.firstToken(section_expr) - 1; | |
| 1823 | const section_rparen = tree.lastToken(section_expr) + 1; | |
| 1827 | 1824 | |
| 1828 | 1825 | try renderToken(r, section_lparen - 1, .none); // section |
| 1829 | 1826 | try renderToken(r, section_lparen, .none); // ( |
| 1830 | try renderExpression(r, fn_proto.ast.section_expr, .none); | |
| 1827 | try renderExpression(r, section_expr, .none); | |
| 1831 | 1828 | try renderToken(r, section_rparen, .space); // ) |
| 1832 | 1829 | } |
| 1833 | 1830 | |
| 1834 | // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE | |
| 1835 | const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodes.items(.main_token)[fn_proto.ast.callconv_expr])); | |
| 1836 | const is_declaration = fn_proto.name_token != null; | |
| 1837 | if (fn_proto.ast.callconv_expr != 0 and !(is_declaration and is_callconv_inline)) { | |
| 1838 | const callconv_lparen = tree.firstToken(fn_proto.ast.callconv_expr) - 1; | |
| 1839 | const callconv_rparen = tree.lastToken(fn_proto.ast.callconv_expr) + 1; | |
| 1831 | if (fn_proto.ast.callconv_expr.unwrap()) |callconv_expr| { | |
| 1832 | // Keep in sync with logic in `renderMember`. Search this file for the marker PROMOTE_CALLCONV_INLINE | |
| 1833 | const is_callconv_inline = mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr))); | |
| 1834 | const is_declaration = fn_proto.name_token != null; | |
| 1835 | if (!(is_declaration and is_callconv_inline)) { | |
| 1836 | const callconv_lparen = tree.firstToken(callconv_expr) - 1; | |
| 1837 | const callconv_rparen = tree.lastToken(callconv_expr) + 1; | |
| 1840 | 1838 | |
| 1841 | try renderToken(r, callconv_lparen - 1, .none); // callconv | |
| 1842 | try renderToken(r, callconv_lparen, .none); // ( | |
| 1843 | try renderExpression(r, fn_proto.ast.callconv_expr, .none); | |
| 1844 | try renderToken(r, callconv_rparen, .space); // ) | |
| 1839 | try renderToken(r, callconv_lparen - 1, .none); // callconv | |
| 1840 | try renderToken(r, callconv_lparen, .none); // ( | |
| 1841 | try renderExpression(r, callconv_expr, .none); | |
| 1842 | try renderToken(r, callconv_rparen, .space); // ) | |
| 1843 | } | |
| 1845 | 1844 | } |
| 1846 | 1845 | |
| 1847 | if (token_tags[maybe_bang] == .bang) { | |
| 1846 | if (tree.tokenTag(maybe_bang) == .bang) { | |
| 1848 | 1847 | try renderToken(r, maybe_bang, .none); // ! |
| 1849 | 1848 | } |
| 1850 | return renderExpression(r, fn_proto.ast.return_type, space); | |
| 1849 | return renderExpression(r, return_type, space); | |
| 1851 | 1850 | } |
| 1852 | 1851 | |
| 1853 | 1852 | fn renderSwitchCase( |
| ... | ... | @@ -1857,9 +1856,7 @@ fn renderSwitchCase( |
| 1857 | 1856 | ) Error!void { |
| 1858 | 1857 | const ais = r.ais; |
| 1859 | 1858 | const tree = r.tree; |
| 1860 | const node_tags = tree.nodes.items(.tag); | |
| 1861 | const token_tags = tree.tokens.items(.tag); | |
| 1862 | const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .comma; | |
| 1859 | const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma; | |
| 1863 | 1860 | const has_comment_before_arrow = blk: { |
| 1864 | 1861 | if (switch_case.ast.values.len == 0) break :blk false; |
| 1865 | 1862 | break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token); |
| ... | ... | @@ -1886,7 +1883,7 @@ fn renderSwitchCase( |
| 1886 | 1883 | } |
| 1887 | 1884 | |
| 1888 | 1885 | // Render the arrow and everything after it |
| 1889 | const pre_target_space = if (node_tags[switch_case.ast.target_expr] == .multiline_string_literal) | |
| 1886 | const pre_target_space = if (tree.nodeTag(switch_case.ast.target_expr) == .multiline_string_literal) | |
| 1890 | 1887 | // Newline gets inserted when rendering the target expr. |
| 1891 | 1888 | Space.none |
| 1892 | 1889 | else |
| ... | ... | @@ -1896,12 +1893,12 @@ fn renderSwitchCase( |
| 1896 | 1893 | |
| 1897 | 1894 | if (switch_case.payload_token) |payload_token| { |
| 1898 | 1895 | try renderToken(r, payload_token - 1, .none); // pipe |
| 1899 | const ident = payload_token + @intFromBool(token_tags[payload_token] == .asterisk); | |
| 1900 | if (token_tags[payload_token] == .asterisk) { | |
| 1896 | const ident = payload_token + @intFromBool(tree.tokenTag(payload_token) == .asterisk); | |
| 1897 | if (tree.tokenTag(payload_token) == .asterisk) { | |
| 1901 | 1898 | try renderToken(r, payload_token, .none); // asterisk |
| 1902 | 1899 | } |
| 1903 | 1900 | try renderIdentifier(r, ident, .none, .preserve_when_shadowing); // identifier |
| 1904 | if (token_tags[ident + 1] == .comma) { | |
| 1901 | if (tree.tokenTag(ident + 1) == .comma) { | |
| 1905 | 1902 | try renderToken(r, ident + 1, .space); // , |
| 1906 | 1903 | try renderIdentifier(r, ident + 2, .none, .preserve_when_shadowing); // identifier |
| 1907 | 1904 | try renderToken(r, ident + 3, pre_target_space); // pipe |
| ... | ... | @@ -1921,12 +1918,9 @@ fn renderBlock( |
| 1921 | 1918 | ) Error!void { |
| 1922 | 1919 | const tree = r.tree; |
| 1923 | 1920 | const ais = r.ais; |
| 1924 | const token_tags = tree.tokens.items(.tag); | |
| 1925 | const lbrace = tree.nodes.items(.main_token)[block_node]; | |
| 1921 | const lbrace = tree.nodeMainToken(block_node); | |
| 1926 | 1922 | |
| 1927 | if (token_tags[lbrace - 1] == .colon and | |
| 1928 | token_tags[lbrace - 2] == .identifier) | |
| 1929 | { | |
| 1923 | if (tree.isTokenPrecededByTags(lbrace, &.{ .identifier, .colon })) { | |
| 1930 | 1924 | try renderIdentifier(r, lbrace - 2, .none, .eagerly_unquote); // identifier |
| 1931 | 1925 | try renderToken(r, lbrace - 1, .space); // : |
| 1932 | 1926 | } |
| ... | ... | @@ -1948,13 +1942,12 @@ fn finishRenderBlock( |
| 1948 | 1942 | space: Space, |
| 1949 | 1943 | ) Error!void { |
| 1950 | 1944 | const tree = r.tree; |
| 1951 | const node_tags = tree.nodes.items(.tag); | |
| 1952 | 1945 | const ais = r.ais; |
| 1953 | 1946 | for (statements, 0..) |stmt, i| { |
| 1954 | 1947 | if (i != 0) try renderExtraNewline(r, stmt); |
| 1955 | 1948 | if (r.fixups.omit_nodes.contains(stmt)) continue; |
| 1956 | 1949 | try ais.pushSpace(.semicolon); |
| 1957 | switch (node_tags[stmt]) { | |
| 1950 | switch (tree.nodeTag(stmt)) { | |
| 1958 | 1951 | .global_var_decl, |
| 1959 | 1952 | .local_var_decl, |
| 1960 | 1953 | .simple_var_decl, |
| ... | ... | @@ -1978,12 +1971,13 @@ fn renderStructInit( |
| 1978 | 1971 | ) Error!void { |
| 1979 | 1972 | const tree = r.tree; |
| 1980 | 1973 | const ais = r.ais; |
| 1981 | const token_tags = tree.tokens.items(.tag); | |
| 1982 | if (struct_init.ast.type_expr == 0) { | |
| 1983 | try renderToken(r, struct_init.ast.lbrace - 1, .none); // . | |
| 1974 | ||
| 1975 | if (struct_init.ast.type_expr.unwrap()) |type_expr| { | |
| 1976 | try renderExpression(r, type_expr, .none); // T | |
| 1984 | 1977 | } else { |
| 1985 | try renderExpression(r, struct_init.ast.type_expr, .none); // T | |
| 1978 | try renderToken(r, struct_init.ast.lbrace - 1, .none); // . | |
| 1986 | 1979 | } |
| 1980 | ||
| 1987 | 1981 | if (struct_init.ast.fields.len == 0) { |
| 1988 | 1982 | try ais.pushIndent(.normal); |
| 1989 | 1983 | try renderToken(r, struct_init.ast.lbrace, .none); // lbrace |
| ... | ... | @@ -1992,7 +1986,7 @@ fn renderStructInit( |
| 1992 | 1986 | } |
| 1993 | 1987 | |
| 1994 | 1988 | const rbrace = tree.lastToken(struct_node); |
| 1995 | const trailing_comma = token_tags[rbrace - 1] == .comma; | |
| 1989 | const trailing_comma = tree.tokenTag(rbrace - 1) == .comma; | |
| 1996 | 1990 | if (trailing_comma or hasComment(tree, struct_init.ast.lbrace, rbrace)) { |
| 1997 | 1991 | // Render one field init per line. |
| 1998 | 1992 | try ais.pushIndent(.normal); |
| ... | ... | @@ -2002,9 +1996,8 @@ fn renderStructInit( |
| 2002 | 1996 | try renderIdentifier(r, struct_init.ast.lbrace + 2, .space, .eagerly_unquote); // name |
| 2003 | 1997 | // Don't output a space after the = if expression is a multiline string, |
| 2004 | 1998 | // since then it will start on the next line. |
| 2005 | const nodes = tree.nodes.items(.tag); | |
| 2006 | 1999 | const field_node = struct_init.ast.fields[0]; |
| 2007 | const expr = nodes[field_node]; | |
| 2000 | const expr = tree.nodeTag(field_node); | |
| 2008 | 2001 | var space_after_equal: Space = if (expr == .multiline_string_literal) .none else .space; |
| 2009 | 2002 | try renderToken(r, struct_init.ast.lbrace + 3, space_after_equal); // = |
| 2010 | 2003 | |
| ... | ... | @@ -2017,7 +2010,7 @@ fn renderStructInit( |
| 2017 | 2010 | try renderExtraNewlineToken(r, init_token - 3); |
| 2018 | 2011 | try renderToken(r, init_token - 3, .none); // . |
| 2019 | 2012 | try renderIdentifier(r, init_token - 2, .space, .eagerly_unquote); // name |
| 2020 | space_after_equal = if (nodes[field_init] == .multiline_string_literal) .none else .space; | |
| 2013 | space_after_equal = if (tree.nodeTag(field_init) == .multiline_string_literal) .none else .space; | |
| 2021 | 2014 | try renderToken(r, init_token - 1, space_after_equal); // = |
| 2022 | 2015 | |
| 2023 | 2016 | try ais.pushSpace(.comma); |
| ... | ... | @@ -2050,12 +2043,11 @@ fn renderArrayInit( |
| 2050 | 2043 | const tree = r.tree; |
| 2051 | 2044 | const ais = r.ais; |
| 2052 | 2045 | const gpa = r.gpa; |
| 2053 | const token_tags = tree.tokens.items(.tag); | |
| 2054 | 2046 | |
| 2055 | if (array_init.ast.type_expr == 0) { | |
| 2056 | try renderToken(r, array_init.ast.lbrace - 1, .none); // . | |
| 2047 | if (array_init.ast.type_expr.unwrap()) |type_expr| { | |
| 2048 | try renderExpression(r, type_expr, .none); // T | |
| 2057 | 2049 | } else { |
| 2058 | try renderExpression(r, array_init.ast.type_expr, .none); // T | |
| 2050 | try renderToken(r, array_init.ast.lbrace - 1, .none); // . | |
| 2059 | 2051 | } |
| 2060 | 2052 | |
| 2061 | 2053 | if (array_init.ast.elements.len == 0) { |
| ... | ... | @@ -2067,14 +2059,14 @@ fn renderArrayInit( |
| 2067 | 2059 | |
| 2068 | 2060 | const last_elem = array_init.ast.elements[array_init.ast.elements.len - 1]; |
| 2069 | 2061 | const last_elem_token = tree.lastToken(last_elem); |
| 2070 | const trailing_comma = token_tags[last_elem_token + 1] == .comma; | |
| 2062 | const trailing_comma = tree.tokenTag(last_elem_token + 1) == .comma; | |
| 2071 | 2063 | const rbrace = if (trailing_comma) last_elem_token + 2 else last_elem_token + 1; |
| 2072 | assert(token_tags[rbrace] == .r_brace); | |
| 2064 | assert(tree.tokenTag(rbrace) == .r_brace); | |
| 2073 | 2065 | |
| 2074 | 2066 | if (array_init.ast.elements.len == 1) { |
| 2075 | 2067 | const only_elem = array_init.ast.elements[0]; |
| 2076 | 2068 | const first_token = tree.firstToken(only_elem); |
| 2077 | if (token_tags[first_token] != .multiline_string_literal_line and | |
| 2069 | if (tree.tokenTag(first_token) != .multiline_string_literal_line and | |
| 2078 | 2070 | !anythingBetween(tree, last_elem_token, rbrace)) |
| 2079 | 2071 | { |
| 2080 | 2072 | try renderToken(r, array_init.ast.lbrace, .none); |
| ... | ... | @@ -2137,7 +2129,7 @@ fn renderArrayInit( |
| 2137 | 2129 | } |
| 2138 | 2130 | |
| 2139 | 2131 | const maybe_comma = expr_last_token + 1; |
| 2140 | if (token_tags[maybe_comma] == .comma) { | |
| 2132 | if (tree.tokenTag(maybe_comma) == .comma) { | |
| 2141 | 2133 | if (hasSameLineComment(tree, maybe_comma)) |
| 2142 | 2134 | break :sec_end i - this_line_size + 1; |
| 2143 | 2135 | } |
| ... | ... | @@ -2277,13 +2269,12 @@ fn renderContainerDecl( |
| 2277 | 2269 | ) Error!void { |
| 2278 | 2270 | const tree = r.tree; |
| 2279 | 2271 | const ais = r.ais; |
| 2280 | const token_tags = tree.tokens.items(.tag); | |
| 2281 | 2272 | |
| 2282 | 2273 | if (container_decl.layout_token) |layout_token| { |
| 2283 | 2274 | try renderToken(r, layout_token, .space); |
| 2284 | 2275 | } |
| 2285 | 2276 | |
| 2286 | const container: Container = switch (token_tags[container_decl.ast.main_token]) { | |
| 2277 | const container: Container = switch (tree.tokenTag(container_decl.ast.main_token)) { | |
| 2287 | 2278 | .keyword_enum => .@"enum", |
| 2288 | 2279 | .keyword_struct => for (container_decl.ast.members) |member| { |
| 2289 | 2280 | if (tree.fullContainerField(member)) |field| if (!field.ast.tuple_like) break .other; |
| ... | ... | @@ -2296,10 +2287,10 @@ fn renderContainerDecl( |
| 2296 | 2287 | try renderToken(r, container_decl.ast.main_token, .none); // union |
| 2297 | 2288 | try renderToken(r, enum_token - 1, .none); // lparen |
| 2298 | 2289 | try renderToken(r, enum_token, .none); // enum |
| 2299 | if (container_decl.ast.arg != 0) { | |
| 2290 | if (container_decl.ast.arg.unwrap()) |arg| { | |
| 2300 | 2291 | try renderToken(r, enum_token + 1, .none); // lparen |
| 2301 | try renderExpression(r, container_decl.ast.arg, .none); | |
| 2302 | const rparen = tree.lastToken(container_decl.ast.arg) + 1; | |
| 2292 | try renderExpression(r, arg, .none); | |
| 2293 | const rparen = tree.lastToken(arg) + 1; | |
| 2303 | 2294 | try renderToken(r, rparen, .none); // rparen |
| 2304 | 2295 | try renderToken(r, rparen + 1, .space); // rparen |
| 2305 | 2296 | lbrace = rparen + 2; |
| ... | ... | @@ -2307,11 +2298,11 @@ fn renderContainerDecl( |
| 2307 | 2298 | try renderToken(r, enum_token + 1, .space); // rparen |
| 2308 | 2299 | lbrace = enum_token + 2; |
| 2309 | 2300 | } |
| 2310 | } else if (container_decl.ast.arg != 0) { | |
| 2301 | } else if (container_decl.ast.arg.unwrap()) |arg| { | |
| 2311 | 2302 | try renderToken(r, container_decl.ast.main_token, .none); // union |
| 2312 | 2303 | try renderToken(r, container_decl.ast.main_token + 1, .none); // lparen |
| 2313 | try renderExpression(r, container_decl.ast.arg, .none); | |
| 2314 | const rparen = tree.lastToken(container_decl.ast.arg) + 1; | |
| 2304 | try renderExpression(r, arg, .none); | |
| 2305 | const rparen = tree.lastToken(arg) + 1; | |
| 2315 | 2306 | try renderToken(r, rparen, .space); // rparen |
| 2316 | 2307 | lbrace = rparen + 1; |
| 2317 | 2308 | } else { |
| ... | ... | @@ -2320,9 +2311,10 @@ fn renderContainerDecl( |
| 2320 | 2311 | } |
| 2321 | 2312 | |
| 2322 | 2313 | const rbrace = tree.lastToken(container_decl_node); |
| 2314 | ||
| 2323 | 2315 | if (container_decl.ast.members.len == 0) { |
| 2324 | 2316 | try ais.pushIndent(.normal); |
| 2325 | if (token_tags[lbrace + 1] == .container_doc_comment) { | |
| 2317 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) { | |
| 2326 | 2318 | try renderToken(r, lbrace, .newline); // lbrace |
| 2327 | 2319 | try renderContainerDocComments(r, lbrace + 1); |
| 2328 | 2320 | } else { |
| ... | ... | @@ -2332,7 +2324,7 @@ fn renderContainerDecl( |
| 2332 | 2324 | return renderToken(r, rbrace, space); // rbrace |
| 2333 | 2325 | } |
| 2334 | 2326 | |
| 2335 | const src_has_trailing_comma = token_tags[rbrace - 1] == .comma; | |
| 2327 | const src_has_trailing_comma = tree.tokenTag(rbrace - 1) == .comma; | |
| 2336 | 2328 | if (!src_has_trailing_comma) one_line: { |
| 2337 | 2329 | // We print all the members in-line unless one of the following conditions are true: |
| 2338 | 2330 | |
| ... | ... | @@ -2342,10 +2334,10 @@ fn renderContainerDecl( |
| 2342 | 2334 | } |
| 2343 | 2335 | |
| 2344 | 2336 | // 2. The container has a container comment. |
| 2345 | if (token_tags[lbrace + 1] == .container_doc_comment) break :one_line; | |
| 2337 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) break :one_line; | |
| 2346 | 2338 | |
| 2347 | 2339 | // 3. A member of the container has a doc comment. |
| 2348 | for (token_tags[lbrace + 1 .. rbrace - 1]) |tag| { | |
| 2340 | for (tree.tokens.items(.tag)[lbrace + 1 .. rbrace - 1]) |tag| { | |
| 2349 | 2341 | if (tag == .doc_comment) break :one_line; |
| 2350 | 2342 | } |
| 2351 | 2343 | |
| ... | ... | @@ -2365,12 +2357,12 @@ fn renderContainerDecl( |
| 2365 | 2357 | // One member per line. |
| 2366 | 2358 | try ais.pushIndent(.normal); |
| 2367 | 2359 | try renderToken(r, lbrace, .newline); // lbrace |
| 2368 | if (token_tags[lbrace + 1] == .container_doc_comment) { | |
| 2360 | if (tree.tokenTag(lbrace + 1) == .container_doc_comment) { | |
| 2369 | 2361 | try renderContainerDocComments(r, lbrace + 1); |
| 2370 | 2362 | } |
| 2371 | 2363 | for (container_decl.ast.members, 0..) |member, i| { |
| 2372 | 2364 | if (i != 0) try renderExtraNewline(r, member); |
| 2373 | switch (tree.nodes.items(.tag)[member]) { | |
| 2365 | switch (tree.nodeTag(member)) { | |
| 2374 | 2366 | // For container fields, ensure a trailing comma is added if necessary. |
| 2375 | 2367 | .container_field_init, |
| 2376 | 2368 | .container_field_align, |
| ... | ... | @@ -2396,7 +2388,6 @@ fn renderAsm( |
| 2396 | 2388 | ) Error!void { |
| 2397 | 2389 | const tree = r.tree; |
| 2398 | 2390 | const ais = r.ais; |
| 2399 | const token_tags = tree.tokens.items(.tag); | |
| 2400 | 2391 | |
| 2401 | 2392 | try renderToken(r, asm_node.ast.asm_token, .space); // asm |
| 2402 | 2393 | |
| ... | ... | @@ -2422,13 +2413,13 @@ fn renderAsm( |
| 2422 | 2413 | while (true) : (tok_i += 1) { |
| 2423 | 2414 | try renderToken(r, tok_i, .none); |
| 2424 | 2415 | tok_i += 1; |
| 2425 | switch (token_tags[tok_i]) { | |
| 2416 | switch (tree.tokenTag(tok_i)) { | |
| 2426 | 2417 | .r_paren => { |
| 2427 | 2418 | ais.popIndent(); |
| 2428 | 2419 | return renderToken(r, tok_i, space); |
| 2429 | 2420 | }, |
| 2430 | 2421 | .comma => { |
| 2431 | if (token_tags[tok_i + 1] == .r_paren) { | |
| 2422 | if (tree.tokenTag(tok_i + 1) == .r_paren) { | |
| 2432 | 2423 | ais.popIndent(); |
| 2433 | 2424 | return renderToken(r, tok_i + 1, space); |
| 2434 | 2425 | } else { |
| ... | ... | @@ -2480,7 +2471,7 @@ fn renderAsm( |
| 2480 | 2471 | ais.popSpace(); |
| 2481 | 2472 | const comma_or_colon = tree.lastToken(asm_output) + 1; |
| 2482 | 2473 | ais.popIndent(); |
| 2483 | break :colon2 switch (token_tags[comma_or_colon]) { | |
| 2474 | break :colon2 switch (tree.tokenTag(comma_or_colon)) { | |
| 2484 | 2475 | .comma => comma_or_colon + 1, |
| 2485 | 2476 | else => comma_or_colon, |
| 2486 | 2477 | }; |
| ... | ... | @@ -2516,7 +2507,7 @@ fn renderAsm( |
| 2516 | 2507 | ais.popSpace(); |
| 2517 | 2508 | const comma_or_colon = tree.lastToken(asm_input) + 1; |
| 2518 | 2509 | ais.popIndent(); |
| 2519 | break :colon3 switch (token_tags[comma_or_colon]) { | |
| 2510 | break :colon3 switch (tree.tokenTag(comma_or_colon)) { | |
| 2520 | 2511 | .comma => comma_or_colon + 1, |
| 2521 | 2512 | else => comma_or_colon, |
| 2522 | 2513 | }; |
| ... | ... | @@ -2529,7 +2520,7 @@ fn renderAsm( |
| 2529 | 2520 | const first_clobber = asm_node.first_clobber.?; |
| 2530 | 2521 | var tok_i = first_clobber; |
| 2531 | 2522 | while (true) { |
| 2532 | switch (token_tags[tok_i + 1]) { | |
| 2523 | switch (tree.tokenTag(tok_i + 1)) { | |
| 2533 | 2524 | .r_paren => { |
| 2534 | 2525 | ais.setIndentDelta(indent_delta); |
| 2535 | 2526 | try renderToken(r, tok_i, .newline); |
| ... | ... | @@ -2537,7 +2528,7 @@ fn renderAsm( |
| 2537 | 2528 | return renderToken(r, tok_i + 1, space); |
| 2538 | 2529 | }, |
| 2539 | 2530 | .comma => { |
| 2540 | switch (token_tags[tok_i + 2]) { | |
| 2531 | switch (tree.tokenTag(tok_i + 2)) { | |
| 2541 | 2532 | .r_paren => { |
| 2542 | 2533 | ais.setIndentDelta(indent_delta); |
| 2543 | 2534 | try renderToken(r, tok_i, .newline); |
| ... | ... | @@ -2576,7 +2567,6 @@ fn renderParamList( |
| 2576 | 2567 | ) Error!void { |
| 2577 | 2568 | const tree = r.tree; |
| 2578 | 2569 | const ais = r.ais; |
| 2579 | const token_tags = tree.tokens.items(.tag); | |
| 2580 | 2570 | |
| 2581 | 2571 | if (params.len == 0) { |
| 2582 | 2572 | try ais.pushIndent(.normal); |
| ... | ... | @@ -2587,7 +2577,7 @@ fn renderParamList( |
| 2587 | 2577 | |
| 2588 | 2578 | const last_param = params[params.len - 1]; |
| 2589 | 2579 | const after_last_param_tok = tree.lastToken(last_param) + 1; |
| 2590 | if (token_tags[after_last_param_tok] == .comma) { | |
| 2580 | if (tree.tokenTag(after_last_param_tok) == .comma) { | |
| 2591 | 2581 | try ais.pushIndent(.normal); |
| 2592 | 2582 | try renderToken(r, lparen, .newline); // ( |
| 2593 | 2583 | for (params, 0..) |param_node, i| { |
| ... | ... | @@ -2616,7 +2606,7 @@ fn renderParamList( |
| 2616 | 2606 | if (i + 1 < params.len) { |
| 2617 | 2607 | const comma = tree.lastToken(param_node) + 1; |
| 2618 | 2608 | const next_multiline_string = |
| 2619 | token_tags[tree.firstToken(params[i + 1])] == .multiline_string_literal_line; | |
| 2609 | tree.tokenTag(tree.firstToken(params[i + 1])) == .multiline_string_literal_line; | |
| 2620 | 2610 | const comma_space: Space = if (next_multiline_string) .none else .space; |
| 2621 | 2611 | try renderToken(r, comma, comma_space); |
| 2622 | 2612 | } |
| ... | ... | @@ -2629,9 +2619,8 @@ fn renderParamList( |
| 2629 | 2619 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2630 | 2620 | fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void { |
| 2631 | 2621 | const tree = r.tree; |
| 2632 | const token_tags = tree.tokens.items(.tag); | |
| 2633 | 2622 | const maybe_comma = tree.lastToken(node) + 1; |
| 2634 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2623 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2635 | 2624 | try renderExpression(r, node, .none); |
| 2636 | 2625 | return renderToken(r, maybe_comma, space); |
| 2637 | 2626 | } else { |
| ... | ... | @@ -2643,9 +2632,8 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v |
| 2643 | 2632 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2644 | 2633 | fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void { |
| 2645 | 2634 | const tree = r.tree; |
| 2646 | const token_tags = tree.tokens.items(.tag); | |
| 2647 | 2635 | const maybe_comma = token + 1; |
| 2648 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2636 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2649 | 2637 | try renderToken(r, token, .none); |
| 2650 | 2638 | return renderToken(r, maybe_comma, space); |
| 2651 | 2639 | } else { |
| ... | ... | @@ -2657,9 +2645,8 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void |
| 2657 | 2645 | /// If a comma is present, and `space` is `Space.comma`, render only a single comma. |
| 2658 | 2646 | fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { |
| 2659 | 2647 | const tree = r.tree; |
| 2660 | const token_tags = tree.tokens.items(.tag); | |
| 2661 | 2648 | const maybe_comma = token + 1; |
| 2662 | if (token_tags[maybe_comma] == .comma and space != .comma) { | |
| 2649 | if (tree.tokenTag(maybe_comma) == .comma and space != .comma) { | |
| 2663 | 2650 | try renderIdentifier(r, token, .none, quote); |
| 2664 | 2651 | return renderToken(r, maybe_comma, space); |
| 2665 | 2652 | } else { |
| ... | ... | @@ -2709,37 +2696,39 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: |
| 2709 | 2696 | fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void { |
| 2710 | 2697 | const tree = r.tree; |
| 2711 | 2698 | const ais = r.ais; |
| 2712 | const token_tags = tree.tokens.items(.tag); | |
| 2713 | const token_starts = tree.tokens.items(.start); | |
| 2714 | 2699 | |
| 2715 | const token_start = token_starts[token_index]; | |
| 2700 | const next_token_tag = tree.tokenTag(token_index + 1); | |
| 2716 | 2701 | |
| 2717 | 2702 | if (space == .skip) return; |
| 2718 | 2703 | |
| 2719 | if (space == .comma and token_tags[token_index + 1] != .comma) { | |
| 2704 | if (space == .comma and next_token_tag != .comma) { | |
| 2720 | 2705 | try ais.writer().writeByte(','); |
| 2721 | 2706 | } |
| 2722 | 2707 | if (space == .semicolon or space == .comma) ais.enableSpaceMode(space); |
| 2723 | 2708 | defer ais.disableSpaceMode(); |
| 2724 | const comment = try renderComments(r, token_start + lexeme_len, token_starts[token_index + 1]); | |
| 2709 | const comment = try renderComments( | |
| 2710 | r, | |
| 2711 | tree.tokenStart(token_index) + lexeme_len, | |
| 2712 | tree.tokenStart(token_index + 1), | |
| 2713 | ); | |
| 2725 | 2714 | switch (space) { |
| 2726 | 2715 | .none => {}, |
| 2727 | 2716 | .space => if (!comment) try ais.writer().writeByte(' '), |
| 2728 | 2717 | .newline => if (!comment) try ais.insertNewline(), |
| 2729 | 2718 | |
| 2730 | .comma => if (token_tags[token_index + 1] == .comma) { | |
| 2719 | .comma => if (next_token_tag == .comma) { | |
| 2731 | 2720 | try renderToken(r, token_index + 1, .newline); |
| 2732 | 2721 | } else if (!comment) { |
| 2733 | 2722 | try ais.insertNewline(); |
| 2734 | 2723 | }, |
| 2735 | 2724 | |
| 2736 | .comma_space => if (token_tags[token_index + 1] == .comma) { | |
| 2725 | .comma_space => if (next_token_tag == .comma) { | |
| 2737 | 2726 | try renderToken(r, token_index + 1, .space); |
| 2738 | 2727 | } else if (!comment) { |
| 2739 | 2728 | try ais.writer().writeByte(' '); |
| 2740 | 2729 | }, |
| 2741 | 2730 | |
| 2742 | .semicolon => if (token_tags[token_index + 1] == .semicolon) { | |
| 2731 | .semicolon => if (next_token_tag == .semicolon) { | |
| 2743 | 2732 | try renderToken(r, token_index + 1, .newline); |
| 2744 | 2733 | } else if (!comment) { |
| 2745 | 2734 | try ais.insertNewline(); |
| ... | ... | @@ -2770,8 +2759,7 @@ const QuoteBehavior = enum { |
| 2770 | 2759 | |
| 2771 | 2760 | fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void { |
| 2772 | 2761 | const tree = r.tree; |
| 2773 | const token_tags = tree.tokens.items(.tag); | |
| 2774 | assert(token_tags[token_index] == .identifier); | |
| 2762 | assert(tree.tokenTag(token_index) == .identifier); | |
| 2775 | 2763 | const lexeme = tokenSliceForRender(tree, token_index); |
| 2776 | 2764 | |
| 2777 | 2765 | if (r.fixups.rename_identifiers.get(lexeme)) |mangled| { |
| ... | ... | @@ -2880,8 +2868,7 @@ fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote |
| 2880 | 2868 | fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, comptime unquote: bool) !void { |
| 2881 | 2869 | const tree = r.tree; |
| 2882 | 2870 | const ais = r.ais; |
| 2883 | const token_tags = tree.tokens.items(.tag); | |
| 2884 | assert(token_tags[token_index] == .identifier); | |
| 2871 | assert(tree.tokenTag(token_index) == .identifier); | |
| 2885 | 2872 | const lexeme = tokenSliceForRender(tree, token_index); |
| 2886 | 2873 | assert(lexeme.len >= 3 and lexeme[0] == '@'); |
| 2887 | 2874 | |
| ... | ... | @@ -2934,12 +2921,10 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void { |
| 2934 | 2921 | /// fn_proto should be wrapped and have a trailing comma inserted even if |
| 2935 | 2922 | /// there is none in the source. |
| 2936 | 2923 | fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 2937 | const token_starts = tree.tokens.items(.start); | |
| 2938 | ||
| 2939 | var i = start_token; | |
| 2940 | while (i < end_token) : (i += 1) { | |
| 2941 | const start = token_starts[i] + tree.tokenSlice(i).len; | |
| 2942 | const end = token_starts[i + 1]; | |
| 2924 | for (start_token..end_token) |i| { | |
| 2925 | const token: Ast.TokenIndex = @intCast(i); | |
| 2926 | const start = tree.tokenStart(token) + tree.tokenSlice(token).len; | |
| 2927 | const end = tree.tokenStart(token + 1); | |
| 2943 | 2928 | if (mem.indexOf(u8, tree.source[start..end], "//") != null) return true; |
| 2944 | 2929 | } |
| 2945 | 2930 | |
| ... | ... | @@ -2949,16 +2934,11 @@ fn hasComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) |
| 2949 | 2934 | /// Returns true if there exists a multiline string literal between the start |
| 2950 | 2935 | /// of token `start_token` and the start of token `end_token`. |
| 2951 | 2936 | fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 2952 | const token_tags = tree.tokens.items(.tag); | |
| 2953 | ||
| 2954 | for (token_tags[start_token..end_token]) |tag| { | |
| 2955 | switch (tag) { | |
| 2956 | .multiline_string_literal_line => return true, | |
| 2957 | else => continue, | |
| 2958 | } | |
| 2959 | } | |
| 2960 | ||
| 2961 | return false; | |
| 2937 | return std.mem.indexOfScalar( | |
| 2938 | Token.Tag, | |
| 2939 | tree.tokens.items(.tag)[start_token..end_token], | |
| 2940 | .multiline_string_literal_line, | |
| 2941 | ) != null; | |
| 2962 | 2942 | } |
| 2963 | 2943 | |
| 2964 | 2944 | /// Assumes that start is the first byte past the previous token and |
| ... | ... | @@ -3034,18 +3014,17 @@ fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void { |
| 3034 | 3014 | fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void { |
| 3035 | 3015 | const tree = r.tree; |
| 3036 | 3016 | const ais = r.ais; |
| 3037 | const token_starts = tree.tokens.items(.start); | |
| 3038 | const token_start = token_starts[token_index]; | |
| 3017 | const token_start = tree.tokenStart(token_index); | |
| 3039 | 3018 | if (token_start == 0) return; |
| 3040 | 3019 | const prev_token_end = if (token_index == 0) |
| 3041 | 3020 | 0 |
| 3042 | 3021 | else |
| 3043 | token_starts[token_index - 1] + tokenSliceForRender(tree, token_index - 1).len; | |
| 3022 | tree.tokenStart(token_index - 1) + tokenSliceForRender(tree, token_index - 1).len; | |
| 3044 | 3023 | |
| 3045 | 3024 | // If there is a immediately preceding comment or doc_comment, |
| 3046 | 3025 | // skip it because required extra newline has already been rendered. |
| 3047 | 3026 | if (mem.indexOf(u8, tree.source[prev_token_end..token_start], "//") != null) return; |
| 3048 | if (token_index > 0 and tree.tokens.items(.tag)[token_index - 1] == .doc_comment) return; | |
| 3027 | if (tree.isTokenPrecededByTags(token_index, &.{.doc_comment})) return; | |
| 3049 | 3028 | |
| 3050 | 3029 | // Iterate backwards to the end of the previous token, stopping if a |
| 3051 | 3030 | // non-whitespace character is encountered or two newlines have been found. |
| ... | ... | @@ -3063,10 +3042,9 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void { |
| 3063 | 3042 | fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3064 | 3043 | const tree = r.tree; |
| 3065 | 3044 | // Search backwards for the first doc comment. |
| 3066 | const token_tags = tree.tokens.items(.tag); | |
| 3067 | 3045 | if (end_token == 0) return; |
| 3068 | 3046 | var tok = end_token - 1; |
| 3069 | while (token_tags[tok] == .doc_comment) { | |
| 3047 | while (tree.tokenTag(tok) == .doc_comment) { | |
| 3070 | 3048 | if (tok == 0) break; |
| 3071 | 3049 | tok -= 1; |
| 3072 | 3050 | } else { |
| ... | ... | @@ -3076,7 +3054,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3076 | 3054 | if (first_tok == end_token) return; |
| 3077 | 3055 | |
| 3078 | 3056 | if (first_tok != 0) { |
| 3079 | const prev_token_tag = token_tags[first_tok - 1]; | |
| 3057 | const prev_token_tag = tree.tokenTag(first_tok - 1); | |
| 3080 | 3058 | |
| 3081 | 3059 | // Prevent accidental use of `renderDocComments` for a function argument doc comment |
| 3082 | 3060 | assert(prev_token_tag != .l_paren); |
| ... | ... | @@ -3086,7 +3064,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3086 | 3064 | } |
| 3087 | 3065 | } |
| 3088 | 3066 | |
| 3089 | while (token_tags[tok] == .doc_comment) : (tok += 1) { | |
| 3067 | while (tree.tokenTag(tok) == .doc_comment) : (tok += 1) { | |
| 3090 | 3068 | try renderToken(r, tok, .newline); |
| 3091 | 3069 | } |
| 3092 | 3070 | } |
| ... | ... | @@ -3094,15 +3072,14 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void { |
| 3094 | 3072 | /// start_token is first container doc comment token. |
| 3095 | 3073 | fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void { |
| 3096 | 3074 | const tree = r.tree; |
| 3097 | const token_tags = tree.tokens.items(.tag); | |
| 3098 | 3075 | var tok = start_token; |
| 3099 | while (token_tags[tok] == .container_doc_comment) : (tok += 1) { | |
| 3076 | while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) { | |
| 3100 | 3077 | try renderToken(r, tok, .newline); |
| 3101 | 3078 | } |
| 3102 | 3079 | // Render extra newline if there is one between final container doc comment and |
| 3103 | 3080 | // the next token. If the next token is a doc comment, that code path |
| 3104 | 3081 | // will have its own logic to insert a newline. |
| 3105 | if (token_tags[tok] != .doc_comment) { | |
| 3082 | if (tree.tokenTag(tok) != .doc_comment) { | |
| 3106 | 3083 | try renderExtraNewlineToken(r, tok); |
| 3107 | 3084 | } |
| 3108 | 3085 | } |
| ... | ... | @@ -3112,11 +3089,10 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void { |
| 3112 | 3089 | const ais = r.ais; |
| 3113 | 3090 | var buf: [1]Ast.Node.Index = undefined; |
| 3114 | 3091 | const fn_proto = tree.fullFnProto(&buf, fn_proto_node).?; |
| 3115 | const token_tags = tree.tokens.items(.tag); | |
| 3116 | 3092 | var it = fn_proto.iterate(tree); |
| 3117 | 3093 | while (it.next()) |param| { |
| 3118 | 3094 | const name_ident = param.name_token.?; |
| 3119 | assert(token_tags[name_ident] == .identifier); | |
| 3095 | assert(tree.tokenTag(name_ident) == .identifier); | |
| 3120 | 3096 | const w = ais.writer(); |
| 3121 | 3097 | try w.writeAll("_ = "); |
| 3122 | 3098 | try w.writeAll(tokenSliceForRender(r.tree, name_ident)); |
| ... | ... | @@ -3126,7 +3102,7 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void { |
| 3126 | 3102 | |
| 3127 | 3103 | fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 { |
| 3128 | 3104 | var ret = tree.tokenSlice(token_index); |
| 3129 | switch (tree.tokens.items(.tag)[token_index]) { | |
| 3105 | switch (tree.tokenTag(token_index)) { | |
| 3130 | 3106 | .container_doc_comment, .doc_comment => { |
| 3131 | 3107 | ret = mem.trimRight(u8, ret, &std.ascii.whitespace); |
| 3132 | 3108 | }, |
| ... | ... | @@ -3136,8 +3112,7 @@ fn tokenSliceForRender(tree: Ast, token_index: Ast.TokenIndex) []const u8 { |
| 3136 | 3112 | } |
| 3137 | 3113 | |
| 3138 | 3114 | fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool { |
| 3139 | const token_starts = tree.tokens.items(.start); | |
| 3140 | const between_source = tree.source[token_starts[token_index]..token_starts[token_index + 1]]; | |
| 3115 | const between_source = tree.source[tree.tokenStart(token_index)..tree.tokenStart(token_index + 1)]; | |
| 3141 | 3116 | for (between_source) |byte| switch (byte) { |
| 3142 | 3117 | '\n' => return false, |
| 3143 | 3118 | '/' => return true, |
| ... | ... | @@ -3150,8 +3125,7 @@ fn hasSameLineComment(tree: Ast, token_index: Ast.TokenIndex) bool { |
| 3150 | 3125 | /// start_token and end_token. |
| 3151 | 3126 | fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 3152 | 3127 | if (start_token + 1 != end_token) return true; |
| 3153 | const token_starts = tree.tokens.items(.start); | |
| 3154 | const between_source = tree.source[token_starts[start_token]..token_starts[start_token + 1]]; | |
| 3128 | const between_source = tree.source[tree.tokenStart(start_token)..tree.tokenStart(start_token + 1)]; | |
| 3155 | 3129 | for (between_source) |byte| switch (byte) { |
| 3156 | 3130 | '/' => return true, |
| 3157 | 3131 | else => continue, |
| ... | ... | @@ -3245,12 +3219,10 @@ fn nodeCausesSliceOpSpace(tag: Ast.Node.Tag) bool { |
| 3245 | 3219 | |
| 3246 | 3220 | // Returns the number of nodes in `exprs` that are on the same line as `rtoken`. |
| 3247 | 3221 | fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usize { |
| 3248 | const token_tags = tree.tokens.items(.tag); | |
| 3249 | ||
| 3250 | 3222 | const first_token = tree.firstToken(exprs[0]); |
| 3251 | 3223 | if (tree.tokensOnSameLine(first_token, rtoken)) { |
| 3252 | 3224 | const maybe_comma = rtoken - 1; |
| 3253 | if (token_tags[maybe_comma] == .comma) | |
| 3225 | if (tree.tokenTag(maybe_comma) == .comma) | |
| 3254 | 3226 | return 1; |
| 3255 | 3227 | return exprs.len; // no newlines |
| 3256 | 3228 | } |
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]), |
| ... | ... | @@ -2322,7 +2322,7 @@ const TestFetchBuilder = struct { |
| 2322 | 2322 | .arena = std.heap.ArenaAllocator.init(allocator), |
| 2323 | 2323 | .location = .{ .path_or_url = path_or_url }, |
| 2324 | 2324 | .location_tok = 0, |
| 2325 | .hash_tok = 0, | |
| 2325 | .hash_tok = .none, | |
| 2326 | 2326 | .name_tok = 0, |
| 2327 | 2327 | .lazy_status = .eager, |
| 2328 | 2328 | .parent_package_root = Cache.Path{ .root_dir = Cache.Directory{ .handle = cache_dir, .path = null } }, |
src/Package/Manifest.zig+42-61| ... | ... | @@ -17,8 +17,8 @@ pub const Dependency = struct { |
| 17 | 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); |
| ... | ... | @@ -17867,7 +17886,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17867 | 17886 | const ip = &zcu.intern_pool; |
| 17868 | 17887 | const captures = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type).getCaptures(zcu); |
| 17869 | 17888 | |
| 17870 | const src_node: i32 = @bitCast(extended.operand); | |
| 17889 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 17871 | 17890 | const src = block.nodeOffset(src_node); |
| 17872 | 17891 | |
| 17873 | 17892 | const capture_ty = switch (captures.get(ip)[extended.small].unwrap()) { |
| ... | ... | @@ -17891,8 +17910,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17891 | 17910 | }); |
| 17892 | 17911 | break :name null; |
| 17893 | 17912 | }; |
| 17894 | const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); | |
| 17895 | const token = tree.nodes.items(.main_token)[node]; | |
| 17913 | const node = src_node.toAbsolute(src_base_node); | |
| 17914 | const token = tree.nodeMainToken(node); | |
| 17896 | 17915 | break :name tree.tokenSlice(token); |
| 17897 | 17916 | }; |
| 17898 | 17917 | |
| ... | ... | @@ -17919,8 +17938,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17919 | 17938 | }); |
| 17920 | 17939 | break :name null; |
| 17921 | 17940 | }; |
| 17922 | const node: std.zig.Ast.Node.Index = @bitCast(src_node + @as(i32, @bitCast(src_base_node))); | |
| 17923 | const token = tree.nodes.items(.main_token)[node]; | |
| 17941 | const node = src_node.toAbsolute(src_base_node); | |
| 17942 | const token = tree.nodeMainToken(node); | |
| 17924 | 17943 | break :name tree.tokenSlice(token); |
| 17925 | 17944 | }; |
| 17926 | 17945 | |
| ... | ... | @@ -17930,7 +17949,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17930 | 17949 | try sema.errMsg(src, "variable not accessible from inner function", .{}); |
| 17931 | 17950 | errdefer msg.destroy(sema.gpa); |
| 17932 | 17951 | |
| 17933 | try sema.errNote(block.nodeOffset(0), msg, "crossed function definition here", .{}); | |
| 17952 | try sema.errNote(block.nodeOffset(.zero), msg, "crossed function definition here", .{}); | |
| 17934 | 17953 | |
| 17935 | 17954 | // TODO add "declared here" note |
| 17936 | 17955 | break :msg msg; |
| ... | ... | @@ -17962,7 +17981,8 @@ fn zirFrameAddress( |
| 17962 | 17981 | block: *Block, |
| 17963 | 17982 | extended: Zir.Inst.Extended.InstData, |
| 17964 | 17983 | ) CompileError!Air.Inst.Ref { |
| 17965 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 17984 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 17985 | const src = block.nodeOffset(src_node); | |
| 17966 | 17986 | try sema.requireRuntimeBlock(block, src, null); |
| 17967 | 17987 | return try block.addNoOp(.frame_addr); |
| 17968 | 17988 | } |
| ... | ... | @@ -18059,7 +18079,7 @@ fn zirBuiltinSrc( |
| 18059 | 18079 | } }); |
| 18060 | 18080 | }; |
| 18061 | 18081 | |
| 18062 | const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(0), .SourceLocation); | |
| 18082 | const src_loc_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .SourceLocation); | |
| 18063 | 18083 | const fields = .{ |
| 18064 | 18084 | // module: [:0]const u8, |
| 18065 | 18085 | module_name_val, |
| ... | ... | @@ -19528,7 +19548,7 @@ fn zirCondbr( |
| 19528 | 19548 | fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19529 | 19549 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19530 | 19550 | const src = parent_block.nodeOffset(inst_data.src_node); |
| 19531 | const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 19551 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); | |
| 19532 | 19552 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 19533 | 19553 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 19534 | 19554 | const err_union = try sema.resolveInst(extra.data.operand); |
| ... | ... | @@ -19587,7 +19607,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! |
| 19587 | 19607 | fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 19588 | 19608 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 19589 | 19609 | const src = parent_block.nodeOffset(inst_data.src_node); |
| 19590 | const operand_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 19610 | const operand_src = parent_block.src(.{ .node_offset_try_operand = inst_data.src_node }); | |
| 19591 | 19611 | const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); |
| 19592 | 19612 | const body = sema.code.bodySlice(extra.end, extra.data.body_len); |
| 19593 | 19613 | const operand = try sema.resolveInst(extra.data.operand); |
| ... | ... | @@ -19790,7 +19810,7 @@ fn zirRetImplicit( |
| 19790 | 19810 | } |
| 19791 | 19811 | |
| 19792 | 19812 | const operand = try sema.resolveInst(inst_data.operand); |
| 19793 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = 0 }); | |
| 19813 | const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero }); | |
| 19794 | 19814 | const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu); |
| 19795 | 19815 | if (base_tag == .noreturn) { |
| 19796 | 19816 | const msg = msg: { |
| ... | ... | @@ -21277,7 +21297,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { |
| 21277 | 21297 | const pt = sema.pt; |
| 21278 | 21298 | const zcu = pt.zcu; |
| 21279 | 21299 | const ip = &zcu.intern_pool; |
| 21280 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(0), .StackTrace); | |
| 21300 | const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace); | |
| 21281 | 21301 | try stack_trace_ty.resolveFields(pt); |
| 21282 | 21302 | const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); |
| 21283 | 21303 | const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern()); |
| ... | ... | @@ -21299,7 +21319,8 @@ fn zirFrame( |
| 21299 | 21319 | block: *Block, |
| 21300 | 21320 | extended: Zir.Inst.Extended.InstData, |
| 21301 | 21321 | ) CompileError!Air.Inst.Ref { |
| 21302 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 21322 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 21323 | const src = block.nodeOffset(src_node); | |
| 21303 | 21324 | return sema.failWithUseOfAsync(block, src); |
| 21304 | 21325 | } |
| 21305 | 21326 | |
| ... | ... | @@ -21553,13 +21574,13 @@ fn zirReify( |
| 21553 | 21574 | const tracked_inst = try block.trackZir(inst); |
| 21554 | 21575 | const src: LazySrcLoc = .{ |
| 21555 | 21576 | .base_node_inst = tracked_inst, |
| 21556 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 21577 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 21557 | 21578 | }; |
| 21558 | 21579 | const operand_src: LazySrcLoc = .{ |
| 21559 | 21580 | .base_node_inst = tracked_inst, |
| 21560 | 21581 | .offset = .{ |
| 21561 | 21582 | .node_offset_builtin_call_arg = .{ |
| 21562 | .builtin_call_node = 0, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 | |
| 21583 | .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0 | |
| 21563 | 21584 | .arg_index = 0, |
| 21564 | 21585 | }, |
| 21565 | 21586 | }, |
| ... | ... | @@ -22867,7 +22888,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C |
| 22867 | 22888 | } |
| 22868 | 22889 | |
| 22869 | 22890 | fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| 22870 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 22891 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 22892 | const src = block.nodeOffset(src_node); | |
| 22871 | 22893 | |
| 22872 | 22894 | const va_list_ty = try sema.getBuiltinType(src, .VaList); |
| 22873 | 22895 | try sema.requireRuntimeBlock(block, src, null); |
| ... | ... | @@ -24272,12 +24294,12 @@ fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 24272 | 24294 | fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 { |
| 24273 | 24295 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 24274 | 24296 | const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); |
| 24275 | const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); | |
| 24276 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); | |
| 24297 | const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0); | |
| 24298 | const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); | |
| 24277 | 24299 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 24278 | 24300 | |
| 24279 | const ty = try sema.resolveType(block, lhs_src, extra.lhs); | |
| 24280 | const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, .{ .simple = .field_name }); | |
| 24301 | const ty = try sema.resolveType(block, ty_src, extra.lhs); | |
| 24302 | const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name }); | |
| 24281 | 24303 | |
| 24282 | 24304 | const pt = sema.pt; |
| 24283 | 24305 | const zcu = pt.zcu; |
| ... | ... | @@ -24285,15 +24307,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 24285 | 24307 | try ty.resolveLayout(pt); |
| 24286 | 24308 | switch (ty.zigTypeTag(zcu)) { |
| 24287 | 24309 | .@"struct" => {}, |
| 24288 | else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(pt)}), | |
| 24310 | else => return sema.fail(block, ty_src, "expected struct type, found '{}'", .{ty.fmt(pt)}), | |
| 24289 | 24311 | } |
| 24290 | 24312 | |
| 24291 | 24313 | const field_index = if (ty.isTuple(zcu)) blk: { |
| 24292 | 24314 | if (field_name.eqlSlice("len", ip)) { |
| 24293 | 24315 | return sema.fail(block, src, "no offset available for 'len' field of tuple", .{}); |
| 24294 | 24316 | } |
| 24295 | break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src); | |
| 24296 | } else try sema.structFieldIndex(block, ty, field_name, rhs_src); | |
| 24317 | break :blk try sema.tupleFieldIndex(block, ty, field_name, field_name_src); | |
| 24318 | } else try sema.structFieldIndex(block, ty, field_name, field_name_src); | |
| 24297 | 24319 | |
| 24298 | 24320 | if (ty.structFieldIsComptime(field_index, zcu)) { |
| 24299 | 24321 | return sema.fail(block, src, "no offset available for comptime field", .{}); |
| ... | ... | @@ -25077,7 +25099,7 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 25077 | 25099 | fn analyzeShuffle( |
| 25078 | 25100 | sema: *Sema, |
| 25079 | 25101 | block: *Block, |
| 25080 | src_node: i32, | |
| 25102 | src_node: std.zig.Ast.Node.Offset, | |
| 25081 | 25103 | elem_ty: Type, |
| 25082 | 25104 | a_arg: Air.Inst.Ref, |
| 25083 | 25105 | b_arg: Air.Inst.Ref, |
| ... | ... | @@ -27004,7 +27026,8 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 27004 | 27026 | const gpa = zcu.gpa; |
| 27005 | 27027 | const ip = &zcu.intern_pool; |
| 27006 | 27028 | |
| 27007 | const src = block.nodeOffset(@bitCast(extended.operand)); | |
| 27029 | const src_node: std.zig.Ast.Node.Offset = @enumFromInt(@as(i32, @bitCast(extended.operand))); | |
| 27030 | const src = block.nodeOffset(src_node); | |
| 27008 | 27031 | const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); |
| 27009 | 27032 | |
| 27010 | 27033 | const ty = switch (value) { |
| ... | ... | @@ -29479,7 +29502,7 @@ const CoerceOpts = struct { |
| 29479 | 29502 | return .{ |
| 29480 | 29503 | .base_node_inst = func_inst, |
| 29481 | 29504 | .offset = .{ .fn_proto_param_type = .{ |
| 29482 | .fn_proto_node_offset = 0, | |
| 29505 | .fn_proto_node_offset = .zero, | |
| 29483 | 29506 | .param_index = info.param_i, |
| 29484 | 29507 | } }, |
| 29485 | 29508 | }; |
| ... | ... | @@ -30084,7 +30107,7 @@ fn coerceExtra( |
| 30084 | 30107 | |
| 30085 | 30108 | const ret_ty_src: LazySrcLoc = .{ |
| 30086 | 30109 | .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip), |
| 30087 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, | |
| 30110 | .offset = .{ .node_offset_fn_type_ret_ty = .zero }, | |
| 30088 | 30111 | }; |
| 30089 | 30112 | try sema.errNote(ret_ty_src, msg, "'noreturn' declared here", .{}); |
| 30090 | 30113 | break :msg msg; |
| ... | ... | @@ -30124,7 +30147,7 @@ fn coerceExtra( |
| 30124 | 30147 | { |
| 30125 | 30148 | const ret_ty_src: LazySrcLoc = .{ |
| 30126 | 30149 | .base_node_inst = ip.getNav(zcu.funcInfo(sema.func_index).owner_nav).srcInst(ip), |
| 30127 | .offset = .{ .node_offset_fn_type_ret_ty = 0 }, | |
| 30150 | .offset = .{ .node_offset_fn_type_ret_ty = .zero }, | |
| 30128 | 30151 | }; |
| 30129 | 30152 | if (inst_ty.isError(zcu) and !dest_ty.isError(zcu)) { |
| 30130 | 30153 | try sema.errNote(ret_ty_src, msg, "function cannot return an error", .{}); |
| ... | ... | @@ -32325,7 +32348,7 @@ pub fn ensureNavResolved(sema: *Sema, src: LazySrcLoc, nav_index: InternPool.Nav |
| 32325 | 32348 | if (zcu.analysis_in_progress.contains(anal_unit)) { |
| 32326 | 32349 | return sema.failWithOwnedErrorMsg(null, try sema.errMsg(.{ |
| 32327 | 32350 | .base_node_inst = nav.analysis.?.zir_index, |
| 32328 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 32351 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 32329 | 32352 | }, "dependency loop detected", .{})); |
| 32330 | 32353 | } |
| 32331 | 32354 | |
| ... | ... | @@ -33942,7 +33965,7 @@ const PeerTypeCandidateSrc = union(enum) { |
| 33942 | 33965 | /// index i in this slice |
| 33943 | 33966 | override: []const ?LazySrcLoc, |
| 33944 | 33967 | /// resolvePeerTypes originates from a @TypeOf(...) call |
| 33945 | typeof_builtin_call_node_offset: i32, | |
| 33968 | typeof_builtin_call_node_offset: std.zig.Ast.Node.Offset, | |
| 33946 | 33969 | |
| 33947 | 33970 | pub fn resolve( |
| 33948 | 33971 | self: PeerTypeCandidateSrc, |
| ... | ... | @@ -35545,7 +35568,7 @@ fn backingIntType( |
| 35545 | 35568 | |
| 35546 | 35569 | const backing_int_src: LazySrcLoc = .{ |
| 35547 | 35570 | .base_node_inst = struct_type.zir_index, |
| 35548 | .offset = .{ .node_offset_container_tag = 0 }, | |
| 35571 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 35549 | 35572 | }; |
| 35550 | 35573 | block.comptime_reason = .{ .reason = .{ |
| 35551 | 35574 | .src = backing_int_src, |
| ... | ... | @@ -35566,7 +35589,7 @@ fn backingIntType( |
| 35566 | 35589 | struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); |
| 35567 | 35590 | } else { |
| 35568 | 35591 | if (fields_bit_sum > std.math.maxInt(u16)) { |
| 35569 | return sema.fail(&block, block.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | |
| 35592 | return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | |
| 35570 | 35593 | } |
| 35571 | 35594 | const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum)); |
| 35572 | 35595 | struct_type.setBackingIntType(ip, backing_int_ty.toIntern()); |
| ... | ... | @@ -36167,7 +36190,7 @@ fn structFields( |
| 36167 | 36190 | .comptime_reason = .{ .reason = .{ |
| 36168 | 36191 | .src = .{ |
| 36169 | 36192 | .base_node_inst = struct_type.zir_index, |
| 36170 | .offset = .nodeOffset(0), | |
| 36193 | .offset = .nodeOffset(.zero), | |
| 36171 | 36194 | }, |
| 36172 | 36195 | .r = .{ .simple = .struct_fields }, |
| 36173 | 36196 | } }, |
| ... | ... | @@ -36508,7 +36531,7 @@ fn unionFields( |
| 36508 | 36531 | |
| 36509 | 36532 | const src: LazySrcLoc = .{ |
| 36510 | 36533 | .base_node_inst = union_type.zir_index, |
| 36511 | .offset = .nodeOffset(0), | |
| 36534 | .offset = .nodeOffset(.zero), | |
| 36512 | 36535 | }; |
| 36513 | 36536 | |
| 36514 | 36537 | var block_scope: Block = .{ |
| ... | ... | @@ -36537,7 +36560,7 @@ fn unionFields( |
| 36537 | 36560 | if (tag_type_ref != .none) { |
| 36538 | 36561 | const tag_ty_src: LazySrcLoc = .{ |
| 36539 | 36562 | .base_node_inst = union_type.zir_index, |
| 36540 | .offset = .{ .node_offset_container_tag = 0 }, | |
| 36563 | .offset = .{ .node_offset_container_tag = .zero }, | |
| 36541 | 36564 | }; |
| 36542 | 36565 | const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref); |
| 36543 | 36566 | if (small.auto_enum_tag) { |
| ... | ... | @@ -38512,7 +38535,7 @@ pub fn resolveDeclaredEnum( |
| 38512 | 38535 | const zcu = pt.zcu; |
| 38513 | 38536 | const gpa = zcu.gpa; |
| 38514 | 38537 | |
| 38515 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(0) }; | |
| 38538 | const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) }; | |
| 38516 | 38539 | |
| 38517 | 38540 | var arena: std.heap.ArenaAllocator = .init(gpa); |
| 38518 | 38541 | defer arena.deinit(); |
| ... | ... | @@ -38599,7 +38622,7 @@ fn resolveDeclaredEnumInner( |
| 38599 | 38622 | |
| 38600 | 38623 | const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable; |
| 38601 | 38624 | |
| 38602 | const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = 0 } }; | |
| 38625 | const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } }; | |
| 38603 | 38626 | |
| 38604 | 38627 | const int_tag_ty = ty: { |
| 38605 | 38628 | if (body.len != 0) { |
| ... | ... | @@ -38752,9 +38775,9 @@ pub fn resolveNavPtrModifiers( |
| 38752 | 38775 | const gpa = zcu.gpa; |
| 38753 | 38776 | const ip = &zcu.intern_pool; |
| 38754 | 38777 | |
| 38755 | const align_src = block.src(.{ .node_offset_var_decl_align = 0 }); | |
| 38756 | const section_src = block.src(.{ .node_offset_var_decl_section = 0 }); | |
| 38757 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 }); | |
| 38778 | const align_src = block.src(.{ .node_offset_var_decl_align = .zero }); | |
| 38779 | const section_src = block.src(.{ .node_offset_var_decl_section = .zero }); | |
| 38780 | const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = .zero }); | |
| 38758 | 38781 | |
| 38759 | 38782 | const alignment: InternPool.Alignment = a: { |
| 38760 | 38783 | const align_body = zir_decl.align_body orelse break :a .none; |
| ... | ... | @@ -38827,7 +38850,7 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38827 | 38850 | |
| 38828 | 38851 | const src: LazySrcLoc = .{ |
| 38829 | 38852 | .base_node_inst = ip.getNav(nav).srcInst(ip), |
| 38830 | .offset = .nodeOffset(0), | |
| 38853 | .offset = .nodeOffset(.zero), | |
| 38831 | 38854 | }; |
| 38832 | 38855 | |
| 38833 | 38856 | const result = try sema.analyzeNavVal(block, src, nav); |
src/Type.zig+1-1| ... | ... | @@ -3505,7 +3505,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc { |
| 3505 | 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+278-295| ... | ... | @@ -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, |
| ... | ... | @@ -1031,10 +1031,6 @@ pub const SrcLoc = struct { |
| 1031 | 1031 | return tree.firstToken(src_loc.base_node); |
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | pub fn relativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index { | |
| 1035 | return @bitCast(offset + @as(i32, @bitCast(src_loc.base_node))); | |
| 1036 | } | |
| 1037 | ||
| 1038 | 1034 | pub const Span = Ast.Span; |
| 1039 | 1035 | |
| 1040 | 1036 | pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { |
| ... | ... | @@ -1046,7 +1042,7 @@ pub const SrcLoc = struct { |
| 1046 | 1042 | |
| 1047 | 1043 | .token_abs => |tok_index| { |
| 1048 | 1044 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1049 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1045 | const start = tree.tokenStart(tok_index); | |
| 1050 | 1046 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1051 | 1047 | return Span{ .start = start, .end = end, .main = start }; |
| 1052 | 1048 | }, |
| ... | ... | @@ -1057,133 +1053,137 @@ pub const SrcLoc = struct { |
| 1057 | 1053 | .byte_offset => |byte_off| { |
| 1058 | 1054 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1059 | 1055 | const tok_index = src_loc.baseSrcToken(); |
| 1060 | const start = tree.tokens.items(.start)[tok_index] + byte_off; | |
| 1056 | const start = tree.tokenStart(tok_index) + byte_off; | |
| 1061 | 1057 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1062 | 1058 | return Span{ .start = start, .end = end, .main = start }; |
| 1063 | 1059 | }, |
| 1064 | 1060 | .token_offset => |tok_off| { |
| 1065 | 1061 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1066 | const tok_index = src_loc.baseSrcToken() + tok_off; | |
| 1067 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1062 | const tok_index = tok_off.toAbsolute(src_loc.baseSrcToken()); | |
| 1063 | const start = tree.tokenStart(tok_index); | |
| 1068 | 1064 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1069 | 1065 | return Span{ .start = start, .end = end, .main = start }; |
| 1070 | 1066 | }, |
| 1071 | 1067 | .node_offset => |traced_off| { |
| 1072 | 1068 | const node_off = traced_off.x; |
| 1073 | 1069 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1074 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1070 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1075 | 1071 | return tree.nodeToSpan(node); |
| 1076 | 1072 | }, |
| 1077 | 1073 | .node_offset_main_token => |node_off| { |
| 1078 | 1074 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1079 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1080 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 1075 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1076 | const main_token = tree.nodeMainToken(node); | |
| 1081 | 1077 | return tree.tokensToSpan(main_token, main_token, main_token); |
| 1082 | 1078 | }, |
| 1083 | 1079 | .node_offset_bin_op => |node_off| { |
| 1084 | 1080 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1085 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1081 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1086 | 1082 | return tree.nodeToSpan(node); |
| 1087 | 1083 | }, |
| 1088 | 1084 | .node_offset_initializer => |node_off| { |
| 1089 | 1085 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1090 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1086 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1091 | 1087 | return tree.tokensToSpan( |
| 1092 | 1088 | tree.firstToken(node) - 3, |
| 1093 | 1089 | tree.lastToken(node), |
| 1094 | tree.nodes.items(.main_token)[node] - 2, | |
| 1090 | tree.nodeMainToken(node) - 2, | |
| 1095 | 1091 | ); |
| 1096 | 1092 | }, |
| 1097 | 1093 | .node_offset_var_decl_ty => |node_off| { |
| 1098 | 1094 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1099 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1100 | const node_tags = tree.nodes.items(.tag); | |
| 1101 | const full = switch (node_tags[node]) { | |
| 1095 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1096 | const full = switch (tree.nodeTag(node)) { | |
| 1102 | 1097 | .global_var_decl, |
| 1103 | 1098 | .local_var_decl, |
| 1104 | 1099 | .simple_var_decl, |
| 1105 | 1100 | .aligned_var_decl, |
| 1106 | 1101 | => tree.fullVarDecl(node).?, |
| 1107 | 1102 | .@"usingnamespace" => { |
| 1108 | const node_data = tree.nodes.items(.data); | |
| 1109 | return tree.nodeToSpan(node_data[node].lhs); | |
| 1103 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1110 | 1104 | }, |
| 1111 | 1105 | else => unreachable, |
| 1112 | 1106 | }; |
| 1113 | if (full.ast.type_node != 0) { | |
| 1114 | return tree.nodeToSpan(full.ast.type_node); | |
| 1107 | if (full.ast.type_node.unwrap()) |type_node| { | |
| 1108 | return tree.nodeToSpan(type_node); | |
| 1115 | 1109 | } |
| 1116 | 1110 | const tok_index = full.ast.mut_token + 1; // the name token |
| 1117 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1111 | const start = tree.tokenStart(tok_index); | |
| 1118 | 1112 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1119 | 1113 | return Span{ .start = start, .end = end, .main = start }; |
| 1120 | 1114 | }, |
| 1121 | 1115 | .node_offset_var_decl_align => |node_off| { |
| 1122 | 1116 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1123 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1117 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1124 | 1118 | var buf: [1]Ast.Node.Index = undefined; |
| 1125 | 1119 | const align_node = if (tree.fullVarDecl(node)) |v| |
| 1126 | v.ast.align_node | |
| 1120 | v.ast.align_node.unwrap().? | |
| 1127 | 1121 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1128 | f.ast.align_expr | |
| 1122 | f.ast.align_expr.unwrap().? | |
| 1129 | 1123 | else |
| 1130 | 1124 | unreachable; |
| 1131 | 1125 | return tree.nodeToSpan(align_node); |
| 1132 | 1126 | }, |
| 1133 | 1127 | .node_offset_var_decl_section => |node_off| { |
| 1134 | 1128 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1135 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1129 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1136 | 1130 | var buf: [1]Ast.Node.Index = undefined; |
| 1137 | 1131 | const section_node = if (tree.fullVarDecl(node)) |v| |
| 1138 | v.ast.section_node | |
| 1132 | v.ast.section_node.unwrap().? | |
| 1139 | 1133 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1140 | f.ast.section_expr | |
| 1134 | f.ast.section_expr.unwrap().? | |
| 1141 | 1135 | else |
| 1142 | 1136 | unreachable; |
| 1143 | 1137 | return tree.nodeToSpan(section_node); |
| 1144 | 1138 | }, |
| 1145 | 1139 | .node_offset_var_decl_addrspace => |node_off| { |
| 1146 | 1140 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1147 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1141 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1148 | 1142 | var buf: [1]Ast.Node.Index = undefined; |
| 1149 | 1143 | const addrspace_node = if (tree.fullVarDecl(node)) |v| |
| 1150 | v.ast.addrspace_node | |
| 1144 | v.ast.addrspace_node.unwrap().? | |
| 1151 | 1145 | else if (tree.fullFnProto(&buf, node)) |f| |
| 1152 | f.ast.addrspace_expr | |
| 1146 | f.ast.addrspace_expr.unwrap().? | |
| 1153 | 1147 | else |
| 1154 | 1148 | unreachable; |
| 1155 | 1149 | return tree.nodeToSpan(addrspace_node); |
| 1156 | 1150 | }, |
| 1157 | 1151 | .node_offset_var_decl_init => |node_off| { |
| 1158 | 1152 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1159 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1160 | const full = tree.fullVarDecl(node).?; | |
| 1161 | return tree.nodeToSpan(full.ast.init_node); | |
| 1153 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1154 | const init_node = switch (tree.nodeTag(node)) { | |
| 1155 | .global_var_decl, | |
| 1156 | .local_var_decl, | |
| 1157 | .aligned_var_decl, | |
| 1158 | .simple_var_decl, | |
| 1159 | => tree.fullVarDecl(node).?.ast.init_node.unwrap().?, | |
| 1160 | .assign_destructure => tree.assignDestructure(node).ast.value_expr, | |
| 1161 | else => unreachable, | |
| 1162 | }; | |
| 1163 | return tree.nodeToSpan(init_node); | |
| 1162 | 1164 | }, |
| 1163 | 1165 | .node_offset_builtin_call_arg => |builtin_arg| { |
| 1164 | 1166 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1165 | const node = src_loc.relativeToNodeIndex(builtin_arg.builtin_call_node); | |
| 1167 | const node = builtin_arg.builtin_call_node.toAbsolute(src_loc.base_node); | |
| 1166 | 1168 | var buf: [2]Ast.Node.Index = undefined; |
| 1167 | 1169 | const params = tree.builtinCallParams(&buf, node).?; |
| 1168 | 1170 | return tree.nodeToSpan(params[builtin_arg.arg_index]); |
| 1169 | 1171 | }, |
| 1170 | 1172 | .node_offset_ptrcast_operand => |node_off| { |
| 1171 | 1173 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1172 | const main_tokens = tree.nodes.items(.main_token); | |
| 1173 | const node_datas = tree.nodes.items(.data); | |
| 1174 | const node_tags = tree.nodes.items(.tag); | |
| 1175 | 1174 | |
| 1176 | var node = src_loc.relativeToNodeIndex(node_off); | |
| 1175 | var node = node_off.toAbsolute(src_loc.base_node); | |
| 1177 | 1176 | while (true) { |
| 1178 | switch (node_tags[node]) { | |
| 1177 | switch (tree.nodeTag(node)) { | |
| 1179 | 1178 | .builtin_call_two, .builtin_call_two_comma => {}, |
| 1180 | 1179 | else => break, |
| 1181 | 1180 | } |
| 1182 | 1181 | |
| 1183 | if (node_datas[node].lhs == 0) break; // 0 args | |
| 1184 | if (node_datas[node].rhs != 0) break; // 2 args | |
| 1182 | const first_arg, const second_arg = tree.nodeData(node).opt_node_and_opt_node; | |
| 1183 | if (first_arg == .none) break; // 0 args | |
| 1184 | if (second_arg != .none) break; // 2 args | |
| 1185 | 1185 | |
| 1186 | const builtin_token = main_tokens[node]; | |
| 1186 | const builtin_token = tree.nodeMainToken(node); | |
| 1187 | 1187 | const builtin_name = tree.tokenSlice(builtin_token); |
| 1188 | 1188 | const info = BuiltinFn.list.get(builtin_name) orelse break; |
| 1189 | 1189 | |
| ... | ... | @@ -1197,16 +1197,15 @@ pub const SrcLoc = struct { |
| 1197 | 1197 | => {}, |
| 1198 | 1198 | } |
| 1199 | 1199 | |
| 1200 | node = node_datas[node].lhs; | |
| 1200 | node = first_arg.unwrap().?; | |
| 1201 | 1201 | } |
| 1202 | 1202 | |
| 1203 | 1203 | return tree.nodeToSpan(node); |
| 1204 | 1204 | }, |
| 1205 | 1205 | .node_offset_array_access_index => |node_off| { |
| 1206 | 1206 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1207 | const node_datas = tree.nodes.items(.data); | |
| 1208 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1209 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1207 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1208 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1210 | 1209 | }, |
| 1211 | 1210 | .node_offset_slice_ptr, |
| 1212 | 1211 | .node_offset_slice_start, |
| ... | ... | @@ -1214,32 +1213,30 @@ pub const SrcLoc = struct { |
| 1214 | 1213 | .node_offset_slice_sentinel, |
| 1215 | 1214 | => |node_off| { |
| 1216 | 1215 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1217 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1216 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1218 | 1217 | const full = tree.fullSlice(node).?; |
| 1219 | 1218 | const part_node = switch (src_loc.lazy) { |
| 1220 | 1219 | .node_offset_slice_ptr => full.ast.sliced, |
| 1221 | 1220 | .node_offset_slice_start => full.ast.start, |
| 1222 | .node_offset_slice_end => full.ast.end, | |
| 1223 | .node_offset_slice_sentinel => full.ast.sentinel, | |
| 1221 | .node_offset_slice_end => full.ast.end.unwrap().?, | |
| 1222 | .node_offset_slice_sentinel => full.ast.sentinel.unwrap().?, | |
| 1224 | 1223 | else => unreachable, |
| 1225 | 1224 | }; |
| 1226 | 1225 | return tree.nodeToSpan(part_node); |
| 1227 | 1226 | }, |
| 1228 | 1227 | .node_offset_call_func => |node_off| { |
| 1229 | 1228 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1230 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1229 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1231 | 1230 | var buf: [1]Ast.Node.Index = undefined; |
| 1232 | 1231 | const full = tree.fullCall(&buf, node).?; |
| 1233 | 1232 | return tree.nodeToSpan(full.ast.fn_expr); |
| 1234 | 1233 | }, |
| 1235 | 1234 | .node_offset_field_name => |node_off| { |
| 1236 | 1235 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1237 | const node_datas = tree.nodes.items(.data); | |
| 1238 | const node_tags = tree.nodes.items(.tag); | |
| 1239 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1236 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1240 | 1237 | var buf: [1]Ast.Node.Index = undefined; |
| 1241 | const tok_index = switch (node_tags[node]) { | |
| 1242 | .field_access => node_datas[node].rhs, | |
| 1238 | const tok_index = switch (tree.nodeTag(node)) { | |
| 1239 | .field_access => tree.nodeData(node).node_and_token[1], | |
| 1243 | 1240 | .call_one, |
| 1244 | 1241 | .call_one_comma, |
| 1245 | 1242 | .async_call_one, |
| ... | ... | @@ -1254,43 +1251,41 @@ pub const SrcLoc = struct { |
| 1254 | 1251 | }, |
| 1255 | 1252 | else => tree.firstToken(node) - 2, |
| 1256 | 1253 | }; |
| 1257 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1254 | const start = tree.tokenStart(tok_index); | |
| 1258 | 1255 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1259 | 1256 | return Span{ .start = start, .end = end, .main = start }; |
| 1260 | 1257 | }, |
| 1261 | 1258 | .node_offset_field_name_init => |node_off| { |
| 1262 | 1259 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1263 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1260 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1264 | 1261 | const tok_index = tree.firstToken(node) - 2; |
| 1265 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1262 | const start = tree.tokenStart(tok_index); | |
| 1266 | 1263 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1267 | 1264 | return Span{ .start = start, .end = end, .main = start }; |
| 1268 | 1265 | }, |
| 1269 | 1266 | .node_offset_deref_ptr => |node_off| { |
| 1270 | 1267 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1271 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1268 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1272 | 1269 | return tree.nodeToSpan(node); |
| 1273 | 1270 | }, |
| 1274 | 1271 | .node_offset_asm_source => |node_off| { |
| 1275 | 1272 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1276 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1273 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1277 | 1274 | const full = tree.fullAsm(node).?; |
| 1278 | 1275 | return tree.nodeToSpan(full.ast.template); |
| 1279 | 1276 | }, |
| 1280 | 1277 | .node_offset_asm_ret_ty => |node_off| { |
| 1281 | 1278 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1282 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1279 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1283 | 1280 | const full = tree.fullAsm(node).?; |
| 1284 | 1281 | const asm_output = full.outputs[0]; |
| 1285 | const node_datas = tree.nodes.items(.data); | |
| 1286 | return tree.nodeToSpan(node_datas[asm_output].lhs); | |
| 1282 | return tree.nodeToSpan(tree.nodeData(asm_output).opt_node_and_token[0].unwrap().?); | |
| 1287 | 1283 | }, |
| 1288 | 1284 | |
| 1289 | 1285 | .node_offset_if_cond => |node_off| { |
| 1290 | 1286 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1291 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1292 | const node_tags = tree.nodes.items(.tag); | |
| 1293 | const src_node = switch (node_tags[node]) { | |
| 1287 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1288 | const src_node = switch (tree.nodeTag(node)) { | |
| 1294 | 1289 | .if_simple, |
| 1295 | 1290 | .@"if", |
| 1296 | 1291 | => tree.fullIf(node).?.ast.cond_expr, |
| ... | ... | @@ -1317,20 +1312,19 @@ pub const SrcLoc = struct { |
| 1317 | 1312 | }, |
| 1318 | 1313 | .for_input => |for_input| { |
| 1319 | 1314 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1320 | const node = src_loc.relativeToNodeIndex(for_input.for_node_offset); | |
| 1315 | const node = for_input.for_node_offset.toAbsolute(src_loc.base_node); | |
| 1321 | 1316 | const for_full = tree.fullFor(node).?; |
| 1322 | 1317 | const src_node = for_full.ast.inputs[for_input.input_index]; |
| 1323 | 1318 | return tree.nodeToSpan(src_node); |
| 1324 | 1319 | }, |
| 1325 | 1320 | .for_capture_from_input => |node_off| { |
| 1326 | 1321 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1327 | const token_tags = tree.tokens.items(.tag); | |
| 1328 | const input_node = src_loc.relativeToNodeIndex(node_off); | |
| 1322 | const input_node = node_off.toAbsolute(src_loc.base_node); | |
| 1329 | 1323 | // We have to actually linear scan the whole AST to find the for loop |
| 1330 | 1324 | // that contains this input. |
| 1331 | 1325 | const node_tags = tree.nodes.items(.tag); |
| 1332 | 1326 | for (node_tags, 0..) |node_tag, node_usize| { |
| 1333 | const node = @as(Ast.Node.Index, @intCast(node_usize)); | |
| 1327 | const node: Ast.Node.Index = @enumFromInt(node_usize); | |
| 1334 | 1328 | switch (node_tag) { |
| 1335 | 1329 | .for_simple, .@"for" => { |
| 1336 | 1330 | const for_full = tree.fullFor(node).?; |
| ... | ... | @@ -1339,7 +1333,7 @@ pub const SrcLoc = struct { |
| 1339 | 1333 | var count = input_index; |
| 1340 | 1334 | var tok = for_full.payload_token; |
| 1341 | 1335 | while (true) { |
| 1342 | switch (token_tags[tok]) { | |
| 1336 | switch (tree.tokenTag(tok)) { | |
| 1343 | 1337 | .comma => { |
| 1344 | 1338 | count -= 1; |
| 1345 | 1339 | tok += 1; |
| ... | ... | @@ -1366,13 +1360,12 @@ pub const SrcLoc = struct { |
| 1366 | 1360 | }, |
| 1367 | 1361 | .call_arg => |call_arg| { |
| 1368 | 1362 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1369 | const node = src_loc.relativeToNodeIndex(call_arg.call_node_offset); | |
| 1363 | const node = call_arg.call_node_offset.toAbsolute(src_loc.base_node); | |
| 1370 | 1364 | var buf: [2]Ast.Node.Index = undefined; |
| 1371 | 1365 | const call_full = tree.fullCall(buf[0..1], node) orelse { |
| 1372 | const node_tags = tree.nodes.items(.tag); | |
| 1373 | assert(node_tags[node] == .builtin_call); | |
| 1374 | const call_args_node = tree.extra_data[tree.nodes.items(.data)[node].rhs - 1]; | |
| 1375 | switch (node_tags[call_args_node]) { | |
| 1366 | assert(tree.nodeTag(node) == .builtin_call); | |
| 1367 | const call_args_node: Ast.Node.Index = @enumFromInt(tree.extra_data[@intFromEnum(tree.nodeData(node).extra_range.end) - 1]); | |
| 1368 | switch (tree.nodeTag(call_args_node)) { | |
| 1376 | 1369 | .array_init_one, |
| 1377 | 1370 | .array_init_one_comma, |
| 1378 | 1371 | .array_init_dot_two, |
| ... | ... | @@ -1404,7 +1397,7 @@ pub const SrcLoc = struct { |
| 1404 | 1397 | }, |
| 1405 | 1398 | .fn_proto_param, .fn_proto_param_type => |fn_proto_param| { |
| 1406 | 1399 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1407 | const node = src_loc.relativeToNodeIndex(fn_proto_param.fn_proto_node_offset); | |
| 1400 | const node = fn_proto_param.fn_proto_node_offset.toAbsolute(src_loc.base_node); | |
| 1408 | 1401 | var buf: [1]Ast.Node.Index = undefined; |
| 1409 | 1402 | const full = tree.fullFnProto(&buf, node).?; |
| 1410 | 1403 | var it = full.iterate(tree); |
| ... | ... | @@ -1416,14 +1409,14 @@ pub const SrcLoc = struct { |
| 1416 | 1409 | .fn_proto_param_type => if (param.anytype_ellipsis3) |tok| { |
| 1417 | 1410 | return tree.tokenToSpan(tok); |
| 1418 | 1411 | } else { |
| 1419 | return tree.nodeToSpan(param.type_expr); | |
| 1412 | return tree.nodeToSpan(param.type_expr.?); | |
| 1420 | 1413 | }, |
| 1421 | 1414 | .fn_proto_param => if (param.anytype_ellipsis3) |tok| { |
| 1422 | 1415 | const first = param.comptime_noalias orelse param.name_token orelse tok; |
| 1423 | 1416 | return tree.tokensToSpan(first, tok, first); |
| 1424 | 1417 | } else { |
| 1425 | const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr); | |
| 1426 | return tree.tokensToSpan(first, tree.lastToken(param.type_expr), first); | |
| 1418 | const first = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr.?); | |
| 1419 | return tree.tokensToSpan(first, tree.lastToken(param.type_expr.?), first); | |
| 1427 | 1420 | }, |
| 1428 | 1421 | else => unreachable, |
| 1429 | 1422 | } |
| ... | ... | @@ -1432,28 +1425,24 @@ pub const SrcLoc = struct { |
| 1432 | 1425 | }, |
| 1433 | 1426 | .node_offset_bin_lhs => |node_off| { |
| 1434 | 1427 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1435 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1436 | const node_datas = tree.nodes.items(.data); | |
| 1437 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1428 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1429 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]); | |
| 1438 | 1430 | }, |
| 1439 | 1431 | .node_offset_bin_rhs => |node_off| { |
| 1440 | 1432 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1441 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1442 | const node_datas = tree.nodes.items(.data); | |
| 1443 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1433 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1434 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1444 | 1435 | }, |
| 1445 | 1436 | .array_cat_lhs, .array_cat_rhs => |cat| { |
| 1446 | 1437 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1447 | const node = src_loc.relativeToNodeIndex(cat.array_cat_offset); | |
| 1448 | const node_datas = tree.nodes.items(.data); | |
| 1438 | const node = cat.array_cat_offset.toAbsolute(src_loc.base_node); | |
| 1449 | 1439 | const arr_node = if (src_loc.lazy == .array_cat_lhs) |
| 1450 | node_datas[node].lhs | |
| 1440 | tree.nodeData(node).node_and_node[0] | |
| 1451 | 1441 | else |
| 1452 | node_datas[node].rhs; | |
| 1442 | tree.nodeData(node).node_and_node[1]; | |
| 1453 | 1443 | |
| 1454 | const node_tags = tree.nodes.items(.tag); | |
| 1455 | 1444 | var buf: [2]Ast.Node.Index = undefined; |
| 1456 | switch (node_tags[arr_node]) { | |
| 1445 | switch (tree.nodeTag(arr_node)) { | |
| 1457 | 1446 | .array_init_one, |
| 1458 | 1447 | .array_init_one_comma, |
| 1459 | 1448 | .array_init_dot_two, |
| ... | ... | @@ -1470,27 +1459,30 @@ pub const SrcLoc = struct { |
| 1470 | 1459 | } |
| 1471 | 1460 | }, |
| 1472 | 1461 | |
| 1462 | .node_offset_try_operand => |node_off| { | |
| 1463 | const tree = try src_loc.file_scope.getTree(gpa); | |
| 1464 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1465 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1466 | }, | |
| 1467 | ||
| 1473 | 1468 | .node_offset_switch_operand => |node_off| { |
| 1474 | 1469 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1475 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1476 | const node_datas = tree.nodes.items(.data); | |
| 1477 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1470 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1471 | const condition, _ = tree.nodeData(node).node_and_extra; | |
| 1472 | return tree.nodeToSpan(condition); | |
| 1478 | 1473 | }, |
| 1479 | 1474 | |
| 1480 | 1475 | .node_offset_switch_special_prong => |node_off| { |
| 1481 | 1476 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1482 | const switch_node = src_loc.relativeToNodeIndex(node_off); | |
| 1483 | const node_datas = tree.nodes.items(.data); | |
| 1484 | const node_tags = tree.nodes.items(.tag); | |
| 1485 | const main_tokens = tree.nodes.items(.main_token); | |
| 1486 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1487 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1477 | const switch_node = node_off.toAbsolute(src_loc.base_node); | |
| 1478 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1479 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1488 | 1480 | for (case_nodes) |case_node| { |
| 1489 | 1481 | const case = tree.fullSwitchCase(case_node).?; |
| 1490 | 1482 | const is_special = (case.ast.values.len == 0) or |
| 1491 | 1483 | (case.ast.values.len == 1 and |
| 1492 | node_tags[case.ast.values[0]] == .identifier and | |
| 1493 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); | |
| 1484 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 1485 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")); | |
| 1494 | 1486 | if (!is_special) continue; |
| 1495 | 1487 | |
| 1496 | 1488 | return tree.nodeToSpan(case_node); |
| ... | ... | @@ -1499,22 +1491,19 @@ pub const SrcLoc = struct { |
| 1499 | 1491 | |
| 1500 | 1492 | .node_offset_switch_range => |node_off| { |
| 1501 | 1493 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1502 | const switch_node = src_loc.relativeToNodeIndex(node_off); | |
| 1503 | const node_datas = tree.nodes.items(.data); | |
| 1504 | const node_tags = tree.nodes.items(.tag); | |
| 1505 | const main_tokens = tree.nodes.items(.main_token); | |
| 1506 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1507 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1494 | const switch_node = node_off.toAbsolute(src_loc.base_node); | |
| 1495 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1496 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1508 | 1497 | for (case_nodes) |case_node| { |
| 1509 | 1498 | const case = tree.fullSwitchCase(case_node).?; |
| 1510 | 1499 | const is_special = (case.ast.values.len == 0) or |
| 1511 | 1500 | (case.ast.values.len == 1 and |
| 1512 | node_tags[case.ast.values[0]] == .identifier and | |
| 1513 | mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); | |
| 1501 | tree.nodeTag(case.ast.values[0]) == .identifier and | |
| 1502 | mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_")); | |
| 1514 | 1503 | if (is_special) continue; |
| 1515 | 1504 | |
| 1516 | 1505 | for (case.ast.values) |item_node| { |
| 1517 | if (node_tags[item_node] == .switch_range) { | |
| 1506 | if (tree.nodeTag(item_node) == .switch_range) { | |
| 1518 | 1507 | return tree.nodeToSpan(item_node); |
| 1519 | 1508 | } |
| 1520 | 1509 | } |
| ... | ... | @@ -1522,47 +1511,46 @@ pub const SrcLoc = struct { |
| 1522 | 1511 | }, |
| 1523 | 1512 | .node_offset_fn_type_align => |node_off| { |
| 1524 | 1513 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1525 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1514 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1526 | 1515 | var buf: [1]Ast.Node.Index = undefined; |
| 1527 | 1516 | const full = tree.fullFnProto(&buf, node).?; |
| 1528 | return tree.nodeToSpan(full.ast.align_expr); | |
| 1517 | return tree.nodeToSpan(full.ast.align_expr.unwrap().?); | |
| 1529 | 1518 | }, |
| 1530 | 1519 | .node_offset_fn_type_addrspace => |node_off| { |
| 1531 | 1520 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1532 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1521 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1533 | 1522 | var buf: [1]Ast.Node.Index = undefined; |
| 1534 | 1523 | const full = tree.fullFnProto(&buf, node).?; |
| 1535 | return tree.nodeToSpan(full.ast.addrspace_expr); | |
| 1524 | return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?); | |
| 1536 | 1525 | }, |
| 1537 | 1526 | .node_offset_fn_type_section => |node_off| { |
| 1538 | 1527 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1539 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1528 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1540 | 1529 | var buf: [1]Ast.Node.Index = undefined; |
| 1541 | 1530 | const full = tree.fullFnProto(&buf, node).?; |
| 1542 | return tree.nodeToSpan(full.ast.section_expr); | |
| 1531 | return tree.nodeToSpan(full.ast.section_expr.unwrap().?); | |
| 1543 | 1532 | }, |
| 1544 | 1533 | .node_offset_fn_type_cc => |node_off| { |
| 1545 | 1534 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1546 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1535 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1547 | 1536 | var buf: [1]Ast.Node.Index = undefined; |
| 1548 | 1537 | const full = tree.fullFnProto(&buf, node).?; |
| 1549 | return tree.nodeToSpan(full.ast.callconv_expr); | |
| 1538 | return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?); | |
| 1550 | 1539 | }, |
| 1551 | 1540 | |
| 1552 | 1541 | .node_offset_fn_type_ret_ty => |node_off| { |
| 1553 | 1542 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1554 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1543 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1555 | 1544 | var buf: [1]Ast.Node.Index = undefined; |
| 1556 | 1545 | const full = tree.fullFnProto(&buf, node).?; |
| 1557 | return tree.nodeToSpan(full.ast.return_type); | |
| 1546 | return tree.nodeToSpan(full.ast.return_type.unwrap().?); | |
| 1558 | 1547 | }, |
| 1559 | 1548 | .node_offset_param => |node_off| { |
| 1560 | 1549 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1561 | const token_tags = tree.tokens.items(.tag); | |
| 1562 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1550 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1563 | 1551 | |
| 1564 | 1552 | var first_tok = tree.firstToken(node); |
| 1565 | while (true) switch (token_tags[first_tok - 1]) { | |
| 1553 | while (true) switch (tree.tokenTag(first_tok - 1)) { | |
| 1566 | 1554 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1567 | 1555 | else => break, |
| 1568 | 1556 | }; |
| ... | ... | @@ -1574,12 +1562,11 @@ pub const SrcLoc = struct { |
| 1574 | 1562 | }, |
| 1575 | 1563 | .token_offset_param => |token_off| { |
| 1576 | 1564 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1577 | const token_tags = tree.tokens.items(.tag); | |
| 1578 | const main_token = tree.nodes.items(.main_token)[src_loc.base_node]; | |
| 1579 | const tok_index = @as(Ast.TokenIndex, @bitCast(token_off + @as(i32, @bitCast(main_token)))); | |
| 1565 | const main_token = tree.nodeMainToken(src_loc.base_node); | |
| 1566 | const tok_index = token_off.toAbsolute(main_token); | |
| 1580 | 1567 | |
| 1581 | 1568 | var first_tok = tok_index; |
| 1582 | while (true) switch (token_tags[first_tok - 1]) { | |
| 1569 | while (true) switch (tree.tokenTag(first_tok - 1)) { | |
| 1583 | 1570 | .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, |
| 1584 | 1571 | else => break, |
| 1585 | 1572 | }; |
| ... | ... | @@ -1592,109 +1579,108 @@ pub const SrcLoc = struct { |
| 1592 | 1579 | |
| 1593 | 1580 | .node_offset_anyframe_type => |node_off| { |
| 1594 | 1581 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1595 | const node_datas = tree.nodes.items(.data); | |
| 1596 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1597 | return tree.nodeToSpan(node_datas[parent_node].rhs); | |
| 1582 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1583 | _, const child_type = tree.nodeData(parent_node).token_and_node; | |
| 1584 | return tree.nodeToSpan(child_type); | |
| 1598 | 1585 | }, |
| 1599 | 1586 | |
| 1600 | 1587 | .node_offset_lib_name => |node_off| { |
| 1601 | 1588 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1602 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1589 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1603 | 1590 | var buf: [1]Ast.Node.Index = undefined; |
| 1604 | 1591 | const full = tree.fullFnProto(&buf, parent_node).?; |
| 1605 | 1592 | const tok_index = full.lib_name.?; |
| 1606 | const start = tree.tokens.items(.start)[tok_index]; | |
| 1593 | const start = tree.tokenStart(tok_index); | |
| 1607 | 1594 | const end = start + @as(u32, @intCast(tree.tokenSlice(tok_index).len)); |
| 1608 | 1595 | return Span{ .start = start, .end = end, .main = start }; |
| 1609 | 1596 | }, |
| 1610 | 1597 | |
| 1611 | 1598 | .node_offset_array_type_len => |node_off| { |
| 1612 | 1599 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1613 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1600 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1614 | 1601 | |
| 1615 | 1602 | const full = tree.fullArrayType(parent_node).?; |
| 1616 | 1603 | return tree.nodeToSpan(full.ast.elem_count); |
| 1617 | 1604 | }, |
| 1618 | 1605 | .node_offset_array_type_sentinel => |node_off| { |
| 1619 | 1606 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1620 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1607 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1621 | 1608 | |
| 1622 | 1609 | const full = tree.fullArrayType(parent_node).?; |
| 1623 | return tree.nodeToSpan(full.ast.sentinel); | |
| 1610 | return tree.nodeToSpan(full.ast.sentinel.unwrap().?); | |
| 1624 | 1611 | }, |
| 1625 | 1612 | .node_offset_array_type_elem => |node_off| { |
| 1626 | 1613 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1627 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1614 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1628 | 1615 | |
| 1629 | 1616 | const full = tree.fullArrayType(parent_node).?; |
| 1630 | 1617 | return tree.nodeToSpan(full.ast.elem_type); |
| 1631 | 1618 | }, |
| 1632 | 1619 | .node_offset_un_op => |node_off| { |
| 1633 | 1620 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1634 | const node_datas = tree.nodes.items(.data); | |
| 1635 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1636 | ||
| 1637 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1621 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1622 | return tree.nodeToSpan(tree.nodeData(node).node); | |
| 1638 | 1623 | }, |
| 1639 | 1624 | .node_offset_ptr_elem => |node_off| { |
| 1640 | 1625 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1641 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1626 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1642 | 1627 | |
| 1643 | 1628 | const full = tree.fullPtrType(parent_node).?; |
| 1644 | 1629 | return tree.nodeToSpan(full.ast.child_type); |
| 1645 | 1630 | }, |
| 1646 | 1631 | .node_offset_ptr_sentinel => |node_off| { |
| 1647 | 1632 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1648 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1633 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1649 | 1634 | |
| 1650 | 1635 | const full = tree.fullPtrType(parent_node).?; |
| 1651 | return tree.nodeToSpan(full.ast.sentinel); | |
| 1636 | return tree.nodeToSpan(full.ast.sentinel.unwrap().?); | |
| 1652 | 1637 | }, |
| 1653 | 1638 | .node_offset_ptr_align => |node_off| { |
| 1654 | 1639 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1655 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1640 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1656 | 1641 | |
| 1657 | 1642 | const full = tree.fullPtrType(parent_node).?; |
| 1658 | return tree.nodeToSpan(full.ast.align_node); | |
| 1643 | return tree.nodeToSpan(full.ast.align_node.unwrap().?); | |
| 1659 | 1644 | }, |
| 1660 | 1645 | .node_offset_ptr_addrspace => |node_off| { |
| 1661 | 1646 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1662 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1647 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1663 | 1648 | |
| 1664 | 1649 | const full = tree.fullPtrType(parent_node).?; |
| 1665 | return tree.nodeToSpan(full.ast.addrspace_node); | |
| 1650 | return tree.nodeToSpan(full.ast.addrspace_node.unwrap().?); | |
| 1666 | 1651 | }, |
| 1667 | 1652 | .node_offset_ptr_bitoffset => |node_off| { |
| 1668 | 1653 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1669 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1654 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1670 | 1655 | |
| 1671 | 1656 | const full = tree.fullPtrType(parent_node).?; |
| 1672 | return tree.nodeToSpan(full.ast.bit_range_start); | |
| 1657 | return tree.nodeToSpan(full.ast.bit_range_start.unwrap().?); | |
| 1673 | 1658 | }, |
| 1674 | 1659 | .node_offset_ptr_hostsize => |node_off| { |
| 1675 | 1660 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1676 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1661 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1677 | 1662 | |
| 1678 | 1663 | const full = tree.fullPtrType(parent_node).?; |
| 1679 | return tree.nodeToSpan(full.ast.bit_range_end); | |
| 1664 | return tree.nodeToSpan(full.ast.bit_range_end.unwrap().?); | |
| 1680 | 1665 | }, |
| 1681 | 1666 | .node_offset_container_tag => |node_off| { |
| 1682 | 1667 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1683 | const node_tags = tree.nodes.items(.tag); | |
| 1684 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1668 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1685 | 1669 | |
| 1686 | switch (node_tags[parent_node]) { | |
| 1670 | switch (tree.nodeTag(parent_node)) { | |
| 1687 | 1671 | .container_decl_arg, .container_decl_arg_trailing => { |
| 1688 | 1672 | const full = tree.containerDeclArg(parent_node); |
| 1689 | return tree.nodeToSpan(full.ast.arg); | |
| 1673 | const arg_node = full.ast.arg.unwrap().?; | |
| 1674 | return tree.nodeToSpan(arg_node); | |
| 1690 | 1675 | }, |
| 1691 | 1676 | .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { |
| 1692 | 1677 | const full = tree.taggedUnionEnumTag(parent_node); |
| 1678 | const arg_node = full.ast.arg.unwrap().?; | |
| 1693 | 1679 | |
| 1694 | 1680 | return tree.tokensToSpan( |
| 1695 | tree.firstToken(full.ast.arg) - 2, | |
| 1696 | tree.lastToken(full.ast.arg) + 1, | |
| 1697 | tree.nodes.items(.main_token)[full.ast.arg], | |
| 1681 | tree.firstToken(arg_node) - 2, | |
| 1682 | tree.lastToken(arg_node) + 1, | |
| 1683 | tree.nodeMainToken(arg_node), | |
| 1698 | 1684 | ); |
| 1699 | 1685 | }, |
| 1700 | 1686 | else => unreachable, |
| ... | ... | @@ -1702,60 +1688,55 @@ pub const SrcLoc = struct { |
| 1702 | 1688 | }, |
| 1703 | 1689 | .node_offset_field_default => |node_off| { |
| 1704 | 1690 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1705 | const node_tags = tree.nodes.items(.tag); | |
| 1706 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1691 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1707 | 1692 | |
| 1708 | const full: Ast.full.ContainerField = switch (node_tags[parent_node]) { | |
| 1693 | const full: Ast.full.ContainerField = switch (tree.nodeTag(parent_node)) { | |
| 1709 | 1694 | .container_field => tree.containerField(parent_node), |
| 1710 | 1695 | .container_field_init => tree.containerFieldInit(parent_node), |
| 1711 | 1696 | else => unreachable, |
| 1712 | 1697 | }; |
| 1713 | return tree.nodeToSpan(full.ast.value_expr); | |
| 1698 | return tree.nodeToSpan(full.ast.value_expr.unwrap().?); | |
| 1714 | 1699 | }, |
| 1715 | 1700 | .node_offset_init_ty => |node_off| { |
| 1716 | 1701 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1717 | const parent_node = src_loc.relativeToNodeIndex(node_off); | |
| 1702 | const parent_node = node_off.toAbsolute(src_loc.base_node); | |
| 1718 | 1703 | |
| 1719 | 1704 | var buf: [2]Ast.Node.Index = undefined; |
| 1720 | 1705 | const type_expr = if (tree.fullArrayInit(&buf, parent_node)) |array_init| |
| 1721 | array_init.ast.type_expr | |
| 1706 | array_init.ast.type_expr.unwrap().? | |
| 1722 | 1707 | else |
| 1723 | tree.fullStructInit(&buf, parent_node).?.ast.type_expr; | |
| 1708 | tree.fullStructInit(&buf, parent_node).?.ast.type_expr.unwrap().?; | |
| 1724 | 1709 | return tree.nodeToSpan(type_expr); |
| 1725 | 1710 | }, |
| 1726 | 1711 | .node_offset_store_ptr => |node_off| { |
| 1727 | 1712 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1728 | const node_tags = tree.nodes.items(.tag); | |
| 1729 | const node_datas = tree.nodes.items(.data); | |
| 1730 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1713 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1731 | 1714 | |
| 1732 | switch (node_tags[node]) { | |
| 1715 | switch (tree.nodeTag(node)) { | |
| 1733 | 1716 | .assign => { |
| 1734 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1717 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[0]); | |
| 1735 | 1718 | }, |
| 1736 | 1719 | else => return tree.nodeToSpan(node), |
| 1737 | 1720 | } |
| 1738 | 1721 | }, |
| 1739 | 1722 | .node_offset_store_operand => |node_off| { |
| 1740 | 1723 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1741 | const node_tags = tree.nodes.items(.tag); | |
| 1742 | const node_datas = tree.nodes.items(.data); | |
| 1743 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1724 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1744 | 1725 | |
| 1745 | switch (node_tags[node]) { | |
| 1726 | switch (tree.nodeTag(node)) { | |
| 1746 | 1727 | .assign => { |
| 1747 | return tree.nodeToSpan(node_datas[node].rhs); | |
| 1728 | return tree.nodeToSpan(tree.nodeData(node).node_and_node[1]); | |
| 1748 | 1729 | }, |
| 1749 | 1730 | else => return tree.nodeToSpan(node), |
| 1750 | 1731 | } |
| 1751 | 1732 | }, |
| 1752 | 1733 | .node_offset_return_operand => |node_off| { |
| 1753 | 1734 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1754 | const node = src_loc.relativeToNodeIndex(node_off); | |
| 1755 | const node_tags = tree.nodes.items(.tag); | |
| 1756 | const node_datas = tree.nodes.items(.data); | |
| 1757 | if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { | |
| 1758 | return tree.nodeToSpan(node_datas[node].lhs); | |
| 1735 | const node = node_off.toAbsolute(src_loc.base_node); | |
| 1736 | if (tree.nodeTag(node) == .@"return") { | |
| 1737 | if (tree.nodeData(node).opt_node.unwrap()) |lhs| { | |
| 1738 | return tree.nodeToSpan(lhs); | |
| 1739 | } | |
| 1759 | 1740 | } |
| 1760 | 1741 | return tree.nodeToSpan(node); |
| 1761 | 1742 | }, |
| ... | ... | @@ -1765,7 +1746,7 @@ pub const SrcLoc = struct { |
| 1765 | 1746 | .container_field_align, |
| 1766 | 1747 | => |field_idx| { |
| 1767 | 1748 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1768 | const node = src_loc.relativeToNodeIndex(0); | |
| 1749 | const node = src_loc.base_node; | |
| 1769 | 1750 | var buf: [2]Ast.Node.Index = undefined; |
| 1770 | 1751 | const container_decl = tree.fullContainerDecl(&buf, node) orelse |
| 1771 | 1752 | return tree.nodeToSpan(node); |
| ... | ... | @@ -1778,36 +1759,36 @@ pub const SrcLoc = struct { |
| 1778 | 1759 | continue; |
| 1779 | 1760 | } |
| 1780 | 1761 | const field_component_node = switch (src_loc.lazy) { |
| 1781 | .container_field_name => 0, | |
| 1762 | .container_field_name => .none, | |
| 1782 | 1763 | .container_field_value => field.ast.value_expr, |
| 1783 | 1764 | .container_field_type => field.ast.type_expr, |
| 1784 | 1765 | .container_field_align => field.ast.align_expr, |
| 1785 | 1766 | else => unreachable, |
| 1786 | 1767 | }; |
| 1787 | if (field_component_node == 0) { | |
| 1788 | return tree.tokenToSpan(field.ast.main_token); | |
| 1768 | if (field_component_node.unwrap()) |component_node| { | |
| 1769 | return tree.nodeToSpan(component_node); | |
| 1789 | 1770 | } else { |
| 1790 | return tree.nodeToSpan(field_component_node); | |
| 1771 | return tree.tokenToSpan(field.ast.main_token); | |
| 1791 | 1772 | } |
| 1792 | 1773 | } else unreachable; |
| 1793 | 1774 | }, |
| 1794 | 1775 | .tuple_field_type, .tuple_field_init => |field_info| { |
| 1795 | 1776 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1796 | const node = src_loc.relativeToNodeIndex(0); | |
| 1777 | const node = src_loc.base_node; | |
| 1797 | 1778 | var buf: [2]Ast.Node.Index = undefined; |
| 1798 | 1779 | const container_decl = tree.fullContainerDecl(&buf, node) orelse |
| 1799 | 1780 | return tree.nodeToSpan(node); |
| 1800 | 1781 | |
| 1801 | 1782 | const field = tree.fullContainerField(container_decl.ast.members[field_info.elem_index]).?; |
| 1802 | 1783 | return tree.nodeToSpan(switch (src_loc.lazy) { |
| 1803 | .tuple_field_type => field.ast.type_expr, | |
| 1804 | .tuple_field_init => field.ast.value_expr, | |
| 1784 | .tuple_field_type => field.ast.type_expr.unwrap().?, | |
| 1785 | .tuple_field_init => field.ast.value_expr.unwrap().?, | |
| 1805 | 1786 | else => unreachable, |
| 1806 | 1787 | }); |
| 1807 | 1788 | }, |
| 1808 | 1789 | .init_elem => |init_elem| { |
| 1809 | 1790 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1810 | const init_node = src_loc.relativeToNodeIndex(init_elem.init_node_offset); | |
| 1791 | const init_node = init_elem.init_node_offset.toAbsolute(src_loc.base_node); | |
| 1811 | 1792 | var buf: [2]Ast.Node.Index = undefined; |
| 1812 | 1793 | if (tree.fullArrayInit(&buf, init_node)) |full| { |
| 1813 | 1794 | const elem_node = full.ast.elements[init_elem.elem_index]; |
| ... | ... | @@ -1817,7 +1798,7 @@ pub const SrcLoc = struct { |
| 1817 | 1798 | return tree.tokensToSpan( |
| 1818 | 1799 | tree.firstToken(field_node) - 3, |
| 1819 | 1800 | tree.lastToken(field_node), |
| 1820 | tree.nodes.items(.main_token)[field_node] - 2, | |
| 1801 | tree.nodeMainToken(field_node) - 2, | |
| 1821 | 1802 | ); |
| 1822 | 1803 | } else unreachable; |
| 1823 | 1804 | }, |
| ... | ... | @@ -1846,7 +1827,7 @@ pub const SrcLoc = struct { |
| 1846 | 1827 | else => unreachable, |
| 1847 | 1828 | }; |
| 1848 | 1829 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1849 | const node = src_loc.relativeToNodeIndex(builtin_call_node); | |
| 1830 | const node = builtin_call_node.toAbsolute(src_loc.base_node); | |
| 1850 | 1831 | var builtin_buf: [2]Ast.Node.Index = undefined; |
| 1851 | 1832 | const args = tree.builtinCallParams(&builtin_buf, node).?; |
| 1852 | 1833 | const arg_node = args[1]; |
| ... | ... | @@ -1861,7 +1842,7 @@ pub const SrcLoc = struct { |
| 1861 | 1842 | return tree.tokensToSpan( |
| 1862 | 1843 | name_token - 1, |
| 1863 | 1844 | tree.lastToken(field_node), |
| 1864 | tree.nodes.items(.main_token)[field_node] - 2, | |
| 1845 | tree.nodeMainToken(field_node) - 2, | |
| 1865 | 1846 | ); |
| 1866 | 1847 | } |
| 1867 | 1848 | } |
| ... | ... | @@ -1885,12 +1866,9 @@ pub const SrcLoc = struct { |
| 1885 | 1866 | }; |
| 1886 | 1867 | |
| 1887 | 1868 | const tree = try src_loc.file_scope.getTree(gpa); |
| 1888 | const node_datas = tree.nodes.items(.data); | |
| 1889 | const node_tags = tree.nodes.items(.tag); | |
| 1890 | const main_tokens = tree.nodes.items(.main_token); | |
| 1891 | const switch_node = src_loc.relativeToNodeIndex(switch_node_offset); | |
| 1892 | const extra = tree.extraData(node_datas[switch_node].rhs, Ast.Node.SubRange); | |
| 1893 | const case_nodes = tree.extra_data[extra.start..extra.end]; | |
| 1869 | const switch_node = switch_node_offset.toAbsolute(src_loc.base_node); | |
| 1870 | _, const extra_index = tree.nodeData(switch_node).node_and_extra; | |
| 1871 | const case_nodes = tree.extraDataSlice(tree.extraData(extra_index, Ast.Node.SubRange), Ast.Node.Index); | |
| 1894 | 1872 | |
| 1895 | 1873 | var multi_i: u32 = 0; |
| 1896 | 1874 | var scalar_i: u32 = 0; |
| ... | ... | @@ -1898,8 +1876,8 @@ pub const SrcLoc = struct { |
| 1898 | 1876 | const case = tree.fullSwitchCase(case_node).?; |
| 1899 | 1877 | const is_special = special: { |
| 1900 | 1878 | if (case.ast.values.len == 0) break :special true; |
| 1901 | if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .identifier) { | |
| 1902 | break :special mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"); | |
| 1879 | if (case.ast.values.len == 1 and tree.nodeTag(case.ast.values[0]) == .identifier) { | |
| 1880 | break :special mem.eql(u8, tree.tokenSlice(tree.nodeMainToken(case.ast.values[0])), "_"); | |
| 1903 | 1881 | } |
| 1904 | 1882 | break :special false; |
| 1905 | 1883 | }; |
| ... | ... | @@ -1911,7 +1889,7 @@ pub const SrcLoc = struct { |
| 1911 | 1889 | } |
| 1912 | 1890 | |
| 1913 | 1891 | const is_multi = case.ast.values.len != 1 or |
| 1914 | node_tags[case.ast.values[0]] == .switch_range; | |
| 1892 | tree.nodeTag(case.ast.values[0]) == .switch_range; | |
| 1915 | 1893 | |
| 1916 | 1894 | switch (want_case_idx.kind) { |
| 1917 | 1895 | .scalar => if (!is_multi and want_case_idx.index == scalar_i) break case, |
| ... | ... | @@ -1931,18 +1909,17 @@ pub const SrcLoc = struct { |
| 1931 | 1909 | .switch_case_item_range_last, |
| 1932 | 1910 | => |x| x.item_idx, |
| 1933 | 1911 | .switch_capture, .switch_tag_capture => { |
| 1934 | const token_tags = tree.tokens.items(.tag); | |
| 1935 | 1912 | const start = switch (src_loc.lazy) { |
| 1936 | 1913 | .switch_capture => case.payload_token.?, |
| 1937 | 1914 | .switch_tag_capture => tok: { |
| 1938 | 1915 | var tok = case.payload_token.?; |
| 1939 | if (token_tags[tok] == .asterisk) tok += 1; | |
| 1940 | tok += 2; // skip over comma | |
| 1916 | if (tree.tokenTag(tok) == .asterisk) tok += 1; | |
| 1917 | tok = tok + 2; // skip over comma | |
| 1941 | 1918 | break :tok tok; |
| 1942 | 1919 | }, |
| 1943 | 1920 | else => unreachable, |
| 1944 | 1921 | }; |
| 1945 | const end = switch (token_tags[start]) { | |
| 1922 | const end = switch (tree.tokenTag(start)) { | |
| 1946 | 1923 | .asterisk => start + 1, |
| 1947 | 1924 | else => start, |
| 1948 | 1925 | }; |
| ... | ... | @@ -1955,7 +1932,7 @@ pub const SrcLoc = struct { |
| 1955 | 1932 | .single => { |
| 1956 | 1933 | var item_i: u32 = 0; |
| 1957 | 1934 | for (case.ast.values) |item_node| { |
| 1958 | if (node_tags[item_node] == .switch_range) continue; | |
| 1935 | if (tree.nodeTag(item_node) == .switch_range) continue; | |
| 1959 | 1936 | if (item_i != want_item.index) { |
| 1960 | 1937 | item_i += 1; |
| 1961 | 1938 | continue; |
| ... | ... | @@ -1966,15 +1943,16 @@ pub const SrcLoc = struct { |
| 1966 | 1943 | .range => { |
| 1967 | 1944 | var range_i: u32 = 0; |
| 1968 | 1945 | for (case.ast.values) |item_node| { |
| 1969 | if (node_tags[item_node] != .switch_range) continue; | |
| 1946 | if (tree.nodeTag(item_node) != .switch_range) continue; | |
| 1970 | 1947 | if (range_i != want_item.index) { |
| 1971 | 1948 | range_i += 1; |
| 1972 | 1949 | continue; |
| 1973 | 1950 | } |
| 1951 | const first, const last = tree.nodeData(item_node).node_and_node; | |
| 1974 | 1952 | return switch (src_loc.lazy) { |
| 1975 | 1953 | .switch_case_item => tree.nodeToSpan(item_node), |
| 1976 | .switch_case_item_range_first => tree.nodeToSpan(node_datas[item_node].lhs), | |
| 1977 | .switch_case_item_range_last => tree.nodeToSpan(node_datas[item_node].rhs), | |
| 1954 | .switch_case_item_range_first => tree.nodeToSpan(first), | |
| 1955 | .switch_case_item_range_last => tree.nodeToSpan(last), | |
| 1978 | 1956 | else => unreachable, |
| 1979 | 1957 | }; |
| 1980 | 1958 | } else unreachable; |
| ... | ... | @@ -1997,7 +1975,7 @@ pub const SrcLoc = struct { |
| 1997 | 1975 | var param_it = full.iterate(tree); |
| 1998 | 1976 | for (0..param_idx) |_| assert(param_it.next() != null); |
| 1999 | 1977 | const param = param_it.next().?; |
| 2000 | return tree.nodeToSpan(param.type_expr); | |
| 1978 | return tree.nodeToSpan(param.type_expr.?); | |
| 2001 | 1979 | }, |
| 2002 | 1980 | } |
| 2003 | 1981 | } |
| ... | ... | @@ -2028,212 +2006,217 @@ pub const LazySrcLoc = struct { |
| 2028 | 2006 | byte_abs: u32, |
| 2029 | 2007 | /// The source location points to a token within a source file, |
| 2030 | 2008 | /// offset from 0. The source file is determined contextually. |
| 2031 | token_abs: u32, | |
| 2009 | token_abs: Ast.TokenIndex, | |
| 2032 | 2010 | /// The source location points to an AST node within a source file, |
| 2033 | 2011 | /// offset from 0. The source file is determined contextually. |
| 2034 | node_abs: u32, | |
| 2012 | node_abs: Ast.Node.Index, | |
| 2035 | 2013 | /// The source location points to a byte offset within a source file, |
| 2036 | 2014 | /// offset from the byte offset of the base node within the file. |
| 2037 | 2015 | byte_offset: u32, |
| 2038 | 2016 | /// This data is the offset into the token list from the base node's first token. |
| 2039 | token_offset: u32, | |
| 2017 | token_offset: Ast.TokenOffset, | |
| 2040 | 2018 | /// The source location points to an AST node, which is this value offset |
| 2041 | 2019 | /// from its containing base node AST index. |
| 2042 | 2020 | node_offset: TracedOffset, |
| 2043 | 2021 | /// The source location points to the main token of an AST node, found |
| 2044 | 2022 | /// by taking this AST node index offset from the containing base node. |
| 2045 | node_offset_main_token: i32, | |
| 2023 | node_offset_main_token: Ast.Node.Offset, | |
| 2046 | 2024 | /// The source location points to the beginning of a struct initializer. |
| 2047 | node_offset_initializer: i32, | |
| 2025 | node_offset_initializer: Ast.Node.Offset, | |
| 2048 | 2026 | /// The source location points to a variable declaration type expression, |
| 2049 | 2027 | /// found by taking this AST node index offset from the containing |
| 2050 | 2028 | /// base node, which points to a variable declaration AST node. Next, navigate |
| 2051 | 2029 | /// to the type expression. |
| 2052 | node_offset_var_decl_ty: i32, | |
| 2030 | node_offset_var_decl_ty: Ast.Node.Offset, | |
| 2053 | 2031 | /// The source location points to the alignment expression of a var decl. |
| 2054 | node_offset_var_decl_align: i32, | |
| 2032 | node_offset_var_decl_align: Ast.Node.Offset, | |
| 2055 | 2033 | /// The source location points to the linksection expression of a var decl. |
| 2056 | node_offset_var_decl_section: i32, | |
| 2034 | node_offset_var_decl_section: Ast.Node.Offset, | |
| 2057 | 2035 | /// The source location points to the addrspace expression of a var decl. |
| 2058 | node_offset_var_decl_addrspace: i32, | |
| 2036 | node_offset_var_decl_addrspace: Ast.Node.Offset, | |
| 2059 | 2037 | /// The source location points to the initializer of a var decl. |
| 2060 | node_offset_var_decl_init: i32, | |
| 2038 | node_offset_var_decl_init: Ast.Node.Offset, | |
| 2061 | 2039 | /// The source location points to the given argument of a builtin function call. |
| 2062 | 2040 | /// `builtin_call_node` points to the builtin call. |
| 2063 | 2041 | /// `arg_index` is the index of the argument which hte source location refers to. |
| 2064 | 2042 | node_offset_builtin_call_arg: struct { |
| 2065 | builtin_call_node: i32, | |
| 2043 | builtin_call_node: Ast.Node.Offset, | |
| 2066 | 2044 | arg_index: u32, |
| 2067 | 2045 | }, |
| 2068 | 2046 | /// Like `node_offset_builtin_call_arg` but recurses through arbitrarily many calls |
| 2069 | 2047 | /// to pointer cast builtins (taking the first argument of the most nested). |
| 2070 | node_offset_ptrcast_operand: i32, | |
| 2048 | node_offset_ptrcast_operand: Ast.Node.Offset, | |
| 2071 | 2049 | /// The source location points to the index expression of an array access |
| 2072 | 2050 | /// expression, found by taking this AST node index offset from the containing |
| 2073 | 2051 | /// base node, which points to an array access AST node. Next, navigate |
| 2074 | 2052 | /// to the index expression. |
| 2075 | node_offset_array_access_index: i32, | |
| 2053 | node_offset_array_access_index: Ast.Node.Offset, | |
| 2076 | 2054 | /// The source location points to the LHS of a slice expression |
| 2077 | 2055 | /// expression, found by taking this AST node index offset from the containing |
| 2078 | 2056 | /// base node, which points to a slice AST node. Next, navigate |
| 2079 | 2057 | /// to the sentinel expression. |
| 2080 | node_offset_slice_ptr: i32, | |
| 2058 | node_offset_slice_ptr: Ast.Node.Offset, | |
| 2081 | 2059 | /// The source location points to start expression of a slice expression |
| 2082 | 2060 | /// expression, found by taking this AST node index offset from the containing |
| 2083 | 2061 | /// base node, which points to a slice AST node. Next, navigate |
| 2084 | 2062 | /// to the sentinel expression. |
| 2085 | node_offset_slice_start: i32, | |
| 2063 | node_offset_slice_start: Ast.Node.Offset, | |
| 2086 | 2064 | /// The source location points to the end expression of a slice |
| 2087 | 2065 | /// expression, found by taking this AST node index offset from the containing |
| 2088 | 2066 | /// base node, which points to a slice AST node. Next, navigate |
| 2089 | 2067 | /// to the sentinel expression. |
| 2090 | node_offset_slice_end: i32, | |
| 2068 | node_offset_slice_end: Ast.Node.Offset, | |
| 2091 | 2069 | /// The source location points to the sentinel expression of a slice |
| 2092 | 2070 | /// expression, found by taking this AST node index offset from the containing |
| 2093 | 2071 | /// base node, which points to a slice AST node. Next, navigate |
| 2094 | 2072 | /// to the sentinel expression. |
| 2095 | node_offset_slice_sentinel: i32, | |
| 2073 | node_offset_slice_sentinel: Ast.Node.Offset, | |
| 2096 | 2074 | /// The source location points to the callee expression of a function |
| 2097 | 2075 | /// call expression, found by taking this AST node index offset from the containing |
| 2098 | 2076 | /// base node, which points to a function call AST node. Next, navigate |
| 2099 | 2077 | /// to the callee expression. |
| 2100 | node_offset_call_func: i32, | |
| 2078 | node_offset_call_func: Ast.Node.Offset, | |
| 2101 | 2079 | /// The payload is offset from the containing base node. |
| 2102 | 2080 | /// The source location points to the field name of: |
| 2103 | 2081 | /// * a field access expression (`a.b`), or |
| 2104 | 2082 | /// * the callee of a method call (`a.b()`) |
| 2105 | node_offset_field_name: i32, | |
| 2083 | node_offset_field_name: Ast.Node.Offset, | |
| 2106 | 2084 | /// The payload is offset from the containing base node. |
| 2107 | 2085 | /// The source location points to the field name of the operand ("b" node) |
| 2108 | 2086 | /// of a field initialization expression (`.a = b`) |
| 2109 | node_offset_field_name_init: i32, | |
| 2087 | node_offset_field_name_init: Ast.Node.Offset, | |
| 2110 | 2088 | /// The source location points to the pointer of a pointer deref expression, |
| 2111 | 2089 | /// found by taking this AST node index offset from the containing |
| 2112 | 2090 | /// base node, which points to a pointer deref AST node. Next, navigate |
| 2113 | 2091 | /// to the pointer expression. |
| 2114 | node_offset_deref_ptr: i32, | |
| 2092 | node_offset_deref_ptr: Ast.Node.Offset, | |
| 2115 | 2093 | /// The source location points to the assembly source code of an inline assembly |
| 2116 | 2094 | /// expression, found by taking this AST node index offset from the containing |
| 2117 | 2095 | /// base node, which points to inline assembly AST node. Next, navigate |
| 2118 | 2096 | /// to the asm template source code. |
| 2119 | node_offset_asm_source: i32, | |
| 2097 | node_offset_asm_source: Ast.Node.Offset, | |
| 2120 | 2098 | /// The source location points to the return type of an inline assembly |
| 2121 | 2099 | /// expression, found by taking this AST node index offset from the containing |
| 2122 | 2100 | /// base node, which points to inline assembly AST node. Next, navigate |
| 2123 | 2101 | /// to the return type expression. |
| 2124 | node_offset_asm_ret_ty: i32, | |
| 2102 | node_offset_asm_ret_ty: Ast.Node.Offset, | |
| 2125 | 2103 | /// The source location points to the condition expression of an if |
| 2126 | 2104 | /// expression, found by taking this AST node index offset from the containing |
| 2127 | 2105 | /// base node, which points to an if expression AST node. Next, navigate |
| 2128 | 2106 | /// to the condition expression. |
| 2129 | node_offset_if_cond: i32, | |
| 2107 | node_offset_if_cond: Ast.Node.Offset, | |
| 2130 | 2108 | /// The source location points to a binary expression, such as `a + b`, found |
| 2131 | 2109 | /// by taking this AST node index offset from the containing base node. |
| 2132 | node_offset_bin_op: i32, | |
| 2110 | node_offset_bin_op: Ast.Node.Offset, | |
| 2133 | 2111 | /// The source location points to the LHS of a binary expression, found |
| 2134 | 2112 | /// by taking this AST node index offset from the containing base node, |
| 2135 | 2113 | /// which points to a binary expression AST node. Next, navigate to the LHS. |
| 2136 | node_offset_bin_lhs: i32, | |
| 2114 | node_offset_bin_lhs: Ast.Node.Offset, | |
| 2137 | 2115 | /// The source location points to the RHS of a binary expression, found |
| 2138 | 2116 | /// by taking this AST node index offset from the containing base node, |
| 2139 | 2117 | /// which points to a binary expression AST node. Next, navigate to the RHS. |
| 2140 | node_offset_bin_rhs: i32, | |
| 2118 | node_offset_bin_rhs: Ast.Node.Offset, | |
| 2119 | /// The source location points to the operand of a try expression, found | |
| 2120 | /// by taking this AST node index offset from the containing base node, | |
| 2121 | /// which points to a try expression AST node. Next, navigate to the | |
| 2122 | /// operand expression. | |
| 2123 | node_offset_try_operand: Ast.Node.Offset, | |
| 2141 | 2124 | /// The source location points to the operand of a switch expression, found |
| 2142 | 2125 | /// by taking this AST node index offset from the containing base node, |
| 2143 | 2126 | /// which points to a switch expression AST node. Next, navigate to the operand. |
| 2144 | node_offset_switch_operand: i32, | |
| 2127 | node_offset_switch_operand: Ast.Node.Offset, | |
| 2145 | 2128 | /// The source location points to the else/`_` prong of a switch expression, found |
| 2146 | 2129 | /// by taking this AST node index offset from the containing base node, |
| 2147 | 2130 | /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. |
| 2148 | node_offset_switch_special_prong: i32, | |
| 2131 | node_offset_switch_special_prong: Ast.Node.Offset, | |
| 2149 | 2132 | /// The source location points to all the ranges of a switch expression, found |
| 2150 | 2133 | /// by taking this AST node index offset from the containing base node, |
| 2151 | 2134 | /// which points to a switch expression AST node. Next, navigate to any of the |
| 2152 | 2135 | /// range nodes. The error applies to all of them. |
| 2153 | node_offset_switch_range: i32, | |
| 2136 | node_offset_switch_range: Ast.Node.Offset, | |
| 2154 | 2137 | /// The source location points to the align expr of a function type |
| 2155 | 2138 | /// expression, found by taking this AST node index offset from the containing |
| 2156 | 2139 | /// base node, which points to a function type AST node. Next, navigate to |
| 2157 | 2140 | /// the calling convention node. |
| 2158 | node_offset_fn_type_align: i32, | |
| 2141 | node_offset_fn_type_align: Ast.Node.Offset, | |
| 2159 | 2142 | /// The source location points to the addrspace expr of a function type |
| 2160 | 2143 | /// expression, found by taking this AST node index offset from the containing |
| 2161 | 2144 | /// base node, which points to a function type AST node. Next, navigate to |
| 2162 | 2145 | /// the calling convention node. |
| 2163 | node_offset_fn_type_addrspace: i32, | |
| 2146 | node_offset_fn_type_addrspace: Ast.Node.Offset, | |
| 2164 | 2147 | /// The source location points to the linksection expr of a function type |
| 2165 | 2148 | /// expression, found by taking this AST node index offset from the containing |
| 2166 | 2149 | /// base node, which points to a function type AST node. Next, navigate to |
| 2167 | 2150 | /// the calling convention node. |
| 2168 | node_offset_fn_type_section: i32, | |
| 2151 | node_offset_fn_type_section: Ast.Node.Offset, | |
| 2169 | 2152 | /// The source location points to the calling convention of a function type |
| 2170 | 2153 | /// expression, found by taking this AST node index offset from the containing |
| 2171 | 2154 | /// base node, which points to a function type AST node. Next, navigate to |
| 2172 | 2155 | /// the calling convention node. |
| 2173 | node_offset_fn_type_cc: i32, | |
| 2156 | node_offset_fn_type_cc: Ast.Node.Offset, | |
| 2174 | 2157 | /// The source location points to the return type of a function type |
| 2175 | 2158 | /// expression, found by taking this AST node index offset from the containing |
| 2176 | 2159 | /// base node, which points to a function type AST node. Next, navigate to |
| 2177 | 2160 | /// the return type node. |
| 2178 | node_offset_fn_type_ret_ty: i32, | |
| 2179 | node_offset_param: i32, | |
| 2180 | token_offset_param: i32, | |
| 2161 | node_offset_fn_type_ret_ty: Ast.Node.Offset, | |
| 2162 | node_offset_param: Ast.Node.Offset, | |
| 2163 | token_offset_param: Ast.TokenOffset, | |
| 2181 | 2164 | /// The source location points to the type expression of an `anyframe->T` |
| 2182 | 2165 | /// expression, found by taking this AST node index offset from the containing |
| 2183 | 2166 | /// base node, which points to a `anyframe->T` expression AST node. Next, navigate |
| 2184 | 2167 | /// to the type expression. |
| 2185 | node_offset_anyframe_type: i32, | |
| 2168 | node_offset_anyframe_type: Ast.Node.Offset, | |
| 2186 | 2169 | /// The source location points to the string literal of `extern "foo"`, found |
| 2187 | 2170 | /// by taking this AST node index offset from the containing |
| 2188 | 2171 | /// base node, which points to a function prototype or variable declaration |
| 2189 | 2172 | /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. |
| 2190 | node_offset_lib_name: i32, | |
| 2173 | node_offset_lib_name: Ast.Node.Offset, | |
| 2191 | 2174 | /// The source location points to the len expression of an `[N:S]T` |
| 2192 | 2175 | /// expression, found by taking this AST node index offset from the containing |
| 2193 | 2176 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2194 | 2177 | /// to the len expression. |
| 2195 | node_offset_array_type_len: i32, | |
| 2178 | node_offset_array_type_len: Ast.Node.Offset, | |
| 2196 | 2179 | /// The source location points to the sentinel expression of an `[N:S]T` |
| 2197 | 2180 | /// expression, found by taking this AST node index offset from the containing |
| 2198 | 2181 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2199 | 2182 | /// to the sentinel expression. |
| 2200 | node_offset_array_type_sentinel: i32, | |
| 2183 | node_offset_array_type_sentinel: Ast.Node.Offset, | |
| 2201 | 2184 | /// The source location points to the elem expression of an `[N:S]T` |
| 2202 | 2185 | /// expression, found by taking this AST node index offset from the containing |
| 2203 | 2186 | /// base node, which points to an `[N:S]T` expression AST node. Next, navigate |
| 2204 | 2187 | /// to the elem expression. |
| 2205 | node_offset_array_type_elem: i32, | |
| 2188 | node_offset_array_type_elem: Ast.Node.Offset, | |
| 2206 | 2189 | /// The source location points to the operand of an unary expression. |
| 2207 | node_offset_un_op: i32, | |
| 2190 | node_offset_un_op: Ast.Node.Offset, | |
| 2208 | 2191 | /// The source location points to the elem type of a pointer. |
| 2209 | node_offset_ptr_elem: i32, | |
| 2192 | node_offset_ptr_elem: Ast.Node.Offset, | |
| 2210 | 2193 | /// The source location points to the sentinel of a pointer. |
| 2211 | node_offset_ptr_sentinel: i32, | |
| 2194 | node_offset_ptr_sentinel: Ast.Node.Offset, | |
| 2212 | 2195 | /// The source location points to the align expr of a pointer. |
| 2213 | node_offset_ptr_align: i32, | |
| 2196 | node_offset_ptr_align: Ast.Node.Offset, | |
| 2214 | 2197 | /// The source location points to the addrspace expr of a pointer. |
| 2215 | node_offset_ptr_addrspace: i32, | |
| 2198 | node_offset_ptr_addrspace: Ast.Node.Offset, | |
| 2216 | 2199 | /// The source location points to the bit-offset of a pointer. |
| 2217 | node_offset_ptr_bitoffset: i32, | |
| 2200 | node_offset_ptr_bitoffset: Ast.Node.Offset, | |
| 2218 | 2201 | /// The source location points to the host size of a pointer. |
| 2219 | node_offset_ptr_hostsize: i32, | |
| 2202 | node_offset_ptr_hostsize: Ast.Node.Offset, | |
| 2220 | 2203 | /// The source location points to the tag type of an union or an enum. |
| 2221 | node_offset_container_tag: i32, | |
| 2204 | node_offset_container_tag: Ast.Node.Offset, | |
| 2222 | 2205 | /// The source location points to the default value of a field. |
| 2223 | node_offset_field_default: i32, | |
| 2206 | node_offset_field_default: Ast.Node.Offset, | |
| 2224 | 2207 | /// The source location points to the type of an array or struct initializer. |
| 2225 | node_offset_init_ty: i32, | |
| 2208 | node_offset_init_ty: Ast.Node.Offset, | |
| 2226 | 2209 | /// The source location points to the LHS of an assignment. |
| 2227 | node_offset_store_ptr: i32, | |
| 2210 | node_offset_store_ptr: Ast.Node.Offset, | |
| 2228 | 2211 | /// The source location points to the RHS of an assignment. |
| 2229 | node_offset_store_operand: i32, | |
| 2212 | node_offset_store_operand: Ast.Node.Offset, | |
| 2230 | 2213 | /// The source location points to the operand of a `return` statement, or |
| 2231 | 2214 | /// the `return` itself if there is no explicit operand. |
| 2232 | node_offset_return_operand: i32, | |
| 2215 | node_offset_return_operand: Ast.Node.Offset, | |
| 2233 | 2216 | /// The source location points to a for loop input. |
| 2234 | 2217 | for_input: struct { |
| 2235 | 2218 | /// Points to the for loop AST node. |
| 2236 | for_node_offset: i32, | |
| 2219 | for_node_offset: Ast.Node.Offset, | |
| 2237 | 2220 | /// Picks one of the inputs from the condition. |
| 2238 | 2221 | input_index: u32, |
| 2239 | 2222 | }, |
| ... | ... | @@ -2241,11 +2224,11 @@ pub const LazySrcLoc = struct { |
| 2241 | 2224 | /// by taking this AST node index offset from the containing |
| 2242 | 2225 | /// base node, which points to one of the input nodes of a for loop. |
| 2243 | 2226 | /// Next, navigate to the corresponding capture. |
| 2244 | for_capture_from_input: i32, | |
| 2227 | for_capture_from_input: Ast.Node.Offset, | |
| 2245 | 2228 | /// The source location points to the argument node of a function call. |
| 2246 | 2229 | call_arg: struct { |
| 2247 | 2230 | /// Points to the function call AST node. |
| 2248 | call_node_offset: i32, | |
| 2231 | call_node_offset: Ast.Node.Offset, | |
| 2249 | 2232 | /// The index of the argument the source location points to. |
| 2250 | 2233 | arg_index: u32, |
| 2251 | 2234 | }, |
| ... | ... | @@ -2272,25 +2255,25 @@ pub const LazySrcLoc = struct { |
| 2272 | 2255 | /// array initialization expression. |
| 2273 | 2256 | init_elem: struct { |
| 2274 | 2257 | /// Points to the AST node of the initialization expression. |
| 2275 | init_node_offset: i32, | |
| 2258 | init_node_offset: Ast.Node.Offset, | |
| 2276 | 2259 | /// The index of the field/element the source location points to. |
| 2277 | 2260 | elem_index: u32, |
| 2278 | 2261 | }, |
| 2279 | 2262 | // The following source locations are like `init_elem`, but refer to a |
| 2280 | 2263 | // field with a specific name. If such a field is not given, the entire |
| 2281 | 2264 | // initialization expression is used instead. |
| 2282 | // The `i32` points to the AST node of a builtin call, whose *second* | |
| 2265 | // The `Ast.Node.Offset` points to the AST node of a builtin call, whose *second* | |
| 2283 | 2266 | // argument is the init expression. |
| 2284 | init_field_name: i32, | |
| 2285 | init_field_linkage: i32, | |
| 2286 | init_field_section: i32, | |
| 2287 | init_field_visibility: i32, | |
| 2288 | init_field_rw: i32, | |
| 2289 | init_field_locality: i32, | |
| 2290 | init_field_cache: i32, | |
| 2291 | init_field_library: i32, | |
| 2292 | init_field_thread_local: i32, | |
| 2293 | init_field_dll_import: i32, | |
| 2267 | init_field_name: Ast.Node.Offset, | |
| 2268 | init_field_linkage: Ast.Node.Offset, | |
| 2269 | init_field_section: Ast.Node.Offset, | |
| 2270 | init_field_visibility: Ast.Node.Offset, | |
| 2271 | init_field_rw: Ast.Node.Offset, | |
| 2272 | init_field_locality: Ast.Node.Offset, | |
| 2273 | init_field_cache: Ast.Node.Offset, | |
| 2274 | init_field_library: Ast.Node.Offset, | |
| 2275 | init_field_thread_local: Ast.Node.Offset, | |
| 2276 | init_field_dll_import: Ast.Node.Offset, | |
| 2294 | 2277 | /// The source location points to the value of an item in a specific |
| 2295 | 2278 | /// case of a `switch`. |
| 2296 | 2279 | switch_case_item: SwitchItem, |
| ... | ... | @@ -2315,14 +2298,14 @@ pub const LazySrcLoc = struct { |
| 2315 | 2298 | |
| 2316 | 2299 | pub const FnProtoParam = struct { |
| 2317 | 2300 | /// The offset of the function prototype AST node. |
| 2318 | fn_proto_node_offset: i32, | |
| 2301 | fn_proto_node_offset: Ast.Node.Offset, | |
| 2319 | 2302 | /// The index of the parameter the source location points to. |
| 2320 | 2303 | param_index: u32, |
| 2321 | 2304 | }; |
| 2322 | 2305 | |
| 2323 | 2306 | pub const SwitchItem = struct { |
| 2324 | 2307 | /// The offset of the switch AST node. |
| 2325 | switch_node_offset: i32, | |
| 2308 | switch_node_offset: Ast.Node.Offset, | |
| 2326 | 2309 | /// The index of the case to point to within this switch. |
| 2327 | 2310 | case_idx: SwitchCaseIndex, |
| 2328 | 2311 | /// The index of the item to point to within this case. |
| ... | ... | @@ -2331,7 +2314,7 @@ pub const LazySrcLoc = struct { |
| 2331 | 2314 | |
| 2332 | 2315 | pub const SwitchCapture = struct { |
| 2333 | 2316 | /// The offset of the switch AST node. |
| 2334 | switch_node_offset: i32, | |
| 2317 | switch_node_offset: Ast.Node.Offset, | |
| 2335 | 2318 | /// The index of the case whose capture to point to. |
| 2336 | 2319 | case_idx: SwitchCaseIndex, |
| 2337 | 2320 | }; |
| ... | ... | @@ -2353,34 +2336,34 @@ pub const LazySrcLoc = struct { |
| 2353 | 2336 | |
| 2354 | 2337 | pub const ArrayCat = struct { |
| 2355 | 2338 | /// Points to the array concat AST node. |
| 2356 | array_cat_offset: i32, | |
| 2339 | array_cat_offset: Ast.Node.Offset, | |
| 2357 | 2340 | /// The index of the element the source location points to. |
| 2358 | 2341 | elem_index: u32, |
| 2359 | 2342 | }; |
| 2360 | 2343 | |
| 2361 | 2344 | pub const TupleField = struct { |
| 2362 | 2345 | /// Points to the AST node of the tuple type decaration. |
| 2363 | tuple_decl_node_offset: i32, | |
| 2346 | tuple_decl_node_offset: Ast.Node.Offset, | |
| 2364 | 2347 | /// The index of the tuple field the source location points to. |
| 2365 | 2348 | elem_index: u32, |
| 2366 | 2349 | }; |
| 2367 | 2350 | |
| 2368 | 2351 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 2369 | 2352 | |
| 2370 | noinline fn nodeOffsetDebug(node_offset: i32) Offset { | |
| 2353 | noinline fn nodeOffsetDebug(node_offset: Ast.Node.Offset) Offset { | |
| 2371 | 2354 | var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; |
| 2372 | 2355 | result.node_offset.trace.addAddr(@returnAddress(), "init"); |
| 2373 | 2356 | return result; |
| 2374 | 2357 | } |
| 2375 | 2358 | |
| 2376 | fn nodeOffsetRelease(node_offset: i32) Offset { | |
| 2359 | fn nodeOffsetRelease(node_offset: Ast.Node.Offset) Offset { | |
| 2377 | 2360 | return .{ .node_offset = .{ .x = node_offset } }; |
| 2378 | 2361 | } |
| 2379 | 2362 | |
| 2380 | 2363 | /// This wraps a simple integer in debug builds so that later on we can find out |
| 2381 | 2364 | /// where in semantic analysis the value got set. |
| 2382 | 2365 | pub const TracedOffset = struct { |
| 2383 | x: i32, | |
| 2366 | x: Ast.Node.Offset, | |
| 2384 | 2367 | trace: std.debug.Trace = std.debug.Trace.init, |
| 2385 | 2368 | |
| 2386 | 2369 | const want_tracing = false; |
| ... | ... | @@ -2405,7 +2388,7 @@ pub const LazySrcLoc = struct { |
| 2405 | 2388 | |
| 2406 | 2389 | // If we're relative to .main_struct_inst, we know the ast node is the root and don't need to resolve the ZIR, |
| 2407 | 2390 | // which may not exist e.g. in the case of errors in ZON files. |
| 2408 | if (zir_inst == .main_struct_inst) return .{ file, 0 }; | |
| 2391 | if (zir_inst == .main_struct_inst) return .{ file, .root }; | |
| 2409 | 2392 | |
| 2410 | 2393 | // Otherwise, make sure ZIR is loaded. |
| 2411 | 2394 | const zir = file.zir.?; |
| ... | ... | @@ -2438,7 +2421,7 @@ pub const LazySrcLoc = struct { |
| 2438 | 2421 | pub fn upgradeOrLost(lazy: LazySrcLoc, zcu: *Zcu) ?SrcLoc { |
| 2439 | 2422 | const file, const base_node: Ast.Node.Index = if (lazy.offset == .entire_file) .{ |
| 2440 | 2423 | zcu.fileByIndex(lazy.base_node_inst.resolveFile(&zcu.intern_pool)), |
| 2441 | 0, | |
| 2424 | .root, | |
| 2442 | 2425 | } else resolveBaseNode(lazy.base_node_inst, zcu) orelse return null; |
| 2443 | 2426 | return .{ |
| 2444 | 2427 | .file_scope = file, |
| ... | ... | @@ -4007,7 +3990,7 @@ pub fn navSrcLoc(zcu: *const Zcu, nav_index: InternPool.Nav.Index) LazySrcLoc { |
| 4007 | 3990 | const ip = &zcu.intern_pool; |
| 4008 | 3991 | return .{ |
| 4009 | 3992 | .base_node_inst = ip.getNav(nav_index).srcInst(ip), |
| 4010 | .offset = LazySrcLoc.Offset.nodeOffset(0), | |
| 3993 | .offset = LazySrcLoc.Offset.nodeOffset(.zero), | |
| 4011 | 3994 | }; |
| 4012 | 3995 | } |
| 4013 | 3996 |
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+10-8| ... | ... | @@ -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,8 +7284,8 @@ 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 | if (dep.hash_node != 0) { | |
| 7286 | try fixups.replace_nodes_with_string.put(gpa, dep.hash_node, hash_replace); | |
| 7287 | if (dep.hash_node.unwrap()) |hash_node| { | |
| 7288 | try fixups.replace_nodes_with_string.put(gpa, hash_node, hash_replace); | |
| 7287 | 7289 | } else { |
| 7288 | 7290 | // https://github.com/ziglang/zig/issues/21690 |
| 7289 | 7291 | } |
| ... | ... | @@ -7292,9 +7294,9 @@ fn cmdFetch( |
| 7292 | 7294 | const deps = manifest.dependencies.values(); |
| 7293 | 7295 | const last_dep_node = deps[deps.len - 1].node; |
| 7294 | 7296 | try fixups.append_string_after_node.put(gpa, last_dep_node, new_node_text); |
| 7295 | } else if (manifest.dependencies_node != 0) { | |
| 7297 | } else if (manifest.dependencies_node.unwrap()) |dependencies_node| { | |
| 7296 | 7298 | // Add fixup for replacing the entire dependencies struct. |
| 7297 | try fixups.replace_nodes_with_string.put(gpa, manifest.dependencies_node, dependencies_init); | |
| 7299 | try fixups.replace_nodes_with_string.put(gpa, dependencies_node, dependencies_init); | |
| 7298 | 7300 | } else { |
| 7299 | 7301 | // Add fixup for adding dependencies struct. |
| 7300 | 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); |