Skip to content

Commit 7db6491

Browse files
committed
fix
1 parent c890823 commit 7db6491

2 files changed

Lines changed: 60 additions & 58 deletions

File tree

Mathlib/Tactic/Setm.lean

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Lua Viana Reis, Kyle Miller, Gareth Ma
66
module
77

88
public meta import Mathlib.Tactic.Set
9+
public meta import Mathlib.Tactic.Core
910
public meta import Lean.Elab.BuiltinTerm
1011
public meta import Batteries.Tactic.Exact
1112

@@ -17,26 +18,26 @@ This module defines the `setm` tactic.
1718

1819
meta section
1920

20-
open Lean Elab Tactic Meta Term Syntax
21+
open Lean Mathlib Elab Tactic Meta Term Syntax
2122

22-
abbrev SetMReplaceM := StateT (AssocList Name MVarId) TermElabM
23+
abbrev SetMReplaceM := StateT (List (Name × MVarId)) TermElabM
2324

2425
/-- Collect all synthetic holes and replace them with fresh metavariables. -/
2526
partial def replaceWithMVars (stx : Term) : SetMReplaceM Term := do
2627
let stx ← stx.raw.replaceM fun stx ↦ do
27-
if let `(?$n:ident) := stx then
28-
let mvar ← ((← get).find? n.getId).getDM do
29-
let name ← mkFreshUserName n.getId
30-
let mvar := (← mkFreshExprMVar none (userName := name)).mvarId!
31-
modify (.cons n.getId mvar)
32-
pure mvar
33-
return ← withRef stx <| `(? $(mkIdent (← mvar.getTag)))
34-
else if let `(?_) := stx then
35-
let mvar ← mkFreshExprMVar none
36-
let name ← mkFreshUserName .anonymous
37-
modify (.cons name mvar.mvarId!)
38-
return ← withRef stx <| `(? $(mkIdent name))
39-
else pure none
28+
let pair ←
29+
if let `(?$n:ident) := stx then
30+
(← get).find? (·.1 == n.getId) |>.getDM do
31+
let name ← mkFreshUserName n.getId
32+
let mvar ← mkFreshExprMVar none (userName := name)
33+
pure (n.getId, mvar.mvarId!)
34+
else if let `(?_) := stx then
35+
let name ← mkFreshUserName `x
36+
let mvar ← mkFreshExprMVar none (userName := name)
37+
pure (name, mvar.mvarId!)
38+
else return none
39+
modify (.cons pair)
40+
return ← withRef stx <| `(? $(mkIdent (← pair.2.getTag)))
4041
return ⟨stx⟩
4142

4243
/--
@@ -45,41 +46,41 @@ local declaration (using the `at h` syntax) or the main goal, and introduces `le
4546
representing subexpressions whose location corresponds to the given named hole. These variables are
4647
also substituted into the type of declaration (or main goal).
4748
-/
48-
syntax (name := setM) "setm " term (Parser.Tactic.location)? : tactic
49+
syntax (name := setM) "setm " term ("using" ident)? (Parser.Tactic.location)? : tactic
4950

50-
@[tactic setM]
51-
public def evalSetM : Tactic
52-
| `(tactic| setm $pat:term $[$loc:location]?) => withReducibleAndInstances do
53-
let locations := expandOptLocation (Lean.mkOptionalNode loc)
54-
withMainContext do
55-
let (pat, mvars) ← (replaceWithMVars pat).run {}
56-
let pat ← Term.elabTerm pat none
57-
let mut g ← getMainGoal
58-
for (name, mvar) in mvars.toList.reverse do
59-
let mvar' ← mkFreshExprMVar none
60-
g ← g.define name (← mvar'.mvarId!.getType) mvar'
61-
let (fvar, g')g.intro1P
62-
mvar.assign (.fvar fvar)
63-
g := g'
64-
replaceMainGoal [g]
65-
withLocation locations
66-
(atLocal := fun loc ↦ do
67-
if ← isDefEq pat (← loc.getType) then
68-
liftMetaTactic fun g ↦ do
69-
return [← g.replaceLocalDeclDefEq loc pat]
70-
else
71-
defeqError pat (← loc.getType))
72-
(atTarget := do
73-
liftMetaTactic fun g ↦ do
74-
if ← isDefEq pat (← g.getType) then
75-
return [← g.replaceTargetDefEq pat]
76-
else
77-
defeqError pat (← g.getType))
78-
(failed := fun _ ↦ throwError "tactic `setm` failed")
79-
| _ => throwUnsupportedSyntax
80-
where
81-
defeqError {α} (p e : Expr) : MetaM α :=
82-
throwError MessageData.ofLazyM (es := #[p, e]) do
83-
let (p, tgt) ← addPPExplicitToExposeDiff p e
84-
return m!"setm pattern{indentExpr p}\nis not definitionally equal {
85-
""}to the target{indentExpr tgt}"
51+
def defeqError {α} (p e : Expr) : MetaM α :=
52+
throwError MessageData.ofLazyM (es := #[p, e]) do
53+
let (p, tgt) ← addPPExplicitToExposeDiff p e
54+
return m!"setm pattern{indentExpr p}\nis not definitionally equal {
55+
""}to the target{indentExpr tgt}"
56+
57+
elab_rules : tactic
58+
| `(tactic| setm $pat:term $[using $usingArg]? $[$loc:location]?) =>
59+
withMainContext do
60+
let (pat, mvars) ← (replaceWithMVars pat).run {}
61+
let pat ← Term.elabTerm pat none
62+
let mut ggetMainGoal
63+
for (name, mvar) in mvars.reverse do
64+
let mvar' ← mkFreshExprMVar none
65+
g ← g.define name (← mvar'.mvarId!.getType) mvar'
66+
let (fvar, g') ← g.intro1P
67+
mvar.assign (.fvar fvar)
68+
g := g'
69+
replaceMainGoal [g]
70+
withMainContext <| withReducibleAndInstances do
71+
if let some place := usingArg.map getId then
72+
let loc := (← getLocalDeclFromUserName place).fvarId
73+
if ← isDefEq pat (← loc.getType) then
74+
replaceMainGoal [← g.changeLocalDecl loc pat false]
75+
else
76+
defeqError pat (← loc.getType)
77+
else
78+
if ← isDefEq pat (← g.getType) then
79+
replaceMainGoal [← g.replaceTargetDefEq pat]
80+
else
81+
defeqError pat (← g.getType)
82+
if let some loc := loc then
83+
for (name, _) in mvars do
84+
let expr := (← getLocalDeclFromUserName name).value
85+
evalTactic (← `(tactic| try
86+
rewrite [show $(← Term.exprToSyntax expr) = $(mkIdent name) from rfl] $loc))

MathlibTest/Tactic/Setm.lean

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ example : 1 + 2 = 3 := by
1616

1717
/- Usage with `at` keywords -/
1818
example (h1 : 1 + 1 = 5) (h2 : 1 + 3 = 5) (h3 : 1 + 2 = 5) : True := by
19-
setm ?A + _ = ?B at h1 h2 h3
19+
setm ?A + _ = ?B using h1 at *
2020
guard_hyp A :=ₛ 1
2121
guard_hyp B :=ₛ 5
22-
guard_hyp h1 :ₛ A + 1 = B
22+
guard_hyp h1 :ₛ A + A = B
2323
guard_hyp h2 :ₛ A + 3 = B
2424
guard_hyp h3 :ₛ A + 2 = B
2525
trivial
@@ -35,16 +35,17 @@ example (h : b + a = c) : a + b = c := by
3535
clear A B
3636
/- setm 2 -/
3737
rewrite [Nat.add_comm]
38-
setm ?A + ?B = _ at h
38+
setm ?A + ?B = _ at h
3939
guard_hyp A :=ₛ b
4040
guard_hyp B :=ₛ a
41+
guard_hyp h :ₛ A + B = c
4142
exact h
4243

4344
/- Strange problem -/
4445

4546
example (n : Bool) : 1 + 2 = 3 := by
4647
cases n
47-
· setm ?A + ?B = _
48+
· setm ?A + ?B = ?_
4849
guard_hyp A :=ₛ 1
4950
guard_hyp B :=ₛ 2
5051
trivial
@@ -59,7 +60,7 @@ instance : HAdd NotQuiteNat NotQuiteNat NotQuiteNat := inferInstanceAs (HAdd Nat
5960

6061
example {a b c : NotQuiteNat} (h : a + b = c) : True := by
6162
/- setm 1-/
62-
setm ?A + ?B = _ at h
63+
setm ?A + ?B = _ using h
6364
guard_hyp A := a
6465
guard_hyp B := b
6566
trivial
@@ -73,7 +74,7 @@ is not definitionally equal to the target
7374
#guard_msgs in
7475
example {a b c : NotQuiteNat} (h : a + b = c) : True := by
7576
/- setm 1-/
76-
setm (?A : Nat) + ?B = _ at h
77+
setm (?A : Nat) + ?B = _ using h
7778

7879
/- Test conflicts with goal metavariables (thanks to Niklas Halonen for this example!) -/
7980

0 commit comments

Comments
 (0)