Module F := FSetFacts.WFacts_fun E M.(** [push not using db] will pushes all negations to the
        leaves of propositions in the goal, using the lemmas in
        [db] to assist in checking the decidability of the
        propositions involved.  If [using db] is omitted, then
        [core] will be used.  Additional versions are provided
        to manipulate the hypotheses or the hypotheses and goal
        together.

        XXX: This tactic and the similar subsequent ones should
        have been defined using [autorewrite]. However, dealing
        with multiples rewrite sites and side-conditions is
        done more cleverly with the following explicit
        analysis of goals. *)

    Ltac or_not_l_iff P Q tac :=
      (rewrite (or_not_l_iff_1 P Q) by tac) ||
      (rewrite (or_not_l_iff_2 P Q) by tac).Ltac or_not_r_iff P Q tac :=
      (rewrite (or_not_r_iff_1 P Q) by tac) ||
      (rewrite (or_not_r_iff_2 P Q) by tac).Ltac or_not_l_iff_in P Q H tac :=
      (rewrite (or_not_l_iff_1 P Q) in H by tac) ||
      (rewrite (or_not_l_iff_2 P Q) in H by tac).Ltac or_not_r_iff_in P Q H tac :=
      (rewrite (or_not_r_iff_1 P Q) in H by tac) ||
      (rewrite (or_not_r_iff_2 P Q) in H by tac).

(* Specifications: *)
Lemma test_push : forall P Q R : Prop, decidable P -> decidable Q -> (~ True) -> (~ False) -> (~ ~ P) -> (~ (P /\ Q) -> ~ R) -> ((P /\ Q) \/ ~ R) -> (~ (P /\ Q) \/ R) -> (R \/ ~ (P /\ Q)) -> (~ R \/ (P /\ Q)) -> (~ P -> R) -> (~ ((R -> P) \/ (Q -> R))) -> (~ (P /\ R)) -> (~ (P -> R)) -> True.
Lemma test_pull : forall P Q R : Prop, decidable P -> decidable Q -> (~ True) -> (~ False) -> (~ ~ P) -> (~ (P /\ Q) -> ~ R) -> ((P /\ Q) \/ ~ R) -> (~ (P /\ Q) \/ R) -> (R \/ ~ (P /\ Q)) -> (~ R \/ (P /\ Q)) -> (~ P -> R) -> (~ (R -> P) /\ ~ (Q -> R)) -> (~ P \/ ~ R) -> (P /\ ~ R) -> (~ R /\ P) -> True.