aboutsummaryrefslogtreecommitdiff
path: root/tactics
diff options
context:
space:
mode:
Diffstat (limited to 'tactics')
-rw-r--r--tactics/hiddentac.ml3
-rw-r--r--tactics/hiddentac.mli2
-rw-r--r--tactics/tacinterp.ml3
-rw-r--r--tactics/tactics.ml55
-rw-r--r--tactics/tactics.mli4
5 files changed, 46 insertions, 21 deletions
diff --git a/tactics/hiddentac.ml b/tactics/hiddentac.ml
index f5c54a5336..60f1ccf0ca 100644
--- a/tactics/hiddentac.ml
+++ b/tactics/hiddentac.ml
@@ -83,7 +83,7 @@ let h_new_induction ev c e idl =
let h_new_destruct ev c e idl =
abstract_tactic (TacNewDestruct (ev,List.map inj_ia c,Option.map inj_open_wb e,idl))
(new_destruct ev c e idl)
-let h_specialize n d = abstract_tactic (TacSpecialize (n,inj_open_wb d)) (new_hyp n d)
+let h_specialize n d = abstract_tactic (TacSpecialize (n,inj_open_wb d)) (specialize n d)
let h_lapply c = abstract_tactic (TacLApply (inj_open c)) (cut_and_apply c)
(* Context management *)
@@ -94,6 +94,7 @@ let h_move dep id1 id2 =
abstract_tactic (TacMove (dep,id1,id2)) (move_hyp dep id1 id2)
let h_rename l =
abstract_tactic (TacRename l) (rename_hyp l)
+let h_revert l = abstract_tactic (TacRevert l) (revert l)
(* Constructors *)
let h_left l = abstract_tactic (TacLeft l) (left_with_ebindings l)
diff --git a/tactics/hiddentac.mli b/tactics/hiddentac.mli
index 87232988b8..909d294cf6 100644
--- a/tactics/hiddentac.mli
+++ b/tactics/hiddentac.mli
@@ -76,7 +76,7 @@ val h_clear : bool -> identifier list -> tactic
val h_clear_body : identifier list -> tactic
val h_move : bool -> identifier -> identifier -> tactic
val h_rename : (identifier*identifier) list -> tactic
-
+val h_revert : identifier list -> tactic
(* Constructors *)
val h_constructor : int -> open_constr bindings -> tactic
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 3245c31c7e..821586e7f0 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -718,6 +718,7 @@ let rec intern_atomic lf ist x =
TacRename (List.map (fun (id1,id2) ->
intern_hyp_or_metaid ist id1,
intern_hyp_or_metaid ist id2) l)
+ | TacRevert l -> TacRevert (List.map (intern_hyp_or_metaid ist) l)
(* Constructors *)
| TacLeft bl -> TacLeft (intern_bindings ist bl)
@@ -2079,6 +2080,7 @@ and interp_atomic ist gl = function
h_rename (List.map (fun (id1,id2) ->
interp_hyp ist gl id1,
interp_fresh_ident ist gl (snd id2)) l)
+ | TacRevert l -> h_revert (interp_hyp_list ist gl l)
(* Constructors *)
| TacLeft bl -> h_left (interp_bindings ist gl bl)
@@ -2386,6 +2388,7 @@ let rec subst_atomic subst (t:glob_atomic_tactic_expr) = match t with
| TacClearBody l as x -> x
| TacMove (dep,id1,id2) as x -> x
| TacRename l as x -> x
+ | TacRevert _ as x -> x
(* Constructors *)
| TacLeft bl -> TacLeft (subst_bindings subst bl)
diff --git a/tactics/tactics.ml b/tactics/tactics.ml
index 6119185438..5f919a4dbe 100644
--- a/tactics/tactics.ml
+++ b/tactics/tactics.ml
@@ -725,25 +725,41 @@ let rec intros_clearing = function
tclTHENLIST
[ intro; onLastHyp (fun id -> clear [id]); intros_clearing tl]
-(* Adding new hypotheses *)
-
-let new_hyp mopt (c,lbind) g =
- let clause = make_clenv_binding g (c,pf_type_of g c) lbind in
- let clause = clenv_unify_meta_types clause in
- let (thd,tstack) = whd_stack (clenv_value clause) in
- let nargs = List.length tstack in
- let cut_pf =
- applist(thd,
- match mopt with
- | Some m -> if m < nargs then list_firstn m tstack else tstack
- | None -> tstack)
+(* Modifying/Adding an hypothesis *)
+
+let specialize mopt (c,lbind) g =
+ let evars, term =
+ if lbind = NoBindings then None, c
+ else
+ let clause = make_clenv_binding g (c,pf_type_of g c) lbind in
+ let clause = clenv_unify_meta_types clause in
+ let (thd,tstack) = whd_stack (clenv_value clause) in
+ let nargs = List.length tstack in
+ let tstack = match mopt with
+ | Some m ->
+ if m < nargs then list_firstn m tstack else tstack
+ | None ->
+ let rec chk = function
+ | [] -> []
+ | t::l -> if occur_meta t then [] else t :: chk l
+ in chk tstack
+ in
+ let term = applist(thd,tstack) in
+ if occur_meta term then
+ errorlabstrm "" (str "Cannot infer an instance for " ++
+ pr_name (meta_name clause.evd (List.hd (collect_metas term))));
+ Some (evars_of clause.evd), term
in
- if occur_meta cut_pf then
- errorlabstrm "" (str "Cannot infer an instance for " ++
- pr_name (meta_name clause.evd (List.hd (collect_metas cut_pf))));
- (tclTHENLAST (tclTHEN (tclEVARS (evars_of clause.evd))
- (cut (pf_type_of g cut_pf)))
- ((tclORELSE (apply cut_pf) (exact_no_check cut_pf)))) g
+ tclTHEN
+ (match evars with Some e -> tclEVARS e | _ -> tclIDTAC)
+ (match kind_of_term (fst (decompose_app c)) with
+ | Var id when List.exists (fun (i,_,_)-> i=id) (pf_hyps g) ->
+ let id' = fresh_id [] id g in
+ tclTHENS (internal_cut id' (pf_type_of g term))
+ [ exact_no_check term;
+ tclTHEN (clear [id]) (rename_hyp [id',id]) ]
+ | _ -> tclTHENLAST (cut (pf_type_of g term)) (exact_no_check term))
+ g
(* Keeping only a few hypotheses *)
@@ -1084,6 +1100,9 @@ let generalize lconstr gl =
let newcl = List.fold_right (generalize_goal gl) lconstr (pf_concl gl) in
apply_type newcl lconstr gl
+let revert hyps gl =
+ tclTHEN (generalize (List.map mkVar hyps)) (clear hyps) gl
+
(* Faudra-t-il une version avec plusieurs args de generalize_dep ?
Cela peut-être troublant de faire "Generalize Dependent H n" dans
"n:nat; H:n=n |- P(n)" et d'échouer parce que H a disparu après la
diff --git a/tactics/tactics.mli b/tactics/tactics.mli
index eb62f602aa..3a3bf6de51 100644
--- a/tactics/tactics.mli
+++ b/tactics/tactics.mli
@@ -156,11 +156,13 @@ val clear : identifier list -> tactic
val clear_body : identifier list -> tactic
val keep : identifier list -> tactic
-val new_hyp : int option -> constr with_ebindings -> tactic
+val specialize : int option -> constr with_ebindings -> tactic
val move_hyp : bool -> identifier -> identifier -> tactic
val rename_hyp : (identifier * identifier) list -> tactic
+val revert : identifier list -> tactic
+
(*s Resolution tactics. *)
val apply_type : constr -> constr list -> tactic