Built with
doc-gen4, running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑Ctrl+↓to navigate,
Ctrl+🖱️to focus.
On Mac, use
Cmdinstead of
Ctrl.
/-
Copyright (c) 2021 Gabriel Ebner. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
import Lean
import Mathlib.Tactic.Eqns
import Mathlib.Data.Subtype
/-!
# Irreducible definitions
This file defines an `irreducible_def` command,
which works almost like the `def` command
except that the introduced definition
does not reduce to the value.
Instead, the command
adds a `_def` lemma
which can be used for rewriting.
```
irreducible_def frobnicate (a b : Nat) :=
a + b
example : frobnicate a 0 = a := by
simp [frobnicate_def]
```
-/
namespace Lean.Elab.Command
open Term Meta
/-- `delta% t` elaborates to a head-delta reduced version of `t`. -/
elab "delta% " t:term : term <= expectedType => do
let t ← elabTerm t expectedType
synthesizeSyntheticMVars
let t ← instantiateMVars t
let some t ← delta? t | throwError "cannot delta reduce {t}"
pure: {f : Type ?u.736 → Type ?u.735} → [self : Pure f] → {α : Type ?u.736} → α → f α
pure t
/- `eta_helper f = (· + 3)` elabs to `∀ x, f x = x + 3` -/
local elab "eta_helper " t:term : term => do
let t ← elabTerm t none
let some (_, lhs, rhs) := t.eq? | throwError "not an equation: {t}"
synthesizeSyntheticMVars
let rhs ← instantiateMVars rhs
lambdaTelescope rhs fun xs rhs ↦ do
let lhs := (mkAppN lhs xs).headBeta
mkForallFVars xs <|← mkEq lhs rhs
/-- `val_proj x` elabs to the *primitive projection* `@x.val`. -/
local elab "val_proj " e:term : term => do
let e ← elabTerm (← `(($e : Subtype _))): ?m.6961
(← `(($e(← `(($e : Subtype _))): ?m.6961
: Subtype _))) none
return mkProj ``Subtype 0 e
/--
Executes the commands,
and stops after the first error.
In short, S-A-F-E.
-/
local syntax "stop_at_first_error" (ppLine command)* : command
open Command in elab_rules : command
| `(stop_at_first_error $[$cmds]*) => do
for cmd in cmds do
elabCommand cmd.raw
if (← get).messages.hasErrors then break
syntax irredDefLemma := atomic("(" "lemma" " := ") ident ")"
/--
Introduces an irreducible definition.
`irreducible_def foo := 42` generates
a constant `foo : Nat` as well as
a theorem `foo_def : foo = 42`.
-/
elab mods:declModifiers "irreducible_def" n_id:declId n_def:(irredDefLemma)?
declSig:optDeclSig val:declVal :
command => do
let (n, us) ← match n_id with
| `(Parser.Command.declId| $n:ident $[.{$us,*}]?) => pure: {f : Type ?u.14035 → Type ?u.14034} → [self : Pure f] → {α : Type ?u.14035} → α → f α
pure (n, us)
| _ => throwUnsupportedSyntax
let us' := us.getD { elemsAndSeps := #[] }
let n_def ← match n_def.getD ⟨mkNullNode⟩ with
| `(irredDefLemma| (lemma := $id)) => pure: {f : Type ?u.14601 → Type ?u.14600} → [self : Pure f] → {α : Type ?u.14601} → α → f α
pure id
| _ => pure: {f : Type ?u.14696 → Type ?u.14695} → [self : Pure f] → {α : Type ?u.14696} → α → f α
purepure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
<| mkIdentpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
<| (·.reviewpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
) <|
pure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
letpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
scopespure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
:= extractMacroScopespure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
npure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
.getIdpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
{ scopespure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
pure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
withpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
namepure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
:= scopespure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
.namepure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
.appendAfterpure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
"_def"pure <| mkIdent <| (·.review) <|
let scopes := extractMacroScopes n.getId
{ scopes with name := scopes.name.appendAfter "_def" }: CommandElabM (?m.14425 y✝)
}
let `(Parser.Command.declModifiersF|
$[$doc:docComment]? $[@[$attrs,*]]?
$[$vis]? $[$nc:noncomputable]? $[$uns:unsafe]?) := mods
| throwError "unsupported modifiers {format mods}"
let attrs := attrs.getD {}
let prot := vis.filter (· matches `(Parser.Command.visibility| protected))
let priv := vis.filter (· matches `(Parser.Command.visibility| private))
elabCommand <|<- `(stop_at_first_error
$[$nc:noncomputable]? $[$uns: TSyntax `Lean.Parser.Command.unsafe
uns]? def definition$[.{$us,*}]? $declSig:optDeclSig $val
$[$nc:noncomputable]? $[$uns: TSyntax `Lean.Parser.Command.unsafe
uns]? opaque wrapped$[.{$us,*}]? : Subtype (Eq @definition.{$us',*}) :=
⟨_, rfl⟩
$[$doc:docComment]? $[private%$priv]? $[$nc: TSyntax `Lean.Parser.Command.noncomputable
nc:noncomputable]? $[$uns]?
def $n:ident$[.{$us,*}]? :=
val_proj @wrapped.{$us',*}
$[private%$priv]? $[$uns: TSyntax `Lean.Parser.Command.unsafe
uns:unsafe]? theorem $n_def:ident $[.{$us,*}]? :
eta_helper Eq @$n.{$us',*} @(delta% @definition) := by
intros
delta $n:ident
rw [show wrapped = ⟨@definition.{$us',*}, rfl⟩ from Subtype.ext wrapped.2.symm]
rfl
attribute [irreducible] $n definition
attribute [eqns $n_def] $n
attribute [$attrs:attrInstance,*] $n)
if prot.isSome then
modifyEnv (addProtected · ((← getCurrNamespace) ++ n.getId))