An all-in-one Brainfuck development tool/VM
This project uses CMake for builds and requires a compiler that provides GCC/Clang-style builtins. It is tested with GCC, Clang, and clang-cl. To compile:
cmake -S . -B build -G Ninja
cmake --build buildThe resulting executable will be located in the build directory.
The project can also be built on Windows using CMake with either the MinGW or Clang toolchains (for example, clang-cl). Pure MSVC builds are not supported:
cmake -S . -B build -G Ninja
cmake --build build --config ReleaseANSI escape sequences are enabled automatically on startup so colored
output works in both PowerShell and cmd.exe.
On platforms where Valgrind is available (e.g., Linux), you can run the test suite under Valgrind to detect memory leaks and invalid memory use:
sudo apt-get install -y valgrind # Debian/Ubuntu
cmake -S . -B build -G Ninja
cmake --build build
cmake --build build --target memcheckThis invokes ctest -T memcheck with strict options
(--leak-check=full, --show-leak-kinds=all, --error-exitcode=2, etc.).
The memcheck target is only available when Valgrind is found.
The VM can execute a Brainfuck program from a file using -i <file> or directly from
an inline string with -e <code>. When -e is provided any -i option is ignored.
Inline execution works with all other flags, e.g. optimization or tape settings.
printf 'A' | ./goof2 -e ',.'
./goof2 -e '+++' -noptThe VM supports selectable cell widths. Use the --cw option to choose 8-, 16-, 32- or 64-bit
cells at startup:
./goof2 --cw 64 program.bfAdd --profile to measure execution time and instruction count:
./goof2 --profile program.bfSelect a memory allocation strategy with -mm <contiguous|fibonacci|paged|os>. If omitted,
the VM chooses a model heuristically.
Run a Brainfuck program from a file:
./goof2 -i hello.bfExecute inline code and collect profiling data:
./goof2 -e ',.' --profileUse 16-bit cells with the paged memory model:
./goof2 -i program.bf --cw 16 -mm pagedCompiled programs are cached in memory to speed up repeated executions. The cache reserves space for roughly 64 entries up front and evicts the least recently used entry when the limit is exceeded.
The virtual machine grows its cell tape using several strategies:
- Contiguous doubles the allocation each time more space is needed.
- Fibonacci expands according to the Fibonacci sequence to balance memory usage against allocation frequency.
- Paged adds memory in fixed 64 KB pages.
- OS-backed reserves memory from the operating system using virtual memory facilities. This model is used only when such APIs are available and otherwise falls back to the contiguous model.
Use the -mm flag to select a model explicitly.
This project is licensed under the terms of the GNU Affero General Public License v3.0 or later. It includes third-party components under separate licenses:
- linenoise-ng (BSD-2-Clause), included via git submodule; see
linenoise-ng/LICENSE - simde (MIT and CC0), included via git submodule; see
simde/COPYING - xxhash (BSD-2-Clause), included via git submodule; see
xxhash/LICENSE