Brainf*
Language overview
- Brainf* instructions are as follows:
| Instruction | Description |
|---|---|
+ | Increment the current memory cell |
- | Decrement the current memory cell |
< | Move the data pointer to the left |
> | Move the data pointer to the right |
. | Output the value of the current memory cell as a character |
, | Input a character and store its value in the current memory cell |
[ | Jump to the instruction after the matching ] if the value in the current memory cell is zero |
] | Jump to the instruction after the matching [ if the value in the current memory cell is non-zero |
Implementations
we currently have two implementations of the brainf* esoteric programming language:
Compiler
- this is the most efficient way to run brainf* programs on the DSA architecture, but of course, still terribly inefficient due to the nature of the language.
- compiling allows us to calculate the jump addresses at compile time, therefore making each brainf* instruction take at maximum three DSA instructions to execute
Interpreter
- this method is much slower, with even jumping to the start of a loop having an O(n) time complexity, which depending on the complexity of the program can up to double the running time.
- additionally, interpreting the language means much more logic is required at runtime relative to compiling.
- from our testing on a few example programs such as a fibonacci sequence generator, the interpreter is several orders of magnitude slower, with the fibonacci generator beingabout 10 times slower than it's compiled equivalent, at around 3.8 million instructions to generate and pretty-print the first 16 fibonacci numbers, compared to around 350,000 for the compiled version, which we estimate is about as efficient as brainf* can be on our architecture without writing an optimiser.
Usage
Compiling
- currently The DSA Assembler supports compiling brainf* programs, with the following command:
<assembler binary name> -brainf