From 2f0f823a738ced78d28de2cb86e1ef186a35778b Mon Sep 17 00:00:00 2001 From: Dave Gauer Date: Sat, 24 Apr 2021 14:34:46 -0400 Subject: [PATCH] add 072 comptime 7 --- build.zig | 4 ++ exercises/072_comptime7.zig | 66 +++++++++++++++++++++++++++++ patches/patches/072_comptime7.patch | 4 ++ 3 files changed, 74 insertions(+) create mode 100644 exercises/072_comptime7.zig create mode 100644 patches/patches/072_comptime7.patch 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) {