...

Semantica Operazionale

by user

on
Category: Documents
10

views

Report

Comments

Transcript

Semantica Operazionale
Elementi di semantica
operazionale
1
Sintassi e semantica
 un linguaggio di programmazione, come ogni sistema formale, possiede

una sintassi
• le formule ben formate del linguaggio (o programmi sintatticamente
corretti)

una semantica
• che assegna un significato alle formule ben formate
• dando un’interpretazione ai simboli
– in termini di entità (matematiche) note
2
Sintassi e semantica
 la teoria dei linguaggi formali fornisce i formalismi di specifica
(e le tecniche di analisi) per trattare gli aspetti sintattici
 per la semantica esistono diverse teorie
 le più importanti sono la semantica denotazionale e la
semantica operazionale
 la semantica formale viene di solito definita su una
rappresentazione dei programmi in sintassi astratta
 invece che sulla reale rappresentazione sintattica concreta
3
Semantica operazionale
• lo stile di definizione tradizionale è quello dei sistemi di transizione
• insieme di regole che definiscono
•
attraverso un insieme di relazioni di transizione
come lo stato cambia per effetto dell’esecuzione dei vari costrutti
• una tipica regola descrive la semantica di un costrutto sintattico c
eseguito nello stato s, specificando il nuovo stato s’ e/o il valore
calcolato v
• i domini semantici con cui rappresentiamo lo stato ed i valori
dipendono dal linguaggio di programmazione
4
Linguaggio Didattico
 Semplice linguaggio imperativo (frammento
di C), blocchi, puntatori, chiamata di
funzione
 Rivediamo l’interprete presentato a
Programmazione I
5
Sintassi concreta
Programma::= int main() {StmtList}
StmtList ::= Stmt ; StmtList | e
Stmt::=Decl | Com
Comandi
Com::=Ide=Exp |
Assegnamento
if (Exp) Com else Com |
Condizionale
while (Exp) Com |
Iteratore
{StmtList} |
Blocco
Ide(Exp) |
Invocazione di fun
return Exp
Calcolo dei risultato di una fun
Espressioni
Exp::= Ide |
Identificatore
Costante |
Costante
Exp Op Exp |
Operazioni Binarie
Uop Exp |
Operazioni Unarie
Ide(Exp) |
Chiamata di fun
(Exp)
Parentesi
Espressioni 2
Ide::= Lettera (Lettera | Cifra | Simbolo)*
Costante::= Numero | Carattere
UnOp::= ! | * |
Op::=+ | - | * |...& | > | < | ==....
Numero::=É
Puntatori
 ! si applica per semplicita’ ai soli identificatori. La
locazione calcolata, in questo caso `e la locazione in
cui `e memorizzato il valore dell’identificatore
 * che si applica ad una qualunque espressione, la
calcola ottenendo un valore v che viene per`o
trasformato in una locazione l. Il valore finale
calcolato `e il valore v’ contenuto nella locazione l.
Dichiarazioni
Decl ::=
Type Ide [=Exp] |
FunctDec
variabile
funzione
FunctDec::= Type Ide (Formal) {StmtList}
Type::= int
Formal::= Type Ide
Nota
 Per semplicita’ si considerano funzioni che
hanno un solo parametro formale
 L’estensione a piu’ parametri e’ banale
 Ricordiamo che il passaggio dei parametri
e’ per valore
Semantica Operazionale
 Domini dei valori
 Componenti dello stato
 Regole di Transizione per ogni categoria
sintattica (espressioni, dichiarazioni,
comandi,programmi)
Domini semantici: lo stato
 in un qualunque linguaggio ad alto livello, lo stato
deve comprendere una componente chiamato
ambiente (environment)
 per modellare l’associazione tra gli identificatori
ed i valori che questi possono denotare (dval)
 il nostro frammento è imperativo ed ha la nozione di
entità modificabile, cioè le variabili ed i puntatori
(create con le dichiarazioni e modificate con
l’assegnamento)
 è quindi necessario un secondo componente dello
stato, chiamato memoria (store)
 per modellare l’associazione fra locazioni e valori
che possono essere memorizzati (mval)
14
L’ambiente
 Per modellare i blocchi l’ambiente e’ una
