This commit is contained in:
parent
730ce53b71
commit
43f634db8d
3 changed files with 69 additions and 1 deletions
|
|
@ -1673,7 +1673,8 @@ A ``distinct`` type is new type derived from a `base type`:idx: that is
|
||||||
incompatible with its base type. In particular, it is an essential property
|
incompatible with its base type. In particular, it is an essential property
|
||||||
of a distinct type that it **does not** imply a subtype relation between it
|
of a distinct type that it **does not** imply a subtype relation between it
|
||||||
and its base type. Explicit type conversions from a distinct type to its
|
and its base type. Explicit type conversions from a distinct type to its
|
||||||
base type and vice versa are allowed.
|
base type and vice versa are allowed. See also ``distinctBase`` to get the
|
||||||
|
reverse operation.
|
||||||
|
|
||||||
|
|
||||||
Modelling currencies
|
Modelling currencies
|
||||||
|
|
|
||||||
|
|
@ -198,3 +198,41 @@ macro dump*(x: typed): untyped =
|
||||||
let r = quote do:
|
let r = quote do:
|
||||||
debugEcho `s`, " = ", `x`
|
debugEcho `s`, " = ", `x`
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
# TODO: consider exporting this in macros.nim
|
||||||
|
proc freshIdentNodes(ast: NimNode): NimNode =
|
||||||
|
# Replace NimIdent and NimSym by a fresh ident node
|
||||||
|
# see also https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458
|
||||||
|
proc inspect(node: NimNode): NimNode =
|
||||||
|
case node.kind:
|
||||||
|
of nnkIdent, nnkSym:
|
||||||
|
result = ident($node)
|
||||||
|
of nnkEmpty, nnkLiterals:
|
||||||
|
result = node
|
||||||
|
else:
|
||||||
|
result = node.kind.newTree()
|
||||||
|
for child in node:
|
||||||
|
result.add inspect(child)
|
||||||
|
result = inspect(ast)
|
||||||
|
|
||||||
|
macro distinctBase*(T: typedesc): untyped =
|
||||||
|
## reverses ``type T = distinct A``; works recursively.
|
||||||
|
runnableExamples:
|
||||||
|
type T = distinct int
|
||||||
|
doAssert distinctBase(T) is int
|
||||||
|
doAssert: not compiles(distinctBase(int))
|
||||||
|
type T2 = distinct T
|
||||||
|
doAssert distinctBase(T2) is int
|
||||||
|
|
||||||
|
let typeNode = getTypeImpl(T)
|
||||||
|
expectKind(typeNode, nnkBracketExpr)
|
||||||
|
if typeNode[0].typeKind != ntyTypeDesc:
|
||||||
|
error "expected typeDesc, got " & $typeNode[0]
|
||||||
|
var typeSym = typeNode[1]
|
||||||
|
typeSym = getTypeImpl(typeSym)
|
||||||
|
if typeSym.typeKind != ntyDistinct:
|
||||||
|
error "type is not distinct"
|
||||||
|
typeSym = typeSym[0]
|
||||||
|
while typeSym.typeKind == ntyDistinct:
|
||||||
|
typeSym = getTypeImpl(typeSym)[0]
|
||||||
|
typeSym.freshIdentNodes
|
||||||
|
|
|
||||||
29
tests/stdlib/tsugar.nim
Normal file
29
tests/stdlib/tsugar.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
discard """
|
||||||
|
file: "tsugar.nim"
|
||||||
|
output: ""
|
||||||
|
"""
|
||||||
|
import sugar
|
||||||
|
import macros
|
||||||
|
|
||||||
|
block distinctBase:
|
||||||
|
block:
|
||||||
|
type
|
||||||
|
Foo[T] = distinct seq[T]
|
||||||
|
var a: Foo[int]
|
||||||
|
doAssert a.type.distinctBase is seq[int]
|
||||||
|
|
||||||
|
block:
|
||||||
|
# simplified from https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458
|
||||||
|
macro uintImpl(bits: static[int]): untyped =
|
||||||
|
if bits >= 128:
|
||||||
|
let inner = getAST(uintImpl(bits div 2))
|
||||||
|
result = newTree(nnkBracketExpr, ident("UintImpl"), inner)
|
||||||
|
else:
|
||||||
|
result = ident("uint64")
|
||||||
|
|
||||||
|
type
|
||||||
|
BaseUint = UintImpl or SomeUnsignedInt
|
||||||
|
UintImpl[Baseuint] = object
|
||||||
|
Uint[bits: static[int]] = distinct uintImpl(bits)
|
||||||
|
|
||||||
|
doAssert Uint[128].distinctBase is UintImpl[uint64]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue