• Aucun résultat trouvé

Langages de programmation et compilation

N/A
N/A
Protected

Academic year: 2022

Partager "Langages de programmation et compilation"

Copied!
12
0
0

Texte intégral

(1)

Ecole Normale Sup´erieure´

Langages de programmation et compilation

Jean-Christophe Filliˆatre typage

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 1

typage

si j’´ecris l’expression

"5" + 37 dois-je obtenir

• une erreur `a la compilation ? (OCaml, Rust, Go)

• une erreur `a l’ex´ecution ? (Python, Julia)

• l’entier 42 ? (Visual Basic, PHP)

• la chaˆıne"537"? (Java, Scala, Kotlin)

• un pointeur ? (C, C++)

• autre chose encore ?

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 4

typage

et si on additionne deux expressions arbitraires e1 + e2

comment d´eterminer si cela est l´egal et ce que l’on doit faire le cas

´ech´eant ?

la r´eponse est letypage, une analyse qui associe untype`a chaque valeur/expression, dans le but de rejeter les programmes incoh´erents

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 5

`a quel moment ?

certains langages sonttyp´es dynamiquement: les types sont associ´es auxvaleurset utilis´es pendant l’ex´ecutiondu programme

exemples : Lisp, PHP, Python, Julia

d’autres sonttyp´es statiquement: les types sont associ´es aux expressionset utilis´es pendant lacompilationdu programme

exemples : C, Java, OCaml, Rust, Go

c’est ce second cas que l’on consid`ere dans le cours d’aujourd’hui

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 6

remarque

un langage peut utiliser`a la foisdes notions de typage statique et de typage dynamique

on le verra avec l’exemple de Java dans un autre cours

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 7

slogan

well typed programs do not go wrong

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 8

objectifs du typage

• le typage doit ˆetred´ecidable

• le typage doit rejeter les programmes absurdes comme 1 2, dont l’´evaluation ´echouerait ; c’est lasˆuret´e du typage

• le typage ne doit pas rejeter trop de programmes non-absurdes, i.e.le syst`eme de types doit ˆetreexpressif

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 9

plusieurs solutions

1.toutes les sous-expressions sont annot´ees par un type

fun(x:int)→let(y:int) = (+ :)(((x:int),(1 :int)) :int×int)in facile de v´erifier mais trop fastidieux pour le programmeur

2.annoter seulement les d´eclarations de variables (Pascal, C, Java, etc.) fun(x:int)→let(y:int) = +(x,1)iny

3.annoter seulement les param`etres de fonctions fun(x:int)→lety= +(x,1)iny

4.ne rien annoter⇒inf´erencecompl`ete (OCaml, Haskell, etc.)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 10

(2)

propri´et´es attendues

un algorithme de typage doit avoir les propri´et´es de

• correction: si l’algorithme r´epond “oui” alors le programme est effectivement bien typ´e

• compl´etude: si le programme est bien typ´e, alors l’algorithme doit r´epondre “oui”

et ´eventuellement de

• principalit´e: le type calcul´e pour une expression est le plus g´en´eral possible

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 11

typage de mini-ML

consid´erons le typage de mini-ML 1.typage monomorphe

2.typage polymorphe, inf´erence de types

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 12

mini-ML

rappel

e ::= x identificateur

| c constante (1, 2, . . .,true, . . .)

| op primitive (+,×,fst, . . .)

| funx→e fonction

| e e application

| (e,e) paire

| letx=eine liaison locale

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 13

typage monomorphe de mini-ML

on se donne destypes simples, dont la syntaxe abstraite est τ ::= int|bool| . . . types de base

| τ→τ type d’une fonction

| τ×τ type d’une paire

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 14

jugement de typage

lejugementde typage que l’on va d´efinir se note Γ`e:τ

et se litdans l’environnement Γ, l’expressione a le typeτ

l’environnement Γ associe un type Γ(x) `a toute variablexlibre danse

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 15

r`egles de typage

Γ`x: Γ(x) Γ`n:int...

Γ`+ :int×int→int...

Γ +x:τ1`e:τ2

Γ`funx→e:τ1→τ2

Γ`e10→τ Γ`e20 Γ`e1e2:τ Γ`e11 Γ`e22

Γ`(e1,e2) :τ1×τ2

Γ`e11 Γ +x:τ1`e22

Γ`letx=e1ine22

