BFInterpreter
Eight instructions. One tape. No mercy.

A machine with eight moving parts.

BFInterpreter runs programs written in Brainfuck — the esoteric language whose entire vocabulary fits on one hand: move, increment, decrement, print, read, loop. Tape size, cell width, and overflow behaviour are all yours to configure.

Releases, changelogs, and packaged builds live on GitLab.

Hello, World! — example.bf
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.
+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

The instruction set, in full

Eight characters. Everything else in the source is a comment, so you can write prose right next to the code and the machine will skip over it.

SymbolNameEffect
>shift rightMove the data pointer one cell to the right.
<shift leftMove the data pointer one cell to the left.
+incrementAdd one to the byte under the pointer.
-decrementSubtract one from the byte under the pointer.
.outputPrint the byte under the pointer as a character.
,inputRead one character and store it under the pointer; once input runs out, this stores zero.
[loop startIf the byte under the pointer is zero, jump forward past the matching ].
]loop endIf the byte under the pointer is nonzero, jump back to the matching [.

Install and run

A single Python file, no dependencies. Grab it from the release page above, then run it however suits you.

# run a program file brainfk example.bf # run code inline brainfk -e "++++++++[>++++<-]>." # feed input to ',' brainfk -i "hello" cat.bf # no file, no -e: drop into the interactive REPL brainfk

How the machine is built

One tape, one pointer, one instruction at a time. No hidden registers, no call stack — just a strip of cells and eight ways to touch them.

The tape

A flat array of cells, all zero to start. The pointer begins at cell zero and can only move one cell at a time — there's no addressing, no jumping to an arbitrary index. Everything a program does, it does by walking there.

Wrapping

By default the machine wraps: step past the last cell and you land back on the first; increment past the top of a cell's range and it rolls back to zero. Run with --no-wrap and the same moves raise an error instead — useful if you want a program's bugs to surface immediately rather than silently corrupt neighbouring cells.

Loops

Brackets are the only control flow there is. [ and ] are matched up front, so a jump is a single lookup rather than a scan.

--tape-sizecells on the tape
--cell-sizebits per cell
--no-wrapraise instead of wrapping
-e / --executerun code passed inline
-i / --inputtext fed to ','
--versionprint the version and exit
(no file, no -e)drop into the REPL