Browse Source

add 072 comptime 7

Dave Gauer 4 years ago
parent
commit
14c7e73343
3 changed files with 74 additions and 0 deletions
  1. 4 0
      build.zig
  2. 66 0
      exercises/072_comptime7.zig
  3. 4 0
      patches/patches/072_comptime7.patch

+ 4 - 0
build.zig

@@ -362,6 +362,10 @@ const exercises = [_]Exercise{
         .main_file = "071_comptime6.zig",
         .main_file = "071_comptime6.zig",
         .output = "Narcissus has room in his heart for: me myself.",
         .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.
 /// Check the zig version to make sure it can compile the examples properly.

+ 66 - 0
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});
+}

+ 4 - 0
patches/patches/072_comptime7.patch

@@ -0,0 +1,4 @@
+38c38
+<     ??? (i < instructions.len) : (???) {
+---
+>     inline while (i < instructions.len) : (i += 3) {