• Aucun résultat trouvé

Exhaustivité du ltrage

Dans le document Programmation Web Typée (Page 139-154)

11.1 Analyses de programme

11.1.2 Exhaustivité du ltrage

ors du ltrage d'une valeur d'un type somme, d'une liste ou d'une constante (booléen, entier, chaîne), tous les cas doivent apparaître dans les motifs pour que l'évaluation soit bien dé nie. ne implantation d' ne doit accepter le programme que lorsque ce n'est pas le cas, ou donner un avertis-sement et lever une erreur dynamique si l'implantation dispose d'un tel mécanisme. En pratique, cee véri cation est souvent faite au moment de la compilation et de l'optimisation, comme décrit dans  1] ou plus récemment  13].

Dans ido, le langage ne disposant pas d'exceptions ou de mécanisme similaire, nous devons refuser les programmes n'assurant pas l'exhaustivité du ltrage. Pour véri er cee exhaustivité, il faut aussi traiter les ltres de nœuds, puisque nous permeons le ltrage d'une valeur de type node avec des ltres de di érentes étiquees. ous ne donnons que la véri cation du ltrage et non son optimisation, il ne s'agit pas d'une transformation de programme.

mat ProgChe (p) = mat ProgChe (F,∅,∅)(p) mat ProgChe (v,EN,EC)(ǫ) = T

mat ProgChe (F,EN,EC)(node type <t> · · · end ;; p) = mat ProgChe (F,EN∪{t},EC)(p) mat ProgChe (T,EN,EC)(node type <t> · · · end ;; p) = F

mat ProgChe (F,EN,EC)(type (· · · ) t = c0 of τ0 | · · · | cn of τn;; p) = mat ProgChe (F,EN,(c0,Cd)::···::(cn,Cd)::EC)(p) où Cd=∪

i{ci} mat ProgChe (v,EN,EC)(let [ rec ] n =e ;; p) =

mat ExprChe (EN,EC)(e) ∧mat ProgChe (v′,EN,EC)

