| ... | @@ -104,6 +104,11 @@ pub const Parser = struct { | ... | @@ -104,6 +104,11 @@ pub const Parser = struct { |
| 104 | ptr: &Token, | 104 | ptr: &Token, |
| 105 | }; | 105 | }; |
| 106 | | 106 | |
| | 107 | const ElseCtx = struct { |
| | 108 | payload: ?DestPtr, |
| | 109 | body: DestPtr, |
| | 110 | }; |
| | 111 | |
| 107 | fn ListSave(comptime T: type) type { | 112 | fn ListSave(comptime T: type) type { |
| 108 | return struct { | 113 | return struct { |
| 109 | list: &ArrayList(T), | 114 | list: &ArrayList(T), |
| ... | @@ -140,7 +145,7 @@ pub const Parser = struct { | ... | @@ -140,7 +145,7 @@ pub const Parser = struct { |
| 140 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), | 145 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), |
| 141 | FieldListCommaOrEnd: &ast.NodeContainerDecl, | 146 | FieldListCommaOrEnd: &ast.NodeContainerDecl, |
| 142 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), | 147 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), |
| 143 | SwitchCaseCapture: &?ast.NodeSwitchCase.Capture, | 148 | Payload: DestPtr, |
| 144 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), | 149 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), |
| 145 | SwitchCaseItem: &ArrayList(&ast.Node), | 150 | SwitchCaseItem: &ArrayList(&ast.Node), |
| 146 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), | 151 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), |
| ... | @@ -635,9 +640,6 @@ pub const Parser = struct { | ... | @@ -635,9 +640,6 @@ pub const Parser = struct { |
| 635 | Token.Id.Keyword_await => { | 640 | Token.Id.Keyword_await => { |
| 636 | @panic("TODO: await"); | 641 | @panic("TODO: await"); |
| 637 | }, | 642 | }, |
| 638 | Token.Id.Keyword_suspend => { | | |
| 639 | @panic("TODO: suspend"); | | |
| 640 | }, | | |
| 641 | else => { | 643 | else => { |
| 642 | self.putBackToken(token); | 644 | self.putBackToken(token); |
| 643 | stack.append(State { .AssignmentExpressionBegin = dest_ptr }) catch unreachable; | 645 | stack.append(State { .AssignmentExpressionBegin = dest_ptr }) catch unreachable; |
| ... | @@ -705,21 +707,14 @@ pub const Parser = struct { | ... | @@ -705,21 +707,14 @@ pub const Parser = struct { |
| 705 | | 707 | |
| 706 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; | 708 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; |
| 707 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); | 709 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); |
| 708 | | | |
| 709 | const next = self.getNextToken(); | | |
| 710 | if (next.id != Token.Id.Pipe) { | | |
| 711 | self.putBackToken(next); | | |
| 712 | continue; | | |
| 713 | } | | |
| 714 | | | |
| 715 | node.op.Catch = try self.createIdentifier(arena, Token(undefined)); | | |
| 716 | try stack.append(State { .ExpectToken = Token.Id.Pipe }); | | |
| 717 | try stack.append(State { | 710 | try stack.append(State { |
| 718 | .ExpectTokenSave = ExpectTokenSave { | 711 | .Optional = RevertState { |
| 719 | .id = Token.Id.Identifier, | 712 | .tokenizer = *self.tokenizer, |
| 720 | .ptr = &(??node.op.Catch).name_token | 713 | .parser = *self, |
| | 714 | .ptr = &node.op.Catch, |
| 721 | } | 715 | } |
| 722 | }); | 716 | }); |
| | 717 | try stack.append(State { .Payload = DestPtr { .NullableField = &node.op.Catch } }); |
| 723 | continue; | 718 | continue; |
| 724 | }, | 719 | }, |
| 725 | Token.Id.QuestionMarkQuestionMark => { | 720 | Token.Id.QuestionMarkQuestionMark => { |
| ... | @@ -1404,12 +1399,25 @@ pub const Parser = struct { | ... | @@ -1404,12 +1399,25 @@ pub const Parser = struct { |
| 1404 | @panic("TODO: inline if"); | 1399 | @panic("TODO: inline if"); |
| 1405 | }, | 1400 | }, |
| 1406 | Token.Id.Keyword_while => { | 1401 | Token.Id.Keyword_while => { |
| | 1402 | const node = try arena.create(ast.NodeWhile); |
| | 1403 | *node = ast.NodeWhile { |
| | 1404 | .base = self.initNode(ast.Node.Id.While), |
| | 1405 | .while_token = token, |
| | 1406 | .condition = undefined, |
| | 1407 | .payload = null, |
| | 1408 | .continue_expr = null, |
| | 1409 | .body = undefined, |
| | 1410 | .@"else" = null, |
| | 1411 | }; |
| | 1412 | dest_ptr.store(&node.base); |
| | 1413 | |
| 1407 | @panic("TODO: inline while"); | 1414 | @panic("TODO: inline while"); |
| 1408 | }, | 1415 | }, |
| 1409 | Token.Id.Keyword_for => { | 1416 | Token.Id.Keyword_for => { |
| 1410 | @panic("TODO: inline for"); | 1417 | @panic("TODO: inline for"); |
| 1411 | }, | 1418 | }, |
| 1412 | Token.Id.Keyword_switch => { | 1419 | Token.Id.Keyword_switch => { |
| | 1420 | @breakpoint(); |
| 1413 | const node = try arena.create(ast.NodeSwitch); | 1421 | const node = try arena.create(ast.NodeSwitch); |
| 1414 | *node = ast.NodeSwitch { | 1422 | *node = ast.NodeSwitch { |
| 1415 | .base = self.initNode(ast.Node.Id.Switch), | 1423 | .base = self.initNode(ast.Node.Id.Switch), |
| ... | @@ -1434,9 +1442,6 @@ pub const Parser = struct { | ... | @@ -1434,9 +1442,6 @@ pub const Parser = struct { |
| 1434 | Token.Id.Keyword_comptime => { | 1442 | Token.Id.Keyword_comptime => { |
| 1435 | @panic("TODO: inline comptime"); | 1443 | @panic("TODO: inline comptime"); |
| 1436 | }, | 1444 | }, |
| 1437 | Token.Id.Keyword_suspend => { | | |
| 1438 | @panic("TODO: inline suspend"); | | |
| 1439 | }, | | |
| 1440 | else => { | 1445 | else => { |
| 1441 | try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id)); | 1446 | try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id)); |
| 1442 | continue; | 1447 | continue; |
| ... | @@ -1547,13 +1552,21 @@ pub const Parser = struct { | ... | @@ -1547,13 +1552,21 @@ pub const Parser = struct { |
| 1547 | *node = ast.NodeSwitchCase { | 1552 | *node = ast.NodeSwitchCase { |
| 1548 | .base = self.initNode(ast.Node.Id.SwitchCase), | 1553 | .base = self.initNode(ast.Node.Id.SwitchCase), |
| 1549 | .items = ArrayList(&ast.Node).init(arena), | 1554 | .items = ArrayList(&ast.Node).init(arena), |
| 1550 | .capture = null, | 1555 | .payload = null, |
| 1551 | .expr = undefined, | 1556 | .expr = undefined, |
| 1552 | }; | 1557 | }; |
| 1553 | try list_state.list.append(node); | 1558 | try list_state.list.append(node); |
| 1554 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; | 1559 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; |
| 1555 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); | 1560 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); |
| 1556 | try stack.append(State { .SwitchCaseCapture = &node.capture }); | 1561 | try stack.append(State { |
| | 1562 | .Optional = RevertState { |
| | 1563 | .tokenizer = *self.tokenizer, |
| | 1564 | .parser = *self, |
| | 1565 | .ptr = &node.payload, |
| | 1566 | } |
| | 1567 | }); |
| | 1568 | try stack.append(State { .Payload = DestPtr { .NullableField = &node.payload } }); |
| | 1569 | try stack.append(State.Required); |
| 1557 | | 1570 | |
| 1558 | const maybe_else = self.getNextToken(); | 1571 | const maybe_else = self.getNextToken(); |
| 1559 | if (maybe_else.id == Token.Id.Keyword_else) { | 1572 | if (maybe_else.id == Token.Id.Keyword_else) { |
| ... | @@ -1572,12 +1585,8 @@ pub const Parser = struct { | ... | @@ -1572,12 +1585,8 @@ pub const Parser = struct { |
| 1572 | } | 1585 | } |
| 1573 | }, | 1586 | }, |
| 1574 | | 1587 | |
| 1575 | State.SwitchCaseCapture => |capture| { | 1588 | State.Payload => |dest_ptr| { |
| 1576 | const token = self.getNextToken(); | 1589 | const lpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1577 | if (token.id != Token.Id.Pipe) { | | |
| 1578 | self.putBackToken(token); | | |
| 1579 | continue; | | |
| 1580 | } | | |
| 1581 | | 1590 | |
| 1582 | const is_ptr = blk: { | 1591 | const is_ptr = blk: { |
| 1583 | const asterik = self.getNextToken(); | 1592 | const asterik = self.getNextToken(); |
| ... | @@ -1590,11 +1599,16 @@ pub const Parser = struct { | ... | @@ -1590,11 +1599,16 @@ pub const Parser = struct { |
| 1590 | }; | 1599 | }; |
| 1591 | | 1600 | |
| 1592 | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; | 1601 | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1593 | _ = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; | 1602 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1594 | *capture = ast.NodeSwitchCase.Capture { | 1603 | const node = try arena.create(ast.NodePayload); |
| | 1604 | *node = ast.NodePayload { |
| | 1605 | .base = self.initNode(ast.Node.Id.Payload), |
| | 1606 | .lpipe = lpipe, |
| | 1607 | .is_ptr = is_ptr, |
| 1595 | .symbol = try self.createIdentifier(arena, ident), | 1608 | .symbol = try self.createIdentifier(arena, ident), |
| 1596 | .is_ptr = is_ptr | 1609 | .rpipe = rpipe |
| 1597 | }; | 1610 | }; |
| | 1611 | dest_ptr.store(&node.base); |
| 1598 | }, | 1612 | }, |
| 1599 | | 1613 | |
| 1600 | State.SwitchCaseItem => |case_items| { | 1614 | State.SwitchCaseItem => |case_items| { |
| ... | @@ -1856,6 +1870,8 @@ pub const Parser = struct { | ... | @@ -1856,6 +1870,8 @@ pub const Parser = struct { |
| 1856 | stack.append(State { .Block = inner_block }) catch unreachable; | 1870 | stack.append(State { .Block = inner_block }) catch unreachable; |
| 1857 | continue; | 1871 | continue; |
| 1858 | }, | 1872 | }, |
| | 1873 | Token.Id.Keyword_suspend, Token.Id.Keyword_if, |
| | 1874 | Token.Id.Keyword_while, Token.Id.Keyword_for, |
| 1859 | Token.Id.Keyword_switch => { | 1875 | Token.Id.Keyword_switch => { |
| 1860 | self.putBackToken(next); | 1876 | self.putBackToken(next); |
| 1861 | stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable; | 1877 | stack.append(State { .Expression = DestPtr{.Field = try block.statements.addOne() } }) catch unreachable; |
| ... | @@ -2572,9 +2588,8 @@ pub const Parser = struct { | ... | @@ -2572,9 +2588,8 @@ pub const Parser = struct { |
| 2572 | | 2588 | |
| 2573 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { | 2589 | if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { |
| 2574 | if (prefix_op_node.op.Catch) |payload| { | 2590 | if (prefix_op_node.op.Catch) |payload| { |
| 2575 | try stack.append(RenderState { .Text = "| " }); | 2591 | try stack.append(RenderState { .Text = " " }); |
| 2576 | try stack.append(RenderState { .Expression = &payload.base }); | 2592 | try stack.append(RenderState { .Expression = payload }); |
| 2577 | try stack.append(RenderState { .Text = "|" }); | | |
| 2578 | } | 2593 | } |
| 2579 | try stack.append(RenderState { .Text = " catch " }); | 2594 | try stack.append(RenderState { .Text = " catch " }); |
| 2580 | } else { | 2595 | } else { |
| ... | @@ -2764,6 +2779,17 @@ pub const Parser = struct { | ... | @@ -2764,6 +2779,17 @@ pub const Parser = struct { |
| 2764 | try stack.append(RenderState { .Expression = rhs }); | 2779 | try stack.append(RenderState { .Expression = rhs }); |
| 2765 | } | 2780 | } |
| 2766 | }, | 2781 | }, |
| | 2782 | ast.Node.Id.Payload => { |
| | 2783 | const payload = @fieldParentPtr(ast.NodePayload, "base", base); |
| | 2784 | try stack.append(RenderState { .Text = "|"}); |
| | 2785 | try stack.append(RenderState { .Expression = &payload.symbol.base }); |
| | 2786 | |
| | 2787 | if (payload.is_ptr) { |
| | 2788 | try stack.append(RenderState { .Text = "*"}); |
| | 2789 | } |
| | 2790 | |
| | 2791 | try stack.append(RenderState { .Text = "|"}); |
| | 2792 | }, |
| 2767 | ast.Node.Id.GroupedExpression => { | 2793 | ast.Node.Id.GroupedExpression => { |
| 2768 | const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base); | 2794 | const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base); |
| 2769 | try stack.append(RenderState { .Text = ")"}); | 2795 | try stack.append(RenderState { .Text = ")"}); |
| ... | @@ -2985,14 +3011,9 @@ pub const Parser = struct { | ... | @@ -2985,14 +3011,9 @@ pub const Parser = struct { |
| 2985 | const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base); | 3011 | const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base); |
| 2986 | | 3012 | |
| 2987 | try stack.append(RenderState { .Expression = switch_case.expr }); | 3013 | try stack.append(RenderState { .Expression = switch_case.expr }); |
| 2988 | if (switch_case.capture) |capture| { | 3014 | if (switch_case.payload) |payload| { |
| 2989 | try stack.append(RenderState { .Text = "| "}); | 3015 | try stack.append(RenderState { .Text = " " }); |
| 2990 | try stack.append(RenderState { .Expression = &capture.symbol.base }); | 3016 | try stack.append(RenderState { .Expression = payload }); |
| 2991 | | | |
| 2992 | if (capture.is_ptr) { | | |
| 2993 | try stack.append(RenderState { .Text = "*"}); | | |
| 2994 | } | | |
| 2995 | try stack.append(RenderState { .Text = "|"}); | | |
| 2996 | } | 3017 | } |
| 2997 | try stack.append(RenderState { .Text = " => "}); | 3018 | try stack.append(RenderState { .Text = " => "}); |
| 2998 | | 3019 | |
| ... | @@ -3011,6 +3032,7 @@ pub const Parser = struct { | ... | @@ -3011,6 +3032,7 @@ pub const Parser = struct { |
| 3011 | const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); | 3032 | const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); |
| 3012 | try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); | 3033 | try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); |
| 3013 | }, | 3034 | }, |
| | 3035 | ast.Node.Id.While => @panic("TODO: Render while"), |
| 3014 | | 3036 | |
| 3015 | ast.Node.Id.StructField, | 3037 | ast.Node.Id.StructField, |
| 3016 | ast.Node.Id.UnionTag, | 3038 | ast.Node.Id.UnionTag, |