Université Paris 6 Licence d'informatique Maîtrise de Sciences et Techniques (Experts en Systèmes Informatiques) |
Module de Programmation Année 1999-2000 |
---|
<decl> :: = let <nom> = <expr>;;où
<expr>
désigne n'importe quelle expression. Un <nom>
est une séquence ininterrompue de lettres de l'alphabet.
Les expressions sont définies par la grammaire suivante au format BNF
(Bachus Naur Form): <expr> ::= if <expr> then <expr> else <expr> | let <nom> = <expr> in <expr> | function <nom> -> <expr> | rec <nom> <nom> = <expr> | <expr> <expr> | ( <expr> ) | <expr>,<expr> | fst <expr> | snd <expr> | <nom> | i | true | false | <expr> <op> <expr> | <infix> <expr> <op> ::= + | - | * | / | < | > | <= | >= | != | = <infix>::= -Une expression peut être une expression conditionnelle (
if
), une
déclaration locale (let
), une fonction, une fonction récursive,
une application de fonction, une expression entre parenthèses, une
paire de deux expressions, un accès à la première composante d'une
paire (fst
), un accès à la deuxième (snd
), une
variable (nom
), une constante entière (i
), un booléen
(true
et false
), une expression
arithmétique infixe ou une expression arithmétique préfixe.let f = function x -> function y -> if y = x then let x = 2 in x+y else 3;; let resultat = f 2 3;; let rec fact x = if x = 0 then 1 else x * (fact (x-1));; let app f g x = f (g x);;
type decl = ... and expr = ... and immediat = .. and localisation = ... and typ = ... and var_type = ... and schema_de_type = ...Cette partie définit les déclarations, les expressions, les valeurs dites immédiates (entiers, booléens), une information donnant la position de l'expression analysée dans le fichier source, les types du langage, les variables de type et les schémas de type. Ce module vous est donné.
global
déclarant l'environnement de typage global ainsi qu'une
exception qui sera levée lorsqu'une erreur est survenue lors de l'analyse du
programme (erreur de syntaxe ou erreur de typage).exception Erreur;; value env_global : (string * schema_de_type) list ref;; value ajout_global : (string * schema_de_type) list -> unit;; value env_global : unit -> (string * schema_de_type) list;;Ce module vous est donné.
lexing
du manuel de référence de Caml Light
(page 151).lire_decl_chaine : string -> decl lire_expr_chaine : string -> expr lire_decl : lexing__lexbuf -> declCette partie vous est donnée.
subst_type
dans la suite du
texte. Par exemple, les deux types:
exception Unification;; value reinit_var_de_type : unit -> unit;; value gen_var_type : unit -> var_type;; value vars : var_type list -> var_type list -> typ -> var_type list;; value var_libres : typ -> var_type list;; value var_libres_env : (string * schema_de_type) list -> var_type list;; value substituer : (var_type * typ) list -> typ -> typ;; value unifier : (var_type * typ) list -> typ -> typ -> (var_type * typ) list;; value generaliser : (string * schema_de_type) list -> typ * (var_type * typ) list -> schema_de_type;; value instancier : schema_de_type -> typ;;La fonction
gen_var_type
rend une nouvelle variable de type et
reinit_var_de_type
permet d'initialiser cette fonction.substituer subst_type t
où subst_type
est une
substitution de type (associant des types à des variables de type) et
t
, un type, rend un type t'
déduit de t
en
remplaçant les variables de t
figurant dans subst_type
par les types qui leur sont associés.unifier subst_type t1 t2
, où subst_type
est une
substitution de type, t1
et t2
sont des types, rend une
nouvelle substitution subst_type'
telle que
substituer subst_type' t1 = substituer subst_type' t2.
Lorsque les deux types ne sont pas unifiables, l'exception
Unification est levée. value unifier_exp : (var_type * typ) list -> expr -> typ -> typ -> (var_type * typ) list;; value typer : (string * schema_de_type) list -> (var_type * typ) list -> expr -> typ * (var_type * typ) list;; value typer_decl : decl -> unit;;
unifier_exp subst_type e typ_obtenu typ_attendu
unifie le type
typ_obtenu
pour l'expression e
avec le type
typ_attendu
. Si l'unification a échoué (l'exception
Unification
a été levée), cette fonction devra émettre un
message d'erreur approprié.typer env_de_type subst_type e
rend le type obtenu pour
l'expression e
ainsi qu'une nouvelle substitution de type (on
peut en effet supposer que le typage de e
a fait apparaitre de
nouvelles contraintes de type). Elle est paramétrée par un
environnement de type env_type
(associant des schémas de type
aux variables du
programme) et subst_type
. typer_decl
s'occupe du typage des déclarations: cette fonction
type une déclaration, modifie l'environnement global et affiche le
type obtenu.initialiser_localisation : string -> in_channel -> lexing__lexbuf -> unit afficher_source : syntaxe_abstraite__localisation -> unit
initialiser_localisation fichier ic lexbuf
permet d'initialiser
les fonctions du module: fichier
est le nom du fichier dans
lequel se trouvent les déclarations, ic
est son descripteur de
fichier (voir page 126 du manuel Caml Light), lexbuf
est un
buffer lexical. Cette fonction doit impérativement être
exécutée avant d'utiliser la fonction afficher_source
sur un
programme écrit dans un fichier.afficher_source loc
permet d'afficher une partie du code source
autour de la localisation loc
.value erreur_de_syntaxe : localisation -> unit;; value erreur_identificateur : localisation -> string -> unit;; value erreur_de_type : localisation -> typ -> typ -> unit;;
erreur_de_syntaxe loc
traite des erreurs de syntaxe.
erreur_identificateur loc x
indique que x
n'est pas
déclaré en montrant la ligne concernée.
erreur_de_type loc ty_obtenu ty_attendu
indique que le type
obtenu n'est pas unifiable avec le type attendu.main_decl : unit -> unit main_string : string -> unitCe module est à écrire.
main_decl
lance l'analyse syntaxique et le typage
de la suite des déclarations apparaissant dans un fichier. Les
déclarations sont analysées les unes après les autres. L'analyse
d'un fichier s'arrête dès que l'analyse d'une déclaration échoue.typer
et
main
. Dans un
premier temps, vous considèrerez que les expressions ne sont pas
polymorphes (elles ne contiennent pas de variables de type). Vous
traiterez ensuite le cas général. Pour cela, vous
devrez développer votre implantation à l'aide d'un Makefile
et
de manière interactive en vérifiant qu'à chaque étape, la succession
des étapes élémentaires est correcte.Non_implante
pourra être levée.1 + 3
est vue comme une double application de la
variable +
à la constante 1
puis à la constante
3
.if c then e1 else e2
est bien typée si c
est un booléen
et si e1
et e2
sont de même type.
(string * schema_de_type) listQuestion 4
typer
et la fonction principale dans le module
main
. Il faudra pour cela ouvrir le fichier en lecture, lancer
l'analyse syntaxique puis le typage et enfin, mettre à jour
l'environnement de type global.
typer
pour qu'elle traite les
expressions ayant des types polymorphes. fst
et snd
dont le
type est polymorphe.
env_type
est:
fst
et
snd
ainsi que le traitement des expressions arithmétiques en remarquant
qu'il suffit, pour les typer, de charger un environnement initial
donnant le schéma de type associé à chaque opérateur arithmétique. Par
exemple:
+ : Tpour_tout([],Tfleche(int,Tfleche(int,int)))Indication: L'ensemble de ces déclarations pourra être rassemblé dans un module d'initialisation.
typer
complète peut
être écrite en moins de 100 lignes.
/Infos/caml-ens/99-00/tp2
.
Vous y trouverez un fichier LISEZMOI
qui décrit les différents
fichiers ainsi qu'un Makefile
donnant l'architecture générale de
l'évaluateur. Ce fichier est à modifier suivant vos besoin. Enfin, le
fichier exemples.txt
vous donne quelques exemples de programmes du
langage et le résultat rendu par le typage.typer
qui prend en entrée un
fichier fichier.mml
et qui affiche sur la sortie standard le
résultat du typage.
Ce document a été traduit de LATEX par HEVEA.