• Aucun résultat trouvé

Les invariants

Dans le document Réécriture et compilation de confiance (Page 107-110)

4. Structure de données sûre 65

4.5. Interactions avec Tom

4.5.4. Les invariants

En utilisant la définition de structure de données de la figure 4.12, on manipule des

objets, commepar(concPar()), qui ne correspondent pas nécessairement aux structures

que l’on veut décrire. Le problème posé par des objets commepar(concPar())s’ajoute

à celui qui est présenté dans la note A : cet objet ne correspond directement à aucun

objet dans le langage des structures du systèmeBV. On peut toutefois le considérer égal

au neutre pour l’opérateur [ ],◦.

La possibilité de représenter de différentes manières des structures équivalentes pour

le système BV pousse à choisir un de ces représentants comme représentant canonique.

Exemple 23. Les structures par(concPar(a())) et cop(concCop(a())) sont toutes

deux équivalentes à la structurea(), carhRi ≈[R]≈(R)≈R.

– [],hi et()sont réduits lorsqu’ils contiennent une seule sous-structure :

par(concPar(x))→x

cop(concCop(x))→x

seq(concSeq(x))→x

– Les structures imbriquées sont aplaties, en utilisant les règles :

par(concPar(a

1

, . . . ,a

i

,par(concPar(x

1

, . . . ,x

n

)),b

1

, . . . ,b

j

))

par(concPar(a

1

, . . . ,a

i

,x

1

, . . . ,x

n

,b

1

, . . . ,b

j

))

cop(concCop(a

1

, . . . ,a

i

,cop(concCop(x

1, . . . ,

x

n

)),b

1, . . . ,

b

j

))

→cop(concCop(a

1

, . . . ,a

i

,x

1

, . . . ,x

n

,b

1

, . . . ,b

j

))

seq(concSeq(a

1

, . . . ,a

i

,seq(concSeq(x

1

, . . . ,x

n

)),b

1

, . . . ,b

j

))

→seq(concSeq(a

1, . . . ,

a

i,

x

1, . . . ,

x

n,

b

1, . . . ,

b

j

))

– Les sous-termes depar etcopar sont triés selon un ordre total< :

concPar(. . . ,x

i

, . . . ,x

j

, . . .)→concPar(. . . ,x

j

, . . . ,x

i

, . . .) ifx

j

<x

i

concCop(. . . ,x

i

, . . . ,x

j

, . . .)→concCop(. . . ,x

j

, . . . ,x

i

, . . .) ifx

j

<x

i

Cette notion de forme canonique nous permet de vérifier efficacement si deux objets

représentent la même structure modulo l’associativité, la commutativité, les éléments

neutres et les règles de réduction des différents connecteurs. Cette vérification est de

fait très efficace, car elle correspond à une comparaison de pointeurs, deux objets d’une

même classe d’équivalence étant représentés par le même représentant canonique, donc

le même objet en mémoire grâce au partage maximal.

Le premier invariant à maintenir est la réduction des singletons pour les structures

seq, par et copar. Lorsque l’utilisateur essaye de construire un seq, par ou cop avec

une liste vide de structures, alors la fonction de création doit retourner l’unité o().

Sinon, si la liste contient un seul élément, elle doit retourner l’élément lui même. Dans

les autres cas, cette fonction de création construira la structure demandée. Comme tous

les objets manipulés par l’utilisateur sont en forme normale (sont des représentants

canoniques), il n’est pas nécessaire dans le cas de cet invariant de traiter le cas d’une

liste de structures en argument contenant l’unité ou un seul élément, car cela est rendu

impossible par l’invariant sur la liste. Ce comportement est implanté comme un hook

pour les opérateursseq,par etcop.

Le premier hook de la figure 4.13 implémente la réduction des singletons pour

l’opé-rateurparen utilisant le filtrage de Tom. Le filtrage sur les opérateurs de liste de Tom

