Feeding the Snake
c-number-in-language

Now the real thing. Write a program in our language that:
1. Takes a character from memory (simulating input)
2. Recognizes a digit
3. Emits i64.const N

This is c_number() -- in our language:

    check(
        \\var src_pos: i64 = 0;
        \\var out_len: i64 = 0;
        \\fn cur() i64 { return load8(src_pos); }
        \\fn emit_byte(b: i64) i64 {
        \\    store8(50000 + out_len, b);
        \\    out_len = out_len + 1;
        \\    return 0;
        \\}
        \\fn emit_s(s: i64) i64 {
        \\    var a: i64 = s / 65536;
        \\    var l: i64 = s - a * 65536;
        \\    var i: i64 = 0;
        \\    while (i < l) { emit_byte(load8(a + i)); i = i + 1; }
        \\    return 0;
        \\}
        \\fn emit_digit(d: i64) i64 {
        \\    emit_byte(48 + d);
        \\    return 0;
        \\}
        \\fn c_number() i64 {
        \\    var val: i64 = 0;
        \\    while (cur() >= 48) {
        \\        if (cur() > 57) { return val; }
        \\        val = val * 10 + (cur() - 48);
        \\        src_pos = src_pos + 1;
        \\    }
        \\    emit_s("  i64.const ");
        \\    emit_digit(val);
        \\    emit_byte(10);
        \\    return val;
        \\}
        \\store8(0, 55);
        \\c_number()
    , 7);

We stored 55 (the ASCII code for '7') at address 0, then called c_number(). It read the digit, emitted i64.const 7\n to the output buffer at address 50000, and returned 7.

That's the compiler's number parser, running in our language, reading from memory, writing to memory. It works.