Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq 2012-09-26 02:22:39 +02:00
commit 5538727945
13 changed files with 118 additions and 81 deletions

View file

@ -344,6 +344,12 @@ type
tfFromGeneric, # type is an instantiation of a generic; this is needed tfFromGeneric, # type is an instantiation of a generic; this is needed
# because for instantiations of objects, structural # because for instantiations of objects, structural
# type equality has to be used # type equality has to be used
tfInstantiated # XXX: used to mark generic params after instantiation.
# if the concrete type happens to be an implicit generic
# this can lead to invalid proc signatures in the second
# pass of semProcTypeNode performed after instantiation.
# this won't be needed if we don't perform this redundant
# second pass (stay tuned).
tfAll, # type class requires all constraints to be met (default) tfAll, # type class requires all constraints to be met (default)
tfAny, # type class requires any constraint to be met tfAny, # type class requires any constraint to be met
tfCapturesEnv, # whether proc really captures some environment tfCapturesEnv, # whether proc really captures some environment

View file

@ -163,6 +163,7 @@ proc genConstStmt(p: BProc, t: PNode) =
if it.kind == nkCommentStmt: continue if it.kind == nkCommentStmt: continue
if it.kind != nkConstDef: InternalError(t.info, "genConstStmt") if it.kind != nkConstDef: InternalError(t.info, "genConstStmt")
var c = it.sons[0].sym var c = it.sons[0].sym
if c.typ.containsCompileTimeOnly: continue
if sfFakeConst in c.flags: if sfFakeConst in c.flags:
genSingleVar(p, it) genSingleVar(p, it)
elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and

View file

@ -140,6 +140,14 @@ proc mangleName(s: PSym): PRope =
proc isCompileTimeOnly(t: PType): bool = proc isCompileTimeOnly(t: PType): bool =
result = t.kind in {tyTypedesc, tyExpr} result = t.kind in {tyTypedesc, tyExpr}
proc containsCompileTimeOnly(t: PType): bool =
if isCompileTimeOnly(t): return true
if t.sons != nil:
for i in 0 .. <t.sonsLen:
if t.sons[i] != nil and isCompileTimeOnly(t.sons[i]):
return true
return false
var anonTypeName = toRope"TY" var anonTypeName = toRope"TY"
proc typeName(typ: PType): PRope = proc typeName(typ: PType): PRope =

View file

@ -869,7 +869,7 @@ proc evalTypeTrait*(n: PNode, context: PSym): PNode =
let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc}) let typ = n.sons[1].sym.typ.skipTypes({tyTypeDesc})
case n.sons[0].sym.name.s.normalize case n.sons[0].sym.name.s.normalize
of "name": of "name":
result = newStrNode(nkStrLit, typ.typeToString(preferExported)) result = newStrNode(nkStrLit, typ.typeToString(preferName))
result.typ = newType(tyString, context) result.typ = newType(tyString, context)
result.info = n.info result.info = n.info
else: else:
@ -965,7 +965,9 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mParseExprToAst: result = evalParseExpr(c, n) of mParseExprToAst: result = evalParseExpr(c, n)
of mParseStmtToAst: result = evalParseStmt(c, n) of mParseStmtToAst: result = evalParseStmt(c, n)
of mExpandToAst: result = evalExpandToAst(c, n) of mExpandToAst: result = evalExpandToAst(c, n)
of mTypeTrait: result = evalTypeTrait(n, c.module) of mTypeTrait:
n.sons[1] = evalAux(c, n.sons[1], {})
result = evalTypeTrait(n, c.module)
of mSlurp: result = evalSlurp(evalAux(c, n.sons[1], {}), c.module) of mSlurp: result = evalSlurp(evalAux(c, n.sons[1], {}), c.module)
of mStaticExec: of mStaticExec:
let cmd = evalAux(c, n.sons[1], {}) let cmd = evalAux(c, n.sons[1], {})

View file

@ -28,7 +28,8 @@ proc equalGenericParams(procA, procB: PNode): bool =
return return
a = procA.sons[i].sym a = procA.sons[i].sym
b = procB.sons[i].sym b = procB.sons[i].sym
if (a.name.id != b.name.id) or not sameTypeOrNil(a.typ, b.typ): return if (a.name.id != b.name.id) or
not sameTypeOrNil(a.typ, b.typ, {TypeDescExactMatch}): return
if (a.ast != nil) and (b.ast != nil): if (a.ast != nil) and (b.ast != nil):
if not ExprStructuralEquivalent(a.ast, b.ast): return if not ExprStructuralEquivalent(a.ast, b.ast): return
result = true result = true

