Feeding the Snake
streq-in-language

The crucial one: write a streq_mem function in our language that compares two packed string values byte by byte. This is the equivalent of the streq we wrote in Zig -- but running in our language.

    check(
        \\fn streq_mem(a: i64, b: i64) i64 {
        \\    var a_addr: i64 = a / 65536;
        \\    var a_len: i64 = a - a_addr * 65536;
        \\    var b_addr: i64 = b / 65536;
        \\    var b_len: i64 = b - b_addr * 65536;
        \\    if (a_len != b_len) { return 0; }
        \\    var i: i64 = 0;
        \\    while (i < a_len) {
        \\        if (load8(a_addr + i) != load8(b_addr + i)) { return 0; }
        \\        i = i + 1;
        \\    }
        \\    return 1;
        \\}
        \\streq_mem("cat", "cat")
    , 1);

    check(
        \\fn streq_mem(a: i64, b: i64) i64 {
        \\    var a_addr: i64 = a / 65536;
        \\    var a_len: i64 = a - a_addr * 65536;
        \\    var b_addr: i64 = b / 65536;
        \\    var b_len: i64 = b - b_addr * 65536;
        \\    if (a_len != b_len) { return 0; }
        \\    var i: i64 = 0;
        \\    while (i < a_len) {
        \\        if (load8(a_addr + i) != load8(b_addr + i)) { return 0; }
        \\        i = i + 1;
        \\    }
        \\    return 1;
        \\}
        \\streq_mem("cat", "dog")
    , 0);

Stop and look at that. We just wrote string comparison in our own language. load8 reads bytes from memory. The while loop walks both strings. != checks each pair. This is the same logic as our Zig streq, expressed in the language we built. The language is starting to be useful for real work.