ELS is a staticly typed Lisp which compiles to Web Assembly
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.



PLEASE NOTE: The author of this project does in no way speak for Evan or the future of Elm. This project is not an official experiment or pre-stage for web assembly support in the Elm compiler.

ELS is a staticly typed language which looks a bit like Lisp and compiles to Web Assembly (WASM). It's not intended for production use. This is just a hobby, won't be big and professional like Elm. The goal is instead to learn more about WASM as a compile target. More specifically, the goal is to learn how a staticly typed language like Elm can be compiled to WASM.


I've always found it helpful to specify the goals for a software project up front, to keep help me focused on the things I actually want to get done.

  • Learn about WASM.
  • Support the same language constructs as Elm. So immutable data, ADTs, curried functions, ports...
  • Have a REPL without an interpreter.
  • Document the compiler, the repl, the language etc. through markdown files, tests and well commented code.


Just as I find it helpful to write down the things to focus on, it's also helpful to specify what I shouldn't focus on. This doesn't mean that these things will never added to the project, just that I don't want to spend my time on it.

  • Compile code that actually looks like Elm (Lisp has simple semantics, so let's compile that).
  • Support only the features that Elm supports.
  • Be a true Lisp (no macros)
  • Backwards compatibility between releases.
  • Develop a package manager or other tools besides the compiler and the REPL.
  • Have awesome error messages.

Current status

I'd say what is currently implemented is a MVP. You can define functions, call those functions, and basic integer arithmetic. Let's try it out:

Clone the repo and install the dependencies: npm install Boot up the REPL: npm run repl

To start with, enter the following:

(defn triple [n Int] Int (+ n (+ n n))) (triple 5)

The first time you enter code into the REPL it will take some time to load the WASM binary tools and compile the code. Subsequent entries will compile much faster.

Make sure you write it all on one line, or it won't work. The result should be 15.

Documenting the language, the compiler and how the REPL works is targeted for the next release (check out the 0.1.0 milestone for more info).

Currently, these are the supported constructs:

  • defn defines a function (there are no variables, local or global).
  • Int and Float are the only supported types.
  • +, *, - and / are the only builtin functions.
  • The REPL doesn't remember what has been combined earlier, so you can't define one function on one line, then call it on the next.
  • There are no control constructs like if or recursive functions.
  • There are no higher order functions.

All of this will improve in future releases.

There are other REPLs available if you want to learn more:

  • npm run repl-ast spits out the AST after the compiler has type checked it.
  • npm run repl-wat spits out the WAT (web assembly text format) of the code.
  • npm run repl-wasm spits out the actual WASM bytecode, with annotations.

You can also compile files to .wat or .wasm:

npm run compile <file>.els <output>.{.wat|.wasm}


This is learning project, so I want to do the big ticket items myself. Like adding support for ADTs, Records, Arrays, ifs, etc. Bug reports and PRs that fixes bugs are of course welcome.