feat: Collect sorry/elab failure boundaries
This commit is contained in:
parent
0b4ded1049
commit
dd00d803d1
|
@ -30,6 +30,13 @@ end Lean.PersistentArray
|
|||
|
||||
namespace Pantograph.Frontend
|
||||
|
||||
@[export pantograph_frontend_stx_byte_range]
|
||||
def stxByteRange (stx : Syntax) : String.Pos × String.Pos :=
|
||||
let pos := stx.getPos?.getD 0
|
||||
let endPos := stx.getTailPos?.getD 0
|
||||
(pos, endPos)
|
||||
|
||||
|
||||
abbrev FrontendM := Elab.Frontend.FrontendM
|
||||
|
||||
structure CompilationStep where
|
||||
|
|
|
@ -129,28 +129,37 @@ private def collectSorrysInTree (t : Elab.InfoTree) : IO (List InfoWithContext)
|
|||
def collectSorrys (step: CompilationStep) : IO (List InfoWithContext) := do
|
||||
return (← step.trees.mapM collectSorrysInTree).join
|
||||
|
||||
structure AnnotatedGoalState where
|
||||
state : GoalState
|
||||
srcBoundaries : List (String.Pos × String.Pos)
|
||||
|
||||
/--
|
||||
Since we cannot directly merge `MetavarContext`s, we have to get creative. This
|
||||
function duplicates frozen mvars in term and tactic info nodes, and add them to
|
||||
the current `MetavarContext`.
|
||||
-/
|
||||
@[export pantograph_frontend_sorrys_to_goal_state_m]
|
||||
def sorrysToGoalState (sorrys : List InfoWithContext) : MetaM GoalState := do
|
||||
def sorrysToGoalState (sorrys : List InfoWithContext) : MetaM AnnotatedGoalState := do
|
||||
assert! !sorrys.isEmpty
|
||||
let goalsM := sorrys.mapM λ i => do
|
||||
match i.info with
|
||||
| .ofTermInfo termInfo => do
|
||||
let mvarId ← MetaTranslate.translateMVarFromTermInfo termInfo i.context?
|
||||
return [mvarId]
|
||||
return [(mvarId, stxByteRange termInfo.stx)]
|
||||
| .ofTacticInfo tacticInfo => do
|
||||
MetaTranslate.translateMVarFromTacticInfoBefore tacticInfo i.context?
|
||||
let mvarIds ← MetaTranslate.translateMVarFromTacticInfoBefore tacticInfo i.context?
|
||||
let range := stxByteRange tacticInfo.stx
|
||||
return mvarIds.map (·, range)
|
||||
| _ => panic! "Invalid info"
|
||||
let goals := List.join (← goalsM.run {} |>.run' {})
|
||||
let annotatedGoals := List.join (← goalsM.run {} |>.run' {})
|
||||
let goals := annotatedGoals.map Prod.fst
|
||||
let srcBoundaries := annotatedGoals.map Prod.snd
|
||||
let root := match goals with
|
||||
| [] => panic! "No MVars generated"
|
||||
| [g] => g
|
||||
| _ => { name := .anonymous }
|
||||
GoalState.createFromMVars goals root
|
||||
let state ← GoalState.createFromMVars goals root
|
||||
return { state, srcBoundaries }
|
||||
|
||||
|
||||
@[export pantograph_frontend_collect_new_defined_constants_m]
|
||||
|
|
|
@ -329,6 +329,8 @@ structure CompilationUnit where
|
|||
invocations?: Option (List InvokedTactic) := .none
|
||||
goalStateId?: Option Nat := .none
|
||||
goals: Array Goal := #[]
|
||||
-- Code segments which generated the goals
|
||||
goalSrcBoundaries: Array (Nat × Nat) := #[]
|
||||
messages: Array String := #[]
|
||||
deriving Lean.ToJson
|
||||
structure FrontendProcessResult where
|
||||
|
|
13
Repl.lean
13
Repl.lean
|
@ -265,18 +265,19 @@ def execute (command: Protocol.Command): MainM Lean.Json := do
|
|||
return (step.before, boundary, invocations?, sorrys, messages)
|
||||
let li ← frontendM.run context |>.run' state
|
||||
let units ← li.mapM λ (env, boundary, invocations?, sorrys, messages) => Lean.withEnv env do
|
||||
let (goalStateId?, goals) ← if sorrys.isEmpty then do
|
||||
pure (.none, #[])
|
||||
let (goalStateId?, goals, goalSrcBoundaries) ← if sorrys.isEmpty then do
|
||||
pure (.none, #[], #[])
|
||||
else do
|
||||
let goalState ← runMetaInMainM $ Frontend.sorrysToGoalState sorrys
|
||||
let stateId ← newGoalState goalState
|
||||
let goals ← goalSerialize goalState options
|
||||
pure (.some stateId, goals)
|
||||
let { state, srcBoundaries } ← runMetaInMainM $ Frontend.sorrysToGoalState sorrys
|
||||
let stateId ← newGoalState state
|
||||
let goals ← goalSerialize state options
|
||||
pure (.some stateId, goals, srcBoundaries.toArray.map (λ (b, e) => (b.byteIdx, e.byteIdx)))
|
||||
return {
|
||||
boundary,
|
||||
invocations?,
|
||||
goalStateId?,
|
||||
goals,
|
||||
goalSrcBoundaries,
|
||||
messages,
|
||||
}
|
||||
return .ok { units }
|
||||
|
|
|
@ -15,8 +15,8 @@ def collectSorrysFromSource (source: String) : MetaM (List GoalState) := do
|
|||
let goalStates ← li.filterMapM λ (env, sorrys) => withEnv env do
|
||||
if sorrys.isEmpty then
|
||||
return .none
|
||||
let goalState ← Frontend.sorrysToGoalState sorrys
|
||||
return .some goalState
|
||||
let { state, .. } ← Frontend.sorrysToGoalState sorrys
|
||||
return .some state
|
||||
return goalStates
|
||||
|
||||
def test_multiple_sorrys_in_proof : TestT MetaM Unit := do
|
||||
|
|
Loading…
Reference in New Issue