pila di Frames
• La politica FIFO permette di catturare la
dichiarazione piu’ recente di una variabile
Valori (memorizzabili)
 Ide identificatori
 Val=Int + {omega}+{Undef}
 Loc le locazioni di memoria, possono essere
rappresentati come numeri naturali. Nel seguito
useremo la notazione 0L , 1L , 2L ...ecc, per indicare
rispettivamente le locazioni di indirizzo 0, 1, 2 ecc
Memoria
• store: Loc ---> Val
(si usa la metavariabile μ)
 Nota: Val non contiene le locazioni. Nella
semantica data, si usano meccanismi per
trasformare locazioni in valori e viceversa. La
seconda `e possibile ed anzi molto semplice
perch`e le locazioni sono numeri naturali
Frame
• frame: Ide ---> Den
(si usa la metavariabile φ)
 Den = Loc ∪ FunDecl ∪ Unbound.
L’insieme delle denotazioni `e l’unione
dell’insieme Loc degli indirizzi di memoria e
dell’insieme FunDecl delle definizioni di
funzione e della denotazione speciale Undef,
che rappresenta una situazione di errore.
Funzioni
FunDecl `e una tripla
Ide × SList × Env
1) il nome del parametro formale
2) il corpo della funzione
3) l’ambiente di definizione (scoping
statico)
Operazioni sui Frames
 EmptyFrame crea il frame ovunque
indefinito
φ(x)=Unbound per ogni x
Modifica di un frame
φ[d/x](y)= φ(y) se x e’ diverso da y
d se x=y
• La definizione cos`ı data risulta corretta
anche nell’eventualit`a che un legame diverso
da Unbound per x esista gia’
• non e’ molto corretto solo per programmi
sintatticamente corretti
Ambiente
• env=Stack(Frames)
(si usa la metavariabile σ)
Operazioni sulla pila
• EmptyStack crea la pila vuota
• top restituisce l’elemento in testa alla pila
ovvero l’ultimo elemento inserito. Non
modifica la pila.
• pop restituisce l’elemento in testa alla pila.
Modifica la pila, eliminando l’elemento in
testa.
• push inserisce un elemento in testa alla pila.
Operazioni sulla memoria
• μ : Loc ---> Val
Val=Int + {omega}+{Undef}
• Verrebbe da dare operazioni analoghe a
quelle del frame....si tratta di una
funzione parziale
Gestione della memoria
• allocazione di memoria: l’inserzione di
nuovi legami nella memoria corrisponde alla
allocazione di memoria su una machina, e
differisce dall’inserzione di un nuovo legame
in un generico frame
• Deve esserci un meccanismo per assegnare una
nuova locazione ancora libera
• Deve esserci un modo per distinguere una
locazione assegnata con valore indefinito da
una libera
Operazioni sulla Memoria
• μ(l)=omega
• μ(l)=Undef
valore speciale
indefinita
 EmptyStore crea una memoria ovunque
indefinita
μ(x)=Undef per ogni x
Allocazione di Memoria
• free: Store---> Loc *Store
• restitituisce una nuova locazione libera e la
memoria modificata di conseguenza
• free(μ) = (μ’,l) dove
μ’(l’)= μ(l’) per ogni l’!= l
μ’(l)=omega se μ(l)=Undef
Modifica di Memoria
μ[v/l](l’)= μ(l’) se l != l’
Undef
se μ(l)=Undef
v altrimenti
 l’operazione di modifica non effettua
l’inserzione del legame per l nel caso non ne
esista alcuno ma in questo ultimo caso, lascia
la memoria invariata (da un punto di vista
matematico va bene....)
Le funzioni di valutazione semantica
 per ogni dominio sintattico esiste una funzione di
valutazione semantica
 E : EXPR * env * store  (eval * store)
 C : COM * env * store  store
 D : DEC * env * store  (env * store)
 P : PROG * env * store  store
29
Implementazione in OCaml
 Vediamo i domini
 La Sintassi Astratta
 Le funzioni di valutazione semantica che
assegnano un significato ai vari costrutti, con una
definizione data sui casi della sintassi astratta
 Per semplicita’ nell’interprete si usano funzioni
