mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
If both are used, 'else' handles named members and '_' handles unnamed members. In this case the 'else' prong will be unrolled to an explicit case containing all remaining named values.
276 lines
8.6 KiB
Zig
276 lines
8.6 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
|
|
test "simple switch loop" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var start: u32 = undefined;
|
|
start = 32;
|
|
const result: u32 = s: switch (start) {
|
|
0 => 0,
|
|
1 => 1,
|
|
2 => 2,
|
|
3 => 3,
|
|
else => |x| continue :s x / 2,
|
|
};
|
|
try expect(result == 2);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop with ranges" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var start: u32 = undefined;
|
|
start = 32;
|
|
const result = s: switch (start) {
|
|
0...3 => |x| x,
|
|
else => |x| continue :s x / 2,
|
|
};
|
|
try expect(result == 2);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop on enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = enum { a, b, c };
|
|
|
|
fn doTheTest() !void {
|
|
var start: E = undefined;
|
|
start = .a;
|
|
const result: u32 = s: switch (start) {
|
|
.a => continue :s .b,
|
|
.b => continue :s .c,
|
|
.c => 123,
|
|
};
|
|
try expect(result == 123);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop with error set" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = error{ Foo, Bar, Baz };
|
|
|
|
fn doTheTest() !void {
|
|
var start: E = undefined;
|
|
start = error.Foo;
|
|
const result: u32 = s: switch (start) {
|
|
error.Foo => continue :s error.Bar,
|
|
error.Bar => continue :s error.Baz,
|
|
error.Baz => 123,
|
|
};
|
|
try expect(result == 123);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop on tagged union" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
const U = union(enum) {
|
|
a: u32,
|
|
b: f32,
|
|
c: f32,
|
|
};
|
|
|
|
fn doTheTest() !void {
|
|
var start: U = undefined;
|
|
start = .{ .a = 80 };
|
|
const result = s: switch (start) {
|
|
.a => |x| switch (x) {
|
|
0...49 => continue :s .{ .b = @floatFromInt(x) },
|
|
50 => continue :s .{ .c = @floatFromInt(x) },
|
|
else => continue :s .{ .a = x / 2 },
|
|
},
|
|
.b => |x| x,
|
|
.c => return error.TestFailed,
|
|
};
|
|
try expect(result == 40.0);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop dispatching instructions" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const Inst = union(enum) {
|
|
set: u32,
|
|
add: u32,
|
|
sub: u32,
|
|
end,
|
|
};
|
|
|
|
fn doTheTest() !void {
|
|
var insts: [5]Inst = undefined;
|
|
@memcpy(&insts, &[5]Inst{
|
|
.{ .set = 123 },
|
|
.{ .add = 100 },
|
|
.{ .sub = 50 },
|
|
.{ .sub = 10 },
|
|
.end,
|
|
});
|
|
var i: u32 = 0;
|
|
var cur: u32 = undefined;
|
|
eval: switch (insts[0]) {
|
|
.set => |x| {
|
|
cur = x;
|
|
i += 1;
|
|
continue :eval insts[i];
|
|
},
|
|
.add => |x| {
|
|
cur += x;
|
|
i += 1;
|
|
continue :eval insts[i];
|
|
},
|
|
.sub => |x| {
|
|
cur -= x;
|
|
i += 1;
|
|
continue :eval insts[i];
|
|
},
|
|
.end => {},
|
|
}
|
|
try expect(cur == 163);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch loop with pointer capture" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const U = union(enum) {
|
|
a: u32,
|
|
b: u32,
|
|
c: u32,
|
|
};
|
|
|
|
fn doTheTest() !void {
|
|
var a: U = .{ .a = 100 };
|
|
var b: U = .{ .b = 200 };
|
|
var c: U = .{ .c = 300 };
|
|
inc: switch (a) {
|
|
.a => |*x| {
|
|
x.* += 1;
|
|
continue :inc b;
|
|
},
|
|
.b => |*x| {
|
|
x.* += 10;
|
|
continue :inc c;
|
|
},
|
|
.c => |*x| {
|
|
x.* += 50;
|
|
},
|
|
}
|
|
try expect(a.a == 101);
|
|
try expect(b.b == 210);
|
|
try expect(c.c == 350);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "unanalyzed continue with operand" {
|
|
@setRuntimeSafety(false);
|
|
label: switch (false) {
|
|
false => if (false) continue :label true,
|
|
true => {},
|
|
}
|
|
}
|
|
|
|
test "switch loop on larger than pointer integer" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
|
|
|
var entry: @Type(.{ .int = .{
|
|
.signedness = .unsigned,
|
|
.bits = @bitSizeOf(usize) + 1,
|
|
} }) = undefined;
|
|
entry = 0;
|
|
loop: switch (entry) {
|
|
0 => {
|
|
entry += 1;
|
|
continue :loop 1;
|
|
},
|
|
1 => |x| {
|
|
entry += 1;
|
|
continue :loop x + 1;
|
|
},
|
|
2 => entry += 1,
|
|
else => unreachable,
|
|
}
|
|
try expect(entry == 3);
|
|
}
|
|
|
|
test "switch loop on non-exhaustive enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
const E = enum(u8) { a, b, c, _ };
|
|
|
|
fn doTheTest() !void {
|
|
var start: E = undefined;
|
|
start = .a;
|
|
const result: u32 = s: switch (start) {
|
|
.a => continue :s .c,
|
|
else => continue :s @enumFromInt(123),
|
|
.b, _ => |x| break :s @intFromEnum(x),
|
|
};
|
|
try expect(result == 123);
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|