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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 366 - (hide annotations)
Tue Jul 10 17:28:31 2007 UTC (5 years, 10 months ago) by abate
File size: 45859 byte(s)
[r2003-05-18 14:10:33 by cvscast] Improve pretty-printer

Original author: cvscast
Date: 2003-05-18 14:10:33+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 abate 364 cap descrs.(i) { empty with absent = true }; (* TODO:OPT *)
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 364 let merge_same_2 r =
781     let r =
782     List.fold_left
783     (fun accu (t1,t2) ->
784     let t = try DescrMap.find t2 accu with Not_found -> empty in
785     DescrMap.add t2 (cup t t1) accu
786     ) DescrMap.empty r in
787     DescrMap.fold (fun t2 t1 accu -> (t1,t2)::accu) r []
788    
789    
790 abate 355 let constraint_on_2 n t1 =
791     List.fold_left
792     (fun accu (d1,d2) ->
793     if is_empty (cap d1 t1) then accu else cap accu d2)
794     any
795     n
796    
797 abate 110 let any = { empty with times = any.times }
798     and any_xml = { empty with xml = any.xml }
799 abate 332 let is_empty d = d == []
800 abate 110 end
801    
802 abate 364 module Record =
803 abate 71 struct
804 abate 364 let has_record d = not (is_empty { empty with record = d.record })
805     let or_absent d = { d with absent = true }
806     let any_or_absent = or_absent any
807     let has_absent d = d.absent
808 abate 110
809 abate 364 let only_absent = {empty with absent = true}
810     let only_absent_node = cons only_absent
811 abate 110
812 abate 364 module T = struct
813     type t = descr
814     let any = any_or_absent
815     let cap = cap
816     let cup = cup
817     let diff = diff
818     let is_empty = is_empty
819     let empty = empty
820     end
821     module R = struct
822     type t = descr
823     let any = { empty with record = any.record }
824     let cap = cap
825     let cup = cup
826     let diff = diff
827     let is_empty = is_empty
828     let empty = empty
829     end
830     module TR = Normal.Make(T)(R)
831    
832     let any_record = { empty with record = BoolRec.full }
833    
834     let atom o l =
835     if o && LabelMap.is_empty l then any_record else
836     { empty with record = BoolRec.atom (o,l) }
837    
838     type zor = Pair of descr * descr | Any
839    
840     let aux_split d l=
841     let f (o,r) =
842     try
843     let (lt,rem) = LabelMap.assoc_remove l r in
844     Pair (descr lt, atom o rem)
845     with Not_found ->
846     if o then
847     if LabelMap.is_empty r then Any else
848     Pair (any_or_absent, { empty with record = BoolRec.atom (o,r) })
849     else
850     Pair (only_absent,
851     { empty with record = BoolRec.atom (o,r) })
852     in
853     List.fold_left
854     (fun b (p,n) ->
855     let rec aux_p accu = function
856     | x::p ->
857     (match f x with
858     | Pair (t1,t2) -> aux_p ((t1,t2)::accu) p
859     | Any -> aux_p accu p)
860     | [] -> aux_n accu [] n
861     and aux_n p accu = function
862     | x::n ->
863     (match f x with
864     | Pair (t1,t2) -> aux_n p ((t1,t2)::accu) n
865     | Any -> b)
866     | [] -> (p,accu) :: b in
867     aux_p [] p)
868     []
869     (BoolRec.get d.record)
870    
871     let split (d : descr) l =
872     TR.boolean (aux_split d l)
873    
874     let split_normal d l =
875     TR.boolean_normal (aux_split d l)
876    
877    
878     let project d l =
879     let t = TR.pi1 (split d l) in
880     if t.absent then raise Not_found;
881     t
882    
883     let project_opt d l =
884     let t = TR.pi1 (split d l) in
885     { t with absent = false }
886    
887     let condition d l t =
888     TR.pi2_restricted t (split d l)
889    
890     (* TODO: eliminate this cap ... (reord l only_absent_node) when
891     not necessary. eg. {| ..... |} \ l *)
892    
893     let remove_field d l =
894     cap (TR.pi2 (split d l)) (record l only_absent_node)
895    
896     let first_label d =
897     let min = ref LabelPool.dummy_max in
898     let aux (_,r) =
899     match LabelMap.get r with
900     (l,_)::_ -> if (l:int) < !min then min := l | _ -> () in
901     BoolRec.iter aux d.record;
902     !min
903    
904     let empty_cases d =
905     let x = BoolRec.compute
906     ~empty:0 ~full:3 ~cup:(lor) ~cap:(land)
907     ~diff:(fun a b -> a land lnot b)
908     ~atom:(function (o,r) ->
909     assert (LabelMap.get r == []);
910     if o then 3 else 1
911     )
912     d.record in
913     (x land 2 <> 0, x land 1 <> 0)
914    
915     let has_empty_record d =
916     BoolRec.compute
917     ~empty:false ~full:true ~cup:(||) ~cap:(&&)
918     ~diff:(fun a b -> a && not b)
919     ~atom:(function (o,r) ->
920     List.for_all
921     (fun (l,t) -> (descr t).absent)
922     (LabelMap.get r)
923     )
924     d.record
925    
926    
927     (*TODO: optimize merge
928     - pre-compute the sequence of labels
929     - remove empty or full { l = t }
930     *)
931    
932     let merge d1 d2 =
933     let res = ref empty in
934     let rec aux accu d1 d2 =
935     let l = min (first_label d1) (first_label d2) in
936     if l = LabelPool.dummy_max then
937     let (some1,none1) = empty_cases d1
938     and (some2,none2) = empty_cases d2 in
939     let none = none1 && none2 and some = some1 || some2 in
940     let accu = LabelMap.from_list (fun _ _ -> assert false) accu in
941     (* approx for the case (some && not none) ... *)
942     res := cup !res (record' (some, accu))
943     else
944     let l1 = split d1 l and l2 = split d2 l in
945     let loop (t1,d1) (t2,d2) =
946     let t =
947     if t2.absent
948     then cup t1 { t2 with absent = false }
949     else t2
950     in
951     aux ((l,cons t)::accu) d1 d2
952     in
953     List.iter (fun x -> List.iter (loop x) l2) l1
954    
955     in
956     aux [] d1 d2;
957     !res
958    
959     let any = { empty with record = any.record }
960    
961     let get d =
962     let rec aux r accu d =
963     let l = first_label d in
964     if l == LabelPool.dummy_max then
965     let (o1,o2) = empty_cases d in
966     if o1 || o2 then (LabelMap.from_list_disj r,o1,o2)::accu else accu
967     else
968     List.fold_left
969     (fun accu (t1,t2) -> aux ((l,t1)::r) accu t2)
970     accu
971     (split d l)
972     in
973     aux [] [] d
974     end
975    
976    
977     module Print =
978     struct
979 abate 71 let print_const ppf = function
980 abate 222 | Integer i -> Intervals.print_v ppf i
981     | Atom a -> Atoms.print_v ppf a
982     | Char c -> Chars.print_v ppf c
983 abate 71
984 abate 364 let nil_atom = Atoms.mk "nil"
985     let nil_type = atom (Atoms.atom nil_atom)
986     let (seqs_node,seqs_descr) =
987     let n = make () in
988     let d = cup nil_type (times any_node n) in
989     define n d;
990     (n, d)
991    
992     let is_regexp t = subtype t seqs_descr
993     module Decompile = Pretty.Decompile(DescrHash)
994    
995     type t = { mutable def : d list; mutable name : string option }
996     and d =
997     | Name of string
998     | Regexp of t Pretty.regexp
999     | Atomic of (Format.formatter -> unit)
1000     | Pair of t * t
1001     | Char of Chars.v
1002     | Xml of [ `Tag of string | `Type of t ] * t * t
1003     | Record of (bool * t) label_map * bool * bool
1004     | Arrows of (t * t) list * (t * t) list
1005 abate 366 | Neg of t
1006 abate 364
1007     module DescrPairMap =
1008     Map.Make(
1009     struct
1010     type t = descr * descr
1011     let compare (x1,y1) (x2,y2) =
1012     let c = compare_descr x1 x2 in
1013     if c = 0 then compare_descr y1 y2 else c
1014     end)
1015    
1016     let named = State.ref "Types.Print.named" DescrMap.empty
1017     let named_xml = State.ref "Types.Print.named_xml" DescrPairMap.empty
1018 abate 95 let register_global name d =
1019 abate 364 if equal_descr { d with xml = BoolPair.empty } empty then
1020     (let l = (*Product.merge_same_2*) (Product.get ~kind:`XML d) in
1021     match l with
1022     | [(t1,t2)] -> named_xml := DescrPairMap.add (t1,t2) name !named_xml
1023     | _ -> ());
1024 abate 95 named := DescrMap.add d name !named
1025 abate 71
1026 abate 364 let memo = DescrHash.create 63
1027     let empty_t = { def = []; name = None }
1028    
1029 abate 71 let count_name = ref 0
1030     let name () =
1031     incr count_name;
1032     "X" ^ (string_of_int !count_name)
1033    
1034 abate 364 let to_print = ref []
1035    
1036     let trivial_rec b = b == BoolRec.empty || (is_empty { empty with record = BoolRec.diff BoolRec.full b})
1037    
1038 abate 332 let trivial_pair b = b == BoolPair.empty || b == BoolPair.full
1039 abate 71
1040     let worth_abbrev d =
1041 abate 233 not (trivial_pair d.times && trivial_pair d.xml &&
1042     trivial_pair d.arrow && trivial_rec d.record)
1043 abate 71
1044 abate 366 let worth_complement d =
1045     let aux f x y = if f x y = 0 then 1 else 0 in
1046     let n =
1047     aux Atoms.compare d.atoms any.atoms +
1048     aux Chars.compare d.chars any.chars +
1049     aux Intervals.compare d.ints any.ints +
1050     aux BoolPair.compare d.times any.times +
1051     aux BoolPair.compare d.xml any.xml +
1052     aux BoolPair.compare d.arrow any.arrow +
1053     aux BoolRec.compare d.record any.record in
1054     n >= 4
1055    
1056    
1057 abate 364 let rec prepare d =
1058     try
1059     let slot = DescrHash.find memo d in
1060     if (slot.name == None) then
1061     (let n = name () in
1062     slot.name <- Some n;
1063     to_print := (n,slot) :: !to_print);
1064     slot
1065     with Not_found ->
1066 abate 71 try
1067 abate 364 let n = DescrMap.find d !named in
1068     let s = { name = Some n; def = [] } in
1069     DescrHash.add memo d s;
1070     s
1071     with Not_found ->
1072 abate 366 if worth_complement d then
1073     { empty_t with def = [Neg (prepare (neg d))] }
1074     else
1075 abate 364 let slot = { empty_t with def = [] } in
1076     if worth_abbrev d then DescrHash.add memo d slot;
1077     let (seq,not_seq) =
1078     if (subtype { empty with times = d.times } seqs_descr) then
1079     (cap d seqs_descr, diff d seqs_descr)
1080     else
1081     (empty, d) in
1082    
1083     let add u = slot.def <- u :: slot.def in
1084     if (non_empty seq) then
1085     add (Regexp (decompile seq));
1086     List.iter
1087     (fun (t1,t2) -> add (Pair (prepare t1, prepare t2)))
1088     (Product.get not_seq);
1089     List.iter
1090     (fun (t1,t2) ->
1091     try
1092     let n = DescrPairMap.find (t1,t2) !named_xml in
1093     add (Name n)
1094     with
1095     Not_found ->
1096     let tag =
1097     match Atoms.is_atom t1.atoms with
1098     | Some a when is_empty { t1 with atoms = Atoms.empty } ->
1099     `Tag (Atoms.value a)
1100     | _ -> `Type (prepare t1) in
1101 abate 111 List.iter
1102 abate 364 (fun (ta,tb) -> add (Xml (tag, prepare ta, prepare tb)))
1103     (Product.get t2)
1104     )
1105     ((*Product.merge_same_2*) (Product.get ~kind:`XML not_seq));
1106     List.iter
1107     (fun (r,some,none) ->
1108     let r = LabelMap.map
1109     (fun t ->
1110     (t.absent, prepare { t with absent = false })) r in
1111     add (Record (r,some,none)))
1112     (Record.get not_seq);
1113     (match Chars.is_char not_seq.chars with
1114     | Some c -> add (Char c)
1115     | None ->
1116     List.iter (fun x -> add (Atomic x)) (Chars.print not_seq.chars));
1117     List.iter (fun x -> add (Atomic x)) (Intervals.print not_seq.ints);
1118     List.iter (fun x -> add (Atomic x)) (Atoms.print not_seq.atoms);
1119     List.iter
1120     (fun (p,n) ->
1121     let aux (t,s) = prepare (descr t), prepare (descr s) in
1122     let p = List.map aux p and n = List.map aux n in
1123     add (Arrows (p,n)))
1124     (BoolPair.get not_seq.arrow);
1125     slot.def <- List.rev slot.def;
1126     slot
1127    
1128 abate 71
1129 abate 364 and decompile d =
1130     Decompile.decompile
1131     (fun t ->
1132     let tr = Product.get t in
1133     let tr = List.map (fun (l,t) -> prepare l, t) tr in
1134     tr, Atoms.contains nil_atom t.atoms)
1135     d
1136    
1137     let rec do_print_slot pri ppf s =
1138     match s.name with
1139     | None -> do_print_slot_real pri ppf s.def
1140     | Some n -> Format.fprintf ppf "%s" n
1141     and do_print_slot_real pri ppf def =
1142     let rec aux ppf = function
1143     | [] -> Format.fprintf ppf "Empty"
1144     | [ h ] -> do_print ppf h
1145     | h :: t -> Format.fprintf ppf "%a |@ %a" do_print h aux t
1146 abate 110 in
1147 abate 364 if (pri >= 2) && (List.length def >= 2)
1148     then Format.fprintf ppf "@[(%a)@]" aux def
1149     else aux ppf def
1150     and do_print ppf = function
1151 abate 366 | Neg t -> Format.fprintf ppf "Any \\ (@[%a@])" (do_print_slot 0) t
1152 abate 364 | Name n -> Format.fprintf ppf "%s" n
1153     | Char c -> Chars.print_v ppf c
1154     | Regexp r -> Format.fprintf ppf "@[[ %a ]@]" (do_print_regexp 0) r
1155     | Atomic a -> a ppf
1156     | Pair (t1,t2) ->
1157     Format.fprintf ppf "@[(%a,%a)@]"
1158     (do_print_slot 0) t1
1159     (do_print_slot 0) t2
1160     | Xml (tag,t2,t3) ->
1161     Format.fprintf ppf "<%a%a>%a"
1162     do_print_tag tag
1163     do_print_attr t2
1164     (do_print_slot 0) t3
1165     | Record (r,some,none) ->
1166     if some then Format.fprintf ppf "@[{"
1167     else Format.fprintf ppf "@[{|";
1168     do_print_record ppf r;
1169     if not none then Format.fprintf ppf ";@ ...";
1170     if some then Format.fprintf ppf " }@]"
1171     else Format.fprintf ppf " |}@]"
1172     | Arrows (p,n) ->
1173     (match p with
1174     | [] -> Format.fprintf ppf "Arrow"
1175     | (t,s)::l ->
1176     Format.fprintf ppf "%a" do_print_arrow (t,s);
1177     List.iter
1178     (fun (t,s) ->
1179     Format.fprintf ppf " &@ %a" do_print_arrow (t,s)
1180     ) l);
1181     List.iter
1182     (fun (t,s) ->
1183     Format.fprintf ppf " \\@ %a" do_print_arrow (t,s)
1184     ) n
1185     and do_print_arrow ppf (t,s) =
1186     Format.fprintf ppf "%a -> %a"
1187     (do_print_slot 0) t
1188     (do_print_slot 0) s
1189     and do_print_tag ppf = function
1190     | `Tag s -> Format.fprintf ppf "%s" s
1191     | `Type t -> Format.fprintf ppf "(%a)" (do_print_slot 0) t
1192     and do_print_attr ppf = function
1193     | { name = None; def = [ Record (r,true,true) ] } -> do_print_record ppf r
1194     | t -> Format.fprintf ppf " %a" (do_print_slot 2) t
1195     and do_print_record ppf r =
1196 abate 156 let first = ref true in
1197 abate 364 List.iter
1198     (fun (l,(o,t)) ->
1199     let sep = if !first then (first := false; "") else ";" in
1200     let opt = if o then "?" else "" in
1201     Format.fprintf ppf "%s@ @[%s =%s@] %a" sep
1202     (LabelPool.value l) opt (do_print_slot 0) t
1203     ) (LabelMap.get r)
1204     and do_print_regexp pri ppf = function
1205     | Pretty.Empty -> assert false
1206     | Pretty.Epsilon -> ()
1207     | Pretty.Seq (Pretty.Trans t1,Pretty.Star (Pretty.Trans t2))
1208     | Pretty.Seq (Pretty.Star (Pretty.Trans t1),Pretty.Trans t2)
1209     when t1 == t2 ->
1210     Format.fprintf ppf "@[%a@]+" (do_print_slot 3) t1
1211     | Pretty.Seq (Pretty.Trans { name = None; def = [ Char _ ] }, _) as r->
1212     (match extract_string [] r with
1213     | s, None ->
1214     Format.fprintf ppf "'";
1215     List.iter (Chars.print_v_in_string ppf) s;
1216     Format.fprintf ppf "'"
1217     | s, Some r ->
1218     if pri >= 3 then Format.fprintf ppf "@[(";
1219     Format.fprintf ppf "'";
1220     List.iter (Chars.print_v_in_string ppf) s;
1221     Format.fprintf ppf "' %a" (do_print_regexp 2) r;
1222     if pri >= 3 then Format.fprintf ppf ")@]")
1223     | Pretty.Seq (r1,r2) ->
1224     if pri >= 3 then Format.fprintf ppf "@[(";
1225     Format.fprintf ppf "%a@ %a"
1226     (do_print_regexp 2) r1
1227     (do_print_regexp 2) r2;
1228     if pri >= 3 then Format.fprintf ppf ")@]"
1229     | Pretty.Alt (r,Pretty.Epsilon) | Pretty.Alt (Pretty.Epsilon,r) ->
1230     Format.fprintf ppf "@[%a@]?" (do_print_regexp 3) r
1231     | Pretty.Alt (r1,r2) ->
1232     if pri >= 2 then Format.fprintf ppf "@[(";
1233     Format.fprintf ppf "%a |@ %a"
1234     (do_print_regexp 1) r1
1235     (do_print_regexp 1) r2;
1236     if pri >= 2 then Format.fprintf ppf ")@]"
1237     | Pretty.Star r ->
1238     Format.fprintf ppf "@[%a@]*" (do_print_regexp 3) r
1239     | Pretty.Trans t ->
1240     do_print_slot pri ppf t
1241     and extract_string accu = function
1242     | Pretty.Seq (Pretty.Trans { name = None; def = [ Char c ] }, r) ->
1243     extract_string (c :: accu) r
1244     | Pretty.Trans { name = None; def = [ Char c ] } ->
1245     (List.rev (c :: accu), None)
1246     | r -> (List.rev accu,Some r)
1247 abate 71
1248 abate 364
1249     let print_descr ppf d =
1250     let t = prepare d in
1251     Format.fprintf ppf "@[@[%a@]" (do_print_slot 0) t;
1252     (match List.rev !to_print with
1253 abate 71 | [] -> ()
1254 abate 364 | (n,s)::t ->
1255     Format.fprintf ppf
1256     " where@ @[<v>%s = @[%a@]" n (do_print_slot_real 0) s.def;
1257 abate 71 List.iter
1258 abate 364 (fun (n,s) ->
1259     Format.fprintf ppf " and@ %s = @[%a@]"
1260     n (do_print_slot_real 0) s.def)
1261 abate 71 t;
1262     Format.fprintf ppf "@]"
1263     );
1264 abate 364 Format.fprintf ppf "@]";
1265 abate 71 count_name := 0;
1266 abate 364 to_print := [];
1267     DescrHash.clear memo
1268 abate 71
1269     let print ppf n = print_descr ppf (descr n)
1270    
1271     end
1272    
1273 abate 131 let () = print_descr := Print.print_descr
1274 abate 71
1275 abate 1 module Positive =
1276     struct
1277 abate 263 type rhs = [ `Type of descr | `Cup of v list | `Times of v * v | `Xml of v * v ]
1278 abate 1 and v = { mutable def : rhs; mutable node : node option }
1279    
1280    
1281     let rec make_descr seen v =
1282     if List.memq v seen then empty
1283     else
1284     let seen = v :: seen in
1285     match v.def with
1286     | `Type d -> d
1287     | `Cup vl ->
1288     List.fold_left (fun acc v -> cup acc (make_descr seen v)) empty vl
1289     | `Times (v1,v2) -> times (make_node v1) (make_node v2)
1290 abate 263 | `Xml (v1,v2) -> xml (make_node v1) (make_node v2)
1291 abate 1
1292     and make_node v =
1293     match v.node with
1294     | Some n -> n
1295     | None ->
1296     let n = make () in
1297     v.node <- Some n;
1298     let d = make_descr [] v in
1299     define n d;
1300     n
1301    
1302     let forward () = { def = `Cup []; node = None }
1303     let def v d = v.def <- d
1304     let cons d = let v = forward () in def v d; v
1305     let ty d = cons (`Type d)
1306     let cup vl = cons (`Cup vl)
1307     let times d1 d2 = cons (`Times (d1,d2))
1308 abate 263 let xml d1 d2 = cons (`Xml (d1,d2))
1309 abate 1 let define v1 v2 = def v1 (`Cup [v2])
1310    
1311     let solve v = internalize (make_node v)
1312     end
1313    
1314    
1315    
1316    
1317     (* Sample value *)
1318     module Sample =
1319     struct
1320    
1321 abate 158
1322 abate 1 let rec find f = function
1323     | [] -> raise Not_found
1324     | x::r -> try f x with Not_found -> find f r
1325    
1326     type t =
1327 abate 222 | Int of Intervals.v
1328     | Atom of Atoms.v
1329     | Char of Chars.v
1330 abate 110 | Pair of (t * t)
1331     | Xml of (t * t)
1332 abate 252 | Record of (bool * (label * t) list)
1333 abate 1 | Fun of (node * node) list
1334 abate 156 | Other
1335 abate 263 exception FoundSampleRecord of bool * (label * t) list
1336 abate 1
1337     let rec sample_rec memo d =
1338     if (Assumptions.mem d memo) || (is_empty d) then raise Not_found
1339     else
1340     try Int (Intervals.sample d.ints) with Not_found ->
1341 abate 222 try Atom (Atoms.sample d.atoms) with
1342 abate 78 Not_found ->
1343     (* Here: could create a fresh atom ... *)
1344 abate 13 try Char (Chars.sample d.chars) with Not_found ->
1345 abate 224 try sample_rec_arrow (BoolPair.get d.arrow) with Not_found ->
1346 abate 1
1347     let memo = Assumptions.add d memo in
1348 abate 224 try Pair (sample_rec_times memo (BoolPair.get d.times)) with Not_found ->
1349     try Xml (sample_rec_times memo (BoolPair.get d.xml)) with Not_found ->
1350 abate 281 try sample_rec_record memo d.record with Not_found ->
1351 abate 1 raise Not_found
1352    
1353    
1354     and sample_rec_times memo c =
1355     find (sample_rec_times_aux memo) c
1356    
1357     and sample_rec_times_aux memo (left,right) =
1358     let rec aux accu1 accu2 = function
1359     | (t1,t2)::right ->
1360 abate 158 (*TODO: check: is this correct ? non_empty could return true
1361     but because of coinduction, the call to aux may raise Not_found, no ? *)
1362 abate 1 let accu1' = diff_t accu1 t1 in
1363     if non_empty accu1' then aux accu1' accu2 right else
1364     let accu2' = diff_t accu2 t2 in
1365     if non_empty accu2' then aux accu1 accu2' right else
1366     raise Not_found
1367 abate 110 | [] -> (sample_rec memo accu1, sample_rec memo accu2)
1368 abate 1 in
1369     let (accu1,accu2) = cap_product left in
1370     if (is_empty accu1) || (is_empty accu2) then raise Not_found;
1371     aux accu1 accu2 right
1372    
1373     and sample_rec_arrow c =
1374     find sample_rec_arrow_aux c
1375    
1376 abate 10 and check_empty_simple_arrow_line left (s1,s2) =
1377     let rec aux accu1 accu2 = function
1378     | (t1,t2)::left ->
1379     let accu1' = diff_t accu1 t1 in
1380     if non_empty accu1' then aux accu1 accu2 left;
1381     let accu2' = cap_t accu2 t2 in
1382     if non_empty accu2' then aux accu1 accu2 left
1383     | [] -> raise NotEmpty
1384     in
1385     let accu1 = descr s1 in
1386     (is_empty accu1) ||
1387     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1388    
1389     and check_empty_arrow_line left right =
1390     List.exists (check_empty_simple_arrow_line left) right
1391    
1392 abate 1 and sample_rec_arrow_aux (left,right) =
1393 abate 10 if (check_empty_arrow_line left right) then raise Not_found
1394 abate 1 else Fun left
1395    
1396    
1397     and sample_rec_record memo c =
1398     Record (find (sample_rec_record_aux memo) (get_record c))
1399    
1400 abate 229 and sample_rec_record_aux memo (labels,(oleft,left),rights) =
1401 abate 158 let rec aux = function
1402     | [] ->
1403     let l = ref labels and fields = ref [] in
1404     for i = 0 to Array.length left - 1 do
1405 abate 229 fields := (List.hd !l, sample_rec memo left.(i))::!fields;
1406 abate 158 l := List.tl !l
1407     done;
1408 abate 252 raise (FoundSampleRecord (oleft, List.rev !fields))
1409 abate 229 | (oright,right)::rights ->
1410 abate 158 let next = (oleft && (not oright)) in
1411     if next then aux rights
1412     else
1413     for i = 0 to Array.length left - 1 do
1414     let back = left.(i) in
1415     let di = diff back right.(i) in
1416 abate 229 if not (is_empty di) then (
1417 abate 158 left.(i) <- diff back right.(i);
1418     aux rights;
1419     left.(i) <- back;
1420     )
1421     done
1422     in
1423     if exists (Array.length left)
1424 abate 229 (fun i -> is_empty left.(i)) then raise Not_found;
1425 abate 158 try aux rights; raise Not_found
1426 abate 252 with FoundSampleRecord (o,r) -> (o,r)
1427 abate 1
1428 abate 158
1429    
1430    
1431 abate 365
1432     let get x = try sample_rec Assumptions.empty x with Not_found -> Other
1433 abate 158
1434 abate 71 let rec print_sep f sep ppf = function
1435     | [] -> ()
1436     | [x] -> f ppf x
1437     | x::rem -> f ppf x; Format.fprintf ppf "%s" sep; print_sep f sep ppf rem
1438    
1439 abate 365 let rec is_seq = function
1440     | Atom a -> a == Print.nil_atom
1441     | Pair (_,y) -> is_seq y
1442     | _ -> false
1443 abate 71
1444 abate 365 let rec print ppf s =
1445     if is_seq s then
1446     Format.fprintf ppf "@[[@ %a]@]" print_seq s
1447     else match s with
1448 abate 222 | Int i -> Intervals.print_v ppf i
1449     | Atom a -> Atoms.print_v ppf a
1450     | Char c -> Chars.print_v ppf c
1451 abate 71 | Pair (x1,x2) -> Format.fprintf ppf "(%a,%a)" print x1 print x2
1452 abate 365 | Xml (Atom tag, Pair (Record (o,r), child)) ->
1453     Format.fprintf ppf "<%s%a>%a" (Atoms.value tag) print_rec r
1454     print child
1455 abate 263 | Xml (Atom tag, Pair (attr, child)) ->
1456 abate 283 Format.fprintf ppf "<%s %a>%a" (Atoms.value tag) print attr print child
1457 abate 110 | Xml (x1,x2) -> Format.fprintf ppf "XML(%a,%a)" print x1 print x2
1458 abate 252 | Record (o,r) ->
1459 abate 365 Format.fprintf ppf "{%a%s }"
1460     print_rec r
1461 abate 252 (if o then "; ..." else "")
1462 abate 71 | Fun iface ->
1463     Format.fprintf ppf "(fun ( %a ) x -> ...)"
1464     (print_sep
1465     (fun ppf (t1,t2) ->
1466     Format.fprintf ppf "%a -> %a; "
1467     Print.print t1 Print.print t2
1468     )
1469     " ; "
1470     ) iface
1471 abate 156 | Other ->
1472     Format.fprintf ppf "[cannot determine value]"
1473 abate 365 and print_rec ppf r =
1474     print_sep
1475     (fun ppf (l,x) ->
1476     Format.fprintf ppf " %s = %a"
1477     (LabelPool.value l)
1478     print x
1479     )
1480     " ;" ppf r
1481     and print_seq ppf = function
1482     | Pair(x,y) -> print ppf x; Format.fprintf ppf "@ "; print_seq ppf y
1483     | _ -> ()
1484 abate 1 end
1485    
1486    
1487    
1488 abate 156
1489 abate 241
1490 abate 160
1491 abate 71 let memo_normalize = ref DescrMap.empty
1492 abate 1
1493    
1494     let rec rec_normalize d =
1495 abate 71 try DescrMap.find d !memo_normalize
1496 abate 1 with Not_found ->
1497     let n = make () in
1498 abate 71 memo_normalize := DescrMap.add d n !memo_normalize;
1499 abate 1 let times =
1500 abate 224 List.fold_left
1501     (fun accu (d1,d2) -> BoolPair.cup accu (BoolPair.atom (rec_normalize d1, rec_normalize d2)))
1502     BoolPair.empty (Product.normal d)
1503 abate 1 in
1504 abate 110 let xml =
1505 abate 224 List.fold_left
1506     (fun accu (d1,d2) -> BoolPair.cup accu (BoolPair.atom (rec_normalize d1, rec_normalize d2)))
1507     BoolPair.empty (Product.normal ~kind:`XML d)
1508 abate 110 in
1509 abate 156 let record = d.record
1510 abate 1 in
1511 abate 110 define n { d with times = times; xml = xml; record = record };
1512 abate 1 n
1513    
1514     let normalize n =
1515 abate 29 descr (internalize (rec_normalize n))
1516 abate 6
1517 abate 11 module Arrow =
1518     struct
1519 abate 19 let check_simple left s1 s2 =
1520     let rec aux accu1 accu2 = function
1521     | (t1,t2)::left ->
1522     let accu1' = diff_t accu1 t1 in
1523 abate 45 if non_empty accu1' then aux accu1 accu2 left;
1524 abate 19 let accu2' = cap_t accu2 t2 in
1525 abate 45 if non_empty accu2' then aux accu1 accu2 left
1526 abate 19 | [] -> raise NotEmpty
1527     in
1528     let accu1 = descr s1 in
1529     (is_empty accu1) ||
1530     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1531    
1532     let check_strenghten t s =
1533 abate 271 (*
1534 abate 224 let left = match (BoolPair.get t.arrow) with [ (p,[]) ] -> p | _ -> assert false in
1535 abate 19 let rec aux = function
1536     | [] -> raise Not_found
1537     | (p,n) :: rem ->
1538     if (List.for_all (fun (a,b) -> check_simple left a b) p) &&
1539     (List.for_all (fun (a,b) -> not (check_simple left a b)) n) then
1540 abate 224 { empty with arrow = Obj.magic [ (SortedList.cup left p, n) ] } (* rework this ! *)
1541 abate 19 else aux rem
1542     in
1543 abate 224 aux (BoolPair.get s.arrow)
1544 abate 271 *)
1545     if subtype t s then t else raise Not_found
1546 abate 19
1547 abate 45 let check_simple_iface left s1 s2 =
1548     let rec aux accu1 accu2 = function
1549     | (t1,t2)::left ->
1550     let accu1' = diff accu1 t1 in
1551     if non_empty accu1' then aux accu1 accu2 left;
1552     let accu2' = cap accu2 t2 in
1553     if non_empty accu2' then aux accu1 accu2 left
1554     | [] -> raise NotEmpty
1555     in
1556     let accu1 = descr s1 in
1557     (is_empty accu1) ||
1558     (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1559    
1560     let check_iface iface s =
1561     let rec aux = function
1562     | [] -> false
1563     | (p,n) :: rem ->
1564     ((List.for_all (fun (a,b) -> check_simple_iface iface a b) p) &&
1565     (List.for_all (fun (a,b) -> not (check_simple_iface iface a b)) n))
1566     || (aux rem)
1567     in
1568 abate 224 aux (BoolPair.get s.arrow)
1569 abate 45
1570 abate 11 type t = descr * (descr * descr) list list
1571    
1572     let get t =
1573     List.fold_left
1574     (fun ((dom,arr) as accu) (left,right) ->
1575     if Sample.check_empty_arrow_line left right
1576     then accu
1577     else (
1578     let left =
1579     List.map
1580     (fun (t,s) -> (descr t, descr s)) left in
1581     let d = List.fold_left (fun d (t,_) -> cup d t) empty left in
1582     (cap dom d, left :: arr)
1583     )
1584     )
1585     (any, [])
1586 abate 224 (BoolPair.get t.arrow)
1587 abate 11
1588     let domain (dom,_) = dom
1589    
1590     let apply_simple t result left =
1591     let rec aux result accu1 accu2 = function
1592     | (t1,s1)::left ->
1593     let result =
1594     let accu1 = diff accu1 t1 in
1595     if non_empty accu1 then aux result accu1 accu2 left
1596     else result in
1597     let result =
1598     let accu2 = cap accu2 s1 in
1599     aux result accu1 accu2 left in
1600     result
1601     | [] ->
1602     if subtype accu2 result
1603     then result
1604     else cup result accu2
1605     in
1606     aux result t any left
1607    
1608     let apply (_,arr) t =
1609     List.fold_left (apply_simple t) empty arr
1610    
1611 abate 19 let need_arg (dom, arr) =
1612     List.exists (function [_] -> false | _ -> true) arr
1613    
1614     let apply_noarg (_,arr) =
1615     List.fold_left
1616     (fun accu ->
1617     function
1618     | [(t,s)] -> cup accu s
1619     | _ -> assert false
1620     )
1621     empty arr
1622    
1623 abate 11 let any = { empty with arrow = any.arrow }
1624 abate 332 let is_empty (_,arr) = arr == []
1625 abate 11 end
1626    
1627    
1628 abate 16 module Int = struct
1629 abate 45 let has_int d i = Intervals.contains i d.ints
1630 abate 16 let get d = d.ints
1631     let any = { empty with ints = Intervals.any }
1632     end
1633 abate 11
1634 abate 17 module Atom = struct
1635     let has_atom d a = Atoms.contains a d.atoms
1636 abate 243 let get d = d.atoms
1637 abate 17 end
1638    
1639 abate 45 module Char = struct
1640     let has_char d c = Chars.contains c d.chars
1641 abate 364 let get d = d.chars
1642 abate 58 let any = { empty with chars = Chars.any }
1643 abate 45 end
1644    
1645 abate 186 let print_stat ppf =
1646 abate 188 (* Format.fprintf ppf "nb_rec = %i@." !nb_rec;
1647 abate 186 Format.fprintf ppf "nb_norec = %i@." !nb_norec;
1648 abate 188 *)
1649 abate 186 ()
1650    

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