I've been using meta-programming to create a sequence of tuples of procs at compile time, usable at run-time, but am having difficulty now with 0.16.0 release.
This is a minimal example working with 0.14.2; my actual code has a macro to create something like ptest() and proc_list:
proc ptest(pid: int): bool {.procvar.} =
echo "foo",$pid
return if pid == 100: true else: false
var proc_list = newSeq[tuple[id:int; myproc:proc (pid:int):bool{.gcsafe, locks: 0.}]]()
proc_list.add((0,ptest))
proc_list.add((0,ptest))
proc_list.add((0,ptest))
echo (proc_list[0][1](100),"\n")
echo (proc_list[1][1](200),"\n")
echo (proc_list[2][1](300))
The error:
Error: type mismatch: got (seq[tuple[id: int, myproc: proc (pid: int): bool{.closure, gcsafe, locks: 0.}]], (int, proc (pid: int): bool{.gcsafe, locks: 0.}))
but expected one of:
proc add[T](x: var seq[T]; y: T)
proc add(result: var string; x: float)
proc add(x: var string; y: string)
proc add(x: var string; y: cstring)
proc add(x: var string; y: char)
proc add(result: var string; x: int64)
proc add[T](x: var seq[T]; y: openArray[T])
Can anybody help me so I don't pull all my hair out? It could be something simple I'm missing. I tried starting the pragma with "{.closure" but that didn't help.
I don't have much experience with different lambda types in Nim and what is compatible and what is not compatible, but this works for me:
import macros
proc ptest(pid: int): bool {.procvar.} =
echo "foo",$pid
return if pid == 100: true else: false
type
ProcType = proc (pid:int):bool {.gcsafe, locks: 0.}
var proc_list = newSeq[tuple[id:int; myproc: ProcType]]()
var foo : ProcType = ptest
proc_list.add((0,foo))
proc_list.add((0,foo))
proc_list.add((0,foo))
echo proc_list[0][1](100), "\n"
echo proc_list[1][1](200), "\n"
echo proc_list[2][1](300)
I found it more randomly, I don't know what the problem is.
EDIT:
It might be that your type of ptest is just implicitly convertable to ProcType, but not of that type. When X is convertable to Y, it doesn't mean that tuple[a: int, x: X] is convertable to tuple[a: int, x: Y].
I ended-up blending both your answers in the example:
proc ptest(pid: int): bool {.procvar.} =
echo "foo",$pid
return if pid == 100: true else: false
type ProcType = proc (pid:int): bool {.gcsafe, locks: 0, nimcall.}
var proc_list = newSeq[tuple[id:int; myproc: ProcType]]()
proc_list.add((0,ptest))
proc_list.add((0,ptest))
proc_list.add((0,ptest))
echo proc_list[0][1](100), "\n"
echo proc_list[1][1](200), "\n"
echo proc_list[2][1](300)
For my real code, the macro which generates and populates proc_list is now simpler, and works again. Less AST to create. Thanks!