**Compiling Scheme to WebAssembly**

The Bob project, a suite of implementations of the Scheme programming language in Python, has reached a significant milestone: its 15th anniversary. To celebrate this occasion, I embarked on an exciting new adventure - compiling Scheme directly to WebAssembly (WASM). In this article, we'll delve into the intricacies of this endeavor and explore the challenges that arose along the way.

**The Journey Begins**

My fascination with CPython internals led me to create Bob as an experiment in implementing a Scheme VM from scratch. Over time, I added a C++ VM to Bob, which implemented its own mark-and-sweep garbage collection (GC). After a quiet period, I felt the itch to revisit Bob and explore new horizons. The goal was clear: compile Scheme directly to WASM.

**The Challenges of WASM GC**

Representing Scheme objects in WASM posed an interesting challenge. To ensure memory management, we needed to properly box/wrap all values in references. This led to some creative solutions, such as using the `ref` type to represent nullable references and leveraging WASM's `i31` type to represent references to integers without boxing.

**Representing Scheme Objects**

In Bob, key Scheme objects are represented as follows:

* `$PAIR`: A pair containing arbitrary objects in its fields. This is represented by a nullable reference (`(ref null eq)`) to ensure memory management. * `$SYMBOL`: A symbol type that looks unusual at first glance. To address this, we implemented string interning using offsets to linear memory. When emitting symbols like "foo" and "bar", the compiler stores them in linear memory along with their offset and length.

**Implementing the `write` Builtin**

One of the most interesting aspects of this project was implementing the `write` builtin. This required printing recursive representations of arbitrary Scheme values, including lists and symbols. Initially, I was hesitant to implement this functionality by hand in WASM text, but all alternatives presented challenges. With AI assistance for the tedious parts, I wrote an implementation of `write` directly in WASM text - a surprisingly enjoyable experience.

**The Result**

After several months of work, the new WasmCompiler class is complete. This compiler lowers parsed Scheme expressions all the way down to WebAssembly text, which can then be compiled to a binary and executed using standard WASM tools. The source code for WasmCompiler is well-documented and available for exploration.

**Conclusion**

Compiling Scheme directly to WebAssembly has been an enlightening experience, with many lessons learned along the way. If you're interested in exploring this project further or have questions about the implementation details, please don't hesitate to reach out via email. The Bob project continues to evolve, and I look forward to seeing where this new path will lead.

**Update:**

The WasmCompiler class is now available for use in the Bob repository. Feel free to explore and contribute to this ongoing project.