This document describes how the interpreter works internally.
The interpreter directly executes brainfuck source code. It is not involved in brainlite compilation. If you are using brainlite, the compiler outputs a file with brainfuck code in it which can be executed anywhere needed but can be fed into this interpreter as well.
The interpreter allocates a flat 38000-byte array at startup using malloc. This is the entire memory available to a running program.
A single integer runtime_pointer tracks the current position in this array. It starts at 0.
Memory is freed when the interpreter shuts down, or immediately before any error-triggered exit.
The interpreter() function takes a source file path. It:
source_code (a std::vector<std::string>).parse().parse() walks each character in a line one at a time. Each character is treated as a token.
If a token is not in validTokens, the interpreter prints an error and exits immediately.
If valid, the corresponding function from execTokens is dispatched via exec_func(). The variable validTokens is an unordered set and execTokens is unordered map.
collectedArgsLength is used to skip characters consumed by instructions like [...] so the outer loop does not re-process them.
| Token | Instruction |
|---|---|
+ |
Increment current cell |
- |
Decrement current cell |
> |
Move pointer right |
< |
Move pointer left |
[ |
Start loop |
] |
End loop |
. |
Print current cell as ASCII |
, |
Read one character from stdin into current cell |
Any character not in this set is an invalid token and causes an immediate exit.
right() increments runtime_pointer. If it exceeds 37999, it prints a runtime overflow error and exits.
left() decrements runtime_pointer. If it goes below 0, it prints a runtime underflow error and exits.
Loops are the most complex part of the interpreter.
When [ is encountered, the interpreter:
], tracking nested brackets with a counter.] is found on the same line, it exits with a loop-not-terminated error.[ and ].exec_func() while the current cell is non-zero.Assumption: The closing ] must be on the same line as the opening [. This is a known design constraint.
When ] is encountered outside of a loop dispatch (i.e., as a standalone token), it decrements isLooping. If isLooping is already 0, it exits with an invalid loop termination error.
The reason for this decrement logic is to support multi-layer looping.
The interpreter uses integer exit codes defined elsewhere. The ones triggered here are:
INTERPRETER_ERR_INVALID_TOKEN — unknown character encounteredINTERPRETER_ERR_RUNTIME_POINTER_UNDERFLOW — pointer went below 0 or above 37999INTERPRETER_ERR_LOOP_NOT_TERMINATED — [ with no matching ] on the same lineINTERPRETER_ERR_INVALID_LOOP_TERMINATED — ] encountered with no active loopThat covers the interpreter’s internal behavior. It is deliberately simple and makes no attempt at optimization.