| ... | ... | @@ -170,7 +170,9 @@ pub const Parser = struct { |
| 170 | 170 | FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), |
| 171 | 171 | FieldListCommaOrEnd: &ast.NodeContainerDecl, |
| 172 | 172 | SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), |
| 173 | | Payload: &?&ast.NodePayload, |
| 173 | ErrorPayload: &?&ast.NodeErrorPayload, |
| 174 | ValuePayload: &?&ast.NodeValuePayload, |
| 175 | ValueIndexPayload: &?&ast.NodeValueIndexPayload, |
| 174 | 176 | SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), |
| 175 | 177 | SwitchCaseItem: &ArrayList(&ast.Node), |
| 176 | 178 | SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), |
| ... | ... | @@ -769,7 +771,7 @@ pub const Parser = struct { |
| 769 | 771 | |
| 770 | 772 | stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; |
| 771 | 773 | try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); |
| 772 | | try stack.append(State { .Payload = &node.op.Catch }); |
| 774 | try stack.append(State { .ErrorPayload = &node.op.Catch }); |
| 773 | 775 | continue; |
| 774 | 776 | }, |
| 775 | 777 | Token.Id.QuestionMarkQuestionMark => { |
| ... | ... | @@ -1471,7 +1473,15 @@ pub const Parser = struct { |
| 1471 | 1473 | continue; |
| 1472 | 1474 | }, |
| 1473 | 1475 | Token.Id.Keyword_for => { |
| 1474 | | @panic("TODO: inline for"); |
| 1476 | stack.append(State { |
| 1477 | .For = LoopCtx { |
| 1478 | .label = null, |
| 1479 | .inline_token = null, |
| 1480 | .loop_token = token, |
| 1481 | .dest_ptr = dest_ptr, |
| 1482 | } |
| 1483 | }) catch unreachable; |
| 1484 | continue; |
| 1475 | 1485 | }, |
| 1476 | 1486 | Token.Id.Keyword_switch => { |
| 1477 | 1487 | const node = try arena.create(ast.NodeSwitch); |
| ... | ... | @@ -1614,7 +1624,7 @@ pub const Parser = struct { |
| 1614 | 1624 | try list_state.list.append(node); |
| 1615 | 1625 | stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; |
| 1616 | 1626 | try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); |
| 1617 | | try stack.append(State { .Payload = &node.payload }); |
| 1627 | try stack.append(State { .ValuePayload = &node.payload }); |
| 1618 | 1628 | |
| 1619 | 1629 | const maybe_else = self.getNextToken(); |
| 1620 | 1630 | if (maybe_else.id == Token.Id.Keyword_else) { |
| ... | ... | @@ -1681,7 +1691,7 @@ pub const Parser = struct { |
| 1681 | 1691 | *dest = node; |
| 1682 | 1692 | |
| 1683 | 1693 | stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable; |
| 1684 | | try stack.append(State { .Payload = &node.payload }); |
| 1694 | try stack.append(State { .ErrorPayload = &node.payload }); |
| 1685 | 1695 | }, |
| 1686 | 1696 | |
| 1687 | 1697 | State.WhileContinueExpr => |dest| { |
| ... | ... | @@ -1696,7 +1706,26 @@ pub const Parser = struct { |
| 1696 | 1706 | try stack.append(State { .Expression = DestPtr { .NullableField = dest } }); |
| 1697 | 1707 | }, |
| 1698 | 1708 | |
| 1699 | | State.Payload => |dest| { |
| 1709 | State.ErrorPayload => |dest| { |
| 1710 | const lpipe = self.getNextToken(); |
| 1711 | if (lpipe.id != Token.Id.Pipe) { |
| 1712 | self.putBackToken(lpipe); |
| 1713 | continue; |
| 1714 | } |
| 1715 | |
| 1716 | const error_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1717 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1718 | const node = try arena.create(ast.NodeErrorPayload); |
| 1719 | *node = ast.NodeErrorPayload { |
| 1720 | .base = self.initNode(ast.Node.Id.ErrorPayload), |
| 1721 | .lpipe = lpipe, |
| 1722 | .error_symbol = try self.createIdentifier(arena, error_symbol), |
| 1723 | .rpipe = rpipe |
| 1724 | }; |
| 1725 | *dest = node; |
| 1726 | }, |
| 1727 | |
| 1728 | State.ValuePayload => |dest| { |
| 1700 | 1729 | const lpipe = self.getNextToken(); |
| 1701 | 1730 | if (lpipe.id != Token.Id.Pipe) { |
| 1702 | 1731 | self.putBackToken(lpipe); |
| ... | ... | @@ -1713,14 +1742,56 @@ pub const Parser = struct { |
| 1713 | 1742 | } |
| 1714 | 1743 | }; |
| 1715 | 1744 | |
| 1716 | | const ident = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1745 | const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1717 | 1746 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1718 | | const node = try arena.create(ast.NodePayload); |
| 1719 | | *node = ast.NodePayload { |
| 1720 | | .base = self.initNode(ast.Node.Id.Payload), |
| 1747 | const node = try arena.create(ast.NodeValuePayload); |
| 1748 | *node = ast.NodeValuePayload { |
| 1749 | .base = self.initNode(ast.Node.Id.ValuePayload), |
| 1721 | 1750 | .lpipe = lpipe, |
| 1722 | 1751 | .is_ptr = is_ptr, |
| 1723 | | .symbol = try self.createIdentifier(arena, ident), |
| 1752 | .value_symbol = try self.createIdentifier(arena, value_symbol), |
| 1753 | .rpipe = rpipe |
| 1754 | }; |
| 1755 | *dest = node; |
| 1756 | }, |
| 1757 | |
| 1758 | State.ValueIndexPayload => |dest| { |
| 1759 | const lpipe = self.getNextToken(); |
| 1760 | if (lpipe.id != Token.Id.Pipe) { |
| 1761 | self.putBackToken(lpipe); |
| 1762 | continue; |
| 1763 | } |
| 1764 | |
| 1765 | const is_ptr = blk: { |
| 1766 | const asterik = self.getNextToken(); |
| 1767 | if (asterik.id == Token.Id.Asterisk) { |
| 1768 | break :blk true; |
| 1769 | } else { |
| 1770 | self.putBackToken(asterik); |
| 1771 | break :blk false; |
| 1772 | } |
| 1773 | }; |
| 1774 | |
| 1775 | const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1776 | const index_symbol = blk: { |
| 1777 | const comma = self.getNextToken(); |
| 1778 | if (comma.id != Token.Id.Comma) { |
| 1779 | self.putBackToken(comma); |
| 1780 | break :blk null; |
| 1781 | } |
| 1782 | |
| 1783 | const symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; |
| 1784 | break :blk try self.createIdentifier(arena, symbol); |
| 1785 | }; |
| 1786 | |
| 1787 | const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; |
| 1788 | const node = try arena.create(ast.NodeValueIndexPayload); |
| 1789 | *node = ast.NodeValueIndexPayload { |
| 1790 | .base = self.initNode(ast.Node.Id.ValueIndexPayload), |
| 1791 | .lpipe = lpipe, |
| 1792 | .is_ptr = is_ptr, |
| 1793 | .value_symbol = try self.createIdentifier(arena, value_symbol), |
| 1794 | .index_symbol = index_symbol, |
| 1724 | 1795 | .rpipe = rpipe |
| 1725 | 1796 | }; |
| 1726 | 1797 | *dest = node; |
| ... | ... | @@ -1986,13 +2057,32 @@ pub const Parser = struct { |
| 1986 | 2057 | stack.append(State { .Else = &node.@"else" }) catch unreachable; |
| 1987 | 2058 | try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); |
| 1988 | 2059 | try stack.append(State { .WhileContinueExpr = &node.continue_expr }); |
| 1989 | | try stack.append(State { .Payload = &node.payload }); |
| 2060 | try stack.append(State { .ValuePayload = &node.payload }); |
| 1990 | 2061 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 1991 | 2062 | try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); |
| 1992 | 2063 | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 1993 | 2064 | }, |
| 1994 | 2065 | |
| 1995 | 2066 | State.For => |ctx| { |
| 2067 | const node = try arena.create(ast.NodeFor); |
| 2068 | *node = ast.NodeFor { |
| 2069 | .base = self.initNode(ast.Node.Id.For), |
| 2070 | .label = ctx.label, |
| 2071 | .inline_token = ctx.inline_token, |
| 2072 | .for_token = ctx.loop_token, |
| 2073 | .array_expr = undefined, |
| 2074 | .payload = null, |
| 2075 | .body = undefined, |
| 2076 | .@"else" = null, |
| 2077 | }; |
| 2078 | ctx.dest_ptr.store(&node.base); |
| 2079 | |
| 2080 | stack.append(State { .Else = &node.@"else" }) catch unreachable; |
| 2081 | try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); |
| 2082 | try stack.append(State { .ValueIndexPayload = &node.payload }); |
| 2083 | try stack.append(State { .ExpectToken = Token.Id.RParen }); |
| 2084 | try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } }); |
| 2085 | try stack.append(State { .ExpectToken = Token.Id.LParen }); |
| 1996 | 2086 | }, |
| 1997 | 2087 | |
| 1998 | 2088 | State.Block => |block| { |
| ... | ... | @@ -2071,7 +2161,9 @@ pub const Parser = struct { |
| 2071 | 2161 | ast.Node.Id.EnumTag, |
| 2072 | 2162 | ast.Node.Id.ParamDecl, |
| 2073 | 2163 | ast.Node.Id.Block, |
| 2074 | | ast.Node.Id.Payload, |
| 2164 | ast.Node.Id.ErrorPayload, |
| 2165 | ast.Node.Id.ValuePayload, |
| 2166 | ast.Node.Id.ValueIndexPayload, |
| 2075 | 2167 | ast.Node.Id.Switch, |
| 2076 | 2168 | ast.Node.Id.SwitchCase, |
| 2077 | 2169 | ast.Node.Id.SwitchElse, |
| ... | ... | @@ -2087,6 +2179,15 @@ pub const Parser = struct { |
| 2087 | 2179 | |
| 2088 | 2180 | n = while_node.body; |
| 2089 | 2181 | }, |
| 2182 | ast.Node.Id.For => { |
| 2183 | const for_node = @fieldParentPtr(ast.NodeFor, "base", n); |
| 2184 | if (for_node.@"else") |@"else"| { |
| 2185 | n = @"else".base; |
| 2186 | continue; |
| 2187 | } |
| 2188 | |
| 2189 | n = for_node.body; |
| 2190 | }, |
| 2090 | 2191 | ast.Node.Id.Else => { |
| 2091 | 2192 | const else_node = @fieldParentPtr(ast.NodeElse, "base", n); |
| 2092 | 2193 | n = else_node.body; |
| ... | ... | @@ -2982,10 +3083,33 @@ pub const Parser = struct { |
| 2982 | 3083 | try stack.append(RenderState { .Expression = rhs }); |
| 2983 | 3084 | } |
| 2984 | 3085 | }, |
| 2985 | | ast.Node.Id.Payload => { |
| 2986 | | const payload = @fieldParentPtr(ast.NodePayload, "base", base); |
| 3086 | ast.Node.Id.ErrorPayload => { |
| 3087 | const payload = @fieldParentPtr(ast.NodeErrorPayload, "base", base); |
| 3088 | try stack.append(RenderState { .Text = "|"}); |
| 3089 | try stack.append(RenderState { .Expression = &payload.error_symbol.base }); |
| 3090 | try stack.append(RenderState { .Text = "|"}); |
| 3091 | }, |
| 3092 | ast.Node.Id.ValuePayload => { |
| 3093 | const payload = @fieldParentPtr(ast.NodeValuePayload, "base", base); |
| 3094 | try stack.append(RenderState { .Text = "|"}); |
| 3095 | try stack.append(RenderState { .Expression = &payload.value_symbol.base }); |
| 3096 | |
| 3097 | if (payload.is_ptr) { |
| 3098 | try stack.append(RenderState { .Text = "*"}); |
| 3099 | } |
| 3100 | |
| 3101 | try stack.append(RenderState { .Text = "|"}); |
| 3102 | }, |
| 3103 | ast.Node.Id.ValueIndexPayload => { |
| 3104 | const payload = @fieldParentPtr(ast.NodeValueIndexPayload, "base", base); |
| 2987 | 3105 | try stack.append(RenderState { .Text = "|"}); |
| 2988 | | try stack.append(RenderState { .Expression = &payload.symbol.base }); |
| 3106 | |
| 3107 | if (payload.index_symbol) |index_symbol| { |
| 3108 | try stack.append(RenderState { .Expression = &index_symbol.base }); |
| 3109 | try stack.append(RenderState { .Text = ", "}); |
| 3110 | } |
| 3111 | |
| 3112 | try stack.append(RenderState { .Expression = &payload.value_symbol.base }); |
| 2989 | 3113 | |
| 2990 | 3114 | if (payload.is_ptr) { |
| 2991 | 3115 | try stack.append(RenderState { .Text = "*"}); |
| ... | ... | @@ -3303,6 +3427,48 @@ pub const Parser = struct { |
| 3303 | 3427 | try stack.append(RenderState { .Expression = while_node.condition }); |
| 3304 | 3428 | try stack.append(RenderState { .Text = "(" }); |
| 3305 | 3429 | }, |
| 3430 | ast.Node.Id.For => { |
| 3431 | const for_node = @fieldParentPtr(ast.NodeFor, "base", base); |
| 3432 | if (for_node.label) |label| { |
| 3433 | try stream.print("{}: ", self.tokenizer.getTokenSlice(label)); |
| 3434 | } |
| 3435 | |
| 3436 | if (for_node.inline_token) |inline_token| { |
| 3437 | try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token)); |
| 3438 | } |
| 3439 | |
| 3440 | try stream.print("{} ", self.tokenizer.getTokenSlice(for_node.for_token)); |
| 3441 | |
| 3442 | if (for_node.@"else") |@"else"| { |
| 3443 | try stack.append(RenderState { .Expression = &@"else".base }); |
| 3444 | |
| 3445 | if (for_node.body.id == ast.Node.Id.Block) { |
| 3446 | try stack.append(RenderState { .Text = " " }); |
| 3447 | } else { |
| 3448 | try stack.append(RenderState { .Text = "\n" }); |
| 3449 | } |
| 3450 | } |
| 3451 | |
| 3452 | if (for_node.body.id == ast.Node.Id.Block) { |
| 3453 | try stack.append(RenderState { .Expression = for_node.body }); |
| 3454 | try stack.append(RenderState { .Text = " " }); |
| 3455 | } else { |
| 3456 | try stack.append(RenderState { .Indent = indent }); |
| 3457 | try stack.append(RenderState { .Expression = for_node.body }); |
| 3458 | try stack.append(RenderState.PrintIndent); |
| 3459 | try stack.append(RenderState { .Indent = indent + indent_delta }); |
| 3460 | try stack.append(RenderState { .Text = "\n" }); |
| 3461 | } |
| 3462 | |
| 3463 | if (for_node.payload) |payload| { |
| 3464 | try stack.append(RenderState { .Expression = &payload.base }); |
| 3465 | try stack.append(RenderState { .Text = " " }); |
| 3466 | } |
| 3467 | |
| 3468 | try stack.append(RenderState { .Text = ")" }); |
| 3469 | try stack.append(RenderState { .Expression = for_node.array_expr }); |
| 3470 | try stack.append(RenderState { .Text = "(" }); |
| 3471 | }, |
| 3306 | 3472 | |
| 3307 | 3473 | ast.Node.Id.StructField, |
| 3308 | 3474 | ast.Node.Id.UnionTag, |
| ... | ... | @@ -4022,10 +4188,10 @@ test "zig fmt: for" { |
| 4022 | 4188 | \\ continue; |
| 4023 | 4189 | \\ |
| 4024 | 4190 | \\ const res = for (a) |v, i| { |
| 4025 | | \\ breal v; |
| 4191 | \\ break v; |
| 4026 | 4192 | \\ } else { |
| 4027 | 4193 | \\ unreachable; |
| 4028 | | \\ } |
| 4194 | \\ }; |
| 4029 | 4195 | \\ |
| 4030 | 4196 | \\ var num: usize = 0; |
| 4031 | 4197 | \\ inline for (a) |v, i| { |