diff options
| author | herbelin | 2011-07-16 20:35:13 +0000 |
|---|---|---|
| committer | herbelin | 2011-07-16 20:35:13 +0000 |
| commit | 6a4c604f17719bd782efd71517a865d327ec6b0e (patch) | |
| tree | 3356c3aa6a98cfe3681da988428f812a5628fb41 /tactics | |
| parent | 928070fda675de585b40e8f8eca500d2695f09b9 (diff) | |
Use "subst_one" instead of "multi_rewrite" to implement intro-patterns -> and <- when a variable is about to be substituted (subst_one rewrite the whole context at once, while multi_rewrite rewrites each hyp independently, what may break typing in case of dependencies). Also generalize "dependent rewrite" to "sig" (to be done: generalize it to eq_dep, eq_dep1, and any dependent tuple).
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@14279 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'tactics')
| -rw-r--r-- | tactics/equality.ml | 61 | ||||
| -rw-r--r-- | tactics/hipattern.ml4 | 4 | ||||
| -rw-r--r-- | tactics/tactics.ml | 14 | ||||
| -rw-r--r-- | tactics/tactics.mli | 3 |
4 files changed, 55 insertions, 27 deletions
diff --git a/tactics/equality.ml b/tactics/equality.ml index 51265d7231..9d2e3c8e81 100644 --- a/tactics/equality.ml +++ b/tactics/equality.ml @@ -1390,29 +1390,16 @@ let is_eq_x gl x (id,_,c) = with PatternMatchingFailure -> () -let subst_one dep_proof_ok x gl = - let hyps = pf_hyps gl in - let (_,xval,_) = pf_get_hyp gl x in - (* If x has a body, simply replace x with body and clear x *) - if xval <> None then tclTHEN (unfold_body x) (clear [x]) gl else - (* x is a variable: *) - let varx = mkVar x in - (* Find a non-recursive definition for x *) - let (hyp,rhs,dir) = - try - let test hyp _ = is_eq_x gl varx hyp in - Sign.fold_named_context test ~init:() hyps; - errorlabstrm "Subst" - (str "Cannot find any non-recursive equality over " ++ pr_id x ++ - str".") - with FoundHyp res -> res - in +(* Rewrite "hyp:x=rhs" or "hyp:rhs=x" (if dir=false) everywhere and + erase hyp and x; proceed by generalizing all dep hyps *) + +let subst_one dep_proof_ok x (hyp,rhs,dir) gl = (* The set of hypotheses using x *) let depdecls = let test (id,_,c as dcl) = if id <> hyp && occur_var_in_decl (pf_env gl) x dcl then dcl else failwith "caught" in - List.rev (map_succeed test hyps) in + List.rev (map_succeed test (pf_hyps gl)) in let dephyps = List.map (fun (id,_,_) -> id) depdecls in (* Decides if x appears in conclusion *) let depconcl = occur_var (pf_env gl) x (pf_concl gl) in @@ -1428,8 +1415,8 @@ let subst_one dep_proof_ok x gl = (id,None,_) -> intro_using id | (id,Some hval,htyp) -> letin_tac None (Name id) - (replace_term varx rhs hval) - (Some (replace_term varx rhs htyp)) nowhere + (replace_term (mkVar x) rhs hval) + (Some (replace_term (mkVar x) rhs htyp)) nowhere in let need_rewrite = dephyps <> [] || depconcl in tclTHENLIST @@ -1438,13 +1425,37 @@ let subst_one dep_proof_ok x gl = general_rewrite dir all_occurrences true dep_proof_ok (mkVar hyp); thin dephyps; tclMAP introtac depdecls] - else - [thin dephyps; - tclMAP introtac depdecls]) @ + else + [tclIDTAC]) @ [tclTRY (clear [x;hyp])]) gl +(* Look for an hypothesis hyp of the form "x=rhs" or "rhs=x", rewrite + it everywhere, and erase hyp and x; proceed by generalizing all dep hyps *) + +let subst_one_var dep_proof_ok x gl = + let hyps = pf_hyps gl in + let (_,xval,_) = pf_get_hyp gl x in + (* If x has a body, simply replace x with body and clear x *) + if xval <> None then tclTHEN (unfold_body x) (clear [x]) gl else + (* x is a variable: *) + let varx = mkVar x in + (* Find a non-recursive definition for x *) + let (hyp,rhs,dir) = + try + let test hyp _ = is_eq_x gl varx hyp in + Sign.fold_named_context test ~init:() hyps; + errorlabstrm "Subst" + (str "Cannot find any non-recursive equality over " ++ pr_id x ++ + str".") + with FoundHyp res -> res in + subst_one dep_proof_ok x (hyp,rhs,dir) gl + let subst_gen dep_proof_ok ids = - tclTHEN tclNORMEVAR (tclMAP (subst_one dep_proof_ok) ids) + tclTHEN tclNORMEVAR (tclMAP (subst_one_var dep_proof_ok) ids) + +(* For every x, look for an hypothesis hyp of the form "x=rhs" or "rhs=x", + rewrite it everywhere, and erase hyp and x; proceed by generalizing + all dep hyps *) let subst = subst_gen true @@ -1521,3 +1532,5 @@ let replace_multi_term dir_opt c = let _ = Tactics.register_general_multi_rewrite (fun b evars t cls -> general_multi_rewrite b evars t cls) + +let _ = Tactics.register_subst_one (fun b -> subst_one b) diff --git a/tactics/hipattern.ml4 b/tactics/hipattern.ml4 index e02ddb926b..f0773f793d 100644 --- a/tactics/hipattern.ml4 +++ b/tactics/hipattern.ml4 @@ -423,6 +423,7 @@ let dest_nf_eq gls eqn = (* Patterns "(existS ?1 ?2 ?3 ?4)" and "(existT ?1 ?2 ?3 ?4)" *) let coq_ex_pattern_gen ex = lazy PATTERN [ %ex ?X1 ?X2 ?X3 ?X4 ] let coq_existT_pattern = coq_ex_pattern_gen coq_existT_ref +let coq_exist_pattern = coq_ex_pattern_gen coq_exist_ref let match_sigma ex ex_pat = match matches (Lazy.force ex_pat) ex with @@ -434,7 +435,8 @@ let match_sigma ex ex_pat = let find_sigma_data_decompose ex = (* fails with PatternMatchingFailure *) first_match (match_sigma ex) - [coq_existT_pattern, build_sigma_type] + [coq_existT_pattern, build_sigma_type; + coq_exist_pattern, build_sigma] (* Pattern "(sig ?1 ?2)" *) let coq_sig_pattern = lazy PATTERN [ %coq_sig_ref ?X1 ?X2 ] diff --git a/tactics/tactics.ml b/tactics/tactics.ml index 97928c87c2..ce27649d22 100644 --- a/tactics/tactics.ml +++ b/tactics/tactics.ml @@ -1222,12 +1222,20 @@ let simplest_split = split NoBindings (* Decomposing introductions *) (*****************************) +(* Rewriting function for rewriting one hypothesis at the time *) let forward_general_multi_rewrite = ref (fun _ -> failwith "general_multi_rewrite undefined") +(* Rewriting function for substitution (x=t) everywhere at the same time *) +let forward_subst_one = + ref (fun _ -> failwith "subst_one undefined") + let register_general_multi_rewrite f = forward_general_multi_rewrite := f +let register_subst_one f = + forward_subst_one := f + let error_unexpected_extra_pattern loc nb pat = let s1,s2,s3 = match pat with | IntroIdentifier _ -> "name", (plural nb " introduction pattern"), "no" @@ -1261,6 +1269,8 @@ let intro_or_and_pattern loc b ll l' tac id gl = let rewrite_hyp l2r id gl = let rew_on l2r = !forward_general_multi_rewrite l2r false (mkVar id,NoBindings) in + let subst_on l2r x rhs = + !forward_subst_one true x (id,rhs,l2r) in let clear_var_and_eq c = tclTRY (tclTHEN (clear [id]) (tclTRY (clear [destVar c]))) in let t = pf_whd_betadeltaiota gl (pf_type_of gl (mkVar id)) in @@ -1268,9 +1278,9 @@ let rewrite_hyp l2r id gl = match match_with_equality_type t with | Some (hdcncl,[_;lhs;rhs]) -> if l2r & isVar lhs & not (occur_var (pf_env gl) (destVar lhs) rhs) then - tclTHEN (rew_on l2r allHypsAndConcl) (clear_var_and_eq lhs) gl + subst_on l2r (destVar lhs) rhs gl else if not l2r & isVar rhs & not (occur_var (pf_env gl) (destVar rhs) lhs) then - tclTHEN (rew_on l2r allHypsAndConcl) (clear_var_and_eq rhs) gl + subst_on l2r (destVar rhs) lhs gl else tclTHEN (rew_on l2r onConcl) (tclTRY (clear [id])) gl | Some (hdcncl,[c]) -> diff --git a/tactics/tactics.mli b/tactics/tactics.mli index c52c145879..e148c5a2d6 100644 --- a/tactics/tactics.mli +++ b/tactics/tactics.mli @@ -379,3 +379,6 @@ val specialize_eqs : identifier -> tactic val register_general_multi_rewrite : (bool -> evars_flag -> constr with_bindings -> clause -> tactic) -> unit + +val register_subst_one : + (bool -> identifier -> identifier * constr * bool -> tactic) -> unit |