où v′= {

Tsi e contient un ltrage de nœuds vsinon

mat ExprChe (EN,EC)(match e with p0 -> e0 | · · · | pn -> en) = mat ExprChe (EN,EC)(e) ∧∧

imat ExprChe (EN,EC)(ei) ∧mat Che (EN,EC)(∪

i{pi}) mat ExprChe (EN,EC)(e) =

e∈Emat ExprChe (N,C)(e) avec E l'ensemble des sous-expression de e mat Che (EN,EC)({n, · · · }) = mat Che (EN,EC)({_, · · · }) = T

mat Che (EN,EC)({true, false}) = T

mat Che (EN,EC)({[], h0:: t0,· · · , hn:: tn}) = mat Che (EN,EC)(∪

06i6n{hi}) ∧mat Che (EN,EC)(∪

06i6n{ti}) mat Che (EN,EC)(P = {(p0

i,· · · ,pn

i) | i ∈ I}) =

06j6nmat Che (EN,EC)({tji | i ∈ I}) mat Che (EN,EC)(P = {c0p0,· · · , cnpn}) =

(tous les constructeurs sont présents)

( nd(c0, EC) = · · · = nd(cn, En) = C)

(véri cation des sousffimotifs)

∧∧

g∈Gmat Che (EN,EC)(g)

(constructeurs apparaissant)

où C = {c | c p ∈ P }

(motifs groupés par constructeur)

où G = {{p | c p ∈ P } | c ∈ C}

mat Che (EN,EC)(P = {node <ti> pi prop l0 = p0

i · · · prop ln = pn

i | i ∈ I}) =

(toutes les étique es sont présentes)

i{ti} = EN

(véri cation des sousffimotifs)

∧∧

g∈Gmat Che (EN,EC)(g) ∧∧

gj∈Gj,06j6nmat Che (EN,EC)(gj)

(étique es apparaissant)

où E = {e | node <e> · · · end ∈ P }

(motifs de liste groupés par constructeur)

où G = {{p | node <e> p · · · end ∈ P } | e ∈ E}

où Gj = {{pj|node <e> · · · prop lj = pj · · · end ∈ P } | e ∈ E} où 0 6 i 6 n

(motifs de aque propriété groupés par constructeur)

mat Che (EN,EC)(autres cas) = F

 11.3: éri cation d'exhaustivité du ltrage. Dé nition de l'analyse a véri cation est donnée dans la gure 11.3.

– a fonction principale mat ProgChe véri e qu'aucun ltrage n'intervient avant que l'ensemble des types de nœuds soit xé. on premier paramètre booléen, initialement à F , passe à T dès qu'un ltrage de nœuds a été e ectué. e programme est refusé si ce paramètre vaut T et que l'analyse rencontre une nouvelle dé nition de type de nœud.

– Pour e ectuer l'exhaustivité du ltrage, et véri er qu'une étiquee n'est pas déjà utilisée, elle accumule l'ensemble des étiquees de nœuds dans un paramètre EN ⊆ (tag).

– Elle collecte aussi les dé nitions de constructeurs a n de véri er l'exhaustivité sur les types sommes dans un paramètre accumulateur EC ⊆ (cstr × id), qui mémorise pour chaque

construc-11

émantique statique de ido

teur le nom du type associé, pour prendre en compte le masquage de constructeurs. – Puis mat ExprChe véri e que tous les ltrages sont exhaustifs au sein d'une expression. – Cee dernière utilise mat Che qui véri e qu'un ensemble de motifs traite bien tous les cas

possibles. Pour simpli er. mat Che n'est dé nie que sur les motifs bien typés.

11.2 Système de types

Dans un langage comme , chaque expression du langage doit pouvoir se voir aribuer un type pour que le programme soit accepté. n dit alors qu'il est bien typé. a légende  47] dit même qu'un pro-gramme bien typé se comporte correctement (nous donnerons des éléments de correction section 12.6). e système de types présenté ici n'est cependant pas auto-su sant, et la sûreté d'exécution n'est assu-rée que si les analyses statiques de la section précédente ont elles-aussi accepté le programme. Concrè-tement, il est possible d'appliquer les analyses avant ou après la phase de typage. ne implantation pourrait aussi e ectuer à la demande les véri cations en même temps que l'inférence de types.

e système de types est celui classique dé ni par indley et ilner  47] pour le langage , auquel a été ajouté la gestion des nœuds présentée en introduction. a correction du polymorphisme en présence d'e ets de bord est assurée par la value restriction de right  52].

ous présentons d'abord à la section 11.2.1 la forme des types et les environnements de typage. ous donnons aussi le traitement des dé nitions de types de données personnalisés et des annotations de types en tenant compte des di érents espaces de noms, toujours dans l'esprit de fournir une spéci cation d'implantation complète. Puis, à la section 11.2.2 nous donnons l'ensemble des règles de typage du cœur du langage, et l'étendons avec les règles spéci ques aux nœuds.

11.2.1 Types et dé nitions de types

'ensemble des types sur lesquels travaille le système est directement engendré par la grammaire suivante.

τ ::= int | bool | unit | string types prédé nis

| τ → τ type fonctionnel

| τ × · · · × τ type produit

| α variable de type

| node type générique des nœuds

| <tag> node nœuds étiquetés

| (τ, · · · , τ )id instance de type personnalisé paramétré

Cee grammaire est exactement la grammaire concrète des types du langage, dans laquelle on a simplement substitué les notations concrètes par celles usuelles des systèmes de types : (type ≡ τ ), (typeffivar≡ α), (->≡→) et (*≡ ×), et où on regroupe les cas des types à 0, 1 ou n paramètres. a conversion étant sans aucune ambiguïté, on se permera dans la suite de confondre la syntaxe concrète et la syntaxe formelle.

