authorgravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-02-08 13:38:24+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-08 15:41:31-08:00
logd869133a9fb96fb27a07c1e42c12c5270eae5940
tree6ea7c15c277ae03fa3d2c60a89a90288adce7532
parent837cd748a8607a6ac9f1a5bfc6d625512bacb906

zig fmt: implement switches


4 files changed, 249 insertions(+), 262 deletions(-)

lib/std/zig/ast.zig+88-13
...@@ -213,6 +213,7 @@ pub const Tree = struct {...@@ -213,6 +213,7 @@ pub const Tree = struct {
213 .Await,213 .Await,
214 .OptionalType,214 .OptionalType,
215 .Switch,215 .Switch,
216 .SwitchComma,
216 .IfSimple,217 .IfSimple,
217 .If,218 .If,
218 .Suspend,219 .Suspend,
...@@ -313,7 +314,6 @@ pub const Tree = struct {...@@ -313,7 +314,6 @@ pub const Tree = struct {
313 .StructInit,314 .StructInit,
314 .CallOne,315 .CallOne,
315 .Call,316 .Call,
316 .SwitchCaseOne,
317 .SwitchRange,317 .SwitchRange,
318 .FnDecl,318 .FnDecl,
319 .ErrorUnion,319 .ErrorUnion,
...@@ -406,7 +406,19 @@ pub const Tree = struct {...@@ -406,7 +406,19 @@ pub const Tree = struct {
406 };406 };
407 },407 },
408408
409 .SwitchCaseMulti => unreachable, // TODO409 .SwitchCaseOne => {
410 if (datas[n].lhs == 0) {
411 return main_tokens[n] - 1; // else token
412 } else {
413 n = datas[n].lhs;
414 }
415 },
416 .SwitchCase => {
417 const extra = tree.extraData(datas[n].lhs, Node.SubRange);
418 assert(extra.end - extra.start > 0);
419 n = extra.start;
420 },
421
410 .WhileSimple => unreachable, // TODO422 .WhileSimple => unreachable, // TODO
411 .WhileCont => unreachable, // TODO423 .WhileCont => unreachable, // TODO
412 .While => unreachable, // TODO424 .While => unreachable, // TODO
...@@ -494,6 +506,8 @@ pub const Tree = struct {...@@ -494,6 +506,8 @@ pub const Tree = struct {
494 .PtrTypeSentinel,506 .PtrTypeSentinel,
495 .PtrType,507 .PtrType,
496 .PtrTypeBitRange,508 .PtrTypeBitRange,
509 .SwitchCaseOne,
510 .SwitchCase,
497 => n = datas[n].rhs,511 => n = datas[n].rhs,
498512
499 .FieldAccess,513 .FieldAccess,
...@@ -532,6 +546,16 @@ pub const Tree = struct {...@@ -532,6 +546,16 @@ pub const Tree = struct {
532 }546 }
533 n = tree.extra_data[params.end - 1]; // last parameter547 n = tree.extra_data[params.end - 1]; // last parameter
534 },548 },
549 .Switch => {
550 const cases = tree.extraData(datas[n].rhs, Node.SubRange);
551 if (cases.end - cases.start == 0) {
552 end_offset += 3; // rparen, lbrace, rbrace
553 n = datas[n].lhs; // condition expression
554 } else {
555 end_offset += 1; // for the rbrace
556 n = tree.extra_data[cases.end - 1]; // last case
557 }
558 },
535 .ContainerDeclArg => {559 .ContainerDeclArg => {
536 const members = tree.extraData(datas[n].rhs, Node.SubRange);560 const members = tree.extraData(datas[n].rhs, Node.SubRange);
537 if (members.end - members.start == 0) {561 if (members.end - members.start == 0) {
...@@ -542,7 +566,9 @@ pub const Tree = struct {...@@ -542,7 +566,9 @@ pub const Tree = struct {
542 n = tree.extra_data[members.end - 1]; // last parameter566 n = tree.extra_data[members.end - 1]; // last parameter
543 }567 }
544 },568 },
545 .ContainerDeclArgComma => {569 .ContainerDeclArgComma,
570 .SwitchComma,
571 => {
546 const members = tree.extraData(datas[n].rhs, Node.SubRange);572 const members = tree.extraData(datas[n].rhs, Node.SubRange);
547 assert(members.end - members.start > 0);573 assert(members.end - members.start > 0);
548 end_offset += 2; // for the comma + rbrace574 end_offset += 2; // for the comma + rbrace
...@@ -737,16 +763,13 @@ pub const Tree = struct {...@@ -737,16 +763,13 @@ pub const Tree = struct {
737763
738 .TaggedUnionEnumTag => unreachable, // TODO764 .TaggedUnionEnumTag => unreachable, // TODO
739 .TaggedUnionEnumTagComma => unreachable, // TODO765 .TaggedUnionEnumTagComma => unreachable, // TODO
740 .Switch => unreachable, // TODO
741 .If => unreachable, // TODO766 .If => unreachable, // TODO
742 .Continue => unreachable, // TODO767 .Continue => unreachable, // TODO
743 .AsmSimple => unreachable, // TODO768 .AsmSimple => unreachable, // TODO
744 .Asm => unreachable, // TODO769 .Asm => unreachable, // TODO
745 .SwitchCaseOne => unreachable, // TODO
746 .SwitchRange => unreachable, // TODO770 .SwitchRange => unreachable, // TODO
747 .ArrayType => unreachable, // TODO771 .ArrayType => unreachable, // TODO
748 .ArrayTypeSentinel => unreachable, // TODO772 .ArrayTypeSentinel => unreachable, // TODO
749 .SwitchCaseMulti => unreachable, // TODO
750 .WhileCont => unreachable, // TODO773 .WhileCont => unreachable, // TODO
751 .While => unreachable, // TODO774 .While => unreachable, // TODO
752 .ForSimple => unreachable, // TODO775 .ForSimple => unreachable, // TODO
...@@ -1202,7 +1225,8 @@ pub const Tree = struct {...@@ -1202,7 +1225,8 @@ pub const Tree = struct {
1202 }1225 }
12031226
1204 pub fn containerDeclArg(tree: Tree, node: Node.Index) Full.ContainerDecl {1227 pub fn containerDeclArg(tree: Tree, node: Node.Index) Full.ContainerDecl {
1205 assert(tree.nodes.items(.tag)[node] == .ContainerDeclArg);1228 assert(tree.nodes.items(.tag)[node] == .ContainerDeclArg or
1229 tree.nodes.items(.tag)[node] == .ContainerDeclArgComma);
1206 const data = tree.nodes.items(.data)[node];1230 const data = tree.nodes.items(.data)[node];
1207 const members_range = tree.extraData(data.rhs, Node.SubRange);1231 const members_range = tree.extraData(data.rhs, Node.SubRange);
1208 return tree.fullContainerDecl(.{1232 return tree.fullContainerDecl(.{
...@@ -1214,7 +1238,8 @@ pub const Tree = struct {...@@ -1214,7 +1238,8 @@ pub const Tree = struct {
1214 }1238 }
12151239
1216 pub fn taggedUnionTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl {1240 pub fn taggedUnionTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl {
1217 assert(tree.nodes.items(.tag)[node] == .TaggedUnionTwo);1241 assert(tree.nodes.items(.tag)[node] == .TaggedUnionTwo or
1242 tree.nodes.items(.tag)[node] == .TaggedUnionTwoComma);
1218 const data = tree.nodes.items(.data)[node];1243 const data = tree.nodes.items(.data)[node];
1219 buffer.* = .{ data.lhs, data.rhs };1244 buffer.* = .{ data.lhs, data.rhs };
1220 const members = if (data.rhs != 0)1245 const members = if (data.rhs != 0)
...@@ -1233,7 +1258,8 @@ pub const Tree = struct {...@@ -1233,7 +1258,8 @@ pub const Tree = struct {
1233 }1258 }
12341259
1235 pub fn taggedUnion(tree: Tree, node: Node.Index) Full.ContainerDecl {1260 pub fn taggedUnion(tree: Tree, node: Node.Index) Full.ContainerDecl {
1236 assert(tree.nodes.items(.tag)[node] == .TaggedUnion);1261 assert(tree.nodes.items(.tag)[node] == .TaggedUnion or
1262 tree.nodes.items(.tag)[node] == .TaggedUnionComma);
1237 const data = tree.nodes.items(.data)[node];1263 const data = tree.nodes.items(.data)[node];
1238 const main_token = tree.nodes.items(.main_token)[node];1264 const main_token = tree.nodes.items(.main_token)[node];
1239 return tree.fullContainerDecl(.{1265 return tree.fullContainerDecl(.{
...@@ -1245,7 +1271,8 @@ pub const Tree = struct {...@@ -1245,7 +1271,8 @@ pub const Tree = struct {
1245 }1271 }
12461272
1247 pub fn taggedUnionEnumTag(tree: Tree, node: Node.Index) Full.ContainerDecl {1273 pub fn taggedUnionEnumTag(tree: Tree, node: Node.Index) Full.ContainerDecl {
1248 assert(tree.nodes.items(.tag)[node] == .TaggedUnionEnumTag);1274 assert(tree.nodes.items(.tag)[node] == .TaggedUnionEnumTag or
1275 tree.nodes.items(.tag)[node] == .TaggedUnionEnumTagComma);
1249 const data = tree.nodes.items(.data)[node];1276 const data = tree.nodes.items(.data)[node];
1250 const members_range = tree.extraData(data.rhs, Node.SubRange);1277 const members_range = tree.extraData(data.rhs, Node.SubRange);
1251 const main_token = tree.nodes.items(.main_token)[node];1278 const main_token = tree.nodes.items(.main_token)[node];
...@@ -1257,6 +1284,25 @@ pub const Tree = struct {...@@ -1257,6 +1284,25 @@ pub const Tree = struct {
1257 });1284 });
1258 }1285 }
12591286
1287 pub fn switchCaseOne(tree: Tree, node: Node.Index) Full.SwitchCase {
1288 const data = &tree.nodes.items(.data)[node];
1289 return tree.fullSwitchCase(.{
1290 .values = if (data.lhs == 0) &.{} else @ptrCast([*]Node.Index, &data.lhs)[0..1],
1291 .arrow_token = tree.nodes.items(.main_token)[node],
1292 .target_expr = data.rhs,
1293 });
1294 }
1295
1296 pub fn switchCase(tree: Tree, node: Node.Index) Full.SwitchCase {
1297 const data = tree.nodes.items(.data)[node];
1298 const extra = tree.extraData(data.lhs, Node.SubRange);
1299 return tree.fullSwitchCase(.{
1300 .values = tree.extra_data[extra.start..extra.end],
1301 .arrow_token = tree.nodes.items(.main_token)[node],
1302 .target_expr = data.rhs,
1303 });
1304 }
1305
1260 fn fullVarDecl(tree: Tree, info: Full.VarDecl.Ast) Full.VarDecl {1306 fn fullVarDecl(tree: Tree, info: Full.VarDecl.Ast) Full.VarDecl {
1261 const token_tags = tree.tokens.items(.tag);1307 const token_tags = tree.tokens.items(.tag);
1262 var result: Full.VarDecl = .{1308 var result: Full.VarDecl = .{
...@@ -1407,6 +1453,18 @@ pub const Tree = struct {...@@ -1407,6 +1453,18 @@ pub const Tree = struct {
1407 }1453 }
1408 return result;1454 return result;
1409 }1455 }
1456
1457 fn fullSwitchCase(tree: Tree, info: Full.SwitchCase.Ast) Full.SwitchCase {
1458 const token_tags = tree.tokens.items(.tag);
1459 var result: Full.SwitchCase = .{
1460 .ast = info,
1461 .payload_token = null,
1462 };
1463 if (token_tags[info.arrow_token + 1] == .Pipe) {
1464 result.payload_token = info.arrow_token + 2;
1465 }
1466 return result;
1467 }
1410};1468};
14111469
1412/// Fully assembled AST node information.1470/// Fully assembled AST node information.
...@@ -1552,6 +1610,20 @@ pub const Full = struct {...@@ -1552,6 +1610,20 @@ pub const Full = struct {
1552 arg: Node.Index,1610 arg: Node.Index,
1553 };1611 };
1554 };1612 };
1613
1614 pub const SwitchCase = struct {
1615 /// Points to the first token after the `|`. Will either be an identifier or
1616 /// a `*` (with an identifier immediately after it).
1617 payload_token: ?TokenIndex,
1618 ast: Ast,
1619
1620 pub const Ast = struct {
1621 /// If empty, this is an else case
1622 values: []const Node.Index,
1623 arrow_token: TokenIndex,
1624 target_expr: Node.Index,
1625 };
1626 };
1555};1627};
15561628
1557pub const Error = union(enum) {1629pub const Error = union(enum) {
...@@ -1996,13 +2068,16 @@ pub const Node = struct {...@@ -1996,13 +2068,16 @@ pub const Node = struct {
1996 /// `lhs(a, b, c)`. `sub_range_list[rhs]`.2068 /// `lhs(a, b, c)`. `sub_range_list[rhs]`.
1997 /// main_token is the `(`.2069 /// main_token is the `(`.
1998 Call,2070 Call,
1999 /// `switch(lhs) {}`. `sub_range_list[rhs]`.2071 /// `switch(lhs) {}`. `SubRange[rhs]`.
2000 Switch,2072 Switch,
2073 /// Same as Switch except there is known to be a trailing comma
2074 /// before the final rbrace
2075 SwitchComma,
2001 /// `lhs => rhs`. If lhs is omitted it means `else`.2076 /// `lhs => rhs`. If lhs is omitted it means `else`.
2002 /// main_token is the `=>`2077 /// main_token is the `=>`
2003 SwitchCaseOne,2078 SwitchCaseOne,
2004 /// `a, b, c => rhs`. `sub_range_list[lhs]`.2079 /// `a, b, c => rhs`. `SubRange[lhs]`.
2005 SwitchCaseMulti,2080 SwitchCase,
2006 /// `lhs...rhs`.2081 /// `lhs...rhs`.
2007 SwitchRange,2082 SwitchRange,
2008 /// `while (lhs) rhs`.2083 /// `while (lhs) rhs`.
lib/std/zig/parse.zig+3-2
...@@ -2887,10 +2887,11 @@ const Parser = struct {...@@ -2887,10 +2887,11 @@ const Parser = struct {
2887 _ = try p.expectToken(.RParen);2887 _ = try p.expectToken(.RParen);
2888 _ = try p.expectToken(.LBrace);2888 _ = try p.expectToken(.LBrace);
2889 const cases = try p.parseSwitchProngList();2889 const cases = try p.parseSwitchProngList();
2890 const trailing_comma = p.token_tags[p.tok_i - 1] == .Comma;
2890 _ = try p.expectToken(.RBrace);2891 _ = try p.expectToken(.RBrace);
28912892
2892 return p.addNode(.{2893 return p.addNode(.{
2893 .tag = .Switch,2894 .tag = if (trailing_comma) .SwitchComma else .Switch,
2894 .main_token = switch_token,2895 .main_token = switch_token,
2895 .data = .{2896 .data = .{
2896 .lhs = expr_node,2897 .lhs = expr_node,
...@@ -3208,7 +3209,7 @@ const Parser = struct {...@@ -3208,7 +3209,7 @@ const Parser = struct {
3208 const arrow_token = try p.expectToken(.EqualAngleBracketRight);3209 const arrow_token = try p.expectToken(.EqualAngleBracketRight);
3209 _ = try p.parsePtrPayload();3210 _ = try p.parsePtrPayload();
3210 return p.addNode(.{3211 return p.addNode(.{
3211 .tag = .SwitchCaseMulti,3212 .tag = .SwitchCase,
3212 .main_token = arrow_token,3213 .main_token = arrow_token,
3213 .data = .{3214 .data = .{
3214 .lhs = try p.addExtra(Node.SubRange{3215 .lhs = try p.addExtra(Node.SubRange{
lib/std/zig/parser_test.zig+72-72
...@@ -1671,32 +1671,32 @@ test "zig fmt: block in slice expression" {...@@ -1671,32 +1671,32 @@ test "zig fmt: block in slice expression" {
1671// \\1671// \\
1672// );1672// );
1673//}1673//}
1674//1674
1675//test "zig fmt: switch cases trailing comma" {1675test "zig fmt: switch cases trailing comma" {
1676// try testTransform(1676 try testTransform(
1677// \\fn switch_cases(x: i32) void {1677 \\test "switch cases trailing comma"{
1678// \\ switch (x) {1678 \\ switch (x) {
1679// \\ 1,2,3 => {},1679 \\ 1,2,3 => {},
1680// \\ 4,5, => {},1680 \\ 4,5, => {},
1681// \\ 6... 8, => {},1681 \\ 6... 8, => {},
1682// \\ else => {},1682 \\ else => {},
1683// \\ }1683 \\ }
1684// \\}1684 \\}
1685// ,1685 ,
1686// \\fn switch_cases(x: i32) void {1686 \\test "switch cases trailing comma" {
1687// \\ switch (x) {1687 \\ switch (x) {
1688// \\ 1, 2, 3 => {},1688 \\ 1, 2, 3 => {},
1689// \\ 4,1689 \\ 4,
1690// \\ 5,1690 \\ 5,
1691// \\ => {},1691 \\ => {},
1692// \\ 6...8 => {},1692 \\ 6...8 => {},
1693// \\ else => {},1693 \\ else => {},
1694// \\ }1694 \\ }
1695// \\}1695 \\}
1696// \\1696 \\
1697// );1697 );
1698//}1698}
1699//1699
1700//test "zig fmt: slice align" {1700//test "zig fmt: slice align" {
1701// try testCanonical(1701// try testCanonical(
1702// \\const A = struct {1702// \\const A = struct {
...@@ -1996,16 +1996,16 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {...@@ -1996,16 +1996,16 @@ test "zig fmt: ptr deref operator and unwrap optional operator" {
1996// \\1996// \\
1997// );1997// );
1998//}1998//}
1999//1999
2000//test "zig fmt: switch with empty body" {2000test "zig fmt: switch with empty body" {
2001// try testCanonical(2001 try testCanonical(
2002// \\test "" {2002 \\test "" {
2003// \\ foo() catch |err| switch (err) {};2003 \\ foo() catch |err| switch (err) {};
2004// \\}2004 \\}
2005// \\2005 \\
2006// );2006 );
2007//}2007}
2008//2008
2009//test "zig fmt: line comments in struct initializer" {2009//test "zig fmt: line comments in struct initializer" {
2010// try testCanonical(2010// try testCanonical(
2011// \\fn foo() void {2011// \\fn foo() void {
...@@ -2725,42 +2725,42 @@ test "zig fmt: blocks" {...@@ -2725,42 +2725,42 @@ test "zig fmt: blocks" {
2725 );2725 );
2726}2726}
27272727
2728//test "zig fmt: switch" {2728test "zig fmt: switch" {
2729// try testCanonical(2729 try testCanonical(
2730// \\test "switch" {2730 \\test "switch" {
2731// \\ switch (0) {2731 \\ switch (0) {
2732// \\ 0 => {},2732 \\ 0 => {},
2733// \\ 1 => unreachable,2733 \\ 1 => unreachable,
2734// \\ 2, 3 => {},2734 \\ 2, 3 => {},
2735// \\ 4...7 => {},2735 \\ 4...7 => {},
2736// \\ 1 + 4 * 3 + 22 => {},2736 \\ 1 + 4 * 3 + 22 => {},
2737// \\ else => {2737 \\ else => {
2738// \\ const a = 1;2738 \\ const a = 1;
2739// \\ const b = a;2739 \\ const b = a;
2740// \\ },2740 \\ },
2741// \\ }2741 \\ }
2742// \\2742 \\
2743// \\ const res = switch (0) {2743 \\ const res = switch (0) {
2744// \\ 0 => 0,2744 \\ 0 => 0,
2745// \\ 1 => 2,2745 \\ 1 => 2,
2746// \\ 1 => a = 4,2746 \\ 1 => a = 4,
2747// \\ else => 4,2747 \\ else => 4,
2748// \\ };2748 \\ };
2749// \\2749 \\
2750// \\ const Union = union(enum) {2750 \\ const Union = union(enum) {
2751// \\ Int: i64,2751 \\ Int: i64,
2752// \\ Float: f64,2752 \\ Float: f64,
2753// \\ };2753 \\ };
2754// \\2754 \\
2755// \\ switch (u) {2755 \\ switch (u) {
2756// \\ Union.Int => |int| {},2756 \\ Union.Int => |int| {},
2757// \\ Union.Float => |*float| unreachable,2757 \\ Union.Float => |*float| unreachable,
2758// \\ }2758 \\ }
2759// \\}2759 \\}
2760// \\2760 \\
2761// );2761 );
2762//}2762}
2763//2763
2764//test "zig fmt: while" {2764//test "zig fmt: while" {
2765// try testCanonical(2765// try testCanonical(
2766// \\test "while" {2766// \\test "while" {
lib/std/zig/render.zig+86-175
...@@ -207,19 +207,18 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -207,19 +207,18 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
207 => {207 => {
208 const statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs };208 const statements = [2]ast.Node.Index{ datas[node].lhs, datas[node].rhs };
209 if (datas[node].lhs == 0) {209 if (datas[node].lhs == 0) {
210 return renderBlock(ais, tree, main_tokens[node], statements[0..0], space);210 return renderBlock(ais, tree, node, statements[0..0], space);
211 } else if (datas[node].rhs == 0) {211 } else if (datas[node].rhs == 0) {
212 return renderBlock(ais, tree, main_tokens[node], statements[0..1], space);212 return renderBlock(ais, tree, node, statements[0..1], space);
213 } else {213 } else {
214 return renderBlock(ais, tree, main_tokens[node], statements[0..2], space);214 return renderBlock(ais, tree, node, statements[0..2], space);
215 }215 }
216 },216 },
217 .Block,217 .Block,
218 .BlockSemicolon,218 .BlockSemicolon,
219 => {219 => {
220 const lbrace = main_tokens[node];
221 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];220 const statements = tree.extra_data[datas[node].lhs..datas[node].rhs];
222 return renderBlock(ais, tree, main_tokens[node], statements, space);221 return renderBlock(ais, tree, node, statements, space);
223 },222 },
224223
225 .ErrDefer => {224 .ErrDefer => {
...@@ -615,81 +614,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -615,81 +614,6 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
615 try renderToken(ais, tree, rbrace, space);614 try renderToken(ais, tree, rbrace, space);
616 }615 }
617 },616 },
618 //.ErrorSetDecl => {
619 // const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
620
621 // const lbrace = tree.nextToken(err_set_decl.error_token);
622
623 // if (err_set_decl.decls_len == 0) {
624 // try renderToken(ais, tree, err_set_decl.error_token, Space.None);
625 // try renderToken(ais, tree, lbrace, Space.None);
626 // return renderToken(ais, tree, err_set_decl.rbrace_token, space);
627 // }
628
629 // if (err_set_decl.decls_len == 1) blk: {
630 // const node = err_set_decl.decls()[0];
631
632 // // if there are any doc comments or same line comments
633 // // don't try to put it all on one line
634 // if (node.cast(ast.Node.ErrorTag)) |tag| {
635 // if (tag.doc_comments != null) break :blk;
636 // } else {
637 // break :blk;
638 // }
639
640 // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
641 // try renderToken(ais, tree, lbrace, Space.None); // lbrace
642 // try renderExpression(ais, tree, node, Space.None);
643 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
644 // }
645
646 // try renderToken(ais, tree, err_set_decl.error_token, Space.None); // error
647
648 // const src_has_trailing_comma = blk: {
649 // const maybe_comma = tree.prevToken(err_set_decl.rbrace_token);
650 // break :blk tree.token_tags[maybe_comma] == .Comma;
651 // };
652
653 // if (src_has_trailing_comma) {
654 // {
655 // ais.pushIndent();
656 // defer ais.popIndent();
657
658 // try renderToken(ais, tree, lbrace, Space.Newline); // lbrace
659 // const decls = err_set_decl.decls();
660 // for (decls) |node, i| {
661 // if (i + 1 < decls.len) {
662 // try renderExpression(ais, tree, node, Space.None);
663 // try renderToken(ais, tree, tree.nextToken(node.lastToken()), Space.Newline); // ,
664
665 // try renderExtraNewline(ais, tree, decls[i + 1]);
666 // } else {
667 // try renderExpression(ais, tree, node, Space.Comma);
668 // }
669 // }
670 // }
671
672 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
673 // } else {
674 // try renderToken(ais, tree, lbrace, Space.Space); // lbrace
675
676 // const decls = err_set_decl.decls();
677 // for (decls) |node, i| {
678 // if (i + 1 < decls.len) {
679 // try renderExpression(ais, tree, node, Space.None);
680
681 // const comma_token = tree.nextToken(node.lastToken());
682 // assert(tree.token_tags[comma_token] == .Comma);
683 // try renderToken(ais, tree, comma_token, Space.Space); // ,
684 // try renderExtraNewline(ais, tree, decls[i + 1]);
685 // } else {
686 // try renderExpression(ais, tree, node, Space.Space);
687 // }
688 // }
689
690 // return renderToken(ais, tree, err_set_decl.rbrace_token, space); // rbrace
691 // }
692 //},
693617
694 .BuiltinCallTwo, .BuiltinCallTwoComma => {618 .BuiltinCallTwo, .BuiltinCallTwoComma => {
695 if (datas[node].lhs == 0) {619 if (datas[node].lhs == 0) {
...@@ -732,92 +656,38 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac...@@ -732,92 +656,38 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
732 // }656 // }
733 //},657 //},
734658
735 .Switch => unreachable, // TODO659 .Switch,
736 //.Switch => {660 .SwitchComma,
737 // const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);661 => {
738662 const switch_token = main_tokens[node];
739 // try renderToken(ais, tree, switch_node.switch_token, Space.Space); // switch663 const condition = datas[node].lhs;
740 // try renderToken(ais, tree, tree.nextToken(switch_node.switch_token), Space.None); // (664 const extra = tree.extraData(datas[node].rhs, ast.Node.SubRange);
741665 const cases = tree.extra_data[extra.start..extra.end];
742 // const rparen = tree.nextToken(switch_node.expr.lastToken());666 const rparen = tree.lastToken(condition) + 1;
743 // const lbrace = tree.nextToken(rparen);667
744668 try renderToken(ais, tree, switch_token, .Space); // switch keyword
745 // if (switch_node.cases_len == 0) {669 try renderToken(ais, tree, switch_token + 1, .None); // lparen
746 // try renderExpression(ais, tree, switch_node.expr, Space.None);670 try renderExpression(ais, tree, condition, .None); // condtion expression
747 // try renderToken(ais, tree, rparen, Space.Space); // )671 try renderToken(ais, tree, rparen, .Space); // rparen
748 // try renderToken(ais, tree, lbrace, Space.None); // lbrace672
749 // return renderToken(ais, tree, switch_node.rbrace, space); // rbrace673 if (cases.len == 0) {
750 // }674 try renderToken(ais, tree, rparen + 1, .None); // lbrace
751675 try renderToken(ais, tree, rparen + 2, space); // rbrace
752 // try renderExpression(ais, tree, switch_node.expr, Space.None);676 } else {
753 // try renderToken(ais, tree, rparen, Space.Space); // )677 try renderToken(ais, tree, rparen + 1, .Newline); // lbrace
754678 ais.pushIndent();
755 // {679 try renderExpression(ais, tree, cases[0], .Comma);
756 // ais.pushIndentNextLine();680 for (cases[1..]) |case| {
757 // defer ais.popIndent();681 try renderExtraNewline(ais, tree, case);
758 // try renderToken(ais, tree, lbrace, Space.Newline); // lbrace682 try renderExpression(ais, tree, case, .Comma);
759683 }
760 // const cases = switch_node.cases();684 ais.popIndent();
761 // for (cases) |node, i| {685 try renderToken(ais, tree, tree.lastToken(node), space); // rbrace
762 // try renderExpression(ais, tree, node, Space.Comma);686 }
763687 },
764 // if (i + 1 < cases.len) {
765 // try renderExtraNewline(ais, tree, cases[i + 1]);
766 // }
767 // }
768 // }
769
770 // return renderToken(ais, tree, switch_node.rbrace, space); // rbrace
771 //},
772
773 .SwitchCaseOne => unreachable, // TODO
774 .SwitchCaseMulti => unreachable, // TODO
775 //.SwitchCase => {
776 // const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
777
778 // assert(switch_case.items_len != 0);
779 // const src_has_trailing_comma = blk: {
780 // const last_node = switch_case.items()[switch_case.items_len - 1];
781 // const maybe_comma = tree.nextToken(last_node.lastToken());
782 // break :blk tree.token_tags[maybe_comma] == .Comma;
783 // };
784
785 // if (switch_case.items_len == 1 or !src_has_trailing_comma) {
786 // const items = switch_case.items();
787 // for (items) |node, i| {
788 // if (i + 1 < items.len) {
789 // try renderExpression(ais, tree, node, Space.None);
790
791 // const comma_token = tree.nextToken(node.lastToken());
792 // try renderToken(ais, tree, comma_token, Space.Space); // ,
793 // try renderExtraNewline(ais, tree, items[i + 1]);
794 // } else {
795 // try renderExpression(ais, tree, node, Space.Space);
796 // }
797 // }
798 // } else {
799 // const items = switch_case.items();
800 // for (items) |node, i| {
801 // if (i + 1 < items.len) {
802 // try renderExpression(ais, tree, node, Space.None);
803
804 // const comma_token = tree.nextToken(node.lastToken());
805 // try renderToken(ais, tree, comma_token, Space.Newline); // ,
806 // try renderExtraNewline(ais, tree, items[i + 1]);
807 // } else {
808 // try renderExpression(ais, tree, node, Space.Comma);
809 // }
810 // }
811 // }
812
813 // try renderToken(ais, tree, switch_case.arrow_token, Space.Space); // =>
814
815 // if (switch_case.payload) |payload| {
816 // try renderExpression(ais, tree, payload, Space.Space);
817 // }
818688
819 // return renderExpression(ais, tree, switch_case.expr, space);689 .SwitchCaseOne => try renderSwitchCase(ais, tree, tree.switchCaseOne(node), space),
820 //},690 .SwitchCase => try renderSwitchCase(ais, tree, tree.switchCase(node), space),
821691
822 .WhileSimple => unreachable, // TODO692 .WhileSimple => unreachable, // TODO
823 .WhileCont => unreachable, // TODO693 .WhileCont => unreachable, // TODO
...@@ -1745,16 +1615,64 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: S...@@ -1745,16 +1615,64 @@ fn renderFnProto(ais: *Ais, tree: ast.Tree, fn_proto: ast.Full.FnProto, space: S
1745 return renderExpression(ais, tree, fn_proto.ast.return_type, space);1615 return renderExpression(ais, tree, fn_proto.ast.return_type, space);
1746}1616}
17471617
1618fn renderSwitchCase(
1619 ais: *Ais,
1620 tree: ast.Tree,
1621 switch_case: ast.Full.SwitchCase,
1622 space: Space,
1623) Error!void {
1624 const token_tags = tree.tokens.items(.tag);
1625 const trailing_comma = token_tags[switch_case.ast.arrow_token - 1] == .Comma;
1626
1627 // Render everything before the arrow
1628 if (switch_case.ast.values.len == 0) {
1629 try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .Space); // else keyword
1630 } else if (switch_case.ast.values.len == 1) {
1631 // render on one line and drop the trailing comma if any
1632 try renderExpression(ais, tree, switch_case.ast.values[0], .Space);
1633 } else if (trailing_comma) {
1634 // Render each value on a new line
1635 try renderExpression(ais, tree, switch_case.ast.values[0], .Comma);
1636 for (switch_case.ast.values[1..]) |value_expr| {
1637 try renderExtraNewline(ais, tree, value_expr);
1638 try renderExpression(ais, tree, value_expr, .Comma);
1639 }
1640 } else {
1641 // Render on one line
1642 for (switch_case.ast.values) |value_expr| {
1643 try renderExpression(ais, tree, value_expr, .CommaSpace);
1644 }
1645 }
1646
1647 // Render the arrow and everything after it
1648 try renderToken(ais, tree, switch_case.ast.arrow_token, .Space);
1649
1650 if (switch_case.payload_token) |payload_token| {
1651 try renderToken(ais, tree, payload_token - 1, .None); // pipe
1652 if (token_tags[payload_token] == .Asterisk) {
1653 try renderToken(ais, tree, payload_token, .None); // asterisk
1654 try renderToken(ais, tree, payload_token + 1, .None); // identifier
1655 try renderToken(ais, tree, payload_token + 2, .Space); // pipe
1656 } else {
1657 try renderToken(ais, tree, payload_token, .None); // identifier
1658 try renderToken(ais, tree, payload_token + 1, .Space); // pipe
1659 }
1660 }
1661
1662 try renderExpression(ais, tree, switch_case.ast.target_expr, space);
1663}
1664
1748fn renderBlock(1665fn renderBlock(
1749 ais: *Ais,1666 ais: *Ais,
1750 tree: ast.Tree,1667 tree: ast.Tree,
1751 lbrace: ast.TokenIndex,1668 block_node: ast.Node.Index,
1752 statements: []const ast.Node.Index,1669 statements: []const ast.Node.Index,
1753 space: Space,1670 space: Space,
1754) Error!void {1671) Error!void {
1755 const token_tags = tree.tokens.items(.tag);1672 const token_tags = tree.tokens.items(.tag);
1756 const node_tags = tree.nodes.items(.tag);1673 const node_tags = tree.nodes.items(.tag);
1757 const nodes_data = tree.nodes.items(.data);1674 const nodes_data = tree.nodes.items(.data);
1675 const lbrace = tree.nodes.items(.main_token)[block_node];
17581676
1759 if (token_tags[lbrace - 1] == .Colon and1677 if (token_tags[lbrace - 1] == .Colon and
1760 token_tags[lbrace - 2] == .Identifier)1678 token_tags[lbrace - 2] == .Identifier)
...@@ -1783,15 +1701,8 @@ fn renderBlock(...@@ -1783,15 +1701,8 @@ fn renderBlock(
1783 }1701 }
1784 }1702 }
1785 ais.popIndent();1703 ais.popIndent();
1786 // The rbrace could be +1 or +2 from the last token of the last1704
1787 // statement in the block because lastToken() does not count semicolons.1705 try renderToken(ais, tree, tree.lastToken(block_node), space); // rbrace
1788 const maybe_rbrace = tree.lastToken(statements[statements.len - 1]) + 1;
1789 if (token_tags[maybe_rbrace] == .RBrace) {
1790 return renderToken(ais, tree, maybe_rbrace, space);
1791 } else {
1792 assert(token_tags[maybe_rbrace + 1] == .RBrace);
1793 return renderToken(ais, tree, maybe_rbrace + 1, space);
1794 }
1795}1706}
17961707
1797// TODO: handle comments between fields1708// TODO: handle comments between fields