Nel libro Compilatori: principi, tecniche e strumenti (seconda edizione) , Appendice A, gli autori offrono un'implementazione di un front-end del compilatore che genera un codice a tre indirizzi per un linguaggio molto semplice.
Come molte altre lingue, la lingua del libro ha ambiti definiti dall'apertura e chiusura di parentesi graffe. Per evitare conflitti di nomi durante la generazione di codice a tre indirizzi per blocchi nidificati, il parser utilizza una struttura gerarchica di tabelle di simboli.
Tuttavia, mentre questo funziona bene durante la generazione del codice, come evitare i conflitti di nome nel codice a tre indirizzi proprio auto ?
Per dimostrare cosa intendo, considera questo codice di esempio scritto secondo la grammatica nel libro:
{
int a;
a = 1
{
int a;
a = 2;
}
int b;
b = a;
}
Il compilatore nel libro genererebbe il seguente codice:
L1: a = 1
L3: a = 2
L4: b = a;
L2:
Nel codice precedente, come fa il compilatore ad accedere al valore corretto di a
quando traduce l'istruzione b = a;
? La variabile a
dichiarata nell'ambito nidificato calpesta il valore di a
nello scope precedente.
Nella sezione 8.4 del libro, gli autori menzionano l'assegnazione del codice a tre indirizzi in blocchi di base che sembravano risolvere i problemi sopra. Tuttavia, a seguito di un esame più approfondito, questo non ha impedito che nomi di ambiti diversi cancellassero i rispettivi valori.
È normale nel codice a tre indirizzi? In tal caso, come fa il compilatore a distinguere tra vari nomi locali e globali? In caso contrario, qual è la sintassi solitamente utilizzata per indicare le variabili in ambiti diversi?
La ragione per cui questo sembra un grosso problema, è perché nella sezione 8.6 del libro, gli autori introducono un semplice algoritmo di generazione del codice per tradurre il codice a tre indirizzi in un linguaggio di assemblaggio forzato. Nella sezione 8.6.1, menzionano che, per il buon funzionamento dell'algoritmo, ogni variabile nel codice sorgente ha bisogno di un descrittore di variabili . Essenzialmente una struttura dati per contenere tutti gli indirizzi di dove si trova attualmente il valore della variabile.
Con la struttura del codice a tre indirizzi sopra, come dovrebbero essere seguite correttamente queste istruzioni. In che modo ciascun nome di variabile nel programma ha un descrittore di variabile distinto? Questo semplicemente non sembra possibile.