diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/typetraits.nim | 3 | ||||
-rw-r--r-- | lib/system.nim | 21 | ||||
-rw-r--r-- | lib/system/helpers.nim | 19 | ||||
-rw-r--r-- | lib/system/helpers2.nim | 2 |
4 files changed, 39 insertions, 6 deletions
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim index 5f5bfdbd7..a373a9370 100644 --- a/lib/pure/typetraits.nim +++ b/lib/pure/typetraits.nim @@ -10,7 +10,10 @@ ## This module defines compile-time reflection procs for ## working with types +include "system/helpers" # for `isNamedTuple` + export system.`$` +export isNamedTuple proc name*(t: typedesc): string {.magic: "TypeTrait".} ## Alias for system.`$`(t) since Nim v0.20.0. diff --git a/lib/system.nim b/lib/system.nim index 1d2401940..c68eba2e0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2669,19 +2669,28 @@ proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime. ## echo "'+' for integers is available" discard +include "system/helpers" # for `lineInfoToString`, `isNamedTuple` + proc `$`*[T: tuple|object](x: T): string = ## generic ``$`` operator for tuples that is lifted from the components ## of `x`. Example: ## ## .. code-block:: nim - ## $(23, 45) == "(Field0: 23, Field1: 45)" + ## $(23, 45) == "(23, 45)" + ## $(a: 23, b: 45) == "(a: 23, b: 45)" ## $() == "()" result = "(" 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(", ") - result.add(name) - result.add(": ") + when isNamed: + result.add(name) + result.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" @@ -2691,6 +2700,10 @@ proc `$`*[T: tuple|object](x: T): string = firstElement = false else: result.add("...") + when not isNamed: + if count == 1: + result.add(",") # $(1,) should print as the semantically legal (1,) + result.add(")") proc collectionToString[T](x: T, prefix, separator, suffix: string): string = @@ -3958,8 +3971,6 @@ proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} = tags: [].} Hide(raiseAssert)(msg) -include "system/helpers" # for `lineInfoToString` - template assertImpl(cond: bool, msg: string, expr: string, enabled: static[bool]) = const loc = $instantiationInfo(-1, true) bind instantiationInfo diff --git a/lib/system/helpers.nim b/lib/system/helpers.nim index 7b2b32679..a7e47915e 100644 --- a/lib/system/helpers.nim +++ b/lib/system/helpers.nim @@ -6,6 +6,23 @@ proc lineInfoToString(file: string, line, column: int): string = file & "(" & $line & ", " & $column & ")" -proc `$`(info: type(instantiationInfo(0))): string = +type InstantiationInfo = tuple[filename: string, line: int, column: int] + +proc `$`(info: InstantiationInfo): string = # The +1 is needed here + # instead of overriding `$` (and changing its meaning), consider explicit name. lineInfoToString(info.fileName, info.line, info.column+1) + +proc isNamedTuple(T: type): bool = + ## return true for named tuples, false for any other type. + 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 + # empty tuple should be un-named, + # see https://github.com/nim-lang/Nim/issues/8861#issue-356631191 + return false diff --git a/lib/system/helpers2.nim b/lib/system/helpers2.nim index 1c9e7c068..c67a2c278 100644 --- a/lib/system/helpers2.nim +++ b/lib/system/helpers2.nim @@ -1,3 +1,5 @@ +# imported by other modules, unlike helpers.nim which is included + template formatErrorIndexBound*[T](i, a, b: T): string = "index out of bounds: (a:" & $a & ") <= (i:" & $i & ") <= (b:" & $b & ") " |