-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Introduce #check_simp command and usage. (#583)
Co-authored-by: François G. Dorais <fgdorais@gmail.com>
- Loading branch information
1 parent
15b92f4
commit 18bbb9c
Showing
4 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/- | ||
Copyright (c) 2024 Lean FRO. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Joe Hendrix | ||
-/ | ||
import Lean.Elab.Tactic.ElabTerm | ||
|
||
/- | ||
This file is the home for commands to tactics behave as expected. | ||
It currently includes two tactixs: | ||
#check_tactic t ~> res | ||
only a #check_simp command that applies simp | ||
IT | ||
-/ | ||
|
||
namespace Std.Tactic | ||
|
||
open Lean | ||
open Elab.Tactic | ||
open Meta | ||
|
||
/-- | ||
Type used to lift an arbitrary value into a type parameter so it can | ||
appear in a proof goal. | ||
It is used by the #check_tactic command. | ||
-/ | ||
private inductive CheckGoalType {α : Sort u} : (val : α) → Prop where | ||
| intro : (val : α) → CheckGoalType val | ||
|
||
/-- | ||
`check_tactic_goal t` verifies that the goal has is equal to | ||
`CheckGoalType t` with reducible transparency. It closes the goal if so | ||
and otherwise reports an error. | ||
It is used by #check_tactic. | ||
-/ | ||
local syntax (name := check_tactic_goal) "check_tactic_goal " term : tactic | ||
|
||
|
||
/-- | ||
Implementation of `check_tactic_goal` | ||
-/ | ||
@[tactic check_tactic_goal] private def evalCheckTacticGoal : Tactic := fun stx => | ||
match stx with | ||
| `(tactic| check_tactic_goal $exp) => | ||
closeMainGoalUsing (checkUnassigned := false) fun goalType => do | ||
let u ← mkFreshLevelMVar | ||
let type ← mkFreshExprMVar (.some (.sort u)) | ||
let val ← mkFreshExprMVar (.some type) | ||
let extType := mkAppN (.const ``CheckGoalType [u]) #[type, val] | ||
if !(← isDefEq goalType extType) then | ||
throwErrorAt stx "Goal{indentExpr goalType}\nis expected to match {indentExpr extType}" | ||
let expTerm ← elabTermEnsuringType exp type | ||
if !(← Meta.withReducible <| isDefEq val expTerm) then | ||
throwErrorAt stx | ||
m!"Term reduces to{indentExpr val}\nbut is expected to reduce to {indentExpr expTerm}" | ||
return mkAppN (.const ``CheckGoalType.intro [u]) #[type, val] | ||
| _ => throwErrorAt stx "check_goal syntax error" | ||
|
||
/-- | ||
`#check_tactic t ~> r by commands` runs the tactic sequence `commands` | ||
on a goal with t in the type and sees if the resulting expression has | ||
reduced it to `r`. | ||
-/ | ||
macro "#check_tactic " t:term "~>" result:term "by" tac:tactic : command => | ||
`(command|example : CheckGoalType $t := by $tac; check_tactic_goal $result) | ||
|
||
/-- | ||
`#check_simp t ~> r` checks `try simp` reduces `t` to `r`. | ||
-/ | ||
macro "#check_simp " t:term "~>" exp:term : command => | ||
`(command|#check_tactic $t ~> $exp by try simp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Std.Util.CheckTactic | ||
import Std.Data.Array | ||
|
||
section | ||
variable {α : Type _} | ||
variable [Inhabited α] | ||
variable (a : Array α) | ||
variable (i : Nat) | ||
variable (v d : α) | ||
variable (g : i < (a.set! i v).size) | ||
|
||
#check_simp (a.set! i v).get ⟨i, g⟩ ~> v | ||
#check_simp (a.set! i v).get! i ~> if i < a.size then v else default | ||
#check_simp (a.set! i v).getD i d ~> if i < a.size then v else d | ||
#check_simp (a.set! i v)[i] ~> v | ||
|
||
-- This doesn't work currently. | ||
-- It will be address in the comprehensive overhaul of array lemmas. | ||
-- #check_simp (a.set! i v)[i]? ~> .some v | ||
|
||
end |