• Aucun résultat trouvé

Traduction du graphe d'evaluation en code imperatif



EVALUATION EN CODEIMP 

ERATIF 103 Nous notons N

1 le nud codant T et respectivement N 2 et N

3 pour les sous-termes

append(x;y) et reverse(x).

Nous souhaitons deriver le nud N

2 avant N

3 pour eviter que la valeur de x ne soit modi ee avant son utilisation parN

2. La derivation deN

2 engendre un code fonc-tionnel: ([[ ]];hjAPPEND(x;y)ji) et celle de N

3 un code procedural: ([[REVERSE(x)]];hjxji). En generant le code Ada par un parcours de gauche a droite, le nudN

2 est appa-remment deja derive pourN

3, mais le code engendre non encore execute s'il est inclus dans la partie fonctionnelle deN

1: ([[REVERSE(x)]];hjAPPEND(APPEND(x;y);x)ji). SiTest le terme en partie droite de l'equation a deriver nous obtenons:

begin

REVERSE(x);

return APPEND(APPEND(x,y),x); end;

qui est incorrect. Nous devons faire en sorte que tout le texte derive vers une forme fonctionnelle et qui doit ^etre execute par anticipation soit evalue avant tout code pro-cedural qu'il doit preceder. La facon correcte est que le code engendre pourN

2 (partie fonctionnelle et partie procedurale) apparaisse avant le code engendre pourN

3, c'est-a-dire: begin v1:= APPEND(x,y); REVERSE(x); return APPEND(v1,x); end;

Algorithme

Nous proposons de faire un parcours de l'arbre abstrait en profondeur d'abord, de gauche a droite pour les operandes, et les nuds antecedents (calculs anticipes determines par les arcs R

<) apres les operandes, en generant le texte imperatif de chaque nud dans l'ordre de depilement inverse (de la pile de retour en arriere pour le parcours de l'arbre). Nous partons du nud racine N

1,et chaque nud traduit est annoteexecute =vrai de maniere a ce que le terme calcule par anticipation ne soit pas re-calcule lorsque sa valeur est necesaire.

La derivation #(N) se fait de la maniere suivante:

 Cas \le code du nudN a deja ete genere" (N:execute=vrai): le code en retour est ([[]];hjf 1 ;:::;f n ji) pourN:destination= (f 1 ;:::;f n).

 Cas \le code du nud N n'a pas encore ete genere" (N:execute= faux). Nous obtenons ce code ([[p]];hjfji) de la maniere suivante:

1. nous generons le code necessaire aux sauvegardes creees lors de l'application des coupures de cycles:

8i2N:sauvegardes[[p]] := [[p]] + #(N i)

104 CHAPITRE4. R 

ESOLUTION DESCONFLITSD'ACC 

ES AUX VARIABLES

avec N

i qui codeduplication(x;y), 2. pour tous ses nuds operandes N

0 (i 2 N:operandes ^ N 0 = N

i), nous generons le code correspondant:

#(N 0) = ([[p 0 1 ;:::;p 0 k]];hjf 0 1 ;:::;f 0 k ji) et ajoutons la partie procedurale a celle deja obtenue:

8i2N:operandes[[p]] := [[p]] + [[p 0 i]]) 3. pour tous ses nuds N

