| 331 |
[ `Label of Types.label * record dispatch * record option |
[ `Label of Types.label * record dispatch * record option |
| 332 |
| `Result of result ] |
| `Result of result ] |
| 333 |
|
|
| 334 |
and 'a dispatch = dispatcher * 'a array |
and 'a dispatch = |
| 335 |
and result = int * source list |
[ `Dispatch of dispatcher * 'a array |
| 336 |
|
| `TailCall of dispatcher |
| 337 |
|
| `Ignore of 'a |
| 338 |
|
| `None ] |
| 339 |
|
|
| 340 |
|
and result = int * source array |
| 341 |
and source = |
and source = |
| 342 |
[ `Catch | `Const of Types.const |
[ `Catch | `Const of Types.const |
| 343 |
| `Left of int | `Right of int | `Recompose of int * int |
| `Left of int | `Right of int | `Recompose of int * int |
| 362 |
mutable actions : actions option |
mutable actions : actions option |
| 363 |
} |
} |
| 364 |
|
|
| 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 |
|
let combine disp act = |
| 380 |
|
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 |
let cur_id = ref 0 |
let cur_id = ref 0 |
| 429 |
|
|
| 430 |
module DispMap = Map.Make( |
module DispMap = Map.Make( |
| 496 |
aux 0 d.interface |
aux 0 d.interface |
| 497 |
|
|
| 498 |
let create_result pl = |
let create_result pl = |
| 499 |
|
Array.of_list ( |
| 500 |
Array.fold_right |
Array.fold_right |
| 501 |
(fun x accu -> match x with |
(fun x accu -> match x with |
| 502 |
| Some b -> b @ accu |
| Some b -> b @ accu |
| 503 |
| None -> accu) |
| None -> accu) |
| 504 |
pl [] |
pl [] |
| 505 |
|
) |
| 506 |
|
|
| 507 |
let return disp pl f = |
let return disp pl f = |
| 508 |
let aux = function [x] -> Some (f x) | [] -> None | _ -> assert false in |
let aux = function [x] -> Some (f x) | [] -> None | _ -> assert false in |
| 554 |
!accu |
!accu |
| 555 |
|
|
| 556 |
|
|
| 557 |
let get_tests pl f t d = |
let get_tests pl f t d post = |
| 558 |
let accu = ref [] in |
let accu = ref [] in |
| 559 |
let unselect = Array.create (Array.length pl) [] in |
let unselect = Array.create (Array.length pl) [] in |
| 560 |
let aux i x = |
let aux i x = |
| 575 |
d t selected unselect |
d t selected unselect |
| 576 |
in |
in |
| 577 |
let res = Array.map result disp.codes in |
let res = Array.map result disp.codes in |
| 578 |
(disp,res) |
post (combine disp res) |
| 579 |
|
|
| 580 |
|
|
| 581 |
|
|
| 586 |
(fun (res,(p,q)) -> [p, (res,q)], []) |
(fun (res,(p,q)) -> [p, (res,q)], []) |
| 587 |
(Types.Product.pi1 t) |
(Types.Product.pi1 t) |
| 588 |
(dispatch_prod1 disp t) |
(dispatch_prod1 disp t) |
| 589 |
|
detect_left_tail_call |
| 590 |
and dispatch_prod1 disp t t1 pl _ = |
and dispatch_prod1 disp t t1 pl _ = |
| 591 |
let t = Types.Product.restrict_1 t t1 in |
let t = Types.Product.restrict_1 t t1 in |
| 592 |
get_tests pl |
get_tests pl |
| 593 |
(fun (ret1, (res,q)) -> [q, (ret1,res)], [] ) |
(fun (ret1, (res,q)) -> [q, (ret1,res)], [] ) |
| 594 |
(Types.Product.pi2 t) |
(Types.Product.pi2 t) |
| 595 |
(dispatch_prod2 disp t) |
(dispatch_prod2 disp t) |
| 596 |
|
detect_right_tail_call |
| 597 |
and dispatch_prod2 disp t t2 pl _ = |
and dispatch_prod2 disp t t2 pl _ = |
| 598 |
let aux_final (ret2, (ret1, res)) = |
let aux_final (ret2, (ret1, res)) = |
| 599 |
List.map (conv_source_prod ret1 ret2) res in |
List.map (conv_source_prod ret1 ret2) res in |
| 656 |
| x -> [],[x]) |
| x -> [],[x]) |
| 657 |
(Types.Record.project_field t l) |
(Types.Record.project_field t l) |
| 658 |
(dispatch_record_field l disp t) |
(dispatch_record_field l disp t) |
| 659 |
|
(fun x -> x) |
| 660 |
in |
in |
| 661 |
let absent = |
let absent = |
| 662 |
let pl = label_not_found l pl in |
let pl = label_not_found l pl in |
| 663 |
let t = Types.Record.restrict_label_absent t l in |
let t = Types.Record.restrict_label_absent t l in |
| 664 |
dispatch_record_opt disp t pl |
dispatch_record_opt disp t pl |
| 665 |
in |
in |
| 666 |
`Label (l, present, absent) |
combine_record l present absent |
| 667 |
and dispatch_record_field l disp t tfield pl others = |
and dispatch_record_field l disp t tfield pl others = |
| 668 |
let t = Types.Record.restrict_field t l tfield in |
let t = Types.Record.restrict_field t l tfield in |
| 669 |
let aux (ret, (res, catch, rem)) = (res, (l,ret) :: catch, rem) in |
let aux (ret, (res, catch, rem)) = (res, (l,ret) :: catch, rem) in |
| 702 |
| `Recompose (i,j) -> Format.fprintf ppf "(l%i,r%i)" i j |
| `Recompose (i,j) -> Format.fprintf ppf "(l%i,r%i)" i j |
| 703 |
| `Field (l,i) -> Format.fprintf ppf "%s%i" (Types.label_name l) i |
| `Field (l,i) -> Format.fprintf ppf "%s%i" (Types.label_name l) i |
| 704 |
in |
in |
| 705 |
let rec print_result ppf = function |
let print_result ppf = |
| 706 |
| [] -> () |
Array.iteri |
| 707 |
| [s] -> print_source ppf s |
(fun i s -> |
| 708 |
| s :: rem -> |
if i > 0 then Format.fprintf ppf ","; |
| 709 |
Format.fprintf ppf "%a," print_source s; |
print_source ppf s; |
| 710 |
print_result ppf rem |
) |
| 711 |
in |
in |
| 712 |
let print_ret ppf (code,ret) = |
let print_ret ppf (code,ret) = |
| 713 |
Format.fprintf ppf "$%i" code; |
Format.fprintf ppf "$%i" code; |
| 714 |
if ret <> [] then Format.fprintf ppf "(%a)" print_result ret in |
if Array.length ret <> 0 then |
| 715 |
|
Format.fprintf ppf "(%a)" print_result ret in |
| 716 |
let print_lhs ppf (code,prefix,d) = |
let print_lhs ppf (code,prefix,d) = |
| 717 |
let arity = match d.codes.(code) with (_,a,_) -> a in |
let arity = match d.codes.(code) with (_,a,_) -> a in |
| 718 |
Format.fprintf ppf "$%i(" code; |
Format.fprintf ppf "$%i(" code; |
| 726 |
Types.Print.print_descr t |
Types.Print.print_descr t |
| 727 |
print_ret ret |
print_ret ret |
| 728 |
in |
in |
| 729 |
let print_prod2 (d,rem) = |
let print_prod2 = function |
| 730 |
|
| `None -> assert false |
| 731 |
|
| `Ignore r -> |
| 732 |
|
Format.fprintf ppf " %a\n" |
| 733 |
|
print_ret r |
| 734 |
|
| `TailCall d -> |
| 735 |
|
queue d; |
| 736 |
|
Format.fprintf ppf " disp_%i v2@\n" d.id |
| 737 |
|
| `Dispatch (d, branches) -> |
| 738 |
queue d; |
queue d; |
| 739 |
Format.fprintf ppf " match v2 with disp_%i@\n" d.id; |
Format.fprintf ppf " match v2 with disp_%i@\n" d.id; |
| 740 |
Array.iteri |
Array.iteri |
| 743 |
print_lhs (code, "r", d) |
print_lhs (code, "r", d) |
| 744 |
print_ret r; |
print_ret r; |
| 745 |
) |
) |
| 746 |
rem |
branches |
| 747 |
in |
in |
| 748 |
let print_prod (d,rem) = |
let print_prod = function |
| 749 |
if Array.length rem > 0 then ( |
| `None -> () |
| 750 |
|
| `Ignore d2 -> |
| 751 |
|
Format.fprintf ppf " | (v1,v2) -> @\n"; |
| 752 |
|
print_prod2 d2 |
| 753 |
|
| `TailCall d -> |
| 754 |
|
queue d; |
| 755 |
|
Format.fprintf ppf " | (v1,v2) -> @\n"; |
| 756 |
|
Format.fprintf ppf " disp_%i v1@\n" d.id |
| 757 |
|
| `Dispatch (d,branches) -> |
| 758 |
queue d; |
queue d; |
| 759 |
Format.fprintf ppf " | (v1,v2) -> @\n"; |
Format.fprintf ppf " | (v1,v2) -> @\n"; |
| 760 |
Format.fprintf ppf " match v1 with disp_%i@\n" d.id; |
Format.fprintf ppf " match v1 with disp_%i@\n" d.id; |
| 764 |
print_lhs (code, "l", d); |
print_lhs (code, "l", d); |
| 765 |
print_prod2 d2; |
print_prod2 d2; |
| 766 |
) |
) |
| 767 |
rem |
branches |
|
) |
|
| 768 |
in |
in |
| 769 |
let rec print_record_opt ppf = function |
let rec print_record_opt ppf = function |
| 770 |
| None -> () |
| None -> () |
| 773 |
Format.fprintf ppf " @[%a@]@\n" print_record r |
Format.fprintf ppf " @[%a@]@\n" print_record r |
| 774 |
and print_record ppf = function |
and print_record ppf = function |
| 775 |
| `Result r -> print_ret ppf r |
| `Result r -> print_ret ppf r |
| 776 |
| `Label (l, (d,present), absent) -> |
| `Label (l, present, absent) -> |
| 777 |
let l = Types.label_name l in |
let l = Types.label_name l in |
|
queue d; |
|
| 778 |
Format.fprintf ppf " check label %s:@\n" l; |
Format.fprintf ppf " check label %s:@\n" l; |
| 779 |
Format.fprintf ppf " Present => match with disp_%i@\n" d.id; |
Format.fprintf ppf "Present => @[%a@]@\n" (print_present l) present; |
| 780 |
|
match absent with |
| 781 |
|
| Some r -> |
| 782 |
|
Format.fprintf ppf "Absent => @[%a@]@\n" |
| 783 |
|
print_record r |
| 784 |
|
| None -> () |
| 785 |
|
and print_present l ppf = function |
| 786 |
|
| `None -> assert false |
| 787 |
|
| `TailCall d -> |
| 788 |
|
queue d; |
| 789 |
|
Format.fprintf ppf "disp_%i@\n" d.id |
| 790 |
|
| `Dispatch (d,branches) -> |
| 791 |
|
queue d; |
| 792 |
|
Format.fprintf ppf "match with disp_%i@\n" d.id; |
| 793 |
Array.iteri |
Array.iteri |
| 794 |
(fun code r -> |
(fun code r -> |
| 795 |
Format.fprintf ppf " | %a -> @\n" |
Format.fprintf ppf " | %a -> @\n" |
| 796 |
print_lhs (code, l, d); |
print_lhs (code, l, d); |
| 797 |
Format.fprintf ppf " @[%a@]@\n" |
Format.fprintf ppf " @[%a@]@\n" |
| 798 |
print_record r |
print_record r |
| 799 |
) present; |
) branches |
| 800 |
match absent with |
| `Ignore r -> |
| 801 |
| Some r -> |
Format.fprintf ppf "@[%a@]@\n" |
|
Format.fprintf ppf " Absent => @[%a@]@\n" |
|
| 802 |
print_record r |
print_record r |
|
| None -> () |
|
| 803 |
in |
in |
| 804 |
|
|
| 805 |
List.iter print_basic actions.basic; |
List.iter print_basic actions.basic; |
| 846 |
end |
end |
| 847 |
|
|
| 848 |
|
|
|
(* |
|
|
let test_filter t p = |
|
|
let t = Syntax.make_type (Syntax.parse t) |
|
|
and p = Syntax.make_pat (Syntax.parse p) in |
|
|
let r = Patterns.filter (Types.descr t) p in |
|
|
List.iter (fun (v,t) -> |
|
|
let t = Types.normalize t in |
|
|
Format.fprintf Format.std_formatter "@[%s => %a@]@\n" |
|
|
v Types.Print.print t) r;; |
|
|
test_filter "[ (1 2 3?)* ]" "[ (x::(1 2) 3?)* ]";; |
|
|
*) |
|
|
|
|
|
(* |
|
|
disp " [(`A `B `C?)*] " [" [ (((x::`A) `B (x::`C))|_)* ] "];; |
|
|
disp " [(`A)*] " [" [ (x::`A)* ] "];; |
|
|
|
|
|
disp "_" ["{x=`A;y=`B}"];; |
|
|
disp "_" [" [((x::1)|(y::2))*] "];; |
|
|
|
|
|
disp "_" [ "((x,_),_)"; "((_,x),_)" ];; |
|
|
disp " [ (1 3?)* ]" [ " [(x::1 3?)*] " ];; |
|
|
disp " [ (1 3?)* ]" [ " [(1 (x::3)?)*] " ];; |
|
|
*) |
|
|
|
|
|
|
|
|
|
|
|
(* |
|
|
#install_printer Types.Print.print_descr;; |
|
|
let pat s = Patterns.descr (Typer.pat (Parser.From_string.pat s));; |
|
|
let typ s = Types.descr (Typer.typ (Parser.From_string.pat s));; |
|
|
|
|
|
let disp t l = |
|
|
let l = Array.of_list ( |
|
|
List.map (fun p -> Patterns.Compile.normal (pat p)) l) in |
|
|
let t = typ t in |
|
|
Patterns.Compile.show Format.std_formatter t l;; |
|
|
|
|
|
let () = disp "_" ["(x,y,z)"];; |
|
|
|
|
|
disp "_" ["`A"];; |
|
|
disp "_" ["((x,y),z) | ((x := 1) & (y := 2), z)"];; |
|
|
*) |
|
|
|
|