loading...

Exploring how Elm can target Web Assembly

skinney profile image Robin Heggelund Hansen ・3 min read

Title sounds interesting, doesn't it? Last week I got this idea into my head that wouldn't leave. And so, I'm announcing ELS.

What's ELS? It's an experimental compiler for a statically typed Lisp which compiles to Web Assembly. As to what ELS actually means... I'm not sure yet, but I'll be sure to let you know once I find a phrase it can be a fitting acronym for =)

I imagine you might be a bit confused at this point. You might even have double checked the title to make sure it actually contains the word Elm, which it does. So why am I talking about Lisp?

Web Assembly

There are several people who've asked if, or when, Elm will target Web Assembly (WASM). I do believe Elm will target WASM eventually as it will let us escape some wierd Javascript semantics (like 53-bit ints, ugh), promises smaller asset sizes and (maybe) better performance.

It's early days, however, and targeting WASM isn't as easy as targeting Javascript. There are no objects in WASM. No arrays, strings or closures. Heck, there isn't even a builtin memory allocator, let alone a garbage collector.

Now, a garbage collector will come sometime in the future. So in the meantime, the time of Evan (author of Elm) is better spent on other things.

So what's this ELS thing about?

Well. Even though adding Elm support in the compiler will be a huge effort for potentially little gain (let's be honest, there are better ways to improve Elm than what it compiles to), that doesn't mean that exploring the space is wasted effort. As Evan has said previously: "Code is the easy part."

How should ports work in a WASM world? How should strings work? Would using the future builtin GC be best, or could a language like Elm do better with a custom GC scheme? How do we compile curried functions to WASM? How would the REPL work? Could Erlang like processes be implemented?

There are a bunch of questions to answer, and there is no reason not to explore that space early on. If we're lucky, by the time Elm is ready to target WASM, some of the ground work will be done already.

But... Lisp?

So, I had a problem. I wanted to explore how Elm could compile down to WASM, but I don't really know how the Elm compiler works and, more importantly, don't know Haskell. Luckily, the important thing isn't actually to compile Elm, but compiling a language which has the same semantics as Elm. So I decided to build my own language in Javascript which meets that requirement. Since I don't really care what the language looks like, I chose syntax which was easy to parse, and that was Lisp (with type annotations, of course).

There where other considerations as well. There already are tools for WASM in Javascript, and being able to execute WASM requires a Javascript environment. Writing the compiler in JS therefore makes things a bit simpler.

The big downside is that none of the compiler work I do can be merged into the Elm compiler sometime down the road. But that's fine. This is an experiment, and I don't expect that the code I write is something one would want to re-use anyway.

What I do hope is that the experience I get from this makes it possible for me to assist with porting Elm to WASM in the future. I might even be able to write some modules which Elm can make use of when that happens, like a string library or even a basic garbage collector which can serve as a stop gap until WASM gets a GC of its own.

Can I try it out?

Sure. The code, and instructions for trying it out, are available here.

Posted on by:

Discussion

markdown guide
 

I don't think the intention is to add a general purpose GC to WASM because GC implementations vary significantly based on language characteristics. I believe they intend to introduce GC primitives from which a GC can be implemented.

An Elm specific GC would actually be pretty simple as I understand it, thanks to all the assumptions that can be made with a pure, functional, eagerly evaluated language.

 

I'd also assume that what's called garbage collection here is due to the conclusion that if JavaScript needs one Elm will also need one.

Some years ago I wrote a PostScript interpreter and quite a while it worked very well without a garbage collector - all was done with reference counting. Apple shows with ARC (Automatic Reference Counting) that even a language much more complex than ELM can work without GC.

So as long as you don't have cyclic references reference counting should do the trick.

 

Ahh, you're right. I didn't read the proposal properly. That's actually better though =)