Nucleo di Java: Struttura e Semantica Espressioni Assegnamento Controllo di sequenza Dichiarazioni
La sintassi del linguaggio minimo Progr::=prog {StmtList} programma Stmt_List::= Stmt | Stmt StmtList lista di statement Stmt::= Com | Decl Com::= Ide= Exp; | assegnamento Block | blocco while (BoolExp) Com; | iteratore if (BoolExp) Com else Com; condizionale Decl::= Type Ide | Type Ide= Exp; dichiarazioni Type::= int | boolean tipi Block::= {StmtList} blocco Exp::= NumExp | BoolExp espressioni
Esempio public class esempio{ public static void main (){ int x; int y=5; x=y+1; if (x!=y) { int z=0; while (x>y){ x=x-y; z=z+1} while (x<y) { y=y-x; z=z-1;} }} programma Java prog{ int x; int y=5; x=y+1; if (x!=y) { int z=0; while (x>y){ x=x-y; z=z+1} while (x<y) { y=y-x; z=z-1;} } programma nel linguaggio didattico
Modifica di frame L’operazione di modifica di un frame [Val/Ide] ha il significato di modificare il valore associato ad Ide con il valore Val. Se (Ide)= un’associazione Ide Val viene inserita nel frame risultante. Formalmente: Val se Ide1=Ide2 [Val/Ide1](Ide2)= (Ide2) se Ide1 Ide2
Sistema di transizioni per: Semantica dei Comandi S S com ={< com, T com, com } {Ide Val} com = { | C Com, {Ide Val} } {Ide Val} { | {Ide Val} } {Ide Val} T com = { | {Ide Val} } com = {(=),..., tutte le regole che vedremo }
Comandi: Assegnamento E::= NumExp | BoolExp Com::= Ide = E; exp v com [v/x] (=) Sintassi Semantica
Comandi: Block e Sequenza Com::=... |Block |... Block::= {StmtList} StmtList::= Stmt StmtList | Stmt com ’ com ’ com ” com ’ com ” com ’ com ’ com ’ (Block) (Stml ) Sintassi Semantica
Comandi Comandi (riepilogo: =, Block, Stml) com ’ com ’ com ” com ’ com ” com ’ com ’ com ’ (Block) (Stml ) exp v com [v/x] (=)
Calcoliamo com {(Block), com {(Stls), com {(=), exp 2} [2/x] com {(Stls), com {(=), exp 3} [2/x][3/y] com {(Stls), com {(=), < y-x, [2/x][3/y] exp 1} [2/x][3/y][1/x]} [2/x][3/y][1/x]} [2/x][3/y][1/x] Un calcolo parametrico in ci dice molto sul calcolo generato da ogni specifico stato: 1) Sia ={x->0,y->0,z->8}. Quale stato e’ calcolato? Quale stato e’ calcolato? 2) Sia ={x->0,z->8}. Quale stato e’ calcolato? Quale stato e’ calcolato? 3) Per quale insieme di stati e’ calcolata una configurazione finale configurazione finale
Com::=... | (BE) Com else Com |... Com::=... | if (BE) Com else Com |... exp tt com ’ exp tt com ’ com ’ com ’ exp ff com ’ exp ff com ’ com ’ com ’ (if-tt) (if-ff) Condizionale (if) Sintassi Semantica
Com::=... | while (BE) Com |... exp ff exp ff com com exp tt, com ”, com ’ exp tt, com ”, com ’ com ’ com ’ (W-ff) (W-tt) Iterazione (while) Sintassi Semantica
Dichiarazioni Chi introduce lo stato da cui siamo “partiti” nella valutazione dei nostri comandi,…? Dcl::= Type Ide; | Type Ide = Exp; Type ::= int | boolean Stmt::= Dcl | Com Prog::=prog {StmtList} prog {int x; boolean ok= true; if (ok) x=6; else x=1;} esempio
Semantica del programma e delle dichiarazioni dcl [ /x] dcl [ /x] exp v exp v dcl [v/x] dcl [v/x] (var1) (var2) com com dcl dcl (prog)
0) y=x-1 else y=0;}, > com {(Prog), 0) y=x-1 else y=0;, > com {(Stls), com {(var2), exp 2} [2/x] 0) y=x-1 else y=0;, [2/x] > com {(Stls), com {(var1), [2/x][ /y] 0) y=x-1 else y=0;, [2/x][ /y] > com {(if-t), 0;, [2/x][ /y]> exp {(BE), 0, [2/x][ /y]> exp true} com {(=), exp 1} 1 [2/x][1/y]} Un esempio prog {int x=2; int y; if (x>0) y=x-1 else y=0;} Calcoliamo
Un altro esempio prog { int x=9; (1) int y=3; (2) if (x>=y) {int z=x; (3) x=z-y;} (4) y=z; } (5) Notare il blocco annidato e l’uso di z. È corretto? Ha senso? Proviamo a calcolare lo stato ai punti (1),(2),(3),(4) e (5) x 9 (1) x 9 y 3 (2) x 6 y 3 z 9 (4) x 9 y 3 z 9 (3) x 6 y 9 z 9 (5) ?
Variabili locali ad un blocco Se la visibilità (portata o scope) di z fosse quella che risulta dalla semantica non si capisce perchè z non venga definito subito. Poter definire variabili dove e quando servono aumenta la leggibilità del programma. In realtà il programma precedente dà un errore perchè z risulta indefinita alla riga (5). In effetti z è una variabile locale al blocco comando dell’if. Per dare la semantica dei linguaggi a blocchi è necessario rappresentare lo stato con una struttura più complessa.
Lo stack (o pila ) (proprio quella dei piatti che avete lavato ieri sera) Lo stack è una sequenza di elementi in cui è definito un particolare ordine di manipolazione degli elementi. Definiamo – –lo stack vuoto: è la particolare pila che non contiene elementi (indicata con nil, EmptyStack, ecc.) – –la testa dello stack (top dello stack): calcola l’ultimo elemento inserito, non modifica lo stack – –pop: calcola l’elemento in testa allo stack e modifica lo stack eliminando l’elemento in testa. – –push: inserisce un elemento in testa allo stack, nel seguito push è indicata con ‘.’. Modifica lo stack.
Esempi di stack e operazioni s pop(s)=6 testa s s pop(nil)= (indefinito) è una situazione di errore push(1,s)
Lo stato I frame sono insufficienti per definire la semantica di un linguaggio di programmazione come Java. Definiamo lo stato come uno stack di frame. Indichiamo con lo stack(stato) vuoto, con ‘.’ push, esempio: 1 ={, }, 2 ={, },
Selezione del valore associato ad un identificatore in uno stack di frame L’operazione di selezione di un valore associato ad un identificatore (Ide) restituisce il valore associato ad Ide nel frame top dello stack.Se non c’è nessun legame in tale frame si va a cercare nel resto dello stack Quindi nel caso ci sia più di un frame che contiene un’associazione per Ide, il valore che viene restituito è quello del primo frame che si incontra accedendo allo stack secondo l’ordine consueto (degli stack)
Selezione del valore di un identificatore nello stato (stack di frame) (Ide)se = ‘ (Ide) ‘(Ide) se = ‘ (Ide) = (Ide)= se = Formalmente abbiamo la seguente definizione ricorsiva:
Modifica di stack di frame L’operazione di modifica di uno stato costituito da uno stack di frame [Val/Ide] ha il significato di modificare il valore associato ad Ide con il valore Val, solo nel caso che ci sia, nello stato, almeno un frame che contiene un’associazione per Ide. Nel caso ci sia più di un frame che contiene un’associazione per Ide, il frame che viene modificato è il primo frame che si incontra accedendo allo stack secondo l’ordine consueto (degli stack)
Modifica dello stato (stack di frame) [Val/Ide]. ‘ se = ‘ (Ide) . ‘[Val/Ide] se = ‘ (Ide) = [Val/Ide]= se = Formalmente abbiamo la seguente definizione ricorsiva:
Modifica dello stato (stack di frame) ESERCIZIO Si consideri lo stack di frames: = . ’.Ω dove e ’ sono i seguenti frames: = [0/x] [1/y] ’= [4/y] [10/x]. Indicare i valori ’(x), ’(y) e ’(z) nei seguenti casi: ’= ( [0/z])[10/z] ’= [10/z]. ’[5/z, 9/x].Ω
Sistema di transizioni con stack di frame S S com ={< com, T com, com } com = { | C Com, } { | } T com = { | } com = {(=),..., tutte le regole che vedremo }
La nuova semantica: il Blocco e StmtList com . ’ com . ’ com ’ com ’ com ” com ’ com ” com ’ com ’ com ’ (Block) (StmtList)
com com (prog) La nuova semantica: il programma e = exp v (x)≠ com [v/x] (=) Che succede con questa nuova semantica se (x)= ? Vedi semantica della modifica di stack di frame
Semantica delle dichiarazioni ” ’ [ /x] ” dcl ’ dcl ’ exp v ” ’ [v/x] ” exp v ” ’ [v/x] ” dcl ’ dcl ’ (var1) (var2) Notare l’inserzione del legame nel top dello stack (vedi la semantica della modifica di frame e stack)
Com::=... | if (BE) Com else Com |... exp tt cmd ’ exp tt cmd ’ com ’ com ’ exp ff cmd ’ exp ff cmd ’ com ’ com ’ (if-tt) (if-ff) La nuova semantica: if Sintassi Semantica
Com::=... | while (BE) Com |... exp ff exp ff com com exp tt, com ”, com ’ exp tt, com ”, com ’ com ’ com ’ (W-ff) (W-tt) La nuova semantica: while Sintassi Semantica
(B () ) (B true ) exp b exp b’ b [op] b’ = b” exp b” exp b exp b’ b [|] b’ = b” exp b” exp b exp b’ b [&] b’ = b” exp b” exp b not b = b’ (x)= b ! E exp b’ exp b exp tt exp ff (B Ide ) (B | ) (B & ) (B ! ) (BE op ) (B false ) (B true ) La nuova semantica: le espressioni
x 6 y 3 (6) Stack con 1 frame x 6 y 3 (5) z 9 L’ultimo esempio prog {int x=9; (1) int y=3; (2) if (x>=y) {(3) int z=x; (4) x=z-y;(5) } (6) y=z; } Calcoliamo, con la nuova semantica, le transizioni di stato x9 (1) x 9 y 3 (2) Stack con 2 frame Errore (5) (z) Top dello stack x 9 y 3 z 9 (4) x 9 y 3 (3)
Linguaggi a blocchi Java è un linguaggio a blocchi perchè le variabili esistono solo all’interno del blocco in cui sono definite. In Java è vietato definire in un blocco una variabile con lo stesso nome di una variabile già definita, cioè definita in un blocco più esterno. La ridefinizione è ammessa, invece, in quasi tutti i linguaggi a blocchi con la seguente semantica: Sia y la variabile definita nel blocco più esterno e y la variabile definita nel blocco interno. y e y sono due variabili diverse. La y esiste solo nel blocco interno e poi scompare. La y esiste sempre (cioè nel blocco esterno e quindi in quello interno) ma nel blocco interno non si riesce a denotare (è coperta dalla y).
x 4 y 3 (5) x 4 y 3 (4) y 5 Un esempio di ridefinizione x9 (1) x 9 y 3 (2) x 9 y 3 y 5 (3) prog { int x=9; (1) int y=3; (2) if (x>=y) {int y=5; (3) x=x-y;(4) } (5) y=x+1; } (6) È corretto? la y e la y sono la stessa variabile o no? Calcoliamo lo stato ai punti (1),(2),(3),(4),(5),(6) x 4 y 5 (5) Questo programma in Java dà un errore
Com::=... | for (T Ide =Exp1; BE ; Ide=Exp2) C |... com ’, com ’, ’ com ” com ” com ” com ” Iterazione (for) Sintassi Semantica (for)
Equivalenza di programmi I comandi C e C’ sono equivalenti se vale – – e NON portano ad una configurazione terminale – – * ’ e * ’ raggiungono la STESSA configurazione terminale Dimostrazione per casi se necessario
Equivalenza debole di programmi I comandi C e C’ sono equivalenti in uno stato tale che...(es (x)=v) – – * ’ e * ’ raggiungono la STESSA configurazione terminale Dimostrazione per casi se necessario anche in questo caso