View file

@ -19,7 +19,8 @@ proc restoreOldStyleType(n: PNode) =
# #
# This is strictly for backward compatibility until # This is strictly for backward compatibility until
# the transition to types as first-class values is complete. # the transition to types as first-class values is complete.
n.typ = n.typ.skipTypes({tyTypeDesc}) if n.typ.kind == tyTypeDesc and n.typ.sonsLen == 1:
n.typ = n.typ.sons[0]
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
markUsed(n, s) markUsed(n, s)
@ -376,6 +377,8 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
addSon(result, semExprWithType(c, x)) addSon(result, semExprWithType(c, x))
var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal}) var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
# turn any concrete typedesc into the absract typedesc type
if typ.kind == tyTypeDesc: typ.sons = nil
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
x = n.sons[i] x = n.sons[i]
if x.kind == nkExprColonExpr and sonsLen(x) == 2: if x.kind == nkExprColonExpr and sonsLen(x) == 2:

View file

@ -33,6 +33,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
#t = instGenericContainer(c, a, t) #t = instGenericContainer(c, a, t)
t = generateTypeInstance(c, pt, a, t) t = generateTypeInstance(c, pt, a, t)
#t = ReplaceTypeVarsT(cl, t) #t = ReplaceTypeVarsT(cl, t)
t.flags.incl tfInstantiated
s.typ = t s.typ = t
addDecl(c, s) addDecl(c, s)
entry.concreteTypes[i] = t entry.concreteTypes[i] = t
@ -41,7 +42,8 @@ proc sameInstantiation(a, b: TInstantiatedSymbol): bool =
if a.genericSym.id == b.genericSym.id and if a.genericSym.id == b.genericSym.id and
a.concreteTypes.len == b.concreteTypes.len: a.concreteTypes.len == b.concreteTypes.len:
for i in 0 .. < a.concreteTypes.len: for i in 0 .. < a.concreteTypes.len:
if not sameType(a.concreteTypes[i], b.concreteTypes[i]): return if not compareTypes(a.concreteTypes[i], b.concreteTypes[i],
flags = {TypeDescExactMatch}): return
result = true result = true
proc GenericCacheGet(c: PContext, entry: var TInstantiatedSymbol): PSym = proc GenericCacheGet(c: PContext, entry: var TInstantiatedSymbol): PSym =
@ -122,33 +124,6 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
s.ast.sons[genericParamsPos].kind == nkEmpty: s.ast.sons[genericParamsPos].kind == nkEmpty:
c.threadEntries.add(s) c.threadEntries.add(s)
proc applyConcreteTypesToSig(genericProc: PSym, concTypes: seq[PType]): PType =
# XXX: This is intended to replace the use of semParamList in generateInstance.
# The results of semParamList's analysis are already encoded in the original
# proc type and any concrete types may be aplied directly over it.
# Besides being more efficient, it will remove the awkward case of
# genericParams == nil in semParamList.
# Currenly, it fails in some cases such as:
# proc inc2*[T](x: var ordinal[T], y = 1) {.magic: "Inc", noSideEffect.}
let sig = genericProc.typ
result = copyType(sig, getCurrOwner(), false)
result.n = sig.n.shallowCopy
for i in countup(0, sig.len - 1):
let tOrig = sig.sons[i]
if tOrig == nil: continue
let oGenParams = genericProc.ast.sons[genericParamsPos]
if skipTypes(tOrig, skipPtrs).kind in {tyGenericParam}:
var tConcrete = concTypes[tOrig.sym.position]
if i > 0:
let param = sig.n.sons[i].sym.copySym
param.typ = tConcrete
result.n.sons[i] = newSymNode(param)
result.sons[i] = tConcrete
else:
result.sons[i] = tOrig
if i > 0: result.n.sons[i] = sig.n.sons[i]
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym = info: TLineInfo): PSym =
# no need to instantiate generic templates/macros: # no need to instantiate generic templates/macros:
@ -182,12 +157,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
n.sons[genericParamsPos] = ast.emptyNode n.sons[genericParamsPos] = ast.emptyNode
# semantic checking for the parameters: # semantic checking for the parameters:
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
if false and nimdbg: removeDefaultParamValues(n.sons[ParamsPos])
result.typ = applyConcreteTypesToSig(fn, entry.concreteTypes) semParamList(c, n.sons[ParamsPos], nil, result)
addParams(c, result.typ.n, fn.kind)
else:
removeDefaultParamValues(n.sons[ParamsPos])
semParamList(c, n.sons[ParamsPos], nil, result)
else: else:
result.typ = newTypeS(tyProc, c) result.typ = newTypeS(tyProc, c)
rawAddSon(result.typ, nil) rawAddSon(result.typ, nil)

