Elm compiler written in Elm!
📖compiler as Elm library: so that we can publish it on https://package.elm-lang.org/ and unlock new kinds of Elm applications (like Elm-evaluating Slack bots, Klipse integration, stepping debuggers, ...)! 🚸learning friendly: so that folks can learn how to write a compiler in Elm (similarly to Richard Feldman's elm-spa-example). This means
elm-in-elmis focused on readability, beauty, approachability, simplicity, great docs and great tests first, and only then completeness and speed.
elm-in-elm aims to unblock and encourage people to play with compilers and the Elm language itself, explore new frontiers and have fun!
- To dethrone or replace the official Elm compiler written in Haskell.
elm-in-elm. We don't want to and aren't planning to divide the community into multiple Elm derivatives, and will actively try to prevent that.
elm-in-elm is, for all intents and purposes, a sandbox, a place to try out ideas, an experimentation environment.
elm-in-elm consists of:
elm-in-elmis definitely not ready for usage yet, even though its library is published already. The main blocker is the parsers for expressions not being all implemented yet. See the
parsecolumn in the table below.
|parser tests||optimize tests||emit tests||parse||desugar||infer types||optimize||emit|
emitwill have to change a bit: conversion from target platform lists to Elm "custom type" lists is now missing; tracked in #29
- To be optimized with multiplication, subtraction, division, modulo, exponentiation... maybe more?
- Multi-line binops (probably) don't work correctly now
- Custom type patterns aren't supported yet
- To be optimized the same way Ints are
- Not implemented; partially tracked in #29
- We're currently doing nothing about the type parameters in the type aliases.
Q: Why not use
stil4m/elm-syntaxfor the parsers?
A: We'd love to use
elm-syntax- it would save us so much trouble. But that would not be ideal in some regards:
- less flexibility wrt. how our types look
- would be less educational (compare with the learning resource goal) - would skip parsers entirely
- even if we didn't use it as a library but copypasted the parsers code, those are written in the 0.18
elm-community/parser-combinatorsstyle - we'd like, again because of the learning resource goal, to have the parsers written in idiomatic
But yeah, there's definitely a little bit of NIH syndrome happening
The easy way: if you have Nix installed, run
and you'll drop into a shell that has all the dev dependencies set up and ready!
Alternatively, this is what the project needs.
Running the compiler
Essentially compiles the compiler (using the official Elm compiler
build/elm.js file and runs it using
Very handy for running the whole compiler pipeline on an example project living in
example-project/, which the CLI is currently hardcoded to try and compile! In some cases this might be more convenient than writing tests - just add an interesting snippet to
Debug.log what you need in the compiler itself, and
So absolutely feel free to go bonkers on that
example-project/ - it's there for developer convenience!
Running the tests
$ make test
elm-test on the test suite (gasp!)
$ make format
Runs elm-format. Make sure to format code before submitting a pull request!
This is a brain-dump of some low-level stuff. (High-level stuff should be in the roadmap.) My apologies if it's hard to make sense of this! ~janiczek
- @janiczek: Share your Firefox bookmarks relevant to
elm-in-elm(ie. talks about Haskell hierarchical optimizations etc.)
- Add tests for stages other than parsing and emit into the matrix above
- Compare our
Main.compilewith official compiler's
Compile.compile- is that a better API?
- Types module: remove, refactor into "module per datastructure" style?
- Deal with kernel modules
- Deal with ports
- Deal with effect modules
- Deal with typeclasses (number, comparable, ...)
- Deal with pattern matching
- Deal with custom binary operators
- Try the Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism and see where that leads
- Let polymorphism
Typed.Letcase. This paper might have a parable written well enough that we might actually understand type schemes from this. Otherwise, "Write you a Haskell" for the rescue! There is also the Damas and Milner paper proving the inferred type is the most general one.
- Extensible records (link):
D. Leijen, “Extensible records with scoped labels,” in Revised Selected Papersfrom the Sixth Symposium on Trends in Functional Programming, TFP 2005,Tallinn, Estonia, 23-24 September 2005.(M. C. J. D. van Eekelen, ed.), vol. 6 of Trends in Functional Programming, pp. 179–194, Intellect, 2005.
- Typecheck across modules, not each module separately. This will probably be clearer after we try and implement the library.
- Annotate type errors with position in source code (for better error messages)
- Try to find a better name for "occurs check" and make the error message easier to understand
- Document the typechecking stages better (ie. at all)
- Rename types to be able to show nice type variables (ie. the classic
type #0or something).
- Experiment with Prepack-like optimization: compute everything you can in the compile-time instead of runtime
- Implement constant propagation?
- Implement inlining (maybe it will need some heuristic? Look at how other langs do it?)
(|>)fusion (eg. transform both
x |> fand
f <| xinto
- Check that the
- Native binary target (x86_64), possibly through LLVM?
- Would this simplify / be a good fit for Elchemy (Elm -> Elixir)?
- Would this simplify / be a good fit for philip2 (Elm -> OCaml)?
- Would it be worth concatenating single-arg lambdas back to multi-arg ones (so that we emit eg.
(a,b) => a+binstead of
(a) => (b) => a+b)?
- How to emit
let? How does official compiler do it? Seems the dependency graph will have to be computed for its binidng too, similarly to how the path to
maingets computed for the program itself.
- Do we need to mangle variable names? (ie. do what the official compiler does) Maybe not! Check
- What's good JS style for Google Closure Compiler's advanced optimizations?
- What's good JS style for UglifyJS?
- What's good JS style for modern JS engines?
- "person using laptop" icon created by alvaro_cabrera