diff options
Diffstat (limited to 'lang/zig/switch.zig')
-rw-r--r-- | lang/zig/switch.zig | 86 |
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); +} |