diff options
| author | herbelin | 2000-09-10 07:19:28 +0000 |
|---|---|---|
| committer | herbelin | 2000-09-10 07:19:28 +0000 |
| commit | 79dc33cbc403ebab0bd1fe815c13f740f0a1b850 (patch) | |
| tree | e38e167003d7dd97d95a59ea7c026a1629b346f8 /kernel/closure.ml | |
| parent | c0ff579606f2eba24bc834316d8bb7bcc076000d (diff) | |
Ajout d'un LetIn primitif.
Abstraction de constr via kind_of_constr dans une bonne partie du code.
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@591 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'kernel/closure.ml')
| -rw-r--r-- | kernel/closure.ml | 366 |
1 files changed, 256 insertions, 110 deletions
diff --git a/kernel/closure.ml b/kernel/closure.ml index f452a6dfc2..948361690d 100644 --- a/kernel/closure.ml +++ b/kernel/closure.ml @@ -4,7 +4,6 @@ open Util open Pp open Term -open Generic open Names open Environ open Instantiate @@ -31,6 +30,9 @@ let stop() = (* sets of reduction kinds *) type red_kind = BETA | DELTA of sorts oper | IOTA +(* Hack: we use oper (Const "$LOCAL VAR$") for local variables *) +let local_const_oper = Const (make_path [] (id_of_string "$LOCAL VAR$") CCI) + type reds = { r_beta : bool; r_delta : sorts oper -> bool; (* this is unsafe: exceptions may pop out *) @@ -157,6 +159,58 @@ let infos_under infos = i_tab = infos.i_tab } +(* explicit substitutions of type 'a *) +type 'a subs = + | ESID (* ESID = identity *) + | CONS of 'a * 'a subs (* CONS(t,S) = (S.t) parallel substitution *) + | SHIFT of int * 'a subs (* SHIFT(n,S) = (^n o S) terms in S are relocated *) + (* with n vars *) + | LIFT of int * 'a subs (* LIFT(n,S) = (%n S) stands for ((^n o S).n...1) *) + +(* operations of subs: collapses constructors when possible. + * Needn't be recursive if we always use these functions + *) + +let subs_cons(x,s) = CONS(x,s) + +let subs_liftn n = function + | ESID -> ESID (* the identity lifted is still the identity *) + (* (because (^1.1) --> id) *) + | LIFT (p,lenv) -> LIFT (p+n, lenv) + | lenv -> LIFT (n,lenv) + +let subs_lift a = subs_liftn 1 a + +let subs_shft = function + | (0, s) -> s + | (n, SHIFT (k,s1)) -> SHIFT (k+n, s1) + | (n, s) -> SHIFT (n,s) + +(* Expands de Bruijn k in the explicit substitution subs + * lams accumulates de shifts to perform when retrieving the i-th value + * the rules used are the following: + * + * [id]k --> k + * [S.t]1 --> t + * [S.t]k --> [S](k-1) if k > 1 + * [^n o S] k --> [^n]([S]k) + * [(%n S)] k --> k if k <= n + * [(%n S)] k --> [^n]([S](k-n)) + * + * the result is (Inr k) when the variable is just relocated + *) +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 + | (_, LIFT (n,_)) when k<=n -> Inr(lams+k) + | (_, LIFT (n,l)) -> exp_rel (n+lams) (k-n) l + | (_, SHIFT (n,s)) -> exp_rel (n+lams) k s + | (_, ESID) -> Inr(lams+k) + +let expand_rel k subs = exp_rel 0 k subs + + (**** Call by value reduction ****) (* The type of terms with closure. The meaning of the constructors and @@ -185,7 +239,8 @@ let infos_under infos = type cbv_value = | VAL of int * constr | LAM of name * constr * constr * cbv_value subs - | FIXP of sorts oper * constr array * cbv_value subs * cbv_value list + | FIXP of fixpoint * cbv_value subs * cbv_value list + | COFIXP of cofixpoint * cbv_value subs * cbv_value list | CONSTR of int * (section_path * int) * cbv_value array * cbv_value list (* les vars pourraient etre des constr, @@ -197,8 +252,10 @@ type cbv_value = let rec shift_value n = function | VAL (k,v) -> VAL ((k+n),v) | LAM (x,a,b,s) -> LAM (x,a,b,subs_shft (n,s)) - | FIXP (op,bv,s,args) -> - FIXP (op,bv,subs_shft (n,s), List.map (shift_value n) args) + | FIXP (fix,s,args) -> + FIXP (fix,subs_shft (n,s), List.map (shift_value n) args) + | COFIXP (cofix,s,args) -> + COFIXP (cofix,subs_shft (n,s), List.map (shift_value n) args) | CONSTR (i,spi,vars,args) -> CONSTR (i, spi, Array.map (shift_value n) vars, List.map (shift_value n) args) @@ -210,20 +267,23 @@ let rec shift_value n = function * (S, (fix Fi {F0 := T0 .. Fn-1 := Tn-1})) * -> (S. [S]F0 . [S]F1 ... . [S]Fn-1, Ti) *) -let contract_fixp env fix = - let (bnum, bodies, make_body) = match fix with - | DOPN(Fix(reci,i),bvect) -> - (i, array_last bvect, (fun j -> FIXP(Fix(reci,j), bvect, env, []))) - | DOPN(CoFix i,bvect) -> - (i, array_last bvect, (fun j -> FIXP(CoFix j, bvect, env, []))) - | _ -> anomaly "Closure.contract_fixp: not a (co)fixpoint" - in - let rec subst_bodies_from_i i subs = function - | DLAM(_,t) -> subst_bodies_from_i (i+1) (subs_cons (make_body i, subs)) t - | DLAMV(_,bds) -> (subs_cons (make_body i, subs), bds.(bnum)) - | _ -> anomaly "Closure.contract_fixp: malformed (co)fixpoint" +let contract_fixp env ((reci,i),(_,_,bds as bodies)) = + let make_body j = FIXP(((reci,j),bodies), env, []) in + let n = Array.length bds in + let rec subst_bodies_from_i i subs = + if i=n then subs + else subst_bodies_from_i (i+1) (subs_cons (make_body i, subs)) + in + subst_bodies_from_i 0 env, bds.(i) + +let contract_cofixp env (i,(_,_,bds as bodies)) = + let make_body j = COFIXP((j,bodies), env, []) in + let n = Array.length bds in + let rec subst_bodies_from_i i subs = + if i=n then subs + else subst_bodies_from_i (i+1) (subs_cons (make_body i, subs)) in - subst_bodies_from_i 0 env bodies + subst_bodies_from_i 0 env, bds.(i) (* type of terms with a hole. This hole can appear only under AppL or Case. @@ -274,12 +334,13 @@ let red_allowed flags stack rk = *) let strip_appl head stack = match head with - | FIXP (op,bv,env,app) -> (FIXP(op,bv,env,[]), stack_app app stack) + | FIXP (fix,env,app) -> (FIXP(fix,env,[]), stack_app app stack) + | COFIXP (cofix,env,app) -> (COFIXP(cofix,env,[]), stack_app app stack) | CONSTR (i,spi,vars,app) -> (CONSTR(i,spi,vars,[]), stack_app app stack) | _ -> (head, stack) -(* Invariant: if the result of norm_head is CONSTR or FIXP, it last +(* Invariant: if the result of norm_head is CONSTR or (CO)FIXP, it last * argument is []. * Because we must put all the applied terms in the stack. *) @@ -298,12 +359,18 @@ let rec check_app_constr redfun = function | _ -> false) | (_::l, n) -> check_app_constr redfun (l,(pred n)) -let fixp_reducible redfun flgs op stk = +let fixp_reducible redfun flgs ((reci,i),_) stk = + if red_allowed flgs stk IOTA then + match stk with (* !!! for Acc_rec: reci.(i) = -2 *) + | APP(appl,_) -> reci.(i) >=0 & check_app_constr redfun (appl, reci.(i)) + | _ -> false + else + false + +let cofixp_reducible redfun flgs _ stk = if red_allowed flgs stk IOTA then - match (op,stk) with (* !!! for Acc_rec: reci.(i) = -2 *) - | (Fix (reci,i), APP(appl,_)) -> - (reci.(i) >= 0 & check_app_constr redfun (appl, reci.(i))) - | (CoFix i, (CASE _ | APP(_,CASE _))) -> true + match stk with + | (CASE _ | APP(_,CASE _)) -> true | _ -> false else false @@ -318,65 +385,72 @@ let mindsp_nparams env sp = * constructor, a lambda or a fixp in the head. If not, it is a value * and is completely computed here. The head redexes are NOT reduced: * the function returns the pair of a cbv_value and its stack. * - * Invariant: if the result of norm_head is CONSTR or FIXP, it last + * Invariant: if the result of norm_head is CONSTR or (CO)FIXP, it last * argument is []. Because we must put all the applied terms in the * stack. *) let rec norm_head info env t stack = (* no reduction under binders *) - match t with + match kind_of_term t with (* stack grows (remove casts) *) - | DOPN (AppL,appl) -> (* Applied terms are normalized immediately; + | IsAppL (head,args) -> (* Applied terms are normalized immediately; they could be computed when getting out of the stack *) - (match Array.to_list appl with - | head::args -> - let nargs = List.map (cbv_stack_term info TOP env) args in - norm_head info env head (stack_app nargs stack) - | [] -> anomaly "norm_head : malformed constr AppL [||]") - | DOPN (MutCase _,_) -> - let (ci,p,c,v) = destCase t in - norm_head info env c (CASE(p,v,ci,env,stack)) - | DOP2 (Cast,ct,c) -> norm_head info env ct stack + let nargs = List.map (cbv_stack_term info TOP env) args in + norm_head info env head (stack_app nargs stack) + | IsMutCase (ci,p,c,v) -> norm_head info env c (CASE(p,v,ci,env,stack)) + | IsCast (ct,_) -> norm_head info env ct stack (* constants, axioms * the first pattern is CRUCIAL, n=0 happens very often: * when reducing closed terms, n is always 0 *) - | Rel i -> (match expand_rel i env with + | IsRel i -> (match expand_rel i env with | Inl (0,v) -> reduce_const_body (cbv_norm_more info) v stack | Inl (n,v) -> reduce_const_body (cbv_norm_more info) (shift_value n v) stack | Inr n -> (VAL(0, Rel n), stack)) - | DOPN ((Const _ | Evar _ | Abst _) as op, vars) - when red_allowed info.i_flags stack (DELTA op) -> - let normt = DOPN(op, Array.map (cbv_norm_term info env) vars) in - (match const_value_cache info normt with - | Some body -> reduce_const_body (cbv_norm_more info) body stack - | None -> (VAL(0,normt), stack)) + | IsConst (sp,vars) -> + let normt = mkConst (sp,Array.map (cbv_norm_term info env) vars) in + if red_allowed info.i_flags stack (DELTA (Const sp)) then + match const_value_cache info normt with + | Some body -> reduce_const_body (cbv_norm_more info) body stack + | None -> (VAL(0,normt), stack) + else (VAL(0,normt), stack) + | IsLetIn (x, b, t, c) -> + if red_allowed info.i_flags stack (DELTA local_const_oper) then + let b = cbv_stack_term info TOP env b in + norm_head info (subs_cons (b,env)) c stack + else + let normt = + mkLetIn (x, cbv_norm_term info env b, + cbv_norm_term info env t, + cbv_norm_term info (subs_lift env) c) in + (VAL(0,normt), stack) (* Considérer une coupure commutative ? *) + | IsEvar (n,vars) -> + let normt = mkEvar (n,Array.map (cbv_norm_term info env) vars) in + if red_allowed info.i_flags stack (DELTA (Evar n)) then + match const_value_cache info normt with + | Some body -> reduce_const_body (cbv_norm_more info) body stack + | None -> (VAL(0,normt), stack) + else (VAL(0,normt), stack) (* non-neutral cases *) - | DOP2 (Lambda,a,DLAM(x,b)) -> (LAM(x,a,b,env), stack) - | DOPN ((Fix _ | CoFix _) as op, v) -> (FIXP(op,v,env,[]), stack) - | DOPN (MutConstruct(spi,i),vars) -> + | IsLambda (x,a,b) -> (LAM(x,a,b,env), stack) + | IsFix fix -> (FIXP(fix,env,[]), stack) + | IsCoFix cofix -> (COFIXP(cofix,env,[]), stack) + | IsMutConstruct ((spi,i),vars) -> (CONSTR(i,spi, Array.map (cbv_stack_term info TOP env) vars,[]), stack) (* neutral cases *) - | (VAR _ | DOP0 _) -> (VAL(0, t), stack) - | DOP1 (op, nt) -> (VAL(0, DOP1(op, cbv_norm_term info env nt)), stack) - | DOP2 (op,a,b) -> - (VAL(0, DOP2(op, cbv_norm_term info env a, cbv_norm_term info env b)), - stack) - | DOPN (op,vars) -> - (VAL(0, DOPN(op, Array.map (cbv_norm_term info env) vars)), stack) - | DOPL (op,l) -> - (VAL(0, DOPL(op, List.map (cbv_norm_term info env) l)), stack) - | DLAM (x,t) -> - (VAL(0, DLAM(x, cbv_norm_term info (subs_lift env) t)), stack) - | DLAMV (x,ve) -> - (VAL(0, DLAMV(x, Array.map(cbv_norm_term info (subs_lift env)) ve)), - stack) - + | (IsVar _ | IsSort _ | IsMeta _ | IsXtra _ ) -> (VAL(0, t), stack) + | IsMutInd (sp,vars) -> + (VAL(0, mkMutInd (sp, Array.map (cbv_norm_term info env) vars)), stack) + | IsProd (x,t,c) -> + (VAL(0, mkProd (x, cbv_norm_term info env t, + cbv_norm_term info (subs_lift env) c)), + stack) + | IsAbst (_,_) -> failwith "No longer implemented" (* cbv_stack_term performs weak reduction on constr t under the subs * env, with context stack, i.e. ([env]t stack). First computes weak @@ -392,12 +466,17 @@ and cbv_stack_term info stack env t = let subs = subs_cons (arg,env) in cbv_stack_term info (stack_app args stk) subs b - (* a Fix applied enough, - constructor guard satisfied or Cofix in a Case -> IOTA *) - | (FIXP(op,bv,env,_), stk) - when fixp_reducible (cbv_norm_more info) info.i_flags op stk -> - let (envf,redfix) = contract_fixp env (DOPN(op,bv)) in - cbv_stack_term info stk envf redfix + (* a Fix applied enough -> IOTA *) + | (FIXP(fix,env,_), stk) + when fixp_reducible (cbv_norm_more info) info.i_flags fix stk -> + let (envf,redfix) = contract_fixp env fix in + cbv_stack_term info stk envf redfix + + (* constructor guard satisfied or Cofix in a Case -> IOTA *) + | (COFIXP(cofix,env,_), stk) + when cofixp_reducible (cbv_norm_more info) info.i_flags cofix stk -> + let (envf,redfix) = contract_cofixp env cofix in + cbv_stack_term info stk envf redfix (* constructor in a Case -> IOTA (use red_under because we know there is a Case) *) @@ -414,7 +493,8 @@ and cbv_stack_term info stack env t = (* may be reduced later by application *) | (head, TOP) -> head - | (FIXP(op,bv,env,_), APP(appl,TOP)) -> FIXP(op,bv,env,appl) + | (FIXP(fix,env,_), APP(appl,TOP)) -> FIXP(fix,env,appl) + | (COFIXP(cofix,env,_), APP(appl,TOP)) -> COFIXP(cofix,env,appl) | (CONSTR(n,spi,vars,_), APP(appl,TOP)) -> CONSTR(n,spi,vars,appl) (* definitely a value *) @@ -452,19 +532,28 @@ and cbv_norm_term info env t = (* reduction of a cbv_value to a constr *) and cbv_norm_value info = function (* reduction under binders *) | VAL (n,v) -> lift n v - | LAM (x,a,b,env) -> DOP2(Lambda, cbv_norm_term info env a, - DLAM(x,cbv_norm_term info (subs_lift env) b)) - | FIXP (op,cl,env,args) -> + | LAM (x,a,b,env) -> + mkLambda (x, cbv_norm_term info env a, + cbv_norm_term info (subs_lift env) b) + | FIXP ((lij,(lty,lna,bds)),env,args) -> + applistc + (mkFix (lij, + (Array.map (cbv_norm_term info env) lty, lna, + Array.map (cbv_norm_term info + (subs_liftn (Array.length lty) env)) bds))) + (List.map (cbv_norm_value info) args) + | COFIXP ((j,(lty,lna,bds)),env,args) -> applistc - (DOPN(op, Array.map (cbv_norm_term info env) cl)) + (mkCoFix (j, + (Array.map (cbv_norm_term info env) lty, lna, + Array.map (cbv_norm_term info + (subs_liftn (Array.length lty) env)) bds))) (List.map (cbv_norm_value info) args) | CONSTR (n,spi,vars,args) -> applistc - (DOPN (MutConstruct(spi,n), Array.map (cbv_norm_value info) vars)) + (mkMutConstruct ((spi,n), Array.map (cbv_norm_value info) vars)) (List.map (cbv_norm_value info) args) - - type 'a cbv_infos = (cbv_value, 'a) infos (* constant bodies are normalized at the first expansion *) @@ -499,22 +588,40 @@ let cbv_norm infos constr = * substitution applied to a constr *) -type 'oper freeze = { +type freeze = { mutable norm: bool; - mutable term: 'oper frterm } + mutable term: frterm } -and 'oper frterm = +and frterm = | FRel of int | FVAR of identifier - | FOP0 of 'oper - | FOP1 of 'oper * 'oper freeze - | FOP2 of 'oper * 'oper freeze * 'oper freeze - | FOPN of 'oper * 'oper freeze array - | FOPL of 'oper * 'oper freeze list - | FLAM of name * 'oper freeze * 'oper term * 'oper freeze subs - | FLAMV of name * 'oper freeze array * 'oper term array * 'oper freeze subs - | FLIFT of int * 'oper freeze - | FFROZEN of 'oper term * 'oper freeze subs + | FOP0 of sorts oper + | FOP1 of sorts oper * freeze + | FOP2 of sorts oper * freeze * freeze + | FOPN of sorts oper * freeze array + | FLAM of name * freeze * constr * freeze subs + | FLAMV of name * freeze array * constr array * freeze subs + | FLam of name * type_freeze * freeze * constr * freeze subs + | FPrd of name * type_freeze * freeze * constr * freeze subs + | FLet of name * freeze * type_freeze * freeze * constr * freeze subs + | FLIFT of int * freeze + | FFROZEN of constr * freeze subs + +(* Cas où typed_type est casté en interne +and type_freeze = freeze * sorts + *) +(* Cas où typed_type n'est pas casté *) +and type_freeze = freeze +(**) + +(* +let typed_map f t = f (body_of_type t), level_of_type t +let typed_unmap f (t,s) = make_typed (f t) s +*) +(**) +let typed_map f t = f (body_of_type t) +let typed_unmap f t = make_typed_lazy (f t) (fun _ -> assert false) +(**) let frterm_of v = v.term let is_val v = v.norm @@ -579,8 +686,6 @@ let rec traverse_term env t = term = FOP2 (op, traverse_term env a, traverse_term env b)} | DOPN (op,v) -> { norm = false; term = FOPN (op, Array.map (traverse_term env) v) } - | DOPL (op,l) -> - { norm = false; term = FOPL (op, List.map (traverse_term env) l) } | DLAM (x,a) -> { norm = false; term = FLAM (x, traverse_term (subs_lift env) a, a, env) } @@ -588,9 +693,24 @@ let rec traverse_term env t = { norm = (ve=[||]); term = FLAMV (x, Array.map (traverse_term (subs_lift env)) ve, ve, env) } + | CLam (n,t,c) -> + { norm = false; + term = FLam (n, traverse_type env t, traverse_term (subs_lift env) c, + c, env) } + | CPrd (n,t,c) -> + { norm = false; + term = FPrd (n, traverse_type env t, traverse_term (subs_lift env) c, + c, env) } + | CLet (n,b,t,c) -> + { norm = false; + term = FLet (n, traverse_term env b, traverse_type env t, + traverse_term (subs_lift env) c, + c, env) } + +and traverse_type env = typed_map (traverse_term env) (* Back to regular terms: remove all FFROZEN, keep casts (since this - * fun is not dedicated to the Calulus of Constructions). + * fun is not dedicated to the Calculus of Constructions). *) let rec lift_term_of_freeze lfts v = match v.term with @@ -601,10 +721,19 @@ let rec lift_term_of_freeze lfts v = | FOP2 (op,a,b) -> DOP2 (op, lift_term_of_freeze lfts a, lift_term_of_freeze lfts b) | FOPN (op,ve) -> DOPN (op, Array.map (lift_term_of_freeze lfts) ve) - | FOPL (op,l) -> DOPL (op, List.map (lift_term_of_freeze lfts) l) | FLAM (x,a,_,_) -> DLAM (x, lift_term_of_freeze (el_lift lfts) a) | FLAMV (x,ve,_,_) -> DLAMV (x, Array.map (lift_term_of_freeze (el_lift lfts)) ve) + | FLam (n,t,c,_,_) -> + CLam (n, typed_unmap (lift_term_of_freeze lfts) t, + lift_term_of_freeze (el_lift lfts) c) + | FPrd (n,t,c,_,_) -> + CPrd (n, typed_unmap (lift_term_of_freeze lfts) t, + lift_term_of_freeze (el_lift lfts) c) + | FLet (n,b,t,c,_,_) -> + CLet (n, lift_term_of_freeze lfts b, + typed_unmap (lift_term_of_freeze lfts) t, + lift_term_of_freeze (el_lift lfts) c) | FLIFT (k,a) -> lift_term_of_freeze (el_shft k lfts) a | FFROZEN (t,env) -> let unfv = freeze_assign v (traverse_term env t) in @@ -629,30 +758,34 @@ let rec fstrong unfreeze_fun lfts v = | FOP2 (op,a,b) -> DOP2 (op, fstrong unfreeze_fun lfts a, fstrong unfreeze_fun lfts b) | FOPN (op,ve) -> DOPN (op, Array.map (fstrong unfreeze_fun lfts) ve) - | FOPL (op,l) -> DOPL (op, List.map (fstrong unfreeze_fun lfts) l) | FLAM (x,a,_,_) -> DLAM (x, fstrong unfreeze_fun (el_lift lfts) a) | FLAMV (x,ve,_,_) -> DLAMV (x, Array.map (fstrong unfreeze_fun (el_lift lfts)) ve) + | FLam (n,t,c,_,_) -> + CLam (n, typed_unmap (fstrong unfreeze_fun lfts) t, + fstrong unfreeze_fun (el_lift lfts) c) + | FPrd (n,t,c,_,_) -> + CPrd (n, typed_unmap (fstrong unfreeze_fun lfts) t, + fstrong unfreeze_fun (el_lift lfts) c) + | FLet (n,b,t,c,_,_) -> + CLet (n, fstrong unfreeze_fun lfts b, + typed_unmap (fstrong unfreeze_fun lfts) t, + fstrong unfreeze_fun (el_lift lfts) c) | FLIFT (k,a) -> fstrong unfreeze_fun (el_shft k lfts) a | FFROZEN _ -> anomaly "Closure.fstrong" -(* Build a freeze, which represents the substitution of arg in fun_body. +(* Build a freeze, which represents the substitution of arg in t * Used to constract a beta-redex: - * [^depth](FLAM(S,t)) arg -> [(^depth o S).arg]t - * We also deal with FLIFT that would have been inserted between the - * Lambda and FLAM operators. This never happens in practice. + * [^depth](FLam(S,t)) arg -> [(^depth o S).arg]t *) -let rec contract_subst depth fun_body arg = - match fun_body.term with - FLAM(_,_,t,subs) -> freeze (subs_cons (arg, subs_shft (depth,subs))) t - | FLIFT(k,fb) -> contract_subst (depth+k) fb arg - | _ -> anomaly "Closure.contract_subst: malformed function" +let rec contract_subst depth t subs arg = + freeze (subs_cons (arg, subs_shft (depth,subs))) t (* Calculus of Constructions *) -type fconstr = sorts oper freeze +type fconstr = freeze let inject constr = freeze ESID constr @@ -760,6 +893,7 @@ and whnf_frterm info ft = | None -> { norm = array_for_all is_val vars; term = ft.term }) else ft + | FOPN (MutCase ci,cl) -> if red_under info.i_flags IOTA then let c = unfreeze (infos_under info) cl.(1) in @@ -777,8 +911,11 @@ and whnf_frterm info ft = else ft - | FRel _ | FVAR _ | FOP0 _ -> { norm = true; term = ft.term } - | _ -> ft + | FLet (na,b,_,_,t,subs) -> warning "Should be catch in whnf_term"; + contract_subst 0 t subs b + + | FRel _ | FVAR _ | FOP0 _ -> { norm = true; term = ft.term } + | FOPN _ | FOP2 _ | FOP1 _ | FLam _ | FPrd _ | FLAM _ | FLAMV _ -> ft (* Weak head reduction: case of the application (head appl) *) and whnf_apply info head appl = @@ -788,8 +925,8 @@ and whnf_apply info head appl = else let (lft_hd,whd,args) = strip_frterm 0 head [appl] in match whd.term with - | FOP2(Lambda,_,b) when red_under info.i_flags BETA -> - let vbody = contract_subst lft_hd (unfreeze info b) args.(0) in + | FLam (_,_,_,t,subs) when red_under info.i_flags BETA -> + let vbody = contract_subst lft_hd t subs args.(0) in whnf_apply info vbody (array_tl args) | (FOPN(Fix(reci,bnum), tb) as fx) when red_under info.i_flags IOTA @@ -815,21 +952,30 @@ and whnf_term info env t = | DOP0 op -> {norm = true; term = FOP0 op } | DOP1 (op, nt) -> { norm = false; term = FOP1 (op, freeze env nt) } | DOP2 (Cast,ct,c) -> whnf_term info env ct (* remove outer casts *) - | DOP2 (op,a,b) -> (* Lambda Prod *) - { norm = false; term = FOP2 (op, freeze env a, freeze env b) } + | DOP2 (_,_,_) -> assert false (* Lambda|Prod made explicit *) | DOPN ((AppL | Const _ | Evar _ | Abst _ | MutCase _) as op, ve) -> whnf_frterm info { norm = false; term = FOPN (op, freeze_vect env ve) } | DOPN ((MutInd _ | MutConstruct _) as op,v) -> { norm = (v=[||]); term = FOPN (op, freeze_vect env v) } | DOPN (op,v) -> { norm = false; term = FOPN (op, freeze_vect env v) } (* Fix CoFix *) - | DOPL (op,l) -> { norm = false; term = FOPL (op, freeze_list env l) } | DLAM (x,a) -> { norm = false; term = FLAM (x, freeze (subs_lift env) a, a, env) } | DLAMV (x,ve) -> { norm = (ve=[||]); term = FLAMV (x, freeze_vect (subs_lift env) ve, ve, env) } - + | CLam (n,t,c) -> + { norm = false; + term = FLam (n, typed_map (freeze env) t, freeze (subs_lift env) c, + c, env) } + | CPrd (n,t,c) -> + { norm = false; + term = FPrd (n, typed_map (freeze env) t, freeze (subs_lift env) c, + c, env) } + + (* WHNF removes LetIn (see Paula Severi) *) + | CLet (n,b,t,c) -> whnf_term info (subs_cons (freeze env b,env)) c + (* parameterized norm *) let norm_val info v = if !stats then begin |
