Hi,
I am trying to declare a var inside a template via a macro which should be gensymed, but this does not work. I can't see what I am doing wrong:
proc append* (father, child: PNimrodNode): PNimrodNode {.compiletime.} =
father.add(child)
return father
proc append* (father: PNimrodNode, children: varargs[PNimrodNode]): PNimrodNode {.compiletime.} =
father.add(children)
return father
macro declareVarOfRetType(vname, fun: expr): stmt {.immediate.} =
result = newNimNode(nnkStmtList).append(newNimNode(nnkVarSection).append(
newNimNode(nnkIdentDefs).append([newNimNode(nnkPragmaExpr).
append([newIdentNode(vname.repr),newNimNode(nnkPragma).append(newIdentNode("gensym"))]),
fun[3][0],
newNimNode(nnkEmpty)])) )
template foo[T] (exec: expr, init: T): T =
exec(init)
template foo(exec: expr): expr =
var init: int
foo(exec, init)
template foo1(exec: expr): expr =
declareVarOfRetType(init, exec) # i want to infer the return type
foo(exec, init)
echo foo(proc (x: int): int = 2 + x, 3)
echo foo(proc (x: int): int = 2 + x)
echo foo(proc (x: int): int = 3 + x)
echo foo1(proc (x: int): int = 2 + x) # first instantiation works
echo foo1(proc (x: int): int = 3 + x) # second throws error about redefinition of init
It's a limitation that's even documented:
http://nimrod-code.org/manual.html#hygiene-in-templates
"The inject and gensym pragmas are second class annotations; they have no semantics outside of a template definition and cannot be abstracted over ..."
I'm sure somebody here can come up with a workaround, sorry, I'm busy with other things ... ;-)