• Aucun résultat trouvé

Traduction directe d'une classe formelle

Evaluation de la conformite TAG/CF

7.8 Implantation des classes formelles

7.8.2 Traduction directe d'une classe formelle

Le principe de la traduction directe est de produire une classe concrete dans un langage donne qui soit une representation operationnelle de celle-ci. Si le langage cible est type dy- namiquement il sut de ne pas tenir compte des informations de typage ou de les mettre en commentaire. Ce type de traduction est directe dans le sens ou il y a un isomorphisme entre les structures abstraites et les structures concretes. La demarche de traduction que nous proposons est la suivante:

1. Pour chaque classe formelle de nir une classe concrete.

2. La structure de la classe concrete est un ensemble de champs variables d'instance, slots ou attributs (suivant le langage) prives correspondant aux selecteurs de champ.

3. De nir les methodes primitives non prevues par le langage concret, ceci est facile a partir de la structure et concerne les methodes:new, copy, =, describe.

4. Pour chaque selecteur une methode de lecture (publique) est de nie avec une eventuelle pre-condition.

5. Pour chaque methode secondaire (extension) implanter une methode concrete. Dans nos exemples nous avons une speci cation quasi-operationnelle ce qui rend la traduction im- mediate. Ce n'est pas toujours le cas.

6. Si il existe une contrainte elle intervient comme un predicat de de nition du type. Il sut d'en faire une preconditions du generateur new.

7. Suivant le langage des declarations d'attributs exportables (prive, public, ...) sont a faire. Dans une classe formelle les methodes primitives et secondaires sont exportables (excep- tion faite de certaines methodes auxilliaires).

8. L'acces a l'objet receveur et plus generalement le mode de selection sont importants. Dans le modele a classes formelles nous avons implicitement une selection simple donc une traduction en CLOS doit ^etre faite avec attention si il y a plusieurs arguments qui sont des objets. Dans les autres cas l'acces a l'objet receveur est important syntaxiquement et assez variable (current, self, me...).

Illustrons cette methode en traduisant la classe formelleONFLOORLiften Ei el et en Small-

talk. Cette classe formelle et ses traductions sont detaillees en annexe C.6 .

7.8.3 Ei el

Ei el propose un cadre de programmation rigoureux, ou les classes sont des implantations de types abstraits de donnees. Une presentation detaillee du langage se trouve dans [Mey88].

A chaque classe formelle est associee une classe Ei el ecrite dans le chier <CFC>.e. Si

la classe formelle est abstraite, la classe Ei el est DEFERRED. Il en est de m^eme pour les methodes. Si la classe est generique, la notation crochetclass[T]est utilisee. Les commentaires

sont ceux de la classe formelle.

-- Class for onfloor lift

-- straight translation without optimization -- EIFFEL 2.3

-- 06/06/94 CLASS ONFLOORLift

La seconde t^ache est d'ecrire la clause d'exportationEXPORT. Elle contient les methodes pri-

mitives et les caracteristiques exportees de la classe formelle. Chaque classe est libre d'exporter ou non les caracteristiques de la super-classe. La regle suivante est la m^eme que dans les classes formelles: toute caracteristique exportee dans une super-classe est exportee dans la sous-classe. La routine speciale Createest implicitement exportee et ne gure pas dans la liste.

EXPORT weight, bottomLevel, topLevel, capacity, chgCapacity, limits, isIn, oldstate, up, down, getIn, getOut, install, isOverloaded;

Ensuite la clause d'heritage INHERIT est construite. Le nom de chaque super-classe est

indique et les methodes qui sont rede nies ou renommees par les clauses RENAMEet REDEFINE.

Les renommages sont utilisees pour resoudre les con its de noms. Le calcul est realise par comparaison du comportement de la super-classe avec celui de la classe formelle en cours de traduction. Comme dans les classes formelles, la methode d'instanciation Createn'est jamais

heritee.

INHERIT ONLift

REDEFINE weight, bottomLevel, topLevel, capacity, chgCapacity, isIn

En n, la partie la plus delicate est la de nition des caracteristiques de la clauseFEATURE. Des

