File: Mathlib/Tactic/PushNeg.lean

full_name: Mathlib.Tactic.PushNeg.not_not_eq
code: theorem not_not_eq : (¬ ¬ p) = p 
goal: (¬¬p) = p

full_name: Mathlib.Tactic.PushNeg.not_and_eq
code: theorem not_and_eq : (¬ (p ∧ q)) = (p → ¬ q) 
goal: (¬(p ∧ q)) = (p → ¬q)

full_name: Mathlib.Tactic.PushNeg.not_and_or_eq
code: theorem not_and_or_eq : (¬ (p ∧ q)) = (¬ p ∨ ¬ q) 
goal: (¬(p ∧ q)) = (¬p ∨ ¬q)

full_name: Mathlib.Tactic.PushNeg.not_or_eq
code: theorem not_or_eq : (¬ (p ∨ q)) = (¬ p ∧ ¬ q) 
goal: (¬(p ∨ q)) = (¬p ∧ ¬q)

full_name: Mathlib.Tactic.PushNeg.not_forall_eq
code: theorem not_forall_eq : (¬ ∀ x, s x) = (∃ x, ¬ s x) 
goal: (¬∀ (x : α), s x) = ∃ x, ¬s x

full_name: Mathlib.Tactic.PushNeg.not_exists_eq
code: theorem not_exists_eq : (¬ ∃ x, s x) = (∀ x, ¬ s x) 
goal: (¬∃ x, s x) = ∀ (x : α), ¬s x

full_name: Mathlib.Tactic.PushNeg.not_implies_eq
code: theorem not_implies_eq : (¬ (p → q)) = (p ∧ ¬ q) 
goal: (¬(p → q)) = (p ∧ ¬q)

full_name: Mathlib.Tactic.PushNeg.not_ne_eq
code: theorem not_ne_eq (x y : α) : (¬ (x ≠ y)) = (x = y) 
goal: (¬x ≠ y) = (x = y)

full_name: Mathlib.Tactic.PushNeg.not_iff
code: theorem not_iff : (¬ (p ↔ q)) = ((p ∧ ¬ q) ∨ (¬ p ∧ q)) 
goal: (¬(p ↔ q)) = (p ∧ ¬q ∨ ¬p ∧ q)

full_name: Mathlib.Tactic.PushNeg.not_le_eq
code: theorem not_le_eq (a b : β) : (¬ (a ≤ b)) = (b < a) 
goal: (¬a ≤ b) = (b < a)

full_name: Mathlib.Tactic.PushNeg.not_lt_eq
code: theorem not_lt_eq (a b : β) : (¬ (a < b)) = (b ≤ a) 
goal: (¬a < b) = (b ≤ a)

full_name: Mathlib.Tactic.PushNeg.not_ge_eq
code: theorem not_ge_eq (a b : β) : (¬ (a ≥ b)) = (a < b) 
goal: (¬a ≥ b) = (a < b)

full_name: Mathlib.Tactic.PushNeg.not_gt_eq
code: theorem not_gt_eq (a b : β) : (¬ (a > b)) = (a ≤ b) 
goal: (¬a > b) = (a ≤ b)

full_name: Mathlib.Tactic.PushNeg.not_nonempty_eq
code: theorem not_nonempty_eq (s : Set β) : (¬ s.Nonempty) = (s = ∅) 
goal: (¬s.Nonempty) = (s = ∅)

full_name: Mathlib.Tactic.PushNeg.ne_empty_eq_nonempty
code: theorem ne_empty_eq_nonempty (s : Set β) : (s ≠ ∅) = s.Nonempty 
goal: (s ≠ ∅) = s.Nonempty

full_name: Mathlib.Tactic.PushNeg.empty_ne_eq_nonempty
code: theorem empty_ne_eq_nonempty (s : Set β) : (∅ ≠ s) = s.Nonempty 
goal: (∅ ≠ s) = s.Nonempty

full_name: Mathlib.Tactic.PushNeg.push_neg.use_distrib
code: /-- Make `push_neg` use `not_and_or` rather than the default `not_and`. -/
register_option push_neg.use_distrib : Bool :=
  { defValue := false
    group := ""
    descr := "Make `push_neg` use `not_and_or` rather than the default `not_and`." }
goal: Lean.Option Bool

full_name: Mathlib.Tactic.PushNeg.initFn._@.Mathlib.Tactic.PushNeg._hyg.715
code: /-- Make `push_neg` use `not_and_or` rather than the default `not_and`. -/
register_option push_neg.use_distrib : Bool :=
  { defValue := false
    group := ""
    descr := "Make `push_neg` use `not_and_or` rather than the default `not_and`." }
goal: IO (Lean.Option Bool)

full_name: Mathlib.Tactic.PushNeg.transformNegationStep
code: /-- Push negations at the top level of the current expression. -/
def transformNegationStep (e : Expr) : SimpM (Option Simp.Step) 
goal: Lean.Meta.SimpM (Option Lean.Meta.Simp.Step)

full_name: Mathlib.Tactic.PushNeg.transformNegation
code: /-- Recursively push negations at the top level of the current expression. This is needed
to handle e.g. triple negation. -/
partial def transformNegation (e : Expr) : SimpM Simp.Step 
goal: Lean.Meta.SimpM Lean.Meta.Simp.Step

full_name: Mathlib.Tactic.PushNeg.pushNegCore
code: /-- Common entry point to `push_neg` as a conv. -/
def pushNegCore (tgt : Expr) : MetaM Simp.Result 
goal: Lean.MetaM Lean.Meta.Simp.Result

