代写 C ocaml compiler Projet de Compilation Avanc ́ee

Projet de Compilation Avanc ́ee
Mini-ZAM : Interpr`ete de bytecode fonctionnel
28 f ́evrier 2019
Pr ́esentation du sujet
Contexte : La machine virtuelle du langage OCaml, nomm ́ee ZAM (ZINC Abstract Machine) est une machine a` pile qui peut ˆetre vue, dans son noyau fonctionnel, comme une machine de Krivine avec une strat ́egie d’ ́evaluation par appel par valeur (call-by-value). Pour ex ́ecuter tout programme OCaml, la ZAM interpr`ete du bytecode OCaml repr ́esent ́e par 149 instructions diff ́erentes1. Chaque instruction bytecode modifie l’ ́etat interne de la machine virtuelle, et l’ ́evolution de cet ́etat repr ́esente l’ex ́ecution du programme OCaml associ ́e.
Une grande partie des instructions de la ZAM correspond a` des instructions qui ne sont que des versions sp ́ecialis ́ees d’autres instructions (par exemple, l’instruction d’application d’une fonction avec 1 argument APPLY1, est une version sp ́ecialis ́ee de l’application n-aire APPLY n), ou bien le regroupe- ment en une instruction de plusieurs instructions distinctes (par exemple, l’instruction PUSHACC n est s ́emantiquement ́equivalente a` l’instruction PUSH suivie de ACC n). D’autres part, un certain nombre d’instructions de la ZAM sert traiter les aspects imp ́eratifs ou orient ́es objet du langage, ainsi que plusieurs traits de haut niveau, comme la gestion des exceptions ou le filtrage par motif.
Il est alors possible, en ne s’int ́eressant qu’au noyau fonctionnel du langage, et en supprimant les instructions sp ́ecialis ́ees, de r ́ealiser une version simplifi ́ee de la ZAM qui n ́ecessite moins de 20 instructions bytecode diff ́erentes.
Objectif : Ce projet consiste en la r ́ealisation (dans le langage de programmation de votre choix) d’un interpr`ete de bytecode pour un langage ML restreint `a un tel noyau fonctionnel simple. L’interpr`ete cr ́e ́e permettra l’ex ́ecution de programmes fonctionnels qui r ́ealisent des op ́erations simples (calculs arithm ́etiques et logiques, branchements,…), ainsi que l’application de fonctions `a plusieurs arguments (potentiellement r ́ecursives 2).
Nous ́etendrons ensuite l’interpr`ete de la machine virtuelle afin de g ́erer certaines optimisations et aspects suppl ́ementaires du langage OCaml (comme la gestion des exceptions et l’usage de structures de donn ́ees r ́ecusrives potentiellement mutables).
La traduction du code ML source vers le bytecode associ ́e ne sera pas abord ́ee : nous vous fournissons directement des fichiers contenant les instructions bytecode a` interpr ́eter, ainsi que les fichiers .ml qui leur sont associ ́es.
Ces fichiers sont accessibles `a l’adresse https://www-apr.lip6.fr/~varoumas/
Rendu : Vous devrez rendre, avant le 25/03/2019 `a 23h59 (UTC+1), une archive au format .tar.gz contenant le code de votre impl ́ementation de l’interpr`ete Mini-ZAM (avec un Makefile et un fichier README pr ́ecisant, si besoin, quelles sont les d ́ependances logicielles du programme), ainsi qu’un rapport (en franc ̧ais). Ce rapport (maximum 10 pages) devra d ́ecrire la structure g ́en ́erale du projet, vos choix d’impl ́ementation (en particulier la repr ́esentation des valeurs fonctionnelles), et de nouveaux jeux d’essai. Le rendu du projet se fera par courrier ́electronique, aux adresses steven.varoumas@lip6.fr et emmanuel.chailloux@lip6.fr.
1. dans la version actuelle d’OCaml – la 4.07
2. cependant, nous ne traiterons pas dans ce sujet le cas des fonctions mutuellement r ́ecursives
1

Le sujet du mail aura la forme suivante :
[4I504] Rendu Projet –
(en rempla ̧cant par les noms des membres de votre binˆome) Tout d ́epassement de la date limite entraˆınera des p ́enalit ́es.
1 Description de la machine virtuelle
Valeurs : La machine virtuelle que vous r ́ealiserez manipulera des valeurs d’un type que nous nom- merons dans ce sujet mlvalue. Au d ́epart, ces valeurs correspondront `a deux cat ́egories de valeurs distinctes :
1. Des entiers, qui repr ́esenteront toutes les valeurs imm ́ediates manipul ́ees par le programme (on repr ́esentera par cons ́equent true par l’entier 1, false par 0, et () par 0, tandis qu’une valeur enti`ere quelconque sera repr ́esent ́ee tel quel).
2. Des fermetures, qui sont des couples (pointeur de code, environnement) qui repr ́esentent les valeurs fonctionnelles manipul ́ees par le langage. Un pointeur de code pourra ˆetre repr ́esent ́e par un entier, tandis qu’un environnement sera une collection de valeurs.
Dans la suite, nous repr ́esenterons une fermeture associ ́ee `a un pointeur de code pc et un environnement e de la fac ̧on suivante : { pc , e } .
Le type mlvalue pourra ˆetre plus tard ́etendu pour repr ́esenter d’autres types de valeurs. Vous ferez donc attention `a ce que votre impl ́ementation soit suffisamment souple pour g ́erer sans trop de difficult ́e ces ajouts.
Registres de la VM : La Mini-Zam est compos ́ee de 5 registres :
1. prog, un tableau de couples (label, instruction) qui repr ́esente le programme en cours d’in-
terpr ́etation.
2. stack, la pile dans laquelle seront plac ́ees les param`etres des fonctions, des pointeurs de code, des fermetures, etc : c’est une structure LIFO (Last In First Out ) qui contient des mlvalue (au d ́ebut du programme, la pile est vide).
Dans la suite, nous repr ́esenterons les ́el ́ements dans la pile entre crochets […], avec la tˆete de pile correspondant `a la valeur la plus `a gauche.
3. env, l’environnement de la fermeture courante : c’est un collection de mlvalue qui repr ́esente les valeurs accessibles pour la fonction en cours d’ex ́ecution (au d ́ebut du programme, l’envi- ronnement est vide).
Dans la suite, nous repr ́esenterons les ́el ́ements dans l’environnement entre chevrons <...>.
4. pc, le pointeur de code vers l’instruction courante (au d ́ebut du programme, pc = 0).
5. accu, un accumulateur utilis ́e pour stocker certaines valeurs (mlvalue) interm ́ediaires (au d ́ebut
du programme, l’accumulateur vaut ()).
Le roˆle de chaque instruction bytecode est de modifier tout ou partie des valeurs contenues dans ces registres. L’ ́etat de ces registres repr ́esentera ainsi `a tout instant de l’ex ́ecution l’ ́etat de la machine virtuelle. Vous devrez fournir des fonctions permettant d’afficher lors de l’interpr ́etation d’un fichier bytecode le contenu de ces registres.
2 Description des fichiers bytecode
Instructions : Le bytecode associ ́e `a un programme de notre langage ≪ mini-ML ≫ vous sera fourni sous la forme d’un fichier texte, dans lequel chaque ligne repr ́esente une instruction `a ex ́ecuter. L’ins- truction est repr ́esent ́ee par un caract`ere de tabulation (→), suivi par son nom, en lettres majuscules. Par exemple, la ligne suivante correspond a` l’instruction PUSH qui ajoute une valeur en tˆete de la pile :
−−−→PUSH
2

