Il compilatore microscopico.


Pensate a un compilatore compatto. Fatto? Bene, pensatene uno ancora più piccolo. E' una sfida impossibile? No, se la affidate ad un amighista sempre pronto ad arrampicarsi sugli specchi tirati a lucido. Se poi l'amighista in questione si chiama Wouter van Oortmerssen, noto ai più per la sua passione quasi morbosa per la progettazioni di linguaggi e compilatori, il risultato sarà certamente esplosivo.
Il compilatore di cui sto per per parlarvi ha proprio dell'incredibile, è grosso, si fa per dire, ben 1020 bytes, si avete letto bene meno di 1Kb.

Dite che tutto ciò sia falso? Avete proprio ragione, infatti di tratta di FALSE e del suo compilatore. L'obiettivo di Wouter era di realizzare un linguaggio dalla sintassi criptica e dotato di un compilatore tanto potente quanto microscopico. Il gioiellino in questione è scritto in puro Assembly 68000, anche se esistono almeno 2 porting sotto x86, e centra in pieno l'obiettivo iniziale.

Per utilizzarlo è sufficiente avere un Amiga con almeno il Kickstart 37 (cioè il 2.0) e qualche kbyte di memoria su disco per contenere il compilatore, il sorgente ed anche l'eseguibile generato, oltre ad un banale text-editor come Ed, che correda tutti gli Amiga fin dalla notte dei tempi.

Programmare in FALSE non è facile, non solo per la sua sintassi criptica ed adatta a degli hacker, ma anche perchè non ci sono strumenti di debug e lo stesso compilatore segnala un esiguità di circostanze anomale. Per la precisione sono segnalati solo l'impossibilità di allocare la memoria, di leggere il sorgente, creare l'eseguibile o recuperare il puntatore alla dos.library, o l'uso di simboli non appartenenti al linguaggio. Inoltre la segnalazione avviene attivando il codice di ritorno del dos pari a 10 in luogo di 0, quindi non è neanche possibile discriminare quale errore sia avvenuto. Di contro, l'organizzazione del linguaggio, è tale che se il programma viene compilato quasi certamente farà quello che deve fare.

Per risparmiare spazio, Wouter ha deciso che l'algoritmo risolvente debba essere espresso come se si trattasse di un albero e in ciascun nodo è racchiusa un espressione che manipola il contenuto dello Stack. Tutto ciò si traduce in una sintassi fortemente legata alla Notazione Polacca Inversa, croce e delizia dei programmatori delle calcolatrici scientifiche della HP.
In questo modo il compilatore non deve più tradurre il sorgente in albero e quindi in assembly, ma fa solo la metà del lavoro.

La notazione polacca inversa prevede la presenza dell'operatore in coda ai due operandi, per esempio la banale somma:

1 + 2 = 3

diventa:

1 2 +

Il risultato sarà sempre 3. La valutazione dell'espressione avviene nel modo seguente. Si preleva il primo simbolo dall'espressione, essendo un operando viene posto nello stack e si passa al successivo che subisce la stessa sorte, raggiunto il terzo ed ultimo simbolo si prelevano i due elementi affioranti dallo stack e si sommano, dato che il + indica l'operatore somma, ed il risultato viene nuovamente memorizzato nello stack, per successive elaborazioni o per essere passato alla routine che ha richiesto la valutazione della somma.

Per esempio, provate a risolvere la seguente espressione:

2 3 * 1 +

Il risultato corretto è 7.

Per limiti intrinsechi del compilatore il massimo numero intero che può gestire è 320000, anche se lo tratta come un entità a 32bit. Comunque in FALSE non scriveremo mai applicazioni tecnico-scientifiche, anche perchè il compilatore genera codice "a caso" quando o il sorgente o l'eseguibile superano i 32Kb, e soprattutto la sintassi è troppo contorta per consentire la scrittura di un programma ampio.

Qualcuno potrebbe pensare che FALSE sia inutile. Si e no, come risponde un mio professore universitario a qualunque domanda sottopostagli.
FALSE può essere utilissimo per scrivere piccole utility per scopi specifici, tipo per rimuovere i Carriage Return da un testo proveniente da una macchina WINTEL o per convertire in una tabella HTML un input numerico proveniente da un file o da tastiera.

Vediamo il classico e banale programma di ogni corso di linguaggio di programmazione, cioè il solito programmino "Helloworld":

{ Helloworld.f }
"Hello world!
"


Per compilarlo basta salvarlo con il nome hello.f e dare da SHELL il comando:

false hello.f


Dopo qualche frazione di secondo, nella stessa directory troveremo il file eseguibile dall'inequivocabile nome storico di a.out. Quando lo lanciamo, vedremo apparire la frase:

Hello world!

La prima riga è un commento, che in FALSE sono racchiusi tra { e }, la seconda definisce una stringa con tanto di Line Feed, ecco perchè il doppio apice è su un'altra riga, la quale viene immediatamente stampata nello StdOut che nel nostro caso è la Consolle. Volendo possiamo ridirigere l'output in un file basta usare il comando:

a.out >ram:prova.txt


Se volete realizzare un microscopico comando Copy, bastano le seguenti linee per realizzarlo:

{ Copy }
ß[^$1_=][,]#


Aveva o no Wouter ragione a dire che la sintassi è criptica? In un pseudo-pascal il programma sarebbe più a meno equivalente a:

while c := getc() <> EOF do putc()


Che tradotto in un linguaggio a noi ancora più comprensibile suonerebbe come: "fino a quando il buffer di input non è vuoto, preleva un carattere ed invialo al buffer di output".

Così com'è il comando opera con la Consolle, ma con la ridirezione dell'input e dell'output si possono compiare i file.

Per assegnare ad una variabile un valore si usa una sintassi sempre di tipo RPN (notazione polacca inversa), e l'operatore di assegnazione non è "=" ma ":", mentre quello per leggerne il contenuto è ";". Vediamo due esempi che spero chiariranno le idee:

1-a: { a := -1 }
a;1+b { b := a + 1 }


Le funzioni sono dichiarate come espressioni Lambda e sono costituite da un pezzo di codice racchiuso tra [ e ], al quale viene associato un nome:

[2-]f:


Abbiamo appena definito una funzione di nome f che sottrae 2 all'argomento passato. Questa viene avvalorata tramite l'operatore !, per esempio per usarla nel nostro ipotetico programma è sufficiente dare il comando:

af;!


Nel caso la variabile a contenga -1, otterremo come risultato -3.

Si conclude qui questa breve escursione alla scoperta del FALSE, un linguaggio strano e compatto, ma molto interessante e che spero possa aver solleticato la vostra curiosità. Potete prelevare la documentazione ed il compilatore dal sito http://www.ecs.soton.ac.uk/~wvo96r/ .
Buon divertimento.

Francesco De Napoli