chore: upstream classical tactic (#5730)
This commit is contained in:
parent
487c2a937a
commit
dec1262697
4 changed files with 65 additions and 0 deletions
|
|
@ -910,6 +910,15 @@ macro_rules | `(tactic| trivial) => `(tactic| simp)
|
|||
-/
|
||||
syntax "trivial" : tactic
|
||||
|
||||
/--
|
||||
`classical tacs` runs `tacs` in a scope where `Classical.propDecidable` is a low priority
|
||||
local instance.
|
||||
|
||||
Note that `classical` is a scoping tactic: it adds the instance only within the
|
||||
scope of the tactic.
|
||||
-/
|
||||
syntax (name := classical) "classical" ppDedent(tacticSeq) : tactic
|
||||
|
||||
/--
|
||||
The `split` tactic is useful for breaking nested if-then-else and `match` expressions into separate cases.
|
||||
For a `match` expression with `n` cases, the `split` tactic generates at most `n` subgoals.
|
||||
|
|
|
|||
|
|
@ -43,3 +43,4 @@ import Lean.Elab.Tactic.Rewrites
|
|||
import Lean.Elab.Tactic.DiscrTreeKey
|
||||
import Lean.Elab.Tactic.BVDecide
|
||||
import Lean.Elab.Tactic.BoolToPropSimps
|
||||
import Lean.Elab.Tactic.Classical
|
||||
|
|
|
|||
34
src/Lean/Elab/Tactic/Classical.lean
Normal file
34
src/Lean/Elab/Tactic/Classical.lean
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/-
|
||||
Copyright (c) 2021 Mario Carneiro. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Mario Carneiro, Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Lean.Elab.Tactic.Basic
|
||||
|
||||
/-! # `classical` tactic -/
|
||||
|
||||
namespace Lean.Elab.Tactic
|
||||
open Lean Meta Elab.Tactic
|
||||
|
||||
/--
|
||||
`classical t` runs `t` in a scope where `Classical.propDecidable` is a low priority
|
||||
local instance.
|
||||
-/
|
||||
def classical [Monad m] [MonadEnv m] [MonadFinally m] [MonadLiftT MetaM m] (t : m α) :
|
||||
m α := do
|
||||
modifyEnv Meta.instanceExtension.pushScope
|
||||
Meta.addInstance ``Classical.propDecidable .local 10
|
||||
try
|
||||
t
|
||||
finally
|
||||
modifyEnv Meta.instanceExtension.popScope
|
||||
|
||||
@[builtin_tactic Lean.Parser.Tactic.classical]
|
||||
def evalClassical : Tactic := fun stx => do
|
||||
match stx with
|
||||
| `(tactic| classical $tacs:tacticSeq) =>
|
||||
classical <| Elab.Tactic.evalTactic tacs
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
end Lean.Elab.Tactic
|
||||
21
tests/lean/run/classical.lean
Normal file
21
tests/lean/run/classical.lean
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
example : Bool := by
|
||||
fail_if_success have := ∀ p, decide p -- no classical in scope
|
||||
classical
|
||||
have := ∀ p, decide p -- uses the classical instance
|
||||
guard_expr decide (0 < 1) = @decide (0 < 1) (Nat.decLt 0 1)
|
||||
exact decide (0 < 1) -- will use the decidable instance
|
||||
|
||||
-- double check no leakage
|
||||
example : Bool := by
|
||||
fail_if_success have := ∀ p, decide p -- no classical in scope
|
||||
exact decide (0 < 1) -- uses the decidable instance
|
||||
|
||||
-- check that classical respects tactic blocks
|
||||
example : Bool := by
|
||||
fail_if_success have := ∀ p, decide p -- no classical in scope
|
||||
( -- start a scope
|
||||
classical
|
||||
have := ∀ p, decide p -- uses the classical instance
|
||||
)
|
||||
fail_if_success have := ∀ p, decide p -- no classical in scope again
|
||||
exact decide (0 < 1) -- will use the decidable instance
|
||||
Loading…
Add table
Reference in a new issue