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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 78 - (show annotations)
Tue Jul 10 17:04:23 2007 UTC (5 years, 10 months ago) by abate
File size: 26843 byte(s)
[r2002-11-06 07:46:53 by cvscast] Empty log message

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

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