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

Contents of /types/patterns.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (show annotations)
Tue Jul 10 17:03:32 2007 UTC (5 years, 11 months ago) by abate
File size: 26717 byte(s)
[r2002-11-01 20:09:48 by cvscast] Empty log message

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

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