98 lines
2.7 KiB
Text
98 lines
2.7 KiB
Text
/-
|
||
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura
|
||
-/
|
||
prelude
|
||
import Lean.Meta.Tactic.Grind.Combinators
|
||
import Lean.Meta.Tactic.Grind.Split
|
||
import Lean.Meta.Tactic.Grind.EMatch
|
||
import Lean.Meta.Tactic.Grind.Arith
|
||
|
||
namespace Lean.Meta.Grind
|
||
|
||
namespace Solve
|
||
|
||
structure State where
|
||
todo : List Goal
|
||
failures : List Goal := []
|
||
stop : Bool := false
|
||
|
||
private abbrev M := StateRefT State GrindM
|
||
|
||
def getNext? : M (Option Goal) := do
|
||
let goal::todo := (← get).todo | return none
|
||
modify fun s => { s with todo }
|
||
return some goal
|
||
|
||
def pushGoal (goal : Goal) : M Unit :=
|
||
modify fun s => { s with todo := goal :: s.todo }
|
||
|
||
def pushGoals (goals : List Goal) : M Unit :=
|
||
modify fun s => { s with todo := goals ++ s.todo }
|
||
|
||
def pushFailure (goal : Goal) : M Unit := do
|
||
modify fun s => { s with failures := goal :: s.failures }
|
||
if (← get).failures.length ≥ (← getConfig).failures then
|
||
modify fun s => { s with stop := true }
|
||
|
||
@[inline] def stepGuard (x : Goal → M Bool) (goal : Goal) : M Bool := do
|
||
try
|
||
x goal
|
||
catch ex =>
|
||
if ex.isMaxHeartbeat || ex.isMaxRecDepth then
|
||
reportIssue! ex.toMessageData
|
||
pushFailure goal
|
||
return true
|
||
else
|
||
throw ex
|
||
|
||
def applyTac (x : GrindTactic) (goal : Goal) : M Bool := do
|
||
let go (goal : Goal) : M Bool := do
|
||
let some goals ← x goal | return false
|
||
pushGoals goals
|
||
return true
|
||
stepGuard go goal
|
||
|
||
def tryAssertNext : Goal → M Bool := applyTac assertNext
|
||
|
||
def tryEmatch : Goal → M Bool := applyTac ematchAndAssert
|
||
|
||
def trySplit : Goal → M Bool := applyTac splitNext
|
||
|
||
def tryArith : Goal → M Bool := applyTac Arith.check
|
||
|
||
def maxNumFailuresReached : M Bool := do
|
||
return (← get).failures.length ≥ (← getConfig).failures
|
||
|
||
partial def main (fallback : Fallback) : M Unit := do
|
||
repeat do
|
||
if (← get).stop then
|
||
return ()
|
||
let some goal ← getNext? |
|
||
return ()
|
||
if goal.inconsistent then
|
||
continue
|
||
if (← tryAssertNext goal) then
|
||
continue
|
||
if (← tryArith goal) then
|
||
continue
|
||
if (← tryEmatch goal) then
|
||
continue
|
||
if (← trySplit goal) then
|
||
continue
|
||
let goal ← GoalM.run' goal fallback
|
||
if goal.inconsistent || (← goal.mvarId.isAssigned) then
|
||
continue
|
||
pushFailure goal
|
||
|
||
end Solve
|
||
|
||
/--
|
||
Try to solve/close the given goals, and returns the ones that could not be solved.
|
||
-/
|
||
def solve (goals : List Goal) (fallback : Fallback) : GrindM (List Goal × List Goal) := do
|
||
let (_, s) ← Solve.main fallback |>.run { todo := goals }
|
||
return (s.failures.reverse, s.todo)
|
||
|
||
end Lean.Meta.Grind
|