aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intf/tacexpr.mli2
-rw-r--r--parsing/g_ltac.ml41
-rw-r--r--printing/pptactic.ml4
-rw-r--r--proofs/proofview.ml22
-rw-r--r--proofs/proofview.mli7
-rw-r--r--tactics/tacintern.ml2
-rw-r--r--tactics/tacinterp.ml2
-rw-r--r--tactics/tacsubst.ml2
-rw-r--r--tactics/tacticals.ml2
-rw-r--r--tactics/tacticals.mli1
10 files changed, 45 insertions, 0 deletions
diff --git a/intf/tacexpr.mli b/intf/tacexpr.mli
index 839294c0a1..0ddf58b74a 100644
--- a/intf/tacexpr.mli
+++ b/intf/tacexpr.mli
@@ -219,6 +219,8 @@ and ('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr =
('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr
| TacOnce of
('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr
+ | TacExactlyOnce of
+ ('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr
| TacOrelse of
('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr *
('t,'p,'c,'i,'r,'n,'l) gen_tactic_expr
diff --git a/parsing/g_ltac.ml4 b/parsing/g_ltac.ml4
index 033de89df3..d075a77904 100644
--- a/parsing/g_ltac.ml4
+++ b/parsing/g_ltac.ml4
@@ -67,6 +67,7 @@ GEXTEND Gram
| IDENT "repeat"; ta = tactic_expr -> TacRepeat ta
| IDENT "progress"; ta = tactic_expr -> TacProgress ta
| IDENT "once"; ta = tactic_expr -> TacOnce ta
+ | IDENT "exactly_once"; ta = tactic_expr -> TacExactlyOnce ta
| IDENT "infoH"; ta = tactic_expr -> TacShowHyps ta
(*To do: put Abstract in Refiner*)
| IDENT "abstract"; tc = NEXT -> TacAbstract (tc,None)
diff --git a/printing/pptactic.ml b/printing/pptactic.ml
index f0d713be48..c5a8a380d6 100644
--- a/printing/pptactic.ml
+++ b/printing/pptactic.ml
@@ -895,6 +895,10 @@ let rec pr_tac inherited tac =
(* arnaud: vérifier qu'il s'agit bien de la syntaxe définitive. *)
hov 1 (str "once" ++ spc () ++ pr_tac (ltactical,E) t),
ltactical
+ | TacExactlyOnce t ->
+ (* arnaud: vérifier qu'il s'agit bien de la syntaxe définitive. *)
+ hov 1 (str "exactly_once" ++ spc () ++ pr_tac (ltactical,E) t),
+ ltactical
| TacOrelse (t1,t2) ->
hov 1 (pr_tac (lorelse,L) t1 ++ str " ||" ++ brk (1,1) ++
pr_tac (lorelse,E) t2),
diff --git a/proofs/proofview.ml b/proofs/proofview.ml
index 823082aced..bb1d5758d6 100644
--- a/proofs/proofview.ml
+++ b/proofs/proofview.ml
@@ -253,6 +253,28 @@ let tclONCE t =
| Nil e -> tclZERO e
| Cons (x,_) -> tclUNIT x
+exception MoreThanOneSuccess
+let _ = Errors.register_handler begin function
+ | MoreThanOneSuccess -> Errors.error "This tactic has more than one success."
+ | _ -> raise Errors.Unhandled
+end
+
+(* [tclONCE e t] succeeds as [t] if [t] has exactly one
+ success. Otherwise it fails. It may behave differently than [t] as
+ there may be extra non-logical effects used to discover that [t]
+ does not have a second success. Moreover the second success may be
+ conditional on the error recieved: [e] is used. *)
+let tclEXACTLY_ONCE e t =
+ (* spiwack: convenience notations, waiting for ocaml 3.12 *)
+ let (>>=) = Proof.bind in
+ Proof.split t >>= function
+ | Nil e -> tclZERO e
+ | Cons (x,k) ->
+ Proof.split (k e) >>= function
+ | Nil _ -> tclUNIT x
+ | _ -> tclZERO MoreThanOneSuccess
+
+
(* Focuses a tactic at a range of subgoals, found by their indices. *)
(* arnaud: bug if 0 goals ! *)
let tclFOCUS i j t =
diff --git a/proofs/proofview.mli b/proofs/proofview.mli
index 0504efea57..5b25c003d6 100644
--- a/proofs/proofview.mli
+++ b/proofs/proofview.mli
@@ -160,6 +160,13 @@ val tclIFCATCH : 'a tactic -> ('a -> 'b tactic) -> (exn -> 'b tactic) -> 'b tact
success. *)
val tclONCE : 'a tactic -> 'a tactic
+(* [tclONCE e t] succeeds as [t] if [t] has exactly one
+ success. Otherwise it fails. It may behave differently than [t] as
+ there may be extra non-logical effects used to discover that [t]
+ does not have a second success. Moreover the second success may be
+ conditional on the error recieved: [e] is used. *)
+val tclEXACTLY_ONCE : exn -> 'a tactic -> 'a tactic
+
(* Focuses a tactic at a range of subgoals, found by their indices. *)
val tclFOCUS : int -> int -> 'a tactic -> 'a tactic
diff --git a/tactics/tacintern.ml b/tactics/tacintern.ml
index 2f41ff2aea..42ea649ecd 100644
--- a/tactics/tacintern.ml
+++ b/tactics/tacintern.ml
@@ -691,6 +691,8 @@ and intern_tactic_seq onlytac ist = function
ist.ltacvars, TacOr (intern_pure_tactic ist tac1,intern_pure_tactic ist tac2)
| TacOnce tac ->
ist.ltacvars, TacOnce (intern_pure_tactic ist tac)
+ | TacExactlyOnce tac ->
+ ist.ltacvars, TacExactlyOnce (intern_pure_tactic ist tac)
| TacOrelse (tac1,tac2) ->
ist.ltacvars, TacOrelse (intern_pure_tactic ist tac1,intern_pure_tactic ist tac2)
| TacFirst l -> ist.ltacvars, TacFirst (List.map (intern_pure_tactic ist) l)
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 2c64b669c5..edb9ab66d3 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -1141,6 +1141,8 @@ and eval_tactic ist = function
Tacticals.New.tclOR (interp_tactic ist tac1) (interp_tactic ist tac2)
| TacOnce tac ->
Tacticals.New.tclONCE (interp_tactic ist tac)
+ | TacExactlyOnce tac ->
+ Tacticals.New.tclEXACTLY_ONCE (interp_tactic ist tac)
| TacOrelse (tac1,tac2) ->
Tacticals.New.tclORELSE (interp_tactic ist tac1) (interp_tactic ist tac2)
| TacFirst l -> Tacticals.New.tclFIRST (List.map (interp_tactic ist) l)
diff --git a/tactics/tacsubst.ml b/tactics/tacsubst.ml
index 44327abef2..7c968865ac 100644
--- a/tactics/tacsubst.ml
+++ b/tactics/tacsubst.ml
@@ -251,6 +251,8 @@ and subst_tactic subst (t:glob_tactic_expr) = match t with
TacOr (subst_tactic subst tac1,subst_tactic subst tac2)
| TacOnce tac ->
TacOnce (subst_tactic subst tac)
+ | TacExactlyOnce tac ->
+ TacExactlyOnce (subst_tactic subst tac)
| TacOrelse (tac1,tac2) ->
TacOrelse (subst_tactic subst tac1,subst_tactic subst tac2)
| TacFirst l -> TacFirst (List.map (subst_tactic subst) l)
diff --git a/tactics/tacticals.ml b/tactics/tacticals.ml
index 1b8cf531bc..f25bae9bb8 100644
--- a/tactics/tacticals.ml
+++ b/tactics/tacticals.ml
@@ -400,6 +400,8 @@ module New = struct
let tclONCE = Proofview.tclONCE
+ let tclEXACTLY_ONCE t = Proofview.tclEXACTLY_ONCE (Refiner.FailError(0,lazy (assert false))) t
+
let tclORELSE0 t1 t2 =
tclINDEPENDENT begin
tclORELSE
diff --git a/tactics/tacticals.mli b/tactics/tacticals.mli
index 722cb8b135..efeb4a7478 100644
--- a/tactics/tacticals.mli
+++ b/tactics/tacticals.mli
@@ -185,6 +185,7 @@ module New : sig
val tclFAIL : int -> Pp.std_ppcmds -> 'a tactic
val tclOR : unit tactic -> unit tactic -> unit tactic
val tclONCE : unit tactic -> unit tactic
+ val tclEXACTLY_ONCE : unit tactic -> unit tactic
val tclORELSE0 : unit tactic -> unit tactic -> unit tactic
val tclORELSE : unit tactic -> unit tactic -> unit tactic