Add sym owner to macros (#8253)

This commit is contained in:
cooldome
2018-09-03 12:25:59 +01:00
committed by Andreas Rumpf
parent 1abef2dc59
commit e63c66b810
7 changed files with 50 additions and 3 deletions

View File

@@ -657,7 +657,7 @@ type
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo,
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
mException, mBuiltinType
mException, mBuiltinType, mSymOwner
# things that we can evaluate safely at compile time, even if not asked for it:
const

View File

@@ -75,6 +75,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNoZeroTerminator")
defineSymbol("nimNotNil")
defineSymbol("nimVmExportFixed")
defineSymbol("nimHasSymOwnerInMacro")
defineSymbol("nimNewRuntime")
defineSymbol("nimIncrSeqV3")
defineSymbol("nimAshr")

View File

@@ -920,6 +920,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.flags.incl nfIsRef
else:
stackTrace(c, tos, pc, "node is not a symbol")
of opcSymOwner:
decodeB(rkNode)
let a = regs[rb].node
if a.kind == nkSym:
regs[ra].node = if a.sym.owner.isNil: newNode(nkNilLit)
else: newSymNode(a.sym.skipGenericOwner)
regs[ra].node.flags.incl nfIsRef
else:
stackTrace(c, tos, pc, "node is not a symbol")
of opcEcho:
let rb = instr.regB
if rb == 1:

View File

@@ -141,7 +141,8 @@ type
opcSetType, # dest.typ = types[Bx]
opcTypeTrait,
opcMarshalLoad, opcMarshalStore,
opcToNarrowInt
opcToNarrowInt,
opcSymOwner
TBlock* = object
label*: PSym

View File

@@ -1118,6 +1118,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
of mNLen: genUnaryABI(c, n, dest, opcLenSeq, nimNodeFlag)
of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner)
of mNChild: genBinaryABC(c, n, dest, opcNChild)
of mNSetChild: genVoidABC(c, n, dest, opcNSetChild)
of mNDel: genVoidABC(c, n, dest, opcNDel)

View File

@@ -237,6 +237,12 @@ else: # bootstrapping substitute
else:
n.strValOld
when defined(nimHasSymOwnerInMacro):
proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.}
## accepts node of kind nnkSym and returns its owner's symbol.
## result is also mnde of kind nnkSym if owner exists otherwise
## nnkNilLit is returned
proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
## with 'getType' you can access the node's `type`:idx:. A Nim type is
## mapped to a Nim AST too, so it's slightly confusing but it means the same

View File

@@ -1,6 +1,7 @@
discard """
msg: '''"muhaha"
proc poo(x, y: int) =
let y = x
echo ["poo"]'''
"""
@@ -10,11 +11,39 @@ const
foo = "muhaha"
proc poo(x, y: int) =
let y = x
echo "poo"
macro m(x: typed): untyped =
echo repr x.symbol.getImpl
echo repr x.getImpl
result = x
discard m foo
discard m poo
#------------
macro checkOwner(x: typed, check_id: static[int]): untyped =
let sym = case check_id:
of 0: x
of 1: x.getImpl.body[0][0][0]
of 2: x.getImpl.body[0][0][^1]
of 3: x.getImpl.body[1][0]
else: x
result = newStrLitNode($sym.owner.symKind)
macro isSameOwner(x, y: typed): untyped =
result =
if x.owner == y.owner: bindSym"true"
else: bindSym"false"
static:
doAssert checkOwner(foo, 0) == "nskModule"
doAssert checkOwner(poo, 0) == "nskModule"
doAssert checkOwner(poo, 1) == "nskProc"
doAssert checkOwner(poo, 2) == "nskProc"
doAssert checkOwner(poo, 3) == "nskModule"
doAssert isSameOwner(foo, poo)
doAssert isSameOwner(foo, echo) == false
doAssert isSameOwner(poo, len) == false