attributs Ei el prives sont de nis pour chaque nouveau selecteur de champ et chaque selecteur de champ specialise. Chaque selecteur de champ devient une routine a n de pouvoir inclure la precondition du selecteur de champ par la clause REQUIRE. Ce travail peut ^etre ane en ne

-- private fields bottomLevel_private : Integer; topLevel_private : Integer; capacity_private : Real; contents_private : ListWeightable; isInstalled_private := Boolean; oldState_private : INTERMEDIATELift; -- field selectors bottomLevel : Integer IS DO RESULT := bottomLevel_private; END; -- bottomLevel oldState : INTERMEDIATELift IS REQUIRES not(isInstalled); DO RESULT := oldState_private; END; -- oldState

Viennent ensuite les methodes primitives. La routine de creation standard Createest la

traduction de la primitive de creationnew<CFC>. Les parametres sont les attributs de la classe

(herites, de nis ou rede nis). L'operationnew<CFC>est un appel fonctionnel aCreate.

-- creation

Create (Xbottom, Xtop : Integer; Xcap : Real; Xcontents : List; Xinst : Boolean; Xold : INTERMEDIATELift) IS

-- constraint translation

REQUIRES Xbottom < Xtop and 0 <= contents.sum_weight and Xbottom <= Xlevel and ((Xinst and Xbottom <= Xtop)

or (not(Xinst) and Xold.oldState.level + oldState.offset <= Xtp)) DO bottomLevel_private := Xbottom; topLevel_private := Xtop; capacity_private := Xcap; contents_private := Xcontents; isInstalled_private := Xinst; oldState_private := Xold; END; -- Create

La contrainte est traduite par une precondition REQUIRE sur new<CFC> ou mieux par un

invariant (INVARIANT) de classe. La methode primitiveequal?est implantee pardeep equal

etcopyest implantee pardeep clone.

A chaque extension est associee une routine Ei el dont le pro l est celui de l'extension hormis le receveur. La traduction des axiomes doit respecter la notation pointee d'Ei el:

<selector>(<receiver><,args>*)devient <receiver>.<selector>(<,args>+)0=1. La pre-

condition est donnee dans une clauseREQUIRE. Les conditions des axiomes sont de nies par les

structures de contr^ole conditionnellesIF...THEN...ELSIF...END. Le resultat de la methode

est a ecte a la pseudo-variableRESULT. La variableSelfs'ecritCurrenten Ei el et un message

de type m(Self, args)s'ecritm(args).

-- overload

isOverloaded : Boolean IS DO

RESULT := weight > capacity; END; -- isOverloaded

-- level

level : Integer IS

REQUIRES not(isOverloaded); DO

IF isInstalled

THEN RESULT := bottomlevel;

ELSE RESULT := oldState.level + oldState.offset; END;

END; -- level -- set a new capacity

chgCapacity (Xcap : Real) : ONFLOORLift IS DO

-- copy is translated in creation IF isInstalled

THEN RESULT.Create(bottomLevel, topLevel, Xcap, contents, isInstalled, undefined);

ELSE RESULT.Create(bottomLevel, topLevel, Xcap, contents, isInstalled, oldState.chgCapacity(Xcap));

END;

END; -- chgCapacity -- get up Xd levels

up (Xd : Integer) : INTERMEDIATELift IS

REQUIRES Xd <= (toplevel - level) AND not(isOverloaded); DO

RESULT.Create(current, Xd, false); END; -- up

Les methodes de classes sont maintenant de nies comme des methodes d'instance en Ei el.

-- it's a instance method in Eiffel, create a new lift

install (Xbottom, Xtop : Integer; Xcap : Real) : ONFLOORLift IS LOCAL undefined;

DO

-- it is an undefined value for oldState of Lift undefined.Create;

RESULT.Create(bottomLevel, topLevel, capacity, empty, true, undefined); END; -- install

Le typage fort d'Ei el est respecte dans la mesure ou celui des classes formelles suit des regles similaires, hormis l'associattion de type like.

7.8.4 Smalltalk

Smalltalk-80 [LP90] est a la fois un langage, un systeme d'exploitation et un environnement de programmation.La richesse de la bibliotheque de classes prede nies et sa facilite d'utilisation en font un outil ideal pour le prototypage d'applications. A la di erence d'Ei el, toutes les classes sont accessibles directement dans l'environnement de travail. L'interface avec des chiers se fait par la commandefileInappliquee a des descriptions textuelles Smalltalk ( chier avec

le suxe .st). Il est conseille de rentrer les classes dans l'ordre super-classe ?!sous-classe