View file

@ -34,10 +34,14 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
proc semTypeTraits(c: PContext, n: PNode): PNode = proc semTypeTraits(c: PContext, n: PNode): PNode =
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
internalAssert n.sons[1].kind == nkSym internalAssert n.sons[1].kind == nkSym
if n.sons[1].sym.kind == skType: let typArg = n.sons[1].sym
if typArg.kind == skType or
(typArg.kind == skParam and typArg.typ.sonsLen > 0):
# This is either a type known to sem or a typedesc
# param to a regular proc (again, known at instantiation)
result = evalTypeTrait(n, GetCurrOwner()) result = evalTypeTrait(n, GetCurrOwner())
else: else:
# pass unmodified to evals # a typedesc variable, pass unmodified to evals
result = n result = n
proc semOrd(c: PContext, n: PNode): PNode = proc semOrd(c: PContext, n: PNode): PNode =

View file

@ -552,7 +552,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
incl(result.flags, tfFinal) incl(result.flags, tfFinal)
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
if kind == skMacro: if kind == skMacro and param.typ.kind != tyTypeDesc:
# within a macro, every param has the type PNimrodNode! # within a macro, every param has the type PNimrodNode!
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}: # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
let nn = getSysSym"PNimrodNode" let nn = getSysSym"PNimrodNode"
@ -579,7 +579,8 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
result.typ = newTypeS(tyExpr, c) result.typ = newTypeS(tyExpr, c)
result.typ.sons = paramType.sons result.typ.sons = paramType.sons
of tyTypeDesc: of tyTypeDesc:
if procKind notin {skTemplate, skMacro}: if procKind notin {skTemplate, skMacro} and
tfInstantiated notin paramType.flags:
result.typ = newTypeS(tyTypeDesc, c) result.typ = newTypeS(tyTypeDesc, c)
result.typ.sons = paramType.sons result.typ.sons = paramType.sons
of tyDistinct: of tyDistinct:
@ -777,19 +778,12 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
else: else:
result = instGenericContainer(c, n, result) result = instGenericContainer(c, n, result)
proc semTypeFromMacro(c: PContext, n: PNode): PType = proc semTypeExpr(c: PContext, n: PNode): PType =
# Expands a macro or template until a type is returned var n = semExprWithType(c, n)
# results in an error type if the macro expands to something different if n.kind == nkSym and n.sym.kind == skType:
var sym = expectMacroOrTemplateCall(c, n) result = n.sym.typ
markUsed(n, sym)
case sym.kind
of skMacro:
result = semTypeNode(c, semMacroExpr(c, n, n, sym), nil)
of skTemplate:
result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
else: else:
LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree) LocalError(n.info, errTypeExpected, n.renderTree)
result = errorType(c)
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
@ -823,7 +817,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result.addSonSkipIntLit(t2) result.addSonSkipIntLit(t2)
result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny) result.flags.incl(if op.id == ord(wAnd): tfAll else: tfAny)
else: else:
result = semTypeFromMacro(c, n) result = semTypeExpr(c, n)
of nkCurlyExpr: of nkCurlyExpr:
result = semTypeNode(c, n.sons[0], nil) result = semTypeNode(c, n.sons[0], nil)
if result != nil: if result != nil:

View file

@ -271,7 +271,7 @@ proc matchTypeClass(c: var TCandidate, typeClass, t: PType): TTypeRelation =
of tyTypeClass: of tyTypeClass:
match = matchTypeClass(c, req, t) == isGeneric match = matchTypeClass(c, req, t) == isGeneric
else: nil else: nil
elif t.kind in {tyTypeDesc, tyObject}: elif t.kind in {tyObject}:
match = sameType(t, req) match = sameType(t, req)
if tfAny in typeClass.flags: if tfAny in typeClass.flags:
@ -659,7 +659,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
of isGeneric: of isGeneric:
inc(m.genericMatches) inc(m.genericMatches)
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}: if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}:
result = argOrig if f.kind == tyTypeDesc: result = arg
else: result = argOrig
else: else:
result = copyTree(arg) result = copyTree(arg)
result.typ = getInstantiatedType(c, arg, m, f) result.typ = getInstantiatedType(c, arg, m, f)

