-
Notifications
You must be signed in to change notification settings - Fork 2
/
typeutils.nim
78 lines (67 loc) · 2.67 KB
/
typeutils.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#
# Anonymous unions in Nim
# Copyright (c) 2021 Leorize
#
# Licensed under the terms of the MIT license which can be found in
# the file "license.txt" included with this distribution. Alternatively,
# the full text can be found at: https://spdx.org/licenses/MIT.html
## Additional tools for introspecting Nim types
import std/macros
import astutils
const
Skippable* = {ntyAlias, ntyTypeDesc}
## Type kinds that can be skipped by getTypeSkip
SkippableInst* = {ntyTypeDesc}
## Type kinds that can be skipped by getTypeSkipInst
proc getTypeSkip*(n: NimNode, skip = Skippable): NimNode =
## Obtain the type of `n`, while skipping through type kinds matching `skip`.
##
## See `Skippable` for supported type kinds.
assert skip <= Skippable, "`skip` contains unsupported type kinds: " & $(skip - Skippable)
result = getType(n).applyLineInfo(n)
if result.typeKind in skip:
case result.typeKind
of ntyAlias:
result = getTypeSkip(result, skip)
of ntyTypeDesc:
result = getTypeSkip(result[1], skip)
else:
discard "return as is"
proc getTypeInstSkip*(n: NimNode, skip = SkippableInst): NimNode =
## Obtain the type instantiation of `n`, while skipping through type kinds matching `skip`.
##
## See `SkippableInst` for supported type kinds.
assert skip <= SkippableInst, "`skip` contains unsupported type kinds: " & $(skip - SkippableInst)
result = getTypeInst(n).applyLineInfo(n)
if result.typeKind in skip:
case result.typeKind
of ntyTypeDesc:
result = getTypeInstSkip(result[1], skip)
else:
discard "return as is"
proc getTypeImplSkip*(n: NimNode, skip = Skippable): NimNode =
## Obtain the type implementation of `n`, while skipping through type kinds matching `skip`.
result = getTypeImpl:
getTypeSkip(n, skip)
result = result.applyLineInfo(n)
func newTypedesc*(n: NimNode): NimNode =
## Create a typedesc[n]
nnkBracketExpr.newTree(bindSym"typedesc", copy(n))
func sameType*(a, b: NimNode): bool =
## A variant of sameType to workaround:
##
## * https://github.com/nim-lang/Nim/issues/18867
##
## * https://github.com/nim-lang/Nim/issues/19072
# XXX: compiler bug workaround; see https://github.com/nim-lang/Nim/issues/18867
if macros.sameType(a, b) or macros.sameType(b, a):
# XXX: compiler bug workaround; see https://github.com/nim-lang/Nim/issues/19072
# In case the types are generic parmeters
if a.typeKind == ntyGenericParam and b.typeKind == ntyGenericParam:
# The result will be whether they are the same symbol. This is due to
# sameType() treating uninstantiated generics to be the same.
a == b
else:
true
else:
false