On rappelle l’énoncé du théorème 5.1.
Théorème D.1 (Progrès). Supposons que Γ � i. Soit m un état mémoire tel que Γ�m. Alors l’un des cas suivants est vrai :
• i = PASS
• ∃v,i = RETURN(v) • ∃(i�,m�),〈i,m〉 → 〈i�,m�〉
• ∃Ω ∈ {Ωdi v,Ωar r ay,Ωptr},〈i,m〉 → Ω
� � �
Supposons que Γ � e : t. Soit m un état mémoire tel que Γ�m. Alors l’un des cas suivant est vrai :
• ∃v �= Ω,e = v
• ∃(e�,m�),〈e,m〉 → 〈e�,m�〉
• ∃Ω ∈ {Ωdi v,Ωar r ay,Ωptr},〈e,m〉 → Ω
� � �
Supposons que Γ � l v : t. Soit m un état mémoire tel que Γ�m. Alors l’un des cas suivants est vrai :
• ∃ϕ,l v = ϕ
• ∃(l v�,m�),〈l v,m〉 → 〈l v�,m�〉
• ∃Ω ∈ {Ωdi v,Ωar r ay,Ωptr},〈l v,m〉 → Ω C’est-à-dire, soit :
• l’entité (instruction, expression ou valeur gauche) est complètement évaluée. • un pas d’évaluation est possible.
D.2. PROGRÈS 149
Démonstration. On procède par induction sur la dérivation du jugement de typage. Puisque
les jugements Γ � i, Γ � e : t et Γ � l v : t sont interdépendants, on traite tous les cas par récursion mutuelle.
Le squelette de cette preuve est une analyse de cas selon la dernière règle utilisée. La plu-part des cas ont la même forme : on utilise l’hypothèse de récurrence sur les sous-éléments syntaxiques (en appliquant éventuellement le lemme 5.1 d’inversion pour établir qu’ils sont bien typés). Dans le cas « valeur », on appelle une règle qui permet de transformer une opé-ration syntaxique en opéopé-ration sémantique (par exemple, on transforme le + unaire en un �+ sémantique). Dans le cas « évaluation », on applique la règle CTXavec un contexte particulier qui permet de passer d’un jugement 〈a,m〉 → 〈a�,m�〉 à un jugement 〈b,m〉 → 〈b�,m�〉 (où a apparaît dans b). Enfin, dans le cas « erreur », on utilise EVAL-ERRavec ce même contexte C .
Ceci est valable pour la majorité des cas. Il faut faire attention en particulier aux opé-rations sémantiques qui peuvent produire des erreurs (comme la division, ou l’opérateur Lookup(·,·)).
Instructions
PASS: Ce cas est immédiat.
RETURN: Partant de i = RETURN(e), on applique le lemme d’inversion. Il nous donne l’exis-tence de t tel que Γ � e : t. On applique alors l’hypothèse de récurrence à e.
• e = v. Alors i = RETURN(v), ce qui nous permet de conclure.
• 〈e,m〉 → 〈e�,m�〉. Alors en appliquant CTX avec C = RETURN(•)1, on conclut que 〈RETURN(e),m〉 → 〈RETURN(e�),m�〉.
• 〈e,m〉 → Ω. On applique EVAL-ERRavec ce même C .
SEQ: Avec i = i1;i2, on applique l’hypothèse de récurrence à i1.
• i1= PASS. On peut donc appliquer la règle SEQet donc 〈i,m〉 → 〈i2,m〉.
• i1= RETURN(v). Alors on peut appliquer la règle RETURN: 〈i,m〉 → 〈RETURN(v),m〉. • 〈i1,m〉 → 〈i�
1,m�〉. Soit C = •;i2. Par CTXil vient 〈i,m〉 → 〈i�
1;i2,m�〉. • 〈i1,m〉 → Ω. Avec ce même C dans EVAL-ERRon trouve 〈i,m〉 → Ω.
EXP: Ici i = e. On peut appliquer l’hypothèse de récurrence à e qui est « plus petit » que i
(i ::= e introduit un constructeur implicite).
• e = v. Alors on peut appliquer EXP: 〈e,m〉 → 〈PASS,m〉.
• 〈e,m〉 → 〈e�,m�〉. Alors 〈i,m〉 → 〈e�,m�〉 (cela revient à appliquer CTXau constructeur implicite mentionné ci-dessus).
• 〈e,m〉 → Ω. C’est-à-dire 〈i,m〉 → Ω.
1. Les contextes sont des objets purement syntaxiques : on peut les appliquer entre instructions et expressions indifféremment
DECL: Ici i = DECLx = eIN{i�}. On commence par appliquer l’hypothèse de récurrence à e. • e = v. On applique alors l’hypothèse de récurrence à i� sous Γ�= Γ,local x : t et avec
m�= Extend(m, x �→ v).
• i�= PASS. Dans ce cas la règle DECL-PASSs’applique. • i�= RETURN(v). Idem avec DECL-RETURN.
• 〈i�,m�〉 → 〈i��,m��〉. On peut alors appliquer la règle DECL-CTX. • 〈i�,m�〉 → Ω. On applique DECL-ERR.
• 〈e,m〉 → 〈e�,m�〉. On pose C = DECLx = •IN{i�} et on conclut avec la règle CTX. • 〈e,m〉 → Ω. Idem avec EVAL-ERR.
IF: Ici i = IF(e){i1}ELSE{i2}. On applique l’hypothèse de récurrence à e. • e = v.
Si v �= 0, on applique IF-TRUE. Dans le cas contraire, on applique IF-FALSE. • 〈e,m〉 → 〈e�,m�〉. On pose C = IF(•){i1}ELSE{i2} et on conclut avec CTX. • 〈e,m〉 → Ω. Avec ce même C et EVAL-ERR.
WHILE: Ce cas est direct : on applique la règle d’évaluation WHILE.
Expressions
CST-INT: e est alors de la forme n, qui est une valeur. CST-FLOAT: e est alors de la forme d, qui est une valeur. CST-NULL: e est alors égale à NULL, qui est une valeur.
CST-UNIT: e est alors égale à ( ), qui est une valeur. FUN: Ce cas est direct : la règle EXP-FUNs’applique.
OP-INT: Cela implique que e = e1 � e2. Par le lemme 5.1, on en déduit que Γ � e1: INTet Γ� e2: INT.
Appliquons l’hypothèse de récurrence sur e1. Trois cas peuvent se produire. • e1= v1. On a alors 〈e1,m〉 = 〈v1,m�〉 avec m�= m.
On applique l’hypothèse de récurrence à e2.
• e2 = v2 : alors 〈e2,m�〉 = 〈v2,m��〉 avec m�� = m. On peut alors appliquer EXP -BINOP, sauf dans le cas d’une division par zéro (�∈ {/;%;/.} et v2= 0) où alors
v1 �� v2= Ωdi v. Dans ce cas, on a alors par EXP-ERR〈e,m〉 → Ωdi v. Notons que comme les opérandes sont bien typés, Ωt y pne peut pas être levée.
• ∃(e�2,m��),〈e2,m�〉 → 〈e�2,m��〉.
En appliquant CTXavec C = v1 � •, on en déduit 〈v1 � e2,m�〉 → 〈v1 � e� 2,m��〉 soit 〈e,m〉 → 〈v1 �e�2,m��〉.
D.2. PROGRÈS 151 • ∃(e1�,m�),〈e1,m〉 → 〈e�
1,m�〉. En appliquant CTX avec C = • � e2, on obtient 〈e1 �e2,m〉 → 〈e�
1 �e2,m�〉, ou 〈e,m〉 → 〈e�1 �e2,m�〉.
• 〈e1,m〉 → Ω. D’après EVAL-ERRavec C = •�e2, on a 〈e,m〉 → Ω.
OP-FLOAT: Ce cas est similaire à OP-INT.
OP-EQ: Ce cas est similaire à OP-INT.
UNOP-PLUS-INT: Alors e = + e1. En appliquant l’hypothèse d’induction sur e1:
• soit e1= v1. Alors en appliquant EXP-UNOP, 〈+ v1,m〉 → 〈�+ v1,m〉, c’est-à-dire en po-sant v = �+ v1, 〈e,m〉 → 〈v,m〉.
• soit ∃e�
1,m�,〈e1,m〉 → 〈e�
1,m�〉. Alors en appliquant CTX avec C = + •, on obtient 〈e,m〉 → 〈e�1,m�〉.
• soit 〈e1,m〉 → Ω. De EVAL-ERRavec C = + • il vient〈e,m〉 → Ω.
UNOP-PLUS-FLOAT: Ce cas est similaire à UNOP-PLUS-INT.
UNOP-MINUS-INT: Ce cas est similaire à UNOP-PLUS-INT.
UNOP-MINUS-FLOAT: Ce cas est similaire à UNOP-PLUS-INT.
UNOP-NOT: Ce cas est similaire à UNOP-PLUS-INT.
ADDR: On applique l’hypothèse de récurrence à l v.
Les cas d’évaluation et d’erreur sont traités en appliquant respectivement CTXet EVAL -ERRavec C = &•. Dans le cas où l v = ϕ, on peut appliquer EXP-ADDR.
SET: On applique l’hypothèse de récurrence à l v.
• l v = ϕ. On applique l’hypothèse de récurrence à e. • e = v. Alors on peut appliquer EXP-SET. • 〈e,m〉 → 〈e�,m�〉. On conclut avec C = ϕ ← •. • 〈e,m〉 → Ω. Idem.
• 〈l v,m〉 → 〈l v�,m�〉. On conclut avec C = • ← e. • 〈l v,m〉 → Ω. Idem.
ARRAY: On va appliquer l’hypothèse de récurrence à e1, puis, si e1= v1, on l’applique à e2, etc. Alors on se retrouve dans un des cas suivants :
• ∃p ∈ [1;n],e�p,m : e1= v1,...,ep−1= vp−1,〈ep,m〉 → 〈e�
p,m�〉. Alors on peut appliquer CTXavec C = [v1;...; vp−1;•;ep+1;...;en].
• ∃p ∈ [1;n],Ω : e1= v1,...,ep−1= vp−1,〈ep,m〉 → Ω. Dans ce cas EVAL-ERRest applicable avec ce même C .
STRUCT: Le schéma de preuve est similaire au cas ARRAY. En cas de pas d’évaluation ou d’erreur, on utilise le contexte C = {l1: v1;...;lp−1: vp−1;lp: •;lp+1: ep+1;...;ln: en} ; et dans le cas où toutes les expressions sont évaluées, on applique EXP-STRUCT.
CALL : On commence par appliquer l’hypothèse de récurrence à e. Dans le cas d’un pas
d’évaluation ou d’erreur, on applique respectivement CTXou EVAL-ERRavec C = •(e1,...,en). Reste le cas où e est une valeur : d’après le lemme 5.2, e est de la forme f = fun(a1,..., an){i }.
Ensuite, appliquons le même schéma que pour ARRAY. En cas de pas d’évaluation ou d’er-reur, on utilise CTXou EVAL-ERRavec C = f (v1,..., vp−1,•,ep+1,...,en). Le seul cas restant est celui où l’expression considérée a pour forme f (v1,..., vn) avec f = fun(a1,..., an){i }.
Soit Γ� = (ΓG,[a1: t1,..., an : tn,R : t]) et m1 = Push(m0,(a1 �→ v1,... an �→ vn)) où Γ = (ΓG,ΓL).
On applique alors l’hypothèse de récurrence à Γ�, m1et i (le lemme d’inversion garantit que Γ�� i).
• i = RETURN(v). Alors on applique EXP-CALL-RETURN.
• i = PASS. Ce cas est impossible puisqu’on prend l’hypothèse que les fonctions se ter-minent par une instruction RETURN(·) (page 56).
• 〈i,m1〉 → 〈i�,m2〉. Alors on peut appliquer EXP-CALL-CTX. • 〈i,m〉 → Ω. On peut alors appliquer EXP-CALL-ERR.
Valeurs gauches
LV-VAR: Le but est d’appliquer PHI-VAR. La seule condition pour que cela soit possible est que Lookup(x,m) renvoie une adresse et non Ωvar.
Puisque Γ � x : t, on peut appliquer le lemme 5.5 : x est soit une variable locale, soit une globale. Dans ces deux cas, Lookup(x,m) renvoie une adresse correcte.
LV-DEREF: Appliquons l’hypothèse de récurrence à e vue en tant qu’expression.
• e = v. Puisque Γ � v : t∗, on déduit du lemme 5.2 que v = NULLou v = �& ϕ. Dans le premier cas, puisque 〈∗NULL,m〉 → Ωptr, on a 〈e,m〉 → Ωptr. Dans le second cas, EXP-DEREFs’applique.
• 〈e,m〉 → 〈e�,m�〉. De CTXavec C = ∗•, on obtient 〈e,m〉 → 〈∗e�,m�〉. • 〈e,m〉 → Ω. En appliquant EVAL-ERRavec C = ∗•, on obtient 〈e,m〉 → Ω.
LV-INDEX: De même, on applique l’hypothèse de récurrence à l v.
• l v = v.
Comme Γ � v : t[ ], on déduit du lemme 5.2 que v = [v1;...; vp]. Appliquons l’hypothèse de récurrence à e.
• e = v�. Puisque Γ � e : INT, on réapplique le lemme 5.2 et v� = n. D’après PHI -ARRAY, 〈l v[e],m〉 → 〈[v1;...; vp] �[n],m〉. Deux cas sont à distinguer : si n ∈ [0; p−1], la partie droite vaut vn+1et donc 〈l v[e],m〉 → 〈vn+1,m〉. Sinon elle vaut Ωar r ayet 〈l v[e],m〉 → Ωar r aypar EXP-ERR.
• 〈e,m〉 → 〈e�,m�〉. En appliquant CTX avec C = v[•], on en déduit 〈l v[e],m〉 → 〈l v[e�],m�〉.
D.3. PRÉSERVATION 153