Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
15 changes: 8 additions & 7 deletions lib/pure/typetraits.nim
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,23 @@ 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 =
## Return `i`th element of `T`
# 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:
Expand Down
40 changes: 36 additions & 4 deletions tests/metatype/ttypetraits.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down