Arguments : Certaines instructions du bytecode doivent ˆetre param ́etr ́ees par une ou plusieurs valeurs. Ces arguments sont ajout ́es `a la suite du nom de l’instruction (apr`es un espace), s ́epar ́es par des virgules. Par exemple, la ligne suivante repr ́esente l’instruction CLOSURE (cr ́eation de fermeture) avec comme argument un label L1 et une valeur 0 :
−−−→CLOSURE L1,0
Labels : Enfin, certaines instructions sont identifi ́ees par un label, afin d’y faire r ́ef ́erence depuis un autre point du bytecode. Une instruction labellis ́ee commence par une chaˆıne de caract`eres qui se termine par le symbole ’:’. Ce label est suivi d’un caract`ere de tabulation, puis de l’instruction bytecode associ ́ee. Par exemple, la ligne suivante repr ́esente l’instruction d’application de l’op ́erateur +, labellis ́ee par un label N :
N:−→PRIM +
Exemple : L’exemple suivant est le contenu d’un fichier bytecode qui correspond au programme
(if true then 2 else 3) :
−−−→CONST 1 −−−→BRANCHIFNOT L −−−→CONST 2 −−−→BRANCH M L:−→CONST 3 M:−→STOP
3 Instructions de base et fonctions unaires
Nous vous demandons en premier lieu d’impl ́ementer un interpr`ete de bytecode Mini-ML qui puisse traiter des programmes faisant usage d’op ́erateurs de base (comme les op ́erateurs arithm ́etiques ou le if then else) et permettant l’application de fonctions non-r ́ecursives qui n’ont pour le moment qu’un argument. La gestion de tels programmes entraˆıne la d ́efinition d’une douzaine d’instructions distinctes.
Nous pr ́esentons dans la suite le d ́etail du fonctionnement de ces derni`eres 3 , ainsi que leur effet sur les registres de la machine virtuelle.
Attention : Pour chaque instruction, seuls les registres ayant ́et ́e modifi ́es (ou ayant un rˆole dans l’instruction) seront mentionn ́es. En plus des modifications explicitement d ́ecrites, le pointeur de code (pc) sera incr ́ement ́e `a la fin de chaque instruction (sauf dans les cas ou` il est pr ́ecis ́e que pc prend une valeur diff ́erente).
1. CONST n (Valeur constante)
Description :
— L’accumulateur (accu) prend pour valeur la constante n.
2. PRIM op (Application de primitive) Description :
— op est une primitive parmi :
3. Il est a` noter qu’a` des fins de simplification les instructions d ́ecrites dans ce sujet diff`erent pour certaines des instructions de la ≪ vraie ≫ machine virtuelle OCaml
Avant
Apr`es
accu
n
3

