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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 240 - (hide annotations)
Tue Jul 10 17:18:24 2007 UTC (5 years, 10 months ago) by abate
File size: 29796 byte(s)
[r2003-03-14 18:11:21 by cvscast] Empty log message

Original author: cvscast
Date: 2003-03-14 18:13:42+00:00
1 abate 107 exception Error of string
2 abate 225 open Ident
3 abate 1
4     (* Syntactic algebra *)
5 abate 121 (* Constraint: any node except Constr has fv<>[] ... *)
6 abate 1 type d =
7 abate 121 | Constr of Types.descr
8 abate 1 | Cup of descr * descr
9 abate 121 | Cap of descr * descr
10 abate 1 | Times of node * node
11 abate 110 | Xml of node * node
12 abate 233 | Record of label * node
13 abate 225 | Capture of id
14     | Constant of id * Types.const
15 abate 1 and node = {
16     id : int;
17     mutable descr : descr option;
18     accept : Types.node;
19     fv : fv
20     } and descr = Types.descr * fv * d
21    
22 abate 136 let id x = x.id
23     let descr x = match x.descr with Some d -> d | None -> failwith "Patterns.descr"
24     let fv x = x.fv
25     let accept x = Types.internalize x.accept
26 abate 121
27     let printed = ref []
28     let to_print = ref []
29 abate 136 let rec print ppf (a,_,d) =
30     (* Format.fprintf ppf "[%a]" Types.Print.print_descr a; *)
31 abate 121 match d with
32     | Constr t -> Types.Print.print_descr ppf t
33     | Cup (p1,p2) -> Format.fprintf ppf "(%a | %a)" print p1 print p2
34     | Cap (p1,p2) -> Format.fprintf ppf "(%a & %a)" print p1 print p2
35     | Times (n1,n2) ->
36     Format.fprintf ppf "(P%i,P%i)" n1.id n2.id;
37     to_print := n1 :: n2 :: !to_print
38     | Xml (n1,n2) ->
39     Format.fprintf ppf "XML(P%i,P%i)" n1.id n2.id;
40     to_print := n1 :: n2 :: !to_print
41     | Record (l,n) ->
42 abate 233 Format.fprintf ppf "{ %s = P%i }" (LabelPool.value l) n.id;
43 abate 121 to_print := n :: !to_print
44     | Capture x ->
45 abate 225 Format.fprintf ppf "%s" (Id.value x)
46 abate 121 | Constant (x,c) ->
47 abate 225 Format.fprintf ppf "(%s := %a)" (Id.value x)
48     Types.Print.print_const c
49 abate 121
50 abate 136 let dump_print ppf =
51     while !to_print <> [] do
52     let p = List.hd !to_print in
53     to_print := List.tl !to_print;
54     if not (List.mem p.id !printed) then
55     ( printed := p.id :: !printed;
56     Format.fprintf ppf "P%i:=%a\n" p.id print (descr p)
57     )
58     done
59 abate 121
60 abate 136 let print ppf d =
61     Format.fprintf ppf "%a@\n" print d;
62     dump_print ppf
63 abate 121
64 abate 136
65 abate 95 let counter = State.ref "Patterns.counter" 0
66 abate 1
67 abate 95 let make fv =
68     incr counter;
69     { id = !counter; descr = None; accept = Types.make (); fv = fv }
70    
71 abate 1 let define x ((accept,fv,_) as d) =
72     assert (x.fv = fv);
73     Types.define x.accept accept;
74     x.descr <- Some d
75    
76 abate 225 let constr x = (x,IdSet.empty,Constr x)
77 abate 1 let cup ((acc1,fv1,_) as x1) ((acc2,fv2,_) as x2) =
78 abate 225 if not (IdSet.equal fv1 fv2) then (
79     let x = match IdSet.pick (IdSet.diff fv1 fv2) with
80     | Some x -> x
81     | None -> match IdSet.pick (IdSet.diff fv2 fv1) with Some x -> x
82     | None -> assert false
83 abate 107 in
84     raise
85     (Error
86 abate 225 ("The capture variable " ^ (Id.value x) ^
87 abate 107 " should appear on both side of this | pattern"))
88     );
89 abate 225 (Types.cup acc1 acc2, IdSet.cup fv1 fv2, Cup (x1,x2))
90 abate 121 let cap ((acc1,fv1,_) as x1) ((acc2,fv2,_) as x2) =
91 abate 225 if not (IdSet.disjoint fv1 fv2) then (
92     match IdSet.pick (IdSet.cap fv1 fv2) with
93     | Some x ->
94 abate 107 raise
95     (Error
96 abate 225 ("The capture variable " ^ (Id.value x) ^
97 abate 107 " cannot appear on both side of this & pattern"))
98 abate 225 | None -> assert false
99 abate 107 );
100 abate 225 (Types.cap acc1 acc2, IdSet.cup fv1 fv2, Cap (x1,x2))
101 abate 1 let times x y =
102 abate 225 (Types.times x.accept y.accept, IdSet.cup x.fv y.fv, Times (x,y))
103 abate 110 let xml x y =
104 abate 225 (Types.xml x.accept y.accept, IdSet.cup x.fv y.fv, Xml (x,y))
105 abate 1 let record l x =
106 abate 229 (Types.record l x.accept, x.fv, Record (l,x))
107 abate 225 let capture x = (Types.any, IdSet.singleton x, Capture x)
108     let constant x c = (Types.any, IdSet.singleton x, Constant (x,c))
109 abate 1
110    
111    
112    
113     (* Static semantics *)
114    
115     let cup_res v1 v2 = Types.Positive.cup [v1;v2]
116 abate 225 let empty_res fv = IdMap.constant (Types.Positive.ty Types.empty) fv
117 abate 1 let times_res v1 v2 = Types.Positive.times v1 v2
118    
119     module MemoFilter = Map.Make
120     (struct type t = Types.descr * node let compare = compare end)
121    
122     let memo_filter = ref MemoFilter.empty
123    
124 abate 225 let rec filter_descr t (_,fv,d) : Types.Positive.v id_map =
125 abate 121 (* TODO: avoid is_empty t when t is not changing (Cap) *)
126 abate 1 if Types.is_empty t
127     then empty_res fv
128     else
129     match d with
130 abate 225 | Constr _ -> IdMap.empty
131 abate 1 | Cup ((a,_,_) as d1,d2) ->
132 abate 225 IdMap.merge cup_res
133 abate 1 (filter_descr (Types.cap t a) d1)
134     (filter_descr (Types.diff t a) d2)
135 abate 121 | Cap (d1,d2) ->
136 abate 225 IdMap.merge cup_res (filter_descr t d1) (filter_descr t d2)
137 abate 110 | Times (p1,p2) -> filter_prod fv p1 p2 t
138     | Xml (p1,p2) -> filter_prod ~kind:`XML fv p1 p2 t
139 abate 1 | Record (l,p) ->
140     filter_node (Types.Record.project t l) p
141     | Capture c ->
142 abate 225 IdMap.singleton c (Types.Positive.ty t)
143 abate 1 | Constant (c, cst) ->
144 abate 225 IdMap.singleton c (Types.Positive.ty (Types.constant cst))
145 abate 1
146 abate 110 and filter_prod ?kind fv p1 p2 t =
147     List.fold_left
148     (fun accu (d1,d2) ->
149     let term =
150 abate 225 IdMap.merge times_res (filter_node d1 p1) (filter_node d2 p2)
151 abate 110 in
152 abate 225 IdMap.merge cup_res accu term
153 abate 110 )
154     (empty_res fv)
155     (Types.Product.normal ?kind t)
156    
157    
158 abate 225 and filter_node t p : Types.Positive.v id_map =
159 abate 1 try MemoFilter.find (t,p) !memo_filter
160     with Not_found ->
161     let (_,fv,_) as d = descr p in
162 abate 225 let res = IdMap.map_from_slist (fun _ -> Types.Positive.forward ()) fv in
163 abate 1 memo_filter := MemoFilter.add (t,p) res !memo_filter;
164     let r = filter_descr t (descr p) in
165 abate 225 IdMap.collide Types.Positive.define res r;
166 abate 1 r
167    
168     let filter t p =
169     let r = filter_node t p in
170     memo_filter := MemoFilter.empty;
171 abate 225 IdMap.get (IdMap.map Types.Positive.solve r)
172 abate 1
173    
174     (* Normal forms for patterns and compilation *)
175    
176 abate 229 let min (a:int) (b:int) = if a < b then a else b
177    
178 abate 149 module Normal : sig
179     type 'a sl = 'a SortedList.t
180     type ('a,'b) sm = ('a,'b) SortedMap.t
181    
182     type source =
183 abate 172 | SCatch | SConst of Types.const
184     | SLeft | SRight | SRecompose
185 abate 225 type result = source id_map
186 abate 149
187     type nnf = node sl * Types.descr
188     type 'a nline = (result * 'a) list
189     type record =
190 abate 230 | RecNolabel of result option * result option
191 abate 233 | RecLabel of label * (nnf * nnf) nline
192 abate 149 type t = {
193     nfv : fv;
194     ncatchv: fv;
195     na : Types.descr;
196     nbasic : Types.descr nline;
197     nprod : (nnf * nnf) nline;
198     nxml : (nnf * nnf) nline;
199 abate 229 nrecord: record;
200 abate 149 }
201    
202     val any_basic: Types.descr
203 abate 233 val first_label: descr -> label
204     val normal: label option -> Types.descr -> node list -> t
205 abate 149 end =
206 abate 1 struct
207 abate 229 let any_basic =
208     Types.Record.or_absent
209     (Types.neg (List.fold_left Types.cup Types.empty
210     [Types.Product.any_xml;
211     Types.Product.any;
212     Types.Record.any]))
213 abate 172
214    
215 abate 1 type 'a sl = 'a SortedList.t
216     type ('a,'b) sm = ('a,'b) SortedMap.t
217    
218     type source =
219 abate 172 | SCatch | SConst of Types.const
220     | SLeft | SRight | SRecompose
221 abate 225 type result = source id_map
222 abate 1
223 abate 149 type nnf = node sl * Types.descr (* pl,t; t <= \accept{pl} *)
224     type 'a nline = (result * 'a) sl
225 abate 39 type record =
226 abate 230 | RecNolabel of result option * result option
227 abate 233 | RecLabel of label * (nnf * nnf) nline
228 abate 43 type t = {
229 abate 42 nfv : fv;
230 abate 57 ncatchv: fv;
231 abate 42 na : Types.descr;
232 abate 39 nbasic : Types.descr nline;
233 abate 148 nprod : (nnf * nnf) nline;
234     nxml : (nnf * nnf) nline;
235 abate 229 nrecord: record
236 abate 39 }
237    
238 abate 172
239 abate 225 let fus = IdMap.union_disj
240 abate 165 let slcup = SortedList.cup
241 abate 172
242 abate 229 let nempty lab =
243     { nfv = IdSet.empty; ncatchv = IdSet.empty;
244     na = Types.empty;
245     nbasic = []; nprod = []; nxml = [];
246     nrecord = (match lab with
247 abate 230 | Some l -> RecLabel (l,[])
248     | None -> RecNolabel (None,None))
249 abate 229 }
250 abate 149
251    
252     let ncup nf1 nf2 =
253     (* assert (Types.is_empty (Types.cap nf1.na nf2.na)); *)
254     (* assert (nf1.nfv = nf2.nfv); *)
255     { nfv = nf1.nfv;
256 abate 225 ncatchv = IdSet.cap nf1.ncatchv nf2.ncatchv;
257 abate 149 na = Types.cup nf1.na nf2.na;
258     nbasic = SortedList.cup nf1.nbasic nf2.nbasic;
259     nprod = SortedList.cup nf1.nprod nf2.nprod;
260     nxml = SortedList.cup nf1.nxml nf2.nxml;
261 abate 229 nrecord = (match (nf1.nrecord,nf2.nrecord) with
262 abate 230 | RecLabel (l1,r1), RecLabel (l2,r2) ->
263     assert (l1 = l2); RecLabel (l1, slcup r1 r2)
264     | RecNolabel (x1,y1), RecNolabel (x2,y2) ->
265     RecNolabel((if x1 = None then x2 else x1),
266 abate 229 (if y1 = None then y2 else y1))
267     | _ -> assert false)
268 abate 149 }
269    
270     let double_fold f l1 l2 =
271     SortedList.from_list
272     (List.fold_left
273     (fun accu x1 ->
274     List.fold_left
275     (fun accu x2 ->
276     f accu x1 x2
277     )
278     accu l2
279     ) [] l1)
280    
281     let ncap nf1 nf2 =
282     let prod accu (res1,((pl1,t1),(ql1,s1))) (res2,((pl2,t2),(ql2,s2))) =
283     let t = Types.cap t1 t2 in
284     if Types.is_empty t then accu else
285     let s = Types.cap s1 s2 in
286     if Types.is_empty s then accu else
287     (fus res1 res2, ((slcup pl1 pl2,t),(slcup ql1 ql2,s))) :: accu
288     in
289     let basic accu (res1,t1) (res2,t2) =
290     let t = Types.cap t1 t2 in
291     if Types.is_empty t then accu else
292     (fus res1 res2, t) :: accu
293     in
294 abate 229 let do_record r1 r2 = match r1,r2 with
295 abate 230 | RecLabel (l1,r1), RecLabel (l2,r2) ->
296 abate 229 assert (l1 = l2);
297 abate 230 RecLabel(l1, double_fold prod r1 r2)
298     | RecNolabel (x1,y1), RecNolabel (x2,y2) ->
299 abate 229 let x = match x1,x2 with
300     | Some res1, Some res2 -> Some (fus res1 res2)
301     | _ -> None
302     and y = match y1,y2 with
303     | Some res1, Some res2 -> Some (fus res1 res2)
304     | _ -> None in
305 abate 230 RecNolabel (x,y)
306 abate 229 | _ -> assert false
307 abate 172 in
308 abate 225 { nfv = IdSet.cup nf1.nfv nf2.nfv;
309     ncatchv = IdSet.cup nf1.ncatchv nf2.ncatchv;
310 abate 149 na = Types.cap nf1.na nf2.na;
311     nbasic = double_fold basic nf1.nbasic nf2.nbasic;
312     nprod = double_fold prod nf1.nprod nf2.nprod;
313     nxml = double_fold prod nf1.nxml nf2.nxml;
314 abate 229 nrecord = do_record nf1.nrecord nf2.nrecord;
315 abate 149 }
316    
317 abate 172 let nnode p = [p], Types.descr p.accept
318 abate 225 let empty_res = IdMap.empty
319 abate 172
320 abate 229 let ntimes lab acc p q =
321 abate 225 let src_p = IdMap.constant SLeft p.fv
322     and src_q = IdMap.constant SRight q.fv in
323     let src = IdMap.merge_elem SRecompose src_p src_q in
324 abate 229 { nempty lab with
325 abate 225 nfv = IdSet.cup p.fv q.fv;
326 abate 149 na = acc;
327 abate 172 nprod = [ (src, (nnode p, nnode q)) ];
328 abate 149 }
329 abate 172
330 abate 229 let nxml lab acc p q =
331 abate 225 let src_p = IdMap.constant SLeft p.fv
332     and src_q = IdMap.constant SRight q.fv in
333     let src = IdMap.merge_elem SRecompose src_p src_q in
334 abate 229 { nempty lab with
335 abate 225 nfv = IdSet.cup p.fv q.fv;
336 abate 172 na = acc;
337     nxml = [ (src, (nnode p, nnode q)) ];
338     }
339 abate 149
340 abate 229 let nrecord lab acc l p =
341     match lab with
342     | None -> assert false
343     | Some label ->
344     (* Printf.eprintf "[ l = %s; label = %s ]\n"
345 abate 233 (LabelPool.value l)
346     (LabelPool.value label); *)
347 abate 229 assert (label <= l);
348     if l == label then
349     let src = IdMap.constant SLeft p.fv in
350     { nempty lab with
351     nfv = p.fv;
352     na = acc;
353 abate 230 nrecord = RecLabel(label,
354 abate 229 [ (src,(nnode p, ([], Types.any))) ])}
355     else
356     let src = IdMap.constant SRight p.fv in
357     let p' = make p.fv in (* optimize this ... *)
358     (* cache the results to avoid looping ... *)
359     define p' (record l p);
360     { nempty lab with
361     nfv = p.fv;
362     na = acc;
363 abate 230 nrecord = RecLabel(label,
364 abate 229 [ (src,(([], Types.Record.any_or_absent),
365     nnode p')) ])}
366    
367 abate 149
368 abate 229 let nconstr lab t =
369     let aux = List.map (fun (t1,t2) -> empty_res, (([],t1),([],t2))) in
370     let record =
371     match lab with
372     | None ->
373     let (x,y) = Types.Record.empty_cases t in
374 abate 230 RecNolabel ((if x then Some empty_res else None),
375 abate 229 (if y then Some empty_res else None))
376     | Some l ->
377 abate 230 RecLabel (l,aux (Types.Record.split_normal t l))
378 abate 229 in
379     { nempty lab with
380 abate 172 na = t;
381 abate 225 nbasic = [ empty_res, Types.cap t any_basic ];
382 abate 229 nprod = aux (Types.Product.normal t);
383     nxml = aux (Types.Product.normal ~kind:`XML t);
384     nrecord = record
385 abate 172 }
386    
387 abate 229 let nconstant lab x c =
388 abate 225 let l = IdMap.singleton x (SConst c) in
389     { nfv = IdSet.singleton x;
390     ncatchv = IdSet.empty;
391 abate 172 na = Types.any;
392     nbasic = [ (l,any_basic) ];
393     nprod = [ (l,(([], Types.any),([], Types.any))) ];
394     nxml = [ (l,(([], Types.any),([], Types.any))) ];
395 abate 229 nrecord = match lab with
396 abate 230 | None -> RecNolabel (Some l, Some l)
397 abate 229 | Some lab ->
398 abate 230 RecLabel (lab, [ (l,(([], Types.Record.any_or_absent),
399 abate 229 ([], Types.any))) ])
400 abate 172 }
401    
402 abate 229 let ncapture lab x =
403 abate 225 let l = IdMap.singleton x SCatch in
404     { nfv = IdSet.singleton x;
405     ncatchv = IdSet.singleton x;
406 abate 172 na = Types.any;
407     nbasic = [ (l,any_basic) ];
408     nprod = [ (l,(([], Types.any),([], Types.any))) ];
409     nxml = [ (l,(([], Types.any),([], Types.any))) ];
410 abate 229 nrecord = match lab with
411 abate 230 | None -> RecNolabel (Some l, Some l)
412 abate 229 | Some lab ->
413 abate 230 RecLabel (lab, [ (l,(([], Types.Record.any_or_absent),([], Types.any))) ])
414 abate 172 }
415    
416 abate 229 let rec nnormal lab (acc,fv,d) =
417 abate 172 if Types.is_empty acc
418 abate 229 then nempty lab
419 abate 172 else match d with
420 abate 229 | Constr t -> nconstr lab t
421     | Cap (p,q) -> ncap (nnormal lab p) (nnormal lab q)
422 abate 172 | Cup ((acc1,_,_) as p,q) ->
423 abate 229 ncup (nnormal lab p) (ncap (nnormal lab q)
424     (nconstr lab (Types.neg acc1)))
425     | Times (p,q) -> ntimes lab acc p q
426     | Xml (p,q) -> nxml lab acc p q
427     | Capture x -> ncapture lab x
428     | Constant (x,c) -> nconstant lab x c
429     | Record (l,p) -> nrecord lab acc l p
430    
431     (*TODO: when an operand of Cap has its first_label > lab,
432     directly shift it*)
433    
434     let rec first_label (acc,fv,d) =
435     if Types.is_empty acc
436 abate 233 then LabelPool.dummy_max
437 abate 229 else match d with
438     | Constr t -> Types.Record.first_label t
439     | Cap (p,q) -> min (first_label p) (first_label q)
440     | Cup ((acc1,_,_) as p,q) -> min (first_label p) (first_label q)
441     (* should "first_label_type acc1" ? *)
442     | Record (l,p) -> l
443 abate 233 | _ -> LabelPool.dummy_max
444 abate 229
445 abate 172
446     let remove_catchv n =
447     let ncv = n.ncatchv in
448     let nlines l =
449 abate 225 let l = List.map (fun (res,x) -> (IdMap.diff res ncv,x)) l in
450 abate 172 (* let l = SortedList.from_list l in (* Can get rid of it ? *) *)
451     l in
452 abate 225 { nfv = IdSet.diff n.nfv ncv;
453 abate 172 ncatchv = n.ncatchv;
454     na = n.na;
455     nbasic = nlines n.nbasic;
456     nprod = nlines n.nprod;
457     nxml = nlines n.nxml;
458 abate 229 nrecord = (match n.nrecord with
459 abate 230 | RecNolabel (x,y) ->
460 abate 229 let x = match x with
461     | Some res -> Some (IdMap.diff res ncv)
462     | None -> None in
463     let y = match y with
464     | Some res -> Some (IdMap.diff res ncv)
465     | None -> None in
466 abate 230 RecNolabel (x,y)
467     | RecLabel (lab,l) -> RecLabel (lab, nlines l))
468 abate 172 }
469    
470 abate 229 let normal l t pl =
471 abate 172 remove_catchv
472 abate 229 (List.fold_left
473     (fun a p -> ncap a (nnormal l (descr p)))
474     (nconstr l t)
475     pl)
476 abate 43 end
477 abate 42
478    
479 abate 43 module Compile =
480     struct
481 abate 56 type actions =
482 abate 172 | AIgnore of result
483     | AKind of actions_kind
484 abate 56 and actions_kind = {
485 abate 43 basic: (Types.descr * result) list;
486     prod: result dispatch dispatch;
487 abate 110 xml: result dispatch dispatch;
488 abate 43 record: record option;
489     }
490     and record =
491 abate 233 | RecLabel of label * result dispatch dispatch
492 abate 230 | RecNolabel of result option * result option
493 abate 42
494 abate 45 and 'a dispatch =
495 abate 172 | Dispatch of dispatcher * 'a array
496     | TailCall of dispatcher
497     | Ignore of 'a
498     | Impossible
499 abate 45
500     and result = int * source array
501 abate 43 and source =
502 abate 172 | Catch | Const of Types.const
503     | Left of int | Right of int | Recompose of int * int
504 abate 43
505     and return_code =
506     Types.descr * int * (* accepted type, arity *)
507 abate 225 (int * int id_map) list
508 abate 42
509 abate 43 and interface =
510 abate 147 [ `Result of int
511     | `Switch of interface * interface
512 abate 43 | `None ]
513 abate 42
514 abate 43 and dispatcher = {
515     id : int;
516     t : Types.descr;
517     pl : Normal.t array;
518 abate 233 label : label option;
519 abate 43 interface : interface;
520     codes : return_code array;
521 abate 226 mutable actions : actions option;
522     mutable printed : bool
523 abate 43 }
524 abate 45
525     let array_for_all f a =
526     let rec aux f a i =
527     if i = Array.length a then true
528     else f a.(i) && (aux f a (succ i))
529     in
530     aux f a 0
531    
532     let array_for_all_i f a =
533     let rec aux f a i =
534     if i = Array.length a then true
535     else f i a.(i) && (aux f a (succ i))
536     in
537     aux f a 0
538    
539 abate 110 let combine_kind basic prod xml record =
540 abate 56 try (
541     let rs = [] in
542     let rs = match basic with
543     | [_,r] -> r :: rs
544     | [] -> rs
545     | _ -> raise Exit in
546     let rs = match prod with
547 abate 172 | Impossible -> rs
548     | Ignore (Ignore r) -> r :: rs
549 abate 56 | _ -> raise Exit in
550 abate 110 let rs = match xml with
551 abate 172 | Impossible -> rs
552     | Ignore (Ignore r) -> r :: rs
553 abate 110 | _ -> raise Exit in
554 abate 56 let rs = match record with
555     | None -> rs
556 abate 230 | Some (RecLabel (_,Ignore (Ignore r))) -> r :: rs
557     | Some (RecNolabel (Some r1, Some r2)) -> r1 :: r2 :: rs
558 abate 56 | _ -> raise Exit in
559     match rs with
560 abate 57 | ((_, ret) as r) :: rs when
561     List.for_all ( (=) r ) rs
562     && array_for_all
563 abate 172 (function Catch | Const _ -> true | _ -> false) ret
564     -> AIgnore r
565 abate 56 | _ -> raise Exit
566     )
567 abate 172 with Exit -> AKind { basic = basic; prod = prod; xml = xml; record = record }
568 abate 56
569 abate 46 let combine (disp,act) =
570 abate 172 if Array.length act = 0 then Impossible
571 abate 45 else
572     if (array_for_all (fun (_,ar,_) -> ar = 0) disp.codes)
573     && (array_for_all ( (=) act.(0) ) act) then
574 abate 172 Ignore act.(0)
575 abate 45 else
576 abate 172 Dispatch (disp, act)
577 abate 45
578    
579     let detect_right_tail_call = function
580 abate 172 | Dispatch (disp,branches)
581 abate 45 when
582     array_for_all_i
583     (fun i (code,ret) ->
584     (i = code) &&
585     (array_for_all_i
586     (fun pos ->
587 abate 172 function Right j when pos = j -> true | _ -> false)
588 abate 45 ret
589     )
590     ) branches
591 abate 172 -> TailCall disp
592 abate 45 | x -> x
593    
594     let detect_left_tail_call = function
595 abate 172 | Dispatch (disp,branches)
596 abate 45 when
597     array_for_all_i
598     (fun i ->
599     function
600 abate 172 | Ignore (code,ret) ->
601 abate 45 (i = code) &&
602     (array_for_all_i
603     (fun pos ->
604 abate 172 function Left j when pos = j -> true | _ -> false)
605 abate 45 ret
606     )
607     | _ -> false
608     ) branches
609     ->
610 abate 172 TailCall disp
611 abate 45 | x -> x
612    
613 abate 95 let cur_id = State.ref "Patterns.cur_id" 0
614     (* TODO: save dispatchers ? *)
615 abate 43
616 abate 42 module DispMap = Map.Make(
617     struct
618 abate 43 type t = Types.descr * Normal.t array
619 abate 42 let compare = compare
620     end
621     )
622 abate 43
623 abate 42 let dispatchers = ref DispMap.empty
624 abate 43
625 abate 229 let dispatcher t pl lab : dispatcher =
626 abate 42 try DispMap.find (t,pl) !dispatchers
627     with Not_found ->
628 abate 43 let nb = ref 0 in
629 abate 147 let codes = ref [] in
630     let rec aux t arity i accu =
631 abate 43 if Types.is_empty t then `None
632     else
633 abate 42 if i = Array.length pl
634 abate 147 then (incr nb; codes := (t,arity,accu)::!codes; `Result (!nb - 1))
635 abate 42 else
636     let p = pl.(i) in
637 abate 43 let tp = p.Normal.na in
638 abate 225 assert(IdSet.disjoint p.Normal.nfv p.Normal.ncatchv);
639     let v = p.Normal.nfv in
640     (* let v = IdSet.diff p.Normal.nfv p.Normal.ncatchv in*)
641    
642 abate 52 (* let tp = Types.normalize tp in *)
643 abate 225 let accu' = (i,IdMap.num arity v) :: accu in
644 abate 43 `Switch
645 abate 147 (
646 abate 225 aux (Types.cap t tp) (arity + (IdSet.length v)) (i+1) accu',
647 abate 147 aux (Types.diff t tp) arity (i+1) accu
648 abate 43 )
649 abate 42 in
650 abate 147 let iface = aux t 0 0 [] in
651 abate 42 let res = { id = !cur_id;
652     t = t;
653 abate 229 label = lab;
654 abate 42 pl = pl;
655 abate 43 interface = iface;
656 abate 147 codes = Array.of_list (List.rev !codes);
657 abate 226 actions = None; printed = false } in
658 abate 42 incr cur_id;
659     dispatchers := DispMap.add (t,pl) res !dispatchers;
660     res
661    
662 abate 43 let find_code d a =
663     let rec aux i = function
664 abate 147 | `Result code -> code
665     | `None -> assert false
666     | `Switch (yes,_) when a.(i) <> None -> aux (i + 1) yes
667     | `Switch (_,no) -> aux (i + 1) no
668 abate 43 in
669     aux 0 d.interface
670 abate 42
671 abate 43 let create_result pl =
672 abate 166 let aux x accu = match x with Some b -> b @ accu | None -> accu in
673     Array.of_list (Array.fold_right aux pl [])
674 abate 43
675     let return disp pl f =
676     let aux = function [x] -> Some (f x) | [] -> None | _ -> assert false in
677     let final = Array.map aux pl in
678     (find_code disp final, create_result final)
679    
680 abate 225 let conv_source_basic s = match s with
681 abate 172 | Normal.SCatch -> Catch
682     | Normal.SConst c -> Const c
683 abate 42 | _ -> assert false
684    
685 abate 57 let assoc v l =
686 abate 225 try IdMap.assoc v l with Not_found -> -1
687 abate 57
688 abate 225 let conv_source_prod left right v s = match s with
689 abate 172 | Normal.SCatch -> Catch
690     | Normal.SConst c -> Const c
691     | Normal.SLeft -> Left (assoc v left)
692     | Normal.SRight -> Right (assoc v right)
693     | Normal.SRecompose -> Recompose (assoc v left, assoc v right)
694 abate 42
695 abate 43 let dispatch_basic disp : (Types.descr * result) list =
696 abate 147 (* TODO: try other algo, using disp.codes .... *)
697 abate 43 let pl = Array.map (fun p -> p.Normal.nbasic) disp.pl in
698     let tests =
699     let accu = ref [] in
700     let aux i (res,x) = accu := (x, [i,res]) :: !accu in
701     Array.iteri (fun i -> List.iter (aux i)) pl;
702     SortedMap.from_list SortedList.cup !accu in
703    
704     let t = Types.cap Normal.any_basic disp.t in
705 abate 42 let accu = ref [] in
706 abate 43 let rec aux (success : (int * Normal.result) list) t l =
707 abate 42 if Types.non_empty t
708     then match l with
709     | [] ->
710 abate 43 let selected = Array.create (Array.length pl) [] in
711     let add (i,res) = selected.(i) <- res :: selected.(i) in
712     List.iter add success;
713    
714 abate 225 let aux_final res = IdMap.map_to_list conv_source_basic res in
715 abate 43 accu := (t, return disp selected aux_final) :: !accu
716     | (ty,i) :: rem ->
717     aux (i @ success) (Types.cap t ty) rem;
718     aux success (Types.diff t ty) rem
719 abate 42 in
720 abate 43 aux [] t tests;
721 abate 42 !accu
722    
723    
724 abate 45 let get_tests pl f t d post =
725 abate 42 let accu = ref [] in
726     let unselect = Array.create (Array.length pl) [] in
727     let aux i x =
728     let yes, no = f x in
729 abate 229 List.iter (fun ( (pl,ty), info) -> accu := (ty,pl,i,info) :: !accu
730 abate 42 ) yes;
731     unselect.(i) <- no @ unselect.(i) in
732     Array.iteri (fun i -> List.iter (aux i)) pl;
733 abate 52
734 abate 229 let lab =
735     List.fold_left
736     (fun l (ty,pl,_,_) ->
737     List.fold_left
738     (fun l p -> min l (Normal.first_label (descr p)))
739     (min l (Types.Record.first_label ty))
740     pl
741 abate 233 ) LabelPool.dummy_max !accu in
742     let lab = if lab= LabelPool.dummy_max then None else Some lab in
743 abate 229
744     let accu =
745     List.map (fun (ty,pl,i,info) ->
746     let p = Normal.normal lab ty pl in
747     (p,[i, p.Normal.ncatchv, info]))
748     !accu in
749     let sorted = Array.of_list (SortedMap.from_list SortedList.cup accu) in
750 abate 42 let infos = Array.map snd sorted in
751 abate 229 let disp = dispatcher t (Array.map fst sorted) lab in
752 abate 43 let result (t,_,m) =
753 abate 42 let selected = Array.create (Array.length pl) [] in
754 abate 148 let add r (i, ncv, inf) = selected.(i) <- (r,ncv,inf) :: selected.(i) in
755 abate 43 List.iter (fun (j,r) -> List.iter (add r) infos.(j)) m;
756 abate 42 d t selected unselect
757     in
758 abate 43 let res = Array.map result disp.codes in
759 abate 46 post (disp,res)
760 abate 42
761 abate 71
762 abate 46 let make_branches t brs =
763     let (_,brs) =
764     List.fold_left
765     (fun (t,brs) (p,e) ->
766 abate 149 let p' = ([p],t) in
767 abate 148 let t' = Types.diff t (Types.descr (accept p)) in
768     (t', (p',e) :: brs)
769 abate 46 ) (t,[]) brs in
770 abate 52
771 abate 46 let pl = Array.map (fun x -> [x]) (Array.of_list brs) in
772     get_tests
773     pl
774     (fun x -> [x],[])
775     t
776     (fun _ pl _ ->
777     let r = ref None in
778     let aux = function
779 abate 148 | [(res,catchv,e)] -> assert (!r = None);
780 abate 225 let catchv = IdMap.constant (-1) catchv in
781     r := Some (IdMap.union_disj catchv res,e)
782 abate 46 | [] -> () | _ -> assert false in
783     Array.iter aux pl;
784     let r = match !r with None -> assert false | Some x -> x in
785     r
786     )
787     (fun x -> x)
788 abate 42
789    
790 abate 110 let rec dispatch_prod ?(kind=`Normal) disp =
791     let pl =
792     match kind with
793     | `Normal -> Array.map (fun p -> p.Normal.nprod) disp.pl
794     | `XML -> Array.map (fun p -> p.Normal.nxml) disp.pl
795     in
796     let t = Types.Product.get ~kind disp.t in
797 abate 229 dispatch_prod0 disp t pl
798     and dispatch_prod0 disp t pl =
799 abate 42 get_tests pl
800     (fun (res,(p,q)) -> [p, (res,q)], [])
801     (Types.Product.pi1 t)
802     (dispatch_prod1 disp t)
803 abate 46 (fun x -> detect_left_tail_call (combine x))
804 abate 42 and dispatch_prod1 disp t t1 pl _ =
805     get_tests pl
806 abate 148 (fun (ret1, ncatchv, (res,q)) -> [q, (ret1,res)], [] )
807 abate 229 (Types.Product.pi2_restricted t1 t)
808     (dispatch_prod2 disp)
809 abate 46 (fun x -> detect_right_tail_call (combine x))
810 abate 229 and dispatch_prod2 disp t2 pl _ =
811 abate 148 let aux_final (ret2, ncatchv, (ret1, res)) =
812 abate 225 IdMap.mapi_to_list (conv_source_prod ret1 ret2) res in
813 abate 43 return disp pl aux_final
814 abate 42
815    
816     let rec dispatch_record disp : record option =
817 abate 229 let t = disp.t in
818     if not (Types.Record.has_record t) then None
819     else
820     match disp.label with
821     | None ->
822     let (some,none) = Types.Record.empty_cases t in
823     let some =
824     if some then
825     let pl = Array.map (fun p -> match p.Normal.nrecord with
826 abate 230 | Normal.RecNolabel (Some x,_) -> [x]
827     | Normal.RecNolabel (None,_) -> []
828 abate 229 | _ -> assert false) disp.pl in
829     Some (return disp pl (IdMap.map_to_list conv_source_basic))
830     else None
831     in
832     let none =
833     if none then
834     let pl = Array.map (fun p -> match p.Normal.nrecord with
835 abate 230 | Normal.RecNolabel (_,Some x) -> [x]
836     | Normal.RecNolabel (_,None) -> []
837 abate 229 | _ -> assert false) disp.pl in
838     Some (return disp pl (IdMap.map_to_list conv_source_basic))
839     else None
840     in
841 abate 230 Some (RecNolabel (some,none))
842 abate 229 | Some lab ->
843     let t = Types.Record.split t lab in
844     let pl = Array.map (fun p -> match p.Normal.nrecord with
845 abate 230 | Normal.RecLabel (_,l) -> l
846 abate 229 | _ -> assert false) disp.pl in
847 abate 230 Some (RecLabel (lab,dispatch_prod0 disp t pl))
848 abate 229 (* soucis avec les ncatchv ?? *)
849 abate 119
850 abate 75
851 abate 42 let actions disp =
852     match disp.actions with
853     | Some a -> a
854     | None ->
855 abate 56 let a = combine_kind
856     (dispatch_basic disp)
857     (dispatch_prod disp)
858 abate 110 (dispatch_prod ~kind:`XML disp)
859 abate 56 (dispatch_record disp)
860     in
861 abate 42 disp.actions <- Some a;
862     a
863    
864     let to_print = ref []
865    
866 abate 226 module DSET = Set.Make (struct type t = int let compare (x:t) (y:t) = x - y end)
867     let printed = ref DSET.empty
868    
869 abate 42 let queue d =
870 abate 226 if not d.printed then (
871     d.printed <- true;
872 abate 42 to_print := d :: !to_print
873     )
874    
875 abate 57 let rec print_source ppf = function
876 abate 172 | Catch -> Format.fprintf ppf "v"
877     | Const c -> Types.Print.print_const ppf c
878     | Left (-1) -> Format.fprintf ppf "v1"
879     | Right (-1) -> Format.fprintf ppf "v2"
880     | Left i -> Format.fprintf ppf "l%i" i
881     | Right j -> Format.fprintf ppf "r%i" j
882     | Recompose (i,j) ->
883 abate 57 Format.fprintf ppf "(%a,%a)"
884 abate 172 print_source (Left i)
885     print_source (Right j)
886 abate 56
887     let print_result ppf =
888     Array.iteri
889     (fun i s ->
890     if i > 0 then Format.fprintf ppf ",";
891     print_source ppf s;
892     )
893    
894     let print_ret ppf (code,ret) =
895     Format.fprintf ppf "$%i" code;
896     if Array.length ret <> 0 then
897     Format.fprintf ppf "(%a)" print_result ret
898    
899 abate 229 let print_ret_opt ppf = function
900     | None -> Format.fprintf ppf "*"
901     | Some r -> print_ret ppf r
902    
903 abate 56 let print_kind ppf actions =
904 abate 42 let print_lhs ppf (code,prefix,d) =
905 abate 43 let arity = match d.codes.(code) with (_,a,_) -> a in
906 abate 42 Format.fprintf ppf "$%i(" code;
907     for i = 0 to arity - 1 do
908     if i > 0 then Format.fprintf ppf ",";
909     Format.fprintf ppf "%s%i" prefix i;
910     done;
911     Format.fprintf ppf ")" in
912     let print_basic (t,ret) =
913 abate 43 Format.fprintf ppf " | %a -> %a@\n"
914 abate 42 Types.Print.print_descr t
915     print_ret ret
916     in
917 abate 45 let print_prod2 = function
918 abate 172 | Impossible -> assert false
919     | Ignore r ->
920 abate 45 Format.fprintf ppf " %a\n"
921     print_ret r
922 abate 172 | TailCall d ->
923 abate 45 queue d;
924     Format.fprintf ppf " disp_%i v2@\n" d.id
925 abate 172 | Dispatch (d, branches) ->
926 abate 45 queue d;
927     Format.fprintf ppf " match v2 with disp_%i@\n" d.id;
928     Array.iteri
929     (fun code r ->
930     Format.fprintf ppf " | %a -> %a\n"
931     print_lhs (code, "r", d)
932     print_ret r;
933     )
934     branches
935 abate 42 in
936 abate 229 let print_prod prefix ppf = function
937 abate 172 | Impossible -> ()
938     | Ignore d2 ->
939 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
940 abate 45 print_prod2 d2
941 abate 172 | TailCall d ->
942 abate 45 queue d;
943 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
944 abate 45 Format.fprintf ppf " disp_%i v1@\n" d.id
945 abate 172 | Dispatch (d,branches) ->
946 abate 45 queue d;
947 abate 110 Format.fprintf ppf " | %s(v1,v2) -> @\n" prefix;
948 abate 45 Format.fprintf ppf " match v1 with disp_%i@\n" d.id;
949     Array.iteri
950     (fun code d2 ->
951     Format.fprintf ppf " | %a -> @\n"
952     print_lhs (code, "l", d);
953     print_prod2 d2;
954     )
955     branches
956 abate 42 in
957     let rec print_record_opt ppf = function
958     | None -> ()
959     | Some r ->
960     Format.fprintf ppf " | Record -> @\n";
961     Format.fprintf ppf " @[%a@]@\n" print_record r
962     and print_record ppf = function
963 abate 230 | RecNolabel (r1,r2) ->
964 abate 168 Format.fprintf ppf "SomeField:%a;NoField:%a"
965 abate 229 print_ret_opt r1 print_ret_opt r2
966 abate 230 | RecLabel (l, d) ->
967 abate 233 let l = LabelPool.value l in
968 abate 45 Format.fprintf ppf "check label %s:@\n" l;
969 abate 229 Format.fprintf ppf "Present => @[%a@]@\n" (print_prod "record") d
970 abate 42 in
971    
972     List.iter print_basic actions.basic;
973 abate 229 print_prod "" ppf actions.prod;
974     print_prod "XML" ppf actions.xml;
975 abate 42 print_record_opt ppf actions.record
976    
977 abate 56 let print_actions ppf = function
978 abate 172 | AKind k -> print_kind ppf k
979     | AIgnore r -> Format.fprintf ppf "v -> %a@\n" print_ret r
980 abate 56
981 abate 229 let print_dispatcher ppf d =
982     (* Format.fprintf ppf "Dispatcher %i accepts [%a]@\n"
983     d.id Types.Print.print_descr (Types.normalize d.t);
984     let print_code code (t, arity, m) =
985     Format.fprintf ppf " Returns $%i(arity=%i) for [%a]"
986     code arity
987     Types.Print.print_descr (Types.normalize t);
988     (*
989     List.iter
990     (fun (i,b) ->
991     Format.fprintf ppf "[%i:" i;
992     List.iter
993     (fun (v,i) -> Format.fprintf ppf "%s=>%i;" v i)
994     b;
995     Format.fprintf ppf "]"
996     ) m; *)
997    
998     Format.fprintf ppf "@\n";
999     in
1000     Array.iteri print_code d.codes; *)
1001     Format.fprintf ppf "let disp_%i = function@\n" d.id;
1002     print_actions ppf (actions d);
1003     Format.fprintf ppf "====================================@\n"
1004    
1005    
1006 abate 42 let rec print_dispatchers ppf =
1007     match !to_print with
1008     | [] -> ()
1009 abate 229 | d :: rem ->
1010     to_print := rem;
1011     print_dispatcher ppf d;
1012 abate 42 print_dispatchers ppf
1013    
1014 abate 229
1015     let show ppf t pl lab =
1016     let disp = dispatcher t pl lab in
1017 abate 42 queue disp;
1018     print_dispatchers ppf
1019    
1020 abate 149 let debug_compile ppf t pl =
1021     let t = Types.descr t in
1022 abate 229 let lab =
1023     List.fold_left
1024     (fun l p -> min l (Normal.first_label (descr p)))
1025     (Types.Record.first_label t) pl in
1026 abate 233 let lab = if lab= LabelPool.dummy_max then None else Some lab in
1027 abate 229
1028     let pl = Array.of_list
1029     (List.map (fun p -> Normal.normal lab Types.Record.any_or_absent [p]) pl) in
1030    
1031     show ppf t pl lab;
1032 abate 172 Format.fprintf ppf "# compiled dispatchers: %i@\n" !cur_id
1033 abate 43 end
1034 abate 42
1035    

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