Befunge


Befunge is a stack-based, reflective, esoteric programming language. It differs from conventional languages in that programs are arranged on a two-dimensional grid. "Arrow" instructions direct the control flow to the left, right, up or down, and loops are constructed by sending the control flow in a cycle. It has been described as "a cross between Forth and Lemmings".

History

The language was originally created by Chris Pressey in 1993 for the Amiga, as an attempt to devise a language which is as hard to compile as possible. Note that the p command allows for self-modifying code. Nevertheless, a number of compilers have subsequently been written. A number of extensions to the original "Befunge-93" specification also exist, most notably Funge-98, which extends the concept to an arbitrary number of dimensions and can be multithreaded, with multiple instruction pointers operating simultaneously on the same space. Befunge-extensions and variants are called Fungeoids or just Funges.
The Befunge-93 specification restricts each valid program to a grid of 80 instructions horizontally by 25 instructions vertically. Program execution which exceeds these limits "wraps around" to a corresponding point on the other side of the grid; a Befunge program is in this manner topologically equivalent to a torus. Since a Befunge-93 program can only have a single stack and its storage array is bounded, the Befunge-93 language is not Turing-complete. The later Funge-98 specification provides Turing completeness by removing the size restrictions on the program; rather than wrapping around at a fixed limit, the movement of a Funge-98 instruction pointer follows a model dubbed "Lahey-space" after its originator, Chris Lahey. In this model, the grid behaves like a torus of finite size with respect to wrapping, while still allowing itself to be extended indefinitely.

Compilation

As stated, the design goal for Befunge was to create a language which was difficult to compile. This was attempted with the implementation of self-modifying code and a multi-dimensional playfield.
Nevertheless, these obstacles have been overcome, to some degree, and Befunge compilers have been written using appropriate techniques.
The bef2c compiler included with the standard Befunge-93 distribution uses threaded code: each instruction is compiled to a snippet of C code, and control flows through the snippets just as it does in a Befunge interpreter. This does not result in a significant advantage over a good interpreter. Note that the bef2c compiler is not correct since it does not handle either 'p' or string mode, but it would not be impossible to make it do so.
The Betty compiler, for example, treats every possible straight line of instructions as a subprogram, and if a 'p' instruction alters that subprogram, that subprogram is recompiled. This is an interesting variation on just-in-time compilation, and it results in a much better advantage over an interpreter, since many instructions can be executed in native code without making intervening decisions on the 'direction' register.

Sample Befunge-93 code

The technique of using arrows to change control flow is demonstrated in the random number generator program below. The Befunge instruction pointer begins in the upper left corner and will travel to the right if not redirected. Following the arrows around, the ? instructions send the instruction pointer in random cardinal directions until the pointer hits a digit, pushing it to the stack. Then the arrows navigate to the . to output the digit from the stack and return the pointer to the first directional randomiser. There is no @ to terminate this program, so it produces an endless stream of random numbers from 1 to 9.

v>>>>>v
12345
^?^
> ? ?^
v?v
6789
>>>> v
^ .<

The following code is an example of the classic "Hello World!" program. First the letters "olleH" are pushed onto the stack as ASCII numbers. These are then popped from the stack in LIFO order and output as text characters to give "Hello". A space is character number 32 in ASCII, which here is constructed by multiplying 4 and 8, before being output as text. The remaining code then outputs "World!" in a similar way, followed by ASCII character 10.

> v
v ,,,,,"Hello"<
>48*, v
v,,,,,,"World!"<
>25*,@

The following code is a slightly more complicated version. It adds the ASCII character 10 to the stack, and then pushes "!dlrow,olleH" to the stack. Again, LIFO ordering means that "H" is now the top of the stack and will be the first printed, "e" is second, and so on. To print the characters, the program enters a loop that first duplicates the top value on the stack. Then the "_" operation will pop the duplicated value, and go right if it's a zero, left otherwise. When it goes left, it pops and prints the top value as an ASCII character. It then duplicates the next character and loops back to the "_" test, continuing to print the rest of the stack until it is empty and so the next value popped is 0, at which point "@" ends the program.

>25*"!dlrow,olleH":v
v:,_@
> ^

Befunge-93 instruction list

Most one-dimensional programming languages require some syntactic distinction between comment text and source code — although that distinction may be as trivial as Brainfuck's rule that any character not in the set +-<>,. is a comment. Languages like Lisp and Python treat strings as comments in contexts where the values are not used. Similarly, in Befunge, there is no comment syntax: to embed documentation in the code, the programmer simply routes the control flow around the "comment" area, so that the text in that area is never executed.