From 335a78f8f5ef8b86922dc241422acb033e0b3b2a Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Sun, 15 Sep 2024 20:14:49 +0200 Subject: [PATCH 1/7] 108: Add a exercise for a labeled switch --- build.zig | 6 ++++++ exercises/108_labeled_switch.zig | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 exercises/108_labeled_switch.zig diff --git a/build.zig b/build.zig index 0ddc23f..06d6483 100644 --- a/build.zig +++ b/build.zig @@ -1197,6 +1197,12 @@ const exercises = [_]Exercise{ \\Successfully Read 18 bytes: It's zigling time! , }, + .{ + .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..623e359 --- /dev/null +++ b/exercises/108_labeled_switch.zig @@ -0,0 +1,34 @@ +// +// A labeled switch in zig allows the usage of continue and break +// just like loops, these allow you to create very concise +// Finite State Automata to represent state transitions +// +// foo: switch (state) { +// 1 => continue :foo 2, +// 2 => continue :foo 3, +// 3 => return, +// 4 => {}, +// ... +// } +// +const std = @import("std"); + +const PullRequestState = enum { + Draft, + InReview, + Approved, + Rejected, + Merged, +}; + +pub fn main() void { + // Something is wrong, it seems your Pull Request can never be merged + // try to 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", .{}), + PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), + } +} From 580e126266b2ccef8f73c1b5aa49f2983339641b Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Sun, 15 Sep 2024 20:16:57 +0200 Subject: [PATCH 2/7] Add .patch for 108_labeled_switch --- patches/patches/108_labeled_switch.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 patches/patches/108_labeled_switch.patch diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch new file mode 100644 index 0000000..dfb65dd --- /dev/null +++ b/patches/patches/108_labeled_switch.patch @@ -0,0 +1,11 @@ +--- a/exercises/108_labeled_switch.zig ++++ b/exercises/108_labeled_switch.zig +@@ -26,7 +26,7 @@ pub fn main() void { + // try to 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", .{}), + PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), From 798bb403963f15028db7d0325d93ab1af6dde684 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:34:35 +0200 Subject: [PATCH 3/7] update zig version in build and readme --- README.md | 5 +++-- build.zig | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d33754c..6d15f9f 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.1575 +* *2024-09-16* zig 0.14.0-dev.1575 - 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 06d6483..dbd08d5 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.1575"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From db569a1478d11c1014ce9569ad65fc5cea9a09c9 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:38:43 +0200 Subject: [PATCH 4/7] update labeled switch to also have a break statement --- exercises/108_labeled_switch.zig | 16 ++++++++++------ patches/patches/108_labeled_switch.patch | 15 +++++++++++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 623e359..dfc061a 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -6,14 +6,14 @@ // foo: switch (state) { // 1 => continue :foo 2, // 2 => continue :foo 3, -// 3 => return, +// 3 => break :foo, // 4 => {}, // ... // } // const std = @import("std"); -const PullRequestState = enum { +const PullRequestState = enum(u8) { Draft, InReview, Approved, @@ -22,13 +22,17 @@ const PullRequestState = enum { }; pub fn main() void { - // Something is wrong, it seems your Pull Request can never be merged - // try to fix it! + // 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", .{}), - PullRequestState.Merged => std.debug.print("The pull request has been 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 index dfb65dd..230b8fb 100644 --- a/patches/patches/108_labeled_switch.patch +++ b/patches/patches/108_labeled_switch.patch @@ -1,11 +1,18 @@ --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig -@@ -26,7 +26,7 @@ pub fn main() void { - // try to fix it! +@@ -26,13 +26,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", .{}), - PullRequestState.Merged => std.debug.print("The pull request has been 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", .{}); + } From d9ce18631d160a011a64bbdea19b64a2fd65a523 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:44:36 +0200 Subject: [PATCH 5/7] downgrade zig version to eowyn version It is just 2 days behind so all features are already present for the new labeled switch test --- README.md | 4 ++-- build.zig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6d15f9f..eb3036a 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.1575 -* *2024-09-16* zig 0.14.0-dev.1575 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) +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) diff --git a/build.zig b/build.zig index dbd08d5..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.1575"; + 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) { From ed1a20d51b4d319a32adb7d1552f7316599c3d60 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:26:33 +0200 Subject: [PATCH 6/7] improve explanantions in labeled switch --- exercises/108_labeled_switch.zig | 59 ++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index dfc061a..0748d9d 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -1,15 +1,54 @@ // -// A labeled switch in zig allows the usage of continue and break -// just like loops, these allow you to create very concise -// Finite State Automata to represent state transitions +// 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. // -// foo: switch (state) { -// 1 => continue :foo 2, -// 2 => continue :foo 3, -// 3 => break :foo, -// 4 => {}, -// ... -// } +// 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"); From f0c2c56087bfd4398b896d3a8304a90cddbb3583 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:29:08 +0200 Subject: [PATCH 7/7] update108 .patch due to line change --- patches/patches/108_labeled_switch.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch index 230b8fb..467540c 100644 --- a/patches/patches/108_labeled_switch.patch +++ b/patches/patches/108_labeled_switch.patch @@ -1,6 +1,6 @@ --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig -@@ -26,13 +26,13 @@ pub fn main() void { +@@ -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,