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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 52 - (hide annotations)
Tue Jul 10 17:01:20 2007 UTC (5 years, 11 months ago) by abate
File size: 24522 byte(s)
[r2002-10-26 20:45:22 by cvscast] Empty log message

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

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