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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 119 - (hide annotations)
Tue Jul 10 17:07:48 2007 UTC (5 years, 10 months ago) by abate
File size: 30760 byte(s)
[r2002-11-11 23:10:17 by cvscast] Empty log message

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

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