INF6120 - Laboratoire 9
Pour ce laboratoire, nous allons utiliser l’exemple interp5.ml
Avant tout :
- clonez le dépôt d’exemples :
git clone https://gitlab.info.uqam.ca/inf6120/exemples
- exécutez l’exemple
interp5
:cd exemples/interpreter ; dune exec ./interp5.exe
- lisez attentivement le code
interp5.ml
Tout le reste du labo se fera à partir du code de interp5.ml
. Vous pouvez donc effectuer vos modifications directement dans ce fichier.
Représentation d’un programme
- Écrire le programme OCaml qui correspond au code qui est évalué dans l’exemple
interp5
(à la dernière ligne du fichier) - Transcrire le code OCaml suivant en représentation sous forme d’AST, et vérifier le résultat avec l’interpréteur
interp5
:
let a = 1 in
let b = 2 in
let f = function x -> function y -> x + y in
f a b
Booléens
Ajouter le support des booléens tel que vu au cours.
Ajout de comparaisons
- Définir les opérateurs
<
et>
qui opèrent sur des nombres. Utiliser un typage fort. - Définir l’opérateur
=
qui compare les types primitifs du langage (booléens, entiers). Utiliser un typage fort.
Nombres réels
Ajouter le support pour des nombres réels (représentés par le type float
en OCaml), de façon à ce que :
- on aie un constructeur
Float
pour introduire une expression représentant un réel - les opérations mathématiques soient supportés sur les flottants avec un typage strict (on ne peut pas additionner un réel avec un entier par exemple)
Typage faible
Modifier le code de l’exercice précédent pour introduire du typage faible sur les nombres : on peut par exemple ajouter un flottant avec un entier.
Afficher une valeur
Ajouter une nouvelle expression Print
qui affiche la valeur de l’expression qui lui est passée en argument.
Application partielle
L’interpréteur d’exemple ne permet pas l’application partielle, par exemple (function x y -> x + y) 1
donnera lieu a une TypeError
. Dans cet exercice, vous devez adapter le code pour permettre l’évaluation partielle. Cela peut se faire de deux façons :
- modifier les fonctions pour n’avoir qu’un seul paramètre
- détecter les cas d’applications partielles lors de l’appel de fonction, et retourner une fermeture plutôt que d’appliquer la fonction
Implémenter les deux solutions, une à la fois.
Liaison dynamique
Ceci est un exercice bonus avancé.
Une approche alternative pour la gestion des environnements lors de l’appel de fonction est ce qu’on appelle la liaison dynamique (dynamic binding ou dynamic scoping). Dans cette approche, plutôt que d’étendre l’environnement de définition de la fermeture, c’est l’environnement d’appel qui est étendu.
Par exemple, avec cette approche, la liaison a
sera évaluée à 5
plutôt que 3
dans la fonction p
du programme suivant :
let a = 3 in
let p = fun x -> x - a in
a := 5;
p 2
Gestion des erreurs
Ceci est un exercice bonus avancé.
Enlever le type d’exception TypeError
de l’interpréteur. Adapter le type de retour de eval
pour retourner une valeur optionnel : soit l’évaluation réussi et on récupère une valeur, soit l’évaluation échoue et on récupère une erreur (par exemple, représentée par None
). Adapter ensuite les définitions pour que le code compile et s’exécute.
La fonction (monadique) Option.bind
peut s’avérer utile pour éviter d’avoir trop de match
imbriqués.