Add optional recursive arg to distinctBase (v2) (#18659)

* Add optional recursive arg to distinctBase
* Add docs and examples

Co-authored-by: ALANVF <alan.invents@gmail.com>
This commit is contained in:
Timothee Cour 2021-08-08 23:51:39 -07:00 • committed by GitHub
commit 8ce782d463
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 10 deletions

View file

@ -190,9 +190,10 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
result = newIntNodeT(toInt128(operand.len), traitCall, c.idgen, c.graph) result = newIntNodeT(toInt128(operand.len), traitCall, c.idgen, c.graph)
of "distinctBase": of "distinctBase":
var arg = operand.skipTypes({tyGenericInst}) var arg = operand.skipTypes({tyGenericInst})
let rec = semConstExpr(c, traitCall[2]).intVal != 0
while arg.kind == tyDistinct: while arg.kind == tyDistinct:
arg = arg.base arg = arg.base.skipTypes(skippedTypes + {tyGenericInst})
arg = arg.skipTypes(skippedTypes + {tyGenericInst}) if not rec: break
result = getTypeDescNode(c, arg, operand.owner, traitCall.info) result = getTypeDescNode(c, arg, operand.owner, traitCall.info)
else: else:
localError(c.config, traitCall.info, "unknown trait: " & s) localError(c.config, traitCall.info, "unknown trait: " & s)

View file

@ -110,25 +110,32 @@ template pointerBase*[T](_: typedesc[ptr T | ref T]): typedesc =
assert (var s = "abc"; s[0].addr).typeof.pointerBase is char assert (var s = "abc"; s[0].addr).typeof.pointerBase is char
T T
proc distinctBase*(T: typedesc): typedesc {.magic: "TypeTrait".} = proc distinctBase*(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".} =
## Returns the base type for distinct types, or the type itself otherwise. ## Returns the base type for distinct types, or the type itself otherwise.
## If `recursive` is false, only the immediate distinct base will be returned.
## ##
## **See also:** ## **See also:**
## * `distinctBase template <#distinctBase.t,T>`_ ## * `distinctBase template <#distinctBase.t,T,static[bool]>`_
runnableExamples: runnableExamples:
type MyInt = distinct int type MyInt = distinct int
type MyOtherInt = distinct MyInt
doAssert distinctBase(MyInt) is int doAssert distinctBase(MyInt) is int
doAssert distinctBase(MyOtherInt) is int
doAssert distinctBase(MyOtherInt, false) is MyInt
doAssert distinctBase(int) is int doAssert distinctBase(int) is int
since (1, 1): since (1, 1):
template distinctBase*[T](a: T): untyped = template distinctBase*[T](a: T, recursive: static bool = true): untyped =
## Overload of `distinctBase <#distinctBase,typedesc>`_ for values. ## Overload of `distinctBase <#distinctBase,typedesc,static[bool]>`_ for values.
runnableExamples: runnableExamples:
type MyInt = distinct int type MyInt = distinct int
type MyOtherInt = distinct MyInt
doAssert 12.MyInt.distinctBase == 12 doAssert 12.MyInt.distinctBase == 12
doAssert 12.MyOtherInt.distinctBase == 12
doAssert 12.MyOtherInt.distinctBase(false) is MyInt
doAssert 12.distinctBase == 12 doAssert 12.distinctBase == 12
when T is distinct: when T is distinct:
distinctBase(typeof(a))(a) distinctBase(typeof(a), recursive)(a)
else: # avoids hint ConvFromXtoItselfNotNeeded else: # avoids hint ConvFromXtoItselfNotNeeded
a a

View file

@ -78,8 +78,8 @@ proc initToJsonOptions*(): ToJsonOptions =
## initializes `ToJsonOptions` with sane options. ## initializes `ToJsonOptions` with sane options.
ToJsonOptions(enumMode: joptEnumOrd, jsonNodeMode: joptJsonNodeAsRef) ToJsonOptions(enumMode: joptEnumOrd, jsonNodeMode: joptJsonNodeAsRef)
proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".} proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
template distinctBase[T](a: T): untyped = distinctBase(typeof(a))(a) template distinctBase[T](a: T, recursive: static bool = true): untyped = distinctBase(typeof(a), recursive)(a)
macro getDiscriminants(a: typedesc): seq[string] = macro getDiscriminants(a: typedesc): seq[string] =
## return the discriminant keys ## return the discriminant keys

View file

@ -1,7 +1,7 @@
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".} proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
## imported from typetraits ## imported from typetraits
proc distinctBase(T: typedesc): typedesc {.magic: "TypeTrait".} proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
## imported from typetraits ## imported from typetraits
proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.} proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}