All Projects → elm-in-elm → Compiler

elm-in-elm / Compiler

Licence: bsd-3-clause
Elm compiler written in Elm

Programming Languages

language
365 projects
elm
856 projects

Labels

Projects that are alternatives of or similar to Compiler

Interim
Low-level Lisp with compile-time memory management
Stars: ✭ 204 (-8.11%)
Mutual labels:  compiler
Dmd
dmd D Programming Language compiler
Stars: ✭ 2,498 (+1025.23%)
Mutual labels:  compiler
Silt
An in-progress fast, dependently typed, functional programming language implemented in Swift.
Stars: ✭ 217 (-2.25%)
Mutual labels:  compiler
Transcrypt
Python 3.7 to JavaScript compiler - Lean, fast, open! -
Stars: ✭ 2,502 (+1027.03%)
Mutual labels:  compiler
Ppci
A compiler for ARM, X86, MSP430, xtensa and more implemented in pure Python
Stars: ✭ 210 (-5.41%)
Mutual labels:  compiler
Urlang
Urlang is JavaScript with a sane syntax
Stars: ✭ 215 (-3.15%)
Mutual labels:  compiler
Nxdk
The cross-platform, open-source SDK to develop for original Xbox: *new* xdk
Stars: ✭ 200 (-9.91%)
Mutual labels:  compiler
Saltwater
A C compiler written in Rust, with a focus on good error messages.
Stars: ✭ 219 (-1.35%)
Mutual labels:  compiler
Customasm
💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/
Stars: ✭ 211 (-4.95%)
Mutual labels:  compiler
Retyped
Access 3600+ libraries from C# and let Bridge.NET compile your project into JavaScript.
Stars: ✭ 216 (-2.7%)
Mutual labels:  compiler
Compiler
Pawn compiler for SA-MP with bug fixes and new features - runs on Windows, Linux, macOS
Stars: ✭ 209 (-5.86%)
Mutual labels:  compiler
Ichbins
A tiny self-hosting Lisp-to-C compiler
Stars: ✭ 210 (-5.41%)
Mutual labels:  compiler
Emojicode
😀😜🔂 World’s only programming language that’s bursting with emojis
Stars: ✭ 2,561 (+1053.6%)
Mutual labels:  compiler
8cc.vim
C Compiler written in Vim script
Stars: ✭ 205 (-7.66%)
Mutual labels:  compiler
Nit
Nit language
Stars: ✭ 217 (-2.25%)
Mutual labels:  compiler
Binaryen.js
A buildbot for binaryen.js, a port of Binaryen to the Web, with TypeScript support.
Stars: ✭ 201 (-9.46%)
Mutual labels:  compiler
Mimium
mimium (MInimal Musical medIUM) a programming language as an infrastructure for sound and music.
Stars: ✭ 212 (-4.5%)
Mutual labels:  compiler
Amulet
An ML-like functional programming language
Stars: ✭ 219 (-1.35%)
Mutual labels:  compiler
Goron
Yet another llvm based obfuscator
Stars: ✭ 218 (-1.8%)
Mutual labels:  compiler
Lumen
An alternative BEAM implementation, designed for WebAssembly
Stars: ✭ 2,742 (+1135.14%)
Mutual labels:  compiler

elm-in-elm logo

elm-in-elm

Elm compiler written in Elm!



