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

12 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 ?

1 Like

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.

1 Like

This is great! It’s crazy how many new Elm or close to Elm compilers are released these days. This was unimagible just a year ago and makes me wonder what the future might bring.

When I read “native outputs”, I presumed that was Rust and assumed that was how you had WASM support…

I tried that but the llvm wasm target doesn’t support wasm gc which created huge binaries and bad performance.

Interesting and :slightly_frowning_face: - LLVM WASM target was what I was hoping to do for eco.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.