# Day 6: my language now compiles to WebAssembly — and I emit the bytes by hand

> Source: <https://dev.to/umbraaeternaa/day-6-my-language-now-compiles-to-webassembly-and-i-emit-the-bytes-by-hand-c0o>
> Published: 2026-06-26 21:22:32+00:00

I'm building LOOM — a small open-source language that is a machine-checked trust layer for AI-written code. I don't write it by hand anymore: an organism I built grows it, day and night, on my own machine. This is Day 6, and the whole day went to one thing — **WebAssembly**.

LOOM already runs three ways: an interpreter, and backends that compile checked code to Python and JavaScript. The thesis is "trust survives translation" — effects and provenance, proven once, hold the same on every target. WebAssembly is the strongest test of that: a low-level stack machine with linear memory, nothing like Python or JS.

And there was a constraint. This machine's clang has no wasm target, and I install nothing paid or heavy. So I don't compile *to* wasm through a toolchain — **I emit the wasm bytes myself** (LEB128, the type / function / memory / global / export / code sections, the i32 stack machine) and run them through node's built-in `WebAssembly`

. Zero dependencies.

`fib`

to a value runtime, in a day
Every step was prototyped and proven (wasm output == interpreter output) *before* it touched the kernel:

`if`

, first-order calls and recursion. `fib(10)`

becomes 61 bytes of real WebAssembly and returns 55, identically on the interpreter, Python, Node and wasm.`let`

and integer `$cons`

cell allocator; `head`

/`tail`

are `i32.load`

, `empty`

is `i32.eqz`

). A list sums and folds by recursion, inside wasm.`(variant Tag e)`

becomes a tagged cell `[tag-id | payload]`

; `match`

loads the tag, compares, binds the payload, branches.You can watch it: the live playground has a **Compile → WAT** button and `WASM · fib`

/ `list-sum`

/ `match`

examples. Type a program, see it become real assembly, in your browser.

**Honest scope:** ints, `let`

, integer lists and sum types compile to wasm today. Records, closures and effects are the next frontiers (closures are the hard one — a function table plus a heap environment). Anything outside the supported set fails closed — it never emits wrong code.

While I worked on wasm, the organism worked on the trust layer. I'd landed D26 — a rule that provenance does **not** survive an opaque foreign (FFI) call, so the host can vouch for what foreign code is *granted* but never for what it *returns*. D26 left an honest gap in its own comments: a vetted, signed library was treated no better than an arbitrary `.so`

.

The organism, on its own overnight pass, proposed the answer — and I reviewed it and landed it. `(vouch ROLE WHO COMP)`

: a non-AI authority signs a **specific** foreign component, so that component's output carries the authority's anchor instead of being stripped. It's an *attestation* — traceability to a named, non-AI auditor of that exact component — not a claim the component is correct. It fails closed everywhere (an AI vouching for itself, a name mismatch, a value laundered through the call — all rejected). A machine I built found and closed a gap in my own design.

**298 checks, all green.** Across every day, the language has only ever gotten greener.

Built solo, in the open, from Ukraine 🇺🇦.

⭐ Code (MIT): [https://github.com/umbraaeternaa/loom](https://github.com/umbraaeternaa/loom)

▶ Try it live: [https://umbraaeternaa.github.io/loom/play.html](https://umbraaeternaa.github.io/loom/play.html)

☕ Support: [https://send.monobank.ua/jar/AHaziFXjYX](https://send.monobank.ua/jar/AHaziFXjYX)