Γ +x:τ est l’environnement Γ0d´efini par Γ0(x) =τ et Γ0(y) = Γ(y) sinon

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 16

exemple

... ...

x:int`(x,1) :int×int x:int`+(x,1) :int

∅ `funx→+(x,1) :int→int

...`f:int→int ...`2 :int f:int→int`f 2 :int

∅ `letf =funx→+(x,1)inf 2 :int

expressions non typables

en revanche, on ne peut pas typer le programme 1 2 Γ`1 :τ0→τ Γ`2 :τ0

Γ`1 2 :τ ni le programmefunx→x x

Γ +x:τ1`x:τ3→τ2 Γ +x:τ1`x:τ3 Γ +x:τ1`x x:τ2

Γ`funx→x x:τ1→τ2

carτ11→τ2n’a pas de solution (les types sont finis)

(3)

plusieurs types possibles

on peut montrer

∅ `funx→x:int→int mais aussi

∅ `funx→x:bool→bool

attention: ce n’est pas du polymorphisme

pour une occurrence donn´ee defunx→xil fautchoisirun type

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 19

plusieurs types possibles

ainsi, le termeletf =funx→xin(f 1,f true) n’est pas typable car il n’y a pas de typeτ tel que

f:τ→τ`(f 1,f true) :τ1×τ2

en revanche,

((funx→x) (funx→x)) 42 est typable (exercice : le montrer)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 20

primitives

en particulier, on ne peut pas donnerun typesatisfaisant `a une primitive commefst; il faudrait choisir entre

int×int→int int×bool→int bool×int→bool

(int→int)×int→int→int etc.

mais on peut en revanche donnerune r`eglede typage pour l’application defst:

Γ`e:τ1×τ2

Γ`fste:τ1

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 21

primitives

de mˆeme, on ne peut pas donner de type `aopfixde mani`ere g´en´erale, mais on peut donner une r`egle de typage pour son application

Γ`e:τ→τ Γ`opfixe:τ

et si on souhaite se limiter `a desfonctionsr´ecursives, on peut modifier ainsi

Γ`e: (τ1→τ2)→(τ1→τ2) Γ`opfixe:τ1→τ2

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 22

fonction r´ecursive

si on ajoutait plutˆot une constructionlet recdans le langage, cela donnerait

Γ +x:τ1`e11 Γ +x:τ1`e22

Γ`let recx=e1ine22 ou encore, pour des fonctions uniquement,

Γ + (f :τ→τ1) + (x:τ)`e11 Γ + (f :τ→τ1)`e22

Γ`let recf x=e1ine22

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 23

diff´erence entre r`egles de typage et algorithme de typage

quand on typefunx→e, comment trouve-t-on le type `a donner `ax? c’est toute la diff´erence entre lesr`egles de typage, qui d´efinissent la relation ternaire

Γ`e:τ

et l’algorithme de typagequi v´erifie qu’une certaine expressioneest bien typ´ee dans un certain environnement Γ

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 24

typage simple de mini-ML

consid´erons l’approche o`u seuls les param`etres de fonctions sont annot´es et programmons-la en OCaml

on se donne une syntaxe abstraite des types type typ =

| Tint

| Tarrow of typ * typ

| Tproduct of typ * typ

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 25

typage simple de mini-ML

le constructeurFunprend un argument suppl´ementaire type expression =

| Var of string

| Const of int

| Op of string

| Fun of string * typ * expression (* seul changement *)

| App of expression * expression

| Pair of expression * expression

| Let of string * expression * expression

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 26

(4)

typage simple de mini-ML

l’environnement Γ est r´ealis´e par une structure persistante en l’occurrence on utilise le moduleMapd’OCaml

module Smap = Map.Make(String) type env = typ Smap.t

(performances : arbres ´equilibr´es⇒insertion et recherche enO(logn))

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 27

typage simple de mini-ML

let rec type_expr env = function

| Const _ -> Tint

| Var x -> Smap.find x env

| Op "+" -> Tarrow (Tproduct (Tint, Tint), Tint)

| Pair (e1, e2) ->

Tproduct (type_expr env e1, type_expr env e2) pour la fonction, le type de la variable est donn´e

| Fun (x, ty, e) ->

Tarrow (ty, type_expr (Smap.add x ty env) e) pour la variable locale, il est calcul´e

| Let (x, e1, e2) ->

type_expr (Smap.add x (type_expr env e1) env) e2

(noter l’int´erˆet de la persistance deenv)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 28

