File: Mathlib/Tactic/DefEqTransformations.lean

full_name: Lean.MVarId.changeLocalDecl'
code: /--
This is `Lean.MVarId.changeLocalDecl` but makes sure to preserve local variable order.
-/
def _root_.Lean.MVarId.changeLocalDecl' (mvarId : MVarId) (fvarId : FVarId) (typeNew : Expr)
    (checkDefEq := true) : MetaM MVarId 
goal: Lean.MetaM Lean.MVarId

full_name: Mathlib.Tactic.runDefEqTactic
code: /-- For the main goal, use `m` to transform the types of locations specified by `loc?`.
If `loc?` is none, then transforms the type of target. `m` is provided with an expression
with instantiated metavariables as well as, if the location is a local hypothesis, the fvar.

`m` *must* transform expressions to defeq expressions.
If `checkDefEq = true` (the default) then `runDefEqTactic` will throw an error
if the resulting expression is not definitionally equal to the original expression. -/
def runDefEqTactic (m : Option FVarId → Expr → MetaM Expr)
    (loc? : Option (TSyntax ``Parser.Tactic.location))
    (tacticName : String)
    (checkDefEq : Bool := true) :
    TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Mathlib.Tactic.runDefEqConvTactic
code: /-- Like `Mathlib.Tactic.runDefEqTactic` but for `conv` mode. -/
def runDefEqConvTactic (m : Expr → MetaM Expr) : TacticM Unit 
goal: Lean.Elab.Tactic.TacticM Unit

full_name: Mathlib.Tactic.tacticWhnf__
code: /--
`whnf at loc` puts the given location into weak-head normal form.
This also exists as a `conv`-mode tactic.

Weak-head normal form is when the outer-most expression has been fully reduced, the expression
may contain subexpressions which have not been reduced.
-/
elab "whnf" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (checkDefEq := false) (fun _ => whnf) loc? "whnf"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_tacticWhnf___1
code: /--
`whnf at loc` puts the given location into weak-head normal form.
This also exists as a `conv`-mode tactic.

Weak-head normal form is when the outer-most expression has been fully reduced, the expression
may contain subexpressions which have not been reduced.
-/
elab "whnf" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (checkDefEq := false) (fun _ => whnf) loc? "whnf"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.betaReduceStx
code: /--
`beta_reduce at loc` completely beta reduces the given location.
This also exists as a `conv`-mode tactic.

This means that whenever there is an applied lambda expression such as
`(fun x => f x) y` then the argument is substituted into the lambda expression
yielding an expression such as `f y`.
-/
elab (name := betaReduceStx) "beta_reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (checkDefEq := false) (fun _ e => Core.betaReduce e) loc? "beta_reduce"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_betaReduceStx_1
code: /--
`beta_reduce at loc` completely beta reduces the given location.
This also exists as a `conv`-mode tactic.

This means that whenever there is an applied lambda expression such as
`(fun x => f x) y` then the argument is substituted into the lambda expression
yielding an expression such as `f y`.
-/
elab (name := betaReduceStx) "beta_reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (checkDefEq := false) (fun _ e => Core.betaReduce e) loc? "beta_reduce"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convBeta_reduce_1
code: @[inherit_doc betaReduceStx]
elab "beta_reduce" : conv => runDefEqConvTactic (Core.betaReduce ·)
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convBeta_reduce
code: @[inherit_doc betaReduceStx]
elab "beta_reduce" : conv => runDefEqConvTactic (Core.betaReduce ·)
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.tacticReduce__
code: /--
`reduce at loc` completely reduces the given location.
This also exists as a `conv`-mode tactic.

This does the same transformation as the `#reduce` command.
-/
elab "reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ e => reduce e (skipTypes := false) (skipProofs := false)) loc? "reduce"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_tacticReduce___1
code: /--
`reduce at loc` completely reduces the given location.
This also exists as a `conv`-mode tactic.

