@@ -14,58 +14,34 @@ public meta import Lean.Elab.BuiltinTerm
1414This module defines the `setm` tactic.
1515-/
1616
17- public meta section
17+ meta section
1818
1919open Lean Elab Tactic Meta Term Syntax
2020
2121namespace Mathlib.Tactic.SetM
2222
23- /-- This parser is declared inside a hidden namespace and should never be used. Its
24- purpose is to register the ``Hidden.setmSyntheticHole` syntaax node kind in
25- the environment. -/
26- scoped syntax :max (name := Hidden.setmSyntheticHole)
27- "?" (ident <|> "_" ) : term
28-
29- open Hidden in
30- /-- We give a distinguished name to the named holes appearing in the `setm` match pattern,
31- to avoid unifying them with other metavariables in the context which have the same name. The
32- distinguished name is reused across all holes with the same name in the pattern. -/
33- meta partial def wrapSyntheticHoles : Syntax → StateT (NameMap Name) TacticM Syntax :=
23+ partial def wrapSyntheticHoles : Syntax → StateT (NameMap MVarId) TacticM Syntax :=
3424 fun stx => do
3525 if stx.isOfKind ``Lean.Parser.Term.syntheticHole && stx[1 ].isIdent then
36- let name ←
26+ let mvar ←
3727 if let .some old := (← get).get? stx[1 ].getId then
3828 pure old
3929 else
40- let unique ← mkFreshUserName stx[1 ].getId
41- modify (.insert · stx[1 ].getId unique)
42- pure unique
43- return stx.setKind ``setmSyntheticHole |>.setArg 1 (mkIdent name)
30+ let name ← mkFreshUserName stx[1 ].getId
31+ let mvar := (← mkFreshExprMVar .none (userName := name)).mvarId!
32+ modify (.insert · stx[1 ].getId mvar)
33+ pure mvar
34+ let ident : Ident := mkIdent (← mvar.getTag)
35+ return ← withRef stx <| `(? $ident)
4436 match stx with
4537 | .node info kind args => return .node info kind (← args.mapM wrapSyntheticHoles)
4638 | _ => return stx
4739
48- open Hidden in
49- /-- Elaborate the named `setm` holes, creating metavariables for them. -/
50- @ [term_elab Hidden.setmSyntheticHole]
51- def elabSetmSyntheticHole : Term.TermElab := fun stx expectedType? => do
52- unless stx.isOfKind ``setmSyntheticHole do
53- throwUnsupportedSyntax
54- if let .ident _ _ n _ := stx[1 ] then
55- -- Reuse metavariables in the context who have the same name.
56- -- nb: at this point, they already have the distinguished names, so this is safe.
57- for (id, decl) in (← getMCtx).decls do
58- if decl.userName == n then return .mvar id
59- let mvar ← mkFreshExprMVar expectedType? (userName := n)
60- registerMVarErrorHoleInfo mvar.mvarId! stx
61- return mvar
62- else elabHole stx expectedType?
63-
6440syntax (name := setMStx) "setm " term (Parser.Tactic.location)? : tactic
6541
6642-- This code was copied from the `change` tactic in core. I am not sure if in our context,
6743-- all of it is necessary (could there be other synthetic opaque MVars that were not holes?).
68- meta def elabSetM (e : Expr) (p : Syntax) : TacticM Expr := do
44+ def elabSetM (e : Expr) (p : Syntax) : TacticM Expr := do
6945 let p ← runTermElab do
7046 let p ← Term.elabTermEnsuringType p (← inferType e)
7147 unless ← isDefEq p e do
@@ -80,25 +56,16 @@ meta def elabSetM (e : Expr) (p : Syntax) : TacticM Expr := do
8056 return ← instantiateMVars p
8157
8258@ [tactic setMStx]
83- meta def evalSetM : Tactic
59+ public def evalSetM : Tactic
8460 | `(tactic| setm $pat:term $[$loc:location]?) => withReducibleAndInstances do
85- let (pat, names ) ← StateT.run (wrapSyntheticHoles pat) .empty
61+ let (pat, mvars ) ← StateT.run (wrapSyntheticHoles pat) .empty
8662 let locations := expandOptLocation (Lean.mkOptionalNode loc)
8763 -- First, unify the pattern with the target of each location.
8864 withLocation locations
8965 (atLocal := unify pat ∘ .some)
9066 (atTarget := unify pat .none)
9167 (failed := fun _ ↦ throwError "'setm' tactic failed" )
92- -- Now, make a mapping of hole names to the metavariables that appeared in the pattern.
93- let mctx ← getMCtx
94- let mvars : NameMap MVarId := mctx.decls.foldl (init := {}) fun acc id decl =>
95- if let Option.some n := Id.run <| do
96- for (n, un) in names do
97- if un == decl.userName then return .some n
98- return .none
99- then acc.insert n id
100- else acc
101- -- Finally, for each metavariable...
68+ -- The, for each metavariable...
10269 for (n, m) in mvars do
10370 -- ... instantiate it and introduce a let into the context...
10471 let val ← instantiateMVars (.mvar m)
0 commit comments