Zulip Chat Archive

Stream: lean4

Topic: Simulating conversion tactic with evalTactic


Leni Aniva (May 27 2023 at 07:46):

Consider this example

example :  (a b c : Nat), a * (b * c) = a * (c * b) := by
  intro a b c
  conv =>
    lhs
    congr
    rfl
    rw [Nat.mul_comm]

After conv =>, the current proof state shows the conversion goal | a * (b * c) = a * (c * b). I would like to simulate this with Tactic.evalTactic:

import Lean

open Lean Elab Term Meta

def start_tactic_state (goal : String)
    (x : Tactic.SavedState  MVarId  Tactic.TacticM Unit) : CoreM Unit := do
  MetaM.run' <| TermElabM.run' <| do
  let .ok syn := Parser.runParserCategory ( getEnv) `term goal (fileName := "<stdin>") | failure
  let expr  elabType syn
  synthesizeSyntheticMVarsNoPostponing
  let expr  instantiateMVars expr
  let g := ( mkFreshExprMVar expr).mvarId!
  let goals  Tactic.run g do
      IO.println "Tactic state started"
      x ( saveState) g
  if goals.isEmpty then
    IO.println "goals accomplished"
  else
    let goals  goals.mapM fun g => do pure $ toString ( Meta.ppGoal g)
    IO.println s!"goals not solved: {goals}"

def execute_tactic (state : Tactic.SavedState) (g : MVarId) (tactic : String) :
    Tactic.TacticM (Tactic.SavedState × List MVarId) := do
  state.restore
  Tactic.setGoals [g]
  let .ok stx :=
    Parser.runParserCategory ( getEnv) `tactic tactic (fileName := "<stdin>") | failure
  try
    Tactic.evalTactic stx
  catch e =>
    IO.println s!"{← e.toMessageData.toString}"
    return (state, [g])
  if ( getThe Core.State).messages.hasErrors then
    let messages := ( getThe Core.State).messages |>.toList.toArray
    let errors  (messages.map Message.data).mapM fun md => md.toString
    IO.println s!"{errors}"
    return (state, [g])
  let unsolvedGoals  Tactic.getUnsolvedGoals
  let goals  unsolvedGoals.mapM fun g => do pure $ toString ( Meta.ppGoal g)
  IO.println s!"Tactic succeeded with goals {goals}"
  return ( saveState, unsolvedGoals)

def proof_1: CoreM Unit := do
  start_tactic_state "∀ (p q: Prop), p ∨ q → q ∨ p" fun state g => do
    let (state, [g])  execute_tactic state g "intro p q h" | failure
    let (state, [g1, g2])  execute_tactic state g "cases h" | failure
    let (state, [g1])  execute_tactic state g1 "apply Or.inr" | failure
    let (state, [])  execute_tactic state g1 "assumption" | failure
    let (state, [g2])  execute_tactic state g2 "apply Or.inl" | failure
    let (_, [])  execute_tactic state g2 "assumption" | failure

def proof_2: CoreM Unit := do
  start_tactic_state "∀ (a b c: Nat), a * (b * c) = a * (c * b)" fun state g => do
    let (state, [g])  execute_tactic state g "intro a b c" | failure
    let (state, [g1])  execute_tactic state g "conv => lhs" | failure


def main: IO Unit := do
  let env  importModules
    (imports := [{ module := Name.str .anonymous "Init", runtimeOnly := false }])
    (opts := {})
    (trustLevel := 1)
  let coreContext : Core.Context := {
    currNamespace := Name.anonymous,
    openDecls := [],     -- No 'open' directives needed
    fileName := "<onion>",
    fileMap := { source := "", positions := #[0], lines := #[1] }
  }
  discard <| proof_2.toIO coreContext { env := env }

However, this outputs

Tactic state started
Tactic succeeded with goals [a b c : Nat
 a * (b * c) = a * (c * b)]
Tactic succeeded with goals [a b c : Nat
 a * (b * c) = a * (c * b)]
goals not solved: [a b c : Nat
 a * (b * c) = a * (c * b)]

which shows that the state has exited conversion mode. If I replace conv => lhs by conv, The tactic fails.

Is there a way to interactively view the result of conversion mode?


Last updated: Dec 20 2023 at 11:08 UTC