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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1350 - (hide annotations)
Tue Jul 10 18:41:32 2007 UTC (5 years, 10 months ago) by abate
File size: 44128 byte(s)
[r2004-12-20 22:08:36 by afrisch] Pretty print patterns

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

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