Upload
hahanh
View
225
Download
0
Embed Size (px)
Citation preview
Ecole Polytechnique
INF564 – Compilation
Jean-Christophe Filliatre
Cours 4 / 1er fevrier 2018
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 1
typage
si j’ecris l’expression
"5" + 37
dois-je obtenir
• une erreur a la compilation ? (OCaml)
• une erreur a l’execution ? (Python)
• l’entier 42 ? (Visual Basic, PHP)
• la chaıne "537" ? (Java)
• autre chose encore ?
et qu’en est-il de
37 / "5"
?Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 4
typage
et si on additionne deux expressions arbitraires
e1 + e2
comment determiner si cela est legal et ce que l’on doit faire le casecheant ?
la reponse est le typage, une analyse qui associe un type a chaquesous-expression, dans le but de rejeter les programmes incoherents
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 5
a quel moment ?
certains langages sont types dynamiquement, c’est-a-dire pendantl’execution du programme
exemples : Lisp, PHP, Python
d’autres sont types statiquement, c’est-a-dire pendant la compilation duprogramme
exemples : C, Java, OCaml
c’est ce second cas que l’on considere dans ce cours
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 6
slogan
well typed programs do not go wrong
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 7
objectifs du typage
• le typage doit etre decidable
• le typage doit rejeter les programmes absurdes dont l’evaluationechouerait ; c’est la surete du typage
• le typage ne doit pas rejeter trop de programmes non-absurdes,i.e. le systeme de types doit etre expressif
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 8
plusieurs solutions
1. toutes les sous-expressions sont annotees par un type
int f(int x) { int y = ((x:int)+(1:int):int); ... }
facile a verifier mais trop fastidieux pour le programmeur
2. annoter seulement les declarations de variables (C, C++, Java, etc.)
int f(int x) { int y = x+1; return y; }
3. annoter seulement les parametres de fonctions (C++)
int f(int x) { auto y = x+1; return y; }
4. ne rien annoter ⇒ inference complete (OCaml, Haskell, etc.)
fun x -> x+1
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 9
proprietes attendues
un algorithme de typage doit avoir les proprietes de
• correction : si l’algorithme repond “oui” alors le programme esteffectivement bien type
• completude : si le programme est bien type, alors l’algorithme doitrepondre “oui”
et eventuellement de
• principalite : le type calcule pour une expression est le plus generalpossible
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 10
typage de while
reprenons le langage while du cours 2
pour le rendre un peu plus interessant, on y ajoute des enregistrements
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 11
syntaxe
e ::= expression| c constante entiere ou booleenne| x variable| e.f acces a un champ| e op e operateur binaire (+, <, . . .)
s ::= instruction| e.f ← e affectation| if e then s else s conditionnelle| while e do s boucle| s; s sequence| skip ne rien faire
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 12
exemple
x .a← 0;x .b ← 1;while x .b < 100 do
x .b ← x .a + x .b;x .a← x .b − x .a
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 13
semantique
la notion de valeur est legerement modifiee
v ::= valeur| n valeur entiere| b valeur booleenne| x variable (vue comme une adresse)
ainsi que la notion d’environnement E ,qui associe une valeur E (x , f ) a certains couples (x , f )
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 14
semantique
on definit une semantique a grands pas pour les expressions
E , e � v
et une semantique a petits pas pour les instructions
E , s → E ′, s ′
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 15
semantique des expressions
E , n � n E , b � b
E , x � x
E , e � x (x , f ) ∈ dom(E )
E , e.f � E (x , f )
E , e1 � n1 E , e2 � n2 n = n1 + n2
E , e1 + e2 � netc.
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 16
semantique des instructions
E , e1 � x E , e2 � v (x , f ) ∈ dom(E )
E , e1.f ← e2 → E{(x , f ) 7→ v}, skip
E , skip; s → E , s
E , s1 → E1, s′1
E , s1; s2 → E1, s ′1; s2
E , e � true
E , if e then s1 else s2 → E , s1
E , e � false
E , if e then s1 else s2 → E , s2
E , e � true
E , while e do s → E , s; while e do s
E , e � false
E , while e do s → E , skip
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 17
typage
on se donne des types, dont la syntaxe abstraite est
τ ::= type| int entier| bool booleen| {f : τ ; . . . ; f : τ} enregistrement
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 18
jugement de typage
le type d’une variable est donne par un environnement Γ(une fonction des variables vers les types)
le jugement de typage que l’on va definir se note
Γ ` e : τ
et se lit � dans l’environnement Γ, l’expression e a le type τ �
on utilise des regles d’inference pour definir Γ ` e : τ
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 19
typage des expressions
Γ ` n : int Γ ` b : bool
x ∈ dom(Γ)
Γ ` x : Γ(x)
Γ ` e : {. . . ; f : τ ; . . .}Γ ` e.f : τ
Γ ` e1 : int Γ ` e2 : int
Γ ` e1 + e2 : intetc.
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 20
exemple
en posant Γ = {x 7→ {a : int; b : int}}, on a
Γ ` x : {a : int; b : int}Γ ` x .a : int Γ ` 1 : int
Γ ` x .a + 1 : int
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 21
expressions non typables
en revanche, on ne peut pas typer des expressions comme
x .c
ou encore comme42.a
c’est precisement l’objectif, car ces expressions n’ont pas de valeur dansnotre semantique
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 22
typage des instructions
pour typer les instructions, on introduit un autre jugement
Γ ` s
qui se lit � dans l’environnement Γ, l’instruction s est bien typee �
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 23
typage des instructions
Γ ` skipΓ ` s1 Γ ` s2
Γ ` s1; s2
Γ ` e1 : {. . . ; f : τ : . . .} Γ ` e2 : τ
Γ ` e1.f ← e2
Γ ` e : bool Γ ` s1 Γ ` s2Γ ` if e then s1 else s2
Γ ` e : bool Γ ` s
Γ ` while e do s
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 24
surete du typage
well typed programs do not go wrong
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 25
surete du typage
montrons l’adequation du typage par rapport a la semantique a reductions
Theoreme (surete du typage)
Si Γ ` s, alors la reduction de s est infinie ou termine sur skip.
ou, de maniere equivalente,
Theoreme
Si Γ ` s et E , s →? E ′, s ′ et s ′ irreductible, alors s ′ est skip.
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 26
surete du typage
cela veut dire que l’evaluation ne se retrouvera pas bloquee sur uneexpression telle que
42.a
ou encore sur une instruction
if e then s1 else s2
ou e ne s’evalue ni en true ni en false
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 27
expressions
montrons en premier lieu qu’une expression bien typee s’evaluecorrectement, c’est-a-dire
si Γ ` e : τ , alors E , e � v
dit comme cela, c’est faux, car il manque un lien entre l’environnement detypage Γ et l’environnement d’execution E
contre-exemple :Γ = {x 7→ {a : int}}e = x .aE = ∅
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 28
coherence des environnements
Definition (environnement bien type)
Un environnement d’execution E est bien type dans un environnement detypage Γ, note Γ ` E , si
∀x , si Γ(x) = {. . . f : τ . . .} alors (x , f ) ∈ dom(E ) et Γ ` E (x , f ) : τ
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 29
expressions
Lemme (evaluation d’une expression bien typee)
Si Γ ` e : τ et Γ ` E , alors E , e � v et Γ ` v : τ .
preuve : par recurrence sur la derivation Γ ` e : τ .
e = c immediat avec v = c
e = x immediat avec v = x
e = e1.f par HR E , e1 � v1 et Γ ` v1 : τ1 avec τ1 = {. . . f : τ . . .}.donc v1 est une variable x et v = E (x , f )comme E est bien type, on a Γ ` v : τ
e = e1 + e2 par HR sur e1 et e2 on a E , ei � vi et Γ ` vi : int, donc v1et v2 sont des entiers et on conclut avec v = v1 + v2
�
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 30
evaluation des instructions
la preuve de la surete s’appuie sur deux lemmes
Lemme (progres)
Si Γ ` s et Γ ` E , alors soit s est skip, soit E , s → E ′, s ′.
Lemme (preservation)
Si Γ ` s, si Γ ` E et si E , s → E ′, s ′ alors Γ ` s ′ et Γ ` E ′.
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 31
progres
Lemme (progres)
Si Γ ` s et Γ ` E , alors soit s est skip, soit E , s → E ′, s ′.
preuve : par recurrence sur la derivation Γ ` s
s = skip immediat
s = s1; s2 si s1 = skip, on a E , s1; s2 → E , s2sinon, on applique l’HR a s1, d’ou E , s1 → E ′, s ′1 et doncE , s1; s2 → E ′, s ′1; s2
s = e1.f ← e2 comme e1 et e2 sont bien typees, elles s’evaluent en x et vrespectivementcomme Γ ` x : {. . . f : τ . . .} alors (x , f ) ∈ dom(E ) et doncE , s → E ′, skip avec E ′ = E{(x , f ) 7→ v}
autres cas laisses en exercice �
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 32
preservation
on montre ensuite
Lemme (preservation)
Si Γ ` s, si Γ ` E et si E , s → E ′, s ′ alors Γ ` s ′ et Γ ` E ′.
preuve : par recurrence sur la derivation Γ ` s
s = s1; s2 on a Γ ` s1 et Γ ` s2• si s1 = skip, alors E , s1; s2 → E , s2• sinon, E , s1 → E ′, s ′1 et par HR Γ ` s ′1 et Γ ` E ′
d’ou Γ ` s ′1; s2
s = e1.f ← e2 on a E , e1 � x , E , e2 � v , s ′ = skip (donc Γ ` s ′) etE ′ = E{(x , f ) 7→ v}or Γ ` e1 : {. . . f : τ . . .} et Γ ` e2 : τ donc Γ ` v : τ (cftransparent 30) et donc Γ ` E ′
autres cas laisses en exercice �
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 33
surete du typage
on peut maintenant prouver le theoreme facilement
Theoreme (surete du typage)
Si Γ ` s et E , s →? E ′, s ′ et s ′ irreductible, alors s ′ est skip.
preuve : on a E , s → E1, s1 → · · · → E ′, s ′ et par applications repetees dulemme de preservation, on a donc Γ ` s ′
par le lemme de progres, s ′ se reduit ou est skipc’est donc skip �
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 34
dans la vie reelle
des langages comme OCaml ou Java possedent une telle propriete desurete du typage
ce qui signifie que l’evaluation d’une expression de type τ
• soit ne termine pas
• soit leve une exception
• soit termine sur une valeur de type τ
en OCaml, l’absence de null fait de ce dernier cas une propriete tres forte
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 35
le typage en pratique
il y a une difference entre les regles de typage, qui definissent la relationternaire
Γ ` e : τ
et l’algorithme de typage qui verifie qu’une certaine expression e est bientypee dans un certain environnement Γ
par exemple
• τ pourrait ne pas etre donne (inference de types)
• plusieurs regles pourraient s’appliquer a une meme expression
• en particulier, une meme expression pourrait avoir plusieurs types
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 37
dans notre cas
ici c’est simple, car une seule regle s’applique a chaque fois
on dit que le typage est dirige par la syntaxe (syntax-directed)
le typage est donc realise par un parcours de complexite lineaire
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 38
en pratique
• on ne se contente pas d’un message
erreur de typage
mais on indique l’origine du probleme avec precision
• on conserve les types pour les phases ulterieures du compilateur
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 39
en pratique
pour cela, on decore les arbres de syntaxe abstraite
• en entree du typage avec une localisation dans le fichier source
• en sortie du typage avec les types obtenus
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 40
des arbres decores
en OCaml
type loc = ...
type expr =
| Evar of string
| Econst of int
| Efield of expr * string
...
en Java
class Loc { ... }
abstract class Expr {
}
class Evar extends Expr {...}
class Econst extends Expr {...}
class Efield extends Expr {...}
...
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 41
des arbres decores
en OCaml
type loc = ...
type expr = {
desc: desc;
loc : loc;
}
and desc =
| Evar of string
| Econst of int
| Efield of expr * string
...
en Java
class Loc { ... }
abstract class Expr {
Loc loc;
}
class Evar extends Expr {...}
class Econst extends Expr {...}
class Efield extends Expr {...}
...
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 42
signaler une erreur
on signale une erreur de typage en levant une exception
cette exception contient
• la nature de l’erreur (un message precis)
• une localisation
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 43
signaler une erreur
on rattrape cette exception dans le programme principal
on affiche la localisation et le message
test.c:8:14: error: too few arguments to function ’f’
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 44
en sortie
type typ = ...
type texpr = {
tdesc: tdesc;
typ : typ
}
and tdesc =
| Tvar of string
| Tconst of int
| Tfield of texpr * string
...
class Typ { ... }
abstract class Texpr {
Typ typ;
}
class Tvar extends Texpr {...}
class Tconst extends Texpr {...}
class Tfield extends Texpr {...}
...
c’est un autre type d’expressions
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 45
typage du typage
le typage transforme des arbres de syntaxe abstraite d’un certain type endes arbres de syntaxe abstraite d’un autre type
on reconstruit de nouveaux arbres
cela reste efficace, car
• c’est typiquement un parcours lineaire
• les anciens arbres seront recuperes par le GC
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 46
definition
on dit qu’un type τ1 est un sous-type d’un type τ2, ce que l’on note
τ1 ≤ τ2
si toute valeur de type τ1 peut etre vue comme une valeur de type τ2
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 48
exemple
dans beaucoup de langages, il existe un sous-typage entre typesnumeriques
en Java, ce sous-typage est le suivant :
ainsi on peut ecrire
int n = ’a’;
mais pas
byte b = 144;
double
float
long
int
char short
byte
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 49
heritage
dans un langage oriente objet, la notion d’heritage s’accompagne d’unenotion de sous-typage : si une classe B herite d’une classe A, on a
B ≤ A
i.e. toute valeur de type B peut etre vue comme une valeur de type A
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 50
exemple en Java
les deux classes
class Vehicle { ... void move() { ... } ... }
class Car extends Vehicle { ... void move() { ... } ... }
introduisent le sous-typage
Car ≤ Vehicle
et on peut donc ecrire
Vehicle v = new Car();
v.move();
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 51
type statique et type dynamique
la construction new C(...) construit un objet de classe C, et la classe decet objet ne peut etre modifiee par la suite ; on l’appelle le typedynamique de l’objet
en revanche, le type statique d’une expression, tel qu’il est calcule par lecompilateur, peut etre different du type dynamique, du fait de la relationde sous-typage introduite par l’heritage
quand on ecrit
Vehicle v = new Car();
v.move();
pour le compilateur, v a le type Vehicle,mais c’est bien la methode move de la classe Car qui est executee
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 52
type statique et type dynamique
dans beaucoup de circonstances, le compilateur ne peut pas connaıtre letype dynamique
exemple :
void moveAll(LinkedList<Vehicule> l) {
for (Vehicule v: l)
v.move();
}
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 53
transtypage
il est parfois necessaire de � forcer la main � au compilateur, enpretendant qu’une valeur appartient a un certain type
on appelle cela le transtypage (en anglais cast)
la notation de Java (heritee du langage C) est
(τ)e
le type statique d’une telle expression est τ
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 54
exemple
ainsi on peut ecrire en Java
int n = ...;
byte b = (byte)n;
ici, il n’y a pas de verification dynamique(si l’entier est trop grand, il est tronque)
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 55
cas d’un objet
considerons l’expression(C )e
soit
• D le type dynamique de (l’objet designe par) e
• E le type statique de l’expression e
il y a trois situations
• C est une super classe de E : on parle d’upcast et le code produitpour (C )e est le meme que pour e (mais le cast a une influence sur letypage puisque le type de (C )e est C )
• C est une sous-classe de E : on parle de downcast et le code contientun test dynamique pour verifier que D est bien une sous-classe de C
• C n’est ni une sous-classe ni une super classe de E : le compilateurrefuse l’expression
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 56
exemple (upcast)
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
B b = new B();
System.out.println(b.x); // 2
System.out.println(((A)b).x); // 1
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 57
exemple (downcast)
void m(Vehicle v, Vehicle w) {
((Car)v).await(w);
}
rien ne garantit que l’objet passe a m sera bien une voiture ; en particulier ilpourrait ne meme pas posseder de methode await !
le test dynamique est donc necessaire
l’exception ClassCastException est levee si le test echoue
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 58
tester l’appartenance a une classe
pour permettre une programmation un peu plus defensive, il existe uneconstruction booleenne
e instanceof C
qui determine si la classe de e est bien une sous-classe de C
on trouve souvent le schema
if (e instanceof C) {
C c = (C)e;
...
}
dans ce cas, le compilateur effectue typiquement une optimisationconsistant a ne pas generer de second test pour le cast
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 59
definition
la surcharge (en anglais overloading) est la capacite d’utiliser le memenom pour plusieurs operations
la surcharge est resolue au typage, grace au nombre et aux types(statiques) des arguments
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 61
exemple
en Java, l’operation + est surchargee
int n = 40 + 2;
String s = "foo" + "bar";
Strint t = "foo" + 42;
il faut le voir comme trois operations
int +(int , int )
String +(String, String)
String +(String, int )
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 62
attention
quand on ecrit
int n = ’a’ + 42;
c’est le sous-typage qui permet de voir ’a’ de type char comme unevaleur de type int, et il s’agit donc de l’operation +(int, int)
mais quand on ecrit
Strint t = "foo" + 42;
ce n’est pas du sous-typage int ≤ String
en particulier, on ne peut pas ecrire
String t = 42;
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 63
autre exemple
en Java, l’utilisateur ne peut pas surcharger les operateurs comme +
mais il peut surcharger les methodes/constructeurs
int f(int n, int m) { ... }
int f(int n) { ... }
int f(String s) { ... }
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 64
resolution
tout se passe comme si on avait defini plutot
int f_int_int(int n, int m) { ... }
int f_int (int n) { ... }
int f_String (String s) { ... }
et le compilateur utilise les types (statiques) des arguments d’un appel a f
pour determiner quelle methode appeler
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 65
resolution
resoudre la surcharge peut etre delicat
class A {...}
class B extends A {
void m(A a) {...}
void m(B b) {...}
}
dans le code
{ ... B b = new B(); b.m(b); ... }
les deux methodes s’appliquent potentiellement
c’est la methode m(B b) qui est appelee,car plus precise du point de vue du type de l’argument
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 66
ambiguıte
il peut y avoir ambiguıte
class A {...}
class B extends A {
void m(A a, B b) {...}
void m(B b, A a) {...}
}
{ ... B b = new B(); b.m(b, b); ... }
surcharge1.java:13: reference to m is ambiguous,
both method m(A,B) in B and method m(B,A) in B match
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 67
algorithme de resolution de Java
a chaque methode definie dans la classe C
τ m(τ1 x1, ..., τn xn)
on associe le profil (C, τ1, . . . , τn)
on ordonne les profils : (τ0, τ1, . . . , τn) v (τ ′0, τ′1, . . . , τ
′n) si et seulement si
τi est un sous-type de τ ′i pour tout i
pour un appele.m(e1, . . . , en)
ou e a le type statique τ0 et ei le type statique τi , on considere l’ensembledes elements minimaux dans l’ensemble des profils compatibles
• aucun element ⇒ aucune methode ne s’applique
• plusieurs elements ⇒ ambiguıte
• un unique element ⇒ c’est la methode a appeler
Jean-Christophe Filliatre INF564 – Compilation 2017–2018 / cours 4 68