Brainfuck is one of the most iconic programming languages out there, and probably the king of esolangs. So today, I will share how to create Brainfuck.
Understanding Brainfuck
So as we all might have known, Brainfuck has 8 commands:
- ">" increment the data pointer (to point to the next cell to the right).
- "<" decrement the data pointer (to point to the next cell to the left).
- "+" increment (increase by one) the byte at the data pointer.
- "-" decrement (decrease by one) the byte at the data pointer.
- "." output the byte at the data pointer.
- "," accept one byte of input, storing its value in the byte at the data pointer.
- "[" if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.
- "]" if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command.
Choosing a way to run our code
Normally, you would have these programs to execute a programming language's codes:
- Compiler (compiles to machine code)
- Interpreter
- Transpiler (compiles to source code)
Compilers are quite complex and they require you to have machine code's understanding which is not our choice when just creating a simple esolang. Interpreters and transpilers are good ones since they are easy to create, especially for esolangs. In this article, I will create a transpiler as it's the easiest.
Creating a transpiler
Language to use
I will use Javascript to create the transpiler, and the compilation target will be Javascript as well. Now, let's get our hand dirty.
Create a transpile function
We just simply create a function which takes all the codes as input
, and return the compiled codes to output
.
const transpile = input => {
let output = 'let cells = Array(30000).fill(0), ptr=0;';
return output;
}
The output
variable already has 1 line to declare an array cells
which has 30000 elements all start at 0 and a ptr
variable which is the pointer of the cell.
Parsing commands
We can create a simple lexer like this:
const transpile = input => {
let output = 'let cells = Array(30000).fill(0), ptr=0;';
input.split('').forEach(token => {
})
return output;
}
Now, we want to do stuffs which each token (command), we just need to add a switch statement:
const transpile = input => {
let output = 'let cells = Array(30000).fill(0), ptr=0;';
input.split('').forEach(token => {
switch (token) {
case '+':
break;
case '-':
break;
case '>':
break;
case '<':
break;
case '.':
break;
case ',':
break;
case '[':
break;
case ']':
break;
}
})
return output;
}
Then, we just implement each token's functionality in JS:
const transpile = input => {
let output = 'let cells = Array(30000).fill(0), ptr=0;';
input.split('').forEach(token => {
switch (token) {
case '+':
output+='++cells[ptr];';
break;
case '-':
output+='--cells[ptr];';
break;
case '>':
output+='++ptr;';
break;
case '<':
output+='--ptr;';
break;
case '.':
output+='document.write(String.fromCharCode(cells[ptr]));';
break;
case ',':
output+='cells[ptr]=prompt();';
break;
case '[':
output+='while (cells[ptr] > 0) {';
break;
case ']':
output+='}';
break;
}
})
return output;
}
There you go, that's how you can create a Brainfuck transpiler, you just need to take the output codes and run them in a browser, then it should work fine.
Running it immediately
If you're tired of copying the output codes and run it in a different place, you can create a version that runs the code immediately like this:
const transpile = input => {
let output = 'let cells = Array(30000).fill(0), ptr=0;';
input.split('').forEach(token => {
switch (token) {
case '+':
output+='++cells[ptr];';
break;
case '-':
output+='--cells[ptr];';
break;
case '>':
output+='++ptr;';
break;
case '<':
output+='--ptr;';
break;
case '.':
output+='document.write(String.fromCharCode(cells[ptr]));';
break;
case ',':
output+='cells[ptr]=prompt();';
break;
case '[':
output+='while (cells[ptr] > 0) {';
break;
case ']':
output+='}';
break;
}
})
new Function(output)();
}
Basically, we just create a new function and execute the codes.
Thanks for your time, if you're interested in programming languages, please consider checking out my language "FreakC".