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