Completing the Language
compound-assignment

Add +=, -=, *= to exec_stmt() and c_stmt(). When we see name followed by +=, desugar to name = name + expr.

Interpreter -- after reading a name, before the regular = check:

        if (cur() == '+' and pos + 1 < source.len and source[pos + 1] == '=') {
            pos += 2; skip();
            const val: i64 = expression();
            if (cur() == ';') { pos += 1; skip(); }
            setVar(word, getVar(word) + val);
            return getVar(word);
        }

Compiler -- emit get, compile right side, emit add, emit set:

        if (cur() == '+' and pos + 1 < source.len and source[pos + 1] == '=') {
            pos += 2; skip();
            if (c_is_global(word)) { emit_str("  global.get $"); } else { emit_str("  local.get $"); }
            emit_str(word); emit_byte('\n');
            c_expression();
            emit_op("i64.add");
            if (c_is_global(word)) { emit_str("  global.set $"); } else { emit_str("  local.set $"); }
            emit_str(word); emit_byte('\n');
            if (cur() == ';') { pos += 1; skip(); }
            return false;
        }

Same pattern for -= (with sub) and *= (with mul).

    check_both("var x: i64 = 10; x += 5; x", 15);
    check_both("var x: i64 = 10; x -= 3; x", 7);
    check_both("var x: i64 = 10; x *= 2; x", 20);

191 occurrences of += 1 in the Zig code. After this, every one compiles in both languages.

### Break