Time to actually run the WAT. The stack machine has one rule: i64.const N pushes N on the stack. Let's get that one working first; i64.add comes next.
To dispatch, we'll compare each line to a known instruction name. Two helpers, both at file scope:
fn stringsEqual(
a: []const u8,
b: []const u8,
) bool {
if (a.len != b.len) {
return false;
}
var i: usize = 0;
while (i < a.len) {
if (a[i] != b[i]) {
return false;
}
i += 1;
}
return true;
}
fn stringStartsWith(
s: []const u8,
prefix: []const u8,
) bool {
if (s.len < prefix.len) {
return false;
}
return stringsEqual(s[0..prefix.len], prefix);
}
stringsEqual for full matches like "i64.add". stringStartsWith for "i64.const " -- the prefix is fixed but the digit after isn't.
In main, walk the WAT and dispatch on each line. For now the WAT only has consts. If a line starts with "i64.const ", parse the last char as a digit and push. Anything else is an error.
pub fn main() void {
// (interpreter section unchanged)
const wat: [:0]const u8 =
\\i64.const 3
\\i64.const 4
;
var stack: [16]i64 = undefined;
var stack_pointer: usize = 0;
var wat_pos: usize = 0;
while (wat_pos < wat.len) {
var wat_line_end: usize = wat_pos;
while (wat_line_end < wat.len and wat[wat_line_end] != '\n') {
wat_line_end += 1;
}
const line: []const u8 = wat[wat_pos..wat_line_end];
// YOU: dispatch on line.
// If it starts with "i64.const ", parse line[line.len - 1] as a digit, push.
// Otherwise, printString("error: unknown instruction\n").
wat_pos = wat_line_end + 1;
}
printString("top of stack: ");
printNumber(stack[stack_pointer - 1]);
printChar('\n');
}
if (stringStartsWith(line, "i64.const ")) {
stack[stack_pointer] = @as(i64, line[line.len - 1]) - '0';
stack_pointer += 1;
} else {
printString("error: unknown instruction\n");
return;
}
After two i64.const instructions, the stack holds 3, 4. The top is 4. We print it to confirm the loop pushed both values.