| ... | @@ -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), |
| 99 | | 99 | |
| | 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(); |
| 640 | | 645 | |
| 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 | } |
| 657 | | 659 | |
| 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 | } |
| 3551 | | 3551 | |
| 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); | | |
| 3580 | | 3576 | |
| 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 }); |
| 3603 | | 3602 | |
| 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); |