Update
[less_retarded_wiki.git] / brainfuck.md
blobe317d31f097dbf0e9594c3126b5df07fb2f869d3
1 # Brainfuck
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 `.
15 ## Specification
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.
36 ## Implementation
38 This is a very simple [C](c.md) implementation of Brainfuck interpreter:
40 ```
41 #include <stdio.h>
43 const char program[] = ",[.-]"; // your program here
45 #define CELLS 30000
46 char tape[CELLS];
48 int main(void)
50   unsigned int cell = 0;
51   const char *i = program;
52   int bDir, bCount;
53   
54   while (*i != 0)
55   {
56     switch (*i)
57     {
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;
64       case '[':
65       case ']':
66         if ((tape[cell] == 0) == (*i == ']'))
67           break;
69         bDir = (*i == '[') ? 1 : -1;
70         bCount = 0;
71           
72         while (1)
73         {
74           if (*i == '[')
75             bCount += bDir;
76           else if (*i == ']')
77             bCount -= bDir;
78           
79           if (bCount == 0)
80             break;
81           
82           i += bDir;
83         }
84         
85         break;
86       
87       default: break;
88     }
89     
90     i++;
91   }
92   
93   return 0;
95 ```
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:
104 #include <stdio.h>
106 int main(void)
108   int c, cNext;
110   puts("#include <stdio.h>\nunsigned char m[1024];\n"
111        "char *c = m;\nint main(void) {");
113 #define NEXT { c = cNext; cNext = getchar(); }
115   NEXT NEXT
117   while (c != EOF)
118   {
119     switch (c)
120     {
121       case '>': case '<': case '+': case '-':
122       {
123         unsigned int n = 1;
125         while (cNext == c)
126         {
127           NEXT
128           n++;
129         }
131         printf("  %s %c= %u;\n",(c == '<' || c == '>') ? "c" : "*c",
132           (c == '>' || c == '+') ? '+' : '-',n);
134         break;
135       }
137       case '.': puts("  putchar(*c);"); break;
138       case ',': puts("  *c = getchar();"); break;
139       case '[': puts("  while (*c) {"); break;
140       case ']': puts("  }"); break;
141       default: break;
142     }
144     NEXT
145   }
147   puts("return 0; }");
148   return 0;
152 ## Programs
154 Here are some simple programs in brainfuck.
156 Print `HI`:
159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ . + .
162 Read two 0-9 numbers (as ASCII digits) and add them:
165 ,>,[<+>-]<------------------------------------------------.
168 ## Variants
170 TODO
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:
200 0 10 11 12 13
201            ^
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:
209 #include <stdio.h>
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
241   {
242     c++;
244     while (*c >= '0' && *c <= '9')
245     {
246       n = 10 * n + *c - '0';
247       c++;
248     }
249   }
251 #define IS_MACRO(x) ((x) >= 'A' && (x) <= 'Z')
252   c = program;
254   while (*c)                     // search for the macro definition
255   {
256     if (topLevel || (c[0] == ':' && c[1] == f))
257     {
258       c += topLevel ? 0 : 2;     // skip the beginning macro chars
260       while (*c && *c != ';')
261       {
262         if (*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
269         else if (*c == '$')
270         {
271           c++;
272           for (unsigned int i = 0; i < n; ++i)
273             IS_MACRO(*c) ? process(c,0) : putchar(*c);
274         }
276         c++;
277       }
279       return;
280     }
282     c++;
283   }
286 int main(int argc, char **argv)
288   process(program,1);
289   putchar(0);    // allows separating program on stdin from program input
290   //puts("013"); // program input may go here
291   return 0;
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):
300 :Z[-];                                        zero the cell
301 :L$<;                                         go left by n
302 :R$>;                                         go right by n
303 :XZ$+;                                        store constant n
304 :N>Z+<[Z>-<]>[<$++>Z]<;                       not
305 :CZ>Z<<$<[-$>>+>+<$<<]$>>>[-<$<<+>>$>]<;      copy
306 :F>Z<[->+<]<$<[->$>+<$<]$>>>[-<<$<+>>$>]<;    flip
307 :A>C1[-<+>]<;                                 add
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
313 main program
315 >X10   loop counter
316 >X0    first number
317 >X1    second number
320 [-             loop
321   R3
322   C1 A         copy and add
323   P > X10 .    print number and newline
324   < F < F <<   go back and shift numbers
328 which translates to:
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 [->+<]<[->+<]>>[-<<+>>]<<<]
364 which outputs:
379 ## See Also
381 - [False](false.md) (a very similar esolang)
382 - [comun](comun.md)