Zulip Chat Archive
Stream: lean4
Topic: Extending tacticSeqs
Reinier van der Gronden (Aug 24 2022 at 08:51):
I'm looking to understand the best way of working with tacticSeq
s. Up to this point, I've worked with tactic
, but I want to implement a tactic that make changes to a 'group of tactics', which is basically a tacticSeq
. I struggle to find ways to take an existing tacticSeq
, and make some changes to it.
One of the main issues for me is that I don't properly know how to work with parsers yet, and tacticSeq
seems to be some sort of parser-wrapper around a list of tactics (but not really).
a MWE for my use case is as follows:
import Lean
open
Lean
Lean.Elab.Tactic
Lean.Parser.Tactic
#eval Lean.versionString -- 4.0.0, commit 7dbfaf9b751917a7fe020485bf57f41fdddcaafa
def testTactic (tacSeq : TSyntax ``tacticSeq) : TacticM Unit := do
let tacSeqStr := toString tacSeq
addTrace `test m!"{tacSeqStr}"
elab &"testTactic " t:tacticSeq : tactic =>
testTactic t
example : true := by
testTactic
rfl
rfl
sorry
The testTactic now adds the trace object (Tactic.tacticSeq (Tactic.tacticSeq1Indented [(group (Tactic.tacticRfl "rfl") []) (group (Tactic.tacticRfl "rfl") [])]))
. What would be the proper way of, say, extending/appending this tacticSeq with another rfl
call?
Alternatively, how can you consistently get a 'list of tactics' that are inside the tacticSeq? With that, it would be easier to construct a new tacticSeq like `(tacticSeq|($[$tacs]*))
, but I'm pretty sure that objects inside the tacticSeq need not necessarily be tactics, they can also be nested tacticSeqs. For example, changing the above example to
example : true := by
testTactic
rfl
{
rfl
rfl
}
rfl
sorry
Adds the trace (Tactic.tacticSeq1Indented [(group (Tactic.tacticRfl "rfl") []) (group (Tactic.tacticSeqBracketed "{" [(group (Tactic.tacticRfl "rfl") []) (group (Tactic.tacticRfl "rfl") [])] "}") []) (group (Tactic.tacticRfl "rfl") [])]))
, where it contains a tacticSeq, not just a list of tactics.
Reinier van der Gronden (Aug 24 2022 at 13:02):
For those interested, with the help of @Jannis Limperg , we have constructed a function that matches on the tacticSeq and appends a tactic to it. Our solution looks like this, with a bit of matching magic:
def mkTacticSeqAppend (ts : TSyntax ``tacticSeq) (t : TSyntax `tactic) : TermElabM (TSyntax ``tacticSeq) :=
match ts with
| `(tacticSeq| { $[$tacs:tactic $[;]?]* }) =>
`(tacticSeq| { $[$(tacs.push t)]* })
| `(tacticSeq| $[$tacs:tactic $[;]?]*) =>
`(tacticSeq| $[$(tacs.push t)]*)
| _ => throwError "unknown syntax"
Having access to the list of tactics inside of the tacticSeq makes it much easier to make arbitrary changes and create a new tacticSeq. The fact that the list of tacs can contain a tacticSeq(Bracketed) itself doesn't seem to matter, since this should/seems to always be interpretable as a tactic (focus a goal and execute this list of tactics).
Last updated: Dec 20 2023 at 11:08 UTC