View file

@ -585,10 +585,17 @@ type
## or a == (distinct b) ## or a == (distinct b)
dcEqOrDistinctOf ## a equals b or a is distinct of b dcEqOrDistinctOf ## a equals b or a is distinct of b
TTypeCmpFlag* = enum
IgnoreTupleFields,
TypeDescExactMatch,
AllowCommonBase
TTypeCmpFlags* = set[TTypeCmpFlag]
TSameTypeClosure = object {.pure.} TSameTypeClosure = object {.pure.}
cmp: TDistinctCompare cmp: TDistinctCompare
ignoreTupleFields: bool
recCheck: int recCheck: int
flags: TTypeCmpFlags
s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
# (few elements expected) # (few elements expected)
@ -610,13 +617,14 @@ proc SameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
if a == nil or b == nil: result = false if a == nil or b == nil: result = false
else: result = SameTypeAux(a, b, c) else: result = SameTypeAux(a, b, c)
proc SameTypeOrNil*(a, b: PType): bool = proc SameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
if a == b: if a == b:
result = true result = true
else: else:
if a == nil or b == nil: result = false if a == nil or b == nil: result = false
else: else:
var c = initSameTypeClosure() var c = initSameTypeClosure()
c.flags = flags
result = SameTypeAux(a, b, c) result = SameTypeAux(a, b, c)
proc equalParam(a, b: PSym): TParamsEquality = proc equalParam(a, b: PSym): TParamsEquality =
@ -655,7 +663,7 @@ proc equalParams(a, b: PNode): TParamsEquality =
return paramsNotEqual # paramsIncompatible; return paramsNotEqual # paramsIncompatible;
# continue traversal! If not equal, we can return immediately; else # continue traversal! If not equal, we can return immediately; else
# it stays incompatible # it stays incompatible
if not SameTypeOrNil(a.sons[0].typ, b.sons[0].typ): if not SameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {TypeDescExactMatch}):
if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): if (a.sons[0].typ == nil) or (b.sons[0].typ == nil):
result = paramsNotEqual # one proc has a result, the other not is OK result = paramsNotEqual # one proc has a result, the other not is OK
else: else:
@ -683,13 +691,13 @@ proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
var x = a.sons[i] var x = a.sons[i]
var y = b.sons[i] var y = b.sons[i]
if c.ignoreTupleFields: if IgnoreTupleFields in c.flags:
x = skipTypes(x, {tyRange}) x = skipTypes(x, {tyRange})
y = skipTypes(y, {tyRange}) y = skipTypes(y, {tyRange})
result = SameTypeAux(x, y, c) result = SameTypeAux(x, y, c)
if not result: return if not result: return
if a.n != nil and b.n != nil and not c.ignoreTupleFields: if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
for i in countup(0, sonsLen(a.n) - 1): for i in countup(0, sonsLen(a.n) - 1):
# check field names: # check field names:
if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym: if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym:
@ -760,6 +768,13 @@ proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
if not SameObjectTree(a.n, b.n, c): return if not SameObjectTree(a.n, b.n, c): return
result = true result = true
proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
if sonsLen(a) != sonsLen(b): return false
result = true
for i in countup(0, sonsLen(a) - 1):
result = SameTypeOrNilAux(a.sons[i], b.sons[i], c)
if not result: return
proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
template CycleCheck() = template CycleCheck() =
# believe it or not, the direct check for ``containsOrIncl(c, a, b)`` # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
@ -808,18 +823,20 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
CycleCheck() CycleCheck()
result = sameTuple(a, b, c) result = sameTuple(a, b, c)
of tyGenericInst: result = sameTypeAux(lastSon(a), lastSon(b), c) of tyGenericInst: result = sameTypeAux(lastSon(a), lastSon(b), c)
of tyTypeDesc:
if TypeDescExactMatch in c.flags:
CycleCheck()
result = sameChildrenAux(x, y, c)
else:
result = true
of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence, of tyGenericParam, tyGenericInvokation, tyGenericBody, tySequence,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter, tyArray, tyProc, tyConst, tyMutable, tyVarargs, tyIter,
tyOrdinal, tyTypeDesc, tyTypeClass: tyOrdinal, tyTypeClass:
if sonsLen(a) == sonsLen(b): CycleCheck()
CycleCheck() result = sameChildrenAux(a, b, c)
result = true if result and (a.kind == tyProc):
for i in countup(0, sonsLen(a) - 1): result = a.callConv == b.callConv
result = SameTypeOrNilAux(a.sons[i], b.sons[i], c)
if not result: return
if result and (a.kind == tyProc):
result = a.callConv == b.callConv
of tyRange: of tyRange:
CycleCheck() CycleCheck()
result = SameTypeOrNilAux(a.sons[0], b.sons[0], c) and result = SameTypeOrNilAux(a.sons[0], b.sons[0], c) and
@ -827,19 +844,22 @@ proc SameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
SameValue(a.n.sons[1], b.n.sons[1]) SameValue(a.n.sons[1], b.n.sons[1])
of tyNone: result = false of tyNone: result = false
proc SameType*(x, y: PType): bool = proc sameType*(x, y: PType): bool =
var c = initSameTypeClosure() var c = initSameTypeClosure()
result = sameTypeAux(x, y, c) result = sameTypeAux(x, y, c)
proc sameBackendType*(x, y: PType): bool = proc sameBackendType*(x, y: PType): bool =
var c = initSameTypeClosure() var c = initSameTypeClosure()
c.ignoreTupleFields = true c.flags.incl IgnoreTupleFields
result = sameTypeAux(x, y, c) result = sameTypeAux(x, y, c)
proc compareTypes*(x, y: PType, cmp: TDistinctCompare): bool = proc compareTypes*(x, y: PType,
cmp: TDistinctCompare = dcEq,
flags: TTypeCmpFlags = {}): bool =
## compares two type for equality (modulo type distinction) ## compares two type for equality (modulo type distinction)
var c = initSameTypeClosure() var c = initSameTypeClosure()
c.cmp = cmp c.cmp = cmp
c.flags = flags
result = sameTypeAux(x, y, c) result = sameTypeAux(x, y, c)
proc inheritanceDiff*(a, b: PType): int = proc inheritanceDiff*(a, b: PType): int =

