Tactic analysis framework #
In this file we define a framework for analyzing sequences of tactics.
This can be used for linting (for instance: report when two rw
calls can be merged into one),
but it can also be run in a more batch-like mode to report larger potential refactors
(for instance: report when a sequence of three or more tactics can be replaced with grind
,
without taking more heartbeats than the original proof did).
Using the framework #
The framework runs, but does nothing by default (set_option linter.tacticAnalysis false
to turn it off completely). Enable the analysis round roundName
by enabling its corresponding
option: set_option linter.tacticAnalysis.roundName true
.
To add a round of analysis called roundName
, declare an option linter.tacticAnalysis.roundName
,
make a definition of type Mathlib.TacticAnalysis.Config
and give the Config
declaration the
@[tacticAnalysis linter.tacticAnalysis.roundName]
attribute. Don't forget to enable the option.
Warning #
The ComplexConfig
interface doesn't feel quite intuitive and flexible yet and should be changed
in the future. Please do not rely on this interface being stable.
The tactic analysis framework hooks into the linter to run analysis rounds on sequences of tactics. This can be used for linting, or in a more batch-like mode to report potential refactors.
Stores the configuration for a tactic analysis pass.
This provides the low-level interface into the tactic analysis framework.
The function that runs this pass. Takes an array of infotree nodes corresponding to a sequence of tactics from the source file. Should do all reporting itself, for example by
Lean.Linter.logLint
.
Instances For
The internal representation of a tactic analysis pass,
extending Config
with some declaration meta-information.
- opt : Option (Lean.Option Bool)
The option corresponding to this pass, used to enable it.
Example:
linter.tacticAnalysis.grindReplacement
.
Instances For
Read a configuration from a declaration of the right type.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Mathlib.TacticAnalysis.instOrdEntry = { compare := fun (a b : Mathlib.TacticAnalysis.Entry) => compare (a.declName, a.optionName) (b.declName, b.optionName) }
Environment extensions for tacticAnalysis
declarations
Parse an infotree to find all the sequences of tactics contained within stx
.
We consider a sequence here to be a maximal interval of tactics joined by ;
or newlines.
This function returns an array of sequences. For example, a proof of the form:
by
tac1
· tac2; tac3
· tac4; tac5
would result in three sequences:
#[tac1, (· tac2; tac3), (· tac4; tac5)]
#[tac2, tac3]
#[tac4, tac5]
Similarly, a declaration with multiple by
blocks results in each of the blocks getting its
own sequence.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Run the tactic analysis passes from configs
on the tactic sequences in stx
,
using trees
to get the infotrees.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A tactic analysis framework. It is aimed at allowing developers to specify refactoring patterns, which will be tested against a whole project, to report proposed changes.
It hooks into the linting system to move through the infotree, collecting tactic syntax and state to call the passes on.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Work in progress: Config
building blocks #
In this section we define ComplexConfig
which is supposed to make it easier to build standard
analysis rounds.
Work in progress note: This interface does not feel intuitive yet and might be redesigned. Please do not rely on it being stable!
The condition is returned from the .trigger
function to indicate which sublists of a
tactic sequence to test.
The context
field can be used to accumulate data between different invocations of .trigger
.
- skip
{ctx : Type u_1}
: TriggerCondition ctx
skip
means that the current tactic and the ones before it will be discarded. - continue
{ctx : Type u_1}
(context : ctx)
: TriggerCondition ctx
continue
means to accumulate the current tactic, but not yet run the test on it. - accept {ctx : Type u_1} (context : ctx) : TriggerCondition ctx
Instances For
Specifies which analysis steps to take.
The overall design will have three user-supplied components:
- trigger on a piece of syntax (which could contain multiple tactic calls);
- test if a suggested change is indeed an improvement;
- tell the user where changes can be made.
- out : Type
Type returned by the
.test
function. - ctx : Type
Type returned by the
.trigger
function. Determines which (sequences of) tactics to analyze.
context
issome ctx
whenever the previous trigger returnedcontinue ctx
,none
at the start of a tactic sequence or after askip
/accept
.If the last returned value is
continue
at the end of the sequence, the framework inserts an extradone
to run thetrigger
on.Code to run in the context of the tactic, for example an alternative tactic.
- tell (stx : Lean.Syntax) (original : List Lean.MVarId × Nat) (new : self.out × Nat) : Option Lean.MessageData
Decides what to report to the user.
Instances For
Test the config
against a sequence of tactics, using the context info and tactic info
from the start of the sequence.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Run the config
against a sequence of tactics, using the trigger
to determine which
subsequences should be test
ed.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Constructor for a Config
which breaks the pass up into multiple pieces.
Equations
- Mathlib.TacticAnalysis.Config.ofComplex config = { run := Mathlib.TacticAnalysis.runPass config }