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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 252 - (show annotations)
Tue Jul 10 17:19:28 2007 UTC (5 years, 10 months ago) by abate
File size: 41143 byte(s)
[r2003-03-16 17:39:47 by cvscast] Empty log message

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

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