omnifuck

From Esolang
Jump to navigation Jump to search

omnifuck is an extension of brainfuck intended to give it function-call like functionality in a way that adheres to the original brainfuck philosophy.

In omnifuck there is a list of 'brains', objects that each behave somewhat like an instance of brainfuck with a tape of unsigned integer variables, a pointer to the tape location. Each brain has its own list of commands and a pointer to the current command.

Brains

At any time only one brain is active; as described below, there is a command to change which is the active brain. If the active brains command pointer is pointing beyond the end of the command list, the next command in the program is appended. The command at the command pointer is executed if appropriate. It may not be appropriate, there are two modes, an execution mode where commands are executed and a non-execution mode where they are appended but not executed; commands are also not executed when skipping from a [ to a matching ]. Either way the command list pointer is then advanced.

Commands

Most of the commands are the same as in brainfuck

Command Description
> Move the tape pointer to the right
< Move the tape pointer to the left
+ Increment the memory cell under the tape pointer
- Decrement the memory cell under the tape pointer
. Output the character signified by the cell at the pointer
, Input a character and store it in the cell at the pointer
[ Jump past the matching ] if the cell under the pointer is 0
] Jump back to the matching [ if the cell under the pointer is nonzero


There are three new commands

Command Description
! Toggle between execution and non-execution mode
} Change the execution brain by moving right the number of steps along the list of brains given to the value under the tape pointer.
{ The same as } except it moves to the left.

The ! is not appended to the execution brain's command list when executed and it is executed even in non-execution mode. When moving between execution brains three memory cells in the tape are copied, the value under the tape pointer is copied to the position under the tape pointer in the new execution brain, the values to the left and right of the pointer are also copied.

This is illustrated with a code snipped, writing b0 for the first brain and b2 for the third. Consider the situation where b0 has tape (0 0 0 0 0) and b2 has tape (1 5 4 4), with the bold showing the tape pointer location then, after

> >++>+++>+<}

b0 has tape (0 0 2 3 1) and b2 has tape (1 2 3 1).


Example programs

A heavily commented example

+}![> >+< <!{}]

Say b0 is the first brain and b1 the second, here is a commented description

+ b0’s tape now reads (1 0) its command list reads +

} b0’s command list reads +} but b1 is now the execution brain; its tape is (1 0) because of the tape values mapped from b0

![ > >+< <! b1’s command list reads [> >+< > but not commands were executed except the !s

{ b1’s command list reads > >+< <{ and b0 is the execution brain

} b1 is again the execution brain

] b1’s command list reads [> >+< <{] and it’s command pointer points to the location directly after the [ that is at [>>+< <{]; these commands now execute so its tape (1 0 1) and when it reaches the { b0 becomes the execution brain again, there are no more commands left in the program so the program is done.

A program with two functions

+}> >++++[>+++<-]>[<++++>-]![>[>+>+>+< < <-]> >[< <+> >-]<.> >[< <-> >-]< < < <!< < <{+}> >++++++++++< <![> >.< <!{->+<}]+}]> >+++++[<+<-}+}> >-]

This prints the numbers from 1\n to 6\n, it uses one function to add 48 to the number for printing and another to store and print \n.

Computational class

omnifuck is Turing-complete by a trivial reduction from Brainfuck.

External resources

A crude omnifuck interpreter in python, it loads a program.of