Runs a term elaborator inside a tactic.
This function ensures that term elaboration fails when backtracking,
i.e., in first| tac term | other.
タクティクは構文カテゴリ tactic に含まれるプロダクションです。タクティクの構文が与えられると、タクティクのインタプリタはタクティクモナド TacticM でアクションを実行します。これは Lean の項エラボレータのラッパーで、タクティクの実行にあたって追加で状態を追跡するものです。カスタムタクティクは tactic カテゴリの拡張と、以下のいずれかから構成されます:
新しいタクティクを定義する最も簡単な方法は、 マクロ として既存のタクティクに展開することです。マクロ展開はタクティクの実行と同時に行われます。タクティクのインタプリタは、まずタクティクマクロを解釈する直前に展開します。タクティクマクロはタクティクスクリプトを実行する前に完全には展開されないため、再帰を使用することができます;マクロ構文の再帰的な出現が実行可能なタクティクの下にある限り、マクロの展開は無限に連鎖しません。
以下の repeat に似たタクティクの再帰的な実装は、マクロ展開によって定義されます。引数 $t が失敗した時、 rep の再帰的な発生は絶対に呼び出されず、したがってマクロ展開も決して行われません。
syntax "rep" tactic : tactic
macro_rules
| `(tactic|rep $t) =>
`(tactic|
first
| $t; rep $t
| skip)
example : 0 ≤ 4 := ⊢ 0 ≤ 4
rep (⊢ Nat.le 0 0)
All goals completed! 🐙
他の Lean のマクロと同様に、タクティクマクロは hygienic です。グローバル名への参照はマクロが定義された時に解決され、タクティクマクロによって導入された名前はその呼び出しサイトから名前をキャプチャすることはできません。
タクティクマクロを定義するとき、パターンマッチと構成に用いられる構文が構文カテゴリ tactic のものであることを指定することが重要です。そうでない場合、構文は項の構文として解釈され、タクティクのための正しくない AST とマッチしたり構成されたりします。
マクロの展開は失敗することがあるため、複数のマクロが同じ構文にマッチすることができ、バックトラックが可能になります。タクティクマクロはこれをさらに推し進めます:タクティクマクロの展開が成功しても解釈時に展開に失敗すると、タクティクのインタプリタは次の展開を試みます。これは Lean の多くの組み込みタクティクを拡張可能にするためにしようされます。 Lean.Parser.Command.macro_rules : commandmacro_rules 宣言を追加することで新しい動作をタクティクに追加できます。
trivial の拡張
trivial はユーザを煩わせる価値のないサブゴールを素早くディスパッチするために、他の多くのタクティクから使用されますが、新しいマクロ展開によって拡張できるように設計されています。Lean のデフォルトの trivial は IsEmpty [] ゴールを解決できません:
def IsEmpty (xs : List α) : Prop :=
¬ xs ≠ []
example (α : Type u) : IsEmpty (α := α) [] := α:Type u⊢ IsEmpty [] α:Type u⊢ IsEmpty []
このエラーメッセージは trivial が最後に assumption を試したことによるものです。ここで別の拡張を追加することで trivial がこれらのゴールを対応するようにできます:
def emptyIsEmpty : IsEmpty (α := α) [] := α:Type u_1⊢ IsEmpty [] All goals completed! 🐙
macro_rules | `(tactic|trivial) => `(tactic|exact emptyIsEmpty)
example (α : Type u) : IsEmpty (α := α) [] := α:Type u⊢ IsEmpty []
All goals completed! 🐙
マクロ展開は、展開された構文のいずれかの部分で失敗した場合にバックトラックを引き起こす可能性があります。複数の展開を別々の Lean.Parser.Command.macro_rules : commandmacro_rules 宣言で定義することで、 first の中置バージョンを定義することができます:
syntax tactic "<|||>" tactic : tactic
macro_rules
| `(tactic|$t1 <|||> $t2) => pure t1
macro_rules
| `(tactic|$t1 <|||> $t2) => pure t2
example : 2 = 2 := ⊢ 2 = 2
All goals completed! 🐙 <|||> apply And.intro
example : 2 = 2 := ⊢ 2 = 2
apply And.intro <|||> All goals completed! 🐙
複数の Lean.Parser.Command.macro_rules : commandmacro_rules 宣言は、それぞれがパターンマッチ関数を定義し、常に最初にマッチする選択肢を取ることができるようにするために必要です。バックトラックは Lean.Parser.Command.macro_rules : commandmacro_rules 宣言の粒度であり、個々のケースではありません。
Relationship to Lean.Elab.Term.TermElabM, Lean.Meta.MetaM
Overview of available effects
Checkpointing
Tracked at issue #67
Lean.Elab.Tactic.Tactic : Type
Lean.Elab.Tactic.TacticM (α : Type) : Type
Lean.Elab.Tactic.run (mvarId : Lean.MVarId) (x : TacticM Unit) : Lean.Elab.TermElabM (List Lean.MVarId)
Lean.Elab.Tactic.runTermElab {α : Type} (k : Lean.Elab.TermElabM α) (mayPostpone : Bool := false) : TacticM α
Runs a term elaborator inside a tactic.
This function ensures that term elaboration fails when backtracking,
i.e., in first| tac term | other.
Lean.Elab.Tactic.getFVarId (id : Lean.Syntax) : TacticM Lean.FVarId
Lean.Elab.Tactic.getFVarIds
(ids : Array Lean.Syntax)
: TacticM (Array Lean.FVarId)
Lean.Elab.Tactic.withLocation (loc : Location) (atLocal : Lean.FVarId → TacticM Unit) (atTarget : TacticM Unit) (failed : Lean.MVarId → TacticM Unit) : TacticM Unit
Runs the given atLocal and atTarget methods on each of the locations selected by the given loc.
If loc is a list of locations, runs at each specified hypothesis (and finally the goal if ⊢ is included),
and fails if any of the tactic applications fail.
If loc is *, runs at the target first and then the hypotheses in reverse order.
If atTarget closes the main goal, withLocation does not run atLocal.
If all tactic applications fail, withLocation with call failed with the main goal mvar.
Lean.Elab.Tactic.getGoals
: TacticM (List Lean.MVarId)Returns the list of goals. Goals may or may not already be assigned.
Lean.Elab.Tactic.closeMainGoal (tacName : Lean.Name) (val : Lean.Expr) (checkUnassigned : Bool := true) : TacticM Unit
Lean.Elab.Tactic.tagUntaggedGoals
(parentTag newSuffix : Lean.Name)
(newGoals : List Lean.MVarId) : TacticM Unit
Use parentTag to tag untagged goals at newGoals.
If there are multiple new untagged goals, they are named using <parentTag>.<newSuffix>_<idx> where idx > 0.
If there is only one new untagged goal, then we just use parentTag
Lean.Elab.Tactic.appendGoals
(mvarIds : List Lean.MVarId) : TacticM UnitAdd the given goals at the end of the current list of goals.
Lean.Elab.Tactic.closeMainGoalUsing (tacName : Lean.Name) (x : Lean.Expr → Lean.Name → TacticM Lean.Expr) (checkNewUnassigned : Bool := true) : TacticM Unit
Try to close main goal using x target tag, where target is the type of the main goal and tag is its user name.
If checkNewUnassigned is true, then throws an error if the resulting value has metavariables that were created during the execution of x.
If it is false, then it is the responsibility of x to add such metavariables to the goal list.
During the execution of x:
The local context is that of the main goal.
The goal list has the main goal removed.
It is allowable to modify the goal list, for example with Lean.Elab.Tactic.pushGoals.
On failure, the main goal remains at the front of the goal list.
Lean.Elab.Tactic.elabTerm (stx : Lean.Syntax) (expectedType? : Option Lean.Expr) (mayPostpone : Bool := false) : TacticM Lean.Expr
Elaborate stx in the current MVarContext. If given, the expectedType will be used to help
elaboration but not enforced (use elabTermEnsuringType to enforce an expected type).
Lean.Elab.Tactic.elabTermEnsuringType (stx : Lean.Syntax) (expectedType? : Option Lean.Expr) (mayPostpone : Bool := false) : TacticM Lean.Expr
Elaborate stx in the current MVarContext. If given, the expectedType will be used to help
elaboration and then a TypeMismatchError will be thrown if the elaborated type doesn't match.
Lean.Elab.Tactic.elabTermWithHoles (stx : Lean.Syntax) (expectedType? : Option Lean.Expr) (tagSuffix : Lean.Name) (allowNaturalHoles : Bool := false) (parentTag? : Option Lean.Name := none) : TacticM (Lean.Expr × List Lean.MVarId)
Elaborates stx and collects the MVarIds of any holes that were created during elaboration.
With allowNaturalHoles := false (the default), any new natural holes (_) which cannot
be synthesized during elaboration cause elabTermWithHoles to fail. (Natural goals appearing in
stx which were created prior to elaboration are permitted.)
Unnamed MVarIds are renamed to share the tag parentTag? (or the main goal's tag if parentTag? is none).
If multiple unnamed goals are encountered, tagSuffix is appended to this tag along with a numerical index.
Note:
Previously-created MVarIds which appear in stx are not returned.
All parts of elabTermWithHoles operate at the current MCtxDepth, and therefore may assign
metavariables.
When allowNaturalHoles := true, stx is elaborated under withAssignableSyntheticOpaque,
meaning that .syntheticOpaque metavariables might be assigned during elaboration. This is a
consequence of the implementation.
これらの操作は主に TacticM や特定のタクティクの実装の一部として使用されます。新しいタクティクを実装する際に役に立つことは稀です。
これらの操作は標準的な Lean のモナド型クラスを通して公開されます。
Lean.Elab.Tactic.tryCatch {α : Type}
(x : TacticM α)
(h : Lean.Exception → TacticM α) : TacticM α
Non-backtracking try/catch.
Lean.Elab.Tactic.liftMetaMAtMain {α : Type}
(x : Lean.MVarId → Lean.MetaM α) : TacticM α
Lean.Elab.Tactic.getMainModule
: TacticM Lean.Name
Lean.Elab.Tactic.getCurrMacroScope
: TacticM Lean.MacroScope
Lean.Elab.Tactic.adaptExpander
(exp : Lean.Syntax → TacticM Lean.Syntax)
: TacticAdapt a syntax transformation to a regular tactic evaluator.
Lean.Elab.Tactic.elabCasesTargets
(targets : Array Lean.Syntax)
: TacticM
(Array Lean.Expr ×
Array (Lean.Ident × Lean.FVarId))
Lean.Elab.Tactic.elabSimpArgs
(stx : Lean.Syntax)
(ctx : Lean.Meta.Simp.Context)
(simprocs : Lean.Meta.Simp.SimprocsArray)
(eraseLocal : Bool) (kind : SimpKind)
: TacticM ElabSimpArgsResult
Elaborate extra simp theorems provided to simp. stx is of the form "[" simpTheorem,* "]"
If eraseLocal == true, then we consider local declarations when resolving names for erased theorems (- id),
this option only makes sense for simp_all or * is used.
When recover := true, try to recover from errors as much as possible so that users keep seeing
the current goal.
Lean.Elab.Tactic.elabSimpConfig
(optConfig : Lean.Syntax) (kind : SimpKind)
: TacticM Lean.Meta.Simp.Config
Lean.Elab.Tactic.elabSimpConfigCtxCore
: Lean.Syntax →
TacticM Lean.Meta.Simp.ConfigCtx
Lean.Elab.Tactic.dsimpLocation'
(ctx : Lean.Meta.Simp.Context)
(simprocs : Lean.Meta.Simp.SimprocsArray)
(loc : Location)
: TacticM Lean.Meta.Simp.Stats
Implementation of dsimp?.
Lean.Elab.Tactic.elabDSimpConfigCore
: Lean.Syntax →
TacticM Lean.Meta.DSimp.Config
Lean.Elab.Tactic.tacticElabAttribute
: Lean.KeyedDeclsAttribute Tactic