fix incorrect lenTuple implementation (#13423)

This commit is contained in:
Timothee Cour
2020-02-19 02:07:18 -08:00
committed by GitHub
parent d1f9f11245
commit 273a93581f
3 changed files with 48 additions and 11 deletions

View File

@@ -187,6 +187,10 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
var operand = operand.skipTypes({tyGenericInst})
let cond = operand.kind == tyTuple and operand.n != nil
result = newIntNodeT(toInt128(ord(cond)), traitCall, c.graph)
of "lenTuple":
var operand = operand.skipTypes({tyGenericInst})
assert operand.kind == tyTuple, $operand.kind
result = newIntNodeT(toInt128(operand.len), traitCall, c.graph)
of "distinctBase":
var arg = operand.skipTypes({tyGenericInst})
if arg.kind == tyDistinct:

View File

@@ -71,15 +71,14 @@ 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).} =
proc lenTuple*(T: typedesc[tuple]): int {.magic: "TypeTrait", since: (1, 1).}
## Return number of elements of `T`
newLit t.len
since (1, 1):
template lenTuple*(t: tuple): int =
## Return number of elements of `t`
lenTuple(type(t))
since (1, 1):
template get*(T: typedesc[tuple], i: static int): untyped =
@@ -87,6 +86,8 @@ since (1, 1):
# Note: `[]` currently gives: `Error: no generic parameters allowed for ...`
type(default(T)[i])
import std/macros
macro genericParams*(T: typedesc): untyped {.since: (1, 1).} =
## return tuple of generic params for generic `T`
runnableExamples:

View File

@@ -92,7 +92,43 @@ block distinctBase:
doAssert($distinctBase(typeof(b2)) == "string")
doAssert($distinctBase(typeof(c2)) == "int")
block: # lenTuple
doAssert not compiles(lenTuple(int))
type
MyTupleType = (int,float,string)
static: doAssert MyTupleType.lenTuple == 3
type
MyGenericTuple[T] = (T,int,float)
MyGenericAlias = MyGenericTuple[string]
static: doAssert MyGenericAlias.lenTuple == 3
type
MyGenericTuple2[T,U] = (T,U,string)
MyGenericTuple2Alias[T] = MyGenericTuple2[T,int]
MyGenericTuple2Alias2 = MyGenericTuple2Alias[float]
static: doAssert MyGenericTuple2Alias2.lenTuple == 3
static: doAssert (int, float).lenTuple == 2
static: doAssert (1, ).lenTuple == 1
static: doAssert ().lenTuple == 0
let x = (1,2,)
doAssert x.lenTuple == 2
doAssert ().lenTuple == 0
doAssert (1,).lenTuple == 1
doAssert (int,).lenTuple == 1
doAssert type(x).lenTuple == 2
doAssert type(x).default.lenTuple == 2
type T1 = (int,float)
type T2 = T1
doAssert T2.lenTuple == 2
block genericParams:
type Foo[T1, T2]=object
doAssert genericParams(Foo[float, string]) is (float, string)
type Foo1 = Foo[float, int]
@@ -103,10 +139,6 @@ block genericParams:
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
##############################################
# bug 13095