one machine · two implementations · one answer
The Loom's Weft-8 is about 180 lines of C here as well as a single JavaScript file — sixteen registers, four flags, 256 bytes, twenty-seven instructions. Eleven programs, with results worked out by hand, must agree across all three: the hand computation, the C machine, and the JavaScript one. If any of them drifts, the build goes red.
/* the whole machine, in one switch */ case W8_ADD: va = m->r[a]; vb = m->r[b]; res = (unsigned)va + vb; m->r[a] = (uint8_t)res; m->c = res > 0xFF; m->v = (((va ^ res) & (vb ^ res)) & 0x80) != 0; set_nz(m, m->r[a]); break;
A machine described in one language can hide a mistake inside that language's habits. A second implementation, written from the same specification and checked against an independent answer, cannot.
Ten programs with results computed by hand from the ISA — registers, flags and what reached the ports.
c/weft8.c and c/weft8.h. Built with
gcc -O2, run over the corpus in CI.
The Loom's own weft8.js, byte for byte
— the engine every other Weft app runs.
Every row is a claim about the machine, and each one is checked three ways.
| program | what it proves |
|---|---|
| add | 5 + 7 lands in a register, no flags raised |
| borrow | 2 − 5 wraps to 0xFD and sets carry and negative |
| overflow | 127 + 1 sets overflow, which is what makes signed branches correct |
| countdown | a loop runs exactly five times |
| signed | −1 is less than 1, though 255 is greater |
| stack | PUSH/POP return values in reverse order |
| callret | CALL and RET come back to the right place |
| ram | STORE then LOAD round-trips through scratch RAM |
| shift | SHL moves the top bit into carry |
| ports | two bytes written to a port arrive in order |
| signed-cmp | −2 is less than −1, so a signed branch works on negatives |
the weft-8 family — one machine, seven faces
Every one of these runs the same engine — weft8.js from the Loom, byte for byte. Learn it once and you have learned all seven.