aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Martin-Dorel2019-03-04 01:25:39 +0100
committerErik Martin-Dorel2019-04-23 20:22:05 +0200
commitbb6dc2355bcd027a3a89c40629b82eb2019eff6a (patch)
tree97495eceee09a17c9739f8e1db532ccde54e203c
parent7c598f9f1f6da2cecc70557f9f436392322fc6d9 (diff)
[ssr] under: Add iff support in side-conditions
-rw-r--r--plugins/ssr/ssrcommon.ml9
-rw-r--r--plugins/ssr/ssrcommon.mli3
-rw-r--r--plugins/ssr/ssreflect.v42
-rw-r--r--plugins/ssr/ssrequality.ml4
-rw-r--r--plugins/ssr/ssrfwd.ml13
-rw-r--r--test-suite/ssr/under.v34
6 files changed, 99 insertions, 6 deletions
diff --git a/plugins/ssr/ssrcommon.ml b/plugins/ssr/ssrcommon.ml
index 0b3bfab366..a05b1e3d81 100644
--- a/plugins/ssr/ssrcommon.ml
+++ b/plugins/ssr/ssrcommon.ml
@@ -828,10 +828,12 @@ let view_error s gv =
open Locus
(****************************** tactics ***********************************)
-let rewritetac dir c =
+let rewritetac ?(under=false) dir c =
(* Due to the new optional arg ?tac, application shouldn't be too partial *)
+ let open Proofview.Notations in
Proofview.V82.of_tactic begin
- Equality.general_rewrite (dir = L2R) AllOccurrences true false c
+ Equality.general_rewrite (dir = L2R) AllOccurrences true false c <*>
+ if under then Proofview.cycle 1 else Proofview.tclUNIT ()
end
(**********************`:********* hooks ************************************)
@@ -1542,6 +1544,7 @@ end
let is_construct_ref sigma c r =
EConstr.isConstruct sigma c && GlobRef.equal (ConstructRef (fst(EConstr.destConstruct sigma c))) r
let is_ind_ref sigma c r = EConstr.isInd sigma c && GlobRef.equal (IndRef (fst(EConstr.destInd sigma c))) r
-
+let is_const_ref sigma c r =
+ EConstr.isConst sigma c && GlobRef.equal (ConstRef (fst(EConstr.destConst sigma c))) r
(* vim: set filetype=ocaml foldmethod=marker: *)
diff --git a/plugins/ssr/ssrcommon.mli b/plugins/ssr/ssrcommon.mli
index 3049f67f87..58ce84ecb3 100644
--- a/plugins/ssr/ssrcommon.mli
+++ b/plugins/ssr/ssrcommon.mli
@@ -349,7 +349,7 @@ val resolve_typeclasses :
(*********************** Wrapped Coq tactics *****************************)
-val rewritetac : ssrdir -> EConstr.t -> tactic
+val rewritetac : ?under:bool -> ssrdir -> EConstr.t -> tactic
type name_hint = (int * EConstr.types array) option ref
@@ -486,3 +486,4 @@ end
val is_ind_ref : Evd.evar_map -> EConstr.t -> Names.GlobRef.t -> bool
val is_construct_ref : Evd.evar_map -> EConstr.t -> Names.GlobRef.t -> bool
+val is_const_ref : Evd.evar_map -> EConstr.t -> Names.GlobRef.t -> bool
diff --git a/plugins/ssr/ssreflect.v b/plugins/ssr/ssreflect.v
index 37390e1af7..94e0b2a724 100644
--- a/plugins/ssr/ssreflect.v
+++ b/plugins/ssr/ssreflect.v
@@ -550,7 +550,49 @@ End Under.
Register Under as plugins.ssreflect.Under.
Register Under_from_eq as plugins.ssreflect.Under_from_eq.
+Module Type UNDER_IFF.
+Parameter Under_iff : Prop -> Prop -> Prop.
+Parameter Under_from_iff : forall x y : Prop, @Under_iff x y -> x <-> y.
+
+(** [Over_iff, over_iff, over_iff_done]: for "by rewrite over_iff" *)
+Parameter Over_iff : Prop -> Prop -> Prop.
+Parameter over_iff :
+ forall (x : Prop) (y : Prop), @Under_iff x y = @Over_iff x y.
+Parameter over_iff_done :
+ forall (x : Prop), @Over_iff x x.
+Hint Extern 0 (@Over_iff _ _) => solve [ apply over_iff_done ] : core.
+Hint Resolve over_iff_done : core.
+
+(** [under_iff_done]: for Ltac-style over *)
+Parameter under_iff_done :
+ forall (x : Prop), @Under_iff x x.
+Notation "''Under_iff[' x ]" := (@Under_iff x _)
+ (at level 8, format "''Under_iff[' x ]").
+End UNDER_IFF.
+
+Module Export Under_iff : UNDER_IFF.
+Definition Under_iff := iff.
+Lemma Under_from_iff (x y : Prop) :
+ @Under_iff x y -> x <-> y.
+Proof. by []. Qed.
+Definition Over_iff := Under_iff.
+Lemma over_iff :
+ forall (x : Prop) (y : Prop), @Under_iff x y = @Over_iff x y.
+Proof. by []. Qed.
+Lemma over_iff_done :
+ forall (x : Prop), @Over_iff x x.
+Proof. by []. Qed.
+Lemma under_iff_done :
+ forall (x : Prop), @Under_iff x x.
+Proof. by []. Qed.
+End Under_iff.
+
+Register Under_iff as plugins.ssreflect.Under_iff.
+Register Under_from_iff as plugins.ssreflect.Under_from_iff.
+
Ltac over :=
by [ apply: Under.under_done
| rewrite over
+ | apply: Under_iff.under_iff_done
+ | rewrite over_iff
].
diff --git a/plugins/ssr/ssrequality.ml b/plugins/ssr/ssrequality.ml
index ff6dd8f75a..842e4feecf 100644
--- a/plugins/ssr/ssrequality.ml
+++ b/plugins/ssr/ssrequality.ml
@@ -406,7 +406,7 @@ let rwcltac ?under ?map_redex cl rdx dir sr gl =
let cl' = EConstr.mkApp (EConstr.mkNamedLambda (make_annot pattern_id Sorts.Relevant) rdxt cl, [|rdx|]) in
let sigma, _ = Typing.type_of env sigma cl' in
let gl = pf_merge_uc_of sigma gl in
- Proofview.V82.of_tactic (convert_concl cl'), rewritetac dir r', gl
+ Proofview.V82.of_tactic (convert_concl cl'), rewritetac ?under dir r', gl
else
let dc, r2 = EConstr.decompose_lam_n_assum (project gl) n r' in
let r3, _, r3t =
@@ -417,7 +417,7 @@ let rwcltac ?under ?map_redex cl rdx dir sr gl =
let cl'' = EConstr.mkNamedProd (make_annot pattern_id Sorts.Relevant) rdxt cl' in
let itacs = [introid pattern_id; introid rule_id] in
let cltac = Proofview.V82.of_tactic (Tactics.clear [pattern_id; rule_id]) in
- let rwtacs = [rewritetac dir (EConstr.mkVar rule_id); cltac] in
+ let rwtacs = [rewritetac ?under dir (EConstr.mkVar rule_id); cltac] in
apply_type cl'' [rdx; EConstr.it_mkLambda_or_LetIn r3 dc], tclTHENLIST (itacs @ rwtacs), gl
in
let cvtac' _ =
diff --git a/plugins/ssr/ssrfwd.ml b/plugins/ssr/ssrfwd.ml
index b5082582c9..2bac69b5b7 100644
--- a/plugins/ssr/ssrfwd.ml
+++ b/plugins/ssr/ssrfwd.ml
@@ -339,6 +339,19 @@ let intro_lock ipats =
let c = Proofview.Goal.concl gl in
let sigma = Proofview.Goal.sigma gl in
let env = Proofview.Goal.env gl in
+ match EConstr.kind_of_type sigma c with
+ | Term.AtomicType(hd, args) when
+ Ssrcommon.is_const_ref sigma hd (Coqlib.lib_ref "core.iff.type") &&
+ Array.length args = 2 && is_app_evar sigma args.(1) ->
+ Tactics.New.refine ~typecheck:true (fun sigma ->
+ let sigma, under_iff =
+ Ssrcommon.mkSsrConst "Under_iff" env sigma in
+ let sigma, under_from_iff =
+ Ssrcommon.mkSsrConst "Under_from_iff" env sigma in
+ let ty = EConstr.mkApp (under_iff,args) in
+ let sigma, t = Evarutil.new_evar env sigma ty in
+ sigma, EConstr.mkApp(under_from_iff,Array.append args [|t|]))
+ | _ ->
let t = Reductionops.whd_all env sigma c in
match EConstr.kind_of_type sigma t with
| Term.AtomicType(hd, args) when
diff --git a/test-suite/ssr/under.v b/test-suite/ssr/under.v
index 5f27858d17..1e3b0f678b 100644
--- a/test-suite/ssr/under.v
+++ b/test-suite/ssr/under.v
@@ -162,3 +162,37 @@ under x: Lem.
under Lem => [|x|] do [done|rewrite f_eq|done].
done.
Qed.
+
+
+(* Inspired From Coquelicot.Lub. *)
+(* http://coquelicot.saclay.inria.fr/html/Coquelicot.Lub.html#Lub_Rbar_eqset *)
+
+Parameters (R Rbar : Set) (R0 : R) (Rbar0 : Rbar).
+Parameter Rbar_le : Rbar -> Rbar -> Prop.
+Parameter Lub_Rbar : (R -> Prop) -> Rbar.
+Parameter Lub_Rbar_eqset :
+ forall E1 E2 : R -> Prop,
+ (forall x : R, E1 x <-> E2 x) ->
+ Lub_Rbar E1 = Lub_Rbar E2.
+
+Lemma test_Lub_Rbar (E : R -> Prop) :
+ Rbar_le Rbar0 (Lub_Rbar (fun x => x = R0 \/ E x)).
+Proof.
+under Lub_Rbar_eqset => r.
+by rewrite over.
+Abort.
+
+
+Lemma ex_iff R (P1 P2 : R -> Prop) :
+ (forall x : R, P1 x <-> P2 x) -> ((exists x, P1 x) <-> (exists x, P2 x)).
+Proof.
+by move=> H; split; move=> [x Hx]; exists x; apply H.
+Qed.
+
+Arguments ex_iff [R P1] P2 iffP12.
+
+Require Import Setoid.
+Lemma test_ex_iff (P : nat -> Prop) : (exists x, P x) -> True.
+under ex_iff => n.
+by rewrite over.
+Abort.