This does the same transformation as the `#reduce` command.
-/
elab "reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ e => reduce e (skipTypes := false) (skipProofs := false)) loc? "reduce"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.unfoldFVars
code: /-- Unfold all the fvars from `fvars` in `e` that have local definitions (are "let-bound"). -/
def unfoldFVars (fvars : Array FVarId) (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic.unfoldLetStx
code: /--
`unfold_let x y z at loc` unfolds the local definitions `x`, `y`, and `z` at the given
location, which is known as "zeta reduction."
This also exists as a `conv`-mode tactic.

If no local definitions are given, then all local definitions are unfolded.
This variant also exists as the `conv`-mode tactic `zeta`.

This is similar to the `unfold` tactic, which instead is for unfolding global definitions.
-/
syntax (name := unfoldLetStx) "unfold_let" (ppSpace colGt term:max)*
  (ppSpace Parser.Tactic.location)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_unfoldLetStx_1
code: elab_rules : tactic
  | `(tactic| unfold_let $[$loc?]?) =>
    runDefEqTactic (fun _ => zetaReduce) loc? "unfold_let"
  | `(tactic| unfold_let $hs:term* $[$loc?]?) => do
    let fvars ← getFVarIds hs
    runDefEqTactic (fun _ => unfoldFVars fvars) loc? "unfold_let"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convUnfold_let___
code: @[inherit_doc unfoldLetStx]
syntax "unfold_let" (ppSpace colGt term:max)* : conv
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convUnfold_let____1
code: elab_rules : conv
  | `(conv| unfold_let) => runDefEqConvTactic zetaReduce
  | `(conv| unfold_let $hs:term*) => do
    runDefEqConvTactic (unfoldFVars (← getFVarIds hs))
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.refoldFVars
code: /-- For each fvar, looks for its body in `e` and replaces it with the fvar. -/
def refoldFVars (fvars : Array FVarId) (loc? : Option FVarId) (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic.refoldLetStx
code: /--
`refold_let x y z at loc` looks for the bodies of local definitions `x`, `y`, and `z` at the given
location and replaces them with `x`, `y`, or `z`. This is the inverse of "zeta reduction."
This also exists as a `conv`-mode tactic.
-/
syntax (name := refoldLetStx) "refold_let" (ppSpace colGt term:max)*
  (ppSpace Parser.Tactic.location)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_refoldLetStx_1
code: elab_rules : tactic
  | `(tactic| refold_let $hs:term* $[$loc?]?) => do
    let fvars ← getFVarIds hs
    runDefEqTactic (refoldFVars fvars) loc? "refold_let"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convRefold_let___
code: @[inherit_doc refoldLetStx]
syntax "refold_let" (ppSpace colGt term:max)* : conv
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convRefold_let____1
code: elab_rules : conv
  | `(conv| refold_let $hs:term*) => do
    runDefEqConvTactic (refoldFVars (← getFVarIds hs) none)
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.unfoldProjs
code: /-- Recursively unfold all the projection applications for class instances. -/
def unfoldProjs (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic.unfoldProjsStx
code: /--
`unfold_projs at loc` unfolds projections of class instances at the given location.
This also exists as a `conv`-mode tactic.
-/
elab (name := unfoldProjsStx) "unfold_projs" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => unfoldProjs) loc? "unfold_projs"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_unfoldProjsStx_1
code: /--
`unfold_projs at loc` unfolds projections of class instances at the given location.
This also exists as a `conv`-mode tactic.
-/
elab (name := unfoldProjsStx) "unfold_projs" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => unfoldProjs) loc? "unfold_projs"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convUnfold_projs
code: @[inherit_doc unfoldProjsStx]
elab "unfold_projs" : conv => runDefEqConvTactic unfoldProjs
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convUnfold_projs_1
code: @[inherit_doc unfoldProjsStx]
elab "unfold_projs" : conv => runDefEqConvTactic unfoldProjs
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.etaReduceAll
code: /-- Eta reduce everything -/
def etaReduceAll (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic.etaReduceStx
code: /--
`eta_reduce at loc` eta reduces all sub-expressions at the given location.
This also exists as a `conv`-mode tactic.

For example, `fun x y => f x y` becomes `f` after eta reduction.
-/
elab (name := etaReduceStx) "eta_reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaReduceAll) loc? "eta_reduce"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_etaReduceStx_1
code: /--
`eta_reduce at loc` eta reduces all sub-expressions at the given location.
This also exists as a `conv`-mode tactic.

For example, `fun x y => f x y` becomes `f` after eta reduction.
-/
elab (name := etaReduceStx) "eta_reduce" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaReduceAll) loc? "eta_reduce"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convEta_reduce
code: @[inherit_doc etaReduceStx]
elab "eta_reduce" : conv => runDefEqConvTactic etaReduceAll
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convEta_reduce_1
code: @[inherit_doc etaReduceStx]
elab "eta_reduce" : conv => runDefEqConvTactic etaReduceAll
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.etaExpandAll
code: /-- Eta expand every sub-expression in the given expression.

As a side-effect, beta reduces any pre-existing instances of eta expanded terms.  -/
partial def etaExpandAll (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic.etaExpandStx
code: /--
`eta_expand at loc` eta expands all sub-expressions at the given location.
It also beta reduces any applications of eta expanded terms, so it puts it
into an eta-expanded "normal form."
This also exists as a `conv`-mode tactic.

For example, if `f` takes two arguments, then `f` becomes `fun x y => f x y`
and `f x` becomes `fun y => f x y`.

This can be useful to turn, for example, a raw `HAdd.hAdd` into `fun x y => x + y`.
-/
elab (name := etaExpandStx) "eta_expand" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaExpandAll) loc? "eta_expand"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_etaExpandStx_1
code: /--
`eta_expand at loc` eta expands all sub-expressions at the given location.
It also beta reduces any applications of eta expanded terms, so it puts it
into an eta-expanded "normal form."
This also exists as a `conv`-mode tactic.

For example, if `f` takes two arguments, then `f` becomes `fun x y => f x y`
and `f x` becomes `fun y => f x y`.

This can be useful to turn, for example, a raw `HAdd.hAdd` into `fun x y => x + y`.
-/
elab (name := etaExpandStx) "eta_expand" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaExpandAll) loc? "eta_expand"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.convEta_expand
code: @[inherit_doc etaExpandStx]
elab "eta_expand" : conv => runDefEqConvTactic etaExpandAll
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convEta_expand_1
code: @[inherit_doc etaExpandStx]
elab "eta_expand" : conv => runDefEqConvTactic etaExpandAll
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.getProjectedExpr
code: /-- Given an expression that's either a native projection or a registered projection
function, gives (1) the name of the structure type, (2) the index of the projection, and
(3) the object being projected. -/
def getProjectedExpr (e : Expr) : MetaM (Option (Name × Nat × Expr)) 
goal: Lean.MetaM (Option (Lean.Name × Nat × Lean.Expr))