Goals

  1. 📖 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, ...)!
  2. 🚸 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-elm is focused on readability, beauty, approachability, simplicity, great docs and great tests first, and only then completeness and speed.
  3. 💡 exploration ready: the first two points enable folks to hack on the compiler (as it's written in Elm, which they know, and the code is new-people-friendly) and answer some questions! (For example, what's the best order of optimizations? How would emitting to JavaScript have to look like to make it extra amenable to Google Closure Compiler's advanced optimizations?)
  4. 🔧 extensible: again, the first two (three?) points make it easy and invite extending the compiler in various ways, eg. a native binary target, different type inference algorithm, new optimizations, where syntax, etc.

In short, elm-in-elm aims to unblock and encourage people to play with compilers and the Elm language itself, explore new frontiers and have fun!

📺 For more context and information, you can watch Martin Janiczek's talk from Elm Europe 2019 which served as an unveiling of elm-in-elm to public. Here are 📊 the slides.

Non-goals ❎

  1. To dethrone or replace the official Elm compiler written in Haskell.

This is ❎❎❎ NOT THE REASON and NOT THE GOAL ❎❎❎ of 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.

What?

elm-in-elm consists of:

It is written in Elm, and compiles Elm to JavaScript, but lays the foundation to be able to compile to different targets in the future.

⚠️ Warning! elm-in-elm is 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 parse column in the table below.

Contributing

Please yes! ❤️ Feel free to look around the help wanted or good first issue issues, have a look around the codebase for some general nitpicks or refactorings, or hit us up on Discord!

Roadmap

Roadmap

parser tests optimize tests emit tests parse desugar infer types optimize emit
integers ✔️ ⚠️ [2] ✔️ ✔️ ✔️ ✔️ ⚠️ [2] ✔️
floats ✔️ [5] ✔️ ✔️ ✔️ ✔️ [5] ✔️
characters ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
strings ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
booleans ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
variables ⚠️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
lists ✔️ [6] ⚠️ [1] ✔️ ✔️ ✔️ [6] ⚠️ [1]
binary operators ⚠️ [3] ✔️ ✔️ ⚠️ [3] ✔️ ⚠️ ⚠️
lambdas ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ⚠️ ✔️
function calls ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
if...then...else ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
let..in ✔️ ✔️ ✔️ ✔️ ✔️ ⚠️ ✔️ ⚠️
case...of ⚠️ [4] ⚠️ [4]
records ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
record accessors
record updates
unit type ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
tuples, 3-tuples ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
type annotations ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
type aliases ✔️ ✔️ ✔️ ✔️ ✔️ ⚠️ [7] ✔️ ✔️
custom types ✔️ ✔️
custom operators
shaders (?)
  1. Lists' emit will have to change a bit: conversion from target platform lists to Elm "custom type" lists is now missing; tracked in #29
  2. To be optimized with multiplication, subtraction, division, modulo, exponentiation... maybe more?
  3. Multi-line binops (probably) don't work correctly now
  4. Custom type patterns aren't supported yet
  5. To be optimized the same way Ints are
  6. Not implemented; partially tracked in #29
  7. We're currently doing nothing about the type parameters in the type aliases.

FAQ

    • Q: Why not use stil4m/elm-syntax for 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-combinators style - we'd like, again because of the learning resource goal, to have the parsers written in idiomatic elm/parser style

      But yeah, there's definitely a little bit of NIH syndrome happening 😉

Prerequisites

The easy way: if you have Nix installed, run

$ nix-shell

and you'll drop into a shell that has all the dev dependencies set up and ready!

Alternatively, this is what the project needs.

  • make for the Makefile
  • NodeJS 10+ for the CLI tool
  • elm, elm-test and elm-format

Running the compiler

$ make

Essentially compiles the compiler (using the official Elm compiler 😉 ) to a build/elm.js file and runs it using node.

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 example-project/src/Main.elm, Debug.log what you need in the compiler itself, and make!

So absolutely feel free to go bonkers on that example-project/ - it's there for developer convenience!

Running the tests

$ make test

Runs elm-test on the test suite (gasp!)

Formatting code

$ make format 

Runs elm-format. Make sure to format code before submitting a pull request!

Small TODOs

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

Project management

  • [ ] @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

General

  • [ ] Compare our Main.compile with 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

Type inference

  • [ ] Try the Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism and see where that leads
  • [ ] Let polymorphism 😶: Stage.InferTypes.generateEquations, the Typed.Let case. 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 a instead of type #0 or something). Stage.InferTypes.getType

Optimizations

  • [ ] 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?)
  • [ ] Implement (<|) and (|>) fusion (eg. transform both x |> f and f <| x into f x)

PrepareForBackend

  • [ ] Check that the Lambda case of Stage.PrepareForBackend.findDependencies works correctly

Emit

  • [ ] Native binary target (x86_64), possibly through LLVM?
  • [ ] WebAssembly?
  • [ ] 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+b instead 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 main gets computed for the program itself. Stage.Emit.emitExpr, the Let case.
  • [ ] 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?

Tests

  • [ ] Test Common.unalias
  • [ ] Test Stage.Desugar.findModuleOfVar

Contributors

Martin Janiczek Rémi Lefèvre Harry Sarson Maxime Dantec Aaron Janse
Eduard Kyvenko Sébastien Besnier sgdan Pablo Hirafuji You?

License

BSD-3-Clause

Attribution

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].