pour eviter les liens inde nis. Cette commande execute aussi les methodes d'initialisation de classe.

Toujours a la di erence d'Ei el, les noms de variables et de methodes ne contiennent pas le caractere souligne, qui dans une version precedente de Smalltalk, designait le destinaire du resultat d'une methode (sorte d'a ectation). Ils sont remplaces par des majuscules (manipula- tion de chaines de caracteres). Certains noms ne doivent pas ^etre interpretes, ils sont designes par des symboles, ils sont pre xes par#.

Les di erentes declarations Smalltalk sont separees par le point d'exclamation (!). La pre-

miere chose a faire est l'ecriture d'une ent^ete de la description textuelle. Nous l'obtenons en lisant un chier quelconque suxe par.st.

'From Objectworks(r)\Smalltalk, Release 4 of 25 February 1991 on 17 October 1994 et\\ 1:45:18 am'!

Viennent ensuite les declarations de structure des instances de la classe et des liens d'heri- tage. Pour passer de l'heritage multiple des classes formelles a l'heritage simple de Smalltalk. Une politique simple est utilisee: un chemin d'heritage principal est choisi, puis les variables d'instance et les methodes des chemins secondaires qui ne sont pas rede nies dans la classe elle- m^eme sont recopiees (regle de gestion des con its des classes formelles). Autre particularite, en smalltalk les variables d'instance heritees ne sont pas declarees. Un petit contr^ole permet de savoir lesquelles sont heritees, lesquelles sont de nies, lesquelles sont rede nies (la rede ni- tion correspond a un sous-typage du type de la variable d'instance). Ces informations gurent en commentaire de la classe. Les parametres de type n'apparaissent pas explicitement dans la declaration, du fait de l'absence de types statiques. Ils gurent aussi en commentaire.

ONLift variableSubclass: #ONFLOORLift

instanceVariableNames: 'bottomLevel topLevel capacity contents isInstalled oldState ' classVariableNames: ''

poolDictionaries: '' category: 'TAGLift'!

Noter que le premier nom correspond a la super-classe (unique), et que le message

variableSubclass: .. category: .. est envoye a la classe ONLift, supposee exister. Le

second nom ne designe pas la classe mais uniquement son nom (c'est un symbole Smalltalk). Il n'y a pas de variables de classes ou de pool dans la traduction directe. La categorie est le nom du TAG de depart. Les variables ne sont pas typees, pour ne pas perdre cette information, on la place en commentaire comme la contrainte ou la liste d'exportation.

ONFLOORLift comment: '@Copyright P. Andre 1994

This class implements the ONFLOORLift class. Here is the CF description :

bottomLevel <Integer> topLevel <Integer> capacity <RealGt1> contents <ListWeightable> isInstalled <Boolean>

oldState <INTERMEDIATELift> requires: isInstalled(Self) == false comment : class for onfloor lift

exports : limits, weight, level, getIn, getOut, isIn, up, down, install constraints :

bottomLevel(Self) < topLevel(Self) and 0 <= weight(Self) and

bottomLevel(Self) <= level(Self) <= topLevel(Self)'!

Les methodes d'instance sont alors ecrites. Quatre protocoles par defaut existent : field selectors, constructors,observerset private. Dans la description textuelle, chaque de-

claration de protocole ou de methode se termine par un!.

Tout d'abord, les methodes correspondant aux selecteurs de champ, en lecture et en ecriture, sont crees automatiquement selon la convention usuelle de Smalltalk. La methode de lecture

est le nom du selecteur de champ lui-m^eme. La methode d'ecriture est le nom du selecteur de champ suxee par:et suivie du parametre. Le nom du parametre est celui du type correspon-

dant, precede du caractere a ouan selon la notation habituelle. La precondition est traduite

automatiquement, lorsqu'elle est simple comme ici, par une alternative.

!ONFLOORLift methodsFor: 'field selectors'! oldState

"requires: isInstalled(Self) == false" self.isInstalled

ifTrue: [^nil] ifFalse: [^oldState]! oldState: anINTERMEDIATELift

oldState := anINTERMEDIATELift!...!

Les autres methodes primitives sont ainsi traduites:

{ equal: l'egalite porte sur le contenu des objets (=) et non leur identite.

{ describe: protocole printing, methodeprintOn:. Soit la methode de description tex-

tuelle par defaut est utilisee, soit elle est rede nie.

!FCObject methodsFor: 'printing'! describe

"Textual representation of the object in a String" |aStream |

aStream := WriteStream on: (String new: 16). self printOn: aStream.

^aStream contents! !

d'autres methodes sont possibles :printString,storeOn:, ...

{ copy: implante par les methodes de copie simplecopy(copie de pointeur par defaut), en

profondeurdeepCopy, de pointeurshallowCopy.

{ d'autres sont propres a Smalltalk (isNil, release, ==, inspect, class, isKindOf:, respondsTo:,perform:,error,doesNotUnderstand,shouldNotImplement,

subclassResponsability).

Les extensions sont ensuite transformees en methodes. Lorsque le traducteur ne peut tra- duire completement les axiomes d'une methode, il demande au concepteur Smalltalk de com- pleter.

Le pro l est calcule automatiquement. Le commentaire correspond a la methode de la classe formelle sous une forme textuelle. Les preconditions sont implantees par des alternatives, de m^eme que les conditions des axiomes. Le resultat est le second terme de l'equation principale si le receveur de la methode du premier terme est Self.

!ONLift methodsFor: 'constructors'! getOOO

";; getOOO : the lift becomes out of order getOOO : ONLift --> OOOLift

getOOO(Self) == new(OOOLift, oldState = Self)" ^OOOLift newXoldState: self! !

...

!Lift methodsFor: 'observers'! bottomLevel

";; bottomLevel : bottom level of the lift bottomLevel : Lift --> Integer

ABSTRACT"

self subclassResponsability!...!

Les methodes privees sont mises dans le protocoleprivate. Les methodes de creation sont

mises dans le protocole de la metaclasse selon les m^emes normes que la traduction des methodes d'instance. Si la classe formelle comprend des valeurs par defaut pour ses selecteurs de champ, ils sont decrits en commentaire et mis en oeuvre dans la methode d'initialisationinitialize.

Il n'y a pas de distinction entre classe abstraite et classe instanciable en Smalltalk. Cette distinction est forcee en rede nissant la methodenew. Nous ne ferons qu'indiquer la di erence

en commentaire. Les methodes abstraites sont implantees parself subclassResponsability.

Le masquage est possible en Smalltalk parself shouldNotImplement.

Plusieurs methodes d'instanciation sont possibles, faisant appel a la methode de creation par defautnew. Pour simpli er la presentation, nous pouvons de nir une classe CFObjectqui

synthetise le comportement minimal d'un objet issu d'une classe formelle et dont heriteront toutes les classes produites par le traducteur.

7.9 Conclusion

Dans cette section, nous avons donne des elements d'une demarche de conception. Nous avons decrit plus precisement le passage des TAG aux classes formelles et celui des classes for- melles aux classes des langages de programmation.

Pour la conception des TAG en classes, nous proposons une solution en plusieurs etapes realisant des t^aches independantes, dont l'inter^et est d'^etre applicables a d'autres situations. L'automatisation n'est que partielle et le concepteur doit intervenir pour choisir entre plusieurs alternatives et doit proposer des idees de restructuration.

Le passage des classes formelles aux classes des langages de programmation est plus direct. Si les axiomes respectent une presentation fonctionnelle alors la traduction est entierement au- tomatisable. Il n'en reste pas moins que le programme n'est pas ecace et n'utilise pas au mieux les speci cites du langage cible. Le programmeur devra intervenir ensuite pour ameliorer cette situation. Cette section demontre toutefois des avantages certains du modele: reutilisabilite entre langages de programmation, retro-conception de classes, portabilite d'applications entre langages et entre versions successives d'un m^eme langage.

Des experimentations plus poussees sont indispensables pour documenter le processus et fournir des conseils plus precis au concepteur. D'autres traductions sont envisagees, notamment celle vers un systeme a automates communicants pour concevoir des architectures distribuees.