est utilisé pour examiner la liste passée en argument du constructeur depar. Si la liste

n’est pas un singleton, alors la fonction originale de construction est implicitement

ap-pelée. Cette fonction de création originale n’est accessible que depuis la définition du

hook correspondant à l’opérateur. Ainsi, l’utilisateur de la structure de données ne peut

l’utiliser, mais utilisera la fonction comportant le hook, qui met en place les invariants.

Les opérateurscopetseqsont munis de hooks similaires.

Les hooks permettant de normaliser les listes de structures sont plus complexes. Il

est tout d’abord nécessaire d’utiliser un ordre total sur les structures. Cet ordre peut

4.5. Interactions avecTom

...

par:make(l) {

%match(StrucPar l) {

concPar() -> { return ‘o(); }

concPar(x) -> { return ‘x; }

}

}

cop:make(l) {

%match(StrucCop l) {

concCop() -> { return ‘o(); }

concCop(x) -> { return ‘x; }

}

}

seq:make(l) {

%match(StrucSeq l) {

concSeq() -> { return ‘o(); }

concSeq(x) -> { return ‘x; }

}

}

...

Fig. 4.13: Leshooks pour par,copetseq.

être implanté par une fonction extérieure

3

. Toutefois, les structures générées par Gom

comportent une implantation d’un ordre total très efficace, rendu disponible par

l’im-plantation de l’interfaceComparablepar toutes les classes correspondant aux opérateurs.

Il est donc raisonnable dans ce cas d’utiliser cet ordre, car aucune condition particulière

n’est requise sur l’ordre utilisé (il doit toutefois être total).

On peut donc définir les hooks pour les opérateurs variadiquesconcSeq, concPar et

concCop. Ceux-ci sont définis en surchargeant la fonction d’insertion en tête dans la liste

d’arguments de l’opérateur variadique, en utilisantmake_insert.

Lehook pour concSeqest le plus simple, car les structureshisont seulement

associa-tives, avec ◦leur élément neutre. Le hook correspondant doit donc supprimer les unités

et aplatir les seq imbriqués. L’implantation de ce hook en figure 4.14 utilise une fois

encore le filtrage de Tom pour examiner la forme de l’élément à insérer dans la liste

d’arguments d’un opérateur concSeq. Si celui-ci est une unité, la liste de départ est

retournée, et si c’est une structure seq, sa liste interne d’arguments est concaténée à la

liste d’arguments de l’opérateur. Les hooks pour concCop et concPar, présentés en

fi-gure 4.15 sont similaires, mais examinent aussi le second argument : la liste dans laquelle

on insère l’élément, afin d’implanter une insertion triée selon l’ordre interne à la

struc-3

La seule contrainte est que cette fonction doit être déclarée statique, et être accessible. Elle peut être écrite en utilisant le filtrage deTom.

StrucSeq = concSeq( Struc* )

concSeq:make_insert(e,l) {

%match(Struc e) {

o() -> { return l; }

seq(concSeq(subL*)) -> { return ‘concSeq(subL*,l*); }

}

}

Fig.4.14: Lehook pour l’opérateurconcSeq

ture. Cehook utilise‘concPar(L*,l*)pour effectuer un appel récursif à la fonction de

création (utilisant la construction de Tom, présentée en section 2.2.4). Il utilise aussi

l’appel à la fonctionrealMake, qui correspond à l’opération de construction originale.

Le calcul des structures vérifie aussi les lois de De Morgan pour la négation. On peut

donc aussi écrire unhook pour l’opérateur de négationneg, qui applique les lois de De

Morgan de manière similaire auhook de l’exemple 22. L’application de ce hook garantit

que dans les structures manipulées seuls les atomes peuvent être en position négative.

Cela simplifie l’application des règles de déduction, en supprimant le besoin de propager

les négations.

Dans le document Réécriture et compilation de confiance (Page 107-110)