This commit is contained in:
parent
fcd2f305ad
commit
4cd86c0842
4 changed files with 60 additions and 4 deletions
|
|
@ -47,6 +47,10 @@
|
||||||
- Added `sugar.capture` for capturing some local loop variables when creating a closure.
|
- Added `sugar.capture` for capturing some local loop variables when creating a closure.
|
||||||
This is an enhanced version of `closureScope`.
|
This is an enhanced version of `closureScope`.
|
||||||
|
|
||||||
|
- Added `typetraits.lenTuple` to get number of elements of a tuple/type tuple,
|
||||||
|
and `typetraits.get` to get the ith element of a type tuple.
|
||||||
|
- Added `typetraits.genericParams` to return a tuple of generic params from a generic instantiation
|
||||||
|
|
||||||
## Library changes
|
## Library changes
|
||||||
|
|
||||||
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
|
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
export system.`$` # for backward compatibility
|
export system.`$` # for backward compatibility
|
||||||
|
|
||||||
|
include "system/inclrtl"
|
||||||
|
|
||||||
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.
|
||||||
|
|
@ -70,6 +71,45 @@ proc distinctBase*(T: typedesc): typedesc {.magic: "TypeTrait".}
|
||||||
## Returns base type for distinct types, works only for distinct types.
|
## Returns base type for distinct types, works only for distinct types.
|
||||||
## compile time error otherwise
|
## compile time error otherwise
|
||||||
|
|
||||||
|
import std/macros
|
||||||
|
|
||||||
|
macro lenTuple*(t: tuple): int {.since: (1, 1).} =
|
||||||
|
## Return number of elements of `t`
|
||||||
|
newLit t.len
|
||||||
|
|
||||||
|
macro lenTuple*(t: typedesc[tuple]): int {.since: (1, 1).} =
|
||||||
|
## Return number of elements of `T`
|
||||||
|
newLit t.len
|
||||||
|
|
||||||
|
when (NimMajor, NimMinor) >= (1, 1):
|
||||||
|
template get*(T: typedesc[tuple], i: static int): untyped =
|
||||||
|
## Return `i`th element of `T`
|
||||||
|
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
|
||||||
|
type(default(T)[i])
|
||||||
|
|
||||||
|
macro genericParams*(T: typedesc): untyped {.since: (1, 1).} =
|
||||||
|
## return tuple of generic params for generic `T`
|
||||||
|
runnableExamples:
|
||||||
|
type Foo[T1, T2]=object
|
||||||
|
doAssert genericParams(Foo[float, string]) is (float, string)
|
||||||
|
result = newNimNode(nnkTupleConstr)
|
||||||
|
var impl = getTypeImpl(T)
|
||||||
|
expectKind(impl, nnkBracketExpr)
|
||||||
|
impl = impl[1]
|
||||||
|
while true:
|
||||||
|
case impl.kind
|
||||||
|
of nnkSym:
|
||||||
|
impl = impl.getImpl
|
||||||
|
continue
|
||||||
|
of nnkTypeDef:
|
||||||
|
impl = impl[2]
|
||||||
|
continue
|
||||||
|
of nnkBracketExpr:
|
||||||
|
for i in 1..<impl.len:
|
||||||
|
result.add impl[i]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
error "wrong kind: " & $impl.kind
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
static:
|
static:
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,7 @@ else:
|
||||||
{.pragma: benign, gcsafe.}
|
{.pragma: benign, gcsafe.}
|
||||||
|
|
||||||
template since(version, body: untyped) {.dirty.} =
|
template since(version, body: untyped) {.dirty.} =
|
||||||
|
## limitation: can't be used to annotate a template (eg typetraits.get), would
|
||||||
|
## error: cannot attach a custom pragma.
|
||||||
when version <= (NimMajor, NimMinor):
|
when version <= (NimMajor, NimMinor):
|
||||||
body
|
body
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,6 @@ block: # typeToString
|
||||||
doAssert (tuple[a: C2b[MyInt, C4[cstring]], b: cint, c: float]).name3 ==
|
doAssert (tuple[a: C2b[MyInt, C4[cstring]], b: cint, c: float]).name3 ==
|
||||||
"tuple[a: C2b{C}[MyInt{int}, C4[cstring]], b: cint{int32}, c: float]"
|
"tuple[a: C2b{C}[MyInt{int}, C4[cstring]], b: cint{int32}, c: float]"
|
||||||
|
|
||||||
|
|
||||||
#----------------------------------------------------
|
|
||||||
|
|
||||||
block distinctBase:
|
block distinctBase:
|
||||||
block:
|
block:
|
||||||
type
|
type
|
||||||
|
|
@ -90,4 +87,17 @@ block distinctBase:
|
||||||
doAssert($distinctBase(typeof(b2)) == "string")
|
doAssert($distinctBase(typeof(b2)) == "string")
|
||||||
doAssert($distinctBase(typeof(c2)) == "int")
|
doAssert($distinctBase(typeof(c2)) == "int")
|
||||||
|
|
||||||
|
block genericParams:
|
||||||
|
type Foo[T1, T2]=object
|
||||||
|
doAssert genericParams(Foo[float, string]) is (float, string)
|
||||||
|
type Foo1 = Foo[float, int]
|
||||||
|
doAssert genericParams(Foo1) is (float, int)
|
||||||
|
type Foo2 = Foo[float, Foo1]
|
||||||
|
doAssert genericParams(Foo2) is (float, Foo[float, int])
|
||||||
|
doAssert genericParams(Foo2) is (float, Foo1)
|
||||||
|
doAssert genericParams(Foo2).get(1) is Foo1
|
||||||
|
doAssert (int,).get(0) is int
|
||||||
|
doAssert (int, float).get(1) is float
|
||||||
|
static: doAssert (int, float).lenTuple == 2
|
||||||
|
static: doAssert (1, ).lenTuple == 1
|
||||||
|
static: doAssert ().lenTuple == 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue