Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,12 @@ type

TTypeFlags* = set[TTypeFlag]

TSymKind* = enum # the different symbols (start with the prefix sk);
# order is important for the documentation generator!
TSymKind* = enum
# Contributors:
# Start new fields with the prefix 'sk'.
# The order of this enum *MUST* not change. Other modules such as the doc
# generator and macros depend on the order.
# When extending this enum, also extend `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
30 changes: 29 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:
# The order of this enum *MUST* be identical to `compiler/ast.TSymKind`.
# Test its members 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,28 @@ proc extractDocCommentsAndRunnables*(n: NimNode): NimNode =
result.add ni
else: break
else: break

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

func getPackage*(sym: NimNode): NimNode =
## Return the owning package symbol.
## Returns `sym` when `sym` is a package symbol.
case sym.symKind
of nskPackage: return sym
of nskModule: return sym.owner
else:
var sym = sym
while sym.symKind != nskPackage:
sym = sym.owner
return sym
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"