aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2008-06-10 19:35:23 +0000
committerGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2008-06-10 19:35:23 +0000
commit5d8d8e858e56c0d12cb262d5ff8e733ae7afc102 (patch)
tree90c20481422f774db9d25e70f98713a907e8894f
parent0039bf5442d91443f9ef3e2a83afdbd65524de84 (diff)
- Officialisation de la notation "pattern c at -1" (cf wish 1798 sur coq-bugs)
- Changement au passage de la convention "at -n1 ... -n2" en "at - n1 ... n2" qui me paraît plus clair à partir du moment où on peut pas mélanger des positifs et des négatifs. - Au passage: - simplification de gclause avec fusion de onconcl et concl_occs, - généralisation de l'utilisation de la désignation des occurrences par la négative aux cas de setoid_rewrite, clrewrite et rewrite at, - correction d'un bug de "rewrite in at" qui utilisait le at de la conclusion dans les hyps. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@11094 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r--contrib/firstorder/rules.ml6
-rw-r--r--contrib/funind/functional_principles_proofs.ml13
-rw-r--r--contrib/funind/invfun.ml5
-rw-r--r--contrib/funind/recdef.ml24
-rw-r--r--contrib/interface/blast.ml4
-rw-r--r--contrib/interface/pbp.ml2
-rw-r--r--contrib/interface/showproof.ml4
-rw-r--r--contrib/interface/xlate.ml42
-rw-r--r--contrib/omega/coq_omega.ml2
-rw-r--r--contrib/ring/ring.ml6
-rw-r--r--contrib/setoid_ring/newring.ml43
-rwxr-xr-xdoc/common/macros.tex4
-rw-r--r--doc/refman/RefMan-tac.tex74
-rw-r--r--parsing/g_tactic.ml451
-rw-r--r--parsing/ppconstr.ml14
-rw-r--r--parsing/ppconstr.mli2
-rw-r--r--parsing/pptactic.ml25
-rw-r--r--parsing/q_coqast.ml413
-rw-r--r--pretyping/rawterm.ml9
-rw-r--r--pretyping/rawterm.mli9
-rw-r--r--pretyping/tacred.ml182
-rw-r--r--pretyping/tacred.mli7
-rw-r--r--pretyping/termops.ml56
-rw-r--r--pretyping/termops.mli12
-rw-r--r--pretyping/unification.ml3
-rw-r--r--proofs/redexpr.ml4
-rw-r--r--proofs/redexpr.mli3
-rw-r--r--proofs/tacexpr.ml14
-rw-r--r--proofs/tacmach.mli2
-rw-r--r--tactics/auto.ml4
-rw-r--r--tactics/autorewrite.ml22
-rw-r--r--tactics/class_tactics.ml445
-rw-r--r--tactics/dhyp.ml8
-rw-r--r--tactics/eauto.ml46
-rw-r--r--tactics/equality.ml55
-rw-r--r--tactics/equality.mli13
-rw-r--r--tactics/extraargs.ml45
-rw-r--r--tactics/hiddentac.ml3
-rw-r--r--tactics/setoid_replace.ml10
-rw-r--r--tactics/setoid_replace.mli8
-rw-r--r--tactics/tacinterp.ml45
-rw-r--r--tactics/tacticals.ml19
-rw-r--r--tactics/tactics.ml27
-rw-r--r--tactics/tactics.mli28
-rw-r--r--toplevel/auto_ind_decl.ml6
45 files changed, 474 insertions, 425 deletions
diff --git a/contrib/firstorder/rules.ml b/contrib/firstorder/rules.ml
index b6112e653..813e951cf 100644
--- a/contrib/firstorder/rules.ml
+++ b/contrib/firstorder/rules.ml
@@ -204,8 +204,8 @@ let ll_forall_tac prod backtrack id continue seq=
let constant str = Coqlib.gen_constant "User" ["Init";"Logic"] str
let defined_connectives=lazy
- [[],EvalConstRef (destConst (constant "not"));
- [],EvalConstRef (destConst (constant "iff"))]
+ [all_occurrences,EvalConstRef (destConst (constant "not"));
+ all_occurrences,EvalConstRef (destConst (constant "iff"))]
let normalize_evaluables=
onAllClauses
@@ -213,4 +213,4 @@ let normalize_evaluables=
None->unfold_in_concl (Lazy.force defined_connectives)
| Some ((_,id),_)->
unfold_in_hyp (Lazy.force defined_connectives)
- (([],id),Tacexpr.InHypTypeOnly))
+ ((Rawterm.all_occurrences_expr,id),Tacexpr.InHypTypeOnly))
diff --git a/contrib/funind/functional_principles_proofs.ml b/contrib/funind/functional_principles_proofs.ml
index 558ca6c21..3d80bd004 100644
--- a/contrib/funind/functional_principles_proofs.ml
+++ b/contrib/funind/functional_principles_proofs.ml
@@ -637,7 +637,7 @@ let build_proof
[
h_generalize (term_eq::(List.map mkVar dyn_infos.rec_hyps));
thin dyn_infos.rec_hyps;
- pattern_option [[-1],t] None;
+ pattern_option [(false,[1]),t] None;
h_simplest_case t;
(fun g' ->
let g'_nb_prod = nb_prod (pf_concl g') in
@@ -1246,7 +1246,7 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _nparams :
in
let fname = destConst (fst (decompose_app (List.hd (List.rev pte_args)))) in
tclTHENSEQ
- [unfold_in_concl [([],Names.EvalConstRef fname)];
+ [unfold_in_concl [(all_occurrences,Names.EvalConstRef fname)];
let do_prove =
build_proof
interactive_proof
@@ -1347,11 +1347,10 @@ let build_clause eqs =
{
Tacexpr.onhyps =
Some (List.map
- (fun id -> ([],id),Tacexpr.InHyp)
+ (fun id -> (Rawterm.all_occurrences_expr,id),Tacexpr.InHyp)
eqs
);
- Tacexpr.onconcl = false;
- Tacexpr.concl_occs = []
+ Tacexpr.concl_occs = Rawterm.no_occurrences_expr
}
let rec rewrite_eqs_in_eqs eqs =
@@ -1364,7 +1363,7 @@ let rec rewrite_eqs_in_eqs eqs =
(fun id gl ->
observe_tac
(Format.sprintf "rewrite %s in %s " (string_of_id eq) (string_of_id id))
- (tclTRY (Equality.general_rewrite_in true [] id (mkVar eq) false))
+ (tclTRY (Equality.general_rewrite_in true all_occurrences id (mkVar eq) false))
gl
)
eqs
@@ -1386,7 +1385,7 @@ let new_prove_with_tcc is_mes acc_inv hrec tcc_hyps eqs : tactic =
(fun g ->
if is_mes
then
- unfold_in_concl [([], evaluable_of_global_reference (delayed_force ltof_ref))] g
+ unfold_in_concl [(all_occurrences, evaluable_of_global_reference (delayed_force ltof_ref))] g
else tclIDTAC g
);
observe_tac "rew_and_finish"
diff --git a/contrib/funind/invfun.ml b/contrib/funind/invfun.ml
index a5bd519e2..0160c290f 100644
--- a/contrib/funind/invfun.ml
+++ b/contrib/funind/invfun.ml
@@ -16,6 +16,7 @@ open Tacticals
open Tactics
open Indfun_common
open Tacmach
+open Termops
open Sign
open Hiddentac
@@ -314,7 +315,7 @@ let prove_fun_correct functional_induction funs_constr graphs_constr schemes lem
| None -> (id::pre_args,pre_tac)
| Some b ->
(pre_args,
- tclTHEN (h_reduce (Rawterm.Unfold([[],EvalVarRef id])) allHyps) pre_tac
+ tclTHEN (h_reduce (Rawterm.Unfold([Rawterm.all_occurrences_expr,EvalVarRef id])) allHyps) pre_tac
)
else (pre_args,pre_tac)
@@ -687,7 +688,7 @@ let prove_fun_complete funcs graphs schemes lemmas_types_infos i : tactic =
h_generalize (List.map mkVar ids);
thin ids
]
- else unfold_in_concl [([],Names.EvalConstRef (destConst f))]
+ else unfold_in_concl [(all_occurrences,Names.EvalConstRef (destConst f))]
in
(* The proof of each branche itself *)
let ind_number = ref 0 in
diff --git a/contrib/funind/recdef.ml b/contrib/funind/recdef.ml
index f4f852d36..13989f03b 100644
--- a/contrib/funind/recdef.ml
+++ b/contrib/funind/recdef.ml
@@ -296,7 +296,7 @@ let mkCaseEq a : tactic =
[h_generalize [mkApp(delayed_force refl_equal, [| type_of_a; a|])];
(fun g2 ->
change_in_concl None
- (pattern_occs [([-1], a)] (pf_env g2) Evd.empty (pf_concl g2))
+ (pattern_occs [((false,[1]), a)] (pf_env g2) Evd.empty (pf_concl g2))
g2);
simplest_case a] g);;
@@ -323,7 +323,7 @@ let mkDestructEq :
[h_generalize new_hyps;
(fun g2 ->
change_in_concl None
- (pattern_occs [([-1], expr)] (pf_env g2) Evd.empty (pf_concl g2)) g2);
+ (pattern_occs [((false,[1]), expr)] (pf_env g2) Evd.empty (pf_concl g2)) g2);
simplest_case expr], to_revert
let rec mk_intros_and_continue thin_intros (extra_eqn:bool)
@@ -336,7 +336,7 @@ let rec mk_intros_and_continue thin_intros (extra_eqn:bool)
h_intros thin_intros;
tclMAP
- (fun eq -> tclTRY (Equality.general_rewrite_in true [] teq eq false))
+ (fun eq -> tclTRY (Equality.general_rewrite_in true all_occurrences teq eq false))
(List.rev eqs);
(fun g1 ->
let ty_teq = pf_type_of g1 (mkVar teq) in
@@ -397,7 +397,7 @@ let tclUSER tac is_mes l g =
clear_tac;
if is_mes
then tclTHEN
- (unfold_in_concl [([], evaluable_of_global_reference
+ (unfold_in_concl [(all_occurrences, evaluable_of_global_reference
(delayed_force ltof_ref))])
tac
else tac
@@ -496,7 +496,7 @@ let rec list_cond_rewrite k def pmax cond_eqs le_proofs =
Nameops.out_name k_na,Nameops.out_name def_na
in
tclTHENS
- (general_rewrite_bindings false []
+ (general_rewrite_bindings false all_occurrences
(mkVar eq,
ExplicitBindings[dummy_loc, NamedHyp k_id, mkVar k;
dummy_loc, NamedHyp def_id, mkVar def]) false)
@@ -531,7 +531,7 @@ let rec introduce_all_equalities func eqs values specs bound le_proofs
observe_tac "intros k h' def" (h_intros [k;h';def]);
observe_tac "simple_iter" (simpl_iter onConcl);
observe_tac "unfold functional"
- (unfold_in_concl[([1],evaluable_of_global_reference func)]);
+ (unfold_in_concl[((true,[1]),evaluable_of_global_reference func)]);
observe_tac "rewriting equations"
(list_rewrite true eqs);
observe_tac ("cond rewrite "^(string_of_id k)) (list_cond_rewrite k def bound cond_eqs le_proofs);
@@ -1120,7 +1120,7 @@ let start_equation (f:global_reference) (term_f:global_reference)
let x = n_x_id ids nargs in
tclTHENLIST [
h_intros x;
- unfold_in_concl [([], evaluable_of_global_reference f)];
+ unfold_in_concl [(all_occurrences, evaluable_of_global_reference f)];
observe_tac "simplest_case"
(simplest_case (mkApp (terminate_constr,
Array.of_list (List.map mkVar x))));
@@ -1144,7 +1144,7 @@ let base_leaf_eq func eqs f_id g =
[|mkApp (delayed_force coq_S, [|mkVar p|]);
mkApp(delayed_force lt_n_Sn, [|mkVar p|]); f_id|])));
simpl_iter onConcl;
- tclTRY (unfold_in_concl [([1], evaluable_of_global_reference func)]);
+ tclTRY (unfold_in_concl [((true,[1]), evaluable_of_global_reference func)]);
list_rewrite true eqs;
apply (delayed_force refl_equal)] g;;
@@ -1160,9 +1160,9 @@ let rec introduce_all_values_eq cont_tac functional termine
[forward None (IntroIdentifier heq2)
(mkApp(mkVar heq1, [|f_S(f_S(mkVar pmax))|]));
simpl_iter (onHyp heq2);
- unfold_in_hyp [([1], evaluable_of_global_reference
+ unfold_in_hyp [((true,[1]), evaluable_of_global_reference
(global_of_constr functional))]
- (([], heq2), Tacexpr.InHyp);
+ ((all_occurrences_expr, heq2), Tacexpr.InHyp);
tclTHENS
(fun gls ->
let t_eq = compute_renamed_type gls (mkVar heq2) in
@@ -1170,7 +1170,7 @@ let rec introduce_all_values_eq cont_tac functional termine
let _,_,t = destProd t_eq in let def_na,_,_ = destProd t in
Nameops.out_name def_na
in
- observe_tac "rewrite heq" (general_rewrite_bindings false []
+ observe_tac "rewrite heq" (general_rewrite_bindings false all_occurrences
(mkVar heq2,
ExplicitBindings[dummy_loc,NamedHyp def_id,
f]) false) gls)
@@ -1226,7 +1226,7 @@ let rec introduce_all_values_eq cont_tac functional termine
f_S(mkVar pmax');
dummy_loc, NamedHyp def_id, f])
in
- observe_tac "general_rewrite_bindings" ( (general_rewrite_bindings false []
+ observe_tac "general_rewrite_bindings" ( (general_rewrite_bindings false all_occurrences
c_b false))
g
)
diff --git a/contrib/interface/blast.ml b/contrib/interface/blast.ml
index 10fafaefc..6ec0fac42 100644
--- a/contrib/interface/blast.ml
+++ b/contrib/interface/blast.ml
@@ -188,7 +188,7 @@ and e_my_find_search db_list local_db hdc concl =
| Res_pf_THEN_trivial_fail (term,cl) ->
tclTHEN (unify_e_resolve (term,cl))
(e_trivial_fail_db db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast -> Auto.conclPattern concl
(Option.get p) tacast
in
@@ -403,7 +403,7 @@ and my_find_search db_list local_db hdc concl =
tclTHEN
(unify_resolve st (term,cl))
(trivial_fail_db db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast ->
conclPattern concl (Option.get p) tacast))
tacl
diff --git a/contrib/interface/pbp.ml b/contrib/interface/pbp.ml
index ac152f906..06b957d9c 100644
--- a/contrib/interface/pbp.ml
+++ b/contrib/interface/pbp.ml
@@ -166,7 +166,7 @@ let make_pbp_atomic_tactic = function
TacAtom (zz, TacSplit (false,true,ImplicitBindings [make_pbp_pattern x]))
| PbpGeneralize (h,args) ->
let l = List.map make_pbp_pattern args in
- TacAtom (zz, TacGeneralize [([],make_app (make_var h) l),Anonymous])
+ TacAtom (zz, TacGeneralize [((true,[]),make_app (make_var h) l),Anonymous])
| PbpLeft -> TacAtom (zz, TacLeft (false,NoBindings))
| PbpRight -> TacAtom (zz, TacRight (false,NoBindings))
| PbpIntros l -> TacAtom (zz, TacIntroPattern l)
diff --git a/contrib/interface/showproof.ml b/contrib/interface/showproof.ml
index a2a504fb4..953fb5e79 100644
--- a/contrib/interface/showproof.ml
+++ b/contrib/interface/showproof.ml
@@ -1612,7 +1612,7 @@ and natural_fix ig lh g gs narg ltree =
| _ -> assert false
and natural_reduce ig lh g gs ge mode la ltree =
match la with
- {onhyps=Some[];onconcl=true} ->
+ {onhyps=Some[]} when la.concl_occs <> no_occurrences_expr ->
spv
[ (natural_lhyp lh ig.ihsg);
(show_goal2 lh ig g gs "");
@@ -1620,7 +1620,7 @@ and natural_reduce ig lh g gs ge mode la ltree =
{ihsg=All_subgoals_hyp;isgintro="simpl"})
ltree)
]
- | {onhyps=Some[hyp]; onconcl=false} ->
+ | {onhyps=Some[hyp]} when la.concl_occs = no_occurrences_expr ->
spv
[ (natural_lhyp lh ig.ihsg);
(show_goal2 lh ig g gs "");
diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml
index b041272c1..fa8f05713 100644
--- a/contrib/interface/xlate.ml
+++ b/contrib/interface/xlate.ml
@@ -464,24 +464,31 @@ let (xlate_ident_or_metaid:
AI (_, x) -> xlate_ident x
| MetaId(_, x) -> CT_metaid x;;
+let nums_of_occs (b,nums) =
+ if b then nums
+ else List.map (function ArgArg x -> ArgArg (-x) | y -> y) nums
+
let xlate_hyp = function
| AI (_,id) -> xlate_ident id
| MetaId _ -> xlate_error "MetaId should occur only in quotations"
let xlate_hyp_location =
function
- | (nums, AI (_,id)), InHypTypeOnly ->
- CT_intype(xlate_ident id, nums_or_var_to_int_list nums)
- | (nums, AI (_,id)), InHypValueOnly ->
- CT_invalue(xlate_ident id, nums_or_var_to_int_list nums)
- | ([], AI (_,id)), InHyp ->
+ | (occs, AI (_,id)), InHypTypeOnly ->
+ CT_intype(xlate_ident id, nums_or_var_to_int_list (nums_of_occs occs))
+ | (occs, AI (_,id)), InHypValueOnly ->
+ CT_invalue(xlate_ident id, nums_or_var_to_int_list (nums_of_occs occs))
+ | ((true,[]), AI (_,id)), InHyp ->
CT_coerce_UNFOLD_to_HYP_LOCATION
(CT_coerce_ID_to_UNFOLD (xlate_ident id))
- | (a::l, AI (_,id)), InHyp ->
+ | ((_,a::l as occs), AI (_,id)), InHyp ->
+ let nums = nums_of_occs occs in
+ let a = List.hd nums and l = List.tl nums in
CT_coerce_UNFOLD_to_HYP_LOCATION
(CT_unfold_occ (xlate_ident id,
CT_int_ne_list(num_or_var_to_int a,
nums_or_var_to_int_list_aux l)))
+ | ((false,[]), AI (_,id)), InHyp -> xlate_error "Unused"
| (_, MetaId _),_ ->
xlate_error "MetaId not supported in xlate_hyp_location (should occur only in quotations)"
@@ -494,7 +501,7 @@ let xlate_clause cls =
| Some l -> CT_hyp_location_list(List.map xlate_hyp_location l) in
CT_clause
(hyps_info,
- if cls.onconcl then
+ if cls.concl_occs <> no_occurrences_expr then
CT_coerce_STAR_to_STAR_OPT CT_star
else
CT_coerce_NONE_to_STAR_OPT CT_none)
@@ -667,11 +674,13 @@ let xlate_using = function
| Some (c2,sl2) -> CT_using (xlate_formula c2, xlate_bindings sl2);;
let xlate_one_unfold_block = function
- ([],qid) ->
+ ((true,[]),qid) ->
CT_coerce_ID_to_UNFOLD(apply_or_by_notation tac_qualid_to_ct_ID qid)
- | (n::nums, qid) ->
+ | (((_,_::_) as occs), qid) ->
+ let l = nums_of_occs occs in
CT_unfold_occ(apply_or_by_notation tac_qualid_to_ct_ID qid,
- nums_or_var_to_int_ne_list n nums)
+ nums_or_var_to_int_ne_list (List.hd l) (List.tl l))
+ | ((false,[]), qid) -> xlate_error "Unused"
;;
let xlate_with_names = function
@@ -732,7 +741,8 @@ and xlate_red_tactic =
| CbvVm -> CT_cbvvm
| Hnf -> CT_hnf
| Simpl None -> CT_simpl ctv_PATTERN_OPT_NONE
- | Simpl (Some (l,c)) ->
+ | Simpl (Some (occs,c)) ->
+ let l = nums_of_occs occs in
CT_simpl
(CT_coerce_PATTERN_to_PATTERN_OPT
(CT_pattern_occ
@@ -751,9 +761,9 @@ and xlate_red_tactic =
| Fold formula_list ->
CT_fold(CT_formula_list(List.map xlate_formula formula_list))
| Pattern l ->
- let pat_list = List.map (fun (nums,c) ->
+ let pat_list = List.map (fun (occs,c) ->
CT_pattern_occ
- (CT_int_list (nums_or_var_to_int_list_aux nums),
+ (CT_int_list (nums_or_var_to_int_list_aux (nums_of_occs occs)),
xlate_formula c)) l in
(match pat_list with
| first :: others -> CT_pattern (CT_pattern_ne_list (first, others))
@@ -907,6 +917,7 @@ and xlate_tac =
| TacChange (None, f, b) -> CT_change (xlate_formula f, xlate_clause b)
| TacChange (Some(l,c), f, b) ->
(* TODO LATER: combine with other constructions of pattern_occ *)
+ let l = nums_of_occs l in
CT_change_local(
CT_pattern_occ(CT_int_list(nums_or_var_to_int_list_aux l),
xlate_formula c),
@@ -1151,8 +1162,9 @@ and xlate_tac =
| TacSpecialize (nopt, (c,sl)) ->
CT_specialize (xlate_int_opt nopt, xlate_formula c, xlate_bindings sl)
| TacGeneralize [] -> xlate_error ""
- | TacGeneralize ((([],first),Anonymous) :: cl)
- when List.for_all (fun ((o,_),na) -> o = [] & na = Anonymous) cl ->
+ | TacGeneralize ((((true,[]),first),Anonymous) :: cl)
+ when List.for_all (fun ((o,_),na) -> o = all_occurrences_expr
+ & na = Anonymous) cl ->
CT_generalize
(CT_formula_ne_list (xlate_formula first,
List.map (fun ((_,c),_) -> xlate_formula c) cl))
diff --git a/contrib/omega/coq_omega.ml b/contrib/omega/coq_omega.ml
index b96b57d5b..0bb18b3b0 100644
--- a/contrib/omega/coq_omega.ml
+++ b/contrib/omega/coq_omega.ml
@@ -133,7 +133,7 @@ let exists_tac c = constructor_tac false (Some 1) 1 (Rawterm.ImplicitBindings [c
let generalize_tac t = generalize_time (generalize t)
let elim t = elim_time (simplest_elim t)
let exact t = exact_time (Tactics.refine t)
-let unfold s = Tactics.unfold_in_concl [[], Lazy.force s]
+let unfold s = Tactics.unfold_in_concl [all_occurrences, Lazy.force s]
let rev_assoc k =
let rec loop = function
diff --git a/contrib/ring/ring.ml b/contrib/ring/ring.ml
index 66246faf5..92f74d1d9 100644
--- a/contrib/ring/ring.ml
+++ b/contrib/ring/ring.ml
@@ -826,9 +826,11 @@ let raw_polynom th op lc gl =
c'''i; ci; c'i_eq_c''i |]))))
(tclTHENS
(tclORELSE
- (Setoid_replace.general_s_rewrite true [] c'i_eq_c''i
+ (Setoid_replace.general_s_rewrite true
+ Termops.all_occurrences c'i_eq_c''i
~new_goals:[])
- (Setoid_replace.general_s_rewrite false [] c'i_eq_c''i
+ (Setoid_replace.general_s_rewrite false
+ Termops.all_occurrences c'i_eq_c''i
~new_goals:[]))
[tac]))
else
diff --git a/contrib/setoid_ring/newring.ml4 b/contrib/setoid_ring/newring.ml4
index c3caa403e..474b3616a 100644
--- a/contrib/setoid_ring/newring.ml4
+++ b/contrib/setoid_ring/newring.ml4
@@ -104,7 +104,8 @@ let protect_tac map =
Tactics.reduct_option (protect_red map,DEFAULTcast) None ;;
let protect_tac_in map id =
- Tactics.reduct_option (protect_red map,DEFAULTcast) (Some(([],id),InHyp));;
+ Tactics.reduct_option (protect_red map,DEFAULTcast)
+ (Some((all_occurrences_expr,id),InHyp));;
TACTIC EXTEND protect_fv
diff --git a/doc/common/macros.tex b/doc/common/macros.tex
index 1c4fa7e1f..b464a9622 100755
--- a/doc/common/macros.tex
+++ b/doc/common/macros.tex
@@ -127,7 +127,9 @@
\newcommand{\ifitem}{\nterm{dep\_ret\_type}}
\newcommand{\convclause}{\nterm{conversion\_clause}}
\newcommand{\occclause}{\nterm{occurrence\_clause}}
-\newcommand{\occset}{\nterm{occurrence\_set}}
+\newcommand{\occgoalset}{\nterm{goal\_occurrences}}
+\newcommand{\atoccurrences}{\nterm{at\_occurrences}}
+\newcommand{\occlist}{\nterm{occurrences}}
\newcommand{\params}{\nterm{params}} % vernac
\newcommand{\returntype}{\nterm{return\_type}}
\newcommand{\idparams}{\nterm{ident\_with\_params}}
diff --git a/doc/refman/RefMan-tac.tex b/doc/refman/RefMan-tac.tex
index 9589963fe..f71d66319 100644
--- a/doc/refman/RefMan-tac.tex
+++ b/doc/refman/RefMan-tac.tex
@@ -447,10 +447,10 @@ replacement only in the conclusion.
\begin{Variants}
-\item {\tt set (} {\ident} {\tt :=} {\term} {\tt ) in {\occset}}
+\item {\tt set (} {\ident} {\tt :=} {\term} {\tt ) in {\occgoalset}}
This notation allows to specify which occurrences of {\term} have to
-be substituted in the context. The {\tt in {\occset}} clause is an
+be substituted in the context. The {\tt in {\occgoalset}} clause is an
occurrence clause whose syntax and behavior is described in
Section~\ref{Occurrences clauses}.
@@ -465,8 +465,8 @@ Section~\ref{Occurrences clauses}.
is generated by {\Coq}. This variant also supports an occurrence clause.
\item {\tt set (} {\ident$_0$} \nelist{\binder}{} {\tt :=} {\term}
- {\tt ) in {\occset}}\\
- {\tt set {\term} in {\occset}}
+ {\tt ) in {\occgoalset}}\\
+ {\tt set {\term} in {\occgoalset}}
These are the general forms which combine the previous possibilities.
@@ -475,7 +475,7 @@ Section~\ref{Occurrences clauses}.
This behaves as {\tt set (} {\ident} := {\term} {\tt ) in *} and using a
logical (Leibniz's) equality instead of a local definition.
-\item {\tt remember {\term} {\tt as} {\ident} in {\occset}}
+\item {\tt remember {\term} {\tt as} {\ident} in {\occgoalset}}
This is a more general form of {\tt remember} that remembers the
occurrences of {\term} specified by an occurrences set.
@@ -900,18 +900,18 @@ An occurrences clause is a modifier to some tactics that obeys the
following syntax:
$\!\!\!$\begin{tabular}{lcl}
-{\occclause} & ::= & {\tt in} {\occset} \\
-{\occset} & ::= &
- \zeroone{{\ident$_1$} \zeroone{{\tt at} {\num$_1^1$} \dots\ {\num$_{n_1}^1$}} {\tt ,} {\dots} {\tt ,}
- {\ident$_m$} \zeroone{{\tt at} {\num$_1^m$} \dots {\num$_{n_m}^m$}}}\\
-& &
- \zeroone{{\tt |-}
- \zeroone{{\tt *} \zeroone{{\tt at} {\num$'_1$} \dots\ {\num$'_n$}}}}\\
+{\occclause} & ::= & {\tt in} {\occgoalset} \\
+{\occgoalset} & ::= &
+ \zeroone{{\ident$_1$} \zeroone{\atoccurrences} {\tt ,} \\
+& & {\dots} {\tt ,}\\
+& & {\ident$_m$} \zeroone{\atoccurrences}}\\
+& & \zeroone{{\tt |-} \zeroone{{\tt *} \zeroone{\atoccurrences}}}\\
& | &
- {\tt *} {\tt |-}
- \zeroone{{\tt *} \zeroone{{\tt at} {\num$'_1$} \dots\ {\num$'_n$}}}\\
+ {\tt *} {\tt |-} \zeroone{{\tt *} \zeroone{\atoccurrences}}\\
& | &
{\tt *}\\
+{\atoccurrences} & ::= & {\tt at} {\occlist}\\
+{\occlist} & ::= & \zeroone{\tt -} {\num$_1$} \dots\ {\num$_n$}
\end{tabular}
The role of an occurrence clause is to select a set of occurrences of
@@ -927,10 +927,13 @@ particular, occurrences of {\term} in implicit arguments (see
Section~\ref{Implicit Arguments}) or coercions (see
Section~\ref{Coercions}) are counted.
-A negative occurrence number means an occurrence which should not be
-substituted. As an exception to the left-to-right order, the
-occurrences in the {\tt return} subexpression of a {\tt match} are
-considered {\em before} the occurrences in the matched term.
+If a minus sign is given between {\tt at} and the list of occurrences,
+it negates the condition so that the clause denotes all the occurrences except
+the ones explicitly mentioned after the minus sign.
+
+As an exception to the left-to-right order, the occurrences in the
+{\tt return} subexpression of a {\tt match} are considered {\em
+before} the occurrences in the matched term.
In the second case, the {\tt *} on the left of {\tt |-} means that
all occurrences of {\term} are selected in every hypothesis.
@@ -1290,10 +1293,16 @@ x}$)$) $t$}. This command can be used, for instance, when the tactic
\begin{Variants}
\item {\tt pattern {\term} at {\num$_1$} \dots\ {\num$_n$}}
- Only the occurrences {\num$_1$} \dots\ {\num$_n$} of {\term} will be
+ Only the occurrences {\num$_1$} \dots\ {\num$_n$} of {\term} are
considered for $\beta$-expansion. Occurrences are located from left
to right.
+\item {\tt pattern {\term} at - {\num$_1$} \dots\ {\num$_n$}}
+
+ All occurrences except the occurrences of indexes {\num$_1$} \dots\
+ {\num$_n$} of {\term} are considered for
+ $\beta$-expansion. Occurrences are located from left to right.
+
\item {\tt pattern {\term$_1$}, \dots, {\term$_m$}}
Starting from a goal $\phi(t_1 \dots\ t_m)$, the tactic
@@ -1310,6 +1319,11 @@ x}$)$) $t$}. This command can be used, for instance, when the tactic
\dots, \num$_i^1$ of \term$_1$, \dots, \num$_1^m$, \dots, \num$_j^m$
of \term$_m$ starting from \term$_m$.
+\item {\tt pattern} {\term$_1$} \zeroone{{\tt at \zeroone{-}} {\num$_1^1$} \dots\ {\num$_{n_1}^1$}} {\tt ,} \dots {\tt ,}
+ {\term$_m$} \zeroone{{\tt at \zeroone{-}} {\num$_1^m$} \dots\ {\num$_{n_m}^m$}}
+
+ This is the most general syntax that combines the different variants.
+
\end{Variants}
\subsection{Conversion tactics applied to hypotheses}
@@ -1524,10 +1538,10 @@ induction n.
This syntax tells to keep an equation between {\term} and the value
it gets in each case of the induction.
-\item \texttt{induction {\term} in {\occset}}
+\item \texttt{induction {\term} in {\occgoalset}}
This syntax is used for selecting which occurrences of {\term} the
- induction has to be carried on. The {\tt in {\occset}} clause is an
+ induction has to be carried on. The {\tt in {\atoccurrences}} clause is an
occurrence clause whose syntax and behavior is described in
Section~\ref{Occurrences clause}.
@@ -1535,8 +1549,8 @@ induction n.
the value it gets in each case of the induction is added to the
context of the subgoals corresponding to the induction cases.
-\item{\tt induction {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occset}}\\
- {\tt einduction {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occset}}
+\item{\tt induction {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occgoalset}}\\
+ {\tt einduction {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occgoalset}}
This is the most general form of {\tt induction} and {\tt
einduction}. It combines the effects of the {\tt with}, {\tt as},
@@ -1700,10 +1714,10 @@ last introduced hypothesis.
This syntax tells to keep an equation between {\term} and the value
it gets in each cases of the analysis.
-\item \texttt{destruct {\term} in {\occset}}
+\item \texttt{destruct {\term} in {\occgoalset}}
This syntax is used for selecting which occurrences of {\term} the
- case analysis has to be done on. The {\tt in {\occset}} clause is an
+ case analysis has to be done on. The {\tt in {\occgoalset}} clause is an
occurrence clause whose syntax and behavior is described in
Section~\ref{Occurrences clauses}.
@@ -1711,8 +1725,8 @@ last introduced hypothesis.
the value it gets in each cases of the analysis is added to the
context of the subgoals corresponding to the cases.
-\item{\tt destruct {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occset}}\\
- {\tt edestruct {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occset}}
+\item{\tt destruct {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occgoalset}}\\
+ {\tt edestruct {\term$_1$} with {\bindinglist$_1$} as {\intropattern} using {\term$_2$} with {\bindinglist$_2$} in {\occgoalset}}
This is the most general form of {\tt destruct} and {\tt edestruct}.
It combines the effects of the {\tt with}, {\tt as}, {\tt using},
@@ -2146,8 +2160,8 @@ This happens if \term$_1$ does not occur in the goal.
\begin{itemize}
\item \texttt{rewrite H in H1} will rewrites \texttt{H} in the hypothesis
\texttt{H1} instead of the current goal.
- \item \texttt{rewrite H in H1,H2 |- *} means \texttt{rewrite H; rewrite H in H1;
- rewrite H in H2}. In particular a failure will happen if any of
+ \item \texttt{rewrite H in H1 at 1, H2 at - 2 |- *} means \texttt{rewrite H; rewrite H in H1 at 1;
+ rewrite H in H2 at - 2}. In particular a failure will happen if any of
these three simpler tactics fails.
\item \texttt{rewrite H in * |- } will do \texttt{rewrite H in
H$_i$} for all hypothesis \texttt{H$_i$ <> H}. A success will happen
@@ -2159,7 +2173,7 @@ This happens if \term$_1$ does not occur in the goal.
Orientation {\tt ->} or {\tt <-} can be
inserted before the term to rewrite.
-\item {\tt rewrite {\term} at \textit{occurrences}}
+\item {\tt rewrite {\term} at {\occlist}}
\tacindex{rewrite \dots\ at}
Rewrite only the given occurrences of \term$_1'$. Occurrences are
diff --git a/parsing/g_tactic.ml4 b/parsing/g_tactic.ml4
index 5ab401550..bea3929df 100644
--- a/parsing/g_tactic.ml4
+++ b/parsing/g_tactic.ml4
@@ -162,6 +162,10 @@ let mkCLambdaN_simple bl c =
let loc = join_loc (fst (List.hd (pi1 (List.hd bl)))) (constr_loc c) in
mkCLambdaN_simple_loc loc bl c
+let map_int_or_var f = function
+ | Rawterm.ArgArg x -> Rawterm.ArgArg (f x)
+ | Rawterm.ArgVar _ as y -> y
+
(* Auxiliary grammar rules *)
GEXTEND Gram
@@ -173,6 +177,10 @@ GEXTEND Gram
[ [ n = integer -> Rawterm.ArgArg n
| id = identref -> Rawterm.ArgVar id ] ]
;
+ nat_or_var:
+ [ [ n = natural -> Rawterm.ArgArg n
+ | id = identref -> Rawterm.ArgVar id ] ]
+ ;
(* An identifier or a quotation meta-variable *)
id_or_meta:
[ [ id = identref -> AI id
@@ -203,18 +211,22 @@ GEXTEND Gram
;
conversion:
[ [ c = constr -> (None, c)
- | c1 = constr; "with"; c2 = constr -> (Some ([],c1), c2)
- | c1 = constr; "at"; nl = LIST1 int_or_var; "with"; c2 = constr ->
- (Some (nl,c1), c2) ] ]
+ | c1 = constr; "with"; c2 = constr -> (Some (all_occurrences_expr,c1),c2)
+ | c1 = constr; "at"; occs = occs_nums; "with"; c2 = constr ->
+ (Some (occs,c1), c2) ] ]
;
smart_global:
[ [ c = global -> AN c
| s = ne_string -> ByNotation (loc,s) ] ]
;
+ occs_nums:
+ [ [ nl = LIST1 nat_or_var -> no_occurrences_expr_but nl
+ | "-"; n = nat_or_var; nl = LIST0 int_or_var ->
+ (* have used int_or_var instead of nat_or_var for compatibility *)
+ all_occurrences_expr_but (List.map (map_int_or_var abs) (n::nl)) ] ]
+ ;
occs:
- [ [ "at"; nl = LIST1 integer -> List.map (fun x -> Rawterm.ArgArg x) nl
- | "at"; id = identref -> [Rawterm.ArgVar id]
- | -> [] ] ]
+ [ [ "at"; occs = occs_nums -> occs | -> all_occurrences_expr_but [] ] ]
;
pattern_occ:
[ [ c = constr; nl = occs -> (nl,c) ] ]
@@ -323,29 +335,29 @@ GEXTEND Gram
;
in_clause:
[ [ "*"; occs=occs ->
- {onhyps=None; onconcl=true; concl_occs=occs}
- | "*"; "|-"; (b,occs)=concl_occ ->
- {onhyps=None; onconcl=b; concl_occs=occs}
- | hl=LIST0 hypident_occ SEP","; "|-"; (b,occs)=concl_occ ->
- {onhyps=Some hl; onconcl=b; concl_occs=occs}
+ {onhyps=None; concl_occs=occs}
+ | "*"; "|-"; occs=concl_occ ->
+ {onhyps=None; concl_occs=occs}
+ | hl=LIST0 hypident_occ SEP","; "|-"; occs=concl_occ ->
+ {onhyps=Some hl; concl_occs=occs}
| hl=LIST0 hypident_occ SEP"," ->
- {onhyps=Some hl; onconcl=false; concl_occs=[]} ] ]
+ {onhyps=Some hl; concl_occs=no_occurrences_expr} ] ]
;
clause_dft_concl:
[ [ "in"; cl = in_clause -> cl
- | occs=occs -> {onhyps=Some[]; onconcl=true; concl_occs=occs}
- | -> {onhyps=Some[]; onconcl=true; concl_occs=[]} ] ]
+ | occs=occs -> {onhyps=Some[]; concl_occs=occs}
+ | -> {onhyps=Some[]; concl_occs=all_occurrences_expr} ] ]
;
clause_dft_all:
[ [ "in"; cl = in_clause -> cl
- | -> {onhyps=None; onconcl=true; concl_occs=[]} ] ]
+ | -> {onhyps=None; concl_occs=all_occurrences_expr} ] ]
;
opt_clause:
[ [ "in"; cl = in_clause -> Some cl | -> None ] ]
;
concl_occ:
- [ [ "*"; occs = occs -> (true,occs)
- | -> (false, []) ] ]
+ [ [ "*"; occs = occs -> occs
+ | -> no_occurrences_expr ] ]
;
simple_clause:
[ [ "in"; idl = LIST1 id_or_meta -> idl
@@ -493,9 +505,10 @@ GEXTEND Gram
| IDENT "cut"; c = constr -> TacCut c
| IDENT "generalize"; c = constr ->
- TacGeneralize [(([],c),Names.Anonymous)]
+ TacGeneralize [((all_occurrences_expr,c),Names.Anonymous)]
| IDENT "generalize"; c = constr; l = LIST1 constr ->
- TacGeneralize (List.map (fun c -> (([],c),Names.Anonymous)) (c::l))
+ let gen_everywhere c = ((all_occurrences_expr,c),Names.Anonymous) in
+ TacGeneralize (List.map gen_everywhere (c::l))
| IDENT "generalize"; c = constr; lookup_at_as_coma; nl = occs;
na = as_name;
l = LIST0 [","; c = pattern_occ; na = as_name -> (c,na)] ->
diff --git a/parsing/ppconstr.ml b/parsing/ppconstr.ml
index 0f0c38adc..04b700236 100644
--- a/parsing/ppconstr.ml
+++ b/parsing/ppconstr.ml
@@ -674,10 +674,16 @@ let pr_cases_pattern_expr = pr_patt ltop
let pr_binders = pr_undelimited_binders (pr ltop)
-let pr_with_occurrences pr = function
- ([],c) -> pr c
- | (nl,c) -> hov 1 (pr c ++ spc() ++ str"at " ++
- hov 0 (prlist_with_sep spc (pr_or_var int) nl))
+let pr_with_occurrences_with_trailer pr occs trailer =
+ match occs with
+ ((false,[]),c) -> pr c ++ trailer
+ | ((nowhere_except_in,nl),c) ->
+ hov 1 (pr c ++ spc() ++ str"at " ++
+ (if nowhere_except_in then mt() else str "- ") ++
+ hov 0 (prlist_with_sep spc (pr_or_var int) nl) ++ trailer)
+
+let pr_with_occurrences pr occs =
+ pr_with_occurrences_with_trailer pr occs (mt())
let pr_red_flag pr r =
(if r.rBeta then pr_arg str "beta" else mt ()) ++
diff --git a/parsing/ppconstr.mli b/parsing/ppconstr.mli
index f351144dc..83339ee2f 100644
--- a/parsing/ppconstr.mli
+++ b/parsing/ppconstr.mli
@@ -55,6 +55,8 @@ val pr_qualid : qualid -> std_ppcmds
val pr_with_occurrences :
('a -> std_ppcmds) -> 'a with_occurrences -> std_ppcmds
+val pr_with_occurrences_with_trailer :
+ ('a -> std_ppcmds) -> 'a with_occurrences -> std_ppcmds -> std_ppcmds
val pr_red_expr :
('a -> std_ppcmds) * ('a -> std_ppcmds) * ('b -> std_ppcmds) ->
('a,'b) red_expr_gen -> std_ppcmds
diff --git a/parsing/pptactic.ml b/parsing/pptactic.ml
index c0dbc0eff..e59df48aa 100644
--- a/parsing/pptactic.ml
+++ b/parsing/pptactic.ml
@@ -417,14 +417,14 @@ let pr_simple_clause pr_id = function
| l -> pr_in (spc () ++ prlist_with_sep spc pr_id l)
let pr_clauses pr_id = function
- { onhyps=None; onconcl=true; concl_occs=nl } ->
- pr_in (pr_with_occurrences (fun () -> str " *") (nl,()))
- | { onhyps=None; onconcl=false } -> pr_in (str " * |-")
- | { onhyps=Some l; onconcl=true; concl_occs=nl } ->
- pr_in (prlist_with_sep (fun () -> str",") (pr_hyp_location pr_id) l
- ++ pr_with_occurrences (fun () -> str" |- *") (nl,()))
- | { onhyps=Some l; onconcl=false } ->
- pr_in (prlist_with_sep (fun()->str",") (pr_hyp_location pr_id) l)
+ | { onhyps=None; concl_occs=occs } ->
+ if occs = no_occurrences_expr then pr_in (str " * |-")
+ else pr_in (pr_with_occurrences (fun () -> str " *") (occs,()))
+ | { onhyps=Some l; concl_occs=occs } ->
+ pr_in
+ (prlist_with_sep (fun () -> str",") (pr_hyp_location pr_id) l ++
+ (if occs = no_occurrences_expr then mt ()
+ else pr_with_occurrences (fun () -> str" |- *") (occs,())))
let pr_clause_pattern pr_id = function
| (None, []) -> mt ()
@@ -829,12 +829,9 @@ and pr_atom1 = function
hov 1 (str "change" ++ brk (1,1) ++
(match occ with
None -> mt()
- | Some([],c1) -> hov 1 (pr_constr c1 ++ spc() ++ str "with ")
- | Some(ocl,c1) ->
- hov 1 (pr_constr c1 ++ spc() ++
- str "at " ++ prlist_with_sep spc (pr_or_var int) ocl) ++
- spc() ++
- str "with ") ++
+ | Some occlc ->
+ pr_with_occurrences_with_trailer pr_constr occlc
+ (spc () ++ str "with ")) ++
pr_constr c ++ pr_clauses pr_ident h)
(* Equivalence relations *)
diff --git a/parsing/q_coqast.ml4 b/parsing/q_coqast.ml4
index 5c31fcee6..4b52772b5 100644
--- a/parsing/q_coqast.ml4
+++ b/parsing/q_coqast.ml4
@@ -95,7 +95,9 @@ let mlexpr_of_or_var f = function
let mlexpr_of_hyp = mlexpr_of_or_metaid (mlexpr_of_located mlexpr_of_ident)
-let mlexpr_of_occs = mlexpr_of_list (mlexpr_of_or_var mlexpr_of_int)
+let mlexpr_of_occs =
+ mlexpr_of_pair
+ mlexpr_of_bool (mlexpr_of_list (mlexpr_of_or_var mlexpr_of_int))
let mlexpr_of_occurrences f = mlexpr_of_pair mlexpr_of_occs f
@@ -111,7 +113,6 @@ let mlexpr_of_clause cl =
<:expr< {Tacexpr.onhyps=
$mlexpr_of_option (mlexpr_of_list mlexpr_of_hyp_location)
cl.Tacexpr.onhyps$;
- Tacexpr.onconcl= $mlexpr_of_bool cl.Tacexpr.onconcl$;
Tacexpr.concl_occs= $mlexpr_of_occs cl.Tacexpr.concl_occs$} >>
let mlexpr_of_red_flags {
@@ -165,8 +166,7 @@ let rec mlexpr_of_constr = function
| _ -> failwith "mlexpr_of_constr: TODO"
let mlexpr_of_occ_constr =
- mlexpr_of_pair (mlexpr_of_list (mlexpr_of_or_var mlexpr_of_int))
- mlexpr_of_constr
+ mlexpr_of_occurrences mlexpr_of_constr
let mlexpr_of_red_expr = function
| Rawterm.Red b -> <:expr< Rawterm.Red $mlexpr_of_bool b$ >>
@@ -177,9 +177,8 @@ let mlexpr_of_red_expr = function
| Rawterm.Lazy f ->
<:expr< Rawterm.Lazy $mlexpr_of_red_flags f$ >>
| Rawterm.Unfold l ->
- let f1 = mlexpr_of_list (mlexpr_of_or_var mlexpr_of_int) in
- let f2 = mlexpr_of_by_notation mlexpr_of_reference in
- let f = mlexpr_of_list (mlexpr_of_pair f1 f2) in
+ let f1 = mlexpr_of_by_notation mlexpr_of_reference in
+ let f = mlexpr_of_list (mlexpr_of_occurrences f1) in
<:expr< Rawterm.Unfold $f l$ >>
| Rawterm.Fold l ->
<:expr< Rawterm.Fold $mlexpr_of_list mlexpr_of_constr l$ >>
diff --git a/pretyping/rawterm.ml b/pretyping/rawterm.ml
index fe48cd4fa..79708e9fb 100644
--- a/pretyping/rawterm.ml
+++ b/pretyping/rawterm.ml
@@ -335,7 +335,14 @@ let all_flags =
type 'a or_var = ArgArg of 'a | ArgVar of identifier located
-type 'a with_occurrences = int or_var list * 'a
+type occurrences_expr = bool * int or_var list
+
+let all_occurrences_expr_but l = (false,l)
+let no_occurrences_expr_but l = (true,l)
+let all_occurrences_expr = (false,[])
+let no_occurrences_expr = (true,[])
+
+type 'a with_occurrences = occurrences_expr * 'a
type ('a,'b) red_expr_gen =
| Red of bool
diff --git a/pretyping/rawterm.mli b/pretyping/rawterm.mli
index ab67a0922..0eee3e73a 100644
--- a/pretyping/rawterm.mli
+++ b/pretyping/rawterm.mli
@@ -146,7 +146,14 @@ val all_flags : 'a raw_red_flag
type 'a or_var = ArgArg of 'a | ArgVar of identifier located
-type 'a with_occurrences = int or_var list * 'a
+type occurrences_expr = bool * int or_var list
+
+val all_occurrences_expr_but : int or_var list -> occurrences_expr
+val no_occurrences_expr_but : int or_var list -> occurrences_expr
+val all_occurrences_expr : occurrences_expr
+val no_occurrences_expr : occurrences_expr
+
+type 'a with_occurrences = occurrences_expr * 'a
type ('a,'b) red_expr_gen =
| Red of bool
diff --git a/pretyping/tacred.ml b/pretyping/tacred.ml
index 05d108673..47bc132ac 100644
--- a/pretyping/tacred.ml
+++ b/pretyping/tacred.ml
@@ -35,16 +35,23 @@ exception ReductionTacticError of reduction_tactic_error
exception Elimconst
exception Redelimination
-let is_evaluable env ref =
- match ref with
- 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 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
@@ -627,20 +634,16 @@ let is_head c t =
| 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
@@ -656,112 +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 _ ->
- (Flags.if_verbose
- warning "do not consider occurrences inside fixpoints"; (n,ol,c))
-
- | CoFix _ ->
- (Flags.if_verbose
- 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
@@ -779,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 =
diff --git a/pretyping/tacred.mli b/pretyping/tacred.mli
index 0ff5154f6..1516a2bd6 100644
--- a/pretyping/tacred.mli
+++ b/pretyping/tacred.mli
@@ -16,6 +16,7 @@ open Evd
open Reductionops
open Closure
open Rawterm
+open Termops
(*i*)
type reduction_tactic_error =
@@ -47,13 +48,13 @@ val hnf_constr : reduction_function
(* Unfold *)
val unfoldn :
- (int list * evaluable_global_reference) list -> reduction_function
+ (occurrences * evaluable_global_reference) list -> reduction_function
(* Fold *)
val fold_commands : constr list -> reduction_function
(* Pattern *)
-val pattern_occs : (int list * constr) list -> reduction_function
+val pattern_occs : (occurrences * constr) list -> reduction_function
(* Rem: Lazy strategies are defined in Reduction *)
(* Call by value strategy (uses Closures) *)
@@ -81,7 +82,7 @@ val reduce_to_quantified_ref :
val reduce_to_atomic_ref :
env -> evar_map -> Libnames.global_reference -> types -> types
-val contextually : bool -> int list * constr -> reduction_function
+val contextually : bool -> occurrences * constr -> reduction_function
-> reduction_function
(* Compatibility *)
diff --git a/pretyping/termops.ml b/pretyping/termops.ml
index 9a9e25c59..aa6c37491 100644
--- a/pretyping/termops.ml
+++ b/pretyping/termops.ml
@@ -621,32 +621,33 @@ let subst_term = subst_term_gen eq_constr
let replace_term = replace_term_gen eq_constr
-(* Substitute only a list of locations locs, the empty list is
- interpreted as substitute all, if 0 is in the list then no
- bindings is done. The list may contain only negative occurrences
- that will not be substituted. *)
+(* Substitute only at a list of locations or excluding a list of
+ locations; in the occurrences list (b,l), b=true means no
+ occurrence except the ones in l and b=false, means all occurrences
+ except the ones in l *)
+
+type occurrences = bool * int list
+let all_occurrences = (false,[])
+let no_occurrences_in_set = (true,[])
let error_invalid_occurrence l =
errorlabstrm ""
(str ("Invalid occurrence " ^ plural (List.length l) "number" ^": ") ++
prlist_with_sep spc int l)
-let subst_term_occ_gen locs occ c t =
+let subst_term_occ_gen (nowhere_except_in,locs) occ c t =
let maxocc = List.fold_right max locs 0 in
let pos = ref occ 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 substrec (k,c as kc) t =
- if (not except) & (!pos > maxocc) then t
+ assert (List.for_all (fun x -> x >= 0) locs);
+ let rec substrec (k,c as kc) t =
+ if nowhere_except_in & !pos > maxocc then t
else
if eq_constr c t then
let r =
- if except then
- if List.mem (- !pos) locs then t else (mkRel k)
- else
+ if nowhere_except_in then
if List.mem !pos locs then (mkRel k) else t
+ else
+ if List.mem !pos locs then t else (mkRel k)
in incr pos; r
else
map_constr_with_binders_left_to_right
@@ -656,28 +657,27 @@ let subst_term_occ_gen locs occ c t =
let t' = substrec (1,c) t in
(!pos, t')
-let subst_term_occ locs c t =
- if locs = [] then subst_term c t
- else if List.mem 0 locs then
- t
+let subst_term_occ (nowhere_except_in,locs as plocs) c t =
+ if locs = [] then if nowhere_except_in then t else subst_term c t
else
- let (nbocc,t') = subst_term_occ_gen locs 1 c t in
- let rest = List.filter (fun o -> o >= nbocc or o <= -nbocc) locs in
+ let (nbocc,t') = subst_term_occ_gen plocs 1 c t in
+ let rest = List.filter (fun o -> o >= nbocc) locs in
if rest <> [] then error_invalid_occurrence rest;
t'
-let subst_term_occ_decl locs c (id,bodyopt,typ as d) =
+let subst_term_occ_decl (nowhere_except_in,locs as plocs) c (id,bodyopt,typ as d) =
match bodyopt with
- | None -> (id,None,subst_term_occ locs c typ)
+ | None -> (id,None,subst_term_occ plocs c typ)
| Some body ->
if locs = [] then
- (id,Some (subst_term c body),subst_term c typ)
- else if List.mem 0 locs then
- d
+ if nowhere_except_in then
+ (id,Some (subst_term c body),subst_term c typ)
+ else
+ d
else
- let (nbocc,body') = subst_term_occ_gen locs 1 c body in
- let (nbocc',t') = subst_term_occ_gen locs nbocc c typ in
- let rest = List.filter (fun o -> o >= nbocc' or o <= -nbocc') locs in
+ let (nbocc,body') = subst_term_occ_gen plocs 1 c body in
+ let (nbocc',t') = subst_term_occ_gen plocs nbocc c typ in
+ let rest = List.filter (fun o -> o >= nbocc') locs in
if rest <> [] then error_invalid_occurrence rest;
(id,Some body',t')
diff --git a/pretyping/termops.mli b/pretyping/termops.mli
index bc483cfc3..f80deab10 100644
--- a/pretyping/termops.mli
+++ b/pretyping/termops.mli
@@ -131,18 +131,24 @@ val subst_term : constr -> constr -> constr
(* [replace_term d e c] replaces [d] by [e] in [c] *)
val replace_term : constr -> constr -> constr -> constr
+(* In occurrences sets, false = everywhere except and true = nowhere except *)
+type occurrences = bool * int list
+val all_occurrences : occurrences
+val no_occurrences_in_set : occurrences
+
(* [subst_term_occ_gen occl n c d] replaces occurrences of [c] at
positions [occl], counting from [n], by [Rel 1] in [d] *)
-val subst_term_occ_gen : int list -> int -> constr -> types -> int * types
+val subst_term_occ_gen :
+ occurrences -> int -> constr -> types -> int * types
(* [subst_term_occ occl c d] replaces occurrences of [c] at
positions [occl] by [Rel 1] in [d] (see also Note OCC) *)
-val subst_term_occ : int list -> constr -> constr -> constr
+val subst_term_occ : occurrences -> constr -> constr -> constr
(* [subst_term_occ_decl occl c decl] replaces occurrences of [c] at
positions [occl] by [Rel 1] in [decl] *)
val subst_term_occ_decl :
- int list -> constr -> named_declaration -> named_declaration
+ occurrences -> constr -> named_declaration -> named_declaration
val error_invalid_occurrence : int list -> 'a
diff --git a/pretyping/unification.ml b/pretyping/unification.ml
index ca1be55bb..41d6ff4c1 100644
--- a/pretyping/unification.ml
+++ b/pretyping/unification.ml
@@ -44,7 +44,8 @@ let abstract_scheme env c l lname_typ =
let abstract_list_all env evd typ c l =
let ctxt,_ = decomp_n_prod env (evars_of evd) (List.length l) typ in
- let p = abstract_scheme env c (List.map (function a -> [],a) l) ctxt in
+ let l_with_all_occs = List.map (function a -> (all_occurrences,a)) l in
+ let p = abstract_scheme env c l_with_all_occs ctxt in
try
if is_conv_leq env (evars_of evd) (Typing.mtype_of env evd p) typ then p
else error "abstract_list_all"
diff --git a/proofs/redexpr.ml b/proofs/redexpr.ml
index 27db71755..71e7cdc21 100644
--- a/proofs/redexpr.ml
+++ b/proofs/redexpr.ml
@@ -154,8 +154,8 @@ let out_arg = function
| ArgVar _ -> anomaly "Unevaluated or_var variable"
| ArgArg x -> x
-let out_with_occurrences (l,c) =
- (List.map out_arg l, c)
+let out_with_occurrences ((b,l),c) =
+ ((b,List.map out_arg l), c)
let reduction_of_red_expr = function
| Red internal ->
diff --git a/proofs/redexpr.mli b/proofs/redexpr.mli
index 68c1fd669..70db56c48 100644
--- a/proofs/redexpr.mli
+++ b/proofs/redexpr.mli
@@ -13,11 +13,12 @@ open Term
open Closure
open Rawterm
open Reductionops
+open Termops
type red_expr = (constr, evaluable_global_reference) red_expr_gen
-val out_with_occurrences : 'a with_occurrences -> int list * 'a
+val out_with_occurrences : 'a with_occurrences -> occurrences * 'a
val reduction_of_red_expr : red_expr -> reduction_function * cast_kind
(* [true] if we should use the vm to verify the reduction *)
diff --git a/proofs/tacexpr.ml b/proofs/tacexpr.ml
index d0b015552..17961fd42 100644
--- a/proofs/tacexpr.ml
+++ b/proofs/tacexpr.ml
@@ -94,15 +94,17 @@ type 'id gsimple_clause = ('id raw_hyp_location) option
[Some l] means on hypothesis belonging to l *)
type 'id gclause =
{ onhyps : 'id raw_hyp_location list option;
- onconcl : bool;
- concl_occs : int or_var list }
+ concl_occs : bool * int or_var list }
-let nowhere = {onhyps=Some[]; onconcl=false; concl_occs=[]}
+let nowhere = {onhyps=Some[]; concl_occs=(false,[])}
let simple_clause_of = function
- { onhyps = Some[scl]; onconcl = false } -> Some scl
- | { onhyps = Some []; onconcl = true; concl_occs=[] } -> None
- | _ -> error "not a simple clause (one hypothesis or conclusion)"
+| { onhyps = Some [scl]; concl_occs = occs } when occs = no_occurrences_expr ->
+ Some scl
+| { onhyps = Some []; concl_occs = occs } when occs = all_occurrences_expr ->
+ None
+| _ ->
+ error "not a simple clause (one hypothesis or conclusion)"
type multi =
| Precisely of int
diff --git a/proofs/tacmach.mli b/proofs/tacmach.mli
index 6b6305a17..2b007112f 100644
--- a/proofs/tacmach.mli
+++ b/proofs/tacmach.mli
@@ -79,7 +79,7 @@ val pf_nf_betaiota : goal sigma -> constr -> constr
val pf_reduce_to_quantified_ind : goal sigma -> types -> inductive * types
val pf_reduce_to_atomic_ind : goal sigma -> types -> inductive * types
val pf_compute : goal sigma -> constr -> constr
-val pf_unfoldn : (int list * evaluable_global_reference) list
+val pf_unfoldn : (Termops.occurrences * evaluable_global_reference) list
-> goal sigma -> constr -> constr
val pf_const_value : goal sigma -> constant -> constr
diff --git a/tactics/auto.ml b/tactics/auto.ml
index e41bebea1..a4933a896 100644
--- a/tactics/auto.ml
+++ b/tactics/auto.ml
@@ -677,7 +677,7 @@ and my_find_search_nodelta db_list local_db hdc concl =
tclTHEN
(unify_resolve_nodelta (term,cl))
(trivial_fail_db false db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast ->
conclPattern concl (Option.get p) tacast))
tacl
@@ -717,7 +717,7 @@ and my_find_search_delta db_list local_db hdc concl =
tclTHEN
(unify_resolve st (term,cl))
(trivial_fail_db true db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast ->
conclPattern concl (Option.get p) tacast))
tacl
diff --git a/tactics/autorewrite.ml b/tactics/autorewrite.ml
index e3e90c7ca..3be1e45de 100644
--- a/tactics/autorewrite.ml
+++ b/tactics/autorewrite.ml
@@ -17,7 +17,9 @@ open Tacticals
open Tacinterp
open Tactics
open Term
+open Termops
open Util
+open Rawterm
open Vernacinterp
open Tacexpr
open Mod_subst
@@ -80,7 +82,10 @@ let one_base general_rewrite_maybe_in tac_main bas =
let autorewrite tac_main lbas =
tclREPEAT_MAIN (tclPROGRESS
(List.fold_left (fun tac bas ->
- tclTHEN tac (one_base (fun dir -> general_rewrite dir []) tac_main bas)) tclIDTAC lbas))
+ tclTHEN tac
+ (one_base (fun dir -> general_rewrite dir all_occurrences)
+ tac_main bas))
+ tclIDTAC lbas))
let autorewrite_multi_in idl tac_main lbas : tactic =
fun gl ->
@@ -96,7 +101,7 @@ let autorewrite_multi_in idl tac_main lbas : tactic =
| _ -> (* even the hypothesis id is missing *)
error ("No such hypothesis : " ^ (string_of_id !id))
in
- let gl' = general_rewrite_in dir [] !id cstr false gl in
+ let gl' = general_rewrite_in dir all_occurrences !id cstr false gl in
let gls = (fst gl').Evd.it in
match gls with
g::_ ->
@@ -132,7 +137,9 @@ let gen_auto_multi_rewrite tac_main lbas cl =
let try_do_hyps treat_id l =
autorewrite_multi_in (List.map treat_id l) tac_main lbas
in
- if cl.concl_occs <> [] then
+ if cl.concl_occs <> all_occurrences_expr &
+ cl.concl_occs <> no_occurrences_expr
+ then
error "The \"at\" syntax isn't available yet for the autorewrite tactic"
else
let compose_tac t1 t2 =
@@ -141,7 +148,7 @@ let gen_auto_multi_rewrite tac_main lbas cl =
| _ -> tclTHENFIRST t1 t2
in
compose_tac
- (if cl.onconcl then autorewrite tac_main lbas else tclIDTAC)
+ (if cl.concl_occs <> no_occurrences_expr then autorewrite tac_main lbas else tclIDTAC)
(match cl.onhyps with
| Some l -> try_do_hyps (fun ((_,id),_) -> id) l
| None ->
@@ -153,11 +160,12 @@ let gen_auto_multi_rewrite tac_main lbas cl =
let auto_multi_rewrite = gen_auto_multi_rewrite Refiner.tclIDTAC
-let auto_multi_rewrite_with tac_main lbas cl gl =
- match cl.Tacexpr.onconcl,cl.Tacexpr.onhyps with
+let auto_multi_rewrite_with tac_main lbas cl gl =
+ let onconcl = cl.Tacexpr.concl_occs <> no_occurrences_expr in
+ match onconcl,cl.Tacexpr.onhyps with
| false,Some [_] | true,Some [] | false,Some [] ->
(* autorewrite with .... in clause using tac n'est sur que
- si clause reprensente soit le but soit UNE hypothse
+ si clause represente soit le but soit UNE hypothese
*)
gen_auto_multi_rewrite tac_main lbas cl gl
| _ ->
diff --git a/tactics/class_tactics.ml4 b/tactics/class_tactics.ml4
index bbeeb4e03..37fe7c3c8 100644
--- a/tactics/class_tactics.ml4
+++ b/tactics/class_tactics.ml4
@@ -125,7 +125,7 @@ and e_my_find_search db_list local_db hdc concl =
| Res_pf_THEN_trivial_fail (term,cl) ->
tclTHEN (unify_e_resolve st (term,cl))
(e_trivial_fail_db db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast -> conclPattern concl
(Option.get p) tacast
in
@@ -793,8 +793,10 @@ type rewrite_flags = { under_lambdas : bool; on_morphisms : bool }
let default_flags = { under_lambdas = true; on_morphisms = true; }
-let build_new gl env sigma flags occs hypinfo concl cstr evars =
- let is_occ occ = occs = [] || List.mem occ occs in
+let build_new gl env sigma flags loccs hypinfo concl cstr evars =
+ let (nowhere_except_in,occs) = loccs in
+ let is_occ occ =
+ if nowhere_except_in then List.mem occ occs else not (List.mem occ occs) in
let rec aux env t occ cstr =
let unif = unify_eqn env sigma hypinfo t in
let occ = if unif = None then occ else succ occ in
@@ -899,7 +901,11 @@ let build_new gl env sigma flags occs hypinfo concl cstr evars =
Some (prf', (car', rel', c1', c2'))
in res, occ
| _ -> None, occ
- in aux env concl 0 cstr
+ in
+ let eq,nbocc_min_1 = aux env concl 0 cstr in
+ let rest = List.filter (fun o -> o > nbocc_min_1) occs in
+ if rest <> [] then error_invalid_occurrence rest;
+ eq
let resolve_typeclass_evars d p env evd onlyargs =
let pred =
@@ -924,7 +930,7 @@ let cl_rewrite_clause_aux ?(flags=default_flags) hypinfo goal_meta occs clause g
let evars = ref (Evd.create_evar_defs Evd.empty) in
let env = pf_env gl in
let sigma = project gl in
- let eq, _ = build_new gl env sigma flags occs hypinfo concl (Some (Lazy.lazy_from_val cstr)) evars
+ let eq = build_new gl env sigma flags occs hypinfo concl (Some (Lazy.lazy_from_val cstr)) evars
in
match eq with
| Some (p, (_, _, oldt, newt)) ->
@@ -993,12 +999,19 @@ let cl_rewrite_clause c left2right occs clause gl =
open Genarg
open Extraargs
+let occurrences_of = function
+ | n::_ as nl when n < 0 -> (false,List.map abs nl)
+ | nl ->
+ if List.exists (fun n -> n < 0) nl then
+ error "Illegal negative occurrence number";
+ (true,nl)
+
TACTIC EXTEND class_rewrite
-| [ "clrewrite" orient(o) constr(c) "in" hyp(id) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o occ (Some (([],id), [])) ]
-| [ "clrewrite" orient(o) constr(c) "at" occurrences(occ) "in" hyp(id) ] -> [ cl_rewrite_clause c o occ (Some (([],id), [])) ]
-| [ "clrewrite" orient(o) constr(c) "in" hyp(id) ] -> [ cl_rewrite_clause c o [] (Some (([],id), [])) ]
-| [ "clrewrite" orient(o) constr(c) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o occ None ]
-| [ "clrewrite" orient(o) constr(c) ] -> [ cl_rewrite_clause c o [] None ]
+| [ "clrewrite" orient(o) constr(c) "in" hyp(id) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o (occurrences_of occ) (Some (([],id), [])) ]
+| [ "clrewrite" orient(o) constr(c) "at" occurrences(occ) "in" hyp(id) ] -> [ cl_rewrite_clause c o (occurrences_of occ) (Some (([],id), [])) ]
+| [ "clrewrite" orient(o) constr(c) "in" hyp(id) ] -> [ cl_rewrite_clause c o all_occurrences (Some (([],id), [])) ]
+| [ "clrewrite" orient(o) constr(c) "at" occurrences(occ) ] -> [ cl_rewrite_clause c o (occurrences_of occ) None ]
+| [ "clrewrite" orient(o) constr(c) ] -> [ cl_rewrite_clause c o all_occurrences None ]
END
@@ -1008,7 +1021,7 @@ let clsubstitute o c =
(fun cl ->
match cl with
| Some ((_,id),_) when is_tac id -> tclIDTAC
- | _ -> tclTRY (cl_rewrite_clause c o [] cl))
+ | _ -> tclTRY (cl_rewrite_clause c o all_occurrences cl))
TACTIC EXTEND substitute
| [ "substitute" orient(o) constr(c) ] -> [ clsubstitute o c ]
@@ -1098,15 +1111,15 @@ let _ =
TACTIC EXTEND setoid_rewrite
[ "setoid_rewrite" orient(o) constr(c) ]
- -> [ cl_rewrite_clause c o [] None ]
+ -> [ cl_rewrite_clause c o all_occurrences None ]
| [ "setoid_rewrite" orient(o) constr(c) "in" hyp(id) ] ->
- [ cl_rewrite_clause c o [] (Some (([],id), []))]
+ [ cl_rewrite_clause c o all_occurrences (Some (([],id), []))]
| [ "setoid_rewrite" orient(o) constr(c) "at" occurrences(occ) ] ->
- [ cl_rewrite_clause c o occ None]
+ [ cl_rewrite_clause c o (occurrences_of occ) None]
| [ "setoid_rewrite" orient(o) constr(c) "at" occurrences(occ) "in" hyp(id)] ->
- [ cl_rewrite_clause c o occ (Some (([],id), []))]
+ [ cl_rewrite_clause c o (occurrences_of occ) (Some (([],id), []))]
| [ "setoid_rewrite" orient(o) constr(c) "in" hyp(id) "at" occurrences(occ)] ->
- [ cl_rewrite_clause c o occ (Some (([],id), []))]
+ [ cl_rewrite_clause c o (occurrences_of occ) (Some (([],id), []))]
END
(* let solve_obligation lemma = *)
diff --git a/tactics/dhyp.ml b/tactics/dhyp.ml
index 843554bae..7d2ccbe21 100644
--- a/tactics/dhyp.ml
+++ b/tactics/dhyp.ml
@@ -261,11 +261,13 @@ let add_destructor_hint local na loc pat pri code =
(inDD (local,na,{ d_pat = pat; d_pri=pri; d_code=code }))
let match_dpat dp cls gls =
+ let onconcl = cls.concl_occs <> no_occurrences_expr in
match (cls,dp) with
- | ({onhyps=lo;onconcl=false},HypLocation(_,hypd,concld)) ->
+ | ({onhyps=lo},HypLocation(_,hypd,concld)) when not onconcl ->
let hl = match lo with
Some l -> l
- | None -> List.map (fun id -> (([],id),InHyp)) (pf_ids_of_hyps gls) in
+ | None -> List.map (fun id -> ((all_occurrences_expr,id),InHyp))
+ (pf_ids_of_hyps gls) in
if not
(List.for_all
(fun ((_,id),hl) ->
@@ -278,7 +280,7 @@ let match_dpat dp cls gls =
(is_matching concld.d_sort (pf_type_of gls cl)))
hl)
then error "No match"
- | ({onhyps=Some[];onconcl=true},ConclLocation concld) ->
+ | ({onhyps=Some[]},ConclLocation concld) when onconcl ->
let cl = pf_concl gls in
if not
((is_matching concld.d_typ cl) &
diff --git a/tactics/eauto.ml4 b/tactics/eauto.ml4
index c6804329b..3b982b4c0 100644
--- a/tactics/eauto.ml4
+++ b/tactics/eauto.ml4
@@ -140,7 +140,7 @@ and e_my_find_search_nodelta db_list local_db hdc concl =
| Res_pf_THEN_trivial_fail (term,cl) ->
tclTHEN (unify_e_resolve_nodelta (term,cl))
(e_trivial_fail_db false db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast -> conclPattern concl
(Option.get p) tacast
in
@@ -179,7 +179,7 @@ and e_my_find_search_delta db_list local_db hdc concl =
| Res_pf_THEN_trivial_fail (term,cl) ->
tclTHEN (unify_e_resolve st (term,cl))
(e_trivial_fail_db true db_list local_db)
- | Unfold_nth c -> unfold_in_concl [[],c]
+ | Unfold_nth c -> unfold_in_concl [all_occurrences,c]
| Extern tacast -> conclPattern concl
(Option.get p) tacast
in
@@ -448,7 +448,7 @@ END
let autosimpl db cl =
let unfold_of_elts constr (b, elts) =
if not b then
- List.map (fun c -> [], constr c) elts
+ List.map (fun c -> all_occurrences, constr c) elts
else []
in
let unfolds = List.concat (List.map (fun dbname ->
diff --git a/tactics/equality.ml b/tactics/equality.ml
index b0c5a29eb..f907b1fd7 100644
--- a/tactics/equality.ml
+++ b/tactics/equality.ml
@@ -109,7 +109,7 @@ let general_rewrite_ebindings_clause cls lft2rgt occs (c,l) with_evars gl =
then !general_setoid_rewrite_clause cls lft2rgt occs c ~new_goals:[] gl
else error "The term provided does not end with an equation"
| Some (hdcncl,_) ->
- if occs <> [] then (
+ if occs <> all_occurrences then (
!general_setoid_rewrite_clause cls lft2rgt occs c ~new_goals:[] gl)
else
let hdcncls = string_of_inductive hdcncl in
@@ -145,10 +145,10 @@ let general_rewrite_in l2r occs id c =
general_rewrite_ebindings_clause (Some id) l2r occs (c,NoBindings)
let general_multi_rewrite l2r with_evars c cl =
- let occs = List.fold_left
+ let occs_of = on_snd (List.fold_left
(fun acc ->
function ArgArg x -> x :: acc | ArgVar _ -> acc)
- [] cl.concl_occs
+ [])
in
match cl.onhyps with
| Some l ->
@@ -156,24 +156,24 @@ let general_multi_rewrite l2r with_evars c cl =
each of these locations. *)
let rec do_hyps = function
| [] -> tclIDTAC
- | ((_,id),_) :: l ->
- tclTHENFIRST
- (general_rewrite_ebindings_in l2r occs id c with_evars)
- (do_hyps l)
+ | ((occs,id),_) :: l ->
+ tclTHENFIRST
+ (general_rewrite_ebindings_in l2r (occs_of occs) id c with_evars)
+ (do_hyps l)
in
- if not cl.onconcl then do_hyps l else
+ if cl.concl_occs = no_occurrences_expr then do_hyps l else
tclTHENFIRST
- (general_rewrite_ebindings l2r occs c with_evars)
- (do_hyps l)
+ (general_rewrite_ebindings l2r (occs_of cl.concl_occs) c with_evars)
+ (do_hyps l)
| None ->
(* Otherwise, if we are told to rewrite in all hypothesis via the
syntax "* |-", we fail iff all the different rewrites fail *)
let rec do_hyps_atleastonce = function
| [] -> (fun gl -> error "Nothing to rewrite.")
| id :: l ->
- tclIFTHENTRYELSEMUST
- (general_rewrite_ebindings_in l2r occs id c with_evars)
- (do_hyps_atleastonce l)
+ tclIFTHENTRYELSEMUST
+ (general_rewrite_ebindings_in l2r all_occurrences id c with_evars)
+ (do_hyps_atleastonce l)
in
let do_hyps gl =
(* If the term to rewrite uses an hypothesis H, don't rewrite in H *)
@@ -182,10 +182,10 @@ let general_multi_rewrite l2r with_evars c cl =
Idset.fold (fun id l -> list_remove id l) ids_in_c (pf_ids_of_hyps gl)
in do_hyps_atleastonce ids gl
in
- if not cl.onconcl then do_hyps else
- tclIFTHENTRYELSEMUST
- (general_rewrite_ebindings l2r occs c with_evars)
- do_hyps
+ if cl.concl_occs = no_occurrences_expr then do_hyps else
+ tclIFTHENTRYELSEMUST
+ (general_rewrite_ebindings l2r (occs_of cl.concl_occs) c with_evars)
+ do_hyps
let general_multi_multi_rewrite with_evars l cl tac =
let do1 l2r c =
@@ -212,20 +212,22 @@ let general_multi_multi_rewrite with_evars l cl tac =
to the resolution of the conditions by a given tactic *)
let conditional_rewrite lft2rgt tac (c,bl) =
- tclTHENSFIRSTn (general_rewrite_ebindings lft2rgt [] (c,bl) false)
+ tclTHENSFIRSTn
+ (general_rewrite_ebindings lft2rgt all_occurrences (c,bl) false)
[|tclIDTAC|] (tclCOMPLETE tac)
-let rewriteLR_bindings = general_rewrite_bindings true []
-let rewriteRL_bindings = general_rewrite_bindings false []
+let rewriteLR_bindings = general_rewrite_bindings true all_occurrences
+let rewriteRL_bindings = general_rewrite_bindings false all_occurrences
-let rewriteLR = general_rewrite true []
-let rewriteRL = general_rewrite false []
+let rewriteLR = general_rewrite true all_occurrences
+let rewriteRL = general_rewrite false all_occurrences
-let rewriteLRin_bindings = general_rewrite_bindings_in true []
-let rewriteRLin_bindings = general_rewrite_bindings_in false []
+let rewriteLRin_bindings = general_rewrite_bindings_in true all_occurrences
+let rewriteRLin_bindings = general_rewrite_bindings_in false all_occurrences
let conditional_rewrite_in lft2rgt id tac (c,bl) =
- tclTHENSFIRSTn (general_rewrite_ebindings_in lft2rgt [] id (c,bl) false)
+ tclTHENSFIRSTn
+ (general_rewrite_ebindings_in lft2rgt all_occurrences id (c,bl) false)
[|tclIDTAC|] (tclCOMPLETE tac)
let rewriteRL_clause = function
@@ -1124,7 +1126,8 @@ let unfold_body x gl =
| _ -> errorlabstrm "unfold_body"
(pr_id x ++ str" is not a defined hypothesis") in
let aft = afterHyp x gl in
- let hl = List.fold_right (fun (y,yval,_) cl -> (([],y),InHyp) :: cl) aft [] in
+ let hl = List.fold_right
+ (fun (y,yval,_) cl -> ((all_occurrences_expr,y),InHyp) :: cl) aft [] in
let xvar = mkVar x in
let rfun _ _ c = replace_term xvar xval c in
tclTHENLIST
diff --git a/tactics/equality.mli b/tactics/equality.mli
index 19cf1ed56..acbaca235 100644
--- a/tactics/equality.mli
+++ b/tactics/equality.mli
@@ -21,14 +21,15 @@ open Pattern
open Tacticals
open Tactics
open Tacexpr
+open Termops
open Rawterm
open Genarg
(*i*)
val general_rewrite_bindings :
- bool -> int list -> constr with_bindings -> evars_flag -> tactic
+ bool -> occurrences -> constr with_bindings -> evars_flag -> tactic
val general_rewrite :
- bool -> int list -> constr -> tactic
+ bool -> occurrences -> constr -> tactic
(* Obsolete, use [general_rewrite_bindings l2r]
[val rewriteLR_bindings : constr with_bindings -> tactic]
@@ -42,13 +43,13 @@ val rewriteRL : constr -> tactic
(* Warning: old [general_rewrite_in] is now [general_rewrite_bindings_in] *)
val register_general_setoid_rewrite_clause :
- (identifier option ->
- bool -> int list -> constr -> new_goals:constr list -> tactic) -> unit
+ (identifier option -> bool ->
+ occurrences -> constr -> new_goals:constr list -> tactic) -> unit
val general_rewrite_bindings_in :
- bool -> int list -> identifier -> constr with_bindings -> evars_flag -> tactic
+ bool -> occurrences -> identifier -> constr with_bindings -> evars_flag -> tactic
val general_rewrite_in :
- bool -> int list -> identifier -> constr -> evars_flag -> tactic
+ bool -> occurrences -> identifier -> constr -> evars_flag -> tactic
val general_multi_rewrite :
bool -> evars_flag -> constr with_ebindings -> clause -> tactic
diff --git a/tactics/extraargs.ml4 b/tactics/extraargs.ml4
index f768e98e4..158cecfc7 100644
--- a/tactics/extraargs.ml4
+++ b/tactics/extraargs.ml4
@@ -288,12 +288,11 @@ let gen_in_arg_hyp_to_clause trad_id (hyps ,concl) : Tacticals.clause =
Option.map
(fun l ->
List.map
- (fun id -> ( ([],trad_id id) ,Tacexpr.InHyp))
+ (fun id -> ( (all_occurrences_expr,trad_id id) ,Tacexpr.InHyp))
l
)
hyps;
- Tacexpr.onconcl=concl;
- Tacexpr.concl_occs = []}
+ Tacexpr.concl_occs = if concl then all_occurrences_expr else no_occurrences_expr}
let raw_in_arg_hyp_to_clause = gen_in_arg_hyp_to_clause snd
diff --git a/tactics/hiddentac.ml b/tactics/hiddentac.ml
index 0a9ed111f..11ace2abb 100644
--- a/tactics/hiddentac.ml
+++ b/tactics/hiddentac.ml
@@ -65,7 +65,8 @@ let h_generalize_gen cl =
abstract_tactic (TacGeneralize (List.map (on_fst inj_occ) cl))
(generalize_gen (List.map (on_fst Redexpr.out_with_occurrences) cl))
let h_generalize cl =
- h_generalize_gen (List.map (fun c -> (([],c),Names.Anonymous)) cl)
+ h_generalize_gen (List.map (fun c -> ((all_occurrences_expr,c),Names.Anonymous))
+ cl)
let h_generalize_dep c =
abstract_tactic (TacGeneralizeDep (inj_open c))(generalize_dep c)
let h_let_tac b na c cl =
diff --git a/tactics/setoid_replace.ml b/tactics/setoid_replace.ml
index dc8ff2b9c..98c0c1104 100644
--- a/tactics/setoid_replace.ml
+++ b/tactics/setoid_replace.ml
@@ -1806,7 +1806,7 @@ let relation_rewrite_no_unif c1 c2 hyp ~new_goals sigma gl =
if_output_relation_is_if gl
with
Optimize ->
- !general_rewrite (fst hyp = Left2Right) [] (snd hyp) gl
+ !general_rewrite (fst hyp = Left2Right) all_occurrences (snd hyp) gl
let relation_rewrite c1 c2 (input_direction,cl) ~new_goals gl =
let (sigma,cl,c1,c2) = unification_rewrite c1 c2 cl (pf_concl gl) gl in
@@ -1825,6 +1825,8 @@ let analyse_hypothesis gl c =
eqclause,mkApp (equiv, Array.of_list others),c1,c2
let general_s_rewrite lft2rgt occs c ~new_goals gl =
+ if occs <> all_occurrences then
+ warning "Rewriting at selected occurrences not supported";
let eqclause,_,c1,c2 = analyse_hypothesis gl c in
if lft2rgt then
relation_rewrite c1 c2 (Left2Right,eqclause) ~new_goals gl
@@ -1862,6 +1864,8 @@ let relation_rewrite_in id c1 c2 (direction,eqclause) ~new_goals gl =
gl
let general_s_rewrite_in id lft2rgt occs c ~new_goals gl =
+ if occs <> all_occurrences then
+ warning "Rewriting at selected occurrences not supported";
let eqclause,_,c1,c2 = analyse_hypothesis gl c in
if lft2rgt then
relation_rewrite_in id c1 c2 (Left2Right,eqclause) ~new_goals gl
@@ -1916,7 +1920,7 @@ let general_setoid_replace rewrite_tac try_prove_eq_tac_opt relation c1 c2 ~new_
tclTHENS (assert_tac false Anonymous eq)
[onLastHyp (fun id ->
tclTHEN
- (rewrite_tac dir [] (mkVar id) ~new_goals)
+ (rewrite_tac dir all_occurrences (mkVar id) ~new_goals)
(clear [id]));
try_prove_eq_tac]
in
@@ -1928,7 +1932,7 @@ let general_setoid_replace rewrite_tac try_prove_eq_tac_opt relation c1 c2 ~new_
tclTHENS (assert_tac false Anonymous eq)
[onLastHyp (fun id ->
tclTHEN
- (rewrite_tac false [] (mkVar id) ~new_goals)
+ (rewrite_tac false all_occurrences (mkVar id) ~new_goals)
(clear [id]));
try_prove_eq_tac] gl
diff --git a/tactics/setoid_replace.mli b/tactics/setoid_replace.mli
index 1eb0141c6..244e02dd4 100644
--- a/tactics/setoid_replace.mli
+++ b/tactics/setoid_replace.mli
@@ -12,6 +12,7 @@ open Term
open Proof_type
open Topconstr
open Names
+open Termops
type relation =
{ rel_a: constr ;
@@ -40,7 +41,7 @@ type morphism_signature = (bool option * constr_expr) list * constr_expr
val pr_morphism_signature : morphism_signature -> Pp.std_ppcmds
val register_replace : (tactic option -> constr -> constr -> tactic) -> unit
-val register_general_rewrite : (bool -> int list -> constr -> tactic) -> unit
+val register_general_rewrite : (bool -> occurrences -> constr -> tactic) -> unit
val print_setoids : unit -> unit
@@ -58,9 +59,10 @@ val setoid_replace_in :
identifier -> constr option -> constr -> constr -> new_goals:constr list ->
tactic
-val general_s_rewrite : bool -> int list -> constr -> new_goals:constr list -> tactic
+val general_s_rewrite :
+ bool -> occurrences -> constr -> new_goals:constr list -> tactic
val general_s_rewrite_in :
- identifier -> bool -> int list -> constr -> new_goals:constr list -> tactic
+ identifier -> bool -> occurrences -> constr -> new_goals:constr list -> tactic
val setoid_reflexivity : tactic
val setoid_symmetry : tactic
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 20b4abf8a..2fc6692a8 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -204,7 +204,7 @@ let add_primitive_tactic s tac =
atomic_mactab := Idmap.add id tac !atomic_mactab
let _ =
- let nocl = {onhyps=Some[];onconcl=true; concl_occs=[]} in
+ let nocl = {onhyps=Some[];concl_occs=all_occurrences_expr} in
List.iter
(fun (s,t) -> add_primitive_tactic s (TacAtom(dloc,t)))
[ "red", TacReduce(Red false,nocl);
@@ -610,8 +610,8 @@ let intern_inversion_strength lf ist = function
InversionUsing (intern_constr ist c, List.map (intern_hyp_or_metaid ist) idl)
(* Interprets an hypothesis name *)
-let intern_hyp_location ist ((occs,id),hl) =
- ((List.map (intern_or_var ist) occs,intern_hyp ist (skip_metaid id)), hl)
+let intern_hyp_location ist (((b,occs),id),hl) =
+ (((b,List.map (intern_or_var ist) occs),intern_hyp ist (skip_metaid id)), hl)
let interp_constrpattern_gen sigma env ?(as_type=false) ltacvar c =
let c = intern_gen as_type ~allow_patvar:true ~ltacvars:(ltacvar,[])
@@ -672,10 +672,10 @@ let extract_let_names lrc =
lrc []
let clause_app f = function
- { onhyps=None; onconcl=b;concl_occs=nl } ->
- { onhyps=None; onconcl=b; concl_occs=nl }
- | { onhyps=Some l; onconcl=b;concl_occs=nl } ->
- { onhyps=Some(List.map f l); onconcl=b;concl_occs=nl}
+ { onhyps=None; concl_occs=nl } ->
+ { onhyps=None; concl_occs=nl }
+ | { onhyps=Some l; concl_occs=nl } ->
+ { onhyps=Some(List.map f l); concl_occs=nl}
(* Globalizes tactics : raw_tactic_expr -> glob_tactic_expr *)
let rec intern_atomic lf ist x =
@@ -783,7 +783,9 @@ let rec intern_atomic lf ist x =
TacReduce (intern_red_expr ist r, clause_app (intern_hyp_location ist) cl)
| TacChange (occl,c,cl) ->
TacChange (Option.map (intern_constr_with_occurrences ist) occl,
- (if occl = None & cl.onhyps = None & cl.concl_occs = []
+ (if occl = None & (cl.onhyps = None or cl.onhyps = Some []) &
+ (cl.concl_occs = all_occurrences_expr or
+ cl.concl_occs = no_occurrences_expr)
then intern_type ist c else intern_constr ist c),
clause_app (intern_hyp_location ist) cl)
@@ -1279,13 +1281,15 @@ let interp_evaluable ist env = function
interp_ltac_var (coerce_to_evaluable_ref env) ist (Some env) locid
(* Interprets an hypothesis name *)
+let interp_occurrences ist (b,occs) =
+ (b,interp_int_or_var_list ist occs)
+
let interp_hyp_location ist gl ((occs,id),hl) =
- ((interp_int_or_var_list ist occs,interp_hyp ist gl id),hl)
+ ((interp_occurrences ist occs,interp_hyp ist gl id),hl)
-let interp_clause ist gl { onhyps=ol; onconcl=b; concl_occs=occs } =
+let interp_clause ist gl { onhyps=ol; concl_occs=occs } =
{ onhyps=Option.map(List.map (interp_hyp_location ist gl)) ol;
- onconcl=b;
- concl_occs= interp_int_or_var_list ist occs }
+ concl_occs=interp_occurrences ist occs }
(* Interpretation of constructions *)
@@ -1483,22 +1487,23 @@ let pf_interp_type ist gl =
interp_type ist (project gl) (pf_env gl)
(* Interprets a reduction expression *)
-let interp_unfold ist env (l,qid) =
- (interp_int_or_var_list ist l,interp_evaluable ist env qid)
+let interp_unfold ist env (occs,qid) =
+ (interp_occurrences ist occs,interp_evaluable ist env qid)
let interp_flag ist env red =
{ red with rConst = List.map (interp_evaluable ist env) red.rConst }
-let interp_pattern ist sigma env (l,c) =
- (interp_int_or_var_list ist l, interp_constr ist sigma env c)
+let interp_pattern ist sigma env (occs,c) =
+ (interp_occurrences ist occs, interp_constr ist sigma env c)
let pf_interp_constr_with_occurrences ist gl =
interp_pattern ist (project gl) (pf_env gl)
let pf_interp_constr_with_occurrences_and_name_as_list =
pf_interp_constr_in_compound_list
- (fun c -> (([],c),Anonymous))
- (function (([],c),Anonymous) -> c | _ -> raise Not_found)
+ (fun c -> ((all_occurrences_expr,c),Anonymous))
+ (function ((occs,c),Anonymous) when occs = all_occurrences_expr -> c
+ | _ -> raise Not_found)
(fun ist gl (occ_c,na) ->
(interp_pattern ist (project gl) (pf_env gl) occ_c,
interp_fresh_name ist gl na))
@@ -2189,7 +2194,9 @@ and interp_atomic ist gl = function
h_reduce (pf_interp_red_expr ist gl r) (interp_clause ist gl cl)
| TacChange (occl,c,cl) ->
h_change (Option.map (pf_interp_constr_with_occurrences ist gl) occl)
- (if occl = None & cl.onhyps = None & cl.concl_occs = []
+ (if occl = None & (cl.onhyps = None or cl.onhyps = Some []) &
+ (cl.concl_occs = all_occurrences_expr or
+ cl.concl_occs = no_occurrences_expr)
then pf_interp_type ist gl c
else pf_interp_constr ist gl c)
(interp_clause ist gl cl)
diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml
index dd8aa1294..577ef0c6f 100644
--- a/tactics/tacticals.ml
+++ b/tactics/tacticals.ml
@@ -23,6 +23,7 @@ open Refiner
open Tacmach
open Clenv
open Clenvtac
+open Rawterm
open Pattern
open Matching
open Evar_refiner
@@ -123,17 +124,21 @@ let tclTRY_HYPS (tac : constr->tactic) gl =
type simple_clause = identifier gsimple_clause
type clause = identifier gclause
-let allClauses = { onhyps=None; onconcl=true; concl_occs=[] }
-let allHyps = { onhyps=None; onconcl=false; concl_occs=[] }
-let onHyp id = { onhyps=Some[(([],id),InHyp)]; onconcl=false; concl_occs=[] }
-let onConcl = { onhyps=Some[]; onconcl=true; concl_occs=[] }
+let allClauses = { onhyps=None; concl_occs=all_occurrences_expr }
+let allHyps = { onhyps=None; concl_occs=no_occurrences_expr }
+let onConcl = { onhyps=Some[]; concl_occs=all_occurrences_expr }
+let onHyp id =
+ { onhyps=Some[((all_occurrences_expr,id),InHyp)]; concl_occs=no_occurrences_expr }
let simple_clause_list_of cl gls =
let hyps =
match cl.onhyps with
- None -> List.map (fun id -> Some(([],id),InHyp)) (pf_ids_of_hyps gls)
- | Some l -> List.map (fun h -> Some h) l in
- if cl.onconcl then None::hyps else hyps
+ | None ->
+ let f id = Some((all_occurrences_expr,id),InHyp) in
+ List.map f (pf_ids_of_hyps gls)
+ | Some l ->
+ List.map (fun h -> Some h) l in
+ if cl.concl_occs = all_occurrences_expr then None::hyps else hyps
(* OR-branch *)
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 905511b12..4ec8ee0ae 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -56,6 +56,8 @@ let rec nb_prod x =
| _ -> n
in count 0 x
+let inj_with_occurrences e = (all_occurrences_expr,e)
+
let inj_open c = (Evd.empty,c)
let inj_occ (occ,c) = (occ,inj_open c)
@@ -214,7 +216,8 @@ let change_option occl t = function
let change occl c cls =
(match cls, occl with
- ({onhyps=(Some(_::_::_)|None)}|{onhyps=Some(_::_);onconcl=true}),
+ ({onhyps=(Some(_::_::_)|None)}
+ |{onhyps=Some(_::_);concl_occs=((false,_)|(true,_::_))}),
Some _ ->
error "No occurrences expected when changing several hypotheses"
| _ -> ());
@@ -256,8 +259,8 @@ let reduce redexp cl goal =
(* Unfolding occurrences of a constant *)
let unfold_constr = function
- | ConstRef sp -> unfold_in_concl [[],EvalConstRef sp]
- | VarRef id -> unfold_in_concl [[],EvalVarRef id]
+ | ConstRef sp -> unfold_in_concl [all_occurrences,EvalConstRef sp]
+ | VarRef id -> unfold_in_concl [all_occurrences,EvalVarRef id]
| _ -> errorlabstrm "unfold_constr" (str "Cannot unfold a non-constant.")
(*******************************************)
@@ -1175,7 +1178,7 @@ let generalize_dep c gl =
| _ -> tothin
in
let cl' = it_mkNamedProd_or_LetIn (pf_concl gl) to_quantify in
- let cl'' = generalize_goal gl 0 (([],c),Anonymous) cl' in
+ let cl'' = generalize_goal gl 0 ((all_occurrences,c),Anonymous) cl' in
let args = Array.to_list (instance_from_named_context to_quantify_rev) in
tclTHEN
(apply_type cl'' (c::args))
@@ -1187,7 +1190,8 @@ let generalize_gen lconstr gl =
list_fold_right_i (generalize_goal gl) 0 lconstr (pf_concl gl) in
apply_type newcl (List.map (fun ((_,c),_) -> c) lconstr) gl
-let generalize l = generalize_gen (List.map (fun c -> (([],c),Anonymous)) l)
+let generalize l =
+ generalize_gen (List.map (fun c -> ((all_occurrences,c),Anonymous)) l)
let revert hyps gl =
tclTHEN (generalize (List.map mkVar hyps)) (clear hyps) gl
@@ -1235,14 +1239,15 @@ let out_arg = function
let occurrences_of_hyp id cls =
let rec hyp_occ = function
[] -> None
- | ((occs,id'),hl)::_ when id=id' -> Some (List.map out_arg occs)
+ | (((b,occs),id'),hl)::_ when id=id' -> Some (b,List.map out_arg occs)
| _::l -> hyp_occ l in
match cls.onhyps with
- None -> Some []
+ None -> Some (all_occurrences)
| Some l -> hyp_occ l
let occurrences_of_goal cls =
- if cls.onconcl then Some (List.map out_arg cls.concl_occs) else None
+ if cls.concl_occs = no_occurrences_expr then None
+ else Some (on_snd (List.map out_arg) cls.concl_occs)
let in_every_hyp cls = (cls.onhyps=None)
@@ -1311,7 +1316,7 @@ let letin_abstract id c occs gl =
| None -> depdecls
| Some occ ->
let newdecl = subst_term_occ_decl occ c d in
- if occ = [] & d = newdecl then
+ if occ = all_occurrences & d = newdecl then
if not (in_every_hyp occs)
then raise (RefinerError (DoesNotOccurIn (c,hyp)))
else depdecls
@@ -2297,8 +2302,6 @@ let recolle_clenv scheme lid elimclause gl =
(List.rev clauses)
elimclause
-
-
(* Unification of the goal and the principle applied to meta variables:
(elimc ?i ?j ?k...?l). This solves partly meta variables (and may
produce new ones). Then refine with the resulting term with holes.
@@ -2364,7 +2367,7 @@ let induction_from_context_l isrec with_evars elim_info lid names gl =
if deps = [] then tclIDTAC else apply_type tmpcl deps_cstr;
thin dephyps; (* clear dependent hyps *)
(* pattern to make the predicate appear. *)
- reduce (Pattern (List.map (fun e -> ([],e)) lidcstr)) onConcl;
+ reduce (Pattern (List.map inj_with_occurrences lidcstr)) onConcl;
(* FIXME: Tester ca avec un principe dependant et non-dependant *)
(if isrec then tclTHENFIRSTn else tclTHENLASTn)
(tclTHENLIST [
diff --git a/tactics/tactics.mli b/tactics/tactics.mli
index bfb49cba7..0492e296f 100644
--- a/tactics/tactics.mli
+++ b/tactics/tactics.mli
@@ -26,6 +26,7 @@ open Genarg
open Tacexpr
open Nametab
open Rawterm
+open Termops
(*i*)
val inj_open : constr -> open_constr
@@ -121,9 +122,9 @@ type tactic_reduction = env -> evar_map -> constr -> constr
val reduct_in_hyp : tactic_reduction -> hyp_location -> tactic
val reduct_option : tactic_reduction * cast_kind -> simple_clause -> tactic
val reduct_in_concl : tactic_reduction * cast_kind -> tactic
-val change_in_concl : (int list * constr) option -> constr -> tactic
-val change_in_hyp : (int list * constr) option -> constr -> hyp_location ->
- tactic
+val change_in_concl : (occurrences * constr) option -> constr -> tactic
+val change_in_hyp : (occurrences * constr) option -> constr ->
+ hyp_location -> tactic
val red_in_concl : tactic
val red_in_hyp : hyp_location -> tactic
val red_option : simple_clause -> tactic
@@ -137,18 +138,19 @@ val normalise_in_concl : tactic
val normalise_in_hyp : hyp_location -> tactic
val normalise_option : simple_clause -> tactic
val normalise_vm_in_concl : tactic
-val unfold_in_concl : (int list * evaluable_global_reference) list -> tactic
+val unfold_in_concl :
+ (occurrences * evaluable_global_reference) list -> tactic
val unfold_in_hyp :
- (int list * evaluable_global_reference) list -> hyp_location -> tactic
+ (occurrences * evaluable_global_reference) list -> hyp_location -> tactic
val unfold_option :
- (int list * evaluable_global_reference) list -> simple_clause
+ (occurrences * evaluable_global_reference) list -> simple_clause
-> tactic
-val reduce : red_expr -> clause -> tactic
val change :
- (int list * constr) option -> constr -> clause -> tactic
-
+ (occurrences * constr) option -> constr -> clause -> tactic
+val pattern_option :
+ (occurrences * constr) list -> simple_clause -> tactic
+val reduce : red_expr -> clause -> tactic
val unfold_constr : global_reference -> tactic
-val pattern_option : (int list * constr) list -> simple_clause -> tactic
(*s Modification of the local context. *)
@@ -326,9 +328,9 @@ val forward : tactic option -> intro_pattern_expr -> constr -> tactic
val letin_tac : bool option -> name -> constr -> clause -> tactic
val true_cut : name -> constr -> tactic
val assert_tac : bool -> name -> constr -> tactic
-val generalize : constr list -> tactic
-val generalize_gen : ((int list * constr) * name) list -> tactic
-val generalize_dep : constr -> tactic
+val generalize : constr list -> tactic
+val generalize_gen : ((occurrences * constr) * name) list -> tactic
+val generalize_dep : constr -> tactic
val tclABSTRACT : identifier option -> tactic -> tactic
diff --git a/toplevel/auto_ind_decl.ml b/toplevel/auto_ind_decl.ml
index a6ae7240c..0ef835689 100644
--- a/toplevel/auto_ind_decl.ml
+++ b/toplevel/auto_ind_decl.ml
@@ -527,7 +527,8 @@ let compute_bl_tact ind lnamesparrec nparrec =
tclTRY (
tclORELSE reflexivity (Equality.discr_tac None)
);
- simpl_in_hyp (([],freshz),Tacexpr.InHyp);
+ simpl_in_hyp
+ ((Rawterm.all_occurrences_expr,freshz),Tacexpr.InHyp);
(*
repeat ( apply andb_prop in z;let z1:= fresh "Z" in destruct z as [z1 z]).
*)
@@ -798,7 +799,8 @@ let compute_dec_tact ind lnamesparrec nparrec =
(tclTHENSEQ [apply (mkApp(lbI,Array.map (fun x->mkVar x) xargs));
Auto.default_auto
]);
- Pfedit.by (Equality.general_rewrite_bindings_in true []
+ Pfedit.by (Equality.general_rewrite_bindings_in true
+ all_occurrences
(List.hd !avoid)
((mkVar (List.hd (List.tl !avoid))),
Rawterm.NoBindings