From Esolang
Jump to: navigation, search

Basicfuck is an esoteric programming language by User:Rdococ. Contrary to what its name might suggest, it is not a brainfuck derivative - rather, it is designed to be compiled into brainfuck fairly easily while hiding as many temporary variables from the program as possible.


Basicfuck programs have directives, which in this case dictate the size of the tape, and the maximum and minimum values on each cell of that tape. These settings affect the requirements of interpreting the resulting brainfuck program, rather than the compiler itself. Directives should be of the form #basicfuck t=<TAPE SIZE> r=<MINIMUM CELL VALUE>~<MAXIMUM CELL VALUE> o=<OVERFLOW BEHAVIOR>, but t may be set to unbounded, and r may omit one or both ends of the cell value range to indicate an unbounded range. If r is unbounded in both directions, then o=<OVERFLOW BEHAVIOR> should be omitted.

<OVERFLOW BEHAVIOR> may be one of the following words:

wrap The cell value should wrap when it overflows or underflows.
halt The program should halt upon a cell value overflow/underflow.
nearest The cell value should be bounded to the nearest in-range value when an overflow/underflow occurs.

Below the main directive should be an #allocate statement, followed by a comma-separated list of the variables to allocate to cells. Variables can either be of the form <X>, which allocates one cell for <X> to point to, or <X>-><Y>, which allocates <Y> cells, the first of which <X> points to. As an example:

#basicfuck t=unbounded r=0~ o=nearest
#allocate a, b, x, y, arr->3, z

y += 23;
arr->2 += y;

The above code would increment the fourth cell (y) 23 times, and then increments the seventh (5 + 2) cell (arr is 5, arr->2 is 7) by the value of the fourth cell. In this case, z refers to the eighth cell, as does arr->3.


Instruction Description
<X> += <Y> Writes the value of <X>, plus the value of <Y> to the cell that <X> points to.
<X> -= <Y> Writes the value of <X>, minus the value of <Y> to the cell that <X> points to.
if (<X>) { <CODE> } Runs <CODE> if the value of <X> is non-zero. You may optionally add a ! before the parentheses (example: !(<X>)) to negate the condition (runs the code if the value is zero, instead).
while (<X>) { <CODE> } Runs <CODE> unless/until the value of <X> is/reaches zero. You may optionally add a ! before the parentheses (example: !(<X>)) to negate the condition (runs the code unless/until the value is non-zero, instead).
write <- <X> Writes the value of <X> as an ASCII character.
read -> <X> Reads the ASCII value of the next input character, and stores it in <X>.
<X>-><Y> An expression that refers to the cell at <X>'s position plus the value of <Y>. In other words, pointer arithmetic.

All instructions, excluding instructions that end with a closed bracket (for example, the while loop), must end with a semicolon, excluding the directives mentioned above.


Compilation of code in basicfuck would take a few steps.

  1. Allocation is to be performed in the order of variable names in the #allocate directive.
  2. All instances of incrementation/decrementation by the value of another cell, rather than a fixed constant, would be treated as code that allocates temporary variables to perform the inc/dec without the use of the aforementioned instances.
  3. While loops are to begin by firstly moving to the cell of the variable specified, and then returning to the aforementioned cell at the end of - but inside - the loop. As a result of this, the compiler can easily keep track the current cell pointer's position.



Basicfuck does not have variable assignment, mainly because it can be replicated by subtracting a variable's value from itself.

#basicfuck t=unbounded r=0~ o=nearest
#allocate v

v += 21;  // Say v was allocated, and at 21.

v -= v;  // This sets v to 0.
v += 3;  // Then we can add 3.


This calculates the multiplication of two non-negative numbers. In brainfuck, this would require several temporary cells, but only one is required in basicfuck to avoid destroying the original arguments.

#basicfuck t=unbounded r=0~ o=nearest
#allocate x, y, y2, result

x += 8;  // These are the numbers to multiply.
y += 3;

y2 += y;

while (y2) {
    result += x;
    y2 -= 1;


This cat supports EOF=0, -1 (which wraps to 255), and no change.

#basicfuck t=unbounded r=0~255 o=wrap
#allocate char, eof255

read -> char;
while (char) {
    write <- char;
    char -= char;  // This line is to support EOF = no change.
    read -> char;

    // These support EOF = -1 = 255.
    eof255 -= eof255;  // First, we clear 'eof255'.
    eof255 += char;  // Then we increment 'eof255' by the value of 'char'.
    eof255 += 1;  // Finally, we add one so that a value of 255 wraps over to 0.
    if !(eof255) {
        char -= char;  // If eof255 is zero, then we set char to 0 to effectively break out of the loop.