Title: CAP.5 LA PRODUZIONE DI CODICE
1CAP.5 LA PRODUZIONE DI CODICE
- 5.1 I languaggi intermedi
- 5.2 Le instruzioni di assegnamento
- 5.3 I collegamenti e le espressioni booleane
- 5.4 La ripresa indietro
25.1 I linguaggi intermedi
analizzatore sintattico
controllatore semantico
produttore di codice intermedio
produttore di codice
Vantaggi separare la parte frontale dalla parte
finale, portabilità migliorata, facilità di
ottimizazzione.
Rappresentazione di un programma con un albero
astratto o con un grafo aciclico
orientato. Qui, questi alberi saranno
rappresentati da un pseudo-codice, il codice
con tre indirizzi, ben adattato alle strutture
di controllo embricate e alle espressioni
algebriche. Codice di bassissimo livello.
3Istruzioni x lt- y op z dove x, y et z sono
costanti o nomi espliciti o prodotti dal
compilatore stesso (temporanei) e op è un
operatore qualsiasi (rappresentato da _nome).
Esempio
a b - c b - c
è rappresentato da
t1 lt- _opp c t2 lt- b _mul t1 t3 lt- _opp c t4 lt- b
_mul t3 t5 lt- t2 _plu t4 a lt- t5
t1 lt- _opp c t2 lt- b _mul t1 t3 lt- t2 _plu t2 a
lt- t3
Grafo aciclico, ottimizzato
Albero astratto, non ottimizzato
Temporari nodi interni dellalbero o del grafo
aciclico.
4Varie istruzioni, con etichette simboliche se
necessario, per controllare il flusso.
Assegnamento x lt- y op z Assegnamento x lt-
op y Copia x lt- y Collegamento incondizionale
goto L Collegamento condizionale if x oprel y
goto L Puntatori e indirizzi x lt- y et x lt- y
et x lt- y Etichette etiq (niente operazione)
Vediamo come produrre codice a tre indirizzi con
un traduttore diretto dalla sintassi.
5Qui, disegna la concatenazione, NewTemp
fabbrica una nuova variabile temporanea e
Print stampa suoi argomenti.
Regola Azione E ? E E E.place NewTemp
E.code E1 .code E2 .code
Print (E . place lt- E1 . place _plu E2 .
place ) E ? E E E.place NewTemp E.code
E1 .code E2 .code Print (E .
place lt- E1 . place _mul E2 . place ) E ?
E E.place NewTemp E.code E1 .code
Print (E . place lt- _opp E1 . place
) E ? (E ) E.place E1 .place E.code E1
.code E ? id E.place id.place E.code
65.2 Le istruzioni di assegnamento
Interazione con la tabella dei simboli. Nelle
istruzioni, invece di utilizzare i nomi, si
ricerca nella tabella dei simboli se questo
nome già esiste. Se è il caso, viene ritornato
suo indice. Si no, un errore è segnalato. Qui
segue una parte della grammatica attribuita per
gli assegnamenti
I ?? idE p Look ( id.name ) if
p ltgt nil then I.code E .code Print (
id.place lt- E.place ) else error
E ? E E E.place NewTemp E.code E1
.code E2 .code Print ( E . place
lt- E1 . place _plu E2 . place ) E ? (E )
E.place E1 .place E.code E1 .code E ?
id p Look ( id.name ) if p ltgt nil
then begin E.place id.place E.code
end else error
7Ottimizazzione delluso delle variabili
temporanee.
Si possono reutilizzare variabili temporanee.
Infatti, queste sono "liberate" dopo la loro
uso come argomento di una operazione. Si può
dunque modificare la funzione NewTemp per
ritornare la prima variabile temporanea libera.
Assegnamento degli elementi delle tabelle
Supponiamo che le tabelle abbiano una sola
dimensione, con indici da 0 fino a n 1. Una
tabella è dichiarata come Tn.
8Due tipi di costruzione utilizzano elementi di
tabelle E ??idE dove in elemento di una
tabella è utilizzato invece di un identificatore
in unespressione, e I ??idEE dove si
realizza un assegnamento a un elemento di una
tabella. Infatti, lindice indica solo uno
spostamento dellindirizzo in memoria. T5 è
dunque sinonimo di (T5)(o, più esattamente
trasformato). Questo è realizzato con E
??idE p NewTemp E.place NewTemp
E.code E1 .code Print ( p lt-
id.place _plu E1 . place ) Print (
E.place lt- p ) I ?? idE E p
NewTemp I.code E1 .code E2 .code
Print ( p lt- id.place _plu E1 . place )
Print ( p lt- E2 . place ) (Le
verificazioni della presenza nella tabella dei
simboli sono state omesse)
9Esempio Supponiamo che T e U siano due tabelle,
listruzione Ta b Ub Tc produce
il codice
t1 lt- a _plu b t2 lt- T _plu c t3 lt- t2 t4 lt-
b _plu t3 t5 lt- U _plu t4 t6 lt- t5 t7 lt- T
_plu t1 t7 lt- t6
105.3 I collegamenti e le espressioni booleane
Grammatica utilizzata per espressioni booleane
E ? E or E E and E not E ( E ) E oprel
E true false
Convenzione numerica (1 true, 0
false) Supponiamo che abbiamo operazioni
corrispondenti nel codice a tre indirizzi (_or
_and _not e per operatori relazionali come
_equ). La valutazione delle espressioni booleane
non presenta differenze con quella delle
espressioni algebriche (Se si vuole una
distinzione tra numeri e valori logici, è
meglio usare unaltro simbolo invece del
E). Abbiamo bisogno di un construttore di
etichette simboliche NewLabel.
11Azioni per un confronto.
Regola
E ?? E gt E
Azioni
p NewLabel q NewLabel E.place
NewTemp E.code E1 . code E2 . code
Print ( if E1 . place _leq E2 . place
goto p ) Print ( E.place lt- 1 ) Print
( goto q ) Print ( p ) Print ( E.place
lt- 0 ) Print ( q )
12Azioni per un while.
Regola
I ?? while E do I
Azioni
p NewLabel q NewLabel I.code Print
( p ) E .code Print ( ifE . place
_equ 0 goto q ) I1 . code Print (
goto p ) Print ( q )
13Azioni per un if...then
Regola
I ? if E then I
Azioni
p NewLabel I.code E .code Print (
ifE . place _equ 0 goto p ) I1 . code
Print ( p )
14Azioni per un if...then..else
Regola
I ? if E then I else I
Azioni
p NewLabel q NewLabel I.code E .code
Print ( ifE . place _equ 0 goto p )
I1 . code Print ( goto q ) Print (
p ) I2 . code Print ( q )
15Esempio
while a gt b do if c gt d then a 1 else b 0
produce il codice
etiq7 if a _leq b goto etiq1 t1 lt- 1 goto
etiq2 etiq1 t1 lt- 0 etiq2 if t1 _equ 0 goto
etiq8 if c _leq d goto etiq3 t2 lt- 1 goto
etiq4 etiq3 t2 lt- 0 etiq4
if t2 _equ 0 goto etiq5 a lt- 1 goto etiq6 etiq5 b
lt- 0 etiq6 goto etiq7 etiq8
Questo è un poco pesante (grande numero di
etichette). Si può ottimizzare il codice.
16Certe volte si utilizza un metodo di valutazione
pigra delle congiunzioni o disgiunzioni. In
questa, se il valore dellespressione non
necessita il calcolo del secondo termine
dellespressione, non viene calcolata.
E ? E land E
Azioni
p NewLabel q NewLabel E.code E1
.code Print ( if E1 . place _equ 0
goto p ) E2 . code Print ( if E2 .
place _equ 0 goto p ) Print ( E.place
lt- 1 ) Print ( goto q ) Print ( p )
Print ( E.place lt- 0 ) Print ( q )
175.4 La ripresa indietro
Lottimizzazione delle etichette può essere
realizzato in un secondo passo sul codice a
tre indirizzi prodotto. Si può anche evitare
completamente luso di etichette simboliche
colla tecnica di ripresa indietro. Come si vede
nellesempio precedente, le etichette non sono
create secondo lordine nel quale sono
utilizzate nel codice. Certi collegamenti
devono di più essere fatti verso istruzioni non
ancora scritte. Nella tecnica di ripresa
indietro, i collegamenti sono lasciati
provvisoriamente indeterminati e vengono
completati quando si produce il codice
dellistruzione di destinazione. Questi
collegamenti sono gestiti come liste di numeri di
istruzioni. (supponiamo qui che ogni
istruzione ha un numero proprio).
18Questo permette anche di non scrivere i pezzi di
codice in modo separato, ma direttamente su
una fila, lasciando però righe di goto
incomplete. Per gestire le liste, abbiamo
CreateList ( i ) fabbrica una nuova lista che
contiene i e ritorna un puntatore verso
essa Fusion ( p1, p2 ) concatena due liste e
ritorna un puntatore Back ( p, i ) inserisce i
come etichetta in tutte le istruzioni della
lista p, poi libera lo spazio occupato da p.
Una variabile globale numero contiene il numero
della prossima istruzione da produrre. Un
altro vantaggio è che la grammatica prodotta è
sempre S-attribuita. Ogni espressione
booleana ha due attributi E.true e E.false che
sono liste di istruzioni da riprendere più
tardi.
19E ? E lor M E Back (E1.false , M.num )
E.true Fusion (E1.true, E2.true ) E.false
E2.false E ? E land M E Back (E1.true ,
M.num ) E.true E2.true E.false
Fusion (E1.false, E2.false ) E ? not E
E.false E1.true E.true E1.false E ? (
E ) E.true E1.true E.false E1.false
E ??id oprel id E.true CreateList (numero
) E.false CreateList (numero 1)
Print ( if id 1.place oprel.op
id2.place goto ) Print (
goto ) E ??true E.true CreateList
(numero ) Print ( goto ) E
??false E.true CreateList (numero )
Print ( goto ) M ? ? M.num numero
20Nellesempio a lt b or c lt d and e lt f si ottiene
finalmente
E.true vale 100, 104 E.false vale 103, 105. I
collegamenti di queste istruzioni saranno
completati più tardi.
100 if a _les b goto 101 goto 102 102 if c
_les d goto 104 103 goto 104 if e _les f
goto 105 goto
Si nota che abbiamo utilizzato la valutazione
pigra. Implementare la valutazione normale è
un pò più complicato. Ora, la traduzioni dei
collegamenti condizionali.
I ? if E then I if E then I else I while E
do I begin L end A L ??L I I
dove L è una lista di istruzioni e A un
assegnamento.
21Per la traduzione, si utilizzano due liste L.next
et I.next che contengono i numeri delle
istruzioni che contengono un collegamento
verso listruzione che segue L o I. Caso del
while do
I ? while M E do M I Back ( E.true, M2.num )
Back (I1.next, M1.num )
Print ( goto M1.num ) I.next
E.false
Caso del if then else
I ? if E then M I N else M I Back ( E.truei,
M1.num ) Back ( E.false, M2.num )
I.next Fusion (I1.next, N.next, I2.next )
Il marchio N serve a passare sopra il secondo I.
N ? ? ? N.next CreateList (numero )
Print ( goto )
22Lassegnamento inizializza I.next e produce il
codice adeguato
I ? idE I.next CreateList ( )
Print ( id.place lt- E.place )
Per la riduzione in una lista
L ? L M I Back (L1.next, M.num )
L.next I.next
Si ottiene la grammatica seguente
23I ? if E then M I Back ( E.true, M.num )
I.next Fusion (E.false, I1.next ) I
? if E then M I N else M I Back ( E.true,
M1.num ) Back ( E.false, M2.num )
I.next Fusion (I1.next, N.next, I2.next )
I ? while M E do M I Back ( E.true, M2.num )
Back (I1.next, M1.num )
Prod ( goto M1.num ) I.next
E.false M ? ? M.num numero N ?
? ? N.next CreateList (numero )
Prod ( goto ) I ? begin L end I.next
L.next I ? idE I.next CreateList ( )
Print ( id.place lt- E.place ) L ? L
M I Back (L1.next, M.num )
L.next I.next
24Così, il frammento
if a lt b lor c lt d land e lt f then x 1 else
begin x 0 u 1 end while a lt b do x
x 1
produce
100 if a _les b goto 106 101 goto 102 102
if c _les d goto 104 103 goto 108 104 if e
_les f goto 106 105 goto 108 106 x lt- 1 107
goto 110
108 x lt- 0 109 u lt- 1 110 if a lt b goto
112 111 goto 112 t1 x _plu 1 113 x lt-
t1 114 goto 110
Il risultato è la variabile L e L.next vale 111.