I need your macro knowable!
Say I have two functions:
proc foobar(x: string): string =
discard
proc foobar(x: int): int =
discard
I can get the a ClosedSymChoice of the foobar(string) or foobar(int). To get foobar(int) I can just pick the 2nd one:
macro choose(f: typed) =
echo f[1].getImpl.treeRepr
choose(foobar)
But what if I don't know the order? How to get the foobar(int) specifically? Some thing like this:
# does not work:
macro choose(f: typed) =
echo f.getImpl.treeRepr
choose(foobar(int))
Or maybe?
# does not work:
macro choose(f: typed) =
echo f.getImpl.treeRepr
choose(foobar[int])
I can go the hacky way and call it with a type, then get it out of the Call statement:
macro choose(f: typed) =
echo f[0].getImpl.treeRepr
choose(foobar(0))
But what if the type int and instance 0 is more complex then and integer, and its hard to create a default version of?
Is there a way to select foobar(known-type) version directly?
Thanks!
To select a specific overload you can use a type conversion:
proc p(a: int) = echo "int"
proc p(a: string) = echo "string"
(proc (a: string) {.nimcall.})(p)("a")
@treeform you could also do something like this:
import macros
import strformat
type
Stuff = object
x: int
y: int
proc foobar(x: string): string =
discard
proc foobar(x: int): int =
discard
proc foobar(x: Stuff, y: string): int =
discard
proc findChild(root: NimNode, target: NimNodeKind): NimNode =
var stack = newSeqOfCap[NimNode](root.len)
# Do a iterative recursive loop using a stack
stack.add(root)
while stack.len > 0:
let elem = stack.pop()
if elem.kind == target:
return elem
else:
for child in elem:
stack.add(child)
raise newException(Exception, &"Nimnode of kind {target} not found!")
macro choose(f: typed, ty: varargs[typed]) =
for choice in f:
let impl = choice.getImpl
# Get the nested child that contains the parameters
let tree = findChild(impl, nnkFormalParams)
# FormalParams
# Sym "int"
# IdentDefs (-> arg)
# Sym "x"
# Sym "Stuff" (-> arg[1], which is the type)
# Empty
var i = 1 # skip the return type
# This loop will match the param types in order, from left to right
# and you don't have to specify them all
while i < tree.len:
let arg = tree[i]
let argTy = arg[1]
if (i-1) < ty.len and argTy == ty[i-1]:
echo impl.treeRepr
i += 1
choose(foobar, Stuff)
# This works too!
choose(foobar, Stuff, int)
choose(foobar, int)