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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 229 - (show annotations)
Tue Jul 10 17:17:01 2007 UTC (5 years, 11 months ago) by abate
File size: 37461 byte(s)
[r2003-03-09 23:48:48 by cvscast] Groose simplification records + ralentissement

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

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