aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.zig4
-rw-r--r--exercises/072_comptime7.zig66
-rw-r--r--patches/patches/072_comptime7.patch4
3 files changed, 74 insertions, 0 deletions
diff --git a/build.zig b/build.zig
index b4f0b29..22ee5d4 100644
--- a/build.zig
+++ b/build.zig
@@ -362,6 +362,10 @@ const exercises = [_]Exercise{
.main_file = "071_comptime6.zig",
.output = "Narcissus has room in his heart for: me myself.",
},
+ .{
+ .main_file = "072_comptime7.zig",
+ .output = "26",
+ },
};
/// Check the zig version to make sure it can compile the examples properly.
diff --git a/exercises/072_comptime7.zig b/exercises/072_comptime7.zig
new file mode 100644
index 0000000..c5e04dd
--- /dev/null
+++ b/exercises/072_comptime7.zig
@@ -0,0 +1,66 @@
+//
+// There is also an 'inline while'. Just like 'inline for', it
+// loops at compile time, allowing you do all sorts of
+// interesting things not possible at runtime. See if you can
+// figure out what this rather bonkers example prints:
+//
+// const foo = [3]*const [5]u8{ "~{s}~", "<{s}>", "d{s}b" };
+// comptime var i = 0;
+//
+// inline while ( i < foo.len ) : (i += 1) {
+// print(foo[i] ++ "\n", .{foo[i]});
+// }
+//
+// You haven't taken off that wizard hat yet, have you?
+//
+const print = @import("std").debug.print;
+
+pub fn main() void {
+ // Here is a string containing a series of arithmetic
+ // operations and single-digit decimal values. Let's call
+ // each operation and digit pair an "instruction".
+ const instructions = "+3 *5 -2 *2";
+
+ // Here is a u32 variable that will keep track of our current
+ // value in the program at runtime. It starts at 0, and we
+ // will get the final value by performing the sequence of
+ // instructions above.
+ var value: u32 = 0;
+
+ // This "index" variable will only be used at compile time in
+ // our loop.
+ comptime var i = 0;
+
+ // Here we wish to loop over each "instruction" in the string
+ // at compile time.
+ //
+ // Please fix this to loop once per "instruction":
+ ??? (i < instructions.len) : (???) {
+
+ // This gets the digit from the "instruction". Can you
+ // figure out why we subtract '0' from it?
+ comptime var digit = instructions[i + 1] - '0';
+
+ // This 'switch' statement contains the actual work done
+ // at runtime. At first, this doesn't seem exciting...
+ switch (instructions[i]) {
+ '+' => value += digit,
+ '-' => value -= digit,
+ '*' => value *= digit,
+ else => unreachable,
+ }
+ // ...But it's quite a bit more exciting than it first appears.
+ // The 'inline while' no longer exists at runtime and neither
+ // does anything else not touched by directly by runtime
+ // code. The 'instructions' string, for example, does not
+ // appear anywhere in the compiled program because it's
+ // not used by it!
+ //
+ // So in a very real sense, this loop actually converts
+ // the instructions contained in a string into runtime
+ // code at compile time. Guess we're compiler writers
+ // now. See? The wizard hat was justified after all.
+ }
+
+ print("{}\n", .{value});
+}
diff --git a/patches/patches/072_comptime7.patch b/patches/patches/072_comptime7.patch
new file mode 100644
index 0000000..205e238
--- /dev/null
+++ b/patches/patches/072_comptime7.patch
@@ -0,0 +1,4 @@
+38c38
+< ??? (i < instructions.len) : (???) {
+---
+> inline while (i < instructions.len) : (i += 3) {