blob: a784b7dc2cd7f4c993d0ffc4d1e720d5a8dfb9d9 [file] [edit]
/-
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Gabriel Ebner
-/
prelude
import Init.Core
open Lean
-- Implementation detail of TypeName, since classes cannot be opaque
private opaque TypeNameData (α : Type u) : NonemptyType.{0} :=
⟨Name, inferInstance⟩
/--
Dynamic type name information.
Types with an instance of `TypeName` can be stored in an `Dynamic`.
The type class contains the declaration name of the type,
which must not have any universe parameters
and be of type `Sort ..` (i.e., monomorphic).
The preferred way to declare instances of this type is using the derive
handler, which will internally use the unsafe `TypeName.mk` function.
Morally, this is the same as:
```lean
class TypeName (α : Type) where unsafe mk ::
typeName : Name
```
-/
@[nospecialize]
class TypeName (α : Type u) where private mk' ::
private data : (TypeNameData α).type
instance : Nonempty (TypeName α) := (TypeNameData α).property.elim (⟨⟨·⟩⟩)
/--
Creates a `TypeName` instance.
For safety, it is required that the constant `typeName` is definitionally equal
to `α`.
-/
unsafe def TypeName.mk (α : Type u) (typeName : Name) : TypeName α :=
⟨unsafeCast typeName⟩
private unsafe def TypeName.typeNameImpl (α) [TypeName α] : Name :=
unsafeCast (@TypeName.data α _)
/--
Returns a declaration name of the type.
-/
@[implemented_by TypeName.typeNameImpl]
opaque TypeName.typeName (α) [TypeName α] : Name
private opaque DynamicPointed : NonemptyType.{0} :=
⟨Name × NonScalar, inferInstance⟩
/--
Type-tagged union that can store any type with a `TypeName` instance.
This is roughly equivalent to `(α : Type) × TypeName α × α` but without the
universe bump.
-/
def Dynamic : Type := DynamicPointed.type
instance : Nonempty Dynamic := DynamicPointed.property
private unsafe def Dynamic.typeNameImpl (any : Dynamic) : Name :=
(unsafeCast any : Name × NonScalar).1
/--
The name of the type of the value stored in the `Dynamic`.
-/
@[implemented_by Dynamic.typeNameImpl]
opaque Dynamic.typeName (any : Dynamic) : Name
private unsafe def Dynamic.get?Impl (α) (any : Dynamic) [TypeName α] : Option α :=
let ((typeName, obj) : Name × NonScalar) := unsafeCast any
if typeName == TypeName.typeName α then
some (unsafeCast obj)
else
none
/--
Retrieves the value stored in the `Dynamic`.
Returns `some a` if the value has the right type, and `none` otherwise.
-/
@[implemented_by Dynamic.get?Impl]
opaque Dynamic.get? (α) (any : Dynamic) [TypeName α] : Option α
private unsafe def Dynamic.mkImpl [TypeName α] (obj : α) : Dynamic :=
unsafeCast (TypeName.typeName α, (unsafeCast obj : NonScalar))
@[implemented_by Dynamic.mkImpl]
opaque Dynamic.mk [TypeName α] (obj : α) : Dynamic