From a0cfa4f118023d35b767a999d5a2ac4b082857b4 Mon Sep 17 00:00:00 2001 From: Samuel Mimram Date: Fri, 25 Jul 2008 15:12:53 +0200 Subject: Imported Upstream version 8.2~beta3+dfsg --- pretyping/tacred.ml | 524 +++++++++++++++++++++++++--------------------------- 1 file changed, 247 insertions(+), 277 deletions(-) (limited to 'pretyping/tacred.ml') diff --git a/pretyping/tacred.ml b/pretyping/tacred.ml index 64e9ebec..50401502 100644 --- a/pretyping/tacred.ml +++ b/pretyping/tacred.ml @@ -6,7 +6,7 @@ (* * GNU Lesser General Public License Version 2.1 *) (************************************************************************) -(* $Id: tacred.ml 10135 2007-09-21 14:28:12Z herbelin $ *) +(* $Id: tacred.ml 11094 2008-06-10 19:35:23Z herbelin $ *) open Pp open Util @@ -35,18 +35,23 @@ exception ReductionTacticError of reduction_tactic_error exception Elimconst exception Redelimination -let is_evaluable env ref = - match ref with - EvalConstRef kn -> - let (ids,kns) = Conv_oracle.freeze() in - Cpred.mem kn kns & - let cb = Environ.lookup_constant kn env in - cb.const_body <> None & not cb.const_opaque - | EvalVarRef id -> - let (ids,sps) = Conv_oracle.freeze() in - Idpred.mem id ids & - let (_,value,_) = Environ.lookup_named id env in - value <> None +let is_evaluable env = function + | EvalConstRef kn -> + is_transparent (ConstKey kn) && + let cb = Environ.lookup_constant kn env in + cb.const_body <> None & not cb.const_opaque + | EvalVarRef id -> + is_transparent (VarKey id) && + let (_,value,_) = Environ.lookup_named id env in + value <> None + +let value_of_evaluable_ref env = function + | EvalConstRef con -> constant_value env con + | EvalVarRef id -> Option.get (pi2 (lookup_named id env)) + +let constr_of_evaluable_ref = function + | EvalConstRef con -> mkConst con + | EvalVarRef id -> mkVar id type evaluable_reference = | EvalConst of constant @@ -80,7 +85,7 @@ let reference_opt_value sigma env = function v | EvalRel n -> let (_,v,_) = lookup_rel n env in - option_map (lift n) v + Option.map (lift n) v | EvalEvar ev -> Evd.existential_opt_value sigma ev exception NotEvaluable @@ -90,8 +95,8 @@ let reference_value sigma env c = | Some d -> d (************************************************************************) -(* Reduction of constant hiding fixpoints (e.g. for Simpl). The trick *) -(* is to reuse the name of the function after reduction of the fixpoint *) +(* Reduction of constants hiding a fixpoint (e.g. for "simpl" tactic). *) +(* One reuses the name of the function after reduction of the fixpoint *) type constant_evaluation = | EliminationFix of int * (int * (int * constr) list * int) @@ -103,7 +108,6 @@ type constant_evaluation = (* We use a cache registered as a global table *) - module CstOrdered = struct type t = constant @@ -325,20 +329,18 @@ let make_elim_fun (names,(nbfix,lv,n)) largs = list_fold_left_i (fun q (* j from comment is n+1-q *) c (ij,tij) -> let subst = List.map (lift (-q)) (list_firstn (n-ij) la) in let tij' = substl (List.rev subst) tij in - mkLambda (x,tij',c) - ) 1 body (List.rev lv) + mkLambda (x,tij',c)) 1 body (List.rev lv) in Some g -(* [f] is convertible to [Fix(recindices,bodynum),bodyvect)] make - the reduction using this extra information *) +(* [f] is convertible to [Fix(recindices,bodynum),bodyvect)]: + do so that the reduction uses this extra information *) let contract_fix_use_function f - ((recindices,bodynum),(types,names,bodies as typedbodies)) = + ((recindices,bodynum),(_names,_types,bodies as typedbodies)) = let nbodies = Array.length recindices in let make_Fi j = match f j with | None -> mkFix((recindices,j),typedbodies) | Some c -> c in -(* match List.nth names j with Name id -> f id | _ -> assert false in*) let lbodies = list_tabulate make_Fi nbodies in substl (List.rev lbodies) bodies.(bodynum) @@ -378,7 +380,7 @@ let reduce_mind_case_use_function func env mia = fun i -> if i = bodynum then Some func else match names.(i) with - | Anonymous -> None + | Anonymous -> None | Name id -> (* In case of a call to another component of a block of mutual inductive, try to reuse the global name if @@ -419,20 +421,23 @@ let special_red_case sigma env whfun (ci, p, c, lf) = in redrec (c, empty_stack) +(* [red_elim_const] contracts iota/fix/cofix redexes hidden behind + constants by keeping the name of the constants in the recursive calls; + it fails if no redex is around *) let rec red_elim_const env sigma ref largs = match reference_eval sigma env ref with | EliminationCases n when stack_args_size largs >= n -> let c = reference_value sigma env ref in let c', lrest = whd_betadelta_state env sigma (c,largs) in - (special_red_case sigma env (construct_const env sigma) (destCase c'), - lrest) + let whfun = whd_simpl_state env sigma in + (special_red_case sigma env whfun (destCase c'), lrest) | EliminationFix (min,infos) when stack_args_size largs >=min -> let c = reference_value sigma env ref in let d, lrest = whd_betadelta_state env sigma (c,largs) in let f = make_elim_fun ([|Some ref|],infos) largs in - let co = construct_const env sigma in - (match reduce_fix_use_function f co (destFix d) lrest with + let whfun = whd_construct_state env sigma in + (match reduce_fix_use_function f whfun (destFix d) lrest with | NotReducible -> raise Redelimination | Reduced (c,rest) -> (nf_beta c, rest)) | EliminationMutualFix (min,refgoal,refinfos) @@ -447,53 +452,65 @@ let rec red_elim_const env sigma ref largs = let (_, midargs as s) = descend ref largs in let d, lrest = whd_betadelta_state env sigma s in let f = make_elim_fun refinfos midargs in - let co = construct_const env sigma in - (match reduce_fix_use_function f co (destFix d) lrest with + let whfun = whd_construct_state env sigma in + (match reduce_fix_use_function f whfun (destFix d) lrest with | NotReducible -> raise Redelimination | Reduced (c,rest) -> (nf_beta c, rest)) | _ -> raise Redelimination -and construct_const env sigma = - let rec hnfstack (x, stack as s) = +(* reduce to whd normal form or to an applied constant that does not hide + a reducible iota/fix/cofix redex (the "simpl" tactic) *) + +and whd_simpl_state env sigma s = + let rec redrec (x, stack as s) = match kind_of_term x with - | Cast (c,_,_) -> hnfstack (c, stack) - | App (f,cl) -> hnfstack (f, append_stack cl stack) - | Lambda (id,t,c) -> + | Lambda (na,t,c) -> (match decomp_stack stack with - | None -> assert false - | Some (c',rest) -> - stacklam hnfstack [c'] c rest) - | LetIn (n,b,t,c) -> stacklam hnfstack [b] c stack + | None -> s + | Some (a,rest) -> stacklam redrec [a] c rest) + | LetIn (n,b,t,c) -> stacklam redrec [b] c stack + | App (f,cl) -> redrec (f, append_stack cl stack) + | Cast (c,_,_) -> redrec (c, stack) | Case (ci,p,c,lf) -> - hnfstack - (special_red_case sigma env - (construct_const env sigma) (ci,p,c,lf), stack) - | Construct _ -> s - | CoFix _ -> s - | Fix fix -> - (match reduce_fix hnfstack fix stack with - | Reduced s' -> hnfstack s' - | NotReducible -> raise Redelimination) + (try + redrec (special_red_case sigma env redrec (ci,p,c,lf), stack) + with + Redelimination -> s) + | Fix fix -> + (try match reduce_fix (whd_construct_state env sigma) fix stack with + | Reduced s' -> redrec s' + | NotReducible -> s + with Redelimination -> s) | _ when isEvalRef env x -> let ref = destEvalRef x in (try - hnfstack (red_elim_const env sigma ref stack) + redrec (red_elim_const env sigma ref stack) with Redelimination -> - (match reference_opt_value sigma env ref with - | Some cval -> - (match kind_of_term cval with - | CoFix _ -> s - | _ -> hnfstack (cval, stack)) - | None -> - raise Redelimination)) - | _ -> raise Redelimination + s) + | _ -> s in - hnfstack + redrec s + +(* reduce until finding an applied constructor or fail *) + +and whd_construct_state env sigma s = + let (constr, cargs as s') = whd_simpl_state env sigma s in + if reducible_mind_case constr then s' + else if isEvalRef env constr then + let ref = destEvalRef constr in + match reference_opt_value sigma env ref with + | None -> raise Redelimination + | Some gvalue -> whd_construct_state env sigma (gvalue, cargs) + else + raise Redelimination (************************************************************************) (* Special Purpose Reduction Strategies *) -(* Red reduction tactic: reduction to a product *) +(* Red reduction tactic: one step of delta reduction + full + beta-iota-fix-cofix-zeta-cast at the head of the conclusion of a + sequence of products; fails if no delta redex is around +*) let try_red_product env sigma c = let simpfun = clos_norm_flags betaiotazeta env sigma in @@ -528,97 +545,105 @@ let red_product env sigma c = try try_red_product env sigma c with Redelimination -> error "Not reducible" -let hnf_constr env sigma c = - let rec redrec (x, largs as s) = +(* +(* This old version of hnf uses betadeltaiota instead of itself (resp + whd_construct_state) to reduce the argument of Case (resp Fix); + The new version uses the "simpl" strategy instead. For instance, + + Variable n:nat. + Eval hnf in match (plus (S n) O) with S n => n | _ => O end. + + returned + + (fix plus (n m : nat) {struct n} : nat := + match n with + | O => m + | S p => S (plus p m) + end) n 0 + + while the new version returns (plus n O) + *) + +let whd_simpl_orelse_delta_but_fix_old env sigma c = + let whd_all = whd_betadeltaiota_state env sigma in + let rec redrec (x, stack as s) = match kind_of_term x with - | Lambda (n,t,c) -> - (match decomp_stack largs with - | None -> app_stack s - | Some (a,rest) -> - stacklam redrec [a] c rest) - | LetIn (n,b,t,c) -> stacklam redrec [b] c largs - | App (f,cl) -> redrec (f, append_stack cl largs) - | Cast (c,_,_) -> redrec (c, largs) - | Case (ci,p,c,lf) -> + | Lambda (na,t,c) -> + (match decomp_stack stack with + | None -> s + | Some (a,rest) -> stacklam redrec [a] c rest) + | LetIn (n,b,t,c) -> stacklam redrec [b] c stack + | App (f,cl) -> redrec (f, append_stack cl stack) + | Cast (c,_,_) -> redrec (c, stack) + | Case (ci,p,d,lf) -> (try - redrec - (special_red_case sigma env (whd_betadeltaiota_state env sigma) - (ci, p, c, lf), largs) + redrec (special_red_case sigma env whd_all (ci,p,d,lf), stack) with Redelimination -> - app_stack s) + s) | Fix fix -> - (match reduce_fix (whd_betadeltaiota_state env sigma) fix largs with + (match reduce_fix whd_all fix stack with | Reduced s' -> redrec s' - | NotReducible -> app_stack s) + | NotReducible -> s) | _ when isEvalRef env x -> let ref = destEvalRef x in (try - let (c',lrest) = red_elim_const env sigma ref largs in - redrec (c', lrest) + redrec (red_elim_const env sigma ref stack) with Redelimination -> match reference_opt_value sigma env ref with | Some c -> (match kind_of_term (snd (decompose_lam c)) with - | CoFix _ | Fix _ -> app_stack (x,largs) - | _ -> redrec (c, largs)) - | None -> app_stack s) - | _ -> app_stack s - in - redrec (c, empty_stack) + | CoFix _ | Fix _ -> s + | _ -> redrec (c, stack)) + | None -> s) + | _ -> s + in app_stack (redrec (c, empty_stack)) +*) -(* Simpl reduction tactic: same as simplify, but also reduces - elimination constants *) +(* Same as [whd_simpl] but also reduces constants that do not hide a + reducible fix, but does this reduction of constants only until it + it immediately hides a non reducible fix or a cofix *) -let whd_nf env sigma c = - let rec nf_app (c, stack as s) = - match kind_of_term c with - | Lambda (name,c1,c2) -> - (match decomp_stack stack with - | None -> (c,empty_stack) - | Some (a1,rest) -> - stacklam nf_app [a1] c2 rest) - | LetIn (n,b,t,c) -> stacklam nf_app [b] c stack - | App (f,cl) -> nf_app (f, append_stack cl stack) - | Cast (c,_,_) -> nf_app (c, stack) - | Case (ci,p,d,lf) -> - (try - nf_app (special_red_case sigma env nf_app (ci,p,d,lf), stack) - with Redelimination -> - s) - | Fix fix -> - (match reduce_fix nf_app fix stack with - | Reduced s' -> nf_app s' - | NotReducible -> s) - | _ when isEvalRef env c -> - (try - nf_app (red_elim_const env sigma (destEvalRef c) stack) - with Redelimination -> - s) - | _ -> s - in - app_stack (nf_app (c, empty_stack)) +let whd_simpl_orelse_delta_but_fix env sigma c = + let rec redrec s = + let (constr, stack as s') = whd_simpl_state env sigma s in + if isEvalRef env constr then + match reference_opt_value sigma env (destEvalRef constr) with + | Some c -> + (match kind_of_term (snd (decompose_lam c)) with + | CoFix _ | Fix _ -> s' + | _ -> redrec (c, stack)) + | None -> s' + else s' + in app_stack (redrec (c, empty_stack)) + +let hnf_constr = whd_simpl_orelse_delta_but_fix + +(* The "simpl" reduction tactic *) + +let whd_simpl env sigma c = + app_stack (whd_simpl_state env sigma (c, empty_stack)) -let nf env sigma c = strong whd_nf env sigma c +let simpl env sigma c = strong whd_simpl env sigma c + +let nf = simpl (* Compatibility *) + +(* Reduction at specific subterms *) let is_head c t = match kind_of_term t with | App (f,_) -> f = c | _ -> false -let contextually byhead (locs,c) f env sigma t = +let contextually byhead ((nowhere_except_in,locs),c) f env sigma t = let maxocc = List.fold_right max locs 0 in let pos = ref 1 in - let except = List.exists (fun n -> n<0) locs in - if except & (List.exists (fun n -> n>=0) locs) - then error "mixing of positive and negative occurences" - else - let rec traverse (env,c as envc) t = - if locs <> [] & (not except) & (!pos > maxocc) then t + let rec traverse (env,c as envc) t = + if nowhere_except_in & (!pos > maxocc) then t else if (not byhead & eq_constr c t) or (byhead & is_head c t) then let ok = - if except then not (List.mem (- !pos) locs) - else (locs = [] or List.mem !pos locs) in + if nowhere_except_in then List.mem !pos locs + else not (List.mem !pos locs) in incr pos; if ok then f env sigma t @@ -634,110 +659,34 @@ let contextually byhead (locs,c) f env sigma t = traverse envc t in let t' = traverse (env,c) t in - if locs <> [] & List.exists (fun o -> o >= !pos or o <= - !pos) locs then - error_invalid_occurrence locs; + if List.exists (fun o -> o >= !pos) locs then error_invalid_occurrence locs; t' (* linear bindings (following pretty-printer) of the value of name in c. * n is the number of the next occurence of name. * ol is the occurence list to find. *) -let rec substlin env name n ol c = - match kind_of_term c with - | Const kn when EvalConstRef kn = name -> - if List.hd ol = n then - try - (n+1, List.tl ol, constant_value env kn) - with - NotEvaluableConst _ -> - errorlabstrm "substlin" - (pr_con kn ++ str " is not a defined constant") - else - ((n+1), ol, c) - - | Var id when EvalVarRef id = name -> - if List.hd ol = n then - match lookup_named id env with - | (_,Some c,_) -> (n+1, List.tl ol, c) - | _ -> - errorlabstrm "substlin" - (pr_id id ++ str " is not a defined constant") - else - ((n+1), ol, c) - - (* INEFFICIENT: OPTIMIZE *) - | App (c1,cl) -> - Array.fold_left - (fun (n1,ol1,c1') c2 -> - (match ol1 with - | [] -> (n1,[],applist(c1',[c2])) - | _ -> - let (n2,ol2,c2') = substlin env name n1 ol1 c2 in - (n2,ol2,applist(c1',[c2'])))) - (substlin env name n ol c1) cl - - | Lambda (na,c1,c2) -> - let (n1,ol1,c1') = substlin env name n ol c1 in - (match ol1 with - | [] -> (n1,[],mkLambda (na,c1',c2)) - | _ -> - let (n2,ol2,c2') = substlin env name n1 ol1 c2 in - (n2,ol2,mkLambda (na,c1',c2'))) - - | LetIn (na,c1,t,c2) -> - let (n1,ol1,c1') = substlin env name n ol c1 in - (match ol1 with - | [] -> (n1,[],mkLetIn (na,c1',t,c2)) - | _ -> - let (n2,ol2,c2') = substlin env name n1 ol1 c2 in - (n2,ol2,mkLetIn (na,c1',t,c2'))) - - | Prod (na,c1,c2) -> - let (n1,ol1,c1') = substlin env name n ol c1 in - (match ol1 with - | [] -> (n1,[],mkProd (na,c1',c2)) - | _ -> - let (n2,ol2,c2') = substlin env name n1 ol1 c2 in - (n2,ol2,mkProd (na,c1',c2'))) - - | Case (ci,p,d,llf) -> - let rec substlist nn oll = function - | [] -> (nn,oll,[]) - | f::lfe -> - let (nn1,oll1,f') = substlin env name nn oll f in - (match oll1 with - | [] -> (nn1,[],f'::lfe) - | _ -> - let (nn2,oll2,lfe') = substlist nn1 oll1 lfe in - (nn2,oll2,f'::lfe')) - in - (* p is printed after d in v8 syntax *) - let (n1,ol1,d') = substlin env name n ol d in - (match ol1 with - | [] -> (n1,[],mkCase (ci, p, d', llf)) - | _ -> - let (n2,ol2,p') = substlin env name n1 ol1 p in - (match ol2 with - | [] -> (n2,[],mkCase (ci, p', d', llf)) - | _ -> - let (n3,ol3,lf') = substlist n2 ol2 (Array.to_list llf) - in (n3,ol3,mkCase (ci, p', d', Array.of_list lf')))) - - | Cast (c1,k,c2) -> - let (n1,ol1,c1') = substlin env name n ol c1 in - (match ol1 with - | [] -> (n1,[],mkCast (c1',k,c2)) - | _ -> - let (n2,ol2,c2') = substlin env name n1 ol1 c2 in - (n2,ol2,mkCast (c1',k,c2'))) - - | Fix _ -> - (warning "do not consider occurrences inside fixpoints"; (n,ol,c)) - - | CoFix _ -> - (warning "do not consider occurrences inside cofixpoints"; (n,ol,c)) - | (Rel _|Meta _|Var _|Sort _ - |Evar _|Const _|Ind _|Construct _) -> (n,ol,c) +let substlin env evalref n (nowhere_except_in,locs) c = + let maxocc = List.fold_right max locs 0 in + let pos = ref n in + assert (List.for_all (fun x -> x >= 0) locs); + let value = value_of_evaluable_ref env evalref in + let term = constr_of_evaluable_ref evalref in + let rec substrec () c = + if nowhere_except_in & !pos > maxocc then c + else if c = term then + let ok = + if nowhere_except_in then List.mem !pos locs + else not (List.mem !pos locs) in + incr pos; + if ok then value else c + else + map_constr_with_binders_left_to_right + (fun _ () -> ()) + substrec () c + in + let t' = substrec () c in + (!pos, t') let string_of_evaluable_ref env = function | EvalVarRef id -> string_of_id id @@ -755,16 +704,15 @@ let unfold env sigma name = * Unfolds the constant name in a term c following a list of occurrences occl. * at the occurrences of occ_list. If occ_list is empty, unfold all occurences. * Performs a betaiota reduction after unfolding. *) -let unfoldoccs env sigma (occl,name) c = - match occl with - | [] -> unfold env sigma name c - | l -> - match substlin env name 1 (Sort.list (<) l) c with - | (_,[],uc) -> nf_betaiota uc - | (1,_,_) -> - error ((string_of_evaluable_ref env name)^" does not occur") - | (_,l,_) -> - error_invalid_occurrence l +let unfoldoccs env sigma ((nowhere_except_in,locs as plocs),name) c = + if locs = [] then if nowhere_except_in then c else unfold env sigma name c + else + let (nbocc,uc) = substlin env name 1 plocs c in + if nbocc = 1 then + error ((string_of_evaluable_ref env name)^" does not occur"); + let rest = List.filter (fun o -> o >= nbocc) locs in + if rest <> [] then error_invalid_occurrence rest; + nf_betaiota uc (* Unfold reduction tactic: *) let unfoldn loccname env sigma c = @@ -775,7 +723,17 @@ let fold_one_com com env sigma c = let rcom = try red_product env sigma com with Redelimination -> error "Not reducible" in - subst1 com (subst_term rcom c) + (* Reason first on the beta-iota-zeta normal form of the constant as + unfold produces it, so that the "unfold f; fold f" configuration works + to refold fix expressions *) + let a = subst_term (clos_norm_flags unfold_side_red env sigma rcom) c in + if not (eq_constr a c) then + subst1 com a + else + (* Then reason on the non beta-iota-zeta form for compatibility - + even if it is probably a useless configuration *) + let a = subst_term rcom c in + subst1 com a let fold_commands cl env sigma c = List.fold_right (fun com -> fold_one_com com env sigma) (List.rev cl) c @@ -815,70 +773,81 @@ let pattern_occs loccs_trm env sigma c = (* Used in several tactics. *) +(* put t as t'=(x1:A1)..(xn:An)B with B an inductive definition of name name + return name, B and t' *) + +let reduce_to_ind_gen allow_product env sigma t = + let rec elimrec env t l = + let t = hnf_constr env sigma t in + match kind_of_term (fst (decompose_app t)) with + | Ind ind-> (ind, it_mkProd_or_LetIn t l) + | Prod (n,ty,t') -> + if allow_product then + elimrec (push_rel (n,None,ty) env) t' ((n,None,ty)::l) + else + errorlabstrm "" (str"Not an inductive definition") + | _ -> + (* Last chance: we allow to bypass the Opaque flag (as it + was partially the case between V5.10 and V8.1 *) + let t' = whd_betadeltaiota env sigma t in + match kind_of_term (fst (decompose_app t')) with + | Ind ind-> (ind, it_mkProd_or_LetIn t' l) + | _ -> errorlabstrm "" (str"Not an inductive product") + in + elimrec env t [] + +let reduce_to_quantified_ind x = reduce_to_ind_gen true x +let reduce_to_atomic_ind x = reduce_to_ind_gen false x + +(* Reduce the weak-head redex [beta,iota/fix/cofix[all],cast,zeta,simpl/delta] + or raise [NotStepReducible] if not a weak-head redex *) + exception NotStepReducible let one_step_reduce env sigma c = - let rec redrec (x, largs) = + let rec redrec (x, stack) = match kind_of_term x with | Lambda (n,t,c) -> - (match decomp_stack largs with + (match decomp_stack stack with | None -> raise NotStepReducible | Some (a,rest) -> (subst1 a c, rest)) - | App (f,cl) -> redrec (f, append_stack cl largs) - | LetIn (_,f,_,cl) -> (subst1 f cl,largs) + | App (f,cl) -> redrec (f, append_stack cl stack) + | LetIn (_,f,_,cl) -> (subst1 f cl,stack) + | Cast (c,_,_) -> redrec (c,stack) | Case (ci,p,c,lf) -> (try - (special_red_case sigma env (whd_betadeltaiota_state env sigma) - (ci,p,c,lf), largs) + (special_red_case sigma env (whd_simpl_state env sigma) + (ci,p,c,lf), stack) with Redelimination -> raise NotStepReducible) | Fix fix -> - (match reduce_fix (whd_betadeltaiota_state env sigma) fix largs with + (match reduce_fix (whd_construct_state env sigma) fix stack with | Reduced s' -> s' | NotReducible -> raise NotStepReducible) - | Cast (c,_,_) -> redrec (c,largs) | _ when isEvalRef env x -> - let ref = - try destEvalRef x - with Redelimination -> raise NotStepReducible in + let ref = destEvalRef x in (try - red_elim_const env sigma ref largs + red_elim_const env sigma ref stack with Redelimination -> match reference_opt_value sigma env ref with - | Some d -> d, largs + | Some d -> d, stack | None -> raise NotStepReducible) | _ -> raise NotStepReducible in app_stack (redrec (c, empty_stack)) -(* put t as t'=(x1:A1)..(xn:An)B with B an inductive definition of name name - return name, B and t' *) +let isIndRef = function IndRef _ -> true | _ -> false -let reduce_to_ind_gen allow_product env sigma t = - let rec elimrec env t l = - let c, _ = Reductionops.whd_stack t in - match kind_of_term c with - | Ind (mind,args) -> ((mind,args),it_mkProd_or_LetIn t l) - | Prod (n,ty,t') -> - if allow_product then - elimrec (push_rel (n,None,t) env) t' ((n,None,ty)::l) - else - errorlabstrm "tactics__reduce_to_mind" - (str"Not an inductive definition") - | _ -> - (try - let t' = nf_betaiota (one_step_reduce env sigma t) in - elimrec env t' l - with NotStepReducible -> - errorlabstrm "tactics__reduce_to_mind" - (str"Not an inductive product")) - in - elimrec env t [] - -let reduce_to_quantified_ind x = reduce_to_ind_gen true x -let reduce_to_atomic_ind x = reduce_to_ind_gen false x - -let reduce_to_ref_gen allow_product env sigma ref t = +let reduce_to_ref_gen allow_product env sigma ref t = + if isIndRef ref then + let (mind,t) = reduce_to_ind_gen allow_product env sigma t in + if IndRef mind <> ref then + errorlabstrm "" (str "Cannot recognize a statement based on " ++ + Nametab.pr_global_env Idset.empty ref) + else + t + else + (* lazily reduces to match the head of [t] with the expected [ref] *) let rec elimrec env t l = let c, _ = Reductionops.whd_stack t in match kind_of_term c with @@ -886,8 +855,9 @@ let reduce_to_ref_gen allow_product env sigma ref t = if allow_product then elimrec (push_rel (n,None,t) env) t' ((n,None,ty)::l) else - errorlabstrm "Tactics.reduce_to_ref_gen" - (str"Not an induction object of atomic type") + errorlabstrm "" + (str "Cannot recognize an atomic statement based on " ++ + Nametab.pr_global_env Idset.empty ref) | _ -> try if global_of_constr c = ref @@ -899,8 +869,8 @@ let reduce_to_ref_gen allow_product env sigma ref t = elimrec env t' l with NotStepReducible -> errorlabstrm "" - (str "Not a statement of conclusion " ++ - Nametab.pr_global_env Idset.empty ref) + (str "Cannot recognize a statement based on " ++ + Nametab.pr_global_env Idset.empty ref) in elimrec env t [] -- cgit v1.2.3