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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 355 - (hide annotations)
Tue Jul 10 17:27:46 2007 UTC (5 years, 11 months ago) by abate
File size: 40429 byte(s)
[r2003-05-15 09:26:56 by cvscast] Empty log message

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

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