◦ des op ́erateurs arithm ́etiques `a deux arguments : +,-,/,*
◦ des op ́erateurs logiques `a deux arguments : or,and
◦ l’op ́erateur bool ́een not
◦ des op ́erateurs de comparaison <>,=,<,<=,>,>=
◦ une primitive d’ ́ecriture (d’un caract`ere repr ́esent ́e par sa valeur ASCII) sur stdout : print
— Pour les op ́erateurs `a deux arguments, op est appliqu ́e `a l’accumulateur et `a une valeur d ́epil ́ee, et le r ́esultat est mis dans accu :
— Pour les op ́erateurs unaires, op est appliqu ́e `a l’accumulateur, et le r ́esultat est mis dans accu :
3. BRANCH L (Branchement) Description :
— pc prend pour valeur la position du label L.
— On utilisera une fonction position qui associe un label `a une position dans le code (une
valeur enti`ere)
4. BRANCHIFNOT L (Branchement conditionnel)
Description :
— Si l’accumulateur vaut 0, alors pc prend pour valeur la position du label L :
— Sinon, pc est incr ́ement ́e normalement :
5. PUSH (Empilement)
Description :
— Empile dans stack la valeur situ ́ee dans accu :
6. POP (D ́epilement)
Description :
— D ́epile la valeur situ ́ee en tˆete de stack :
Avant
Apr`es
stack
[a0; a1; …]
Avant
[a1; …]
accu
x
op(x, a0)
Apr`es
accu
x
op(x)
Avant
Apr`es
pc
4
position(L)
Avant
Apr`es
accu
0
0
pc
position(L)
Avant
Apr`es
accu
1
1
pc
n
n+1
Avant
Apr`es
stack
[]
[x; ]
accu
x
Avant
x
Apr`es
stack
[x; ]
[]

7. ACC i (Acc`es `a la i-i`eme valeur de la pile) Description :
— stack[i] est mis dans accu :
8. ENVACC i (Acc`es `a la i-i`eme valeur de l’environnement) Description :
— env[i] est mis dans accu :
9. CLOSURE L,n (Cr ́eation de fermeture) Description :
— Si n > 0 alors l’accumulateur est empil ́e.
— Puis, une fermeture dont le code correspond au label L et dont l’environnement est constitu ́e
de n valeurs d ́epil ́ees de stack est cr ́e ́ee et mise dans l’accumulateur. Par exemple, si n > 0 :
10. APPLY n (Application de fonction) Description :
— n arguments sont d ́epil ́es 4
— env puis pc+1 sont empil ́es
— les n arguments sont rempil ́es
On se met dans le contexte de la fonction appel ́ee :
— pc re ̧coit le pointeur de code de la fermeture situ ́ee dans accu — env re ̧coit l’environnement de la fermeture situ ́ee dans accu
11. RETURN n (Sortie de fonction) Description :
— n valeurs sont d ́epil ́ees
On retourne dans le contexte de l’appelant :
— les valeurs associ ́ees `a pc et env sont d ́epil ́ees
12. STOP (Fin de programme) Description :
— Fin de l’ex ́ecution du programme
— La valeur calcul ́ee par le programme est alors situ ́ee dans accu
4. pour le moment, on ne traitera que les fonctions unaires
Avant
Apr`es
stack
[a0; a1; a2; …; ai; …]
[a0; a1; a2; …; ai; …]
accu
ai
Avant
Apr`es
env


accu
ei
Avant
Apr`es
stack
[a0;…;an−2; an−1; …]
[an−1; …]
accu
x
{ position(L),}
Avant
Apr`es
stack
[a0; …; an−1; an; ]
[a0;…;an−1;c+1;e;an;]
pc
c
c′
env
e
e′
accu
{ c′ , e′ }
{ c′ , e′ }
Avant
Apr`es
stack
[a0; …; an−1; p; e; an; …]
[an;…]
env
e
pc
p
5

Fichiers de test
Vous disposez dans l’archive qui vous est fournie de fichiers vous permettant de tester votre impl ́ementation. Pour cette partie, ces fichiers se trouvent dans le dossier unary funs. Chaque fi- chier “bytecode” (extension .txt) est fourni avec une repr ́esentation en syntaxe OCaml du programme `a t e s t e r 5 .
Par exemple, consid ́erons le programme fun1.ml : let f x = 1 + x in (f 4) * 2
Le contenu du fichier bytecode correspondant, fun1.txt, est :
−−−→BRANCH L2
L 1 : →− A C C 0 −−−→PUSH −−−→CONST 1 −−−→PRIM + −−−→RETURN 1 L2:→− CLOSURE L1,0 −−−→PUSH −−−→CONST 2 −−−→PUSH −−−→CONST 4 −−−→PUSH
−−−→ACC 2 −−−→APPLY 1 −−−→PRIM * −−−→POP −−−→STOP
Et l’interpr ́etation de ce fichier produit la suite suivante d’ ́etats :
au d ́ebut : pc=0 accu=0 stack=[] env=<>
BRANCH L2 -> pc=6 accu=0 stack=[] env=<>
L2: CLOSURE L1,0 -> pc=7 accu={ L1, <> } stack=[] env=<>
PUSH
CONST 2
PUSH
CONST 4
PUSH
ACC 2
APPLY 1
L1: ACC 0
PUSH
CONST 1
PRIM +
RETURN 1
PRIM *
POP
-> pc=8 accu={ L1, <> } stack=[{ L1, <> }] env=<>
-> pc=9 accu=2 stack=[{ L1, <> }] env=<>
-> pc=10 accu=2 stack=[2;{ L1, <> }] env=<>
-> pc=11 accu=4 stack=[2;{ L1, <> }] env=<>
-> pc=12 accu=4 stack=[4;2;{ L1, <> }] env=<>
-> pc=13 accu={ L1, <> } stack=[4;2;{ L1, <> }] env=<>
-> pc=1 accu={ L1, <> } stack=[4;14;<>;2;{ L1, <> }] env=<>
-> pc=2 accu=4 stack=[4;14;<>;2;{ L1, <> }] env=<>
-> pc=3 accu=4 stack=[4;4;14;<>;2;{ L1, <> }] env=<>
-> pc=4 accu=1 stack=[4;4;14;<>;2;{ L1, <> }] env=<>
-> pc=5 accu=5 stack=[4;14;<>;2;{ L1, <> }] env=<>
-> pc=14 accu=5 stack=[2;{ L1, <> }] env=<>
-> pc=15 accu=10 stack=[{ L1, <> }] env=<>
-> pc=15 accu=10 stack=[] env=<>
STOP
4
Fonctions r ́ecursives
Ajoutons d ́esormais la gestion des fonctions r ́ecursives. Pour qu’une fonction puisse faire appel `a elle-mˆeme, elle doit avoir acc`es `a un pointeur vers la premi`ere instruction de son code.
5. A` ce propos, les fichiers bytecode fournis ressemblent a` ce qu’affiche le compilateur ocamlc lorsqu’on lui donne l’option -dinstr
6

Vous devez ajouter alors deux nouvelles instructions :
1. L’instruction CLOSUREREC L,n permet de cr ́eer une fermeture r ́ecursive. Elle est tr`es semblable `a l’instruction CLOSURE L,n, `a ceci pr`es qu’elle stocke ́egalement en tˆete de env le pointeur de code correspondant au label L (afin de pouvoir se rappeler elle-mˆeme). De surcroˆıt, pour faire comme dans la ZAM, la fermeture cr ́e ́ee sera empil ́ee `a la fin de l’instruction.
2. L’instruction OFFSETCLOSURE qui met dans accu une fermeture dont le code correspond au pre- mier ́el ́ement de l’environnement courant (env[0]) et l’environnement correspond `a l’ensemble de valeurs contenues dans env.
Fichiers de test
Des fichiers de test associ ́es aux fonctions r ́ecursives sont situ ́es dans le sous-dossier rec funs. 5 Fonctions n-aires et application partielle
Il est possible de compiler une fonction d’arit ́e n grˆace `a un processus de curryfication 6 qui consiste `a transformer une fonction `a n arguments en une fonction `a un argument qui retourne une fonction `a n−1 arguments. Par exemple, la fonction (fun x y z -> x + y + z) peut ˆetre r ́e ́ecrite (en curryfiant toutes les fonctions) en :
(fun x -> (fun y -> (fun z -> x + y + z)))
Cependant, ce proc ́ed ́e est assez couˆteux, car avec notre mode d’application des fonctions, il serait alors cr ́e ́e n fermetures pour une fonction n−aire. Et ce surcouˆt semble encore plus inutile quand on r ́ealise que, la plupart du temps, les fonctions sont appliqu ́ees avec tous leurs arguments.
Pour pallier `a ce d ́efaut, nous g ́erons alors l’application d’une fonction `a n arguments en ajoutant `a la machine Mini-ZAM un registre extra args dont le roˆle est de repr ́esenter le nombre d’arguments restant `a appliquer `a une fonction pour r ́ealiser une application totale. Ce registre fera alors partie de l’ ́etat de la machine virtuelle, qui contiendra d ́esormais 6 ́el ́ements.
Le contexte stock ́e lors de l’appel d’une fonction contiendra donc un ́el ́ement suppl ́ementaire. En effet, on aura besoin, en plus du pc et de l’environnement, de la valeur de extra args pour enregistrer toutes les informations du contexte de l’appelant. Le m ́ecanisme d’application de fonction est alors modifi ́e en cons ́equence :
1. L’instruction APPLY n empilera extra args en plus de pc et env, et mettra ensuite la valeur n − 1 dans extra args.
2. L’instruction RETURN n est modifi ́ee comme suit :
◦ Dans tous les cas, on d ́epile d’abord n valeurs.
◦ Puis, si extra args = 0, on conserve le fonctionnement pr ́ec ́edent (mais on fera attention `a bien se remettre dans le contexte de l’appelant en tenant compte des modifications apport ́ees `a APPLY)
◦ Sinon :
— extra args est d ́ecr ́ement ́e de 1.
— pc re ̧coit le pointeur de code de la fermeture situ ́ee dans accu. — env re ̧coit l’environnement de la fermeture situ ́ee dans accu.
Par exemple, si extra args > 0 :
6. https://fr.wikipedia.org/wiki/Curryfication
7
Avant
m
Apr`es
stack
[a0; a1; …; an−1; an;…]
[an;…]
extra args
m−1
pc
c
env
e
accu
{c,e}
{c,e}

De plus, deux nouvelles instructions seront `a traiter :
1. GRAB n (Gestion de l’application partielle) Description :
— Si extra args ≥ n, alors on a assez d’arguments pour appliquer la fonction : d ́ecr ́ementer
extra args de n et continuer a` l’instruction suivante.
— Sinon, on g ́en`ere une nouvelle fermeture :
◦ D ́epiler extra args+1 ́el ́ements
◦ Mettre dans accu une nouvelle fermeture {c′,e′} telle que :
• c′ = pc−1 (i.e une instruction RESTART)
• e′[0]=env
• les autres ́el ́ements de e′ correspondent aux extra args+1 ́el ́ements qui ont ́et ́e d ́epil ́es juste avant.
◦ Trois valeurs sont d ́epil ́ees et associ ́ees `a extra args, env, et pc.
Avant
Apr`es
extra args
m+n
m
pc
c
c+1
Avant
m
Apr`es
stack
[a0; a1; …; am−1; am; am+1; am+2; am+3; am+4;…]
[am+4;…]
extra args
am+1
pc
c
am+2
env
e
am+3
accu
{ c−1 , }
2. RESTART
Description : Cette instruction pr ́ec ́edera toujours une instruction GRAB
— Soit n, la taille de l’environnement
— D ́eplacer les ́el ́ements de env `a partir du deuxi`eme (donc de env[1] a` env[n − 1]) dans la
pile
— env prend pour valeur celle de son premier ́el ́ement (env[0])
— extra args est incr ́ement ́e de (n − 1).
Fichiers de test
Des fichiers de test associ ́es aux fonctions n-aires sont situ ́es dans le sous-dossier n-ary funs. 6 Optimisations et nouvelles fonctionnalit ́es
Pour ́etendre le fonctionnement de votre Mini-ZAM, nous vous demandons finalement d’ajouter au moins une des fonctionnalit ́es d ́ecrites dans cette section.
Avant
Apr`es
stack
[a0; …]
[e1; …; en−1; a0; …]
extra args
m
m+(n−1)
pc
an+1
env

e0
8

6.1 Appels terminaux
Il arrive assez souvent que l’appel `a une fonction soit la derni`ere chose qui est r ́ealis ́ee dans la fonction appelante. Ainsi, une instruction APPLY pr ́ec`ede r ́eguli`erement une instruction RETURN, et il est inutile (et couˆteux) de sauvegarder le contexte de l’appelant dans la pile et le restaurer apr`es l’appel pour simplement en sortir juste apr`es.
De ce fait, nous vous proposons d’ajouter une nouvelle instruction APPTERM n,m dont le comportement est identique `a la suite d’instructions APPLY n; RETURN m-n, mais sans passer par une sauvegarde et restauration de la fonction appelante.
Le d ́eroul ́e d’une instruction APPTERM n,m est le suivant :
— D ́epilement des n arguments de l’appel.
— D ́epilement des m − n variables locales de la fonction appelante. — Rempilement des n arguments de l’appel.
— Positionnement dans le contexte de la fonction appel ́ee.
— Incr ́ementation de extra args de n − 1.
Ajoutez dans votre impl ́ementation le code d’interpr ́etation de la nouvelle instruction APPTERM, ainsi qu’une passe de transformation du bytecode du programme qui remplace toutes les occurences de APPLY + RETURN par le APPTERM correspondant.
Fichiers de test : Des fichiers de test se situent dans le sous-dossier appterm. Tous ne contiennent pas d’instruction APPTERM : il faudra bien d’abord utiliser la passe de transformation du bytecode pour g ́en ́erer des instructions APPTERM. Vous comparerez la taille maximale de la pile avec et sans cette optimisation.
6.2 Blocs de valeurs (potentiellement mutables)
Les programmes traˆıt ́es jusqu’ici manipulent uniquement des valeurs imm ́ediates enti`eres. Nous vous proposons d’ajouter d ́esormais un nouveau type de valeurs, que nous nommerons bloc, et qui repr ́esente une valeur allou ́ee sur le tas qui contient plusieurs valeurs. Nous repr ́esenterons un bloc entre parenth`eses, avec ses diff ́erentes valeurs s ́epar ́ees par des virgules.
Par exemple, le bloc (1, 2) repr ́esente une paire constitu ́ee de l’entier 1 et de l’entier 2.
La liste 1::2::3::4::[] sera, quant `a elle, repr ́esent ́ee par le bloc (1,(2,(3,(4,0)))) (la valeur 0, ici plac ́ee en seconde position d’un bloc, repr ́esente la liste vide).
Le tableau [| 10 ; 20 ; 30 ; 40 |] sera repr ́esent ́e par le bloc suivant : (10, 20, 30, 40). Pour manipuler de tels blocs, vous aurez `a ajouter plusieurs instructions :
1. MAKEBLOCK n qui cr ́ee un bloc de taille n. Si n > 0 alors la valeur pr ́esente dans accu constitue le premier ́el ́ement du bloc, tandis que les n − 1 ́el ́ements suivants sont d ́epil ́es de stack. A` la fin de l’instruction, l’accumulateur contiendra le nouveau bloc cr ́e ́e.
2. GETFIELD n qui met dans l’accumulateur la n-i`eme valeur du bloc contenu dans accu.
3. VECTLENGTH qui met dans l’accumulateur la taille du bloc situ ́e dans accu.
4. GETVECTITEM qui d ́epile un ́el ́ement n de stack puis met dans accu la n-i`eme valeur du bloc situ ́e dans l’accumulateur.
5. On pourra alors traiter des valeurs mutables (comme les r ́ef ́erences ou les tableaux) avec les instructions suivantes :
— SETFIELD n qui met dans la n-i`eme valeur du bloc situ ́e dans accu la valeur d ́epil ́ee de
stack.
— SETVECTITEM qui d ́epile deux ́el ́ements n et v de stack, puis met v dans la n-i`eme
valeur du bloc situ ́e dans accu. La valeur repr ́esentant () est ensuite mise dans l’accumu-
lateur.
— ASSIGN n qui remplace le n-i`eme ́el ́ement `a partir du sommet de la pile par la valeur
situ ́ee dans accu, puis met la valeur () dans l’accumulateur. 9

Fichiers de test : Des fichiers de test pour les blocs de valeurs sont situ ́es dans le sous-dossier block values.
6.3 Gestion des exceptions
Les exceptions repr ́esentent un m ́ecanisme puissant pour g ́erer la pr ́esence d’anomalies ou autres conditions exceptionnelles au cours de l’ex ́ecution d’un programme. Les syst`emes de gestion d’ex- ception permettent alors de modifier le flot de controˆle d’un programme afin de traiter de mani`ere sp ́ecifique de telles conditions.
Dans la Mini-ZAM, une exception sera repr ́esent ́ee par un nombre entier, et l’ajout d’un syst`eme permettant de g ́erer des exceptions reposera sur les modifications suivantes :
1. Ajout d’un nouveau registre dans la machine virtuelle, nomm ́e trap sp. Ce registre repr ́esentera la position du rattrapeur d’exceptions situ ́e au plus haut dans la pile.
2. Ajout de l’instruction PUSHTRAP L qui empile un nouveau r ́ecup ́erateur d’exception. Ses effets sur les registres de la machine virtuelle sont les suivants :
— Empile extra args, env, trap sp et position(L)
— Met dans trap sp un pointeur vers l’ ́el ́ement en tˆete de pile
3. Ajout de l’instruction POPTRAP qui sort du r ́ecup ́erateur d’exception courant. Ses effets sur les registres de la machine virtuelle sont les suivants :
— D ́epile un ́el ́ement, puis un second dont la valeur est mise dans trap sp, puis deux autres
́el ́ements.
4. Ajout de l’instruction RAISE qui l`eve l’exception contenue dans l’accumulateur :
— Si aucun r ́ecup ́erateur n’est d ́efini, alors le programme s’arrˆete et le num ́ero de l’exception
est affich ́e.
— Sinon, on remet la pile dans l’ ́etat ou` elle ́etait au dernier PUSHTRAP (i.e. on repositionne
le sommet de pile `a l’endroit point ́e par trap sp), et on r ́ecup`ere pc, trap sp, env et extra args `a partir de quatre ́el ́ements d ́epil ́es de stack.
Fichiers de test : Des fichiers de test concernant la gestion des exceptions sont situ ́es dans le sous-dossier exceptions.
Powered by TCPDF (www.tcpdf.org)
10