Environnement de dé nitions es dé nitions de types et de types de nœuds enrichissent un environ-nement global D : D= (DA, DR, DF enregistrements , DN , DP nœuds , DS, DC sommes

es composantes DX servent à encoder les di érents espaces de noms. Chaque composante est encodée soit par une structure de fonction partielle lorsque l'espace de nom ne permet pas la redé nition (types, propriétés et étiquees), soit par une liste associative (selon la dé nition de la gure 8.2) si l'espace de nom permet la redé nition, l'ordre induit par la structure de liste étant alors utilisé pour représenter le masquage.

– DA ⊂ (id × (List(var) × τ)) est l'ensemble des alias de types (types qui ne dé nissent pas de nouvelles structures de données) dé nis par le programmeur. l associe les noms des alias aux paramètres et aux types associés. Contrairement aux dé nitions de types algébriques suivantes, cet ensemble ne peut contenir de dé nitions cycliques.

– DR ⊂ (id × (List(var) × P(id))) associe chaque nom de type enregistrement à ses paramètres et à l'ensemble des noms de ses champs.

– DF ∈ List(id × (id × τ × {T, F })) représente l'espace de noms des champs d'enregistrement et associe à chaque nom de champ le nom du type produit auquel il appartient, son propre type, et s'il est mutable ou non. 'ordre qu'implique la structure de liste représente le masquage des noms de champs.

– DN ⊂ (tag × P(id)) associe à chaque étiquee de nœud l'ensemble de ses propriétés.

– DP ⊂ (id × (τ × {T, F })) associe à chaque nom de propriété le type associé et la mutabilité. Contrairement aux champs d'enregistrement, il n'y a pas de masquage. i deux types de nœuds dé nissent deux propriétés avec le même nom, alors elles doivent avoir le même type et la même mutabilité.

– DS ⊂ (id × (List(var) × P(cstr))) associe chaque nom de type somme à ses paramètres et à l'ensemble des noms de ses constructeurs.

– DC ∈ List(id × (id × (τ ∪ ⊥))) représente l'espace de noms des constructeurs et associe à chaque constructeur le nom du type somme auquel il appartient et son propre type, s'il en a un. Comme pour les champs d'enregistrements, l'ordre qu'implique la structure de liste représente le masquage (le premier constructeur dans la liste est le dernier dé ni).

Notations A n de simpli er et uniformiser les écritures, on utilise les notations suivantes, qui utilisent soit celles usuelles des fonctions, soit celles que nous avons dé ni pour les listes associatives :

– dom(DX) représente l'ensemble des noms dé nis dans l'espace de noms représenté par DX. – DX(n), dé nie surdom(DX), renvoie la dé nition associée à n dans cet de noms. i l'espace de

noms permet la redé nition, il s'agit de la dernière dé nition.

– n dé nit aussi le prédicat d'appartenance d'un type à l'environnement de dé nitions selon la notation suivante. (α0,· · · , αn) t ∈dom(DA) ≡ (t, (α0:: · · · :: αn:: [ ], τ )) ∈ DA0,· · · , αn) t ∈dom(DR) ≡ (t, (α0:: · · · :: αn:: [ ], F )) ∈ DR0,· · · , αn) t ∈dom(DS) ≡ (t, (α0:: · · · :: αn:: [ ], C)) ∈ DS0,· · · , αn) t ∈dom(D) ≡ (α0,· · · , αn) t ∈dom(DA) ∨ (α0,· · · , αn) t ∈dom(DR) ∨ (α0,· · · , αn) t ∈dom(DS)

Dé nitions de types ors des dé nitions de types (ainsi que lors de la véri cation des annotations de types dans les expressions) il faut s'assurer que le type donné par le programmeur a du sens dans l'envi-ronnement de typage courant. a fonction wd(τ, D, V ) donnée gure 11.4 véri e que τ est correctement dé ni dans l'environnement D. Elle est dé nie par induction sur la structure des types, s'assurant que

11

émantique statique de ido

chaque type nommé apparaissant est bien dé ni dans D, et avec le bon nombre de paramètres le cas échéant. a fonction prend aussi l'ensemble des variables de types autorisées à apparaître.

wd(unit | int | bool | string, D, V ) = T wd(node, D, V ) = T wd(α, D, V ) = T si α ∈ V, F sinon wd(τ0× · · · × τn, D, V) = wd(τ0, D, V) ∧ · · · ∧wd(τn, D, V) wd(τa→ τb, D, V) = wd(τa, D, V) ∧wd(τb, D, V) wd((τ0,· · · , τn) t, D, V ) = (α0,· · · , αn) t ∈dom(D) ∧wd(τ0, D, V) ∧ · · · ∧wd(τn, D, V) wd(t, D, V ) = t ∈ dom(D)

wd(<t> node, D, V ) = T(utilisation avant dé nition possible)

 11.4: éri cation de type dans un environnement de dé nitions.

'environnement peut alors être enrichi de façon correcte par la fonction def de la gure 11.5 en utilisant wd.

def (D, type (α0,· · ·,αn) t = { l0 : em0 τ0; · · ·; lm : emm τm }) = (DA, DR , DF, DN, DP, DS, DC) = D

où D

F = (l0,(τ0, m0)) :: · · · :: (lm,(τm, mm)) :: DF

où mi= T si emi =mutable, F sinon, 0 6 i 6 m et D R= DR∪ {(t, (α0 :: · · · :: αn:: [], {li| 0 6 i 6 m}))} si ∀i, ∀j, li 6= lj et ∀0 6 i 6 m, wd(τi, D,{αk,0 6 k 6 n}) def (D, type (α0,· · ·,αn) t = c0 e0 | · · · | cm em) = (DA, DR, DF, DN, DP, DS, DC ) = D où τi= { τei si ei =of τei ⊥ si ei = ǫ pour 0 6 i 6 m où D C = (c0, τ0) :: · · · :: (cm, τm) :: DC et D S = DS∪ {(t, (α0 :: · · · :: αn:: [], {ci| 0 6 i 6 m}))} si ∀i, ∀j, ci6= cjet ∀0 6 i 6 m, wd(τi, D,{αk,0 6 k 6 n}) def (D, type (α0,· · ·,αn) t = τ) = (DA , DR, DF, DN, DP, DS, DC) où D A= DA∪ {(t, (α0:: · · · :: αn:: [], τ ))} si wd(τ, D, {αk,0 6 k 6 n})

def (D, node type <tag> prop em0 p0 : τ0 · · · prop emm pm : τm end) = (DA, DR, DF, DN , DP, DS, DC)

où D

N = DN ∪ {(tag, {pi| 0 6 i 6 m})} où mi= T si emi =mutable, F sinon, 0 6 i 6 m

et D

P = DP ∪ {(pi,(τi, mi)) | 0 6 i 6 m}

si t /∈ dom(DN) et ∀0 6 i 6 m, li ∈dom(DP) ⇒ DP(li) = τi, mi et ∀i, ∀j, pi6= pj et ∀0 6 i 6 m, wd(τi, D,∅)

 11.5: Enrichissement d'un environnement de dé nitions.

n type somme (resp. enregistrement) est bien dé ni si ses constructeurs (resp. champs) sont tous

11émantique statique de ido

di érents et associés à un type bien dé ni. Comme en Caml ¹, le système fournit dé nitions iso-récursives, mais pas équi-récursives. En clair, la récursion doit être gardée par une construction, les dé nitions de types sommes et enregistrements sont donc implicitement récursives, mais les alias ne le sont pas.

11.2.2 Typage ML

e système de types de ido est classiquement décrit comme un ensemble de règles d'inférence de la forme ( )Γ,D ⊢prémissesexpr : τ se lisant : τ est un type correct pour une expression de la forme expr si les prémisses sont véri ées dans un environnement de typage Γ et un environnement de dé nitions D. a formule Γ, D ⊢ expr : τ est ce qu'on appelle jugement de typage. 'environnement D a déjà été présenté, l'environnement Γ, que nous présenterons juste après, contient les variables, globales et locales, dé nies à cet endroit du programme, et les associe à leurs types. es prémisses sont un ensemble de jugements de typage et conditions devant tous être véri és pour que la règle soit applicable. En général, expr ne représente pas une expression unique, mais est dé nie de façon symbolique, tout ou partie de ses sous-expressions étant des variables. es prémisses sont donc dé nies en fonction de ces variables, de même que le type τ.

n dit alors qu'une expression e est typable dans un environnement Γ, D si il est possible de dériver un jugement de typage Γ, D ⊢ e : τ, depuis une des règles du système. Pour qu'une telle dérivation soit possible, il faut bien sûr trouver une instanciation des symboles au sein de la règle telle que l'expression symbolique soit instanciée en e, mais il faut aussi que les prémisses ainsi instanciées soient des formules logiques correctes. En particulier, si les prémisses contiennent des jugements de typage à véri er (ce qui est en général le cas pour les expressions composées), il faut aussi dériver une règle du système pour chacune de ces prémisses, et ainsi de suite récursivement (de façon nie). n parle alors d'arbre de dérivation ou d'arbre d'inférence.

Pour ce système, nous avons choisi un ensemble de règles dirigés par la syntaxe, c'est-à-dire qu'il n'y a qu'un choix de règle possible pour une expression donnée de la syntaxe concrète. Cee approche utilise des règles un peu plus compliquées que si on permeait le choix de plusieurs règles pour une même expression, mais elle est intéressante car elle facilite la dé nition d'un algorithme d'inférence de types. ous donnons d'abord l'ensemble de jugements de typage correspondant au indley-ilner classique. ous l'enrichirons ensuite progressivement avec les dé nitions de types personnalisés, puis les règles spéci ques auxnœuds.

Cœur du langage es règles de typage pour les constantes n'ont pas de prémisses, ce sont, avec les variables, les feuilles de l'arbre d'inférence.

( )

Γ, D ⊢ i : int ( )Γ, D ⊢() : unit

( )

Γ, D ⊢true : bool ( )Γ, D ⊢false : bool

a règle de typage de la construction de liste introduit l'homogénéité de listes d' en reliant par un même symbole τ le jugement de typage de la sous-expression correspondant à la tête et celui correspon-dant à la queue. De même, le type de l'expression est lié par le même symbole τ faisant le lien entre le type de l'expression et les types des sous-expressions. Bien sûr, cee homogénéité va se propager dans les deux sous-arbres d'inférence des sous-expressions. En particulier, la liste vide peut être considérée comme une liste d'éléments de n'importe quelle type τ, mais ce symbole τ devra être cohérent avec le reste de l'arbre d'inférence.

1. e compilateurocamlpeut permere l'équi-récursion via l'option-rectypes.

11

émantique statique de ido

( 2) Γ, D ⊢ e : τ Γ, D ⊢ l : τlist

Γ, D ⊢ e :: l : τ list ( 1)Γ, D ⊢[] : τ list

Pour les n-uplets, la règle de typage introduit un symbole di érent par composante, qui sont indé-pendants comme voulu. es mêmes symboles se retrouvent dans le type global du n-uplet, faisant le lien entre les composantes du type produit et les types des composantes du produit.

Pour la projection de composante d'un n-uplet, il faut véri er que l'expression à projeter a bien un type de n-uplet, que la constante de taille donnée par le programmeur est bien ce n, et que la projection i demandée est bien dans l'intervalle [0, n−1]. e type de l'expression d'accès est alors lié symboliquement à la iᵉ composante du type du n-uplet.

( ) Γ, D ⊢ e0 : τ0 · · · Γ, D ⊢ en : τn

Γ, D ⊢(e0,· · ·,en) : τ0× · · · × τn

(P ) Γ, D ⊢ e : τ0× · · · × τn 0 6 i 6 n Γ, D ⊢ e.(proj i / n) : τi

Pour qu'une expression if soit typable et soit de type τ, il faut pouvoir donner ce même type τ aux deux branches.

(  E ) Γ, D ⊢ e : bool Γ, D ⊢ et : τ Γ, D ⊢ ef : τ Γ, D ⊢if e then et else ef : τ

(  ) Γ, D ⊢ e : bool Γ, D ⊢ et : unit Γ, D ⊢if e then et : unit

ne dé nition de fonction est typable si son corps est typable dans un environnement où le nom du paramètre est lié au type de son argument. éciproquement, une application est bien typée si l'expres-sion gauche est bien d'un type èche, dont la partie gauche correspond au type de l'argument.

(A ) Γ, D ⊢ ef : τ1→ τ2 Γ, D ⊢ ea : τ1 Γ, D ⊢ ef ea : τ2

(A ) (n, τ1) :: Γ, D ⊢ e : τ2 Γ, D ⊢fun n -> e : τ1 → τ2

Polymorphisme e sous-ensemble du système que nous avons présenté jusqu'ici ne su t par pour prendre en charge le polymorphisme à la . Plus précisément, le mécanisme simple de liaison sym-bolique des types des expressions et de leurs sous-expressions dans l'arbre d'inférence fait qu'il est impossible de donner un type générique (contenant une variable de type) à une sous-expression intrin-sèquement générique, si celle-ci est utilisée par ailleurs sous un type moins générique. C'est exactement ce que nous avons vu avec le type de la liste vide, dont le paramètre doit être le même que celui du type de l'expression de liste qui la contient, alors que la liste vide est intrinsèquement polymorphe.

ous voulons donc permere de donner un type générique, contenant des variables, à une sous-expression, et l'utiliser par ailleurs dans l'arbre avec di érentes valeurs de ces variables. Pour ceci, on introduit une notion de s éma de types, qui est un type dont les variables (ou éventuellement seulement une partie) sont placées sous quanti cation universelle. Dans indley-ilner, on introduit seulement les quanti cations en position prénexe. Concrètement, nous utilisons donc la notation σ dé nie ci-dessous pour les schémas de types.

σ ::= ∀α.σ | τ

11émantique statique de ido

l faut alors introduire dans le système ces schémas de types par deux mécanismes permeant l'in-troduction et l'élimination des quanti cations, la généralisation et l'instanciation.

Généralisation et instanciation a généralisation construit un type polymorphe à partir d'un type contenant des variables, en quanti ant tout ou partie de ses variables, de façon appropriée suivant le contexte (nous verrons qu'il n'est pas toujours possible de généraliser toutes les variables). a réciproque, l'instanciation, construit un type spécialisé à partir d'un type polymorphe en remplaçant des variables et leurs quanti cations par des types là encore cohérents par rapport au contexte.

Dans un système de règles non dirigé par la syntaxe, il est possible d'introduire une règle ( ) et une règle ( ) pouvant s'insérer n'importe-où dans l'arbre. Classiquement, dans notre système à la indley-ilner dirigé par la syntaxe, et comme c'est le cas dans l'algorithme d'inférence induit, les schémas de types n'apparaissent pas directement dans les jugements de typage, mais sont introduits dans le système via l'environnement de typage. a généralisation est donc faite explicitement à l'aide d'une fonction gen(τ, Γ) lors de la règle ( ), qui enrichit l'environnement d'un schéma de type. 'ins-tanciation est alors faite à l'aide d'une relation 6 au niveau des variables, en spécialisant le type associé dans l'environnement.

'environnement de typage Γ est donc une liste associative de noms à des schémas de types : Γ ∈List(id × σ)

a fonction de généralisation gen(τ, Γ) quanti e les variables de types α0,· · · , αnprésentes dans τ et n'apparaissant pas libres dans Γ pour constituer le schéma de type ∀α0.· · · ∀αn.τ. a dé nition formelle est donnée gure 11.6.

gen(τ, Γ) = ∀α0.· · · ∀αn.τ où {αi| 0 6 i 6 n} = F(τ )\F(Γ) avec F la collecte des variables libres dans les schémas :

F(∀α.σ) = F(σ)\{α} F(α) = {α} F(int | bool | unit | string) = ∅

F(node | <t> node) = ∅

F(τa→ τb) = F(τa) ∪ F(τb) F(τ0× · · · × τn) = F(τ0) ∪ · · · ∪ F(τn) F((τ0,· · · , τn) t) = F(τ0) ∪ · · · ∪ F(τn)

et dans les environnements : F([ ]) = ∅

F((n, τ ) :: t) = F(τ ) ∪ F(t)

 11.6: onction de généralisation. a relation d'instanciation est alors notée σ 6 τ et dé nie comme suit.

∃τi,0 6 i 6 n, τ = τi← τi,0 6 i 6 n] ⇒ ∀α0.· · · ∀αn

Généralisation en présence d'e ets de bord ous utilisons la value restriction de right  52], qui montre qu'en présence d'e ets de bord, la généralisation au let est possible, si l'expression liée est dite non expansive selon la dé nition syntaxique de la gure 11.7. ous étendons trivialement la dé nition aux nœuds, puisque ceux-ci ne sont pas polymorphes.

11

émantique statique de ido

Liaisons locales Avec ces dé nitions, on peut nalement donner le typage des dé nitions et utili-sations de variables. i on lie une expression non expansive, celle-ci devient polymorphe dans l'envi-ronnement de typage du corps de la dé nition. 'il s'agit d'une expression expansive, les éventuelles inconnues dans son type se retrouveront tel quel (non généralisées) dans l'environnement du corps de la dé nition. ( ) Γ(x) = σ σ 6 τ Γ, D ⊢ x : τ (  1) ¬expansive(ed) Γ, D ⊢ ed : τd (n,gen(τd,Γ)) :: Γ, D ⊢ eb : τb Γ, D ⊢let n = ed in eb : τb (  2) expansive(ed) Γ, D ⊢ ed : τd (n, τd) :: Γ, D ⊢ eb : τb Γ, D ⊢let n = ed in eb : τb (   1) ¬expansive(ed) (n, τd) :: Γ, D ⊢ ed : τd (n,gen(τd,Γ)) :: Γ, D ⊢ eb : τb Γ, D ⊢let rec n = ed in eb : τb (   2) expansive(ed) (n, τd) :: Γ, D ⊢ ed : τd (n, τd) :: Γ, D ⊢ eb : τb Γ, D ⊢let rec n = ed in eb : τb

Liaisons globales Pour le typage des phrases du programme, on introduit une nouvelle forme de règles ( )Γ,D ⊢ p : Γ,Dprémisses . En d'autres termes, on considère que le type d'un programme est l'ensemble des liaisons globales avec leurs types, ainsi que l'ensemble des dé nitions de types personnalisés.

De façon similaire aux liaison locales, si on lie une expression non expansive, celle-ci devient poly-morphe dans l'environnement de typage de la suite du programme. Par contre, dans ido, on n'au-torise pas la liaison globale d'expression de type non généralisable.

( ) ¬expansive(e) Γ, D ⊢ e : τ Γ = (n,gen(τ, Γ)) :: Γ Γ, D ⊢let n = e : Γ, D (  ) ¬expansive(e) (n, τ ) :: Γ, D ⊢ e : τ Γ = (n,gen(τ, Γ)) :: Γ Γ, D ⊢let rec n = e : Γ, D (E ) Γ, D ⊢ e : τ Γ, D ⊢ e : Γ, D ( ) Γ, D ⊢ p1 : Γ, D Γ, D ⊢ p2 : Γ′′, D′′ Γ, D ⊢ p1;; p2 : Γ′′, D′′ expansive(fun ea -> eb) = F expansive(e1; e2) = expansive(e2)

expansive(let n = e1 in e2) = expansive(e1) ∨expansive(e2) expansive(n) = F

expansive(cstr e) = expansive(e)

expansive((e0,· · ·,en)) = expansive(e0) ∨ · · · ∨expansive(en) expansive({ l0 = e0; · · ·; en }) = expansive(e0) ∨ · · · ∨expansive(en)

expansive(node <t> · · · end) = F expansive(autres cas) = T

 11.7: Expressions expansives.

11.2.3 Types personnalisés

l y a deux possibilités principales pour typer les structures de données dé nies par le programmeur. ne approche possible est d'enrichir l'environnement de typage de fonctions virtuelles de création,

11émantique statique de ido

d'accès et de modi cation. es jugements de typage se contentent alors d'ajouter un étage faisant la traduction entre les structures de la syntaxe concrète et des applications virtuelles des fonctions décrites précédemment. Ce type d'encodage est en général plutôt utilisé lorsqu'on cherche à décrire un modèle théorique minimal du système de types, sur lequel on cherche à montrer des propriétés et où on ne se soucie pas les problèmes pratiques comme le masquage, l'exhaustivité des champs, etc.

Dans notre optique de donner une spéci cation en vue d'implantation, nous avons préféré ajouter les dé nitions et utilisations de types personnalisés sans les trans gurer. ous proposons alors des règles un peu plus nombreuses et complexes, mais moins arti cielles, ne laissant pas de côté des détails non centraux mais néanmoins nécessaires à résoudre en vue d'une implantation.

ous pouvons alors étendre l'ensemble des règles de typage au niveau programme pour prendre en compte les dé nitions de types. Ces règles utilisent la fonction def dé nie plus tôt pour enrichir l'environnement D pour le typage de la suite du programme, et par extension pour le type du programme

Dans le document Programmation Web Typée (Page 139-154)

Documents relatifs