Alm - an Elm compiler written in Rust

This has been a summer hobby project of mine that kind of got out of hand :sweat_smile:

Some highlights:

  • Faster compilation
  • Exactly the same error messages as 0.19
  • Faster or the same runtime performance
  • Experimental WASM and native outputs
  • Hot reload built in
  • Source maps

Here’s some benchmarks: Claude Artifact

6 Likes

I was curious about how you implemented the virtual DOM in the WASM version, so I had Calude analyze the implementation for me. Here is what it said:

“The Elm Architecture runs inside wasm: vdom diff/patch, the CPS task scheduler, the _Platform effect-manager protocol, ports, Http/Time/Random. The browser is reached through 48 imported host functions (wasmgc.rs:283) — dom_create_element, dom_insert_before, dom_add_event_listener, host_push_url, host_http, Math.* for transcendentals, etc. — plus a small set of exports (alm_browser_start, alm_event, alm_port_in, alm_tick). Strings cross via the module’s linear memory (ptr+len), DOM nodes are integer handles into a JS-side table, and a batched dom_build opcode stream builds whole subtrees in one host call. Finished modules are tree-shaken by re-parsing the binary, BFS-ing the call graph from exports, and stubbing dead bodies with unreachable without renumbering anything.”

The bit that caught my attention is: DOM nodes are integer handles into a JS-side table, and a batched dom_build opcode stream builds whole subtrees in one host call.

Is this analysis correct ?

I had the exact same idea for how to do this, but have not implemented it. But basically you put all the static DOM fragments from the Elm program into a table on the JS side. Then compile elm/virtual-dom to a bytecode that you chuck over to the JS side in one go, and it assembles the DOM from the fragmets.

Great stuff, I love it.

Have you also handled the return direction ? When an event occurs on the JS side, you get an event object, and Elm might run a JSON decoder on that to extract details of the event. Where do you do this JSON decoding, and how do you get the decoded event back to the WASM side efficiently ?

Yea, I went back and forth a bit on that design but ultimately the DOM API calls are basically optimized away by the web runtime anyway so it doesn’t matter a huge amount if you batch it or not :shrug:

Re return events: I don’t really remember. I think the wasm target passes all the same test suites, which is the total test suite of all packages in the package manager, but not sure about apps. I haven’t had a ton of time to test on my work code yet as I’m still on vacation.