bfx: A Tape-Based Esolang Interpreter, Compiler, and REPL

bfx is a Brainfuck toolkit written in C99 that includes an interpreter, compiler, and interactive REPL. Rather than implementing only a basic interpreter, the project provides multiple ways to execute Brainfuck programs while exposing the underlying compilation and execution pipeline for experimentation and performance analysis.

Motivation

I built bfx to explore language implementation from the ground up. Brainfuck’s minimal instruction set makes it possible to focus on the core concepts behind interpreters, compilation, parsing, and optimization without the complexity of a full programming language. The goal was to build a practical developer tool rather than simply a proof of concept.

Technical Highlights

Challenges

One of the more interesting challenges was designing the program in a way that allowed for interpretation of similar Brainfuck-like languages without duplicating code. I achieved this by creating a common language representation and a shared execution engine. Files in libbfx/src/langs contain language-specific initialization, deinitialization, and instruction functions, while the core interpreter logic is implemented in libbfx/src/interpret.c. In C, this required careful use of function pointers and structs to ensure that the language-specific code could be cleanly separated from the shared interpreter logic.

In addition, some derivatives, such as Weave and Grin, modify the behavior of the Brainfuck instruction set in ways that required additional logic to handle. For example, Weave introduces a new instruction that toggles between a thread’s memory tape and a shared memory tape, while Grin changes the behavior of the +-,. instructions. This made it necessary to include a language-specific data structure to track the state of the interpreter for each language, and rewriting certain parts of the interpreter to accommodate these differences.

What I Learned

This project gave me hands-on experience with compiler construction, parsing, and optimization techniques. It also provided insight into the challenges of designing a language implementation that is both flexible and efficient.

Future Work