Projet de Scheme : Un compilateur d'expressions


Date de remise : le 12 Juin 1998

On considère des expressions à opérateurs binaires, dont la syntaxe peut être décrite de la manière suivante:
expression ::= IDENTIFIER | ( operator left_operand right_operand )
operator ::= + | - | * | /
left_operand ::= expression
right_operand ::= expression
Le terminal IDENTIFIER correspond à l'ensemble des symboles Scheme.

Exemples d'expressions:

X,
(X + (Y * X)),
((X / X) * (A / (B + B)))

Les expressions sont munies de leur sémantique habituelle. On peut évaluer une expression dans tout environnement où chaque identifieur figurant dans l'expression est défini. Un environnement est une liste d'associations entre des identificateurs et des nombres (voir exemples plus loin).

On dispose d'autre part d'une machine à 5 instructions et une infinité de registres R0, R1, R2, ...:
instruction ::= (ld REGISTER IDENTIFIER) | (operation target source)
operation ::= add | sub | mult | div
target ::= REGISTER
source ::= REGISTER

Les REGISTER sont des identificateurs particuliers de la forme R0, R1, R2, ... La sémantique des instructions est la suivante:

- Exécuter une instruction "ld" dans un certain environnement produit un nouvel environnement identique au précédent, sauf que REGISTER a pris la valeur de IDENTIFIER;

- Exécuter une instruction "operation" dans un certain environnement produit un nouvel environnement identique au précédent, sauf que "target" a pris la valeur obtenue en appliquant "operation" aux valeurs précédentes de "target" et "source" dans cet ordre.

Un programme machine est une liste d'instructions machines. L'exécution d'un programme machine dans un certain environnement produit normalement un nouvel environnement qui résulte de l'exécution séquentielle des instructions. Un environnement peut être représenté par une liste d'associations entre des identificateurs et des nombres.

Exemples d'environnements:
((A . 12) (B . 24) (C . 36) (R2001 . 367))
((A . 12) (B . 24) (A . 36))
Dans le second environnement, A apparaît deux fois: on ne tient compte que de la première occurrence, donc A vaut 12.

Exemple d'exécution de programme:
environnemment de départ: ((A . 12) (B . 24) (C . 36))
programme machine:
((ld R0 A)
(ld R1 B)
(add R0 R1)
(ld R1 C))
environnement résultant: ((R1 . 36) (R0 . 36) (R1 . 24) (R0 . 12) (A . 12) (B . 24) (C . 36))
On se propose d'écrire un compilateur du langage des expressions vers le langage des programmes machine. Bien entendu, ce compilateur doit respecter la sémantique des expressions en ce sens précis:

"Soit e une expression et p le programme machine correspondant. Soit s un environnement définissant toutes les identificateurs présents dans e. Soit v la valeur de e dans l'environnement s. Alors, l'exécution de p dans l'environnement s doit produire un environnement s' dans lequel R0 vaut v."

Exemple de compilation: Soit e l'expression ((A + B) * (C - D)). Programme p correspondant:
((ld R0 A) ; A
(ld R1 B) ; B
(add R0 R1) ; (A + B)
(ld R1 C) ; C
(ld R2 D) ; D
(sub R1 R2) ; (C - D)
(mult R0 R1)) ; ((A + B) * (C - D))

Travail à faire:

On écrira un évaluateur d'expressions appelé "evalexpr", un évaluateur de programmes machine appelé "evalprog", et un compilateur appelé "compile", dans un style purement fonctionnel.

Puis on réalisera une version impérative de l'évaluateur de programmes machines appelée "exec" pour laquelle l'environnement sera implicitement représenté par l'environnement global de Scheme: "ld", "add", "sub", "mult", "div" seront implantés comme des macros de Scheme; on utilisera une macro auxiliaire "mexec" (voir fichier "exec.scm").

On respectera la décomposition en modules proposée:

- expressions.scm : type de données des expressions, avec leur évaluateur;
- machine.scm : types de données des instructions et programme machine, avec leur évaluateur fonctionnel;
- compiler.scm : le compilateur;
- exec.scm : l'évaluateur impératif d'instructions ou de programmes machine;
- test.scm : un module de test;
- all.scm : chargement du tout.

On rédigera un petit rapport.

Remarque: des détails et suggestions sur les fonctions à implanter figurent dans les fichiers ".scm" ci-dessus qui sont à compléter.