full_name: Mathlib.Tactic.PushNeg.pushNegConv
code: /--
Push negations into the conclusion of an expression.
For instance, an expression `¬ ∀ x, ∃ y, x ≤ y` will be transformed by `push_neg` into
`∃ x, ∀ y, y < x`. Variable names are conserved.
This tactic pushes negations inside expressions. For instance, given a hypothesis
```lean
| ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε)
```
writing `push_neg` will turn the target into
```lean
| ∃ ε, ε > 0 ∧ ∀ δ, δ > 0 → (∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|),
```
(The pretty printer does *not* use the abbreviations `∀ δ > 0` and `∃ ε > 0` but this issue
has nothing to do with `push_neg`).

Note that names are conserved by this tactic, contrary to what would happen with `simp`
using the relevant lemmas.

This tactic has two modes: in standard mode, it transforms `¬(p ∧ q)` into `p → ¬q`, whereas in
distrib mode it produces `¬p ∨ ¬q`. To use distrib mode, use `set_option push_neg.use_distrib true`.
-/
syntax (name := pushNegConv) "push_neg" : conv
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.PushNeg.elabPushNegConv
code: /-- Execute `push_neg` as a conv tactic. -/
@[tactic pushNegConv] def elabPushNegConv : Tactic 
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.PushNeg._aux_Mathlib_Tactic_PushNeg___macroRules_Mathlib_Tactic_PushNeg_pushNeg_1
code: macro (name := pushNeg) tk:"#push_neg " e:term : command => `(command| #conv%$tk push_neg => $e)
goal: Lean.Macro

full_name: Mathlib.Tactic.PushNeg.pushNeg
code: macro (name := pushNeg) tk:"#push_neg " e:term : command => `(command| #conv%$tk push_neg => $e)
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.PushNeg.pushNegTarget
code: /-- Execute main loop of `push_neg` at the main goal. -/
def pushNegTarget : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Mathlib.Tactic.PushNeg.pushNegLocalDecl
code: /-- Execute main loop of `push_neg` at a local hypothesis. -/
def pushNegLocalDecl (fvarId : FVarId) : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Mathlib.Tactic.PushNeg._aux_Mathlib_Tactic_PushNeg___elabRules_Mathlib_Tactic_PushNeg_tacticPush_neg__1
code: /--
Push negations into the conclusion of a hypothesis.
For instance, a hypothesis `h : ¬ ∀ x, ∃ y, x ≤ y` will be transformed by `push_neg at h` into
`h : ∃ x, ∀ y, y < x`. Variable names are conserved.
This tactic pushes negations inside expressions. For instance, given a hypothesis
```lean
h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε)
```
writing `push_neg at h` will turn `h` into
```lean
h : ∃ ε, ε > 0 ∧ ∀ δ, δ > 0 → (∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|),
```
(The pretty printer does *not* use the abbreviations `∀ δ > 0` and `∃ ε > 0` but this issue
has nothing to do with `push_neg`).

Note that names are conserved by this tactic, contrary to what would happen with `simp`
using the relevant lemmas. One can also use this tactic at the goal using `push_neg`,
at every hypothesis and the goal using `push_neg at *` or at selected hypotheses and the goal
using say `push_neg at h h' ⊢` as usual.

This tactic has two modes: in standard mode, it transforms `¬(p ∧ q)` into `p → ¬q`, whereas in
distrib mode it produces `¬p ∨ ¬q`. To use distrib mode, use `set_option push_neg.use_distrib true`.
-/
elab "push_neg" loc:(location)? : tactic =>
  let loc := (loc.map expandLocation).getD (.targets #[] true)
  withLocation loc
    pushNegLocalDecl
    pushNegTarget
    (fun _ ↦ logInfo "push_neg couldn't find a negation to push")
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.PushNeg.tacticPush_neg_
code: /--
Push negations into the conclusion of a hypothesis.
For instance, a hypothesis `h : ¬ ∀ x, ∃ y, x ≤ y` will be transformed by `push_neg at h` into
`h : ∃ x, ∀ y, y < x`. Variable names are conserved.
This tactic pushes negations inside expressions. For instance, given a hypothesis
```lean
h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε)
```
writing `push_neg at h` will turn `h` into
```lean
h : ∃ ε, ε > 0 ∧ ∀ δ, δ > 0 → (∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|),
```
(The pretty printer does *not* use the abbreviations `∀ δ > 0` and `∃ ε > 0` but this issue
has nothing to do with `push_neg`).

Note that names are conserved by this tactic, contrary to what would happen with `simp`
using the relevant lemmas. One can also use this tactic at the goal using `push_neg`,
at every hypothesis and the goal using `push_neg at *` or at selected hypotheses and the goal
using say `push_neg at h h' ⊢` as usual.

This tactic has two modes: in standard mode, it transforms `¬(p ∧ q)` into `p → ¬q`, whereas in
distrib mode it produces `¬p ∨ ¬q`. To use distrib mode, use `set_option push_neg.use_distrib true`.
-/
elab "push_neg" loc:(location)? : tactic =>
  let loc := (loc.map expandLocation).getD (.targets #[] true)
  withLocation loc
    pushNegLocalDecl
    pushNegTarget
    (fun _ ↦ logInfo "push_neg couldn't find a negation to push")
goal: Lean.ParserDescr