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 {
760760 n = extra.sentinel;
761761 },
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 },
763770 .Break => {
764771 if (datas[n].rhs != 0) {
765772 n = datas[n].rhs;
......@@ -837,6 +844,21 @@ pub const Tree = struct {
837844 n = max_node;
838845 end_offset += max_offset;
839846 },
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
841863 // These are not supported by lastToken() because implementation would
842864 // require recursion due to the optional comma followed by rbrace.
......@@ -851,13 +873,9 @@ pub const Tree = struct {
851873
852874 .TaggedUnionEnumTag => unreachable, // TODO
853875 .TaggedUnionEnumTagComma => unreachable, // TODO
854 .If => unreachable, // TODO
855 .Continue => unreachable, // TODO
856876 .SwitchRange => unreachable, // TODO
857877 .ArrayType => unreachable, // TODO
858878 .ArrayTypeSentinel => unreachable, // TODO
859 .WhileCont => unreachable, // TODO
860 .While => unreachable, // TODO
861879 .ForSimple => unreachable, // TODO
862880 .For => unreachable, // TODO
863881 .ErrorValue => unreachable, // TODO
......@@ -1404,6 +1422,41 @@ pub const Tree = struct {
14041422 });
14051423 }
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
14071460 fn fullVarDecl(tree: Tree, info: full.VarDecl.Ast) full.VarDecl {
14081461 const token_tags = tree.tokens.items(.tag);
14091462 var result: full.VarDecl = .{
......@@ -1623,6 +1676,41 @@ pub const Tree = struct {
16231676
16241677 return result;
16251678 }
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 }
16261714};
16271715
16281716/// Fully assembled AST node information.
......@@ -1645,12 +1733,12 @@ pub const full = struct {
16451733 };
16461734
16471735 pub const If = struct {
1648 // Points to the first token after the `|`. Will either be an identifier or
1649 // a `*` (with an identifier immediately after it).
1736 /// Points to the first token after the `|`. Will either be an identifier or
1737 /// a `*` (with an identifier immediately after it).
16501738 payload_token: ?TokenIndex,
1651 // Points to the identifier after the `|`.
1739 /// Points to the identifier after the `|`.
16521740 error_token: ?TokenIndex,
1653 // Populated only if else_expr != 0.
1741 /// Populated only if else_expr != 0.
16541742 else_token: TokenIndex,
16551743 ast: Ast,
16561744
......@@ -1662,6 +1750,24 @@ pub const full = struct {
16621750 };
16631751 };
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
16651771 pub const ContainerField = struct {
16661772 comptime_token: ?TokenIndex,
16671773 ast: Ast,
......@@ -2270,9 +2376,9 @@ pub const Node = struct {
22702376 /// `if (lhs) rhs`.
22712377 /// `if (lhs) |a| rhs`.
22722378 IfSimple,
2273 /// `if (lhs) a else b`. `if_list[rhs]`.
2274 /// `if (lhs) |x| a else b`. `if_list[rhs]`.
2275 /// `if (lhs) |x| a else |y| b`. `if_list[rhs]`.
2379 /// `if (lhs) a else b`. `If[rhs]`.
2380 /// `if (lhs) |x| a else b`. `If[rhs]`.
2381 /// `if (lhs) |x| a else |y| b`. `If[rhs]`.
22762382 If,
22772383 /// `suspend lhs`. lhs can be omitted. rhs is unused.
22782384 Suspend,
......@@ -2497,13 +2603,13 @@ pub const Node = struct {
24972603 };
24982604
24992605 pub const While = struct {
2500 continue_expr: Index,
2606 cont_expr: Index,
25012607 then_expr: Index,
25022608 else_expr: Index,
25032609 };
25042610
25052611 pub const WhileCont = struct {
2506 continue_expr: Index,
2612 cont_expr: Index,
25072613 then_expr: Index,
25082614 };
25092615
lib/std/zig/parse.zig+14-14
......@@ -1085,7 +1085,7 @@ const Parser = struct {
10851085 const condition = try p.expectExpr();
10861086 _ = try p.expectToken(.RParen);
10871087 const then_payload = try p.parsePtrPayload();
1088 const continue_expr = try p.parseWhileContinueExpr();
1088 const cont_expr = try p.parseWhileContinueExpr();
10891089
10901090 // TODO propose to change the syntax so that semicolons are always required
10911091 // inside while statements, even if there is an `else`.
......@@ -1098,7 +1098,7 @@ const Parser = struct {
10981098 return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
10991099 }
11001100 if (p.eatToken(.Semicolon)) |_| {
1101 if (continue_expr == 0) {
1101 if (cont_expr == 0) {
11021102 return p.addNode(.{
11031103 .tag = .WhileSimple,
11041104 .main_token = while_token,
......@@ -1114,7 +1114,7 @@ const Parser = struct {
11141114 .data = .{
11151115 .lhs = condition,
11161116 .rhs = try p.addExtra(Node.WhileCont{
1117 .continue_expr = continue_expr,
1117 .cont_expr = cont_expr,
11181118 .then_expr = assign_expr,
11191119 }),
11201120 },
......@@ -1128,7 +1128,7 @@ const Parser = struct {
11281128 if (else_required) {
11291129 return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
11301130 }
1131 if (continue_expr == 0) {
1131 if (cont_expr == 0) {
11321132 return p.addNode(.{
11331133 .tag = .WhileSimple,
11341134 .main_token = while_token,
......@@ -1144,7 +1144,7 @@ const Parser = struct {
11441144 .data = .{
11451145 .lhs = condition,
11461146 .rhs = try p.addExtra(Node.WhileCont{
1147 .continue_expr = continue_expr,
1147 .cont_expr = cont_expr,
11481148 .then_expr = then_expr,
11491149 }),
11501150 },
......@@ -1159,7 +1159,7 @@ const Parser = struct {
11591159 .data = .{
11601160 .lhs = condition,
11611161 .rhs = try p.addExtra(Node.While{
1162 .continue_expr = continue_expr,
1162 .cont_expr = cont_expr,
11631163 .then_expr = then_expr,
11641164 .else_expr = else_expr,
11651165 }),
......@@ -2073,11 +2073,11 @@ const Parser = struct {
20732073 const condition = try p.expectExpr();
20742074 _ = try p.expectToken(.RParen);
20752075 const then_payload = try p.parsePtrPayload();
2076 const continue_expr = try p.parseWhileContinueExpr();
2076 const cont_expr = try p.parseWhileContinueExpr();
20772077
20782078 const then_expr = try p.expectExpr();
20792079 const else_token = p.eatToken(.Keyword_else) orelse {
2080 if (continue_expr == 0) {
2080 if (cont_expr == 0) {
20812081 return p.addNode(.{
20822082 .tag = .WhileSimple,
20832083 .main_token = while_token,
......@@ -2093,7 +2093,7 @@ const Parser = struct {
20932093 .data = .{
20942094 .lhs = condition,
20952095 .rhs = try p.addExtra(Node.WhileCont{
2096 .continue_expr = continue_expr,
2096 .cont_expr = cont_expr,
20972097 .then_expr = then_expr,
20982098 }),
20992099 },
......@@ -2108,7 +2108,7 @@ const Parser = struct {
21082108 .data = .{
21092109 .lhs = condition,
21102110 .rhs = try p.addExtra(Node.While{
2111 .continue_expr = continue_expr,
2111 .cont_expr = cont_expr,
21122112 .then_expr = then_expr,
21132113 .else_expr = else_expr,
21142114 }),
......@@ -2836,11 +2836,11 @@ const Parser = struct {
28362836 const condition = try p.expectExpr();
28372837 _ = try p.expectToken(.RParen);
28382838 const then_payload = try p.parsePtrPayload();
2839 const continue_expr = try p.parseWhileContinueExpr();
2839 const cont_expr = try p.parseWhileContinueExpr();
28402840
28412841 const then_expr = try p.expectTypeExpr();
28422842 const else_token = p.eatToken(.Keyword_else) orelse {
2843 if (continue_expr == 0) {
2843 if (cont_expr == 0) {
28442844 return p.addNode(.{
28452845 .tag = .WhileSimple,
28462846 .main_token = while_token,
......@@ -2856,7 +2856,7 @@ const Parser = struct {
28562856 .data = .{
28572857 .lhs = condition,
28582858 .rhs = try p.addExtra(Node.WhileCont{
2859 .continue_expr = continue_expr,
2859 .cont_expr = cont_expr,
28602860 .then_expr = then_expr,
28612861 }),
28622862 },
......@@ -2871,7 +2871,7 @@ const Parser = struct {
28712871 .data = .{
28722872 .lhs = condition,
28732873 .rhs = try p.addExtra(Node.While{
2874 .continue_expr = continue_expr,
2874 .cont_expr = cont_expr,
28752875 .then_expr = then_expr,
28762876 .else_expr = else_expr,
28772877 }),
lib/std/zig/parser_test.zig+13-13
......@@ -714,19 +714,19 @@ test "zig fmt: async function" {
714714// \\
715715// );
716716//}
717//
718//test "zig fmt: while else err prong with no block" {
719// try testCanonical(
720// \\test "" {
721// \\ const result = while (returnError()) |value| {
722// \\ break value;
723// \\ } else |err| @as(i32, 2);
724// \\ expect(result == 2);
725// \\}
726// \\
727// );
728//}
729//
717
718test "zig fmt: while else err prong with no block" {
719 try testCanonical(
720 \\test "" {
721 \\ const result = while (returnError()) |value| {
722 \\ break value;
723 \\ } else |err| @as(i32, 2);
724 \\ expect(result == 2);
725 \\}
726 \\
727 );
728}
729
730730//test "zig fmt: tagged union with enum values" {
731731// try testCanonical(
732732// \\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
567567 if (lbrace + 1 == rbrace) {
568568 // There is nothing between the braces so render condensed: `error{}`
569569 try renderToken(ais, tree, lbrace, .None);
570 try renderToken(ais, tree, rbrace, space);
570 return renderToken(ais, tree, rbrace, space);
571571 } else if (lbrace + 2 == rbrace and token_tags[lbrace + 1] == .Identifier) {
572572 // There is exactly one member and no trailing comma or
573573 // comments, so render without surrounding spaces: `error{Foo}`
574574 try renderToken(ais, tree, lbrace, .None);
575575 try renderToken(ais, tree, lbrace + 1, .None); // identifier
576 try renderToken(ais, tree, rbrace, space);
576 return renderToken(ais, tree, rbrace, space);
577577 } else if (token_tags[rbrace - 1] == .Comma) {
578578 // There is a trailing comma so render each member on a new line.
579579 try renderToken(ais, tree, lbrace, .Newline);
......@@ -589,7 +589,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
589589 }
590590 }
591591 ais.popIndent();
592 try renderToken(ais, tree, rbrace, space);
592 return renderToken(ais, tree, rbrace, space);
593593 } else {
594594 // There is no trailing comma so render everything on one line.
595595 try renderToken(ais, tree, lbrace, .Space);
......@@ -602,7 +602,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
602602 else => unreachable,
603603 }
604604 }
605 try renderToken(ais, tree, rbrace, space);
605 return renderToken(ais, tree, rbrace, space);
606606 }
607607 },
608608
......@@ -663,7 +663,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
663663
664664 if (cases.len == 0) {
665665 try renderToken(ais, tree, rparen + 1, .None); // lbrace
666 try renderToken(ais, tree, rparen + 2, space); // rbrace
666 return renderToken(ais, tree, rparen + 2, space); // rbrace
667667 } else {
668668 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
669669 ais.pushIndent();
......@@ -673,83 +673,16 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
673673 try renderExpression(ais, tree, case, .Comma);
674674 }
675675 ais.popIndent();
676 try renderToken(ais, tree, tree.lastToken(node), space); // rbrace
676 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
677677 }
678678 },
679679
680 .SwitchCaseOne => try renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
681 .SwitchCase => try renderSwitchCase(ais, tree, tree.switchCase(node), space),
680 .SwitchCaseOne => return renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
681 .SwitchCase => return renderSwitchCase(ais, tree, tree.switchCase(node), space),
682682
683 .WhileSimple => unreachable, // TODO
684 .WhileCont => unreachable, // TODO
685 .While => unreachable, // TODO
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 //},
683 .WhileSimple => return renderWhile(ais, tree, tree.whileSimple(node), space),
684 .WhileCont => return renderWhile(ais, tree, tree.whileCont(node), space),
685 .While => return renderWhile(ais, tree, tree.whileFull(node), space),
753686
754687 .ForSimple => unreachable, // TODO
755688 .For => unreachable, // TODO
......@@ -1092,105 +1025,142 @@ fn renderVarDecl(ais: *Ais, tree: ast.Tree, var_decl: ast.full.VarDecl) Error!vo
10921025}
10931026
10941027fn 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 {
10951047 const node_tags = tree.nodes.items(.tag);
10961048 const token_tags = tree.tokens.items(.tag);
10971049
1098 try renderToken(ais, tree, if_node.ast.if_token, .Space); // if
1050 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); // (
1103 try renderExpression(ais, tree, if_node.ast.cond_expr, .None); // condition
1059 try renderToken(ais, tree, while_node.ast.while_token, .Space); // if
1060 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]) {
1106 .If, .IfSimple => {
1107 try renderExtraNewline(ais, tree, if_node.ast.then_expr);
1108 },
1109 .Block, .For, .ForSimple, .While, .WhileSimple, .Switch => {
1110 if (if_node.payload_token) |payload_token| {
1111 try renderToken(ais, tree, payload_token - 2, .Space); // )
1112 try renderToken(ais, tree, payload_token - 1, .None); // |
1113 if (token_tags[payload_token] == .Asterisk) {
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 }
1063 if (nodeIsBlock(node_tags[while_node.ast.then_expr])) {
1064 const payload_space: Space = if (while_node.ast.cont_expr != 0) .Space else .BlockStart;
1065 if (while_node.payload_token) |payload_token| {
1066 try renderToken(ais, tree, payload_token - 2, .Space); // )
1067 try renderToken(ais, tree, payload_token - 1, .None); // |
1068 if (token_tags[payload_token] == .Asterisk) {
1069 try renderToken(ais, tree, payload_token, .None); // *
1070 try renderToken(ais, tree, payload_token + 1, .None); // identifier
1071 try renderToken(ais, tree, payload_token + 2, payload_space); // |
11211072 } else {
1122 const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;
1123 try renderToken(ais, tree, rparen, .BlockStart); // )
1073 try renderToken(ais, tree, payload_token, .None); // identifier
1074 try renderToken(ais, tree, payload_token + 1, payload_space); // |
11241075 }
1125 if (if_node.ast.else_expr != 0) {
1126 try renderExpression(ais, tree, if_node.ast.then_expr, Space.Space);
1127 try renderToken(ais, tree, if_node.else_token, .Space); // else
1128 if (if_node.error_token) |error_token| {
1129 try renderToken(ais, tree, error_token - 1, .None); // |
1130 try renderToken(ais, tree, error_token, .None); // identifier
1131 try renderToken(ais, tree, error_token + 1, .Space); // |
1132 }
1133 return renderExpression(ais, tree, if_node.ast.else_expr, space);
1134 } else {
1135 return renderExpression(ais, tree, if_node.ast.then_expr, space);
1076 } else {
1077 const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
1078 try renderToken(ais, tree, rparen, payload_space); // )
1079 }
1080 if (while_node.ast.cont_expr != 0) {
1081 const rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
1082 const lparen = tree.firstToken(while_node.ast.cont_expr) - 1;
1083 try renderToken(ais, tree, lparen - 1, .Space); // :
1084 try renderToken(ais, tree, lparen, .None); // lparen
1085 try renderExpression(ais, tree, while_node.ast.cont_expr, .None);
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); // |
11361095 }
1137 },
1138 else => {},
1096 return renderExpression(ais, tree, while_node.ast.else_expr, space);
1097 } else {
1098 return renderExpression(ais, tree, while_node.ast.then_expr, space);
1099 }
11391100 }
11401101
1141 const rparen = tree.lastToken(if_node.ast.cond_expr) + 1;
1142 const last_then_token = tree.lastToken(if_node.ast.then_expr);
1102 const rparen = tree.lastToken(while_node.ast.cond_expr) + 1;
1103 const last_then_token = tree.lastToken(while_node.ast.then_expr);
11431104 const src_has_newline = !tree.tokensOnSameLine(rparen, last_then_token);
11441105
11451106 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| {
11471109 try renderToken(ais, tree, payload_token - 2, .Space); // )
11481110 try renderToken(ais, tree, payload_token - 1, .None); // |
11491111 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); // |
11511113 } else {
11521114 ais.pushIndent();
1153 try renderToken(ais, tree, rparen, .Newline); // )
1115 try renderToken(ais, tree, rparen, payload_space); // )
11541116 ais.popIndent();
11551117 }
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) {
11571127 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);
11591129 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]);
11611131 if (else_is_block) {
1162 try renderToken(ais, tree, if_node.else_token, .Space); // else
1163 if (if_node.error_token) |error_token| {
1132 try renderToken(ais, tree, while_node.else_token, .Space); // else
1133 if (while_node.error_token) |error_token| {
11641134 try renderToken(ais, tree, error_token - 1, .None); // |
11651135 try renderToken(ais, tree, error_token, .None); // identifier
11661136 try renderToken(ais, tree, error_token + 1, .Space); // |
11671137 }
1168 return renderExpression(ais, tree, if_node.ast.else_expr, space);
1138 return renderExpression(ais, tree, while_node.ast.else_expr, space);
11691139 } else {
1170 if (if_node.error_token) |error_token| {
1171 try renderToken(ais, tree, if_node.else_token, .Space); // else
1140 if (while_node.error_token) |error_token| {
1141 try renderToken(ais, tree, while_node.else_token, .Space); // else
11721142 try renderToken(ais, tree, error_token - 1, .None); // |
11731143 try renderToken(ais, tree, error_token, .None); // identifier
11741144 try renderToken(ais, tree, error_token + 1, .Space); // |
11751145 } else {
1176 try renderToken(ais, tree, if_node.else_token, .Newline); // else
1146 try renderToken(ais, tree, while_node.else_token, .Newline); // else
11771147 }
11781148 ais.pushIndent();
1179 try renderExpression(ais, tree, if_node.ast.else_expr, space);
1149 try renderExpression(ais, tree, while_node.ast.else_expr, space);
11801150 ais.popIndent();
11811151 return;
11821152 }
11831153 } else {
11841154 ais.pushIndent();
1185 try renderExpression(ais, tree, if_node.ast.then_expr, space);
1155 try renderExpression(ais, tree, while_node.ast.then_expr, space);
11861156 ais.popIndent();
11871157 return;
11881158 }
11891159 }
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| {
11941164 assert(payload_token - 2 == rparen);
11951165 try renderToken(ais, tree, payload_token - 2, .Space); // )
11961166 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
12061176 try renderToken(ais, tree, rparen, .Space); // )
12071177 }
12081178
1209 if (if_node.ast.else_expr != 0) {
1210 try renderExpression(ais, tree, if_node.ast.then_expr, .Space);
1211 try renderToken(ais, tree, if_node.else_token, .Space); // else
1179 if (while_node.ast.cont_expr != 0) {
1180 const cont_rparen = tree.lastToken(while_node.ast.cont_expr) + 1;
1181 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| {
12141193 try renderToken(ais, tree, error_token - 1, .None); // |
12151194 try renderToken(ais, tree, error_token, .None); // identifier
12161195 try renderToken(ais, tree, error_token + 1, .Space); // |
12171196 }
12181197
1219 return renderExpression(ais, tree, if_node.ast.else_expr, space);
1198 return renderExpression(ais, tree, while_node.ast.else_expr, space);
12201199 } else {
1221 return renderExpression(ais, tree, if_node.ast.then_expr, space);
1200 return renderExpression(ais, tree, while_node.ast.then_expr, space);
12221201 }
12231202}
12241203
......@@ -2079,12 +2058,16 @@ fn renderDocComments(ais: *Ais, tree: ast.Tree, end_token: ast.TokenIndex) Error
20792058fn nodeIsBlock(tag: ast.Node.Tag) bool {
20802059 return switch (tag) {
20812060 .Block,
2061 .BlockSemicolon,
2062 .BlockTwo,
2063 .BlockTwoSemicolon,
20822064 .If,
20832065 .IfSimple,
20842066 .For,
20852067 .ForSimple,
20862068 .While,
20872069 .WhileSimple,
2070 .WhileCont,
20882071 .Switch,
20892072 => true,
20902073 else => false,