Hi all,
I'm needing help with a seq of tuples of procs, used with this example:
type
Test* = ref TestInternal
TestInternal* = object
o*: seq[ffloat]
proc addTest* (): Test =
# constructor
result = Test(o: newSeq[ffloat]())
result.o.add(0.0);
var testSeq = @["abc","123"]
proc ptest(test: Test): bool {.procvar, discardable.} =
echo "success from ptest"
echo "testSeq = ", testSeq.repr
result = true
Now I need a sequence of tuples, with the "myproc" tuple element pointing to the ptest() procedure, but get a type mismatch error:
var seq_test = newSeq[tuple[name:string; procID:int; procBody:string; myproc:proc (test:Test):bool]]()
Error: type mismatch: got (seq[tuple[name: string, procID: int, procBody: string, myproc: proc (test: Test): bool{.closure.}]], (string, int, string, proc (test: Test): bool{.gcsafe, locks: 0.}))
but expected one of:
proc add(x: var string; y: cstring)
proc add(x: var string; y: string)
proc add[T](x: var seq[T]; y: T)
proc add[T](x: var seq[T]; y: openArray[T])
proc add(x: var string; y: char)
proc add[A, B](t: var OrderedTable[A, B]; key: A; val: B)
proc add[A, B](t: OrderedTableRef[A, B]; key: A; val: B)
proc add[A, B](t: TableRef[A, B]; key: A; val: B)
proc add[A, B](t: var Table[A, B]; key: A; val: B)
proc add(father, child: NimNode): NimNode
proc add(father: NimNode; children: varargs[NimNode]): NimNode
But this works:
# Create seq_test.
var seq_test = newSeq[tuple[name:string; procID:int; procBody:string; myproc:proc (test:Test):bool{.gcsafe, locks: 0.}]]()
# Populate the seq, and call our procedure referenced in the tuple.
seq_test.add(("yo",1,"hey",ptest))
var testing123 = addTest()
discard seq_test[0][3](testing123)
Couple questions:
1) Is there a way for the compiler to not infer 'gcsafe' and 'locks'? I don't want to hang myself later. For instance, ptest() accesses a global seq of strings called testSeq, and I don't know if that's safe.
My next experiment is to use tables with procs, which gives useful compiler warnings when our procs are not GC-safe.
import tables
# These three lines give GC-safe warnings when "gprocs[1] = ptest" runs.
# var gprocs*: Table[int, proc (test: Test): bool]
# gprocs = initTable[int, proc (test: Test): bool](initialSize = 16)
# gprocs[1] = ptest
# If we use "gcsafe" and "locks" pragmas, and remove the testSeq line
# from ptest(), there aren't any GC-safe warnings.
var gprocs: Table[int, proc (test: Test): bool{.gcsafe, locks: 0.}]
gprocs = initTable[int, proc (test: Test): bool{.gcsafe, locks: 0.}](initialSize = 16)
gprocs[1] = ptest
echo "CALLING PTEST (GCSAFE): "; discard gprocs[1](testing123)
I get good compiler warnings when using tables, but as I'm doing this all within AST meta-programming, I'd like to keep things as simple as possible and keep using seq of tuples-of-procs. I am hoping the compiler warnings improve when using tuples-of-procs.
Am I missing the proper way to use meta-programming proc calls with non-GC-safe procs? I'd like a way to pass them around easily, without the requirement that they're GC-safe.
Now I'm at a bottleneck.. Inside one of my dynamically-created procedures, I need to access a sequence of tuples, dynamically created earlier in the AST tree.
Is this horrible to do? Nim is giving me a warning about not being GC-safe, but all I'm doing is using the sequence to know which procs to run. For instance, in the below code, asset_def_nau is a sequence of tuples (same structure as seq_test from above post 1) created within a macro, which I'm looping to run my procs.
for i in asset_def_nau:
mynaut = i[3](chart)
echo "result = ", mynaut
So before I just turn-off the warning, is it safe to do so? I'm NOT changing the asset_def_nau sequence, but do need to iterate it.
Thanks.. please bear with me as I'm a nim newbie.