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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 74 - (show annotations)
Tue Jul 10 17:03:46 2007 UTC (5 years, 10 months ago) by abate
File size: 24662 byte(s)
[r2002-11-01 22:06:20 by cvscast] Empty log message

Original author: cvscast
Date: 2002-11-01 22:06:20+00:00
1 open Recursive
2 open Printf
3
4
5
6 type label = int
7 type atom = int
8
9 let counter_label = ref 0
10 let label_table = Hashtbl.create 63
11 let label_names = Hashtbl.create 63
12
13 let label s =
14 try Hashtbl.find label_table s
15 with Not_found ->
16 incr counter_label;
17 Hashtbl.add label_table s !counter_label;
18 Hashtbl.add label_names !counter_label s;
19 !counter_label
20
21 let label_name l =
22 Hashtbl.find label_names l
23
24 let mk_atom = label
25
26 let atom_name = label_name
27
28 type const = Integer of Big_int.big_int | Atom of atom | Char of Chars.Unichar.t
29
30 module I = struct
31 type 'a t = {
32 ints : Intervals.t;
33 atoms : atom Atoms.t;
34 times : ('a * 'a) Boolean.t;
35 arrow : ('a * 'a) Boolean.t;
36 record: (label * bool * 'a) Boolean.t;
37 chars : Chars.t;
38 }
39
40 let empty = {
41 times = Boolean.empty;
42 arrow = Boolean.empty;
43 record= Boolean.empty;
44 ints = Intervals.empty;
45 atoms = Atoms.empty;
46 chars = Chars.empty;
47 }
48
49 let any = {
50 times = Boolean.full;
51 arrow = Boolean.full;
52 record= Boolean.full;
53 ints = Intervals.any;
54 atoms = Atoms.any;
55 chars = Chars.any;
56 }
57
58 let interval i = { empty with ints = i }
59 let times x y = { empty with times = Boolean.atom (x,y) }
60 let arrow x y = { empty with arrow = Boolean.atom (x,y) }
61 let record label opt t = { empty with record = Boolean.atom (label,opt,t) }
62 let atom a = { empty with atoms = a }
63 let char c = { empty with chars = c }
64 let constant = function
65 | Integer i -> interval (Intervals.atom i)
66 | Atom a -> atom (Atoms.atom a)
67 | Char c -> char (Chars.atom c)
68
69
70 let any_record = { empty with record = any.record }
71
72 let cup x y =
73 if x = y then x else {
74 times = Boolean.cup x.times y.times;
75 arrow = Boolean.cup x.arrow y.arrow;
76 record= Boolean.cup x.record y.record;
77 ints = Intervals.cup x.ints y.ints;
78 atoms = Atoms.cup x.atoms y.atoms;
79 chars = Chars.cup x.chars y.chars;
80 }
81
82 let cap x y =
83 if x = y then x else {
84 times = Boolean.cap x.times y.times;
85 record= Boolean.cap x.record y.record;
86 arrow = Boolean.cap x.arrow y.arrow;
87 ints = Intervals.cap x.ints y.ints;
88 atoms = Atoms.cap x.atoms y.atoms;
89 chars = Chars.cap x.chars y.chars;
90 }
91
92 let diff x y =
93 if x = y then empty else {
94 times = Boolean.diff x.times y.times;
95 arrow = Boolean.diff x.arrow y.arrow;
96 record= Boolean.diff x.record y.record;
97 ints = Intervals.diff x.ints y.ints;
98 atoms = Atoms.diff x.atoms y.atoms;
99 chars = Chars.diff x.chars y.chars;
100 }
101
102 let neg x = diff any x
103
104 let equal e a b =
105 if a.atoms <> b.atoms then raise NotEqual;
106 if a.chars <> b.chars then raise NotEqual;
107 if a.ints <> b.ints then raise NotEqual;
108 Boolean.equal (fun (x1,x2) (y1,y2) -> e x1 y1; e x2 y2) a.times b.times;
109 Boolean.equal (fun (x1,x2) (y1,y2) -> e x1 y1; e x2 y2) a.arrow b.arrow;
110 Boolean.equal (fun (l1,o1,x1) (l2,o2,x2) ->
111 if (l1 <> l2) || (o1 <> o2) then raise NotEqual;
112 e x1 x2) a.record b.record
113
114 let map f a =
115 { times = Boolean.map (fun (x1,x2) -> (f x1, f x2)) a.times;
116 arrow = Boolean.map (fun (x1,x2) -> (f x1, f x2)) a.arrow;
117 record= Boolean.map (fun (l,o,x) -> (l,o, f x)) a.record;
118 ints = a.ints;
119 atoms = a.atoms;
120 chars = a.chars;
121 }
122
123 let hash h a =
124 Hashtbl.hash (map h a)
125 (*
126 (Hashtbl.hash { (map h a) with ints = Intervals.empty })
127 + (Intervals.hash a.ints)
128 *)
129
130 let iter f a =
131 ignore (map f a)
132
133 let deep = 4
134 end
135
136
137 module Algebra = Recursive_noshare.Make(I)
138 include I
139 include Algebra
140 module DescrHash =
141 Hashtbl.Make(
142 struct
143 type t = descr
144 let hash = hash_descr
145 let equal = equal_descr
146 end
147 )
148
149 module DescrMap = Map.Make(struct type t = descr let compare = compare end)
150
151 let check d =
152 Boolean.check d.times;
153 Boolean.check d.arrow;
154 Boolean.check d.record;
155 ()
156
157 (*
158 let define n d = check d; define n d
159 *)
160
161 let cons d =
162 let n = make () in
163 define n d;
164 internalize n
165
166
167 module Print =
168 struct
169 let print_atom ppf a = Format.fprintf ppf "`%s" (atom_name a)
170
171 let print_const ppf = function
172 | Integer i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
173 | Atom a -> print_atom ppf a
174 | Char c -> Chars.Unichar.print ppf c
175
176 let named = DescrHash.create 10
177 let register_global name d = DescrHash.add named d name
178
179 let marks = DescrHash.create 63
180 let wh = ref []
181 let count_name = ref 0
182 let name () =
183 incr count_name;
184 "X" ^ (string_of_int !count_name)
185 (* TODO:
186 check that these generated names does not conflict with declared types *)
187
188 let bool_iter f b =
189 List.iter (fun (p,n) -> List.iter f p; List.iter f n) b
190
191 let trivial b = b = Boolean.empty || b = Boolean.full
192
193 let worth_abbrev d =
194 not (trivial d.times && trivial d.arrow && trivial d.record)
195
196 let rec mark n = mark_descr (descr n)
197 and mark_descr d =
198 if not (DescrHash.mem named d) then
199 try
200 let r = DescrHash.find marks d in
201 if (!r = None) && (worth_abbrev d) then
202 let na = name () in
203 r := Some na;
204 wh := (na,d) :: !wh
205 with Not_found ->
206 DescrHash.add marks d (ref None);
207 bool_iter (fun (n1,n2) -> mark n1; mark n2) d.times;
208 bool_iter (fun (n1,n2) -> mark n1; mark n2) d.arrow;
209 bool_iter (fun (l,o,n) -> mark n) d.record
210
211
212 let rec print_union ppf = function
213 | [] -> Format.fprintf ppf "Empty"
214 | [h] -> h ppf
215 | h::t -> Format.fprintf ppf "@[%t |@ %a@]" h print_union t
216
217
218 let rec print ppf n = print_descr ppf (descr n)
219 and print_descr ppf d =
220 try
221 let name = DescrHash.find named d in
222 Format.fprintf ppf "%s" name
223 with Not_found ->
224 try
225 match !(DescrHash.find marks d) with
226 | Some n -> Format.fprintf ppf "%s" n
227 | None -> real_print_descr ppf d
228 with
229 Not_found -> Format.fprintf ppf "XXX"
230 and real_print_descr ppf d =
231 if d = any then Format.fprintf ppf "Any" else
232 print_union ppf
233 (Intervals.print d.ints @
234 Chars.print d.chars @
235 Atoms.print "Atom" print_atom d.atoms @
236 Boolean.print "Pair" print_times d.times @
237 Boolean.print "Arrow" print_arrow d.arrow @
238 Boolean.print "Record" print_record d.record
239 )
240 and print_times ppf (t1,t2) =
241 Format.fprintf ppf "@[(%a,%a)@]" print t1 print t2
242 and print_arrow ppf (t1,t2) =
243 Format.fprintf ppf "@[(%a -> %a)@]" print t1 print t2
244 and print_record ppf (l,o,t) =
245 Format.fprintf ppf "@[{ %s =%s %a }@]"
246 (label_name l) (if o then "?" else "") print t
247
248
249 let end_print ppf =
250 (match List.rev !wh with
251 | [] -> ()
252 | (na,d)::t ->
253 Format.fprintf ppf " where@ @[%s = %a" na real_print_descr d;
254 List.iter
255 (fun (na,d) ->
256 Format.fprintf ppf " and@ %s = %a" na real_print_descr d)
257 t;
258 Format.fprintf ppf "@]"
259 );
260 Format.fprintf ppf "@]";
261 count_name := 0;
262 wh := [];
263 DescrHash.clear marks
264
265 let print_descr ppf d =
266 mark_descr d;
267 Format.fprintf ppf "@[%a" print_descr d;
268 end_print ppf
269
270 let print ppf n = print_descr ppf (descr n)
271
272 end
273
274
275
276 module Positive =
277 struct
278 type rhs = [ `Type of descr | `Cup of v list | `Times of v * v ]
279 and v = { mutable def : rhs; mutable node : node option }
280
281
282 let rec make_descr seen v =
283 if List.memq v seen then empty
284 else
285 let seen = v :: seen in
286 match v.def with
287 | `Type d -> d
288 | `Cup vl ->
289 List.fold_left (fun acc v -> cup acc (make_descr seen v)) empty vl
290 | `Times (v1,v2) -> times (make_node v1) (make_node v2)
291
292 and make_node v =
293 match v.node with
294 | Some n -> n
295 | None ->
296 let n = make () in
297 v.node <- Some n;
298 let d = make_descr [] v in
299 define n d;
300 n
301
302 let forward () = { def = `Cup []; node = None }
303 let def v d = v.def <- d
304 let cons d = let v = forward () in def v d; v
305 let ty d = cons (`Type d)
306 let cup vl = cons (`Cup vl)
307 let times d1 d2 = cons (`Times (d1,d2))
308 let define v1 v2 = def v1 (`Cup [v2])
309
310 let solve v = internalize (make_node v)
311 end
312
313
314 let get_record r =
315 let add = SortedMap.add (fun (o1,t1) (o2,t2) -> (o1&&o2, cap t1 t2)) in
316 let line (p,n) =
317 let accu = List.fold_left
318 (fun accu (l,o,t) -> add l (o,descr t) accu) [] p in
319 List.fold_left
320 (fun accu (l,o,t) -> add l (not o,neg (descr t)) accu) accu n in
321 List.map line r
322
323
324
325 (* Subtyping algorithm *)
326
327 let diff_t d t = diff d (descr t)
328 let cap_t d t = cap d (descr t)
329 let cap_product l =
330 List.fold_left
331 (fun (d1,d2) (t1,t2) -> (cap_t d1 t1, cap_t d2 t2))
332 (any,any)
333 l
334
335
336 module Assumptions = Set.Make(struct type t = descr let compare = compare end)
337
338 let memo = ref Assumptions.empty
339 let cache_false = ref Assumptions.empty
340
341 exception NotEmpty
342
343 let rec empty_rec d =
344 if Assumptions.mem d !cache_false then false
345 else if Assumptions.mem d !memo then true
346 else if not (Intervals.is_empty d.ints) then false
347 else if not (Atoms.is_empty d.atoms) then false
348 else if not (Chars.is_empty d.chars) then false
349 else (
350 let backup = !memo in
351 memo := Assumptions.add d backup;
352 if
353 (empty_rec_times d.times) &&
354 (empty_rec_arrow d.arrow) &&
355 (empty_rec_record d.record)
356 then true
357 else (
358 memo := backup;
359 cache_false := Assumptions.add d !cache_false;
360 false
361 )
362 )
363
364 and empty_rec_times c =
365 List.for_all empty_rec_times_aux c
366
367 and empty_rec_times_aux (left,right) =
368 let rec aux accu1 accu2 = function
369 | (t1,t2)::right ->
370 let accu1' = diff_t accu1 t1 in
371 if not (empty_rec accu1') then aux accu1' accu2 right;
372 let accu2' = diff_t accu2 t2 in
373 if not (empty_rec accu2') then aux accu1 accu2' right
374 | [] -> raise NotEmpty
375 in
376 let (accu1,accu2) = cap_product left in
377 (empty_rec accu1) || (empty_rec accu2) ||
378 (try aux accu1 accu2 right; true with NotEmpty -> false)
379
380 and empty_rec_arrow c =
381 List.for_all empty_rec_arrow_aux c
382
383 and empty_rec_arrow_aux (left,right) =
384 let single_right (s1,s2) =
385 let rec aux accu1 accu2 = function
386 | (t1,t2)::left ->
387 let accu1' = diff_t accu1 t1 in
388 if not (empty_rec accu1') then aux accu1 accu2 left;
389 let accu2' = cap_t accu2 t2 in
390 if not (empty_rec accu2') then aux accu1 accu2 left
391 | [] -> raise NotEmpty
392 in
393 let accu1 = descr s1 in
394 (empty_rec accu1) ||
395 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
396 in
397 List.exists single_right right
398
399 and empty_rec_record c =
400 let aux = List.exists (fun (_,(opt,t)) -> (not opt) && (empty_rec t)) in
401 List.for_all aux (get_record c)
402
403 let is_empty d =
404 let old = !memo in
405 let r = empty_rec d in
406 if not r then memo := old;
407 (* cache_false := Assumptions.empty; *)
408 r
409
410 let non_empty d =
411 not (is_empty d)
412
413 let subtype d1 d2 =
414 is_empty (diff d1 d2)
415
416 (* Sample value *)
417 module Sample =
418 struct
419
420 let rec find f = function
421 | [] -> raise Not_found
422 | x::r -> try f x with Not_found -> find f r
423
424 type t =
425 | Int of Big_int.big_int
426 | Atom of atom
427 | Char of Chars.Unichar.t
428 | Pair of t * t
429 | Record of (label * t) list
430 | Fun of (node * node) list
431
432 let rec gen_atom i l =
433 if SortedList.mem l i then gen_atom (succ i) l else i
434
435 let rec sample_rec memo d =
436 if (Assumptions.mem d memo) || (is_empty d) then raise Not_found
437 else
438 try Int (Intervals.sample d.ints) with Not_found ->
439 try Atom (Atoms.sample (gen_atom 0) d.atoms) with Not_found ->
440 try Char (Chars.sample d.chars) with Not_found ->
441 try sample_rec_arrow d.arrow with Not_found ->
442
443 let memo = Assumptions.add d memo in
444 try sample_rec_times memo d.times with Not_found ->
445 try sample_rec_record memo d.record with Not_found ->
446 raise Not_found
447
448
449 and sample_rec_times memo c =
450 find (sample_rec_times_aux memo) c
451
452 and sample_rec_times_aux memo (left,right) =
453 let rec aux accu1 accu2 = function
454 | (t1,t2)::right ->
455 let accu1' = diff_t accu1 t1 in
456 if non_empty accu1' then aux accu1' accu2 right else
457 let accu2' = diff_t accu2 t2 in
458 if non_empty accu2' then aux accu1 accu2' right else
459 raise Not_found
460 | [] -> Pair (sample_rec memo accu1, sample_rec memo accu2)
461 in
462 let (accu1,accu2) = cap_product left in
463 if (is_empty accu1) || (is_empty accu2) then raise Not_found;
464 aux accu1 accu2 right
465
466 and sample_rec_arrow c =
467 find sample_rec_arrow_aux c
468
469 and check_empty_simple_arrow_line left (s1,s2) =
470 let rec aux accu1 accu2 = function
471 | (t1,t2)::left ->
472 let accu1' = diff_t accu1 t1 in
473 if non_empty accu1' then aux accu1 accu2 left;
474 let accu2' = cap_t accu2 t2 in
475 if non_empty accu2' then aux accu1 accu2 left
476 | [] -> raise NotEmpty
477 in
478 let accu1 = descr s1 in
479 (is_empty accu1) ||
480 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
481
482 and check_empty_arrow_line left right =
483 List.exists (check_empty_simple_arrow_line left) right
484
485 and sample_rec_arrow_aux (left,right) =
486 if (check_empty_arrow_line left right) then raise Not_found
487 else Fun left
488
489
490 and sample_rec_record memo c =
491 Record (find (sample_rec_record_aux memo) (get_record c))
492
493 and sample_rec_record_aux memo fields =
494 let aux acc (l,(o,t)) = if o then acc else (l, sample_rec memo t) :: acc in
495 List.fold_left aux [] fields
496
497 let get x = sample_rec Assumptions.empty x
498
499 let rec print_sep f sep ppf = function
500 | [] -> ()
501 | [x] -> f ppf x
502 | x::rem -> f ppf x; Format.fprintf ppf "%s" sep; print_sep f sep ppf rem
503
504
505 let rec print ppf = function
506 | Int i -> Format.fprintf ppf "%s" (Big_int.string_of_big_int i)
507 | Atom a -> Format.fprintf ppf "`%s" (atom_name a)
508 | Char c -> Chars.Unichar.print ppf c
509 | Pair (x1,x2) -> Format.fprintf ppf "(%a,%a)" print x1 print x2
510 | Record r ->
511 Format.fprintf ppf "{ %a }"
512 (print_sep
513 (fun ppf (l,x) ->
514 Format.fprintf ppf "%s = %a"
515 (label_name l)
516 print x
517 )
518 " ; "
519 ) r
520 | Fun iface ->
521 Format.fprintf ppf "(fun ( %a ) x -> ...)"
522 (print_sep
523 (fun ppf (t1,t2) ->
524 Format.fprintf ppf "%a -> %a; "
525 Print.print t1 Print.print t2
526 )
527 " ; "
528 ) iface
529 end
530
531
532 module Product =
533 struct
534 type t = (descr * descr) list
535
536 let other d = { d with times = empty.times }
537 let is_product d = is_empty (other d)
538
539 let need_second = function _::_::_ -> true | _ -> false
540
541 let normal_aux d =
542 let res = ref [] in
543
544 let add (t1,t2) =
545 let rec loop t1 t2 = function
546 | [] -> res := (ref (t1,t2)) :: !res
547 | ({contents = (d1,d2)} as r)::l ->
548 (*OPT*)
549 if d1 = t1 then r := (d1,cup d2 t2) else
550
551 let i = cap t1 d1 in
552 if is_empty i then loop t1 t2 l
553 else (
554 r := (i, cup t2 d2);
555 let k = diff d1 t1 in
556 if non_empty k then res := (ref (k,d2)) :: !res;
557
558 let j = diff t1 d1 in
559 if non_empty j then loop j t2 l
560 )
561 in
562 loop t1 t2 !res
563 in
564 List.iter add d;
565 List.map (!) !res
566
567 (*
568 This version explodes when dealing with
569 Any - [ t1? t2? t3? ... tn? ]
570 ==> need partitioning
571 *)
572 let get_aux d =
573 let line accu (left,right) =
574 let debug = List.length right = 28 in
575 let rec aux accu d1 d2 = function
576 | (t1,t2)::right ->
577 let accu =
578 let d1 = diff_t d1 t1 in
579 if is_empty d1 then accu else aux accu d1 d2 right in
580 let accu =
581 let d2 = diff_t d2 t2 in
582 if is_empty d2 then accu else aux accu d1 d2 right in
583 accu
584 | [] -> (d1,d2) :: accu
585 in
586 let (d1,d2) = cap_product left in
587 if (is_empty d1) || (is_empty d2) then accu else aux accu d1 d2 right
588 in
589 List.fold_left line [] d
590
591 (* Partitioning:
592
593 (t,s) - ((t1,s1) | (t2,s2) | ... | (tn,sn))
594 =
595 (t & t1, s - s1) | ... | (t & tn, s - sn) | (t - (t1|...|tn), s)
596
597 *)
598
599 let get_aux d =
600 let accu = ref [] in
601 let line (left,right) =
602 let (d1,d2) = cap_product left in
603 if (non_empty d1) && (non_empty d2) then
604 let right = List.map (fun (t1,t2) -> descr t1, descr t2) right in
605 let right = normal_aux right in
606 let resid1 = ref d1 in
607 let () =
608 List.iter
609 (fun (t1,t2) ->
610 let t1 = cap d1 t1 in
611 if (non_empty t1) then
612 let () = resid1 := diff !resid1 t1 in
613 let t2 = diff d2 t2 in
614 if (non_empty t2) then accu := (t1,t2) :: !accu
615 ) right in
616 if non_empty !resid1 then accu := (!resid1, d2) :: !accu
617 in
618 List.iter line d;
619 !accu
620
621 let get d = get_aux d.times
622
623 let pi1 = List.fold_left (fun acc (t1,_) -> cup acc t1) empty
624 let pi2 = List.fold_left (fun acc (_,t2) -> cup acc t2) empty
625
626 let restrict_1 rects pi1 =
627 let aux accu (t1,t2) =
628 let t1 = cap t1 pi1 in if is_empty t1 then accu else (t1,t2)::accu in
629 List.fold_left aux [] rects
630
631 type normal = t
632
633 module Memo = Map.Make(struct
634 type t = (node * node) Boolean.t
635 let compare = compare end)
636
637
638
639 let memo = ref Memo.empty
640 let normal d =
641 let d = d.times in
642 try Memo.find d !memo
643 with
644 Not_found ->
645 let gd = get_aux d in
646 let n = normal_aux gd in
647 memo := Memo.add d n !memo;
648 n
649
650 let any = { empty with times = any.times }
651 let is_empty d = d = []
652 end
653
654
655 module Record =
656 struct
657 type t = (label, (bool * descr)) SortedMap.t list
658
659 let get d =
660 let line r = List.for_all (fun (l,(o,d)) -> o || non_empty d) r in
661 List.filter line (get_record d.record)
662
663
664 let restrict_label_present t l =
665 let restr = function
666 | (true, d) -> if non_empty d then (false,d) else raise Exit
667 | x -> x in
668 let aux accu r =
669 try SortedMap.change l restr (false,any) r :: accu
670 with Exit -> accu in
671 List.fold_left aux [] t
672
673 let restrict_label_absent t l =
674 let restr = function (true, _) -> (true,empty) | _ -> raise Exit in
675 let aux accu r =
676 try SortedMap.change l restr (true,empty) r :: accu
677 with Exit -> accu in
678 List.fold_left aux [] t
679
680 let restrict_field t l d =
681 let restr (_,d1) =
682 let d1 = cap d d1 in
683 if is_empty d1 then raise Exit else (false,d1) in
684 let aux accu r =
685 try SortedMap.change l restr (false,d) r :: accu
686 with Exit -> accu in
687 List.fold_left aux [] t
688
689 let project_field t l =
690 let aux accu x =
691 match List.assoc l x with
692 | (false,t) -> cup accu t
693 | _ -> raise Not_found
694 in
695 List.fold_left aux empty t
696
697 let project d l =
698 project_field (get_record d.record) l
699
700 type normal =
701 [ `Success
702 | `Fail
703 | `Label of label * (descr * normal) list * normal ]
704
705 let rec merge_record n r =
706 match (n, r) with
707 | (`Success, _) | (_, []) -> `Success
708 | (`Fail, r) ->
709 let aux (l,(o,t)) n = `Label (l, [t,n], if o then n else `Fail) in
710 List.fold_right aux r `Success
711 | (`Label (l1,present,absent), (l2,(o,t2))::r') ->
712 if (l1 < l2) then
713 let pr = List.map (fun (t,x) -> (t, merge_record x r)) present in
714 `Label (l1,pr,merge_record absent r)
715 else if (l2 < l1) then
716 let n' = merge_record n r' in
717 `Label (l2, [t2, n'], if o then n' else n)
718 else
719 let res = ref [] in
720 let aux a (t,x) =
721 (let t = diff t t2 in
722 if non_empty t then res := (t,x) :: !res);
723 (let t = cap t t2 in
724 if non_empty t then res := (t, merge_record x r') :: !res);
725 diff a t
726 in
727 let t2 = List.fold_left aux t2 present in
728 let () =
729 if non_empty t2 then
730 res := (t2, merge_record `Fail r') :: !res in
731 let abs = if o then merge_record absent r' else absent in
732 `Label (l1, !res, abs)
733
734
735 let normal d =
736 List.fold_left merge_record `Fail (get d)
737
738
739 let any = { empty with record = any.record }
740 let is_empty d = d = []
741 end
742
743
744
745 let memo_normalize = ref DescrMap.empty
746
747 let map_sort f l =
748 SortedList.from_list (List.map f l)
749
750 let rec rec_normalize d =
751 try DescrMap.find d !memo_normalize
752 with Not_found ->
753 let n = make () in
754 memo_normalize := DescrMap.add d n !memo_normalize;
755 let times =
756 map_sort
757 (fun (d1,d2) -> [(rec_normalize d1, rec_normalize d2)],[])
758 (Product.normal d)
759 in
760 let record =
761 map_sort
762 (fun f -> map_sort (fun (l,(o,d)) -> (l,o,rec_normalize d)) f, [])
763 (Record.get d)
764 in
765 define n { d with times = times; record = record };
766 n
767
768 let normalize n =
769 descr (internalize (rec_normalize n))
770
771 module Arrow =
772 struct
773 let check_simple left s1 s2 =
774 let rec aux accu1 accu2 = function
775 | (t1,t2)::left ->
776 let accu1' = diff_t accu1 t1 in
777 if non_empty accu1' then aux accu1 accu2 left;
778 let accu2' = cap_t accu2 t2 in
779 if non_empty accu2' then aux accu1 accu2 left
780 | [] -> raise NotEmpty
781 in
782 let accu1 = descr s1 in
783 (is_empty accu1) ||
784 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
785
786 let check_strenghten t s =
787 let left = match t.arrow with [ (p,[]) ] -> p | _ -> assert false in
788 let rec aux = function
789 | [] -> raise Not_found
790 | (p,n) :: rem ->
791 if (List.for_all (fun (a,b) -> check_simple left a b) p) &&
792 (List.for_all (fun (a,b) -> not (check_simple left a b)) n) then
793 { empty with arrow = [ (SortedList.cup left p, n) ] }
794 else aux rem
795 in
796 aux s.arrow
797
798 let check_simple_iface left s1 s2 =
799 let rec aux accu1 accu2 = function
800 | (t1,t2)::left ->
801 let accu1' = diff accu1 t1 in
802 if non_empty accu1' then aux accu1 accu2 left;
803 let accu2' = cap accu2 t2 in
804 if non_empty accu2' then aux accu1 accu2 left
805 | [] -> raise NotEmpty
806 in
807 let accu1 = descr s1 in
808 (is_empty accu1) ||
809 (try aux accu1 (diff any (descr s2)) left; true with NotEmpty -> false)
810
811 let check_iface iface s =
812 let rec aux = function
813 | [] -> false
814 | (p,n) :: rem ->
815 ((List.for_all (fun (a,b) -> check_simple_iface iface a b) p) &&
816 (List.for_all (fun (a,b) -> not (check_simple_iface iface a b)) n))
817 || (aux rem)
818 in
819 aux s.arrow
820
821 type t = descr * (descr * descr) list list
822
823 let get t =
824 List.fold_left
825 (fun ((dom,arr) as accu) (left,right) ->
826 if Sample.check_empty_arrow_line left right
827 then accu
828 else (
829 let left =
830 List.map
831 (fun (t,s) -> (descr t, descr s)) left in
832 let d = List.fold_left (fun d (t,_) -> cup d t) empty left in
833 (cap dom d, left :: arr)
834 )
835 )
836 (any, [])
837 t.arrow
838
839 let domain (dom,_) = dom
840
841 let apply_simple t result left =
842 let rec aux result accu1 accu2 = function
843 | (t1,s1)::left ->
844 let result =
845 let accu1 = diff accu1 t1 in
846 if non_empty accu1 then aux result accu1 accu2 left
847 else result in
848 let result =
849 let accu2 = cap accu2 s1 in
850 aux result accu1 accu2 left in
851 result
852 | [] ->
853 if subtype accu2 result
854 then result
855 else cup result accu2
856 in
857 aux result t any left
858
859 let apply (_,arr) t =
860 List.fold_left (apply_simple t) empty arr
861
862 let need_arg (dom, arr) =
863 List.exists (function [_] -> false | _ -> true) arr
864
865 let apply_noarg (_,arr) =
866 List.fold_left
867 (fun accu ->
868 function
869 | [(t,s)] -> cup accu s
870 | _ -> assert false
871 )
872 empty arr
873
874 let any = { empty with arrow = any.arrow }
875 let is_empty (_,arr) = arr = []
876 end
877
878
879 module Int = struct
880 let has_int d i = Intervals.contains i d.ints
881
882 let get d = d.ints
883 let put i = { empty with ints = i }
884 let is_int d = is_empty { d with ints = Intervals.empty }
885 let any = { empty with ints = Intervals.any }
886 end
887
888 module Atom = struct
889 let has_atom d a = Atoms.contains a d.atoms
890 end
891
892 module Char = struct
893 let has_char d c = Chars.contains c d.chars
894 let any = { empty with chars = Chars.any }
895 end
896
897 (*
898 let rec print_normal_record ppf = function
899 | Success -> Format.fprintf ppf "Yes"
900 | Fail -> Format.fprintf ppf "No"
901 | FirstLabel (l,present,absent) ->
902 Format.fprintf ppf "%s?@[<v>@\n" (label_name l);
903 List.iter
904 (fun (t,n) ->
905 Format.fprintf ppf "(%a)=>@[%a@]@\n"
906 Print.print_descr t
907 print_normal_record n
908 ) present;
909 if absent <> Fail then
910 Format.fprintf ppf "(absent)=>@[%a@]@\n" print_normal_record absent;
911 Format.fprintf ppf "@]"
912 *)
913
914
915 (*
916 let pr s = Types.Print.print Format.std_formatter (Syntax.make_type (Syntax.parse s));;
917
918 let pr' s = Types.Print.print Format.std_formatter
919 (Types.normalize (Syntax.make_type (Syntax.parse s)));;
920
921 BUG:
922 pr "'a | 'b where 'a = ('a , 'a) and 'b= ('b , 'b)";;
923 *)
924
925
926 (*
927 let nr s =
928 let t = Types.descr (Syntax.make_type (Syntax.parse s)) in
929 let n = Types.normal_record' t.Types.record in
930 Types.print_normal_record Format.std_formatter n;;
931 *)

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