Source in, machine code out
Write a real compiler: it parses expressions like (x + 3) * y - 4 with correct precedence (recursive descent — one function per precedence level), emits stack-machine bytecode as it goes, wraps it in a module with your buildModule, and returns a function the browser runs natively.
Recursive descent
A recursive-descent parser has one function per precedence level. expr handles + and - and calls term for its operands; term handles * and / and calls factor; factor handles numbers, variables, parentheses and unary minus. Because term finishes multiplying before expr sees a +, 2 + 3 * 4 naturally groups as 2 + (3 * 4).
function expr() {
term();
while (peek() === "+" || peek() === "-") {
const op = next();
term();
emit(op === "+" ? 0x6a : 0x6b);
}
}