The compiler still emits one byte per number:
appendStringLiteral(&wat_buffer, &wat_length, "i64.const ");
appendChar(&wat_buffer, &wat_length, input[input_pos]);
appendChar(&wat_buffer, &wat_length, '\n');
input_pos += 1;
Cleanest path: parse the number with parseNumber (gives us an i64), then write the digits back into the wat buffer with a new helper. Same shape as printNumber, but the output sink is appendChar(buffer, position, c) instead of printChar(c):
fn appendNumber(
buffer: [*]u8,
position: *usize,
n: i64,
) void {
var value: i64 = n;
if (value < 0) {
appendChar(buffer, position, '-');
value = -value;
}
if (value == 0) {
appendChar(buffer, position, '0');
return;
}
var buf: [20]u8 = undefined;
var i: usize = 0;
while (value > 0) {
const d: i64 = @mod(value, 10);
buf[i] = @intCast('0' + d);
i += 1;
value = @divTrunc(value, 10);
}
while (i > 0) {
i -= 1;
appendChar(buffer, position, buf[i]);
}
}
Now in the compiler, replace the byte-copy with parseNumber + appendNumber. Same fix in two places: the initial number, and the next number inside the chain loop.
// 2. THE COMPILER
var wat_buffer: [512]u8 = undefined;
var wat_length: usize = 0;
input_pos = 0;
appendStringLiteral(&wat_buffer, &wat_length, "i64.const ");
appendNumber(&wat_buffer, &wat_length, parseNumber(input, &input_pos));
appendChar(&wat_buffer, &wat_length, '\n');
while (input[input_pos] != 0) {
const op: u8 = input[input_pos];
input_pos += 1;
appendStringLiteral(&wat_buffer, &wat_length, "i64.const ");
appendNumber(&wat_buffer, &wat_length, parseNumber(input, &input_pos));
appendChar(&wat_buffer, &wat_length, '\n');
if (op == '+') {
appendStringLiteral(&wat_buffer, &wat_length, "i64.add\n");
} else if (op == '-') {
appendStringLiteral(&wat_buffer, &wat_length, "i64.sub\n");
} else if (op == '*') {
appendStringLiteral(&wat_buffer, &wat_length, "i64.mul\n");
} else if (op == '/') {
appendStringLiteral(&wat_buffer, &wat_length, "i64.div_s\n");
} else {
printString("error: unknown operator\n");
return;
}
}
The compiler reads from input via parseNumber, writes to wat_buffer via appendNumber. One line per number on each side. The bytes of input and the bytes of wat_buffer never touch -- everything goes through i64. Try 12+3, 100+23, 12*12 and watch the VM agree with the interpreter.