In che modo i nomi globali e locali sono disambiguati dal compilatore nel codice a tre indirizzi?

1

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.

    
posta Christian Dean 16.09.2017 - 21:14
fonte

1 risposta

1

La descrizione nel libro sembra fuorviante. Avrei scritto:

outer_a = 1
inner_a = 2
outer_b = outer_a

Potresti aggiungere alcuni bit per renderlo più chiaro:

outer_a.startsexisting
outer_a = 1
inner_a.startsexisting
inner_a = 2
inner_a.endsexisting
outer_b.startsexisting
outer_b = outer_a
outer_b.endsexisting
outer_a.endsexisting

I due a sono variabili diverse. Hanno anche diversi ambiti (intervalli in cui esiste la variabile), in questo caso gli ambiti sono nidificati. La variabile b esiste solo dopo che l'interno si ferma.

Un compilatore potrebbe usare solo tre differenti locazioni di memoria per outer_a, outer_b e inner_a. Con un po 'di intelligenza può usare la stessa locazione di memoria per outer_b e inner_a perché non esistono allo stesso tempo.

    
risposta data 16.09.2017 - 21:48
fonte

Leggi altre domande sui tag