| author | |
| committer | |
| log | d869133a9fb96fb27a07c1e42c12c5270eae5940 |
| tree | 6ea7c15c277ae03fa3d2c60a89a90288adce7532 |
| parent | 837cd748a8607a6ac9f1a5bfc6d625512bacb906 |
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 | }, |
| 408 | 408 | ||
| 409 | .SwitchCaseMulti => unreachable, // TODO | 409 | .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, // TODO | 422 | .WhileSimple => unreachable, // TODO |
| 411 | .WhileCont => unreachable, // TODO | 423 | .WhileCont => unreachable, // TODO |
| 412 | .While => unreachable, // TODO | 424 | .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, |
| 498 | 512 | ||
| 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 parameter | 547 | 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 parameter | 566 | 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 + rbrace | 574 | end_offset += 2; // for the comma + rbrace |
| ... | @@ -737,16 +763,13 @@ pub const Tree = struct { | ... | @@ -737,16 +763,13 @@ pub const Tree = struct { |
| 737 | 763 | ||
| 738 | .TaggedUnionEnumTag => unreachable, // TODO | 764 | .TaggedUnionEnumTag => unreachable, // TODO |
| 739 | .TaggedUnionEnumTagComma => unreachable, // TODO | 765 | .TaggedUnionEnumTagComma => unreachable, // TODO |
| 740 | .Switch => unreachable, // TODO | ||
| 741 | .If => unreachable, // TODO | 766 | .If => unreachable, // TODO |
| 742 | .Continue => unreachable, // TODO | 767 | .Continue => unreachable, // TODO |
| 743 | .AsmSimple => unreachable, // TODO | 768 | .AsmSimple => unreachable, // TODO |
| 744 | .Asm => unreachable, // TODO | 769 | .Asm => unreachable, // TODO |
| 745 | .SwitchCaseOne => unreachable, // TODO | ||
| 746 | .SwitchRange => unreachable, // TODO | 770 | .SwitchRange => unreachable, // TODO |
| 747 | .ArrayType => unreachable, // TODO | 771 | .ArrayType => unreachable, // TODO |
| 748 | .ArrayTypeSentinel => unreachable, // TODO | 772 | .ArrayTypeSentinel => unreachable, // TODO |
| 749 | .SwitchCaseMulti => unreachable, // TODO | ||
| 750 | .WhileCont => unreachable, // TODO | 773 | .WhileCont => unreachable, // TODO |
| 751 | .While => unreachable, // TODO | 774 | .While => unreachable, // TODO |
| 752 | .ForSimple => unreachable, // TODO | 775 | .ForSimple => unreachable, // TODO |
| ... | @@ -1202,7 +1225,8 @@ pub const Tree = struct { | ... | @@ -1202,7 +1225,8 @@ pub const Tree = struct { |
| 1202 | } | 1225 | } |
| 1203 | 1226 | ||
| 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 | } |
| 1215 | 1239 | ||
| 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 | } |
| 1234 | 1259 | ||
| 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 | } |
| 1246 | 1272 | ||
| 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 | } |
| 1259 | 1286 | ||
| 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 | }; |
| 1411 | 1469 | ||
| 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 | }; |
| 1556 | 1628 | ||
| 1557 | pub const Error = union(enum) { | 1629 | pub 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); |
| 2891 | 2892 | ||
| 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" { | 1675 | test "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" { | 2000 | test "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 | } |
| 2727 | 2727 | ||
| 2728 | //test "zig fmt: switch" { | 2728 | test "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 | }, |
| 224 | 223 | ||
| 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 | //}, | ||
| 693 | 617 | ||
| 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 | //}, |
| 734 | 658 | ||
| 735 | .Switch => unreachable, // TODO | 659 | .Switch, |
| 736 | //.Switch => { | 660 | .SwitchComma, |
| 737 | // const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); | 661 | => { |
| 738 | 662 | const switch_token = main_tokens[node]; | |
| 739 | // try renderToken(ais, tree, switch_node.switch_token, Space.Space); // switch | 663 | 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); |
| 741 | 665 | 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 | |
| 744 | 668 | 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); // lbrace | 672 | |
| 749 | // return renderToken(ais, tree, switch_node.rbrace, space); // rbrace | 673 | if (cases.len == 0) { |
| 750 | // } | 674 | try renderToken(ais, tree, rparen + 1, .None); // lbrace |
| 751 | 675 | 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 |
| 754 | 678 | 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); // lbrace | 682 | try renderExpression(ais, tree, case, .Comma); |
| 759 | 683 | } | |
| 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 | } |
| 763 | 687 | }, | |
| 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 | // } | ||
| 818 | 688 | ||
| 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), |
| 821 | 691 | ||
| 822 | .WhileSimple => unreachable, // TODO | 692 | .WhileSimple => unreachable, // TODO |
| 823 | .WhileCont => unreachable, // TODO | 693 | .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 | } |
| 1747 | 1617 | ||
| 1618 | fn 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 | |||
| 1748 | fn renderBlock( | 1665 | fn 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]; | ||
| 1758 | 1676 | ||
| 1759 | if (token_tags[lbrace - 1] == .Colon and | 1677 | 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 last | 1704 | |
| 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 | } |
| 1796 | 1707 | ||
| 1797 | // TODO: handle comments between fields | 1708 | // TODO: handle comments between fields |