A number
check-harness

Write check(input, expected) -- evaluates the input, prints ok or FAIL. We'll use this for every test from here on.

Use this main:

pub fn main() void {
    check("7", 7);
    check("3", 9);
}

One should pass, one should fail.

fn check(input: []const u8, expected: i64) void {
    const got: i64 = eval(input);
    if (got == expected) {
        print("{s} = {d} ok\n", .{ input, got });
    } else {
        print("{s} = {d} FAIL want {d}\n", .{ input, got, expected });
    }
}

{s} prints a string.

Two style notes that will hold for the rest of the book:

Braces around every branch. Even single-statement ifs get { ... }. Zig allows you to omit them sometimes, but uniform syntax is easier to read and edit.

Every variable declaration carries its type. Even when Zig can infer it (const got: i64 = eval(input) instead of const got = eval(input)). We're being anal about "reading is more important than writing" even more than Andrew Kelley.