L.in.oleum 4: ci sto lavorando.
Si lascia alle spalle molte scelte sbagliate di ben 13 anni fa.
A partire dal numero di registri, che con la loro emulazione dove non ce ne sono abbastanza passa dai miseri 5 delle altre versioni ai 26 attuali (uno per ogni lettera dell'alfabeto).
Il compilatore comprende poi un assembler interno, invece del pacchetto d'istruzioni preassemblate con gli operandi da riempire, e la sintassi, meno permissiva ma appunto per questo piu` canonizzabile (si dira` poi cosi?), ha subito cambiamenti notevoli. Adesso e` piu` pulita e discorsiva. E` inoltre un linguaggio almeno parzialmente strutturato, con cicli e blocchi condizionali complessi (c'e` perfino un equivalente di switch-case, per giunta molto piu` flessibile: un costrutto che ho chiamato when...then).
Ma la cosa buffa e` che il kickstart compiler, cioe` il compilatore che viene prima di quello scritto nel suo stesso linguaggio, e` scritto in... Javascript! E gira in un browser come front-end di un server NodeJS. Il server provvede a rispondere alle richieste del compilatore quando deve caricare una libreria, nonche` al link dell'eseguibile che poi fornisce in risposta al browser, come file da scaricare. Qui, con un po' di scena, c'e` come appare in Firefox a schermo intero e zoom al 200%:


E questo e` il primissimo hello world (scritto "a crudo", in assenza di qualsiasi libreria) che e` riuscito a compilare, linkare ed eseguire:


Di seguito il listato. Nella finestra del compilatore si possono vedere scorci della sua traduzione, da destra a sinistra, da L.in.oleum 4 alle corrispondenti istruzioni native, al corrispondente linguaggio macchina assemblato.
message = 8 : { Hello_world! \}
messageBytes eq 12
messageUnits eq 4
to Enter Text Mode
r = ik
r . displayStatus | engage
r . exec
leave
to Swap n Units At p
--> m (save register m)
n times
m = P (11223344) (put copy #1 of sample value into m)
r = m (11223344) (put copy #2 of sample value into q)
m [ 8 (22334411) (copy #1 rotates 8 bits left)
r ] 8 (44112233) (copy #2 rotates 8 bits right)
m & 00FF00FFh (00330011) (bytes #1 and #3 are zeroed in copy #1)
r & FF00FF00h (44002200) (bytes #2 and #4 are zeroed in copy #2)
m | r (44332211) (merge copies with a bit-wise OR)
P = m (44332211) (write back sample value)
p + 1 (access next unit to reverse bytes of)
<-- m (restore register m)
leave
to Print Message m Of n Bytes
r = ik
r . fileCommand = writeFile
r . fileName = stdOut
r . fileBlockPointer = m
r . fileBlockSize = n
r . exec
leave
to Wait n Milliseconds
r = n
n = ik
n . suspend
leave
to Begin
Enter Text Mode
Swap messageUnits Units At message
Print Message message Of messageBytes Bytes
Wait 10000 Milliseconds
Non vi sto a spiegare tutto nei dettagli senno` finisco di scrivere l'anno prossimo. Comunque e` per dire: pian pianino, sta procedendo. Ma poi neanche tanto pianino, visto che ho ripreso a lavorarci da un paio di settimane... pero` e` ancora lunghetta. Piu` o meno a livello di parser c'e` tutto, il "canovaccio" e` pronto: manca solo una fraccata di funzioni per l'assemblaggio di istruzioni, e qualche modifica alla gestione dei threads nel modulo di runtime.