Click here to Skip to main content
Click here to Skip to main content
Go to top

BrainFix, the language that translates to fluent Brainfuck

, 8 Mar 2013
Rate this:
Please Sign up or sign in to vote.
This article describes how to program in the BrainFix language and how to compile your programs to Brainfuck.
This is an old version of the currently published article.

Introduction to BrainFuck

BrainFuck is an esoteric programming language devised by Urban Müller in 1993. It is a Turing Complete language, because it provides sufficient tools to solve any computational task. However, it can also be called a true Turing tar-pit, in that it is of no actual practical use despite the fact that it is so easy to learn. The reason it is so easy to learn is mainly due to its simplicity: only 8 operations are defined by the language, resembling the workings of a Turing Machine. An (infinite) array is assumed, together with a pointer to some element of the array. The operations that can now be performed are the following (the equivalent C-code displayed between parentheses):

  • > Move the pointer one position to the right. (++ptr;)
  • < Move the pointer one position to the left. (--ptr;)
  • + Increment the value pointed to by 1. (++*ptr;)
  • - Decrement the value pointed to by 1. (--*ptr;)
  • . Print the value in the current cell to the output. (putchar(*ptr);)
  • , Read a value from the input and store it in the current cell. (*ptr = getchar();)
  • [ If the current value is zero, the program skip the code between [ and ]. (while (*ptr) {)
  • ] Program flow will move back to the corresponding ] (}).

Background

The language described below was defined using Bisonc++ and Flexc++ by Frank B. Brokken.

Introduction to BrainFix

It is a difficult task to write complex algorithms using the limited toolset offered by BrainFuck, so and intermediate language was designed to be able to translate readable source-code to (almost) unreadable BrainFuck code. I have called this language BrainFix, as it fixes the impracticalities of the BrainFuck but still produces valid code. The language inherits its syntax from Matlab, C, and Python. A complete program must at least have a main() function defined in one of its source-files. The smallest possible BrainFix program, that does nothing at all, is the following:

function main() {}

The function body may contain expressions that are built from variables, keywords, constants, operators and function-calls and are terminated by a semicolon (;). Each of these features is discussed in the coming sections. If this manual came with a package distributed by myself, the examples are included as .bfx files. If not, you can easily copy and paste the code yourself!

Hello World

Let us start with the classical “Hello World!” example. BrainFix supports string literals. This allows us to print strings to the standard output using the prints keyword, as illustrated below. In order to print a newline, the escape sequence \n can be embedded in the string (as of version 0.41).

/* hello.bfx */  
 
function main()  
{  
    prints "Hello World!\n";  
}

Printing

There are four different print keywords in BrainFix: print, printc, printd, prints. In the previous section, we have already seen how to print strings using the prints keyword, and how to print a newline using an escape character. The print and printc commands print the character representation (according to your system’s locale) of the expression it is being passed. Therefore one could also use printc 10; to print a newline. The printd command will print the decimal value of the expression, but it only supports 3 digits. The BrainFuck language assumes an array of single bytes, therefore 3 digits should be enough to print all output.

Scanning

Using the scan keyword, a value is read from standard input, and stored in the variable passed to the scan command (e.g. scan x;). It is currently only possible to scan decimal values.

Variables and Keywords

The variables in BrainFix start with a letter (lower- or uppercase), followed by any number of alphanumerics (no underscores). They need not be declared or allocated and their type is deduced by the compiler. BrainFix can handle three types of variables: integers/characters, string-literals and arrays. Integers and characters (between single quotes, e.g., 'a') are treated exactly the same, and string-literals are just a special case of array: an array of characters with a terminating 0-character. Only positive integer values are supported. Negative values will not be recognized by the parser and subtractions that would otherwise result in negative values will now result in 0. A value is parsed as a string when it appears within double quotes (as illustrated in the “Hello World!” example). Of course, the BrainFix keywords listed below may not be used as variables.

Escape sequences can be used to print characters that have a special meaning in the BrainFix language. For example, in order to print double quotation-marks within a string, one can do the following:

prints "Hello \"World\"!\n";

When the escaped character has no special meaning, its regular representation is used (e.g. \j is parsed as j).

Keywords:

print   printc  printd
prints  scan    if
else    for     array

Functions

A BrainFix program consists of functions, one of which must be named main. This is the function that is executed when the program is started. From main(), other functions can be called that are defined in either the same sourcefile or another. When the other function is defined in a different sourcefile than main(), be sure to pass this file to the BrainFix compiler (bfx). Functions may receive arguments (by value) and are able to return computed values through the following syntax (expressions within brackets are optional):

function [return-variable =] functionName([arg1, arg2, ...])  
{  
    // ... body  
}

A function-call is essentially inlined by the compiler, so it is not supported to call a function recursively. The compiler will report an error when a function appears more than once on the function-call-stack. In the example below, the “Hello World!” program from before is adapted to involve a function-call (without a return-value):

/* hellofunction.bfx */  
 
function main()  
{  
    hello("World");  
}  
 
function hello(who)  
{  
    prints "Hello ";  
    prints who;  
    prints "!\n";  
}

Comments

BrainFix supports two types of comments: end-of-line comments and C-style comments. EOL comments start at // and end at, of course, the end of the line. C-style comments are delimited by /* and */ respectively. All commented text will be ignored by the compiler.

Operators

