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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 149 - (hide annotations)
Tue Jul 10 17:10:34 2007 UTC (5 years, 11 months ago) by abate
File size: 30978 byte(s)
[r2002-11-24 20:44:12 by cvscast] Empty log message

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

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