Les programmes Smalltalk ont une description textuelle accessible par n'importe quel éditeur de texte. Ces fichiers sont suffixés par .st. Ils comprennent indifféremment des déclarations de méthodes, de protocoles et de classes. Les conventions d'écritures (générales ou personnelles) suivantes sont inspirées de la traduction des classes formelles [ACR94].
Les différentes déclarations Smalltalk sont séparées par le point d'exclamation (!). La première chose à faire est l'écriture d'une entête de la description textuelle. Nous l'obtenons en lisant un fichier quelconque suffixé par .st.
'From Objectworks(r)\Smalltalk, Release 4 of 25 February 1991 on 17 October 1994 et\\ 1:45:18 am'!
Viennent ensuite les déclarations de structure des instances de la classe et des liens d'héritage. Pour passer de l'héritage multiple des classes formelles à l'héritage simple de Smalltalk. Une politique simple est utilisée : un chemin d'héritage principal est choisi, puis les variables d'instance et les méthodes des chemins secondaires qui ne sont pas redéfinies dans la classe elle-même sont recopiées (règle de gestion des conflits des classes formelles). Autre particularité, en smalltalk les variables d'instance héritées ne sont pas déclarées. Un petit contrôle permet de savoir lesquelles sont héritées, lesquelles sont définies, lesquelles sont redéfinies (la redéfinition correspond à un sous-typage du type de la variable d'instance). Ces informations figurent en commentaire de la classe. Les paramètres de type n'apparaissent pas explicitement dans la déclaration, du fait de l'absence de types statiques. Ils figurent aussi en commentaire.
ONLift variableSubclass: #ONFLOORLift instanceVariableNames: 'bottomLevel topLevel capacity contents isInstalled oldState ' classVariableNames: '' poolDictionaries: '' category: 'TAGLift'!
Noter que le premier nom correspond à la super-classe (unique), et que le message
variableSubclass: .. category: .. est envoyé à la classe ONLift, supposée exister.
Le second nom ne désigne 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 catégorie est le nom du TAG de départ.
Les variables ne sont pas typées, 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 méthodes d'instance sont alors écrites. Quatre protocoles par défaut existent : field selectors, constructors, observers et private. Dans la description textuelle, chaque déclaration de protocole ou de méthode se termine par un !.
Tout d'abord, les méthodes correspondant aux sélecteurs de champ, en lecture et en écriture, sont créés automatiquement selon la convention usuelle de Smalltalk. La méthode de lecture est le nom du sélecteur de champ lui-même. La méthode d'écriture est le nom du sélecteur de champ suffixée par : et suivie du paramètre. Le nom du paramètre est celui du type correspondant, précédé du caractère a ou an selon la notation habituelle. La précondition 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 méthodes primitives sont ainsi traduites :
!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 méthodes sont possibles : printString, storeOn:, ...
Les extensions sont ensuite transformées en méthodes. Lorsque le traducteur ne peut traduire complètement les axiomes d'une méthode, il demande au concepteur Smalltalk de compléter.
Le profil est calculé automatiquement. Le commentaire correspond à la méthode de la classe formelle sous une forme textuelle. Les préconditions sont implantées par des alternatives, de même que les conditions des axiomes. Le résultat est le second terme de l'équation principale si le receveur de la méthode 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 méthodes privées sont mises dans le protocole private. Les méthodes de création sont mises dans le protocole de la métaclasse selon les mêmes normes que la traduction des méthodes d'instance. Si la classe formelle comprend des valeurs par défaut pour ses sélecteurs de champ, ils sont décrits en commentaire et mis en oeuvre dans la méthode d'initialisation initialize.