Skip to content

Commit

Permalink
Extend package support for
Browse files Browse the repository at this point in the history
  • Loading branch information
quantimnot committed May 23, 2022
1 parent 6c55a0e commit f7ec832
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 2 deletions.
3 changes: 2 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,8 @@ type
TTypeFlags* = set[TTypeFlag]

TSymKind* = enum # the different symbols (start with the prefix sk);
# order is important for the documentation generator!
# *Order is important for the documentation generator!*
# *Keep this enum synced with `macros.NimSymKind`.*
skUnknown, # unknown symbol: used for parsing assembler blocks
# and first phase symbol lookup in generics
skConditional, # symbol for the preprocessor (may become obsolete)
Expand Down
28 changes: 27 additions & 1 deletion lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,16 @@ type

TNimTypeKinds* {.deprecated.} = set[NimTypeKind]
NimSymKind* = enum
# Contributors:
# * Keep the order of this enum synced with `ast.TSymKind`.
# * Test these values in `tests/macros/tsymkind.nim`.
nskUnknown, nskConditional, nskDynLib, nskParam,
nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
nskConst, nskResult,
nskProc, nskFunc, nskMethod, nskIterator,
nskConverter, nskMacro, nskTemplate, nskField,
nskEnumField, nskForVar, nskLabel,
nskStub
nskStub, nskPackage, nskAlias

TNimSymKinds* {.deprecated.} = set[NimSymKind]

Expand Down Expand Up @@ -1755,3 +1758,26 @@ proc extractDocCommentsAndRunnables*(n: NimNode): NimNode =
result.add ni
else: break
else: break

func getModule*(n: NimNode): NimNode =
## Returns the owning module of a node.
## Returns `nil` if the node is package symbol `nskPackage`.
case n.symKind
of nskModule: return n
of nskPackage: return nil
else:
var n = n
while n.symKind != nskModule:
n = n.owner
return n

func getPackage*(n: NimNode): NimNode =
## Returns the owning package of a node.
case n.symKind
of nskPackage: return n
of nskModule: return n.owner
else:
var n = n
while n.symKind != nskPackage:
n = n.owner
return n
77 changes: 77 additions & 0 deletions tests/macros/tsymkind.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

# Test `NimSymKind` and related procs.

import std/macros

# A package symbol can't be directly referenced, so this macro will return it.
macro getPackageSym(sym: typed): NimNode =
getPackage(sym)

# these are used in tests below
method someMethod(n: NimNode) = discard
converter someConverter(a: char): byte = discard
type Obj = object
field: int

block test_symKind:
macro kind(sym: typed): NimSymKind =
newLit(symKind(sym))
template checkKind(sym) {.dirty.} =
doAssert kind(sym) == member, $kind(sym)
for member in NimSymKind:
case member
of nskUnknown: discard # how to test?
of nskConditional: discard # how to test?
of nskDynLib: discard # how to test?
of nskParam:
proc aProc(aParam = 0) =
checkKind aParam
aProc()
of nskGenericParam: discard # how to test?
# proc aGenericProc[T](aParam: T) =
# checkKind T
# aGenericProc(0)
of nskTemp: discard # how to test?
of nskModule: checkKind macros
of nskType: checkKind NimNode
of nskVar:
var someVar = 0
checkKind someVar
of nskLet:
let someLet = 0
checkKind someLet
of nskConst: discard # how to test?
# const someConst = 0
# checkKind someConst
of nskResult:
proc aProc: int =
checkKind result
discard aProc()
of nskProc: checkKind symKind
of nskFunc: checkKind getModule
of nskMethod: checkKind someMethod
of nskIterator: checkKind items
of nskConverter: checkKind someConverter
of nskMacro: checkKind getPackageSym
of nskTemplate: checkKind checkKind
of nskField: discard # how to test?
of nskEnumField: discard # how to test?
of nskForVar: discard # how to test?
of nskLabel: checkKind test_symKind
of nskStub: discard # how to test?
of nskPackage: discard # checkKind getPackageSym(macros)
of nskAlias: discard # how to test?

block test_getModule:
macro moduleName(sym: typed): string =
getModule(sym).toStrLit
doAssert moduleName(macros) == "macros"
# doAssert moduleName(getPackageSym(macros)) == "macros"
doAssert moduleName(getModule) == "macros", moduleName(getModule)

block test_getPackage:
macro packageName(sym: typed): string =
getPackage(sym).toStrLit
# doAssert packageName(getPackageSym(macros)) == "stdlib"
doAssert packageName(macros) == "stdlib"
doAssert packageName(getModule) == "stdlib"

0 comments on commit f7ec832

Please sign in to comment.