3 Brainfuck is an extremely simple, [minimalist](minimalism.md) untyped [esoteric programming language](esolang.md); simple by its specification (consisting only of 8 commands) but very hard to program in (it is so called [Turing tarpit](turing_tarpit.md)). It works similarly to a pure [Turing machine](turing_machine.md). In a way it is kind of [beautiful](beauty.md) by its [simplicity](minimalism.md), it is very easy to write your own brainfuck [interpreter](interpreter.md) (or [compiler](compiler.md)) -- in fact the Brainfuck author's goal was to make a language for which the smallest compiler could be made.
5 There exist **[self-hosted](self_hosting.md) Brainfuck interpreters and compilers** (i.e. themselves written in Brainfuck) which is pretty fucked up. The smallest one is probably the one called [dbfi](dbfi.md) which has only slightly above 400 characters, that's incredible!!! (Esolang wiki states that it's one of the smallest self interpreters among imperative languages). Of course, **Brainfuck [quines](quine.md)** (programs printing their own source code) also exist, but it's not easy to make them -- one example found on the web was a little over 2100 characters long.
7 The language is based on a 1964 language P´´ which was published in a mathematical paper; it is very similar to Brainfuck except for having no [I/O](io.md). Brainfuck itself was made in 1993 by Urban Muller, he wrote a compiler for it for Amiga, which he eventually managed to get under 200 bytes.
9 Since then Brainfuck has seen tremendous success in the [esolang](esolang.md) community as the **lowest common denominator language**: just as mathematicians use [Turing machines](turing_machine.md) in proofs, esolang programmers use brainfuck in similar ways -- many esolangs just compile to brainfuck or use brainfuck in proofs of [Turing completeness](turing_complete.md) etc. This is thanks to Brainfuck being an actual, implemented and working language with I/O and working on real computers, not just some abstract mathematical model. For example if one wants to encode a program as an integer number, we can simply take the [binary](binary.md) representation of the program's Brainfuck implementation. Brainfuck also has many derivatives and modifications (esolang wiki currently lists over 600 such languages), e.g. [Brainfork](brainfork.md) (Brainfuck with [multithreading](multithreading.md)), Boolfuck (has only binary cells), Brainfuck++ (adds more features like [networking](network.md)), Pi (encodes Brainfuck program in error agains [pi](pi.md) digits), Unary (encodes Brainfuck with a single symbol) etcetc.
11 In [LRS](lrs.md) programs brainfuck may be seriously used as a super simple [scripting language](script.md).
13 Brainfuck can be trivially translated to [comun](comun.md) like this: remove all comments from brainfuck program, then replace `+`, `-`, `>`, `<`, `.`, `,`, `[` and `]` with `++ ` , `-- `, `$>0 `, `$<0 `, `->' `, `$<0 <- `, `@' ` and `. `, respectively, and prepend `$>0 `.
17 The "vanilla" brainfuck operates as follows:
19 We have a linear memory of **cells** and a **data pointer** which initially points to the 0th cell. The size and count of the cells is implementation-defined, but usually a cell is 8 bits wide and there is at least 30000 cells.
21 A program consists of these possible commands:
23 - `+`: increment the data cell under data pointer
24 - `-`: decrement the data cell under data pointer
25 - `>`: move the data pointer to the right
26 - `<`: move the data pointer to the left
27 - `[`: jump after corresponding `]` if value under data pointer is zero
28 - `]`: jump after corresponding `[` if value under data pointer is not zero
29 - `.`: output value under data pointer as an ASCII character
30 - `,`: read value and store it to the cell under data pointer
32 Characters in the source code that don't correspond to any command are normally ignored, so they can conveniently be used for comments.
34 Brainfuck source code files usually have *.bf* or *.b* extension.
38 This is a very simple [C](c.md) implementation of Brainfuck interpreter:
43 const char program[] = ",[.-]"; // your program here
50 unsigned int cell = 0;
51 const char *i = program;
58 case '>': cell++; break;
59 case '<': cell--; break;
60 case '+': tape[cell]++; break;
61 case '-': tape[cell]--; break;
62 case '.': putchar(tape[cell]); fflush(stdout); break;
63 case ',': scanf("%c",tape + cell); break;
66 if ((tape[cell] == 0) == (*i == ']'))
69 bDir = (*i == '[') ? 1 : -1;
97 TODO: comun implementation
99 Advanced Brainfuck implementations may include [optimizations](optimization.md), for example things like `>>><<>` may be reduced to `>>` etc.
101 And here is a Brainfuck to C transpiler, written in C, which EVEN does the above simple optimization of grouping together additions, subtractions and shifts. It will allow you to compile Brainfuck to native executables. The code is possibly even simpler than the interpreter:
110 puts("#include <stdio.h>\nunsigned char m[1024];\n"
111 "char *c = m;\nint main(void) {");
113 #define NEXT { c = cNext; cNext = getchar(); }
121 case '>': case '<': case '+': case '-':
131 printf(" %s %c= %u;\n",(c == '<' || c == '>') ? "c" : "*c",
132 (c == '>' || c == '+') ? '+' : '-',n);
137 case '.': puts(" putchar(*c);"); break;
138 case ',': puts(" *c = getchar();"); break;
139 case '[': puts(" while (*c) {"); break;
140 case ']': puts(" }"); break;
154 Here are some simple programs in brainfuck.
159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ . + .
162 Read two 0-9 numbers (as ASCII digits) and add them:
165 ,>,[<+>-]<------------------------------------------------.
170 Brainfuck became an inspiration to a plethora of derivative languages (esolang wiki currently lists over 700) many of which pay homage to their ancestor by including the word *fuck* in the name. Oftentimes we see extensions adding new features or languages that just translate to Brainfuck, i.e. are defined in terms of Brainfuck. Some of notable Brainfuck derivatives include: Fuck (only has a single memory cell), Brainfork (adds [multithreading](multithreading.md) with new command `Y`), [Unary](unary.md) (program source code only uses one character, compiled to BF), Mierda (just replaces the commands with Spanish words), Brainfuck++, Agony etc.
172 ## Making Brainfuck Usable: Defining Macrofucker
174 { There probably exist BF derivatives in this spirit, it's very natural, I didn't bother checking too much, here I just want to derive this from scratch myself, for educational purposes. ~drummyfish }
176 What if we want to actually write a more complex program in Brainfuck? How do we tame the beast and get out of the Turing tarpit? We may build a metalanguage on top of Brainfuck that will offer more convenient constructs and will compile to Brainfuck, and maybe we'll learn something about building and [bootstrapping](bootstrap.md) computing environments along the way :) We may do this e.g. with a simple system of [preprocessing](preprocessing.md) [macros](macro.md), i.e. we will create a language with more advanced commands that will be replaced by plain Brainfuck commands -- on the level of source code -- before it gets executed. This turns out to be a quite effective approach that enables us to create sort of a [Forth](forth.md)-like language in which we may program quite complex things with the stack-based computing [paradigm](paradigm.md).
178 Hmmm okay, what name do we give the language? Let's call it **Macrofucker**. It will work like this:
180 - Vanilla Brainfuck commands work normally, they'll be simply copied.
181 - Additionally we introduce macros. A macro will be defined as: `:M<commands>;`. `:` and `;` are simply keywords separating the macro definition, `M` is the macro name, which we'll for simplicity sake limit to single uppercase letters only (so we won't be able to make more macros than there are letters), and `<commands>` are just commands that will be copy-pasted wherever the macro is used.
182 - A macro will be used by simply writing its name, i.e. if we have macro `M` defined (anywhere in the source code), we can use it by simply writing `M`. Optionally we may call it with numeric parameter as `MX`, where `X` is a decimal number. If no parameter is given, we consider it 0. Macro may be invoked even inside another macro.
183 - Inside a macro definition we may use the symbol `$` that will make the next character be repeated the macro's argument number of times -- i.e. if the macro was called with let's argument 3, then `$>` will output `>>>`. This symbol can also be used in the same sense in front of macro invocation.
185 For example consider the following piece of code:
188 :X[-]$+; >X10 >X11 >X12 >X13
191 We first define macro called `X` that serves for storing constants in cells. The macro first zeroes the cell (`[-]`) and then repeats the character `+` the argument number of times. Then we use the macro 4 times, with constants 10, 11, 12 and 13. We also shift right before each macro invocation so it's as if we're pushing the constants on the stack. This code will compile to:
194 >[-]++++++++++>[-]+++++++++++>[-]++++++++++++>[-]+++++++++++++
197 If we examine and run the code, we indeed find that we end up with the values 10, 11, 12 and 13 on the tape:
204 Implementing the preprocessor is about as simple as implementing Brainfuck itself: pretty easy. As soon as we have the preprocessor, we may start implementing a "[library](library.md)" of macros, i.e. we may expand Brainfuck by adding quite powerful commands -- the [beauty](beauty.md) of it is we'll be expanding the language in Macrofucker itself from now on, no more C code is required beyond writing the simple preprocessor. This is a very cool, [minimalist](minimalism.md) approach of building complex things by adding simple but powerful extensions to very simple things, the kind of incremental programming approach that's masterfully applied in languages such as [Forth](forth.md) and [Lisp](lisp.md).
206 So here it is, the Macrofucker preprocessor in C, along with embedded code of the program it processes -- here we include simple library that even includes things such as division, modulus and printing and reading decimal values:
211 const char program[] =
212 // the library (WARNING: cells to the right may be changed):
213 ":Z[-];" // zero: c[0] = 0
214 ":L$<;" // left: c -= N
215 ":R$>;" // right: c += N
216 ":I$+;" // inc: c[0] += N
217 ":D$-;" // dec: c[0] -= N
218 ":XZ$+;" // const: c[0] = N
219 ":N>Z+<[Z>-<]>[<$++>Z]<;" // not: c[0] = c[0] == 0 ? N + 1 : 0
220 ":CZ>Z<<$<[-$>>+>+<$<<]$>>>[-<$<<+>>$>]<;" // copy: c[0] = c[-(N + 1)]
221 ":M>C<Z>[-<$-->]<;" // minus: c[0] *= -(N + 1)
222 ":F>Z<[->+<]<$<[->$>+<$<]$>>>[-<<$<+>>$>]<;" // flip: SWAP(c[0],c[-(N + 1)])
223 ":A>C1[-<+>]<;" // add: c[0] += c[-1]
224 ":S>C1[-<->]<;" // subtract: c[0] -= c[-1]
225 ":T>C1>C1>Z<<-[->>A<<]>>[-L3+R3]L3;" // times: c[0] *= c[-1]
226 ":EC1>C1[-<->]<N;" // equals: c[-2] == c[-1] ? 1 : 0
227 ":GZ>C2>C2+<[->->CN[L3+R3Z]<<]<;" // greater: c[-1] > c[0] ? 1 : 0
228 ":B>C1>C1<<Z>>>GN[L3+>>S>GN]<F<;" // by: c[1] = c[0] % c[-1]; c[0] = c[0] / c[-1]; c++
229 ":P>X100>C1BF>X48A.L3X10>BF>X48A.<F>X48A.L4;" // print: print byte as decimal
230 ":VX48>,SFX100T>X48>,SFX10TF<A>X48>,SF<AF2L3;" // value: reads decimal number of three digits
231 // the main program itself:
232 "Z>V>C[>C1BN[L4+R4Z]<<-]<<P>X10.X2>E[X112.X114.X105.X109.X101.X10.Z]"
235 void process(const char *c, int topLevel)
237 char f = *c; // macro name to search
238 unsigned int n = 0; // macro argument
240 if (!topLevel) // read the argument
244 while (*c >= '0' && *c <= '9')
246 n = 10 * n + *c - '0';
251 #define IS_MACRO(x) ((x) >= 'A' && (x) <= 'Z')
254 while (*c) // search for the macro definition
256 if (topLevel || (c[0] == ':' && c[1] == f))
258 c += topLevel ? 0 : 2; // skip the beginning macro chars
260 while (*c && *c != ';')
263 while ((*++c) != ';'); // skip macro definitions
264 else if (*c == '+' || *c == '-' || *c == '<' || *c == '>' ||
265 *c == '[' || *c == ']' || *c == '.' || *c == ',')
266 putchar(*c); // normal BF commands
267 else if (IS_MACRO(*c))
268 process(c,0); // macro
272 for (unsigned int i = 0; i < n; ++i)
273 IS_MACRO(*c) ? process(c,0) : putchar(*c);
286 int main(int argc, char **argv)
289 putchar(0); // allows separating program on stdin from program input
290 //puts("013"); // program input may go here
295 The main program we have here is the example program from the [algorithm](algorithm.md) article: it reads a number, prints the number of its divisors and says if the number is [prime](prime.md). Code of the Brainfuck program will be simply printed out on standard output and it can then be run using our Brainfuck interpreter above. Unlike "hello world" this is already a pretty cool problem we've solved with Brainfuck, and we didn't even need that much code to make it happen. Improving this further could allow us to make a completely usable (though, truth be said, probably slow) language. Isn't this just beautiful? Yes, it is :)
297 So just for completeness, here is a Macrofucker program that prints out the first 10 [Fibonacci numbers](fibonacci_number.md):
303 :XZ$+; store constant n
304 :N>Z+<[Z>-<]>[<$++>Z]<; not
305 :CZ>Z<<$<[-$>>+>+<$<<]$>>>[-<$<<+>>$>]<; copy
306 :F>Z<[->+<]<$<[->$>+<$<]$>>>[-<<$<+>>$>]<; flip
308 :S>C1[-<->]<; subtract
309 :GZ>C2>C2+<[->->CN[L3+R3Z]<<]<; greater
310 :B>C1>C1<<Z>>>GN[L3+>>S>GN]<F<; divide
311 :P>X100>C1BF>X48A.L3X10>BF>X48A.<F>X48A.L4; print
323 P > X10 . print number and newline
324 < F < F << go back and shift numbers
331 >[-]++++++++++>[-]>[-]+<<[->>>[-]>[-]<<<[->>+>+<<<]>>>[-<<<
332 +>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+>]<>[-]++++++
333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
334 +++++++++++++++++++++++++++++++++++>[-]>[-]<<<[->>+>+<<<]>>
335 >[-<<<+>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<>[-]>[-]<<<
336 [->>+>+<<<]>>>[-<<<+>>>]<<<[-]>>>[-]>[-]>[-]<<<<[->>>+>+<<<
337 <]>>>>[-<<<<+>>>>]<>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>
338 ]<+<[->->[-]>[-]<<[->+>+<<]>>[-<<+>>]<>[-]+<[[-]>-<]>[<+>[-
339 ]]<[<<<+>>>[-]]<<]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]>[-]<
340 <<[->>+>+<<<]>>>[-<<<+>>>]<[-<->]<>[-]>[-]>[-]<<<<[->>>+>+<
341 <<<]>>>>[-<<<<+>>>>]<>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>
342 >>]<+<[->->[-]>[-]<<[->+>+<<]>>[-<<+>>]<>[-]+<[[-]>-<]>[<+>
343 [-]]<[<<<+>>>[-]]<<]<>[-]+<[[-]>-<]>[<+>[-]]<]<>[-]<[->+<]<
344 [->+<]>>[-<<+>>]<<>[-]<[->+<]<[->+<]>>[-<<+>>]<>[-]++++++++
345 ++++++++++++++++++++++++++++++++++++++++>[-]>[-]<<<[->>+>+<
346 <<]>>>[-<<<+>>>]<[-<+>]<.<<<[-]++++++++++>>[-]>[-]<<<[->>+>
347 +<<<]>>>[-<<<+>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<<<[-
348 ]>>>[-]>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<>[-]>[-]<<
349 <<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<+<[->->[-]>[-]<<[->+>+<<]>>
350 [-<<+>>]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]]<<]<>[-]+<[[-]
351 >-<]>[<+>[-]]<[<<<+>>>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-
352 <->]<>[-]>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<>[-]>[-]
353 <<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<+<[->->[-]>[-]<<[->+>+<<]
354 >>[-<<+>>]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]]<<]<>[-]+<[[
355 -]>-<]>[<+>[-]]<]<>[-]<[->+<]<[->+<]>>[-<<+>>]<<>[-]<[->+<]
356 <[->+<]>>[-<<+>>]<>[-]+++++++++++++++++++++++++++++++++++++
357 +++++++++++>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+>]<.<>[-
358 ]<[->+<]<[->+<]>>[-<<+>>]<>[-]+++++++++++++++++++++++++++++
359 +++++++++++++++++++>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+
360 >]<.<<<<>[-]++++++++++.<>[-]<[->+<]<[->+<]>>[-<<+>>]<<>[-]<
361 [->+<]<[->+<]>>[-<<+>>]<<<]
381 - [False](false.md) (a very similar esolang)