diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2020-03-02 09:05:14 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-02 18:05:14 +0100 |
commit | 451b724c40bc04e4a9c756b2fcd457cca3fd437c (patch) | |
tree | ed27564c45f3e2e727e925216cd14dbfa86e169a | |
parent | 27241fda23905280c8b8a13d94efb46a7ebe9836 (diff) | |
download | Nim-451b724c40bc04e4a9c756b2fcd457cca3fd437c.tar.gz |
make genericParams support static[T] generic params (#13433)
* make genericParams support static[T] generic params * WrapStatic => StaticParam
-rw-r--r-- | lib/pure/typetraits.nim | 34 | ||||
-rw-r--r-- | tests/metatype/ttypetraits.nim | 45 |
2 files changed, 72 insertions, 7 deletions
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 04231db09..0335d5488 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -86,13 +86,13 @@ since (1, 1): # Note: `[]` currently gives: `Error: no generic parameters allowed for ...` type(default(T)[i]) + type StaticParam*[value] = object + ## used to wrap a static value in `genericParams` + import std/macros -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) +macro genericParamsImpl(T: typedesc): untyped = + # auxiliary macro needed, can't do it directly in `genericParams` result = newNimNode(nnkTupleConstr) var impl = getTypeImpl(T) expectKind(impl, nnkBracketExpr) @@ -107,11 +107,33 @@ macro genericParams*(T: typedesc): untyped {.since: (1, 1).} = continue of nnkBracketExpr: for i in 1..<impl.len: - result.add impl[i] + let ai = impl[i] + var ret: NimNode + case ai.typeKind + of ntyStatic: + ret = newTree(nnkBracketExpr, @[bindSym"StaticParam", ai]) + of ntyTypeDesc: + ret = ai + else: + assert false, $(ai.typeKind, ai.kind) + result.add ret break else: error "wrong kind: " & $impl.kind +since (1, 1): + template genericParams*(T: typedesc): untyped = + ## return tuple of generic params for generic `T` + runnableExamples: + type Foo[T1, T2]=object + doAssert genericParams(Foo[float, string]) is (float, string) + type Bar[N: static float, T] = object + doAssert genericParams(Bar[1.0, string]) is (StaticParam[1.0], string) + doAssert genericParams(Bar[1.0, string]).get(0).value == 1.0 + + type T2 = T + genericParamsImpl(T2) + when isMainModule: static: doAssert $type(42) == "int" diff --git a/tests/metatype/ttypetraits.nim b/tests/metatype/ttypetraits.nim index a6813ed00..7badf8317 100644 --- a/tests/metatype/ttypetraits.nim +++ b/tests/metatype/ttypetraits.nim @@ -128,7 +128,6 @@ block: # lenTuple doAssert T2.lenTuple == 2 block genericParams: - type Foo[T1, T2]=object doAssert genericParams(Foo[float, string]) is (float, string) type Foo1 = Foo[float, int] @@ -140,6 +139,50 @@ block genericParams: doAssert (int,).get(0) is int doAssert (int, float).get(1) is float + type Bar[N: static int, T] = object + type Bar3 = Bar[3, float] + doAssert genericParams(Bar3) is (StaticParam[3], float) + doAssert genericParams(Bar3).get(0) is StaticParam + doAssert genericParams(Bar3).get(0).value == 3 + doAssert genericParams(Bar[3, float]).get(0).value == 3 + + type + VectorElementType = SomeNumber | bool + Vec[N: static[int], T: VectorElementType] = object + arr: array[N, T] + Vec4[T: VectorElementType] = Vec[4,T] + Vec4f = Vec4[float32] + + MyTupleType = (int,float,string) + MyGenericTuple[T] = (T,int,float) + MyGenericAlias = MyGenericTuple[string] + MyGenericTuple2[T,U] = (T,U,string) + MyGenericTuple2Alias[T] = MyGenericTuple2[T,int] + MyGenericTuple2Alias2 = MyGenericTuple2Alias[float] + + doAssert genericParams(MyGenericAlias) is (string,) + doAssert genericHead(MyGenericAlias) is MyGenericTuple + doAssert genericParams(MyGenericTuple2Alias2) is (float,) + doAssert genericParams(MyGenericTuple2[float, int]) is (float, int) + doAssert genericParams(MyGenericAlias) is (string,) + doAssert genericParams(Vec4f) is (float32,) + doAssert genericParams(Vec[4, bool]) is (StaticParam[4], bool) + + block: + type Foo[T1, T2]=object + doAssert genericParams(Foo[float, string]) is (float, string) + type Bar[N: static float, T] = object + doAssert genericParams(Bar[1.0, string]) is (StaticParam[1.0], string) + type Bar2 = Bar[2.0, string] + doAssert genericParams(Bar2) is (StaticParam[2.0], string) + type Bar3 = Bar[1.0 + 2.0, string] + doAssert genericParams(Bar3) is (StaticParam[3.0], string) + + const F = 5.0 + type Bar4 = Bar[F, string] + doAssert genericParams(Bar4) is (StaticParam[5.0], string) + doAssert genericParams(Bar[F, string]) is (StaticParam[5.0], string) + ############################################## # bug 13095 |