Brainfuck

Brainfuck er et meget minimalistisk, esoterisk
programmeringssprog. Sproget blev udviklet i 1993 af Urban Müller og var et
forsøg på at lave et Turing-komplet programmeringssprog med en meget lille
compiler.

Sammenlignet med programmeringssprog til almene formål er Brainfuck svært at
skrive programmer i fordi det tilbyder meget få instruktioner. Det begrænsede
instruktionssæt er lige præcis tilstrækkeligt for at gøre sprogets teoretiske
udtrykskraft universelt (Turing-komplet).

Sproget er derfor ikke tiltænkt som et praktisk anvendeligt sprog, men i
stedet som en form for underholdning.

Sprogets oprindelse 

Foruden instruktioner til håndtering af input og output er Brainfuck en
variation over programmeringssproget P`` skabt af Corrado Böhm i 1964.
Ved at bruge seks symboler ækvivalent med Brainfucks instruktioner viste
Böhm ved eksempler hvordan de tilsammen er tilstrækkelige for at udtrykke
enhver beregnelig funktion.

Sprogets design 

Inspireret af en compiler til programmeringsssproget FALSE som fyldte 1024
bytes, findes adskillige compilere til Brainfuck på under 200 bytes og en
enkelt på under 100 bytes. Den klassiske compiler er Urban Müllers version 2
som er lavet til Amiga. Sammen med den følger en fortolker, en række
programmer skrevet i Brainfuck, samt et README-dokument.

Sprogets opbygning 

Sproget består af 8 instruktioner som er repræsenteret ved enkelte tegn. De
er hver især beskrevet nedenfor. Et Brainfuck-program er altså en serie af
disse instruktioner. Hvis der forekommer andre tegn end de foruddefinerede
instruktioner, vil disse tegn blive set bort fra som om de var kommentarer.
(I de fleste programmeringssprog markerer man når en kommentar begynder og slutter.)

Hver af instruktionerne udføres i sekvens indtil sidste instruktion er blevet
udført, hvorefter programmet afsluttes. Programmets tilstand følger en simpel
model hvor en række af 30.000 celler som indeholder bytes (nedenfor kaldet
data) opdateres ved at en peger på den aktive celle (nedenfor
kaldet cur) hæves eller sænkes, eller den aktive celles værdi selv
hæves eller sænkes. Det er desuden muligt at tilgå input, eksempelvis fra
tastaturet, samt output, eksempelvis til skærmen. Input og output læses som
ASCII-værdier og behandles som heltal.

Instruktioner 

Sproget tilbyder 8 instruktioner som er repræsenteret ved enkelte tegn.

Eksempler

Omskrivning til C-kode 

Betragt Brainfuck-programmet ++++++++[->++++++++<]>. som udskriver
tegnet @, hvilket svarer til ASCII-tegn nr. 64. Måden dette tegn
konstrueres er ved først at danne værdien 8 i første celle (vha. ++++++++),
hvorefter en løkke trækker én fra værdien i cellen og forøger anden celle med 8
hver gang (vha. [->++++++++<]). Efter 8 gange er værdien i første
celle ikke længere forskellig fra 0, hvorefter den betragtes som falsk. Da stopper
løkken, der peges på anden celle (vha. >) som udskrives (vha. .).

Det samme eksempel kunne skrives ved hjælp af følgende (ineffektive) C-kode:

int main()
{
    unsigned char data[30000] = {0};  // initialisér række af bytes
    int cur = 0;               // initialisér peger

    // forøg værdien af data[0] til 8
    data[cur]++; data[cur]++; data[cur]++; data[cur]++;
    data[cur]++; data[cur]++; data[cur]++; data[cur]++;

    // mens data[0] ikke er lig 0
    while (data[cur] != 0)
    {
        // sænk værdien i data[0] med én
        data[cur]--;
        // bevæg peger til data[1]
        cur++;
        // forøg værdien i data[1] med 8
        data[cur]++; data[cur]++; data[cur]++; data[cur]++;
        data[cur]++; data[cur]++; data[cur]++; data[cur]++;
        // bevæg peger tilbage til data[0]
        cur--;
    }

    // bevæg peger til data[1]
    cur++;
    // udskriv indholdet af data[1] som ASCII-værdi (dvs. som @)
    putc(data[cur]);
}

Det ville imidlertid svare til følgende program:

void main()
{
    unsigned char data[30000];
    int cur = 0;

    cur = 1;
    data[cur] = 64;
    putc(data[cur]);
}

Hello World! 

Et længere eksempel er programmet som udskriver "Hello World!"
efterfulgt af et linjeskift:

 
+++++ +++++             initialisér tæller (celle #0) til 10
[                       brug løkke til at sætte de næste værdier til hhv 70/100/30/10
    > +++++ ++              tilføj  7 til celle #1
    > +++++ +++++           tilføj 10 til celle #2 
    > +++                   tilføj  3 til celle #3
    > +                     tilføj  1 til celle #4
    <<<< -                  sænk tæller (celle #0)
]
> ++ .                  udskriv 'H'
> + .                   udskriv 'e'
+++++ ++ .              udskriv 'l'
.                       udskriv 'l'
+++ .                   udskriv 'o'
> ++ .                  udskriv ' '
<< +++++ +++++ +++++ .  udskriv 'W'
> .                     udskriv 'o'
+++ .                   udskriv 'r'
----- - .               udskriv 'l'
----- --- .             udskriv 'd'
> + .                   udskriv '!'
> .                     udskriv '\n'

For læsbarhedens skyld er ovenstående kildekode spredt på tværs af flere
linjer og kommentarer i form af andre tegn end de 8 instruktioner er blevet
tilføjet. (Det er altså ikke nødvendigt at bemærke at en kommentar starter.)
Koden kunne dog lige så godt være skrevet som:

 ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

Programmeringssprog