File: Mathlib/Tactic/SimpIntro.lean

full_name: Mathlib.Tactic.simpIntroCore
code: /--
Main loop of the `simp_intro` tactic.
* `g`: the original goal
* `ctx`: the simp context, which is extended with local variables as we enter the binders
* `discharge?`: the discharger
* `more`: if true, we will keep introducing binders as long as we can
* `ids`: the list of binder identifiers
-/
partial def simpIntroCore (g : MVarId) (ctx : Simp.Context) (simprocs : Simp.SimprocsArray := #[])
    (discharge? : Option Simp.Discharge) (more : Bool) (ids : List (TSyntax ``binderIdent)) :
    TermElabM (Option MVarId) 
goal: Lean.Elab.TermElabM (Option Lean.MVarId)

full_name: Mathlib.Tactic.«_aux_Mathlib_Tactic_SimpIntro___elabRules_Mathlib_Tactic_tacticSimp_intro_____..Only__1»
code: /--
The `simp_intro` tactic is a combination of `simp` and `intro`: it will simplify the types of
variables as it introduces them and uses the new variables to simplify later arguments
and the goal.
* `simp_intro x y z` introduces variables named `x y z`
* `simp_intro x y z ..` introduces variables named `x y z` and then keeps introducing `_` binders
* `simp_intro (config := cfg) (discharger := tac) x y .. only [h₁, h₂]`:
  `simp_intro` takes the same options as `simp` (see `simp`)
```
example : x + 0 = y → x = z := by
  simp_intro h
  -- h: x = y ⊢ y = z
  sorry
```
-/
elab "simp_intro" cfg:(config)? disch:(discharger)?
    ids:(ppSpace colGt binderIdent)* more:" .."? only:(&" only")? args:(simpArgs)? : tactic => do
  let args := args.map fun args ↦ ⟨args.raw[1].getArgs⟩
  let stx ← `(tactic| simp $(cfg)? $(disch)? $[only%$only]? $[[$args,*]]?)
  let { ctx, simprocs, dischargeWrapper } ←
    withMainContext <| mkSimpContext stx (eraseLocal := false)
  dischargeWrapper.with fun discharge? ↦ do
    let g ← getMainGoal
    g.checkNotAssigned `simp_intro
    g.withContext do
      let g? ← simpIntroCore g ctx (simprocs := simprocs) discharge? more.isSome ids.toList
      replaceMainGoal <| if let some g := g? then [g] else []
goal: Lean.Elab.Tactic.Tactic

full_name: Mathlib.Tactic.«tacticSimp_intro_____..Only_»
code: /--
The `simp_intro` tactic is a combination of `simp` and `intro`: it will simplify the types of
variables as it introduces them and uses the new variables to simplify later arguments
and the goal.
* `simp_intro x y z` introduces variables named `x y z`
* `simp_intro x y z ..` introduces variables named `x y z` and then keeps introducing `_` binders
* `simp_intro (config := cfg) (discharger := tac) x y .. only [h₁, h₂]`:
  `simp_intro` takes the same options as `simp` (see `simp`)
```
example : x + 0 = y → x = z := by
  simp_intro h
  -- h: x = y ⊢ y = z
  sorry
```
-/
elab "simp_intro" cfg:(config)? disch:(discharger)?
    ids:(ppSpace colGt binderIdent)* more:" .."? only:(&" only")? args:(simpArgs)? : tactic => do
  let args := args.map fun args ↦ ⟨args.raw[1].getArgs⟩
  let stx ← `(tactic| simp $(cfg)? $(disch)? $[only%$only]? $[[$args,*]]?)
  let { ctx, simprocs, dischargeWrapper } ←
    withMainContext <| mkSimpContext stx (eraseLocal := false)
  dischargeWrapper.with fun discharge? ↦ do
    let g ← getMainGoal
    g.checkNotAssigned `simp_intro
    g.withContext do
      let g? ← simpIntroCore g ctx (simprocs := simprocs) discharge? more.isSome ids.toList
      replaceMainGoal <| if let some g := g? then [g] else []
goal: Lean.ParserDescr