che restituiscono una coppia (ambiente, memoria)
per ogni categoria sintattica
Programma PicoC
 http://www.di.unipi.it/~occhiuto/PicoC/
 Generatore di programmi PicoC in
sintassi astratta
 Alcuni esempi di programmi PicoC in
sintassi astratta per testare l`interprete
Valori
Val=Int + {omega}+{Undef}
type value =
Val of int |
Omega |
Undef;;
Valori Denotabili
Den = Loc ∪ FunDecl ∪ Unbound
type denotation =
Loc of int |
Funct of string * com * sigma ref |
Unbound;;
•
In FunDecl c’e’ il riferimento all’env (per
trattare la ricorsione ..)
Frame
• frame: Ide ---> Den
(si usa la metavariabile φ)
type fi = Frame of
(string * denotation) list;;
• Definizione molto a basso livello, una lista di
coppie (identificatore, valore)
Ambiente
• env=Stack(Frames)
type sigma = Stack of
fi list;;
• Definizione molto a basso livello, una lista di
frames
Memoria
• μ : Loc ---> Val
 type 'a mu = Mem of 'a list ;;
• Definizione molto a basso livello, una lista
polimorfa
• Si usera’ per memorizzare coppie (identificatore,
valore)
Espressioni
 type aop = Add | Sub | Mul | Div | And
| Or | Ls | Gr | Eq ;;
 type unop = Neg | Amp | Star;;
 type aExp = Num of int |
Exp of aExp * aop * aExp |
Bracket of aExp |
UnExp of unop * aExp |
Var of string |
Apply of string * aExp ;;
Comandi
 type com = Assign of string * aExp |
AssignDeRef of aExp * aExp |
If of aExp * com * com |
While of aExp * com |
Block of (stmt list) |
Return of aExp;;
Dichiarazioni
 type decl =
Decl1 of espType * string |
Decl2 of espType * string * aExp |
DeclFun of espType * string * espType *
string * com;;
Programmi
type stmt = StDec of decl |
StCom of com;;
type prog = Prog of (stmt list);;
• Un programma e’ una lista di statements
(dichiarazioni, comandi)
Funzione main
 let valProg (Prog l)=
let (sigma,mu)=
valStmtL l (Stack[Frame[]],(Mem []))in
(mu,sigma);;
• Il programma e’ valutato nello stato iniziale,
lo stack contiene un frame vuoto e la
memoria e’ vuota
• restituisce lo stato ottenuto
Per valutare una lista di
statements
 Funzione ricorsiva (valStmtL)
 Per ogni statement (comando o
dichiarazione) chiama la funzione di
valutazione corrispondente
Lista di Statements
let valStmtL l (sigma, mu) =
match l with|
[] -> (sigma, mu)|
st::stml ->
(match st with
| StDec d -> let (sigma1, mu1) = valDecl d
(sigma,mu)
in valStmtL stml (sigma1,mu1)
|
StCom c -> let (sigma1,mu1) = valCom c
(sigma,mu)
in valStmtL stml (sigma1,mu1));;
Dichiarazioni
 valDecl:
Decl * (env*mem)---> (env*mem)
 Funzione ricorsiva (valDecl)
 Usa valExp:
Exp* (env*mem)---> (Val*env*mem)
Dichiarazioni
 Variabile senza inizializzazione
 Variabile con inizializzazione
 Funzione
Sintassi Astratta
 type decl =
Decl1 of espType * string |
Decl2 of espType * string * aExp |
DeclFun of espType * string * espType *
string * com;;
Funzioni Ausiliarie: memoria
• free: Store---> Loc *Store
• restitituisce una nuova locazione libera e la
memoria modificata di conseguenza (alla nuova
locazione viene assegnato il valore omega)
type 'a mu = Mem of 'a list ;;
Implementazione
let free (Mem xm) = let loc = (length xm)
in
((Loc loc),
(Mem (append xm [((Loc loc),Omega)]
)));;
• la lista e’ del tipo [(0,v1),(1,v20)...]
• la prima locazione libera e’ detreminata con
length
Modifica della Memoria
 Serve una operazione
updateM:Store*Loc*Val---> Store
• Modifica la memoria rimpiazzando il
valore associato alla locazione con il
nuovo valore
Implementazione
let rec updateM (Mem m) (x,y) = let def m x = foldr
(or) false (map (compose ((=) x) (fst)) m)
and modify m (x,y) = let f (x,y) b = if ((fst b)=x)
then (x,y) else b
in map (f(x,y)) m
in if (not(def m
x)) then (Mem m) else (Mem (modify m (x,y)));;
Usa due funzioni ausiliarie def e modify per
testare se la locazione x e’ definita e per
modificarne il valore nella lista
Modifica dell’env
let rec addBind sigma (x,y) = match sigma with
| Stack [Frame[]] ->
Stack [Frame[(x,y)]]
| Stack ((Frame f)::fs) ->
Stack ((Frame (append f [(x,y)])) ::fs);;
• inserisce il nuovo legame tra x ed y nell’env
sigma (ovvero nel frame al top della pila, tramite
append e’ una lista di coppie)
Dichiarazione di variabile
semplice
let valDecl d (sigma,mu) = match d with
Decl1 (t,i) ->
let (l,mu1) = free mu
in let sigma1= (addBind sigma (i, l))
in (sigma1, mu1)
• viene modificata la memoria (l e’ una locazione
fresh, coniene valore indefinito)
• viene modificato l\’env inserendo l’associazione
(i,l)
Dichiarazione di variabile con
inizializzazione
let valDecl d (sigma,mu) = match d with
Decl2 (t,i,e) ->
let (v,(sigma1,mu1)) = (valExp e (sigma,mu))
in let (l,mu2) = free mu1 in
let sigma2= (addBind sigma1 (i,l))
in let mu3 =
updateM mu2 (l, v) in (sigma2, mu3)
• viene modificata la memoria (l e’ una locazione fresh
coniene valore indefinito)
• viene modificato l ’env inserendo l’associazione (i,l)
• il contenuto della locazione l viene poi aggiornato con il
valore calcolato per l’espressione e
Dichiarazione di Funzione
DeclFun (t,i,tp,ip, c)
• stiamo dichiarando una funzione di nome
i,parametro ip, corpo c in (sigma,mu)
• dovremmo modificare l’env sigma
inserendo l’associazione tra i e la sua
descrizione
(ip,c,sigma1)
• chi e’ sigma1? vediamo la regola formale
Problemi di Implementazione
• bisogna implementarlo usando un
puntatore all’env in FunDecl
Funct of string * com * sigma ref |
Unbound;;
Dichiarazione di Funzione
let valDecl d (sigma,mu) = match d with
DeclFun (t,i,tp,ip, c) ->let rec
sigma1=(addBind sigma (i,
(Funct (ip,c, (ref sigma)))))
in ((update i sigma1 sigma1),mu)
• in sigma1 la descrizione della funzione i contiene
un riferimento a sigma (andrebbe bene se non
fossero ricorsive
• nota che viene restituito come risultato
update i sigma1 sigma1
Intuitivamente
update i sigma1 sigma1
• cerca la descrizione di funzione di i in sigma1
(p,c, sigma ref)
• la modifica assegnando sigma1 al posto di sigma
Funzione Ausiliaria
let rec updateF i f sigma = match f with
[] -> f |
(j, Funct(x,c,var))::fs when (i=j) ->
var :=sigma; f
| (_,_)::fs -> updateF i fs sigma;;
let rec update i s sigma = match s with
Stack [Frame[]]-> s |
Stack ((Frame fs)::ss) ->
(updateF i fs sigma); s;;
Comandi
 valCom:
Com * (env*mem)---> (env*mem)
 Funzione ricorsiva (valCom)
 Usa valExp:
Exp* (env*mem)---> (Val*env*mem)
Comandi





Condizionale
While
Assegnamento
Blocco
Return
Comandi
 type com = Assign of string * aExp |
AssignDeRef of aExp * aExp |
If of aExp * com * com |
While of aExp * com |
Block of (stmt list) |
Return of aExp;;
Funzioni Ausiliarie: env
• lookup: Env * Ide---> Den
Den = Loc ∪ FunDecl ∪ Unbound
• restitituisce il valore denotabile
associato all’identificatore
• Env e’ uno Stack di Frames, in realta’ e’ una lista
di frames
• la ricerca ricorsiva inizia dal frame al top, e.g. dal
primo elemento della lista
Funzioni Ausiliarie: frame
• look: Frame * Ide---> Den
Den = Loc ∪ FunDecl ∪ Unbound
• restitituisce il valore denotabile
associato all’identificatore
• Frame e’ una lista di coppie (identificatore,
valore)
Implementazione
let rec lookUp sigma y =
match sigma with
|
Stack [] -> Unbound
|
Stack (x :: xs) -> let b= (look x y)
in if (not (b=Unbound))
then b else (lookUp (Stack xs) y);;
let rec look fi y = match fi with
|
Frame [] -> Unbound
|
Frame ((i, d) :: xs) ->
if (i=y) then d else (look (Frame xs) y);;
Condizionale
let valCom c (sigma,mu) = match c with
| If (e,c1,c2) -> let
((Val i),(sigma1,mu1)) = (valExp e (sigma,mu))
in if not (i=0) then valCom c1 (sigma,mu1)
else valCom c2 (sigma,mu1)
• viene calcolato il valore di e
• se true esegue c1, altrimenti c2
While
let valCom c (sigma,mu) = match c with
| While (e,c) -> let
((Val i),(sigma1,mu1)) = (valExp e (sigma,mu))
in
if not (i=0) then
let (sigma2,mu2) = (valCom c (sigma1,mu1))in
valCom (While (e,c)) (sigma2,mu2)
else
(sigma1, mu1)
• viene calcolato il valore di e, se false restituisce
(sigma1,mu1)
• se true esegue While (e,c) nello stato
modificato da c
Assegnamento
let valCom c (sigma,mu) = match c with
| Assign (s,e) -> let
(v,(sigma1,mu1)) = (valExp e (sigma,mu))
and (Loc l) = (lookUp sigma s) in
(sigma1, updateM mu1 ((Loc l),v)
• viene calcolato il valore v di e e la locazione l
legata alla variabile s in sigma
• viene modificato lo store assegnando alla
locazione l il valore v
Blocco
let valCom c (sigma,mu) = match c with
| Block l ->
let (Stack (f::rl),mu1) =
valStmtL l
((match sigma with Stack fl ->
Stack (Frame[]::fl)) ,mu)
in (Stack rl, mu1)
• valuta l nello stato in cui un frame vuoto Frame[]
e’ stato messo al top della pila
• restituisce l’env da cui e’ stato fatto pop (le
variabili del blocco sono locali)
Blocco: regola astratta
• l’implementazione delle operazioni di pop() e
push(frame) e’ parecchio complicata
• regola astratta
Return
let valCom c (sigma,mu) =
match c with
| Return e ->
valCom (Assign ("retVal",e))
(sigma,mu))
• assegna il valore di e ad una variabile speciale
retval, valore di ritorno della funzione che e’ in
esecuzione
Assegnamento Deferenziato
let valCom c (sigma,mu) = match c with
| AssignDeRef (e,ev) -> let
(v,(sigma1,mu1)) =
(valExp ev (sigma,mu))
in let
(v1,(sigma2,mu2)) =
(valExp e (sigma1,mu1))
in let (Loc l) = (etaLoc v1) in
(sigma2, updateM mu2 ((Loc l),v))
• viene calcolato il valore v di e e il valore v1 di e
• viene modificato lo store assegnando alla
locazione corrispondente a v1 il valore v
Funzione Ausiliaria:
let niLoc x = match x with
(Loc l) -> (Val l)
|_ -> Undef;;
let etaLoc x = match x with
(Val n) when (n>=0) -> (Loc n)
| _ -> Unbound;;
• trasformano locazioni in valori interi e viceversa
Espressioni
 valExpr:
Expr * (env*mem)---> Val *(env*mem)
 Funzione ricorsiva (valExpr)
Espressioni




costanti
valore di una variabile
risultato di una chiamata di funzione
operazioni di confonto, somma tra
espressioni (binarie)
 operazione unaria
Espressioni
 type aop = Add | Sub | Mul | Div | And
| Or | Ls | Gr | Eq ;;
 type unop = Neg | Amp | Star;;
 type aExp = Num of int |
Exp of aExp * aop * aExp |
Bracket of aExp |
UnExp of unop * aExp |
Var of string |
Apply of string * aExp ;;
Funzioni Ausiliarie: stato
• getVal: (Env*Mem) * Ide---> Val
• deve restituire il valore associato
all’identificatore x
• cercare nella pila di Frames Env la locazione l
associata ad x
• restituire il valore associato ad l nella
memoria
Implementazione
let rec getVal (sigma,mu) x =
let b=(lookUp sigma x) in
match b with
|
Loc n -> (lookM mu (Loc n))
| _ -> Undef;;
• lookUp cerca nell’env (pila) la locazione n
associata ad x
• lookM cerca nella memoria il valore associato ad
n
Implementazione:lookM
let rec lookM mu y = match mu with
Mem [] -> Undef
| Mem (( i, v) :: xs) ->
if (i=y) then v else
(lookM (Mem xs) y);;
|
la memoria e’ una lista di coppie (i,v),
cerca ricorsivamente un identificatore
uguale ad y
Costante, Parentesi
let rec valExp e (sigma,mu) = match e
with
| Num n -> ((Val n),(sigma,mu))
| Bracket x
-> valExp x (sigma,mu)
Variabile
let rec valExp e (sigma,mu) = match e
with
| Var s ->
((getVal (sigma,mu) s),(sigma,mu))
• restituisce il valore associato alla
variabile s, calcolato tramite getVal
Operazioni Binarie
let rec valExp e (sigma,mu) = match e
with
| Exp (x, op, y) -> let
(v1, (sigma1,mu1))= (valExp x (sigma,mu))
in let
(v2,(sigma2,mu2))= (valExp y (sigma,mu1))
in...
• calcola ricorsivamente i valore v1 e v2 di
x ed y, rispettivamente
• in un ordine
Procede per casi sull’operazione
if (isNumOp op) then
(niNum ( (funNumOp op) (etaNum v1)
(etaNum v2)),(sigma2,mu2))
else
• isNumOp restituisce true se e’ una operazione
numerica (somma etc..)
• FunNumOp applica l’operazione corrispondente a op
ai valori v1 e v2
• niNum,etaNum servono solo per convertire i valori
Val i in i e viceversa
Funzioni ausiliarie
let
|
|
|
|
|
isNumOp op = match op with
Add -> true
Sub -> true
Div -> true
Mul -> true
_ ->
false;;
Funzioni ausiliarie
let funNumOp op = match op with|
Add -> (+)|
Sub -> (-)|
Mul -> (fun x y -> x*y) |
Div -> (/) ;;
Funzioni ausiliarie di
conversione per interi
let niNum x =
(Val x);;
let etaNum (Val x) = x;;
Procede per casi
if (isBoolOp op) then
(niBool( (funBoolOp op) (etaBool v1)
(etaBool v2)) ,(sigma2,mu2))
else
(niBool( (funRelOp op) (etaNum v1)
(etaNum v2)) ,(sigma2,mu2))
• se e’ un’operazione booleana applica la relativa
operazione ai valori booleani v1 e v2
• se e’ un’operazione relazionale applica la relativa
operazione ai valori booleani v1 e v2
Funzioni ausiliarie
let
|
|
|
isBoolOp op = match op with
And -> true
Or -> true
_ -> false;;
Funzioni Ausiliarie
let funBoolOp op = match op with
| And -> (&)
| Or -> (or) ;;
let funRelOp op = match op with|
Ls -> (<) |
Gr -> (>) |
Eq -> (=);;
Funzioni Ausiliarie di
conversione
let niBool x = if x then
(Val 1) else (Val 0);;
let etaBool (Val x) = if (x=0)
then false else true;;
Operazioni Unarie: per casi
let rec valExp e (sigma,mu) = match e with
| UnExp (op, x) -> (match op with
Neg ->
let
(v1, (sigma1,mu1))= (valExp x (sigma,mu))
in
(niBool( (funop1 op) (etaBool(v1))
),(sigma1,mu1))
 caso della negazione e’ analogo a quello
visto prima
 calcola il valore v di x e chiama funzioni
Operazioni Unarie: puntatore
| UnExp (op, x) -> (match op with
|Amp -> ((valDen x sigma),(sigma,mu))
 deve restituire la locazione di x
 usa una funzione ausiliaria valDen
Funzione ausiliaria:valDen
let rec valDen e sigma = (match e with |Var s ->
niLoc(lookUp sigma s)
|Exp (x,y,z) ->
Undef|UnExp(x,y) -> Undef|
Bracket x -> Undef);;
 e’ definita nel caso di espressione e generica,
ma e’ definita solo per le variabili
 tramite lookup restituisce la locazione associata
ad s nell’ambiente sigma
Operazioni Unarie: deferenziato
| UnExp (op, x) -> (match op with
|Star ->
let (v,(sigma,mu1)) =(valExp x (sigma,mu))
in (lookM mu1 (etaLoc v),(sigma,mu1)))
 calcola il valore v di x (tramite valExp)
 restuisce il valore memorizzato nella
memoria nella locazione v
Chiamata di Funzione
 Apply(s,a) dobbiamo applicare la funzione s al
parametro attuale a nello stato (sigma,mu)
 Parte I: dobbiamo cercare il nome s nell’ambiente
sigma, restituisce un FunDecl
Funct(f,c,sigmaf)
• f e’ il parametro formale
• c e’ il corpo della funzione
• sigmaf e’ l’ambiente al momento della dichiarazione
della funzione s (scoping statico)
 Parte II: dobbiamo valutare il parametro a nello stato
corrente, calcolarne il valore v (per valore)
Chiamata di Funzione:Part II
 Dobbiamo valutare il corpo della funzione c, in quale
stato?
 Lo stato di valutazione si costruisce a partire da
(sigmaf,mu)
• Bisogna mettere sulla pila sigmaf un EmptyFrame
(push) che serve per contenere le dichiarazioni locali
alla funzione
• Le dichirazioni locali conterranno il legame tra il
parametro formale f ed il valore del parametro attuale
v e la variabile speciale retval
• Nota che per inserire un legame devono essere modifica
sia l’ambiente che la memoria
Chiamata di Funzione:Part III
 Cosa restituisce?
 il valore associato alla variabile retval
 l’ambiente sigma al momento della chiamata (non
modificato)
 la memoria modificata dall’esecuzione dei comandi
Chiamata di Funzione: valExp
• Vediamo il codice di valExp per la funzione
• Molto complicato, perche’ di basso livello
• La nozione di stato (env,mem) non fornisce operazioni
chiare per fare push, pop
• Inoltre l’introduzione di un nuovo legame in un frame
viene fatto a mano, operando direttamente sulla lista
che implementa il frame
• Analogamente l’introduzione di un nuovo legame nella
memoria viene fatto a mano, operando direttamente
sulla lista che lo implementa
Chiamata di funzione
let rec valExp e (sigma,mu) = match e
with
| Apply (s,a) ->
let
(v,(sigma1,mu1))=
valExp a (sigma,mu) in
(match (lookUp sigma s) with
Funct (f,c, sigmaf) ->
....
• calcola tramite valExp il valore v del parametro
attuale a
• cerca tramite lookUp la FunDecl relativa ad s
Chiamata di funzione
(let (l,mu2)=(free mu1) in let (l1,mu3)
=(free mu2)
in let
sigmav=(match (! sigmaf) with
Stack sl ->
addBind (addBind (Stack
(Frame []::sl)) (f,l)) ("retVal",l1))
• sceglie due locazioni libere in memoria l ed l1
• modifica l’ambiente sigmaf , facendo push di
un frame che contiene (f,l) e (retval l1)
Chiamata di funzione
in let (sigma2,mu4)=
valCom c (sigmav,updateM mu3 (l, v))
in ((lookM mu4 l1),(sigma,mu4)))
• valuta il corpo della funzione c nell’ambiente sigmav
costruito in precedenza,e nella memoria ottenuta
aggiungendo il legame tra (l,v)
• restituisce il valore della locazione l1 nella memoria (il
valore di retval), l’ambiente sigma iniziale, e la
memoria finale mu4
Fly UP