Un interprète Pseudo-Pascal |
Ce TD se présente comme le précédent: l’exercice consiste à écrire un morceau manquant pour un programme par ailleurs déjà complet. Cette fois, le programme en question est le petit compilateur de Pseudo-Pascal vers l’assembleur MIPS, et le morceau manquant est l’interprète de Pseudo-Pascal.
On souligne bien le fait qu’un compilateur ne contient habituellement pas d’interprète du langage source, car cela n’est pas utile. Le petit compilateur est un peu particulier: il contient un interprète pour chacun des langages intermédiaires qu’il utilise. Cela permet d’interpréter le programme obtenu à n’importe quel point de la chaîne de compilation, et de vérifier qu’il se comporte de façon identique au programme source. C’est donc un outil de debugging relativement utile.
Il faut télécharger puis dépaqueter l’archive td2.tar.gz:
# tar xvfz td2.tar.gz # cd td2 # make ... ocamlopt.opt -o compilo ...
Cependant, l’interprète ainsi produit ne fonctionne pas :
# ./compilo -ipp test/a.p Fatal error: exception Failure("UNIMPLEMENTED")
Vous noterez l’utilisation de l’option -ipp pour appeler l’interprète du langage Pseudo-Pascal.
Le fichier interpretPP.ml contient un interprète extrêmement incomplet qui ne traite que très peu de formes d’expressions et d’instructions.
Vous pouvez vérifier qu’il fonctionne pour le programme ultra minimal trivial.p:
On obtient:
# ./compilo -ipp test/trivial.p 10
L’implémentation interpretPP.ml doit être conforme à l’interface interpretPP.mli.
Elle doit donc fournir une fonction interpret qui, étant donnée une valeur de type PP.program, c’est-à-dire un arbre de syntaxe abstraite représentant un programme, l’exécute. Cette fonction ne renverra aucun résultat, mais son exécution pourra avoir des effets de bord: par exemple, elle pourra afficher une chaîne de caractères sur la sortie standard si le programme Pseudo-Pascal fourni contient une instruction writeln. C’était le cas de trivial.p ci-dessus.
On tiendra compte du fait que le programme Pseudo-Pascal fourni est supposé bien
typé. Certaines erreurs seront donc impossibles: par exemple, l’opération
d’addition sera toujours appliquée à deux arguments entiers. Cependant, toutes
les erreurs ne sont pas éliminées par le typage: par exemple, déréférencer un
pointeur nul, ou bien accéder à un tableau en dehors de ses bornes, reste
possible. On veillera à distinguer les erreurs qui ne doivent pas se produire
(que l’on signalera par assert false
) de celles qui peuvent se produire
(que l’on signalera en levant l’exception RuntimeError
).
Pour compléter le fichier interpretPP.ml, on s’appuiera sur la syntaxe abstraite du langage Pseudo-Pascal, définie formellement dans PP.mli, et sur la description de la sémantique formelle donnée dans le cours.
On suggère la démarche suivante:
EGetVar
, EFunCall
, EArrayGet
,
EArrayAlloc
. Pour cela, on étend la fonction
interpret_expression pour prendre en compte les cas EUnOp
,
EBinOp
et EConst
. On prendra garde à écrire ce code de façon
aussi compacte et élégante que possible.On peut alors essayer cet interprète minimal en lui proposant un programme très simple, par exemple trivial2.p :
On obtient:
# ./compilo -ipp test/trivial2.p 10
Définir une fonction lookup qui recherche une variable (désignée par son nom) successivement dans ces deux environnements, et qui renvoie non pas le contenu de la variable mais son adresse.
EGetVar
à interpret_expression et le
cas ISetVar
à interpret_instruction. On utilisera bien sûr la fonction
lookup.À présent, on peut tester un exemple simple qui n’utilise que des variables globales, par exemple trivial3.p :
On obtient encore:
# ./compilo -ipp test/trivial3.p 10
Vous pouvez à tout moment lancer une procédure de test complète à l’aide de la commande make test. L’interprète est alors lancé sur une série de programmes (fact.p, …) pour une série d’entrées fixées (fact.in, …). Le résultat obtenu sur la sortie standard est stocké dans un fichier (fact.ipp, …) qui est confronté au résultat attendu (fact.ispim, …). L’ensemble des fichiers utiles aux tests se trouve dans le sous-répertoire test.
Ce document a été traduit de LATEX par HEVEA