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
|
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
|
abbrev FrontendM := Elab.Frontend.FrontendM
|
||||||
|
|
||||||
structure CompilationStep where
|
structure CompilationStep where
|
||||||
|
|
|
@ -129,28 +129,37 @@ private def collectSorrysInTree (t : Elab.InfoTree) : IO (List InfoWithContext)
|
||||||
def collectSorrys (step: CompilationStep) : IO (List InfoWithContext) := do
|
def collectSorrys (step: CompilationStep) : IO (List InfoWithContext) := do
|
||||||
return (← step.trees.mapM collectSorrysInTree).join
|
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
|
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
|
function duplicates frozen mvars in term and tactic info nodes, and add them to
|
||||||
the current `MetavarContext`.
|
the current `MetavarContext`.
|
||||||
-/
|
-/
|
||||||
@[export pantograph_frontend_sorrys_to_goal_state_m]
|
@[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
|
assert! !sorrys.isEmpty
|
||||||
let goalsM := sorrys.mapM λ i => do
|
let goalsM := sorrys.mapM λ i => do
|
||||||
match i.info with
|
match i.info with
|
||||||
| .ofTermInfo termInfo => do
|
| .ofTermInfo termInfo => do
|
||||||
let mvarId ← MetaTranslate.translateMVarFromTermInfo termInfo i.context?
|
let mvarId ← MetaTranslate.translateMVarFromTermInfo termInfo i.context?
|
||||||
return [mvarId]
|
return [(mvarId, stxByteRange termInfo.stx)]
|
||||||
| .ofTacticInfo tacticInfo => do
|
| .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"
|
| _ => 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
|
let root := match goals with
|
||||||
| [] => panic! "No MVars generated"
|
| [] => panic! "No MVars generated"
|
||||||
| [g] => g
|
| [g] => g
|
||||||
| _ => { name := .anonymous }
|
| _ => { name := .anonymous }
|
||||||
GoalState.createFromMVars goals root
|
let state ← GoalState.createFromMVars goals root
|
||||||
|
return { state, srcBoundaries }
|
||||||
|
|
||||||
|
|
||||||
@[export pantograph_frontend_collect_new_defined_constants_m]
|
@[export pantograph_frontend_collect_new_defined_constants_m]
|
||||||
|
|
|
@ -329,6 +329,8 @@ structure CompilationUnit where
|
||||||
invocations?: Option (List InvokedTactic) := .none
|
invocations?: Option (List InvokedTactic) := .none
|
||||||
goalStateId?: Option Nat := .none
|
goalStateId?: Option Nat := .none
|
||||||
goals: Array Goal := #[]
|
goals: Array Goal := #[]
|
||||||
|
-- Code segments which generated the goals
|
||||||
|
goalSrcBoundaries: Array (Nat × Nat) := #[]
|
||||||
messages: Array String := #[]
|
messages: Array String := #[]
|
||||||
deriving Lean.ToJson
|
deriving Lean.ToJson
|
||||||
structure FrontendProcessResult where
|
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)
|
return (step.before, boundary, invocations?, sorrys, messages)
|
||||||
let li ← frontendM.run context |>.run' state
|
let li ← frontendM.run context |>.run' state
|
||||||
let units ← li.mapM λ (env, boundary, invocations?, sorrys, messages) => Lean.withEnv env do
|
let units ← li.mapM λ (env, boundary, invocations?, sorrys, messages) => Lean.withEnv env do
|
||||||
let (goalStateId?, goals) ← if sorrys.isEmpty then do
|
let (goalStateId?, goals, goalSrcBoundaries) ← if sorrys.isEmpty then do
|
||||||
pure (.none, #[])
|
pure (.none, #[], #[])
|
||||||
else do
|
else do
|
||||||
let goalState ← runMetaInMainM $ Frontend.sorrysToGoalState sorrys
|
let { state, srcBoundaries } ← runMetaInMainM $ Frontend.sorrysToGoalState sorrys
|
||||||
let stateId ← newGoalState goalState
|
let stateId ← newGoalState state
|
||||||
let goals ← goalSerialize goalState options
|
let goals ← goalSerialize state options
|
||||||
pure (.some stateId, goals)
|
pure (.some stateId, goals, srcBoundaries.toArray.map (λ (b, e) => (b.byteIdx, e.byteIdx)))
|
||||||
return {
|
return {
|
||||||
boundary,
|
boundary,
|
||||||
invocations?,
|
invocations?,
|
||||||
goalStateId?,
|
goalStateId?,
|
||||||
goals,
|
goals,
|
||||||
|
goalSrcBoundaries,
|
||||||
messages,
|
messages,
|
||||||
}
|
}
|
||||||
return .ok { units }
|
return .ok { units }
|
||||||
|
|
|
@ -15,8 +15,8 @@ def collectSorrysFromSource (source: String) : MetaM (List GoalState) := do
|
||||||
let goalStates ← li.filterMapM λ (env, sorrys) => withEnv env do
|
let goalStates ← li.filterMapM λ (env, sorrys) => withEnv env do
|
||||||
if sorrys.isEmpty then
|
if sorrys.isEmpty then
|
||||||
return .none
|
return .none
|
||||||
let goalState ← Frontend.sorrysToGoalState sorrys
|
let { state, .. } ← Frontend.sorrysToGoalState sorrys
|
||||||
return .some goalState
|
return .some state
|
||||||
return goalStates
|
return goalStates
|
||||||
|
|
||||||
def test_multiple_sorrys_in_proof : TestT MetaM Unit := do
|
def test_multiple_sorrys_in_proof : TestT MetaM Unit := do
|
||||||
|
|
Loading…
Reference in New Issue