Sémantique opérationnelle

Transcription

Sémantique opérationnelle
Sémantique opérationnelle
Evaluation d'une expression
Sans variable libre
Vu dans le châpitre 2
Avec variables libres
#pi *. r *. r ;;
#let f = fun x -> if v > 3*2 then x+3 else x*x*3 + v;;
Les variables qui apparaissent libres dans l'expression
(pi et r dans la première et v dans la seconde) doivent
avoir été définies au préalable.
L'interpréteur doit trouver dans l'environnement les valeurs
auxquelles elles sont liées.
Sémantique opérationnelle
Les notions de base
Liaison
C'est un couple (i, v) ou i est un identificateur et v une
valeur. On dit que i est liee a v.
Environnement
C'est une liste de liaisons
Environnement initial: E0
C'est l'environnement chargé quand on lance Ocaml.
Définition globale
Rajoute une liaison à l'environnement courant
Sémantique opérationnelle
Exemple
Environnement: E0
(pi, 3.14) :: E0
(r, 2.1) :: (pi, 3.14) :: E0
#let pi = 3.14 ;;
# let r = 2.1 ;;
#let s = pi*.r*.r ;;
(s, 13.8474) :: (r, 2.1) :: (pi, 3.14) :: E0
#let pi = 3.1416 ;;
(pi, 3.1416) :: (s, 13.8474) :: (r, 2.1) :: (pi, 3.14) :: E0
L'ancienne valeur de pi n'est plus accessible
# pi;;
- : float = 3.1416
Sémantique opérationnelle
Définitions en parallèle
●
●
Toutes leurs évaluations se font dans l'environnement
courant
Celui-ci est ensuite modifié
Environnement courant
E
# let x = 0;;
(x, 0) :: E
#let x = 3 and y= x+1;;
x : int = 3
y : int = 1
(x,3) :: (y,1) :: (x, 0) :: E
Sémantique opérationnelle
Définitions locales
●
●
●
Modifient momentanément l'environnement
C'est dans cet environnement modifié que se fait
l'évaluation de l'expression sur laquelle elles portent
In fine, l'environnement est inchangé
Sémantique opérationnelle
Définitions locales: exemples
Environnement courant:
#let x = 10 in x+1;;
(x,3) :: (y,1) :: (x, 0) :: E
x+1 évaluée dans (x, 10) :: (x,3) :: (y,1) :: (x, 0) :: E
- : int = 11
Environnement courant: (x,3) :: (y,1) :: (x, 0) :: E
#let x=x+1 and y=x+2 in x+y;;
x+1 et y évalués dans l'environnement courant
x+y évalué dans (x,4) ::(y,5):: (x,3) :: (y,1) :: (x, 0) :: E
- : int = 9
Environnement courant:
(x,3) :: (y,1) :: (x, 0) :: E
Sémantique opérationnelle
Définitions locales: exemples
Environnement courant:
(x,3) :: (y,1) :: (x, 0) :: E
#let x = x+1 in let y = x+2 in x+y;;
x+1 évaluée dans l'environnement courant
y est évalué dans (x, 4) :: (x,3) :: (y,1) :: (x, 0) :: E
x+y évaluée dans (y,6) :: (x, 4) :: (x,3) :: (y,1) :: (x, 0) :: E
- : int = 10
Environnement courant:
(x,3) :: (y,1) :: (x, 0) :: E
Sémantique opérationnelle
Evaluation des fonctions
Fermetures
●
●
●
●
Soit une fonction non récursive définie par:
let f = fun x -> corps
Châpitre 2 : fun x -> corps est sous forme réduite et
peut donc être considéré comme la valeur de f.
Ceci est (presque) vrai en l'absence de VL (variables
libres) (dans les implantations corps est simpifié)
Cette définition pourrait ainsi rajouter à l'environnement
courant la liaison : (f, fun x -> corps)
Quid des définitions de fonctions avec variables libres?
Quid des définitions récursives?
Sémantique opérationnelle
Evaluation des fonctions
Fermetures
_______________________________________________________________________________________
Exemple
____________________________________________________________________________________________
#let v = 2;;
#let f = fun x -> if v > 3*2 then x+3 else x*x*3 + v;;
VL(corps) : v, valeur à chercher dans l'environnement E
___________________________________________________________________________________________________________________________________________________________________________________________________________________________
Let f = fun x -> corps
La valeur de f est un couple
< fun x -> simpl(corps),
E >
simpl(corps): simplification de corps
E: environnement au moment de la définition de f
Sémantique opérationnelle
Evaluation des fonctions
Fermetures
let f = fun x -> corps
Nouvel environnement:
(f, <fun x -> simpl(corps), E> ) :: E
Fermeture
Car toute VL de simpl(corps) autre que x est liée dans E. Ce
couple ne contient aucune VL dont la valeur n'est pas
définie. En ce sens, il est fermé.
On n'évalue pas mais on enregistre dans la fermeture tous
les renseignements pour évaluer ultérieurement, au
moment de l'application à un argument.
Sémantique opérationnelle
Evaluation des fonctions
Liaisons statiques (ou lexicales) des VL
Environnement courant : E0
#let v = 2;;
(v,2) :: E0
#let f x = if v > 3*2 then x+3 else x*x*3 + v;;
(f, < fun x -> x*x*3+v, (v,2)::E0 >) :: (v,2)::E0
#let v = 100;;
(v,100) :: (f, < fun x -> x*x*3+v, (v,2)::E0 >) :: (v,2)::E0
Le v de corps f sera toujours évalué dans l'env. tel qu'il
était au moment de la définition de f (enregistré dans la
fermeture). La rédéfiniton ultérieure de v n'affecte en
rien la valeur de f : liaison statique
Sémantique opérationnelle
Evaluation des applications
Evaluation par valeur
Evaluation de (e1 e2) dans l'environnement E
–
–
–
Evaluation de e1 dans E : v1 = < fun x ->corps, E' >
Evaluation de e2 dans E : v2
Evaluation de corps dans (x, v2) :: E'
Dans corps, x est remplacé par v2 et les autres variables
par leur valeur dans E'
E est inchangé
Sémantique opérationnelle
Evaluation des applications
Evaluation par valeur
E = (v,100) :: (f, < fun x -> x*x*3+v, (v,2)::E0 >) :: (v,2):: E0
#f (2*v);;
- : int = 120002
2*v évalué dans E : 200
f évaluée dans E : < fun x -> x*x*3+v, (v,2)::E0 >
x*x*3+v dans (x,200) :: (v,2)::E0 : 200*200*3+2 = 12002
Sémantique opérationnelle
Evaluation des applications
Evaluation par valeur
E = (v,100) :: (f, < fun x -> x*x*3+v, (v,2)::E0 >) :: (v,2):: E0
#f (2*v);;
- : int = 120002
2*v évalué dans E : 200
f évaluée dans E : < fun x -> x*x*3+v, (v,2)::E0 >
x*x*3+v dans (x,200) :: (v,2)::E0 : 200*200*3+2 = 12002
Sémantique opérationnelle
Evaluation des applications
Evaluation par nom
de (e1 e2) dans l'environnement E
●
●
Evaluation de e1 dans E : v1 = < fun x ->corps, E'>
Evaluation de corps dans (x, <e2, E>) :: E'
–
–
Ce qui ne change pas:
● Les VL de corps autres que x sont évaluées dans E'
Ce qui change:
● Les valeurs des variables sont des fermetures car
elles ne sont pas évaluées immédiatement.
● On évalue corps avant e
2
● la valeur de e
2 dans l'environnement courant est
calculée à chaque occurrence de x dans corps
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
Par analogie avec les fonctions non récursives, la valeur de fact
serait la fermeture définie par:
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Mais le corps contient une variable libre: fact, qui n'est pas dans
E'. Le couple n'est pas fermé et on ne saura où trouver la
valeur de fact quand on évaluera le corps lors d'une
application.
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Exemple
(fun n -> if n=0 then 1 else n * fact(n-1)) 2
Dans le corps, n est remplacé par 2. Mais par quoi est
remplacé fact? E' ne rien là-dessus !
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Il est nécessaire de rajouter dans l'environnement de la
fermeture ... la liaison de la variable fact qui est :
(fact, ?)
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Il est nécessaire de rajouter dans l'environnement de la
fermeture ... la liaison de la variable fact qui est :
(fact, @_fact)
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Il est nécessaire de rajouter dans l'environnement de la
fermeture ... la liaison de la variable fact qui est :
(fact, @_fact)
On obtient:
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1),
(fact, @_fact)::E' >
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1), E' >
Il est nécessaire de rajouter dans l'environnement de la
fermeture ... la liaison de la variable fact qui est :
(fact, @_fact)
On obtient:
@_fact = < fun n -> if n=0 then 1 else n * fact(n-1),
(fact, @_fact)::E' >
Définition circulaire !
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
Dans l'environnement E' on définit:
#let rec fact = fun n -> if n = 0 then 1 else n * fact(n-1);;
On obtient donc un nouvel environnement
E = (fact, @_fact) :: E'
Avec
@_fact = < fun n -> corps, (fact, @_fact) :: E' > I.E.
@_fact = < fun n -> corps, E >
en posant
corps = if n = 0 then 1 else n * fact(n-1)
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
@_fact = < fun n -> corps, (fact, @_fact):: E' >
Il s'agit d'un terme infini: On peut remplacer @_fact dans
la fermeture par sa valeur (on déplie) et on obtient:
@_fact =
< fun n -> corps,
(fact, < fun n -> corps, (fact, @_fact):: E' >):: E' >
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
@_fact = < fun n -> corps, (fact, @_fact):: E' >
@_fact =
< fun n -> corps,
(fact, < fun n -> corps, (fact, @_fact):: E' >):: E' >
En redépliant, on obtient:
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
@_fact = < fun n -> corps, (fact, @_fact):: E' >
@_fact =
< fun n -> corps,
(fact, < fun n -> corps, (fact, @_fact):: E' >):: E' >
En redépliant, on obtient:
@_fact =
< fun n -> corps,
(fact, < fun n -> corps,
(fact, < fun n -> corps, (fact, @_fact):: E' >) :: E' >)
:: E' >
Sémantique opérationnelle
Evaluation des fonctions récursives
Etude d'un exemple
L'idée est que ces termes circulaires sont dépliés autant de
fois que nécessaire à l'évaluation d'un application, pas
plus, pas moins.
Sémantique opérationnelle
Evaluation des fonctions récursives
Evaluation de (fact 2) dans E.
-> Evaluation de fact dans E:
-> @_fact = <fun n-> if n=0 then 1 else n*fact(n-1), E>
-> Evaluation de n*fact(n-1) dans E2 = (n,2)::E
-> Evaluation de fact (n-1) dans E2
-> Evaluation de n-1 dans E2 -> 1
-> Evaluation de fact dans E2 - > @_fact
-> Evaluation de n*fact(n-1) dans E1 = (n,1)::E
E1 est empile sur E2
Sémantique opérationnelle
Evaluation des fonctions récursives
-> Evaluation de fact (n-1) dans E1 = (n,1)::E
-> Evaluation de (n-1) dans E1 -> 0
-> Evaluation de fact dans E1 -> @_fact
-> Evaluation de if n=0 then 1 else n*fact(n-1)
dans E0 = (n,0)::E
E0 est empile sur E1
-> 1
E0 est dépilé. On se retrouve dans E1
-> Evaluation de n -> 1
-> Evaluation de 1*1 ->1
E1 est depilé. On se retrouve dans E2
-> Evaluation de n ->2
-> Evaluation de 2*1 = 2