typage simple de mini-ML

les seules v´erifications se trouvent dans l’application

| App (e1, e2) -> begin match type_expr env e1 with

| Tarrow (ty2, ty) ->

if type_expr env e2 = ty2 then ty

else failwith "erreur : argument de mauvais type"

| _ ->

failwith "erreur : fonction attendue"

end

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 29

typage simple de mini-ML

exemples

# type_expr (Let ("f",

Fun ("x", Tint, App (Op "+", Pair (Var "x", Const 1))), App (Var "f", Const 2)));;

- : typ = Tint

# type_expr (Fun ("x", Tint, App (Var "x", Var "x")));;

Exception: Failure "erreur : fonction attendue".

# type_expr (App (App (Op "+", Const 1), Const 2));;

Exception: Failure "erreur : argument de mauvais type".

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 30

en pratique

• on ne fait pas

failwith "erreur de typage"

mais on indique l’origine du probl`eme avec pr´ecision

• on conserve les types pour les phases ult´erieures du compilateur

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 31

des arbres d´ecor´es

d’une part on d´ecore les arbresen entr´eedu typage avec une localisation dans le fichier source

type loc = ...

type expression =

| Var of string

| Const of int

| Op of string

| Fun of string * typ * expression

| App of expression * expression

| Pair of expression * expression

| Let of string * expression * expression

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 32

des arbres d´ecor´es

d’une part on d´ecore les arbresen entr´eedu typage avec une localisation dans le fichier source

type loc = ...

type expression = { desc: desc;

loc : loc;

}

and desc =

| Var of string

| Const of int

| Op of string

| Fun of string * typ * expression

| App of expression * expression

| Pair of expression * expression

| Let of string * expression * expression

signaler une erreur

on d´eclare une exception de la forme exception Error of loc * string on la l`eve ainsi

let rec type_expr env e = match e.desc with

| ...

| App (e1, e2) -> begin match type_expr env e1 with

| Tarrow (ty2, ty) ->

if type_expr env e2 <> ty2 then

raise (Error (e2.loc, "argument de mauvais type"));

...

(5)

signaler une erreur

et on la rattrape ainsi, par exemple dans le programme principal try

let p = Parser.parse file in let t = Typing.program p in ...

with Error (loc, msg) ->

Format.eprintf "File ’%s’, line ...\n" file loc;

Format.eprintf "error: %s@." msg;

exit 1

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 35

des arbres d´ecor´es

d’autre part, on d´ecore les arbresen sortiedu typage avec des types type texpression = {

tdesc: tdesc;

typ : typ;

}

and tdesc =

| Tvar of string

| Tconst of int

| Top of string

| Tfun of string * typ * texpression

| Tapp of texpression * texpression

| Tpair of texpression * texpression

| Tlet of string * texpression * texpression c’est unautre typed’expressions

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 36

typage du typage

la fonction de typage a donc un type de la forme val type_expr: expression -> texpression

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 37

des arbres typ´es

la fonction de typagereconstruitdes arbres, cette fois typ´es let rec type_expr env e =

let d, ty = compute_type env e in { tdesc = d; typ = ty }

and compute_type env e = match e.desc with

| Const n ->

Tconst n, Tint

| Var x ->

Tvar x, Smap.find x env

| Pair (e1, e2) ->

let te1 = type_expr env e1 in let te2 = type_expr env e2 in

Tpair (te1, te2), Tproduct (te1.typ, te2.typ)

| ...

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 38

sˆuret´e du typage

well typed programs do not go wrong

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 39

sˆuret´e du typage

on montre l’ad´equation du typage par rapport `a la s´emantique `a r´eductions Th´eor`eme (sˆuret´e du typage)

Si∅ `e:τ, alors la r´eduction de e est infinie ou se termine sur une valeur.

ou, de mani`ere ´equivalente, Th´eor`eme

Si∅ `e:τet e→? e0et e0irr´eductible, alors e0est une valeur.

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 40

sˆuret´e du typage

la preuve de ce th´eor`eme s’appuie sur deux lemmes Lemme (progression)

