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 {...@@ -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);
5153
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),
9698 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 };
10899
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 BlockExpr196 /// 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);
209200
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 }
395386
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();
648640
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 }
663657
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 }
18961890
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);
18991893
1900 try statements.appendSlice(&.{ stmt_one, stmt_two });1894 try p.scratch.appendSlice(p.gpa, &.{ stmt_one, stmt_two });
19011895
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 }
20432037
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);
20462040
2047 try init_list.append(field_init);2041 try p.scratch.append(p.gpa, field_init);
20482042
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);
20522046
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 }
21002094
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);
21032097
2104 try init_list.append(elem_init);2098 try p.scratch.append(p.gpa, elem_init);
21052099
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 }
21902184
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);
21932187
2194 try param_list.append(param_one);2188 try p.scratch.append(p.gpa, param_one);
21952189
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 }
22792273
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);
22822276
2283 try param_list.append(param_one);2277 try p.scratch.append(p.gpa, param_one);
22842278
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);
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
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);
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
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 {
29242918
2925 _ = try p.expectToken(.colon);2919 _ = try p.expectToken(.colon);
29262920
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);
29292923
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 }
31943188
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);
31973191
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 }
35573551
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);
35823580
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;
36043602 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 });
36093603
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 }
36323626
...@@ -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);
36403634
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;
36443638
3645 try list.append(item);3639 try p.scratch.append(p.gpa, item);
36463640
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 }
37483742
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);
37513745
3752 try list.appendSlice(&.{ param_one, param_two });3746 try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two });
37533747
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,