Skip to content

Commit

Permalink
test removing dollar for objects out of system (nim-lang#20242)
Browse files Browse the repository at this point in the history
* test removing dollar for objects out of system

* test & fixes

* fix bootstrap

* use nimPreviewSlimSystem, test stdlib category

* fix test
  • Loading branch information
metagn authored and capocasa committed Mar 31, 2023
1 parent 505756a commit 5a2c64f
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 40 deletions.
3 changes: 3 additions & 0 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,9 @@ type
module*: int32
item*: int32

proc `$`*(x: ItemId): string =
"(module: " & $x.module & ", item: " & $x.item & ")"

proc `==`*(a, b: ItemId): bool {.inline.} =
a.item == b.item and a.module == b.module

Expand Down
2 changes: 2 additions & 0 deletions compiler/passaux.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ proc verboseOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext
# xxx consider either removing this or keeping for documentation for how to add a pass
result = VerboseRef(config: graph.config, idgen: idgen)

import std/objectdollar

proc verboseProcess(context: PPassContext, n: PNode): PNode =
# called from `process` in `processTopLevelStmt`.
result = n
Expand Down
3 changes: 3 additions & 0 deletions lib/pure/asyncfutures.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import os, tables, strutils, times, heapqueue, options, deques, cstrutils

import system/stacktraces

when defined(nimPreviewSlimSystem):
import std/objectdollar # for StackTraceEntry

# TODO: This shouldn't need to be included, but should ideally be exported.
type
CallbackFunc = proc () {.closure, gcsafe.}
Expand Down
11 changes: 11 additions & 0 deletions lib/std/objectdollar.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import std/private/miscdollars

proc `$`*[T: object](x: T): string =
## Generic `$` operator for objects with similar output to
## `$` for named tuples.
runnableExamples:
type Foo = object
a, b: int
let x = Foo(a: 23, b: 45)
assert $x == "(a: 23, b: 45)"
tupleObjectDollar(result, x)
39 changes: 39 additions & 0 deletions lib/std/private/miscdollars.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,42 @@ template toLocation*(result: var string, file: string | cstring, line: int, col:
result.add ", "
addInt(result, col)
result.add ")"

when defined(nimHasIsNamedTuple):
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
else:
# for bootstrap; remove after release 1.2
proc isNamedTuple(T: typedesc): bool =
# Taken from typetraits.
when T isnot tuple: result = false
else:
var t: T
for name, _ in t.fieldPairs:
when name == "Field0":
return compiles(t.Field0)
else:
return true
return false

template tupleObjectDollar*[T: tuple | object](result: var string, x: T) =
result = "("
const isNamed = T is object or isNamedTuple(typeof(T))
var count {.used.} = 0
for name, value in fieldPairs(x):
if count > 0: result.add(", ")
when isNamed:
result.add(name)
result.add(": ")
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)
else:
result.add("...")
when not isNamed:
if count == 1:
result.add(",") # $(1,) should print as the semantically legal (1,)
result.add(")")
46 changes: 6 additions & 40 deletions lib/system/dollars.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ runnableExamples:
assert $0.1 == "0.1"
assert $(-2*3) == "-6"

import std/private/digitsutils
import std/private/[digitsutils, miscdollars]
import system/formatfloat
export addFloat

Expand Down Expand Up @@ -69,53 +69,19 @@ proc `$`*(t: typedesc): string {.magic: "TypeTrait".}
## doAssert $(typeof("Foo")) == "string"
## static: doAssert $(typeof(@['A', 'B'])) == "seq[char]"

when defined(nimHasIsNamedTuple):
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
else:
# for bootstrap; remove after release 1.2
proc isNamedTuple(T: typedesc): bool =
# Taken from typetraits.
when T isnot tuple: result = false
else:
var t: T
for name, _ in t.fieldPairs:
when name == "Field0":
return compiles(t.Field0)
else:
return true
return false


proc `$`*[T: tuple|object](x: T): string =
proc `$`*[T: tuple](x: T): string =
## Generic `$` 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)"
## $() == "()"
result = "("
const isNamed = T is object or isNamedTuple(T)
var count {.used.} = 0
for name, value in fieldPairs(x):
if count > 0: result.add(", ")
when isNamed:
result.add(name)
result.add(": ")
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)
else:
result.add("...")
when not isNamed:
if count == 1:
result.add(",") # $(1,) should print as the semantically legal (1,)
result.add(")")
tupleObjectDollar(result, x)

when not defined(nimPreviewSlimSystem):
import std/objectdollar
export objectdollar

proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
result = prefix
Expand Down
14 changes: 14 additions & 0 deletions tests/stdlib/tobjectdollar.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
discard """
matrix: "-d:nimPreviewSlimSystem"
"""

import std/assertions

type Foo = object
a, b: int

let x = Foo(a: 23, b: 45)
doAssert not compiles($x)
import std/objectdollar
doAssert compiles($x)
doAssert $x == "(a: 23, b: 45)"
3 changes: 3 additions & 0 deletions tests/stdlib/toptions.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ discard """

import std/[json, options]

when defined(nimPreviewSlimSystem):
import std/objectdollar


# RefPerson is used to test that overloaded `==` operator is not called by
# options. It is defined here in the global scope, because otherwise the test
Expand Down
3 changes: 3 additions & 0 deletions tests/stdlib/tstrformat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import genericstrformat
import std/[strformat, strutils, times, tables, json]

when defined(nimPreviewSlimSystem):
import std/objectdollar

proc main() =
block: # issue #7632
doAssert works(5) == "formatted 5"
Expand Down

0 comments on commit 5a2c64f

Please sign in to comment.