Si∅ `e:τ, alors soit e est une valeur, soit il existe e0tel que e→e0.

Lemme (pr´eservation)

Si∅ `e:τ et e→e0alors∅ `e0:τ.

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 41

progression

Lemme (progression)

Si∅ `e:τ, alors soit e est une valeur, soit il existe e0tel que e→e0. Preuve : par r´ecurrence sur la d´erivation∅ `e:τ

supposons par exemplee=e1e2; on a donc

∅ `e10→τ ∅ `e20

∅ `e1e2:τ on applique l’HR `ae1

• sie1→e10, alorse1e2→e10e2(cf lemme passage au contexte)

• sie1est une valeur, supposonse1=funx→e3(il y a aussi + etc.) on applique l’HR `ae2

• sie2→e02, alorse1e2→e1e20(mˆeme lemme)

• sie2est une valeur, alorse1e2→e3[x←e2]

(exercice : traiter les autres cas)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 42

(6)

pr´eservation

on commence par de petits lemmes faciles Lemme (permutation)

SiΓ +x:τ1+y:τ2`e:τ et x6=y alorsΓ +y:τ2+x:τ1`e:τ (et la d´erivation a la mˆeme hauteur).

preuve : r´ecurrence imm´ediate

Lemme (affaiblissement)

SiΓ`e:τ et x6∈dom(Γ), alorsΓ +x:τ0`e:τ (et la d´erivation a la mˆeme hauteur).

preuve : r´ecurrence imm´ediate

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 43

pr´eservation

on continue par unlemme cl´e

Lemme (pr´eservation par substitution)

SiΓ +x:τ0`e:τ etΓ`e00alorsΓ`e[x←e0] :τ. preuve : par r´ecurrence sur la d´erivation Γ +x:τ0`e:τ

• cas d’une variablee=y

• six=yalorse[x←e0] =e0etτ=τ0

• six6=yalorse[x←e0] =eetτ= Γ(y)

• cas d’une abstractione=funy→e1

on peut supposery6=x,y6∈dom(Γ) etynon libre danse0(α-conversion) on a Γ +x:τ0+y:τ2`e11et donc Γ +y:τ2+x:τ0`e11 (permutation) ; d’autre part Γ`e00et donc Γ +y:τ2`e00 (affaiblissement)

par HR on a donc Γ +y:τ2`e1[x←e0] :τ1et donc Γ`(funy→e1)[x←e0] :τ2→τ1,i.e.Γ`e[x←e0] :τ

(exercice : traiter les autres cas)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 44

pr´eservation

on peut enfin montrer Lemme (pr´eservation)

Si∅ `e:τ et e→e0alors∅ `e0:τ.

preuve : par r´ecurrence sur la d´erivation∅ `e:τ

• case=letx=e1ine2

∅ `e11 x:τ1`e22

∅ `letx=e1ine22

• sie1→e10, par HR on a∅ `e101et donc∅ `letx=e01ine22

• sie1est une valeur ete0=e2[x←e1] alors on applique le lemme de pr´eservation par substitution

• case=e1e2

• sie1→e10ou sie1valeur ete2→e02alors on utilise l’HR

• sie1=funx→e3ete2valeur alorse0=e3[x←e2]

et on applique l`a encore le lemme de substitution

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 45

sˆuret´e du typage

on peut maintenant prouver le th´eor`eme facilement Th´eor`eme (sˆuret´e du typage)

Si∅ `e:τet e→? e0et e0irr´eductible, alors e0est une valeur.

preuve : on ae→e1→ · · · →e0et par applications r´ep´et´ees du lemme de pr´eservation, on a donc∅ `e0

par le lemme de progression,e0se r´eduit ou est une valeur

c’est donc une valeur

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 46

polymorphisme

il est contraignant de donner un type unique `afunx→xdans letf =funx→xin . . .

de mˆeme, on aimerait pouvoir donnerplusieurs typesaux primitives telles quefstousnd

une solution : lepolymorphisme param´etrique

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 47

polymorphisme param´etrique

on ´etend l’alg`ebre des types :

τ ::= int|bool| . . . types de base

| τ→τ type d’une fonction

| τ×τ type d’une paire

| α variable de type

| ∀α.τ type polymorphe

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 48

variables de types libres

on noteL(τ) l’ensemble des variables de typeslibresdansτ, d´efini par L(int) = ∅

L(α) = {α}

L(τ1→τ2) = L(τ1)∪ L(τ2) L(τ1×τ2) = L(τ1)∪ L(τ2)

L(∀α.τ) = L(τ)\ {α}

pour un environnement Γ, on d´efinit aussi L(Γ) = [

xdom(Γ)

L(Γ(x))

substitution de type

on noteτ[α←τ0] la substitution deαparτ0dansτ, d´efinie par int[α←τ0] = int

α[α←τ0] = τ0

β[α←τ0] = β siβ6=α

1→τ2)[α←τ0] = τ1[α←τ0]→τ2[α←τ0] (τ1×τ2)[α←τ0] = τ1[α←τ0]×τ2[α←τ0]

(∀α.τ)[α←τ0] = ∀α.τ

(∀β.τ)[α←τ0] = ∀β.τ[α←τ0] siβ6=α

(7)

syst`eme F

les r`egles sontexactementles mˆemes qu’auparavant, plus Γ`e:τ α6∈ L(Γ)

Γ`e:∀α.τ

et Γ`e:∀α.τ

Γ`e:τ[α←τ0]

le syst`eme obtenu s’appelle lesyst`eme F(J.-Y. Girard / J. C. Reynolds)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 51

exemple

x:α`x:α

`funx→x:α→α

`funx→x:∀α.α→α

...`f :∀α.α→α ...`f :int→int

... ...`f 1 :int

... ...`f true:bool f :∀α.α→α`(f 1,f true) :int×bool

`letf=funx→xin(f 1,f true) :int×bool

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 52

primitives

on peut maintenant donner un type satisfaisant aux primitives fst: ∀α.∀β.α×β→α

snd: ∀α.∀β.α×β→β opif : ∀α.bool×α×α→α opfix: ∀α.(α→α)→α

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 53

exercice

on peut construire une d´erivation de

Γ`funx→x x: (∀α.α→α)→(∀α.α→α) (exercice : le faire)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 54

remarque

la conditionα6∈ L(Γ) dans la r`egle

Γ`e:τ α6∈ L(Γ) Γ`e:∀α.τ est cruciale

sans elle, on aurait

Γ +x:α`x:α Γ +x:α`x:∀α.α Γ`funx→x:α→ ∀α.α Γ`funx→x:∀α.α→ ∀α.α et on accepterait donc le programme

(funx→x) 1 2

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 55

une mauvaise nouvelle

pour des termes sans annotations, les deux probl`emes

• inf´erence: ´etant donn´eee, existe-t-ilτ tel que`e:τ?

• v´erification: ´etant donn´ese etτ, a-t-on`e:τ? ne sont pas d´ecidables

J. B. Wells.Typability and type checking in the second-order lambda-calculus are equivalent and undecidable, 1994.

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 56

le syst`eme de Hindley-Milner

pour obtenir une inf´erence de types d´ecidable, on va restreindre la puissance du syst`eme F

⇒le syst`eme deHindley-Milner, utilis´e dans OCaml, SML, Haskell, ...

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 57

le syst`eme de Hindley-Milner

on limite la quantification∀en tˆete des types (quantification pr´enexe)

τ ::= int|bool| . . . types de base

| τ→τ type d’une fonction

| τ×τ type d’une paire

| α variable de type

σ ::= τ sch´emas

| ∀α.σ

l’environnement Γ associe un sch´ema de type `a chaque identificateur et la relation de typage a maintenant la forme Γ`e:σ

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 58

(8)

exemples

dans Hindley-Milner, les types suivants sont toujours accept´es

∀α.α→α

∀α.∀β.α×β→α

∀α.bool×α×α→α

∀α.(α→α)→α

mais plus les types tels que

(∀α.α→α)→(∀α.α→α)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 59

notation en OCaml

note : dans la syntaxe d’OCaml, la quantification pr´enexe est implicite

# fst;;

- : ’a * ’b -> ’a = <fun>

∀α.∀β.α×β→α

# List.fold_left;;

- : (’a -> ’b -> ’a) -> ’a -> ’b list -> ’a = <fun>

∀α.∀β.(α→β→α)→α→βlist→α

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 60

le syst`eme de Hindley-Milner

Γ`x: Γ(x) Γ`n:int...

Γ`+ :int×int→int...

Γ +x:τ1`e:τ2

Γ`funx→e:τ1→τ2

Γ`e10→τ Γ`e20 Γ`e1e2:τ Γ`e11 Γ`e22

Γ`(e1,e2) :τ1×τ2

Γ`e11 Γ +x:σ1`e22 Γ`letx=e1ine22

Γ`e:σ α6∈ L(Γ) Γ`e:∀α.σ

Γ`e:∀α.σ Γ`e:σ[α←τ]

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 61

le syst`eme de Hindley-Milner

