parent
13640c08a2
commit
c05d1aab13
1 changed files with 80 additions and 30 deletions
|
|
@ -15,18 +15,22 @@
|
||||||
import std/private/since
|
import std/private/since
|
||||||
export system.`$` # for backward compatibility
|
export system.`$` # for backward compatibility
|
||||||
|
|
||||||
proc name*(t: typedesc): string {.magic: "TypeTrait".}
|
proc name*(t: typedesc): string {.magic: "TypeTrait".} =
|
||||||
## Returns the name of the given type.
|
## Returns the name of the given type.
|
||||||
##
|
##
|
||||||
## Alias for system.`$`(t) since Nim v0.20.
|
## Alias for `system.\`$\`(t) <dollars.html#$,typedesc>`_ since Nim v0.20.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert name(int) == "int"
|
||||||
|
doAssert name(seq[string]) == "seq[string]"
|
||||||
|
|
||||||
proc arity*(t: typedesc): int {.magic: "TypeTrait".} =
|
proc arity*(t: typedesc): int {.magic: "TypeTrait".} =
|
||||||
## Returns the arity of the given type. This is the number of "type"
|
## Returns the arity of the given type. This is the number of "type"
|
||||||
## components or the number of generic parameters a given type ``t`` has.
|
## components or the number of generic parameters a given type `t` has.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
assert arity(seq[string]) == 1
|
doAssert arity(int) == 0
|
||||||
assert arity(array[3, int]) == 2
|
doAssert arity(seq[string]) == 1
|
||||||
assert arity((int, int, float, string)) == 4
|
doAssert arity(array[3, int]) == 2
|
||||||
|
doAssert arity((int, int, float, string)) == 4
|
||||||
|
|
||||||
proc genericHead*(t: typedesc): typedesc {.magic: "TypeTrait".} =
|
proc genericHead*(t: typedesc): typedesc {.magic: "TypeTrait".} =
|
||||||
## Accepts an instantiated generic type and returns its
|
## Accepts an instantiated generic type and returns its
|
||||||
|
|
@ -34,20 +38,23 @@ proc genericHead*(t: typedesc): typedesc {.magic: "TypeTrait".} =
|
||||||
## A compile-time error will be produced if the supplied type
|
## A compile-time error will be produced if the supplied type
|
||||||
## is not generic.
|
## is not generic.
|
||||||
##
|
##
|
||||||
## See also:
|
## **See also:**
|
||||||
## * `stripGenericParams <#stripGenericParams,typedesc>`_
|
## * `stripGenericParams proc <#stripGenericParams,typedesc>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
type
|
type
|
||||||
Foo[T] = object
|
Foo[T] = object
|
||||||
FooInst = Foo[int]
|
FooInst = Foo[int]
|
||||||
Foo2 = genericHead(FooInst)
|
Foo2 = genericHead(FooInst)
|
||||||
|
|
||||||
doAssert Foo2 is Foo and Foo is Foo2
|
doAssert Foo2 is Foo and Foo is Foo2
|
||||||
doAssert genericHead(Foo[seq[string]]) is Foo
|
doAssert genericHead(Foo[seq[string]]) is Foo
|
||||||
doAssert not compiles(genericHead(int))
|
doAssert not compiles(genericHead(int))
|
||||||
|
|
||||||
type Generic = concept f
|
type Generic = concept f
|
||||||
type _ = genericHead(typeof(f))
|
type _ = genericHead(typeof(f))
|
||||||
|
|
||||||
proc bar(a: Generic): typeof(a) = a
|
proc bar(a: Generic): typeof(a) = a
|
||||||
|
|
||||||
doAssert bar(Foo[string].default) == Foo[string]()
|
doAssert bar(Foo[string].default) == Foo[string]()
|
||||||
doAssert not compiles bar(string.default)
|
doAssert not compiles bar(string.default)
|
||||||
|
|
||||||
|
|
@ -55,66 +62,105 @@ proc genericHead*(t: typedesc): typedesc {.magic: "TypeTrait".} =
|
||||||
doAssert genericHead(Foo[int])[float] is Foo[float]
|
doAssert genericHead(Foo[int])[float] is Foo[float]
|
||||||
doAssert seq[int].genericHead is seq
|
doAssert seq[int].genericHead is seq
|
||||||
|
|
||||||
proc stripGenericParams*(t: typedesc): typedesc {.magic: "TypeTrait".}
|
proc stripGenericParams*(t: typedesc): typedesc {.magic: "TypeTrait".} =
|
||||||
## This trait is similar to `genericHead <#genericHead,typedesc>`_, but
|
## This trait is similar to `genericHead <#genericHead,typedesc>`_, but
|
||||||
## instead of producing error for non-generic types, it will just return
|
## instead of producing an error for non-generic types, it will just return
|
||||||
## them unmodified.
|
## them unmodified.
|
||||||
|
runnableExamples:
|
||||||
|
type Foo[T] = object
|
||||||
|
|
||||||
|
doAssert stripGenericParams(Foo[string]) is Foo
|
||||||
|
doAssert stripGenericParams(int) is int
|
||||||
|
|
||||||
proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".}
|
proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".}
|
||||||
## This trait returns true if the type ``t`` is safe to use for
|
## This trait returns true if the type `t` is safe to use for
|
||||||
## `copyMem`:idx:.
|
## `copyMem`:idx:.
|
||||||
##
|
##
|
||||||
## Other languages name a type like these `blob`:idx:.
|
## Other languages name a type like these `blob`:idx:.
|
||||||
|
|
||||||
proc isNamedTuple*(T: typedesc): bool {.magic: "TypeTrait".}
|
proc isNamedTuple*(T: typedesc): bool {.magic: "TypeTrait".} =
|
||||||
## Return true for named tuples, false for any other type.
|
## Returns true for named tuples, false for any other type.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert not isNamedTuple(int)
|
||||||
|
doAssert not isNamedTuple((string, int))
|
||||||
|
doAssert isNamedTuple(tuple[name: string, age: int])
|
||||||
|
|
||||||
proc distinctBase*(T: typedesc): typedesc {.magic: "TypeTrait".}
|
proc distinctBase*(T: typedesc): typedesc {.magic: "TypeTrait".} =
|
||||||
## Returns base type for distinct types, works only for distinct types.
|
## Returns the base type for distinct types. This works only
|
||||||
## compile time error otherwise
|
## for distinct types and produces a compile time error otherwise.
|
||||||
|
##
|
||||||
|
## **See also:**
|
||||||
|
## * `distinctBase template <#distinctBase.t,T>`_
|
||||||
|
runnableExamples:
|
||||||
|
type MyInt = distinct int
|
||||||
|
|
||||||
|
doAssert distinctBase(MyInt) is int
|
||||||
|
doAssert not compiles(distinctBase(int))
|
||||||
|
|
||||||
since (1, 1):
|
since (1, 1):
|
||||||
template distinctBase*[T](a: T): untyped =
|
template distinctBase*[T](a: T): untyped =
|
||||||
## overload for values
|
## Overload of `distinctBase <#distinctBase,typedesc>`_ for values.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
type MyInt = distinct int
|
type MyInt = distinct int
|
||||||
|
|
||||||
doAssert 12.MyInt.distinctBase == 12
|
doAssert 12.MyInt.distinctBase == 12
|
||||||
|
|
||||||
distinctBase(type(a))(a)
|
distinctBase(type(a))(a)
|
||||||
|
|
||||||
proc tupleLen*(T: typedesc[tuple]): int {.magic: "TypeTrait".}
|
proc tupleLen*(T: typedesc[tuple]): int {.magic: "TypeTrait".} =
|
||||||
## Return number of elements of `T`
|
## Returns the number of elements of the tuple type `T`.
|
||||||
|
##
|
||||||
|
## **See also:**
|
||||||
|
## * `tupleLen template <#tupleLen.t>`_
|
||||||
|
runnableExamples:
|
||||||
|
doAssert tupleLen((int, int, float, string)) == 4
|
||||||
|
doAssert tupleLen(tuple[name: string, age: int]) == 2
|
||||||
|
|
||||||
template tupleLen*(t: tuple): int =
|
template tupleLen*(t: tuple): int =
|
||||||
## Return number of elements of `t`
|
## Returns the number of elements of the tuple `t`.
|
||||||
|
##
|
||||||
|
## **See also:**
|
||||||
|
## * `tupleLen proc <#tupleLen,typedesc>`_
|
||||||
|
runnableExamples:
|
||||||
|
doAssert tupleLen((1, 2)) == 2
|
||||||
|
|
||||||
tupleLen(type(t))
|
tupleLen(type(t))
|
||||||
|
|
||||||
template get*(T: typedesc[tuple], i: static int): untyped =
|
template get*(T: typedesc[tuple], i: static int): untyped =
|
||||||
## Return `i`\th element of `T`
|
## Returns the `i`-th element of `T`.
|
||||||
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
|
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
|
||||||
|
runnableExamples:
|
||||||
|
doAssert get((int, int, float, string), 2) is float
|
||||||
|
|
||||||
type(default(T)[i])
|
type(default(T)[i])
|
||||||
|
|
||||||
type StaticParam*[value: static type] = object
|
type StaticParam*[value: static type] = object
|
||||||
## used to wrap a static value in `genericParams`
|
## Used to wrap a static value in `genericParams <#genericParams.t,typedesc>`_.
|
||||||
|
|
||||||
since (1, 3, 5):
|
since (1, 3, 5):
|
||||||
template elementType*(a: untyped): typedesc =
|
template elementType*(a: untyped): typedesc =
|
||||||
## return element type of `a`, which can be any iterable (over which you
|
## Returns the element type of `a`, which can be any iterable (over which you
|
||||||
## can iterate)
|
## can iterate).
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
iterator myiter(n: int): auto =
|
iterator myiter(n: int): auto =
|
||||||
for i in 0..<n: yield i
|
for i in 0 ..< n:
|
||||||
|
yield i
|
||||||
|
|
||||||
doAssert elementType(@[1,2]) is int
|
doAssert elementType(@[1,2]) is int
|
||||||
doAssert elementType("asdf") is char
|
doAssert elementType("asdf") is char
|
||||||
doAssert elementType(myiter(3)) is int
|
doAssert elementType(myiter(3)) is int
|
||||||
|
|
||||||
typeof(block: (for ai in a: ai))
|
typeof(block: (for ai in a: ai))
|
||||||
|
|
||||||
import std/macros
|
import std/macros
|
||||||
|
|
||||||
macro enumLen*(T: typedesc[enum]): int =
|
macro enumLen*(T: typedesc[enum]): int =
|
||||||
## Returns the number of items in the enum `T`.
|
## Returns the number of items in the enum `T`.
|
||||||
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
type Foo = enum fooItem1 fooItem2
|
type Foo = enum
|
||||||
|
fooItem1
|
||||||
|
fooItem2
|
||||||
|
|
||||||
doAssert Foo.enumLen == 2
|
doAssert Foo.enumLen == 2
|
||||||
|
|
||||||
let bracketExpr = getType(T)
|
let bracketExpr = getType(T)
|
||||||
|
|
@ -179,19 +225,23 @@ macro genericParamsImpl(T: typedesc): untyped =
|
||||||
|
|
||||||
since (1, 1):
|
since (1, 1):
|
||||||
template genericParams*(T: typedesc): untyped =
|
template genericParams*(T: typedesc): untyped =
|
||||||
## return tuple of generic params for generic `T`
|
## Returns the tuple of generic parameters for the generic type `T`.
|
||||||
|
##
|
||||||
|
## **Note:** For the builtin array type, the index generic parameter will
|
||||||
|
## **always** become a range type after it's bound to a variable.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
type Foo[T1, T2] = object
|
type Foo[T1, T2] = object
|
||||||
|
|
||||||
doAssert genericParams(Foo[float, string]) is (float, string)
|
doAssert genericParams(Foo[float, string]) is (float, string)
|
||||||
|
|
||||||
type Bar[N: static float, T] = object
|
type Bar[N: static float, T] = object
|
||||||
|
|
||||||
doAssert genericParams(Bar[1.0, string]) is (StaticParam[1.0], string)
|
doAssert genericParams(Bar[1.0, string]) is (StaticParam[1.0], string)
|
||||||
doAssert genericParams(Bar[1.0, string]).get(0).value == 1.0
|
doAssert genericParams(Bar[1.0, string]).get(0).value == 1.0
|
||||||
doAssert genericParams(seq[Bar[2.0, string]]).get(0) is Bar[2.0, string]
|
doAssert genericParams(seq[Bar[2.0, string]]).get(0) is Bar[2.0, string]
|
||||||
var s: seq[Bar[3.0, string]]
|
var s: seq[Bar[3.0, string]]
|
||||||
doAssert genericParams(typeof(s)) is (Bar[3.0, string],)
|
doAssert genericParams(typeof(s)) is (Bar[3.0, string],)
|
||||||
|
|
||||||
# NOTE: For the builtin array type, the index generic param will
|
|
||||||
# **always** become a range type after it's bound to a variable.
|
|
||||||
doAssert genericParams(array[10, int]) is (StaticParam[10], int)
|
doAssert genericParams(array[10, int]) is (StaticParam[10], int)
|
||||||
var a: array[10, int]
|
var a: array[10, int]
|
||||||
doAssert genericParams(typeof(a)) is (range[0..9], int)
|
doAssert genericParams(typeof(a)) is (range[0..9], int)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue