chore: Version 0.3 #136
|
@ -237,25 +237,34 @@ inductive TacticResult where
|
||||||
-- The given action cannot be executed in the state
|
-- The given action cannot be executed in the state
|
||||||
| invalidAction (message: String)
|
| invalidAction (message: String)
|
||||||
|
|
||||||
|
private def dumpMessageLog (prevMessageLength : Nat) : CoreM (Array String) := do
|
||||||
|
let newMessages ← (← Core.getMessageLog).toList.drop prevMessageLength
|
||||||
|
|>.filterMapM λ m => do
|
||||||
|
if m.severity == .error then
|
||||||
|
return .some $ ← m.toString
|
||||||
|
else
|
||||||
|
return .none
|
||||||
|
Core.resetMessageLog
|
||||||
|
return newMessages.toArray
|
||||||
|
|
||||||
/-- Executes a `TacticM` monad on this `GoalState`, collecting the errors as necessary -/
|
/-- Executes a `TacticM` monad on this `GoalState`, collecting the errors as necessary -/
|
||||||
protected def GoalState.tryTacticM (state: GoalState) (goal: MVarId) (tacticM: Elab.Tactic.TacticM Unit) (guardMVarErrors : Bool := false):
|
protected def GoalState.tryTacticM
|
||||||
Elab.TermElabM TacticResult := do
|
(state: GoalState) (goal: MVarId) (tacticM: Elab.Tactic.TacticM Unit)
|
||||||
|
(guardMVarErrors : Bool := false)
|
||||||
|
: Elab.TermElabM TacticResult := do
|
||||||
|
let prevMessageLength := state.coreState.messages.toList.length
|
||||||
try
|
try
|
||||||
let nextState ← state.step goal tacticM guardMVarErrors
|
let nextState ← state.step goal tacticM guardMVarErrors
|
||||||
|
|
||||||
-- Check if error messages have been generated in the core.
|
-- Check if error messages have been generated in the core.
|
||||||
let newMessages ← (← Core.getMessageLog).toList.drop state.coreState.messages.toList.length
|
let newMessages ← dumpMessageLog prevMessageLength
|
||||||
|>.filterMapM λ m => do
|
|
||||||
if m.severity == .error then
|
|
||||||
return .some $ ← m.toString
|
|
||||||
else
|
|
||||||
return .none
|
|
||||||
Core.resetMessageLog
|
|
||||||
if ¬ newMessages.isEmpty then
|
if ¬ newMessages.isEmpty then
|
||||||
return .failure newMessages.toArray
|
return .failure newMessages
|
||||||
return .success nextState
|
return .success nextState
|
||||||
catch exception =>
|
catch exception =>
|
||||||
return .failure #[← exception.toMessageData.toString]
|
match exception with
|
||||||
|
| .internal _ => return .failure $ ← dumpMessageLog prevMessageLength
|
||||||
|
| _ => return .failure #[← exception.toMessageData.toString]
|
||||||
|
|
||||||
/-- Execute a string tactic on given state. Restores TermElabM -/
|
/-- Execute a string tactic on given state. Restores TermElabM -/
|
||||||
@[export pantograph_goal_state_try_tactic_m]
|
@[export pantograph_goal_state_try_tactic_m]
|
||||||
|
|
|
@ -720,7 +720,6 @@ def test_tactic_failure_unresolved_goals : TestM Unit := do
|
||||||
let .failure messages ← state1.tacticOn 0 tactic | addTest $ assertUnreachable s!"{tactic} should fail"
|
let .failure messages ← state1.tacticOn 0 tactic | addTest $ assertUnreachable s!"{tactic} should fail"
|
||||||
checkEq s!"{tactic} fails" messages #[s!"{← getFileName}:0:12: error: unsolved goals\np : Nat → Prop\n⊢ p 0\n"]
|
checkEq s!"{tactic} fails" messages #[s!"{← getFileName}:0:12: error: unsolved goals\np : Nat → Prop\n⊢ p 0\n"]
|
||||||
|
|
||||||
|
|
||||||
def test_tactic_failure_synthesize_placeholder : TestM Unit := do
|
def test_tactic_failure_synthesize_placeholder : TestM Unit := do
|
||||||
let state? ← startProof (.expr "∀ (p q r : Prop) (h : p → q), q ∧ r")
|
let state? ← startProof (.expr "∀ (p q r : Prop) (h : p → q), q ∧ r")
|
||||||
let state0 ← match state? with
|
let state0 ← match state? with
|
||||||
|
@ -736,20 +735,24 @@ def test_tactic_failure_synthesize_placeholder : TestM Unit := do
|
||||||
addTest $ assertUnreachable $ other.toString
|
addTest $ assertUnreachable $ other.toString
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
|
let iex : InternalExceptionId := { idx := 4 }
|
||||||
|
IO.println s!"{← iex.getName}"
|
||||||
let tactic := "simpa [h] using And.imp_left h _"
|
let tactic := "simpa [h] using And.imp_left h _"
|
||||||
let state2 ← match ← state1.tacticOn 0 tactic with
|
--let state2 ← match ← state1.tacticOn 0 tactic with
|
||||||
| .success state => pure state
|
-- | .success state => pure state
|
||||||
| other => do
|
-- | other => do
|
||||||
addTest $ assertUnreachable $ other.toString
|
-- addTest $ assertUnreachable $ other.toString
|
||||||
return ()
|
-- return ()
|
||||||
|
|
||||||
checkEq tactic ((← state2.serializeGoals).map (·.devolatilize)) #[
|
-- Volatile behaviour. This easily changes across Lean versions
|
||||||
buildGoal [("p", "Prop"), ("q", "Prop"), ("r", "Prop"), ("h", "p → q")] "p ∧ r"
|
|
||||||
]
|
|
||||||
|
|
||||||
--let .failure messages ← state1.tacticOn 0 tactic | addTest $ assertUnreachable s!"{tactic} should fail"
|
--checkEq tactic ((← state2.serializeGoals).map (·.devolatilize)) #[
|
||||||
--let message := s!"<Pantograph>:0:31: error: don't know how to synthesize placeholder\ncontext:\np q r : Prop\nh : p → q\n⊢ p ∧ r\n"
|
-- buildGoal [("p", "Prop"), ("q", "Prop"), ("r", "Prop"), ("h", "p → q")] "p ∧ r"
|
||||||
--checkEq s!"{tactic} fails" messages #[message]
|
--]
|
||||||
|
|
||||||
|
let .failure messages ← state1.tacticOn 0 tactic | addTest $ assertUnreachable s!"{tactic} should fail"
|
||||||
|
let message := s!"<Pantograph>:0:31: error: don't know how to synthesize placeholder\ncontext:\np q r : Prop\nh : p → q\n⊢ p ∧ r\n"
|
||||||
|
checkEq s!"{tactic} fails" messages #[message]
|
||||||
|
|
||||||
def suite (env: Environment): List (String × IO LSpec.TestSeq) :=
|
def suite (env: Environment): List (String × IO LSpec.TestSeq) :=
|
||||||
let tests := [
|
let tests := [
|
||||||
|
|
Loading…
Reference in New Issue