From 4cd86c08427205d2e26510a07a3c6980c14e1608 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Thu, 9 Jan 2020 23:51:37 -0800 Subject: [PATCH] typetraits: fixes #6454; genericParams; added lenTuple; added tuple type get (#13064) --- changelog.md | 4 ++++ lib/pure/typetraits.nim | 40 ++++++++++++++++++++++++++++++++++ lib/system/inclrtl.nim | 2 ++ tests/metatype/ttypetraits.nim | 18 +++++++++++---- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index aeb6987c47a31..17eedb3a104d9 100644 --- a/changelog.md +++ b/changelog.md @@ -47,6 +47,10 @@ - Added `sugar.capture` for capturing some local loop variables when creating a closure. 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 - `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations` diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 7a493cb6cbd75..26cbce4d127ba 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -14,6 +14,7 @@ export system.`$` # for backward compatibility +include "system/inclrtl" proc name*(t: typedesc): string {.magic: "TypeTrait".} ## 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. ## 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..