commit
d3fe4a2db1
5 changed files with 306 additions and 38 deletions
|
|
@ -1185,19 +1185,35 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
of opcNGetType:
|
of opcNGetType:
|
||||||
let rb = instr.regB
|
let rb = instr.regB
|
||||||
let rc = instr.regC
|
let rc = instr.regC
|
||||||
if rc == 0:
|
case rc:
|
||||||
ensureKind(rkNode)
|
of 0:
|
||||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
# getType opcode:
|
||||||
regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc])
|
ensureKind(rkNode)
|
||||||
|
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||||
|
regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc])
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||||
|
of 1:
|
||||||
|
# typeKind opcode:
|
||||||
|
ensureKind(rkInt)
|
||||||
|
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||||
|
regs[ra].intVal = ord(regs[rb].node.typ.kind)
|
||||||
|
#else:
|
||||||
|
# stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||||
|
of 2:
|
||||||
|
# getTypeInst opcode:
|
||||||
|
ensureKind(rkNode)
|
||||||
|
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||||
|
regs[ra].node = opMapTypeInstToAst(regs[rb].node.typ, c.debug[pc])
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||||
else:
|
else:
|
||||||
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
# getTypeImpl opcode:
|
||||||
else:
|
ensureKind(rkNode)
|
||||||
# typeKind opcode:
|
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
||||||
ensureKind(rkInt)
|
regs[ra].node = opMapTypeImplToAst(regs[rb].node.typ, c.debug[pc])
|
||||||
if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
|
else:
|
||||||
regs[ra].intVal = ord(regs[rb].node.typ.kind)
|
stackTrace(c, tos, pc, errGenerated, "node has no type")
|
||||||
#else:
|
|
||||||
# stackTrace(c, tos, pc, errGenerated, "node has no type")
|
|
||||||
of opcNStrVal:
|
of opcNStrVal:
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
createStr regs[ra]
|
createStr regs[ra]
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,11 @@ proc atomicTypeX(name: string; t: PType; info: TLineInfo): PNode =
|
||||||
result = newSymNode(sym)
|
result = newSymNode(sym)
|
||||||
result.typ = t
|
result.typ = t
|
||||||
|
|
||||||
proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode
|
proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||||
|
inst=false; allowRecursionX=false): PNode
|
||||||
|
|
||||||
proc mapTypeToBracket(name: string; t: PType; info: TLineInfo): PNode =
|
proc mapTypeToBracketX(name: string; t: PType; info: TLineInfo;
|
||||||
|
inst=false): PNode =
|
||||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||||
result.add atomicTypeX(name, t, info)
|
result.add atomicTypeX(name, t, info)
|
||||||
for i in 0 .. < t.len:
|
for i in 0 .. < t.len:
|
||||||
|
|
@ -78,10 +80,39 @@ proc mapTypeToBracket(name: string; t: PType; info: TLineInfo): PNode =
|
||||||
void.typ = newType(tyEmpty, t.owner)
|
void.typ = newType(tyEmpty, t.owner)
|
||||||
result.add void
|
result.add void
|
||||||
else:
|
else:
|
||||||
result.add mapTypeToAst(t.sons[i], info)
|
result.add mapTypeToAstX(t.sons[i], info, inst)
|
||||||
|
|
||||||
proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
|
proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||||
|
inst=false; allowRecursionX=false): PNode =
|
||||||
|
var allowRecursion = allowRecursionX
|
||||||
template atomicType(name): expr = atomicTypeX(name, t, info)
|
template atomicType(name): expr = atomicTypeX(name, t, info)
|
||||||
|
template mapTypeToAst(t,info): expr = mapTypeToAstX(t, info, inst)
|
||||||
|
template mapTypeToAstR(t,info): expr = mapTypeToAstX(t, info, inst, true)
|
||||||
|
template mapTypeToAst(t,i,info): expr =
|
||||||
|
if i<t.len and t.sons[i]!=nil: mapTypeToAstX(t.sons[i], info, inst)
|
||||||
|
else: ast.emptyNode
|
||||||
|
template mapTypeToBracket(name,t,info): expr =
|
||||||
|
mapTypeToBracketX(name, t, info, inst)
|
||||||
|
template newNodeX(kind):expr =
|
||||||
|
newNodeIT(kind, if t.n.isNil: info else: t.n.info, t)
|
||||||
|
template newIdent(s):expr =
|
||||||
|
var r = newNodeX(nkIdent)
|
||||||
|
r.add !s
|
||||||
|
r
|
||||||
|
template newIdentDefs(n,t):expr =
|
||||||
|
var id = newNodeX(nkIdentDefs)
|
||||||
|
id.add n # name
|
||||||
|
id.add mapTypeToAst(t, info) # type
|
||||||
|
id.add ast.emptyNode # no assigned value
|
||||||
|
id
|
||||||
|
template newIdentDefs(s):expr = newIdentDefs(s, s.typ)
|
||||||
|
|
||||||
|
if inst:
|
||||||
|
if t.sym != nil: # if this node has a symbol
|
||||||
|
if allowRecursion: # getTypeImpl behavior: turn off recursion
|
||||||
|
allowRecursion = false
|
||||||
|
else: # getTypeInst behavior: return symbol
|
||||||
|
return atomicType(t.sym.name.s)
|
||||||
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyNone: result = atomicType("none")
|
of tyNone: result = atomicType("none")
|
||||||
|
|
@ -94,7 +125,14 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
|
||||||
of tyArrayConstr, tyArray:
|
of tyArrayConstr, tyArray:
|
||||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||||
result.add atomicType("array")
|
result.add atomicType("array")
|
||||||
result.add mapTypeToAst(t.sons[0], info)
|
if inst:
|
||||||
|
var rng = newNodeX(nkInfix)
|
||||||
|
rng.add newIdentNode(getIdent(".."), info)
|
||||||
|
rng.add t.sons[0].n.sons[0].copyTree
|
||||||
|
rng.add t.sons[0].n.sons[1].copyTree
|
||||||
|
result.add rng
|
||||||
|
else:
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
result.add mapTypeToAst(t.sons[1], info)
|
result.add mapTypeToAst(t.sons[1], info)
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if t.base != nil:
|
if t.base != nil:
|
||||||
|
|
@ -107,34 +145,95 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
|
||||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||||
for i in 0 .. < t.len:
|
for i in 0 .. < t.len:
|
||||||
result.add mapTypeToAst(t.sons[i], info)
|
result.add mapTypeToAst(t.sons[i], info)
|
||||||
of tyGenericInst, tyGenericBody, tyOrdinal, tyUserTypeClassInst:
|
of tyGenericInst:
|
||||||
|
if inst:
|
||||||
|
if allowRecursion:
|
||||||
|
result = mapTypeToAstR(t.lastSon, info)
|
||||||
|
else:
|
||||||
|
result = newNodeX(nkBracketExpr)
|
||||||
|
result.add mapTypeToAst(t.lastSon, info)
|
||||||
|
for i in 1 .. < t.len-1:
|
||||||
|
result.add mapTypeToAst(t.sons[i], info)
|
||||||
|
else:
|
||||||
|
result = mapTypeToAst(t.lastSon, info)
|
||||||
|
of tyGenericBody, tyOrdinal, tyUserTypeClassInst:
|
||||||
result = mapTypeToAst(t.lastSon, info)
|
result = mapTypeToAst(t.lastSon, info)
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if allowRecursion:
|
if inst:
|
||||||
result = mapTypeToBracket("distinct", t, info)
|
result = newNodeX(nkDistinctTy)
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
else:
|
else:
|
||||||
result = atomicType(t.sym.name.s)
|
if allowRecursion or t.sym==nil:
|
||||||
|
result = mapTypeToBracket("distinct", t, info)
|
||||||
|
else:
|
||||||
|
result = atomicType(t.sym.name.s)
|
||||||
of tyGenericParam, tyForward: result = atomicType(t.sym.name.s)
|
of tyGenericParam, tyForward: result = atomicType(t.sym.name.s)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if allowRecursion:
|
if inst:
|
||||||
result = newNodeIT(nkObjectTy, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeX(nkObjectTy)
|
||||||
if t.sons[0] == nil:
|
result.add ast.emptyNode # pragmas not reconstructed yet
|
||||||
result.add ast.emptyNode
|
if t.sons[0]==nil: result.add ast.emptyNode # handle parent object
|
||||||
else:
|
else:
|
||||||
result.add mapTypeToAst(t.sons[0], info)
|
var nn = newNodeX(nkOfInherit)
|
||||||
result.add copyTree(t.n)
|
nn.add mapTypeToAst(t.sons[0], info)
|
||||||
|
result.add nn
|
||||||
|
if t.n.sons.len>0:
|
||||||
|
var rl = copyNode(t.n) # handle nkRecList
|
||||||
|
for s in t.n.sons:
|
||||||
|
rl.add newIdentDefs(s)
|
||||||
|
result.add rl
|
||||||
|
else:
|
||||||
|
result.add ast.emptyNode
|
||||||
else:
|
else:
|
||||||
result = atomicType(t.sym.name.s)
|
if allowRecursion or t.sym == nil:
|
||||||
|
result = newNodeIT(nkObjectTy, if t.n.isNil: info else: t.n.info, t)
|
||||||
|
result.add ast.emptyNode
|
||||||
|
if t.sons[0] == nil:
|
||||||
|
result.add ast.emptyNode
|
||||||
|
else:
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
|
result.add copyTree(t.n)
|
||||||
|
else:
|
||||||
|
result = atomicType(t.sym.name.s)
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
result = newNodeIT(nkEnumTy, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeIT(nkEnumTy, if t.n.isNil: info else: t.n.info, t)
|
||||||
result.add copyTree(t.n)
|
result.add copyTree(t.n)
|
||||||
of tyTuple: result = mapTypeToBracket("tuple", t, info)
|
of tyTuple:
|
||||||
|
if inst:
|
||||||
|
result = newNodeX(nkTupleTy)
|
||||||
|
for s in t.n.sons:
|
||||||
|
result.add newIdentDefs(s)
|
||||||
|
else:
|
||||||
|
result = mapTypeToBracket("tuple", t, info)
|
||||||
of tySet: result = mapTypeToBracket("set", t, info)
|
of tySet: result = mapTypeToBracket("set", t, info)
|
||||||
of tyPtr: result = mapTypeToBracket("ptr", t, info)
|
of tyPtr:
|
||||||
of tyRef: result = mapTypeToBracket("ref", t, info)
|
if inst:
|
||||||
|
result = newNodeX(nkPtrTy)
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
|
else:
|
||||||
|
result = mapTypeToBracket("ptr", t, info)
|
||||||
|
of tyRef:
|
||||||
|
if inst:
|
||||||
|
result = newNodeX(nkRefTy)
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
|
else:
|
||||||
|
result = mapTypeToBracket("ref", t, info)
|
||||||
of tyVar: result = mapTypeToBracket("var", t, info)
|
of tyVar: result = mapTypeToBracket("var", t, info)
|
||||||
of tySequence: result = mapTypeToBracket("seq", t, info)
|
of tySequence: result = mapTypeToBracket("seq", t, info)
|
||||||
of tyProc: result = mapTypeToBracket("proc", t, info)
|
of tyProc:
|
||||||
|
if inst:
|
||||||
|
result = newNodeX(nkProcTy)
|
||||||
|
var fp = newNodeX(nkFormalParams)
|
||||||
|
if t.sons[0] == nil:
|
||||||
|
fp.add ast.emptyNode
|
||||||
|
else:
|
||||||
|
fp.add mapTypeToAst(t.sons[0], t.n[0].info)
|
||||||
|
for i in 1..<t.sons.len:
|
||||||
|
fp.add newIdentDefs(t.n[i], t.sons[i])
|
||||||
|
result.add fp
|
||||||
|
result.add ast.emptyNode # pragmas aren't reconstructed yet
|
||||||
|
else:
|
||||||
|
result = mapTypeToBracket("proc", t, info)
|
||||||
of tyOpenArray: result = mapTypeToBracket("openArray", t, info)
|
of tyOpenArray: result = mapTypeToBracket("openArray", t, info)
|
||||||
of tyRange:
|
of tyRange:
|
||||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||||
|
|
@ -174,10 +273,24 @@ proc mapTypeToAst(t: PType, info: TLineInfo; allowRecursion=false): PNode =
|
||||||
of tyNot: result = mapTypeToBracket("not", t, info)
|
of tyNot: result = mapTypeToBracket("not", t, info)
|
||||||
of tyAnything: result = atomicType"anything"
|
of tyAnything: result = atomicType"anything"
|
||||||
of tyStatic, tyFromExpr, tyFieldAccessor:
|
of tyStatic, tyFromExpr, tyFieldAccessor:
|
||||||
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
if inst:
|
||||||
result.add atomicType("static")
|
if t.n != nil: result = t.n.copyTree
|
||||||
if t.n != nil:
|
else: result = atomicType "void"
|
||||||
result.add t.n.copyTree
|
else:
|
||||||
|
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
|
||||||
|
result.add atomicType "static"
|
||||||
|
if t.n != nil:
|
||||||
|
result.add t.n.copyTree
|
||||||
|
|
||||||
proc opMapTypeToAst*(t: PType; info: TLineInfo): PNode =
|
proc opMapTypeToAst*(t: PType; info: TLineInfo): PNode =
|
||||||
result = mapTypeToAst(t, info, true)
|
result = mapTypeToAstX(t, info, false, true)
|
||||||
|
|
||||||
|
# the "Inst" version includes generic parameters in the resulting type tree
|
||||||
|
# and also tries to look like the corresponding Nim type declaration
|
||||||
|
proc opMapTypeInstToAst*(t: PType; info: TLineInfo): PNode =
|
||||||
|
result = mapTypeToAstX(t, info, true, false)
|
||||||
|
|
||||||
|
# the "Impl" version includes generic parameters in the resulting type tree
|
||||||
|
# and also tries to look like the corresponding Nim type implementation
|
||||||
|
proc opMapTypeImplToAst*(t: PType; info: TLineInfo): PNode =
|
||||||
|
result = mapTypeToAstX(t, info, true, true)
|
||||||
|
|
|
||||||
|
|
@ -983,7 +983,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||||
of mNGetType:
|
of mNGetType:
|
||||||
let tmp = c.genx(n.sons[1])
|
let tmp = c.genx(n.sons[1])
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opcNGetType, dest, tmp, if n[0].sym.name.s == "typeKind": 1 else: 0)
|
let rc = case n[0].sym.name.s:
|
||||||
|
of "getType": 0
|
||||||
|
of "typeKind": 1
|
||||||
|
of "getTypeInst": 2
|
||||||
|
else: 3 # "getTypeImpl"
|
||||||
|
c.gABC(n, opcNGetType, dest, tmp, rc)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
#genUnaryABC(c, n, dest, opcNGetType)
|
#genUnaryABC(c, n, dest, opcNGetType)
|
||||||
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,18 @@ proc typeKind*(n: NimNode): NimTypeKind {.magic: "NGetType", noSideEffect.}
|
||||||
## Returns the type kind of the node 'n' that should represent a type, that
|
## Returns the type kind of the node 'n' that should represent a type, that
|
||||||
## means the node should have been obtained via `getType`.
|
## means the node should have been obtained via `getType`.
|
||||||
|
|
||||||
|
proc getTypeInst*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
|
||||||
|
## Like getType except it includes generic parameters for a specific instance
|
||||||
|
|
||||||
|
proc getTypeInst*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.}
|
||||||
|
## Like getType except it includes generic parameters for a specific instance
|
||||||
|
|
||||||
|
proc getTypeImpl*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
|
||||||
|
## Like getType except it includes generic parameters for the implementation
|
||||||
|
|
||||||
|
proc getTypeImpl*(n: typedesc): NimNode {.magic: "NGetType", noSideEffect.}
|
||||||
|
## Like getType except it includes generic parameters for the implementation
|
||||||
|
|
||||||
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
|
proc strVal*(n: NimNode): string {.magic: "NStrVal", noSideEffect.}
|
||||||
|
|
||||||
proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
|
proc `intVal=`*(n: NimNode, val: BiggestInt) {.magic: "NSetIntVal", noSideEffect.}
|
||||||
|
|
|
||||||
122
tests/macros/tgettypeinst.nim
Normal file
122
tests/macros/tgettypeinst.nim
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
discard """
|
||||||
|
"""
|
||||||
|
|
||||||
|
import macros, strUtils
|
||||||
|
|
||||||
|
proc symToIdent(x: NimNode): NimNode =
|
||||||
|
case x.kind:
|
||||||
|
of nnkCharLit..nnkUInt64Lit:
|
||||||
|
result = newNimNode(x.kind)
|
||||||
|
result.intVal = x.intVal
|
||||||
|
of nnkFloatLit..nnkFloat64Lit:
|
||||||
|
result = newNimNode(x.kind)
|
||||||
|
result.floatVal = x.floatVal
|
||||||
|
of nnkStrLit..nnkTripleStrLit:
|
||||||
|
result = newNimNode(x.kind)
|
||||||
|
result.strVal = x.strVal
|
||||||
|
of nnkIdent, nnkSym:
|
||||||
|
result = newIdentNode($x)
|
||||||
|
else:
|
||||||
|
result = newNimNode(x.kind)
|
||||||
|
for c in x:
|
||||||
|
result.add symToIdent(c)
|
||||||
|
|
||||||
|
macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed =
|
||||||
|
let inst = x.getTypeInst
|
||||||
|
let impl = x.getTypeImpl
|
||||||
|
let inst0r = inst0.symToIdent.treeRepr
|
||||||
|
let instr = inst.symToIdent.treeRepr
|
||||||
|
#echo inst0r
|
||||||
|
#echo instr
|
||||||
|
doAssert(instr == inst0r)
|
||||||
|
var impl0 =
|
||||||
|
if implX.kind == nnkNilLit: inst0
|
||||||
|
else: implX[0][2]
|
||||||
|
let impl0r = impl0.symToIdent.treerepr
|
||||||
|
let implr = impl.symToIdent.treerepr
|
||||||
|
#echo impl0r
|
||||||
|
#echo implr
|
||||||
|
doAssert(implr == impl0r)
|
||||||
|
template echoString(s:string) = echo s.replace("\n","\n ")
|
||||||
|
result = newStmtList()
|
||||||
|
#result.add getAst(echoString(" " & inst0.repr))
|
||||||
|
#result.add getAst(echoString(" " & inst.repr))
|
||||||
|
#result.add getAst(echoString(" " & impl0.repr))
|
||||||
|
#result.add getAst(echoString(" " & impl.repr))
|
||||||
|
if recurse:
|
||||||
|
template testDecl(n, m :typed) =
|
||||||
|
testV(n, false):
|
||||||
|
type _ = m
|
||||||
|
result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
|
||||||
|
|
||||||
|
template testV(inst, recurse, impl) =
|
||||||
|
block:
|
||||||
|
#echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
|
||||||
|
var x: inst
|
||||||
|
testX(x, inst, recurse, impl)
|
||||||
|
template testT(inst, recurse) =
|
||||||
|
block:
|
||||||
|
type myType = inst
|
||||||
|
testV(myType, recurse):
|
||||||
|
type _ = inst
|
||||||
|
|
||||||
|
template test(inst) =
|
||||||
|
testT(inst, false)
|
||||||
|
testV(inst, true, nil)
|
||||||
|
template test(inst, impl) = testV(inst, true, impl)
|
||||||
|
|
||||||
|
type
|
||||||
|
Model = object of RootObj
|
||||||
|
User = object of Model
|
||||||
|
name : string
|
||||||
|
password : string
|
||||||
|
|
||||||
|
Tree = object of RootObj
|
||||||
|
value : int
|
||||||
|
left,right : ref Tree
|
||||||
|
|
||||||
|
MyEnum = enum
|
||||||
|
valueA, valueB, valueC
|
||||||
|
|
||||||
|
MySet = set[MyEnum]
|
||||||
|
MySeq = seq[int]
|
||||||
|
MyIntPtr = ptr int
|
||||||
|
MyIntRef = ref int
|
||||||
|
|
||||||
|
GenericObject[T] = object
|
||||||
|
value:T
|
||||||
|
Foo[N:static[int],T] = object
|
||||||
|
Bar[N:static[int],T] = object
|
||||||
|
#baz:Foo[N+1,GenericObject[T]]
|
||||||
|
baz:Foo[N,GenericObject[T]]
|
||||||
|
|
||||||
|
test(bool)
|
||||||
|
test(char)
|
||||||
|
test(int)
|
||||||
|
test(float)
|
||||||
|
test(ptr int)
|
||||||
|
test(ref int)
|
||||||
|
test(array[1..10,Bar[2,Foo[3,float]]])
|
||||||
|
test(distinct Bar[2,Foo[3,float]])
|
||||||
|
test(tuple[a:int,b:Foo[-1,float]])
|
||||||
|
#test(MyEnum):
|
||||||
|
# type _ = enum
|
||||||
|
# valueA, valueB, valueC
|
||||||
|
test(set[MyEnum])
|
||||||
|
test(seq[int])
|
||||||
|
test(Bar[2,Foo[3,float]]):
|
||||||
|
type _ = object
|
||||||
|
baz: Foo[2, GenericObject[Foo[3, float]]]
|
||||||
|
test(Model):
|
||||||
|
type _ = object of RootObj
|
||||||
|
test(User):
|
||||||
|
type _ = object of Model
|
||||||
|
name: string
|
||||||
|
password: string
|
||||||
|
test(Tree):
|
||||||
|
type _ = object of RootObj
|
||||||
|
value: int
|
||||||
|
left: ref Tree
|
||||||
|
right: ref Tree
|
||||||
|
test(proc (a: int, b: Foo[2,float]))
|
||||||
|
test(proc (a: int, b: Foo[2,float]): Bar[3,int])
|
||||||
Loading…
Add table
Add a link
Reference in a new issue