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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations)
Tue Jul 10 17:00:48 2007 UTC (5 years, 11 months ago) by abate
File size: 24477 byte(s)
[r2002-10-26 17:05:30 by cvscast] Evaluateur tourne !

Original author: cvscast
Date: 2002-10-26 17:05:31+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     `Switch
455     (num arity v,
456     aux (Types.cap t tp) (arity + (List.length v)) (i+1),
457     aux (Types.diff t tp) arity (i+1)
458     )
459 abate 42 in
460 abate 43 let iface = aux t 0 0 in
461     let codes = Array.create !nb (Types.empty,0,[]) in
462     let rec aux i accu = function
463     | `None -> ()
464     | `Switch (pos, yes, no) ->
465     aux (i + 1) ((i,pos) :: accu) yes; aux (i + 1) accu no
466     | `Result (code,t,arity) -> codes.(code) <- (t,arity, accu)
467     in
468     aux 0 [] iface;
469 abate 42 let res = { id = !cur_id;
470     t = t;
471     pl = pl;
472 abate 43 interface = iface;
473     codes = codes;
474 abate 42 actions = None } in
475     incr cur_id;
476     dispatchers := DispMap.add (t,pl) res !dispatchers;
477     res
478    
479     let compare_masks a1 a2 =
480     try
481     for i = 0 to Array.length a1 - 1 do
482     match a1.(i),a2.(i) with
483     | None,Some _| Some _, None -> raise Exit
484     | _ -> ()
485     done;
486     true
487     with Exit -> false
488    
489 abate 43 let find_code d a =
490     let rec aux i = function
491     | `Result (code,_,_) -> code
492     | `None -> assert false
493     | `Switch (_,yes,no) ->
494     match a.(i) with Some _ -> aux (i + 1) yes | None -> aux (i + 1) no
495     in
496     aux 0 d.interface
497 abate 42
498 abate 43 let create_result pl =
499 abate 45 Array.of_list (
500     Array.fold_right
501     (fun x accu -> match x with
502     | Some b -> b @ accu
503     | None -> accu)
504     pl []
505     )
506 abate 43
507     let return disp pl f =
508     let aux = function [x] -> Some (f x) | [] -> None | _ -> assert false in
509     let final = Array.map aux pl in
510     (find_code disp final, create_result final)
511    
512     let conv_source_basic (v,s) = match s with
513 abate 42 | (`Catch | `Const _) as x -> x
514     | _ -> assert false
515    
516 abate 43 let conv_source_prod left right (v,s) = match s with
517     | (`Catch | `Const _) as x -> x
518     | `Left -> `Left (List.assoc v left)
519     | `Right -> `Right (List.assoc v right)
520     | `Recompose -> `Recompose (List.assoc v left, List.assoc v right)
521     | _ -> assert false
522 abate 42
523 abate 43 let conv_source_record catch (v,s) = match s with
524     | (`Catch | `Const _) as x -> x
525     | `Field l -> `Field (l, List.assoc v (List.assoc l catch))
526     | _ -> assert false
527    
528    
529     let dispatch_basic disp : (Types.descr * result) list =
530     let pl = Array.map (fun p -> p.Normal.nbasic) disp.pl in
531     let tests =
532     let accu = ref [] in
533     let aux i (res,x) = accu := (x, [i,res]) :: !accu in
534     Array.iteri (fun i -> List.iter (aux i)) pl;
535     SortedMap.from_list SortedList.cup !accu in
536    
537     let t = Types.cap Normal.any_basic disp.t in
538 abate 42 let accu = ref [] in
539 abate 43 let rec aux (success : (int * Normal.result) list) t l =
540 abate 42 if Types.non_empty t
541     then match l with
542     | [] ->
543 abate 43 let selected = Array.create (Array.length pl) [] in
544     let add (i,res) = selected.(i) <- res :: selected.(i) in
545     List.iter add success;
546    
547     let aux_final res = List.map conv_source_basic res in
548     accu := (t, return disp selected aux_final) :: !accu
549     | (ty,i) :: rem ->
550     aux (i @ success) (Types.cap t ty) rem;
551     aux success (Types.diff t ty) rem
552 abate 42 in
553 abate 43 aux [] t tests;
554 abate 42 !accu
555    
556    
557 abate 45 let get_tests pl f t d post =
558 abate 42 let accu = ref [] in
559     let unselect = Array.create (Array.length pl) [] in
560     let aux i x =
561     let yes, no = f x in
562     List.iter (fun (p,info) ->
563 abate 43 let p = Normal.normal (Normal.restrict t p) in
564 abate 42 accu := (p,[i, info]) :: !accu
565     ) yes;
566     unselect.(i) <- no @ unselect.(i) in
567     Array.iteri (fun i -> List.iter (aux i)) pl;
568     let sorted = Array.of_list (SortedMap.from_list SortedList.cup !accu) in
569     let infos = Array.map snd sorted in
570     let disp = dispatcher t (Array.map fst sorted) in
571 abate 43 let result (t,_,m) =
572 abate 42 let selected = Array.create (Array.length pl) [] in
573     let add r (i,inf) = selected.(i) <- (r,inf) :: selected.(i) in
574 abate 43 List.iter (fun (j,r) -> List.iter (add r) infos.(j)) m;
575 abate 42 d t selected unselect
576     in
577 abate 43 let res = Array.map result disp.codes in
578 abate 46 post (disp,res)
579 abate 42
580 abate 46 let make_branches t brs =
581     let (_,brs) =
582     List.fold_left
583     (fun (t,brs) (p,e) ->
584     let p = Normal.restrict t (Normal.nf p) in
585     let t = Types.diff t (p.Normal.a) in
586     (t, (p,e) :: brs)
587     ) (t,[]) brs in
588    
589     let pl = Array.map (fun x -> [x]) (Array.of_list brs) in
590     get_tests
591     pl
592     (fun x -> [x],[])
593     t
594     (fun _ pl _ ->
595     let r = ref None in
596     let aux = function
597     | [x] -> assert (!r = None); r := Some x
598     | [] -> () | _ -> assert false in
599     Array.iter aux pl;
600     let r = match !r with None -> assert false | Some x -> x in
601     r
602     )
603     (fun x -> x)
604 abate 42
605    
606 abate 43 let rec dispatch_prod disp =
607     let pl = Array.map (fun p -> p.Normal.nprod) disp.pl in
608 abate 42 let t = Types.Product.get disp.t in
609     get_tests pl
610     (fun (res,(p,q)) -> [p, (res,q)], [])
611     (Types.Product.pi1 t)
612     (dispatch_prod1 disp t)
613 abate 46 (fun x -> detect_left_tail_call (combine x))
614 abate 42 and dispatch_prod1 disp t t1 pl _ =
615     let t = Types.Product.restrict_1 t t1 in
616     get_tests pl
617     (fun (ret1, (res,q)) -> [q, (ret1,res)], [] )
618     (Types.Product.pi2 t)
619     (dispatch_prod2 disp t)
620 abate 46 (fun x -> detect_right_tail_call (combine x))
621 abate 42 and dispatch_prod2 disp t t2 pl _ =
622 abate 43 let aux_final (ret2, (ret1, res)) =
623     List.map (conv_source_prod ret1 ret2) res in
624     return disp pl aux_final
625 abate 42
626    
627     let dummy_label = Types.label ""
628    
629     let collect_first_label pl =
630     let f = ref true and m = ref dummy_label in
631     let aux = function
632     | (res, _, `Label (l, _, _)) ->
633     if (!f) then (f := false; m := l) else if (l < !m) then m:= l;
634     | _ -> () in
635     Array.iter (List.iter aux) pl;
636     if !f then None else Some !m
637    
638     let map_record f =
639     let rec aux = function
640     | [] -> []
641     | h::t -> (match f h with (_,_,`Fail) -> aux t | x -> x :: (aux t)) in
642     Array.map aux
643    
644     let label_found l =
645     map_record
646     (function
647     | (res, catch, `Label (l1, pr, _)) when l1 = l ->
648     (res, catch, `Dispatch pr)
649     | x -> x)
650    
651     let label_not_found l =
652     map_record
653     (function
654     | (res, catch, `Label (l1, _, ab)) when l1 = l -> (res, catch, ab)
655     | x -> x)
656    
657     let rec dispatch_record disp : record option =
658 abate 43 let prep p = List.map (fun (res,r) -> (res,[],r)) p.Normal.nrecord in
659 abate 42 let pl0 = Array.map prep disp.pl in
660     let t = Types.Record.get disp.t in
661     dispatch_record_opt disp t pl0
662     and dispatch_record_opt disp t pl =
663     if Types.Record.is_empty t then None
664     else Some (dispatch_record_label disp t pl)
665     and dispatch_record_label disp t pl =
666     match collect_first_label pl with
667     | None ->
668 abate 43 let aux_final (res, catch, x) =
669     assert (x = `Success);
670     List.map (conv_source_record catch) res in
671     `Result (return disp pl aux_final)
672 abate 42 | Some l ->
673     let present =
674     let pl = label_found l pl in
675     let t = Types.Record.restrict_label_present t l in
676     get_tests pl
677     (function
678     | (res,catch, `Dispatch d) ->
679     List.map (fun (p, r) -> p, (res, catch, r)) d, []
680     | x -> [],[x])
681     (Types.Record.project_field t l)
682     (dispatch_record_field l disp t)
683 abate 46 (fun x -> combine x)
684 abate 42 in
685     let absent =
686     let pl = label_not_found l pl in
687     let t = Types.Record.restrict_label_absent t l in
688     dispatch_record_opt disp t pl
689     in
690 abate 45 combine_record l present absent
691 abate 42 and dispatch_record_field l disp t tfield pl others =
692     let t = Types.Record.restrict_field t l tfield in
693     let aux (ret, (res, catch, rem)) = (res, (l,ret) :: catch, rem) in
694     let pl = Array.map (List.map aux) pl in
695     Array.iteri (fun i o -> pl.(i) <- pl.(i) @ o) others;
696     dispatch_record_label disp t pl
697    
698    
699     let actions disp =
700     match disp.actions with
701     | Some a -> a
702     | None ->
703     let a = {
704     basic = dispatch_basic disp;
705     prod = dispatch_prod disp;
706     record = dispatch_record disp;
707     } in
708     disp.actions <- Some a;
709     a
710    
711     let to_print = ref []
712     let printed = ref []
713    
714     let queue d =
715     if not (List.mem d.id !printed) then (
716     printed := d.id :: !printed;
717     to_print := d :: !to_print
718     )
719    
720     let print_actions ppf actions =
721     let print_source ppf = function
722     | `Catch -> Format.fprintf ppf "v"
723     | `Const c -> Types.Print.print_const ppf c
724     | `Left i -> Format.fprintf ppf "l%i" i
725     | `Right j -> Format.fprintf ppf "r%i" j
726     | `Recompose (i,j) -> Format.fprintf ppf "(l%i,r%i)" i j
727     | `Field (l,i) -> Format.fprintf ppf "%s%i" (Types.label_name l) i
728     in
729 abate 45 let print_result ppf =
730     Array.iteri
731     (fun i s ->
732     if i > 0 then Format.fprintf ppf ",";
733     print_source ppf s;
734     )
735 abate 42 in
736     let print_ret ppf (code,ret) =
737 abate 43 Format.fprintf ppf "$%i" code;
738 abate 45 if Array.length ret <> 0 then
739     Format.fprintf ppf "(%a)" print_result ret in
740 abate 42 let print_lhs ppf (code,prefix,d) =
741 abate 43 let arity = match d.codes.(code) with (_,a,_) -> a in
742 abate 42 Format.fprintf ppf "$%i(" code;
743     for i = 0 to arity - 1 do
744     if i > 0 then Format.fprintf ppf ",";
745     Format.fprintf ppf "%s%i" prefix i;
746     done;
747     Format.fprintf ppf ")" in
748     let print_basic (t,ret) =
749 abate 43 Format.fprintf ppf " | %a -> %a@\n"
750 abate 42 Types.Print.print_descr t
751     print_ret ret
752     in
753 abate 45 let print_prod2 = function
754     | `None -> assert false
755     | `Ignore r ->
756     Format.fprintf ppf " %a\n"
757     print_ret r
758     | `TailCall d ->
759     queue d;
760     Format.fprintf ppf " disp_%i v2@\n" d.id
761     | `Dispatch (d, branches) ->
762     queue d;
763     Format.fprintf ppf " match v2 with disp_%i@\n" d.id;
764     Array.iteri
765     (fun code r ->
766     Format.fprintf ppf " | %a -> %a\n"
767     print_lhs (code, "r", d)
768     print_ret r;
769     )
770     branches
771 abate 42 in
772 abate 45 let print_prod = function
773     | `None -> ()
774     | `Ignore d2 ->
775     Format.fprintf ppf " | (v1,v2) -> @\n";
776     print_prod2 d2
777     | `TailCall d ->
778     queue d;
779     Format.fprintf ppf " | (v1,v2) -> @\n";
780     Format.fprintf ppf " disp_%i v1@\n" d.id
781     | `Dispatch (d,branches) ->
782     queue d;
783     Format.fprintf ppf " | (v1,v2) -> @\n";
784     Format.fprintf ppf " match v1 with disp_%i@\n" d.id;
785     Array.iteri
786     (fun code d2 ->
787     Format.fprintf ppf " | %a -> @\n"
788     print_lhs (code, "l", d);
789     print_prod2 d2;
790     )
791     branches
792 abate 42 in
793     let rec print_record_opt ppf = function
794     | None -> ()
795     | Some r ->
796     Format.fprintf ppf " | Record -> @\n";
797     Format.fprintf ppf " @[%a@]@\n" print_record r
798     and print_record ppf = function
799     | `Result r -> print_ret ppf r
800 abate 45 | `Label (l, present, absent) ->
801 abate 42 let l = Types.label_name l in
802 abate 45 Format.fprintf ppf "check label %s:@\n" l;
803     Format.fprintf ppf "Present => @[%a@]@\n" (print_present l) present;
804     match absent with
805     | Some r ->
806     Format.fprintf ppf "Absent => @[%a@]@\n"
807     print_record r
808     | None -> ()
809     and print_present l ppf = function
810     | `None -> assert false
811     | `TailCall d ->
812 abate 42 queue d;
813 abate 45 Format.fprintf ppf "disp_%i@\n" d.id
814     | `Dispatch (d,branches) ->
815     queue d;
816     Format.fprintf ppf "match with disp_%i@\n" d.id;
817 abate 42 Array.iteri
818     (fun code r ->
819 abate 45 Format.fprintf ppf "| %a -> @\n"
820 abate 42 print_lhs (code, l, d);
821 abate 45 Format.fprintf ppf " @[%a@]@\n"
822 abate 42 print_record r
823 abate 45 ) branches
824     | `Ignore r ->
825     Format.fprintf ppf "@[%a@]@\n"
826     print_record r
827 abate 42 in
828    
829     List.iter print_basic actions.basic;
830     print_prod actions.prod;
831     print_record_opt ppf actions.record
832    
833     let rec print_dispatchers ppf =
834     match !to_print with
835     | [] -> ()
836     | d :: rem ->
837     to_print := rem;
838     Format.fprintf ppf "Dispatcher %i accepts [%a]@\n"
839 abate 44 d.id Types.Print.print_descr (Types.normalize d.t);
840 abate 43 let print_code code (t, arity, m) =
841     Format.fprintf ppf " Returns $%i(arity=%i) for [%a]"
842     code arity
843 abate 44 Types.Print.print_descr (Types.normalize t);
844 abate 42 (*
845 abate 43 List.iter
846     (fun (i,b) ->
847     Format.fprintf ppf "[%i:" i;
848 abate 42 List.iter
849     (fun (v,i) -> Format.fprintf ppf "%s=>%i;" v i)
850     b;
851 abate 43 Format.fprintf ppf "]"
852 abate 42 ) m;
853     *)
854 abate 43 Format.fprintf ppf "@\n";
855     in
856     Array.iteri print_code d.codes;
857     Format.fprintf ppf "let disp_%i = function@\n" d.id;
858 abate 42 print_actions ppf (actions d);
859 abate 43 Format.fprintf ppf "====================================@\n";
860 abate 42 print_dispatchers ppf
861    
862     let show ppf t pl =
863     let disp = dispatcher t pl in
864     queue disp;
865     print_dispatchers ppf
866    
867 abate 43 type normal = Normal.t
868     let normal p = Normal.normal (Normal.nf p)
869 abate 42
870 abate 43 end
871 abate 42
872    

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