Agreement test for strings:
check_both("str_len(\"hello\")", 5);
check_both("str_len(\"\")", 0);
check_both("store8(100, 65); load8(100)", 65);
And the big one -- streq_mem running through both engines:
check_both(
\\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("hello", "hello")
, 1);
If this passes -- a string comparison function, written in our language, compiled to WAT, executed by the VM, producing the same result as the interpreter -- then the language is powerful enough to do real string processing. It can compare keywords. It can check operators. It can parse.
### The taste of self-hosting
Let's write a tiny compiler in our language. Not the full thing -- just enough to compile 3 + 5 into WAT. A proof that the snake's mouth is reaching its tail.