Commit aaf13a2bb3

Isaac Freund <ifreund@ifreund.xyz>
2021-02-08 00:24:58
zig fmt: implement break
1 parent 57cec38
Changed files (3)
lib/std/zig/ast.zig
@@ -438,7 +438,6 @@ pub const Tree = struct {
             .OptionalType,
             .Suspend,
             .Resume,
-            .Break,
             .Nosuspend,
             .Comptime,
             => n = datas[n].lhs,
@@ -715,6 +714,16 @@ pub const Tree = struct {
                 n = extra.sentinel;
             },
 
+            .Break => {
+                if (datas[n].rhs != 0) {
+                    n = datas[n].rhs;
+                } else if (datas[n].lhs != 0) {
+                    return datas[n].lhs + end_offset;
+                } else {
+                    return main_tokens[n] + end_offset;
+                }
+            },
+
             // These are not supported by lastToken() because implementation would
             // require recursion due to the optional comma followed by rbrace.
             // TODO follow the pattern set by StructInitDotTwoComma which will allow
@@ -2023,7 +2032,8 @@ pub const Node = struct {
         Resume,
         /// `continue`. lhs is token index of label if any. rhs is unused.
         Continue,
-        /// `break rhs`. rhs can be omitted. lhs is label token index, if any.
+        /// `break :lhs rhs`
+        /// both lhs and rhs may be omitted.
         Break,
         /// `return lhs`. lhs can be omitted. rhs is unused.
         Return,
lib/std/zig/parser_test.zig
@@ -273,6 +273,24 @@ test "zig fmt: comptime struct field" {
     );
 }
 
+test "zig fmt: break from block" {
+    try testCanonical(
+        \\const a = blk: {
+        \\    break :blk 42;
+        \\};
+        \\const b = blk: {
+        \\    break :blk;
+        \\};
+        \\const c = {
+        \\    break 42;
+        \\};
+        \\const d = {
+        \\    break;
+        \\};
+        \\
+    );
+}
+
 //test "zig fmt: c pointer type" {
 //    try testCanonical(
 //        \\pub extern fn repro() [*c]const u8;
lib/std/zig/render.zig
@@ -487,28 +487,26 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
             return renderToken(ais, tree, datas[node].rhs, space);
         },
 
-        .Break => unreachable, // TODO
-        //.Break => {
-        //    const flow_expr = base.castTag(.Break).?;
-        //    const maybe_rhs = flow_expr.getRHS();
-        //    const maybe_label = flow_expr.getLabel();
-
-        //    if (maybe_label == null and maybe_rhs == null) {
-        //        return renderToken(ais, tree, flow_expr.ltoken, space); // break
-        //    }
-
-        //    try renderToken(ais, tree, flow_expr.ltoken, Space.Space); // break
-        //    if (maybe_label) |label| {
-        //        const colon = tree.nextToken(flow_expr.ltoken);
-        //        try renderToken(ais, tree, colon, Space.None); // :
-
-        //        if (maybe_rhs == null) {
-        //            return renderToken(ais, tree, label, space); // label
-        //        }
-        //        try renderToken(ais, tree, label, Space.Space); // label
-        //    }
-        //    return renderExpression(ais, tree, maybe_rhs.?, space);
-        //},
+        .Break => {
+            const main_token = main_tokens[node];
+            const label_token = datas[node].lhs;
+            const target = datas[node].rhs;
+            if (label_token == 0 and target == 0) {
+                try renderToken(ais, tree, main_token, space); // break keyword
+            } else if (label_token == 0 and target != 0) {
+                try renderToken(ais, tree, main_token, .Space); // break keyword
+                try renderExpression(ais, tree, target, space);
+            } else if (label_token != 0 and target == 0) {
+                try renderToken(ais, tree, main_token, .Space); // break keyword
+                try renderToken(ais, tree, label_token - 1, .None); // colon
+                try renderToken(ais, tree, label_token, space); // identifier
+            } else if (label_token != 0 and target != 0) {
+                try renderToken(ais, tree, main_token, .Space); // break keyword
+                try renderToken(ais, tree, label_token - 1, .None); // colon
+                try renderToken(ais, tree, label_token, .Space); // identifier
+                try renderExpression(ais, tree, target, space);
+            }
+        },
 
         .Continue => unreachable, // TODO
         //.Continue => {