This is my code:
var i {.compileTime.} = 2
template defineId*(t: typedesc): stmt =
const id {.genSym.} = i
static: inc(i)
proc idFor*(T: typedesc[t]): int {.inline, raises: [].} = id
defineId(int8)
defineId(int16)
echo idFor(int8), idFor(int16)
The compiler yields a SEGFAULT (I will create an issue for that separately). My question here is: Is this supposed to work? I just want to have an increasing counter at compile time.
I have no idea whether this is supposed to work or not, but there seems to be a quick workaround using a macro instead of a template, like this:
import macros
var i {.compileTime.} = 2
macro defineId*(t: typedesc): untyped =
var id = i
inc(i)
result = quote do:
proc idFor*(T: typedesc[`t`]): int {.inline, raises: [].} = `id`
defineId(int8)
defineId(int16)
echo idFor(int8)
echo idFor(int16)
Which should do what you want. If you don't like using quote, you can also build the AST for the proc definition from NimNodes by hand.
There also seems to be a series of similar templates which misbehave in various ways:
var i {.compileTime.} = 0
template iSegfault(num: typedesc): untyped =
const j = i
proc test*(n: typedesc[num]): int = j
template iGenBadCode(num: typedesc): untyped =
var j = i
proc test*(n: typedesc[num]): int = j
template iGenMoreBadCode(num: typedesc): untyped =
proc test*(n: typedesc[num]): int = i
iGenMoreBadCode(int)
iGenBadCode(int8)
iSegfault(int16)
echo test(int)
echo test(int8)
echo test(int16)
# SIGSEGV
iGenBadCode results in the following error in gcc:
error: 'i_99001' undeclared (first use in this function)
j_99047 = i_99001;
^
iGenMoreBadCode in:
error: 'i_99001' undeclared (first use in this function)
result = i_99001;
^
Suggesting that in both cases C code for i is never generated, and its value is not otherwise assignable to j. While iSegfault simply segfaults. Putting any of the assignments inside static doesn't help either. I'm not sure if that is intended.