aboutsummaryrefslogtreecommitdiff
path: root/pretyping/termops.ml
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping/termops.ml')
-rw-r--r--pretyping/termops.ml64
1 files changed, 49 insertions, 15 deletions
diff --git a/pretyping/termops.ml b/pretyping/termops.ml
index 9fc7dc9764..442eb7a5dc 100644
--- a/pretyping/termops.ml
+++ b/pretyping/termops.ml
@@ -236,24 +236,55 @@ let map_constr_with_binders_left_to_right g f l c = match kind_of_term c with
mkCoFix (ln,(lna,tl',bl'))
(* strong *)
-let map_constr_with_full_binders g f l c = match kind_of_term c with
+let map_constr_with_full_binders g f l cstr = match kind_of_term cstr with
| (Rel _ | Meta _ | Var _ | Sort _ | Const _ | Ind _
- | Construct _) -> c
- | Cast (c,t) -> mkCast (f l c, f l t)
- | Prod (na,t,c) -> mkProd (na, f l t, f (g (na,None,t) l) c)
- | Lambda (na,t,c) -> mkLambda (na, f l t, f (g (na,None,t) l) c)
- | LetIn (na,b,t,c) -> mkLetIn (na, f l b, f l t, f (g (na,Some b,t) l) c)
- | App (c,al) -> mkApp (f l c, Array.map (f l) al)
- | Evar (e,al) -> mkEvar (e, Array.map (f l) al)
- | Case (ci,p,c,bl) -> mkCase (ci, f l p, f l c, Array.map (f l) bl)
+ | Construct _) -> cstr
+ | Cast (c,t) ->
+ let c' = f l c in
+ let t' = f l t in
+ if c==c' && t==t' then cstr else mkCast (c', t')
+ | Prod (na,t,c) ->
+ let t' = f l t in
+ let c' = f (g (na,None,t) l) c in
+ if t==t' && c==c' then cstr else mkProd (na, t', c')
+ | Lambda (na,t,c) ->
+ let t' = f l t in
+ let c' = f (g (na,None,t) l) c in
+ if t==t' && c==c' then cstr else mkLambda (na, t', c')
+ | LetIn (na,b,t,c) ->
+ let b' = f l b in
+ let t' = f l t in
+ let c' = f (g (na,Some b,t) l) c in
+ if b==b' && t==t' && c==c' then cstr else mkLetIn (na, b', t', c')
+ | App (c,al) ->
+ let c' = f l c in
+ let al' = Array.map (f l) al in
+ if c==c' && array_for_all2 (==) al al' then cstr else mkApp (c', al')
+ | Evar (e,al) ->
+ let al' = Array.map (f l) al in
+ if array_for_all2 (==) al al' then cstr else mkEvar (e, al')
+ | Case (ci,p,c,bl) ->
+ let p' = f l p in
+ let c' = f l c in
+ let bl' = Array.map (f l) bl in
+ if p==p' && c==c' && array_for_all2 (==) bl bl' then cstr else
+ mkCase (ci, p', c', bl')
| Fix (ln,(lna,tl,bl)) ->
+ let tl' = Array.map (f l) tl in
let l' =
array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- mkFix (ln,(lna,Array.map (f l) tl, Array.map (f l') bl))
+ let bl' = Array.map (f l') bl in
+ if array_for_all2 (==) tl tl' && array_for_all2 (==) bl bl'
+ then cstr
+ else mkFix (ln,(lna,tl',bl'))
| CoFix(ln,(lna,tl,bl)) ->
+ let tl' = Array.map (f l) tl in
let l' =
array_fold_left2 (fun l na t -> g (na,None,t) l) l lna tl in
- mkCoFix (ln,(lna,Array.map (f l) tl,Array.map (f l') bl))
+ let bl' = Array.map (f l') bl in
+ if array_for_all2 (==) tl tl' && array_for_all2 (==) bl bl'
+ then cstr
+ else mkCoFix (ln,(lna,tl',bl'))
(* Equality modulo let reduction *)
@@ -416,10 +447,13 @@ let subst_term_gen eq_fun env c t =
| Some x -> x
| None ->
(if eq_fun e c t then mkRel k
- else
- map_constr_with_full_binders
- (fun d (e,k,c) -> (push_rel d e,k+1,lift 1 c))
- substrec kc t)
+ else
+ let red_t = whd_locals env t in
+ let red_t' =
+ map_constr_with_full_binders
+ (fun d (e,k,c) -> (push_rel d e,k+1,lift 1 c))
+ substrec kc red_t in
+ if red_t == red_t' then t else red_t')
in
substrec (env,1,nf_locals env c) t