fixed macros.getTypeImpl for a symbol of type tyGenericBody (#5788) (#5812)

* fixed macros.getTypeImpl for a symbol of type tyGenericBody
* added test case and commented test code
This commit is contained in:
jcosborn 2017-05-14 08:08:41 -05:00 • committed by Andreas Rumpf
commit ec50dab57d
3 changed files with 57 additions and 21 deletions

View file

@ -175,7 +175,12 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
result.add mapTypeToAst(t.sons[i], info) result.add mapTypeToAst(t.sons[i], info)
else: else:
result = mapTypeToAstX(t.lastSon, info, inst, allowRecursion) result = mapTypeToAstX(t.lastSon, info, inst, allowRecursion)
of tyGenericBody, tyOrdinal: of tyGenericBody:
if inst:
result = mapTypeToAstX(t.lastSon, info, inst, true)
else:
result = mapTypeToAst(t.lastSon, info)
of tyOrdinal:
result = mapTypeToAst(t.lastSon, info) result = mapTypeToAst(t.lastSon, info)
of tyDistinct: of tyDistinct:
if inst: if inst:

View file

@ -21,49 +21,67 @@ proc symToIdent(x: NimNode): NimNode =
for c in x: for c in x:
result.add symToIdent(c) result.add symToIdent(c)
# check getTypeInst and getTypeImpl for given symbol x
macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed = macro testX(x,inst0: typed; recurse: static[bool]; implX: stmt): typed =
# check that getTypeInst(x) equals inst0
let inst = x.getTypeInst let inst = x.getTypeInst
let impl = x.getTypeImpl
let inst0r = inst0.symToIdent.treeRepr
let instr = inst.symToIdent.treeRepr let instr = inst.symToIdent.treeRepr
#echo inst0r let inst0r = inst0.symToIdent.treeRepr
#echo instr #echo instr
#echo inst0r
doAssert(instr == inst0r) doAssert(instr == inst0r)
# check that getTypeImpl(x) is correct
# if implX is nil then compare to inst0
# else we expect implX to be a type definition
# and we extract the implementation from that
let impl = x.getTypeImpl
var impl0 = var impl0 =
if implX.kind == nnkNilLit: inst0 if implX.kind == nnkNilLit: inst0
else: implX[0][2] else: implX[0][2]
let impl0r = impl0.symToIdent.treerepr
let implr = impl.symToIdent.treerepr let implr = impl.symToIdent.treerepr
#echo impl0r let impl0r = impl0.symToIdent.treerepr
#echo implr #echo implr
#echo impl0r
doAssert(implr == impl0r) doAssert(implr == impl0r)
template echoString(s:string) = echo s.replace("\n","\n ")
result = newStmtList() result = newStmtList()
#template echoString(s: string) = echo s.replace("\n","\n ")
#result.add getAst(echoString(" " & inst0.repr)) #result.add getAst(echoString(" " & inst0.repr))
#result.add getAst(echoString(" " & inst.repr)) #result.add getAst(echoString(" " & inst.repr))
#result.add getAst(echoString(" " & impl0.repr)) #result.add getAst(echoString(" " & impl0.repr))
#result.add getAst(echoString(" " & impl.repr)) #result.add getAst(echoString(" " & impl.repr))
if recurse: if recurse:
template testDecl(n, m :typed) = # now test using a newly formed variable of type getTypeInst(x)
template testDecl(n,m: typed) =
testV(n, false): testV(n, false):
type _ = m type _ = m
result.add getAst(testDecl(inst.symToIdent, impl.symToIdent)) result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
# test with a variable (instance) of type
template testV(inst, recurse, impl) = template testV(inst, recurse, impl) =
block: block:
#echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl) #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
var x: inst var x: inst
testX(x, inst, recurse, impl) testX(x, inst, recurse, impl)
template testT(inst, recurse) =
block:
type myType = inst
testV(myType, recurse):
type _ = inst
# test with a newly created typedesc (myType)
# using the passed type as the implementation
template testT(impl, recurse) =
block:
type myType = impl
testV(myType, recurse):
type _ = impl
# test a built-in type whose instance is equal to the implementation
template test(inst) = template test(inst) =
testT(inst, false) testT(inst, false)
testV(inst, true, nil) testV(inst, true, nil)
template test(inst, impl) = testV(inst, true, impl)
# test a custom type with provided implementation
template test(inst, impl) =
testV(inst, true, impl)
type type
Model = object of RootObj Model = object of RootObj
@ -87,9 +105,12 @@ type
value:T value:T
Foo[N:static[int],T] = object Foo[N:static[int],T] = object
Bar[N:static[int],T] = object Bar[N:static[int],T] = object
#baz:Foo[N+1,GenericObject[T]] #baz:Foo[N+1,GenericObject[T]] # currently fails
baz:Foo[N,GenericObject[T]] baz:Foo[N,GenericObject[T]]
Generic[T] = seq[int]
Concrete = Generic[int]
test(bool) test(bool)
test(char) test(char)
test(int) test(int)
@ -97,13 +118,17 @@ test(float)
test(ptr int) test(ptr int)
test(ref int) test(ref int)
test(array[1..10,Bar[2,Foo[3,float]]]) test(array[1..10,Bar[2,Foo[3,float]]])
test(array[MyEnum,Bar[2,Foo[3,float]]])
test(distinct Bar[2,Foo[3,float]]) test(distinct Bar[2,Foo[3,float]])
test(tuple[a:int,b:Foo[-1,float]]) test(tuple[a:int,b:Foo[-1,float]])
#test(MyEnum):
# type _ = enum
# valueA, valueB, valueC
test(set[MyEnum])
test(seq[int]) test(seq[int])
test(set[MyEnum])
test(proc (a: int, b: Foo[2,float]))
test(proc (a: int, b: Foo[2,float]): Bar[3,int])
test(MyEnum):
type _ = enum
valueA, valueB, valueC
test(Bar[2,Foo[3,float]]): test(Bar[2,Foo[3,float]]):
type _ = object type _ = object
baz: Foo[2, GenericObject[Foo[3, float]]] baz: Foo[2, GenericObject[Foo[3, float]]]
@ -118,8 +143,12 @@ test(Tree):
value: int value: int
left: ref Tree left: ref Tree
right: ref Tree right: ref Tree
test(proc (a: int, b: Foo[2,float])) test(Concrete):
test(proc (a: int, b: Foo[2,float]): Bar[3,int]) type _ = Generic[int]
test(Generic[int]):
type _ = seq[int]
test(Generic[float]):
type _ = seq[int]
# bug #4862 # bug #4862
static: static:

View file

@ -45,6 +45,8 @@ Changes affecting backwards compatibility
AST that is the same as what is used to define an enum. Previously the AST AST that is the same as what is used to define an enum. Previously the AST
returned had a repeated ``EnumTy`` node and was missing the initial pragma returned had a repeated ``EnumTy`` node and was missing the initial pragma
node (which is currently empty for an enum). node (which is currently empty for an enum).
- ``macros.getTypeImpl`` now correctly returns the implementation for a symbol
of type ``tyGenericBody``.
- If the dispatcher parameter's value used in multi method is ``nil``, - If the dispatcher parameter's value used in multi method is ``nil``,
a ``NilError`` exception is raised. The old behavior was that the method a ``NilError`` exception is raised. The old behavior was that the method
would be a ``nop`` then. would be a ``nop`` then.