@@ -20,9 +20,9 @@ structure Choice where
2020 /--
2121 Expression to be assigned to `goalOld.mvarId` if it is not possible to perform
2222 non-chronological backtracking.
23- `val ` is often a `casesOn` application.
23+ `proof ` is often a `casesOn` application containing meta-variables .
2424 -/
25- val : Expr
25+ proof : Expr
2626 /--
2727 Subgoals that still need to be processed.
2828 -/
@@ -35,6 +35,15 @@ structure SearchM.State where
3535
3636abbrev SearchM := StateRefT SearchM.State GrindM
3737
38+ def getGoal : SearchM Goal :=
39+ return (← get).goal
40+
41+ def setGoal (goal : Goal) : SearchM Unit :=
42+ modify fun s => { s with goal }
43+
44+ abbrev withCurrGoalContext (x : SearchM α) : SearchM α := do
45+ (← getGoal).mvarId.withContext x
46+
3847abbrev liftGoalM (x : GoalM α) : SearchM α := do
3948 let (a, goal) ← x.runCore (← get).goal
4049 modify fun s => { s with goal }
@@ -46,6 +55,42 @@ instance : MonadLift GoalM SearchM where
4655@[inline] def SearchM.run (goal : Goal) (x : SearchM α) : GrindM (α × SearchM.State) :=
4756 goal.mvarId.withContext do StateRefT'.run x { goal }
4857
58+ /--
59+ Given a proof containing meta-variables corresponding to the given subgoals,
60+ create a choice point.
61+ - If there are no choice points, we just close the current goal using `proof`.
62+ - If there is only one subgoal `s`, we close the current goal using `proof`, and
63+ update current goal using `s`.
64+ - If there are more than one `s :: ss`, we create a choice point using the current
65+ goal as the pending goal, and update the current goal with `s`.
66+ -/
67+ def mkChoice (proof : Expr) (subgoals : List Goal) : SearchM Unit := do
68+ assert! !(← isInconsistent)
69+ match subgoals with
70+ | [] =>
71+ (← getGoal).mvarId.assign proof
72+ | [subgoal] =>
73+ (← getGoal).mvarId.assign proof
74+ setGoal subgoal
75+ | subgoal :: subgoals =>
76+ let goalPending ← getGoal
77+ modify fun s => { s with
78+ goal := subgoal
79+ choiceStack := { goalPending, proof, todo := subgoals } :: s.choiceStack
80+ }
81+
82+ /--
83+ Create an auxiliary metavariable with the same type and tag of the metavariable
84+ associated with the current goal.
85+ We use this function to perform `cases` on the current goal without eagerly assignining it.
86+ -/
87+ def mkAuxMVarForCurrGoal : SearchM MVarId := withCurrGoalContext do
88+ let mvarId := (← getGoal).mvarId
89+ let tag ← mvarId.getTag
90+ let type ← mvarId.getType
91+ let mvarNew ← mkFreshExprSyntheticOpaqueMVar type tag
92+ return mvarNew.mvarId!
93+
4994private def findMaxFVarIdx? (e : Expr) : MetaM (Option Nat) := do
5095 let go (e : Expr) : StateT (Option Nat) MetaM Bool := do
5196 unless e.hasFVar do return false
@@ -90,7 +135,7 @@ private def nextChronoGoal : SearchM Bool := do
90135 | [] =>
91136 -- Choice point has been fully resolved.
92137 -- Go to next one.
93- choice.goalPending.mvarId.assign choice.val
138+ choice.goalPending.mvarId.assign choice.proof
94139 choices := choices'
95140 | goal :: todo =>
96141 let choice := { choice with todo }
@@ -144,8 +189,8 @@ def nextGoal : SearchM Bool := do
144189 choices := choices'
145190 else match choice.todo with
146191 | [] =>
147- -- All subgoals have been solved. We can finally assign `choice.val ` to `goalOld.mvarId`.
148- let proof ← instantiateMVars choice.val
192+ -- All subgoals have been solved. We can finally assign `choice.proof ` to `goalOld.mvarId`.
193+ let proof ← instantiateMVars choice.proof
149194 choice.goalPending.mvarId.assign proof
150195 if (← isTargetFalse choice.goalPending.mvarId) then
151196 -- `proof` is a proof of `False`, we can continue using non-chronological backtracking
0 commit comments