Currently the language supports the following operators: =, +, -, *, /, % and their corresponding assignment-operators (e.g. +=). It also contains the common comparison operators <, >, ==, !=, <=, >= and logical AND (&&) and OR (||) to allow for more complex conditionals. Below is listed an example illustrating the use of the common arithmetical operators. The use of the conditional operators is shown in the next section (Flow Constructs).

/* arithmetic.bfx */  
 
function main()  
{  
    scan x; // read an integer value from stdin into the variable x  
    scan y; // same for y  
 
    z = 2 * (x + y) * (x % y); // compute the value and assign to z  
    printd z;   // print the decimal value of z  
    print ’\n’; // print a newline  
}

Flow Control

BrainFix supports flow control to a certain extent by implementing for-loops and if-else conditionals. The syntax of these constructs resembles MATLAB in the sense that no parentheses are required around if-conditions, and the range of the for is indicated using start:step:stop. The specification of a step value is optional and if omitted, it will be set to 1. The body of a for, if or else can contain only a single expression, or a compound statement between { and }.

/* flow.bfx */  
 
function main()  
{  
    // Get x and y from input  
    x = get("x");  
    y = get("y");  
 
    // Compare the two  
    compare(x, y);  
 
    // See if one or both were 0  
    zero(x, y);  
 
    // Print the alphabet  
    printSequence(’a’, ’z’);  
}  
 
function x = get(name)  
{  
    prints "enter ";  
    prints name;  
    prints ": ";  
    scan x;  
}  
 
function compare(x, y)  
{  
    more = "x is greater than y\n";  
    less = "x is less than y\n";  
    same = "x is equal to y\n";  
 
    if x < y  
        prints less;  
    else if x == y  
        prints same;  
    else if x > y  
        prints more;  
}  
 
function zero(x, y)  
{  
    if x == 0 && y == 0  
        prints "Both x and y are zero.\n";  
    else if x != 0 && y == 0  
        prints "x was not zero, but y was.\n";  
    else if x == 0 && y != 0  
        prints "y was not zero, but x was.\n";  
    else  
        prints "neither x nor y was zero.\n";  
}  
 
function printSequence(start, stop)  
{  
    for i = start:stop  
        print i;  
    print ’\n’;  
}

Arrays

As of version 0.32, the language supports arrays of which the size is known compile-time (statically allocated). There are two ways in which an array can be created: using the new array keyword, or by initializing a variable with an array denoted by a comma-seperated list between (square) brackets. Strings have been reimplemented and now behave exactly the same as arrays, meaning that they too can be indexed. A string literal, however, is guaranteed to have a terminating zero. The example below illustrates how arrays may be used:

/* arrays.bfx */  
 
function main()  
{  
    x = [0, 1, 2, 3, 4];  
    zeros1 = array 5;    // array of 5 zeros  
    zeros2 = array 5 0;  // the 0 at the end is optional  
    ones   = array 5 1;  // array of 5 ones  
 
    for i = 0:4  
    {  
        zeros1[i] = x[i];  
        printd zeros1[i];  
        print ’ ’;  
    }  
    print ’\n’;  
 
    str = "Hello World!\n";  
    str[1] = ’o’;  
    str[7] = ’e’;  
    prints str;  
}

Memory Management

A garbage collector collects unreferenced memory and makes it available for other purposes. Old variables can safely be overwritten and reused. Because each function has its own scope, variables having the same name will not cause nameclashes across function scopes. When parameters are passed between functions, they will be passed by value. That is, the function will receive a copy of the original variable, even if it is a string or an array.

Compilation

Compiling BrainFix into BrainFuck using the bfx compiler is a single step procedure, but unless you have a machine that can execute BrainFuck instructions directly, you will need another tool to translate the resulting BrainFuck code to C (or any other mainstream language). I have included my own little translator, called bf2c, to do this work. I recommend you use this one, even though it does not optimize and is very primitive in all respects. The reason I still recommend this is because it implements some minor subtleties:

An array of integers is used to enable computations with numbers that exceed 1 byte. When reading from the input, a decimal value is read instead of a character. Before decrementing a value, it is first checked if this value is already 0. If so, no action is performed. Interpreters that do not implement this behavior will probably fail at producing a working program. To compile your BrainFix progam, simply run1:

$./bfx file1.bfx file2.bfx ... filen.bfx file.bf

This will produce a BrainFuck source-file file.bf, that can be translated to C by bf2c:

$./bf2c file.bf file.c

The final step before running the code is to compile the C-source by a compiler of your choice (e.g., gcc):

$gcc -o program file.c  
$./program

Contact

Feel free to contact me to report bugs, or express your feelings (about this piece of software).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Joren Heit

Netherlands Netherlands
No Biography provided

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
GeneralMy vote of 5 PinmemberKChandos12-Mar-13 9:12 
GeneralRe: My vote of 5 PinmemberJoren Heit12-Mar-13 9:30 
GeneralRe: My vote of 5 PinmemberKChandos12-Mar-13 11:37 
GeneralRe: My vote of 5 PinmemberJoren Heit12-Mar-13 23:27 
GeneralMy vote of 5 PinmvpFlorian Rappl12-Mar-13 8:11 
GeneralRe: My vote of 5 PinmemberJoren Heit12-Mar-13 8:30 
GeneralMy vote of 4 PinmemberKevin Drzycimski8-Mar-13 21:55 
GeneralRe: My vote of 4 PinmemberJoren Heit9-Mar-13 23:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140921.1 | Last Updated 8 Mar 2013
Article Copyright 2013 by Joren Heit
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid