Skip to content

Commit 9a65c5a

Browse files
committed
feat: compute number of anchor digits
1 parent a7ca25a commit 9a65c5a

File tree

2 files changed

+37
-21
lines changed

2 files changed

+37
-21
lines changed

src/Lean/Elab/Tactic/Grind/Show.lean

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -169,22 +169,7 @@ def pushIfSome (msgs : Array MessageData) (msg? : Option MessageData) : Array Me
169169
match stx with
170170
| `(grind| show_splits $[$filter?]?) =>
171171
let filter ← elabFilter filter?
172-
let goal ← getMainGoal
173-
let candidates := goal.split.candidates
174-
let candidates ← liftGoalM <| candidates.toArray.mapM fun c => do
175-
let e := c.getExpr
176-
let anchor ← getAnchor e
177-
let status ← checkSplitStatus c
178-
return (e, status, anchor)
179-
let candidates ← liftGoalM <| candidates.filterM fun (e, status, _) => do
180-
-- **Note**: we ignore case-splits that are not ready or have already been resolved.
181-
-- We may consider adding an option for including "not-ready" splits in the future.
182-
if status matches .resolved | .notReady then return false
183-
filter.eval e
184-
-- **TODO**: Add an option for including propositions that are only considered when using `+splitImp`
185-
-- **TODO**: Add an option for including terms whose type is an inductive predicate or type
186-
let candidates := candidates.map fun (e, _, anchor) => (anchor, e)
187-
let (candidates, numDigits) := truncateAnchors candidates
172+
let { candidates, numDigits } ← liftGoalM <| getSplitCandidateAnchors filter.eval
188173
if candidates.isEmpty then
189174
throwError "no case splits"
190175
let msgs := candidates.map fun (a, e) =>

src/Lean/Meta/Tactic/Grind/Split.lean

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,34 @@ private def casesWithTrace (mvarId : MVarId) (major : Expr) : GoalM (List MVarId
242242
saveCases declName false
243243
cases mvarId major
244244

245+
structure SplitCandidateAnchors where
246+
/-- Pairs `(anchor, split)` -/
247+
candidates : Array (UInt64 × Expr)
248+
/-- Number of digits (≥ 4) sufficient for distinguishing anchors. We usually display only the first `numDigits`. -/
249+
numDigits : Nat
250+
251+
/--
252+
Returns case-split candidates. Case-splits that are tagged as `.resolved` or `.notReady` are skipped.
253+
Applies additional `filter` if provided.
254+
-/
255+
def getSplitCandidateAnchors (filter : Expr → GoalM Bool := fun _ => return true) : GoalM SplitCandidateAnchors := do
256+
let candidates := (← get).split.candidates
257+
let candidates ← candidates.toArray.mapM fun c => do
258+
let e := c.getExpr
259+
let anchor ← getAnchor e
260+
let status ← checkSplitStatus c
261+
return (e, status, anchor)
262+
let candidates ← candidates.filterM fun (e, status, _) => do
263+
-- **Note**: we ignore case-splits that are not ready or have already been resolved.
264+
-- We may consider adding an option for including "not-ready" splits in the future.
265+
if status matches .resolved | .notReady then return false
266+
filter e
267+
-- **TODO**: Add an option for including propositions that are only considered when using `+splitImp`
268+
-- **TODO**: Add an option for including terms whose type is an inductive predicate or type
269+
let candidates := candidates.map fun (e, _, anchor) => (anchor, e)
270+
let (candidates, numDigits) := truncateAnchors candidates
271+
return { candidates, numDigits }
272+
245273
namespace Action
246274

247275
/--
@@ -325,9 +353,10 @@ Remark: `numCases` and `isRec` are computed using `checkSplitStatus`.
325353
private def splitCore (c : SplitInfo) (numCases : Nat) (isRec : Bool)
326354
(stopAtFirstFailure : Bool)
327355
(compress : Bool) : Action := fun goal _ kp => do
356+
let traceEnabled := (← getConfig).trace
328357
let mvarId ← goal.mkAuxMVar
329358
let cExpr := c.getExpr
330-
let (mvarIds, goal) ← GoalM.run goal do
359+
let ((mvarIds, numDigits), goal) ← GoalM.run goal do
331360
let gen ← getGeneration cExpr
332361
let genNew := if numCases > 1 || isRec then gen+1 else gen
333362
saveSplitDiagInfo cExpr genNew numCases c.source
@@ -339,8 +368,12 @@ private def splitCore (c : SplitInfo) (numCases : Nat) (isRec : Bool)
339368
casesMatch mvarId cExpr
340369
else
341370
casesWithTrace mvarId (← mkCasesMajor cExpr)
371+
let numDigits ← if traceEnabled then
372+
pure (← getSplitCandidateAnchors).numDigits
373+
else
374+
pure 0
375+
return (mvarIds, numDigits)
342376
let subgoals := mvarIds.map fun mvarId => { goal with mvarId }
343-
let traceEnabled := (← getConfig).trace
344377
let mut seqNew : Array (List (TSyntax `grind)) := #[]
345378
let mut stuckNew : Array Goal := #[]
346379
for subgoal in subgoals do
@@ -369,9 +402,7 @@ private def splitCore (c : SplitInfo) (numCases : Nat) (isRec : Bool)
369402
if stuckNew.isEmpty then
370403
if traceEnabled then
371404
let anchor ← goal.withContext <| getAnchor cExpr
372-
-- **TODO**: compute the exact number of digits
373-
let numDigits := 4
374-
let anchorPrefix := anchor >>> (64 - 16)
405+
let anchorPrefix := anchor >>> (64 - 4*numDigits.toUInt64)
375406
let hexnum := mkNode `hexnum #[mkAtom (anchorToString numDigits anchorPrefix)]
376407
let cases ← `(grind| cases #$hexnum)
377408
return .closed (← mkCasesResultSeq cases seqNew compress)

0 commit comments

Comments
 (0)