Brainfuck part 3: a brainfuck → JavaScript transpiler
This article is part of a series on brainfuck, a weird programming language:
- Brainfuck part 1: what is it?
- Brainfuck part 2: an interpreter in JavaScript
- Brainfuck part 3: a brainfuck → JavaScript transpiler
Goal
In the last article of this series on brainfuck, I will write a brainfuck → JavaScript transpiler. Instead of interpreting each brainfuck instruction, it will be converted into a JS function once and for all.
Basics
The compiler will be a simple function, taking the brainfuck code as first parameter and returning the corresponding JS function.
1 | var bf = function(code){ |
At some point, we will have a javascript source code. It will be turned
into a function with eval
.
1 | var bf = function(code){ |
Exactly like with the interpreter, we need some place to store the cells: an array.
We also needs pointers. One for the memory, and one
for the input. We don’t need a code pointer anymore.
I also added the out
variable. This is the output string, it’s what
the brainfuck_function will return at the end.
1 | var bf = function(code){ |
Then, we read the code character by character and translate the instructions in JavaScript.
1 |
|
Let’s transpile!
>
move the data pointer forward<
move the data pointer backward+
increments (+1) the current cell-
decrements (-1) the current cell
Cases >
and <
are obvious (mem_ptr++/--;
). +
and -
are simple
too. Since the memory isn’t initialized, we can’t just do mem[mem_ptr]++/--;
.
Instead, we ensure the cell is set to zero: mem[mem_ptr] = (mem[mem_ptr] || 0) +/- 1;
1 | case '>': |
.
outputs the current cell as an ASCII character,
reads one character from the input and writes it in the current cell
.
and ,
are not much complex. .
converts the cell value to the
corresponding character (ascii) and outputs it. The cell may be empty,
we use 0 as the default value.
Reading from the input is as easy. The only thing not to forget is to
increment the input pointer.
1 | case '.': |
[
makes the program jump to the instruction after the matching]
if the current cell’s value is 0.]
makes the program jump to the instruction after the matching[
if the current cell’s value is not 0.
[
and ]
are a lot simpler to write in the transpiler case since we
can use a while loop!
1 | case '[': |
A lot simpler indeed!
Before putting everything together, let’s add a little thing (brainfuck’s memory is supposed to be 30000 cells wide).
1 | js_code.push( |
Complete transpiler
1 | var bf = function(code){ |
Examples
1 |
|
The bf()
function is included in this page so you can open your
javascript console and test it yourself!
Conclusion
I hope you liked this little exercise, now you can forget all about it.
This article is part of a series on brainfuck, a weird programming language: