Vous êtes sur la page 1sur 30

Sommaire

Langages de programmation
Extension du λ-calcul à l’orienté objet

λoo
Sommaire

Sommaire

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
Sommaire

Sommaire

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
Sommaire

Sommaire

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
Sommaire

Sommaire

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Plan

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Rappel

Syntaxe :
e ::= c | x | λx.e | e e | let x = e in e end

Sémantique statique :
Types et schémas de types :
τ ::= int | bool | . . . | τ −→ τ | α
σ ::= ∀α1 , . . . , αn .τ

Environnement de typage :
E ::= [] | E † [ x : σ ]
E(x)
Séquents : E ` e : τ

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Règles de typage

τ ≺ TypeOf(c)
(cte)
E `c:τ

τ ≺ E(x)
(var)
E `x :τ

E † [x : τ ] ` e : τ 0
(abs)
E ` λx.e : τ −→ τ 0

E ` e : τ −→ τ 0 E ` e0 : τ
0 0
(app)
E `ee :τ

E `e:τ E † [x : Gen(E, τ )] ` e0 : τ 0
(let)
E ` let x = e in e0 end : τ 0

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Plan

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Syntaxe étendue

Syntaxe :
e ::= ...
| self | u | {h u = e; . . . ; u = e i} | e#m
| h val u = e; . . . ; val u = e; meth m = e; . . . ; meth m = e i

Exemples :
h val x = 0; meth get = x i
let p = h val x = 0; meth get = x i in p#get end
h val x = 0; meth get = x; meth inc = λv .self#get + v i
h val x = 0; meth deplace = λd.{h x = x + d i} i
h val x = 0; meth get = x; meth inc = λo.o#m1 + 1 i
h val x = 0; meth m = h meth m’ = x i i

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Sémantique statique

Types :
τ ::= ...
| h τ 0 i | rec α.τ
τ0 ::= (m : τ ; τ 0 ) | ρ | ∅

Exemples :
h val x = 0; meth get = x i : h get : int i
let p = h val x = 0; meth get = x i in p#get end : int
h val x = 0; meth get = x; meth inc = λv .self#get + v i :
h get : int; inc : int → int i
h val x = 0; meth deplace = λd.{h x = x + d i} i :
rec α.h deplace : int → α i
h val x = 0; meth get = x; meth inc = λo.o#m1 + 1 i :
h get : int; inc : h m1 : int; ρ i → int i

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Sémantique statique (suite)

Environnement de typage :
E ::= . . . | E † [ val uj : τj ] | E † [ self : τ ]
E ? = E \ {self, val}
On élimine de E toutes les associations val uj : τj ainsi que
l’association self : τ .
Exemple : [ x : int, val y : int, f : int → bool, self : h get : int i ]? =
[ x : int, f : int → bool ]
Séquents : E ` e : τ

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Règles de typages

val u : τ ∈ E
(val)
E`u:τ

E ` e : h m : τ; τ0 i
(send)
E ` e#m : τ

val ui : τi ∈ E self : τy ∈ E E ` ei : τi
(override)
i∈[1..n]
E ` {h ui = ei i} : τy

E ? ` ei : τi E ? † [ self : h mj : τj i ] † [ val ui : τi ] ` ej : τj
(object)
i∈[1..n] j∈[1..n0 ]
E ` h val ui = ei ; meth mj = ej i : h mj : τj i

i∈[1..n]
Réponse à la question : Pour la construction syntaxique {h ui = ei i}, peut-on
avoir pour les expressions ei des valeurs de types différents de ceux de l’objet
courant ?

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve

Règles utilisées

τ ≺ TypeOf(c) val u : τ ∈ E
(cte) (val)
E `c :τ E `u:τ

E ? ` ei : τi E ? † [ self : h mj : τj i ] † [ val ui : τi ] ` ej : τj
(object)
i∈[1..n] j∈[1..n0 ]
E ` h val ui = ei ; meth mj = ej i : h mj : τj i

int ≺ TypeOf(0) val x : int ∈ E1


(cte) ?
(val)
[ ]? ` 0 : int [ ] † [ self : h get : int i ] † [ val x : int ] ` x : int
| {z }
E1
(object)
[ ] ` h val x = 0; meth get = x i : h get : int i

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve

int ≺ TypeOf(0) val x : int ∈ E1


(cte) ?
(val)
[ ]? ` 0 : int [ ] † [ self : τy ] † [ val x : int ] ` x : int A1
| {z }
E1
(object)
[ ] ` h val x = 0; meth get = x; meth inc = λv .self#get + v i : h get : int; inc : int → int i
| {z }
τy

Avec le sous-arbre A1 défini comme suit :

E2 ` self : h get : int; inc : int → int i


| {z }
τy int ≺ E2 (v )
(send) (var)
int × int → int ≺ TypeOf(+) E2 ` self#get : int E2 ` v : int
(cte) (paire)
E2 ` + : int × int → int E2 ` (self#get, v ) : int × int
(app)
E1 † [ v : int ] ` self#get + v : int
| {z } | {z }
E2 + (self#get,v )
(abs)
E1 ` λv .self#get + v : int → int

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve


Une des règles utilisées
val ui : τi ∈ E self : τy ∈ E E ` ei : τi
(override)
i∈[1..n]
E ` {h ui = ei i} : τy

val x : int ∈ E2 int ≺ E2 (d)


(val) (var)
E2 ` x : int E2 ` d : int
(paire)
A1 E2 ` (x, d) : int × int
(app)
val x : int ∈ E2 self : α ∈ E2 E2 ` x + d : int
| {z }
+(x,d)
(override)
E1 † [ d : int ] ` {h x = x + d i} : α
| {z }
int ≺ TypeOf(0) E2
(cte) ?
(abs)
[ ]? ` 0 : int [ ] † [ self : α ] † [ val x : int ] ` λd.{h x = x + d i} : int → α
| {z }
E1
(object)
[ ] ` h val x = 0; meth deplace = λd.{h x = x + d i} i : rec α.h deplace : int → α i

Avec le sous-arbre A1 défini comme suit :

int × int → int ≺ TypeOf(+)


(cte)
E2 ` + : int × int → int

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve

Comme mentionné précédemment, l’expression


h val x = 0; meth m = h meth m’ = x i i
viole la propriété d’encapsulation.
Intuitivement, cette expression devrait avoir le type h m : h m’ : int i i.

val x : int ∈ E2 ← Problème ! val x : int 6∈ E2


(val)
? 0
E1 †[ self : τy ] ` x : int
|{z}
[]
| {z }
int ≺ TypeOf(0) E2
(cte) ?
(object)
[ ]? ` 0 : int [ ] † [ self : τy ] † [ val x : int ] ` h meth m’ = x i : h m’ : int i
| {z } | {z }
E1 τy0
(object)
[ ] ` h val x = 0; meth m = h meth m’ = x i i : h m : h m’ : int i i
| {z }
τy

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Dernier exemple
Règles utilisées

τ ≺ TypeOf(c) τ ≺ E(x)
(cte) (var)
E `c :τ E `x :τ

E † [x : τ ] ` e : τ 0
(abs)
E ` λx.e : τ −→ τ 0

E ` e : τ −→ τ 0 E ` e0 : τ
(app)
E ` e e0 : τ 0

E ` e : h m : τ; τ0 i
(send)
E ` e#m : τ

[ o : hclose : unit → α; ρi] ` o : hclose : unit → α; ρi unit ≺ TypeOf(())


(send) (cte)
[ o : hclose : unit → α; ρi] ` o#close : unit → α [ o : hclose : unit → α; ρi] ` () : unit
(app)
[ o : hclose : unit → α; ρi] ` o#close () : α
(abs)
[ ] ` λo.o#close () : hclose : unit → α; ρi → α

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Plan

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Syntaxe étendue
Syntaxe :
e ::= ...
| h b i | let z = c in e end | new c | s#m
c ::= z | class (x) b
b ::= ∅ | d; b
d ::= inherit c e as s | val u = e | meth m = e

Exemples :
E1 = new class (x0 ) val x = x0 ; meth inc = x + 1
E2 = let point = class (x0 ) val x = x0 ;
meth inc = x + 1
in new point 7
end
E3 = let point = class (x0 ) val x = x0 ;
meth get = x ;
meth inc = self#get + 1
in (new point 7)#inc
end
E4 = let point = class (x0 ) val x = x0 ;
meth inc = λv .x + v
in let point’ = class (x00 ) inherit point x00 as parent ;
val x 0 = x00 ;
meth get = x 0 ;
meth inc = λv .parent#inc (self#get + v )
0
in new point
end
end

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Sémantique statique

Types et schémas de types :

τ ::= ...
γ ::= class (τ ) τ h ϕ i
ϕ ::= ∅ | ϕ; val u : τ | ϕ; meth m : τ | ϕ; super s : ϕ

σ ::= ...
| ∀α1 , . . . , αn .γ

Exemples :
E1 : int → h inc : int i
E2 : h inc : int i
E3 : int
E4 : int → h get : int; inc : int → int i

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Sémantique statique (suite)

Environnement de typage :
E ::= . . . | E † [ z : σ ] | E † [ super s : ϕ ]
E ? = E \ {self, val, meth, super}
ϕ1 + ϕ2 : Mis à jour de ϕ1 par ϕ2 .
Exemple :
(super parent : ϕ1 ; meth m : τ ) + (super parent : ϕ2 ) = (super parent : ϕ2 ; meth m : τ )
(ϕ \ meth) ou (ϕ \ super) : On enlève de ϕ toutes les associations étiquetées par meth ou super.
Exemple : (meth m1 : τ1 ; val u : τ ; meth m2 : τ2 ) \ meth = (val u : τ )
ϕ1 ⊕ ϕ2 : S’apparente à ϕ1 + ϕ2 mais on exige, dans ce cas, que l’intersection des domaines de
ϕ1 et ϕ2 aient des types compatibles 1 (égaux).
Exemple : (meth m1 : int → int; val u : τ ) ⊕ (meth m2 : τ2 ; meth m1 : int → int) =
(meth m1 : int → int; val u : τ ; meth m2 : τ2 )
meth(ϕ) : Retourne toutes les méthodes définies dans ϕ.
Exemple : meth(meth m1 : int → int; val u : τ ; meth m2 : τ2 ) = (m1 : int → int; m2 : τ2 )

Séquents : E ` e : τ , E ` b : ϕ, E `d :ϕ

1. On utilise cet opérateur pour s’assurer que les méthodes ou variables d’instances redéfinies dans une sous-
classe aient les mêmes types que ceux définis dans la super-classe (voir règle (then)).
λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Règles de typage

E `e:τ

γ ≺ E(z)
(class-var)
E `z :γ

E `c :γ E † [z : Gen(E, γ)] ` e : τ
(class-let)
E ` let z = c in e end : τ

E ` c : class (τ ) τy h ϕ i τy = h meth(ϕ) i
(new)
E ` new c : τ → τy

E ? † [ x : τ ] † [ self : τy ] ` b : ϕ
(class)
E ` class (x) b : class (τ ) τy h ϕ i

E ? † [ self : τy ] ` b : ϕ τy = h meth(ϕ) i
(object)
E ` h b i : τy

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Règles de typage (suite)


E `b:ϕ

E ` d : ϕ1 E † (ϕ1 \ meth) ` b : ϕ2
(then)
E ` d; b : (ϕ1 \ super) ⊕ ϕ2

E `d :ϕ

E? ` e : τ E ` self : τy E ` c : class (τ ) τy0 h ϕ i τy ≤ τy0


(inherit)
E ` inherit c e as s : ϕ + (super s : ϕ)

(super s : ϕ) ∈ E (meth m : τ ) ∈ ϕ
(super)
E ` s#m : τ

E ` self : h m : τ ; τ 0 i E `e:τ
(method)
E ` meth m = e : (meth m : τ )

E? ` e : τ
(value)
E ` val u = e : (val u : τ )

2
(basic)
E `∅:∅

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve

val x : int ∈ E2
(val)
E2 ` x : int ...
int ≺ E1? (x0 ) (paire)
(var)
[ x0 : int ] ` x0 : int .
.
| {z } h inc : int; ∅ i ≺ E2 (self) .
(var) (app)
E? E2 ` self : h inc : int; ∅ i E2 ` x + 1 : int
1
(value) (method)
E1 ` val x = x0 : val x : int E1 † [ val x : int ] ` meth inc = x + 1 : meth inc : int
| {z } | {z } | {z }
ϕ1 ϕ2
(ϕ1 \meth)
| {z }
E2
?
(then)
[ ] † [ x0 : int ] † [ self : τy ] ` val x = x0 ; meth inc = x + 1 : ϕ
| {z } |{z}
E1 (ϕ1 \super) ⊕ ϕ2
(class)
[ ] ` E10 : class (int) τy h val x : int; meth inc : int i τy = hmeth(ϕ)i
| {z }
ϕ
(new)
[ ] ` new class (x0 ) val x = x0 ; meth inc = x + 1 : int → h inc : int i
| {z } | {z }
E0 τy
1

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemple d’arbre de preuve

Voir arbre précédent


(class)
[ ] ` E10 : class (int) h inc : int i h val x : int; meth inc : int i A1
| {z }
γ
(class-let)
[ ] ` E2 : h inc : int i

Avec le sous-arbre A1 défini comme suit :

γ ≺ E1 (point)
(var)
E1 ` point : class (int) τy h val x : int; meth inc : int i τy = h meth(ϕ) i
| {z }
ϕ int ≺ TypeOf(7)
(new) (cte)
E1 ` new point : int → h inc : int i E1 ` 7 : int
(app)
[ ] † [ point : γ ] ` new point 7 : h inc : int i
| {z } | {z }
E1 τy

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Plan

1 λ-calcul

2 Extension aux objets

3 Extension aux classes

4 λ-calcul étendu vs OCaml

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemples vs OCaml

Exemples Version OCaml


h val x = 0; meth get = x i object val x = 0 method get = x end ; ;

let p = object val x = 0 method get = x end


let p = h val x = 0; meth get = x i in p#get end
in p#get ; ;

object val x = 0 method get = x


h val x = 0; meth get = x; meth inc = λv .self#get + v i
method inc v = self# get + v end ; ;

object val x = 0
h val x = 0; meth deplace = λd.{h x = x + d i} i
method deplace d = {< x = x + d >} end ; ;

object val x = 0 method get = x


h val x = 0; meth get = x; meth inc = λo.o#m1 + 1 i
method inc o = o#m1 + 1 end ; ;

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Exemples vs OCaml

Exemples Version OCaml

let point = class (x0 ) val x = x0 ;


meth inc = x + 1
class point (x0) = object val x = x0 method inc = x + 1 end ; ;
in
new point 7 ; ;
new point 7
end

class point (x0) =


let point = class (x0 ) val x = x0 ;
object(self)
meth get = x ;
val x = x0
meth inc = self#get + 1
method get = x
in
method inc = self#get + 1
(new point 7)#inc
end ; ;
end
(new point 7)#inc ; ;

λoo
λ-calcul
Extension aux objets
Extension aux classes
λ-calcul étendu vs OCaml

Référence

Didier Rémy et Jérôme Vouillon,


« Objective ML : A simple object-oriented extension of ML »,
Proceedings of the 24th Annual SIGPLAN-SIGACT Symposium
on Principles of Programming Languages, POPL’97, Paris,
15–17 janvier 1997.

λoo

Vous aimerez peut-être aussi