dollars.nim 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
  2. ## The stringify operator for an integer argument. Returns `x`
  3. ## converted to a decimal string. `$` is Nim's general way of
  4. ## spelling `toString`:idx:.
  5. template dollarImpl(x: uint | uint64, result: var string) =
  6. type destTyp = typeof(x)
  7. if x == 0:
  8. result = "0"
  9. else:
  10. result = newString(60)
  11. var i = 0
  12. var n = x
  13. while n != 0:
  14. let nn = n div destTyp(10)
  15. result[i] = char(n - destTyp(10) * nn + ord('0'))
  16. inc i
  17. n = nn
  18. result.setLen i
  19. let half = i div 2
  20. # Reverse
  21. for t in 0 .. half-1: swap(result[t], result[i-t-1])
  22. when defined(js):
  23. import std/private/since
  24. since (1, 3):
  25. proc `$`*(x: uint): string =
  26. ## Caveat: currently implemented as $(cast[int](x)), tied to current
  27. ## semantics of js' Number type.
  28. # for c, see strmantle.`$`
  29. when nimvm:
  30. dollarImpl(x, result)
  31. else:
  32. result = $(int(x))
  33. proc `$`*(x: uint64): string =
  34. ## Compatibility note:
  35. ## the results may change in future releases if/when js target implements
  36. ## 64bit ints.
  37. # pending https://github.com/nim-lang/RFCs/issues/187
  38. when nimvm:
  39. dollarImpl(x, result)
  40. else:
  41. result = $(cast[int](x))
  42. else:
  43. proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
  44. ## The stringify operator for an unsigned integer argument. Returns `x`
  45. ## converted to a decimal string.
  46. dollarImpl(x, result)
  47. proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
  48. ## The stringify operator for an integer argument. Returns `x`
  49. ## converted to a decimal string.
  50. proc `$`*(x: float): string {.magic: "FloatToStr", noSideEffect.}
  51. ## The stringify operator for a float argument. Returns `x`
  52. ## converted to a decimal string.
  53. proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
  54. ## The stringify operator for a boolean argument. Returns `x`
  55. ## converted to the string "false" or "true".
  56. proc `$`*(x: char): string {.magic: "CharToStr", noSideEffect.}
  57. ## The stringify operator for a character argument. Returns `x`
  58. ## converted to a string.
  59. ##
  60. ## .. code-block:: Nim
  61. ## assert $'c' == "c"
  62. proc `$`*(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
  63. ## The stringify operator for a CString argument. Returns `x`
  64. ## converted to a string.
  65. proc `$`*(x: string): string {.magic: "StrToStr", noSideEffect.}
  66. ## The stringify operator for a string argument. Returns `x`
  67. ## as it is. This operator is useful for generic code, so
  68. ## that `$expr` also works if `expr` is already a string.
  69. proc `$`*[Enum: enum](x: Enum): string {.magic: "EnumToStr", noSideEffect.}
  70. ## The stringify operator for an enumeration argument. This works for
  71. ## any enumeration type thanks to compiler magic.
  72. ##
  73. ## If a `$` operator for a concrete enumeration is provided, this is
  74. ## used instead. (In other words: *Overwriting* is possible.)
  75. proc `$`*(t: typedesc): string {.magic: "TypeTrait".}
  76. ## Returns the name of the given type.
  77. ##
  78. ## For more procedures dealing with `typedesc`, see
  79. ## `typetraits module <typetraits.html>`_.
  80. ##
  81. ## .. code-block:: Nim
  82. ## doAssert $(typeof(42)) == "int"
  83. ## doAssert $(typeof("Foo")) == "string"
  84. ## static: doAssert $(typeof(@['A', 'B'])) == "seq[char]"
  85. when defined(nimHasIsNamedTuple):
  86. proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
  87. else:
  88. # for bootstrap; remove after release 1.2
  89. proc isNamedTuple(T: typedesc): bool =
  90. # Taken from typetraits.
  91. when T isnot tuple: result = false
  92. else:
  93. var t: T
  94. for name, _ in t.fieldPairs:
  95. when name == "Field0":
  96. return compiles(t.Field0)
  97. else:
  98. return true
  99. return false
  100. proc `$`*[T: tuple|object](x: T): string =
  101. ## Generic `$` operator for tuples that is lifted from the components
  102. ## of `x`. Example:
  103. ##
  104. ## .. code-block:: Nim
  105. ## $(23, 45) == "(23, 45)"
  106. ## $(a: 23, b: 45) == "(a: 23, b: 45)"
  107. ## $() == "()"
  108. result = "("
  109. const isNamed = T is object or isNamedTuple(T)
  110. var count = 0
  111. for name, value in fieldPairs(x):
  112. if count > 0: result.add(", ")
  113. when isNamed:
  114. result.add(name)
  115. result.add(": ")
  116. count.inc
  117. when compiles($value):
  118. when value isnot string and value isnot seq and compiles(value.isNil):
  119. if value.isNil: result.add "nil"
  120. else: result.addQuoted(value)
  121. else:
  122. result.addQuoted(value)
  123. else:
  124. result.add("...")
  125. when not isNamed:
  126. if count == 1:
  127. result.add(",") # $(1,) should print as the semantically legal (1,)
  128. result.add(")")
  129. proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
  130. result = prefix
  131. var firstElement = true
  132. for value in items(x):
  133. if firstElement:
  134. firstElement = false
  135. else:
  136. result.add(separator)
  137. when value isnot string and value isnot seq and compiles(value.isNil):
  138. # this branch should not be necessary
  139. if value.isNil:
  140. result.add "nil"
  141. else:
  142. result.addQuoted(value)
  143. else:
  144. result.addQuoted(value)
  145. result.add(suffix)
  146. proc `$`*[T](x: set[T]): string =
  147. ## Generic `$` operator for sets that is lifted from the components
  148. ## of `x`. Example:
  149. ##
  150. ## .. code-block:: Nim
  151. ## ${23, 45} == "{23, 45}"
  152. collectionToString(x, "{", ", ", "}")
  153. proc `$`*[T](x: seq[T]): string =
  154. ## Generic `$` operator for seqs that is lifted from the components
  155. ## of `x`. Example:
  156. ##
  157. ## .. code-block:: Nim
  158. ## $(@[23, 45]) == "@[23, 45]"
  159. collectionToString(x, "@[", ", ", "]")
  160. proc `$`*[T, U](x: HSlice[T, U]): string =
  161. ## Generic `$` operator for slices that is lifted from the components
  162. ## of `x`. Example:
  163. ##
  164. ## .. code-block:: Nim
  165. ## $(1 .. 5) == "1 .. 5"
  166. result = $x.a
  167. result.add(" .. ")
  168. result.add($x.b)
  169. when not defined(nimNoArrayToString):
  170. proc `$`*[T, IDX](x: array[IDX, T]): string =
  171. ## Generic `$` operator for arrays that is lifted from the components.
  172. collectionToString(x, "[", ", ", "]")
  173. proc `$`*[T](x: openArray[T]): string =
  174. ## Generic `$` operator for openarrays that is lifted from the components
  175. ## of `x`. Example:
  176. ##
  177. ## .. code-block:: Nim
  178. ## $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
  179. collectionToString(x, "[", ", ", "]")