Précédent Index Suivant

3.9   Impression des types et des erreurs

Comme les variables de types sont codées à l'aide d'entiers, il serait particulièrement désagréable d'avoir un affichage de types dépendant de cette numérotation. Pour cela, pour chaque expression globale est crée une liste d'association des numéros de variables de types et des symboles pour les types polymorphes.

Les constantes de types sont affichées directement par la fonction print_consttype : let print_consttype = function
* Int_type ® print_string ``int''
* Float_type ® print_string ``float''
* String_type ® print_string ``string''
* Bool_type ® print_string ``bool''
* Unit_type ® print_string ``unit''
* ;;
* print_consttype : consttype ® unit = áfunñ

La fonction var_name retourne une chaîne de caractères unique pour chaque entier passé en argument : let ascii i = char_for_read (char_of_int i);;
* ascii : int ® string = áfunñ let var_name n =
* let rec name_of n =
* let q,r = ((n / 26), (n mod 26))
* in
* if q=0 then ascii (96+r)
* else (name_of q)^(ascii (96+r))
* in ``'''^(name_of n)
* ;;
* var_name : int ® string = áfunñ

La fonction principale est l'impression d'un schéma de type. Le seul problème est de trouver le nom d'une variable de types. la fonction locale names_of retourne les variables quantifiées, chacune associée à une chaîne de caractères particulière. Si une variable de type n'est pas donc cet ensemble une exception est déclenchée, car il ne peut avoir d'expression globale contenant des variables de type non quantifiées.

let print_quantified_type (Forall(gv,t)) =
* let names =
* let rec names_of = function
* (n,[  ]) ® [  ]
* (n,(v1::lv)) ® (var_name n)::(names_of (n+1,lv))
* in (names_of (1,gv))
* in
* let var_names = combine (rev gv,names)
* in
* let rec print_rec = function
* Var_type (ref(Instanciated t)) ® print_rec t
* Var_type (ref(Unknown n)) ®
* let name = (try assoc n var_names
* with Not_found ® raise (Failure ``Non quantified variable in type''))
* in print_string name
* Const_type ct ® print_consttype ct
* Pair_type(t1,t2) ® print_string ``('' print_rec t1
* print_string `` * '' print_rec t2 print_string ``)''
* List_type t ® print_string ``(('' print_rec t print_string ``) list)''
* Fun_type(t1,t2) ® print_string ``('' print_rec t1
* print_string `` -> '' print_rec t2 print_string ``)''
* in
* print_rec t
* ;;
* print_quantified_type : quantified_type ® unit = áfunñ

L'impression d'un type simple utilise l'impression des chémas de type en créant pour l'occasion une quantification sur toutes les variables libres du type.

let print_type t = print_quantified_type (Forall(free_vars_of_type ([  ],t),t));;
* print_type : ml_type ® unit = áfunñ

Il est fort intéressant d'afficher les causes d'un échec de typage, comme par exemple les types mis en cause lors d'une erreur de typage ou le nom d'une variable indéfinie. La fonction typing_handler reçoit en argument une fonction de typage, un environnement et une expression à typer. Elle capture les exceptions dues à une erreur de typage, affiche un message plus clair et déclenche une nouvelle exception.

let typing_handler typing_fun env expr =
* reset_unknowns()
* try typing_fun env expr
* with
* type_error (Clash(lt1,lt2)) ®
* print_string ``Type clash between ''print_type lt1
* print_string `` and ''print_type lt2 print_newline()
* failwith ``type_check''
* type_error (Unbound_var s) ®
* print_string ``Unbound variable ''
* print_string s print_newline()
* failwith ``type_check''
* ;;
* typing_handler : (a ® b ® g) ® a ® b ® g = áfunñ


Précédent Index Suivant