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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 221 - (hide annotations)
Tue Jul 10 17:15:42 2007 UTC (5 years, 10 months ago) by abate
File size: 42340 byte(s)
[r2003-03-07 00:18:35 by cvscast] Empty log message

Original author: cvscast
Date: 2003-03-07 00:18:35+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 220 type descr = {
26     atoms : atom Atoms.t;
27     ints : Intervals.t;
28     chars : Chars.t;
29     times : (node * node) Boolean.t;
30     xml : (node * node) Boolean.t;
31     arrow : (node * node) Boolean.t;
32     record: (bool * (label, (bool * node)) SortedMap.t) Boolean.t;
33     } and node = {
34     id : int;
35     mutable descr : descr;
36     }
37 abate 15
38 abate 1
39 abate 220 let empty = {
40     times = Boolean.empty;
41     xml = Boolean.empty;
42     arrow = Boolean.empty;
43     record= Boolean.empty;
44     ints = Intervals.empty;
45     atoms = Atoms.empty;
46     chars = Chars.empty;
47     }
48    
49     let any = {
50     times = Boolean.full;
51     xml = Boolean.full;
52     arrow = Boolean.full;
53     record= Boolean.full;
54     ints = Intervals.any;
55     atoms = Atoms.any;
56     chars = Chars.any;
57     }
58    
59    
60     let interval i = { empty with ints = i }
61     let times x y = { empty with times = Boolean.atom (x,y) }
62     let xml x y = { empty with xml = Boolean.atom (x,y) }
63     let arrow x y = { empty with arrow = Boolean.atom (x,y) }
64     let record label opt t =
65     { empty with record = Boolean.atom (true,[label,(opt,t)]) }
66     let record' x =
67     { empty with record = Boolean.atom x }
68     let atom a = { empty with atoms = a }
69     let char c = { empty with chars = c }
70     let constant = function
71     | Integer i -> interval (Intervals.atom i)
72     | Atom a -> atom (Atoms.atom a)
73     | Char c -> char (Chars.atom c)
74 abate 8
75 abate 220 let cup x y =
76     if x == y then x else {
77     times = Boolean.cup x.times y.times;
78     xml = Boolean.cup x.xml y.xml;
79     arrow = Boolean.cup x.arrow y.arrow;
80     record= Boolean.cup x.record y.record;
81     ints = Intervals.cup x.ints y.ints;
82     atoms = Atoms.cup x.atoms y.atoms;
83     chars = Chars.cup x.chars y.chars;
84     }
85    
86     let cap x y =
87     if x == y then x else {
88     times = Boolean.cap x.times y.times;
89     xml = Boolean.cap x.xml y.xml;
90     record= Boolean.cap x.record y.record;
91     arrow = Boolean.cap x.arrow y.arrow;
92     ints = Intervals.cap x.ints y.ints;
93     atoms = Atoms.cap x.atoms y.atoms;
94     chars = Chars.cap x.chars y.chars;
95     }
96    
97     let diff x y =
98     if x == y then empty else {
99     times = Boolean.diff x.times y.times;
100     xml = Boolean.diff x.xml y.xml;
101     arrow = Boolean.diff x.arrow y.arrow;
102     record= Boolean.diff x.record y.record;
103     ints = Intervals.diff x.ints y.ints;
104     atoms = Atoms.diff x.atoms y.atoms;
105     chars = Chars.diff x.chars y.chars;
106     }
107    
108     let count = ref 0
109     let make () = incr count; { id = !count; descr = empty }
110     let define n d = n.descr <- d
111     let cons d = incr count; { id = !count; descr = d }
112     let descr n = n.descr
113     let internalize n = n
114     let id n = n.id
115    
116     let rec equal_rec r1 r2 =
117     (r1 == r2) ||
118     match (r1,r2) with
119 abate 156 | (l1,(o1,x1))::r1,(l2,(o2,x2))::r2 ->
120 abate 219 (l1 = l2) && (o1 = o2) && (x1.id = x2.id) && (equal_rec r1 r2)
121     | _ -> false
122 abate 220
123     let rec equal_rec_list l1 l2 =
124     (l1 == l2) ||
125     match (l1,l2) with
126     | (o1,r1)::l1, (o2,r2)::l2 ->
127     (o1 = o2) &&
128     (equal_rec r1 r2)
129     | _ -> false
130    
131     let rec equal_rec_bool l1 l2 =
132     (l1 == l2) ||
133     match (l1,l2) with
134     | (p1,n1)::l1, (p2,n2)::l2 ->
135     (equal_rec_list p1 p2) &&
136     (equal_rec_list n1 n2) &&
137     (equal_rec_bool l1 l2)
138     | _ -> false
139    
140     let rec equal_times_list l1 l2 =
141     (l1 == l2) ||
142     match (l1,l2) with
143     | (x1,y1)::l1, (x2,y2)::l2 ->
144     (x1.id = x2.id) &&
145     (y1.id = y2.id) &&
146     (equal_times_list l1 l2)
147     | _ -> false
148    
149     let rec equal_times_bool l1 l2 =
150     (l1 == l2) ||
151     match (l1,l2) with
152     | (p1,n1)::l1, (p2,n2)::l2 ->
153     (equal_times_list p1 p2) &&
154     (equal_times_list n1 n2) &&
155     (equal_times_bool l1 l2)
156     | _ -> false
157    
158     let equal_descr a b =
159     (a.atoms = b.atoms) &&
160     (a.chars = b.chars) &&
161     (a.ints = b.ints) &&
162     (equal_times_bool a.times b.times) &&
163     (equal_times_bool a.xml b.xml) &&
164     (equal_times_bool a.arrow b.arrow) &&
165     (equal_rec_bool a.record b.record)
166    
167     let rec hash_times_list accu = function
168     | (x,y)::l ->
169     hash_times_list (accu * 257 + x.id * 17 + y.id) l
170     | [] -> accu + 17
171    
172     let rec hash_times_bool accu = function
173     | (p,n)::l ->
174     hash_times_bool (hash_times_list (hash_times_list accu p) n) l
175     | [] -> accu + 3
176    
177     let rec hash_rec accu = function
178     | (l,(o,x))::rem ->
179     hash_rec (257 * accu + 17 * (LabelPool.hash l) + x.id) rem
180     | [] -> accu + 5
181    
182     let rec hash_rec_list accu = function
183     | (o,r)::l ->
184     hash_rec_list (hash_rec accu r) l
185     | [] -> accu + 17
186    
187     let rec hash_rec_bool accu = function
188     | (p,n)::l ->
189     hash_rec_bool (hash_rec_list (hash_rec_list accu p) n) l
190     | [] -> accu + 3
191    
192    
193     let hash_descr a =
194     let accu =
195     (Hashtbl.hash a.ints) + 17 * (Hashtbl.hash a.atoms) +
196     257 * (Hashtbl.hash a.chars) in
197     let accu = hash_times_bool accu a.times in
198     let accu = hash_times_bool accu a.xml in
199     let accu = hash_times_bool accu a.arrow in
200     let accu = hash_rec_bool accu a.record in
201     accu
202 abate 156
203 abate 71 module DescrHash =
204     Hashtbl.Make(
205     struct
206     type t = descr
207     let hash = hash_descr
208     let equal = equal_descr
209     end
210     )
211 abate 1
212 abate 131 let print_descr = ref (fun _ _ -> assert false)
213    
214 abate 110 let neg x = diff any x
215    
216 abate 165 let any_node = cons any
217    
218 abate 156 module LabelSet = Set.Make(LabelPool)
219 abate 110
220 abate 156 let get_record r =
221     let labs accu (_,r) =
222     List.fold_left (fun accu (l,_) -> LabelSet.add l accu) accu r in
223     let extend (opts,descrs) labs (o,r) =
224     let rec aux i labs r =
225     match labs with
226     | [] -> ()
227     | l1::labs ->
228     match r with
229     | (l2,(o,x))::r when l1 = l2 ->
230     descrs.(i) <- cap descrs.(i) (descr x);
231     opts.(i) <- opts.(i) && o;
232     aux (i+1) labs r
233     | r ->
234     if not o then descrs.(i) <- empty;
235     aux (i+1) labs r
236     in
237     aux 0 labs r;
238     o
239     in
240     let line (p,n) =
241     let labels =
242     List.fold_left labs (List.fold_left labs LabelSet.empty p) n in
243     let labels = LabelSet.elements labels in
244     let nlab = List.length labels in
245     let mk () = Array.create nlab true, Array.create nlab any in
246    
247     let pos = mk () in
248     let opos = List.fold_left
249     (fun accu x ->
250     (extend pos labels x) && accu)
251     true p in
252     let p = (opos, pos) in
253    
254     let n = List.map (fun x ->
255     let neg = mk () in
256     let o = extend neg labels x in
257     (o,neg)
258     ) n in
259     (labels,p,n)
260     in
261     List.map line r
262    
263    
264 abate 71 module DescrMap = Map.Make(struct type t = descr let compare = compare end)
265    
266 abate 1 let check d =
267     Boolean.check d.times;
268 abate 110 Boolean.check d.xml;
269 abate 1 Boolean.check d.arrow;
270     Boolean.check d.record;
271     ()
272    
273 abate 110
274    
275     (* Subtyping algorithm *)
276    
277     let diff_t d t = diff d (descr t)
278     let cap_t d t = cap d (descr t)
279     let cup_t d t = cup d (descr t)
280     let cap_product l =
281     List.fold_left
282     (fun (d1,d2) (t1,t2) -> (cap_t d1 t1, cap_t d2 t2))
283     (any,any)
284     l
285    
286 abate 156 let rec exists max f =
287     (max > 0) && (f (max - 1) || exists (max - 1) f)
288 abate 110
289 abate 221 let trivially_empty d = equal_descr d empty
290 abate 156
291 abate 221 exception NotEmpty
292    
293     type slot = { mutable status : status;
294     mutable notify : notify;
295     mutable active : bool }
296     and status = Empty | NEmpty | Maybe
297     and notify = Nothing | Do of slot * (slot -> unit) * notify
298    
299     let memo = DescrHash.create 33000
300    
301     let marks = ref []
302     let slot_empty = { status = Empty; active = false; notify = Nothing }
303     let slot_not_empty = { status = NEmpty; active = false; notify = Nothing }
304    
305     let rec notify = function
306     | Nothing -> ()
307     | Do (n,f,rem) ->
308     if n.status = Maybe then (try f n with NotEmpty -> ());
309     notify rem
310    
311     let rec iter_s s f = function
312     | [] -> ()
313     | arg::rem -> f arg s; iter_s s f rem
314    
315    
316     let set s =
317     s.status <- NEmpty;
318     notify s.notify;
319     raise NotEmpty
320    
321     let rec big_conj f l n =
322     match l with
323     | [] -> set n
324     | [arg] -> f arg n
325     | arg::rem ->
326     let s = { status = Maybe; active = false; notify = Do (n,(big_conj f rem), Nothing) } in
327     try
328     f arg s;
329     if s.active then n.active <- true
330     with NotEmpty -> if n.status = NEmpty then raise NotEmpty
331    
332     let rec guard a f n =
333     let s = slot a in
334     match s.status with
335     | Empty -> ()
336     | Maybe -> n.active <- true; s.notify <- Do (n,f,s.notify)
337     | NEmpty -> f n
338    
339     and slot d =
340     if not ((Intervals.is_empty d.ints) &&
341     (Atoms.is_empty d.atoms) &&
342     (Chars.is_empty d.chars)) then slot_not_empty
343     else try DescrHash.find memo d
344     with Not_found ->
345     let s = { status = Maybe; active = false; notify = Nothing } in
346     DescrHash.add memo d s;
347     (try
348     iter_s s check_times d.times;
349     iter_s s check_times d.xml;
350     iter_s s check_arrow d.arrow;
351     iter_s s check_record (get_record d.record);
352     if s.active then marks := s :: !marks else s.status <- Empty;
353     with
354     NotEmpty -> ());
355     s
356    
357     and check_times (left,right) s =
358     let rec aux accu1 accu2 right s = match right with
359     | (t1,t2)::right ->
360     if trivially_empty (cap_t accu1 t1) ||
361     trivially_empty (cap_t accu2 t2) then
362     aux accu1 accu2 right s
363     else
364     let accu1' = diff_t accu1 t1 in guard accu1' (aux accu1' accu2 right) s;
365     let accu2' = diff_t accu2 t2 in guard accu2' (aux accu1 accu2' right) s
366     | [] -> set s
367     in
368     let (accu1,accu2) = cap_product left in
369     guard accu1 (guard accu2 (aux accu1 accu2 right)) s
370    
371     and check_arrow (left,right) s =
372     let single_right (s1,s2) s =
373     let rec aux accu1 accu2 left s = match left with
374     | (t1,t2)::left ->
375     let accu1' = diff_t accu1 t1 in guard accu1' (aux accu1' accu2 left) s;
376     let accu2' = cap_t accu2 t2 in guard accu2' (aux accu1 accu2' left) s
377     | [] -> set s
378     in
379     let accu1 = descr s1 in
380     guard accu1 (aux accu1 (neg (descr s2)) left) s
381     in
382     big_conj single_right right s
383    
384     and check_record (labels,(oleft,(left_opt,left)),rights) s =
385     let rec aux rights s = match rights with
386     | [] -> set s
387     | (oright,(right_opt,right))::rights ->
388     let next =
389     (oleft && (not oright)) ||
390     exists (Array.length left)
391     (fun i ->
392     (not (left_opt.(i) && right_opt.(i))) &&
393     (trivially_empty (cap left.(i) right.(i))))
394     in
395     if next then aux rights s
396     else
397     for i = 0 to Array.length left - 1 do
398     let back = left.(i) in
399     let oback = left_opt.(i) in
400     let odi = oback && (not right_opt.(i)) in
401     let di = diff back right.(i) in
402     if odi then (
403     left.(i) <- diff back right.(i);
404     left_opt.(i) <- odi;
405     aux rights s;
406     left.(i) <- back;
407     left_opt.(i) <- oback;
408     ) else
409     guard di (fun s ->
410     left.(i) <- diff back right.(i);
411     left_opt.(i) <- odi;
412     aux rights s;
413     left.(i) <- back;
414     left_opt.(i) <- oback;
415     ) s
416     done
417     in
418     let rec start i s =
419     if (i < 0) then aux rights s
420     else
421     if left_opt.(i) then start (i - 1) s
422     else guard left.(i) (start (i - 1)) s
423     in
424     start (Array.length left - 1) s
425    
426    
427     let is_empty d =
428     let s = slot d in
429     List.iter
430     (fun s' -> if s'.status = Maybe then s'.status <- Empty; s'.notify <- Nothing)
431     !marks;
432     marks := [];
433     s.status = Empty
434    
435    
436 abate 110 module Assumptions = Set.Make(struct type t = descr let compare = compare end)
437     let memo = ref Assumptions.empty
438 abate 220 let cache_false = DescrHash.create 33000
439 abate 110
440     let rec empty_rec d =
441 abate 221 if not (Intervals.is_empty d.ints) then false
442 abate 110 else if not (Atoms.is_empty d.atoms) then false
443     else if not (Chars.is_empty d.chars) then false
444 abate 221 else if DescrHash.mem cache_false d then false
445     else if Assumptions.mem d !memo then true
446 abate 110 else (
447     let backup = !memo in
448 abate 188 memo := Assumptions.add d backup;
449 abate 110 if
450     (empty_rec_times d.times) &&
451     (empty_rec_times d.xml) &&
452     (empty_rec_arrow d.arrow) &&
453     (empty_rec_record d.record)
454     then true
455     else (
456     memo := backup;
457 abate 220 DescrHash.add cache_false d ();
458 abate 110 false
459     )
460     )
461    
462     and empty_rec_times c =
463     List.for_all empty_rec_times_aux c
464    
465     and empty_rec_times_aux (left,right) =
466     let rec aux accu1 accu2 = function
467     | (t1,t2)::right ->
468 abate 218 if trivially_empty (cap_t accu1 t1) ||
469     trivially_empty (cap_t accu2 t2) then
470 abate 131 aux accu1 accu2 right
471     else
472     let accu1' = diff_t accu1 t1 in
473     if not (empty_rec accu1') then aux accu1' accu2 right;
474     let accu2' = diff_t accu2 t2 in
475 abate 218 if not (empty_rec accu2') then aux accu1 accu2' right
476 abate 110 | [] -> raise NotEmpty
477     in
478     let (accu1,accu2) = cap_product left in
479     (empty_rec accu1) || (empty_rec accu2) ||
480     (try aux accu1 accu2 right; true with NotEmpty -> false)
481    
482 abate 220
483 abate 110 and empty_rec_arrow c =
484     List.for_all empty_rec_arrow_aux c
485    
486     and empty_rec_arrow_aux (left,right) =
487     let single_right (s1,s2) =
488     let rec aux accu1 accu2 = function
489     | (t1,t2)::left ->
490     let accu1' = diff_t accu1 t1 in
491 abate 221 if not (empty_rec accu1') then aux accu1' accu2 left;
492 abate 110 let accu2' = cap_t accu2 t2 in
493 abate 221 if not (empty_rec accu2') then aux accu1 accu2' left
494 abate 110 | [] -> raise NotEmpty
495     in
496     let accu1 = descr s1 in
497     (empty_rec accu1) ||
498     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
499     in
500     List.exists single_right right
501    
502 abate 156 and empty_rec_record_aux (labels,(oleft,(left_opt,left)),rights) =
503     let rec aux = function
504     | [] -> raise NotEmpty
505     | (oright,(right_opt,right))::rights ->
506     let next =
507     (oleft && (not oright)) ||
508     exists (Array.length left)
509     (fun i ->
510     (not (left_opt.(i) && right_opt.(i))) &&
511 abate 220 (trivially_empty (cap left.(i) right.(i))))
512 abate 156 in
513     if next then aux rights
514     else
515     for i = 0 to Array.length left - 1 do
516     let back = left.(i) in
517     let oback = left_opt.(i) in
518     let odi = oback && (not right_opt.(i)) in
519     let di = diff back right.(i) in
520     if odi || not (empty_rec di) then (
521     left.(i) <- diff back right.(i);
522     left_opt.(i) <- odi;
523     aux rights;
524     left.(i) <- back;
525     left_opt.(i) <- oback;
526     )
527     done
528     in
529     exists (Array.length left)
530     (fun i -> not left_opt.(i) && (empty_rec left.(i)))
531     ||
532     (try aux rights; true with NotEmpty -> false)
533    
534    
535 abate 110 and empty_rec_record c =
536 abate 156 List.for_all empty_rec_record_aux (get_record c)
537 abate 110
538 abate 221 (*let is_empty d =
539 abate 219 empty_rec d
540 abate 221 *)
541 abate 110
542     let non_empty d =
543     not (is_empty d)
544    
545     let subtype d1 d2 =
546     is_empty (diff d1 d2)
547    
548     module Product =
549     struct
550     type t = (descr * descr) list
551    
552     let other ?(kind=`Normal) d =
553     match kind with
554     | `Normal -> { d with times = empty.times }
555     | `XML -> { d with xml = empty.xml }
556    
557     let is_product ?kind d = is_empty (other ?kind d)
558    
559     let need_second = function _::_::_ -> true | _ -> false
560    
561     let normal_aux d =
562     let res = ref [] in
563    
564     let add (t1,t2) =
565     let rec loop t1 t2 = function
566     | [] -> res := (ref (t1,t2)) :: !res
567     | ({contents = (d1,d2)} as r)::l ->
568     (*OPT*)
569     if d1 = t1 then r := (d1,cup d2 t2) else
570    
571     let i = cap t1 d1 in
572     if is_empty i then loop t1 t2 l
573     else (
574     r := (i, cup t2 d2);
575     let k = diff d1 t1 in
576     if non_empty k then res := (ref (k,d2)) :: !res;
577    
578     let j = diff t1 d1 in
579     if non_empty j then loop j t2 l
580     )
581     in
582     loop t1 t2 !res
583     in
584     List.iter add d;
585     List.map (!) !res
586    
587 abate 1 (*
588 abate 110 This version explodes when dealing with
589     Any - [ t1? t2? t3? ... tn? ]
590     ==> need partitioning
591 abate 1 *)
592 abate 110 let get_aux d =
593     let line accu (left,right) =
594     let rec aux accu d1 d2 = function
595     | (t1,t2)::right ->
596     let accu =
597     let d1 = diff_t d1 t1 in
598     if is_empty d1 then accu else aux accu d1 d2 right in
599     let accu =
600     let d2 = diff_t d2 t2 in
601     if is_empty d2 then accu else aux accu d1 d2 right in
602     accu
603     | [] -> (d1,d2) :: accu
604     in
605     let (d1,d2) = cap_product left in
606     if (is_empty d1) || (is_empty d2) then accu else aux accu d1 d2 right
607     in
608     List.fold_left line [] d
609 abate 1
610 abate 110 (* Partitioning:
611 abate 1
612 abate 110 (t,s) - ((t1,s1) | (t2,s2) | ... | (tn,sn))
613     =
614     (t & t1, s - s1) | ... | (t & tn, s - sn) | (t - (t1|...|tn), s)
615 abate 1
616 abate 110 *)
617     let get_aux d =
618     let accu = ref [] in
619     let line (left,right) =
620     let (d1,d2) = cap_product left in
621     if (non_empty d1) && (non_empty d2) then
622     let right = List.map (fun (t1,t2) -> descr t1, descr t2) right in
623     let right = normal_aux right in
624     let resid1 = ref d1 in
625     let () =
626     List.iter
627     (fun (t1,t2) ->
628     let t1 = cap d1 t1 in
629     if (non_empty t1) then
630     let () = resid1 := diff !resid1 t1 in
631     let t2 = diff d2 t2 in
632     if (non_empty t2) then accu := (t1,t2) :: !accu
633     ) right in
634     if non_empty !resid1 then accu := (!resid1, d2) :: !accu
635     in
636     List.iter line d;
637     !accu
638 abate 169 (* Maybe, can improve this function with:
639     (t,s) \ (t1,s1) = (t&t',s\s') | (t\t',s),
640     don't call normal_aux *)
641 abate 126
642 abate 218
643 abate 110 let get ?(kind=`Normal) d =
644     match kind with
645     | `Normal -> get_aux d.times
646     | `XML -> get_aux d.xml
647    
648     let pi1 = List.fold_left (fun acc (t1,_) -> cup acc t1) empty
649     let pi2 = List.fold_left (fun acc (_,t2) -> cup acc t2) empty
650    
651     let restrict_1 rects pi1 =
652     let aux accu (t1,t2) =
653     let t1 = cap t1 pi1 in if is_empty t1 then accu else (t1,t2)::accu in
654     List.fold_left aux [] rects
655    
656     type normal = t
657    
658     module Memo = Map.Make(struct
659     type t = (node * node) Boolean.t
660     let compare = compare end)
661    
662    
663    
664     let memo = ref Memo.empty
665     let normal ?(kind=`Normal) d =
666     let d = match kind with `Normal -> d.times | `XML -> d.xml in
667     try Memo.find d !memo
668     with
669     Not_found ->
670     let gd = get_aux d in
671     let n = normal_aux gd in
672 abate 169 (* Could optimize this call to normal_aux because one already
673     know that each line is normalized ... *)
674 abate 110 memo := Memo.add d n !memo;
675     n
676    
677     let any = { empty with times = any.times }
678     and any_xml = { empty with xml = any.xml }
679     let is_empty d = d = []
680     end
681    
682 abate 71 module Print =
683     struct
684 abate 110 let rec print_union ppf = function
685     | [] -> Format.fprintf ppf "Empty"
686     | [h] -> h ppf
687     | h::t -> Format.fprintf ppf "@[%t |@ %a@]" h print_union t
688    
689 abate 78 let print_atom ppf a =
690     Format.fprintf ppf "`%s" (AtomPool.value a)
691 abate 71
692 abate 110 let print_tag ppf a =
693     match Atoms.is_atom a with
694     | Some a -> Format.fprintf ppf "%s" (AtomPool.value a)
695     | None ->
696     Format.fprintf ppf "(%a)"
697     print_union
698     (Atoms.print "Atom" print_atom a)
699    
700 abate 71 let print_const ppf = function
701     | Integer i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
702     | Atom a -> print_atom ppf a
703     | Char c -> Chars.Unichar.print ppf c
704    
705 abate 95 let named = State.ref "Types.Printf.named" DescrMap.empty
706     let register_global name d =
707     named := DescrMap.add d name !named
708 abate 71
709     let marks = DescrHash.create 63
710     let wh = ref []
711     let count_name = ref 0
712     let name () =
713     incr count_name;
714     "X" ^ (string_of_int !count_name)
715     (* TODO:
716     check that these generated names does not conflict with declared types *)
717    
718     let bool_iter f b =
719     List.iter (fun (p,n) -> List.iter f p; List.iter f n) b
720    
721     let trivial b = b = Boolean.empty || b = Boolean.full
722    
723     let worth_abbrev d =
724     not (trivial d.times && trivial d.arrow && trivial d.record)
725    
726     let rec mark n = mark_descr (descr n)
727     and mark_descr d =
728 abate 95 if not (DescrMap.mem d !named) then
729 abate 71 try
730     let r = DescrHash.find marks d in
731     if (!r = None) && (worth_abbrev d) then
732     let na = name () in
733     r := Some na;
734     wh := (na,d) :: !wh
735     with Not_found ->
736     DescrHash.add marks d (ref None);
737     bool_iter (fun (n1,n2) -> mark n1; mark n2) d.times;
738 abate 111 bool_iter
739 abate 156 (fun (n1,n2) -> mark n1; mark n2
740     (*
741 abate 111 List.iter
742     (fun (d1,d2) ->
743     mark_descr d2;
744 abate 156 bool_iter
745     (fun (o,l) -> List.iter (fun (l,(o,n)) -> mark n) l)
746     d1.record
747 abate 111 let l = get_record d1.record in
748 abate 156 List.iter (fun labs,(_,(_,p)),ns ->
749     Array.iter mark_descr p;
750     List.iter (fun (_,(_,n)) ->
751     Array.iter mark_descr n) ns
752     ) l
753 abate 111 )
754     (Product.normal (descr n2))
755 abate 156 *)
756 abate 111 ) d.xml;
757 abate 71 bool_iter (fun (n1,n2) -> mark n1; mark n2) d.arrow;
758 abate 156 bool_iter (fun (o,l) -> List.iter (fun (l,(o,n)) -> mark n) l) d.record
759 abate 71
760    
761     let rec print ppf n = print_descr ppf (descr n)
762     and print_descr ppf d =
763     try
764 abate 95 let name = DescrMap.find d !named in
765 abate 71 Format.fprintf ppf "%s" name
766     with Not_found ->
767     try
768     match !(DescrHash.find marks d) with
769     | Some n -> Format.fprintf ppf "%s" n
770     | None -> real_print_descr ppf d
771     with
772 abate 110 Not_found -> assert false
773 abate 71 and real_print_descr ppf d =
774     if d = any then Format.fprintf ppf "Any" else
775     print_union ppf
776     (Intervals.print d.ints @
777     Chars.print d.chars @
778     Atoms.print "Atom" print_atom d.atoms @
779     Boolean.print "Pair" print_times d.times @
780 abate 110 Boolean.print "XML" print_xml d.xml @
781 abate 71 Boolean.print "Arrow" print_arrow d.arrow @
782     Boolean.print "Record" print_record d.record
783     )
784     and print_times ppf (t1,t2) =
785     Format.fprintf ppf "@[(%a,%a)@]" print t1 print t2
786 abate 110 and print_xml ppf (t1,t2) =
787 abate 156 Format.fprintf ppf "@[XML(%a,%a)@]" print t1 print t2
788     (*
789 abate 110 let l = Product.normal (descr t2) in
790     let l = List.map
791     (fun (d1,d2) ppf ->
792     Format.fprintf ppf "@[<><%a%a>%a@]"
793     print_tag (descr t1).atoms
794     print_attribs d1.record
795     print_descr d2) l
796     in
797     print_union ppf l
798 abate 156 *)
799 abate 71 and print_arrow ppf (t1,t2) =
800     Format.fprintf ppf "@[(%a -> %a)@]" print t1 print t2
801 abate 156 and print_record ppf (o,r) =
802     let o = if o then "" else "|" in
803     Format.fprintf ppf "@[{%s" o;
804     let first = ref true in
805     List.iter (fun (l,(o,t)) ->
806 abate 159 let sep = if !first then (first := false; "") else ";" in
807     Format.fprintf ppf "%s@ @[%s =%s@] %a" sep
808 abate 156 (LabelPool.value l) (if o then "?" else "") print t
809     ) r;
810     Format.fprintf ppf " %s}@]" o
811     (*
812 abate 110 and print_attribs ppf r =
813     let l = get_record r in
814     if l <> [ [] ] then
815     let l = List.map
816     (fun att ppf ->
817     let first = ref true in
818     Format.fprintf ppf "{" ;
819     List.iter (fun (l,(o,d)) ->
820     Format.fprintf ppf "%s%s=%s%a"
821     (if !first then "" else " ")
822     (LabelPool.value l) (if o then "?" else "")
823     print_descr d;
824     first := false
825     ) att;
826     Format.fprintf ppf "}"
827     ) l in
828     print_union ppf l
829 abate 156 *)
830 abate 71
831    
832     let end_print ppf =
833     (match List.rev !wh with
834     | [] -> ()
835     | (na,d)::t ->
836     Format.fprintf ppf " where@ @[%s = %a" na real_print_descr d;
837     List.iter
838     (fun (na,d) ->
839     Format.fprintf ppf " and@ %s = %a" na real_print_descr d)
840     t;
841     Format.fprintf ppf "@]"
842     );
843     Format.fprintf ppf "@]";
844     count_name := 0;
845     wh := [];
846     DescrHash.clear marks
847    
848     let print_descr ppf d =
849     mark_descr d;
850     Format.fprintf ppf "@[%a" print_descr d;
851     end_print ppf
852    
853     let print ppf n = print_descr ppf (descr n)
854    
855     end
856    
857 abate 131 let () = print_descr := Print.print_descr
858 abate 71
859 abate 1 module Positive =
860     struct
861     type rhs = [ `Type of descr | `Cup of v list | `Times of v * v ]
862     and v = { mutable def : rhs; mutable node : node option }
863    
864    
865     let rec make_descr seen v =
866     if List.memq v seen then empty
867     else
868     let seen = v :: seen in
869     match v.def with
870     | `Type d -> d
871     | `Cup vl ->
872     List.fold_left (fun acc v -> cup acc (make_descr seen v)) empty vl
873     | `Times (v1,v2) -> times (make_node v1) (make_node v2)
874    
875     and make_node v =
876     match v.node with
877     | Some n -> n
878     | None ->
879     let n = make () in
880     v.node <- Some n;
881     let d = make_descr [] v in
882     define n d;
883     n
884    
885     let forward () = { def = `Cup []; node = None }
886     let def v d = v.def <- d
887     let cons d = let v = forward () in def v d; v
888     let ty d = cons (`Type d)
889     let cup vl = cons (`Cup vl)
890     let times d1 d2 = cons (`Times (d1,d2))
891     let define v1 v2 = def v1 (`Cup [v2])
892    
893     let solve v = internalize (make_node v)
894     end
895    
896    
897    
898    
899     (* Sample value *)
900     module Sample =
901     struct
902    
903 abate 158
904 abate 1 let rec find f = function
905     | [] -> raise Not_found
906     | x::r -> try f x with Not_found -> find f r
907    
908     type t =
909 abate 15 | Int of Big_int.big_int
910 abate 1 | Atom of atom
911 abate 13 | Char of Chars.Unichar.t
912 abate 110 | Pair of (t * t)
913     | Xml of (t * t)
914 abate 1 | Record of (label * t) list
915     | Fun of (node * node) list
916 abate 156 | Other
917 abate 158 exception FoundSampleRecord of (label * t) list
918 abate 1
919     let rec sample_rec memo d =
920     if (Assumptions.mem d memo) || (is_empty d) then raise Not_found
921     else
922     try Int (Intervals.sample d.ints) with Not_found ->
923 abate 78 try Atom (Atoms.sample (fun _ -> AtomPool.dummy_min) d.atoms) with
924     Not_found ->
925     (* Here: could create a fresh atom ... *)
926 abate 13 try Char (Chars.sample d.chars) with Not_found ->
927 abate 1 try sample_rec_arrow d.arrow with Not_found ->
928    
929     let memo = Assumptions.add d memo in
930 abate 110 try Pair (sample_rec_times memo d.times) with Not_found ->
931     try Xml (sample_rec_times memo d.xml) with Not_found ->
932 abate 1 try sample_rec_record memo d.record with Not_found ->
933     raise Not_found
934    
935    
936     and sample_rec_times memo c =
937     find (sample_rec_times_aux memo) c
938    
939     and sample_rec_times_aux memo (left,right) =
940     let rec aux accu1 accu2 = function
941     | (t1,t2)::right ->
942 abate 158 (*TODO: check: is this correct ? non_empty could return true
943     but because of coinduction, the call to aux may raise Not_found, no ? *)
944 abate 1 let accu1' = diff_t accu1 t1 in
945     if non_empty accu1' then aux accu1' accu2 right else
946     let accu2' = diff_t accu2 t2 in
947     if non_empty accu2' then aux accu1 accu2' right else
948     raise Not_found
949 abate 110 | [] -> (sample_rec memo accu1, sample_rec memo accu2)
950 abate 1 in
951     let (accu1,accu2) = cap_product left in
952     if (is_empty accu1) || (is_empty accu2) then raise Not_found;
953     aux accu1 accu2 right
954    
955     and sample_rec_arrow c =
956     find sample_rec_arrow_aux c
957    
958 abate 10 and check_empty_simple_arrow_line left (s1,s2) =
959     let rec aux accu1 accu2 = function
960     | (t1,t2)::left ->
961     let accu1' = diff_t accu1 t1 in
962     if non_empty accu1' then aux accu1 accu2 left;
963     let accu2' = cap_t accu2 t2 in
964     if non_empty accu2' then aux accu1 accu2 left
965     | [] -> raise NotEmpty
966     in
967     let accu1 = descr s1 in
968     (is_empty accu1) ||
969     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
970    
971     and check_empty_arrow_line left right =
972     List.exists (check_empty_simple_arrow_line left) right
973    
974 abate 1 and sample_rec_arrow_aux (left,right) =
975 abate 10 if (check_empty_arrow_line left right) then raise Not_found
976 abate 1 else Fun left
977    
978    
979     and sample_rec_record memo c =
980     Record (find (sample_rec_record_aux memo) (get_record c))
981    
982 abate 158 and sample_rec_record_aux memo (labels,(oleft,(left_opt,left)),rights) =
983     let rec aux = function
984     | [] ->
985     let l = ref labels and fields = ref [] in
986     for i = 0 to Array.length left - 1 do
987     if not left_opt.(i) then
988     fields := (List.hd !l, sample_rec memo left.(i))::!fields;
989     l := List.tl !l
990     done;
991     raise (FoundSampleRecord (List.rev !fields))
992     | (oright,(right_opt,right))::rights ->
993     let next = (oleft && (not oright)) in
994     if next then aux rights
995     else
996     for i = 0 to Array.length left - 1 do
997     let back = left.(i) in
998     let oback = left_opt.(i) in
999     let odi = oback && (not right_opt.(i)) in
1000     let di = diff back right.(i) in
1001     if odi || not (is_empty di) then (
1002     left.(i) <- diff back right.(i);
1003     left_opt.(i) <- odi;
1004     aux rights;
1005     left.(i) <- back;
1006     left_opt.(i) <- oback;
1007     )
1008     done
1009     in
1010     if exists (Array.length left)
1011     (fun i -> not left_opt.(i) && (is_empty left.(i))) then raise Not_found;
1012     try aux rights; raise Not_found
1013     with FoundSampleRecord r -> r
1014 abate 1
1015 abate 158
1016    
1017    
1018    
1019 abate 156 let get x = try sample_rec Assumptions.empty x with Not_found -> Other
1020 abate 10
1021 abate 71 let rec print_sep f sep ppf = function
1022     | [] -> ()
1023     | [x] -> f ppf x
1024     | x::rem -> f ppf x; Format.fprintf ppf "%s" sep; print_sep f sep ppf rem
1025    
1026    
1027     let rec print ppf = function
1028     | Int i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
1029 abate 78 | Atom a ->
1030     if a = LabelPool.dummy_min then
1031     Format.fprintf ppf "(almost any atom)"
1032     else
1033     Format.fprintf ppf "`%s" (AtomPool.value a)
1034 abate 71 | Char c -> Chars.Unichar.print ppf c
1035     | Pair (x1,x2) -> Format.fprintf ppf "(%a,%a)" print x1 print x2
1036 abate 110 | Xml (x1,x2) -> Format.fprintf ppf "XML(%a,%a)" print x1 print x2
1037 abate 71 | Record r ->
1038     Format.fprintf ppf "{ %a }"
1039     (print_sep
1040     (fun ppf (l,x) ->
1041     Format.fprintf ppf "%s = %a"
1042 abate 78 (LabelPool.value l)
1043 abate 71 print x
1044     )
1045     " ; "
1046     ) r
1047     | Fun iface ->
1048     Format.fprintf ppf "(fun ( %a ) x -> ...)"
1049     (print_sep
1050     (fun ppf (t1,t2) ->
1051     Format.fprintf ppf "%a -> %a; "
1052     Print.print t1 Print.print t2
1053     )
1054     " ; "
1055     ) iface
1056 abate 156 | Other ->
1057     Format.fprintf ppf "[cannot determine value]"
1058 abate 1 end
1059    
1060    
1061    
1062     module Record =
1063     struct
1064 abate 156 type atom = bool * (label, (bool * node)) SortedMap.t
1065     type t = atom Boolean.t
1066    
1067     let get d = d.record
1068    
1069 abate 160 module T = struct
1070     type t = descr
1071     let any = any
1072     let cap = cap
1073     let cup = cup
1074     let diff = diff
1075     let empty = is_empty
1076     end
1077     module R = struct
1078     (*Note: Boolean.cap,cup,diff would be ok,
1079     but we add here the simplification rules:
1080     { } & r --> r ; { } | r -> { }
1081     r \ { } --> Empty *)
1082    
1083     type t = atom Boolean.t
1084     let any = Boolean.full
1085     let cap = Boolean.cap
1086     let cup = Boolean.cup
1087     let diff = Boolean.diff
1088     let empty x = is_empty { empty with record = x }
1089     end
1090     module TR = Normal.Make(T)(R)
1091    
1092     let atom = function
1093     | (true,[]) -> Boolean.full
1094     | (o,l) -> Boolean.atom (o,l)
1095    
1096 abate 165 let somefield_possible t =
1097     not (R.empty (R.diff t (Boolean.atom (false,[]))))
1098    
1099     let nofield_possible t =
1100     not (R.empty (R.cap t (Boolean.atom (false,[]))))
1101    
1102 abate 156 let restrict_label_absent t l =
1103     Boolean.compute_bool
1104 abate 188 (fun ((o,r) as x) ->
1105 abate 156 try
1106     let (lo,_) = List.assoc l r in
1107 abate 160 if lo then atom (o,SortedMap.diff r [l])
1108 abate 156 else Boolean.empty
1109     with Not_found -> Boolean.atom x
1110     )
1111     t
1112    
1113     let restrict_field t l d =
1114     (* Is it correct ? Do we need to keep track of "first component"
1115     (value of l) as in label_present, then filter at the end ... ? *)
1116     Boolean.compute_bool
1117 abate 188 (fun ((o,r) as x) ->
1118 abate 156 try
1119     let (lo,lt) = List.assoc l r in
1120     if (not lo) && (is_empty (cap d (descr lt))) then Boolean.empty
1121 abate 160 else atom (o, SortedMap.diff r [l])
1122 abate 156 with Not_found ->
1123     if o then Boolean.atom x else Boolean.empty
1124     )
1125     t
1126    
1127    
1128    
1129     let label_present (t:t) l : (descr * t) list =
1130     let x =
1131     Boolean.compute_bool
1132 abate 188 (fun ((o,r) as x) ->
1133 abate 156 try
1134     let (_,lt) = List.assoc l r in
1135 abate 160 Boolean.atom (descr lt, atom (o, SortedMap.diff r [l]))
1136 abate 156 with Not_found ->
1137     if o then Boolean.atom (any, Boolean.atom x) else Boolean.empty
1138     )
1139     t
1140     in
1141     TR.boolean x
1142    
1143     let restrict_label_present t l =
1144 abate 165 Boolean.compute_bool
1145 abate 188 (fun ((o,r) as x) ->
1146 abate 165 try
1147     Boolean.atom (o, SortedMap.change_exists l (fun (_,lt) -> (false,lt)) r)
1148     with Not_found ->
1149     if o then Boolean.atom
1150     (true, SortedMap.union_disj [l, (false,any_node)] r)
1151     else Boolean.empty
1152     )
1153     t
1154 abate 156
1155     let project_field t l =
1156     let r = label_present t l in
1157     List.fold_left (fun accu (d,_) -> cup accu d) empty r
1158    
1159     let project t l =
1160     let t = get t in
1161 abate 160 let r = label_present t l in
1162     if r = [] then raise Not_found else
1163     List.fold_left (fun accu (d,_) -> cup accu d) empty r
1164 abate 156
1165     type normal =
1166     [ `Success
1167     | `Fail
1168 abate 159 | `NoField
1169     | `SomeField
1170 abate 156 | `Label of label * (descr * normal) list * normal ]
1171    
1172     let first_label t =
1173     let min = ref None in
1174     let lab l = match !min with
1175     | Some l' when l >= l' -> ()
1176     | _ -> min := Some l in
1177     let aux = function
1178     | _,[] -> ()
1179     | _,(l,_)::_ -> lab l in
1180     Boolean.iter aux t;
1181     match !min with
1182     | Some l -> `Label l
1183     | None ->
1184     let n =
1185     Boolean.compute
1186     ~empty:0
1187     ~full:3
1188     ~cup:(lor)
1189     ~cap:(land)
1190     ~diff:(fun a b -> a land lnot b)
1191     ~atom:(function (true,[]) -> 3 | (false,[]) -> 1 | _ -> assert false)
1192     t in
1193     match n with
1194     | 0 -> `Fail
1195     | 1 -> `NoField
1196     | 2 -> `SomeField
1197     | _ -> `Success
1198    
1199    
1200 abate 160 let normal' t l =
1201     let present = label_present t l
1202     and absent = restrict_label_absent t l in
1203     List.map (fun (d,t) -> d,t) present, absent
1204    
1205 abate 156 let rec normal_aux t =
1206     match first_label t with
1207     | `Label l ->
1208     let present = label_present t l
1209     and absent = restrict_label_absent t l in
1210     `Label (l, List.map (fun (d,t) -> d, normal_aux t) present,
1211     normal_aux absent)
1212     | `Fail -> `Fail
1213     | `Success -> `Success
1214 abate 159 | `NoField -> `NoField
1215     | `SomeField -> `SomeField
1216 abate 156
1217     let normal t = normal_aux (get t)
1218    
1219    
1220    
1221     let descr x = { empty with record = x }
1222     let is_empty x = is_empty (descr x)
1223     (*
1224    
1225 abate 1 type t = (label, (bool * descr)) SortedMap.t list
1226    
1227     let get d =
1228     let line r = List.for_all (fun (l,(o,d)) -> o || non_empty d) r in
1229     List.filter line (get_record d.record)
1230    
1231     let restrict_label_present t l =
1232 abate 29 let restr = function
1233     | (true, d) -> if non_empty d then (false,d) else raise Exit
1234     | x -> x in
1235     let aux accu r =
1236     try SortedMap.change l restr (false,any) r :: accu
1237     with Exit -> accu in
1238     List.fold_left aux [] t
1239 abate 1
1240     let restrict_label_absent t l =
1241     let restr = function (true, _) -> (true,empty) | _ -> raise Exit in
1242     let aux accu r =
1243     try SortedMap.change l restr (true,empty) r :: accu
1244     with Exit -> accu in
1245     List.fold_left aux [] t
1246    
1247     let restrict_field t l d =
1248     let restr (_,d1) =
1249     let d1 = cap d d1 in
1250     if is_empty d1 then raise Exit else (false,d1) in
1251     let aux accu r =
1252     try SortedMap.change l restr (false,d) r :: accu
1253     with Exit -> accu in
1254     List.fold_left aux [] t
1255    
1256     let project_field t l =
1257     let aux accu x =
1258     match List.assoc l x with
1259     | (false,t) -> cup accu t
1260     | _ -> raise Not_found
1261     in
1262     List.fold_left aux empty t
1263    
1264 abate 29 let project d l =
1265     project_field (get_record d.record) l
1266    
1267 abate 1 type normal =
1268     [ `Success
1269     | `Fail
1270     | `Label of label * (descr * normal) list * normal ]
1271    
1272     let rec merge_record n r =
1273     match (n, r) with
1274     | (`Success, _) | (_, []) -> `Success
1275     | (`Fail, r) ->
1276 abate 75 let aux (l,(o,t)) n =
1277     `Label (l, [t,n], if o then n else `Fail) in
1278 abate 1 List.fold_right aux r `Success
1279     | (`Label (l1,present,absent), (l2,(o,t2))::r') ->
1280     if (l1 < l2) then
1281     let pr = List.map (fun (t,x) -> (t, merge_record x r)) present in
1282 abate 75 let t = List.fold_left (fun a (t,_) -> diff a t) any present in
1283     let pr =
1284     if non_empty t then (t, merge_record `Fail r) :: pr
1285     else pr in
1286 abate 1 `Label (l1,pr,merge_record absent r)
1287     else if (l2 < l1) then
1288     let n' = merge_record n r' in
1289     `Label (l2, [t2, n'], if o then n' else n)
1290     else
1291     let res = ref [] in
1292     let aux a (t,x) =
1293     (let t = diff t t2 in
1294     if non_empty t then res := (t,x) :: !res);
1295     (let t = cap t t2 in
1296     if non_empty t then res := (t, merge_record x r') :: !res);
1297     diff a t
1298     in
1299     let t2 = List.fold_left aux t2 present in
1300     let () =
1301     if non_empty t2 then
1302     res := (t2, merge_record `Fail r') :: !res in
1303     let abs = if o then merge_record absent r' else absent in
1304     `Label (l1, !res, abs)
1305    
1306 abate 75 module Unify = Map.Make(struct type t = normal let compare = compare end)
1307 abate 1
1308 abate 75 let repository = ref Unify.empty
1309    
1310     let rec canonize = function
1311     | `Label (l,pr,ab) as x ->
1312     (try Unify.find x !repository
1313     with Not_found ->
1314     let pr = List.map (fun (t,n) -> canonize n,t) pr in
1315     let pr = SortedMap.from_list cup pr in
1316     let pr = List.map (fun (n,t) -> (t,n)) pr in
1317     let x = `Label (l, pr, canonize ab) in
1318     try Unify.find x !repository
1319     with Not_found -> repository := Unify.add x x !repository; x
1320     )
1321     | x -> x
1322    
1323 abate 1 let normal d =
1324 abate 75 let r = canonize (List.fold_left merge_record `Fail (get d)) in
1325     repository := Unify.empty;
1326     r
1327 abate 1
1328 abate 75 type normal' =
1329     [ `Success
1330     | `Label of label * (descr * descr) list * descr option ] option
1331 abate 1
1332 abate 75 (* NOTE: this function relies on the fact that generic order
1333     makes smallest labels appear first *)
1334    
1335     let first_label d =
1336     let d = d.record in
1337     let min = ref None in
1338     let lab (l,o,t) = match !min with
1339     | Some l' when l >= l' -> ()
1340     | _ -> if o && (descr t = any) then () else min := Some l in
1341     let line (p,n) =
1342     (match p with f::_ -> lab f | _ -> ());
1343     (match n with f::_ -> lab f | _ -> ()) in
1344     List.iter line d;
1345     match !min with
1346     | None -> if d = [] then `Empty else `Any
1347     | Some l -> `Label l
1348    
1349     let normal' (d : descr) l =
1350     let ab = ref empty in
1351     let rec extract f = function
1352     | (l',o,t) :: rem when l = l' ->
1353     f o (descr t); extract f rem
1354     | x :: rem -> x :: (extract f rem)
1355     | [] -> [] in
1356     let line (p,n) =
1357     let ao = ref true and ad = ref any in
1358     let p =
1359     extract (fun o d -> ao := !ao && o; ad := cap !ad d) p
1360     and n =
1361     extract (fun o d -> ao := !ao && not o; ad := diff !ad d) n
1362     in
1363     (* Note: p and n are still sorted *)
1364     let d = { empty with record = [(p,n)] } in
1365     if !ao then ab := cup d !ab;
1366     (!ad, d) in
1367     let pr = List.map line d.record in
1368     let pr = Product.normal_aux pr in
1369     let ab = if is_empty !ab then None else Some !ab in
1370     (pr, ab)
1371    
1372 abate 156 *)
1373 abate 75
1374 abate 1 let any = { empty with record = any.record }
1375 abate 156 (*
1376 abate 1 let is_empty d = d = []
1377 abate 75 let descr l =
1378     let line l = map_sort (fun (l,(o,d)) -> (l,o,cons d)) l, [] in
1379     { empty with record = map_sort line l }
1380 abate 156 *)
1381 abate 1 end
1382    
1383    
1384 abate 29
1385 abate 71 let memo_normalize = ref DescrMap.empty
1386 abate 1
1387    
1388     let rec rec_normalize d =
1389 abate 71 try DescrMap.find d !memo_normalize
1390 abate 1 with Not_found ->
1391     let n = make () in
1392 abate 71 memo_normalize := DescrMap.add d n !memo_normalize;
1393 abate 1 let times =
1394     map_sort
1395     (fun (d1,d2) -> [(rec_normalize d1, rec_normalize d2)],[])
1396     (Product.normal d)
1397     in
1398 abate 110 let xml =
1399     map_sort
1400     (fun (d1,d2) -> [(rec_normalize d1, rec_normalize d2)],[])
1401     (Product.normal ~kind:`XML d)
1402     in
1403 abate 156 let record = d.record
1404     (*
1405 abate 1 map_sort
1406     (fun f -> map_sort (fun (l,(o,d)) -> (l,o,rec_normalize d)) f, [])
1407     (Record.get d)
1408 abate 156 *)
1409 abate 1 in
1410 abate 110 define n { d with times = times; xml = xml; record = record };
1411 abate 1 n
1412    
1413     let normalize n =
1414 abate 29 descr (internalize (rec_normalize n))
1415 abate 6
1416 abate 11 module Arrow =
1417     struct
1418 abate 19 let check_simple left s1 s2 =
1419     let rec aux accu1 accu2 = function
1420     | (t1,t2)::left ->
1421     let accu1' = diff_t accu1 t1 in
1422 abate 45 if non_empty accu1' then aux accu1 accu2 left;
1423 abate 19 let accu2' = cap_t accu2 t2 in
1424 abate 45 if non_empty accu2' then aux accu1 accu2 left
1425 abate 19 | [] -> raise NotEmpty
1426     in
1427     let accu1 = descr s1 in
1428     (is_empty accu1) ||
1429     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1430    
1431     let check_strenghten t s =
1432     let left = match t.arrow with [ (p,[]) ] -> p | _ -> assert false in
1433     let rec aux = function
1434     | [] -> raise Not_found
1435     | (p,n) :: rem ->
1436     if (List.for_all (fun (a,b) -> check_simple left a b) p) &&
1437     (List.for_all (fun (a,b) -> not (check_simple left a b)) n) then
1438     { empty with arrow = [ (SortedList.cup left p, n) ] }
1439     else aux rem
1440     in
1441     aux s.arrow
1442    
1443 abate 45 let check_simple_iface left s1 s2 =
1444     let rec aux accu1 accu2 = function
1445     | (t1,t2)::left ->
1446     let accu1' = diff accu1 t1 in
1447     if non_empty accu1' then aux accu1 accu2 left;
1448     let accu2' = cap accu2 t2 in
1449     if non_empty accu2' then aux accu1 accu2 left
1450     | [] -> raise NotEmpty
1451     in
1452     let accu1 = descr s1 in
1453     (is_empty accu1) ||
1454     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1455    
1456     let check_iface iface s =
1457     let rec aux = function
1458     | [] -> false
1459     | (p,n) :: rem ->
1460     ((List.for_all (fun (a,b) -> check_simple_iface iface a b) p) &&
1461     (List.for_all (fun (a,b) -> not (check_simple_iface iface a b)) n))
1462     || (aux rem)
1463     in
1464     aux s.arrow
1465    
1466 abate 11 type t = descr * (descr * descr) list list
1467    
1468     let get t =
1469     List.fold_left
1470     (fun ((dom,arr) as accu) (left,right) ->
1471     if Sample.check_empty_arrow_line left right
1472     then accu
1473     else (
1474     let left =
1475     List.map
1476     (fun (t,s) -> (descr t, descr s)) left in
1477     let d = List.fold_left (fun d (t,_) -> cup d t) empty left in
1478     (cap dom d, left :: arr)
1479     )
1480     )
1481     (any, [])
1482     t.arrow
1483    
1484     let domain (dom,_) = dom
1485    
1486     let apply_simple t result left =
1487     let rec aux result accu1 accu2 = function
1488     | (t1,s1)::left ->
1489     let result =
1490     let accu1 = diff accu1 t1 in
1491     if non_empty accu1 then aux result accu1 accu2 left
1492     else result in
1493     let result =
1494     let accu2 = cap accu2 s1 in
1495     aux result accu1 accu2 left in
1496     result
1497     | [] ->
1498     if subtype accu2 result
1499     then result
1500     else cup result accu2
1501     in
1502     aux result t any left
1503    
1504     let apply (_,arr) t =
1505     List.fold_left (apply_simple t) empty arr
1506    
1507 abate 19 let need_arg (dom, arr) =
1508     List.exists (function [_] -> false | _ -> true) arr
1509    
1510     let apply_noarg (_,arr) =
1511     List.fold_left
1512     (fun accu ->
1513     function
1514     | [(t,s)] -> cup accu s
1515     | _ -> assert false
1516     )
1517     empty arr
1518    
1519 abate 11 let any = { empty with arrow = any.arrow }
1520 abate 19 let is_empty (_,arr) = arr = []
1521 abate 11 end
1522    
1523    
1524 abate 16 module Int = struct
1525 abate 45 let has_int d i = Intervals.contains i d.ints
1526    
1527 abate 16 let get d = d.ints
1528     let put i = { empty with ints = i }
1529     let is_int d = is_empty { d with ints = Intervals.empty }
1530     let any = { empty with ints = Intervals.any }
1531     end
1532 abate 11
1533 abate 17 module Atom = struct
1534     let has_atom d a = Atoms.contains a d.atoms
1535     end
1536    
1537 abate 45 module Char = struct
1538     let has_char d c = Chars.contains c d.chars
1539 abate 58 let any = { empty with chars = Chars.any }
1540 abate 45 end
1541    
1542 abate 186 let print_stat ppf =
1543 abate 188 (* Format.fprintf ppf "nb_rec = %i@." !nb_rec;
1544 abate 186 Format.fprintf ppf "nb_norec = %i@." !nb_norec;
1545 abate 188 *)
1546 abate 186 ()
1547    
1548 abate 1 (*
1549     let rec print_normal_record ppf = function
1550     | Success -> Format.fprintf ppf "Yes"
1551     | Fail -> Format.fprintf ppf "No"
1552     | FirstLabel (l,present,absent) ->
1553     Format.fprintf ppf "%s?@[<v>@\n" (label_name l);
1554     List.iter
1555     (fun (t,n) ->
1556     Format.fprintf ppf "(%a)=>@[%a@]@\n"
1557     Print.print_descr t
1558     print_normal_record n
1559     ) present;
1560     if absent <> Fail then
1561     Format.fprintf ppf "(absent)=>@[%a@]@\n" print_normal_record absent;
1562     Format.fprintf ppf "@]"
1563     *)
1564    
1565    
1566     (*
1567     let pr s = Types.Print.print Format.std_formatter (Syntax.make_type (Syntax.parse s));;
1568    
1569     let pr' s = Types.Print.print Format.std_formatter
1570     (Types.normalize (Syntax.make_type (Syntax.parse s)));;
1571    
1572     BUG:
1573     pr "'a | 'b where 'a = ('a , 'a) and 'b= ('b , 'b)";;
1574     *)
1575    
1576    
1577     (*
1578     let nr s =
1579     let t = Types.descr (Syntax.make_type (Syntax.parse s)) in
1580     let n = Types.normal_record' t.Types.record in
1581     Types.print_normal_record Format.std_formatter n;;
1582     *)

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