1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
include system/inclrtl
when defined(nimPreviewSlimSystem):
import std/formatfloat
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
## imported from typetraits
proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
## imported from typetraits
proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".}
# skip one level of range; return the base type of a range type
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
proc repr*(x: int): string =
## Same as $x
$x
proc repr*(x: int64): string =
## Same as $x
$x
proc repr*(x: uint64): string {.noSideEffect.} =
## Same as $x
$x
proc repr*(x: float): string =
## Same as $x
$x
proc repr*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## repr for a boolean argument. Returns `x`
## converted to the string "false" or "true".
proc repr*(x: char): string {.noSideEffect, raises: [].} =
## repr for a character argument. Returns `x`
## converted to an escaped string.
##
## ```Nim
## assert repr('c') == "'c'"
## ```
result = "'"
# Elides string creations if not needed
if x in {'\\', '\0'..'\31', '\127'..'\255'}:
result.add '\\'
if x in {'\0'..'\31', '\127'..'\255'}:
result.add $x.uint8
else:
result.add x
result.add '\''
proc repr*(x: string | cstring): string {.noSideEffect, raises: [].} =
## repr for a string argument. Returns `x`
## converted to a quoted and escaped string.
result = "\""
for i in 0..<x.len:
if x[i] in {'"', '\\', '\0'..'\31', '\127'..'\255'}:
result.add '\\'
case x[i]:
of '\n':
result.add "n\n"
of '\0'..'\9', '\11'..'\31', '\127'..'\255':
result.add $x[i].uint8
else:
result.add x[i]
result.add '\"'
proc repr*[Enum: enum](x: Enum): string {.magic: "EnumToStr", noSideEffect, raises: [].}
## repr for an enumeration argument. This works for
## any enumeration type thanks to compiler magic.
##
## If a `repr` operator for a concrete enumeration is provided, this is
## used instead. (In other words: *Overwriting* is possible.)
proc reprDiscriminant*(e: int): string {.compilerproc.} =
# repr and reprjs can use `PNimType` to symbolize `e`; making this work here
# would require a way to pass the set of enum stringified values to cgen.
$e
proc repr*(p: pointer): string =
## repr of pointer as its hexadecimal value
if p == nil:
result = "nil"
else:
when nimvm:
result = "ptr"
else:
const HexChars = "0123456789ABCDEF"
const len = sizeof(pointer) * 2
var n = cast[uint](p)
result = newString(len)
for j in countdown(len-1, 0):
result[j] = HexChars[n and 0xF]
n = n shr 4
proc repr*(p: proc | iterator {.closure.}): string =
## repr of a proc as its address
repr(cast[ptr pointer](unsafeAddr p)[])
template repr*[T: distinct|(range and not enum)](x: T): string =
when T is range: # add a branch to handle range
repr(rangeBase(typeof(x))(x))
elif T is distinct:
repr(distinctBase(typeof(x))(x))
else:
{.error: "cannot happen".}
template repr*(t: typedesc): string = $t
proc reprObject[T: tuple|object](res: var string, x: T) {.noSideEffect, raises: [].} =
res.add '('
var firstElement = true
const isNamed = T is object or isNamedTuple(T)
when not isNamed:
var count = 0
for name, value in fieldPairs(x):
if not firstElement: res.add(", ")
when isNamed:
res.add(name)
res.add(": ")
else:
count.inc
res.add repr(value)
firstElement = false
when not isNamed:
if count == 1:
res.add(',') # $(1,) should print as the semantically legal (1,)
res.add(')')
proc repr*[T: tuple|object](x: T): string {.noSideEffect, raises: [].} =
## Generic `repr` operator for tuples that is lifted from the components
## of `x`. Example:
## ```Nim
## $(23, 45) == "(23, 45)"
## $(a: 23, b: 45) == "(a: 23, b: 45)"
## $() == "()"
## ```
when T is object:
result = $typeof(x)
reprObject(result, x)
proc repr*[T](x: ref T | ptr T): string {.noSideEffect, raises: [].} =
if isNil(x): return "nil"
when T is object:
result = $typeof(x)
reprObject(result, x[])
else:
result = when typeof(x) is ref: "ref " else: "ptr "
result.add repr(x[])
proc collectionToRepr[T](x: T, prefix, separator, suffix: string): string {.noSideEffect, raises: [].} =
result = prefix
var firstElement = true
for value in items(x):
if firstElement:
firstElement = false
else:
result.add(separator)
result.add repr(value)
result.add(suffix)
proc repr*[T](x: set[T]): string =
## Generic `repr` operator for sets that is lifted from the components
## of `x`. Example:
## ```Nim
## ${23, 45} == "{23, 45}"
## ```
collectionToRepr(x, "{", ", ", "}")
proc repr*[T](x: seq[T]): string =
## Generic `repr` operator for seqs that is lifted from the components
## of `x`. Example:
## ```Nim
## $(@[23, 45]) == "@[23, 45]"
## ```
collectionToRepr(x, "@[", ", ", "]")
proc repr*[T, IDX](x: array[IDX, T]): string =
## Generic `repr` operator for arrays that is lifted from the components.
collectionToRepr(x, "[", ", ", "]")
proc repr*[T](x: openArray[T]): string =
## Generic `repr` operator for openarrays that is lifted from the components
## of `x`. Example:
## ```Nim
## $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
## ```
collectionToRepr(x, "[", ", ", "]")
proc repr*[T](x: UncheckedArray[T]): string =
"[...]"
|