@@ -6,6 +6,7 @@ Authors: Leonardo de Moura
66module
77prelude
88public import Lean.Elab.Tactic.Grind.Basic
9+ import Lean.Meta.Tactic.TryThis
910import Lean.Meta.Tactic.Grind.Solve
1011import Lean.Meta.Tactic.Grind.Arith.Cutsat.Search
1112import Lean.Meta.Tactic.Grind.Arith.Linear.Search
@@ -22,6 +23,7 @@ import Lean.Meta.Tactic.Grind.AC.PP
2223import Lean.Meta.Tactic.ExposeNames
2324import Lean.Elab.Tactic.Basic
2425import Lean.Elab.Tactic.RenameInaccessibles
26+ import Lean.Elab.Tactic.Grind.Filter
2527namespace Lean.Elab.Tactic.Grind
2628
2729def evalSepTactics (stx : Syntax) : GrindTacticM Unit := do
@@ -126,17 +128,15 @@ def elabAnchor (anchor : TSyntax `hexnum) : CoreM (Nat × UInt64) := do
126128 return (numDigits, val)
127129
128130@[builtin_grind_tactic instantiate] def evalInstantiate : GrindTactic := fun stx => withMainContext do
129- match stx with
130- | `(grind| instantiate $[$thmRefs:thm],*) =>
131- let mut thms := #[]
132- for thmRef in thmRefs do
133- match thmRef with
134- | `(Parser.Tactic.Grind.thm| #$anchor:hexnum) => thms := thms ++ (← withRef thmRef <| elabLocalEMatchTheorem anchor)
135- | `(Parser.Tactic.Grind.thm| $[$mod?:grindMod]? $id:ident) => thms := thms ++ (← withRef thmRef <| elabThm mod? id false )
136- | `(Parser.Tactic.Grind.thm| ! $[$mod?:grindMod]? $id:ident) => thms := thms ++ (← withRef thmRef <| elabThm mod? id true )
137- | _ => throwErrorAt thmRef "unexpected theorem reference"
138- ematchThms thms
139- | _ => throwUnsupportedSyntax
131+ let `(grind| instantiate $[$thmRefs:thm],*) := stx | throwUnsupportedSyntax
132+ let mut thms := #[]
133+ for thmRef in thmRefs do
134+ match thmRef with
135+ | `(Parser.Tactic.Grind.thm| #$anchor:hexnum) => thms := thms ++ (← withRef thmRef <| elabLocalEMatchTheorem anchor)
136+ | `(Parser.Tactic.Grind.thm| $[$mod?:grindMod]? $id:ident) => thms := thms ++ (← withRef thmRef <| elabThm mod? id false )
137+ | `(Parser.Tactic.Grind.thm| ! $[$mod?:grindMod]? $id:ident) => thms := thms ++ (← withRef thmRef <| elabThm mod? id true )
138+ | _ => throwErrorAt thmRef "unexpected theorem reference"
139+ ematchThms thms
140140where
141141 collectThms (numDigits : Nat) (anchorPrefix : UInt64) (thms : PArray EMatchTheorem) : StateT (Array EMatchTheorem) GrindTacticM Unit := do
142142 let mut found : Std.HashSet Expr := {}
@@ -248,31 +248,47 @@ def logAnchor (numDigits : Nat) (anchorPrefix : UInt64) (e : Expr) : TermElabM U
248248 m!"#{anchorToString numDigits anchorPrefix} := {e}"
249249
250250@[builtin_grind_tactic cases] def evalCases : GrindTactic := fun stx => do
251- match stx with
252- | `(grind| cases #$anchor:hexnum) =>
253- let (numDigits, val) ← elabAnchor anchor
254- let goal ← getMainGoal
255- let candidates := goal.split.candidates
256- let (e, goals, genNew) ← liftSearchM do
257- for c in candidates do
258- let e := c.getExpr
259- let anchor ← getAnchor c.getExpr
260- if isAnchorPrefix numDigits val anchor then
261- let some result ← split? c
262- | throwError "`cases` tactic failed, case-split is not ready{indentExpr c.getExpr}"
263- return (e, result)
264- throwError "`cases` tactic failed, invalid anchor"
265- goal.withContext <| withRef anchor <| logAnchor numDigits val e
266- let goals ← goals.filterMapM fun goal => do
267- let (goal, _) ← liftGrindM <| SearchM.run goal do
268- intros genNew
269- getGoal
270- if goal.inconsistent then
271- return none
272- else
273- return some goal
274- replaceMainGoal goals
275- | _ => throwUnsupportedSyntax
251+ let `(grind| cases #$anchor:hexnum) := stx | throwUnsupportedSyntax
252+ let (numDigits, val) ← elabAnchor anchor
253+ let goal ← getMainGoal
254+ let candidates := goal.split.candidates
255+ let (e, goals, genNew) ← liftSearchM do
256+ for c in candidates do
257+ let e := c.getExpr
258+ let anchor ← getAnchor c.getExpr
259+ if isAnchorPrefix numDigits val anchor then
260+ let some result ← split? c
261+ | throwError "`cases` tactic failed, case-split is not ready{indentExpr c.getExpr}"
262+ return (e, result)
263+ throwError "`cases` tactic failed, invalid anchor"
264+ goal.withContext <| withRef anchor <| logAnchor numDigits val e
265+ let goals ← goals.filterMapM fun goal => do
266+ let (goal, _) ← liftGrindM <| SearchM.run goal do
267+ intros genNew
268+ getGoal
269+ if goal.inconsistent then
270+ return none
271+ else
272+ return some goal
273+ replaceMainGoal goals
274+
275+ def mkCasesSuggestions (candidates : Array SplitCandidateWithAnchor) (numDigits : Nat) : MetaM (Array Tactic.TryThis.Suggestion) := do
276+ candidates.mapM fun { anchor, e, .. } => do
277+ let anchorStx ← mkAnchorSyntax numDigits anchor
278+ let tac ← `(grind| cases $anchorStx:anchor)
279+ let msg ← addMessageContext m!"{tac} for{indentExpr e}"
280+ return {
281+ suggestion := .tsyntax tac
282+ messageData? := some msg
283+ }
284+
285+ @[builtin_grind_tactic casesTrace] def evalCasesTrace : GrindTactic := fun stx => withMainContext do
286+ let `(grind| cases? $[$filter?]?) := stx | throwUnsupportedSyntax
287+ let filter ← elabFilter filter?
288+ let { candidates, numDigits } ← liftGoalM <| getSplitCandidateAnchors filter.eval
289+ let suggestions ← mkCasesSuggestions candidates numDigits
290+ Tactic.TryThis.addSuggestions stx suggestions
291+ return ()
276292
277293@[builtin_grind_tactic Parser.Tactic.Grind.focus] def evalFocus : GrindTactic := fun stx => do
278294 let mkInfo ← mkInitialTacticInfo stx[0 ]
@@ -335,28 +351,24 @@ public def renameInaccessibles (mvarId : MVarId) (hs : TSyntaxArray ``binderIden
335351 return mvarId
336352
337353@[builtin_grind_tactic «next»] def evalNext : GrindTactic := fun stx => do
338- match stx with
339- | `(grind| next%$nextTk $hs* =>%$arr $seq:grindSeq) => do
340- let goal :: goals ← getUnsolvedGoals | throwNoGoalsToBeSolved
341- let mvarId ← renameInaccessibles goal.mvarId hs
342- let goal := { goal with mvarId }
343- setGoals [goal]
344- goal.mvarId.setTag Name.anonymous
345- withCaseRef arr seq <| closeUsingOrAdmit <| withTacticInfoContext (mkNullNode #[nextTk, arr]) <|
346- evalGrindTactic stx[3 ]
347- setGoals goals
348- | _ => throwUnsupportedSyntax
354+ let `(grind| next%$nextTk $hs* =>%$arr $seq:grindSeq) := stx | throwUnsupportedSyntax
355+ let goal :: goals ← getUnsolvedGoals | throwNoGoalsToBeSolved
356+ let mvarId ← renameInaccessibles goal.mvarId hs
357+ let goal := { goal with mvarId }
358+ setGoals [goal]
359+ goal.mvarId.setTag Name.anonymous
360+ withCaseRef arr seq <| closeUsingOrAdmit <| withTacticInfoContext (mkNullNode #[nextTk, arr]) <|
361+ evalGrindTactic stx[3 ]
362+ setGoals goals
349363
350364@[builtin_grind_tactic nestedTacticCore] def evalNestedTactic : GrindTactic := fun stx => do
351- match stx with
352- | `(grind| tactic%$tacticTk =>%$arr $seq:tacticSeq) => do
353- let goal ← getMainGoal
354- let recover := (← read).recover
355- discard <| Tactic.run goal.mvarId <| withCaseRef arr seq <| Tactic.closeUsingOrAdmit
356- <| Tactic.withTacticInfoContext (mkNullNode #[tacticTk, arr])
357- <| Tactic.withRecover recover <| evalTactic seq
358- replaceMainGoal []
359- | _ => throwUnsupportedSyntax
365+ let `(grind| tactic%$tacticTk =>%$arr $seq:tacticSeq) := stx | throwUnsupportedSyntax
366+ let goal ← getMainGoal
367+ let recover := (← read).recover
368+ discard <| Tactic.run goal.mvarId <| withCaseRef arr seq <| Tactic.closeUsingOrAdmit
369+ <| Tactic.withTacticInfoContext (mkNullNode #[tacticTk, arr])
370+ <| Tactic.withRecover recover <| evalTactic seq
371+ replaceMainGoal []
360372
361373@[builtin_grind_tactic «first»] partial def evalFirst : GrindTactic := fun stx => do
362374 let tacs := stx[1 ].getArgs
@@ -383,12 +395,11 @@ where
383395 | `(grind| fail $msg:str) => throwError "{msg.getString}\n {goalsMsg}"
384396 | _ => throwUnsupportedSyntax
385397
386- @[builtin_grind_tactic «renameI»] def evalRenameInaccessibles : GrindTactic
387- | `(grind| rename_i $hs*) => do
388- let goal ← getMainGoal
389- let mvarId ← renameInaccessibles goal.mvarId hs
390- replaceMainGoal [{ goal with mvarId }]
391- | _ => throwUnsupportedSyntax
398+ @[builtin_grind_tactic «renameI»] def evalRenameInaccessibles : GrindTactic := fun stx => do
399+ let `(grind| rename_i $hs*) := stx | throwUnsupportedSyntax
400+ let goal ← getMainGoal
401+ let mvarId ← renameInaccessibles goal.mvarId hs
402+ replaceMainGoal [{ goal with mvarId }]
392403
393404@[builtin_grind_tactic exposeNames] def evalExposeNames : GrindTactic := fun _ => do
394405 let goal ← getMainGoal
0 commit comments