full_name: Mathlib.Tactic.etaStruct?
code: /-- Checks if the expression is of the form `S.mk x.1 ... x.n` with `n` nonzero
and `S.mk` a structure constructor and returns `x`.
Each projection `x.i` can be either a native projection or from a projection function.

`tryWhnfR` controls whether to try applying `whnfR` to arguments when none of them
are obviously projections.

Once an obviously correct projection is found, relies on the structure eta rule in `isDefEq`. -/
def etaStruct? (e : Expr) (tryWhnfR : Bool := true) : MetaM (Option Expr) 
goal: Lean.MetaM (Option Lean.Expr)

full_name: Mathlib.Tactic.etaStruct?.findProj
code: /-- Checks if the expression is of the form `S.mk x.1 ... x.n` with `n` nonzero
and `S.mk` a structure constructor and returns `x`.
Each projection `x.i` can be either a native projection or from a projection function.

`tryWhnfR` controls whether to try applying `whnfR` to arguments when none of them
are obviously projections.

Once an obviously correct projection is found, relies on the structure eta rule in `isDefEq`. -/
def etaStruct? (e : Expr) (tryWhnfR : Bool := true) : MetaM (Option Expr) 
goal: Lean.MetaM (Lean.LOption Lean.Expr)

full_name: Mathlib.Tactic.etaStructAll
code: /-- Finds all occurrences of expressions of the form `S.mk x.1 ... x.n` where `S.mk`
is a structure constructor and replaces them by `x`. -/
def etaStructAll (e : Expr) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_etaStructStx_1
code: /--
`eta_struct at loc` transforms structure constructor applications such as `S.mk x.1 ... x.n`
(pretty printed as, for example, `{a := x.a, b := x.b, ...}`) into `x`.
This also exists as a `conv`-mode tactic.

The transformation is known as eta reduction for structures, and it yields definitionally
equal expressions.

For example, given `x : α × β`, then `(x.1, x.2)` becomes `x` after this transformation.
-/
elab (name := etaStructStx) "eta_struct" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaStructAll) loc? "eta_struct"
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.etaStructStx
code: /--
`eta_struct at loc` transforms structure constructor applications such as `S.mk x.1 ... x.n`
(pretty printed as, for example, `{a := x.a, b := x.b, ...}`) into `x`.
This also exists as a `conv`-mode tactic.

The transformation is known as eta reduction for structures, and it yields definitionally
equal expressions.

For example, given `x : α × β`, then `(x.1, x.2)` becomes `x` after this transformation.
-/
elab (name := etaStructStx) "eta_struct" loc?:(ppSpace Parser.Tactic.location)? : tactic =>
  runDefEqTactic (fun _ => etaStructAll) loc? "eta_struct"
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.convEta_struct
code: @[inherit_doc etaStructStx]
elab "eta_struct" : conv => runDefEqConvTactic etaStructAll
goal: Lean.ParserDescr

full_name: Mathlib.Tactic._aux_Mathlib_Tactic_DefEqTransformations___elabRules_Mathlib_Tactic_convEta_struct_1
code: @[inherit_doc etaStructStx]
elab "eta_struct" : conv => runDefEqConvTactic etaStructAll
goal: Lean.Elab.Tactic.Tactic