In questo paragrafo c’è una raccolta di linguaggi nati per divertimento, e per lo più con lo scopo di sfidare la bravura dei programmatori. Una tecnica per affrontarli, e semplificarli, è quella di dotarsi di macro, eventualmente interpretate da un linguaggio di alto livello che ne genera il sorgente finale.
E' un linguaggio di una "macchina" con 8 istruzioni, un registro che punta ad un indirizzo della memoria (MP), un registro che segue il programma (PC), un dispositivo di input, ed uno di output:
E' stato dimostrato che Brainf*** è Touring completo, quindi può calcolare qualsiasi algoritmo algoritmo, nella tabella sottostante sono alcuni "programmi" per dei semplici problemi:
Programma |
Funzione |
Risultato[1] |
,>,[<+>-]<. |
Somma due numeri |
> brainf
-3 17 ,>,[<+>-]<. ^Z Input: -3 Input: 17 Output: 14 |
,[>+++<-]>. |
Moltiplica per 3 |
> brainf
21 ,[>+++<-]>. ^Z Input: 21 Output: 63 |
,[>[-.]+.<-] |
Flip flop |
> brainf 2 ,[>[-.]+.<-] ^Z Input: 2 Output: 1 Output: 0 Output: 1 |
>,
input var in pos 1 [ [-<]
var meno 1 vai a pos 0 +[
>[>+>+<<-]
var in posizioni 2 e 3
>>[-<<+>>]
ripristina var da pos 2
<<[
se var non zero
>-
in copia var meno 1
>>+
risultato più 1
<<<[-]]
azzero var
>[-<+>]
ripristino var (meno 1)
<<
ritorna in pos 0 -] >
ritorna
in pos 1 ] >>>.
Risultato |
Divide per 2 |
> brainf 0 ...(omesso)... Input: 0 Output: 0 >
brainf 1000 Input:
1000 Output:
500 >
brainf 999 Input: 999 Output:
499 >
brainf 2 Input: 2 Output: 1 |
Gli esempi sono stati provati con un interprete generato tramite Bison (v. par.1.7 ); l'interprete accetta anche commenti purché non contengano i caratteri che corrispondono ai codici delle istruzioni.
Brainf*** è una sfida per i programmatori, come si può intuire dagli esempi riportati, tuttavia è una sfida che alcuni hanno affrontato per programmi non banali, quali un interprete di Brainf*** e un programma che stampa se stesso (quine). Per affrontare Brainf*** adeguatamente occorre dotarsi di macrofunzioni, un esempio è stato sviluppato con GNU AWK (v.par. 2.8 ), per generare un programma che verifica il segno di un numero. Le macrofunzioni lasciano il puntatore alla memoria nella posizione in cui è stata eseguita l'operazione, nel caso di COPY e MOVE, alla posizione in cui è stato copiato o mosso il primo operando .
Macroprogramma (file abs.src) |
Programma generato (file brnabs.src) |
|||
|
>, [
>+ >[-]<<<[-]>>[-<<+>>>+<]<<[->>+<<]>>> >+ > [
<<< [
<+ >- ]
>>- >- ]
< [ << [
<- >- ]
>>>+ <- ]
<<[-]>[-<+>]< < ]
>>>> . Variabile COMODO a 3 Variabile COUNT a 2 Variabile NUMBER a 1 Variabile SW1 a 5 Variabile SW2 a 4 |
Befunge é un linguaggio inventato da Chris Pressey nel 1993 con lo scopo di essere complesso da utilizzare (Twisted, Deranged Programming Language in the Tradition of BrainF*** and False). Befunge opera su una memoria stack ed una memoria bidimensionale con un insieme di istruzioni che comprendono:
· spostamenti del Program Counter nelle 4 direzioni, salto di una posizione (PC+2), spostamenti orizzontali o verticali in funzione del contenuto dello stack.
· operazioni sullo stack: duplicazione, scambio, eliminazione, POP in memoria, Push da memoria, stampa, operazioni aritmetiche, immissione di numeri, ecc…
Nel Befunge originale le dimensioni della memoria erano 80x24 ma Befunge-97 permette una griglia di capacità illimitata ed un’insieme di direttive per aiutare la stesura dei programmi. Fra le estensioni proposte, ma non sono a conoscenza se siano state realizzate: Funge-98 con un numero arbitrario di dimensioni, multithreaded e con più di un Program Counter.
La tabella che segue contiene le istruzioni di Befunge.
COMMAND
INITIAL STACK(bot->top)RESULT (STACK) |
+ (add)
<value1> <value2>
<value1 + value2> - (subtract)
<value1> <value2>
<value1 - value2> * (multiply)
<value1> <value2>
<value1 * value2> / (divide)
<value1> <value2>
<value1 / value2> (nb. integer) % (modulo)
<value1> <value2>
<value1 mod value2> ! (not)
<value>
<0 if value non-zero, 1 otherwise> ` (greater)
<value1> <value2>
<1 if value1 > value2, 0 otherwise> > (right)
PC -> right < (left)
PC
-> left ^ (up)
PC -> up v (down)
PC -> down ? (random)
PC -> right? left? up? down? ??? _ (horizontal
if) <boolean value>
PC->left if <value>, else PC->right | (vertical
if) <boolean
value>
PC->up if <value>, else PC->down " (stringmode)
Toggles 'stringmode' : (dup)
<value>
<value> <value> \ (swap)
<value1> <value2>
<value2> <value1> $ (pop)
<value>
pops <value> but does nothing . (pop)
<value>
outputs <value> as integer , (pop)
<value>
outputs <value> as ASCII # (bridge)
'jumps' PC one farther; skips
over next command g (get)
<x> <y>
<value at (x,y)> p (put)
<value> <x> <y>
puts <value> at (x,y) &
(input value)
<value user entered> ~ (input
character)
<character user entered> @ (end)
ends program |
Figura
21
(da Befunge-93 Documentation
di Chris Pressey)
Nella Figura 22 alcuni esempi di istruzioni con la relativa esecuzione, le funzioni sono precedute dalla richiesta di immissione di un numero (&) e sono seguite dalla stampa del risultato (.) e dall’istruzione di fine programma (@).
Programma |
Funzione |
Risultato |
&&+.@ |
Somma due numeri |
Immetti numero 180 Immetti numero 19 199 |
&&04p:04g\04g....@ |
Duplica due numeri sullo stack |
Immetti numero 17 Immetti numero 13 17 13 17 13 |
v
>v 013p123p&33p23g23g+23p113g+13p13g33g-!|23g.@
^<<<<<<<<<<<<<<<<<<<<<<<<<< |
Potenza n-esima di due |
Immetti numero 7 128 |
Figura
22
Infine il codice seguente, (Figura 23 ), genera la serie di Fibonacci. L’interprete (incompleto) di Befunge è stato scritto con BCPL (v. BCPL par. 2.13.1.2 ), la generazione del codice sorgente è stata prodotta con un macrolinguaggio interpretato da un programma in MUMPS (v. MUMPS par. 2.41 ).
REM SERIE DI FIBONACCI MOVE 0 COUNT MOVE 1 A1 MOVE 0 A2 ASK LIMITE LABEL LOOP MOVE 0 COMODO ADD A1 COMODO ADD A2 COMODO MOVE A2 A1 MOVE COMODO A2 PRINT COMODO ADD 1 COUNT COMPARE COUNT LIMITE IFNONEQUAL GOTO LOOP END |
v
>v 013p123p033p&43p053p23g53g+53p33g53g+53p33g23p53g33p53g.113g+13p13g43g-!|@ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
Immetti numero 13 1 1 2 3 5 8 13 21 34 55 89 144 233 |
Figura 23