make genericParams support static[T] generic params (#13433)
* make genericParams support static[T] generic params * WrapStatic => StaticParam
This commit is contained in:
parent
27241fda23
commit
451b724c40
2 changed files with 72 additions and 7 deletions
|
|
@ -86,13 +86,13 @@ since (1, 1):
|
||||||
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
|
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
|
||||||
type(default(T)[i])
|
type(default(T)[i])
|
||||||
|
|
||||||
|
type StaticParam*[value] = object
|
||||||
|
## used to wrap a static value in `genericParams`
|
||||||
|
|
||||||
import std/macros
|
import std/macros
|
||||||
|
|
||||||
macro genericParams*(T: typedesc): untyped {.since: (1, 1).} =
|
macro genericParamsImpl(T: typedesc): untyped =
|
||||||
## return tuple of generic params for generic `T`
|
# auxiliary macro needed, can't do it directly in `genericParams`
|
||||||
runnableExamples:
|
|
||||||
type Foo[T1, T2]=object
|
|
||||||
doAssert genericParams(Foo[float, string]) is (float, string)
|
|
||||||
result = newNimNode(nnkTupleConstr)
|
result = newNimNode(nnkTupleConstr)
|
||||||
var impl = getTypeImpl(T)
|
var impl = getTypeImpl(T)
|
||||||
expectKind(impl, nnkBracketExpr)
|
expectKind(impl, nnkBracketExpr)
|
||||||
|
|
@ -107,11 +107,33 @@ macro genericParams*(T: typedesc): untyped {.since: (1, 1).} =
|
||||||
continue
|
continue
|
||||||
of nnkBracketExpr:
|
of nnkBracketExpr:
|
||||||
for i in 1..<impl.len:
|
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
|
break
|
||||||
else:
|
else:
|
||||||
error "wrong kind: " & $impl.kind
|
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:
|
when isMainModule:
|
||||||
static:
|
static:
|
||||||
doAssert $type(42) == "int"
|
doAssert $type(42) == "int"
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,6 @@ block: # lenTuple
|
||||||
doAssert T2.lenTuple == 2
|
doAssert T2.lenTuple == 2
|
||||||
|
|
||||||
block genericParams:
|
block genericParams:
|
||||||
|
|
||||||
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 Foo1 = Foo[float, int]
|
type Foo1 = Foo[float, int]
|
||||||
|
|
@ -140,6 +139,50 @@ block genericParams:
|
||||||
doAssert (int,).get(0) is int
|
doAssert (int,).get(0) is int
|
||||||
doAssert (int, float).get(1) is float
|
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
|
# bug 13095
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue