typeinfo.nim 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  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: raiseAssert "unreachable"
  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 = Any(value: value)
  138. result.rawType = rawType
  139. proc toAny*[T](x: var T): Any {.inline.} =
  140. ## Constructs an `Any` object from `x`. This captures `x`'s address, so
  141. ## `x` can be modified with its `Any` wrapper! The caller needs to ensure
  142. ## that the wrapper **does not** live longer than `x`!
  143. newAny(addr(x), cast[PNimType](getTypeInfo(x)))
  144. proc kind*(x: Any): AnyKind {.inline.} =
  145. ## Gets the type kind.
  146. result = cast[AnyKind](ord(x.rawType.kind))
  147. proc size*(x: Any): int {.inline.} =
  148. ## Returns the size of `x`'s type.
  149. result = x.rawType.size
  150. proc baseTypeKind*(x: Any): AnyKind {.inline.} =
  151. ## Gets the base type's kind. If `x` has no base type, `akNone` is returned.
  152. if x.rawType.base != nil:
  153. result = cast[AnyKind](ord(x.rawType.base.kind))
  154. else:
  155. result = akNone
  156. proc baseTypeSize*(x: Any): int {.inline.} =
  157. ## Returns the size of `x`'s base type. If `x` has no base type, 0 is returned.
  158. if x.rawType.base != nil:
  159. result = x.rawType.base.size
  160. else:
  161. result = 0
  162. proc invokeNew*(x: Any) =
  163. ## Performs `new(x)`. `x` needs to represent a `ref`.
  164. assert x.rawType.kind == tyRef
  165. when defined(gcDestructors):
  166. cast[ppointer](x.value)[] = nimNewObj(x.rawType.base.size, x.rawType.base.align)
  167. else:
  168. var z = newObj(x.rawType, x.rawType.base.size)
  169. genericAssign(x.value, addr(z), x.rawType)
  170. proc invokeNewSeq*(x: Any, len: int) =
  171. ## Performs `newSeq(x, len)`. `x` needs to represent a `seq`.
  172. assert x.rawType.kind == tySequence
  173. when defined(gcDestructors):
  174. var s = cast[ptr NimSeqV2Reimpl](x.value)
  175. s.len = len
  176. let elem = x.rawType.base
  177. s.p = cast[ptr NimSeqPayloadReimpl](newSeqPayload(len, elem.size, elem.align))
  178. else:
  179. var z = newSeq(x.rawType, len)
  180. genericShallowAssign(x.value, addr(z), x.rawType)
  181. proc extendSeq*(x: Any) =
  182. ## Performs `setLen(x, x.len+1)`. `x` needs to represent a `seq`.
  183. assert x.rawType.kind == tySequence
  184. when defined(gcDestructors):
  185. var s = cast[ptr NimSeqV2Reimpl](x.value)
  186. let elem = x.rawType.base
  187. if s.p == nil or s.p.cap < s.len+1:
  188. s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAddUninit(s.len, s.p, 1, elem.size, elem.align))
  189. zeroNewElements(s.len, s.p, 1, elem.size, elem.align)
  190. inc s.len
  191. else:
  192. var y = cast[ptr PGenSeq](x.value)[]
  193. var z = incrSeq(y, x.rawType.base.size, x.rawType.base.align)
  194. # 'incrSeq' already freed the memory for us and copied over the RC!
  195. # So we simply copy the raw pointer into 'x.value':
  196. cast[ppointer](x.value)[] = z
  197. #genericShallowAssign(x.value, addr(z), x.rawType)
  198. proc setObjectRuntimeType*(x: Any) =
  199. ## This needs to be called to set `x`'s runtime object type field.
  200. assert x.rawType.kind == tyObject
  201. when defined(gcDestructors):
  202. cast[ppointer](x.value)[] = x.rawType.typeInfoV2
  203. else:
  204. objectInit(x.value, x.rawType)
  205. proc skipRange(x: PNimType): PNimType {.inline.} =
  206. result = x
  207. if result.kind == tyRange: result = result.base
  208. proc align(address, alignment: int): int =
  209. result = (address + (alignment - 1)) and not (alignment - 1)
  210. proc `[]`*(x: Any, i: int): Any =
  211. ## Accessor for an any `x` that represents an array or a sequence.
  212. case x.rawType.kind
  213. of tyArray:
  214. let bs = x.rawType.base.size
  215. if i >=% x.rawType.size div bs:
  216. raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
  217. return newAny(x.value +!! i*bs, x.rawType.base)
  218. of tySequence:
  219. when defined(gcDestructors):
  220. var s = cast[ptr NimSeqV2Reimpl](x.value)
  221. if i >=% s.len:
  222. raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
  223. let bs = x.rawType.base.size
  224. let ba = x.rawType.base.align
  225. let headerSize = align(sizeof(int), ba)
  226. return newAny(s.p +!! (headerSize+i*bs), x.rawType.base)
  227. else:
  228. var s = cast[ppointer](x.value)[]
  229. if s == nil: raise newException(ValueError, "sequence is nil")
  230. let bs = x.rawType.base.size
  231. if i >=% cast[PGenSeq](s).len:
  232. raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
  233. return newAny(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), x.rawType.base)
  234. else: raiseAssert "unreachable"
  235. proc `[]=`*(x: Any, i: int, y: Any) =
  236. ## Accessor for an any `x` that represents an array or a sequence.
  237. case x.rawType.kind
  238. of tyArray:
  239. var bs = x.rawType.base.size
  240. if i >=% x.rawType.size div bs:
  241. raise newException(IndexDefect, formatErrorIndexBound(i, x.rawType.size div bs))
  242. assert y.rawType == x.rawType.base
  243. genericAssign(x.value +!! i*bs, y.value, y.rawType)
  244. of tySequence:
  245. when defined(gcDestructors):
  246. var s = cast[ptr NimSeqV2Reimpl](x.value)
  247. if i >=% s.len:
  248. raise newException(IndexDefect, formatErrorIndexBound(i, s.len-1))
  249. let bs = x.rawType.base.size
  250. let ba = x.rawType.base.align
  251. let headerSize = align(sizeof(int), ba)
  252. assert y.rawType == x.rawType.base
  253. genericAssign(s.p +!! (headerSize+i*bs), y.value, y.rawType)
  254. else:
  255. var s = cast[ppointer](x.value)[]
  256. if s == nil: raise newException(ValueError, "sequence is nil")
  257. var bs = x.rawType.base.size
  258. if i >=% cast[PGenSeq](s).len:
  259. raise newException(IndexDefect, formatErrorIndexBound(i, cast[PGenSeq](s).len-1))
  260. assert y.rawType == x.rawType.base
  261. genericAssign(s +!! (align(GenericSeqSize, x.rawType.base.align)+i*bs), y.value, y.rawType)
  262. else: raiseAssert "unreachable"
  263. proc len*(x: Any): int =
  264. ## `len` for an any `x` that represents an array or a sequence.
  265. case x.rawType.kind
  266. of tyArray:
  267. result = x.rawType.size div x.rawType.base.size
  268. of tySequence:
  269. when defined(gcDestructors):
  270. result = cast[ptr NimSeqV2Reimpl](x.value).len
  271. else:
  272. let pgenSeq = cast[PGenSeq](cast[ppointer](x.value)[])
  273. if isNil(pgenSeq):
  274. result = 0
  275. else:
  276. result = pgenSeq.len
  277. else: raiseAssert "unreachable"
  278. proc base*(x: Any): Any =
  279. ## Returns the base type of `x` (useful for inherited object types).
  280. result = Any(value: x.value)
  281. result.rawType = x.rawType.base
  282. proc isNil*(x: Any): bool =
  283. ## `isNil` for an `x` that represents a cstring, proc or
  284. ## some pointer type.
  285. assert x.rawType.kind in {tyCstring, tyRef, tyPtr, tyPointer, tyProc}
  286. result = isNil(cast[ppointer](x.value)[])
  287. const pointerLike =
  288. when defined(gcDestructors): {tyCstring, tyRef, tyPtr, tyPointer, tyProc}
  289. else: {tyString, tyCstring, tyRef, tyPtr, tyPointer, tySequence, tyProc}
  290. proc getPointer*(x: Any): pointer =
  291. ## Retrieves the pointer value out of `x`. `x` needs to be of kind
  292. ## `akString`, `akCString`, `akProc`, `akRef`, `akPtr`,
  293. ## `akPointer` or `akSequence`.
  294. assert x.rawType.kind in pointerLike
  295. result = cast[ppointer](x.value)[]
  296. proc setPointer*(x: Any, y: pointer) =
  297. ## Sets the pointer value of `x`. `x` needs to be of kind
  298. ## `akString`, `akCString`, `akProc`, `akRef`, `akPtr`,
  299. ## `akPointer` or `akSequence`.
  300. assert x.rawType.kind in pointerLike
  301. if y != nil and x.rawType.kind != tyPointer:
  302. genericAssign(x.value, y, x.rawType)
  303. else:
  304. cast[ppointer](x.value)[] = y
  305. proc fieldsAux(p: pointer, n: ptr TNimNode,
  306. ret: var seq[tuple[name: cstring, any: Any]]) =
  307. case n.kind
  308. of nkNone: assert(false)
  309. of nkSlot:
  310. ret.add((n.name, newAny(p +!! n.offset, n.typ)))
  311. assert ret[ret.len()-1][0] != nil
  312. of nkList:
  313. for i in 0..n.len-1: fieldsAux(p, n.sons[i], ret)
  314. of nkCase:
  315. var m = selectBranch(p, n)
  316. ret.add((n.name, newAny(p +!! n.offset, n.typ)))
  317. if m != nil: fieldsAux(p, m, ret)
  318. iterator fields*(x: Any): tuple[name: string, any: Any] =
  319. ## Iterates over every active field of `x`. `x` needs to represent an object
  320. ## or a tuple.
  321. assert x.rawType.kind in {tyTuple, tyObject}
  322. let p = x.value
  323. var t = x.rawType
  324. # XXX BUG: does not work yet, however is questionable anyway
  325. when false:
  326. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  327. var ret: seq[tuple[name: cstring, any: Any]] = @[]
  328. if t.kind == tyObject:
  329. while true:
  330. fieldsAux(p, t.node, ret)
  331. t = t.base
  332. if t.isNil: break
  333. else:
  334. fieldsAux(p, t.node, ret)
  335. for name, any in items(ret):
  336. yield ($name, any)
  337. proc getFieldNode(p: pointer, n: ptr TNimNode, name: cstring): ptr TNimNode =
  338. result = nil
  339. case n.kind
  340. of nkNone: raiseAssert "unreachable"
  341. of nkSlot:
  342. if cmpNimIdentifier(n.name, name) == 0:
  343. result = n
  344. of nkList:
  345. for i in 0..n.len-1:
  346. result = getFieldNode(p, n.sons[i], name)
  347. if result != nil: break
  348. of nkCase:
  349. if cmpNimIdentifier(n.name, name) == 0:
  350. result = n
  351. else:
  352. let m = selectBranch(p, n)
  353. if m != nil: result = getFieldNode(p, m, name)
  354. proc `[]=`*(x: Any, fieldName: string, value: Any) =
  355. ## Sets a field of `x`. `x` needs to represent an object or a tuple.
  356. var t = x.rawType
  357. # XXX BUG: does not work yet, however is questionable anyway
  358. when false:
  359. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  360. assert x.rawType.kind in {tyTuple, tyObject}
  361. let n = getFieldNode(x.value, t.node, fieldName)
  362. if n != nil:
  363. assert n.typ == value.rawType
  364. genericAssign(x.value +!! n.offset, value.value, value.rawType)
  365. else:
  366. raise newException(ValueError, "invalid field name: " & fieldName)
  367. proc `[]`*(x: Any, fieldName: string): Any =
  368. ## Gets a field of `x`. `x` needs to represent an object or a tuple.
  369. var t = x.rawType
  370. # XXX BUG: does not work yet, however is questionable anyway
  371. when false:
  372. if x.rawType.kind == tyObject: t = cast[ptr PNimType](x.value)[]
  373. assert x.rawType.kind in {tyTuple, tyObject}
  374. let n = getFieldNode(x.value, t.node, fieldName)
  375. if n != nil:
  376. result = Any(value: x.value +!! n.offset)
  377. result.rawType = n.typ
  378. elif x.rawType.kind == tyObject and x.rawType.base != nil:
  379. return `[]`(newAny(x.value, x.rawType.base), fieldName)
  380. else:
  381. raise newException(ValueError, "invalid field name: " & fieldName)
  382. proc `[]`*(x: Any): Any =
  383. ## Dereference operator for `Any`. `x` needs to represent a ptr or a ref.
  384. assert x.rawType.kind in {tyRef, tyPtr}
  385. result = Any(value: cast[ppointer](x.value)[])
  386. result.rawType = x.rawType.base
  387. proc `[]=`*(x, y: Any) =
  388. ## Dereference operator for `Any`. `x` needs to represent a ptr or a ref.
  389. assert x.rawType.kind in {tyRef, tyPtr}
  390. assert y.rawType == x.rawType.base
  391. genericAssign(cast[ppointer](x.value)[], y.value, y.rawType)
  392. proc getInt*(x: Any): int =
  393. ## Retrieves the `int` value out of `x`. `x` needs to represent an `int`.
  394. assert skipRange(x.rawType).kind == tyInt
  395. result = cast[ptr int](x.value)[]
  396. proc getInt8*(x: Any): int8 =
  397. ## Retrieves the `int8` value out of `x`. `x` needs to represent an `int8`.
  398. assert skipRange(x.rawType).kind == tyInt8
  399. result = cast[ptr int8](x.value)[]
  400. proc getInt16*(x: Any): int16 =
  401. ## Retrieves the `int16` value out of `x`. `x` needs to represent an `int16`.
  402. assert skipRange(x.rawType).kind == tyInt16
  403. result = cast[ptr int16](x.value)[]
  404. proc getInt32*(x: Any): int32 =
  405. ## Retrieves the `int32` value out of `x`. `x` needs to represent an `int32`.
  406. assert skipRange(x.rawType).kind == tyInt32
  407. result = cast[ptr int32](x.value)[]
  408. proc getInt64*(x: Any): int64 =
  409. ## Retrieves the `int64` value out of `x`. `x` needs to represent an `int64`.
  410. assert skipRange(x.rawType).kind == tyInt64
  411. result = cast[ptr int64](x.value)[]
  412. proc getBiggestInt*(x: Any): BiggestInt =
  413. ## Retrieves the integer value out of `x`. `x` needs to represent
  414. ## some integer, a bool, a char, an enum or a small enough bit set.
  415. ## The value might be sign-extended to `BiggestInt`.
  416. let t = skipRange(x.rawType)
  417. case t.kind
  418. of tyInt: result = BiggestInt(cast[ptr int](x.value)[])
  419. of tyInt8: result = BiggestInt(cast[ptr int8](x.value)[])
  420. of tyInt16: result = BiggestInt(cast[ptr int16](x.value)[])
  421. of tyInt32: result = BiggestInt(cast[ptr int32](x.value)[])
  422. of tyInt64, tyUInt64: result = BiggestInt(cast[ptr int64](x.value)[])
  423. of tyBool: result = BiggestInt(cast[ptr bool](x.value)[])
  424. of tyChar: result = BiggestInt(cast[ptr char](x.value)[])
  425. of tyEnum, tySet:
  426. case t.size
  427. of 1: result = int64(cast[ptr uint8](x.value)[])
  428. of 2: result = int64(cast[ptr uint16](x.value)[])
  429. of 4: result = BiggestInt(cast[ptr int32](x.value)[])
  430. of 8: result = BiggestInt(cast[ptr int64](x.value)[])
  431. else: raiseAssert "unreachable"
  432. of tyUInt: result = BiggestInt(cast[ptr uint](x.value)[])
  433. of tyUInt8: result = BiggestInt(cast[ptr uint8](x.value)[])
  434. of tyUInt16: result = BiggestInt(cast[ptr uint16](x.value)[])
  435. of tyUInt32: result = BiggestInt(cast[ptr uint32](x.value)[])
  436. else: raiseAssert "unreachable"
  437. proc setBiggestInt*(x: Any, y: BiggestInt) =
  438. ## Sets the integer value of `x`. `x` needs to represent
  439. ## some integer, a bool, a char, an enum or a small enough bit set.
  440. let t = skipRange(x.rawType)
  441. case t.kind
  442. of tyInt: cast[ptr int](x.value)[] = int(y)
  443. of tyInt8: cast[ptr int8](x.value)[] = int8(y)
  444. of tyInt16: cast[ptr int16](x.value)[] = int16(y)
  445. of tyInt32: cast[ptr int32](x.value)[] = int32(y)
  446. of tyInt64, tyUInt64: cast[ptr int64](x.value)[] = int64(y)
  447. of tyBool: cast[ptr bool](x.value)[] = y != 0
  448. of tyChar: cast[ptr char](x.value)[] = chr(y.int)
  449. of tyEnum, tySet:
  450. case t.size
  451. of 1: cast[ptr uint8](x.value)[] = uint8(y.int)
  452. of 2: cast[ptr uint16](x.value)[] = uint16(y.int)
  453. of 4: cast[ptr int32](x.value)[] = int32(y)
  454. of 8: cast[ptr int64](x.value)[] = y
  455. else: assert false
  456. of tyUInt: cast[ptr uint](x.value)[] = uint(y)
  457. of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
  458. of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
  459. of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
  460. else: assert false
  461. proc getUInt*(x: Any): uint =
  462. ## Retrieves the `uint` value out of `x`. `x` needs to represent a `uint`.
  463. assert skipRange(x.rawType).kind == tyUInt
  464. result = cast[ptr uint](x.value)[]
  465. proc getUInt8*(x: Any): uint8 =
  466. ## Retrieves the `uint8` value out of `x`. `x` needs to represent a `uint8`.
  467. assert skipRange(x.rawType).kind == tyUInt8
  468. result = cast[ptr uint8](x.value)[]
  469. proc getUInt16*(x: Any): uint16 =
  470. ## Retrieves the `uint16` value out of `x`. `x` needs to represent a `uint16`.
  471. assert skipRange(x.rawType).kind == tyUInt16
  472. result = cast[ptr uint16](x.value)[]
  473. proc getUInt32*(x: Any): uint32 =
  474. ## Retrieves the `uint32` value out of `x`. `x` needs to represent a `uint32`.
  475. assert skipRange(x.rawType).kind == tyUInt32
  476. result = cast[ptr uint32](x.value)[]
  477. proc getUInt64*(x: Any): uint64 =
  478. ## Retrieves the `uint64` value out of `x`. `x` needs to represent a `uint64`.
  479. assert skipRange(x.rawType).kind == tyUInt64
  480. result = cast[ptr uint64](x.value)[]
  481. proc getBiggestUint*(x: Any): uint64 =
  482. ## Retrieves the unsigned integer value out of `x`. `x` needs to
  483. ## represent an unsigned integer.
  484. let t = skipRange(x.rawType)
  485. case t.kind
  486. of tyUInt: result = uint64(cast[ptr uint](x.value)[])
  487. of tyUInt8: result = uint64(cast[ptr uint8](x.value)[])
  488. of tyUInt16: result = uint64(cast[ptr uint16](x.value)[])
  489. of tyUInt32: result = uint64(cast[ptr uint32](x.value)[])
  490. of tyUInt64: result = uint64(cast[ptr uint64](x.value)[])
  491. else: raiseAssert "unreachable"
  492. proc setBiggestUint*(x: Any; y: uint64) =
  493. ## Sets the unsigned integer value of `x`. `x` needs to represent an
  494. ## unsigned integer.
  495. let t = skipRange(x.rawType)
  496. case t.kind:
  497. of tyUInt: cast[ptr uint](x.value)[] = uint(y)
  498. of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
  499. of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
  500. of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
  501. of tyUInt64: cast[ptr uint64](x.value)[] = uint64(y)
  502. else: raiseAssert "unreachable"
  503. proc getChar*(x: Any): char =
  504. ## Retrieves the `char` value out of `x`. `x` needs to represent a `char`.
  505. let t = skipRange(x.rawType)
  506. assert t.kind == tyChar
  507. result = cast[ptr char](x.value)[]
  508. proc getBool*(x: Any): bool =
  509. ## Retrieves the `bool` value out of `x`. `x` needs to represent a `bool`.
  510. let t = skipRange(x.rawType)
  511. assert t.kind == tyBool
  512. result = cast[ptr bool](x.value)[]
  513. proc skipRange*(x: Any): Any =
  514. ## Skips the range information of `x`.
  515. assert x.rawType.kind == tyRange
  516. result = Any(value: x.value)
  517. result.rawType = x.rawType.base
  518. proc getEnumOrdinal*(x: Any, name: string): int =
  519. ## Gets the enum field ordinal from `name`. `x` needs to represent an enum
  520. ## but is only used to access the type information. In case of an error
  521. ## `low(int)` is returned.
  522. let typ = skipRange(x.rawType)
  523. assert typ.kind == tyEnum
  524. let n = typ.node
  525. let s = n.sons
  526. for i in 0 .. n.len-1:
  527. if cmpNimIdentifier($s[i].name, name) == 0:
  528. if ntfEnumHole notin typ.flags:
  529. return i
  530. else:
  531. return s[i].offset
  532. result = low(int)
  533. proc getEnumField*(x: Any, ordinalValue: int): string =
  534. ## Gets the enum field name as a string. `x` needs to represent an enum
  535. ## but is only used to access the type information. The field name of
  536. ## `ordinalValue` is returned.
  537. let typ = skipRange(x.rawType)
  538. assert typ.kind == tyEnum
  539. let e = ordinalValue
  540. if ntfEnumHole notin typ.flags:
  541. if e <% typ.node.len:
  542. return $typ.node.sons[e].name
  543. else:
  544. # ugh we need a slow linear search:
  545. let n = typ.node
  546. let s = n.sons
  547. for i in 0 .. n.len-1:
  548. if s[i].offset == e: return $s[i].name
  549. result = $e
  550. proc getEnumField*(x: Any): string =
  551. ## Gets the enum field name as a string. `x` needs to represent an enum.
  552. result = getEnumField(x, getBiggestInt(x).int)
  553. proc getFloat*(x: Any): float =
  554. ## Retrieves the `float` value out of `x`. `x` needs to represent a `float`.
  555. assert skipRange(x.rawType).kind == tyFloat
  556. result = cast[ptr float](x.value)[]
  557. proc getFloat32*(x: Any): float32 =
  558. ## Retrieves the `float32` value out of `x`. `x` needs to represent a `float32`.
  559. assert skipRange(x.rawType).kind == tyFloat32
  560. result = cast[ptr float32](x.value)[]
  561. proc getFloat64*(x: Any): float64 =
  562. ## Retrieves the `float64` value out of `x`. `x` needs to represent a `float64`.
  563. assert skipRange(x.rawType).kind == tyFloat64
  564. result = cast[ptr float64](x.value)[]
  565. proc getBiggestFloat*(x: Any): BiggestFloat =
  566. ## Retrieves the float value out of `x`. `x` needs to represent
  567. ## some float. The value is extended to `BiggestFloat`.
  568. case skipRange(x.rawType).kind
  569. of tyFloat: result = BiggestFloat(cast[ptr float](x.value)[])
  570. of tyFloat32: result = BiggestFloat(cast[ptr float32](x.value)[])
  571. of tyFloat64: result = BiggestFloat(cast[ptr float64](x.value)[])
  572. else: raiseAssert "unreachable"
  573. proc setBiggestFloat*(x: Any, y: BiggestFloat) =
  574. ## Sets the float value of `x`. `x` needs to represent
  575. ## some float.
  576. case skipRange(x.rawType).kind
  577. of tyFloat: cast[ptr float](x.value)[] = y
  578. of tyFloat32: cast[ptr float32](x.value)[] = y.float32
  579. of tyFloat64: cast[ptr float64](x.value)[] = y
  580. else: raiseAssert "unreachable"
  581. proc getString*(x: Any): string =
  582. ## Retrieves the `string` value out of `x`. `x` needs to represent a `string`.
  583. assert x.rawType.kind == tyString
  584. when defined(gcDestructors):
  585. result = cast[ptr string](x.value)[]
  586. else:
  587. if not isNil(cast[ptr pointer](x.value)[]):
  588. result = cast[ptr string](x.value)[]
  589. proc setString*(x: Any, y: string) =
  590. ## Sets the `string` value of `x`. `x` needs to represent a `string`.
  591. assert x.rawType.kind == tyString
  592. cast[ptr string](x.value)[] = y # also correct for gcDestructors
  593. proc getCString*(x: Any): cstring =
  594. ## Retrieves the `cstring` value out of `x`. `x` needs to represent a `cstring`.
  595. assert x.rawType.kind == tyCstring
  596. result = cast[ptr cstring](x.value)[]
  597. proc assign*(x, y: Any) =
  598. ## Copies the value of `y` to `x`. The assignment operator for `Any`
  599. ## does NOT do this; it performs a shallow copy instead!
  600. assert y.rawType == x.rawType
  601. genericAssign(x.value, y.value, y.rawType)
  602. iterator elements*(x: Any): int =
  603. ## Iterates over every element of `x`. `x` needs to represent a `set`.
  604. assert x.rawType.kind == tySet
  605. let typ = x.rawType
  606. let p = x.value
  607. # "typ.slots.len" field is for sets the "first" field
  608. var u: int64 = 0'i64
  609. case typ.size
  610. of 1: u = int64(cast[ptr uint8](p)[])
  611. of 2: u = int64(cast[ptr uint16](p)[])
  612. of 4: u = int64(cast[ptr uint32](p)[])
  613. of 8: u = cast[ptr int64](p)[]
  614. else:
  615. let a = cast[pbyteArray](p)
  616. for i in 0 .. typ.size*8-1:
  617. if (int(a[i div 8]) and (1 shl (i mod 8))) != 0:
  618. yield i + typ.node.len
  619. if typ.size <= 8:
  620. for i in 0..sizeof(int64)*8-1:
  621. if (u and (1'i64 shl int64(i))) != 0'i64:
  622. yield i + typ.node.len
  623. proc inclSetElement*(x: Any, elem: int) =
  624. ## Includes an element `elem` in `x`. `x` needs to represent a Nim bitset.
  625. assert x.rawType.kind == tySet
  626. let typ = x.rawType
  627. let p = x.value
  628. # "typ.slots.len" field is for sets the "first" field
  629. let e = elem - typ.node.len
  630. case typ.size
  631. of 1:
  632. var a = cast[ptr int8](p)
  633. a[] = a[] or (1'i8 shl int8(e))
  634. of 2:
  635. var a = cast[ptr int16](p)
  636. a[] = a[] or (1'i16 shl int16(e))
  637. of 4:
  638. var a = cast[ptr int32](p)
  639. a[] = a[] or (1'i32 shl int32(e))
  640. of 8:
  641. var a = cast[ptr int64](p)
  642. a[] = a[] or (1'i64 shl e)
  643. else:
  644. var a = cast[pbyteArray](p)
  645. a[e shr 3] = a[e shr 3] or uint8(1 shl (e and 7))