M ATHÉMATIQUES ET SCIENCES HUMAINES
C. P AIR
La formalisation des langages de programmation
Mathématiques et sciences humaines, tome 34 (1971), p. 71-86
<http://www.numdam.org/item?id=MSH_1971__34__71_0>
© Centre d’analyse et de mathématiques sociales de l’EHESS, 1971, tous droits réservés.
L’accès aux archives de la revue « Mathématiques et sciences humaines » (http://
msh.revues.org/) implique l’accord avec les conditions générales d’utilisation (http://www.
numdam.org/conditions). Toute utilisation commerciale ou impression systématique est consti- tutive d’une infraction pénale. Toute copie ou impression de ce fichier doit conte- nir la présente mention de copyright.
Article numérisé dans le cadre du programme
LA FORMALISATION DES LANGAGES DE PROGRAMMATION
par C. PAIR1
Un
langage
deprogrammation
est une «langue artificielle »,
véhicule de la communication homme-machine.On aurait pu penser
qu’il
seraitplus facile
deformaliser
ceslangages
que leslangues
naturelles.Pourtant,
et c’est un
exemple
à méditer pour ceuxqui
veulent construire une théorieformalisée
deslangues naturelles,
leproblème
- pour ceslangages
deprogrammation
- reste très ardu et laformalisation
en demeure inachevée.Les
linguistes
certes n’ont ni àcopier,
ni même às’inspirer
de laformalisation
deslangages
de programma-tion,
mais certainestechniques
mises en oeuvre par leurs «homologues»
peuvent les intéresser. Et surtout, laprise
de conscience de cequi
apparente ou oppose deux domaines contribue à enrichir les deuxchamps
derecherche.
Ainsi,
les deux termes de «Syntaxe»
et de «Sémantique» qu’emploie
aussi lalogique
mathéma-tique
n’ont pas la mêmeacception
dans l’étude deslangages
deprogrammation
et enlinguistique ; cependant,
la
problématique
de délimiter unefrontière (si floue)
entreSyntaxe
etSémantique paraît
enpartie
communeaux deux domaines. On
pourrait multiplier
lesexemples
où l’on peutespérer
éclairer les rapports oudif- férences
et ainsifaire
mieuxafluer
lesdifficultés profondes
etcomplexes.
Dans cet ordred’idées,
nous nousbornons à citer : rapports
loc ute ur- éno ncé- situation, problèmes
desréférents
et desanaphores...
A. LENTIN
RÉSUMÉ
Depuis
une dizaine d’années sedéveloppent
deslangues
d’un nouveau genre, leslangages
deprogrammation.
L’article
indique
lesproblèmes
que pose leurformalisation,
tant dupoint
de vuesyntaxique
que dupoint
devue
sémantique,
et expose les solutionsqui
ont étéapportées
à cesproblèmes.
1. INTRODUCTION
Puisque
programmer c’est donner des ordres à unordinateur,
laprogrammation
demande unelangue qui
soit support de ces ordres. Lapremière
idée estd’employer
unelangue
directement «compréhensible »
par
l’ordinateur,
c’est-à-dire dont les mots, ouinstructions,
provoquent directement les actionsrequises
des circuits de
l’ordinateur ;
dans ce cas, le programmeur doit doncemployer
lalangue
del’ordinateur,
ce
qu’on appelle
lelangage-machine.
C’est ainsi queprocédaient
lespremiers
programmeurs. Mais on1. Université de Nancy 2.
s’est vite rendu compte que le
langage-machine, adapté
à latechnologie
de construction desordinateurs,
ne l’est
guère
à la transmission desalgorithmes
de calcul. Enparticulier,
ilexige
unedécomposition
très
poussée
desopérations
à effectuer. D’autre part,puisqu’il dépend
de la construction de lamachine,
il
change
avec l’ordinateur.Enfin,
il est peucompréhensible
àl’homme,
mêmeentraîné ;
onpourrait
penser que ce dernier aspect est secondaire
puisque
les programmes sont destinés à unordinateur,
maisil n’en est rien car, au cours de son
existence,
un programme doit être souventrelu, corrigé,
modifié.On a donc défini des
langues plus
aptes à servir de support à la communication desalgorithmes,
et
qu’on appelle
deslangages
deprogrammation.
Ils ne sont pas directementcompréhensibles
par l’ordinateur et un programme écrit dans un tellangage (programme source)
doit être traduit en unprogramme
exprimé
enlangage-machine (programme objet) ;
cette traduction est effectuée par l’ordi-nateur lui-même au moyen d’un programme écrit une fois pour toutes et
qu’on appelle
uncompilateur (fig. 1).
Fig. 1
Les
plus
évolués deslangages
deprogrammation
sontindépendants
de l’ordinateur. Ce sont des lan- gages totalementartificiels,
définisd’après
les besoins de laprogrammation
ou d’un certain domaine de laprogrammation (calcul scientifique, gestion,
traitement de textes,simulation...).
Il est donc
possible
d’en donner une définitioncomplètement précise
de manière que la correction d’un programme et sasignification
ne soient en rien affaired’appréciation personnelle.
Une telle défi-nition est d’ailleurs
nécessaire,
car un programmeur doit savoir très exactement cequ’il
peutécrire,
uncompilateur
doit accepter les programmes corrects etrejeter
les autres, enindiquant
sipossible
les fautesde syntaxe, et doit traduire un programme-source en un
programme-objet qui
provoque les actions demandées par le programmeur.On
aperçoit
donc la nécessité dedonner,
pour unlangage
deprogrammation,
une syntaxe et uneSémantique
totalementprécises :
la syntaxe définit l’ensemble des programmes corrects et lasémantique
les actions
qu’ils
entrainent.Il
s’agit
de savoirquels
outils utiliser pour décrire syntaxe etsémantique.
Pour Fortran[3]
premier langage
évolué apparu, tout a été décrit dans unelangue naturelle, l’anglais.
Mais unelangue
naturelle manque de la
précision
nécessaire etbeaucoup
depoints
restaient dansl’ombre,
conduisantà des
interprétations
variées. D’où l’idée de donner des définitions formelles. Cette idée a été enpartie exploitée
pour définir lasyntaxe d’Algol
60[33]
et de nombreux efforts ont été faitsdepuis
en ce sens,pour formaliser soit la syntaxe
plus complètement,
soit lasémantique.
L’intérêt de la formalisation n’est pas seulement
d’apporter
laprécision
nécessaire au program-meur et surtout au constructeur de
compilateurs,
et aussiparfois
la clarté. Une formalisation estéga-
lement
indispensable lorsqu’on
veut effectuer des démonstrations concernant des programmes écrits dans lelangage étudié,
ou concernant uncompilateur,
notamment la démonstration de là correctiond’un
compilateur.
Elle estplus
encore nécessaire pour automatiser l’écriture descompilateurs,
et laformalisation de la syntaxe a été effectivement utilisée à cet effet
[6], [22], [8]. Enfin,
elle peut constituerun
guide
pour les concepteurs delangages.
Dans la suite de cet
article,
nous examinerons successivement la définition de la syntaxe et celle de lasémantique
deslangages
deprogrammation.
Pour fournir un support à cetteétude,
lafigure
2reproduit
un programmesimple
écrit dans lelangage Algol
60.Fig. 2
L’article résume les
principales approches déjà utilisées ;
il propose aussi succinctement certaines idées de l’auteur sur lespoints
encore mal élucidés.Comme pour les
langues naturelles,
la frontière entre syntaxe etsémantique
est d’ailleurs floue.En
effet,
on est engénéral
amené à considérer que,parmi
les programmes corrects, certains sont « sanssignification»,
parexemple
parcequ’ils
ne se terminent pas ; il en est ainsi pour un programmeAlgol
60où est exécutée l’instruction
e : allera e ;
un tel programme peut d’ailleurs
posséder
unesignification
pour certainesdonnées,
cellesqui
ne provo- queront pas l’exécution de cette instruction. On peut considérer commesyntaxiques
lesrègles qui
permettent de
rejeter
des programmes avant toute exécution. Mais cecritère,
s’il fournit une idée inté- ressante, ne suffit pas à tracer une frontièreacceptable,
car parexemple,
il conduit àrejeter
le programmeet à accepter
Certains auteurs
[33]
nomment d’ailleurs « syntaxe» cequ’ils
formalisent et« sémantique»
tout lereste...
D’autres ~ 13~
ne tracent aucuneséparation
et formalisent simultanément syntaxe etsémantique.
2. FORMALISATION DE LA SYNTAXE
L’alphabet
d’unlangage
deprogrammation
est formé d’un certain nombre designes
tels que+ ( > ; ,
des
lettres,
des chiffres et éventuellement de motsprivilégiés
comme début ou si. Deplus,
selon les cas,l’espace
peut avoir ou non uneimportance,
autrement dit faire ou nonpartie
del’alphabet :
enAlgol 60,
les espaces sont sans
importance.
A l’aide des lettres et deschiffres,
on peut engénéral
former des noms,tels que max dans
l’exemple
de lafigure 2,
mais ces noms sont desimples repères (on
lesappelle
d’ailleursidentificateurs),
de sorte que la manière dont ils sont formésn’importe
pas dans laplupart
des cas. Ladéfinition d’un
langage
deprogrammation
nepossède
donc aucune composantemorphologique
et onpeut passer tout de suite à l’étude de la syntaxe.
2.1. EMPLOI DE C-GRAMMAIRES
Comme pour les
langues naturelles,
lapremière
idée estd’employer
unegrammaire
de constituants(ou C-grammaire [19])
pour décrire la syntaxe. Cette idée ne manque pas dejustifications :
lesphrases
d’un
langage
deprogrammation possèdent
une structure fortementparenthétique,
non seulementparce
qu’elles
peuvent engénéral
contenir desexpressions algébriques
comme :mais aussi parce que les instructions peuvent venir s’emboîter l’une dans
l’autre,
comme :max : = t
[il
dans :
si t
[i]
> max alors max : = t[i]
qui
est elle-mêmepartie
de l’instructionplus complexe :
pour i : = 2 pas 1
jusqua
500 faire si t[il
> max alors max : = t[i].
Cette imbrication peut en
général
êtrerécursive,
cequi
permet de construire des instructions arbitrairementlongues
etcompliquées :
ceci est unecaractéristique
deslangages
deprogrammation évolués, qui
lesdistingue
deslangages proches
de la machine pour lesrapprocher
deslangues
naturelles.D’autre part, les
C-grammaires
sont bien lesplus
intuitives pourspécifier
aux programmeurscomment constituer un programme. On écrira par
exemple :
instruction si > ~ si
expression
booléenne > alors instruction inconditionnelle >instruction conditionnelle > - instruction si >
instruction conditionnelle > - instruction si > sinon instructions >
instruction > - instruction inconditionnelle >
instruction > - instruction conditionnelle >
Les
C-grammaires
sont même ici tellement naturellesqu’il
semble bien que les auteursd’Algol
60en ont
employé
une sans se rendre comptequ’il s’agissait
d’un modèledéjà
bien connu.Cependant,
nous allons voir que lesC-grammaires
ne suffisent pas à décrire toutes lesrègles syntaxiques.
2.2. LE PROBLÈME DES ACCORDS
Si les
langues
naturellespossèdent
des genres, leslangages
deprogrammation
admettent des types d’information. Le programme de lafigure
2manipulait
desentiers,
ouplus
exactement des variablesentières,
max eti,
et aussi un tableaud’entiers,
t. On peut aussi traiter des nombresréels,
des valeurslogiques...
Lesopérations
et instructions à effectuer portent sur des valeurs de certainstypes,
et il doitexister certains accords de type. Par
exemple,
on ne peut écrire :et dans une instruction
d’affectation,
telle que :si le
premier
membre est une variable d’un certain type, le second membre doit être uneexpression
demême type ; par
exemple,
dans le programmeprécédent,
on ne doit pas écrire :Tant
qu’il
n’existequ’un
nombre fini de typesd’information,
on peut décrire ces accords à l’aide deC-grammaires,
bien que ce ne soit pas une solutionéconomique
car elle conduit àmultiplier
lesrègles
pour y introduire les diverses combinaisons
acceptables
de types.Mais,
enréalité,
l’ensemble des types d’unlangage
deprogrammation
n’est pas engénéral
fini. Parexemple,
on peut traiter non seulement des tableaux à une dimension comme dans le casprécédent,
mais aussi des tableaux dont le nombre de dimensions estquelconque ;
il estpossible
que dans lapratique
ondépasse
rarement troisdimensions,
maisc’est là une
question
deperformance
et non decompétence.
Demême,
on peut définir et utiliser des fonctions à un nombrequelconque d’arguments, qui
peuvent eux-mêmes être de typesquelconques.
Enrésumé,
on peut dire que leproblème
des accords estplus
difficilepour les langages
deprogrammation
que pour les
langues
naturelles.Pour décrire les accords
possibles,
onpeut
conserver unegrammaire
de constituants à condition d’admettre une infinité decatégories syntaxiques (on symboles
nonterminaux)
et une infinité derègles qui
seront obtenues par des schémas derègles.
Parexemple,
on écrira pour l’instruction d’afi’ectation le schéma :affectation de typ e T > 2013~ variable de type i > : ==
expression
de type T > .Il restera à décrire d’autre part l’ensemble infini des types, dont un élément peut
remplacer
les troisoccurrences de T dans le schéma
précédent
et les autres schémas de lagrammaire.
Leplus simple
est dedéfinir les types par des chaînes de caractères et
d’engendrer
leur ensemble par unegrammaire,
parexemple
par uneC-grammaire.
Lelangage
est ainsi défini par deuxgrammaires superposées.
C’est engros de cette manière que
procède [49]
pour décrire lelangage Algol 68,
bien que dans ce cas les types ne soient pas exactement définis par des chaînes de caractères[39], [36].
Il est intéressant de se demander
quelle
classe delangages
peut être décrite par deuxgrammaires superposées
du genreprécédent :
uneC-grammaire Go
et uneC-grammaire généralisée G1
admettantune infinité de
règles
données par un nombre fini de schémas où entrent dessymboles
àremplacer
parun élément d’une
catégorie syntaxique engendrée
parGo.
Laréponse [38]
est que cette classe est aussivaste que
possible ;
onpeut
décrire ainsi toutlangage
récursivementénumérable,
donc enparticulier
des
langages
indécidables. On se trouve dans une situation hélasfréquente
en théorie deslangages :
en
généralisant
une classe degrammaires
insuffisante pour décrire une classe delangages donnée,
onobtient une classe
beaucoup
troppuissante.
L’inconvénient n’est pas seulementthéorique. Rappelons
en effet que l’un des buts de la formalisation est de conduire à automatiser l’écriture de
compilateurs.
Une condition nécessaire pour cela est de
pouvoir
automatiser l’écriture de programmes de reconnais-sance, car tout
compilateur
contient nécessairement un tel programme ; cetteautomatisation,
facilepour les
C-grammaires,
est évidemmentimpossible lorsqu’il
n’existe pasd’algorithme
de reconnaissance pour toutes lesgrammaires
de la classe considérée.Parmi les autres types de
grammaires qui
ont étéenvisagés
etpermettent
de résoudre leproblème
des
accords,
citons lesgrammaires
indexées[1] :
ellesengendrent
deslangages plus généraux
que lesC-langages,
maisqui
ne sortent pas de la classe deslangages
contextuels.Cependant,
elles sontbeaucoup
moins intuitives à utiliser que les
grammaires superposées.
2.3. LE PROBLÈME DES RÉFÉRENCES
Nous avons dit
plus
haut que dans la définition d’unlangage
deprogrammation
ne se trouve aucunecomposante
morphologique,
car la forme d’un identificateur n’a aucuneconséquence. Cependant, chaque
identificateur
désigne
unobjet
d’un certain type et ce type doit être connu pourappliquer
lesrègles
d’accord : par
exemple,
pour écriremax : = t
[1]
je
dois savoir que t est un tableau à unedimension,
etqu’il
est formé d’éléments dont le type(ici entier)
est
compatible
avec celui de la variable max. Le type des divers identificateurs est engénéral précisé
par une
déclaration,
telle queentier max ou
entier tableau t
[1 : 500].
Il faut donc écrire des
règles qui précisent
que, pour toute occurrenced’identificateur,
doit existerune déclaration
précisant
son type etqui indiquent
comment retrouver cette déclaration. Ils’agit
làd’un
problème
fortanalogue
à celui de lacorrespondance
entre pronom et groupe nominal dans le casdes
langues
naturelles. Il estcependant
clair que, pour éviter lesambiguïtés,
on devra donner pour leslangages
deprogrammation
desrègles beaucoup plus
strictes que pour leslangues
naturelles. Dans lecas le
plus simple,
onimpose qu’un
identificateur utilisé dans un programme doive y fairel’objet
d’unedéclaration et d’une seule. Plus
généralement,
on peutpartager
le programme en blocsdisjoints
ouemboîtés
(fig. 3) ;
toute occurrence d’identificateur doit alorspouvoir
être associée à une déclaration de cetidentificateur, qui
se trouve dans leplus petit
bloc contenant à la fois l’occurrence considérée etune déclaration de
l’identificateur ;
pour assurer l’unicité de cettedéclaration,
leplus petit
bloc contenantune déclaration d’un identificateur et le
plus petit
bloc contenant une autre déclaration du même identi- ficateur nepeuvent
êtreidentiques.
Brièvement,
une déclaration est valide dans leplus petit
blocqui
lacontient,
à l’exclusion des blocs intérieurs où le même identificateur serait redéclaré. Dans certainslangages
existent desrègles plus complexes,
comme cellesqui
gouvernentl’emploi
des identificateurs deschamps
des structures en PL1,
ou les déclarations
d’opérateurs
enAlgol
68(où,
enplus
desidentificateurs,
lesopérateurs
peuvent êtredéclarés).
Fig. 3
Les
règles
concernant les références sont desrègles
de syntaxeglobale,
paropposition
auxrègles
de constituants
qui
sont locales. On voit par cequi précède qu’il
est facile d’écrire enlangue
naturelleces
règles
de syntaxeglobale,
cequi
suffit d’ailleurs pourapprendre
au programmeur à utiliser lelangage,
mais
qu’il
estbeaucoup
moins facile de les formaliser. Les tentatives faitesjusqu’alors
conduisent à des ormalisations fortcomplexes
et non utilisées dans lapratique.
Enparticulier,
il estthéoriquement possible
d’utiliser desgrammaires superposées, puisqu’on
peut ainsiengendrer
toutlangage
récursi-vement
énumérable ;
maisl’expérience
montrequ’on parvient
alors à une formalisation peu naturelleet d’une extrême
complication.
2.4. CONCLUSION
La solution
qui
consiste à ne formaliser que lapartie
de syntaxe pouvant l’être à l’aide deC-grammaires
a été souvent
adoptée,
avec éventuellement des variantes purement notationnelles pourindiquer
dansun second membre de
règle qu’une
composante estfacultative,
que l’ordre des composantes est arbi-traire,
etc.,[11], [20].
Cette solution est utile car elle estsimple
et permet d’automatiserl’analyse syntaxique.
Deux difficultés
l’empêchent cependant
d’êtrepleinement
satisfaisante. Leproblème
des accords peut être traité fort naturellement enemployant
desgrammaires superposées.
Pour éviterd’engendrer
des
langages
indécidables comme nous l’avonssignalé plus haut,
on peutsuggérer
de restreindre cesgrammaires
enexigeant
la conditionsuivante, qui
assure la décidabilité : l’ensemble desrègles
obtenuesà
partir
d’un schéma est telqu’il
n’existequ’un nombre , fini
derègles
de second membre donné.Le
problème
des références ne seposerait
pas si lamorphologie
des identificateurs déterminait leur type ; or les déclarations ont pour but de permettre d’associer un type àchaque
identificateur.La solution à ce
problème apparaît
donc comme étant de nature transformationnelle. Et on peut finalementsuggérer
la solution suivantequi
conduirait à une formalisationcomplète
de la syntaxe deslangages
deprogrammation.
La syntaxe serait définie en deuxparties :
a)
Deuxgrammaires superposées,
au sens duparagraphe 2.2.,
vérifiant la condition de décidabilitéindiquée
à l’alinéaprécédent,
pourengendrer
unlangage
où tout identificateur estaccompagné
de sontype
(et plus généralement
toute indication estaccompagnée
desrenseignements
nécessaires à la véri- fication desrègles d’accord) ;
b)
Unetransformation,
fonction récursive de ramification[37]
portant sur les marqueurs dephrases engendrés
par lesgrammaires superposées, qui supprime
lesrenseignements superflus
en vérifiantqu’il
existe des déclarations
adéquates.
La composante transformationnelle
pourrait
d’ailleurs être utilisée aussi à d’autres fins. Comme dans le cas deslangues naturelles,
elle peut permettre à lagrammaire générative a)
den’engendrer qu’un langage-noyau restreint,
étendu ensuite par transformations. Cetteapproche,
timidementemployée
par
[42],
a pourprincipal
mérite desimplifier
la définition de lasémantique,
si on demande aux trans-formations de conserver la
signification
d’un programme. On peut d’autre part songer aussi à vérifier lesrègles
d’accordtransformationnellement,
cequi permettrait
d’utiliser ena)
uneunique C-grammaire
comme
grammaire générative.
Cette idée[27],
intéressante car elle formalise les méthodes de reconnais-sance utilisées dans la
pratique,
a l’inconvénient de conduire à une formalisation peu naturelle etassez
complexe.
3. FORMALISATION DE LA
SÉMANTIQUE
Les travaux sont ici moins avancés
qu’en
syntaxe, de sortequ’on
devra se borner à un panorama super- ficiel. Dans lapratique,
lasémantique
est décrite enlangue naturelle,
avec un effortplus
ou moinsgrand
pouremployer
lalangue
naturelle de manièrenon-ambiguë,
en définissantsoigneusement
lestermes
employés, jusqu’à parvenir
à unlangage
presque formel :[42]
offre unremarquable exemple
d’un tel effort
(cf. [39]).
Les études faites sur la formalisation de lasémantique
n’ont étéqu’exception-
nellement
appliquées
à de véritableslangages
deprogrammation.
Il fautcependant
citer ici les travauxdu laboratoire IBM de
Vienne,
portant notamment sur PL 1[28].
Définir la
sémantique
d’unlangage
deprogrammation,
c’estindiquer
comment associer à tout programme(syntaxiquement correct)
une « valeursémantique ».
Leproblème
est donc double : définirun ensemble de valeurs
sémantiques,
définir uneapplication
de l’ensemble des programmes dans celui des valeurssémantiques.
Plutôt que de
partir
des programmeseux-mêmes,
il estplus pratique
etplus
normal departir
des marqueurs de
phrase
déterminés par la syntaxe ; on peut même transformer ces ramifications de manière à ne conserver que leursparties signifiantes.
Le passage du texte à des ramifications estparfois appelé
passage de la syntaxe concrète à la syntaxe abstraite[29], [28].
Il n’estcependant
pas utilisé par tous les auteurs, notamment par ceuxqui
se refusent à étudierséparément
syntaxe etsémantique.
3.1.
ÉQUIVALENCE
DE PROGRAMMESUne
première
idée consiste à refuser des’appesantir
sur la nature des valeurssémantiques
et à considérerque la seule chose
importante
est de savoir dansquel
cas deux programmes sontéquivalents.
Formel-lement,
on définit une relationd’équivalence
dans lelangage
et l’ensemble des valeurssémantiques
estl’ensemble-quotient.
Pratiquement,
onimposera
certaineséquivalences :
parexemple,
enAlgol 60,
si Vdésigne
unevariable
réelle,
E uneexpression arithmétique simple,
T un terme, on peutremplacer
l’instruction d’affectation :par le bloc :
début réel x, y ;
où x, y sont les identificateurs
n’ayant
pas d’occurrence dansV, E, T ;
ou encore, on peutremplacer
lasuite des deux instructions d’affectation :
par : O O
si
V, V,, V2 désignent
desvariables,
V etV2 désignant
des variables différentes.L’équivalence sémantique
sera alors laplus petite
relationd’équivalence
satisfaisant aux condi- tionsimposées.
Il est immédiat d’associer à cette définition un
système
formel dont les théorèmes sont les p N q, où p et q sont des programmeséquivalents :
les axiomes sont leséquivalences imposées ;
lesrègles
d’inférence traduisent la
symétrie
et la transitivité de la relationd’équivalence.
Parconséquent,
on peutespérer,
àpartir
de cetteapproche, parvenir
à démontrer deséquivalences
de programmes. Enparti- culier,
on peutespérer justifier
la correction d’uncompilateur
traduisant unlangage
L dans unlangage Li,
en définissant ainsi la
sémantique
d’unlangage qui
contient à la fois L etL, ; L,
peut être considérécomme un
langage-noyau
pour L.Il ne
s’agit
pas d’une définitionexplicite
de lasémantique,
mais d’une définitionaxiomatique,
où on
impose
certainespropriétés
enespérant pouvoir
en déduire toutes lespropriétés
intuitivement souhaitées. Là est ladifficulté,
car pour que lesystème
formel soitcomplet,
c’est-à-dire traduise à lui seul toute lasémantique
dulangage,
on doitimposer
un trèsgrand
nombre deconditions,
rendant ainsi la définition peu maniable. Lesexemples
donnés sur des cas trèssimples [21]
sont instructifs à cetégard.
Heureusement,
pour lesapplications,
on peut se borner à définir uneéquivalence plus faible, qui
permet de démontrer
l’équivalence
de certains programmes, mais neprétend
pas définircomplètement
la
sémantique.
Une idéeproche
a été suivie pourAlgol
60 par[34] qui
associe àchaque
programme unreprésentant canonique
dans unlangage-noyau,
définissant par là uneéquivalence.
C’estégalement
uneéquivalence plus
faiblequi
est utile au programmeur ou au constructeur decompilateurs,
pour luiindiquer
parexemple
lasignification
d’une instructioncomplexe,
comme une instructiond’itération,
en termes d’instructions
plus simples [33], [42] :
pour i : = a
tantque
b f aire Sest
équivalent
à :1 : = a ;
e : si - b alors allera
termine ; S ;
allera e ; termine :
La définition de la
sémantique
paréquivalence, malgré
l’intérêtthéorique qu’elle présente,
nesemble donc pas suffisante. On peut d’ailleurs aussi lui
reprocher, puisqu’elle
refuse de considérer la nature des valeurssémantiques,
de ne pas tenir compte du faitqu’on
traite unlangage
de programma- tion et non pasn’importe quelle langue.
3.2. STRUCTURES D’INFORMATION
Un programme fait passer de données à des résultats. La valeur
sémantique
d’un programme est doncune fonction
(calculable)
transformant les données en des résultats.Le
premier problème
est depréciser
la nature des données et des résultats. Plusieurs auteurs,après [30]
et[4 1 ],
se contentent de considérer des « vecteurs o ayant un certain nombre de composantes.Cette vue idéalise assez bien l’état de la mémoire d’un
ordinateur, qui
est formée d’un certain nombre de mots admettant chacun un contenu. Mais enréalité,
leslangages
deprogrammation
traitent desinformations
abstraites,
de structure pouvant être assezcomplexes (listes, arborescences, tableaux...), dépendant
du domaineauquel
lelangage s’applique, qui
doivent bien sûr êtrereprésentées
dans lamémoire d’un
ordinateur,
maisqu’il
estdommage
de confondre avec leurreprésentation.
L’étude de lasémantique
deslangages
deprogrammation
demande une théorie des structures d’information[14], [32],
recouvrant aussi bien les structures
logiques
ou abstraites que les structuresphysiques
lesreprésentant
dans une mémoire d’ordinateurs.
On peut proposer de définir une information comme un
couple (E, A)
formé d’un ensemble E(pouvant
contenir desnombres,
des caractères..., mais aussi des«repères » permettant
l’accès à d’autreséléments)
et d’un ensemble A de fonctions’ àzéro,
une ouplusieurs
variables deE,
à valeurs dans E(fonctions
d’accès dansl’information).
Lafigure
4 schématise une information où les flèchesreprésentent
Fig. 4
les fonctions de
A, qui
sont ici des fonctions à une variable : A == { a, s, v }. Les informations sontsujettes
à variation et on peut définir une structure d’information comme un
couple
formé d’un ensembled’informations et d’un ensemble de transformations élémentaires sur
elles ;
en composant ces transfor-mations
élémentaires,
on obtient les transformationspermises
dans la structure considérée.Le cas où l’on se limite à des informations arborescentes
[28]
permet d’unifier lareprésentation
des données et des résultats avec celle du programme.
3.3. VALEUR
SÉMANTIQUE
D’UN PROGRAMMEAprès
avoirprécisé
la nature des données et desrésultats,
la définition de lasémantique
d’unlangage
deprogrammation
peut donc consister àindiquer
une fonction «sémantique » qui
associe à tout programmeune fonction faisant passer des données aux résultats :
La fonction
sémantique
doit être effectivement calculable si l’on veutqu’elle
soit utilisable. Une variante consiste àindiquer
une fonction calculable à deux variables :1. Dans tout l’article, « fonction » veut dire « fonction partielle », c’est-à-dire non nécessairement définie dans tout son
ensemble de départ.
Pour définir des fonctions
calculables,
on peut se contenter de définitionsdirectes,
utilisantnotamment la
récurrence,
de manière à définir parexemple
des fonctions récursives sur les marqueurs dephrase, [23]
donne une méthodequi
revient à définir une fonctionimplicitement
par unsystème d’équa-
tions dont les inconnues sont liées aux noeuds du marqueur de
phrase.
Mais ces définitions directes sont souvent considérées comme insuffisamment formelles et on est amené à lespréciser
en utilisant l’un ou l’autre des outils suivants :a)
Les machinesabstraites,
du genre de la machine deTuring,
mais en réalité onemploie
des machinesplus
élaborées que les machines deTuring [15], [28] ;
lesdescriptions d’algorithmes
par une suite derègles
comme lesalgorithmes
deMarkov [31],
ou par unorganigramme [17], [35], [4]
peuvent être considérées comme des variantes de ce type.b)
Le X-calcul de Church[10] (et plus généralement
lalogique
combinatoire[12], [40]).
c)
Dessystèmes formels, qui,
contrairement aux outilsprécédents,
conduisent à des définitions nonexplicites ;
ils donnent deuxpossibilités
essentielles pour définir une fonction f à k variables :- définir
f axiomatiquement
en lui associant unsystème
formel dont les théorèmes sont les- utiliser un
système
formel connu et associer à f une forme F(xi,
..., Xk,y)
telle que F(a,,
..., ak,b)
soit un théorème
si,
et seulementsi,
b =f (al,
...,ak) [16] ;
parexemple,
la fonction valeur absoluepeut
être définie parl’expression
booléenne :La
représentation
de la valeursémantique
d’un programme par unex-expression
ougrâce
à unsystème
formel est moins riche que sareprésentation
par une machineabstraite,
car elle ne donnequ’une
vueglobale
de la transformation des données en lesrésultats,
alorsqu’une
machine abstraite marque lesétapes
de la transformation. Enparticulier,
une machine abstraitepeut
fort bienreprésenter
un programme ne se terminant pas, ou ne se terminant que pour certaines
données,
deux tels programmesne suivant pas les mêmes
étapes
étantreprésentés
par des machines différentes.Or,
ilpeut
être inté-ressant d’étudier des programmes ne se terminant pas, par
exemple
dans le cas deslangages
desimulation.
En
revanche,
lareprésentation
à l’aide d’unsystème formel,
si elleprésente
l’inconvénient de n’être pasexplicite,
semble cellequi
permet leplus
facilement de faire des démonstrations concernant lelangage,
bienqu’on puisse espérer,
en construisant une théorie de certainstypes
de machinesabstraites,
obtenir des résultats assezpuissants
pour effectuer des démonstrationscommodes [15].
En combinant les deux sortes de fonctions
sémantiques
et les divers outils dedéfinition,
onobtient un
grand
nombre de manières de décrire lasémantique,
dontbeaucoup
ont étéproposées
ouutilisées.
[25]
fait usage du X-calcul etemploie
une fonction dupremier
type transformant un programmeen une
a-expression (voir
aussi[5]).
Représenter
une fonction du second type par une machineabstraite,
c’est définir un inter-préteur ; [28] procède
de cettemanière,
ainsi que[7] et ~ 13J qui emploient
des outilsproches
desalgo-
rithmes de Markov.
Représenter
une fonction dupremier
type par une machine abstraitequi
transforme un pro- gramme en une autre machine abstraite transformant les données en lesrésultats, c’est employer
uneapproche analogue
à ladescription
d’uncompilateur.
On aparfois proposé
de définir lasémantique
d’unlangage
en en donnant effectivement uncompilateur [10] ;
mais il ne saurait êtrequestion
de traduire lelangage
donné dans lelangage
d’une machineparticulière,
faute de manquerd’universalité ;
des tenta-tives sans lendemain ont été faites pour définir un
langage
machineuniversel, UNCOL ; plus récemment,
elles ont été
reprises
et ont donné naissance à L M U[35].
Ce genre de définition de lasémantique, peut-être
utile pour le constructeur decompilateurs, risque
d’êtrerebutant,
car très orienté vers lamachine.
Ici,
comme auparagraphe
3.2. concernant lareprésentation
des données et desrésultats,
ontouche d’ailleurs un
point important qui
divise les informaticiens(voir [2]) : l’informatique
est-elled’abord la science des
ordinateurs, auquel
cas il faut tout ramener à lamachine,
ou est-elle celle desalgorithmes
de traitement del’information, qui
existentindépendamment
des ordinateurs ?3.4. TENTATIVE DE SYNTHÈSE
Nous avons vu que la définition de la
sémantique
paréquivalence présente
des aspectsintéressants,
mais devient fort
compliquée lorsqu’elle prétend
tout traiter à elle seule. Plusprécisément,
elle seprête
bien à ramener unlangage
à unlangage
noyau en brisant les constructionscomplexes,
maisbeaucoup
moins à étudier les constructions élémentaires. Les définitions utilisant le À-calcul et surtoutune machine abstraite se
prêtent
mal aux démonstrations et sont aussi assezcompliquées,
mais pour une raisonopposée,
car ellespeinent
à traiter les constructionscomplexes.
Le traitement des sauts(aller à)
est
également
source decomplication,
notamment avec leX-calcul,
car ils’agit
d’une notiondynamique,
essentielle en
programmation,
maisqui
se laisse malapprocher
par les outilsmathématiques, plus
propres à décrire des situationsstatiques.
On peut donc songer à combiner les deux
approches.
Il est un peu ennuyeuxd’employer
si-multanément des outils
différents ;
maisl’emploi
d’unsystème formel, déjà
rencontré avec ladéfinitions par
équivalence,
semble permettre degarder
ununique outil,
en traitant par des axiomes etrègles
d’inférence de types divers aussi bien la transformation des constructionscomplexes
en construc-tions élémentaires que l’étude des constructions élémentaires elles-mêmes. Elle permet aussi d’éviter
une définition
explicite qui
est difficile à obtenir et à maîtriser dans le cas deslangages complexes,
commele sont les véritables
langages
deprogrammation.
Nous proposons donc un
système formel,
dont les formules sont destriplets : (pg, do, res)
où :- pg
représente
une ramification appartenant à l’ensemble des marqueurs dephrase
dulangage
étudié(ou
d’unlangage plus
vaste, cequi
est souvent trèscommode),
- do et res
représentent
desinformations,
au sens définiprécédemment,
d’une certaine structurequi dépend
essentiellement du domained’application
dulangage.
Les théorèmes
(pg, do, res) indiquent
que le programme de marqueur dephrase
pg,appliqué
àla donnée
do,
fournit(ou
peutfournir)
le résultat res.Les axiomes
(pg, do,
t(do)),
où t est une transformationpermise
par la structureconsidérée,
ne portent que sur des pg trèssimples :
ils formalisent donc lasémantique
des constructions élémentaires.Les