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) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro
-/
import Std.Lean.TagAttribute
open Lean
namespace Lean
/--
`TagAttributeExtra` works around a limitation of `TagAttribute`, which is that definitions
must be tagged in the same file that declares the definition.
This works well for definitions in lean core, but for attributes declared outside the core
this is problematic because we may want to tag declarations created before the attribute
was defined.
To resolve this, we allow a one-time exception to the rule that attributes must be applied
in the same file as the declaration: During the declaration of the attribute itself,
we can tag arbitrary other definitions, but once the attribute is declared we must tag things
in the same file as normal.
-/
structure TagAttributeExtra where
/-- The environment extension for the attribute. -/
ext : PersistentEnvExtension Name Name NameSet
/-- A list of "base" declarations which have been pre-tagged. -/
base : NameHashSet
deriving Inhabited
/--
Registers a new tag attribute. The `extra` field is a list of definitions from other modules
which will be "pre-tagged" and are not subject to the usual restriction on tagging in the same
file as the declaration.
Note: The `extra` fields bypass the `validate` function -
we assume the builtins are also pre-validated.
-/
def registerTagAttributeExtra (name : Name) (descr : String) (extra : List Name)
(validate : Name β AttrM Unit := fun _ => pure: {f : Type ?u.860 β Type ?u.859} β [self : Pure f] β {Ξ± : Type ?u.860} β Ξ± β f Ξ±
pure ()) (ref : Name := by exact decl_name%) :
IO TagAttributeExtra := do
let { ext, .. } β registerTagAttribute name descr validate ref
pure: {f : Type ?u.1086 β Type ?u.1085} β [self : Pure f] β {Ξ± : Type ?u.1086} β Ξ± β f Ξ±
pure { ext, base := extra.foldl: {Ξ± : Type ?u.1111} β {Ξ² : Type ?u.1110} β (Ξ± β Ξ² β Ξ±) β Ξ± β List Ξ² β Ξ±
foldl (Β·.insert Β·) {} }
namespace TagAttributeExtra
/-- Does declaration `decl` have the tag `attr`? -/
def hasTag (attr : TagAttributeExtra) (env : Environment) (decl : Name) : Bool :=
match env.getModuleIdxFor? decl with
| some modIdx => (attr.ext.getModuleEntries env modIdx).binSearchContains decl Name.quickLt
| none => (attr.ext.getState env).contains decl
|| attr.base.contains decl
/-- Get the list of declarations tagged with the tag attribute `attr`. -/
def getDecls (attr : TagAttributeExtra) (env : Environment) : Array Name := Id.run: {Ξ± : Type ?u.2267} β Id Ξ± β Ξ±
Id.run do
let decls := TagAttribute.getDecls.core <| attr.ext.toEnvExtension.getState env
attr.base.fold: {Ξ± : Type ?u.2316} β {x : BEq Ξ±} β {x_1 : Hashable Ξ±} β {Ξ΄ : Type ?u.2315} β (Ξ΄ β Ξ± β Ξ΄) β Ξ΄ β HashSet Ξ± β Ξ΄
fold (Β·.push Β·) decls
end TagAttributeExtra
/--
`ParametricAttributeExtra` works around a limitation of `ParametricAttribute`, which is that
definitions must be tagged in the same file that declares the definition.
This works well for definitions in lean core, but for attributes declared outside the core
this is problematic because we may want to tag declarations created before the attribute
was defined.
To resolve this, we allow a one-time exception to the rule that attributes must be applied
in the same file as the declaration: During the declaration of the attribute itself,
we can tag arbitrary other definitions, but once the attribute is declared we must tag things
in the same file as normal.
-/
structure ParametricAttributeExtra (Ξ± : Type) where
/-- The underlying `ParametricAttribute`. -/
attr : ParametricAttribute Ξ±
/-- A list of pre-tagged declarations with their values. -/
base : HashMap: (Ξ± : Type ?u.2841) β Type ?u.2840 β [inst : BEq Ξ±] β [inst : Hashable Ξ±] β Type (max0?u.2841?u.2840)
HashMap Name Ξ±
deriving Inhabited
/--
Registers a new parametric attribute. The `extra` field is a list of definitions from other modules
which will be "pre-tagged" and are not subject to the usual restriction on tagging in the same
file as the declaration.
-/
def registerParametricAttributeExtra [Inhabited: Sort ?u.4008 β Sort (max1?u.4008)
Inhabited Ξ±] (impl : ParametricAttributeImpl Ξ±)
(extra : List (Name Γ Ξ±)) : IO (ParametricAttributeExtra Ξ±) := do
let attr β registerParametricAttribute impl
pure: {f : Type ?u.4161 β Type ?u.4160} β [self : Pure f] β {Ξ± : Type ?u.4161} β Ξ± β f Ξ±
pure { attr, base := extra.foldl: {Ξ± : Type ?u.4189} β {Ξ² : Type ?u.4188} β (Ξ± β Ξ² β Ξ±) β Ξ± β List Ξ² β Ξ±
foldl (fun s (a, b) => s.insert a b) {} }
namespace ParametricAttributeExtra
/--
Gets the parameter of attribute `attr` associated to declaration `decl`,
or `none` if `decl` is not tagged.
-/
def getParam? [Inhabited: Sort ?u.4615 β Sort (max1?u.4615)
Inhabited Ξ±] (attr : ParametricAttributeExtra Ξ±)
(env : Environment) (decl : Name) : Option Ξ± :=
attr.attr.getParam? env decl <|> attr.base.find? decl
/-- Applies attribute `attr` to declaration `decl`, given a value for the parameter. -/
def setParam (attr : ParametricAttributeExtra Ξ±)
(env : Environment) (decl : Name) (param : Ξ±) : Except: Type ?u.4819 β Type ?u.4818 β Type (max?u.4819?u.4818)
Except String Environment :=
attr.attr.setParam env decl param
end ParametricAttributeExtra