Tom MacWright

Wah, a slightly higher level language for WebAssembly, with a reference compiler in Clojure

I’m finally ready to publicize & link to wah, a slightly higher-level language on top of WebAssembly. It’s what I’m using to slowly assemble simple-statistics-wasm, a WebAssembly port of Simple Statistics.

wah is slightly higher-level - it offers

  1. Basic type inference
  2. Infix operators
  3. Shortcuts for literal numbers
  4. Shortcuts for getting & setting variables and parameters

The language is implemented in Clojure, using Clojure’s lovely concepts of edn, metadata, and symbols. I had been tinkering with Clojure before, for instance to assemble the redirects as a moved this site to HTTPS and to implement undo & redo, but wanted a more challenging project to truly learn the language. Wah was that: even targeting such a simple and nice language as WebAssembly pushed me to learn a lot about Clojure, WebAssembly, and systems in general.

There’s a lot in the wah repository to read: the introduction, rationale, and flow diagram are a good place to start to answer any questions.

Notably, the wah project is going to operate with PRs only. I’ve disabled the GitHub issue tracker. I’m more than happy to review and merge PRs, and welcome bug reports in the form of failing testcases. Given the very technical audience for the tool, I hope this works out, and establishes the project firmly as a participatory community rather than a product-customer relationship.

WebAssembly is a really exciting new era in web technology, and I’d highly recommend Rasmus’s article on it for another intro. It’s also extremely bleeding-edge: browsers & node are just starting to support the specification and currently have limited compatibility and predictability. But it’s a lot of fun, and, as a very simple, very low-level, very fast language, was a ton of fun to build around.

Clojure is also a lot of fun: the development environment with vim-fireplace is nothing short of magical, ClojureDocs is great, and the language simply seems well-designed. That said, for a compiler or a similar command-line tool, the Clojure startup time is a major bummer. Clojure is really fast once it gets going, which is great for servers, but short short-lived processes it’s hard for me to see how it’d be usable.

It was really fascinating to go from working on documentation.js - a project that parses and manipulates JavaScript syntax trees using the Babel toolchain - to a project that manipulates S-Expressions. Where JavaScript has so much syntax, the near-total lack of syntax in WebAssembly text format, and to a lesser degree Clojure, is fascinating. It’s much easier to mix around expressions and rewrite source, but also makes me wonder about the importance of types and heterogenous trees. Said differently, it’s much easier to rewrite S-Expressions, but also much easier to do it wrong.

Implementing types was also fascinating, though much simpler than it’d be for, say, Flow, because WebAssembly has only explicit type conversions. How wah does it is using postwalk to walk up the tree in post order, using types collected from explicit variable declarations, more or less ‘bubbling them up’ and storing them with Clojure metadata.