| ... | ... | @@ -131,11 +131,23 @@ const Parser = struct { |
| 131 | 131 | return @intCast(Node.Index, i); |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | | fn reserveNode(p: *Parser) !usize { |
| 134 | fn reserveNode(p: *Parser, tag: Ast.Node.Tag) !usize { |
| 135 | 135 | try p.nodes.resize(p.gpa, p.nodes.len + 1); |
| 136 | p.nodes.items(.tag)[p.nodes.len - 1] = tag; |
| 136 | 137 | return p.nodes.len - 1; |
| 137 | 138 | } |
| 138 | 139 | |
| 140 | fn unreserveNode(p: *Parser, node_index: usize) void { |
| 141 | if (p.nodes.len == node_index) { |
| 142 | p.nodes.resize(p.gpa, p.nodes.len - 1) catch unreachable; |
| 143 | } else { |
| 144 | // There is zombie node left in the tree, let's make it as inoffensive as possible |
| 145 | // (sadly there's no no-op node) |
| 146 | p.nodes.items(.tag)[node_index] = .unreachable_literal; |
| 147 | p.nodes.items(.main_token)[node_index] = p.tok_i; |
| 148 | } |
| 149 | } |
| 150 | |
| 139 | 151 | fn addExtra(p: *Parser, extra: anytype) Allocator.Error!Node.Index { |
| 140 | 152 | const fields = std.meta.fields(@TypeOf(extra)); |
| 141 | 153 | try p.extra_data.ensureUnusedCapacity(p.gpa, fields.len); |
| ... | ... | @@ -637,13 +649,15 @@ const Parser = struct { |
| 637 | 649 | return fn_proto; |
| 638 | 650 | }, |
| 639 | 651 | .l_brace => { |
| 640 | | const fn_decl_index = try p.reserveNode(); |
| 641 | | const body_block = try p.parseBlock(); |
| 642 | | assert(body_block != 0); |
| 643 | 652 | if (is_extern) { |
| 644 | 653 | try p.warnMsg(.{ .tag = .extern_fn_body, .token = extern_export_inline_token }); |
| 645 | 654 | return null_node; |
| 646 | 655 | } |
| 656 | const fn_decl_index = try p.reserveNode(.fn_decl); |
| 657 | errdefer p.unreserveNode(fn_decl_index); |
| 658 | |
| 659 | const body_block = try p.parseBlock(); |
| 660 | assert(body_block != 0); |
| 647 | 661 | return p.setNode(fn_decl_index, .{ |
| 648 | 662 | .tag = .fn_decl, |
| 649 | 663 | .main_token = p.nodes.items(.main_token)[fn_proto], |
| ... | ... | @@ -724,7 +738,8 @@ const Parser = struct { |
| 724 | 738 | const fn_token = p.eatToken(.keyword_fn) orelse return null_node; |
| 725 | 739 | |
| 726 | 740 | // We want the fn proto node to be before its children in the array. |
| 727 | | const fn_proto_index = try p.reserveNode(); |
| 741 | const fn_proto_index = try p.reserveNode(.fn_proto); |
| 742 | errdefer p.unreserveNode(fn_proto_index); |
| 728 | 743 | |
| 729 | 744 | _ = p.eatToken(.identifier); |
| 730 | 745 | const params = try p.parseParamDeclList(); |