6. Stratégies de réécriture réflexives en Java 113
6.4. Rendre les stratégies utilisables
6.4.2. Des stratégies basées sur l’identité comme échec
public T visit_T(T arg) throws jjtraveler.VisitFailure {
%match(T arg) {
f(x,x) -> { return ‘g(x); }
}
}
}
Stratégief(x, x)→g(x) utilisant%strategy :
%strategy Rule() extends Fail() {
visit T {
f(x,x) -> { return ‘g(x); }
}
}
Fig. 6.8: Exemple de stratégie codant une règle de réécriture
6.4.2. Des stratégies basées sur l’identité comme échec
Dans la librairie MuTraveler, comme dans JJTraveler, l’échec d’une stratégie est
repré-senté par la levée d’une exception de type jjtraveler.VisitFailure. Les exceptions
étant un moyen de détourner le flot de contrôle normal d’un programme, cet encodage
est adapté à la plupart des situations, car il permet de représenter lebacktracking local
pour les combinateurs comme le choix.
Cette approche, bien que souple, est en général inefficace, car la pose d’un nouveau
point de choix se fait par l’intermédiaire d’une construction try ... catchqui place
un point de choix sur la pile d’exécution. Cette construction, dans le modèle d’exécution
deJava, n’est pas très coûteuse lorsqu’aucune exception n’est levée. Cependant, le coût
d’exécution augmente lorsque l’exception est effectivement levée.
Des problèmes d’efficacité se font alors sentir lorsque la stratégie utilisateur échoue
souvent, car alors de nombreuses exceptions seront levées et rattrapées au cours du
parcours. Ceci est pourtant un cas commun lorsque l’on considère des règles de
transfor-mation. La stratégie décrite en figure 6.8 par exemple échouera sur tout nœud qui n’est
pas de la formef(x, x). Si cette stratégie est appliquée sous la stratégieInnermost, alors
au moins autant d’exceptions qu’il y a de nœuds dans l’arbre seront levées, conduisant
à une stratégie inefficace.
Afin de pallier ce problème, nous avons introduit la notion de stratégies basées sur
l’identité. Beaucoup d’applications ne nécessitent pas une gestion très fine des échecs,
6.4. Rendre les stratégies utilisables
Combinateur Sémantique
ChoiceId(v
1,v
2)Appliquev
1, puis v
2si v
1retourne l’identité
SequenceId(v
1,v
2) Appliquev
1, puisv
2. Échoue si l’une des deux applications
retourne l’identité
OneId(v) Appliquevà tous les fils dans l’ordre, tant quevretourne
l’identité
AllId(v) Appliquev à tous les fils dans l’ordre, retourne l’identité
si l’un des sous-termes n’est pas changé
TryId(v) v
RepeatId(v) mu(MuVar("x"),SequenceId(v,MuVar("x")))
BottomUpId(v) mu(MuVar("x"),SequenceId(All(MuVar("x")),v))
TopDownId(v) mu(MuVar("x"),SequenceId(v,All(MuVar("x"))))
OnceBottomUpId(v) mu(MuVar("x"),ChoiceId(OneId(MuVar("x")),v))
InnermostId(v) mu(MuVar("x"),Sequence(All(MuVar("x")),
SequenceId(v,MuVar("x"))))
(a) Combinateurs élémentaires et stratégies communes basées sur l’identité
Innermost InnermostId 2 4 6 8 10 12 14 0 5 10 15 20 Hauteur de l’arbre Parcours innermost sur un arbre
Secondes
(b) Application d’un système de réécriture sous stratégie basée sur l’identité
car elles correspondent à calculer un point fixe à l’application d’une stratégie. On peut
dans ce cas considérer que renvoyer l’identité, c’est-à-dire ne pas modifier le terme,
peut représenter un échec de la stratégie. On décide donc d’encoder systématiquement
l’échec de l’application d’une stratégie par l’identité, en introduisant des opérateurs
de composition dits « basés sur l’identité ». Les nouveaux opérateur ainsi introduits
sont présentés en figure 6.9a. La stratégie de l’optimiseur de Tom de la figure 6.8 en
utilise certaines pour encoder l’application jusqu’à un point fixe de stratégies comme
l’élimination des instructions inutiles. Ces combinateurs basiques basés sur l’identité
utilisent alors un simple test d’égalité (qui est effectué en temps constant dans le cas des
structures de données générées parGomgrâce au partage maximal) pour tester l’échec.
Les stratégies employées sous ces combinateurs doivent alors étendre l’identité, ou être
gardés par unTry.
Le gain en efficacité est très important lorsqu’il s’agit d’appliquer un système de
réécriture de manière répétée pour obtenir un point fixe. Le graphe de la figure 6.9b
présente le temps d’exécution de la normalisation sous stratégieleftmost-innermost du
système
a → b
b → c
g(c) → c
appliqué à des termes constitués d’un certain nombre d’étages de f binaires, et dont
les feuilles sont des g(a). Ce système est encodé comme étendant l’échec, et appliqué
sous la stratégie Innermost, puis encodé comme étendant l’identité, et appliqué sous
la stratégie InnermostId. Pour de petites hauteurs de l’arbre, la différence de temps
d’exécution n’est pas importante. Lorsque la hauteur de l’arbre augmente, le nombre
de nœuds augmente de façon exponentielle, exposant alors le coût de la gestion des
exceptions par rapport à celui des tests d’égalité qui les remplacent dans le cas des
stratégies basées sur l’identité.
Ce gain d’efficacité se fait au détriment de l’expressivité. En effet, si l’on ne peut
plus distinguer un échec de l’identité, certaines applications deviennent plus difficiles à
programmer. Par exemple, pour encoder de manière efficace une stratégie recherchant
un sous-terme particulier, on peut utiliser l’échec comme une exception pour stopper le
flot normal d’exécution lorsque ce nœud particulier est trouvé, évitant ainsi de parcourir
tous les nœuds restants.
Cette distinction entre l’échec de l’application d’une stratégie et le fait de considérer
l’identité comme une condition d’arrêt est aussi présent dans le langageMGS[GM01]. Ce
langage de simulation de processus biologiques par règles de transformation de collections
topologiques introduit deux types de point fixe pour l’application de ces transformations :
– «T[fixrule](c)» applique une transformation T jusqu’à ce qu’aucune règle ne
s’applique ;
– «T[fixpoint](c)» applique une transformationTjusqu’à atteindre un point fixe,
c’est-à-dire que l’application de la transformation laisse la collection cinchangée.
L’ajout de ces combinateurs de stratégie « basés dur l’identité » permet d’exprimer de
manière plus simple et efficace les stratégies de normalisation communes en réécriture,
6.4. Rendre les stratégies utilisables
comme la normalisation innermost ou l’obtention de point fixe.
Dans le document
Réécriture et compilation de confiance
(Page 148-151)