Brainfuck Language

The Bad Word police deleted this page. Unfortunately for them, it's about a Programming Language and so On Topic.


Brainfuck is an Esoteric Programming Language. As a language, has some very good points:

Fast learning curve

Easy syntax

200 byte compiler

No trouble finding it on google (unlike with Forth Language, unless "put forth" and "go forth" are excluded; very few people say brainfuck in normal non-programming web sites)

Hmm you might land on some sort of brain fetish site though

One character per command. Easy to tokenize

Makes a great learning language :)

Code reuse is facilitated by an utter lack of variables and subroutines.

It is Turing Complete, and making a C-to-brainfuck compiler would make your programs very portable in object format.

And one or two bad ones:

Unfortunate name when you're trying to have a serious discussion.

Huge loss of time.

Here is a simple brainfuck program:

,[.[-],]

It will work like Unix cat(1), echoing back all input characters until it reaches EOF.

I can't see why the example is not just ,[.,] neither why it has the [-] -- Eduardo Madrid

Clearing the cell each time makes the program work on implementations that leave the current cell unchanged on reading EOF as well as those that set the cell to 0 on EOF, thus increasing the portability. -- Daniel Cristofani


www.nvg.ntnu.no -- amiga original

www.muppetlabs.com -- programs and language description

esoteric.sange.fi -- an archive of implementations, programs, and IDE's for brainfuck

koeln.ccc.de -- tools

www.ecs.soton.ac.uk -- dot-net version

esoteric.sange.fi -- some standards on the language

www.hevanet.com -- more programs and things.

e.a.la -- fast ASCII-2-Brainf*ck converter


Languages inspired by Brainfuck

Path Language hybridizes Brainfuck with Befunge Language obtaining a 2-D execution space. A loop looks like a loop in this language.

Snusp Language uses skip-if-zero ('?') to replace Path Language's four conditional direction operators for a minimalist design and a cleaner look.

Lnusp Language gets rid of the bloat (?!) in Snusp and Path.


Syntax:

[ (opening square bracket):
while(mem[ptr]) {

] (closing square bracket):
}

< (less):
ptr--;

> (greater):
ptr++;

+ (plus):
mem[ptr]++;

- (minus):
mem[ptr]--;

. (period):
putchar(mem[ptr]);

, (comma):
mem[ptr]=getchar();

When you make your own language, it is always a good test of usability to try and make a brainfuck interpreter in it. This shouldn't take more than a few hours under most circumstances.

...although there are a few little issues that trip implementors up with astonishing frequency; it would be wise to consult this document, and the two that it links to near the top, first: www.hevanet.com

(Don't worry, they're brief.)

Something from that epistle; every character not part of the language is insignificant whitespace. That's nice for Literate Programming (if it wasn't for the reserving of . and - that is!)


How would you implement the following 2 (perhaps this might give me a bit more insight on how to do very simple code-structures with a Turing Machine, given these, any program could probably be built).

given x: mem[0]

given ptr = 0 implement:

if (x > 0) x = 1 else x = 2

(Answer: I'd do [>+<[-]]++>[<->-]< ; this assumes mem[1] is zero and uses it as a temp, and also that mem[0] is not negative, which is the best policy in my view.)

([[-]-<]>++ looks better to me.)

(Some problems with that. One, if x>0 it tries to read mem[-1], which should ideally be a fatal runtime error and is likely to be one in practice. Two, if x==0 it stores 2 in mem[1], not in mem[0]. Three, when it's finished we have lost track of the pointer, which is likely to be problematic in the context of a larger program. Though if we left enough structure around, we could re-establish the pointer's location - e.g.:

>+<[[-]->-]>[->]<<++ which assumes that mem[1] and mem[2] are both zero.)

(with a Turing machine this would be something like:

0 2 R 7

1 1 R 7

2 1 R 7

3 1 R 7

etc.

Notice that a Turing machine has nothing in common with brainfuck except the memory model and the fact of being Turing Complete.

Not even the memory model is the same. A Turing Machine tape's squares may only contain one of a fixed finite alphabet of symbols, while a Brainfuck tape's squares store arbitrarily large (implementation details notwithstanding) natural numbers. Really, the Brainfuck tape is more like an inexhaustible supply of registers.

Not exactly. Unlimited-range cells are a feature of Frans Faase's dialect of brainfuck, and of his dialect only. If we were going to talk about an ideal brainfuck language independent of any implementations, we would need to base it on Urban M�ller's original readme file, and based on that we would say: a brainfuck tape's squares store bytes (implementation details notwithstanding).

Sum ar: zero to infinity, negative infinity to positive infinity, or 8 bits 0 to 255, or wrapped around or not wrapped around. Another thing would be whether there is more memery left of the starting place.

There isn't more memory left of the starting place in the original implementations, or in most later implementations, there's nothing in the documentation to suggest there might be, and no careful programmer will move the pointer there deliberately. So it's a particularly useless "feature" to add to an implementation.

)

Or

given x: mem[a]

given y: mem[a + 1] (for some a) implement:

z = &x

(Not clear on that. If you mean something like "find the value of the pointer", there's no way to do that - if your program needs that information, it'll have to keep track of where it moves the pointer to. Also note that the array elements are likely to be bytes, so the address may not fit in one. I think the best move is probably to avoid using absolute addressing schemes where possible.

If you mean something else, please restate.)

(Ditto re: Turing machines.)

Also, where is the program stored? Are program and data completely separated?

(Answer: Yes. At least in theory; in some implementations you can violate this.)(Ditto re: Turing.)


I've seen #s, :s, \s, etc. in bf code before. What do they do?

Ex.: #>>>-<<<[[>+>+<<-]>[>]+[<]>-[[>]<+[<]>-]<<]>>-[>]#>>>+++++[>+++<-] (Code taken from a quine)

I don't think it does anything. If it was taken from a quine, it was just because the program outputs that, they decided to also add that to the program. In ABF, the # switch with temporary register but I don't think that is standard or anything else does that.

Various people have made implementation-specific extensions to brainfuck, which suggests to me that they didn't get the point. The # command has a certain degree of legitimacy, though, for two reasons: One, it's used for debugging, rather than as an integral part of programs. (Its action is to print the values of the first ten cells of the array, in decimal, and a ^ mark on the next line to indicate the pointer's location; and it doesn't even do that unless you set a "debug" command-line option in the interpreter.)

The second reason is that it was made by Urban M�ller, who invented the brainfuck language.

Since it's clearly undesirable to have a proliferation of special commands, any brainfuck implementor who wants to include any kind of "print internal state, for debugging" function should use # as the command for it. Likewise it'd be a good choice for marking breakpoints, for implementations that feature them.


There's a stupider kid on the block: Whitespace Language


See original on c2.com