Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1988,10 +1988,6 @@ template unlikely*(val: bool): bool =
import system/dollars
export dollars

when defined(nimV2):
import system/repr_v2
export repr_v2

const
NimMajor* {.intdefine.}: int = 1
## is the major number of Nim's version.
Expand Down Expand Up @@ -2620,7 +2616,8 @@ type
## Represents a Nim AST node. Macros operate on this type.

when defined(nimV2):
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
import system/repr_v2
export repr_v2

macro lenVarargs*(x: varargs[untyped]): int {.since: (1, 1).} =
## returns number of variadic arguments in `x`
Expand Down
130 changes: 59 additions & 71 deletions lib/system/repr_v2.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
## imported from typetraits

proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".}
## imported from typetraits

proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}

proc repr*(x: int): string {.magic: "IntToStr", noSideEffect.}
## repr for an integer argument. Returns `x`
## converted to a decimal string.
Expand Down Expand Up @@ -37,80 +45,68 @@ proc repr*[Enum: enum](x: Enum): string {.magic: "EnumToStr", noSideEffect.}
## If a `repr` operator for a concrete enumeration is provided, this is
## used instead. (In other words: *Overwriting* is possible.)

template repr(t: typedesc): string = $t

proc isNamedTuple(T: typedesc): bool =
# Taken from typetraits.
when T isnot tuple: result = false
proc repr*(p: pointer): string =
## repr of pointer as its hexadecimal value
if p == nil:
result = "nil"
else:
var t: T
for name, _ in t.fieldPairs:
when name == "Field0":
return compiles(t.Field0)
else:
return true
return false
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*[T: tuple|object](x: T): string =
## Generic `repr` operator for tuples that is lifted from the components
## of `x`. Example:
##
## .. code-block:: Nim
## $(23, 45) == "(23, 45)"
## $(a: 23, b: 45) == "(a: 23, b: 45)"
## $() == "()"
when T is object:
result = $typeof(x)
else:
result = ""
result.add '('
template repr*(x: distinct): string =
repr(distinctBase(typeof(x))(x))

template repr*(t: typedesc): string = $t

proc reprObject[T: tuple|object](res: var string, x: T) =
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: result.add(", ")
if not firstElement: res.add(", ")
when isNamed:
result.add(name)
result.add(": ")
res.add(name)
res.add(": ")
else:
count.inc
when compiles($value):
when value isnot string and value isnot seq and compiles(value.isNil):
if value.isNil: result.add "nil"
else: result.addQuoted(value)
else:
result.addQuoted(value)
firstElement = false
else:
result.add("...")
firstElement = false
res.add repr(value)
firstElement = false
when not isNamed:
if count == 1:
result.add(',') # $(1,) should print as the semantically legal (1,)
result.add(')')
res.add(',') # $(1,) should print as the semantically legal (1,)
res.add(')')


proc repr*[T: (ref object)](x: T): string =
proc repr*[T: tuple|object](x: T): string =
## Generic `repr` operator for tuples that is lifted from the components
## of `x`.
if x == nil: return "nil"
result = $typeof(x) & "("
var firstElement = true
for name, value in fieldPairs(x[]):
if not firstElement: result.add(", ")
result.add(name)
result.add(": ")
when compiles($value):
when value isnot string and value isnot seq and compiles(value.isNil):
if value.isNil: result.add "nil"
else: result.addQuoted(value)
else:
result.addQuoted(value)
firstElement = false
else:
result.add("...")
firstElement = false
result.add(')')
## of `x`. Example:
##
## .. code-block:: 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: ptr T): string =
result.add repr(pointer(x)) & " "
result.add repr(x[])

proc repr*[T](x: ref T | ptr T): string =
if isNil(x): return "nil"
result = $typeof(x)
reprObject(result, x[])

proc collectionToRepr[T](x: T, prefix, separator, suffix: string): string =
result = prefix
Expand All @@ -120,15 +116,7 @@ proc collectionToRepr[T](x: T, prefix, separator, suffix: string): string =
firstElement = false
else:
result.add(separator)

when value isnot string and value isnot seq and compiles(value.isNil):
# this branch should not be necessary
if value.isNil:
result.add "nil"
else:
result.addQuoted(value)
else:
result.addQuoted(value)
result.add repr(value)
result.add(suffix)

proc repr*[T](x: set[T]): string =
Expand All @@ -153,9 +141,9 @@ proc repr*[T, U](x: HSlice[T, U]): string =
##
## .. code-block:: Nim
## $(1 .. 5) == "1 .. 5"
result = $x.a
result = repr(x.a)
result.add(" .. ")
result.add($x.b)
result.add(repr(x.b))

proc repr*[T, IDX](x: array[IDX, T]): string =
## Generic `repr` operator for arrays that is lifted from the components.
Expand Down
34 changes: 34 additions & 0 deletions tests/arc/trepr.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
discard """
cmd: "nim c --gc:arc $file"
nimout: '''(a: true, n: doAssert)
Table[system.string, trepr.MyType](data: @[], counter: 0)
nil
'''
"""
import tables

type
NimSym = distinct NimNode
MyType = tuple
a: bool
n: NimSym

proc myproc(t: MyType) =
echo repr(t)

proc myproc2(t: MyType) =
var x = Table[string, t]()
echo repr(x)

proc myproc3(t: MyType) =
var x: TableRef[string, t]
echo repr(x)


macro dumpSym(a: typed) =
myproc((a: true, n: NimSym(a)))
myproc2((a: true, n: NimSym(a)))
myproc3((a: true, n: NimSym(a)))

dumpSym(doAssert)

2 changes: 1 addition & 1 deletion tests/destructor/tfinalizer.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
discard """
cmd: "nim c --gc:arc $file"
output: '''Foo(field: "Dick Laurent", k: ka, x: 0.0)
output: '''Foo(field: Dick Laurent, k: ka, x: 0.0)
Nobody is dead
Dick Laurent is dead'''
"""
Expand Down