about summary refs log tree commit diff
path: root/lang/zig/switch.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lang/zig/switch.zig')
-rw-r--r--lang/zig/switch.zig86
1 files changed, 86 insertions, 0 deletions
diff --git a/lang/zig/switch.zig b/lang/zig/switch.zig
new file mode 100644
index 0000000..7fd3da5
--- /dev/null
+++ b/lang/zig/switch.zig
@@ -0,0 +1,86 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const os = std.Target.current.os.tag;
+
+test "switch simple" {
+    const a: u64 = 10;
+    const zz: u64 = 103;
+
+    // All branches of a switch expression must be able to be coerced
+    // to a common type.  Branches cannot fallthrough. If fallthrough behavior
+    // is desired, combine the cases and use an if.
+    const b = switch (a) {
+        // Multiple cases can be combined via a ','
+        1, 2, 3 => 0,
+
+        // Ranges can be specified using the ... syntax.
+        // These are inclusive both ends.
+        5...100 => 1,
+
+        // Branches can be arbitrarily complex.
+        101 => blk: {
+            const c: u64 = 5;
+            break :blk c * 2 + 1;
+        },
+
+        // Switching on arbitrary expressions is allowed as long as the
+        // expression is known at compile-time.
+        zz => zz,
+        blk: {
+            const d: u32 = 5;
+            const e: u32 = 100;
+            break :blk d + e;
+        } => 107,
+
+        // The else branch catches everything not already captured.
+        // Else branches are mandatory unless the entire range of values
+        // is handled.
+        else => 9,
+    };
+
+    expect(b == 1);
+}
+
+// Switch expressions can be used outside a function:
+const os_msg = switch (os) {
+    .linux => "we found a linux user",
+    else => "not a linux user",
+};
+
+// Inside a function, switch statements implicitly are compile-time
+// evaluated if the target expression is compile-time known.
+test "switch inside function" {
+    switch (os) {
+        // On an OS other than fuchsia, block is not even analyzed,
+        // so this compile error is not triggered.
+        // On fuchsia this compile error would be triggered.
+        .fuchsia => @compileError("fuchsia not supported"),
+        else => {},
+    }
+}
+
+test "switch on tagged union" {
+    const Point = struct { x: u8, y: u8 };
+    const Item = union(enum) { a: u32, c: Point, d, e: u32 };
+    var a = Item{ .c = Point{ .x = 1, .y = 2 } };
+
+    // Switching on more complex enums is allowed.
+    const b = switch (a) {
+        // A capture group is allowed on a match, and will return the enum
+        // value matched.  If the payload types of both cases are the same
+        // they can be put into the same switch prong.
+        Item.a, Item.e => |item| item,
+
+        // A reference to the matched value can be obtained using `*` syntax.
+        Item.c => |*item| blk: {
+            item.*.x += 1;
+            break :blk 6;
+        },
+
+        // No else is required if the types cases was exhaustively handled
+        Item.d => 8,
+    };
+
+    expect(b == 6);
+    expect(a.c.x == 2);
+}