tgettypeinst.nim 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. discard """
  2. """
  3. import macros, strUtils
  4. proc symToIdent(x: NimNode): NimNode =
  5. case x.kind:
  6. of nnkCharLit..nnkUInt64Lit:
  7. result = newNimNode(x.kind)
  8. result.intVal = x.intVal
  9. of nnkFloatLit..nnkFloat64Lit:
  10. result = newNimNode(x.kind)
  11. result.floatVal = x.floatVal
  12. of nnkStrLit..nnkTripleStrLit:
  13. result = newNimNode(x.kind)
  14. result.strVal = x.strVal
  15. of nnkIdent, nnkSym:
  16. result = newIdentNode($x)
  17. else:
  18. result = newNimNode(x.kind)
  19. for c in x:
  20. result.add symToIdent(c)
  21. # check getTypeInst and getTypeImpl for given symbol x
  22. macro testX(x,inst0: typed; recurse: static[bool]; implX: typed): typed =
  23. # check that getTypeInst(x) equals inst0
  24. let inst = x.getTypeInst
  25. let instr = inst.symToIdent.treeRepr
  26. let inst0r = inst0.symToIdent.treeRepr
  27. #echo instr
  28. #echo inst0r
  29. doAssert(instr == inst0r)
  30. # check that getTypeImpl(x) is correct
  31. # if implX is nil then compare to inst0
  32. # else we expect implX to be a type definition
  33. # and we extract the implementation from that
  34. let impl = x.getTypeImpl
  35. var impl0 =
  36. if implX.kind == nnkNilLit: inst0
  37. else: implX[0][2]
  38. let implr = impl.symToIdent.treerepr
  39. let impl0r = impl0.symToIdent.treerepr
  40. #echo implr
  41. #echo impl0r
  42. doAssert(implr == impl0r)
  43. result = newStmtList()
  44. #template echoString(s: string) = echo s.replace("\n","\n ")
  45. #result.add getAst(echoString(" " & inst0.repr))
  46. #result.add getAst(echoString(" " & inst.repr))
  47. #result.add getAst(echoString(" " & impl0.repr))
  48. #result.add getAst(echoString(" " & impl.repr))
  49. if recurse:
  50. # now test using a newly formed variable of type getTypeInst(x)
  51. template testDecl(n,m: typed) =
  52. testV(n, false):
  53. type _ = m
  54. result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
  55. # test with a variable (instance) of type
  56. template testV(inst, recurse, impl) =
  57. block:
  58. #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
  59. var x: inst
  60. testX(x, inst, recurse, impl)
  61. # test with a newly created typedesc (myType)
  62. # using the passed type as the implementation
  63. template testT(impl, recurse) =
  64. block:
  65. type myType = impl
  66. testV(myType, recurse):
  67. type _ = impl
  68. # test a built-in type whose instance is equal to the implementation
  69. template test(inst) =
  70. testT(inst, false)
  71. testV(inst, true, nil)
  72. # test a custom type with provided implementation
  73. template test(inst, impl) =
  74. testV(inst, true, impl)
  75. type
  76. Model = object of RootObj
  77. User = object of Model
  78. name : string
  79. password : string
  80. Tree = object of RootObj
  81. value : int
  82. left,right : ref Tree
  83. MyEnum = enum
  84. valueA, valueB, valueC
  85. MySet = set[MyEnum]
  86. MySeq = seq[int]
  87. MyIntPtr = ptr int
  88. MyIntRef = ref int
  89. GenericObject[T] = object
  90. value:T
  91. Foo[N:static[int],T] = object
  92. Bar[N:static[int],T] = object
  93. #baz:Foo[N+1,GenericObject[T]] # currently fails
  94. baz:Foo[N,GenericObject[T]]
  95. Generic[T] = seq[int]
  96. Concrete = Generic[int]
  97. test(bool)
  98. test(char)
  99. test(int)
  100. test(float)
  101. test(ptr int)
  102. test(ref int)
  103. test(array[1..10,Bar[2,Foo[3,float]]])
  104. test(array[MyEnum,Bar[2,Foo[3,float]]])
  105. test(distinct Bar[2,Foo[3,float]])
  106. test(tuple[a:int,b:Foo[-1,float]])
  107. test(seq[int])
  108. test(set[MyEnum])
  109. test(proc (a: int, b: Foo[2,float]))
  110. test(proc (a: int, b: Foo[2,float]): Bar[3,int])
  111. test(MyEnum):
  112. type _ = enum
  113. valueA, valueB, valueC
  114. test(Bar[2,Foo[3,float]]):
  115. type _ = object
  116. baz: Foo[2, GenericObject[Foo[3, float]]]
  117. test(Model):
  118. type _ = object of RootObj
  119. test(User):
  120. type _ = object of Model
  121. name: string
  122. password: string
  123. test(Tree):
  124. type _ = object of RootObj
  125. value: int
  126. left: ref Tree
  127. right: ref Tree
  128. test(Concrete):
  129. type _ = Generic[int]
  130. test(Generic[int]):
  131. type _ = seq[int]
  132. test(Generic[float]):
  133. type _ = seq[int]
  134. # bug #4862
  135. static:
  136. discard typedesc[(int, int)].getTypeImpl