Skip to content

Commit

Permalink
Add langref docs for labeled switch
Browse files Browse the repository at this point in the history
This feature was proposed in ziglang#8220, and implemented in ziglang#21257.
  • Loading branch information
LiterallyVoid committed Sep 11, 2024
1 parent 8ec68c6 commit dbc3a8f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 0 deletions.
13 changes: 13 additions & 0 deletions doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,19 @@ or

{#header_close#}

{#header_open|Labeled switch#}
<p>
When a {#syntax#}switch{#endsyntax#} statement is labeled, it can be referenced from a {#syntax#}continue{#endsyntax#} statement. The executed prong is specified by the value passed to the {#syntax#}continue{#endsyntax#} statement.
</p>
{#code|test_switch_continue.zig#}

<p>
The intent is to allow the CPU to create an independent branch-prediction cache for each prong, instead of a single branch prediction cache for the switch's entry point. This can improve performance.
</p>
{#code|test_switch_dispatch_loop.zig#}

{#header_close#}

{#header_open|Inline Switch Prongs#}
<p>
Switch prongs can be marked as {#syntax#}inline{#endsyntax#} to generate
Expand Down
22 changes: 22 additions & 0 deletions doc/langref/test_switch_continue.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const std = @import("std");
const expectEqual = std.testing.expectEqual;

test "switch continue" {
const value: i32 = 54;
const result = sw: switch (value) {
10...60 => |v| continue :sw v - 10,
4 => continue :sw 3,
3 => continue :sw 2,
2 => continue :sw 1,

// A switch statement can be targeted by a break, even if the switch and
// the break are unlabeled.
1 => break -6,

else => unreachable,
};

try expectEqual(-6, result);
}

// test
52 changes: 52 additions & 0 deletions doc/langref/test_switch_dispatch_loop.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const std = @import("std");
const expectEqual = std.testing.expectEqual;

const Instruction = enum {
mul,
add,
end,
};

test "switch dispatch loop" {
var stack = std.ArrayList(i32).init(std.testing.allocator);
defer stack.deinit();

try stack.append(5);
try stack.append(1);
try stack.append(-1);

const instructions: []const Instruction = &.{
.mul, .add, .end,
};

var ip: usize = 0;

const result = vm: switch (instructions[ip]) {
// Because this prong always `continue`s, it's not required to produce
// a result.
.add => {
const l = stack.pop();
const r = stack.pop();

try stack.append(l + r);

ip += 1;
continue :vm instructions[ip];
},
.mul => {
const l = stack.pop();
const r = stack.pop();

try stack.append(l * r);

ip += 1;
continue :vm instructions[ip];
},
.end => stack.pop(),
};

try expectEqual(4, result);
}

// test

0 comments on commit dbc3a8f

Please sign in to comment.