marc walter

DRAFT: An Elm REPL for my phone

2024-09-28

I have been building elm.run/repl to write, type-check and compile Elm code on my mobile phone even if I don't have internet access.

Behavior

As visible in the preview on the left, there is an input area at the bottom where I can enter multiple lines of Elm code. The input field grows as needed, and I tried my best to ensure that it is usually not hidden by the on-screen keyboard on my phone.

With every keystroke, the code is checked and if it is valid I will see the type definition above my input (in the example the declaration elm = "delightful") and the evaluated result below, which is the String "delightful".

If I press the "run code" button, it will print the entire compiler output, which is useful for finding errors like in the example where a number was supplied insted of the expected String to create a Tree type alias.
The formatting is supplied by the compiler and looks like it would in the console.

I can scroll up to see older code that I entered, can easily copy each down into the input area with one button press or remove it completely.
It also has a button to execute multiple bulk clean-up operations. From a full reset to removing all outdated declarations to only removing errors, I have multiple options there.

Apart from colors to make the errors and the input field more readable, I tried to keep the amount of distractions low.
It has a light and dark mode, and auto-detects the user's preferences.

For people just starting out, I added an introductory text at the top of the page and a button to insert example code.
Right now it randomly picks one of several examples each with multiple entered expressions.

Technical background

When I started, all solutions to run Elm code required sending the code to a backend server, which would then send the compiled JavaScript code back to the browser for execution.

To achieve my goal of offline usage, I have been experimenting with compiling the Elm compiler to WebAssembly using the GHC WASM backend.

I made hardly any changes to the Elm compiler itself, mostly I removed code that either does not compile on the wasm32-wasi target (e.g. HTTP requests are not available) and or that was not needed for my use case (to reduce the file size of the build).

The GHC backend has greatly improved, in May the repl.wasm build weighed ~9MiB, now it is down to 6.4MiB even though I added features and did not remove much more.
When compressed with brotli, only 1.4MiB are transferred to the user, which seems very reasonable to me.

Code

The REPL UI is built in Elm, and uses ports to communicate with the WASM compiler. The glue code is written in TypeScript. Both are available on github.

There are two custom elements on the page: One for the color scheme toggle and one for the input area.

The color scheme toggle uses a css media query for auto-detection and stores and reads manual overrides from LocalStorage.

The input area wraps a codemirror 5 input element that was created by Tereza Sokol and Evan Czaplicki for https://elm-lang.org/try