Semantica statica e dinamica 1 Fasi di compilazione Programma sorgente Analisi lessicale front end Analisi sintattica Tabella dei simboli Analisi semantica Generatore di codice intermedio error handler Ottimizzatore Generatore di codice back end Programma target 2
Controlli semantici Congruenza fra le dichiarazioni delle entità e il loro impiego nelle istruzioni Rispetto delle regole che governano i tipi degli operandi nelle espressioni e negli assegnamenti Correttezza delle strutture di controllo del linguaggio Rispetto delle regole di visibilità e unicità degli identificatori Rispetto delle regole di importazione ed esportazione degli oggetti 3 Type Checking Un compilatore esegue le verifiche semantiche oltre che le verifiche sintattiche. Semantica Statica le verifiche semantiche vanno eseguite durante la compilazione Dinamica le verifiche sono eseguite a run-time Type checking è uno delle operazioni di checking statico. non possiamo fare tutti I type checking a compile-time. Alcuni sistemi usano anche dynamic type checking. 4
Type Checking Un type system è una collezione di regole per assegnare una espressione di tipo ad una parte di programmi Un type checker implementa un type system. Un sound type system elimina gli errori di tipo. Un linguaggio di programmazione e detto strongly-typed, se ogni programma è compilato solo se privo di errori di tipo. In pratica, alcune operazioni di type checking sono fatti a runtime (la maggioranza dei programmi non è strongly-typed). Esempi int x[100]; x[i] la maggioranza dei compilatori non garantiscono che i [0.. 99] 5 Type Expression Il tipo si un costrutto di un linguaggio è denotato dal type expression. Una type expression può essere: basic type Un tipo primitivo, int, float, type-error per segnalare un errore di tipo void type name Un nome che denota il tipo di una espressione 6
Type Expression Un costruttore applicato ad altri type expressions arrays: se T è un type expression, allora array(i,t) è un type expression dove I rappresenta il range degli indici: esempio array(0..99,int) products: se T 1 e T 2 sono type expressions, allora il prodotto cartesiano T 1 x T 2 è un type expression. esempio: int x int pointers: se T è una type expression, allora pointer(t) è una type expression. esempio: pointer(int) functions: possiamo trattare funzioni in un linguaggio di programmazione come il mapping da un domain type D ad un range type R. Cosi, il tipo di una funzione puop essere raappresentato dal type expression D R dovee D e R sono type expressions. Esempio: int int reppresenta un tipo di uns funzione che prende come parametro un calore int e tiporrna un valore int. 7 L attributo type È un attributo sintetizzato È associato alle dichiarazioni di tipo, espressioni e descrive il tipo dell entità considerata Azioni semantiche o condizioni 8
Un semplice Type Checking System P D;E D D;D D T id { addtype(id.entry,t.type) } T char { T.type=char } T int { T.type=int } T float { T.type=float } T *T 1 { T.type=pointer(T 1.type) } T T 1 [intnum] {T.type=array(0..intnum-1.val,T 1.type)} 9 Type Checking di espressione E id { E.type=lookup(id.entry) } E charliteral { E.type=char } E intliteral { E.type=int } E realliteral { E.type=real } E E 1 + E 2 { if (E 1.type=int and E 2.type=int) then E.type=int else if (E 1.type=int and E 2.type=real) then E.type=real else if (E 1.type=real and E 2.type=int) then E.type=real else if (E 1.type=real and E 2.type=real) then E.type=real else E.type=type-error } E E 1 [E 2 ] { if (E 2.type=int and E 1.type=array(s,t then E.type=t else E.type=type-error } 10
Type Checking di istruzioni S id = E { if (id.type=e.type) then S.type_error=false else S. type-error = true } S if E then S 1 { if (E.type=int ) then S.type_error=S1.type_error else S.type_error=true} S while E do S 1 S id (A) { if (E.type=int) then S.type_error =S 1.type_error else S..type-error =true } S.type_error(confronta (A,get(id 11 Type Checking di funzioni E E 1 ( E 2 ) { if (E 2.type=s and E 1.type=s t) then E.type=t else E.type=type-error } Ex: int f(double x, char y) {... } f: double x char int argument types return type 12
Equivalenza strutturale di Type Expressions Come verificare che due type expression sono uguali? type expressions sono costruiti dai tipi base e (no type names), possiamo utilizzare equivalenza strutturale per due type expressions 13 Equivalenza strutturale di Type Expressions if (s and t sono dello stesso tipo base) return true else if (s=array(s 1,s 2 ) and t=array(t 1,t 2 return (sequiv(s 1,t 1 ) and sequiv(s 2,t 2 else if (s = s 1 x s 2 and t = t 1 x t 2 ) return (sequiv(s 1,t 1 ) and sequiv(s 2,t 2 else if (s=pointer(s 1 ) and t=pointer(t 1 return (sequiv(s 1,t 1 else if (s = s 1 s 2 and t = t 1 t 2 ) return (sequiv(s 1,t 1 ) and sequiv(s 2,t 2 else return false 14
Names per Type Expressions In alcuni linguaggi di programmazione noi diamo un nome ad type expression, e utilizziamo il type expression. typedef link = *cell; stesso tipo? link p,q; *cell r,s;? p,q,r,s sono dello 15 Definizione ricorsive di Type Expressions typedef *cell link; typedef struct S{ int x; link next; }cell Non è possibile utilizzare equivalenza strutturale se ci sono cicli Il nome del tipo deve essere utilizzato come un tipo base 16
Conversioni di tipi double x; int y; x + y quale è il tipo di questa espressione (int o double)? Quale codice produce? inttofloat float+ y,,t1 t1,x,t2 17 Azioni di controllo L attributo scope rappresenta l insieme di tutte le coppie che definiscono gli identificatori visibili in quel contesto Sintassi S while E do S 1 Condizioni Azioni di controllo if (E.type=boolean then S.type=S 1.type else S.type=type-error E.scope = S.scope S 1.,scope = S.scope 18
S id = E Condizioni Azioni di controllo if (id.type=e.type then S.type=void else S.type=type-error E.scope = S.scope id. scope = S.scope S if E then S 1 Condizioni Azioni di controllo if (E.type=boolean then S.type=S 1.type else S.type=type-error E.scope = S.scope S 1.,scope = S.scope 19 Visibilità e unicità degli identificatori P { Blocco } Blocco.scope = P.scope P.oldscope = Blocco.oldscope Blocco LD LI LI.scope = Blocco.oldscope I.LD Blocco.corr= if (I.LD in Blocco.oldscope) false else Blocco.corr = LI.corr LD LD 1 D LD.scope = LD 1.scope I.LD = I.D LD ε LD.scope = {} D T id I.D = id LI LI Is LI ε Is id = E 20