authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-26 19:14:52-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-26 22:01:04-04:00
log9ddd12ea14ba1aa3f6f97d87fd13a636812aa6ea
tree8075a5802e68e199669e95d7b3129ebf540a49f1
parentf750618846f598836e5170c31ac4988df2d6f00d

parse.zig: use shared scratch buffer to avoid allocating and freeing many small lists


1 files changed, 103 insertions(+), 109 deletions(-)

lib/std/zig/parse.zig+103-109
......@@ -43,11 +43,13 @@ pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!Tree {
4343 .errors = .{},
4444 .nodes = .{},
4545 .extra_data = .{},
46 .scratch = .{},
4647 .tok_i = 0,
4748 };
4849 defer parser.errors.deinit(gpa);
4950 defer parser.nodes.deinit(gpa);
5051 defer parser.extra_data.deinit(gpa);
52 defer parser.scratch.deinit(gpa);
5153
5254 // Empirically, Zig source code has a 2:1 ratio of tokens to AST nodes.
5355 // Make sure at least 1 so we can use appendAssumeCapacity on the root node below.
......@@ -93,18 +95,7 @@ const Parser = struct {
9395 errors: std.ArrayListUnmanaged(AstError),
9496 nodes: ast.NodeList,
9597 extra_data: std.ArrayListUnmanaged(Node.Index),
96
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 };
98 scratch: std.ArrayListUnmanaged(Node.Index),
10899
109100 const Members = struct {
110101 len: usize,
......@@ -204,8 +195,8 @@ const Parser = struct {
204195 /// /
205196 /// TopLevelComptime <- KEYWORD_comptime BlockExpr
206197 fn parseContainerMembers(p: *Parser) !Members {
207 var list = std.ArrayList(Node.Index).init(p.gpa);
208 defer list.deinit();
198 const scratch_top = p.scratch.items.len;
199 defer p.scratch.shrinkRetainingCapacity(scratch_top);
209200
210201 var field_state: union(enum) {
211202 /// No fields have been seen.
......@@ -233,7 +224,7 @@ const Parser = struct {
233224 if (field_state == .seen) {
234225 field_state = .{ .end = test_decl_node };
235226 }
236 try list.append(test_decl_node);
227 try p.scratch.append(p.gpa, test_decl_node);
237228 }
238229 trailing = false;
239230 },
......@@ -254,7 +245,7 @@ const Parser = struct {
254245 field_state = .err;
255246 },
256247 }
257 try list.append(container_field);
248 try p.scratch.append(p.gpa, container_field);
258249 switch (p.token_tags[p.tok_i]) {
259250 .comma => {
260251 p.tok_i += 1;
......@@ -294,7 +285,7 @@ const Parser = struct {
294285 if (field_state == .seen) {
295286 field_state = .{ .end = comptime_node };
296287 }
297 try list.append(comptime_node);
288 try p.scratch.append(p.gpa, comptime_node);
298289 }
299290 trailing = false;
300291 },
......@@ -310,7 +301,7 @@ const Parser = struct {
310301 if (field_state == .seen) {
311302 field_state = .{ .end = top_level_decl };
312303 }
313 try list.append(top_level_decl);
304 try p.scratch.append(p.gpa, top_level_decl);
314305 }
315306 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
316307 },
......@@ -320,7 +311,7 @@ const Parser = struct {
320311 if (field_state == .seen) {
321312 field_state = .{ .end = node };
322313 }
323 try list.append(node);
314 try p.scratch.append(p.gpa, node);
324315 }
325316 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
326317 },
......@@ -338,7 +329,7 @@ const Parser = struct {
338329 if (field_state == .seen) {
339330 field_state = .{ .end = top_level_decl };
340331 }
341 try list.append(top_level_decl);
332 try p.scratch.append(p.gpa, top_level_decl);
342333 }
343334 trailing = p.token_tags[p.tok_i - 1] == .semicolon;
344335 },
......@@ -357,7 +348,7 @@ const Parser = struct {
357348 field_state = .err;
358349 },
359350 }
360 try list.append(container_field);
351 try p.scratch.append(p.gpa, container_field);
361352 switch (p.token_tags[p.tok_i]) {
362353 .comma => {
363354 p.tok_i += 1;
......@@ -393,7 +384,8 @@ const Parser = struct {
393384 }
394385 }
395386
396 switch (list.items.len) {
387 const items = p.scratch.items[scratch_top..];
388 switch (items.len) {
397389 0 => return Members{
398390 .len = 0,
399391 .lhs = 0,
......@@ -402,20 +394,20 @@ const Parser = struct {
402394 },
403395 1 => return Members{
404396 .len = 1,
405 .lhs = list.items[0],
397 .lhs = items[0],
406398 .rhs = 0,
407399 .trailing = trailing,
408400 },
409401 2 => return Members{
410402 .len = 2,
411 .lhs = list.items[0],
412 .rhs = list.items[1],
403 .lhs = items[0],
404 .rhs = items[1],
413405 .trailing = trailing,
414406 },
415407 else => {
416 const span = try p.listToSpan(list.items);
408 const span = try p.listToSpan(items);
417409 return Members{
418 .len = list.items.len,
410 .len = items.len,
419411 .lhs = span.start,
420412 .rhs = span.end,
421413 .trailing = trailing,
......@@ -647,8 +639,10 @@ const Parser = struct {
647639 const fn_proto_index = try p.reserveNode();
648640
649641 _ = 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
650645 const params = try p.parseParamDeclList();
651 defer params.deinit(p.gpa);
652646 const align_expr = try p.parseByteAlign();
653647 const section_expr = try p.parseLinkSection();
654648 const callconv_expr = try p.parseCallconv();
......@@ -662,17 +656,17 @@ const Parser = struct {
662656 }
663657
664658 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
665 switch (params) {
666 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
659 switch (params.len) {
660 0, 1 => return p.setNode(fn_proto_index, .{
667661 .tag = .fn_proto_simple,
668662 .main_token = fn_token,
669663 .data = .{
670 .lhs = param,
664 .lhs = if (params.len > 0) params[0] else 0,
671665 .rhs = return_type_expr,
672666 },
673667 }),
674 .multi => |list| {
675 const span = try p.listToSpan(list);
668 else => {
669 const span = try p.listToSpan(params);
676670 return p.setNode(fn_proto_index, .{
677671 .tag = .fn_proto_multi,
678672 .main_token = fn_token,
......@@ -687,13 +681,13 @@ const Parser = struct {
687681 },
688682 }
689683 }
690 switch (params) {
691 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
684 switch (params.len) {
685 0, 1 => return p.setNode(fn_proto_index, .{
692686 .tag = .fn_proto_one,
693687 .main_token = fn_token,
694688 .data = .{
695689 .lhs = try p.addExtra(Node.FnProtoOne{
696 .param = param,
690 .param = if (params.len > 0) params[0] else 0,
697691 .align_expr = align_expr,
698692 .section_expr = section_expr,
699693 .callconv_expr = callconv_expr,
......@@ -701,8 +695,8 @@ const Parser = struct {
701695 .rhs = return_type_expr,
702696 },
703697 }),
704 .multi => |list| {
705 const span = try p.listToSpan(list);
698 else => {
699 const span = try p.listToSpan(params);
706700 return p.setNode(fn_proto_index, .{
707701 .tag = .fn_proto,
708702 .main_token = fn_token,
......@@ -1894,20 +1888,20 @@ const Parser = struct {
18941888 });
18951889 }
18961890
1897 var statements = std.ArrayList(Node.Index).init(p.gpa);
1898 defer statements.deinit();
1891 const scratch_top = p.scratch.items.len;
1892 defer p.scratch.shrinkRetainingCapacity(scratch_top);
18991893
1900 try statements.appendSlice(&.{ stmt_one, stmt_two });
1894 try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two });
19011895
19021896 while (true) {
19031897 const statement = try p.expectStatementRecoverable();
19041898 if (statement == 0) break;
1905 try statements.append(statement);
1899 try p.scratch.append(p.gpa, statement);
19061900 if (p.token_tags[p.tok_i] == .r_brace) break;
19071901 }
19081902 _ = try p.expectToken(.r_brace);
19091903 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..]);
19111905 return p.addNode(.{
19121906 .tag = if (semicolon) .block_semicolon else .block,
19131907 .main_token = lbrace,
......@@ -2041,14 +2035,14 @@ const Parser = struct {
20412035 });
20422036 }
20432037
2044 var init_list = std.ArrayList(Node.Index).init(p.gpa);
2045 defer init_list.deinit();
2038 const scratch_top = p.scratch.items.len;
2039 defer p.scratch.shrinkRetainingCapacity(scratch_top);
20462040
2047 try init_list.append(field_init);
2041 try p.scratch.append(p.gpa, field_init);
20482042
20492043 while (true) {
20502044 const next = try p.expectFieldInit();
2051 try init_list.append(next);
2045 try p.scratch.append(p.gpa, next);
20522046
20532047 switch (p.token_tags[p.nextToken()]) {
20542048 .comma => {
......@@ -2068,7 +2062,7 @@ const Parser = struct {
20682062 },
20692063 }
20702064 }
2071 const span = try p.listToSpan(init_list.items);
2065 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
20722066 return p.addNode(.{
20732067 .tag = if (p.token_tags[p.tok_i - 2] == .comma) .struct_init_comma else .struct_init,
20742068 .main_token = lbrace,
......@@ -2098,22 +2092,22 @@ const Parser = struct {
20982092 try p.warnExpected(.comma);
20992093 }
21002094
2101 var init_list = std.ArrayList(Node.Index).init(p.gpa);
2102 defer init_list.deinit();
2095 const scratch_top = p.scratch.items.len;
2096 defer p.scratch.shrinkRetainingCapacity(scratch_top);
21032097
2104 try init_list.append(elem_init);
2098 try p.scratch.append(p.gpa, elem_init);
21052099
21062100 var trailing_comma = true;
21072101 var next = try p.parseExpr();
21082102 while (next != 0) : (next = try p.parseExpr()) {
2109 try init_list.append(next);
2103 try p.scratch.append(p.gpa, next);
21102104 if (p.eatToken(.comma) == null) {
21112105 trailing_comma = false;
21122106 break;
21132107 }
21142108 }
21152109 _ = 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..]);
21172111 return p.addNode(.{
21182112 .tag = if (trailing_comma) .array_init_comma else .array_init,
21192113 .main_token = lbrace,
......@@ -2188,18 +2182,18 @@ const Parser = struct {
21882182 try p.warnExpected(.comma);
21892183 }
21902184
2191 var param_list = std.ArrayList(Node.Index).init(p.gpa);
2192 defer param_list.deinit();
2185 const scratch_top = p.scratch.items.len;
2186 defer p.scratch.shrinkRetainingCapacity(scratch_top);
21932187
2194 try param_list.append(param_one);
2188 try p.scratch.append(p.gpa, param_one);
21952189
21962190 while (true) {
21972191 const next = try p.expectExpr();
2198 try param_list.append(next);
2192 try p.scratch.append(p.gpa, next);
21992193 switch (p.token_tags[p.nextToken()]) {
22002194 .comma => {
22012195 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..]);
22032197 return p.addNode(.{
22042198 .tag = .async_call_comma,
22052199 .main_token = lparen,
......@@ -2216,7 +2210,7 @@ const Parser = struct {
22162210 }
22172211 },
22182212 .r_paren => {
2219 const span = try p.listToSpan(param_list.items);
2213 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
22202214 return p.addNode(.{
22212215 .tag = .async_call,
22222216 .main_token = lparen,
......@@ -2277,18 +2271,18 @@ const Parser = struct {
22772271 try p.warnExpected(.comma);
22782272 }
22792273
2280 var param_list = std.ArrayList(Node.Index).init(p.gpa);
2281 defer param_list.deinit();
2274 const scratch_top = p.scratch.items.len;
2275 defer p.scratch.shrinkRetainingCapacity(scratch_top);
22822276
2283 try param_list.append(param_one);
2277 try p.scratch.append(p.gpa, param_one);
22842278
22852279 while (true) {
22862280 const next = try p.expectExpr();
2287 try param_list.append(next);
2281 try p.scratch.append(p.gpa, next);
22882282 switch (p.token_tags[p.nextToken()]) {
22892283 .comma => {
22902284 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..]);
22922286 break :res try p.addNode(.{
22932287 .tag = .call_comma,
22942288 .main_token = lparen,
......@@ -2305,7 +2299,7 @@ const Parser = struct {
23052299 }
23062300 },
23072301 .r_paren => {
2308 const span = try p.listToSpan(param_list.items);
2302 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
23092303 break :res try p.addNode(.{
23102304 .tag = .call,
23112305 .main_token = lparen,
......@@ -2602,15 +2596,15 @@ const Parser = struct {
26022596 if (comma_two == null) {
26032597 try p.warnExpected(.comma);
26042598 }
2605 var init_list = std.ArrayList(Node.Index).init(p.gpa);
2606 defer init_list.deinit();
2599 const scratch_top = p.scratch.items.len;
2600 defer p.scratch.shrinkRetainingCapacity(scratch_top);
26072601
2608 try init_list.appendSlice(&.{ field_init_one, field_init_two });
2602 try p.scratch.appendSlice(p.gpa, &.{ field_init_one, field_init_two });
26092603
26102604 while (true) {
26112605 const next = try p.expectFieldInit();
26122606 assert(next != 0);
2613 try init_list.append(next);
2607 try p.scratch.append(p.gpa, next);
26142608 switch (p.token_tags[p.nextToken()]) {
26152609 .comma => {
26162610 if (p.eatToken(.r_brace)) |_| break;
......@@ -2627,7 +2621,7 @@ const Parser = struct {
26272621 },
26282622 }
26292623 }
2630 const span = try p.listToSpan(init_list.items);
2624 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
26312625 const trailing_comma = p.token_tags[p.tok_i - 2] == .comma;
26322626 return p.addNode(.{
26332627 .tag = if (trailing_comma) .struct_init_dot_comma else .struct_init_dot,
......@@ -2669,15 +2663,15 @@ const Parser = struct {
26692663 if (comma_two == null) {
26702664 try p.warnExpected(.comma);
26712665 }
2672 var init_list = std.ArrayList(Node.Index).init(p.gpa);
2673 defer init_list.deinit();
2666 const scratch_top = p.scratch.items.len;
2667 defer p.scratch.shrinkRetainingCapacity(scratch_top);
26742668
2675 try init_list.appendSlice(&.{ elem_init_one, elem_init_two });
2669 try p.scratch.appendSlice(p.gpa, &.{ elem_init_one, elem_init_two });
26762670
26772671 while (true) {
26782672 const next = try p.expectExpr();
26792673 if (next == 0) break;
2680 try init_list.append(next);
2674 try p.scratch.append(p.gpa, next);
26812675 switch (p.token_tags[p.nextToken()]) {
26822676 .comma => {
26832677 if (p.eatToken(.r_brace)) |_| break;
......@@ -2694,7 +2688,7 @@ const Parser = struct {
26942688 },
26952689 }
26962690 }
2697 const span = try p.listToSpan(init_list.items);
2691 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
26982692 return p.addNode(.{
26992693 .tag = if (p.token_tags[p.tok_i - 2] == .comma) .array_init_dot_comma else .array_init_dot,
27002694 .main_token = lbrace,
......@@ -2924,13 +2918,13 @@ const Parser = struct {
29242918
29252919 _ = try p.expectToken(.colon);
29262920
2927 var list = std.ArrayList(Node.Index).init(p.gpa);
2928 defer list.deinit();
2921 const scratch_top = p.scratch.items.len;
2922 defer p.scratch.shrinkRetainingCapacity(scratch_top);
29292923
29302924 while (true) {
29312925 const output_item = try p.parseAsmOutputItem();
29322926 if (output_item == 0) break;
2933 try list.append(output_item);
2927 try p.scratch.append(p.gpa, output_item);
29342928 switch (p.token_tags[p.tok_i]) {
29352929 .comma => p.tok_i += 1,
29362930 .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters.
......@@ -2945,7 +2939,7 @@ const Parser = struct {
29452939 while (true) {
29462940 const input_item = try p.parseAsmInputItem();
29472941 if (input_item == 0) break;
2948 try list.append(input_item);
2942 try p.scratch.append(p.gpa, input_item);
29492943 switch (p.token_tags[p.tok_i]) {
29502944 .comma => p.tok_i += 1,
29512945 .colon, .r_paren, .r_brace, .r_bracket => break, // All possible delimiters.
......@@ -2971,7 +2965,7 @@ const Parser = struct {
29712965 }
29722966 }
29732967 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..]);
29752969 return p.addNode(.{
29762970 .tag = .@"asm",
29772971 .main_token = asm_token,
......@@ -3192,16 +3186,16 @@ const Parser = struct {
31923186 });
31933187 }
31943188
3195 var list = std.ArrayList(Node.Index).init(p.gpa);
3196 defer list.deinit();
3189 const scratch_top = p.scratch.items.len;
3190 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31973191
3198 try list.append(first_item);
3192 try p.scratch.append(p.gpa, first_item);
31993193 while (p.eatToken(.comma)) |_| {
32003194 const next_item = try p.parseSwitchItem();
32013195 if (next_item == 0) break;
3202 try list.append(next_item);
3196 try p.scratch.append(p.gpa, next_item);
32033197 }
3204 const span = try p.listToSpan(list.items);
3198 const span = try p.listToSpan(p.scratch.items[scratch_top..]);
32053199 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
32063200 _ = try p.parsePtrPayload();
32073201 return p.addNode(.{
......@@ -3556,10 +3550,13 @@ const Parser = struct {
35563550 }
35573551
35583552 /// 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
35603557 _ = try p.expectToken(.l_paren);
35613558 if (p.eatToken(.r_paren)) |_| {
3562 return SmallSpan{ .zero_or_one = 0 };
3559 return p.scratch.items[scratch_top..];
35633560 }
35643561 const param_one = while (true) {
35653562 const param = try p.expectParamDecl();
......@@ -3567,10 +3564,10 @@ const Parser = struct {
35673564 switch (p.token_tags[p.nextToken()]) {
35683565 .comma => {
35693566 if (p.eatToken(.r_paren)) |_| {
3570 return SmallSpan{ .zero_or_one = 0 };
3567 return p.scratch.items[scratch_top..];
35713568 }
35723569 },
3573 .r_paren => return SmallSpan{ .zero_or_one = 0 },
3570 .r_paren => return p.scratch.items[scratch_top..],
35743571 else => {
35753572 // This is likely just a missing comma;
35763573 // give an error but continue parsing this list.
......@@ -3579,11 +3576,12 @@ const Parser = struct {
35793576 },
35803577 }
35813578 } else unreachable;
3579 try p.scratch.append(p.gpa, param_one);
35823580
35833581 const param_two = while (true) {
35843582 switch (p.token_tags[p.nextToken()]) {
35853583 .comma => {},
3586 .r_paren => return SmallSpan{ .zero_or_one = param_one },
3584 .r_paren => return p.scratch.items[scratch_top..],
35873585 .colon, .r_brace, .r_bracket => {
35883586 p.tok_i -= 1;
35893587 return p.failExpected(.r_paren);
......@@ -3596,21 +3594,17 @@ const Parser = struct {
35963594 },
35973595 }
35983596 if (p.eatToken(.r_paren)) |_| {
3599 return SmallSpan{ .zero_or_one = param_one };
3597 return p.scratch.items[scratch_top..];
36003598 }
36013599 const param = try p.expectParamDecl();
36023600 if (param != 0) break param;
36033601 } else unreachable;
3604
3605 var list = std.ArrayList(Node.Index).init(p.gpa);
3606 defer list.deinit();
3607
3608 try list.appendSlice(&.{ param_one, param_two });
3602 try p.scratch.append(p.gpa, param_two);
36093603
36103604 while (true) {
36113605 switch (p.token_tags[p.nextToken()]) {
36123606 .comma => {},
3613 .r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },
3607 .r_paren => return p.scratch.items[scratch_top..],
36143608 .colon, .r_brace, .r_bracket => {
36153609 p.tok_i -= 1;
36163610 return p.failExpected(.r_paren);
......@@ -3623,10 +3617,10 @@ const Parser = struct {
36233617 },
36243618 }
36253619 if (p.eatToken(.r_paren)) |_| {
3626 return SmallSpan{ .multi = list.toOwnedSlice() };
3620 return p.scratch.items[scratch_top..];
36273621 }
36283622 const param = try p.expectParamDecl();
3629 if (param != 0) try list.append(param);
3623 if (param != 0) try p.scratch.append(p.gpa, param);
36303624 }
36313625 }
36323626
......@@ -3635,14 +3629,14 @@ const Parser = struct {
36353629 fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) {
36363630 return struct {
36373631 pub fn parse(p: *Parser) Error!Node.SubRange {
3638 var list = std.ArrayList(Node.Index).init(p.gpa);
3639 defer list.deinit();
3632 const scratch_top = p.scratch.items.len;
3633 defer p.scratch.shrinkRetainingCapacity(scratch_top);
36403634
36413635 while (true) {
36423636 const item = try nodeParseFn(p);
36433637 if (item == 0) break;
36443638
3645 try list.append(item);
3639 try p.scratch.append(p.gpa, item);
36463640
36473641 switch (p.token_tags[p.tok_i]) {
36483642 .comma => p.tok_i += 1,
......@@ -3655,7 +3649,7 @@ const Parser = struct {
36553649 },
36563650 }
36573651 }
3658 return p.listToSpan(list.items);
3652 return p.listToSpan(p.scratch.items[scratch_top..]);
36593653 }
36603654 }.parse;
36613655 }
......@@ -3746,18 +3740,18 @@ const Parser = struct {
37463740 },
37473741 }
37483742
3749 var list = std.ArrayList(Node.Index).init(p.gpa);
3750 defer list.deinit();
3743 const scratch_top = p.scratch.items.len;
3744 defer p.scratch.shrinkRetainingCapacity(scratch_top);
37513745
3752 try list.appendSlice(&.{ param_one, param_two });
3746 try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two });
37533747
37543748 while (true) {
37553749 const param = try p.expectExpr();
3756 try list.append(param);
3750 try p.scratch.append(p.gpa, param);
37573751 switch (p.token_tags[p.nextToken()]) {
37583752 .comma => {
37593753 if (p.eatToken(.r_paren)) |_| {
3760 const params = try p.listToSpan(list.items);
3754 const params = try p.listToSpan(p.scratch.items[scratch_top..]);
37613755 return p.addNode(.{
37623756 .tag = .builtin_call_comma,
37633757 .main_token = builtin_token,
......@@ -3770,7 +3764,7 @@ const Parser = struct {
37703764 continue;
37713765 },
37723766 .r_paren => {
3773 const params = try p.listToSpan(list.items);
3767 const params = try p.listToSpan(p.scratch.items[scratch_top..]);
37743768 return p.addNode(.{
37753769 .tag = .builtin_call,
37763770 .main_token = builtin_token,