00 dont le calcul doit ^etre anticipe pour ^etre execute avant N (i 2 N:antecedents[N:op-dependance ^ N

00 =N

i), nous gene-rons le code correspondant:

soit #(N 00) = ([[p 00 1 ;:::;p 00 k]];hjf 00 1 ;:::;f 00 k j i), avec f 00 1 ;:::;f 00

k qui sont des va-riables, egales a la destination de N

00 (ce ne sont pas des expressions du langage concret, m^eme et surtout si N

00 est egalement un nud operande de N), et ajoutons la partie procedurale a celle deja obtenue:

8i2N:antecedents[N:op-dependance[[p]] := [[p]] + [[p 00 i]])

4. nous generons le code implementant l'application de l'operateur du nud sur ses operandes:

{ pour un constructeur ou operateur de ni:

selon la regle 3.4 page 68, avec les representations des operandes dans

hjf 0 1 ;:::;f 0 k

ji. Nous ne derivons les post-a ectations que siN:anticipe=

vrai. Nous obtenons:

([[p op]];hjf

op ji), (lorsqueN:anticipe =vrai, hjf

op

ji=N:destination, et ajoutons la par-tie procedurale a celle deja obtenue:

8i2N:antecedents[N:op- dependance[[p]] := [[p]] + [[p]]op) et hjfji=hjf

op j i,

{ pour l'operateur prede nilet:

nous avons en premier operande la variablevde nie, en second, le terme qui est a ecte a cette variable, et en troisieme le terme dont la va-leur est la vava-leur dulet, et les derivations correspondantes: ([[p

1]];hjf 1 ji), ([[p 2]];hjf 2 ji) et ([[p 3]];hjf 3 ji), avec [[p 1]] = [[ ]], hjf 1 ji =hjvji et v de sorte s v. Nous obtenons: ( [[ declare v: S(s v) begin p 2; v:=f 2; p 3; end; ]] ,hjf 3 ji )

Nous ajoutons la partie procedurale a celle deja obtenue, ethjfji=hjf 3

4.7. TRADUCTIONDUGRAPHED' 

EVALUATION EN CODEIMP 

ERATIF 105

{

pour l'operateur prede niif-then-else, avecN:operandes= (id1;id2;id3),

nous avons: #(Nid1) = ([[p1]];hjf1 j i), #(Nid2) = ([[p2;1;:::;p2;n]];hjf2;1;:::;f2;nji), #(Nid3) = ([[p3;1;:::;p3;n]];hjf3;1;:::;f3;nji), avec 8i2[1;:::;n](f2;i=f3;i). Nous obtenons: ( [[p1; if f1 then begin p2;1;:::;p2;n; end; else begin p3;1;:::;p3;n; end; endif ;]] ,hjf2;1;:::;f2;nji )

Nous ajoutons la partie procedurale a celle deja obtenue, et hjfji =

hjf2;1;:::;f2;nji, 5. N:execute:=vrai.

Apres avoir parcouru tout le graphe, nous avons donc:

 #

(x1;:::;xm)(N

1) qui donne ([[p]];hjx1;:::;xmji), avecm1, la partie fonctionnelle etant vide pour une derivation d'un operateurop: (s1;:::;sn),>(sn+1;:::;sn+m) en une procedure et en ayant decore le nud N

1 avec ses destinations calculees:

N

1:destination= (x1;:::;xn).

 #(N

1), cas de #

(x1;:::;xm) avec m = 0 qui donne ([[p]];hjfji) ou p est eventuel-lement vide, pour une derivation vers une fonction. Le corps du programme est alors \p; return f;".

Exemple 4.11:

(suite de l'exemple 4.9 page 101).

Un parcours en profondeur d'abord, les nuds ls, puis les nuds operandes, en montrant les nuds sur la pile de retour-en-arriere est:

N8: ([[p 8 ]];hjf 8 ji)=([[duplication(z;z 2 );]];hjz 2 ji) N1 N5 N6 N7 ([[p7]];hjf7ji)=([[p8; renverse(z 2 );]];hjz 2 ji) ([[p6]];hjf6ji)=([[p7; v 1 :=concat 3 (x;y;z 2 );]];hjv 1 j i) ([[p5]];hjf5ji)=([[p6; concat(v1;t);]];hjv1ji) N 4 N 6 === N 3 N 5 === ([[p3]];hjf3ji)=([[p5;

106 CHAPITRE4. R 

ESOLUTION DESCONFLITSD'ACC  ES AUX VARIABLES ([[p4]];hjf4ji)=([[p3; concat(x;z);]];hjxji) N2: ([[p 2 ]];hjf 2 ji)=([[p 4 ; v2 :=tri(t);]];hjv2ji) ([[p2; duplication(v 1 ;z); duplication(v2;t);]];hjz;x;tji)

Nous obtenons donc le texte suivant:

duplication(z;z 2); renverse(z 2); v 1:=concat 3(x;y;z 2); concat(v 1 ;t); concat(t;x); concat(x;z); v 2:=tri(t); duplication(v 1 ;z); duplication(v 2 ;t);

auquel nous devons ajouter la declaration des variables locales (variables \fra^ches" de la derivation) pour former le corps de la procedure:

procedureOP(x: inoutlistint; y: inlistint; z; t: inoutlistint)

Conclusion

Dans ce chapitre nous avons propose une methode de resolution des con its d'ac-ces aux variables qui apparaissent lorsque l'on e ectue, dans le domaine concret, une simulation des calculs necessaires a l'obtention, dans le domaine abstrait, de la valeur d'un terme T.

Nous avons d'abord presente comment localiser les con its dans le termeTa deri-ver:  entre sous-termes deT: op(t 1 ;:::;t n) etop 0(t 0 1 ;:::;t 0

n), dont les textes engendres pour simuler l'application deopetop

0sur respectivement (t 1 ;:::;t n) et (t 0 1 ;:::;t 0 n) ont des acces a une (ou des) variable(s) selon des modes di erents (lecture par rapport a ecriture ou lecture-ecriture) ;

 entre les a ectations qui sont rajoutees lorsque des resultats de calculs doivent ^etre contenus dans des variables precises (parametres formels de retour, variables identiques pour les deux branches alternatives d'unif-then-else).

4.7. TRADUCTIONDUGRAPHED' 

EVALUATION EN CODEIMP 

ERATIF 107 Chaque con it peut ^etre resolu, soit par un deplacement de code genere de maniere a imposer l'ordre dans lequel sont e ectues certains calculs, soit par une duplication de sauvegarde de la valeur de la variable con ictuelle.

Les ordres dans lesquels doivent ^etre e ectues les calculs, pour resoudre l'ensemble des con its, peuvent ^etre contradictoires et introduire des cycles. Nous avons donc propose une methode de resolution de l'ensemble des con its, qui minimise le co^ut en duplication de variables.

Nous avons ensuite montre comment obtenir un texte a la syntaxe Ada, a partir du graphe constitue de l'arbre abstrait et des ordres d'execution des calculs, auxquels nous avons ajoute un ordre de parcours de l'arbre compatible.

Le texte Ada est correct par construction: nous supposons que les implementations existantes des operateurs sont correctes, et notre algorithme est base sur la conservation d'une valeur correcte des representation des operandes.

Soit t=op(t 1

;:::;t

n) le terme a deriver, notre hypothese est que la derivation de

t 1

;:::;t

n est correcte, c'est-a-dire que nous obtenons: ([[instructions id1]];hjexpression id1 ji);:::;([[instructions idn]];hjexpression idn ji) avecfid 1 ;:::;id n

g=f1;:::;ngselon l'ordre choisi pour le parcours de l'arbre abstrait (en largeur ou en profondeur d'abord, de gauche a droite selon un ordre quelconque parmi les operandes). Chaque expression fonctionnellehjexpression

id i2[1:::n]

jiest evaluee apres l'execution de [[instructions

id1; ::: ; instructions id

i]] avec pour valeur celle de

t id

i.

L'implementation de op etant correcte par hypothese, la correction du resultat de l'application (op) sur (expression

1

;:::;expression

n) apres avoir e ectue les dupli-cations de sauvegarde, puis execute [[instructions

id

1; ::: ; instructions id

n]], est condi-tionnee par la non destruction de toute variable deexpression

id

ipar [[instructions id

i+1;

::: ; instructions

idn]]. La preuve de cette correction est triviale: toute modi cation d'une variable x de expression

id

i (qui est un parametre formel ou une variable inter-mediaire de nie par un \let") par une instruction de instructions

id

j2[i+1:::n] ne peut exister. Sinon, un ordre de precedence entre les calculs det

id

i et de t id

j existerait et imposerait la preservation dexou sa duplication.

Compilation des constructeurs

5.1 Derivation systematique

Une derivation d'un type algebrique dans le domaine concret peut ^etre faite de ma-niere systematique en derivant le type LPG en un paquetage Ada dont le nom et ceux des chiers (interfaces et corps) correspondants sont donnes par le lien d'implementa-tion (ceci est decrit dans le secd'implementa-tion 7.2 page 131).

Nous nous limitons aux speci cations algebriques parametrees au maximum d'une sorte formelle. Les sortes connues sont les sortes de la bibliotheque pour lesquelles nous avons choisi une implementation (via son lien). Ainsi, une declaration de type:

Type S requires Formal Sort[s 0 ] sorts s constructors ... end

est derivee en un paquetage dont la speci cation est:

generic type t s 0 is private ; package p S is type t s is ... ... end p S; et le lien d'implementation S(s 0 ;t s

0) est ajoute pour la derivation.

Nous derivons l'interface Ada des constructeurs et operateurs tel que cela est decrit en section 3.2.1 page 60. La derivation automatique du corps d'une fonction ou proce-dure qui implemente un operateur de ni, a partir de son axiomatisation, est detaillee au chapitre precedent. Nous pouvons deriver automatiquement les constructeurs de la sortesde la maniere suivante:

Soit une sorte sdisposant de pconstructeurs tels que:

c i2[1:::p]: (s i;1 ;:::;s i;d i),>s

110 CHAPITRE5. COMPILATIONDESCONSTRUCTEURS

avec 8i2[1:::p](di =Card(Dom(ci))) la cardinalite du domaine de ci2[1:::p].

Soit t s= S(s) et les types qui implementent les sortes des domaines des construc-teurs de s:

8i2[1:::p];j 2[1:::di]ti;j = S(si;j) Le type t speut ^etre de ni de la maniere suivante:

type constructeurde ts is (c1;:::;cp ); type t s is access block t s;

type block t s(cstr: constructeurde t s) is record case cstr is when c1 => c1 1: t1;1 . . . c1 d1 : t1;d 1 . . . when cp => cp 1: tp;1 . . . cp dp : tp;d p end case; end record;

Pour la sortesqui possedepconstructeurs, de nie par le type algebrique S, le lien d'implementation deS par le paquetage Adap Sest compose de:

S(s) =t s

8i2[1:::p]C(ci) = (E(ci);In(ci);Out(ci);Is(ci);Select(ci)) qui sont de nis par:

8i2[1:::p];n=di  8 > > > > > > > > < > > > > > > > > : E(ci) = [v1;:::;vn]fnew ts'(cstr=>ci; ci 1=>v1; ... ci n=>vn)g In(ci) =< 1;:::;n> Out(ci) =< ;:::; >

Le testeuriscdu domaine concret (Ada) permet de tester si une expression de type t(timplementant la sortesdontcest l'un des constructeurs) est la representation d'un terme algebrique construit par c:

E(isc) = [v]fv.cstr = cg; In(isc) =< 1 >;

5.1. D 

ERIVATIONSYST 

EMATIQUE 111

Pour chaque constructeur, le nombre de selecteurs dont nous avons besoin est egal a la cardinalite du domaine du constructeur. Chaque selecteur du domaine abstrait est de ni de la maniere suivante pour un constructeurc: (s

1 ;:::;s n),>s: 8i2[1:::n]; 8v 1:s 1 ; :::;8v n:s n select c i(c(v 1 ;:::;v n)) =v i

Il s'agit d'ecrire l'implementation des selecteurs qui correspondent aux constructeurs derives automatiquement: 8i2[1:::p];j 2[1:::d i] 0 B @ E(select ci j ) = [v]fv:c i jg In(select c i j ) =< 1 > Out(select c i j ) =<> 1 C A

De plus, nous avonsLeftExpr(select c

i

j ) =vrai(ce qui n'est pas utilise dans la deriva-tion de nie au chapitre predent, ou seules les variables sont des expressions-gauches).

Nous de nissons egalement pour toutes les implementations de chaque sorte, deux fonctions Ada:eqetduplication. La fonction booleenneeqdonne l'egalite entre deux valeurs, qui peuvent ^etre deux representations di erentes d'une m^eme valeur algebrique (dans le cas d'insertions d'elements dans un ensemble, par exemple, le resultat de l'exe-cution du texte Ada engendre pourins(x;ins(y;l)) peut ^etre di erent de celui obtenu pour ins(y;ins(x;l))). La fonction duplication, a partir d'une representation d'une valeur algebrique, construit une nouvelle valeur qui ne partage aucun emplacement en memoire avec la precedente.

function eq(x,y: t s) return boolean is begin

if not eq(x.cstr,y.cstr) then return false else case x.cstr is when c 1 => return eq(x.c 1 1, y.c 1 1) and . . . and eq(x.c 1 d 1 , y.c 1 d 1 ); . . . when c p => return eq(x.c p 1, y.c p 1) and . . . and eq(x.c p d p , y.c p d p ); end case;

112 CHAPITRE5. COMPILATIONDESCONSTRUCTEURS

function duplication(x : t s) return t s is begin

case x.cstr is

when c1 => return new t s'(E(c1)(duplication(x.c1 1), ...

,duplication(x.c1 d1)) ...

when cp => return new t s'(E(cp)(duplication(x.cp 1), ...

,duplication(x.cp dp)) end case ;

end eq ;

5.2 Implementation par un type existant