Imports
/-
Copyright (c) 2024 Joseph Tooby-Smith. All rights reserved.
Released under Apache 2.0 license.
Authors: Joseph Tooby-Smith
-/
module
public import Lean
public import Physlib.Meta.TODO.BasicThis file enables us to transverse tactics and test for conditions.
References
The content of this file is based on the following sources (released under the Apache 2.0 license).
https://github.com/dwrensha/tryAtEachStep/blob/main/tryAtEachStep.lean
https://github.com/lean-dojo/LeanDojo/blob/main/src/lean_dojo/data_extraction/ExtractData.lean
Modifications have been made to the original content of these files here.
See also:
https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Memory.20increase.20in.20loops.2E
@[expose] public sectionTakes in a file and returns the infostates of commands and the corresponding environment before the command is processed.
partial def processCommands : Frontend.FrontendM (List (Environment × InfoState)) := do
/- Very roughly, `Frontend.FrontendM (List (Environment × InfoState))` is equivalent
to `Frontend.Context → Frontend.state → List (Environment × InfoState)`.
The `←get` here is returning the inputted value of `Frontend.state`,
from which we get the environment.
-/
let env := (← get).commandState.env
/- Processes a single command, adding it to `env`. This is done using
`modify fun s => { s with commands := s.commands.push cmd }` as part of
`Frontend.processCommand`. -/
let done ← Frontend.processCommand
/- Gets the updated `Frontend.state`. -/
let st := ← get
/- Gets the infostate associated with the single command. -/
let infoState := st.commandState.infoState
set {st with commandState := {st.commandState with infoState := {}}}
if done
then return [(env, infoState)]
else
/- For each command, we return the environment before the command is processed,
and the `infoState` associated with that command. -/
return (env, infoState) :: (← processCommands)
Tests if a given info is ofTacticInfo and if so runs visitTacticInfo.
def visitInfo (file : FilePath) (env : Environment)
(visitTacticInfo : FilePath → ContextInfo → TacticInfo → MetaM Unit) (ci : ContextInfo)
(info : Info) (acc : List (IO Unit)) : List (IO Unit) :=
match info with
| .ofTacticInfo ti =>
(ci.runMetaM default
(do setEnv env
try visitTacticInfo file ci ti
catch e =>
println! "caught: {←e.toMessageData.toString}")) :: acc
| _ => acc
Applies visitInfo to each node of the info trees.
def traverseForest (file : FilePath)
(visitTacticInfo : FilePath → ContextInfo → TacticInfo → MetaM Unit)
(steps : List (Environment × InfoState)) : List (IO Unit) :=
let t := steps.map fun (env, infoState) ↦
(infoState.trees.toList.map fun t ↦
(Lean.Elab.InfoTree.foldInfo (visitInfo file env visitTacticInfo) [] t).reverse)
t.flatten.flattenTODO "Find a way to free the environment `env` in `transverseTactics`.
This leads to memory problems when using `transverseTactics` directly in loops."