Rappel :
graph TD Fopix --> ANF ANF --> Kontix Kontix --> Javix
Kontix
f(x_{1}, \dots, x_{n}) \underset{\text{Kontix}}{\implies} f(K, \text{Env}, x_{1,} \dots, x_{n})
main Kontix -> début du programme Javix
- v0 \leftarrow Kontinuation (l’adresse
int
associée à la kontinuation) : typeint
\RA pas besoin de boxé - v1 \leftarrow Environnment (tableau / référence au tableau) :
E[0], E[1], E[2]...
Au début
- v0 \leftarrow kontinuation initiale (certaine adresse/étiquette)
addr_init
(= 1000)etiquette_init
(= “dispatch”_ret: return
pour terminer le programme) - v1 \leftarrow
env.initial
(tableau vide)
Compilation
En général
\RA Permet d’estimer une taille précise de la taille de la pile
Le If
Le if
basique
Comme dans Javix, rien de spécial, 2 étiquettes if_else
et if_exit
.
Le if(comp, TailExpr, TailExpr)
Si la condition est vraie, alors on continue avec l’expression récursive terminale, donc on ne revient jamais en arrière
Si la condition est fausse, on a une autre expression récursive terminale, alors on ne revient pas en arrière.
Donc vu qu’on ne revient jamais en arrière, pas besoin d’étiquette if_exit
.
Exemple : if(b) call(f) else call(g)
.
if((comp_op, be1, be2), te1, te2)
compil(be1)
compil(be2)
ificmp_invop label_if_else
compil(te1)
label_if_else:
compile(te2)
Let/Blet : Let/BLet(id, e1, e2)
- Création d’une nouvelle variable
Fresh()
Compiler(e1)
; Générer une variable associée à l'id
; Mettre dans cette variable le résultat
Compiler(e2)
Appel de fonction : Call(be, [a0, ..., an]
be
: basic expression
[a_{0}, \dots, a_{n}] un ensemble de variables
- Pas besoin de sauvegarder/restauration des variables, car on ne revient jamais en arrière.
- Pas d’adresse de retour non plus pour la même raison
Appel direct be = Fun f
Exemple
f(1, 3) : Call(Fun f, [Num(1), Num(3)]
; Il faut calculer les arguments a de 0 à n.
; Puis on AStore
AStore(n+2)
; ...
AStore(2)
Goto f_body ; étiquette qui traduit le K de la fonction f
Appel indirect be
n’est pas un Fun
, c’est une expression + compliquée
; Calcul de be
; Il faut calculer les arguments a de 0 à n.
; Puis on AStore
IStore(n+2)
; ...
AStore(2)
Goto dispatch
Appel à Kontinuation : Call(K, [be])
= Ret(be)
be
est l’argument de la kontinuation.
ALoad(0) ; v0 = Kontinuation courante
Calcul(be)
AStore 2 ; résultat de be
Goto dispatch
Push : PushCont(cont, ids, e)
let E = [K, E, eds] in
let K = cont in e
Push taille len(ids) + 2 ; 2 : 1 pour k et 1 pour e
ANewArray ; création du tableau
; Maintenant on écrit dedans les nouvelles valeurs
E[0] <- v0
E[1] <- v1
E[2] <- les autres variables "ids"
AStore 1 ; on met l'adresse du tableau E sur la pile
; Il faut laisser au sommet de la pile l'adresse de la kontinuation correspondante
Push 'adresse'
IStore 0
Def : DefCont(cont, [x, y, z], res, expr)
def kont(e, res) =
let [K, E, x, y, z] = e in
expr
label_kont:
; extraire l'environnement e
; v1 = (kont, env, variables)
v0 <- v1[0] ; on change de Kontinuation
v3 <- v1[2] ; x
v4 <- v1[3] ; y
v5 <- v1[4] ; z
v1 <- v1[1] ; env, qu'il faut faire à la fin pour pas perdre les variables, car on écrit dans v1