typeinfo.nim 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2013 Dominik Picheta, Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module implements an interface to Nim's `runtime type information`:idx:
  10. ## (`RTTI`:idx:). See the `marshal <marshal.html>`_ module for an example of
  11. ## what this allows you to do.
  12. ##
  13. ## .. note:: Even though `Any` and its operations hide the nasty low level
  14. ## details from its users, it remains inherently unsafe! Also, Nim's
  15. ## runtime type information will evolve and may eventually be deprecated.
  16. ## As an alternative approach to programmatically understanding and
  17. ## manipulating types, consider using the `macros <macros.html>`_ module to
  18. ## work with the types' AST representation at compile time. See for example
  19. ## the `getTypeImpl proc <macros.html#getTypeImpl,NimNode>`_. As an alternative
  20. ## approach to storing arbitrary types at runtime, consider using generics.
  21. runnableExamples:
  22. var x: Any
  23. var i = 42
  24. x = i.toAny
  25. assert x.kind == akInt
  26. assert x.getInt == 42
  27. var s = @[1, 2, 3]
  28. x = s.toAny
  29. assert x.kind == akSequence
  30. assert x.len == 3
  31. {.push hints: off.}
  32. include "system/inclrtl.nim"
  33. include "system/hti.nim"
  34. {.pop.}
  35. when defined(nimPreviewSlimSystem):
  36. import std/assertions
  37. type
  38. AnyKind* = enum ## The kind of `Any`.
  39. akNone = 0, ## invalid
  40. akBool = 1, ## bool
  41. akChar = 2, ## char
  42. akEnum = 14, ## enum
  43. akArray = 16, ## array
  44. akObject = 17, ## object
  45. akTuple = 18, ## tuple
  46. akSet = 19, ## set
  47. akRange = 20, ## range
  48. akPtr = 21, ## ptr
  49. akRef = 22, ## ref
  50. akSequence = 24, ## sequence
  51. akProc = 25, ## proc
  52. akPointer = 26, ## pointer
  53. akString = 28, ## string
  54. akCString = 29, ## cstring
  55. akInt = 31, ## int
  56. akInt8 = 32, ## int8
  57. akInt16 = 33, ## int16
  58. akInt32 = 34, ## int32
  59. akInt64 = 35, ## int64
  60. akFloat = 36, ## float
  61. akFloat32 = 37, ## float32
  62. akFloat64 = 38, ## float64
  63. akFloat128 = 39, ## float128
  64. akUInt = 40, ## uint
  65. akUInt8 = 41, ## uint8
  66. akUInt16 = 42, ## uin16
  67. akUInt32 = 43, ## uint32
  68. akUInt64 = 44, ## uint64
  69. # akOpt = 44+18 ## the builtin 'opt' type.
  70. Any* = object
  71. ## A type that can represent any nim value.
  72. ##
  73. ## .. danger:: The wrapped value can be modified with its wrapper! This means
  74. ## that `Any` keeps a non-traced pointer to its wrapped value and
  75. ## **must not** live longer than its wrapped value.
  76. value: pointer
  77. when defined(js):
  78. rawType: PNimType
  79. else:
  80. rawTypePtr: pointer
  81. ppointer = ptr pointer
  82. pbyteArray = ptr array[0xffff, uint8]
  83. when not defined(gcDestructors):
  84. type
  85. TGenericSeq {.importc.} = object
  86. len, space: int
  87. when defined(gogc):
  88. elemSize: int
  89. PGenSeq = ptr TGenericSeq
  90. when defined(gogc):
  91. const GenericSeqSize = 3 * sizeof(int)
  92. else:
  93. const GenericSeqSize = 2 * sizeof(int)
  94. else:
  95. include system/seqs_v2_reimpl
  96. from std/private/strimpl import cmpNimIdentifier
  97. when not defined(js):
  98. template rawType(x: Any): PNimType =
  99. cast[PNimType](x.rawTypePtr)
  100. template `rawType=`(x: var Any, p: PNimType) =
  101. x.rawTypePtr = cast[pointer](p)
  102. proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
  103. when not defined(gcDestructors):
  104. proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
  105. proc incrSeq(seq: PGenSeq, elemSize, elemAlign: int): PGenSeq {.importCompilerProc.}
  106. proc newObj(typ: PNimType, size: int): pointer {.importCompilerProc.}
  107. proc newSeq(typ: PNimType, len: int): pointer {.importCompilerProc.}
  108. proc objectInit(dest: pointer, typ: PNimType) {.importCompilerProc.}
  109. else:
  110. proc nimNewObj(size, align: int): pointer {.importCompilerProc.}
  111. proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc.}
  112. proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
  113. importCompilerProc.}
  114. proc zeroNewElements(len: int; p: pointer; addlen, elemSize, elemAlign: int) {.
  115. importCompilerProc.}
  116. template `+!!`(a, b): untyped = cast[pointer](cast[int](a) + b)
  117. proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
  118. assert(n.kind == nkCase)
  119. var d: int
  120. let a = cast[int](aa)
  121. case n.typ.size
  122. of 1: d = int(cast[ptr uint8](a +% n.offset)[])
  123. of 2: d = int(cast[ptr uint16](a +% n.offset)[])
  124. of 4: d = int(cast[ptr uint32](a +% n.offset)[])
  125. of 8: d = int(cast[ptr uint64](a +% n.offset)[])
  126. else: assert(false)
  127. return d
  128. proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =
  129. let discr = getDiscriminant(aa, n)
  130. if discr <% n.len:
  131. result = n.sons[discr]
  132. if result == nil: result = n.sons[n.len]
  133. # n.sons[n.len] contains the `else` part (but may be nil)
  134. else:
  135. result = n.sons[n.len]
  136. proc newAny(value: pointer, rawType: PNimType): Any {.inline.} =
  137. result.value = value
  138. result.rawType = rawType
  139. when declared(system.VarSlot):
  140. proc toAny*(x: VarSlot): Any {.inline.} =
  141. ## Constructs an `Any` object from a variable slot `x`.
  142. ## This captures `x`'s address, so `x` can be modified with its
  143. ## `Any` wrapper! The caller needs to ensure that the wrapper
  144. ## **does not** live longer than `x`!
  145. ## This is provided for easier reflection capabilities of a debugger.
  146. result.value = x.address
  147. result.rawType = x.typ
  148. proc toAny*[T](x: var T): Any {.inline.} =
  149. ## Constructs an `Any` object from `x`. This captures `x`'s address, so
  150. ## `x` can be modified with its `Any` wrapper! The caller needs to ensure
  151. ## that the wrapper **does not** live longer than `x`!
  152. newAny(addr(x), cast[PNimType](getTypeInfo(x)))
  153. proc kind*(x: Any): AnyKind {.inline.} =
  154. ## Gets the type kind.
  155. result = AnyKind(ord(x.rawType.kind))
  156. proc size*(x: Any): int {.inline.} =
  157. ## Returns the size of `x`'s type.
  158. result = x.rawType.size
  159. proc baseTypeKind*(x: Any): AnyKind {.inline.} =
  160. ## Gets the base type's kind. If `x` has no base type, `akNone` is returned.
  161. if x.rawType.base != nil:
  162. result = AnyKind(ord(x.rawType.base.kind))
  163. proc baseTypeSize*(x: Any): int {.inline.} =
  164. ## Returns the size of `x`'s base type. If `x` has no base type, 0 is returned.
  165. if x.rawType.base != nil:
  166. result = x.rawType.base.size
  167. proc invokeNew*(x: Any) =
  168. ## Performs `new(x)`. `x` needs to represent a `ref`.
  169. assert x.rawType.kind == tyRef
  170. when defined(gcDestructors):
  171. cast[ppointer](x.value)[] = nimNewObj(x.rawType.base.size, x.rawType.base.align)
  172. else:
  173. var z = newObj(x.rawType, x.rawType.base.size)
  174. genericAssign(x.value, addr(z), x.rawType)
  175. proc invokeNewSeq*(x: Any, len: int) =
  176. ## Performs `newSeq(x, len)`. `x` needs to represent a `seq`.
  177. assert x.rawType.kind == tySequence
  178. when defined(gcDestructors):
  179. var s = cast[ptr NimSeqV2Reimpl](x.value)
  180. s.len = len
  181. let elem = x.rawType.base
  182. s.p = cast[ptr NimSeqPayloadReimpl](newSeqPayload(len, elem.size, elem.align))
  183. else:
  184. var z = newSeq(x.rawType, len)
  185. genericShallowAssign(x.value, addr(z), x.rawType)
  186. proc extendSeq*(x: Any) =
  187. ## Performs `setLen(x, x.len+1)`. `x` needs to represent a `seq`.
  188. assert x.rawType.kind == tySequence
  189. when defined(gcDestructors):
  190. var s = cast[ptr NimSeqV2Reimpl](x.value)
  191. let elem = x.rawType.base
  192. if s.p == nil or s.p.cap < s.len+1:
  193. s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAddUninit(s.len, s.p, 1, elem.size, elem.align))
  194. zeroNewElements(s.len, s.p, 1, elem.size, elem.align)
  195. inc s.len
  196. else:
  197. var y = cast[ptr PGenSeq](x.value)[]
  198. var z = incrSeq(y, x.rawType.base.size, x.rawType.base.align)
  199. # 'incrSeq' already freed the memory for us and copied over the RC!
  200. # So we simply copy the raw pointer into 'x.value':
  201. cast[ppointer](x.value)[] = z
  202. #genericShallowAssign(x.value, addr(z), x.rawType)
  203. proc setObjectRuntimeType*(x: Any) =
  204. ## This needs to be called to set `x`'s runtime object type field.
  205. assert x.rawType.kind == tyObject
  206. when defined(gcDestructors):
  207. cast[ppointer](x.value)[] = x.rawType.typeInfoV2
  208. else:
  209. objectInit(x.value, x.rawType)
  210. proc skipRange(x: PNimType): PNimType {.inline.} =
  211. result = x
  212. if result.kind == tyRange: result = result.base
  213. proc align(address, alignment: int): int =
  214. result = (address + (alignment - 1)) and not (alignment - 1)
  215. proc `[]`*(x: Any, i: int): Any =
  216. ## Accessor for an any `x` that represents an array or a sequence.
  217. case x.rawType.kind
  218. of tyArray:
  219. let bs = x.rawType.base.size
  220. if i >=% x.rawType.size div bs:
  221. raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
  222. return newAny(x.value +!! i*bs, x.rawType.base)
  223. of tySequence:
  224. when defined(gcDestructors):
  225. var s = cast[ptr NimSeqV2Reimpl](x.value)
  226. if i >=% s.len:
  227. raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
  228. let bs = x.rawType.base.size
  229. let ba = x.rawType.base.align
  230. let headerSize = align(sizeof(int), ba)
  231. return newAny(s.p +!! (headerSize+i*bs), x.rawType.base)
  232. else:
  233. var s = cast[ppointer](x.value)[]
  234. if s == nil: raise newException(ValueError, "sequence is nil")
  235. let bs = x.rawType.base.size
  236. if i >=% cast[PGenSeq](s).len:
  237. raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
  238. return newAny(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), x.rawType.base)
  239. else: assert false
  240. proc `[]=`*(x: Any, i: int, y: Any) =
  241. ## Accessor for an any `x` that represents an array or a sequence.
  242. case x.rawType.kind
  243. of tyArray:
  244. var bs = x.rawType.base.size
  245. if i >=% x.rawType.size div bs:
  246. raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
  247. assert y.rawType == x.rawType.base
  248. genericAssign(x.value +!! i*bs, y.value, y.rawType)
  249. of tySequence:
  250. when defined(gcDestructors):
  251. var s = cast[ptr NimSeqV2Reimpl](x.value)
  252. if i >=% s.len:
  253. raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
  254. let bs = x.rawType.base.size
  255. let ba = x.rawType.base.align
  256. let headerSize = align(sizeof(int), ba)
  257. assert y.rawType == x.rawType.base
  258. genericAssign(s.p +!! (headerSize+i*bs), y.value, y.rawType)
  259. else:
  260. var s = cast[ppointer](x.value)[]
  261. if s == nil: raise newException(ValueError, "sequence is nil")
  262. var bs = x.rawType.base.size
  263. if i >=% cast[PGenSeq](s).len:
  264. raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
  265. assert y.rawType == x.rawType.base
  266. genericAssign(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), y.value, y.rawType)
  267. else: assert false
  268. proc len*(x: Any): int =
  269. ## `len` for an any `x` that represents an array or a sequence.
  270. case x.rawType.kind
  271. of tyArray:
  272. result = x.rawType.size div x.rawType.base.size
  273. of tySequence:
  274. when defined(gcDestructors):
  275. result = cast[ptr NimSeqV2Reimpl](x.value).len
  276. else:
  277. let pgenSeq = cast[PGenSeq](cast[ppointer](x.value)[])
  278. if isNil(pgenSeq):
  279. result = 0
  280. else:
  281. result = pgenSeq.len
  282. else: assert false
  283. proc base*(x: Any): Any =
  284. ## Returns the base type of `x` (useful for inherited object types).
  285. result.rawType = x.rawType.base
  286. result.value = x.value
  287. proc isNil*(x: Any): bool =
  288. ## `isNil` for an `x` that represents a cstring, proc or
  289. ## some pointer type.
  290. assert x.rawType.kind in {tyCstring, tyRef, tyPtr, tyPointer, tyProc}
  291. result = isNil(cast[ppointer](x.value)[])
  292. const pointerLike =
  293. when defined(gcDestructors): {tyCstring, tyRef, tyPtr, tyPointer, tyProc}
  294. else: {tyString, tyCstring, tyRef, tyPtr, tyPointer, tySequence, tyProc}
  295. proc getPointer*(x: Any): pointer =
  296. ## Retrieves the pointer value out of `x`. `x` needs to be of kind
  297. ## `akString`, `akCString`, `akProc`, `akRef`, `akPtr`,
  298. ## `akPointer` or `akSequence`.
  299. assert x.rawType.kind in pointerLike
  300. result = cast[ppointer](x.value)[]
  301. proc setPointer*(x: Any, y: pointer) =
  302. ## Sets the pointer value of `x`. `x` needs to be of kind
  303. ## `akString`, `akCString`, `akProc`, `akRef`, `akPtr`,
  304. ## `akPointer` or `akSequence`.
  305. assert x.rawType.kind in pointerLike
  306. if y != nil and x.rawType.kind != tyPointer:
  307. genericAssign(x.value, y, x.rawType)
  308. else:
  309. cast[ppointer](x.value)[] = y
  310. proc fieldsAux(p: pointer, n: ptr TNimNode,
  311. ret: var seq[tuple[name: cstring, any: Any]]) =
  312. case n.kind
  313. of nkNone: assert(false)
  314. of nkSlot:
  315. ret.add((n.name, newAny(p +!! n.offset, n.typ)))
  316. assert ret[ret.len()-1][0] != nil
  317. of nkList:
  318. for i in 0..n.len-1: fieldsAux(p, n.sons[i], ret)
  319. of nkCase:
  320. var m = selectBranch(p, n)
  321. ret.add((n.name, newAny(p +!! n.offset, n.typ)))
  322. if m != nil: fieldsAux(p, m, ret)
  323. iterator fields*(x: Any): tuple[name: string, any: Any] =
  324. ## Iterates over every active field of `x`. `x` needs to represent an object
  325. ## or a tuple.
  326. assert x.rawType.kind in {tyTuple, tyObject}
  327. let p = x.value
  328. var t = x.rawType
  329. # XXX BUG: does not work yet, however is questionable anyway
  330. when false:
  331. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  332. var ret: seq[tuple[name: cstring, any: Any]]
  333. if t.kind == tyObject:
  334. while true:
  335. fieldsAux(p, t.node, ret)
  336. t = t.base
  337. if t.isNil: break
  338. else:
  339. fieldsAux(p, t.node, ret)
  340. for name, any in items(ret):
  341. yield ($name, any)
  342. proc getFieldNode(p: pointer, n: ptr TNimNode, name: cstring): ptr TNimNode =
  343. case n.kind
  344. of nkNone: assert(false)
  345. of nkSlot:
  346. if cmpNimIdentifier(n.name, name) == 0:
  347. result = n
  348. of nkList:
  349. for i in 0..n.len-1:
  350. result = getFieldNode(p, n.sons[i], name)
  351. if result != nil: break
  352. of nkCase:
  353. if cmpNimIdentifier(n.name, name) == 0:
  354. result = n
  355. else:
  356. let m = selectBranch(p, n)
  357. if m != nil: result = getFieldNode(p, m, name)
  358. proc `[]=`*(x: Any, fieldName: string, value: Any) =
  359. ## Sets a field of `x`. `x` needs to represent an object or a tuple.
  360. var t = x.rawType
  361. # XXX BUG: does not work yet, however is questionable anyway
  362. when false:
  363. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  364. assert x.rawType.kind in {tyTuple, tyObject}
  365. let n = getFieldNode(x.value, t.node, fieldName)
  366. if n != nil:
  367. assert n.typ == value.rawType
  368. genericAssign(x.value +!! n.offset, value.value, value.rawType)
  369. else:
  370. raise newException(ValueError, "invalid field name: " & fieldName)
  371. proc `[]`*(x: Any, fieldName: string): Any =
  372. ## Gets a field of `x`. `x` needs to represent an object or a tuple.
  373. var t = x.rawType
  374. # XXX BUG: does not work yet, however is questionable anyway
  375. when false:
  376. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  377. assert x.rawType.kind in {tyTuple, tyObject}
  378. let n = getFieldNode(x.value, t.node, fieldName)
  379. if n != nil:
  380. result.value = x.value +!! n.offset
  381. result.rawType = n.typ
  382. elif x.rawType.kind == tyObject and x.rawType.base != nil:
  383. return `[]`(newAny(x.value, x.rawType.base), fieldName)
  384. else:
  385. raise newException(ValueError, "invalid field name: " & fieldName)
  386. proc `[]`*(x: Any): Any =
  387. ## Dereference operator for `Any`. `x` needs to represent a ptr or a ref.
  388. assert x.rawType.kind in {tyRef, tyPtr}
  389. result.value = cast[ppointer](x.value)[]
  390. result.rawType = x.rawType.base
  391. proc `[]=`*(x, y: Any) =
  392. ## Dereference operator for `Any`. `x` needs to represent a ptr or a ref.
  393. assert x.rawType.kind in {tyRef, tyPtr}
  394. assert y.rawType == x.rawType.base
  395. genericAssign(cast[ppointer](x.value)[], y.value, y.rawType)
  396. proc getInt*(x: Any): int =
  397. ## Retrieves the `int` value out of `x`. `x` needs to represent an `int`.
  398. assert skipRange(x.rawType).kind == tyInt
  399. result = cast[ptr int](x.value)[]
  400. proc getInt8*(x: Any): int8 =
  401. ## Retrieves the `int8` value out of `x`. `x` needs to represent an `int8`.
  402. assert skipRange(x.rawType).kind == tyInt8
  403. result = cast[ptr int8](x.value)[]
  404. proc getInt16*(x: Any): int16 =
  405. ## Retrieves the `int16` value out of `x`. `x` needs to represent an `int16`.
  406. assert skipRange(x.rawType).kind == tyInt16
  407. result = cast[ptr int16](x.value)[]
  408. proc getInt32*(x: Any): int32 =
  409. ## Retrieves the `int32` value out of `x`. `x` needs to represent an `int32`.
  410. assert skipRange(x.rawType).kind == tyInt32
  411. result = cast[ptr int32](x.value)[]
  412. proc getInt64*(x: Any): int64 =
  413. ## Retrieves the `int64` value out of `x`. `x` needs to represent an `int64`.
  414. assert skipRange(x.rawType).kind == tyInt64
  415. result = cast[ptr int64](x.value)[]
  416. proc getBiggestInt*(x: Any): BiggestInt =
  417. ## Retrieves the integer value out of `x`. `x` needs to represent
  418. ## some integer, a bool, a char, an enum or a small enough bit set.
  419. ## The value might be sign-extended to `BiggestInt`.
  420. let t = skipRange(x.rawType)
  421. case t.kind
  422. of tyInt: result = BiggestInt(cast[ptr int](x.value)[])
  423. of tyInt8: result = BiggestInt(cast[ptr int8](x.value)[])
  424. of tyInt16: result = BiggestInt(cast[ptr int16](x.value)[])
  425. of tyInt32: result = BiggestInt(cast[ptr int32](x.value)[])
  426. of tyInt64, tyUInt64: result = BiggestInt(cast[ptr int64](x.value)[])
  427. of tyBool: result = BiggestInt(cast[ptr bool](x.value)[])
  428. of tyChar: result = BiggestInt(cast[ptr char](x.value)[])
  429. of tyEnum, tySet:
  430. case t.size
  431. of 1: result = int64(cast[ptr uint8](x.value)[])
  432. of 2: result = int64(cast[ptr uint16](x.value)[])
  433. of 4: result = BiggestInt(cast[ptr int32](x.value)[])
  434. of 8: result = BiggestInt(cast[ptr int64](x.value)[])
  435. else: assert false
  436. of tyUInt: result = BiggestInt(cast[ptr uint](x.value)[])
  437. of tyUInt8: result = BiggestInt(cast[ptr uint8](x.value)[])
  438. of tyUInt16: result = BiggestInt(cast[ptr uint16](x.value)[])
  439. of tyUInt32: result = BiggestInt(cast[ptr uint32](x.value)[])
  440. else: assert false
  441. proc setBiggestInt*(x: Any, y: BiggestInt) =
  442. ## Sets the integer value of `x`. `x` needs to represent
  443. ## some integer, a bool, a char, an enum or a small enough bit set.
  444. let t = skipRange(x.rawType)
  445. case t.kind
  446. of tyInt: cast[ptr int](x.value)[] = int(y)
  447. of tyInt8: cast[ptr int8](x.value)[] = int8(y)
  448. of tyInt16: cast[ptr int16](x.value)[] = int16(y)
  449. of tyInt32: cast[ptr int32](x.value)[] = int32(y)
  450. of tyInt64, tyUInt64: cast[ptr int64](x.value)[] = int64(y)
  451. of tyBool: cast[ptr bool](x.value)[] = y != 0
  452. of tyChar: cast[ptr char](x.value)[] = chr(y.int)
  453. of tyEnum, tySet:
  454. case t.size
  455. of 1: cast[ptr uint8](x.value)[] = uint8(y.int)
  456. of 2: cast[ptr uint16](x.value)[] = uint16(y.int)
  457. of 4: cast[ptr int32](x.value)[] = int32(y)
  458. of 8: cast[ptr int64](x.value)[] = y
  459. else: assert false
  460. of tyUInt: cast[ptr uint](x.value)[] = uint(y)
  461. of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
  462. of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
  463. of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
  464. else: assert false
  465. proc getUInt*(x: Any): uint =
  466. ## Retrieves the `uint` value out of `x`. `x` needs to represent a `uint`.
  467. assert skipRange(x.rawType).kind == tyUInt
  468. result = cast[ptr uint](x.value)[]
  469. proc getUInt8*(x: Any): uint8 =
  470. ## Retrieves the `uint8` value out of `x`. `x` needs to represent a `uint8`.
  471. assert skipRange(x.rawType).kind == tyUInt8
  472. result = cast[ptr uint8](x.value)[]
  473. proc getUInt16*(x: Any): uint16 =
  474. ## Retrieves the `uint16` value out of `x`. `x` needs to represent a `uint16`.
  475. assert skipRange(x.rawType).kind == tyUInt16
  476. result = cast[ptr uint16](x.value)[]
  477. proc getUInt32*(x: Any): uint32 =
  478. ## Retrieves the `uint32` value out of `x`. `x` needs to represent a `uint32`.
  479. assert skipRange(x.rawType).kind == tyUInt32
  480. result = cast[ptr uint32](x.value)[]
  481. proc getUInt64*(x: Any): uint64 =
  482. ## Retrieves the `uint64` value out of `x`. `x` needs to represent a `uint64`.
  483. assert skipRange(x.rawType).kind == tyUInt64
  484. result = cast[ptr uint64](x.value)[]
  485. proc getBiggestUint*(x: Any): uint64 =
  486. ## Retrieves the unsigned integer value out of `x`. `x` needs to
  487. ## represent an unsigned integer.
  488. let t = skipRange(x.rawType)
  489. case t.kind
  490. of tyUInt: result = uint64(cast[ptr uint](x.value)[])
  491. of tyUInt8: result = uint64(cast[ptr uint8](x.value)[])
  492. of tyUInt16: result = uint64(cast[ptr uint16](x.value)[])
  493. of tyUInt32: result = uint64(cast[ptr uint32](x.value)[])
  494. of tyUInt64: result = uint64(cast[ptr uint64](x.value)[])
  495. else: assert false
  496. proc setBiggestUint*(x: Any; y: uint64) =
  497. ## Sets the unsigned integer value of `x`. `x` needs to represent an
  498. ## unsigned integer.
  499. let t = skipRange(x.rawType)
  500. case t.kind:
  501. of tyUInt: cast[ptr uint](x.value)[] = uint(y)
  502. of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
  503. of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
  504. of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
  505. of tyUInt64: cast[ptr uint64](x.value)[] = uint64(y)
  506. else: assert false
  507. proc getChar*(x: Any): char =
  508. ## Retrieves the `char` value out of `x`. `x` needs to represent a `char`.
  509. let t = skipRange(x.rawType)
  510. assert t.kind == tyChar
  511. result = cast[ptr char](x.value)[]
  512. proc getBool*(x: Any): bool =
  513. ## Retrieves the `bool` value out of `x`. `x` needs to represent a `bool`.
  514. let t = skipRange(x.rawType)
  515. assert t.kind == tyBool
  516. result = cast[ptr bool](x.value)[]
  517. proc skipRange*(x: Any): Any =
  518. ## Skips the range information of `x`.
  519. assert x.rawType.kind == tyRange
  520. result.rawType = x.rawType.base
  521. result.value = x.value
  522. proc getEnumOrdinal*(x: Any, name: string): int =
  523. ## Gets the enum field ordinal from `name`. `x` needs to represent an enum
  524. ## but is only used to access the type information. In case of an error
  525. ## `low(int)` is returned.
  526. let typ = skipRange(x.rawType)
  527. assert typ.kind == tyEnum
  528. let n = typ.node
  529. let s = n.sons
  530. for i in 0 .. n.len-1:
  531. if cmpNimIdentifier($s[i].name, name) == 0:
  532. if ntfEnumHole notin typ.flags:
  533. return i
  534. else:
  535. return s[i].offset
  536. result = low(int)
  537. proc getEnumField*(x: Any, ordinalValue: int): string =
  538. ## Gets the enum field name as a string. `x` needs to represent an enum
  539. ## but is only used to access the type information. The field name of
  540. ## `ordinalValue` is returned.
  541. let typ = skipRange(x.rawType)
  542. assert typ.kind == tyEnum
  543. let e = ordinalValue
  544. if ntfEnumHole notin typ.flags:
  545. if e <% typ.node.len:
  546. return $typ.node.sons[e].name
  547. else:
  548. # ugh we need a slow linear search:
  549. let n = typ.node
  550. let s = n.sons
  551. for i in 0 .. n.len-1:
  552. if s[i].offset == e: return $s[i].name
  553. result = $e
  554. proc getEnumField*(x: Any): string =
  555. ## Gets the enum field name as a string. `x` needs to represent an enum.
  556. result = getEnumField(x, getBiggestInt(x).int)
  557. proc getFloat*(x: Any): float =
  558. ## Retrieves the `float` value out of `x`. `x` needs to represent a `float`.
  559. assert skipRange(x.rawType).kind == tyFloat
  560. result = cast[ptr float](x.value)[]
  561. proc getFloat32*(x: Any): float32 =
  562. ## Retrieves the `float32` value out of `x`. `x` needs to represent a `float32`.
  563. assert skipRange(x.rawType).kind == tyFloat32
  564. result = cast[ptr float32](x.value)[]
  565. proc getFloat64*(x: Any): float64 =
  566. ## Retrieves the `float64` value out of `x`. `x` needs to represent a `float64`.
  567. assert skipRange(x.rawType).kind == tyFloat64
  568. result = cast[ptr float64](x.value)[]
  569. proc getBiggestFloat*(x: Any): BiggestFloat =
  570. ## Retrieves the float value out of `x`. `x` needs to represent
  571. ## some float. The value is extended to `BiggestFloat`.
  572. case skipRange(x.rawType).kind
  573. of tyFloat: result = BiggestFloat(cast[ptr float](x.value)[])
  574. of tyFloat32: result = BiggestFloat(cast[ptr float32](x.value)[])
  575. of tyFloat64: result = BiggestFloat(cast[ptr float64](x.value)[])
  576. else: assert false
  577. proc setBiggestFloat*(x: Any, y: BiggestFloat) =
  578. ## Sets the float value of `x`. `x` needs to represent
  579. ## some float.
  580. case skipRange(x.rawType).kind
  581. of tyFloat: cast[ptr float](x.value)[] = y
  582. of tyFloat32: cast[ptr float32](x.value)[] = y.float32
  583. of tyFloat64: cast[ptr float64](x.value)[] = y
  584. else: assert false
  585. proc getString*(x: Any): string =
  586. ## Retrieves the `string` value out of `x`. `x` needs to represent a `string`.
  587. assert x.rawType.kind == tyString
  588. when defined(gcDestructors):
  589. result = cast[ptr string](x.value)[]
  590. else:
  591. if not isNil(cast[ptr pointer](x.value)[]):
  592. result = cast[ptr string](x.value)[]
  593. proc setString*(x: Any, y: string) =
  594. ## Sets the `string` value of `x`. `x` needs to represent a `string`.
  595. assert x.rawType.kind == tyString
  596. cast[ptr string](x.value)[] = y # also correct for gcDestructors
  597. proc getCString*(x: Any): cstring =
  598. ## Retrieves the `cstring` value out of `x`. `x` needs to represent a `cstring`.
  599. assert x.rawType.kind == tyCstring
  600. result = cast[ptr cstring](x.value)[]
  601. proc assign*(x, y: Any) =
  602. ## Copies the value of `y` to `x`. The assignment operator for `Any`
  603. ## does NOT do this; it performs a shallow copy instead!
  604. assert y.rawType == x.rawType
  605. genericAssign(x.value, y.value, y.rawType)
  606. iterator elements*(x: Any): int =
  607. ## Iterates over every element of `x`. `x` needs to represent a `set`.
  608. assert x.rawType.kind == tySet
  609. let typ = x.rawType
  610. let p = x.value
  611. # "typ.slots.len" field is for sets the "first" field
  612. var u: int64
  613. case typ.size
  614. of 1: u = int64(cast[ptr uint8](p)[])
  615. of 2: u = int64(cast[ptr uint16](p)[])
  616. of 4: u = int64(cast[ptr uint32](p)[])
  617. of 8: u = cast[ptr int64](p)[]
  618. else:
  619. let a = cast[pbyteArray](p)
  620. for i in 0 .. typ.size*8-1:
  621. if (int(a[i div 8]) and (1 shl (i mod 8))) != 0:
  622. yield i + typ.node.len
  623. if typ.size <= 8:
  624. for i in 0..sizeof(int64)*8-1:
  625. if (u and (1'i64 shl int64(i))) != 0'i64:
  626. yield i + typ.node.len
  627. proc inclSetElement*(x: Any, elem: int) =
  628. ## Includes an element `elem` in `x`. `x` needs to represent a Nim bitset.
  629. assert x.rawType.kind == tySet
  630. let typ = x.rawType
  631. let p = x.value
  632. # "typ.slots.len" field is for sets the "first" field
  633. let e = elem - typ.node.len
  634. case typ.size
  635. of 1:
  636. var a = cast[ptr int8](p)
  637. a[] = a[] or (1'i8 shl int8(e))
  638. of 2:
  639. var a = cast[ptr int16](p)
  640. a[] = a[] or (1'i16 shl int16(e))
  641. of 4:
  642. var a = cast[ptr int32](p)
  643. a[] = a[] or (1'i32 shl int32(e))
  644. of 8:
  645. var a = cast[ptr int64](p)
  646. a[] = a[] or (1'i64 shl e)
  647. else:
  648. var a = cast[pbyteArray](p)
  649. a[e shr 3] = a[e shr 3] or uint8(1 shl (e and 7))