File: types.ml

package info (click to toggle)
ocaml-doc 3.09-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 10,428 kB
  • ctags: 4,963
  • sloc: ml: 9,244; makefile: 2,413; ansic: 122; sh: 49; asm: 17
file content (164 lines) | stat: -rw-r--r-- 5,545 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*               Pierre Weis, projet Cristal, INRIA Rocquencourt       *)
(*                                                                     *)
(*  Copyright 2001 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  only by permission.                                                *)
(*                                                                     *)
(***********************************************************************)
type type_simple =
   | Variable of variable_de_type
   | Terme of string * type_simple array

and variable_de_type =
  { mutable niveau: int;
    mutable valeur: valeur_d'une_variable }

and valeur_d'une_variable =
  | Inconnue
  | Connue of type_simple;;

type schma_de_types =
  { paramtres: variable_de_type list;
    corps: type_simple };;

exception Conflit of type_simple * type_simple;;
exception Circularit of type_simple * type_simple;;

let type_int = Terme("int", [||])
and type_bool = Terme("bool", [||])
and type_flche t1 t2 = Terme("->", [|t1; t2|])
and type_produit t1 t2 = Terme("*", [|t1; t2|])
and type_liste t = Terme("list", [|t|]);;

let rec valeur_de = function
  | Variable({valeur = Connue ty1} as var) ->
      let valeur_de_ty1 = valeur_de ty1 in
      var.valeur <- Connue valeur_de_ty1;
      valeur_de_ty1
  | ty -> ty;;

let test_d'occurrence var ty =
  let rec test t =
    match valeur_de t with
    | Variable var' ->
        if var == var' then raise(Circularit(Variable var, ty))
    | Terme(constructeur, arguments) ->
        Array.iter test arguments
  in test ty;;

let rec rectifie_niveaux niveau_max ty =
  match valeur_de ty with
  | Variable var ->
      if var.niveau > niveau_max then var.niveau <- niveau_max
  | Terme(constructeur, arguments) ->
      Array.iter (rectifie_niveaux niveau_max) arguments;;

let rec unifie ty1 ty2 =
  let valeur1 = valeur_de ty1
  and valeur2 = valeur_de ty2 in
  if valeur1 == valeur2 then () else
    match (valeur1, valeur2) with
    | Variable var, ty ->
        test_d'occurrence var ty;
        rectifie_niveaux var.niveau ty;        
        var.valeur <- Connue ty
    | ty, Variable var ->
        test_d'occurrence var ty;
        rectifie_niveaux var.niveau ty;        
        var.valeur <- Connue ty
    | Terme(constr1, arguments1), Terme(constr2, arguments2) ->
        if constr1 <> constr2 then
          raise (Conflit(valeur1, valeur2))
        else
          for i = 0 to Array.length arguments1 - 1 do
            unifie arguments1.(i) arguments2.(i)
          done;;
let niveau_de_liaison = ref 0;;

let dbut_de_dfinition () = incr niveau_de_liaison
and fin_de_dfinition () = decr niveau_de_liaison;;

let nouvelle_inconnue () =
  Variable {niveau = !niveau_de_liaison; valeur = Inconnue};;

let gnralisation ty =
  let paramtres = ref [] in
  let rec trouve_paramtres ty =
    match valeur_de ty with
    | Variable var ->
        if var.niveau > !niveau_de_liaison && not (List.memq var !paramtres)
        then paramtres := var :: !paramtres
    | Terme(constr, arguments) ->
        Array.iter trouve_paramtres arguments in
  trouve_paramtres ty;
  {paramtres = !paramtres; corps = ty};;

let schma_trivial ty = {paramtres = []; corps = ty};;

let spcialisation schma =
  match schma.paramtres with
  | [] -> schma.corps
  | paramtres ->
      let nouvelles_inconnues =
        List.map (fun var -> (var, nouvelle_inconnue())) paramtres in
      let rec copie ty =
        match valeur_de ty with
        | Variable var as ty ->
            begin try
              List.assq var nouvelles_inconnues
            with Not_found ->
              ty
            end
        | Terme(constr, arguments) ->
            Terme(constr, Array.map copie arguments) in
      copie schma.corps;;

let noms_des_variables = ref ([] : (variable_de_type * string) list)
and compteur_de_variables = ref 0;;

let imprime_var var =
  print_string "'";
  try
    print_string (List.assq var !noms_des_variables)
  with Not_found ->
    let nom =
      String.make 1
        (char_of_int (int_of_char 'a' + !compteur_de_variables)) in
    incr compteur_de_variables;
    noms_des_variables := (var, nom) :: !noms_des_variables;
    print_string nom;;

let rec imprime ty =
  match valeur_de ty with
  | Variable var ->
      imprime_var var
  | Terme(constructeur, arguments) ->
      match Array.length arguments with
      | 0 -> print_string constructeur
      | 1 -> imprime arguments.(0);
             print_string " "; print_string constructeur
      | 2 -> print_string "("; imprime arguments.(0);
             print_string " "; print_string constructeur;
             print_string " "; imprime arguments.(1);
             print_string ")"
      | _ -> failwith "constructeur de type ayant trop d'arguments";;

let imprime_type ty =
  noms_des_variables := [];
  compteur_de_variables := 0;
  imprime ty;;
  
let imprime_schma schma =
  noms_des_variables := [];
  compteur_de_variables := 0;
  if schma.paramtres <> [] then begin
    print_string "pour tout ";
    List.iter (fun var -> imprime_var var; print_string " ")
            schma.paramtres;
    print_string ", "
  end;
  imprime schma.corps;;