This PR sets up the new integrated test/bench suite. It then migrates all benchmarks and some related tests to the new suite. There's also some documentation and some linting. For now, a lot of the old tests are left alone so this PR doesn't become even larger than it already is. Eventually, all tests should be migrated to the new suite though so there isn't a confusing mix of two systems.
264 lines
5.5 KiB
Text
264 lines
5.5 KiB
Text
import Lean
|
|
/-!
|
|
# Tests for tactic configuration elaboration
|
|
-/
|
|
|
|
open Lean
|
|
|
|
/-!
|
|
Simple tactic configuration
|
|
-/
|
|
structure MyTacticConfig where
|
|
x : Nat := 0
|
|
y : Bool := false
|
|
deriving Repr
|
|
|
|
declare_config_elab elabMyTacticConfig MyTacticConfig
|
|
|
|
elab "my_tactic" cfg:Parser.Tactic.optConfig : tactic => do
|
|
let config ← elabMyTacticConfig cfg
|
|
logInfo m!"config is {repr config}"
|
|
|
|
/--
|
|
info: config is { x := 0, y := false }
|
|
---
|
|
info: config is { x := 0, y := true }
|
|
---
|
|
info: config is { x := 1, y := false }
|
|
---
|
|
info: config is { x := 2, y := false }
|
|
---
|
|
info: config is { x := 1, y := true }
|
|
---
|
|
info: config is { x := 0, y := false }
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
my_tactic
|
|
my_tactic +y
|
|
my_tactic (x := 1)
|
|
my_tactic -y (x := 2)
|
|
my_tactic (config := {x := 1, y := true})
|
|
my_tactic +y (config := {y := false})
|
|
trivial
|
|
|
|
/-!
|
|
Basic errors
|
|
-/
|
|
|
|
/--
|
|
error: Option is not boolean-valued, so `(x := ...)` syntax must be used
|
|
---
|
|
info: config is { x := 0, y := false }
|
|
---
|
|
error: unsolved goals
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in example : True := by my_tactic +x
|
|
|
|
/--
|
|
error: Structure `MyTacticConfig` does not have a field named `w`
|
|
---
|
|
info: config is { x := 0, y := false }
|
|
---
|
|
error: unsolved goals
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in example : True := by my_tactic +w
|
|
|
|
/--
|
|
error: Field `x` of structure `MyTacticConfig` is not a structure
|
|
---
|
|
info: config is { x := 0, y := false }
|
|
---
|
|
error: unsolved goals
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in example : True := by my_tactic +x.a
|
|
|
|
/-!
|
|
A tactic configuration extending another with different default values.
|
|
-/
|
|
structure MyTacticConfig' extends MyTacticConfig where
|
|
x := 22
|
|
y := true
|
|
deriving Repr
|
|
|
|
declare_config_elab elabMyTacticConfig' MyTacticConfig'
|
|
|
|
elab "my_tactic'" cfg:Parser.Tactic.optConfig : tactic => do
|
|
let config ← elabMyTacticConfig' cfg
|
|
logInfo m!"config is {repr config}"
|
|
|
|
/--
|
|
info: config is { toMyTacticConfig := { x := 22, y := true } }
|
|
---
|
|
info: config is { toMyTacticConfig := { x := 22, y := true } }
|
|
---
|
|
info: config is { toMyTacticConfig := { x := 1, y := true } }
|
|
---
|
|
info: config is { toMyTacticConfig := { x := 2, y := false } }
|
|
---
|
|
info: config is { toMyTacticConfig := { x := 1, y := true } }
|
|
---
|
|
info: config is { toMyTacticConfig := { x := 22, y := false } }
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
my_tactic'
|
|
my_tactic' +y
|
|
my_tactic' (x := 1)
|
|
my_tactic' -y (x := 2)
|
|
my_tactic' (config := {x := 1, y := true})
|
|
my_tactic' +y (config := {y := false})
|
|
trivial
|
|
|
|
/-!
|
|
Tactic configurations with hierarchical fields
|
|
-/
|
|
|
|
structure A where
|
|
x : Bool := true
|
|
deriving Repr
|
|
structure B extends A
|
|
deriving Repr
|
|
structure C where
|
|
b : B := {}
|
|
deriving Repr
|
|
declare_config_elab elabC C
|
|
|
|
elab "ctac" cfg:Parser.Tactic.optConfig : tactic => do
|
|
let config ← elabC cfg
|
|
logInfo m!"config is {repr config}"
|
|
|
|
/--
|
|
info: config is { b := { toA := { x := false } } }
|
|
---
|
|
info: config is { b := { toA := { x := false } } }
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
ctac -b.x
|
|
ctac -b.toA.x
|
|
trivial
|
|
|
|
/-!
|
|
Responds to recovery mode. In these, `ctac` continues even though configuration elaboration failed.
|
|
-/
|
|
|
|
/--
|
|
error: Structure `C` does not have a field named `x`
|
|
---
|
|
info: config is { b := { toA := { x := true } } }
|
|
---
|
|
trace: ⊢ True
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
ctac -x
|
|
trace_state
|
|
trivial
|
|
|
|
-- Check that when recovery mode is false, no error is reported.
|
|
/-- trace: ⊢ True -/
|
|
#guard_msgs in
|
|
example : True := by
|
|
fail_if_success ctac -x
|
|
trace_state
|
|
trivial
|
|
|
|
/--
|
|
error: Structure `C` does not have a field named `x`
|
|
---
|
|
info: config is { b := { toA := { x := true } } }
|
|
---
|
|
error: unsolved goals
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
ctac -x
|
|
done
|
|
|
|
/-!
|
|
Responds to recovery mode. In this, `ctac` fails, doesn't report anything, and then execution continues to `exact`.
|
|
-/
|
|
|
|
/-- error: Unknown identifier `blah` -/
|
|
#guard_msgs in
|
|
example : True := by
|
|
first | ctac +x | exact blah
|
|
|
|
/-!
|
|
Elaboration errors cause the tactic to use the default configuration.
|
|
-/
|
|
|
|
/--
|
|
error: Type mismatch
|
|
false
|
|
has type
|
|
Bool
|
|
but is expected to have type
|
|
B
|
|
---
|
|
info: config is { b := { toA := { x := true } } }
|
|
---
|
|
error: unsolved goals
|
|
⊢ True
|
|
-/
|
|
#guard_msgs in
|
|
example : True := by
|
|
ctac (b := false)
|
|
done
|
|
|
|
|
|
/-!
|
|
Elaboration for command configuration
|
|
-/
|
|
|
|
structure MyCommandConfig where
|
|
x : Nat := 0
|
|
y : Bool := false
|
|
deriving Repr
|
|
|
|
declare_command_config_elab elabMyCommandConfig MyCommandConfig
|
|
|
|
elab "my_command" cfg:Parser.Tactic.optConfig : command => do
|
|
let config ← elabMyCommandConfig cfg
|
|
logInfo m!"config is {repr config}"
|
|
|
|
/-- info: config is { x := 0, y := false } -/
|
|
#guard_msgs in my_command
|
|
/-- info: config is { x := 0, y := true } -/
|
|
#guard_msgs in my_command +y
|
|
/-- info: config is { x := 1, y := true } -/
|
|
#guard_msgs in my_command (x := 1) (y := true)
|
|
/-- info: config is { x := 0, y := false } -/
|
|
#guard_msgs in my_command (x := 1) (y := true) (config := {})
|
|
/--
|
|
error: Type mismatch
|
|
true
|
|
has type
|
|
Bool
|
|
but is expected to have type
|
|
Nat
|
|
---
|
|
info: config is { x := 0, y := false }
|
|
-/
|
|
#guard_msgs in my_command (x := true)
|
|
|
|
|
|
/-!
|
|
Pretty printing of configuration, checking whitespace is present.
|
|
-/
|
|
elab "#pp_tac " t:tactic : command => Elab.Command.liftTermElabM do
|
|
logInfo (← PrettyPrinter.ppTactic t)
|
|
|
|
/-- info: simp +contextual -/
|
|
#guard_msgs in #pp_tac simp +contextual
|
|
/-- info: simp +contextual -/
|
|
#guard_msgs in #pp_tac simp+contextual
|
|
/-- info: simp (contextual := true) +zeta -/
|
|
#guard_msgs in #pp_tac simp (contextual := true) +zeta
|
|
/-- info: simp (contextual := true) +zeta -/
|
|
#guard_msgs in #pp_tac simp(contextual := true)+zeta
|