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

Contents of /types/types.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 802 - (hide annotations)
Tue Jul 10 18:04:11 2007 UTC (5 years, 10 months ago) by abate
File size: 49868 byte(s)
[r2003-11-21 12:51:15 by szach] changed rec_of_list* helpers so that they use Ns.qname instead of
string

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