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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1359 - (hide annotations)
Tue Jul 10 18:42:29 2007 UTC (5 years, 10 months ago) by abate
File size: 57125 byte(s)
[r2004-12-23 15:16:34 by afrisch] Simplify

Original author: afrisch
Date: 2004-12-23 15:16:34+00:00
1 abate 107 exception Error of string
2 abate 225 open Ident
3 abate 1
4 abate 310 (*
5     To be sure not to use generic comparison ...
6 abate 332 *)
7     let (=) : int -> int -> bool = (==)
8 abate 310 let (<) : int -> int -> bool = (<)
9 abate 332 let (<=) : int -> int -> bool = (<=)
10     let (<>) : int -> int -> bool = (<>)
11     let compare = 1
12 abate 310
13 abate 332
14 abate 1 (* Syntactic algebra *)
15 abate 121 (* Constraint: any node except Constr has fv<>[] ... *)
16 abate 1 type d =
17 abate 653 | Constr of Types.t
18 abate 1 | Cup of descr * descr
19 abate 121 | Cap of descr * descr
20 abate 1 | Times of node * node
21 abate 110 | Xml of node * node
22 abate 233 | Record of label * node
23 abate 225 | Capture of id
24     | Constant of id * Types.const
25 abate 691 | Dummy
26 abate 1 and node = {
27     id : int;
28 abate 691 mutable descr : descr;
29 abate 653 accept : Types.Node.t;
30 abate 1107 fv : fv
31 abate 653 } and descr = Types.t * fv * d
32 abate 1
33 abate 653
34    
35 abate 136 let id x = x.id
36 abate 691 let descr x = x.descr
37 abate 136 let fv x = x.fv
38     let accept x = Types.internalize x.accept
39 abate 121
40     let printed = ref []
41     let to_print = ref []
42 abate 136 let rec print ppf (a,_,d) =
43 abate 121 match d with
44 abate 367 | Constr t -> Types.Print.print ppf t
45 abate 121 | Cup (p1,p2) -> Format.fprintf ppf "(%a | %a)" print p1 print p2
46     | Cap (p1,p2) -> Format.fprintf ppf "(%a & %a)" print p1 print p2
47     | Times (n1,n2) ->
48     Format.fprintf ppf "(P%i,P%i)" n1.id n2.id;
49     to_print := n1 :: n2 :: !to_print
50     | Xml (n1,n2) ->
51     Format.fprintf ppf "XML(P%i,P%i)" n1.id n2.id;
52     to_print := n1 :: n2 :: !to_print
53     | Record (l,n) ->
54 abate 542 Format.fprintf ppf "{ %a = P%i }" Label.print (LabelPool.value l) n.id;
55 abate 121 to_print := n :: !to_print
56     | Capture x ->
57 abate 374 Format.fprintf ppf "%a" U.print (Id.value x)
58 abate 121 | Constant (x,c) ->
59 abate 374 Format.fprintf ppf "(%a := %a)" U.print (Id.value x)
60 abate 225 Types.Print.print_const c
61 abate 691 | Dummy ->
62     Format.fprintf ppf "*DUMMY*"
63 abate 121
64 abate 136 let dump_print ppf =
65 abate 332 while !to_print != [] do
66 abate 136 let p = List.hd !to_print in
67     to_print := List.tl !to_print;
68     if not (List.mem p.id !printed) then
69     ( printed := p.id :: !printed;
70     Format.fprintf ppf "P%i:=%a\n" p.id print (descr p)
71     )
72     done
73 abate 121
74 abate 136 let print ppf d =
75     Format.fprintf ppf "%a@\n" print d;
76     dump_print ppf
77 abate 121
78 abate 1349 let print_node ppf n =
79     Format.fprintf ppf "P%i" n.id;
80     to_print := n :: !to_print;
81     dump_print ppf
82 abate 136
83 abate 1349
84 abate 95 let counter = State.ref "Patterns.counter" 0
85 abate 1
86 abate 691 let dummy = (Types.empty,IdSet.empty,Dummy)
87 abate 95 let make fv =
88     incr counter;
89 abate 1107 { id = !counter; descr = dummy; accept = Types.make (); fv = fv }
90 abate 95
91 abate 1 let define x ((accept,fv,_) as d) =
92 abate 310 (* assert (x.fv = fv); *)
93 abate 1 Types.define x.accept accept;
94 abate 691 x.descr <- d
95 abate 1
96 abate 225 let constr x = (x,IdSet.empty,Constr x)
97 abate 1 let cup ((acc1,fv1,_) as x1) ((acc2,fv2,_) as x2) =
98 abate 225 if not (IdSet.equal fv1 fv2) then (
99     let x = match IdSet.pick (IdSet.diff fv1 fv2) with
100     | Some x -> x
101     | None -> match IdSet.pick (IdSet.diff fv2 fv1) with Some x -> x
102     | None -> assert false
103 abate 107 in
104     raise
105     (Error
106 abate 374 ("The capture variable " ^ (U.to_string (Id.value x)) ^
107 abate 107 " should appear on both side of this | pattern"))
108     );
109 abate 225 (Types.cup acc1 acc2, IdSet.cup fv1 fv2, Cup (x1,x2))
110 abate 121 let cap ((acc1,fv1,_) as x1) ((acc2,fv2,_) as x2) =
111 abate 225 if not (IdSet.disjoint fv1 fv2) then (
112     match IdSet.pick (IdSet.cap fv1 fv2) with
113     | Some x ->
114 abate 107 raise
115     (Error
116 abate 374 ("The capture variable " ^ (U.to_string (Id.value x)) ^
117 abate 107 " cannot appear on both side of this & pattern"))
118 abate 225 | None -> assert false
119 abate 107 );
120 abate 225 (Types.cap acc1 acc2, IdSet.cup fv1 fv2, Cap (x1,x2))
121 abate 1 let times x y =
122 abate 225 (Types.times x.accept y.accept, IdSet.cup x.fv y.fv, Times (x,y))
123 abate 110 let xml x y =
124 abate 225 (Types.xml x.accept y.accept, IdSet.cup x.fv y.fv, Xml (x,y))
125 abate 1 let record l x =
126 abate 229 (Types.record l x.accept, x.fv, Record (l,x))
127 abate 225 let capture x = (Types.any, IdSet.singleton x, Capture x)
128     let constant x c = (Types.any, IdSet.singleton x, Constant (x,c))
129 abate 1
130    
131 abate 691 module Node = struct
132     type t = node
133     let compare n1 n2 = n1.id - n2.id
134     let equal n1 n2 = n1.id == n2.id
135     let hash n = n.id
136 abate 1
137 abate 698 let check n = ()
138 abate 1349 let dump = print_node
139 abate 1
140 abate 698
141 abate 691 module SMemo = Set.Make(Custom.Int)
142     let memo = Serialize.Put.mk_property (fun t -> ref SMemo.empty)
143     let rec serialize t n =
144     let l = Serialize.Put.get_property memo t in
145     Serialize.Put.int t n.id;
146     if not (SMemo.mem n.id !l) then (
147     l := SMemo.add n.id !l;
148     Types.Node.serialize t n.accept;
149     IdSet.serialize t n.fv;
150     serialize_descr t n.descr
151     )
152     and serialize_descr s (_,_,d) =
153     serialize_d s d
154     and serialize_d s = function
155     | Constr t ->
156     Serialize.Put.bits 3 s 0;
157     Types.serialize s t
158     | Cup (p1,p2) ->
159     Serialize.Put.bits 3 s 1;
160     serialize_descr s p1;
161     serialize_descr s p2
162     | Cap (p1,p2) ->
163     Serialize.Put.bits 3 s 2;
164     serialize_descr s p1;
165     serialize_descr s p2
166     | Times (p1,p2) ->
167     Serialize.Put.bits 3 s 3;
168     serialize s p1;
169     serialize s p2
170     | Xml (p1,p2) ->
171     Serialize.Put.bits 3 s 4;
172     serialize s p1;
173     serialize s p2
174     | Record (l,p) ->
175     Serialize.Put.bits 3 s 5;
176     LabelPool.serialize s l;
177     serialize s p
178     | Capture x ->
179     Serialize.Put.bits 3 s 6;
180     Id.serialize s x
181     | Constant (x,c) ->
182     Serialize.Put.bits 3 s 7;
183     Id.serialize s x;
184     Types.Const.serialize s c
185     | Dummy -> assert false
186    
187     module DMemo = Map.Make(Custom.Int)
188     let memo = Serialize.Get.mk_property (fun t -> ref DMemo.empty)
189     let rec deserialize t =
190     let l = Serialize.Get.get_property memo t in
191     let id = Serialize.Get.int t in
192     try DMemo.find id !l
193     with Not_found ->
194     let accept = Types.Node.deserialize t in
195     let fv = IdSet.deserialize t in
196     incr counter;
197 abate 1107 let n = { id = !counter; descr = dummy; accept = accept; fv = fv } in
198 abate 691 l := DMemo.add id n !l;
199     n.descr <- deserialize_descr t;
200     n
201     and deserialize_descr s =
202     match Serialize.Get.bits 3 s with
203     | 0 -> constr (Types.deserialize s)
204     | 1 ->
205     (* Avoid unnecessary tests *)
206     let (acc1,fv1,_) as x1 = deserialize_descr s in
207     let (acc2,fv2,_) as x2 = deserialize_descr s in
208     (Types.cup acc1 acc2, IdSet.cup fv1 fv2, Cup (x1,x2))
209     | 2 ->
210     let (acc1,fv1,_) as x1 = deserialize_descr s in
211     let (acc2,fv2,_) as x2 = deserialize_descr s in
212     (Types.cap acc1 acc2, IdSet.cup fv1 fv2, Cap (x1,x2))
213     | 3 ->
214     let x = deserialize s in
215     let y = deserialize s in
216     times x y
217     | 4 ->
218     let x = deserialize s in
219     let y = deserialize s in
220     xml x y
221     | 5 ->
222     let l = LabelPool.deserialize s in
223     let x = deserialize s in
224     record l x
225     | 6 -> capture (Id.deserialize s)
226     | 7 ->
227     let x = Id.deserialize s in
228     let c = Types.Const.deserialize s in
229     constant x c
230     | _ -> assert false
231    
232    
233     end
234    
235 abate 1350 (* Pretty-print *)
236 abate 691
237 abate 1352 module Pat = struct
238 abate 1350 type t = descr
239 abate 1358 let rec compare (_,_,d1) (_,_,d2) = if d1 == d2 then 0 else
240 abate 1350 match (d1,d2) with
241     | Constr t1, Constr t2 -> Types.compare t1 t2
242     | Constr _, _ -> -1 | _, Constr _ -> 1
243    
244     | Cup (x1,y1), Cup (x2,y2) | Cap (x1,y1), Cap (x2,y2) ->
245     let c = compare x1 x2 in if c <> 0 then c
246     else compare y1 y2
247     | Cup _, _ -> -1 | _, Cup _ -> 1
248     | Cap _, _ -> -1 | _, Cap _ -> 1
249    
250     | Times (x1,y1), Times (x2,y2) | Xml (x1,y1), Xml (x2,y2) ->
251     let c = Node.compare x1 x2 in if c <> 0 then c
252     else Node.compare y1 y2
253     | Times _, _ -> -1 | _, Times _ -> 1
254     | Xml _, _ -> -1 | _, Xml _ -> 1
255    
256     | Record (x1,y1), Record (x2,y2) ->
257     let c = LabelPool.compare x1 x2 in if c <> 0 then c
258     else Node.compare y1 y2
259     | Record _, _ -> -1 | _, Record _ -> 1
260    
261     | Capture x1, Capture x2 ->
262     Id.compare x1 x2
263     | Capture _, _ -> -1 | _, Capture _ -> 1
264    
265     | Constant (x1,y1), Constant (x2,y2) ->
266     let c = Id.compare x1 x2 in if c <> 0 then c
267     else Types.Const.compare y1 y2
268     | Constant _, _ -> -1 | _, Constant _ -> 1
269    
270     | Dummy, Dummy -> assert false
271 abate 1358
272     let equal p1 p2 = compare p1 p2 == 0
273    
274     let rec hash (_,_,d) = match d with
275     | Constr t -> 1 + 17 * (Types.hash t)
276     | Cup (p1,p2) -> 2 + 17 * (hash p1) + 257 * (hash p2)
277     | Cap (p1,p2) -> 3 + 17 * (hash p1) + 257 * (hash p2)
278     | Times (q1,q2) -> 4 + 17 * q1.id + 257 * q2.id
279     | Xml (q1,q2) -> 5 + 17 * q1.id + 257 * q2.id
280     | Record (l,q) -> 6 + 17 * (LabelPool.hash l) + 257 * q.id
281     | Capture x -> 7 + (Id.hash x)
282     | Constant (x,c) -> 8 + 17 * (Id.hash x) + 257 * (Types.Const.hash c)
283     | Dummy -> assert false
284 abate 1350 end
285    
286     module Print = struct
287 abate 1352 module M = Map.Make(Pat)
288     module S = Set.Make(Pat)
289 abate 1350
290     let names = ref M.empty
291     let printed = ref S.empty
292     let toprint = Queue.create ()
293     let id = ref 0
294    
295     let rec mark seen ((_,_,d) as p) =
296     if (M.mem p !names) then ()
297     else if (S.mem p seen) then
298     (incr id;
299     names := M.add p !id !names;
300     Queue.add p toprint)
301     else
302     let seen = S.add p seen in
303     match d with
304     | Cup (p1,p2) | Cap (p1,p2) -> mark seen p1; mark seen p2
305     | Times (q1,q2) | Xml (q1,q2) -> mark seen q1.descr; mark seen q2.descr
306     | Record (_,q) -> mark seen q.descr
307     | _ -> ()
308    
309     let rec print ppf p =
310     try
311     let i = M.find p !names in
312     Format.fprintf ppf "P%i" i
313     with Not_found ->
314     real_print ppf p
315     and real_print ppf (_,_,d) = match d with
316     | Constr t ->
317     Types.Print.print ppf t
318     | Cup (p1,p2) ->
319     Format.fprintf ppf "(%a | %a)" print p1 print p2
320     | Cap (p1,p2) ->
321     Format.fprintf ppf "(%a & %a)" print p1 print p2
322     | Times (q1,q2) ->
323     Format.fprintf ppf "(%a,%a)" print q1.descr print q2.descr
324     | Xml (q1,{ descr = (_,_,Times(q2,q3)) }) ->
325     Format.fprintf ppf "<(%a) (%a)>(%a)" print q1.descr print q2.descr print q2.descr
326     | Xml _ -> assert false
327     | Record (l,q) ->
328     Format.fprintf ppf "{%a=%a}" Label.print (LabelPool.value l) print q.descr
329     | Capture x ->
330     Format.fprintf ppf "%a" Ident.print x
331     | Constant (x,c) ->
332     Format.fprintf ppf "(%a:=%a)" Ident.print x Types.Print.print_const c
333     | Dummy -> assert false
334    
335     let print ppf p =
336     mark S.empty p;
337     print ppf p;
338     let first = ref true in
339     (try while true do
340     let p = Queue.pop toprint in
341     if not (S.mem p !printed) then
342     ( printed := S.add p !printed;
343     Format.fprintf ppf " %s@ @[%a=%a@]"
344     (if !first then (first := false; "where") else "and")
345     print p
346     real_print p
347     );
348     done with Queue.Empty -> ());
349     id := 0;
350     names := M.empty;
351     printed := S.empty
352 abate 1355
353    
354     let print_xs ppf xs =
355     Format.fprintf ppf "{";
356     let rec aux = function
357     | [] -> ()
358     | [x] -> Ident.print ppf x
359     | x::q -> Ident.print ppf x; Format.fprintf ppf ","; aux q
360     in
361     aux xs;
362     Format.fprintf ppf "}"
363 abate 1350 end
364    
365    
366    
367 abate 1 (* Static semantics *)
368    
369     let cup_res v1 v2 = Types.Positive.cup [v1;v2]
370 abate 225 let empty_res fv = IdMap.constant (Types.Positive.ty Types.empty) fv
371 abate 1 let times_res v1 v2 = Types.Positive.times v1 v2
372    
373 abate 271 (* Try with a hash-table *)
374 abate 1 module MemoFilter = Map.Make
375 abate 271 (struct
376 abate 653 type t = Types.t * node
377 abate 271 let compare (t1,n1) (t2,n2) =
378     if n1.id < n2.id then -1 else if n1.id > n2.id then 1 else
379 abate 653 Types.compare t1 t2
380 abate 271 end)
381 abate 1
382     let memo_filter = ref MemoFilter.empty
383    
384 abate 225 let rec filter_descr t (_,fv,d) : Types.Positive.v id_map =
385 abate 121 (* TODO: avoid is_empty t when t is not changing (Cap) *)
386 abate 1 if Types.is_empty t
387     then empty_res fv
388     else
389     match d with
390 abate 225 | Constr _ -> IdMap.empty
391 abate 1 | Cup ((a,_,_) as d1,d2) ->
392 abate 225 IdMap.merge cup_res
393 abate 1 (filter_descr (Types.cap t a) d1)
394     (filter_descr (Types.diff t a) d2)
395 abate 121 | Cap (d1,d2) ->
396 abate 225 IdMap.merge cup_res (filter_descr t d1) (filter_descr t d2)
397 abate 110 | Times (p1,p2) -> filter_prod fv p1 p2 t
398     | Xml (p1,p2) -> filter_prod ~kind:`XML fv p1 p2 t
399 abate 1 | Record (l,p) ->
400     filter_node (Types.Record.project t l) p
401     | Capture c ->
402 abate 225 IdMap.singleton c (Types.Positive.ty t)
403 abate 1 | Constant (c, cst) ->
404 abate 225 IdMap.singleton c (Types.Positive.ty (Types.constant cst))
405 abate 691 | Dummy -> assert false
406 abate 1
407 abate 110 and filter_prod ?kind fv p1 p2 t =
408     List.fold_left
409     (fun accu (d1,d2) ->
410     let term =
411 abate 225 IdMap.merge times_res (filter_node d1 p1) (filter_node d2 p2)
412 abate 110 in
413 abate 225 IdMap.merge cup_res accu term
414 abate 110 )
415     (empty_res fv)
416     (Types.Product.normal ?kind t)
417    
418    
419 abate 225 and filter_node t p : Types.Positive.v id_map =
420 abate 1 try MemoFilter.find (t,p) !memo_filter
421     with Not_found ->
422     let (_,fv,_) as d = descr p in
423 abate 225 let res = IdMap.map_from_slist (fun _ -> Types.Positive.forward ()) fv in
424 abate 1 memo_filter := MemoFilter.add (t,p) res !memo_filter;
425     let r = filter_descr t (descr p) in
426 abate 225 IdMap.collide Types.Positive.define res r;
427 abate 1 r
428    
429     let filter t p =
430     let r = filter_node t p in
431     memo_filter := MemoFilter.empty;
432 abate 225 IdMap.get (IdMap.map Types.Positive.solve r)
433 abate 1
434 abate 1354 let filter_descr t p =
435     let r = filter_descr t p in
436     memo_filter := MemoFilter.empty;
437     IdMap.get (IdMap.map Types.Positive.solve r)
438 abate 1
439 abate 1354
440 abate 1 (* Normal forms for patterns and compilation *)
441    
442 abate 229 let min (a:int) (b:int) = if a < b then a else b
443    
444 abate 407 let any_basic = Types.Record.or_absent Types.non_constructed
445    
446    
447 abate 653 module Normal = struct
448 abate 149
449 abate 1 type source =
450 abate 172 | SCatch | SConst of Types.const
451     | SLeft | SRight | SRecompose
452 abate 225 type result = source id_map
453 abate 1
454 abate 271 let compare_source s1 s2 =
455     if s1 == s2 then 0
456     else match (s1,s2) with
457     | SCatch, _ -> -1 | _, SCatch -> 1
458     | SLeft, _ -> -1 | _, SLeft -> 1
459     | SRight, _ -> -1 | _, SRight -> 1
460     | SRecompose, _ -> -1 | _, SRecompose -> 1
461 abate 691 | SConst c1, SConst c2 -> Types.Const.compare c1 c2
462 abate 271
463     let hash_source = function
464     | SCatch -> 1
465     | SLeft -> 2
466     | SRight -> 3
467     | SRecompose -> 4
468 abate 691 | SConst c -> Types.Const.hash c
469 abate 271
470     let compare_result r1 r2 =
471     IdMap.compare compare_source r1 r2
472    
473     let hash_result r =
474     IdMap.hash hash_source r
475    
476    
477 abate 1349 let print_result ppf r = Format.fprintf ppf "<result>"
478     let print_result_option ppf = function
479     | Some x -> Format.fprintf ppf "Some(%a)" print_result x
480     | None -> Format.fprintf ppf "None"
481    
482 abate 271 module NodeSet =
483 abate 653 SortedList.Make(Node)
484 abate 271
485    
486 abate 653 type nnf = NodeSet.t * Types.t (* pl,t; t <= \accept{pl} *)
487    
488 abate 1349 let check_nnf (pl,t) =
489     List.iter (fun p -> assert(Types.subtype t (Types.descr p.accept)))
490     (NodeSet.get pl)
491    
492     let print_nnf ppf (pl,t) =
493     Format.fprintf ppf "@[(pl=%a;t=%a)@]" NodeSet.dump pl Types.Print.print t
494    
495    
496 abate 271 let compare_nnf (l1,t1) (l2,t2) =
497     let c = NodeSet.compare l1 l2 in if c <> 0 then c
498 abate 653 else Types.compare t1 t2
499 abate 271
500     let hash_nnf (l,t) =
501 abate 653 (NodeSet.hash l) + 17 * (Types.hash t)
502 abate 271
503     module NLineBasic =
504     SortedList.Make(
505     struct
506 abate 653 include Custom.Dummy
507 abate 698 let serialize s _ = failwith "Patterns.NLineBasic.serialize"
508 abate 653 type t = result * Types.t
509 abate 271 let compare (r1,t1) (r2,t2) =
510     let c = compare_result r1 r2 in if c <> 0 then c
511 abate 653 else Types.compare t1 t2
512 abate 310 let equal x y = compare x y == 0
513 abate 653 let hash (r,t) = hash_result r + 17 * Types.hash t
514 abate 271 end
515     )
516    
517     module NLineProd =
518     SortedList.Make(
519     struct
520 abate 1349 (* include Custom.Dummy*)
521 abate 698 let serialize s _ = failwith "Patterns.NLineProd.serialize"
522 abate 1349 let deserialize s = failwith "Patterns.NLineProd.deserialize"
523     let check x = ()
524     let dump ppf (r,x,y) =
525     Format.fprintf ppf "@[(result=%a;x=%a;y=%a)@]"
526     print_result r
527     print_nnf x
528     print_nnf y
529 abate 653 type t = result * nnf * nnf
530 abate 271 let compare (r1,x1,y1) (r2,x2,y2) =
531     let c = compare_result r1 r2 in if c <> 0 then c
532     else let c = compare_nnf x1 x2 in if c <> 0 then c
533     else compare_nnf y1 y2
534 abate 310 let equal x y = compare x y == 0
535 abate 271 let hash (r,x,y) =
536     hash_result r + 17 * (hash_nnf x) + 267 * (hash_nnf y)
537     end
538     )
539    
540 abate 39 type record =
541 abate 230 | RecNolabel of result option * result option
542 abate 653 | RecLabel of label * NLineProd.t
543 abate 43 type t = {
544 abate 42 nfv : fv;
545 abate 57 ncatchv: fv;
546 abate 653 na : Types.t;
547     nbasic : NLineBasic.t;
548     nprod : NLineProd.t;
549     nxml : NLineProd.t;
550 abate 229 nrecord: record
551 abate 39 }
552    
553 abate 1349 let print_record ppf = function
554     | RecLabel (lab,l) ->
555     Format.fprintf ppf "RecLabel(@[%a@],@ @[%a@])"
556     Label.print (LabelPool.value lab)
557     NLineProd.dump l
558     | RecNolabel (a,b) ->
559     Format.fprintf ppf "RecNolabel(@[%a@],@[%a@])"
560     print_result_option a
561     print_result_option b
562     let print ppf nf =
563     Format.fprintf ppf "@[NF{na=%a;@[nrecord=@ @[%a@]@]}@]"
564     Types.Print.print nf.na
565     print_record nf.nrecord
566    
567    
568 abate 271 let compare_nf t1 t2 =
569     if t1 == t2 then 0
570     else
571     (* TODO: reorder; remove comparison of nfv ? *)
572     let c = IdSet.compare t1.nfv t2.nfv in if c <> 0 then c
573     else let c = IdSet.compare t1.ncatchv t2.ncatchv in if c <> 0 then c
574 abate 653 else let c = Types.compare t1.na t2.na in if c <> 0 then c
575 abate 271 else let c = NLineBasic.compare t1.nbasic t2.nbasic in if c <> 0 then c
576     else let c = NLineProd.compare t1.nprod t2.nprod in if c <> 0 then c
577     else let c = NLineProd.compare t1.nxml t2.nxml in if c <> 0 then c
578     else match t1.nrecord, t2.nrecord with
579     | RecNolabel (s1,n1), RecNolabel (s2,n2) ->
580     let c = match (s1,s2) with
581     | None,None -> 0
582     | Some r1, Some r2 -> compare_result r1 r2
583     | None, _ -> -1
584     | _, None -> 1 in
585     if c <> 0 then c
586     else (match (n1,n2) with
587     | None,None -> 0
588     | Some r1, Some r2 -> compare_result r1 r2
589     | None, _ -> -1
590     | _, None -> 1)
591     | RecNolabel (_,_), _ -> -1
592     | _, RecNolabel (_,_) -> 1
593     | RecLabel (l1,p1), RecLabel (l2,p2) ->
594     let c = LabelPool.compare l1 l2 in if c <> 0 then c
595     else NLineProd.compare p1 p2
596 abate 172
597 abate 225 let fus = IdMap.union_disj
598 abate 172
599 abate 229 let nempty lab =
600     { nfv = IdSet.empty; ncatchv = IdSet.empty;
601     na = Types.empty;
602 abate 271 nbasic = NLineBasic.empty;
603     nprod = NLineProd.empty;
604     nxml = NLineProd.empty;
605 abate 229 nrecord = (match lab with
606 abate 271 | Some l -> RecLabel (l,NLineProd.empty)
607 abate 230 | None -> RecNolabel (None,None))
608 abate 229 }
609 abate 281 let dummy = nempty None
610 abate 149
611    
612     let ncup nf1 nf2 =
613     (* assert (Types.is_empty (Types.cap nf1.na nf2.na)); *)
614     (* assert (nf1.nfv = nf2.nfv); *)
615     { nfv = nf1.nfv;
616 abate 225 ncatchv = IdSet.cap nf1.ncatchv nf2.ncatchv;
617 abate 149 na = Types.cup nf1.na nf2.na;
618 abate 271 nbasic = NLineBasic.cup nf1.nbasic nf2.nbasic;
619     nprod = NLineProd.cup nf1.nprod nf2.nprod;
620     nxml = NLineProd.cup nf1.nxml nf2.nxml;
621 abate 229 nrecord = (match (nf1.nrecord,nf2.nrecord) with
622 abate 230 | RecLabel (l1,r1), RecLabel (l2,r2) ->
623 abate 310 (* assert (l1 = l2); *) RecLabel (l1, NLineProd.cup r1 r2)
624 abate 230 | RecNolabel (x1,y1), RecNolabel (x2,y2) ->
625 abate 310 RecNolabel((if x1 == None then x2 else x1),
626     (if y1 == None then y2 else y1))
627 abate 229 | _ -> assert false)
628 abate 149 }
629    
630     let double_fold f l1 l2 =
631 abate 271 List.fold_left
632     (fun accu x1 -> List.fold_left (fun accu x2 -> f accu x1 x2) accu l2)
633     [] l1
634    
635     let double_fold_prod f l1 l2 =
636     double_fold f (NLineProd.get l1) (NLineProd.get l2)
637 abate 149
638     let ncap nf1 nf2 =
639 abate 271 let prod accu (res1,(pl1,t1),(ql1,s1)) (res2,(pl2,t2),(ql2,s2)) =
640 abate 149 let t = Types.cap t1 t2 in
641     if Types.is_empty t then accu else
642     let s = Types.cap s1 s2 in
643     if Types.is_empty s then accu else
644 abate 271 (fus res1 res2, (NodeSet.cup pl1 pl2,t),(NodeSet.cup ql1 ql2,s))
645     :: accu
646 abate 149 in
647     let basic accu (res1,t1) (res2,t2) =
648     let t = Types.cap t1 t2 in
649     if Types.is_empty t then accu else
650     (fus res1 res2, t) :: accu
651     in
652 abate 271 let record r1 r2 = match r1,r2 with
653 abate 230 | RecLabel (l1,r1), RecLabel (l2,r2) ->
654 abate 310 (* assert (l1 = l2); *)
655 abate 271 RecLabel(l1, NLineProd.from_list (double_fold_prod prod r1 r2))
656 abate 230 | RecNolabel (x1,y1), RecNolabel (x2,y2) ->
657 abate 229 let x = match x1,x2 with
658     | Some res1, Some res2 -> Some (fus res1 res2)
659     | _ -> None
660     and y = match y1,y2 with
661     | Some res1, Some res2 -> Some (fus res1 res2)
662     | _ -> None in
663 abate 230 RecNolabel (x,y)
664 abate 229 | _ -> assert false
665 abate 172 in
666 abate 225 { nfv = IdSet.cup nf1.nfv nf2.nfv;
667     ncatchv = IdSet.cup nf1.ncatchv nf2.ncatchv;
668 abate 149 na = Types.cap nf1.na nf2.na;
669 abate 271 nbasic = NLineBasic.from_list (double_fold basic
670     (NLineBasic.get nf1.nbasic)
671     (NLineBasic.get nf2.nbasic));
672     nprod = NLineProd.from_list (double_fold_prod prod nf1.nprod nf2.nprod);
673     nxml = NLineProd.from_list (double_fold_prod prod nf1.nxml nf2.nxml);
674     nrecord = record nf1.nrecord nf2.nrecord;
675 abate 149 }
676    
677 abate 271 let nnode p = NodeSet.singleton p, Types.descr p.accept
678     let nc t = NodeSet.empty, t
679     let ncany = nc Types.any
680    
681 abate 225 let empty_res = IdMap.empty
682 abate 172
683 abate 229 let ntimes lab acc p q =
684 abate 225 let src_p = IdMap.constant SLeft p.fv
685     and src_q = IdMap.constant SRight q.fv in
686     let src = IdMap.merge_elem SRecompose src_p src_q in
687 abate 229 { nempty lab with
688 abate 225 nfv = IdSet.cup p.fv q.fv;
689 abate 149 na = acc;
690 abate 271 nprod = NLineProd.singleton (src, nnode p, nnode q);
691 abate 149 }
692 abate 172
693 abate 229 let nxml lab acc p q =
694 abate 225 let src_p = IdMap.constant SLeft p.fv
695     and src_q = IdMap.constant SRight q.fv in
696     let src = IdMap.merge_elem SRecompose src_p src_q in
697 abate 229 { nempty lab with
698 abate 225 nfv = IdSet.cup p.fv q.fv;
699 abate 172 na = acc;
700 abate 271 nxml = NLineProd.singleton (src, nnode p, nnode q);
701 abate 172 }
702 abate 149
703 abate 229 let nrecord lab acc l p =
704     match lab with
705     | None -> assert false
706     | Some label ->
707     assert (label <= l);
708     if l == label then
709     let src = IdMap.constant SLeft p.fv in
710     { nempty lab with
711     nfv = p.fv;
712     na = acc;
713 abate 230 nrecord = RecLabel(label,
714 abate 271 NLineProd.singleton (src,nnode p, ncany))}
715 abate 229 else
716     let src = IdMap.constant SRight p.fv in
717     let p' = make p.fv in (* optimize this ... *)
718     (* cache the results to avoid looping ... *)
719     define p' (record l p);
720     { nempty lab with
721     nfv = p.fv;
722     na = acc;
723 abate 271 nrecord =
724     RecLabel(label,
725     NLineProd.singleton(src,nc Types.Record.any_or_absent,
726     nnode p') )}
727 abate 229
728 abate 149
729 abate 229 let nconstr lab t =
730 abate 271 let aux l = NLineProd.from_list
731     (List.map (fun (t1,t2) -> empty_res, nc t1,nc t2) l) in
732 abate 229 let record =
733     match lab with
734     | None ->
735     let (x,y) = Types.Record.empty_cases t in
736 abate 230 RecNolabel ((if x then Some empty_res else None),
737 abate 229 (if y then Some empty_res else None))
738     | Some l ->
739 abate 1349 (*
740     let ppf = Format.std_formatter in
741     Format.fprintf ppf "Constr record t=%a l=%a@."
742     Types.Print.print t Label.print (LabelPool.value l);
743     let sp = Types.Record.split_normal t l in
744     List.iter (fun (t1,t2) ->
745     Format.fprintf ppf "t1=%a t2=%a@."
746     Types.Print.print t1
747     Types.Print.print t2) sp;
748     *)
749 abate 230 RecLabel (l,aux (Types.Record.split_normal t l))
750 abate 229 in
751     { nempty lab with
752 abate 172 na = t;
753 abate 271 nbasic = NLineBasic.singleton (empty_res, Types.cap t any_basic);
754 abate 229 nprod = aux (Types.Product.normal t);
755     nxml = aux (Types.Product.normal ~kind:`XML t);
756     nrecord = record
757 abate 172 }
758    
759 abate 229 let nconstant lab x c =
760 abate 225 let l = IdMap.singleton x (SConst c) in
761     { nfv = IdSet.singleton x;
762     ncatchv = IdSet.empty;
763 abate 172 na = Types.any;
764 abate 271 nbasic = NLineBasic.singleton (l,any_basic);
765     nprod = NLineProd.singleton (l,ncany,ncany);
766     nxml = NLineProd.singleton (l,ncany,ncany);
767 abate 229 nrecord = match lab with
768 abate 230 | None -> RecNolabel (Some l, Some l)
769 abate 229 | Some lab ->
770 abate 271 RecLabel (lab, NLineProd.singleton
771     (l,nc Types.Record.any_or_absent,
772     ncany))
773 abate 172 }
774    
775 abate 229 let ncapture lab x =
776 abate 225 let l = IdMap.singleton x SCatch in
777     { nfv = IdSet.singleton x;
778     ncatchv = IdSet.singleton x;
779 abate 172 na = Types.any;
780 abate 271 nbasic = NLineBasic.singleton (l,any_basic);
781     nprod = NLineProd.singleton (l,ncany,ncany);
782     nxml = NLineProd.singleton (l,ncany,ncany);
783 abate 229 nrecord = match lab with
784 abate 230 | None -> RecNolabel (Some l, Some l)
785 abate 229 | Some lab ->
786 abate 271 RecLabel (lab, NLineProd.singleton
787     (l,nc Types.Record.any_or_absent,
788     ncany))
789 abate 172 }
790    
791 abate 229 let rec nnormal lab (acc,fv,d) =
792 abate 172 if Types.is_empty acc
793 abate 229 then nempty lab
794 abate 172 else match d with
795 abate 229 | Constr t -> nconstr lab t
796     | Cap (p,q) -> ncap (nnormal lab p) (nnormal lab q)
797 abate 172 | Cup ((acc1,_,_) as p,q) ->
798 abate 229 ncup (nnormal lab p) (ncap (nnormal lab q)
799     (nconstr lab (Types.neg acc1)))
800     | Times (p,q) -> ntimes lab acc p q
801     | Xml (p,q) -> nxml lab acc p q
802     | Capture x -> ncapture lab x
803     | Constant (x,c) -> nconstant lab x c
804     | Record (l,p) -> nrecord lab acc l p
805 abate 691 | Dummy -> assert false
806 abate 229
807     (*TODO: when an operand of Cap has its first_label > lab,
808     directly shift it*)
809    
810     let rec first_label (acc,fv,d) =
811     if Types.is_empty acc
812 abate 233 then LabelPool.dummy_max
813 abate 229 else match d with
814     | Constr t -> Types.Record.first_label t
815     | Cap (p,q) -> min (first_label p) (first_label q)
816     | Cup ((acc1,_,_) as p,q) -> min (first_label p) (first_label q)
817     (* should "first_label_type acc1" ? *)
818     | Record (l,p) -> l
819 abate 233 | _ -> LabelPool.dummy_max
820 abate 229
821 abate 172
822     let remove_catchv n =
823     let ncv = n.ncatchv in
824 abate 271 let nlinesbasic l =
825     NLineBasic.map (fun (res,x) -> (IdMap.diff res ncv,x)) l in
826     let nlinesprod l =
827     NLineProd.map (fun (res,x,y) -> (IdMap.diff res ncv,x,y)) l in
828 abate 225 { nfv = IdSet.diff n.nfv ncv;
829 abate 172 ncatchv = n.ncatchv;
830     na = n.na;
831 abate 271 nbasic = nlinesbasic n.nbasic;
832     nprod = nlinesprod n.nprod;
833     nxml = nlinesprod n.nxml;
834 abate 229 nrecord = (match n.nrecord with
835 abate 230 | RecNolabel (x,y) ->
836 abate 229 let x = match x with
837     | Some res -> Some (IdMap.diff res ncv)
838     | None -> None in
839     let y = match y with
840     | Some res -> Some (IdMap.diff res ncv)
841     | None -> None in
842 abate 230 RecNolabel (x,y)
843 abate 271 | RecLabel (lab,l) -> RecLabel (lab, nlinesprod l))
844 abate 172 }
845    
846 abate 1349 let print_node_list ppf pl =
847     List.iter (fun p -> Format.fprintf ppf "%a;" Node.dump p) pl
848    
849 abate 229 let normal l t pl =
850 abate 172 remove_catchv
851 abate 229 (List.fold_left
852     (fun a p -> ncap a (nnormal l (descr p)))
853     (nconstr l t)
854     pl)
855 abate 1349
856     (*
857     let normal l t pl =
858     let nf = normal l t pl in
859     (match l with Some l ->
860     Format.fprintf Format.std_formatter
861     "normal(l=%a;t=%a;pl=%a)=%a@."
862     Label.print (LabelPool.value l)
863     Types.Print.print t
864     print_node_list pl
865     print nf
866     | None -> Format.fprintf Format.std_formatter
867     "normal(t=%a;pl=%a)=%a@."
868     Types.Print.print t
869     print_node_list pl
870     print nf);
871     nf
872     *)
873 abate 43 end
874 abate 42
875    
876 abate 43 module Compile =
877     struct
878 abate 56 type actions =
879 abate 172 | AIgnore of result
880     | AKind of actions_kind
881 abate 56 and actions_kind = {
882 abate 653 basic: (Types.t * result) list;
883 abate 243 atoms: result Atoms.map;
884     chars: result Chars.map;
885 abate 43 prod: result dispatch dispatch;
886 abate 110 xml: result dispatch dispatch;
887 abate 43 record: record option;
888     }
889     and record =
890 abate 233 | RecLabel of label * result dispatch dispatch
891 abate 230 | RecNolabel of result option * result option
892 abate 42
893 abate 45 and 'a dispatch =
894 abate 172 | Dispatch of dispatcher * 'a array
895     | TailCall of dispatcher
896     | Ignore of 'a
897     | Impossible
898 abate 45
899     and result = int * source array
900 abate 43 and source =
901 abate 172 | Catch | Const of Types.const
902     | Left of int | Right of int | Recompose of int * int
903 abate 43
904     and return_code =
905 abate 653 Types.t * int * (* accepted type, arity *)
906 abate 225 (int * int id_map) list
907 abate 42
908 abate 43 and interface =
909 abate 147 [ `Result of int
910     | `Switch of interface * interface
911 abate 43 | `None ]
912 abate 42
913 abate 43 and dispatcher = {
914     id : int;
915 abate 653 t : Types.t;
916 abate 43 pl : Normal.t array;
917 abate 233 label : label option;
918 abate 43 interface : interface;
919     codes : return_code array;
920 abate 226 mutable actions : actions option;
921     mutable printed : bool
922 abate 43 }
923 abate 45
924 abate 310 let equal_array f a1 a2 =
925     let rec aux i = (i < 0) || ((f a1.(i) a2.(i)) && (aux (i - 1))) in
926     let l1 = Array.length a1 and l2 = Array.length a2 in
927     (l1 == l2) && (aux (l1 - 1))
928    
929     let equal_source s1 s2 =
930     (s1 == s2) || match (s1,s2) with
931 abate 691 | Const x, Const y -> Types.Const.equal x y
932 abate 310 | Left x, Left y -> x == y
933     | Right x, Right y -> x == y
934     | Recompose (x1,x2), Recompose (y1,y2) -> (x1 == y1) && (x2 == y2)
935     | _ -> false
936    
937     let equal_result (r1,s1) (r2,s2) =
938     (r1 == r2) && (equal_array equal_source s1 s2)
939    
940     let equal_result_dispatch d1 d2 =
941     (d1 == d2) || match (d1,d2) with
942     | Dispatch (d1,a1), Dispatch (d2,a2) -> (d1 == d2) && (equal_array equal_result a1 a2)
943     | TailCall d1, TailCall d2 -> d1 == d2
944     | Ignore a1, Ignore a2 -> equal_result a1 a2
945     | _ -> false
946    
947    
948 abate 45 let array_for_all f a =
949     let rec aux f a i =
950 abate 310 if i == Array.length a then true
951 abate 45 else f a.(i) && (aux f a (succ i))
952     in
953     aux f a 0
954    
955     let array_for_all_i f a =
956     let rec aux f a i =
957 abate 310 if i == Array.length a then true
958 abate 45 else f i a.(i) && (aux f a (succ i))
959     in
960     aux f a 0
961    
962 abate 110 let combine_kind basic prod xml record =
963 abate 56 try (
964     let rs = [] in
965     let rs = match basic with
966     | [_,r] -> r :: rs
967     | [] -> rs
968     | _ -> raise Exit in
969     let rs = match prod with
970 abate 172 | Impossible -> rs
971     | Ignore (Ignore r) -> r :: rs
972 abate 56 | _ -> raise Exit in
973 abate 110 let rs = match xml with
974 abate 172 | Impossible -> rs
975     | Ignore (Ignore r) -> r :: rs
976 abate 110 | _ -> raise Exit in
977 abate 56 let rs = match record with
978     | None -> rs
979 abate 230 | Some (RecLabel (_,Ignore (Ignore r))) -> r :: rs
980     | Some (RecNolabel (Some r1, Some r2)) -> r1 :: r2 :: rs
981 abate 56 | _ -> raise Exit in
982     match rs with
983 abate 57 | ((_, ret) as r) :: rs when
984 abate 310 List.for_all ( equal_result r ) rs
985 abate 57 && array_for_all
986 abate 172 (function Catch | Const _ -> true | _ -> false) ret
987     -> AIgnore r
988 abate 56 | _ -> raise Exit
989     )
990 abate 243 with Exit ->
991     AKind
992     { basic = basic;
993     atoms =
994 abate 956 Atoms.mk_map (List.map (fun (t,r) -> Types.Atom.get t, r) basic);
995 abate 243 chars =
996 abate 956 Chars.mk_map (List.map (fun (t,r) -> Types.Char.get t, r) basic);
997 abate 243 prod = prod;
998     xml = xml;
999 abate 956 record = record;
1000     }
1001 abate 243
1002 abate 310 let combine f (disp,act) =
1003     if Array.length act == 0 then Impossible
1004 abate 45 else
1005 abate 310 if (array_for_all (fun (_,ar,_) -> ar == 0) disp.codes)
1006     && (array_for_all ( f act.(0) ) act) then
1007 abate 172 Ignore act.(0)
1008 abate 45 else
1009 abate 172 Dispatch (disp, act)
1010 abate 45
1011    
1012     let detect_right_tail_call = function
1013 abate 172 | Dispatch (disp,branches)
1014 abate 45 when
1015     array_for_all_i
1016     (fun i (code,ret) ->
1017 abate 310 (i == code) &&
1018 abate 45 (array_for_all_i
1019     (fun pos ->
1020 abate 310 function Right j when pos == j -> true | _ -> false)
1021 abate 45 ret
1022     )
1023     ) branches
1024 abate 172 -> TailCall disp
1025 abate 45 | x -> x
1026    
1027     let detect_left_tail_call = function
1028 abate 172 | Dispatch (disp,branches)
1029 abate 45 when
1030     array_for_all_i
1031     (fun i ->
1032     function
1033 abate 172 | Ignore (code,ret) ->
1034 abate 310 (i == code) &&
1035 abate 45 (array_for_all_i
1036     (fun pos ->
1037 abate 310 function Left j when pos == j -> true | _ -> false)
1038 abate 45 ret
1039     )
1040     | _ -> false
1041     ) branches
1042     ->
1043 abate 172 TailCall disp
1044 abate 45 | x -> x
1045    
1046 abate 95 let cur_id = State.ref "Patterns.cur_id" 0
1047     (* TODO: save dispatchers ? *)
1048 abate 43
1049 abate 281 module NfMap = Map.Make(
1050     struct
1051     type t = Normal.t
1052     let compare = Normal.compare_nf
1053     end)
1054    
1055 abate 42 module DispMap = Map.Make(
1056     struct
1057 abate 653 type t = Types.t * Normal.t array
1058 abate 271
1059     let rec compare_rec a1 a2 i =
1060     if i < 0 then 0
1061     else
1062     let c = Normal.compare_nf a1.(i) a2.(i) in
1063     if c <> 0 then c else compare_rec a1 a2 (i - 1)
1064    
1065     let compare (t1,a1) (t2,a2) =
1066 abate 653 let c = Types.compare t1 t2 in if c <> 0 then c
1067 abate 271 else let l1 = Array.length a1 and l2 = Array.length a2 in
1068     if l1 < l2 then -1 else if l1 > l2 then 1
1069     else compare_rec a1 a2 (l1 - 1)
1070 abate 42 end
1071     )
1072 abate 271
1073     (* Try with a hash-table ! *)
1074 abate 43
1075 abate 42 let dispatchers = ref DispMap.empty
1076 abate 798
1077     let timer_disp = Stats.Timer.create "Patterns.dispatcher loop"
1078 abate 1349
1079     let rec print_iface ppf = function
1080     | `Result i -> Format.fprintf ppf "Result(%i)" i
1081     | `Switch (yes,no) -> Format.fprintf ppf "Switch(%a,%a)"
1082     print_iface yes print_iface no
1083     | `None -> Format.fprintf ppf "None"
1084 abate 798
1085 abate 229 let dispatcher t pl lab : dispatcher =
1086 abate 42 try DispMap.find (t,pl) !dispatchers
1087     with Not_found ->
1088 abate 1349 (* let ppf = Format.std_formatter in
1089     Format.fprintf ppf "dispatcher %i:" !cur_id;
1090     Array.iter (fun x -> Format.fprintf ppf "%a;" Normal.print x) pl;
1091     Format.fprintf ppf "@."; *)
1092 abate 43 let nb = ref 0 in
1093 abate 147 let codes = ref [] in
1094     let rec aux t arity i accu =
1095 abate 798 if i == Array.length pl
1096     then (incr nb; codes := (t,arity,accu)::!codes; `Result (!nb - 1))
1097 abate 43 else
1098 abate 798 let p = pl.(i) in
1099     let tp = p.Normal.na in
1100 abate 1349 (* let tp = Types.normalize tp in *)
1101 abate 798
1102     let a1 = Types.cap t tp in
1103     if Types.is_empty a1 then
1104     `Switch (`None,aux t arity (i+1) accu)
1105 abate 42 else
1106 abate 225 let v = p.Normal.nfv in
1107 abate 798 let a2 = Types.diff t tp in
1108 abate 225 let accu' = (i,IdMap.num arity v) :: accu in
1109 abate 798 if Types.is_empty a2 then
1110     `Switch (aux t (arity + (IdSet.length v)) (i+1) accu',`None)
1111     else
1112     `Switch (aux a1 (arity + (IdSet.length v)) (i+1) accu',
1113     aux a2 arity (i+1) accu)
1114    
1115     (* Unopt version:
1116 abate 43 `Switch
1117 abate 147 (
1118 abate 225 aux (Types.cap t tp) (arity + (IdSet.length v)) (i+1) accu',
1119 abate 147 aux (Types.diff t tp) arity (i+1) accu
1120 abate 43 )
1121 abate 798 *)
1122    
1123 abate 42 in
1124 abate 1349 (*
1125     Array.iteri (fun i p ->
1126 abate 798 Format.fprintf Format.std_formatter
1127     "Pattern %i/%i accepts %a@." i (Array.length pl)
1128 abate 1349 Types.Print.print p.Normal.na) pl;
1129     *)
1130 abate 798
1131     Stats.Timer.start timer_disp;
1132     let iface =
1133     if Types.is_empty t then `None else aux t 0 0 [] in
1134     Stats.Timer.stop timer_disp ();
1135 abate 1349 (* Format.fprintf Format.std_formatter "iface=%a@." print_iface iface;*)
1136 abate 42 let res = { id = !cur_id;
1137     t = t;
1138 abate 229 label = lab;
1139 abate 42 pl = pl;
1140 abate 43 interface = iface;
1141 abate 147 codes = Array.of_list (List.rev !codes);
1142 abate 226 actions = None; printed = false } in
1143 abate 42 incr cur_id;
1144     dispatchers := DispMap.add (t,pl) res !dispatchers;
1145     res
1146    
1147 abate 43 let find_code d a =
1148     let rec aux i = function
1149 abate 147 | `Result code -> code
1150     | `None -> assert false
1151 abate 332 | `Switch (yes,_) when a.(i) != None -> aux (i + 1) yes
1152 abate 147 | `Switch (_,no) -> aux (i + 1) no
1153 abate 43 in
1154 abate 1349 (*
1155     let ppf = Format.std_formatter in
1156     Format.fprintf ppf "find_code iface=%a [ "
1157     print_iface d.interface;
1158     for i = 0 to Array.length a - 1 do
1159     if (a.(i) != None) then
1160     Format.fprintf ppf "+ "
1161     else
1162     Format.fprintf ppf "- "
1163     done;
1164     Format.fprintf ppf "]@.";
1165     *)
1166 abate 43 aux 0 d.interface
1167 abate 42
1168 abate 43 let create_result pl =
1169 abate 166 let aux x accu = match x with Some b -> b @ accu | None -> accu in
1170     Array.of_list (Array.fold_right aux pl [])
1171 abate 43
1172     let return disp pl f =
1173     let aux = function [x] -> Some (f x) | [] -> None | _ -> assert false in
1174     let final = Array.map aux pl in
1175     (find_code disp final, create_result final)
1176    
1177 abate 225 let conv_source_basic s = match s with
1178 abate 172 | Normal.SCatch -> Catch
1179     | Normal.SConst c -> Const c
1180 abate 42 | _ -> assert false
1181    
1182 abate 57 let assoc v l =
1183 abate 225 try IdMap.assoc v l with Not_found -> -1
1184 abate 57
1185 abate 225 let conv_source_prod left right v s = match s with
1186 abate 172 | Normal.SCatch -> Catch
1187     | Normal.SConst c -> Const c
1188     | Normal.SLeft -> Left (assoc v left)
1189     | Normal.SRight -> Right (assoc v right)
1190     | Normal.SRecompose -> Recompose (assoc v left, assoc v right)
1191 abate 42
1192 abate 653 module TypeList = SortedList.Make(Types)
1193     let dispatch_basic disp : (Types.t * result) list =
1194 abate 147 (* TODO: try other algo, using disp.codes .... *)
1195 abate 43 let pl = Array.map (fun p -> p.Normal.nbasic) disp.pl in
1196     let tests =
1197     let accu = ref [] in
1198     let aux i (res,x) = accu := (x, [i,res]) :: !accu in
1199 abate 271 Array.iteri (fun i -> Normal.NLineBasic.iter (aux i)) pl;
1200 abate 653 TypeList.Map.get (TypeList.Map.from_list (@) !accu) in
1201 abate 43
1202 abate 407 let t = Types.cap any_basic disp.t in
1203 abate 42 let accu = ref [] in
1204 abate 43 let rec aux (success : (int * Normal.result) list) t l =
1205 abate 42 if Types.non_empty t
1206     then match l with
1207     | [] ->
1208 abate 43 let selected = Array.create (Array.length pl) [] in
1209     let add (i,res) = selected.(i) <- res :: selected.(i) in
1210     List.iter add success;
1211    
1212 abate 225 let aux_final res = IdMap.map_to_list conv_source_basic res in
1213 abate 43 accu := (t, return disp selected aux_final) :: !accu
1214     | (ty,i) :: rem ->
1215     aux (i @ success) (Types.cap t ty) rem;
1216     aux success (Types.diff t ty) rem
1217 abate 42 in
1218 abate 43 aux [] t tests;
1219 abate 42 !accu
1220    
1221    
1222 abate 45 let get_tests pl f t d post =
1223 abate 42 let accu = ref [] in
1224     let aux i x =
1225 abate 270 let (pl,ty), info = f x in
1226 abate 271 let pl = Normal.NodeSet.get pl in
1227 abate 270 accu := (ty,pl,i,info) :: !accu in
1228 abate 42 Array.iteri (fun i -> List.iter (aux i)) pl;
1229 abate 52
1230 abate 229 let lab =
1231     List.fold_left
1232     (fun l (ty,pl,_,_) ->
1233     List.fold_left
1234     (fun l p -> min l (Normal.first_label (descr p)))
1235     (min l (Types.Record.first_label ty))
1236     pl
1237 abate 233 ) LabelPool.dummy_max !accu in
1238 abate 310 let lab = if lab == LabelPool.dummy_max then None else Some lab in
1239 abate 229
1240 abate 281
1241     let pats = ref NfMap.empty in
1242     let nb_p = ref 0 in
1243     List.iter
1244     (fun (ty,pl,i,info) ->
1245     let p = Normal.normal lab ty pl in
1246     let x = (i, p.Normal.ncatchv, info) in
1247     try
1248     let s = NfMap.find p !pats in
1249     s := x :: !s
1250     with Not_found ->
1251     pats := NfMap.add p (ref [x]) !pats;
1252     incr nb_p
1253     ) !accu;
1254     let infos = Array.make !nb_p [] in
1255     let ps = Array.make !nb_p Normal.dummy in
1256     let count = ref 0 in
1257     NfMap.iter (fun p l ->
1258     let i = !count in
1259     infos.(i) <- !l;
1260     ps.(i) <- p;
1261     count := succ i) !pats;
1262 abate 310 assert( !nb_p == !count );
1263 abate 281 let disp = dispatcher t ps lab in
1264    
1265 abate 43 let result (t,_,m) =
1266 abate 1349 (* Format.fprintf Format.std_formatter "Result=%a@." Types.Print.print t;*)
1267 abate 42 let selected = Array.create (Array.length pl) [] in
1268 abate 148 let add r (i, ncv, inf) = selected.(i) <- (r,ncv,inf) :: selected.(i) in
1269 abate 43 List.iter (fun (j,r) -> List.iter (add r) infos.(j)) m;
1270 abate 270 d t selected
1271 abate 42 in
1272 abate 43 let res = Array.map result disp.codes in
1273 abate 46 post (disp,res)
1274 abate 42
1275 abate 71
1276 abate 698 type 'a rhs = Match of (id * int) list * 'a | Fail
1277 abate 46 let make_branches t brs =
1278     let (_,brs) =
1279     List.fold_left
1280     (fun (t,brs) (p,e) ->
1281 abate 271 let p' = (Normal.NodeSet.singleton p,t) in
1282 abate 798 (* let td = Types.descr (accept p) in
1283     let t' =
1284     if Types.is_empty (Types.cap t td) then t else
1285     Types.diff t td in*)
1286 abate 148 let t' = Types.diff t (Types.descr (accept p)) in
1287 abate 1107 (t', (p',(fv p, e)) :: brs)
1288 abate 46 ) (t,[]) brs in
1289 abate 52
1290 abate 46 let pl = Array.map (fun x -> [x]) (Array.of_list brs) in
1291     get_tests
1292     pl
1293 abate 270 (fun x -> x)
1294 abate 46 t
1295 abate 270 (fun _ pl ->
1296 abate 374 let r = ref Fail in
1297 abate 46 let aux = function
1298 abate 698 | [(res,catchv,(fvl,e))] -> assert (!r == Fail);
1299 abate 225 let catchv = IdMap.constant (-1) catchv in
1300 abate 698 let m = IdMap.union_disj catchv res in
1301     let m = List.map (fun x -> (x,IdMap.assoc x m)) fvl in
1302     r := Match (m,e)
1303 abate 46 | [] -> () | _ -> assert false in
1304     Array.iter aux pl;
1305 abate 374 !r
1306 abate 46 )
1307     (fun x -> x)
1308 abate 42
1309    
1310 abate 110 let rec dispatch_prod ?(kind=`Normal) disp =
1311     let pl =
1312     match kind with
1313 abate 271 | `Normal ->
1314     Array.map (fun p -> Normal.NLineProd.get p.Normal.nprod) disp.pl
1315     | `XML ->
1316     Array.map (fun p -> Normal.NLineProd.get p.Normal.nxml) disp.pl
1317 abate 110 in
1318     let t = Types.Product.get ~kind disp.t in
1319 abate 229 dispatch_prod0 disp t pl
1320     and dispatch_prod0 disp t pl =
1321 abate 42 get_tests pl
1322 abate 271 (fun (res,p,q) -> p, (res,q))
1323 abate 42 (Types.Product.pi1 t)
1324     (dispatch_prod1 disp t)
1325 abate 310 (fun x -> detect_left_tail_call (combine equal_result_dispatch x))
1326 abate 270 and dispatch_prod1 disp t t1 pl =
1327 abate 42 get_tests pl
1328 abate 270 (fun (ret1, ncatchv, (res,q)) -> q, (ret1,res) )
1329 abate 229 (Types.Product.pi2_restricted t1 t)
1330     (dispatch_prod2 disp)
1331 abate 310 (fun x -> detect_right_tail_call (combine equal_result x))
1332 abate 270 and dispatch_prod2 disp t2 pl =
1333 abate 148 let aux_final (ret2, ncatchv, (ret1, res)) =
1334 abate 225 IdMap.mapi_to_list (conv_source_prod ret1 ret2) res in
1335 abate 43 return disp pl aux_final
1336 abate 42
1337    
1338 abate 1349 let dispatch_record disp : record option =
1339 abate 229 let t = disp.t in
1340     if not (Types.Record.has_record t) then None
1341     else
1342     match disp.label with
1343     | None ->
1344     let (some,none) = Types.Record.empty_cases t in
1345     let some =
1346     if some then
1347     let pl = Array.map (fun p -> match p.Normal.nrecord with
1348 abate 230 | Normal.RecNolabel (Some x,_) -> [x]
1349     | Normal.RecNolabel (None,_) -> []
1350 abate 229 | _ -> assert false) disp.pl in
1351     Some (return disp pl (IdMap.map_to_list conv_source_basic))
1352     else None
1353     in
1354     let none =
1355     if none then
1356     let pl = Array.map (fun p -> match p.Normal.nrecord with
1357 abate 230 | Normal.RecNolabel (_,Some x) -> [x]
1358     | Normal.RecNolabel (_,None) -> []
1359 abate 229 | _ -> assert false) disp.pl in
1360     Some (return disp pl (IdMap.map_to_list conv_source_basic))
1361     else None
1362     in
1363 abate 230 Some (RecNolabel (some,none))
1364 abate 229 | Some lab ->
1365 abate 1349 (* Format.fprintf Format.std_formatter "lab=%a Split:@." Label.print (LabelPool.value lab);*)
1366 abate 229 let t = Types.Record.split t lab in
1367 abate 1349 (* List.iter (fun (t1,t2) ->
1368     Format.fprintf Format.std_formatter "t1=%a t2=%a@."
1369     Types.Print.print t1
1370     Types.Print.print t2) t; *)
1371 abate 229 let pl = Array.map (fun p -> match p.Normal.nrecord with
1372 abate 271 | Normal.RecLabel (_,l) ->
1373     Normal.NLineProd.get l
1374 abate 229 | _ -> assert false) disp.pl in
1375 abate 230 Some (RecLabel (lab,dispatch_prod0 disp t pl))
1376 abate 229 (* soucis avec les ncatchv ?? *)
1377 abate 119
1378 abate 75
1379 abate 42 let actions disp =
1380     match disp.actions with
1381     | Some a -> a
1382     | None ->
1383 abate 56 let a = combine_kind
1384     (dispatch_basic disp)
1385     (dispatch_prod disp)
1386 abate 110 (dispatch_prod ~kind:`XML disp)
1387 abate 56 (dispatch_record disp)
1388     in
1389 abate 42 disp.actions <- Some a;
1390     a
1391    
1392     let to_print = ref []
1393    
1394 abate 226 module DSET = Set.Make (struct type t = int let compare (x:t) (y:t) = x - y end)
1395     let printed = ref DSET.empty
1396    
1397 abate 42 let queue d =
1398 abate 226 if not d.printed then (
1399     d.printed <- true;
1400 abate 42 to_print := d :: !to_print
1401     )
1402    
1403 abate 57 let rec print_source ppf = function
1404 abate 172 | Catch -> Format.fprintf ppf "v"
1405     | Const c -> Types.Print.print_const ppf c
1406     | Left (-1) -> Format.fprintf ppf "v1"
1407     | Right (-1) -> Format.fprintf ppf "v2"
1408     | Left i -> Format.fprintf ppf "l%i" i
1409     | Right j -> Format.fprintf ppf "r%i" j
1410     | Recompose (i,j) ->
1411 abate 57 Format.fprintf ppf "(%a,%a)"
1412 abate 172 print_source (Left i)
1413     print_source (Right j)
1414 abate 56
1415     let print_result ppf =
1416     Array.iteri
1417     (fun i s ->
1418     if i > 0 then Format.fprintf ppf ",";
1419     print_source ppf s;
1420     )
1421    
1422     let print_ret ppf (code,ret) =
1423     Format.fprintf ppf "$%i" code;
1424     if Array.length ret <> 0 then
1425     Format.fprintf ppf "(%a)" print_result ret
1426    
1427 abate 229 let print_ret_opt ppf = function
1428     | None -> Format.fprintf ppf "*"
1429     | Some r -> print_ret ppf r
1430    
1431 abate 56 let print_kind ppf actions =
1432 abate 42 let print_lhs ppf (code,prefix,d) =
1433 abate 43 let arity = match d.codes.(code) with (_,a,_) -> a in
1434 abate 42 Format.fprintf ppf "$%i(" code;
1435     for i = 0 to arity - 1 do
1436     if i > 0 then Format.fprintf ppf ",";
1437     Format.fprintf ppf "%s%i" prefix i;
1438     done;
1439     Format.fprintf ppf ")" in
1440     let print_basic (t,ret) =
1441 abate 43 Format.fprintf ppf " | %a -> %a@\n"
1442 abate 367 Types.Print.print t
1443 abate 42 print_ret ret
1444     in
1445 abate 45 let print_prod2 = function
1446 abate 172 | Impossible -> assert false
1447     | Ignore r ->
1448 abate 45 Format.fprintf ppf " %a\n"
1449     print_ret r
1450 abate 172 | TailCall d ->
1451 abate 45 queue d;
1452     Format.fprintf ppf " disp_%i v2@\n" d.id
1453 abate 172 | Dispatch (d, branches) ->
1454 abate 45 queue d;
1455     Format.fprintf ppf " match v2 with disp_%i@\n" d.id;
1456     Array.iteri
1457     (fun code r ->
1458     Format.fprintf ppf " | %a -> %a\n"
1459     print_lhs (code, "r", d)
1460     print_ret r;
1461     )
1462     branches
1463 abate 42 in
1464 abate 229 let print_prod prefix ppf = function
1465 abate 172 | Impossible -> ()
1466     | Ignore d2 ->
1467 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
1468 abate 45 print_prod2 d2
1469 abate 172 | TailCall d ->
1470 abate 45 queue d;
1471 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
1472 abate 45 Format.fprintf ppf " disp_%i v1@\n" d.id
1473 abate 172 | Dispatch (d,branches) ->
1474 abate 45 queue d;
1475 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
1476 abate 45 Format.fprintf ppf " match v1 with disp_%i@\n" d.id;
1477     Array.iteri
1478     (fun code d2 ->
1479     Format.fprintf ppf " | %a -> @\n"
1480     print_lhs (code, "l", d);
1481     print_prod2 d2;
1482     )
1483     branches
1484 abate 42 in
1485     let rec print_record_opt ppf = function
1486     | None -> ()
1487 abate 1349 | Some (RecLabel (l,d)) ->
1488     let l = LabelPool.value l in
1489     print_prod ("record:"^(Label.to_string l)) ppf d
1490     | Some (RecNolabel (r1,r2)) ->
1491 abate 42 Format.fprintf ppf " | Record -> @\n";
1492 abate 1349 Format.fprintf ppf " SomeField:%a;NoField:%a@\n"
1493     print_ret_opt r1 print_ret_opt r2
1494     in
1495 abate 42
1496     List.iter print_basic actions.basic;
1497 abate 229 print_prod "" ppf actions.prod;
1498     print_prod "XML" ppf actions.xml;
1499 abate 42 print_record_opt ppf actions.record
1500    
1501 abate 56 let print_actions ppf = function
1502 abate 172 | AKind k -> print_kind ppf k
1503     | AIgnore r -> Format.fprintf ppf "v -> %a@\n" print_ret r
1504 abate 56
1505 abate 229 let print_dispatcher ppf d =
1506 abate 1349 Format.fprintf ppf "Dispatcher %i accepts [%a]@\n"
1507 abate 367 d.id Types.Print.print (Types.normalize d.t);
1508 abate 229 let print_code code (t, arity, m) =
1509     Format.fprintf ppf " Returns $%i(arity=%i) for [%a]"
1510     code arity
1511 abate 367 Types.Print.print (Types.normalize t);
1512 abate 229 (*
1513     List.iter
1514     (fun (i,b) ->
1515     Format.fprintf ppf "[%i:" i;
1516     List.iter
1517     (fun (v,i) -> Format.fprintf ppf "%s=>%i;" v i)
1518     b;
1519     Format.fprintf ppf "]"
1520     ) m; *)
1521    
1522     Format.fprintf ppf "@\n";
1523     in
1524 abate 1349 Array.iteri print_code d.codes;
1525 abate 229 Format.fprintf ppf "let disp_%i = function@\n" d.id;
1526     print_actions ppf (actions d);
1527     Format.fprintf ppf "====================================@\n"
1528    
1529    
1530 abate 42 let rec print_dispatchers ppf =
1531     match !to_print with
1532     | [] -> ()
1533 abate 229 | d :: rem ->
1534     to_print := rem;
1535     print_dispatcher ppf d;
1536 abate 42 print_dispatchers ppf
1537    
1538 abate 229
1539     let show ppf t pl lab =
1540     let disp = dispatcher t pl lab in
1541 abate 42 queue disp;
1542     print_dispatchers ppf
1543    
1544 abate 149 let debug_compile ppf t pl =
1545     let t = Types.descr t in
1546 abate 229 let lab =
1547     List.fold_left
1548     (fun l p -> min l (Normal.first_label (descr p)))
1549     (Types.Record.first_label t) pl in
1550 abate 310 let lab = if lab == LabelPool.dummy_max then None else Some lab in
1551 abate 229
1552     let pl = Array.of_list
1553 abate 281 (List.map (fun p -> Normal.normal lab (*t*) Types.Record.any_or_absent [p]) pl) in
1554 abate 229
1555     show ppf t pl lab;
1556 abate 172 Format.fprintf ppf "# compiled dispatchers: %i@\n" !cur_id
1557 abate 43 end
1558 abate 42
1559    
1560 abate 1352
1561    
1562     (* New compilation procedure *)
1563    
1564     module Compile2 = struct
1565    
1566 abate 1359 module PatList = SortedList.Make(struct include Custom.Dummy include Pat end)
1567 abate 1352 module TypesFv = Custom.Pair(Types)(IdSet)
1568 abate 1358 module Req = PatList.MakeMap(TypesFv)
1569 abate 1352 (* Invariant for (p |-> (t,X)):
1570     i) t != Empty
1571     ii) X \subset fv(p) *)
1572    
1573 abate 1358 let empty_reqs = PatList.Map.empty
1574    
1575     let merge_reqs =
1576     PatList.Map.merge
1577     (fun (t1,xs1) (t2,xs2) -> Types.cup t1 t2, IdSet.cup xs1 xs2)
1578    
1579     let add_req reqs p t xs =
1580     merge_reqs reqs (PatList.Map.singleton p (t,xs))
1581    
1582 abate 1353 module NodeSet = Set.Make(Node)
1583    
1584     let pi1 t = Types.Product.pi1 (Types.Product.get t)
1585     let pi2 t = Types.Product.pi2 (Types.Product.get t)
1586    
1587 abate 1352 module Approx = struct
1588    
1589 abate 1354 (* Note: this is incomplete because of non-atomic constant patterns:
1590     # debug approx (_,(x:=(1,2))) (1,2);;
1591     [DEBUG:approx]
1592     x=(1,2)
1593     *)
1594 abate 1355 let rec approx_var seen ((a,fv,d) as p) t xs =
1595     assert (Types.subtype t a);
1596     assert (IdSet.subset xs fv);
1597     if (IdSet.is_empty xs) || (Types.is_empty t) then xs
1598     else match d with
1599     | Cup ((a1,_,_) as p1,p2) ->
1600     IdSet.cap
1601     (approx_var seen p1 (Types.cap t a1) xs)
1602     (approx_var seen p2 (Types.diff t a1) xs)
1603     | Cap ((_,fv1,_) as p1,((_,fv2,_) as p2)) ->
1604     IdSet.cup
1605     (approx_var seen p1 t (IdSet.cap fv1 xs))
1606     (approx_var seen p2 t (IdSet.cap fv2 xs))
1607     | Capture _ ->
1608     xs
1609     | Constant (_,c) ->
1610     if (Types.subtype t (Types.constant c