Elm Compiler in Elm - Update

I finally managed to (hopefully) solve the stack overflow problems when running my port of the Elm compiler on other browsers than Safari.

With the new version I can compile the big module of the elm-default-tailwind-modules package in my Chrome browser, and I can compile the compiler with itself, too :rofl: There still might be problems with other big projects, though, so please tell me if you happen to encounter a stack overflow or other errors.

If you’re interested in the details of the changes I applied, feel free to ask.

25 Likes

In the Elm Slack I was asked what I had changed. I’m answering here because the posts stay longer.

Here is a short list:

  • In the original compiler, types like Parser, Decoder, Result, Tracker are implemented using a technique which is called (I think) “Church Encoding”. I wanted to add something like a stack-safe loop function to some of these types, but didn’t know how to do this in the Church Encoding, so I changed the defiinition of these types. For Decoder and Tracker this was all I had to do to solve the stack overflow problems there.

  • For Parser, Result and my IO monad I added the said “loop” function and used them where needed. I also used them to add some optimized fold and traversal functions to Result and IO.

  • In some places, the Elm compiler builds a graph (of nodes and edges) and then uses a library to dermine the so-called “strongly connected components” of such a graph. I had ported the code from the Haskell library to Elm, but as it turned out, that hasn’t been stack-safe. I had to re-implement the graph algorithm from scratch.

  • Finally, there were some functions where I had to manually try to make them tail-recursive, sometimes using a so-called continuation passing style: the functions constrainDecls and solve from the type checker, and the function checkDecls from the nitpicker. I was also lucky that Jeroen Engels showed me in his pull request how to make my implementation of the MVector type tail recursive. Thank you again @jfmengels.

This is just a very high-level description of my changes. If you want to know more, I’ll try to find some time to describe some points in more detail.

I was also asked whether these changes had any impact on performance, but after some very rudimentary testing I can’t see any substantial difference.

14 Likes

Thank you for making this even better and finding ways to not exceed stack limits on Firefox and Chromium.

Do you maybe have a basic introduction to this maybe-named “church encoding” technique?
Is it similar to defunctionalization, where instead of stacking function executions one returns records that are then handled in later runs, like e.g. in elm/parser loop?

Hey Marc, I am currently handicapped because of a cold, but I’ll try to answer as soon as possible…