on note que seule la constructionletpermet d’introduire un type polymorphe dans l’environnement

Γ`e11 Γ +x:σ1`e22

Γ`letx=e1ine22 en particulier, on peut toujours typer

letf =funx→xin(f 1,f true) avecf :∀α.α→αdans le contexte pour typer (f 1,f true)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 62

le syst`eme de Hindley-Milner

en revanche, la r`egle de typage

Γ +x:τ1`e:τ2

Γ`funx→e:τ1→τ2

n’introduit pas un type polymorphe (sinonτ1→τ2serait mal form´e)

en particulier, on ne peut plus typer funx→x x

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 63

consid´erations algorithmiques

pour programmer une v´erification ou une inf´erence de type, on proc`ede par r´ecurrence sur la structure du programme

or, pour une expression donn´ee, trois r`egles peuvent s’appliquer : la r`egle du syst`eme monomorphe, la r`egle

Γ`e:σ α6∈ L(Γ) Γ`e:∀α.σ ou encore la r`egle

Γ`e:∀α.σ Γ`e:σ[α←τ]

comment choisir ? va-t-on devoir proc´eder par essais/erreurs ?

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 64

syst`eme de Hindley-Milner dirig´e par la syntaxe

nous allons modifier la pr´esentation du syst`eme de Hindley-Milner pour qu’il soitdirig´e par la syntaxe(syntax-directed),i.e., pour toute expression, au plus une r`egle s’applique

les r`egles ont la mˆeme puissance d’expression : tout terme clos est typable dans un syst`eme si et seulement si il est typable dans l’autre

syst`eme de Hindley-Milner dirig´e par la syntaxe

τ ≤Γ(x)

Γ`x:τ Γ`n:int... τ≤type(op) Γ`op:τ Γ +x:τ1`e:τ2

Γ`funx→e:τ1→τ2

Γ`e10→τ Γ`e20 Γ`e1e2:τ Γ`e11 Γ`e22

Γ`(e1,e2) :τ1×τ2

Γ`e11 Γ +x:Gen(τ1,Γ)`e22

Γ`letx=e1ine22

(9)

syst`eme de Hindley-Milner dirig´e par la syntaxe

deux op´erations apparaissent

• l’instanciation, dans la r`egle

τ≤Γ(x) Γ`x:τ

la relationτ ≤σse litτ est une instance deσet est d´efinie par

τ≤ ∀α1...αn0 ssi ∃τ1...∃τn. τ=τ01←τ1, ..., αn←τn]

exemple :int×bool→int≤ ∀α.∀β.α×β→α

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 67

syst`eme de Hindley-Milner dirig´e par la syntaxe

• et lag´en´eralisation, dans la r`egle

Γ`e11 Γ +x:Gen(τ1,Γ)`e22

Γ`letx=e1ine22 o`u

Gen(τ1,Γ) def= ∀α1...∀αn1 o`u {α1, ..., αn}=L(τ1)\L(Γ)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 68

exemple

α≤α x:α`x:α

∅ `funx→x:α→α

intint≤∀α.αα Γ`f:intint ...

Γ`f 1 :int

boolbool≤∀α.αα Γ`f:boolbool ... Γ`f true:bool Γ`(f 1,f true) :int×bool

∅ `letf =funx→xin(f 1,f true) :int×bool

avec Γ = ∅+f :Gen(α→α,∅)

= f :∀α.α→α

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 69

inf´erence de types pour mini-ML

pour inf´erer le type d’une expression, il reste des probl`emes

• dansfunx→e, quel type donner `ax?

• pour une variablex, quelle instance de Γ(x) choisir ?

il existe une solution :l’algorithme W(Milner, Damas, Tofte)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 70

l’algorithme W

deux id´ees

• on utilise denouvelles variables de typespour repr´esenter les types inconnus

• pour le type dexdansfunx→e

• pour instancier les variables du sch´ema Γ(x)

• on d´etermine la valeur de ces variables plus tard, parunification entre typesau moment du typage de l’application

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 71

unification

soient deux typesτ1etτ2contenant des variables de typesα1, . . . , αn existe-t-il une instanciationf des variablesαi telle quef(τ1) =f(τ2) ? on appelle cela l’unification

exemple 1 :

τ1=α×β→int τ2=int×bool→γ

solution : α=int ∧ β=bool ∧ γ=int

exemple 2 :

τ1=α×int→α×int τ2=γ→γ

solution : γ=α×int

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 72

unification

exemple 3 :

τ1=α→int τ2=β×γ pas de solution

exemple 4 :

τ1=α→int τ2=α pas de solution

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 73

pseudo-code de l’unification

unifier(τ1, τ2) d´etermine s’il existe une instance des variables de types de τ1etτ2telle queτ12

unifier(τ, τ) = succ`es

