/multifuck

Brainfuck, with extensions as I think of them. So far: threading, multidimensional memory

Primary LanguageRust

multifuck

Brainfuck, with extensions as I think of them.

Basic Differences

This interpreter is slightly different from the original brainfuck spec:

  • Numbers are 32-bit signed integers, meaning they can become negative. Looping [ and ] check that the value is 0, if it is less than 0 or greater than 0, they loop.
  • Only the left bracket, [, runs the check for a conditional jump. The right bracket ] always makes an unconditional jump back to its matching [. The original spec did the check on both brackets.

Debug Mode

This interpreter also has a visual mode for stepping through your brainfuck program - turn it on with --gui.

ASCII Mode

The interpreter can run in "ASCII mode" using --ascii, where it (counterintuitively) prints the Unicode character corresponding to the number under the tape, rather than the number itself. Input is still in the form of integers, however.

Extensions

So far, there are two extensions:

  • Multithreading
  • Multidimensional memory

Multithreading

Multithreading adds one instruction, &, which spawns a thread which waits one cycle before continuing in the same manner on the program tape.

This means that a thread that is just spawned will initially run the same instructions as its parent, just with a one cycle delay. There are a number of ways to get threads to diverge so that they no longer run the same instructions, some examples of which are in ./examples.

All threads read from and write to the same memory on the same cycle, so simultaneous increments and decrements will either stack or cancel out, rather than overwrite one another. Similarly, thread that checks to loop will not see the increments made to a position in memory by another thread until the next cycle.

One easy way to get threads to diverge is with the following pattern:

&+-[
  PROGRAM 1
]

PROGRAM 2

In this program, the parent thread will run PROGRAM 1 then PROGRAM 2, whereas the spawned thread will only run PROGRAM 2.

In order to get full divergence where both threads run completely different programs, the following pattern is useful:

&+-[+-
  PROGRAM 1
]
[
  PROGRAM 2
]

In this program, the parent thread will run PROGRAM 1, and the spawned thread will run PROGRAM 2. Total divergence!

Common programs such as [->+<] ("move value one cell right") can be well accelerated by running multiple threads in tandem. Many fun examples about spawning many threads with certain delays, moving values more quickly, spawning n threads, can be found in ./examples.

Multidimensional memory

Multidimensional memory adds two instructions, * and /, which allows the memory pointer to access new "dimensions" on the tape.

All pointers start out in dim 0, where < and > move along the x-axis in memory. The * reorients the pointer to move along dim 1, at which point > and < move along the y-axis. A second use of * would make the dim 2, at which point we'd move along the z-axis, and so-on to dim 4, dim 5, etc.

While the * instruction can be said to reorient from dim n to dim n+1, the / instruction reorients from dim n to dim n-1. This means that negative dimensions exist in our memory, and are just as orthogonal as all the positive dimensions are.