authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-27 14:30:42-04:00
committergravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-27 14:30:42-04:00
log80c86ec9608478ade64964e7206487b6178853af
tree42ae3749dedb8486092146394cc41d927277e920
parent9ddd12ea14ba1aa3f6f97d87fd13a636812aa6ea

keep temporary list from escaping `parseParamDeclList`, make SmallSpan.multi hold Node.SubRange instead of owned memory


1 files changed, 25 insertions(+), 26 deletions(-)

lib/std/zig/parse.zig+25-26
...@@ -97,6 +97,11 @@ const Parser = struct {...@@ -97,6 +97,11 @@ const Parser = struct {
97 extra_data: std.ArrayListUnmanaged(Node.Index),97 extra_data: std.ArrayListUnmanaged(Node.Index),
98 scratch: std.ArrayListUnmanaged(Node.Index),98 scratch: std.ArrayListUnmanaged(Node.Index),
9999
100 const SmallSpan = union(enum) {
101 zero_or_one: Node.Index,
102 multi: Node.SubRange,
103 };
104
100 const Members = struct {105 const Members = struct {
101 len: usize,106 len: usize,
102 lhs: Node.Index,107 lhs: Node.Index,
...@@ -639,9 +644,6 @@ const Parser = struct {...@@ -639,9 +644,6 @@ const Parser = struct {
639 const fn_proto_index = try p.reserveNode();644 const fn_proto_index = try p.reserveNode();
640645
641 _ = p.eatToken(.identifier);646 _ = 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
645 const params = try p.parseParamDeclList();647 const params = try p.parseParamDeclList();
646 const align_expr = try p.parseByteAlign();648 const align_expr = try p.parseByteAlign();
647 const section_expr = try p.parseLinkSection();649 const section_expr = try p.parseLinkSection();
...@@ -656,17 +658,16 @@ const Parser = struct {...@@ -656,17 +658,16 @@ const Parser = struct {
656 }658 }
657659
658 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {660 if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
659 switch (params.len) {661 switch (params) {
660 0, 1 => return p.setNode(fn_proto_index, .{662 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
661 .tag = .fn_proto_simple,663 .tag = .fn_proto_simple,
662 .main_token = fn_token,664 .main_token = fn_token,
663 .data = .{665 .data = .{
664 .lhs = if (params.len > 0) params[0] else 0,666 .lhs = param,
665 .rhs = return_type_expr,667 .rhs = return_type_expr,
666 },668 },
667 }),669 }),
668 else => {670 .multi => |span| {
669 const span = try p.listToSpan(params);
670 return p.setNode(fn_proto_index, .{671 return p.setNode(fn_proto_index, .{
671 .tag = .fn_proto_multi,672 .tag = .fn_proto_multi,
672 .main_token = fn_token,673 .main_token = fn_token,
...@@ -681,13 +682,13 @@ const Parser = struct {...@@ -681,13 +682,13 @@ const Parser = struct {
681 },682 },
682 }683 }
683 }684 }
684 switch (params.len) {685 switch (params) {
685 0, 1 => return p.setNode(fn_proto_index, .{686 .zero_or_one => |param| return p.setNode(fn_proto_index, .{
686 .tag = .fn_proto_one,687 .tag = .fn_proto_one,
687 .main_token = fn_token,688 .main_token = fn_token,
688 .data = .{689 .data = .{
689 .lhs = try p.addExtra(Node.FnProtoOne{690 .lhs = try p.addExtra(Node.FnProtoOne{
690 .param = if (params.len > 0) params[0] else 0,691 .param = param,
691 .align_expr = align_expr,692 .align_expr = align_expr,
692 .section_expr = section_expr,693 .section_expr = section_expr,
693 .callconv_expr = callconv_expr,694 .callconv_expr = callconv_expr,
...@@ -695,8 +696,7 @@ const Parser = struct {...@@ -695,8 +696,7 @@ const Parser = struct {
695 .rhs = return_type_expr,696 .rhs = return_type_expr,
696 },697 },
697 }),698 }),
698 else => {699 .multi => |span| {
699 const span = try p.listToSpan(params);
700 return p.setNode(fn_proto_index, .{700 return p.setNode(fn_proto_index, .{
701 .tag = .fn_proto,701 .tag = .fn_proto,
702 .main_token = fn_token,702 .main_token = fn_token,
...@@ -3550,13 +3550,10 @@ const Parser = struct {...@@ -3550,13 +3550,10 @@ const Parser = struct {
3550 }3550 }
35513551
3552 /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?3552 /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
3553 fn parseParamDeclList(p: *Parser) ![]Node.Index {3553 fn parseParamDeclList(p: *Parser) !SmallSpan {
3554 const scratch_top = p.scratch.items.len;
3555 // don't defer p.scratch.shrinkRetainingCapacity because caller will do it
3556
3557 _ = try p.expectToken(.l_paren);3554 _ = try p.expectToken(.l_paren);
3558 if (p.eatToken(.r_paren)) |_| {3555 if (p.eatToken(.r_paren)) |_| {
3559 return p.scratch.items[scratch_top..];3556 return SmallSpan{ .zero_or_one = 0 };
3560 }3557 }
3561 const param_one = while (true) {3558 const param_one = while (true) {
3562 const param = try p.expectParamDecl();3559 const param = try p.expectParamDecl();
...@@ -3564,10 +3561,10 @@ const Parser = struct {...@@ -3564,10 +3561,10 @@ const Parser = struct {
3564 switch (p.token_tags[p.nextToken()]) {3561 switch (p.token_tags[p.nextToken()]) {
3565 .comma => {3562 .comma => {
3566 if (p.eatToken(.r_paren)) |_| {3563 if (p.eatToken(.r_paren)) |_| {
3567 return p.scratch.items[scratch_top..];3564 return SmallSpan{ .zero_or_one = 0 };
3568 }3565 }
3569 },3566 },
3570 .r_paren => return p.scratch.items[scratch_top..],3567 .r_paren => return SmallSpan{ .zero_or_one = 0 },
3571 else => {3568 else => {
3572 // This is likely just a missing comma;3569 // This is likely just a missing comma;
3573 // give an error but continue parsing this list.3570 // give an error but continue parsing this list.
...@@ -3576,12 +3573,11 @@ const Parser = struct {...@@ -3576,12 +3573,11 @@ const Parser = struct {
3576 },3573 },
3577 }3574 }
3578 } else unreachable;3575 } else unreachable;
3579 try p.scratch.append(p.gpa, param_one);
35803576
3581 const param_two = while (true) {3577 const param_two = while (true) {
3582 switch (p.token_tags[p.nextToken()]) {3578 switch (p.token_tags[p.nextToken()]) {
3583 .comma => {},3579 .comma => {},
3584 .r_paren => return p.scratch.items[scratch_top..],3580 .r_paren => return SmallSpan{ .zero_or_one = param_one },
3585 .colon, .r_brace, .r_bracket => {3581 .colon, .r_brace, .r_bracket => {
3586 p.tok_i -= 1;3582 p.tok_i -= 1;
3587 return p.failExpected(.r_paren);3583 return p.failExpected(.r_paren);
...@@ -3594,17 +3590,20 @@ const Parser = struct {...@@ -3594,17 +3590,20 @@ const Parser = struct {
3594 },3590 },
3595 }3591 }
3596 if (p.eatToken(.r_paren)) |_| {3592 if (p.eatToken(.r_paren)) |_| {
3597 return p.scratch.items[scratch_top..];3593 return SmallSpan{ .zero_or_one = param_one };
3598 }3594 }
3599 const param = try p.expectParamDecl();3595 const param = try p.expectParamDecl();
3600 if (param != 0) break param;3596 if (param != 0) break param;
3601 } else unreachable;3597 } else unreachable;
3602 try p.scratch.append(p.gpa, param_two);3598
3599 const scratch_top = p.scratch.items.len;
3600 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3601 try p.scratch.appendSlice(p.gpa, &.{ param_one, param_two });
36033602
3604 while (true) {3603 while (true) {
3605 switch (p.token_tags[p.nextToken()]) {3604 switch (p.token_tags[p.nextToken()]) {
3606 .comma => {},3605 .comma => {},
3607 .r_paren => return p.scratch.items[scratch_top..],3606 .r_paren => return SmallSpan{ .multi = try p.listToSpan(p.scratch.items[scratch_top..]) },
3608 .colon, .r_brace, .r_bracket => {3607 .colon, .r_brace, .r_bracket => {
3609 p.tok_i -= 1;3608 p.tok_i -= 1;
3610 return p.failExpected(.r_paren);3609 return p.failExpected(.r_paren);
...@@ -3617,7 +3616,7 @@ const Parser = struct {...@@ -3617,7 +3616,7 @@ const Parser = struct {
3617 },3616 },
3618 }3617 }
3619 if (p.eatToken(.r_paren)) |_| {3618 if (p.eatToken(.r_paren)) |_| {
3620 return p.scratch.items[scratch_top..];3619 return SmallSpan{ .multi = try p.listToSpan(p.scratch.items[scratch_top..]) };
3621 }3620 }
3622 const param = try p.expectParamDecl();3621 const param = try p.expectParamDecl();
3623 if (param != 0) try p.scratch.append(p.gpa, param);3622 if (param != 0) try p.scratch.append(p.gpa, param);