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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 365 - (show annotations)
Tue Jul 10 17:28:28 2007 UTC (5 years, 10 months ago) by abate
File size: 45264 byte(s)
[r2003-05-18 13:56:14 by cvscast] Pretty-printer for sample values

Original author: cvscast
Date: 2003-05-18 13:56:14+00:00
1 open Ident
2
3 (*
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 module HashedString =
14 struct
15 type t = string
16 let hash = Hashtbl.hash
17 let equal = (=)
18 end
19
20
21 type const =
22 | Integer of Intervals.v
23 | Atom of Atoms.v
24 | Char of Chars.v
25
26 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 let equal_const c1 c2 = compare_const c1 c2 = 0
42
43 type pair_kind = [ `Normal | `XML ]
44
45 type 'a node0 = { id : int; mutable descr : 'a }
46
47 module NodePair = struct
48 type 'a t = 'a node0 * 'a node0
49 let dump ppf (x,y) =
50 Format.fprintf ppf "(%i,%i)" x.id y.id
51 let compare (y1,x1) (y2,x2) =
52 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 module RecArg = struct
60 type 'a t = bool * 'a node0 label_map
61
62 let dump ppf (o,r) = ()
63
64 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 module BoolPair = Bool.Make(NodePair)
99 module BoolRec = Bool.Make(RecArg)
100
101 type descr = {
102 atoms : Atoms.t;
103 ints : Intervals.t;
104 chars : Chars.t;
105 times : descr BoolPair.t;
106 xml : descr BoolPair.t;
107 arrow : descr BoolPair.t;
108 record: descr BoolRec.t;
109 absent: bool
110 } and node = descr node0
111
112
113 let empty = {
114 times = BoolPair.empty;
115 xml = BoolPair.empty;
116 arrow = BoolPair.empty;
117 record= BoolRec.empty;
118 ints = Intervals.empty;
119 atoms = Atoms.empty;
120 chars = Chars.empty;
121 absent= false;
122 }
123
124 let any = {
125 times = BoolPair.full;
126 xml = BoolPair.full;
127 arrow = BoolPair.full;
128 record= BoolRec.full;
129 ints = Intervals.any;
130 atoms = Atoms.any;
131 chars = Chars.any;
132 absent= false;
133 }
134
135
136 let interval i = { empty with ints = i }
137 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 let record label t =
141 { 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 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
151 let cup x y =
152 if x == y then x else {
153 times = BoolPair.cup x.times y.times;
154 xml = BoolPair.cup x.xml y.xml;
155 arrow = BoolPair.cup x.arrow y.arrow;
156 record= BoolRec.cup x.record y.record;
157 ints = Intervals.cup x.ints y.ints;
158 atoms = Atoms.cup x.atoms y.atoms;
159 chars = Chars.cup x.chars y.chars;
160 absent= x.absent || y.absent;
161 }
162
163 let cap x y =
164 if x == y then x else {
165 times = BoolPair.cap x.times y.times;
166 xml = BoolPair.cap x.xml y.xml;
167 record= BoolRec.cap x.record y.record;
168 arrow = BoolPair.cap x.arrow y.arrow;
169 ints = Intervals.cap x.ints y.ints;
170 atoms = Atoms.cap x.atoms y.atoms;
171 chars = Chars.cap x.chars y.chars;
172 absent= x.absent && y.absent;
173 }
174
175 let diff x y =
176 if x == y then empty else {
177 times = BoolPair.diff x.times y.times;
178 xml = BoolPair.diff x.xml y.xml;
179 arrow = BoolPair.diff x.arrow y.arrow;
180 record= BoolRec.diff x.record y.record;
181 ints = Intervals.diff x.ints y.ints;
182 atoms = Atoms.diff x.atoms y.atoms;
183 chars = Chars.diff x.chars y.chars;
184 absent= x.absent && not y.absent;
185 }
186
187
188 let equal_descr a b =
189 (Atoms.equal a.atoms b.atoms) &&
190 (Chars.equal a.chars b.chars) &&
191 (Intervals.equal a.ints b.ints) &&
192 (BoolPair.equal a.times b.times) &&
193 (BoolPair.equal a.xml b.xml) &&
194 (BoolPair.equal a.arrow b.arrow) &&
195 (BoolRec.equal a.record b.record) &&
196 (a.absent == b.absent)
197
198 let compare_descr a b =
199 if a == b then 0
200 else let c = Atoms.compare a.atoms b.atoms in if c <> 0 then c
201 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 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 else let c = BoolRec.compare a.record b.record in if c <> 0 then c
207 else if a.absent && not b.absent then -1
208 else if b.absent && not a.absent then 1
209 else 0
210
211 let hash_descr a =
212 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 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 let accu = 17 * accu + BoolRec.hash a.record in
219 let accu = if a.absent then accu+5 else accu in
220 accu
221
222 (* 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 (BoolRec.trivially_disjoint a.record b.record) &&
231 (not (a.absent && b.absent))
232
233
234 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
244 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 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 let print_descr = ref (fun _ _ -> assert false)
273
274 let neg x = diff any x
275
276 let any_node = cons any
277
278 module LabelS = Set.Make(LabelPool)
279
280 let get_record r =
281 let labs accu (_,r) =
282 List.fold_left
283 (fun accu (l,_) -> LabelS.add l accu) accu (LabelMap.get r) in
284 let extend descrs labs (o,r) =
285 let rec aux i labs r =
286 match labs with
287 | [] -> ()
288 | l1::labs ->
289 match r with
290 | (l2,x)::r when l1 == l2 ->
291 descrs.(i) <- cap descrs.(i) (descr x);
292 aux (i+1) labs r
293 | r ->
294 if not o then descrs.(i) <-
295 cap descrs.(i) { empty with absent = true }; (* TODO:OPT *)
296 aux (i+1) labs r
297 in
298 aux 0 labs (LabelMap.get r);
299 o
300 in
301 let line (p,n) =
302 let labels =
303 List.fold_left labs (List.fold_left labs LabelS.empty p) n in
304 let labels = LabelS.elements labels in
305 let nlab = List.length labels in
306 let mk () = Array.create nlab { any with absent = true } in
307
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 List.map line (BoolRec.get r)
323
324
325
326
327
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 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
344 let rec exists max f =
345 (max > 0) && (f (max - 1) || exists (max - 1) f)
346
347 let trivially_empty d = equal_descr d empty
348
349 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 if n.status == Maybe then (try f n with NotEmpty -> ());
367 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 s.notify <- Nothing;
378 raise NotEmpty
379
380 let count_slot = ref 0
381 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 with NotEmpty -> if n.status == NEmpty then raise NotEmpty
391
392 let rec guard a f n =
393 match slot a with
394 | { status = Empty } -> ()
395 | { status = Maybe } as s -> n.active <- true; s.notify <- Do (n,f,s.notify)
396 | { status = NEmpty } -> f n
397
398 and slot d =
399 if not ((Intervals.is_empty d.ints) &&
400 (Atoms.is_empty d.atoms) &&
401 (Chars.is_empty d.chars) &&
402 (not d.absent)) then slot_not_empty
403 else try DescrHash.find memo d
404 with Not_found ->
405 (* incr count_slot;
406 Printf.eprintf "%i;" !count_slot; *)
407 (* Format.fprintf Format.std_formatter "Empty:%a@\n" !print_descr d; *)
408 let s = { status = Maybe; active = false; notify = Nothing } in
409 DescrHash.add memo d s;
410 (try
411 (* 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 iter_s s check_arrow (BoolPair.get d.arrow);
417 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 (* Printf.eprintf "[%i]" (List.length right);
425 flush stderr; *)
426 let rec aux accu1 accu2 right s = match right with
427 | (t1,t2)::right ->
428 let t1 = descr t1 and t2 = descr t2 in
429 if trivially_disjoint accu1 t1 ||
430 trivially_disjoint accu2 t2 then (
431 aux accu1 accu2 right s )
432 else (
433 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 )
443 | [] -> set s
444 in
445 let (accu1,accu2) = cap_product left in
446 (* if List.length right > 6 then (
447 Printf.eprintf "HEURISTIC\n"; flush stderr;
448 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 Printf.eprintf "HEURISTIC failed\n"; flush stderr;
453 ); *)
454 guard accu1 (guard accu2 (aux accu1 accu2 right)) s
455
456
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 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 and check_record (labels,(oleft,left),rights) s =
497 let rec aux rights s = match rights with
498 | [] -> set s
499 | (oright,right)::rights ->
500 let next =
501 (oleft && (not oright)) ||
502 exists (Array.length left)
503 (fun i -> trivially_disjoint left.(i) right.(i))
504 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 guard di (fun s ->
511 left.(i) <- diff back right.(i);
512 aux rights s;
513 left.(i) <- back;
514 ) s
515 done
516 in
517 let rec start i s =
518 if (i < 0) then aux rights s
519 else
520 guard left.(i) (start (i - 1)) s
521 in
522 start (Array.length left - 1) s
523
524
525 let is_empty d =
526 (* Printf.eprintf "is_empty: start\n"; flush stderr; *)
527 let s = slot d in
528 List.iter
529 (fun s' ->
530 if s'.status == Maybe then s'.status <- Empty; s'.notify <- Nothing)
531 !marks;
532 marks := [];
533 (* Printf.eprintf "is_empty: done\n"; flush stderr; *)
534 s.status == Empty
535
536
537 module Assumptions = Set.Make(struct type t = descr let compare = compare_descr end)
538 let memo = ref Assumptions.empty
539 let cache_false = DescrHash.create 33000
540
541 let rec empty_rec d =
542 if not (Intervals.is_empty d.ints) then false
543 else if not (Atoms.is_empty d.atoms) then false
544 else if not (Chars.is_empty d.chars) then false
545 else if d.absent then false
546 else if DescrHash.mem cache_false d then false
547 else if Assumptions.mem d !memo then true
548 else (
549 let backup = !memo in
550 memo := Assumptions.add d backup;
551 if
552 (empty_rec_times (BoolPair.get d.times)) &&
553 (empty_rec_times (BoolPair.get d.xml)) &&
554 (empty_rec_arrow (BoolPair.get d.arrow)) &&
555 (empty_rec_record d.record)
556 then true
557 else (
558 memo := backup;
559 DescrHash.add cache_false d ();
560 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 if trivially_empty (cap_t accu1 t1) ||
571 trivially_empty (cap_t accu2 t2) then
572 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 if not (empty_rec accu2') then aux accu1 accu2' right
578 | [] -> 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
585 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 if not (empty_rec accu1') then aux accu1' accu2 left;
594 let accu2' = cap_t accu2 t2 in
595 if not (empty_rec accu2') then aux accu1 accu2' left
596 | [] -> 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 and empty_rec_record_aux (labels,(oleft,left),rights) =
605 let rec aux = function
606 | [] -> raise NotEmpty
607 | (oright,right)::rights ->
608 let next =
609 (oleft && (not oright)) ||
610 exists (Array.length left)
611 (fun i ->
612 trivially_empty (cap left.(i) right.(i)))
613 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 if not (empty_rec di) then (
620 left.(i) <- diff back right.(i);
621 aux rights;
622 left.(i) <- back;
623 )
624 done
625 in
626 exists (Array.length left)
627 (fun i -> empty_rec left.(i))
628 ||
629 (try aux rights; true with NotEmpty -> false)
630
631
632 and empty_rec_record c =
633 List.for_all empty_rec_record_aux (get_record c)
634
635 (*
636 let is_empty d =
637 empty_rec d
638 *)
639
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 let normal_aux = function
660 | ([] | [ _ ]) as d -> d
661 | d ->
662
663 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 (* if equal_descr d1 t1 then r := (d1,cup d2 t2) else*)
671
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 (*
689 This version explodes when dealing with
690 Any - [ t1? t2? t3? ... tn? ]
691 ==> need partitioning
692 *)
693 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
711 (* Partitioning:
712
713 (t,s) - ((t1,s1) | (t2,s2) | ... | (tn,sn))
714 =
715 (t & t1, s - s1) | ... | (t & tn, s - sn) | (t - (t1|...|tn), s)
716
717 *)
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 List.iter line (BoolPair.get d);
738 !accu
739 (* 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
743
744 let get ?(kind=`Normal) d =
745 match kind with
746 | `Normal -> get_aux d.times
747 | `XML -> get_aux d.xml
748
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 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
756 let restrict_1 rects pi1 =
757 let aux acc (t1,t2) =
758 let t1 = cap t1 pi1 in if is_empty t1 then acc else (t1,t2)::acc in
759 List.fold_left aux [] rects
760
761 type normal = t
762
763 module Memo = Map.Make(struct type t = descr BoolPair.t let compare = BoolPair.compare end)
764
765 (* TODO: try with an hashtable *)
766 (* Also, avoid lookup for simple products (t1,t2) *)
767 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 let gd = get_aux d in
774 let n = normal_aux gd in
775 (* Could optimize this call to normal_aux because one already
776 know that each line is normalized ... *)
777 memo := Memo.add d n !memo;
778 n
779
780 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 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 let any = { empty with times = any.times }
798 and any_xml = { empty with xml = any.xml }
799 let is_empty d = d == []
800 end
801
802 module Record =
803 struct
804 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
809 let only_absent = {empty with absent = true}
810 let only_absent_node = cons only_absent
811
812 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 let print_const ppf = function
980 | Integer i -> Intervals.print_v ppf i
981 | Atom a -> Atoms.print_v ppf a
982 | Char c -> Chars.print_v ppf c
983
984 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
1006 module DescrPairMap =
1007 Map.Make(
1008 struct
1009 type t = descr * descr
1010 let compare (x1,y1) (x2,y2) =
1011 let c = compare_descr x1 x2 in
1012 if c = 0 then compare_descr y1 y2 else c
1013 end)
1014
1015 let named = State.ref "Types.Print.named" DescrMap.empty
1016 let named_xml = State.ref "Types.Print.named_xml" DescrPairMap.empty
1017 let register_global name d =
1018 if equal_descr { d with xml = BoolPair.empty } empty then
1019 (let l = (*Product.merge_same_2*) (Product.get ~kind:`XML d) in
1020 match l with
1021 | [(t1,t2)] -> named_xml := DescrPairMap.add (t1,t2) name !named_xml
1022 | _ -> ());
1023 named := DescrMap.add d name !named
1024
1025 let memo = DescrHash.create 63
1026 let empty_t = { def = []; name = None }
1027
1028 let count_name = ref 0
1029 let name () =
1030 incr count_name;
1031 "X" ^ (string_of_int !count_name)
1032
1033 let to_print = ref []
1034
1035 let trivial_rec b = b == BoolRec.empty || (is_empty { empty with record = BoolRec.diff BoolRec.full b})
1036
1037 let trivial_pair b = b == BoolPair.empty || b == BoolPair.full
1038
1039 let worth_abbrev d =
1040 not (trivial_pair d.times && trivial_pair d.xml &&
1041 trivial_pair d.arrow && trivial_rec d.record)
1042
1043 let rec prepare d =
1044 try
1045 let slot = DescrHash.find memo d in
1046 if (slot.name == None) then
1047 (let n = name () in
1048 slot.name <- Some n;
1049 to_print := (n,slot) :: !to_print);
1050 slot
1051 with Not_found ->
1052 try
1053 let n = DescrMap.find d !named in
1054 let s = { name = Some n; def = [] } in
1055 DescrHash.add memo d s;
1056 s
1057 with Not_found ->
1058 let slot = { empty_t with def = [] } in
1059 if worth_abbrev d then DescrHash.add memo d slot;
1060 let (seq,not_seq) =
1061 if (subtype { empty with times = d.times } seqs_descr) then
1062 (cap d seqs_descr, diff d seqs_descr)
1063 else
1064 (empty, d) in
1065
1066 let add u = slot.def <- u :: slot.def in
1067 if (non_empty seq) then
1068 add (Regexp (decompile seq));
1069 List.iter
1070 (fun (t1,t2) -> add (Pair (prepare t1, prepare t2)))
1071 (Product.get not_seq);
1072 List.iter
1073 (fun (t1,t2) ->
1074 try
1075 let n = DescrPairMap.find (t1,t2) !named_xml in
1076 add (Name n)
1077 with
1078 Not_found ->
1079 let tag =
1080 match Atoms.is_atom t1.atoms with
1081 | Some a when is_empty { t1 with atoms = Atoms.empty } ->
1082 `Tag (Atoms.value a)
1083 | _ -> `Type (prepare t1) in
1084 List.iter
1085 (fun (ta,tb) -> add (Xml (tag, prepare ta, prepare tb)))
1086 (Product.get t2)
1087 )
1088 ((*Product.merge_same_2*) (Product.get ~kind:`XML not_seq));
1089 List.iter
1090 (fun (r,some,none) ->
1091 let r = LabelMap.map
1092 (fun t ->
1093 (t.absent, prepare { t with absent = false })) r in
1094 add (Record (r,some,none)))
1095 (Record.get not_seq);
1096 (match Chars.is_char not_seq.chars with
1097 | Some c -> add (Char c)
1098 | None ->
1099 List.iter (fun x -> add (Atomic x)) (Chars.print not_seq.chars));
1100 List.iter (fun x -> add (Atomic x)) (Intervals.print not_seq.ints);
1101 List.iter (fun x -> add (Atomic x)) (Atoms.print not_seq.atoms);
1102 List.iter
1103 (fun (p,n) ->
1104 let aux (t,s) = prepare (descr t), prepare (descr s) in
1105 let p = List.map aux p and n = List.map aux n in
1106 add (Arrows (p,n)))
1107 (BoolPair.get not_seq.arrow);
1108 slot.def <- List.rev slot.def;
1109 slot
1110
1111
1112 and decompile d =
1113 Decompile.decompile
1114 (fun t ->
1115 let tr = Product.get t in
1116 let tr = List.map (fun (l,t) -> prepare l, t) tr in
1117 tr, Atoms.contains nil_atom t.atoms)
1118 d
1119
1120 let rec do_print_slot pri ppf s =
1121 match s.name with
1122 | None -> do_print_slot_real pri ppf s.def
1123 | Some n -> Format.fprintf ppf "%s" n
1124 and do_print_slot_real pri ppf def =
1125 let rec aux ppf = function
1126 | [] -> Format.fprintf ppf "Empty"
1127 | [ h ] -> do_print ppf h
1128 | h :: t -> Format.fprintf ppf "%a |@ %a" do_print h aux t
1129 in
1130 if (pri >= 2) && (List.length def >= 2)
1131 then Format.fprintf ppf "@[(%a)@]" aux def
1132 else aux ppf def
1133 and do_print ppf = function
1134 | Name n -> Format.fprintf ppf "%s" n
1135 | Char c -> Chars.print_v ppf c
1136 | Regexp r -> Format.fprintf ppf "@[[ %a ]@]" (do_print_regexp 0) r
1137 | Atomic a -> a ppf
1138 | Pair (t1,t2) ->
1139 Format.fprintf ppf "@[(%a,%a)@]"
1140 (do_print_slot 0) t1
1141 (do_print_slot 0) t2
1142 | Xml (tag,t2,t3) ->
1143 Format.fprintf ppf "<%a%a>%a"
1144 do_print_tag tag
1145 do_print_attr t2
1146 (do_print_slot 0) t3
1147 | Record (r,some,none) ->
1148 if some then Format.fprintf ppf "@[{"
1149 else Format.fprintf ppf "@[{|";
1150 do_print_record ppf r;
1151 if not none then Format.fprintf ppf ";@ ...";
1152 if some then Format.fprintf ppf " }@]"
1153 else Format.fprintf ppf " |}@]"
1154 | Arrows (p,n) ->
1155 (match p with
1156 | [] -> Format.fprintf ppf "Arrow"
1157 | (t,s)::l ->
1158 Format.fprintf ppf "%a" do_print_arrow (t,s);
1159 List.iter
1160 (fun (t,s) ->
1161 Format.fprintf ppf " &@ %a" do_print_arrow (t,s)
1162 ) l);
1163 List.iter
1164 (fun (t,s) ->
1165 Format.fprintf ppf " \\@ %a" do_print_arrow (t,s)
1166 ) n
1167 and do_print_arrow ppf (t,s) =
1168 Format.fprintf ppf "%a -> %a"
1169 (do_print_slot 0) t
1170 (do_print_slot 0) s
1171 and do_print_tag ppf = function
1172 | `Tag s -> Format.fprintf ppf "%s" s
1173 | `Type t -> Format.fprintf ppf "(%a)" (do_print_slot 0) t
1174 and do_print_attr ppf = function
1175 | { name = None; def = [ Record (r,true,true) ] } -> do_print_record ppf r
1176 | t -> Format.fprintf ppf " %a" (do_print_slot 2) t
1177 and do_print_record ppf r =
1178 let first = ref true in
1179 List.iter
1180 (fun (l,(o,t)) ->
1181 let sep = if !first then (first := false; "") else ";" in
1182 let opt = if o then "?" else "" in
1183 Format.fprintf ppf "%s@ @[%s =%s@] %a" sep
1184 (LabelPool.value l) opt (do_print_slot 0) t
1185 ) (LabelMap.get r)
1186 and do_print_regexp pri ppf = function
1187 | Pretty.Empty -> assert false
1188 | Pretty.Epsilon -> ()
1189 | Pretty.Seq (Pretty.Trans t1,Pretty.Star (Pretty.Trans t2))
1190 | Pretty.Seq (Pretty.Star (Pretty.Trans t1),Pretty.Trans t2)
1191 when t1 == t2 ->
1192 Format.fprintf ppf "@[%a@]+" (do_print_slot 3) t1
1193 | Pretty.Seq (Pretty.Trans { name = None; def = [ Char _ ] }, _) as r->
1194 (match extract_string [] r with
1195 | s, None ->
1196 Format.fprintf ppf "'";
1197 List.iter (Chars.print_v_in_string ppf) s;
1198 Format.fprintf ppf "'"
1199 | s, Some r ->
1200 if pri >= 3 then Format.fprintf ppf "@[(";
1201 Format.fprintf ppf "'";
1202 List.iter (Chars.print_v_in_string ppf) s;
1203 Format.fprintf ppf "' %a" (do_print_regexp 2) r;
1204 if pri >= 3 then Format.fprintf ppf ")@]")
1205 | Pretty.Seq (r1,r2) ->
1206 if pri >= 3 then Format.fprintf ppf "@[(";
1207 Format.fprintf ppf "%a@ %a"
1208 (do_print_regexp 2) r1
1209 (do_print_regexp 2) r2;
1210 if pri >= 3 then Format.fprintf ppf ")@]"
1211 | Pretty.Alt (r,Pretty.Epsilon) | Pretty.Alt (Pretty.Epsilon,r) ->
1212 Format.fprintf ppf "@[%a@]?" (do_print_regexp 3) r
1213 | Pretty.Alt (r1,r2) ->
1214 if pri >= 2 then Format.fprintf ppf "@[(";
1215 Format.fprintf ppf "%a |@ %a"
1216 (do_print_regexp 1) r1
1217 (do_print_regexp 1) r2;
1218 if pri >= 2 then Format.fprintf ppf ")@]"
1219 | Pretty.Star r ->
1220 Format.fprintf ppf "@[%a@]*" (do_print_regexp 3) r
1221 | Pretty.Trans t ->
1222 do_print_slot pri ppf t
1223 and extract_string accu = function
1224 | Pretty.Seq (Pretty.Trans { name = None; def = [ Char c ] }, r) ->
1225 extract_string (c :: accu) r
1226 | Pretty.Trans { name = None; def = [ Char c ] } ->
1227 (List.rev (c :: accu), None)
1228 | r -> (List.rev accu,Some r)
1229
1230
1231 let print_descr ppf d =
1232 let t = prepare d in
1233 Format.fprintf ppf "@[@[%a@]" (do_print_slot 0) t;
1234 (match List.rev !to_print with
1235 | [] -> ()
1236 | (n,s)::t ->
1237 Format.fprintf ppf
1238 " where@ @[<v>%s = @[%a@]" n (do_print_slot_real 0) s.def;
1239 List.iter
1240 (fun (n,s) ->
1241 Format.fprintf ppf " and@ %s = @[%a@]"
1242 n (do_print_slot_real 0) s.def)
1243 t;
1244 Format.fprintf ppf "@]"
1245 );
1246 Format.fprintf ppf "@]";
1247 count_name := 0;
1248 to_print := [];
1249 DescrHash.clear memo
1250
1251 let print ppf n = print_descr ppf (descr n)
1252
1253 end
1254
1255 let () = print_descr := Print.print_descr
1256
1257 module Positive =
1258 struct
1259 type rhs = [ `Type of descr | `Cup of v list | `Times of v * v | `Xml of v * v ]
1260 and v = { mutable def : rhs; mutable node : node option }
1261
1262
1263 let rec make_descr seen v =
1264 if List.memq v seen then empty
1265 else
1266 let seen = v :: seen in
1267 match v.def with
1268 | `Type d -> d
1269 | `Cup vl ->
1270 List.fold_left (fun acc v -> cup acc (make_descr seen v)) empty vl
1271 | `Times (v1,v2) -> times (make_node v1) (make_node v2)
1272 | `Xml (v1,v2) -> xml (make_node v1) (make_node v2)
1273
1274 and make_node v =
1275 match v.node with
1276 | Some n -> n
1277 | None ->
1278 let n = make () in
1279 v.node <- Some n;
1280 let d = make_descr [] v in
1281 define n d;
1282 n
1283
1284 let forward () = { def = `Cup []; node = None }
1285 let def v d = v.def <- d
1286 let cons d = let v = forward () in def v d; v
1287 let ty d = cons (`Type d)
1288 let cup vl = cons (`Cup vl)
1289 let times d1 d2 = cons (`Times (d1,d2))
1290 let xml d1 d2 = cons (`Xml (d1,d2))
1291 let define v1 v2 = def v1 (`Cup [v2])
1292
1293 let solve v = internalize (make_node v)
1294 end
1295
1296
1297
1298
1299 (* Sample value *)
1300 module Sample =
1301 struct
1302
1303
1304 let rec find f = function
1305 | [] -> raise Not_found
1306 | x::r -> try f x with Not_found -> find f r
1307
1308 type t =
1309 | Int of Intervals.v
1310 | Atom of Atoms.v
1311 | Char of Chars.v
1312 | Pair of (t * t)
1313 | Xml of (t * t)
1314 | Record of (bool * (label * t) list)
1315 | Fun of (node * node) list
1316 | Other
1317 exception FoundSampleRecord of bool * (label * t) list
1318
1319 let rec sample_rec memo d =
1320 if (Assumptions.mem d memo) || (is_empty d) then raise Not_found
1321 else
1322 try Int (Intervals.sample d.ints) with Not_found ->
1323 try Atom (Atoms.sample d.atoms) with
1324 Not_found ->
1325 (* Here: could create a fresh atom ... *)
1326 try Char (Chars.sample d.chars) with Not_found ->
1327 try sample_rec_arrow (BoolPair.get d.arrow) with Not_found ->
1328
1329 let memo = Assumptions.add d memo in
1330 try Pair (sample_rec_times memo (BoolPair.get d.times)) with Not_found ->
1331 try Xml (sample_rec_times memo (BoolPair.get d.xml)) with Not_found ->
1332 try sample_rec_record memo d.record with Not_found ->
1333 raise Not_found
1334
1335
1336 and sample_rec_times memo c =
1337 find (sample_rec_times_aux memo) c
1338
1339 and sample_rec_times_aux memo (left,right) =
1340 let rec aux accu1 accu2 = function
1341 | (t1,t2)::right ->
1342 (*TODO: check: is this correct ? non_empty could return true
1343 but because of coinduction, the call to aux may raise Not_found, no ? *)
1344 let accu1' = diff_t accu1 t1 in
1345 if non_empty accu1' then aux accu1' accu2 right else
1346 let accu2' = diff_t accu2 t2 in
1347 if non_empty accu2' then aux accu1 accu2' right else
1348 raise Not_found
1349 | [] -> (sample_rec memo accu1, sample_rec memo accu2)
1350 in
1351 let (accu1,accu2) = cap_product left in
1352 if (is_empty accu1) || (is_empty accu2) then raise Not_found;
1353 aux accu1 accu2 right
1354
1355 and sample_rec_arrow c =
1356 find sample_rec_arrow_aux c
1357
1358 and check_empty_simple_arrow_line left (s1,s2) =
1359 let rec aux accu1 accu2 = function
1360 | (t1,t2)::left ->
1361 let accu1' = diff_t accu1 t1 in
1362 if non_empty accu1' then aux accu1 accu2 left;
1363 let accu2' = cap_t accu2 t2 in
1364 if non_empty accu2' then aux accu1 accu2 left
1365 | [] -> raise NotEmpty
1366 in
1367 let accu1 = descr s1 in
1368 (is_empty accu1) ||
1369 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1370
1371 and check_empty_arrow_line left right =
1372 List.exists (check_empty_simple_arrow_line left) right
1373
1374 and sample_rec_arrow_aux (left,right) =
1375 if (check_empty_arrow_line left right) then raise Not_found
1376 else Fun left
1377
1378
1379 and sample_rec_record memo c =
1380 Record (find (sample_rec_record_aux memo) (get_record c))
1381
1382 and sample_rec_record_aux memo (labels,(oleft,left),rights) =
1383 let rec aux = function
1384 | [] ->
1385 let l = ref labels and fields = ref [] in
1386 for i = 0 to Array.length left - 1 do
1387 fields := (List.hd !l, sample_rec memo left.(i))::!fields;
1388 l := List.tl !l
1389 done;
1390 raise (FoundSampleRecord (oleft, List.rev !fields))
1391 | (oright,right)::rights ->
1392 let next = (oleft && (not oright)) in
1393 if next then aux rights
1394 else
1395 for i = 0 to Array.length left - 1 do
1396 let back = left.(i) in
1397 let di = diff back right.(i) in
1398 if not (is_empty di) then (
1399 left.(i) <- diff back right.(i);
1400 aux rights;
1401 left.(i) <- back;
1402 )
1403 done
1404 in
1405 if exists (Array.length left)
1406 (fun i -> is_empty left.(i)) then raise Not_found;
1407 try aux rights; raise Not_found
1408 with FoundSampleRecord (o,r) -> (o,r)
1409
1410
1411
1412
1413
1414 let get x = try sample_rec Assumptions.empty x with Not_found -> Other
1415
1416 let rec print_sep f sep ppf = function
1417 | [] -> ()
1418 | [x] -> f ppf x
1419 | x::rem -> f ppf x; Format.fprintf ppf "%s" sep; print_sep f sep ppf rem
1420
1421 let rec is_seq = function
1422 | Atom a -> a == Print.nil_atom
1423 | Pair (_,y) -> is_seq y
1424 | _ -> false
1425
1426 let rec print ppf s =
1427 if is_seq s then
1428 Format.fprintf ppf "@[[@ %a]@]" print_seq s
1429 else match s with
1430 | Int i -> Intervals.print_v ppf i
1431 | Atom a -> Atoms.print_v ppf a
1432 | Char c -> Chars.print_v ppf c
1433 | Pair (x1,x2) -> Format.fprintf ppf "(%a,%a)" print x1 print x2
1434 | Xml (Atom tag, Pair (Record (o,r), child)) ->
1435 Format.fprintf ppf "<%s%a>%a" (Atoms.value tag) print_rec r
1436 print child
1437 | Xml (Atom tag, Pair (attr, child)) ->
1438 Format.fprintf ppf "<%s %a>%a" (Atoms.value tag) print attr print child
1439 | Xml (x1,x2) -> Format.fprintf ppf "XML(%a,%a)" print x1 print x2
1440 | Record (o,r) ->
1441 Format.fprintf ppf "{%a%s }"
1442 print_rec r
1443 (if o then "; ..." else "")
1444 | Fun iface ->
1445 Format.fprintf ppf "(fun ( %a ) x -> ...)"
1446 (print_sep
1447 (fun ppf (t1,t2) ->
1448 Format.fprintf ppf "%a -> %a; "
1449 Print.print t1 Print.print t2
1450 )
1451 " ; "
1452 ) iface
1453 | Other ->
1454 Format.fprintf ppf "[cannot determine value]"
1455 and print_rec ppf r =
1456 print_sep
1457 (fun ppf (l,x) ->
1458 Format.fprintf ppf " %s = %a"
1459 (LabelPool.value l)
1460 print x
1461 )
1462 " ;" ppf r
1463 and print_seq ppf = function
1464 | Pair(x,y) -> print ppf x; Format.fprintf ppf "@ "; print_seq ppf y
1465 | _ -> ()
1466 end
1467
1468
1469
1470
1471
1472
1473 let memo_normalize = ref DescrMap.empty
1474
1475
1476 let rec rec_normalize d =
1477 try DescrMap.find d !memo_normalize
1478 with Not_found ->
1479 let n = make () in
1480 memo_normalize := DescrMap.add d n !memo_normalize;
1481 let times =
1482 List.fold_left
1483 (fun accu (d1,d2) -> BoolPair.cup accu (BoolPair.atom (rec_normalize d1, rec_normalize d2)))
1484 BoolPair.empty (Product.normal d)
1485 in
1486 let xml =
1487 List.fold_left
1488 (fun accu (d1,d2) -> BoolPair.cup accu (BoolPair.atom (rec_normalize d1, rec_normalize d2)))
1489 BoolPair.empty (Product.normal ~kind:`XML d)
1490 in
1491 let record = d.record
1492 in
1493 define n { d with times = times; xml = xml; record = record };
1494 n
1495
1496 let normalize n =
1497 descr (internalize (rec_normalize n))
1498
1499 module Arrow =
1500 struct
1501 let check_simple left s1 s2 =
1502 let rec aux accu1 accu2 = function
1503 | (t1,t2)::left ->
1504 let accu1' = diff_t accu1 t1 in
1505 if non_empty accu1' then aux accu1 accu2 left;
1506 let accu2' = cap_t accu2 t2 in
1507 if non_empty accu2' then aux accu1 accu2 left
1508 | [] -> raise NotEmpty
1509 in
1510 let accu1 = descr s1 in
1511 (is_empty accu1) ||
1512 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1513
1514 let check_strenghten t s =
1515 (*
1516 let left = match (BoolPair.get t.arrow) with [ (p,[]) ] -> p | _ -> assert false in
1517 let rec aux = function
1518 | [] -> raise Not_found
1519 | (p,n) :: rem ->
1520 if (List.for_all (fun (a,b) -> check_simple left a b) p) &&
1521 (List.for_all (fun (a,b) -> not (check_simple left a b)) n) then
1522 { empty with arrow = Obj.magic [ (SortedList.cup left p, n) ] } (* rework this ! *)
1523 else aux rem
1524 in
1525 aux (BoolPair.get s.arrow)
1526 *)
1527 if subtype t s then t else raise Not_found
1528
1529 let check_simple_iface left s1 s2 =
1530 let rec aux accu1 accu2 = function
1531 | (t1,t2)::left ->
1532 let accu1' = diff accu1 t1 in
1533 if non_empty accu1' then aux accu1 accu2 left;
1534 let accu2' = cap accu2 t2 in
1535 if non_empty accu2' then aux accu1 accu2 left
1536 | [] -> raise NotEmpty
1537 in
1538 let accu1 = descr s1 in
1539 (is_empty accu1) ||
1540 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
1541
1542 let check_iface iface s =
1543 let rec aux = function
1544 | [] -> false
1545 | (p,n) :: rem ->
1546 ((List.for_all (fun (a,b) -> check_simple_iface iface a b) p) &&
1547 (List.for_all (fun (a,b) -> not (check_simple_iface iface a b)) n))
1548 || (aux rem)
1549 in
1550 aux (BoolPair.get s.arrow)
1551
1552 type t = descr * (descr * descr) list list
1553
1554 let get t =
1555 List.fold_left
1556 (fun ((dom,arr) as accu) (left,right) ->
1557 if Sample.check_empty_arrow_line left right
1558 then accu
1559 else (
1560 let left =
1561 List.map
1562 (fun (t,s) -> (descr t, descr s)) left in
1563 let d = List.fold_left (fun d (t,_) -> cup d t) empty left in
1564 (cap dom d, left :: arr)
1565 )
1566 )
1567 (any, [])
1568 (BoolPair.get t.arrow)
1569
1570 let domain (dom,_) = dom
1571
1572 let apply_simple t result left =
1573 let rec aux result accu1 accu2 = function
1574 | (t1,s1)::left ->
1575 let result =
1576 let accu1 = diff accu1 t1 in
1577 if non_empty accu1 then aux result accu1 accu2 left
1578 else result in
1579 let result =
1580 let accu2 = cap accu2 s1 in
1581 aux result accu1 accu2 left in
1582 result
1583 | [] ->
1584 if subtype accu2 result
1585 then result
1586 else cup result accu2
1587 in
1588 aux result t any left
1589
1590 let apply (_,arr) t =
1591 List.fold_left (apply_simple t) empty arr
1592
1593 let need_arg (dom, arr) =
1594 List.exists (function [_] -> false | _ -> true) arr
1595
1596 let apply_noarg (_,arr) =
1597 List.fold_left
1598 (fun accu ->
1599 function
1600 | [(t,s)] -> cup accu s
1601 | _ -> assert false
1602 )
1603 empty arr
1604
1605 let any = { empty with arrow = any.arrow }
1606 let is_empty (_,arr) = arr == []
1607 end
1608
1609
1610 module Int = struct
1611 let has_int d i = Intervals.contains i d.ints
1612 let get d = d.ints
1613 let any = { empty with ints = Intervals.any }
1614 end
1615
1616 module Atom = struct
1617 let has_atom d a = Atoms.contains a d.atoms
1618 let get d = d.atoms
1619 end
1620
1621 module Char = struct
1622 let has_char d c = Chars.contains c d.chars
1623 let get d = d.chars
1624 let any = { empty with chars = Chars.any }
1625 end
1626
1627 let print_stat ppf =
1628 (* Format.fprintf ppf "nb_rec = %i@." !nb_rec;
1629 Format.fprintf ppf "nb_norec = %i@." !nb_norec;
1630 *)
1631 ()
1632

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