Some time ago, I wrote an interpreter for the language brainfuck. It's nice and all, but I thought, "you know what would really make this great? More inscrutable instructions!" How to extend it, though? It already has such a great feature set. You may remember it from hits such as:
- Hilarious-looking source code!
- Turing completeness!
- It somehow manages ultra-verbosity in a language with only 8 valid characters.
Despite that saliva-inducing list, one item you can never get enough of in computing is recursion. So let's add functions! Brainfuck already has an array of data cells, let's expand that to an array of functions to call as well.
Official brainfunction v0.1 spec (subject to revision):
The official brainfunction repository can be found at https://github.com/ryanfox/brainfunction.
A brainfunction program runs on the brain, which is an extended version of the brainfuck VM. It supports the eight standard brainfuck symbols, instruction pointer, data tape, and data pointer. In addition to this, it has an array of functions. When a brainfunction program is parsed, each line of text in the source file becomes a function. These constitute the function array, starting with the first line of text in position 0. A function is exactly one line of source code. This implies one cannot break up logical units multiple lines as is done in brainfuck.
Each function has a function pointer, initialized to 0 (the first line in the file). The function pointer is moved by
^, meaning "move the function pointer down" and "move the function pointer up", respectively.
Each function also has a local data pointer, data tape, and instruction pointer.
To call another function, the
: symbol is used. When this occurs, the function pointed to by the current function
pointer is called. The value in the caller's current data cell is passed to the callee. This argument is placed in
cell 0 of the callee's data tape.
A function returns when the symbol
; is encountered or the function runs out of instructions. When a function
returns, the value in the current data cell is returned. The return value is placed in the caller's current data cell.
The brain begins execution in the zeroth function in the function array, and continues until an error is encountered or the function runs out of symbols. All symbols except the 12 specified are ignored. When a function calls another, execution blocks in the caller until the callee returns.
The reference implementation is an interpreter written in python, which can be found here.
Example hello world:
v:vv:^^:vv:^:v:^:v:^:vv: >++++++++++[>++++++++++<-]>++++.---.+++++++..+++. print hello >++++++++++++[>++++++++++<-]>-.--------.+++.------.--------. print world >++++[>++++++++<-]>. print space character >++++[>++++++++<-]>+. print !
When executed, this will print
hello hello world world world!
Example factorial calculator:
+v[,------------------------------------------------:v:v:^^] [[>+>+<<-]>>-v:<[>[>+>+<<-]>[<+>-]<<-]>>>;]+ [>>+>+<<<-]>>>[<<<+>>>-]<<+>[<->[>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]++++++++[<++++++>-]>[<<+>>-]>[<<+>>-]<<]>]<[->>++++++++[<++++++>-]]<[.[-]<]< >++++++++++.<
When executed, this will prompt the user for input (limited to a single character), calculate the factorial of that number, and print the output:
bf > 5 120
Future developments may include real error messages, and perhaps a debugger, to make it easy to inspect the state of the brain. Maybe even zanier symbols!
That's it! Look on my works, ye mighty, and despair!