chore: upstream haveI tactic
chore: `haveI` and `letI` builtin parsers
This commit is contained in:
parent
9cea1a503e
commit
98085661c7
3 changed files with 66 additions and 0 deletions
|
|
@ -27,3 +27,4 @@ import Lean.Elab.Tactic.Guard
|
|||
import Lean.Elab.Tactic.RCases
|
||||
import Lean.Elab.Tactic.Repeat
|
||||
import Lean.Elab.Tactic.Change
|
||||
import Lean.Elab.Tactic.HaveI
|
||||
|
|
|
|||
59
src/Lean/Elab/Tactic/HaveI.lean
Normal file
59
src/Lean/Elab/Tactic/HaveI.lean
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/-
|
||||
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Gabriel Ebner
|
||||
-/
|
||||
import Lean.Elab.ElabRules
|
||||
open Lean Elab Parser Term Meta Macro
|
||||
|
||||
/-!
|
||||
Defines variants of `have` and `let` syntax which do not produce `let_fun` or `let` bindings,
|
||||
but instead inline the value instead.
|
||||
|
||||
This is useful to declare local instances and proofs in theorem statements
|
||||
and subgoals, where the extra binding is inconvenient.
|
||||
-/
|
||||
|
||||
#exit
|
||||
|
||||
namespace Std.Tactic
|
||||
|
||||
|
||||
macro_rules
|
||||
| `(haveI $hy:hygieneInfo $bs* $[: $ty]? := $val; $body) =>
|
||||
`(haveI $(HygieneInfo.mkIdent hy `this (canonical := true)) $bs* $[: $ty]? := $val; $body)
|
||||
| `(haveI _ $bs* := $val; $body) => `(haveI x $bs* : _ := $val; $body)
|
||||
| `(haveI _ $bs* : $ty := $val; $body) => `(haveI x $bs* : $ty := $val; $body)
|
||||
| `(haveI $x:ident $bs* := $val; $body) => `(haveI $x $bs* : _ := $val; $body)
|
||||
| `(haveI $_:ident $_* : $_ := $_; $_) => throwUnsupported -- handled by elab
|
||||
|
||||
macro_rules
|
||||
| `(letI $hy:hygieneInfo $bs* $[: $ty]? := $val; $body) =>
|
||||
`(letI $(HygieneInfo.mkIdent hy `this (canonical := true)) $bs* $[: $ty]? := $val; $body)
|
||||
| `(letI _ $bs* := $val; $body) => `(letI x $bs* : _ := $val; $body)
|
||||
| `(letI _ $bs* : $ty := $val; $body) => `(letI x $bs* : $ty := $val; $body)
|
||||
| `(letI $x:ident $bs* := $val; $body) => `(letI $x $bs* : _ := $val; $body)
|
||||
| `(letI $_:ident $_* : $_ := $_; $_) => throwUnsupported -- handled by elab
|
||||
|
||||
elab_rules <= expectedType
|
||||
| `(haveI $x:ident $bs* : $ty := $val; $body) => do
|
||||
let (ty, val) ← elabBinders bs fun bs => do
|
||||
let ty ← elabType ty
|
||||
let val ← elabTermEnsuringType val ty
|
||||
pure (← mkForallFVars bs ty, ← mkLambdaFVars bs val)
|
||||
withLocalDeclD x.getId ty fun x => do
|
||||
return (← (← elabTerm body expectedType).abstractM #[x]).instantiate #[val]
|
||||
|
||||
elab_rules <= expectedType
|
||||
| `(letI $x:ident $bs* : $ty := $val; $body) => do
|
||||
let (ty, val) ← elabBinders bs fun bs => do
|
||||
let ty ← elabType ty
|
||||
let val ← elabTermEnsuringType val ty
|
||||
pure (← mkForallFVars bs ty, ← mkLambdaFVars bs val)
|
||||
withLetDecl x.getId ty val fun x => do
|
||||
return (← (← elabTerm body expectedType).abstractM #[x]).instantiate #[val]
|
||||
|
||||
/-- `haveI` behaves like `have`, but inlines the value instead of producing a `let_fun` term. -/
|
||||
macro "haveI" d:haveDecl : tactic => `(tactic| refine_lift haveI $d:haveDecl; ?_)
|
||||
/-- `letI` behaves like `let`, but inlines the value instead of producing a `let_fun` term. -/
|
||||
macro "letI" d:haveDecl : tactic => `(tactic| refine_lift letI $d:haveDecl; ?_)
|
||||
|
|
@ -569,6 +569,12 @@ def haveDecl := leading_parser (withAnonymousAntiquot := false)
|
|||
haveIdDecl <|> (ppSpace >> letPatDecl) <|> haveEqnsDecl
|
||||
@[builtin_term_parser] def «have» := leading_parser:leadPrec
|
||||
withPosition ("have" >> haveDecl) >> optSemicolon termParser
|
||||
/-- `haveI` behaves like `have`, but inlines the value instead of producing a `let_fun` term. -/
|
||||
@[builtin_term_parser] def «haveI» := leading_parser
|
||||
withPosition ("haveI " >> haveDecl) >> optSemicolon termParser
|
||||
/-- `letI` behaves like `let`, but inlines the value instead of producing a `let_fun` term. -/
|
||||
@[builtin_term_parser] def «letI» := leading_parser
|
||||
withPosition ("letI " >> haveDecl) >> optSemicolon termParser
|
||||
|
||||
def «scoped» := leading_parser "scoped "
|
||||
def «local» := leading_parser "local "
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue