Add isInstanceOf for generic procs to the macros module (#9730)

This commit is contained in:
cooldome 2018-11-21 20:30:03 +00:00 • committed by Andreas Rumpf
commit 086676782a
8 changed files with 46 additions and 3 deletions

View file

@ -61,6 +61,10 @@ proc enumToString*(enums: openArray[enum]): string =
- Added `system.typeof` for more control over how `type` expressions - Added `system.typeof` for more control over how `type` expressions
can be deduced. can be deduced.
- Added `macros.isInstantiationOf` for checking if the proc symbol
is instantiation of generic proc symbol.
### Library changes ### Library changes
- The string output of `macros.lispRepr` proc has been tweaked - The string output of `macros.lispRepr` proc has been tweaked

View file

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

View file

@ -86,7 +86,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimUncheckedArrayTyp") defineSymbol("nimUncheckedArrayTyp")
defineSymbol("nimHasTypeof") defineSymbol("nimHasTypeof")
defineSymbol("nimErrorProcCanHaveBody") defineSymbol("nimErrorProcCanHaveBody")
defineSymbol("nimHasInstantiationOfInMacro")
defineSymbol("nimHasNilSeqs") defineSymbol("nimHasNilSeqs")
for f in low(Feature)..high(Feature): for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f) defineSymbol("nimHas" & $f)

View file

@ -960,6 +960,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node.flags.incl nfIsRef regs[ra].node.flags.incl nfIsRef
else: else:
stackTrace(c, tos, pc, "node is not a symbol") stackTrace(c, tos, pc, "node is not a symbol")
of opcSymIsInstantiationOf:
decodeBC(rkInt)
let a = regs[rb].node
let b = regs[rc].node
if a.kind == nkSym and a.sym.kind in skProcKinds and
b.kind == nkSym and b.sym.kind in skProcKinds:
regs[ra].intVal =
if sfFromGeneric in a.sym.flags and a.sym.owner == b.sym: 1
else: 0
else:
stackTrace(c, tos, pc, "node is not a proc symbol")
of opcEcho: of opcEcho:
let rb = instr.regB let rb = instr.regB
if rb == 1: if rb == 1:

View file

@ -147,7 +147,8 @@ type
opcTypeTrait, opcTypeTrait,
opcMarshalLoad, opcMarshalStore, opcMarshalLoad, opcMarshalStore,
opcToNarrowInt, opcToNarrowInt,
opcSymOwner opcSymOwner,
opcSymIsInstantiationOf
TBlock* = object TBlock* = object
label*: PSym label*: PSym

View file

@ -1148,6 +1148,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl) of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
of mGetImplTransf: genUnaryABC(c, n, dest, opcGetImplTransf) of mGetImplTransf: genUnaryABC(c, n, dest, opcGetImplTransf)
of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner) of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner)
of mSymIsInstantiationOf: genBinaryABC(c, n, dest, opcSymIsInstantiationOf)
of mNChild: genBinaryABC(c, n, dest, opcNChild) of mNChild: genBinaryABC(c, n, dest, opcNChild)
of mNSetChild: genVoidABC(c, n, dest, opcNSetChild) of mNSetChild: genVoidABC(c, n, dest, opcNSetChild)
of mNDel: genVoidABC(c, n, dest, opcNDel) of mNDel: genVoidABC(c, n, dest, opcNDel)

View file

@ -274,6 +274,12 @@ when defined(nimHasSymOwnerInMacro):
## result is also mnde of kind nnkSym if owner exists otherwise ## result is also mnde of kind nnkSym if owner exists otherwise
## nnkNilLit is returned ## nnkNilLit is returned
when defined(nimHasInstantiationOfInMacro):
proc isInstantiationOf*(instanceProcSym, genProcSym: NimNode): bool {.magic: "SymIsInstantiationOf", noSideEffect.}
## check if proc symbol is instance of the generic proc symbol
## useful to check proc symbols against generic symbols
## returned by `bindSym`
proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} proc getType*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.}
## with 'getType' you can access the node's `type`:idx:. A Nim type is ## 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 ## mapped to a Nim AST too, so it's slightly confusing but it means the same

View file

@ -46,3 +46,22 @@ static:
doAssert isSameOwner(foo, poo) doAssert isSameOwner(foo, poo)
doAssert isSameOwner(foo, echo) == false doAssert isSameOwner(foo, echo) == false
doAssert isSameOwner(poo, len) == false doAssert isSameOwner(poo, len) == false
#---------------------------------------------------------------
macro check_gen_proc(ex: typed): (bool, bool) =
let lenChoice = bindsym"len"
var is_equal = false
var is_instance_of = false
for child in lenChoice:
if not is_equal:
is_equal = ex[0] == child
if not is_instance_of:
is_instance_of = isInstantiationOf(ex[0], child)
result = nnkTupleConstr.newTree(newLit(is_equal), newLit(is_instance_of))
# check that len(seq[int]) is not equal to bindSym"len", but is instance of it
let a = @[1,2,3]
assert: check_gen_proc(len(a)) == (false, true)