summaryrefslogtreecommitdiff
path: root/contrib/extraction/mlutil.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/extraction/mlutil.ml')
-rw-r--r--contrib/extraction/mlutil.ml79
1 files changed, 48 insertions, 31 deletions
diff --git a/contrib/extraction/mlutil.ml b/contrib/extraction/mlutil.ml
index 6bfedce5..79aeea33 100644
--- a/contrib/extraction/mlutil.ml
+++ b/contrib/extraction/mlutil.ml
@@ -6,7 +6,7 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i $Id: mlutil.ml 8886 2006-06-01 13:53:45Z letouzey $ i*)
+(*i $Id: mlutil.ml 10329 2007-11-21 21:21:36Z letouzey $ i*)
(*i*)
open Pp
@@ -573,14 +573,20 @@ let eta_red e =
if n = 0 then e
else match t with
| MLapp (f,a) ->
- let m = (List.length a) - n in
- if m < 0 then e
- else
- let a1,a2 = list_chop m a in
- let f = if m = 0 then f else MLapp (f,a1) in
- if test_eta_args_lift 0 n a2 && not (ast_occurs_itvl 1 n f)
- then ast_lift (-n) f
- else e
+ let m = List.length a in
+ let ids,body,args =
+ if m = n then
+ [], f, a
+ else if m < n then
+ snd (list_chop (n-m) ids), f, a
+ else (* m > n *)
+ let a1,a2 = list_chop (m-n) a in
+ [], MLapp (f,a1), a2
+ in
+ let p = List.length args in
+ if test_eta_args_lift 0 p args && not (ast_occurs_itvl 1 p body)
+ then named_lams ids (ast_lift (-p) body)
+ else e
| _ -> e
(*s Computes all head linear beta-reductions possible in [(t a)].
@@ -658,20 +664,27 @@ let check_generalizable_case unsafe br =
if check_and_generalize br.(i) <> f then raise Impossible
done; f
-(*s Do all branches correspond to the same thing? *)
+(*s Detecting similar branches of a match *)
-let check_constant_case br =
- if Array.length br = 0 then raise Impossible;
- let (r,l,t) = br.(0) in
- let n = List.length l in
- if ast_occurs_itvl 1 n t then raise Impossible;
- let cst = ast_lift (-n) t in
- for i = 1 to Array.length br - 1 do
- let (r,l,t) = br.(i) in
- let n = List.length l in
- if (ast_occurs_itvl 1 n t) || (cst <> (ast_lift (-n) t))
- then raise Impossible
- done; cst
+(* If several branches of a match are equal (and independent from their
+ patterns) we will print them using a _ pattern. If _all_ branches
+ are equal, we remove the match.
+*)
+
+let common_branches br =
+ let tab = Hashtbl.create 13 in
+ for i = 0 to Array.length br - 1 do
+ let (r,ids,t) = br.(i) in
+ let n = List.length ids in
+ if not (ast_occurs_itvl 1 n t) then
+ let t = ast_lift (-n) t in
+ let l = try Hashtbl.find tab t with Not_found -> [] in
+ Hashtbl.replace tab t (i::l)
+ done;
+ let best = ref [] in
+ Hashtbl.iter
+ (fun _ l -> if List.length l > List.length !best then best := l) tab;
+ if List.length !best < 2 then [] else !best
(*s If all branches are functions, try to permut the case and the functions. *)
@@ -805,18 +818,20 @@ and simpl_case o i br e =
let f = check_generalizable_case o.opt_case_idg br in
simpl o (MLapp (MLlam (anonymous,f),[e]))
with Impossible ->
- try (* Is each branch independant of [e] ? *)
- if not o.opt_case_cst then raise Impossible;
- check_constant_case br
- with Impossible ->
+ (* Detect common branches *)
+ let common_br = if not o.opt_case_cst then [] else common_branches br in
+ if List.length common_br = Array.length br && br <> [||] then
+ let (_,ids,t) = br.(0) in ast_lift (-List.length ids) t
+ else
+ let new_i = (fst i, common_br) in
(* Swap the case and the lam if possible *)
if o.opt_case_fun
then
let ids,br = permut_case_fun br [] in
let n = List.length ids in
- if n <> 0 then named_lams ids (MLcase (i,ast_lift n e, br))
- else MLcase (i,e,br)
- else MLcase (i,e,br)
+ if n <> 0 then named_lams ids (MLcase (new_i,ast_lift n e, br))
+ else MLcase (new_i,e,br)
+ else MLcase (new_i,e,br)
let rec post_simpl = function
| MLletin(_,c,e) when (is_atomic (eta_red c)) ->
@@ -1122,13 +1137,15 @@ let is_not_strict t =
Futhermore we don't expand fixpoints. *)
let inline_test t =
- not (is_fix (eta_red t)) && (ml_size t < 12 && is_not_strict t)
+ let t1 = eta_red t in
+ let t2 = snd (collect_lams t1) in
+ not (is_fix t2) && ml_size t < 12 && is_not_strict t
let manual_inline_list =
let mp = MPfile (dirpath_of_string "Coq.Init.Wf") in
List.map (fun s -> (make_con mp empty_dirpath (mk_label s)))
[ "well_founded_induction_type"; "well_founded_induction";
- "Acc_rect"; "Acc_rec" ; "Acc_iter" ]
+ "Acc_rect"; "Acc_rec" ; "Acc_iter" ; "Fix" ]
let manual_inline = function
| ConstRef c -> List.mem c manual_inline_list