tgettypeinst.nim 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. discard """
  2. """
  3. import macros
  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) =
  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. if instr != inst0r:
  28. echo "instr:\n", instr
  29. echo "inst0r:\n", inst0r
  30. doAssert(instr == inst0r)
  31. # check that getTypeImpl(x) is correct
  32. # if implX is nil then compare to inst0
  33. # else we expect implX to be a type definition
  34. # and we extract the implementation from that
  35. let impl = x.getTypeImpl
  36. var impl0 =
  37. if implX.kind == nnkNilLit: inst0
  38. else: implX[0][2]
  39. let implr = impl.symToIdent.treerepr
  40. let impl0r = impl0.symToIdent.treerepr
  41. if implr != impl0r:
  42. echo "implr:\n", implr
  43. echo "impl0r:\n", impl0r
  44. doAssert(implr == impl0r)
  45. result = newStmtList()
  46. #template echoString(s: string) = echo s.replace("\n","\n ")
  47. #result.add getAst(echoString(" " & inst0.repr))
  48. #result.add getAst(echoString(" " & inst.repr))
  49. #result.add getAst(echoString(" " & impl0.repr))
  50. #result.add getAst(echoString(" " & impl.repr))
  51. if recurse:
  52. # now test using a newly formed variable of type getTypeInst(x)
  53. template testDecl(n,m: typed) =
  54. testV(n, false):
  55. type _ = m
  56. result.add getAst(testDecl(inst.symToIdent, impl.symToIdent))
  57. # test with a variable (instance) of type
  58. template testV(inst, recurse, impl) =
  59. block:
  60. #echo "testV(" & astToStr(inst) & ", " & $recurse & "):" & astToStr(impl)
  61. var x: inst
  62. testX(x, inst, recurse, impl)
  63. # test with a newly created typedesc (myType)
  64. # using the passed type as the implementation
  65. template testT(impl, recurse) =
  66. block:
  67. type myType = impl
  68. testV(myType, recurse):
  69. type _ = impl
  70. # test a built-in type whose instance is equal to the implementation
  71. template test(inst) =
  72. testT(inst, false)
  73. testV(inst, true, nil)
  74. # test a custom type with provided implementation
  75. template test(inst, impl) =
  76. testV(inst, true, impl)
  77. type
  78. Model = object of RootObj
  79. User = object of Model
  80. name : string
  81. password : string
  82. Tree = object of RootObj
  83. value : int
  84. left,right : ref Tree
  85. MyEnum = enum
  86. valueA, valueB, valueC
  87. MySet = set[MyEnum]
  88. MySeq = seq[int]
  89. MyIntPtr = ptr int
  90. MyIntRef = ref int
  91. GenericObject[T] = object
  92. value:T
  93. Foo[N:static[int],T] = object
  94. Bar[N:static[int],T] = object
  95. #baz:Foo[N+1,GenericObject[T]] # currently fails
  96. baz:Foo[N,GenericObject[T]]
  97. Generic[T] = seq[int]
  98. Concrete = Generic[int]
  99. Generic2[T1, T2] = seq[T1]
  100. Concrete2 = Generic2[int, float]
  101. Alias1 = float
  102. Alias2 = Concrete
  103. Alias3 = Concrete2
  104. Vec[N: static[int],T] = object
  105. arr: array[N,T]
  106. Vec4[T] = Vec[4,T]
  107. test(bool)
  108. test(char)
  109. test(int)
  110. test(float)
  111. test(ptr int)
  112. test(ref int)
  113. test(array[1..10,Bar[2,Foo[3,float]]])
  114. test(array[MyEnum,Bar[2,Foo[3,float]]])
  115. test(distinct Bar[2,Foo[3,float]])
  116. test(tuple[a:int,b:Foo[-1,float]])
  117. test(seq[int])
  118. test(set[MyEnum])
  119. test(proc (a: int, b: Foo[2,float]))
  120. test(proc (a: int, b: Foo[2,float]): Bar[3,int])
  121. test(MyEnum):
  122. type _ = enum
  123. valueA, valueB, valueC
  124. test(Bar[2,Foo[3,float]]):
  125. type _ = object
  126. baz: Foo[2, GenericObject[Foo[3, float]]]
  127. test(Model):
  128. type _ = object of RootObj
  129. test(User):
  130. type _ = object of Model
  131. name: string
  132. password: string
  133. test(Tree):
  134. type _ = object of RootObj
  135. value: int
  136. left: ref Tree
  137. right: ref Tree
  138. test(Concrete):
  139. type _ = seq[int]
  140. test(Generic[int]):
  141. type _ = seq[int]
  142. test(Generic[float]):
  143. type _ = seq[int]
  144. test(Concrete2):
  145. type _ = seq[int]
  146. test(Generic2[int,float]):
  147. type _ = seq[int]
  148. test(Alias1):
  149. type _ = float
  150. test(Alias2):
  151. type _ = seq[int]
  152. test(Alias3):
  153. type _ = seq[int]
  154. test(Vec[4,float32]):
  155. type _ = object
  156. arr: array[0..3,float32]
  157. test(Vec4[float32]):
  158. type _ = object
  159. arr: array[0..3,float32]
  160. # bug #4862
  161. static:
  162. discard typedesc[(int, int)].getTypeImpl
  163. # custom pragmas
  164. template myAttr() {.pragma.}
  165. template myAttr2() {.pragma.}
  166. template myAttr3() {.pragma.}
  167. template serializationKey(key: string) {.pragma.}
  168. type
  169. MyObj {.packed,myAttr,serializationKey: "one".} = object
  170. myField {.myAttr2,serializationKey: "two".}: int
  171. myField2 {.myAttr3,serializationKey: "three".}: float
  172. # field pragmas not currently supported
  173. test(MyObj):
  174. type
  175. _ {.packed,myAttr,serializationKey: "one".} = object
  176. myField: int
  177. myField2: float
  178. block t9600:
  179. type
  180. Apple = ref object of RootObj
  181. macro mixer(x: typed): untyped =
  182. let w = getType(x)
  183. let v = getTypeImpl(w[1])
  184. var z: Apple
  185. mixer(z)