unifier(τ1→τ10, τ2→τ20) =unifier(τ1, τ2) ; unifier(τ10, τ20) unifier(τ1×τ10, τ2×τ20) =unifier(τ1, τ2) ; unifier(τ10, τ20)

unifier(α, τ) = siα6∈ L(τ), remplacerαparτ partout sinon, ´echec

unifier(τ, α) =unifier(α, τ)

unifier(τ1, τ2) = ´echec dans tous les autres cas (pas de panique : on le fera en TD)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 74

(10)

l’id´ee de l’algorithme W sur un exemple

consid´erons l’expression funx→+(fst x,1) – `axon donne le typeα1, nouvelle variable de type – la primitive + a le typeint×int→int – typons l’expression (fst x,1)

–fsta pour type le sch´ema∀α.∀β.α×β→α

– on lui donne donc le typeα2×β1→α2pour deux nouvelles variables – l’applicationfst ximpose d’unifierα1etα2×β1,⇒α12×β1

– (fst x,1) a donc le typeα2×int

– l’application +(fst x,1) unifieint×intetα2×int,

⇒α2=int

au final, on obtient le typeint×β1→int,

et si on g´en´eralise (dans unlet) on obtient donc ∀β.int×β→int

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 75

pseudo-code de l’algorithme W

on d´efinit une fonctionW qui prend en arguments un environnement Γ et une expressioneet renvoie le type inf´er´e poure

• sieest une variablex,

renvoyer une instance triviale de Γ(x)

• sieest une constantec,

renvoyer une instance triviale de son type (penser `a [] :αlist)

• sieest une primitiveop,

renvoyer une instance triviale de son type

• sieest une paire (e1,e2), calculerτ1=W(Γ,e1) calculerτ2=W(Γ,e2) renvoyerτ1×τ2

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 76

l’algorithme W

• sieest une fonctionfunx→e1, soitαune nouvelle variable calculerτ=W(Γ +x:α,e1) renvoyerα→τ

• sieest une applicatione1e2, calculerτ1=W(Γ,e1) calculerτ2=W(Γ,e2) soitαune nouvelle variable unifier(τ12→α) renvoyerα

• sieestletx=e1ine2, calculerτ1=W(Γ,e1)

renvoyerW(Γ +x:Gen(τ1,Γ),e2)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 77

r´esultats

Th´eor`eme (Damas, Milner, 1982)

L’algorithme W est correct, complet et d´etermine le type principal :

• si W(∅,e) =τ alors∅ `e:τ

• si∅ `e:τ alorsτ ≤ ∀α.W(¯ ∅,e)

Th´eor`eme (sˆuret´e du typage) Le syst`eme de Hindley-Milner est sˆur.

(Si∅ `e:τ, alors la r´eduction de e est infinie ou se termine sur une valeur.)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 78

consid´erations algorithmiques

il existe plusieurs fa¸cons de r´ealiser l’unification

• en manipulant explicitement unesubstitution type tvar = int

type subst = typ TVmap.t

• en utilisant des variables de typesdestructives

type tvar = { id: int; mutable def: typ option; } il existe ´egalement plusieurs fa¸cons de coder l’algorithme W

• avec dessch´emas expliciteset en calculantGen(τ,Γ) type schema = { tvars: TVset.t; typ: typ; }

• avec desniveaux

Γ`n+1e11 Γ +x: (τ1,n)`ne22

Γ`nletx=e1ine22

cf. TD

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 79

extensions

on peut ´etendre mini-ML de nombreuses fa¸cons

• r´ecursion

• types construits (n-uplets, listes, types sommes et produits)

• r´ef´erences

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 80

r´ecursion

comme d´ej`a expliqu´e, on peut d´efinir let recf x=e1ine2=def

letf =opfix(funf →funx→e1)ine2

o`u

opfix:∀α.∀β.((α→β)→(α→β))→(α→β) de mani`ere ´equivalente, on peut donner la r`egle

Γ +f:τ→τ1+x:τ`e11 Γ +f :Gen(τ →τ1,Γ)`e22

Γ`let recf x=e1ine22

