/[svn]/types/types.ml
ViewVC logotype

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 75 - (hide annotations)
Tue Jul 10 17:03:57 2007 UTC (5 years, 10 months ago) by abate
File size: 26949 byte(s)
[r2002-11-02 19:24:08 by cvscast] Empty log message

Original author: cvscast
Date: 2002-11-02 19:24:09+00:00
1 abate 1 open Recursive
2     open Printf
3    
4    
5 abate 75 let map_sort f l =
6     SortedList.from_list (List.map f l)
7 abate 1
8     type label = int
9     type atom = int
10    
11 abate 71 let counter_label = ref 0
12     let label_table = Hashtbl.create 63
13     let label_names = Hashtbl.create 63
14    
15     let label s =
16     try Hashtbl.find label_table s
17     with Not_found ->
18     incr counter_label;
19     Hashtbl.add label_table s !counter_label;
20     Hashtbl.add label_names !counter_label s;
21     !counter_label
22    
23     let label_name l =
24     Hashtbl.find label_names l
25    
26     let mk_atom = label
27    
28     let atom_name = label_name
29    
30 abate 15 type const = Integer of Big_int.big_int | Atom of atom | Char of Chars.Unichar.t
31 abate 1
32     module I = struct
33     type 'a t = {
34     ints : Intervals.t;
35     atoms : atom Atoms.t;
36     times : ('a * 'a) Boolean.t;
37     arrow : ('a * 'a) Boolean.t;
38     record: (label * bool * 'a) Boolean.t;
39 abate 13 chars : Chars.t;
40 abate 1 }
41 abate 15
42 abate 1 let empty = {
43     times = Boolean.empty;
44     arrow = Boolean.empty;
45     record= Boolean.empty;
46     ints = Intervals.empty;
47     atoms = Atoms.empty;
48 abate 13 chars = Chars.empty;
49 abate 1 }
50 abate 15
51 abate 1 let any = {
52     times = Boolean.full;
53     arrow = Boolean.full;
54     record= Boolean.full;
55 abate 15 ints = Intervals.any;
56 abate 18 atoms = Atoms.any;
57     chars = Chars.any;
58 abate 1 }
59    
60 abate 52 let interval i = { empty with ints = i }
61 abate 1 let times x y = { empty with times = Boolean.atom (x,y) }
62     let arrow x y = { empty with arrow = Boolean.atom (x,y) }
63     let record label opt t = { empty with record = Boolean.atom (label,opt,t) }
64 abate 18 let atom a = { empty with atoms = a }
65     let char c = { empty with chars = c }
66 abate 1 let constant = function
67 abate 52 | Integer i -> interval (Intervals.atom i)
68 abate 18 | Atom a -> atom (Atoms.atom a)
69     | Char c -> char (Chars.atom c)
70 abate 1
71    
72     let any_record = { empty with record = any.record }
73    
74 abate 8 let cup x y =
75 abate 69 if x = y then x else {
76 abate 8 times = Boolean.cup x.times y.times;
77     arrow = Boolean.cup x.arrow y.arrow;
78     record= Boolean.cup x.record y.record;
79     ints = Intervals.cup x.ints y.ints;
80     atoms = Atoms.cup x.atoms y.atoms;
81 abate 13 chars = Chars.cup x.chars y.chars;
82 abate 8 }
83    
84     let cap x y =
85 abate 69 if x = y then x else {
86 abate 8 times = Boolean.cap x.times y.times;
87     record= Boolean.cap x.record y.record;
88     arrow = Boolean.cap x.arrow y.arrow;
89     ints = Intervals.cap x.ints y.ints;
90     atoms = Atoms.cap x.atoms y.atoms;
91 abate 13 chars = Chars.cap x.chars y.chars;
92 abate 8 }
93    
94     let diff x y =
95 abate 69 if x = y then empty else {
96 abate 8 times = Boolean.diff x.times y.times;
97     arrow = Boolean.diff x.arrow y.arrow;
98     record= Boolean.diff x.record y.record;
99     ints = Intervals.diff x.ints y.ints;
100     atoms = Atoms.diff x.atoms y.atoms;
101 abate 13 chars = Chars.diff x.chars y.chars;
102 abate 8 }
103    
104 abate 1 let neg x = diff any x
105    
106     let equal e a b =
107     if a.atoms <> b.atoms then raise NotEqual;
108 abate 13 if a.chars <> b.chars then raise NotEqual;
109 abate 69 if a.ints <> b.ints then raise NotEqual;
110 abate 1 Boolean.equal (fun (x1,x2) (y1,y2) -> e x1 y1; e x2 y2) a.times b.times;
111     Boolean.equal (fun (x1,x2) (y1,y2) -> e x1 y1; e x2 y2) a.arrow b.arrow;
112     Boolean.equal (fun (l1,o1,x1) (l2,o2,x2) ->
113     if (l1 <> l2) || (o1 <> o2) then raise NotEqual;
114     e x1 x2) a.record b.record
115    
116     let map f a =
117     { times = Boolean.map (fun (x1,x2) -> (f x1, f x2)) a.times;
118     arrow = Boolean.map (fun (x1,x2) -> (f x1, f x2)) a.arrow;
119     record= Boolean.map (fun (l,o,x) -> (l,o, f x)) a.record;
120     ints = a.ints;
121     atoms = a.atoms;
122 abate 13 chars = a.chars;
123 abate 1 }
124    
125     let hash h a =
126 abate 69 Hashtbl.hash (map h a)
127     (*
128 abate 60 (Hashtbl.hash { (map h a) with ints = Intervals.empty })
129 abate 15 + (Intervals.hash a.ints)
130 abate 69 *)
131 abate 1
132     let iter f a =
133     ignore (map f a)
134 abate 16
135 abate 1 let deep = 4
136     end
137    
138    
139 abate 67 module Algebra = Recursive_noshare.Make(I)
140 abate 1 include I
141     include Algebra
142 abate 71 module DescrHash =
143     Hashtbl.Make(
144     struct
145     type t = descr
146     let hash = hash_descr
147     let equal = equal_descr
148     end
149     )
150 abate 1
151 abate 71 module DescrMap = Map.Make(struct type t = descr let compare = compare end)
152    
153 abate 1 let check d =
154     Boolean.check d.times;
155     Boolean.check d.arrow;
156     Boolean.check d.record;
157     ()
158    
159     (*
160     let define n d = check d; define n d
161     *)
162    
163     let cons d =
164     let n = make () in
165     define n d;
166     internalize n
167    
168    
169 abate 71 module Print =
170     struct
171     let print_atom ppf a = Format.fprintf ppf "`%s" (atom_name a)
172    
173     let print_const ppf = function
174     | Integer i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
175     | Atom a -> print_atom ppf a
176     | Char c -> Chars.Unichar.print ppf c
177    
178     let named = DescrHash.create 10
179     let register_global name d = DescrHash.add named d name
180    
181     let marks = DescrHash.create 63
182     let wh = ref []
183     let count_name = ref 0
184     let name () =
185     incr count_name;
186     "X" ^ (string_of_int !count_name)
187     (* TODO:
188     check that these generated names does not conflict with declared types *)
189    
190     let bool_iter f b =
191     List.iter (fun (p,n) -> List.iter f p; List.iter f n) b
192    
193     let trivial b = b = Boolean.empty || b = Boolean.full
194    
195     let worth_abbrev d =
196     not (trivial d.times && trivial d.arrow && trivial d.record)
197    
198     let rec mark n = mark_descr (descr n)
199     and mark_descr d =
200     if not (DescrHash.mem named d) then
201     try
202     let r = DescrHash.find marks d in
203     if (!r = None) && (worth_abbrev d) then
204     let na = name () in
205     r := Some na;
206     wh := (na,d) :: !wh
207     with Not_found ->
208     DescrHash.add marks d (ref None);
209     bool_iter (fun (n1,n2) -> mark n1; mark n2) d.times;
210     bool_iter (fun (n1,n2) -> mark n1; mark n2) d.arrow;
211     bool_iter (fun (l,o,n) -> mark n) d.record
212    
213    
214     let rec print_union ppf = function
215     | [] -> Format.fprintf ppf "Empty"
216     | [h] -> h ppf
217     | h::t -> Format.fprintf ppf "@[%t |@ %a@]" h print_union t
218    
219    
220     let rec print ppf n = print_descr ppf (descr n)
221     and print_descr ppf d =
222     try
223     let name = DescrHash.find named d in
224     Format.fprintf ppf "%s" name
225     with Not_found ->
226     try
227     match !(DescrHash.find marks d) with
228     | Some n -> Format.fprintf ppf "%s" n
229     | None -> real_print_descr ppf d
230     with
231     Not_found -> Format.fprintf ppf "XXX"
232     and real_print_descr ppf d =
233     if d = any then Format.fprintf ppf "Any" else
234     print_union ppf
235     (Intervals.print d.ints @
236     Chars.print d.chars @
237     Atoms.print "Atom" print_atom d.atoms @
238     Boolean.print "Pair" print_times d.times @
239     Boolean.print "Arrow" print_arrow d.arrow @
240     Boolean.print "Record" print_record d.record
241     )
242     and print_times ppf (t1,t2) =
243     Format.fprintf ppf "@[(%a,%a)@]" print t1 print t2
244     and print_arrow ppf (t1,t2) =
245     Format.fprintf ppf "@[(%a -> %a)@]" print t1 print t2
246     and print_record ppf (l,o,t) =
247     Format.fprintf ppf "@[{ %s =%s %a }@]"
248     (label_name l) (if o then "?" else "") print t
249    
250    
251     let end_print ppf =
252     (match List.rev !wh with
253     | [] -> ()
254     | (na,d)::t ->
255     Format.fprintf ppf " where@ @[%s = %a" na real_print_descr d;
256     List.iter
257     (fun (na,d) ->
258     Format.fprintf ppf " and@ %s = %a" na real_print_descr d)
259     t;
260     Format.fprintf ppf "@]"
261     );
262     Format.fprintf ppf "@]";
263     count_name := 0;
264     wh := [];
265     DescrHash.clear marks
266    
267     let print_descr ppf d =
268     mark_descr d;
269     Format.fprintf ppf "@[%a" print_descr d;
270     end_print ppf
271    
272     let print ppf n = print_descr ppf (descr n)
273    
274     end
275    
276    
277    
278 abate 1 module Positive =
279     struct
280     type rhs = [ `Type of descr | `Cup of v list | `Times of v * v ]
281     and v = { mutable def : rhs; mutable node : node option }
282    
283    
284     let rec make_descr seen v =
285     if List.memq v seen then empty
286     else
287     let seen = v :: seen in
288     match v.def with
289     | `Type d -> d
290     | `Cup vl ->
291     List.fold_left (fun acc v -> cup acc (make_descr seen v)) empty vl
292     | `Times (v1,v2) -> times (make_node v1) (make_node v2)
293    
294     and make_node v =
295     match v.node with
296     | Some n -> n
297     | None ->
298     let n = make () in
299     v.node <- Some n;
300     let d = make_descr [] v in
301     define n d;
302     n
303    
304     let forward () = { def = `Cup []; node = None }
305     let def v d = v.def <- d
306     let cons d = let v = forward () in def v d; v
307     let ty d = cons (`Type d)
308     let cup vl = cons (`Cup vl)
309     let times d1 d2 = cons (`Times (d1,d2))
310     let define v1 v2 = def v1 (`Cup [v2])
311    
312     let solve v = internalize (make_node v)
313     end
314    
315    
316     let get_record r =
317     let add = SortedMap.add (fun (o1,t1) (o2,t2) -> (o1&&o2, cap t1 t2)) in
318     let line (p,n) =
319     let accu = List.fold_left
320     (fun accu (l,o,t) -> add l (o,descr t) accu) [] p in
321     List.fold_left
322     (fun accu (l,o,t) -> add l (not o,neg (descr t)) accu) accu n in
323     List.map line r
324    
325    
326    
327     (* Subtyping algorithm *)
328    
329     let diff_t d t = diff d (descr t)
330     let cap_t d t = cap d (descr t)
331     let cap_product l =
332     List.fold_left
333     (fun (d1,d2) (t1,t2) -> (cap_t d1 t1, cap_t d2 t2))
334     (any,any)
335     l
336    
337    
338     module Assumptions = Set.Make(struct type t = descr let compare = compare end)
339    
340     let memo = ref Assumptions.empty
341     let cache_false = ref Assumptions.empty
342    
343     exception NotEmpty
344    
345     let rec empty_rec d =
346     if Assumptions.mem d !cache_false then false
347     else if Assumptions.mem d !memo then true
348     else if not (Intervals.is_empty d.ints) then false
349     else if not (Atoms.is_empty d.atoms) then false
350 abate 13 else if not (Chars.is_empty d.chars) then false
351 abate 1 else (
352     let backup = !memo in
353     memo := Assumptions.add d backup;
354     if
355     (empty_rec_times d.times) &&
356     (empty_rec_arrow d.arrow) &&
357     (empty_rec_record d.record)
358     then true
359     else (
360     memo := backup;
361     cache_false := Assumptions.add d !cache_false;
362     false
363     )
364     )
365    
366     and empty_rec_times c =
367     List.for_all empty_rec_times_aux c
368    
369     and empty_rec_times_aux (left,right) =
370     let rec aux accu1 accu2 = function
371     | (t1,t2)::right ->
372     let accu1' = diff_t accu1 t1 in
373     if not (empty_rec accu1') then aux accu1' accu2 right;
374     let accu2' = diff_t accu2 t2 in
375     if not (empty_rec accu2') then aux accu1 accu2' right
376     | [] -> raise NotEmpty
377     in
378     let (accu1,accu2) = cap_product left in
379     (empty_rec accu1) || (empty_rec accu2) ||
380     (try aux accu1 accu2 right; true with NotEmpty -> false)
381    
382     and empty_rec_arrow c =
383     List.for_all empty_rec_arrow_aux c
384    
385     and empty_rec_arrow_aux (left,right) =
386     let single_right (s1,s2) =
387     let rec aux accu1 accu2 = function
388     | (t1,t2)::left ->
389     let accu1' = diff_t accu1 t1 in
390     if not (empty_rec accu1') then aux accu1 accu2 left;
391     let accu2' = cap_t accu2 t2 in
392     if not (empty_rec accu2') then aux accu1 accu2 left
393     | [] -> raise NotEmpty
394     in
395     let accu1 = descr s1 in
396     (empty_rec accu1) ||
397     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
398     in
399     List.exists single_right right
400    
401     and empty_rec_record c =
402     let aux = List.exists (fun (_,(opt,t)) -> (not opt) && (empty_rec t)) in
403     List.for_all aux (get_record c)
404    
405     let is_empty d =
406 abate 20 let old = !memo in
407 abate 1 let r = empty_rec d in
408 abate 20 if not r then memo := old;
409 abate 22 (* cache_false := Assumptions.empty; *)
410 abate 1 r
411    
412     let non_empty d =
413     not (is_empty d)
414    
415     let subtype d1 d2 =
416     is_empty (diff d1 d2)
417    
418     (* Sample value *)
419     module Sample =
420     struct
421    
422     let rec find f = function
423     | [] -> raise Not_found
424     | x::r -> try f x with Not_found -> find f r
425    
426     type t =
427 abate 15 | Int of Big_int.big_int
428 abate 1 | Atom of atom
429 abate 13 | Char of Chars.Unichar.t
430 abate 1 | Pair of t * t
431     | Record of (label * t) list
432     | Fun of (node * node) list
433    
434     let rec gen_atom i l =
435     if SortedList.mem l i then gen_atom (succ i) l else i
436    
437     let rec sample_rec memo d =
438     if (Assumptions.mem d memo) || (is_empty d) then raise Not_found
439     else
440     try Int (Intervals.sample d.ints) with Not_found ->
441     try Atom (Atoms.sample (gen_atom 0) d.atoms) with Not_found ->
442 abate 13 try Char (Chars.sample d.chars) with Not_found ->
443 abate 1 try sample_rec_arrow d.arrow with Not_found ->
444    
445     let memo = Assumptions.add d memo in
446     try sample_rec_times memo d.times with Not_found ->
447     try sample_rec_record memo d.record with Not_found ->
448     raise Not_found
449    
450    
451     and sample_rec_times memo c =
452     find (sample_rec_times_aux memo) c
453    
454     and sample_rec_times_aux memo (left,right) =
455     let rec aux accu1 accu2 = function
456     | (t1,t2)::right ->
457     let accu1' = diff_t accu1 t1 in
458     if non_empty accu1' then aux accu1' accu2 right else
459     let accu2' = diff_t accu2 t2 in
460     if non_empty accu2' then aux accu1 accu2' right else
461     raise Not_found
462     | [] -> Pair (sample_rec memo accu1, sample_rec memo accu2)
463     in
464     let (accu1,accu2) = cap_product left in
465     if (is_empty accu1) || (is_empty accu2) then raise Not_found;
466     aux accu1 accu2 right
467    
468     and sample_rec_arrow c =
469     find sample_rec_arrow_aux c
470    
471 abate 10 and check_empty_simple_arrow_line left (s1,s2) =
472     let rec aux accu1 accu2 = function
473     | (t1,t2)::left ->
474     let accu1' = diff_t accu1 t1 in
475     if non_empty accu1' then aux accu1 accu2 left;
476     let accu2' = cap_t accu2 t2 in
477     if non_empty accu2' then aux accu1 accu2 left
478     | [] -> raise NotEmpty
479     in
480     let accu1 = descr s1 in
481     (is_empty accu1) ||
482     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
483    
484     and check_empty_arrow_line left right =
485     List.exists (check_empty_simple_arrow_line left) right
486    
487 abate 1 and sample_rec_arrow_aux (left,right) =
488 abate 10 if (check_empty_arrow_line left right) then raise Not_found
489 abate 1 else Fun left
490    
491    
492     and sample_rec_record memo c =
493     Record (find (sample_rec_record_aux memo) (get_record c))
494    
495     and sample_rec_record_aux memo fields =
496     let aux acc (l,(o,t)) = if o then acc else (l, sample_rec memo t) :: acc in
497     List.fold_left aux [] fields
498    
499     let get x = sample_rec Assumptions.empty x
500 abate 10
501 abate 71 let rec print_sep f sep ppf = function
502     | [] -> ()
503     | [x] -> f ppf x
504     | x::rem -> f ppf x; Format.fprintf ppf "%s" sep; print_sep f sep ppf rem
505    
506    
507     let rec print ppf = function
508     | Int i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
509     | Atom a -> Format.fprintf ppf "`%s" (atom_name a)
510     | Char c -> Chars.Unichar.print ppf c
511     | Pair (x1,x2) -> Format.fprintf ppf "(%a,%a)" print x1 print x2
512     | Record r ->
513     Format.fprintf ppf "{ %a }"
514     (print_sep
515     (fun ppf (l,x) ->
516     Format.fprintf ppf "%s = %a"
517     (label_name l)
518     print x
519     )
520     " ; "
521     ) r
522     | Fun iface ->
523     Format.fprintf ppf "(fun ( %a ) x -> ...)"
524     (print_sep
525     (fun ppf (t1,t2) ->
526     Format.fprintf ppf "%a -> %a; "
527     Print.print t1 Print.print t2
528     )
529     " ; "
530     ) iface
531 abate 1 end
532    
533    
534     module Product =
535     struct
536     type t = (descr * descr) list
537    
538 abate 17 let other d = { d with times = empty.times }
539     let is_product d = is_empty (other d)
540    
541 abate 19 let need_second = function _::_::_ -> true | _ -> false
542    
543 abate 71 let normal_aux d =
544     let res = ref [] in
545    
546     let add (t1,t2) =
547     let rec loop t1 t2 = function
548     | [] -> res := (ref (t1,t2)) :: !res
549     | ({contents = (d1,d2)} as r)::l ->
550     (*OPT*)
551     if d1 = t1 then r := (d1,cup d2 t2) else
552    
553     let i = cap t1 d1 in
554     if is_empty i then loop t1 t2 l
555     else (
556     r := (i, cup t2 d2);
557     let k = diff d1 t1 in
558     if non_empty k then res := (ref (k,d2)) :: !res;
559    
560     let j = diff t1 d1 in
561     if non_empty j then loop j t2 l
562     )
563     in
564     loop t1 t2 !res
565     in
566     List.iter add d;
567     List.map (!) !res
568    
569     (*
570     This version explodes when dealing with
571     Any - [ t1? t2? t3? ... tn? ]
572     ==> need partitioning
573     *)
574     let get_aux d =
575 abate 1 let line accu (left,right) =
576 abate 71 let debug = List.length right = 28 in
577 abate 1 let rec aux accu d1 d2 = function
578     | (t1,t2)::right ->
579     let accu =
580     let d1 = diff_t d1 t1 in
581     if is_empty d1 then accu else aux accu d1 d2 right in
582     let accu =
583     let d2 = diff_t d2 t2 in
584     if is_empty d2 then accu else aux accu d1 d2 right in
585     accu
586 abate 71 | [] -> (d1,d2) :: accu
587 abate 1 in
588     let (d1,d2) = cap_product left in
589     if (is_empty d1) || (is_empty d2) then accu else aux accu d1 d2 right
590     in
591 abate 71 List.fold_left line [] d
592 abate 1
593 abate 74 (* Partitioning:
594 abate 71
595 abate 74 (t,s) - ((t1,s1) | (t2,s2) | ... | (tn,sn))
596     =
597     (t & t1, s - s1) | ... | (t & tn, s - sn) | (t - (t1|...|tn), s)
598    
599     *)
600    
601 abate 71 let get_aux d =
602     let accu = ref [] in
603     let line (left,right) =
604     let (d1,d2) = cap_product left in
605     if (non_empty d1) && (non_empty d2) then
606     let right = List.map (fun (t1,t2) -> descr t1, descr t2) right in
607     let right = normal_aux right in
608     let resid1 = ref d1 in
609     let () =
610     List.iter
611     (fun (t1,t2) ->
612     let t1 = cap d1 t1 in
613     if (non_empty t1) then
614     let () = resid1 := diff !resid1 t1 in
615     let t2 = diff d2 t2 in
616     if (non_empty t2) then accu := (t1,t2) :: !accu
617     ) right in
618     if non_empty !resid1 then accu := (!resid1, d2) :: !accu
619     in
620     List.iter line d;
621     !accu
622    
623     let get d = get_aux d.times
624    
625 abate 1 let pi1 = List.fold_left (fun acc (t1,_) -> cup acc t1) empty
626     let pi2 = List.fold_left (fun acc (_,t2) -> cup acc t2) empty
627    
628     let restrict_1 rects pi1 =
629     let aux accu (t1,t2) =
630     let t1 = cap t1 pi1 in if is_empty t1 then accu else (t1,t2)::accu in
631     List.fold_left aux [] rects
632    
633     type normal = t
634    
635 abate 71 module Memo = Map.Make(struct
636     type t = (node * node) Boolean.t
637     let compare = compare end)
638    
639 abate 1
640    
641 abate 71 let memo = ref Memo.empty
642     let normal d =
643     let d = d.times in
644     try Memo.find d !memo
645     with
646     Not_found ->
647     let gd = get_aux d in
648     let n = normal_aux gd in
649     memo := Memo.add d n !memo;
650     n
651    
652 abate 1 let any = { empty with times = any.times }
653 abate 19 let is_empty d = d = []
654 abate 1 end
655    
656    
657     module Record =
658     struct
659     type t = (label, (bool * descr)) SortedMap.t list
660    
661     let get d =
662     let line r = List.for_all (fun (l,(o,d)) -> o || non_empty d) r in
663     List.filter line (get_record d.record)
664    
665     let restrict_label_present t l =
666 abate 29 let restr = function
667     | (true, d) -> if non_empty d then (false,d) else raise Exit
668     | x -> x in
669     let aux accu r =
670     try SortedMap.change l restr (false,any) r :: accu
671     with Exit -> accu in
672     List.fold_left aux [] t
673 abate 1
674     let restrict_label_absent t l =
675     let restr = function (true, _) -> (true,empty) | _ -> raise Exit in
676     let aux accu r =
677     try SortedMap.change l restr (true,empty) r :: accu
678     with Exit -> accu in
679     List.fold_left aux [] t
680    
681     let restrict_field t l d =
682     let restr (_,d1) =
683     let d1 = cap d d1 in
684     if is_empty d1 then raise Exit else (false,d1) in
685     let aux accu r =
686     try SortedMap.change l restr (false,d) r :: accu
687     with Exit -> accu in
688     List.fold_left aux [] t
689    
690     let project_field t l =
691     let aux accu x =
692     match List.assoc l x with
693     | (false,t) -> cup accu t
694     | _ -> raise Not_found
695     in
696     List.fold_left aux empty t
697    
698 abate 29 let project d l =
699     project_field (get_record d.record) l
700    
701 abate 1 type normal =
702     [ `Success
703     | `Fail
704     | `Label of label * (descr * normal) list * normal ]
705    
706     let rec merge_record n r =
707     match (n, r) with
708     | (`Success, _) | (_, []) -> `Success
709     | (`Fail, r) ->
710 abate 75 let aux (l,(o,t)) n =
711     `Label (l, [t,n], if o then n else `Fail) in
712 abate 1 List.fold_right aux r `Success
713     | (`Label (l1,present,absent), (l2,(o,t2))::r') ->
714     if (l1 < l2) then
715     let pr = List.map (fun (t,x) -> (t, merge_record x r)) present in
716 abate 75 let t = List.fold_left (fun a (t,_) -> diff a t) any present in
717     let pr =
718     if non_empty t then (t, merge_record `Fail r) :: pr
719     else pr in
720 abate 1 `Label (l1,pr,merge_record absent r)
721     else if (l2 < l1) then
722     let n' = merge_record n r' in
723     `Label (l2, [t2, n'], if o then n' else n)
724     else
725     let res = ref [] in
726     let aux a (t,x) =
727     (let t = diff t t2 in
728     if non_empty t then res := (t,x) :: !res);
729     (let t = cap t t2 in
730     if non_empty t then res := (t, merge_record x r') :: !res);
731     diff a t
732     in
733     let t2 = List.fold_left aux t2 present in
734     let () =
735     if non_empty t2 then
736     res := (t2, merge_record `Fail r') :: !res in
737     let abs = if o then merge_record absent r' else absent in
738     `Label (l1, !res, abs)
739    
740 abate 75 module Unify = Map.Make(struct type t = normal let compare = compare end)
741 abate 1
742 abate 75 let repository = ref Unify.empty
743    
744     let rec canonize = function
745     | `Label (l,pr,ab) as x ->
746     (try Unify.find x !repository
747     with Not_found ->
748     let pr = List.map (fun (t,n) -> canonize n,t) pr in
749     let pr = SortedMap.from_list cup pr in
750     let pr = List.map (fun (n,t) -> (t,n)) pr in
751     let x = `Label (l, pr, canonize ab) in
752     try Unify.find x !repository
753     with Not_found -> repository := Unify.add x x !repository; x
754     )
755     | x -> x
756    
757 abate 1 let normal d =
758 abate 75 let r = canonize (List.fold_left merge_record `Fail (get d)) in
759     repository := Unify.empty;
760     r
761 abate 1
762 abate 75 type normal' =
763     [ `Success
764     | `Label of label * (descr * descr) list * descr option ] option
765 abate 1
766 abate 75 (* NOTE: this function relies on the fact that generic order
767     makes smallest labels appear first *)
768    
769     let first_label d =
770     let d = d.record in
771     let min = ref None in
772     let lab (l,o,t) = match !min with
773     | Some l' when l >= l' -> ()
774     | _ -> if o && (descr t = any) then () else min := Some l in
775     let line (p,n) =
776     (match p with f::_ -> lab f | _ -> ());
777     (match n with f::_ -> lab f | _ -> ()) in
778     List.iter line d;
779     match !min with
780     | None -> if d = [] then `Empty else `Any
781     | Some l -> `Label l
782    
783     let normal' (d : descr) l =
784     let ab = ref empty in
785     let rec extract f = function
786     | (l',o,t) :: rem when l = l' ->
787     f o (descr t); extract f rem
788     | x :: rem -> x :: (extract f rem)
789     | [] -> [] in
790     let line (p,n) =
791     let ao = ref true and ad = ref any in
792     let p =
793     extract (fun o d -> ao := !ao && o; ad := cap !ad d) p
794     and n =
795     extract (fun o d -> ao := !ao && not o; ad := diff !ad d) n
796     in
797     (* Note: p and n are still sorted *)
798     let d = { empty with record = [(p,n)] } in
799     if !ao then ab := cup d !ab;
800     (!ad, d) in
801     let pr = List.map line d.record in
802     let pr = Product.normal_aux pr in
803     let ab = if is_empty !ab then None else Some !ab in
804     (pr, ab)
805    
806    
807 abate 1 let any = { empty with record = any.record }
808     let is_empty d = d = []
809 abate 75 let descr l =
810     let line l = map_sort (fun (l,(o,d)) -> (l,o,cons d)) l, [] in
811     { empty with record = map_sort line l }
812 abate 1 end
813    
814    
815 abate 29
816 abate 71 let memo_normalize = ref DescrMap.empty
817 abate 1
818    
819     let rec rec_normalize d =
820 abate 71 try DescrMap.find d !memo_normalize
821 abate 1 with Not_found ->
822     let n = make () in
823 abate 71 memo_normalize := DescrMap.add d n !memo_normalize;
824 abate 1 let times =
825     map_sort
826     (fun (d1,d2) -> [(rec_normalize d1, rec_normalize d2)],[])
827     (Product.normal d)
828     in
829     let record =
830     map_sort
831     (fun f -> map_sort (fun (l,(o,d)) -> (l,o,rec_normalize d)) f, [])
832     (Record.get d)
833     in
834     define n { d with times = times; record = record };
835     n
836    
837     let normalize n =
838 abate 29 descr (internalize (rec_normalize n))
839 abate 6
840 abate 11 module Arrow =
841     struct
842 abate 19 let check_simple left s1 s2 =
843     let rec aux accu1 accu2 = function
844     | (t1,t2)::left ->
845     let accu1' = diff_t accu1 t1 in
846 abate 45 if non_empty accu1' then aux accu1 accu2 left;
847 abate 19 let accu2' = cap_t accu2 t2 in
848 abate 45 if non_empty accu2' then aux accu1 accu2 left
849 abate 19 | [] -> raise NotEmpty
850     in
851     let accu1 = descr s1 in
852     (is_empty accu1) ||
853     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
854    
855     let check_strenghten t s =
856     let left = match t.arrow with [ (p,[]) ] -> p | _ -> assert false in
857     let rec aux = function
858     | [] -> raise Not_found
859     | (p,n) :: rem ->
860     if (List.for_all (fun (a,b) -> check_simple left a b) p) &&
861     (List.for_all (fun (a,b) -> not (check_simple left a b)) n) then
862     { empty with arrow = [ (SortedList.cup left p, n) ] }
863     else aux rem
864     in
865     aux s.arrow
866    
867 abate 45 let check_simple_iface left s1 s2 =
868     let rec aux accu1 accu2 = function
869     | (t1,t2)::left ->
870     let accu1' = diff accu1 t1 in
871     if non_empty accu1' then aux accu1 accu2 left;
872     let accu2' = cap accu2 t2 in
873     if non_empty accu2' then aux accu1 accu2 left
874     | [] -> raise NotEmpty
875     in
876     let accu1 = descr s1 in
877     (is_empty accu1) ||
878     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
879    
880     let check_iface iface s =
881     let rec aux = function
882     | [] -> false
883     | (p,n) :: rem ->
884     ((List.for_all (fun (a,b) -> check_simple_iface iface a b) p) &&
885     (List.for_all (fun (a,b) -> not (check_simple_iface iface a b)) n))
886     || (aux rem)
887     in
888     aux s.arrow
889    
890 abate 11 type t = descr * (descr * descr) list list
891    
892     let get t =
893     List.fold_left
894     (fun ((dom,arr) as accu) (left,right) ->
895     if Sample.check_empty_arrow_line left right
896     then accu
897     else (
898     let left =
899     List.map
900     (fun (t,s) -> (descr t, descr s)) left in
901     let d = List.fold_left (fun d (t,_) -> cup d t) empty left in
902     (cap dom d, left :: arr)
903     )
904     )
905     (any, [])
906     t.arrow
907    
908     let domain (dom,_) = dom
909    
910     let apply_simple t result left =
911     let rec aux result accu1 accu2 = function
912     | (t1,s1)::left ->
913     let result =
914     let accu1 = diff accu1 t1 in
915     if non_empty accu1 then aux result accu1 accu2 left
916     else result in
917     let result =
918     let accu2 = cap accu2 s1 in
919     aux result accu1 accu2 left in
920     result
921     | [] ->
922     if subtype accu2 result
923     then result
924     else cup result accu2
925     in
926     aux result t any left
927    
928     let apply (_,arr) t =
929     List.fold_left (apply_simple t) empty arr
930    
931 abate 19 let need_arg (dom, arr) =
932     List.exists (function [_] -> false | _ -> true) arr
933    
934     let apply_noarg (_,arr) =
935     List.fold_left
936     (fun accu ->
937     function
938     | [(t,s)] -> cup accu s
939     | _ -> assert false
940     )
941     empty arr
942    
943 abate 11 let any = { empty with arrow = any.arrow }
944 abate 19 let is_empty (_,arr) = arr = []
945 abate 11 end
946    
947    
948 abate 16 module Int = struct
949 abate 45 let has_int d i = Intervals.contains i d.ints
950    
951 abate 16 let get d = d.ints
952     let put i = { empty with ints = i }
953     let is_int d = is_empty { d with ints = Intervals.empty }
954     let any = { empty with ints = Intervals.any }
955     end
956 abate 11
957 abate 17 module Atom = struct
958     let has_atom d a = Atoms.contains a d.atoms
959     end
960    
961 abate 45 module Char = struct
962     let has_char d c = Chars.contains c d.chars
963 abate 58 let any = { empty with chars = Chars.any }
964 abate 45 end
965    
966 abate 1 (*
967     let rec print_normal_record ppf = function
968     | Success -> Format.fprintf ppf "Yes"
969     | Fail -> Format.fprintf ppf "No"
970     | FirstLabel (l,present,absent) ->
971     Format.fprintf ppf "%s?@[<v>@\n" (label_name l);
972     List.iter
973     (fun (t,n) ->
974     Format.fprintf ppf "(%a)=>@[%a@]@\n"
975     Print.print_descr t
976     print_normal_record n
977     ) present;
978     if absent <> Fail then
979     Format.fprintf ppf "(absent)=>@[%a@]@\n" print_normal_record absent;
980     Format.fprintf ppf "@]"
981     *)
982    
983    
984     (*
985     let pr s = Types.Print.print Format.std_formatter (Syntax.make_type (Syntax.parse s));;
986    
987     let pr' s = Types.Print.print Format.std_formatter
988     (Types.normalize (Syntax.make_type (Syntax.parse s)));;
989    
990     BUG:
991     pr "'a | 'b where 'a = ('a , 'a) and 'b= ('b , 'b)";;
992     *)
993    
994    
995     (*
996     let nr s =
997     let t = Types.descr (Syntax.make_type (Syntax.parse s)) in
998     let n = Types.normal_record' t.Types.record in
999     Types.print_normal_record Format.std_formatter n;;
1000     *)

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5