*My [interpreter][abc-interpreter] for the pure, functional language [Clean][] allows interpretation in both C and WebAssembly. The Clean compiler is written in Clean, with a C backend. In my [Clean Sandbox][], I compile the C backend with [Emscripten][] to [WebAssembly][], and interpret the Clean frontend in the WebAssembly interpreter. Combined with a simple `make`-like tool and an editor, this allows you to compile and run Clean code in the browser.* [[toc]] # Introduction Browsers can run programs in only few languages; mainly JavaScript. But JavaScript is a high-level scripting language that makes it hard to optimize performance. [WebAssembly][] operates on a lower level than JavaScript, is more complicated to write code in, but is a relatively easy compilation target for common imperative languages like C. This means that C applications and libraries can be ported to the browser relatively easily. However, WebAssembly lacks some features that make it a difficult compilation target for functional programming languages (in particular, non-local control flow and tail calls). Some of these omissions are being implemented as post-MVP features, but until then we need a workaround. Back in 2019 I implemented such a workaround for the pure, functional programming language [Clean][] (a close cousin of Haskell). The Clean compiler compiles to the intermediate language ABC, which is designed for an abstract imperative machine for graph rewriting. This ABC code is then converted to actual machine code. My solution, published in IFL'2019,[^ifl-2019] involves an interpreter for this intermediate ABC language. The interpreter logic is written in a DSL which targets both C and WebAssembly, so that you can run it both natively and in the browser. Initially, we used this system in the [iTasks][] framework for workflow management web applications. There, it allows you to send arbitrary Clean values (including thunks) to the browser for evaluation there. This has two benefits: (1) reducing server load by evaluating more on the client; (2) the ability to write custom frontend components in Clean, which allows you to make use of the same utility functions, the benefits of strong typing, etc. However, the ABC interpreter is more widely applicable than the iTasks system. To demonstrate this, I set out to run the Clean compiler itself in the browser. You can see the result in the [Clean Sandbox][]. # High-level overview In the end, the architecture turned out to be relatively simple. I needed the following components: - A file system to keep the files (taken from the Emscripten library). - A simple `make`-like tool that checks which files have been modified and calls the compiler for those files only. - The compiler frontend (written in Clean), running in the ABC interpreter. - The compiler backend (written in C), compiled with Emscripten to WebAssembly. - A linker for the generated ABC files (written in C, compiled to WebAssembly). - The ABC interpreter to run the resulting 'executable'. - A nice editor to let the user modify his Clean code. I use something based on the [Monaco Editor][], but will not discuss it here as I want to focus on the build pipeline. Apart from the `make`-like tool, all these components were already available, I only had to connect them together. *Continue to read about the [implementation details][pipeline].* [^ifl-2019]: Camil Staps, John van Groningen and Rinus Plasmeijer, 2019. [Lazy Interworking of Compiled and Interpreted Code for Sandboxing and Distributed Systems](https://camilstaps.nl/assets/pdf/ifl2019.pdf), in Jurriën Stutterheim and Wei Ngan Chin (eds.), *Implementation and Application of Functional Languages (IFL '19), September 25–27, 2019, Singapore, Singapore*. doi: [10.1145/3412932.3412941](https://doi.org/10.1145/3412932.3412941) [abc-interpreter]: https://gitlab.com/clean-and-itasks/abc-interpreter/ [Clean]: http://clean.cs.ru.nl/ [Clean Sandbox]: https://camilstaps.gitlab.io/clean-sandbox/ [Emscripten]: https://emscripten.org/ [iTasks]: https://gitlab.com/clean-and-itasks/itasks-sdk/ [Monaco Editor]: https://microsoft.github.io/monaco-editor/ [WebAssembly]: https://webassembly.org/ [introduction]: 2021-06-23-compiling-clean-in-the-browser-with-webassembly-part-1-introduction.html [pipeline]: 2021-06-23-compiling-clean-in-the-browser-with-webassembly-part-2-the-pipeline.html [integration]: 2021-06-23-compiling-clean-in-the-browser-with-webassembly-part-3-putting-it-all-together.html