authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-09 17:23:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-09 17:23:57-07:00
log1c79eea125c7e21b00a7abeffdc3b64548c54257
treec3f0a52febf7623b44dfe7a3d780860169aa163c
parentbcafc51e58fcd6a4b12e43a780c0e9eef43a8d28

zig fmt: while loops


4 files changed, 266 insertions(+), 177 deletions(-)

lib/std/zig/ast.zig+119-13
...@@ -760,6 +760,13 @@ pub const Tree = struct {...@@ -760,6 +760,13 @@ pub const Tree = struct {
760 n = extra.sentinel;760 n = extra.sentinel;
761 },761 },
762762
763 .Continue => {
764 if (datas[n].lhs != 0) {
765 return datas[n].lhs + end_offset;
766 } else {
767 return main_tokens[n] + end_offset;
768 }
769 },
763 .Break => {770 .Break => {
764 if (datas[n].rhs != 0) {771 if (datas[n].rhs != 0) {
765 n = datas[n].rhs;772 n = datas[n].rhs;
...@@ -837,6 +844,21 @@ pub const Tree = struct {...@@ -837,6 +844,21 @@ pub const Tree = struct {
837 n = max_node;844 n = max_node;
838 end_offset += max_offset;845 end_offset += max_offset;
839 },846 },
847 .WhileCont => {
848 const extra = tree.extraData(datas[n].rhs, Node.WhileCont);
849 assert(extra.then_expr != 0);
850 n = extra.then_expr;
851 },
852 .While => {
853 const extra = tree.extraData(datas[n].rhs, Node.While);
854 assert(extra.else_expr != 0);
855 n = extra.else_expr;
856 },
857 .If => {
858 const extra = tree.extraData(datas[n].rhs, Node.If);
859 assert(extra.else_expr != 0);
860 n = extra.else_expr;
861 },
840862
841 // These are not supported by lastToken() because implementation would863 // These are not supported by lastToken() because implementation would
842 // require recursion due to the optional comma followed by rbrace.864 // require recursion due to the optional comma followed by rbrace.
...@@ -851,13 +873,9 @@ pub const Tree = struct {...@@ -851,13 +873,9 @@ pub const Tree = struct {
851873
852 .TaggedUnionEnumTag => unreachable, // TODO874 .TaggedUnionEnumTag => unreachable, // TODO
853 .TaggedUnionEnumTagComma => unreachable, // TODO875 .TaggedUnionEnumTagComma => unreachable, // TODO
854 .If => unreachable, // TODO
855 .Continue => unreachable, // TODO
856 .SwitchRange => unreachable, // TODO876 .SwitchRange => unreachable, // TODO
857 .ArrayType => unreachable, // TODO877 .ArrayType => unreachable, // TODO
858 .ArrayTypeSentinel => unreachable, // TODO878 .ArrayTypeSentinel => unreachable, // TODO
859 .WhileCont => unreachable, // TODO
860 .While => unreachable, // TODO
861 .ForSimple => unreachable, // TODO879 .ForSimple => unreachable, // TODO
862 .For => unreachable, // TODO880 .For => unreachable, // TODO
863 .ErrorValue => unreachable, // TODO881 .ErrorValue => unreachable, // TODO
...@@ -1404,6 +1422,41 @@ pub const Tree = struct {...@@ -1404,6 +1422,41 @@ pub const Tree = struct {
1404 });1422 });
1405 }1423 }
14061424
1425 pub fn whileSimple(tree: Tree, node: Node.Index) full.While {
1426 const data = tree.nodes.items(.data)[node];
1427 return tree.fullWhile(.{
1428 .while_token = tree.nodes.items(.main_token)[node],
1429 .cond_expr = data.lhs,
1430 .cont_expr = 0,
1431 .then_expr = data.rhs,
1432 .else_expr = 0,
1433 });
1434 }
1435
1436 pub fn whileCont(tree: Tree, node: Node.Index) full.While {
1437 const data = tree.nodes.items(.data)[node];
1438 const extra = tree.extraData(data.rhs, Node.WhileCont);
1439 return tree.fullWhile(.{
1440 .while_token = tree.nodes.items(.main_token)[node],
1441 .cond_expr = data.lhs,
1442 .cont_expr = extra.cont_expr,
1443 .then_expr = extra.then_expr,
1444 .else_expr = 0,
1445 });
1446 }
1447
1448 pub fn whileFull(tree: Tree, node: Node.Index) full.While {
1449 const data = tree.nodes.items(.data)[node];
1450 const extra = tree.extraData(data.rhs, Node.While);
1451 return tree.fullWhile(.{
1452 .while_token = tree.nodes.items(.main_token)[node],
1453 .cond_expr = data.lhs,
1454 .cont_expr = extra.cont_expr,
1455 .then_expr = extra.then_expr,
1456 .else_expr = extra.else_expr,
1457 });
1458 }
1459
1407 fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl {1460 fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl {
1408 const token_tags = tree.tokens.items(.tag);1461 const token_tags = tree.tokens.items(.tag);
1409 var result: full.VarDecl = .{1462 var result: full.VarDecl = .{
...@@ -1623,6 +1676,41 @@ pub const Tree = struct {...@@ -1623,6 +1676,41 @@ pub const Tree = struct {
16231676
1624 return result;1677 return result;
1625 }1678 }
1679
1680 fn fullWhile(tree: Tree, info: full.While.Ast) full.While {
1681 const token_tags = tree.tokens.items(.tag);
1682 var result: full.While = .{
1683 .ast = info,
1684 .inline_token = null,
1685 .label_token = null,
1686 .payload_token = null,
1687 .else_token = undefined,
1688 .error_token = null,
1689 };
1690 var tok_i = info.while_token - 1;
1691 if (token_tags[tok_i] == .Keyword_inline) {
1692 result.inline_token = tok_i;
1693 tok_i -= 1;
1694 }
1695 if (token_tags[tok_i] == .Colon and
1696 token_tags[tok_i - 1] == .Identifier)
1697 {
1698 result.label_token = tok_i - 1;
1699 }
1700 const last_cond_token = tree.lastToken(info.cond_expr);
1701 if (token_tags[last_cond_token + 2] == .Pipe) {
1702 result.payload_token = last_cond_token + 3;
1703 }
1704 if (info.else_expr != 0) {
1705 // then_expr else |x|
1706 // ^ ^
1707 result.else_token = tree.lastToken(info.then_expr) + 1;
1708 if (token_tags[result.else_token + 1] == .Pipe) {
1709 result.error_token = result.else_token + 2;
1710 }
1711 }
1712 return result;
1713 }
1626};1714};
16271715
1628/// Fully assembled AST node information.1716/// Fully assembled AST node information.
...@@ -1645,12 +1733,12 @@ pub const full = struct {...@@ -1645,12 +1733,12 @@ pub const full = struct {
1645 };1733 };
16461734
1647 pub const If = struct {1735 pub const If = struct {
1648 // Points to the first token after the `|`. Will either be an identifier or1736 /// Points to the first token after the `|`. Will either be an identifier or
1649 // a `*` (with an identifier immediately after it).1737 /// a `*` (with an identifier immediately after it).
1650 payload_token: ?TokenIndex,1738 payload_token: ?TokenIndex,
1651 // Points to the identifier after the `|`.1739 /// Points to the identifier after the `|`.
1652 error_token: ?TokenIndex,1740 error_token: ?TokenIndex,
1653 // Populated only if else_expr != 0.1741 /// Populated only if else_expr != 0.
1654 else_token: TokenIndex,1742 else_token: TokenIndex,
1655 ast: Ast,1743 ast: Ast,
16561744
...@@ -1662,6 +1750,24 @@ pub const full = struct {...@@ -1662,6 +1750,24 @@ pub const full = struct {
1662 };1750 };
1663 };1751 };
16641752
1753 pub const While = struct {
1754 ast: Ast,
1755 inline_token: ?TokenIndex,
1756 label_token: ?TokenIndex,
1757 payload_token: ?TokenIndex,
1758 error_token: ?TokenIndex,
1759 /// Populated only if else_expr != 0.
1760 else_token: TokenIndex,
1761
1762 pub const Ast = struct {
1763 while_token: TokenIndex,
1764 cond_expr: Node.Index,
1765 cont_expr: Node.Index,
1766 then_expr: Node.Index,
1767 else_expr: Node.Index,
1768 };
1769 };
1770
1665 pub const ContainerField = struct {1771 pub const ContainerField = struct {
1666 comptime_token: ?TokenIndex,1772 comptime_token: ?TokenIndex,
1667 ast: Ast,1773 ast: Ast,
...@@ -2270,9 +2376,9 @@ pub const Node = struct {...@@ -2270,9 +2376,9 @@ pub const Node = struct {
2270 /// `if (lhs) rhs`.2376 /// `if (lhs) rhs`.
2271 /// `if (lhs) |a| rhs`.2377 /// `if (lhs) |a| rhs`.
2272 IfSimple,2378 IfSimple,
2273 /// `if (lhs) a else b`. `if_list[rhs]`.2379 /// `if (lhs) a else b`. `If[rhs]`.
2274 /// `if (lhs) |x| a else b`. `if_list[rhs]`.2380 /// `if (lhs) |x| a else b`. `If[rhs]`.
2275 /// `if (lhs) |x| a else |y| b`. `if_list[rhs]`.2381 /// `if (lhs) |x| a else |y| b`. `If[rhs]`.
2276 If,2382 If,
2277 /// `suspend lhs`. lhs can be omitted. rhs is unused.2383 /// `suspend lhs`. lhs can be omitted. rhs is unused.
2278 Suspend,2384 Suspend,
...@@ -2497,13 +2603,13 @@ pub const Node = struct {...@@ -2497,13 +2603,13 @@ pub const Node = struct {
2497 };2603 };
24982604
2499 pub const While = struct {2605 pub const While = struct {
2500 continue_expr: Index,2606 cont_expr: Index,
2501 then_expr: Index,2607 then_expr: Index,
2502 else_expr: Index,2608 else_expr: Index,
2503 };2609 };
25042610
2505 pub const WhileCont = struct {2611 pub const WhileCont = struct {
2506 continue_expr: Index,2612 cont_expr: Index,
2507 then_expr: Index,2613 then_expr: Index,
2508 };2614 };
25092615
lib/std/zig/parse.zig+14-14
...@@ -1085,7 +1085,7 @@ const Parser = struct {...@@ -1085,7 +1085,7 @@ const Parser = struct {
1085 const condition = try p.expectExpr();1085 const condition = try p.expectExpr();
1086 _ = try p.expectToken(.RParen);1086 _ = try p.expectToken(.RParen);
1087 const then_payload = try p.parsePtrPayload();1087 const then_payload = try p.parsePtrPayload();
1088 const continue_expr = try p.parseWhileContinueExpr();1088 const cont_expr = try p.parseWhileContinueExpr();
10891089
1090 // TODO propose to change the syntax so that semicolons are always required1090 // TODO propose to change the syntax so that semicolons are always required
1091 // inside while statements, even if there is an `else`.1091 // inside while statements, even if there is an `else`.
...@@ -1098,7 +1098,7 @@ const Parser = struct {...@@ -1098,7 +1098,7 @@ const Parser = struct {
1098 return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });1098 return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
1099 }1099 }
1100 if (p.eatToken(.Semicolon)) |_| {1100 if (p.eatToken(.Semicolon)) |_| {
1101 if (continue_expr == 0) {1101 if (cont_expr == 0) {
1102 return p.addNode(.{1102 return p.addNode(.{
1103 .tag = .WhileSimple,1103 .tag = .WhileSimple,
1104 .main_token = while_token,1104 .main_token = while_token,
...@@ -1114,7 +1114,7 @@ const Parser = struct {...@@ -1114,7 +1114,7 @@ const Parser = struct {
1114 .data = .{1114 .data = .{
1115 .lhs = condition,1115 .lhs = condition,
1116 .rhs = try p.addExtra(Node.WhileCont{1116 .rhs = try p.addExtra(Node.WhileCont{
1117 .continue_expr = continue_expr,1117 .cont_expr = cont_expr,
1118 .then_expr = assign_expr,1118 .then_expr = assign_expr,
1119 }),1119 }),
1120 },1120 },
...@@ -1128,7 +1128,7 @@ const Parser = struct {...@@ -1128,7 +1128,7 @@ const Parser = struct {
1128 if (else_required) {1128 if (else_required) {
1129 return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });1129 return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
1130 }1130 }
1131 if (continue_expr == 0) {1131 if (cont_expr == 0) {
1132 return p.addNode(.{1132 return p.addNode(.{
1133 .tag = .WhileSimple,1133 .tag = .WhileSimple,
1134 .main_token = while_token,1134 .main_token = while_token,
...@@ -1144,7 +1144,7 @@ const Parser = struct {...@@ -1144,7 +1144,7 @@ const Parser = struct {
1144 .data = .{1144 .data = .{
1145 .lhs = condition,1145 .lhs = condition,
1146 .rhs = try p.addExtra(Node.WhileCont{1146 .rhs = try p.addExtra(Node.WhileCont{
1147 .continue_expr = continue_expr,1147 .cont_expr = cont_expr,
1148 .then_expr = then_expr,1148 .then_expr = then_expr,
1149 }),1149 }),
1150 },1150 },
...@@ -1159,7 +1159,7 @@ const Parser = struct {...@@ -1159,7 +1159,7 @@ const Parser = struct {
1159 .data = .{1159 .data = .{
1160 .lhs = condition,1160 .lhs = condition,
1161 .rhs = try p.addExtra(Node.While{1161 .rhs = try p.addExtra(Node.While{
1162 .continue_expr = continue_expr,1162 .cont_expr = cont_expr,
1163 .then_expr = then_expr,1163 .then_expr = then_expr,
1164 .else_expr = else_expr,1164 .else_expr = else_expr,
1165 }),1165 }),
...@@ -2073,11 +2073,11 @@ const Parser = struct {...@@ -2073,11 +2073,11 @@ const Parser = struct {
2073 const condition = try p.expectExpr();2073 const condition = try p.expectExpr();
2074 _ = try p.expectToken(.RParen);2074 _ = try p.expectToken(.RParen);
2075 const then_payload = try p.parsePtrPayload();2075 const then_payload = try p.parsePtrPayload();
2076 const continue_expr = try p.parseWhileContinueExpr();2076 const cont_expr = try p.parseWhileContinueExpr();
20772077
2078 const then_expr = try p.expectExpr();2078 const then_expr = try p.expectExpr();
2079 const else_token = p.eatToken(.Keyword_else) orelse {2079 const else_token = p.eatToken(.Keyword_else) orelse {
2080 if (continue_expr == 0) {2080 if (cont_expr == 0) {
2081 return p.addNode(.{2081 return p.addNode(.{
2082 .tag = .WhileSimple,2082 .tag = .WhileSimple,
2083 .main_token = while_token,2083 .main_token = while_token,
...@@ -2093,7 +2093,7 @@ const Parser = struct {...@@ -2093,7 +2093,7 @@ const Parser = struct {
2093 .data = .{2093 .data = .{
2094 .lhs = condition,2094 .lhs = condition,
2095 .rhs = try p.addExtra(Node.WhileCont{2095 .rhs = try p.addExtra(Node.WhileCont{
2096 .continue_expr = continue_expr,2096 .cont_expr = cont_expr,
2097 .then_expr = then_expr,2097 .then_expr = then_expr,
2098 }),2098 }),
2099 },2099 },
...@@ -2108,7 +2108,7 @@ const Parser = struct {...@@ -2108,7 +2108,7 @@ const Parser = struct {
2108 .data = .{2108 .data = .{
2109 .lhs = condition,2109 .lhs = condition,
2110 .rhs = try p.addExtra(Node.While{2110 .rhs = try p.addExtra(Node.While{
2111 .continue_expr = continue_expr,2111 .cont_expr = cont_expr,
2112 .then_expr = then_expr,2112 .then_expr = then_expr,
2113 .else_expr = else_expr,2113 .else_expr = else_expr,
2114 }),2114 }),
...@@ -2836,11 +2836,11 @@ const Parser = struct {...@@ -2836,11 +2836,11 @@ const Parser = struct {
2836 const condition = try p.expectExpr();2836 const condition = try p.expectExpr();
2837 _ = try p.expectToken(.RParen);2837 _ = try p.expectToken(.RParen);
2838 const then_payload = try p.parsePtrPayload();2838 const then_payload = try p.parsePtrPayload();
2839 const continue_expr = try p.parseWhileContinueExpr();2839 const cont_expr = try p.parseWhileContinueExpr();
28402840
2841 const then_expr = try p.expectTypeExpr();2841 const then_expr = try p.expectTypeExpr();
2842 const else_token = p.eatToken(.Keyword_else) orelse {2842 const else_token = p.eatToken(.Keyword_else) orelse {
2843 if (continue_expr == 0) {2843 if (cont_expr == 0) {
2844 return p.addNode(.{2844 return p.addNode(.{
2845 .tag = .WhileSimple,2845 .tag = .WhileSimple,
2846 .main_token = while_token,2846 .main_token = while_token,
...@@ -2856,7 +2856,7 @@ const Parser = struct {...@@ -2856,7 +2856,7 @@ const Parser = struct {
2856 .data = .{2856 .data = .{
2857 .lhs = condition,2857 .lhs = condition,
2858 .rhs = try p.addExtra(Node.WhileCont{2858 .rhs = try p.addExtra(Node.WhileCont{
2859 .continue_expr = continue_expr,2859 .cont_expr = cont_expr,
2860 .then_expr = then_expr,2860 .then_expr = then_expr,
2861 }),2861 }),
2862 },2862 },
...@@ -2871,7 +2871,7 @@ const Parser = struct {...@@ -2871,7 +2871,7 @@ const Parser = struct {
2871 .data = .{2871 .data = .{
2872 .lhs = condition,2872 .lhs = condition,
2873 .rhs = try p.addExtra(Node.While{2873 .rhs = try p.addExtra(Node.While{
2874 .continue_expr = continue_expr,2874 .cont_expr = cont_expr,
2875 .then_expr = then_expr,2875 .then_expr = then_expr,
2876 .else_expr = else_expr,2876 .else_expr = else_expr,
2877 }),2877 }),
lib/std/zig/parser_test.zig+13-13
...@@ -714,19 +714,19 @@ test "zig fmt: async function" {...@@ -714,19 +714,19 @@ test "zig fmt: async function" {
714// \\714// \\
715// );715// );
716//}716//}
717//717
718//test "zig fmt: while else err prong with no block" {718test "zig fmt: while else err prong with no block" {
719// try testCanonical(719 try testCanonical(
720// \\test "" {720 \\test "" {
721// \\ const result = while (returnError()) |value| {721 \\ const result = while (returnError()) |value| {
722// \\ break value;722 \\ break value;
723// \\ } else |err| @as(i32, 2);723 \\ } else |err| @as(i32, 2);
724// \\ expect(result == 2);724 \\ expect(result == 2);
725// \\}725 \\}
726// \\726 \\
727// );727 );
728//}728}
729//729
730//test "zig fmt: tagged union with enum values" {730//test "zig fmt: tagged union with enum values" {
731// try testCanonical(731// try testCanonical(
732// \\const MultipleChoice2 = union(enum(u32)) {732// \\const MultipleChoice2 = union(enum(u32)) {
lib/std/zig/render.zig+120-137
...@@ -567,13 +567,13 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -567,13 +567,13 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
567 if (lbrace + 1 == rbrace) {567 if (lbrace + 1 == rbrace) {
568 // There is nothing between the braces so render condensed: `error{}`568 // There is nothing between the braces so render condensed: `error{}`
569 try renderToken(ais, tree, lbrace, .None);569 try renderToken(ais, tree, lbrace, .None);
570 try renderToken(ais, tree, rbrace, space);570 return renderToken(ais, tree, rbrace, space);
571 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .Identifier) {571 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .Identifier) {
572 // There is exactly one member and no trailing comma or572 // There is exactly one member and no trailing comma or
573 // comments, so render without surrounding spaces: `error{Foo}`573 // comments, so render without surrounding spaces: `error{Foo}`
574 try renderToken(ais, tree, lbrace, .None);574 try renderToken(ais, tree, lbrace, .None);
575 try renderToken(ais, tree, lbrace + 1, .None); // identifier575 try renderToken(ais, tree, lbrace + 1, .None); // identifier
576 try renderToken(ais, tree, rbrace, space);576 return renderToken(ais, tree, rbrace, space);
577 } else if (token_tags[rbrace - 1] == .Comma) {577 } else if (token_tags[rbrace - 1] == .Comma) {
578 // There is a trailing comma so render each member on a new line.578 // There is a trailing comma so render each member on a new line.
579 try renderToken(ais, tree, lbrace, .Newline);579 try renderToken(ais, tree, lbrace, .Newline);
...@@ -589,7 +589,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -589,7 +589,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
589 }589 }
590 }590 }
591 ais.popIndent();591 ais.popIndent();
592 try renderToken(ais, tree, rbrace, space);592 return renderToken(ais, tree, rbrace, space);
593 } else {593 } else {
594 // There is no trailing comma so render everything on one line.594 // There is no trailing comma so render everything on one line.
595 try renderToken(ais, tree, lbrace, .Space);595 try renderToken(ais, tree, lbrace, .Space);
...@@ -602,7 +602,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -602,7 +602,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
602 else => unreachable,602 else => unreachable,
603 }603 }
604 }604 }
605 try renderToken(ais, tree, rbrace, space);605 return renderToken(ais, tree, rbrace, space);
606 }606 }
607 },607 },
608608
...@@ -663,7 +663,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -663,7 +663,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
663663
664 if (cases.len == 0) {664 if (cases.len == 0) {
665 try renderToken(ais, tree, rparen + 1, .None); // lbrace665 try renderToken(ais, tree, rparen + 1, .None); // lbrace
666 try renderToken(ais, tree, rparen + 2, space); // rbrace666 return renderToken(ais, tree, rparen + 2, space); // rbrace
667 } else {667 } else {
668 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace668 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
669 ais.pushIndent();669 ais.pushIndent();
...@@ -673,83 +673,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -673,83 +673,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
673 try renderExpression(ais, tree, case, .Comma);673 try renderExpression(ais, tree, case, .Comma);
674 }674 }
675 ais.popIndent();675 ais.popIndent();
676 try renderToken(ais, tree, tree.lastToken(node), space); // rbrace676 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
677 }677 }
678 },678 },
679679
680 .SwitchCaseOne => try renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),680 .SwitchCaseOne => return renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
681 .SwitchCase => try renderSwitchCase(ais, tree, tree.switchCase(node), space),681 .SwitchCase => return renderSwitchCase(ais, tree, tree.switchCase(node), space),
682682
683 .WhileSimple => unreachable, // TODO683 .WhileSimple => return renderWhile(ais, tree, tree.whileSimple(node), space),
684 .WhileCont => unreachable, // TODO684 .WhileCont => return renderWhile(ais, tree, tree.whileCont(node), space),
685 .While => unreachable, // TODO685 .While => return renderWhile(ais, tree, tree.whileFull(node), space),
686 //.While => {
687 // const while_node = @fieldParentPtr(ast.Node.While, "base", base);
688
689 // if (while_node.label) |label| {
690 // try renderToken(ais, tree, label, Space.None); // label
691 // try renderToken(ais, tree, tree.nextToken(label), Space.Space); // :
692 // }
693
694 // if (while_node.inline_token) |inline_token| {
695 // try renderToken(ais, tree, inline_token, Space.Space); // inline
696 // }
697
698 // try renderToken(ais, tree, while_node.while_token, Space.Space); // while
699 // try renderToken(ais, tree, tree.nextToken(while_node.while_token), Space.None); // (
700 // try renderExpression(ais, tree, while_node.condition, Space.None);
701
702 // const cond_rparen = tree.nextToken(while_node.condition.lastToken());
703
704 // const body_is_block = nodeIsBlock(while_node.body);
705
706 // var block_start_space: Space = undefined;
707 // var after_body_space: Space = undefined;
708
709 // if (body_is_block) {
710 // block_start_space = Space.BlockStart;
711 // after_body_space = if (while_node.@"else" == null) space else Space.Space;
712 // } else if (tree.tokensOnSameLine(cond_rparen, while_node.body.lastToken())) {
713 // block_start_space = Space.Space;
714 // after_body_space = if (while_node.@"else" == null) space else Space.Space;
715 // } else {
716 // block_start_space = Space.Newline;
717 // after_body_space = if (while_node.@"else" == null) space else Space.Newline;
718 // }
719
720 // {
721 // const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
722 // try renderToken(ais, tree, cond_rparen, rparen_space); // )
723 // }
724
725 // if (while_node.payload) |payload| {
726 // const payload_space = if (while_node.continue_expr != null) Space.Space else block_start_space;
727 // try renderExpression(ais, tree, payload, payload_space);
728 // }
729
730 // if (while_node.continue_expr) |continue_expr| {
731 // const rparen = tree.nextToken(continue_expr.lastToken());
732 // const lparen = tree.prevToken(continue_expr.firstToken());
733 // const colon = tree.prevToken(lparen);
734
735 // try renderToken(ais, tree, colon, Space.Space); // :
736 // try renderToken(ais, tree, lparen, Space.None); // (
737
738 // try renderExpression(ais, tree, continue_expr, Space.None);
739
740 // try renderToken(ais, tree, rparen, block_start_space); // )
741 // }
742
743 // {
744 // if (!body_is_block) ais.pushIndent();
745 // defer if (!body_is_block) ais.popIndent();
746 // try renderExpression(ais, tree, while_node.body, after_body_space);
747 // }
748
749 // if (while_node.@"else") |@"else"| {
750 // return renderExpression(ais, tree, &@"else".base, space);
751 // }
752 //},
753686
754 .ForSimple => unreachable, // TODO687 .ForSimple => unreachable, // TODO
755 .For => unreachable, // TODO688 .For => unreachable, // TODO
...@@ -1092,105 +1025,142 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo...@@ -1092,105 +1025,142 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
1092}1025}
10931026
1094fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void {1027fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error!void {
1028 return renderWhile(ais, tree, .{
1029 .ast = .{
1030 .while_token = if_node.ast.if_token,
1031 .cond_expr = if_node.ast.cond_expr,
1032 .cont_expr = 0,
1033 .then_expr = if_node.ast.then_expr,
1034 .else_expr = if_node.ast.else_expr,
1035 },
1036 .inline_token = null,
1037 .label_token = null,
1038 .payload_token = if_node.payload_token,
1039 .else_token = if_node.else_token,
1040 .error_token = if_node.error_token,
1041 }, space);
1042}
1043
1044/// Note that this function is additionally used to render if expressions, with
1045/// respective values set to null.
1046fn renderWhile(ais: *Ais, tree: ast.Tree, while_node: ast.full.While, space: Space) Error!void {
1095 const node_tags = tree.nodes.items(.tag);1047 const node_tags = tree.nodes.items(.tag);
1096 const token_tags = tree.tokens.items(.tag);1048 const token_tags = tree.tokens.items(.tag);
10971049
1098 try renderToken(ais, tree, if_node.ast.if_token, .Space); // if1050 if (while_node.label_token) |label| {
1051 try renderToken(ais, tree, label, .None); // label
1052 try renderToken(ais, tree, label + 1, .Space); // :
1053 }
10991054
1100 const lparen = if_node.ast.if_token + 1;1055 if (while_node.inline_token) |inline_token| {
1056 try renderToken(ais, tree, inline_token, .Space); // inline
1057 }
11011058
1102 try renderToken(ais, tree, lparen, .None); // (1059 try renderToken(ais, tree, while_node.ast.while_token, .Space); // if
1103 try renderExpression(ais, tree, if_node.ast.cond_expr, .None); // condition1060 try renderToken(ais, tree, while_node.ast.while_token + 1, .None); // (
1061 try renderExpression(ais, tree, while_node.ast.cond_expr, .None); // condition
11041062
1105 switch (node_tags[if_node.ast.then_expr]) {1063 if (nodeIsBlock(node_tags[while_node.ast.then_expr])) {
1106 .If, .IfSimple => {1064 const payload_space: Space = if (while_node.ast.cont_expr != 0) .Space else .BlockStart;
1107 try renderExtraNewline(ais, tree, if_node.ast.then_expr);1065 if (while_node.payload_token) |payload_token| {
1108 },1066 try renderToken(ais, tree, payload_token - 2, .Space); // )
1109 .Block, .For, .ForSimple, .While, .WhileSimple, .Switch => {1067 try renderToken(ais, tree, payload_token - 1, .None); // |
1110 if (if_node.payload_token) |payload_token| {1068 if (token_tags[payload_token] == .Asterisk) {
1111 try renderToken(ais, tree, payload_token - 2, .Space); // )1069 try renderToken(ais, tree, payload_token, .None); // *
1112 try renderToken(ais, tree, payload_token - 1, .None); // |1070 try renderToken(ais, tree, payload_token + 1, .None); // identifier
1113 if (token_tags[payload_token] == .Asterisk) {1071 try renderToken(ais, tree, payload_token + 2, payload_space); // |
1114 try renderToken(ais, tree, payload_token, .None); // *
1115 try renderToken(ais, tree, payload_token + 1, .None); // identifier
1116 try renderToken(ais, tree, payload_token + 2, .BlockStart); // |
1117 } else {
1118 try renderToken(ais, tree, payload_token, .None); // identifier
1119 try renderToken(ais, tree, payload_token + 1, .BlockStart); // |
1120 }
1121 } else {1072 } else {
1122 const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;1073 try renderToken(ais, tree, payload_token, .None); // identifier
1123 try renderToken(ais, tree, rparen, .BlockStart); // )1074 try renderToken(ais, tree, payload_token + 1, payload_space); // |
1124 }1075 }
1125 if (if_node.ast.else_expr != 0) {1076 } else {
1126 try renderExpression(ais, tree, if_node.ast.then_expr, Space.Space);1077 const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
1127 try renderToken(ais, tree, if_node.else_token, .Space); // else1078 try renderToken(ais, tree, rparen, payload_space); // )
1128 if (if_node.error_token) |error_token| {1079 }
1129 try renderToken(ais, tree, error_token - 1, .None); // |1080 if (while_node.ast.cont_expr != 0) {
1130 try renderToken(ais, tree, error_token, .None); // identifier1081 const rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
1131 try renderToken(ais, tree, error_token + 1, .Space); // |1082 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1132 }1083 try renderToken(ais, tree, lparen - 1, .Space); // :
1133 return renderExpression(ais, tree, if_node.ast.else_expr, space);1084 try renderToken(ais, tree, lparen, .None); // lparen
1134 } else {1085 try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
1135 return renderExpression(ais, tree, if_node.ast.then_expr, space);1086 try renderToken(ais, tree, rparen, .BlockStart); // rparen
1087 }
1088 if (while_node.ast.else_expr != 0) {
1089 try renderExpression(ais, tree, while_node.ast.then_expr, Space.Space);
1090 try renderToken(ais, tree, while_node.else_token, .Space); // else
1091 if (while_node.error_token) |error_token| {
1092 try renderToken(ais, tree, error_token - 1, .None); // |
1093 try renderToken(ais, tree, error_token, .None); // identifier
1094 try renderToken(ais, tree, error_token + 1, .Space); // |
1136 }1095 }
1137 },1096 return renderExpression(ais, tree, while_node.ast.else_expr, space);
1138 else => {},1097 } else {
1098 return renderExpression(ais, tree, while_node.ast.then_expr, space);
1099 }
1139 }1100 }
11401101
1141 const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;1102 const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
1142 const last_then_token = tree.lastToken(if_node.ast.then_expr);1103 const last_then_token = tree.lastToken(while_node.ast.then_expr);
1143 const src_has_newline = !tree.tokensOnSameLine(rparen, last_then_token);1104 const src_has_newline = !tree.tokensOnSameLine(rparen, last_then_token);
11441105
1145 if (src_has_newline) {1106 if (src_has_newline) {
1146 if (if_node.payload_token) |payload_token| {1107 const payload_space: Space = if (while_node.ast.cont_expr != 0) .Space else .Newline;
1108 if (while_node.payload_token) |payload_token| {
1147 try renderToken(ais, tree, payload_token - 2, .Space); // )1109 try renderToken(ais, tree, payload_token - 2, .Space); // )
1148 try renderToken(ais, tree, payload_token - 1, .None); // |1110 try renderToken(ais, tree, payload_token - 1, .None); // |
1149 try renderToken(ais, tree, payload_token, .None); // identifier1111 try renderToken(ais, tree, payload_token, .None); // identifier
1150 try renderToken(ais, tree, payload_token + 1, .Newline); // |1112 try renderToken(ais, tree, payload_token + 1, payload_space); // |
1151 } else {1113 } else {
1152 ais.pushIndent();1114 ais.pushIndent();
1153 try renderToken(ais, tree, rparen, .Newline); // )1115 try renderToken(ais, tree, rparen, payload_space); // )
1154 ais.popIndent();1116 ais.popIndent();
1155 }1117 }
1156 if (if_node.ast.else_expr != 0) {1118 if (while_node.ast.cont_expr != 0) {
1119 const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
1120 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1121 try renderToken(ais, tree, cont_lparen - 1, .Space); // :
1122 try renderToken(ais, tree, cont_lparen, .None); // lparen
1123 try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
1124 try renderToken(ais, tree, cont_rparen, .Newline); // rparen
1125 }
1126 if (while_node.ast.else_expr != 0) {
1157 ais.pushIndent();1127 ais.pushIndent();
1158 try renderExpression(ais, tree, if_node.ast.then_expr, Space.Newline);1128 try renderExpression(ais, tree, while_node.ast.then_expr, Space.Newline);
1159 ais.popIndent();1129 ais.popIndent();
1160 const else_is_block = nodeIsBlock(node_tags[if_node.ast.else_expr]);1130 const else_is_block = nodeIsBlock(node_tags[while_node.ast.else_expr]);
1161 if (else_is_block) {1131 if (else_is_block) {
1162 try renderToken(ais, tree, if_node.else_token, .Space); // else1132 try renderToken(ais, tree, while_node.else_token, .Space); // else
1163 if (if_node.error_token) |error_token| {1133 if (while_node.error_token) |error_token| {
1164 try renderToken(ais, tree, error_token - 1, .None); // |1134 try renderToken(ais, tree, error_token - 1, .None); // |
1165 try renderToken(ais, tree, error_token, .None); // identifier1135 try renderToken(ais, tree, error_token, .None); // identifier
1166 try renderToken(ais, tree, error_token + 1, .Space); // |1136 try renderToken(ais, tree, error_token + 1, .Space); // |
1167 }1137 }
1168 return renderExpression(ais, tree, if_node.ast.else_expr, space);1138 return renderExpression(ais, tree, while_node.ast.else_expr, space);
1169 } else {1139 } else {
1170 if (if_node.error_token) |error_token| {1140 if (while_node.error_token) |error_token| {
1171 try renderToken(ais, tree, if_node.else_token, .Space); // else1141 try renderToken(ais, tree, while_node.else_token, .Space); // else
1172 try renderToken(ais, tree, error_token - 1, .None); // |1142 try renderToken(ais, tree, error_token - 1, .None); // |
1173 try renderToken(ais, tree, error_token, .None); // identifier1143 try renderToken(ais, tree, error_token, .None); // identifier
1174 try renderToken(ais, tree, error_token + 1, .Space); // |1144 try renderToken(ais, tree, error_token + 1, .Space); // |
1175 } else {1145 } else {
1176 try renderToken(ais, tree, if_node.else_token, .Newline); // else1146 try renderToken(ais, tree, while_node.else_token, .Newline); // else
1177 }1147 }
1178 ais.pushIndent();1148 ais.pushIndent();
1179 try renderExpression(ais, tree, if_node.ast.else_expr, space);1149 try renderExpression(ais, tree, while_node.ast.else_expr, space);
1180 ais.popIndent();1150 ais.popIndent();
1181 return;1151 return;
1182 }1152 }
1183 } else {1153 } else {
1184 ais.pushIndent();1154 ais.pushIndent();
1185 try renderExpression(ais, tree, if_node.ast.then_expr, space);1155 try renderExpression(ais, tree, while_node.ast.then_expr, space);
1186 ais.popIndent();1156 ais.popIndent();
1187 return;1157 return;
1188 }1158 }
1189 }1159 }
11901160
1191 // Single line if statement.1161 // Render everything on a single line.
11921162
1193 if (if_node.payload_token) |payload_token| {1163 if (while_node.payload_token) |payload_token| {
1194 assert(payload_token - 2 == rparen);1164 assert(payload_token - 2 == rparen);
1195 try renderToken(ais, tree, payload_token - 2, .Space); // )1165 try renderToken(ais, tree, payload_token - 2, .Space); // )
1196 try renderToken(ais, tree, payload_token - 1, .None); // |1166 try renderToken(ais, tree, payload_token - 1, .None); // |
...@@ -1206,19 +1176,28 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error...@@ -1206,19 +1176,28 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.full.If, space: Space) Error
1206 try renderToken(ais, tree, rparen, .Space); // )1176 try renderToken(ais, tree, rparen, .Space); // )
1207 }1177 }
12081178
1209 if (if_node.ast.else_expr != 0) {1179 if (while_node.ast.cont_expr != 0) {
1210 try renderExpression(ais, tree, if_node.ast.then_expr, .Space);1180 const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
1211 try renderToken(ais, tree, if_node.else_token, .Space); // else1181 const cont_lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1182 try renderToken(ais, tree, cont_lparen - 1, .Space); // :
1183 try renderToken(ais, tree, cont_lparen, .None); // lparen
1184 try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
1185 try renderToken(ais, tree, cont_rparen, .Space); // rparen
1186 }
1187
1188 if (while_node.ast.else_expr != 0) {
1189 try renderExpression(ais, tree, while_node.ast.then_expr, .Space);
1190 try renderToken(ais, tree, while_node.else_token, .Space); // else
12121191
1213 if (if_node.error_token) |error_token| {1192 if (while_node.error_token) |error_token| {
1214 try renderToken(ais, tree, error_token - 1, .None); // |1193 try renderToken(ais, tree, error_token - 1, .None); // |
1215 try renderToken(ais, tree, error_token, .None); // identifier1194 try renderToken(ais, tree, error_token, .None); // identifier
1216 try renderToken(ais, tree, error_token + 1, .Space); // |1195 try renderToken(ais, tree, error_token + 1, .Space); // |
1217 }1196 }
12181197
1219 return renderExpression(ais, tree, if_node.ast.else_expr, space);1198 return renderExpression(ais, tree, while_node.ast.else_expr, space);
1220 } else {1199 } else {
1221 return renderExpression(ais, tree, if_node.ast.then_expr, space);1200 return renderExpression(ais, tree, while_node.ast.then_expr, space);
1222 }1201 }
1223}1202}
12241203
...@@ -2079,12 +2058,16 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error...@@ -2079,12 +2058,16 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error
2079fn nodeIsBlock(tag: ast.Node.Tag) bool {2058fn nodeIsBlock(tag: ast.Node.Tag) bool {
2080 return switch (tag) {2059 return switch (tag) {
2081 .Block,2060 .Block,
2061 .BlockSemicolon,
2062 .BlockTwo,
2063 .BlockTwoSemicolon,
2082 .If,2064 .If,
2083 .IfSimple,2065 .IfSimple,
2084 .For,2066 .For,
2085 .ForSimple,2067 .ForSimple,
2086 .While,2068 .While,
2087 .WhileSimple,2069 .WhileSimple,
2070 .WhileCont,
2088 .Switch,2071 .Switch,
2089 => true,2072 => true,
2090 else => false,2073 else => false,