| ... | @@ -43,11 +43,13 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!Tree { | ... | @@ -43,11 +43,13 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!Tree { |
| 43 | .errors = .{}, | 43 | .errors = .{}, |
| 44 | .nodes = .{}, | 44 | .nodes = .{}, |
| 45 | .extra_data = .{}, | 45 | .extra_data = .{}, |
| | 46 | .scratch = .{}, |
| 46 | .tok_i = 0, | 47 | .tok_i = 0, |
| 47 | }; | 48 | }; |
| 48 | defer parser.errors.deinit(gpa); | 49 | defer parser.errors.deinit(gpa); |
| 49 | defer parser.nodes.deinit(gpa); | 50 | defer parser.nodes.deinit(gpa); |
| 50 | defer parser.extra_data.deinit(gpa); | 51 | defer parser.extra_data.deinit(gpa); |
| | 52 | defer parser.scratch.deinit(gpa); |
| 51 | | 53 | |
| 52 | // Empirically, Zig source code has a 2:1 ratio of tokens to AST nodes. | 54 | // Empirically, Zig source code has a 2:1 ratio of tokens to AST nodes. |
| 53 | // Make sure at least 1 so we can use appendAssumeCapacity on the root node below. | 55 | // Make sure at least 1 so we can use appendAssumeCapacity on the root node below. |
| ... | @@ -93,18 +95,7 @@ const Parser = struct { | ... | @@ -93,18 +95,7 @@ const Parser = struct { |
| 93 | errors: std.ArrayListUnmanaged(AstError), | 95 | errors: std.ArrayListUnmanaged(AstError), |
| 94 | nodes: ast.NodeList, | 96 | nodes: ast.NodeList, |
| 95 | extra_data: std.ArrayListUnmanaged(Node.Index), | 97 | extra_data: std.ArrayListUnmanaged(Node.Index), |
| 96 | | 98 | scratch: std.ArrayListUnmanaged(Node.Index), |
| 97 | const SmallSpan = union(enum) { | | |
| 98 | zero_or_one: Node.Index, | | |
| 99 | multi: []Node.Index, | | |
| 100 | | | |
| 101 | fn deinit(self: SmallSpan, gpa: *Allocator) void { | | |
| 102 | switch (self) { | | |
| 103 | .zero_or_one => {}, | | |
| 104 | .multi => |list| gpa.free(list), | | |
| 105 | } | | |
| 106 | } | | |
| 107 | }; | | |
| 108 | | 99 | |
| 109 | const Members = struct { | 100 | const Members = struct { |
| 110 | len: usize, | 101 | len: usize, |
| ... | @@ -204,8 +195,8 @@ const Parser = struct { | ... | @@ -204,8 +195,8 @@ const Parser = struct { |
| 204 | /// / | 195 | /// / |
| 205 | /// TopLevelComptime <- KEYWORD_comptime BlockExpr | 196 | /// TopLevelComptime <- KEYWORD_comptime BlockExpr |
| 206 | fn parseContainerMembers(p: *Parser) !Members { | 197 | fn parseContainerMembers(p: *Parser) !Members { |
| 207 | var list = std.ArrayList(Node.Index).init(p.gpa); | 198 | const scratch_top = p.scratch.items.len; |
| 208 | defer list.deinit(); | 199 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 209 | | 200 | |
| 210 | var field_state: union(enum) { | 201 | var field_state: union(enum) { |
| 211 | /// No fields have been seen. | 202 | /// No fields have been seen. |
| ... | @@ -233,7 +224,7 @@ const Parser = struct { | ... | @@ -233,7 +224,7 @@ const Parser = struct { |
| 233 | if (field_state == .seen) { | 224 | if (field_state == .seen) { |
| 234 | field_state = .{ .end = test_decl_node }; | 225 | field_state = .{ .end = test_decl_node }; |
| 235 | } | 226 | } |
| 236 | try list.append(test_decl_node); | 227 | try p.scratch.append(p.gpa, test_decl_node); |
| 237 | } | 228 | } |
| 238 | trailing = false; | 229 | trailing = false; |
| 239 | }, | 230 | }, |
| ... | @@ -254,7 +245,7 @@ const Parser = struct { | ... | @@ -254,7 +245,7 @@ const Parser = struct { |
| 254 | field_state = .err; | 245 | field_state = .err; |
| 255 | }, | 246 | }, |
| 256 | } | 247 | } |
| 257 | try list.append(container_field); | 248 | try p.scratch.append(p.gpa, container_field); |
| 258 | switch (p.token_tags[p.tok_i]) { | 249 | switch (p.token_tags[p.tok_i]) { |
| 259 | .comma => { | 250 | .comma => { |
| 260 | p.tok_i += 1; | 251 | p.tok_i += 1; |
| ... | @@ -294,7 +285,7 @@ const Parser = struct { | ... | @@ -294,7 +285,7 @@ const Parser = struct { |
| 294 | if (field_state == .seen) { | 285 | if (field_state == .seen) { |
| 295 | field_state = .{ .end = comptime_node }; | 286 | field_state = .{ .end = comptime_node }; |
| 296 | } | 287 | } |
| 297 | try list.append(comptime_node); | 288 | try p.scratch.append(p.gpa, comptime_node); |
| 298 | } | 289 | } |
| 299 | trailing = false; | 290 | trailing = false; |
| 300 | }, | 291 | }, |
| ... | @@ -310,7 +301,7 @@ const Parser = struct { | ... | @@ -310,7 +301,7 @@ const Parser = struct { |
| 310 | if (field_state == .seen) { | 301 | if (field_state == .seen) { |
| 311 | field_state = .{ .end = top_level_decl }; | 302 | field_state = .{ .end = top_level_decl }; |
| 312 | } | 303 | } |
| 313 | try list.append(top_level_decl); | 304 | try p.scratch.append(p.gpa, top_level_decl); |
| 314 | } | 305 | } |
| 315 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; | 306 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; |
| 316 | }, | 307 | }, |
| ... | @@ -320,7 +311,7 @@ const Parser = struct { | ... | @@ -320,7 +311,7 @@ const Parser = struct { |
| 320 | if (field_state == .seen) { | 311 | if (field_state == .seen) { |
| 321 | field_state = .{ .end = node }; | 312 | field_state = .{ .end = node }; |
| 322 | } | 313 | } |
| 323 | try list.append(node); | 314 | try p.scratch.append(p.gpa, node); |
| 324 | } | 315 | } |
| 325 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; | 316 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; |
| 326 | }, | 317 | }, |
| ... | @@ -338,7 +329,7 @@ const Parser = struct { | ... | @@ -338,7 +329,7 @@ const Parser = struct { |
| 338 | if (field_state == .seen) { | 329 | if (field_state == .seen) { |
| 339 | field_state = .{ .end = top_level_decl }; | 330 | field_state = .{ .end = top_level_decl }; |
| 340 | } | 331 | } |
| 341 | try list.append(top_level_decl); | 332 | try p.scratch.append(p.gpa, top_level_decl); |
| 342 | } | 333 | } |
| 343 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; | 334 | trailing = p.token_tags[p.tok_i - 1] == .semicolon; |
| 344 | }, | 335 | }, |
| ... | @@ -357,7 +348,7 @@ const Parser = struct { | ... | @@ -357,7 +348,7 @@ const Parser = struct { |
| 357 | field_state = .err; | 348 | field_state = .err; |
| 358 | }, | 349 | }, |
| 359 | } | 350 | } |
| 360 | try list.append(container_field); | 351 | try p.scratch.append(p.gpa, container_field); |
| 361 | switch (p.token_tags[p.tok_i]) { | 352 | switch (p.token_tags[p.tok_i]) { |
| 362 | .comma => { | 353 | .comma => { |
| 363 | p.tok_i += 1; | 354 | p.tok_i += 1; |
| ... | @@ -393,7 +384,8 @@ const Parser = struct { | ... | @@ -393,7 +384,8 @@ const Parser = struct { |
| 393 | } | 384 | } |
| 394 | } | 385 | } |
| 395 | | 386 | |
| 396 | switch (list.items.len) { | 387 | const items = p.scratch.items[scratch_top..]; |
| | 388 | switch (items.len) { |
| 397 | 0 => return Members{ | 389 | 0 => return Members{ |
| 398 | .len = 0, | 390 | .len = 0, |
| 399 | .lhs = 0, | 391 | .lhs = 0, |
| ... | @@ -402,20 +394,20 @@ const Parser = struct { | ... | @@ -402,20 +394,20 @@ const Parser = struct { |
| 402 | }, | 394 | }, |
| 403 | 1 => return Members{ | 395 | 1 => return Members{ |
| 404 | .len = 1, | 396 | .len = 1, |
| 405 | .lhs = list.items[0], | 397 | .lhs = items[0], |
| 406 | .rhs = 0, | 398 | .rhs = 0, |
| 407 | .trailing = trailing, | 399 | .trailing = trailing, |
| 408 | }, | 400 | }, |
| 409 | 2 => return Members{ | 401 | 2 => return Members{ |
| 410 | .len = 2, | 402 | .len = 2, |
| 411 | .lhs = list.items[0], | 403 | .lhs = items[0], |
| 412 | .rhs = list.items[1], | 404 | .rhs = items[1], |
| 413 | .trailing = trailing, | 405 | .trailing = trailing, |
| 414 | }, | 406 | }, |
| 415 | else => { | 407 | else => { |
| 416 | const span = try p.listToSpan(list.items); | 408 | const span = try p.listToSpan(items); |
| 417 | return Members{ | 409 | return Members{ |
| 418 | .len = list.items.len, | 410 | .len = items.len, |
| 419 | .lhs = span.start, | 411 | .lhs = span.start, |
| 420 | .rhs = span.end, | 412 | .rhs = span.end, |
| 421 | .trailing = trailing, | 413 | .trailing = trailing, |
| ... | @@ -647,8 +639,10 @@ const Parser = struct { | ... | @@ -647,8 +639,10 @@ const Parser = struct { |
| 647 | const fn_proto_index = try p.reserveNode(); | 639 | const fn_proto_index = try p.reserveNode(); |
| 648 | | 640 | |
| 649 | _ = p.eatToken(.identifier); | 641 | _ = p.eatToken(.identifier); |
| | 642 | const scratch_top = p.scratch.items.len; |
| | 643 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| | 644 | // parseParamDeclList does not shrink scratch buffer, but we will |
| 650 | const params = try p.parseParamDeclList(); | 645 | const params = try p.parseParamDeclList(); |
| 651 | defer params.deinit(p.gpa); | | |
| 652 | const align_expr = try p.parseByteAlign(); | 646 | const align_expr = try p.parseByteAlign(); |
| 653 | const section_expr = try p.parseLinkSection(); | 647 | const section_expr = try p.parseLinkSection(); |
| 654 | const callconv_expr = try p.parseCallconv(); | 648 | const callconv_expr = try p.parseCallconv(); |
| ... | @@ -662,17 +656,17 @@ const Parser = struct { | ... | @@ -662,17 +656,17 @@ const Parser = struct { |
| 662 | } | 656 | } |
| 663 | | 657 | |
| 664 | if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) { | 658 | if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) { |
| 665 | switch (params) { | 659 | switch (params.len) { |
| 666 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ | 660 | 0, 1 => return p.setNode(fn_proto_index, .{ |
| 667 | .tag = .fn_proto_simple, | 661 | .tag = .fn_proto_simple, |
| 668 | .main_token = fn_token, | 662 | .main_token = fn_token, |
| 669 | .data = .{ | 663 | .data = .{ |
| 670 | .lhs = param, | 664 | .lhs = if (params.len > 0) params[0] else 0, |
| 671 | .rhs = return_type_expr, | 665 | .rhs = return_type_expr, |
| 672 | }, | 666 | }, |
| 673 | }), | 667 | }), |
| 674 | .multi => |list| { | 668 | else => { |
| 675 | const span = try p.listToSpan(list); | 669 | const span = try p.listToSpan(params); |
| 676 | return p.setNode(fn_proto_index, .{ | 670 | return p.setNode(fn_proto_index, .{ |
| 677 | .tag = .fn_proto_multi, | 671 | .tag = .fn_proto_multi, |
| 678 | .main_token = fn_token, | 672 | .main_token = fn_token, |
| ... | @@ -687,13 +681,13 @@ const Parser = struct { | ... | @@ -687,13 +681,13 @@ const Parser = struct { |
| 687 | }, | 681 | }, |
| 688 | } | 682 | } |
| 689 | } | 683 | } |
| 690 | switch (params) { | 684 | switch (params.len) { |
| 691 | .zero_or_one => |param| return p.setNode(fn_proto_index, .{ | 685 | 0, 1 => return p.setNode(fn_proto_index, .{ |
| 692 | .tag = .fn_proto_one, | 686 | .tag = .fn_proto_one, |
| 693 | .main_token = fn_token, | 687 | .main_token = fn_token, |
| 694 | .data = .{ | 688 | .data = .{ |
| 695 | .lhs = try p.addExtra(Node.FnProtoOne{ | 689 | .lhs = try p.addExtra(Node.FnProtoOne{ |
| 696 | .param = param, | 690 | .param = if (params.len > 0) params[0] else 0, |
| 697 | .align_expr = align_expr, | 691 | .align_expr = align_expr, |
| 698 | .section_expr = section_expr, | 692 | .section_expr = section_expr, |
| 699 | .callconv_expr = callconv_expr, | 693 | .callconv_expr = callconv_expr, |
| ... | @@ -701,8 +695,8 @@ const Parser = struct { | ... | @@ -701,8 +695,8 @@ const Parser = struct { |
| 701 | .rhs = return_type_expr, | 695 | .rhs = return_type_expr, |
| 702 | }, | 696 | }, |
| 703 | }), | 697 | }), |
| 704 | .multi => |list| { | 698 | else => { |
| 705 | const span = try p.listToSpan(list); | 699 | const span = try p.listToSpan(params); |
| 706 | return p.setNode(fn_proto_index, .{ | 700 | return p.setNode(fn_proto_index, .{ |
| 707 | .tag = .fn_proto, | 701 | .tag = .fn_proto, |
| 708 | .main_token = fn_token, | 702 | .main_token = fn_token, |
| ... | @@ -1894,20 +1888,20 @@ const Parser = struct { | ... | @@ -1894,20 +1888,20 @@ const Parser = struct { |
| 1894 | }); | 1888 | }); |
| 1895 | } | 1889 | } |
| 1896 | | 1890 | |
| 1897 | var statements = std.ArrayList(Node.Index).init(p.gpa); | 1891 | const scratch_top = p.scratch.items.len; |
| 1898 | defer statements.deinit(); | 1892 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 1899 | | 1893 | |
| 1900 | try statements.appendSlice(&.{ stmt_one, stmt_two }); | 1894 | try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two }); |
| 1901 | | 1895 | |
| 1902 | while (true) { | 1896 | while (true) { |
| 1903 | const statement = try p.expectStatementRecoverable(); | 1897 | const statement = try p.expectStatementRecoverable(); |
| 1904 | if (statement == 0) break; | 1898 | if (statement == 0) break; |
| 1905 | try statements.append(statement); | 1899 | try p.scratch.append(p.gpa, statement); |
| 1906 | if (p.token_tags[p.tok_i] == .r_brace) break; | 1900 | if (p.token_tags[p.tok_i] == .r_brace) break; |
| 1907 | } | 1901 | } |
| 1908 | _ = try p.expectToken(.r_brace); | 1902 | _ = try p.expectToken(.r_brace); |
| 1909 | const semicolon = p.token_tags[p.tok_i - 2] == .semicolon; | 1903 | const semicolon = p.token_tags[p.tok_i - 2] == .semicolon; |
| 1910 | const statements_span = try p.listToSpan(statements.items); | 1904 | const statements_span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 1911 | return p.addNode(.{ | 1905 | return p.addNode(.{ |
| 1912 | .tag = if (semicolon) .block_semicolon else .block, | 1906 | .tag = if (semicolon) .block_semicolon else .block, |
| 1913 | .main_token = lbrace, | 1907 | .main_token = lbrace, |
| ... | @@ -2041,14 +2035,14 @@ const Parser = struct { | ... | @@ -2041,14 +2035,14 @@ const Parser = struct { |
| 2041 | }); | 2035 | }); |
| 2042 | } | 2036 | } |
| 2043 | | 2037 | |
| 2044 | var init_list = std.ArrayList(Node.Index).init(p.gpa); | 2038 | const scratch_top = p.scratch.items.len; |
| 2045 | defer init_list.deinit(); | 2039 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2046 | | 2040 | |
| 2047 | try init_list.append(field_init); | 2041 | try p.scratch.append(p.gpa, field_init); |
| 2048 | | 2042 | |
| 2049 | while (true) { | 2043 | while (true) { |
| 2050 | const next = try p.expectFieldInit(); | 2044 | const next = try p.expectFieldInit(); |
| 2051 | try init_list.append(next); | 2045 | try p.scratch.append(p.gpa, next); |
| 2052 | | 2046 | |
| 2053 | switch (p.token_tags[p.nextToken()]) { | 2047 | switch (p.token_tags[p.nextToken()]) { |
| 2054 | .comma => { | 2048 | .comma => { |
| ... | @@ -2068,7 +2062,7 @@ const Parser = struct { | ... | @@ -2068,7 +2062,7 @@ const Parser = struct { |
| 2068 | }, | 2062 | }, |
| 2069 | } | 2063 | } |
| 2070 | } | 2064 | } |
| 2071 | const span = try p.listToSpan(init_list.items); | 2065 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2072 | return p.addNode(.{ | 2066 | return p.addNode(.{ |
| 2073 | .tag = if (p.token_tags[p.tok_i - 2] == .comma) .struct_init_comma else .struct_init, | 2067 | .tag = if (p.token_tags[p.tok_i - 2] == .comma) .struct_init_comma else .struct_init, |
| 2074 | .main_token = lbrace, | 2068 | .main_token = lbrace, |
| ... | @@ -2098,22 +2092,22 @@ const Parser = struct { | ... | @@ -2098,22 +2092,22 @@ const Parser = struct { |
| 2098 | try p.warnExpected(.comma); | 2092 | try p.warnExpected(.comma); |
| 2099 | } | 2093 | } |
| 2100 | | 2094 | |
| 2101 | var init_list = std.ArrayList(Node.Index).init(p.gpa); | 2095 | const scratch_top = p.scratch.items.len; |
| 2102 | defer init_list.deinit(); | 2096 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2103 | | 2097 | |
| 2104 | try init_list.append(elem_init); | 2098 | try p.scratch.append(p.gpa, elem_init); |
| 2105 | | 2099 | |
| 2106 | var trailing_comma = true; | 2100 | var trailing_comma = true; |
| 2107 | var next = try p.parseExpr(); | 2101 | var next = try p.parseExpr(); |
| 2108 | while (next != 0) : (next = try p.parseExpr()) { | 2102 | while (next != 0) : (next = try p.parseExpr()) { |
| 2109 | try init_list.append(next); | 2103 | try p.scratch.append(p.gpa, next); |
| 2110 | if (p.eatToken(.comma) == null) { | 2104 | if (p.eatToken(.comma) == null) { |
| 2111 | trailing_comma = false; | 2105 | trailing_comma = false; |
| 2112 | break; | 2106 | break; |
| 2113 | } | 2107 | } |
| 2114 | } | 2108 | } |
| 2115 | _ = try p.expectToken(.r_brace); | 2109 | _ = try p.expectToken(.r_brace); |
| 2116 | const span = try p.listToSpan(init_list.items); | 2110 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2117 | return p.addNode(.{ | 2111 | return p.addNode(.{ |
| 2118 | .tag = if (trailing_comma) .array_init_comma else .array_init, | 2112 | .tag = if (trailing_comma) .array_init_comma else .array_init, |
| 2119 | .main_token = lbrace, | 2113 | .main_token = lbrace, |
| ... | @@ -2188,18 +2182,18 @@ const Parser = struct { | ... | @@ -2188,18 +2182,18 @@ const Parser = struct { |
| 2188 | try p.warnExpected(.comma); | 2182 | try p.warnExpected(.comma); |
| 2189 | } | 2183 | } |
| 2190 | | 2184 | |
| 2191 | var param_list = std.ArrayList(Node.Index).init(p.gpa); | 2185 | const scratch_top = p.scratch.items.len; |
| 2192 | defer param_list.deinit(); | 2186 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2193 | | 2187 | |
| 2194 | try param_list.append(param_one); | 2188 | try p.scratch.append(p.gpa, param_one); |
| 2195 | | 2189 | |
| 2196 | while (true) { | 2190 | while (true) { |
| 2197 | const next = try p.expectExpr(); | 2191 | const next = try p.expectExpr(); |
| 2198 | try param_list.append(next); | 2192 | try p.scratch.append(p.gpa, next); |
| 2199 | switch (p.token_tags[p.nextToken()]) { | 2193 | switch (p.token_tags[p.nextToken()]) { |
| 2200 | .comma => { | 2194 | .comma => { |
| 2201 | if (p.eatToken(.r_paren)) |_| { | 2195 | if (p.eatToken(.r_paren)) |_| { |
| 2202 | const span = try p.listToSpan(param_list.items); | 2196 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2203 | return p.addNode(.{ | 2197 | return p.addNode(.{ |
| 2204 | .tag = .async_call_comma, | 2198 | .tag = .async_call_comma, |
| 2205 | .main_token = lparen, | 2199 | .main_token = lparen, |
| ... | @@ -2216,7 +2210,7 @@ const Parser = struct { | ... | @@ -2216,7 +2210,7 @@ const Parser = struct { |
| 2216 | } | 2210 | } |
| 2217 | }, | 2211 | }, |
| 2218 | .r_paren => { | 2212 | .r_paren => { |
| 2219 | const span = try p.listToSpan(param_list.items); | 2213 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2220 | return p.addNode(.{ | 2214 | return p.addNode(.{ |
| 2221 | .tag = .async_call, | 2215 | .tag = .async_call, |
| 2222 | .main_token = lparen, | 2216 | .main_token = lparen, |
| ... | @@ -2277,18 +2271,18 @@ const Parser = struct { | ... | @@ -2277,18 +2271,18 @@ const Parser = struct { |
| 2277 | try p.warnExpected(.comma); | 2271 | try p.warnExpected(.comma); |
| 2278 | } | 2272 | } |
| 2279 | | 2273 | |
| 2280 | var param_list = std.ArrayList(Node.Index).init(p.gpa); | 2274 | const scratch_top = p.scratch.items.len; |
| 2281 | defer param_list.deinit(); | 2275 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2282 | | 2276 | |
| 2283 | try param_list.append(param_one); | 2277 | try p.scratch.append(p.gpa, param_one); |
| 2284 | | 2278 | |
| 2285 | while (true) { | 2279 | while (true) { |
| 2286 | const next = try p.expectExpr(); | 2280 | const next = try p.expectExpr(); |
| 2287 | try param_list.append(next); | 2281 | try p.scratch.append(p.gpa, next); |
| 2288 | switch (p.token_tags[p.nextToken()]) { | 2282 | switch (p.token_tags[p.nextToken()]) { |
| 2289 | .comma => { | 2283 | .comma => { |
| 2290 | if (p.eatToken(.r_paren)) |_| { | 2284 | if (p.eatToken(.r_paren)) |_| { |
| 2291 | const span = try p.listToSpan(param_list.items); | 2285 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2292 | break :res try p.addNode(.{ | 2286 | break :res try p.addNode(.{ |
| 2293 | .tag = .call_comma, | 2287 | .tag = .call_comma, |
| 2294 | .main_token = lparen, | 2288 | .main_token = lparen, |
| ... | @@ -2305,7 +2299,7 @@ const Parser = struct { | ... | @@ -2305,7 +2299,7 @@ const Parser = struct { |
| 2305 | } | 2299 | } |
| 2306 | }, | 2300 | }, |
| 2307 | .r_paren => { | 2301 | .r_paren => { |
| 2308 | const span = try p.listToSpan(param_list.items); | 2302 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2309 | break :res try p.addNode(.{ | 2303 | break :res try p.addNode(.{ |
| 2310 | .tag = .call, | 2304 | .tag = .call, |
| 2311 | .main_token = lparen, | 2305 | .main_token = lparen, |
| ... | @@ -2602,15 +2596,15 @@ const Parser = struct { | ... | @@ -2602,15 +2596,15 @@ const Parser = struct { |
| 2602 | if (comma_two == null) { | 2596 | if (comma_two == null) { |
| 2603 | try p.warnExpected(.comma); | 2597 | try p.warnExpected(.comma); |
| 2604 | } | 2598 | } |
| 2605 | var init_list = std.ArrayList(Node.Index).init(p.gpa); | 2599 | const scratch_top = p.scratch.items.len; |
| 2606 | defer init_list.deinit(); | 2600 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2607 | | 2601 | |
| 2608 | try init_list.appendSlice(&.{ field_init_one, field_init_two }); | 2602 | try p.scratch.appendSlice(p.gpa, &.{ field_init_one, field_init_two }); |
| 2609 | | 2603 | |
| 2610 | while (true) { | 2604 | while (true) { |
| 2611 | const next = try p.expectFieldInit(); | 2605 | const next = try p.expectFieldInit(); |
| 2612 | assert(next != 0); | 2606 | assert(next != 0); |
| 2613 | try init_list.append(next); | 2607 | try p.scratch.append(p.gpa, next); |
| 2614 | switch (p.token_tags[p.nextToken()]) { | 2608 | switch (p.token_tags[p.nextToken()]) { |
| 2615 | .comma => { | 2609 | .comma => { |
| 2616 | if (p.eatToken(.r_brace)) |_| break; | 2610 | if (p.eatToken(.r_brace)) |_| break; |
| ... | @@ -2627,7 +2621,7 @@ const Parser = struct { | ... | @@ -2627,7 +2621,7 @@ const Parser = struct { |
| 2627 | }, | 2621 | }, |
| 2628 | } | 2622 | } |
| 2629 | } | 2623 | } |
| 2630 | const span = try p.listToSpan(init_list.items); | 2624 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2631 | const trailing_comma = p.token_tags[p.tok_i - 2] == .comma; | 2625 | const trailing_comma = p.token_tags[p.tok_i - 2] == .comma; |
| 2632 | return p.addNode(.{ | 2626 | return p.addNode(.{ |
| 2633 | .tag = if (trailing_comma) .struct_init_dot_comma else .struct_init_dot, | 2627 | .tag = if (trailing_comma) .struct_init_dot_comma else .struct_init_dot, |
| ... | @@ -2669,15 +2663,15 @@ const Parser = struct { | ... | @@ -2669,15 +2663,15 @@ const Parser = struct { |
| 2669 | if (comma_two == null) { | 2663 | if (comma_two == null) { |
| 2670 | try p.warnExpected(.comma); | 2664 | try p.warnExpected(.comma); |
| 2671 | } | 2665 | } |
| 2672 | var init_list = std.ArrayList(Node.Index).init(p.gpa); | 2666 | const scratch_top = p.scratch.items.len; |
| 2673 | defer init_list.deinit(); | 2667 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2674 | | 2668 | |
| 2675 | try init_list.appendSlice(&.{ elem_init_one, elem_init_two }); | 2669 | try p.scratch.appendSlice(p.gpa, &.{ elem_init_one, elem_init_two }); |
| 2676 | | 2670 | |
| 2677 | while (true) { | 2671 | while (true) { |
| 2678 | const next = try p.expectExpr(); | 2672 | const next = try p.expectExpr(); |
| 2679 | if (next == 0) break; | 2673 | if (next == 0) break; |
| 2680 | try init_list.append(next); | 2674 | try p.scratch.append(p.gpa, next); |
| 2681 | switch (p.token_tags[p.nextToken()]) { | 2675 | switch (p.token_tags[p.nextToken()]) { |
| 2682 | .comma => { | 2676 | .comma => { |
| 2683 | if (p.eatToken(.r_brace)) |_| break; | 2677 | if (p.eatToken(.r_brace)) |_| break; |
| ... | @@ -2694,7 +2688,7 @@ const Parser = struct { | ... | @@ -2694,7 +2688,7 @@ const Parser = struct { |
| 2694 | }, | 2688 | }, |
| 2695 | } | 2689 | } |
| 2696 | } | 2690 | } |
| 2697 | const span = try p.listToSpan(init_list.items); | 2691 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2698 | return p.addNode(.{ | 2692 | return p.addNode(.{ |
| 2699 | .tag = if (p.token_tags[p.tok_i - 2] == .comma) .array_init_dot_comma else .array_init_dot, | 2693 | .tag = if (p.token_tags[p.tok_i - 2] == .comma) .array_init_dot_comma else .array_init_dot, |
| 2700 | .main_token = lbrace, | 2694 | .main_token = lbrace, |
| ... | @@ -2924,13 +2918,13 @@ const Parser = struct { | ... | @@ -2924,13 +2918,13 @@ const Parser = struct { |
| 2924 | | 2918 | |
| 2925 | _ = try p.expectToken(.colon); | 2919 | _ = try p.expectToken(.colon); |
| 2926 | | 2920 | |
| 2927 | var list = std.ArrayList(Node.Index).init(p.gpa); | 2921 | const scratch_top = p.scratch.items.len; |
| 2928 | defer list.deinit(); | 2922 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 2929 | | 2923 | |
| 2930 | while (true) { | 2924 | while (true) { |
| 2931 | const output_item = try p.parseAsmOutputItem(); | 2925 | const output_item = try p.parseAsmOutputItem(); |
| 2932 | if (output_item == 0) break; | 2926 | if (output_item == 0) break; |
| 2933 | try list.append(output_item); | 2927 | try p.scratch.append(p.gpa, output_item); |
| 2934 | switch (p.token_tags[p.tok_i]) { | 2928 | switch (p.token_tags[p.tok_i]) { |
| 2935 | .comma => p.tok_i += 1, | 2929 | .comma => p.tok_i += 1, |
| 2936 | .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. | 2930 | .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. |
| ... | @@ -2945,7 +2939,7 @@ const Parser = struct { | ... | @@ -2945,7 +2939,7 @@ const Parser = struct { |
| 2945 | while (true) { | 2939 | while (true) { |
| 2946 | const input_item = try p.parseAsmInputItem(); | 2940 | const input_item = try p.parseAsmInputItem(); |
| 2947 | if (input_item == 0) break; | 2941 | if (input_item == 0) break; |
| 2948 | try list.append(input_item); | 2942 | try p.scratch.append(p.gpa, input_item); |
| 2949 | switch (p.token_tags[p.tok_i]) { | 2943 | switch (p.token_tags[p.tok_i]) { |
| 2950 | .comma => p.tok_i += 1, | 2944 | .comma => p.tok_i += 1, |
| 2951 | .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. | 2945 | .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters. |
| ... | @@ -2971,7 +2965,7 @@ const Parser = struct { | ... | @@ -2971,7 +2965,7 @@ const Parser = struct { |
| 2971 | } | 2965 | } |
| 2972 | } | 2966 | } |
| 2973 | const rparen = try p.expectToken(.r_paren); | 2967 | const rparen = try p.expectToken(.r_paren); |
| 2974 | const span = try p.listToSpan(list.items); | 2968 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 2975 | return p.addNode(.{ | 2969 | return p.addNode(.{ |
| 2976 | .tag = .@"asm", | 2970 | .tag = .@"asm", |
| 2977 | .main_token = asm_token, | 2971 | .main_token = asm_token, |
| ... | @@ -3192,16 +3186,16 @@ const Parser = struct { | ... | @@ -3192,16 +3186,16 @@ const Parser = struct { |
| 3192 | }); | 3186 | }); |
| 3193 | } | 3187 | } |
| 3194 | | 3188 | |
| 3195 | var list = std.ArrayList(Node.Index).init(p.gpa); | 3189 | const scratch_top = p.scratch.items.len; |
| 3196 | defer list.deinit(); | 3190 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3197 | | 3191 | |
| 3198 | try list.append(first_item); | 3192 | try p.scratch.append(p.gpa, first_item); |
| 3199 | while (p.eatToken(.comma)) |_| { | 3193 | while (p.eatToken(.comma)) |_| { |
| 3200 | const next_item = try p.parseSwitchItem(); | 3194 | const next_item = try p.parseSwitchItem(); |
| 3201 | if (next_item == 0) break; | 3195 | if (next_item == 0) break; |
| 3202 | try list.append(next_item); | 3196 | try p.scratch.append(p.gpa, next_item); |
| 3203 | } | 3197 | } |
| 3204 | const span = try p.listToSpan(list.items); | 3198 | const span = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 3205 | const arrow_token = try p.expectToken(.equal_angle_bracket_right); | 3199 | const arrow_token = try p.expectToken(.equal_angle_bracket_right); |
| 3206 | _ = try p.parsePtrPayload(); | 3200 | _ = try p.parsePtrPayload(); |
| 3207 | return p.addNode(.{ | 3201 | return p.addNode(.{ |
| ... | @@ -3556,10 +3550,13 @@ const Parser = struct { | ... | @@ -3556,10 +3550,13 @@ const Parser = struct { |
| 3556 | } | 3550 | } |
| 3557 | | 3551 | |
| 3558 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? | 3552 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? |
| 3559 | fn parseParamDeclList(p: *Parser) !SmallSpan { | 3553 | fn parseParamDeclList(p: *Parser) ![]Node.Index { |
| | 3554 | const scratch_top = p.scratch.items.len; |
| | 3555 | // don't defer p.scratch.shrinkRetainingCapacity because caller will do it |
| | 3556 | |
| 3560 | _ = try p.expectToken(.l_paren); | 3557 | _ = try p.expectToken(.l_paren); |
| 3561 | if (p.eatToken(.r_paren)) |_| { | 3558 | if (p.eatToken(.r_paren)) |_| { |
| 3562 | return SmallSpan{ .zero_or_one = 0 }; | 3559 | return p.scratch.items[scratch_top..]; |
| 3563 | } | 3560 | } |
| 3564 | const param_one = while (true) { | 3561 | const param_one = while (true) { |
| 3565 | const param = try p.expectParamDecl(); | 3562 | const param = try p.expectParamDecl(); |
| ... | @@ -3567,10 +3564,10 @@ const Parser = struct { | ... | @@ -3567,10 +3564,10 @@ const Parser = struct { |
| 3567 | switch (p.token_tags[p.nextToken()]) { | 3564 | switch (p.token_tags[p.nextToken()]) { |
| 3568 | .comma => { | 3565 | .comma => { |
| 3569 | if (p.eatToken(.r_paren)) |_| { | 3566 | if (p.eatToken(.r_paren)) |_| { |
| 3570 | return SmallSpan{ .zero_or_one = 0 }; | 3567 | return p.scratch.items[scratch_top..]; |
| 3571 | } | 3568 | } |
| 3572 | }, | 3569 | }, |
| 3573 | .r_paren => return SmallSpan{ .zero_or_one = 0 }, | 3570 | .r_paren => return p.scratch.items[scratch_top..], |
| 3574 | else => { | 3571 | else => { |
| 3575 | // This is likely just a missing comma; | 3572 | // This is likely just a missing comma; |
| 3576 | // give an error but continue parsing this list. | 3573 | // give an error but continue parsing this list. |
| ... | @@ -3579,11 +3576,12 @@ const Parser = struct { | ... | @@ -3579,11 +3576,12 @@ const Parser = struct { |
| 3579 | }, | 3576 | }, |
| 3580 | } | 3577 | } |
| 3581 | } else unreachable; | 3578 | } else unreachable; |
| | 3579 | try p.scratch.append(p.gpa, param_one); |
| 3582 | | 3580 | |
| 3583 | const param_two = while (true) { | 3581 | const param_two = while (true) { |
| 3584 | switch (p.token_tags[p.nextToken()]) { | 3582 | switch (p.token_tags[p.nextToken()]) { |
| 3585 | .comma => {}, | 3583 | .comma => {}, |
| 3586 | .r_paren => return SmallSpan{ .zero_or_one = param_one }, | 3584 | .r_paren => return p.scratch.items[scratch_top..], |
| 3587 | .colon, .r_brace, .r_bracket => { | 3585 | .colon, .r_brace, .r_bracket => { |
| 3588 | p.tok_i -= 1; | 3586 | p.tok_i -= 1; |
| 3589 | return p.failExpected(.r_paren); | 3587 | return p.failExpected(.r_paren); |
| ... | @@ -3596,21 +3594,17 @@ const Parser = struct { | ... | @@ -3596,21 +3594,17 @@ const Parser = struct { |
| 3596 | }, | 3594 | }, |
| 3597 | } | 3595 | } |
| 3598 | if (p.eatToken(.r_paren)) |_| { | 3596 | if (p.eatToken(.r_paren)) |_| { |
| 3599 | return SmallSpan{ .zero_or_one = param_one }; | 3597 | return p.scratch.items[scratch_top..]; |
| 3600 | } | 3598 | } |
| 3601 | const param = try p.expectParamDecl(); | 3599 | const param = try p.expectParamDecl(); |
| 3602 | if (param != 0) break param; | 3600 | if (param != 0) break param; |
| 3603 | } else unreachable; | 3601 | } else unreachable; |
| 3604 | | 3602 | try p.scratch.append(p.gpa, param_two); |
| 3605 | var list = std.ArrayList(Node.Index).init(p.gpa); | | |
| 3606 | defer list.deinit(); | | |
| 3607 | | | |
| 3608 | try list.appendSlice(&.{ param_one, param_two }); | | |
| 3609 | | 3603 | |
| 3610 | while (true) { | 3604 | while (true) { |
| 3611 | switch (p.token_tags[p.nextToken()]) { | 3605 | switch (p.token_tags[p.nextToken()]) { |
| 3612 | .comma => {}, | 3606 | .comma => {}, |
| 3613 | .r_paren => return SmallSpan{ .multi = list.toOwnedSlice() }, | 3607 | .r_paren => return p.scratch.items[scratch_top..], |
| 3614 | .colon, .r_brace, .r_bracket => { | 3608 | .colon, .r_brace, .r_bracket => { |
| 3615 | p.tok_i -= 1; | 3609 | p.tok_i -= 1; |
| 3616 | return p.failExpected(.r_paren); | 3610 | return p.failExpected(.r_paren); |
| ... | @@ -3623,10 +3617,10 @@ const Parser = struct { | ... | @@ -3623,10 +3617,10 @@ const Parser = struct { |
| 3623 | }, | 3617 | }, |
| 3624 | } | 3618 | } |
| 3625 | if (p.eatToken(.r_paren)) |_| { | 3619 | if (p.eatToken(.r_paren)) |_| { |
| 3626 | return SmallSpan{ .multi = list.toOwnedSlice() }; | 3620 | return p.scratch.items[scratch_top..]; |
| 3627 | } | 3621 | } |
| 3628 | const param = try p.expectParamDecl(); | 3622 | const param = try p.expectParamDecl(); |
| 3629 | if (param != 0) try list.append(param); | 3623 | if (param != 0) try p.scratch.append(p.gpa, param); |
| 3630 | } | 3624 | } |
| 3631 | } | 3625 | } |
| 3632 | | 3626 | |
| ... | @@ -3635,14 +3629,14 @@ const Parser = struct { | ... | @@ -3635,14 +3629,14 @@ const Parser = struct { |
| 3635 | fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) { | 3629 | fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) { |
| 3636 | return struct { | 3630 | return struct { |
| 3637 | pub fn parse(p: *Parser) Error!Node.SubRange { | 3631 | pub fn parse(p: *Parser) Error!Node.SubRange { |
| 3638 | var list = std.ArrayList(Node.Index).init(p.gpa); | 3632 | const scratch_top = p.scratch.items.len; |
| 3639 | defer list.deinit(); | 3633 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3640 | | 3634 | |
| 3641 | while (true) { | 3635 | while (true) { |
| 3642 | const item = try nodeParseFn(p); | 3636 | const item = try nodeParseFn(p); |
| 3643 | if (item == 0) break; | 3637 | if (item == 0) break; |
| 3644 | | 3638 | |
| 3645 | try list.append(item); | 3639 | try p.scratch.append(p.gpa, item); |
| 3646 | | 3640 | |
| 3647 | switch (p.token_tags[p.tok_i]) { | 3641 | switch (p.token_tags[p.tok_i]) { |
| 3648 | .comma => p.tok_i += 1, | 3642 | .comma => p.tok_i += 1, |
| ... | @@ -3655,7 +3649,7 @@ const Parser = struct { | ... | @@ -3655,7 +3649,7 @@ const Parser = struct { |
| 3655 | }, | 3649 | }, |
| 3656 | } | 3650 | } |
| 3657 | } | 3651 | } |
| 3658 | return p.listToSpan(list.items); | 3652 | return p.listToSpan(p.scratch.items[scratch_top..]); |
| 3659 | } | 3653 | } |
| 3660 | }.parse; | 3654 | }.parse; |
| 3661 | } | 3655 | } |
| ... | @@ -3746,18 +3740,18 @@ const Parser = struct { | ... | @@ -3746,18 +3740,18 @@ const Parser = struct { |
| 3746 | }, | 3740 | }, |
| 3747 | } | 3741 | } |
| 3748 | | 3742 | |
| 3749 | var list = std.ArrayList(Node.Index).init(p.gpa); | 3743 | const scratch_top = p.scratch.items.len; |
| 3750 | defer list.deinit(); | 3744 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3751 | | 3745 | |
| 3752 | try list.appendSlice(&.{ param_one, param_two }); | 3746 | try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two }); |
| 3753 | | 3747 | |
| 3754 | while (true) { | 3748 | while (true) { |
| 3755 | const param = try p.expectExpr(); | 3749 | const param = try p.expectExpr(); |
| 3756 | try list.append(param); | 3750 | try p.scratch.append(p.gpa, param); |
| 3757 | switch (p.token_tags[p.nextToken()]) { | 3751 | switch (p.token_tags[p.nextToken()]) { |
| 3758 | .comma => { | 3752 | .comma => { |
| 3759 | if (p.eatToken(.r_paren)) |_| { | 3753 | if (p.eatToken(.r_paren)) |_| { |
| 3760 | const params = try p.listToSpan(list.items); | 3754 | const params = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 3761 | return p.addNode(.{ | 3755 | return p.addNode(.{ |
| 3762 | .tag = .builtin_call_comma, | 3756 | .tag = .builtin_call_comma, |
| 3763 | .main_token = builtin_token, | 3757 | .main_token = builtin_token, |
| ... | @@ -3770,7 +3764,7 @@ const Parser = struct { | ... | @@ -3770,7 +3764,7 @@ const Parser = struct { |
| 3770 | continue; | 3764 | continue; |
| 3771 | }, | 3765 | }, |
| 3772 | .r_paren => { | 3766 | .r_paren => { |
| 3773 | const params = try p.listToSpan(list.items); | 3767 | const params = try p.listToSpan(p.scratch.items[scratch_top..]); |
| 3774 | return p.addNode(.{ | 3768 | return p.addNode(.{ |
| 3775 | .tag = .builtin_call, | 3769 | .tag = .builtin_call, |
| 3776 | .main_token = builtin_token, | 3770 | .main_token = builtin_token, |