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.