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
parent 988c02b7cb
commit 8ce782d463
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)
of "distinctBase":
var arg = operand.skipTypes({tyGenericInst})
let rec = semConstExpr(c, traitCall[2]).intVal != 0
while arg.kind == tyDistinct:
arg = arg.base
arg = arg.skipTypes(skippedTypes + {tyGenericInst})
arg = arg.base.skipTypes(skippedTypes + {tyGenericInst})
if not rec: break
result = getTypeDescNode(c, arg, operand.owner, traitCall.info)
else:
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
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.
## If `recursive` is false, only the immediate distinct base will be returned.
##
## **See also:**
## * `distinctBase template <#distinctBase.t,T>`_
## * `distinctBase template <#distinctBase.t,T,static[bool]>`_
runnableExamples:
type MyInt = distinct int
type MyOtherInt = distinct MyInt
doAssert distinctBase(MyInt) is int
doAssert distinctBase(MyOtherInt) is int
doAssert distinctBase(MyOtherInt, false) is MyInt
doAssert distinctBase(int) is int
since (1, 1):
template distinctBase*[T](a: T): untyped =
## Overload of `distinctBase <#distinctBase,typedesc>`_ for values.
template distinctBase*[T](a: T, recursive: static bool = true): untyped =
## Overload of `distinctBase <#distinctBase,typedesc,static[bool]>`_ for values.
runnableExamples:
type MyInt = distinct int
type MyOtherInt = distinct MyInt
doAssert 12.MyInt.distinctBase == 12
doAssert 12.MyOtherInt.distinctBase == 12
doAssert 12.MyOtherInt.distinctBase(false) is MyInt
doAssert 12.distinctBase == 12
when T is distinct:
distinctBase(typeof(a))(a)
distinctBase(typeof(a), recursive)(a)
else: # avoids hint ConvFromXtoItselfNotNeeded
a

View File

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

View File

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