from std/private/digitsutils import addInt template toLocation*(result: var string, file: string | cstring, line: int, col: int) = ## avoids spurious allocations # Hopefully this can be re-used everywhere so that if a user needs to customize, # it can be done in a single place. result.add file if line > 0: result.add "(" addInt(result, line) if col > 0: 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(")")