types construits

on a d´ej`a vu les paires

les listes ne posent pas de difficult´e []: ∀α. αlist

::: ∀α. α×αlist→αlist

Γ`e1:τ list Γ`e21 Γ +x:τ+y:τ list`e31

Γ`matche1with []→e2|::(x,y)→e31

se g´en´eralise ais´ement aux types sommes et produits

(11)

r´ef´erences

pour les r´ef´erences, on peut na¨ıvement penser qu’il suffit d’ajouter les primitives

ref: ∀α. α→αref : ∀α. αref→α := : ∀α. αref→α→unit

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 83

r´ef´erences

malheureusement, c’est incorrect !

letr=ref(funx→x)in r:∀α.(α→α)ref let =r:=(funx→x+ 1)in

!r true boum!

c’est le probl`eme dit desr´ef´erences polymorphes

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 84

r´ef´erences polymorphes

pour contourner ce probl`eme, il existe une solution extrˆemement simple,

`a savoir une restriction syntaxique de la constructionlet D´efinition (value restriction, Wright 1995)

Un programme satisfait le crit`ere de lavalue restrictionsi toute sous-expressionletest de la forme

letx=v1ine2

o`u v1est unevaleur.

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 85

r´ef´erences polymorphes

on ne peut plus ´ecrire

letr=ref(funx→x)in . . . mais on peut ´ecrire en revanche

(funr→. . .) (ref(funx→x)) o`u le type dern’est pas g´en´eralis´e

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 86

r´ef´erences polymorphes

en pratique, on continue d’´ecrireletr=ref . . . in . . . mais le type der n’est pas g´en´eralis´e

en OCaml, une variable non g´en´eralis´ee est de la forme’ a

# let x = ref (fun x -> x);;

val x : (’_a -> ’_a) ref

lavalue restrictionest ´egalement l´eg`erement relˆach´ee pour autoriser des expressions sˆures, telles que des applications de constructeurs

# let l = [fun x -> x];;

val l : (’a -> ’a) list = [<fun>]

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 87

r´ef´erences polymorphes

il reste quelques petits d´esagr´ements

# let id x = x;;

val id : ’a -> ’a = <fun>

# let f = id id;;

val f : ’_a -> ’_a = <fun>

# f 1;;

- : int = 1

# f true;;

This expression has type bool but is here used with type int

# f;;

- : int -> int = <fun>

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 88

r´ef´erences polymorphes

la solution : expanser pour faire apparaˆıtre une fonction,i.e., une valeur

# let f x = id id x;;

val f : ’a -> ’a = <fun>

(on parle d’η-expansion)

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 89

r´ef´erences polymorphes

en pr´esence du syst`eme de modules, la r´ealit´e est plus complexe encore

´etant donn´e un moduleM module M : sig

type ’a t

val create : int -> ’a t end

ai-je le droit de g´en´eraliser le type deM.create 17?

la r´eponse d´epend du type’a t: non pour un tableau, oui pour une liste, etc.

en OCaml, une indication devariancepermet de distinguer les deux type +’a t (* on peut g´en´eraliser *)

type ’a u (* on ne peut pas *) lireRelaxing the value restriction, J. Garrigue, 2004

Jean-Christophe Filliˆatre Langages de programmation et compilation typage 90

(12)

Références

Documents relatifs

Jean-Christophe Filliˆ atre Langages de programmation et compilation mise ` a niveau OCaml 17. ´enum´erer toutes les rang´ees

dans ce cours, nous allons effectivement nous int´eresser `a la compilation vers de l’assembleur, mais ce n’est qu’un aspect de la compilation un certain nombre de techniques mises

Jean-Christophe Filliˆ atre Langages de programmation et compilation s´emantique op´erationnelle 36. propri´et´es de la s´emantique naturelle

Jean-Christophe Filliˆ atre Langages de programmation et compilation analyse lexicale 1?.

Jean-Christophe Filliˆ atre Langages de programmation et compilation analyse syntaxique (2/2) 25.

Jean-Christophe Filliˆ atre Langages de programmation et compilation mode de passage des param`etres

par extension, on peut dire qu’une fonction est r´ ecursive terminale (tail recursive function) s’il s’agit d’une fonction r´ecursive dont tous les appels r´ecursifs sont

pour cela, on construit pour chaque classe un descripteur de classe qui contient les adresses des codes des m´ethodes dynamiques de cette classe comme pour les champs,