f x
!f:w
='
f 1 A 2P def= [xi
:=ai
][f:h
:='h
] def= 8 < :c:u
=E[('
)] (f) auxCheck
(c;f;
) P ` 0 B B @c y
!c:u
=E[(f a
):w
] (f a
):h
='h
aux 1 C C A )c y
! (SE
)Fig. 8.1: Evaluation symbolique (SE)
Pour illustrer l'utilisation de cette evaluation symbolique et pour montrer en quoi elle eectue de l'evaluation partielle, je considere l'expression
g
denie par un appel a la fonction rev:letg = rev (cons a (cons b nil)) nil
La transformation FP-to-AG appliquee a cette fonction produit, gr^ace a la regle Let' de la transformation preliminaire (gure 7.3) puis par l'application de l'evaluation symbolique du prol (PSE, gure 7.4), la grammaire attribuee suivante:
aglet
g
= g!g
:
result = (cons a (cons b nil)):
rev (cons a (cons b nil)):
h = nilLes deux regles semantiques ci-dessus peuvent alors subir les transformations speciees par l'evaluation symbolique (SE, gure 8.1). Le premier pas d'application de SE sur ces regles est detaille gure 8.2. Deux autres pas de cette m^eme regle de transformation, presentes gures 8.3 et 8.4, conduisent au terme evalue suivant:
g
:
result = (cons b (cons a nil))L'evaluation symbolique eectue donc de l'
evaluation partielle
sur les termes nis.8.2 Projection des schemas de calculs
Je vais maintenant presenter une transformation qui s'inspire des principes de la com-position descriptionnelle mais qui met a prot le formalisme fonctionnel adopte pour les grammaires attribuees, ainsi que de l'evaluation partielle incluse dans l'evaluation symbo-lique precedemment generalisee.
L'idee
Pour donner l'idee de cette transformation, je reprends ici l'exemple illustratif de compo-sition de la fonction rev qui inverse une liste avec la fonction at qui cree la liste des feuilles d'un arbre (cf. gure 7.2). Cette composition aboutit bien s^ur a la liste des feuilles de l'arbre,
8.2. Projection des schemas de calculs 157
0 @
cons head tail !
cons
:
rev = tail:
revtail
:
h = cons head cons:
h1 A
2P
def= [head := a][tail := (cons b nil)][cons:
h := nil] def=
g
:
result = (cons b nil):
rev (cons b nil):
h = (cons a nil)Check
(g;cons;
)P `
g
!g
:
result = (cons a (cons b nil)):
rev(cons a (cons b nil))
:
h = nil )g
!(
SE
)Fig.8.2: Premier pas d'application de SE
0 @
cons head tail !
cons
:
rev = tail:
revtail
:
h = cons head cons:
h1 A
2P
def= [head := b][tail := nil][cons:
h := (cons a nil)] def=
g
:
result = (nil):
rev(nil)
:
h = (cons b (cons a nil))Check
(c;cons;
)P `
g
!g
:
result = (cons b nil):
rev(cons b nil)
:
h = (cons a nil) )g
!(
SE
)Fig. 8.3: Second pas d'application de SE
nil !
nil
:
rev = nil:
h2P
def= [nil:
h := (cons b (cons a nil))] def=g
:
result = (cons b (cons a nil))Check
(g;nil;
)P `
g
!g
:
result = (nil):
rev(nil)
:
h = (cons b (cons a nil)) )g
!(
SE
)158 Chapitre 8. Composition symbolique
agletrev = rev
x h
!rev
:
result = x:
rev rev:
h = hcons head tail !
cons
:
rev = tail:
revtail
:
h = (cons head cons:
h) nil !nil
:
rev = nil:
haglet at = at t l !
at
:
result = t:
at t:
l = lnode left right !
node
:
at = left:
at left:
l = right:
at right:
l = node:
l leaf n !leaf
:
at = cons n leaf:
lFig.8.5: Les grammaires attribuees rev et at
dans le sens inverse de celui decrit par at, mais le but ici est de la transformer de sorte a ce qu'elle ne construise pas la premiere liste des feuilles, mais plut^ot qu'elle projette le calcul de son inversion directement sur le parcours de la structure de l'arbre.
Soit donc la denition de la fonction rev at :
let rev at t = (rev ( at t nil) nil)
De maniere intuitive, dans le contexte des grammaires attribuees correspondant a ces fonc-tions et generees par FP-to-AG (cf. gure 8.5), cette composition implique les deux ensembles d'attributs suivants:
Att at =f at
;
lg and Attrev =frev;
hgLe pas de projection
Plus generalement, considerons une grammaire attribueeF (par exemple at), produisant une structure de donnee intermediaire qui doit ^etre consommee par une grammaire attribuee
G (par exemple rev). Deux ensembles d'attributs sont impliques dans cette composition. Le premier ensemble, AttF, contient tous les attributs utilises pour construire la structure de donnee intermediaire. Le second, AttG, contient les attributs deG.
Tout comme dans la composition descriptionnelle, l'idee de la composition symbolique est de projeter les attributs de AttG (Attrev) partout ou un attribut de AttF (Att at) est deni. Cette operation globale transporte les equations speciant le calcul sur la structure intermediaire a l'interieur m^eme de sa construction. Le pas de base de cette projection est presente a la gure 8.6. La transformation Proj fait appara^tre, par cette projection, des expressions qui peuvent ensuite ^etre traitees par l'evaluation symbolique (SE, gure 8.1). Celle-ci se chargera d'eliminer les constructeurs inutiles de la structure intermediaire.
C'est le principe de base de la deforestation proposee par la composition symbolique.
Les sites d'applications
Il reste cependant une chose a determiner: comment trouver les sites d'application des pas de projection Proj ? Comme je l'ai evoque dans l'introduction de ce chapitre, le predicat Check, qui interdisait dans l'evaluation symbolique du prol l'introduction d'expressions de la
8.2. Projection des schemas de calculs 159
a
2AttFs
= AttS
Gh
= AttH
GAttG
;
AttF `x:a
=e
) (x:a
):s
= (e
):s
8s
2s
(e
):h
= (x:a
):h
8h
2h
(Proj
) AttG;
AttF`
eq
) signie que, en considerant GF, l'equationeq
est transformee en l'ensemble d'equations . AttS
G est l'ensemble des attributs synthetises de AttG. AttH
G est l'ensemble des attributs herites de AttG.Fig. 8.6: Le pas de projection (Proj) rev at t !
rev at
:
result = (t:
at):
rev (t:
at):
h = nilt
:
l = nilnode left right!
node
:
at = left:
at left:
l = right:
at right:
l = node:
l leaf n !leaf
:
at = cons n leaf:
lcons head tail !
cons
:
rev = tail:
rev tail:
h = cons head cons:
h nil !nil
:
rev = nil:
hFig. 8.7: Le bloc de grammaire attribuee correspondant au prol de rev at, avec les blocs correspondants a at et a rev
forme (
x:a
):b
, va ^etre temporairement assoupli. En fait, ces expressions sont representatives des compositions qui doivent avoir lieu et elles indiquent precisement les sites ou la defo-restation doit ^etre eectuee localement (comme (t:
at):
rev). Je parle ici d'assouplissement temporaire du predicat Check car, en sortie de la composition symbolique, apres l'application de toutes les transformations, ces expressions n'appara^tront plus dans la grammaire attribuee resultante.Avec le predicat Check assoupli et a partir de la denition de la fonction rev at, les applications successives de la transformation preliminaire et de l'evaluation symbolique du prol aboutissent aux blocs decrits a la gure 8.7. Dans les regles semantiques des blocs participant a la construction de la structure intermediaire, les sites d'applications des pas de projection sont soulignes et une etoile () marque les constructions a deforester.
L'application du pas de projection Proj est detaillee a la gure 8.8 pour la regle semantique at 2Att at
s
= AttSrev
=frev
gh
= AttHrev
=fh
gAttrev
;
Attflat `leaf:flat
=cons n leaf:l
)
(
leaf:flat
):rev
= (cons n leaf:l
):rev
(cons n cons:l
):h
= (leaf:flat
):h
(
Proj
)160 Chapitre 8. Composition symbolique rev at
t
!rev at
:
result = (t:
at):
rev (t:
at):
h = nil(t
:
l):
rev = (nil):
rev (nil):
h = (t:
l):
h
site d'application pour SE node left right !
(node
:
at):
rev = (left:
at):
rev (left:
at):
h = (node:
at):
h (left:
l):
rev = (right:
at):
rev (right:
at):
h = (left:
l):
h (right:
l):
rev = (node:
l):
rev (node:
l):
h = (right:
l):
h leaf n !(leaf
:
at):
rev = (cons n leaf:
l):
rev (cons n leaf:
l):
h = (leaf:
at):
h
site d'application pour SE
Fig. 8.9: Blocs produits par les dierentes applications de Proj
du pattern (leaf n!). Apres toutes les applications possibles de cette regle, les blocs produits sont presentes a la gure 8.9.
A ce stade de la transformation, l'evaluation symbolique peut ^etre appliquee sur les sites annotes dans la gure 8.9, ce qui permet d'obtenir la veritable deforestation par l'elimination locale, dans les regles semantiques, des constructeurs de la structure intermediaire. Dans ce cas, de nouveaux attributs sont crees par un renommage des expressions
a:b
ena b
lorsquea
2AttF et
b
2AttG. Plus precisement, les compositions reperees par les expressions (x:a
):b
sont transformees dans leur version deforestee parx:a b
. Cette derniere etape complete l'ensemble des transformations qui permettent de denir la composition symbolique:Composition symbolique = Renommage (
SE
) (Proj
)Ainsi, pour la fonction rev at qui illustre les transformations, l'application de la compo-sition symbolique permet d'obtenir la grammaire attribuee presentee a la gure 8.10. Quatre attributs ont ete crees. La liste nale est construite gr^ace aux attributs l h and at h. Une fois construite, cette liste est propagee gr^ace aux attributs at rev and at h en suivant, a l'envers, le parcours de sa construction avant d'^etre assignee a l'attribut result1. Ce parcours peut para^tre inutile et je presenterai dans le chapitre 9 une optimisation statique, appelee eli-mination des regles de copies, qui permet de se debarrasser de ce simple transport d'attribut. Neanmoins, des a present, cette grammaire attribuee obtenue par composition symbolique ne construit plus la structure (liste) intermediaire. Elle est donc deforestee.
Il est possible de voir cette grammaire attribuee comme un programme fonctionnel, corres-pondant a un evaluateur fonctionnel de la grammaire attribuee.
Les fonctions de visites, produites en sortie d'un generateur d'evaluateur tel que Fnc-2
[PDRJ95a, Le 95], correspondant a la grammaire attribuee rev at deforestee sont presentees a
1. La notationresultpeut surprendre le lecteur, mais c'est une simplication, pour cet attribut particulier, de la notationresult result, qui est normalement generee par la phase de renommage de la composition symbolique.
8.2. Projection des schemas de calculs 161
agletrev at = rev at t !
rev at
:
result = t:
at rev t:
at h = nilt
:
l rev = t:
l h node left right !node
:
at rev = left:
at rev left:
at h = node:
at h left:
l rev = right:
at rev right:
at h = left:
l h right:
l rev = node:
l rev node:
l h = right:
l h leaf n !leaf
:
at rev = leaf:
l rev leaf:
l h = cons n leaf:
at hFig.8.10: La grammaire attribuee rev at deforestee par la composition symbolique la gure 8.112. La premiere fonction, rev at appelle deux sous-fonctions, la premiere, rev at1, construisant la structure de liste resultat du parcours de l'arbre de la droite vers la gauche, et la seconde, rev at2, se contentant de propager cette liste le long de l'arbre, de la gauche vers la droite.
Une autre facon de voir cette grammaire attribuee comme un programme fonctionnel est de considerer les travaux de Johnsson [Joh87], qui permettent de generer, a partir d'une gram-maire attribuee non-circulaire, une fonction equivalente qui peut ^etre evaluee dans un langage paresseux. Le principe general de ces travaux est de considerer que pour chaque production, une fonction paresseuse peut evaluer l'ensemble des attributs synthetises du constructeur a partir de ses attributs herites. La fonction qui est produite par cette methode pour l'exemple de la grammaire attribuee deforestee rev at de la gure 8.10 est presentee a la gure 8.12, d'abord dans sa version de base, puis apres quelques simplications.
Remarques
Je viens d'illustrer la composition symbolique sur un exemple assez simple. Pour des pro-grammes plus complexes, les transformations speciees peuvent parfois ^etre interdites par le predicat Check evitant que le resultat de cette transformation soit une grammaire attribuee mal formee. Les raisons sont les suivantes, qui correspondent essentiellement aux contraintes introduites par Giegerich et Ganzinger au sujet de la composition descriptionnelle des gram-maires attribuees classiques.
Les pas de projection de la composition symbolique ne doivent ^etre eectues que sur les termes qui sont impliques dans la construction de la structure de donnees intermediaire. C'est le probleme de la determination de l'ensemble AttF, qui correspond a la separation evoquee par Ganzinger et Giegerich entre les attributs syntaxiques et semantiques. Cette remarque necessite en particulier que la construction de la structure de donnees intermediaire
2. Une presentation de la technique de generation de telles sequences de visites a partir d'une grammaire attribuee est presentee a la section 2.2.4 et illustree sur l'exemplebird.
162 Chapitre 8. Composition symbolique
letrev at t = rev at2 t (rev at1 t nil)
letrev at1 t l =caset of
node left right !
rev at1 right (rev at1 left l) leaf
n
!cons
n l
letrev at2 t l =caset of
node left right !
rev at2 left (rev at2 right l) leaf
n
!l
Fig. 8.11: Les fonctions de visites generees pour la grammaire attribuee rev at deforestee soit completement visible et accessible.
De plus, pour obtenir une grammaire attribuee resultante bien formee par la composition symbolique, chaque occurrence d'attribut doit ^etre denie une fois et une seule. Des problemes peuvent donc arriver en presence de termes non lineaires.
Les contraintes enoncees par Ganzinger and Giegerich peuvent ^etre utilisees en premiere approche pour resoudre ces problemes. Neanmoins, le contexte particulier de programmes fonctionnels correctement types, celui dans lequel se place la transformation FP-to-AG, per-met de reformuler ces problemes en termes d'analyses statiques du programme fonctionnel initial. En eet, les informations requises par le mecanisme de composition peuvent ^etre de-terminees separement, a partir d'une analyse du programme d'entree. M^eme si cette analyse reste un probleme ouvert interessant qui n'est pas etudie dans cette these, sa prise en compte independante ne remet pas en question la composition symbolique.
Le co^ut de la composition symbolique
La complexite de la composition symbolique est plus delicate a estimer que celle de la transformation FP-to-AG presentee dans le chapitre precedent. Il est cependant possible de faire quelques remarques.
Tout d'abord, il est important de noter que la generalisation de l'evaluation symbolique du prol (PSE) en l'evaluation symbolique (SE) utilisee dans la composition symbolique implique des repercussions sur la complexite qui sont de deux ordres. Premierement, elle im-plique la transformation de plusieurs regles et non plus une seule puisqu'elle doit prendre en compte les attributs herites; ce point conserve la linearite mais augmente le facteur. Deuxie-mement, elle peut ^etre utilisee comme mecanisme d'evaluation partielle. En tant que telle, la complexite du terme a evaluer partiellement est repercutee sur la complexite de la transfor-mation. En pratique, il est necessaire de limiter cette utilisation de la regle SE pour eviter que cette transformation ne boucle inniment dans le cas ou, par exemple, elle tente d'evaluer partiellement l'inversion d'une liste innie.
La complexite de la regle de projection Proj est due a la creation de nouveaux attributs et des regles semantiques qui les denissent. Essentiellement, elle est la m^eme que celle de
8.2. Projection des schemas de calculs 163 Version deduite directement d'apres la grammaire attribuee
letrev at t =
let
( at rev
;
l h) = rev atlazy t l rev at h at h = nill rev = l h
in at rev
letrev atlazy t l rev at h =caset of
node left right !
let
( at revleft
;
l hleft) = rev atlazy left l revleft at hleft( at revright
;
l hright) = rev atlazy right l revright at hrightat rev = at revleft
at hleft = at h l revleft = at revright
at hright = l hleft
l revright = l rev l h = l hright in ( at rev
;
l h) leafn
! let at rev = l rev l h = cons n at h in ( at rev;
l h)Version apres simplications
letrev at t = at rev in ( at rev
;
l h) = rev atlazy t l h nilletrev atlazy t l rev at h =caset of
node left right !
let
( at revleft
;
l hleft) = rev atlazy left at revright at h ( at revright;
l hright) = rev atlazy right l rev l hleftin(
flat revleft;l hright
) leafn
!(l rev
;
cons n at h)164 Chapitre 8. Composition symbolique la composition descriptionnelle. Pour la composition d'une grammaire attribuee possedant
n
attributs avec une grammaire attribuee en possedantm
, le nombre d'attributs crees est potentiellementn
m
, avec autant de regles semantiques. L'evaluation symbolique, qui per-met d'eliminer les constructeurs de structures intermediaires, peut alors potentiellement ^etre appliquee sur chacun des termes ainsi crees dans ces regles. On retrouve ici la necessite de borner en pratique le nombre d'applications successives de SE sur un terme genere par un pas de projection. D'une maniere generale, la composition symbolique ainsi utilisee depend de facon quadratique de la taille et de la profondeur des termes des grammaires attribuees a composer.Notons nalement que ces remarques sont indicatives et assez informelles. Il serait tout aussi interessant d'etudier ces problemes de complexite de facon plus formelle que de les comparer avec la complexite des autres techniques de deforestation des programmes fonc-tionnels presentees dans ce memoire. A ma connaissance, ce probleme n'a pas ete aborde, ou du moins publie, dans le cadre de la normalisation des folds ni dans celui de la fusion des hylomorphismes. Les resultats qui ont ete rapportes dans le cadre de la regle d'elimination
foldr/build sont relatifs a l'ecacite de son implantation dans le compilateur d'Haskell [Gil96]; j'y reviendrai brievement dans la conclusion (cf. section 10.4).