English | 简体中文
An experimental Brainfuck toolchain written in Rust. It can parse and optimize BF source, translate it into freestanding C, run programs through the bundled host runtime, and build native executables.
The long-term goal is to explore writing system logic in BF and connecting it to hosted or bare-metal runtimes through BFNI (Brainfuck Native Interface).
- Supports all classic BF instructions:
+ - < > [ ] , . - Layered lexer, parser, IR, and C code generator
- 8-bit cells with wrapping arithmetic modulo 256
- Optional tape boundary checks, enabled by default
- Deterministic multi-function C translation unit output
- BFNI C ABI
- Host runtime backed by standard input and output
bf run: build and run a BF program temporarilybf build: build a native executablebf trans2c: generate freestanding C
- A stable Rust toolchain with Rust 2024 edition support
- A C11 compiler compatible with GCC/Clang command-line options for
bf runandbf build
The CLI selects the C compiler in this order:
--cc <COMMAND>- The
CCenvironment variable cc
bf trans2c only generates C and does not require a local C compiler.
Once published on crates.io, install it with:
cargo install bf-cliTo install from source, run this command from the repository root:
cargo install --path crates/bf-cliThe installed command is named bf. Cargo installs it to ~/.cargo/bin/bf by default; make sure ~/.cargo/bin is in your PATH.
Update a source installation:
cargo install --path crates/bf-cli --forceUninstall:
cargo uninstall bf-cliYou can also run it directly from the workspace without installing:
cargo run -p bf-cli --bin bf -- run examples/hello.bfRun the example:
bf run examples/hello.bfOutput:
Hello, BrainFuck!
Choose a tape length:
bf run examples/hello.bf --tape-len 65536bf build examples/hello.bf
./helloThe default output name is the stem of the BF source file. You can also set it explicitly:
bf build examples/hello.bf -o hello-bf
./hello-bfThe built host executable accepts an optional tape length:
./hello-bf 65536bf trans2c examples/hello.bfBy default, this creates examples/hello.c next to the source file. To choose an output path:
bf trans2c examples/hello.bf -o generated.cWrite the generated C to stdout:
bf trans2c examples/hello.bf -o -Generated C references BFNI with:
#include <bfni.h>The result contains freestanding BF functions rather than a standalone executable with main. Compiling the translation unit requires include/bfni.h and a runtime that implements BFNI. For example, to compile-check generated code:
cc \
-std=c11 \
-ffreestanding \
-Iinclude \
-c generated.c \
-o generated.oAll three subcommands accept a BF IR optimization level:
bf run hello.bf -O0
bf run hello.bf -O1The default is -O1. Current levels are:
-O0: disable IR optimization-O1: perform local optimizations such as merging consecutive cell changes and tape moves
Tape boundary checks are generated by default. To explicitly use unsafe mode:
bf run hello.bf --unsafeIn unsafe mode, the BF program must keep its data pointer within the tape. Out-of-bounds behavior is undefined.
- Cells are unsigned 8-bit integers
+and-wrap modulo 256- The data pointer starts at tape offset 0
- The runtime provides the tape, whose length must be greater than 0
- Initial tape contents are defined by the runtime
- The host runtime uses
calloc, so its tape starts fully zeroed - Input EOF or an I/O failure fills the report and makes the BF function return
BF_FALSE - In checked mode, moving beyond either tape boundary fills the report and returns
BF_FALSE
See include/bfni.h for the complete ABI contract.
BF source
│
▼
bf-frontend Lexer + Parser + AST
│
▼
bf-ir Lowering + IR optimization
│
▼
bf-codegen Freestanding C generation
│
├── trans2c ──> generated C + external BFNI runtime
│
└── run/build ──> embedded host runtime ──> native executable
Workspace layout:
crates/
bf-frontend/ BF lexer, parser, and AST
bf-ir/ IR, lowering, and optimizers
bf-codegen/ C code generator and public compilation API
bf-cli/ The `bf` command-line tool
include/
bfni.h Public BFNI ABI
runtime/
host/ Host runtime using stdio and a dynamic tape
examples/
hello.bf Hello example
bf run and bf build embed the current BFNI header and host runtime into the bf binary, so an installed CLI does not depend on repository paths. Rebuild or reinstall the CLI after changing the ABI or host runtime.
Run the full test suite:
cargo test --workspaceRun strict Clippy checks for the CLI:
cargo clippy -p bf-cli --bin bf --no-deps -- -D warningsView command help:
bf --help
bf run --help
bf build --help
bf trans2c --helpThis is an experimental project. The CLI, generated C ABI, and internal IR may still change. The current host runtime is intended for native validation; bare-metal boot, device drivers, interrupts, and scheduling are not implemented yet.
Internal crates must be published in dependency order. During the first release, a downstream dry run can only succeed after its upstream dependencies have been published and propagated through the crates.io index:
bf-frontend -> bf-ir -> bf-codegen -> bf-cli
Starting with bf-frontend, run a dry run, publish the package, and then continue with the next layer:
cargo publish -p bf-frontend --dry-run
cargo publish -p bf-frontendBefore publishing, make sure the workspace tests and Clippy checks pass. A version already published on crates.io cannot be overwritten, so every subsequent release requires a version bump.
Apache License 2.0. See LICENSE.