View file

@ -1,10 +1,12 @@
import unittest import unittest, typetraits
type type
TFoo[T, U] = object TFoo[T, U] = object
x: T x: T
y: U y: U
proc getTypeName(t: typedesc): string = t.name
proc foo(T: typedesc[float], a: expr): string = proc foo(T: typedesc[float], a: expr): string =
result = "float " & $(a.len > 5) result = "float " & $(a.len > 5)
@ -21,6 +23,9 @@ template foo(T: typedesc[seq]): expr = "seq"
test "types can be used as proc params": test "types can be used as proc params":
# XXX: `check` needs to know that TFoo[int, float] is a type and # XXX: `check` needs to know that TFoo[int, float] is a type and
# cannot be assigned for a local variable for later inspection # cannot be assigned for a local variable for later inspection
check ((string.getTypeName == "string"))
check ((getTypeName(int) == "int"))
check ((foo(TFoo[int, float], 1000) == "TFoo 1000")) check ((foo(TFoo[int, float], 1000) == "TFoo 1000"))
var f = 10.0 var f = 10.0

View file

@ -1,6 +1,6 @@
discard """ discard """
msg: "int\nstring\nTBar[int]" msg: "int\nstring\nTBar[int]"
output: "int\nstring\nTBar[int]\nint\nrange 0..2" output: "int\nstring\nTBar[int]\nint\nrange 0..2\nstring"
""" """
import typetraits import typetraits
@ -36,3 +36,24 @@ proc foo3[R, T](x: array[R, T]) =
echo name(R) echo name(R)
foo3 arr foo3 arr
const TypeList = [int, string, seq[int]]
macro selectType(inType: typedesc): typedesc =
var typeSeq = @[float, TBar[int]]
for t in TypeList:
typeSeq.add(t)
typeSeq.add(inType)
typeSeq.add(type(10))
var typeSeq2: seq[typedesc] = @[]
typeSeq2 = typeSeq
result = typeSeq2[5]
var xvar: selectType(string)
xvar = "proba"
echo xvar.type.name