summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--build.zig8
-rw-r--r--exercises/108_labeled_switch.zig77
-rw-r--r--patches/patches/108_labeled_switch.patch18
4 files changed, 105 insertions, 3 deletions
diff --git a/README.md b/README.md
index d33754c..eb3036a 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,8 @@ that if you update one, you may need to also update the other.
### Version Changes
-Version-0.14.0-dev.1224
+Version-0.14.0-dev.1573
+* *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257)
* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225)
* *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115)
* *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600)
@@ -229,7 +230,7 @@ Zig Core Language
* [X] Bit manipulation
* [X] Working with C
* [X] Threading
-* [ ] Labeled switch (#21257)
+* [x] Labeled switch
Zig Standard Library
diff --git a/build.zig b/build.zig
index 0ddc23f..8041e07 100644
--- a/build.zig
+++ b/build.zig
@@ -15,7 +15,7 @@ const print = std.debug.print;
// 1) Getting Started
// 2) Version Changes
comptime {
- const required_zig = "0.14.0-dev.1409";
+ const required_zig = "0.14.0-dev.1573";
const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
if (current_zig.order(min_zig) == .lt) {
@@ -1198,6 +1198,12 @@ const exercises = [_]Exercise{
,
},
.{
+ .main_file = "108_labeled_switch.zig",
+ .output =
+ \\The pull request has been merged
+ ,
+ },
+ .{
.main_file = "999_the_end.zig",
.output =
\\
diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig
new file mode 100644
index 0000000..0748d9d
--- /dev/null
+++ b/exercises/108_labeled_switch.zig
@@ -0,0 +1,77 @@
+//
+// You've heard of while loops in exercises 011,012,013 and 014
+// You've also heard of switch expressions in exercises 030 and 31.
+// You've also seen how labels can be used in exercise 063.
+//
+// By combining while loops and switch statements with continue and break statements
+// one can create very concise State Machines.
+//
+// One such example would be:
+//
+// pub fn main() void {
+// var op: u8 = 1;
+// while (true) {
+// switch (op) {
+// 1 => { op = 2; continue; },
+// 2 => { op = 3; continue; },
+// 3 => return,
+// 4 => {},
+// }
+// break;
+// }
+// std.debug.print("This statement cannot be reached");
+// }
+//
+// By combining all we've learned so far, we can now proceed with a labeled switch
+//
+// A labeled switch is some extra syntatic sugar, which comes with all sorts of
+// candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367
+//
+// Here is the previous excerpt implemented as a labeled switch instead:
+//
+// pub fn main() void {
+// foo: switch (@as(u8, 1)) {
+// 1 => continue :foo 2,
+// 2 => continue :foo 3,
+// 3 => return,
+// 4 => {},
+// }
+// std.debug.print("This statement cannot be reached");
+// }
+//
+// The flow of execution on this second case is:
+// 1. The switch starts with value '1';
+// 2. The switch evaluates to case '1' which in turn uses the continue statement
+// to re-evaluate the labeled switch again, now providing the value '2';
+// 3. In the case '2' we repeat the same pattern as case '1'
+// but instead the value to be evaluated is now '3';
+// 4. Finally we get to case '3', where we return from the function as a whole.
+//
+// Since step 4 or a break stament do not exist in this switch, the debug statement is
+// never executed
+//
+const std = @import("std");
+
+const PullRequestState = enum(u8) {
+ Draft,
+ InReview,
+ Approved,
+ Rejected,
+ Merged,
+};
+
+pub fn main() void {
+ // Oh no, your pull request keeps being rejected,
+ // how would you fix it?
+ pr: switch (@as(PullRequestState, PullRequestState.Draft)) {
+ PullRequestState.Draft => continue :pr PullRequestState.InReview,
+ PullRequestState.InReview => continue :pr PullRequestState.Rejected,
+ PullRequestState.Approved => continue :pr PullRequestState.Merged,
+ PullRequestState.Rejected => {
+ std.debug.print("The pull request has been rejected", .{});
+ return;
+ },
+ PullRequestState.Merged => break, // Would you know where to break to?
+ }
+ std.debug.print("The pull request has been merged", .{});
+}
diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch
new file mode 100644
index 0000000..467540c
--- /dev/null
+++ b/patches/patches/108_labeled_switch.patch
@@ -0,0 +1,18 @@
+--- a/exercises/108_labeled_switch.zig
++++ b/exercises/108_labeled_switch.zig
+@@ -65,13 +65,13 @@ pub fn main() void {
+ // how would you fix it?
+ pr: switch (@as(PullRequestState, PullRequestState.Draft)) {
+ PullRequestState.Draft => continue :pr PullRequestState.InReview,
+- PullRequestState.InReview => continue :pr PullRequestState.Rejected,
++ PullRequestState.InReview => continue :pr PullRequestState.Approved,
+ PullRequestState.Approved => continue :pr PullRequestState.Merged,
+ PullRequestState.Rejected => {
+ std.debug.print("The pull request has been rejected", .{});
+ return;
+ },
+- PullRequestState.Merged => break, // Would you know where to break to?
++ PullRequestState.Merged => break :pr, // Would you know where to break to?
+ }
+ std.debug.print("The pull request has been merged", .{});
+ }