aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel
diff options
context:
space:
mode:
authorGravatar barras <barras@85f007b7-540e-0410-9357-904b9bb8a0f7>2003-08-05 17:16:58 +0000
committerGravatar barras <barras@85f007b7-540e-0410-9357-904b9bb8a0f7>2003-08-05 17:16:58 +0000
commitef14e67d209edf4581223c6de4c38a79e4831940 (patch)
tree7012a9b32a16a14b765c03e76e4f32415f55ec86 /kernel
parent8235d977028498a99d8c3c097f6fd2094298f3ff (diff)
Improved reduction machine with closure: should use less memory
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@4247 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'kernel')
-rw-r--r--kernel/closure.ml309
-rw-r--r--kernel/closure.mli19
-rw-r--r--kernel/esubst.ml44
-rw-r--r--kernel/esubst.mli1
-rw-r--r--kernel/reduction.ml58
5 files changed, 263 insertions, 168 deletions
diff --git a/kernel/closure.ml b/kernel/closure.ml
index 1e7dadb04..bafdb6f16 100644
--- a/kernel/closure.ml
+++ b/kernel/closure.ml
@@ -489,41 +489,53 @@ let rec stack_nth s p = match s with
(* type of shared terms. fconstr and frterm are mutually recursive.
* Clone of the constr structure, but completely mutable, and
- * annotated with booleans (true when we noticed that the term is
- * normal and neutral) FLIFT is a delayed shift; allows sharing
- * between 2 lifted copies of a given term FCLOS is a delayed
- * substitution applied to a constr
+ * annotated with reduction state (reducible or not).
+ * - FLIFT is a delayed shift; allows sharing between 2 lifted copies
+ * of a given term.
+ * - FCLOS is a delayed substitution applied to a constr
+ * - FLOCKED is used to erase the content of a reference that must
+ * be updated. This is to allow the garbage collector to work
+ * before the term is computed.
*)
+
+(* Norm means the term is fully normalized and cannot create a redex
+ when substituted
+ Cstr means the term is in head normal form and that it can
+ create a redex when substituted (i.e. constructor, fix, lambda)
+ Whnf means we reached the head normal form and that it cannot
+ create a redex when substituted
+ Red is used for terms that might be reduced
+*)
type red_state = Norm | Cstr | Whnf | Red
+let neutr = function
+ | (Whnf|Norm) -> Whnf
+ | (Red|Cstr) -> Red
+
type fconstr = {
mutable norm: red_state;
mutable term: fterm }
and fterm =
| FRel of int
- | FAtom of constr
+ | FAtom of constr (* Metas and Sorts *)
| FCast of fconstr * fconstr
| FFlex of table_key
| FInd of inductive
| FConstruct of constructor
| FApp of fconstr * fconstr array
- | FFix of (int array * int) * (name array * fconstr array * fconstr array)
- * constr array * fconstr subs
- | FCoFix of int * (name array * fconstr array * fconstr array)
- * constr array * fconstr subs
+ | FFix of fixpoint * fconstr subs
+ | FCoFix of cofixpoint * fconstr subs
| FCases of case_info * fconstr * fconstr * fconstr array
- | FLambda of name * fconstr * fconstr * constr * fconstr subs
- | FProd of name * fconstr * fconstr * constr * fconstr subs
- | FLetIn of name * fconstr * fconstr * fconstr * constr * fconstr subs
+ | FLambda of int * (name * constr) list * constr * fconstr subs
+ | FProd of name * fconstr * fconstr
+ | FLetIn of name * fconstr * fconstr * constr * fconstr subs
| FEvar of existential_key * fconstr array
| FLIFT of int * fconstr
| FCLOS of constr * fconstr subs
| FLOCKED
let fterm_of v = v.term
-let set_whnf v = if v.norm = Red then v.norm <- Whnf
-let set_cstr v = if v.norm = Red then v.norm <- Cstr
let set_norm v = v.norm <- Norm
let is_val v = v.norm = Norm
@@ -536,13 +548,19 @@ let update v1 (no,t) =
v1)
else {norm=no;term=t}
-(* Lifting. Preserves sharing.
+(* Lifting. Preserves sharing (useful only for cell with norm=Red).
lft_fconstr always create a new cell, while lift_fconstr avoids it
when the lift is 0. *)
let rec lft_fconstr n ft =
match ft.term with
- FLIFT(k,m) -> lft_fconstr (n+k) m
- | _ -> {norm=ft.norm; term=FLIFT(n,ft)}
+ | (FInd _|FConstruct _|FFlex(ConstKey _|VarKey _)|FAtom _) -> ft
+ | FRel i -> {norm=Norm;term=FRel(i+n)}
+ | FLambda(k,tys,f,e) -> {norm=Cstr; term=FLambda(k,tys,f,subs_shft(n,e))}
+ | FFix(fx,e) -> {norm=Cstr; term=FFix(fx,subs_shft(n,e))}
+ | FCoFix(cfx,e) -> {norm=Cstr; term=FCoFix(cfx,subs_shft(n,e))}
+ | FLIFT(k,m) -> lft_fconstr (n+k) m
+ | FLOCKED -> anomaly "lft_constr found locked term"
+ | _ -> {norm=ft.norm; term=FLIFT(n,ft)}
let lift_fconstr k f =
if k=0 then f else lft_fconstr k f
let lift_fconstr_vect k v =
@@ -573,28 +591,37 @@ let zupdate m s =
Zupdate(m)::s'
else s
+let mk_lambda env t =
+(* let (env,t) =
+ if is_subs_id env then (env,t) else mk_clos_opt env t in*)
+ let (rvars,t') = decompose_lam t in
+ FLambda(List.length rvars, List.rev rvars, t', env)
+
+let destFLambda clos_fun t =
+ match t.term with
+ FLambda(_,[(na,ty)],b,e) -> (na,clos_fun e ty,clos_fun (subs_lift e) b)
+ | FLambda(n,(na,ty)::tys,b,e) ->
+ (na,clos_fun e ty,{norm=Cstr;term=FLambda(n-1,tys,b,subs_lift e)})
+ | _ -> assert false
let clos_rel e i =
match expand_rel i e with
| Inl(n,mt) -> lift_fconstr n mt
- | Inr(k,None) -> {norm=Red; term= FRel k}
+ | Inr(k,None) -> {norm=Norm; term= FRel k}
| Inr(k,Some p) ->
lift_fconstr (k-p) {norm=Norm;term=FFlex(FarRelKey p)}
(* Optimization: do not enclose variables in a closure.
Makes variable access much faster *)
-let rec mk_clos e t =
+let mk_clos e t =
match kind_of_term t with
| Rel i -> clos_rel e i
| Var x -> { norm = Red; term = FFlex (VarKey x) }
+ | Const c -> { norm = Red; term = FFlex (ConstKey c) }
| Meta _ | Sort _ -> { norm = Norm; term = FAtom t }
| Ind kn -> { norm = Norm; term = FInd kn }
| Construct kn -> { norm = Cstr; term = FConstruct kn }
- | Evar (ev,args) ->
- { norm = Cstr; term = FEvar (ev,Array.map (mk_clos e) args) }
- | (Fix _|CoFix _|Lambda _|Prod _) ->
- {norm = Cstr; term = FCLOS(t,e)}
- | (App _|Case _|Cast _|Const _|LetIn _) ->
+ | (CoFix _|Lambda _|Fix _|Prod _|Evar _|App _|Case _|Cast _|LetIn _) ->
{norm = Red; term = FCLOS(t,e)}
let mk_clos_vect env v = Array.map (mk_clos env) v
@@ -605,7 +632,7 @@ let mk_clos_vect env v = Array.map (mk_clos env) v
Could be used insted of mk_clos. *)
let mk_clos_deep clos_fun env t =
match kind_of_term t with
- | (Rel _|Ind _|Construct _|Var _|Meta _ | Sort _|Evar _) ->
+ | (Rel _|Ind _|Const _|Construct _|Var _|Meta _ | Sort _) ->
mk_clos env t
| Cast (a,b) ->
{ norm = Red;
@@ -613,42 +640,27 @@ let mk_clos_deep clos_fun env t =
| App (f,v) ->
{ norm = Red;
term = FApp (clos_fun env f, Array.map (clos_fun env) v) }
- | Const kn ->
- { norm = Red;
- term = FFlex (ConstKey kn) }
| Case (ci,p,c,v) ->
{ norm = Red;
term = FCases (ci, clos_fun env p, clos_fun env c,
Array.map (clos_fun env) v) }
- | Fix (op,(lna,tys,bds)) ->
- let env' = subs_liftn (Array.length bds) env in
- { norm = Cstr;
- term = FFix
- (op,(lna, Array.map (clos_fun env) tys,
- Array.map (clos_fun env') bds),
- bds, env) }
- | CoFix (op,(lna,tys,bds)) ->
- let env' = subs_liftn (Array.length bds) env in
- { norm = Cstr;
- term = FCoFix
- (op,(lna, Array.map (clos_fun env) tys,
- Array.map (clos_fun env') bds),
- bds, env) }
- | Lambda (n,t,c) ->
- { norm = Cstr;
- term = FLambda (n, clos_fun env t,
- clos_fun (subs_lift env) c,
- c, env) }
+ | Fix fx ->
+ { norm = Cstr; term = FFix (fx, env) }
+ | CoFix cfx ->
+ { norm = Cstr; term = FCoFix(cfx,env) }
+ | Lambda _ ->
+ { norm = Cstr; term = mk_lambda env t }
| Prod (n,t,c) ->
- { norm = Cstr;
- term = FProd (n, clos_fun env t,
- clos_fun (subs_lift env) c,
- c, env) }
+ { norm = Whnf;
+ term = FProd (n, clos_fun env t, clos_fun (subs_lift env) c) }
| LetIn (n,b,t,c) ->
{ norm = Red;
- term = FLetIn (n, clos_fun env b, clos_fun env t,
- clos_fun (subs_lift env) c,
- c, env) }
+ term = FLetIn (n, clos_fun env b, clos_fun env t, c, env) }
+ | Evar(ev,args) ->
+ { norm = Whnf; term = FEvar(ev,Array.map (clos_fun env) args) }
+
+(* A better mk_clos? *)
+let mk_clos2 = mk_clos_deep mk_clos
(* The inverse of mk_clos_deep: move back to constr *)
let rec to_constr constr_fun lfts v =
@@ -670,34 +682,43 @@ let rec to_constr constr_fun lfts v =
mkCase (ci, constr_fun lfts p,
constr_fun lfts c,
Array.map (constr_fun lfts) ve)
- | FFix (op,(lna,tys,bds),_,_) ->
- let lfts' = el_liftn (Array.length bds) lfts in
- mkFix (op, (lna, Array.map (constr_fun lfts) tys,
- Array.map (constr_fun lfts') bds))
- | FCoFix (op,(lna,tys,bds),_,_) ->
+ | FFix ((op,(lna,tys,bds)),e) ->
+ let n = Array.length bds in
+ let ftys = Array.map (mk_clos e) tys in
+ let fbds = Array.map (mk_clos (subs_liftn n e)) bds in
+ let lfts' = el_liftn n lfts in
+ mkFix (op, (lna, Array.map (constr_fun lfts) ftys,
+ Array.map (constr_fun lfts') fbds))
+ | FCoFix ((op,(lna,tys,bds)),e) ->
+ let n = Array.length bds in
+ let ftys = Array.map (mk_clos e) tys in
+ let fbds = Array.map (mk_clos (subs_liftn n e)) bds in
let lfts' = el_liftn (Array.length bds) lfts in
- mkCoFix (op, (lna, Array.map (constr_fun lfts) tys,
- Array.map (constr_fun lfts') bds))
+ mkCoFix (op, (lna, Array.map (constr_fun lfts) ftys,
+ Array.map (constr_fun lfts') fbds))
| FApp (f,ve) ->
mkApp (constr_fun lfts f,
Array.map (constr_fun lfts) ve)
- | FLambda (n,t,c,_,_) ->
- mkLambda (n, constr_fun lfts t,
- constr_fun (el_lift lfts) c)
- | FProd (n,t,c,_,_) ->
+ | FLambda _ ->
+ let (na,ty,bd) = destFLambda mk_clos2 v in
+ mkLambda (na, constr_fun lfts ty,
+ constr_fun (el_lift lfts) bd)
+ | FProd (n,t,c) ->
mkProd (n, constr_fun lfts t,
constr_fun (el_lift lfts) c)
- | FLetIn (n,b,t,c,_,_) ->
+ | FLetIn (n,b,t,f,e) ->
+ let fc = mk_clos2 (subs_lift e) f in
mkLetIn (n, constr_fun lfts b,
- constr_fun lfts t,
- constr_fun (el_lift lfts) c)
+ constr_fun lfts t,
+ constr_fun (el_lift lfts) fc)
| FEvar (ev,args) -> mkEvar(ev,Array.map (constr_fun lfts) args)
| FLIFT (k,a) -> to_constr constr_fun (el_shft k lfts) a
| FCLOS (t,env) ->
- let fr = mk_clos_deep mk_clos env t in
+ let fr = mk_clos2 env t in
let unfv = update v (fr.norm,fr.term) in
to_constr constr_fun lfts unfv
- | FLOCKED -> anomaly "Closure.to_constr: found locked term"
+ | FLOCKED -> (*anomaly "Closure.to_constr: found locked term"*)
+mkVar(id_of_string"_LOCK_")
(* This function defines the correspondance between constr and
fconstr. When we find a closure whose substitution is the identity,
@@ -707,6 +728,10 @@ let term_of_fconstr =
let rec term_of_fconstr_lift lfts v =
match v.term with
| FCLOS(t,env) when is_subs_id env & is_lift_id lfts -> t
+ | FLambda(_,tys,f,e) when is_subs_id e & is_lift_id lfts ->
+ compose_lam (List.rev tys) f
+ | FFix(fx,e) when is_subs_id e & is_lift_id lfts -> mkFix fx
+ | FCoFix(cfx,e) when is_subs_id e & is_lift_id lfts -> mkCoFix cfx
| _ -> to_constr term_of_fconstr_lift lfts v in
term_of_fconstr_lift ELID
@@ -719,16 +744,15 @@ let rec fstrong unfreeze_fun lfts v =
to_constr (fstrong unfreeze_fun) lfts (unfreeze_fun v)
*)
-(* TODO: the norm flags are not handled properly *)
let rec zip zfun m stk =
match stk with
| [] -> m
| Zapp args :: s ->
let args = Array.of_list args in
- zip zfun {norm=m.norm; term=FApp(m, Array.map zfun args)} s
+ zip zfun {norm=neutr m.norm; term=FApp(m, Array.map zfun args)} s
| Zcase(ci,p,br)::s ->
let t = FCases(ci, zfun p, m, Array.map zfun br) in
- zip zfun {norm=m.norm; term=t} s
+ zip zfun {norm=neutr m.norm; term=t} s
| Zfix(fx,par)::s ->
zip zfun fx (par @ append_stack_list ([m], s))
| Zshift(n)::s ->
@@ -801,6 +825,28 @@ let get_arg h stk =
Some (v, s') -> (Some (depth,v), s')
| None -> (None, zshift depth stk')
+let rec get_args n tys f e stk =
+ match stk with
+ Zupdate r :: s ->
+ let hd = update r (Cstr,FLambda(n,tys,f,e)) in
+ get_args n tys f e s
+ | Zshift k :: s ->
+ get_args n tys f (subs_shft (k,e)) s
+ | Zapp l :: s ->
+ let na = List.length l in
+ if n == na then
+ let e' = List.fold_left (fun e arg -> subs_cons(arg,e)) e l in
+ (Inl e',s)
+ else if n < na then (* more arguments *)
+ let (args,eargs) = list_chop n l in
+ let e' = List.fold_left (fun e arg -> subs_cons(arg,e)) e args in
+ (Inl e', Zapp eargs :: s)
+ else (* more lambdas *)
+ let (_,etys) = list_chop na tys in
+ let e' = List.fold_left (fun e arg -> subs_cons(arg,e)) e l in
+ get_args (n-na) etys f e' s
+ | _ -> (Inr {norm=Cstr;term=FLambda(n,tys,f,e)}, stk)
+
(* Iota reduction: extract the arguments to be passed to the Case
branches *)
@@ -840,19 +886,19 @@ let rec drop_parameters depth n stk =
let contract_fix_vect fix =
let (thisbody, make_body, env, nfix) =
match fix with
- | FFix ((reci,i),def,bds,env) ->
+ | FFix (((reci,i),(_,_,bds as rdcl)),env) ->
(bds.(i),
- (fun j -> { norm = Whnf; term = FFix ((reci,j),def,bds,env) }),
+ (fun j -> { norm = Cstr; term = FFix (((reci,j),rdcl),env) }),
env, Array.length bds)
- | FCoFix (i,def,bds,env) ->
+ | FCoFix ((i,(_,_,bds as rdcl)),env) ->
(bds.(i),
- (fun j -> { norm = Whnf; term = FCoFix (j,def,bds,env) }),
+ (fun j -> { norm = Cstr; term = FCoFix ((j,rdcl),env) }),
env, Array.length bds)
| _ -> anomaly "Closure.contract_fix_vect: not a (co)fixpoint"
in
let rec subst_bodies_from_i i env =
if i = nfix then
- mk_clos env thisbody
+ (env, thisbody)
else
subst_bodies_from_i (i+1) (subs_cons (make_body i, env))
in
@@ -867,21 +913,19 @@ let contract_fix_vect fix =
let rec knh m stk =
match m.term with
| FLIFT(k,a) -> knh a (zshift k stk)
- | FCLOS(t,e) -> knht e t (Zupdate(m)::stk)
+ | FCLOS(t,e) -> knht e t (zupdate m stk)
| FLOCKED -> anomaly "Closure.knh: found lock"
| FApp(a,b) -> knh a (append_stack b (zupdate m stk))
| FCases(ci,p,t,br) -> knh t (Zcase(ci,p,br)::zupdate m stk)
- | FFix((ri,n),_,_,_) ->
- (set_whnf m;
- match get_nth_arg m ri.(n) stk with
+ | FFix(((ri,n),(_,_,_)),_) ->
+ (match get_nth_arg m ri.(n) stk with
(Some(pars,arg),stk') -> knh arg (Zfix(m,pars)::stk')
| (None, stk') -> (m,stk'))
| FCast(t,_) -> knh t stk
(* cases where knh stops *)
- | (FFlex _|FLetIn _|FConstruct _|FEvar _) -> (m, stk)
- | (FRel _|FAtom _|FInd _) -> (set_norm m; (m, stk))
- | (FLambda _|FCoFix _|FProd _) ->
- (set_whnf m; (m, stk))
+ | (FFlex _|FLetIn _|FConstruct _|FEvar _|
+ FCoFix _|FLambda _|FRel _|FAtom _|FInd _|FProd _) ->
+ (m, stk)
(* The same for pure terms *)
and knht e t stk =
@@ -890,12 +934,12 @@ and knht e t stk =
knht e a (append_stack (mk_clos_vect e b) stk)
| Case(ci,p,t,br) ->
knht e t (Zcase(ci, mk_clos e p, mk_clos_vect e br)::stk)
- | Fix _ -> knh (mk_clos_deep mk_clos e t) stk
+ | Fix _ -> knh (mk_clos2 e t) stk
| Cast(a,b) -> knht e a stk
| Rel n -> knh (clos_rel e n) stk
| (Lambda _|Prod _|Construct _|CoFix _|Ind _|
LetIn _|Const _|Var _|Evar _|Meta _|Sort _) ->
- (mk_clos_deep mk_clos e t, stk)
+ (mk_clos2 e t, stk)
(***********************************************************************)
@@ -903,10 +947,10 @@ and knht e t stk =
(* Computes a normal form from the result of knh. *)
let rec knr info m stk =
match m.term with
- | FLambda(_,_,_,f,e) when red_set info.i_flags fBETA ->
- (match get_arg m stk with
- (Some(depth,arg),s) -> knit info (subs_shift_cons(depth,e,arg)) f s
- | (None,s) -> (m,s))
+ | FLambda(n,tys,f,e) when red_set info.i_flags fBETA ->
+ (match get_args n tys f e stk with
+ Inl e', s -> knit info e' f s
+ | Inr lam, s -> (lam,s))
| FFlex(ConstKey kn) when red_set info.i_flags (fCONST kn) ->
(match ref_value_cache info (ConstKey kn) with
Some v -> kni info v stk
@@ -928,16 +972,16 @@ let rec knr info m stk =
| (_, cargs, Zfix(fx,par)::s) ->
let rarg = fapp_stack(m,cargs) in
let stk' = par @ append_stack [|rarg|] s in
- let efx = contract_fix_vect fx.term in
- kni info efx stk'
+ let (fxe,fxbd) = contract_fix_vect fx.term in
+ knit info fxe fxbd stk'
| (_,args,s) -> (m,args@s))
| FCoFix _ when red_set info.i_flags fIOTA ->
(match strip_update_shift_app m stk with
(_, args, ((Zcase _::_) as stk')) ->
- let efx = contract_fix_vect m.term in
- kni info efx (args@stk')
+ let (fxe,fxbd) = contract_fix_vect m.term in
+ knit info fxe fxbd (args@stk')
| (_,args,s) -> (m,args@s))
- | FLetIn (_,v,_,_,bd,e) when red_set info.i_flags fZETA ->
+ | FLetIn (_,v,_,bd,e) when red_set info.i_flags fZETA ->
knit info (subs_cons(v,e)) bd stk
| _ -> (m,stk)
@@ -953,38 +997,58 @@ let kh info v stk = fapp_stack(kni info v stk)
(***********************************************************************)
+let rec zip_term zfun m stk =
+ match stk with
+ | [] -> m
+ | Zapp args :: s ->
+ let args = Array.of_list args in
+ zip_term zfun (mkApp(m, Array.map zfun args)) s
+ | Zcase(ci,p,br)::s ->
+ let t = mkCase(ci, zfun p, m, Array.map zfun br) in
+ zip_term zfun t s
+ | Zfix(fx,par)::s ->
+ let h = mkApp(zip_term zfun (zfun fx) par,[|m|]) in
+ zip_term zfun h s
+ | Zshift(n)::s ->
+ zip_term zfun (lift n m) s
+ | Zupdate(rf)::s ->
+ zip_term zfun m s
+
(* Computes the strong normal form of a term.
1- Calls kni
2- tries to rebuild the term. If a closure still has to be computed,
calls itself recursively. *)
let rec kl info m =
- if is_val m then (incr prune; m)
+ if is_val m then (incr prune; term_of_fconstr m)
else
let (nm,s) = kni info m [] in
- down_then_up info nm s
+ let _ = fapp_stack(nm,s) in (* to unlock Zupdates! *)
+ zip_term (kl info) (norm_head info nm) s
(* no redex: go up for atoms and already normalized terms, go down
otherwise. *)
-and down_then_up info m stk =
- let nm =
- if is_val m then (incr prune; m) else
- let nt =
- match m.term with
- | FLambda(na,ty,bd,f,e) ->
- FLambda(na, kl info ty, kl info bd, f, e)
- | FLetIn(na,a,b,c,f,e) ->
- FLetIn(na, kl info a, kl info b, kl info c, f, e)
- | FProd(na,dom,rng,f,e) ->
- FProd(na, kl info dom, kl info rng, f, e)
- | FCoFix(n,(na,ftys,fbds),bds,e) ->
- FCoFix(n,(na, Array.map (kl info) ftys,
- Array.map (kl info) fbds),bds,e)
- | FEvar(i,args) -> FEvar(i, Array.map (kl info) args)
- | t -> t in
- {norm=Norm;term=nt} in
-(* Precondition: m.norm = Norm *)
- zip (kl info) nm stk
-
+and norm_head info m =
+ if is_val m then (incr prune; term_of_fconstr m) else
+ match m.term with
+ | FLambda(n,tys,f,e) ->
+ let (e',rvtys) =
+ List.fold_left (fun (e,ctxt) (na,ty) ->
+ (subs_lift e, (na,kl info (mk_clos e ty))::ctxt))
+ (e,[]) tys in
+ let bd = kl info (mk_clos e' f) in
+ List.fold_left (fun b (na,ty) -> mkLambda(na,ty,b)) bd rvtys
+ | FLetIn(na,a,b,f,e) ->
+ let c = mk_clos (subs_lift e) f in
+ mkLetIn(na, kl info a, kl info b, kl info c)
+ | FProd(na,dom,rng) ->
+ mkProd(na, kl info dom, kl info rng)
+ | FCoFix((n,(na,tys,bds)),e) ->
+ let ftys = Array.map (mk_clos e) tys in
+ let fbds =
+ Array.map (mk_clos (subs_liftn (Array.length na) e)) bds in
+ mkCoFix(n,(na, Array.map (kl info) ftys, Array.map (kl info) fbds))
+ | FEvar(i,args) -> mkEvar(i, Array.map (kl info) args)
+ | t -> term_of_fconstr m
(* Initialization and then normalization *)
@@ -994,11 +1058,14 @@ let whd_val info v =
(* strong reduction *)
let norm_val info v =
- with_stats (lazy (term_of_fconstr (kl info v)))
+ with_stats (lazy (kl info v))
let inject = mk_clos (ESID 0)
-let whd_stack = kni
+let whd_stack infos m stk =
+ let k = kni infos m stk in
+ let _ = fapp_stack k in (* to unlock Zupdates! *)
+ k
(* cache of constants: the body is computed only when needed. *)
type clos_infos = fconstr infos
diff --git a/kernel/closure.mli b/kernel/closure.mli
index 4442e49f9..8c8032423 100644
--- a/kernel/closure.mli
+++ b/kernel/closure.mli
@@ -133,26 +133,23 @@ type fconstr
type fterm =
| FRel of int
- | FAtom of constr
+ | FAtom of constr (* Metas and Sorts *)
| FCast of fconstr * fconstr
| FFlex of table_key
| FInd of inductive
| FConstruct of constructor
| FApp of fconstr * fconstr array
- | FFix of (int array * int) * (name array * fconstr array * fconstr array)
- * constr array * fconstr subs
- | FCoFix of int * (name array * fconstr array * fconstr array)
- * constr array * fconstr subs
+ | FFix of fixpoint * fconstr subs
+ | FCoFix of cofixpoint * fconstr subs
| FCases of case_info * fconstr * fconstr * fconstr array
- | FLambda of name * fconstr * fconstr * constr * fconstr subs
- | FProd of name * fconstr * fconstr * constr * fconstr subs
- | FLetIn of name * fconstr * fconstr * fconstr * constr * fconstr subs
+ | FLambda of int * (name * constr) list * constr * fconstr subs
+ | FProd of name * fconstr * fconstr
+ | FLetIn of name * fconstr * fconstr * constr * fconstr subs
| FEvar of existential_key * fconstr array
| FLIFT of int * fconstr
| FCLOS of constr * fconstr subs
| FLOCKED
-
(* To lazy reduce a constr, create a [clos_infos] with
[create_clos_infos], inject the term to reduce with [inject]; then use
a reduction function *)
@@ -160,6 +157,8 @@ type fterm =
val inject : constr -> fconstr
val fterm_of : fconstr -> fterm
val term_of_fconstr : fconstr -> constr
+val destFLambda :
+ (fconstr subs -> constr -> fconstr) -> fconstr -> name * fconstr * fconstr
(* Global and local constant cache *)
type clos_infos
@@ -200,7 +199,7 @@ val mk_clos_deep :
val kni: clos_infos -> fconstr -> fconstr stack -> fconstr * fconstr stack
val knr: clos_infos -> fconstr -> fconstr stack -> fconstr * fconstr stack
-val kl : clos_infos -> fconstr -> fconstr
+val kl : clos_infos -> fconstr -> constr
val to_constr : (lift -> fconstr -> constr) -> lift -> fconstr -> constr
diff --git a/kernel/esubst.ml b/kernel/esubst.ml
index 46be7a747..a72f5a634 100644
--- a/kernel/esubst.ml
+++ b/kernel/esubst.ml
@@ -67,28 +67,30 @@ type 'a subs =
let subs_cons(x,s) = CONS(x,s)
let subs_liftn n = function
- | ESID p -> ESID (p+n) (* bounded identity lifted extends by p *)
+ | ESID p -> ESID (p+n) (* bounded identity lifted extends by p *)
| LIFT (p,lenv) -> LIFT (p+n, lenv)
- | lenv -> LIFT (n,lenv)
+ | lenv -> LIFT (n,lenv)
let subs_lift a = subs_liftn 1 a
+let subs_liftn n a = if n = 0 then a else subs_liftn n a
let subs_shft = function
| (0, s) -> s
| (n, SHIFT (k,s1)) -> SHIFT (k+n, s1)
| (n, s) -> SHIFT (n,s)
+let subs_shft (n,a) = if n = 0 then a else subs_shft(n,a)
let subs_shift_cons = function
- (0, s, t) -> CONS(t,s)
+ (0, s, t) -> CONS(t,s)
| (k, SHIFT(n,s1), t) -> CONS(t,SHIFT(k+n, s1))
-| (k, s, t) -> CONS(t,SHIFT(k, s));;
+| (k, s, t) -> CONS(t,SHIFT(k, s));;
(* Tests whether a substitution is extensionnaly equal to the identity *)
let rec is_subs_id = function
- ESID _ -> true
- | LIFT(_,s) -> is_subs_id s
+ ESID _ -> true
+ | LIFT(_,s) -> is_subs_id s
| SHIFT(0,s) -> is_subs_id s
- | _ -> false
+ | _ -> false
(* Expands de Bruijn k in the explicit substitution subs
* lams accumulates de shifts to perform when retrieving the i-th value
@@ -107,13 +109,29 @@ let rec is_subs_id = function
*)
let rec exp_rel lams k subs =
match (k,subs) with
- | (1, CONS (def,_)) -> Inl(lams,def)
- | (_, CONS (_,l)) -> exp_rel lams (pred k) l
+ | (1, CONS (def,_)) -> Inl(lams,def)
+ | (_, CONS (_,l)) -> exp_rel lams (pred k) l
| (_, LIFT (n,_)) when k<=n -> Inr(lams+k,None)
- | (_, LIFT (n,l)) -> exp_rel (n+lams) (k-n) l
- | (_, SHIFT (n,s)) -> exp_rel (n+lams) k s
- | (_, ESID n) when k<=n -> Inr(lams+k,None)
- | (_, ESID n) -> Inr(lams+k,Some (k-n))
+ | (_, LIFT (n,l)) -> exp_rel (n+lams) (k-n) l
+ | (_, SHIFT (n,s)) -> exp_rel (n+lams) k s
+ | (_, ESID n) when k<=n -> Inr(lams+k,None)
+ | (_, ESID n) -> Inr(lams+k,Some (k-n))
let expand_rel k subs = exp_rel 0 k subs
+let rec comp mk_cl s1 s2 =
+ match (s1, s2) with
+ | _, ESID _ -> s1
+ | ESID _, _ -> s2
+ | SHIFT(k,s), _ -> subs_shft(k, comp mk_cl s s2)
+ | _, CONS(x,s') -> CONS(mk_cl(s1,x), comp mk_cl s1 s')
+ | CONS(x,s), SHIFT(k,s') -> comp mk_cl s (subs_shft(k-1, s'))
+ | CONS(x,s), LIFT(k,s') -> CONS(x,comp mk_cl s (subs_liftn (k-1) s'))
+ | LIFT(k,s), SHIFT(k',s') ->
+ if k<k'
+ then subs_shft(k, comp mk_cl s (subs_shft(k'-k, s')))
+ else subs_shft(k', comp mk_cl (subs_liftn (k-k') s) s')
+ | LIFT(k,s), LIFT(k',s') ->
+ if k<k'
+ then subs_liftn k (comp mk_cl s (subs_liftn (k'-k) s'))
+ else subs_liftn k' (comp mk_cl (subs_liftn (k-k') s) s')
diff --git a/kernel/esubst.mli b/kernel/esubst.mli
index 284c2f32e..cbb5c37cc 100644
--- a/kernel/esubst.mli
+++ b/kernel/esubst.mli
@@ -39,3 +39,4 @@ val subs_liftn: int -> 'a subs -> 'a subs
val subs_shift_cons: int * 'a subs * 'a -> 'a subs
val expand_rel: int -> 'a subs -> (int * 'a, int * int option) Util.union
val is_subs_id: 'a subs -> bool
+val comp : ('a subs * 'a -> 'a) -> 'a subs -> 'a subs -> 'a subs \ No newline at end of file
diff --git a/kernel/reduction.ml b/kernel/reduction.ml
index 8ba8ae61b..5c57c5014 100644
--- a/kernel/reduction.ml
+++ b/kernel/reduction.ml
@@ -77,13 +77,22 @@ let nf_betaiota t =
norm_val (create_clos_infos betaiota empty_env) (inject t)
let whd_betaiotazeta env x =
- whd_val (create_clos_infos betaiotazeta env) (inject x)
+ match kind_of_term x with
+ | (Sort _|Var _|Meta _|Evar _|Const _|Ind _|Construct _|
+ Prod _|Lambda _|Fix _|CoFix _) -> x
+ | _ -> whd_val (create_clos_infos betaiotazeta env) (inject x)
let whd_betadeltaiota env t =
- whd_val (create_clos_infos betadeltaiota env) (inject t)
+ match kind_of_term t with
+ | (Sort _|Meta _|Evar _|Ind _|Construct _|
+ Prod _|Lambda _|Fix _|CoFix _) -> t
+ | _ -> whd_val (create_clos_infos betadeltaiota env) (inject t)
let whd_betadeltaiota_nolet env t =
- whd_val (create_clos_infos betadeltaiotanolet env) (inject t)
+ match kind_of_term t with
+ | (Sort _|Meta _|Evar _|Ind _|Construct _|
+ Prod _|Lambda _|Fix _|CoFix _|LetIn _) -> t
+ | _ -> whd_val (create_clos_infos betadeltaiotanolet env) (inject t)
(* Beta *)
@@ -226,27 +235,20 @@ and eqappr cv_pb infos appr1 appr2 cuniv =
| None -> raise NotConvertible)
(* other constructors *)
- | (FLambda (_,c1,c2,_,_), FLambda (_,c'1,c'2,_,_)) ->
- assert (is_empty_stack v1 && is_empty_stack v2);
- let u1 = ccnv CONV infos el1 el2 c1 c'1 cuniv in
- ccnv CONV infos (el_lift el1) (el_lift el2) c2 c'2 u1
+ | (FLambda _, FLambda _) ->
+ let (_,ty1,bd1) = destFLambda mk_clos hd1 in
+ let (_,ty2,bd2) = destFLambda mk_clos hd2 in
+ let u1 = ccnv CONV infos el1 el2 ty1 ty2 cuniv in
+ ccnv CONV infos (el_lift el1) (el_lift el2) bd1 bd2 u1
- | (FProd (_,c1,c2,_,_), FProd (_,c'1,c'2,_,_)) ->
+ | (FProd (_,c1,c2), FProd (_,c'1,c'2)) ->
assert (is_empty_stack v1 && is_empty_stack v2);
(* Luo's system *)
let u1 = ccnv CONV infos el1 el2 c1 c'1 cuniv in
ccnv cv_pb infos (el_lift el1) (el_lift el2) c2 c'2 u1
- (* Inductive types: MutInd MutConstruct MutCase Fix Cofix *)
+ (* Inductive types: MutInd MutConstruct Fix Cofix *)
- (* Les annotations du MutCase ne servent qu'à l'affichage *)
-(*
- | (FCases (_,p1,c1,cl1), FCases (_,p2,c2,cl2)) ->
- let u1 = ccnv CONV infos el1 el2 p1 p2 cuniv in
- let u2 = ccnv CONV infos el1 el2 c1 c2 u1 in
- let u3 = convert_vect infos el1 el2 cl1 cl2 u2 in
- convert_stacks infos lft1 lft2 v1 v2 u3
-*)
| (FInd (kn1,i1), FInd (kn2,i2)) ->
if i1 = i2 && mind_equiv infos kn1 kn2
then
@@ -259,25 +261,33 @@ and eqappr cv_pb infos appr1 appr2 cuniv =
convert_stacks infos lft1 lft2 v1 v2 cuniv
else raise NotConvertible
- | (FFix (op1,(_,tys1,cl1),_,_), FFix(op2,(_,tys2,cl2),_,_)) ->
+ | (FFix ((op1,(_,tys1,cl1)),e1), FFix((op2,(_,tys2,cl2)),e2)) ->
if op1 = op2
then
- let u1 = convert_vect infos el1 el2 tys1 tys2 cuniv in
- let n = Array.length cl1 in
+ let n = Array.length cl1 in
+ let fty1 = Array.map (mk_clos e1) tys1 in
+ let fty2 = Array.map (mk_clos e2) tys2 in
+ let fcl1 = Array.map (mk_clos (subs_liftn n e1)) cl1 in
+ let fcl2 = Array.map (mk_clos (subs_liftn n e2)) cl2 in
+ let u1 = convert_vect infos el1 el2 fty1 fty2 cuniv in
let u2 =
convert_vect infos
- (el_liftn n el1) (el_liftn n el2) cl1 cl2 u1 in
+ (el_liftn n el1) (el_liftn n el2) fcl1 fcl2 u1 in
convert_stacks infos lft1 lft2 v1 v2 u2
else raise NotConvertible
- | (FCoFix (op1,(_,tys1,cl1),_,_), FCoFix(op2,(_,tys2,cl2),_,_)) ->
+ | (FCoFix ((op1,(_,tys1,cl1)),e1), FCoFix((op2,(_,tys2,cl2)),e2)) ->
if op1 = op2
then
- let u1 = convert_vect infos el1 el2 tys1 tys2 cuniv in
let n = Array.length cl1 in
+ let fty1 = Array.map (mk_clos e1) tys1 in
+ let fty2 = Array.map (mk_clos e2) tys2 in
+ let fcl1 = Array.map (mk_clos (subs_liftn n e1)) cl1 in
+ let fcl2 = Array.map (mk_clos (subs_liftn n e2)) cl2 in
+ let u1 = convert_vect infos el1 el2 fty1 fty2 cuniv in
let u2 =
convert_vect infos
- (el_liftn n el1) (el_liftn n el2) cl1 cl2 u1 in
+ (el_liftn n el1) (el_liftn n el2) fcl1 fcl2 u1 in
convert_stacks infos lft1 lft2 v1 v2 u2
else raise NotConvertible