I have a completely-static array like this:
[
("name1", {ValueType1, ValueType2}),
("name2",{ValueType3, ValueType1}),
...
]
I want to transform the above, at compile-time, to this:
let tName1 = {ValueType1, ValueType2}
let tName2 = {ValueType3, ValueType1}
...
(yes, I know that this capitalization doesn't matter in Nim)
It looks ridiculously simple, but I can't get it to work no matter what.
I've tried with macros/templates, but I always end up getting some "Cannot evaluate at compile time", whenever I attempt any type of v[0] (let's say v is the array), while at the same time I can echo this very v[0], at compile-time... So, it's obviously being totally evaluated and accessible at compile-time.
Obviously, the reason must be that I'm totally messing up the macro, but oh well...
Can you please give me a helping hand?
One of my many different attempts:
static:
for v in attrs:
echo "\t" & $(v[0]) & "=>" & $(v[1]) # this works fine
let att {.compileTime.} = $(v[0]) # broken
let tp {.compileTime.} = v[1][0]
attrTypes(att, tp)
and this attrTypes:
macro attrTypes*(name: untyped, types: untyped): untyped =
let attrRequiredTypes = ident('t' & ($name).capitalizeAscii())
result = quote do:
let `attrRequiredTypes` = `types`
The understand the context a bit (the "array" in question is attrs):
https://github.com/arturo-lang/arturo/blob/master/src/vm/lib.nim#L89
The above example was obviously over-simplified, on purpose.
P.S. I'm pretty sure the macro is already wrong. However, the most baffling thing of all is that after having echo ed v[0], at compile-time, it complains that it cannot evaluate it... in the very next statement. Is this a bug?
it's not a bug, the variables marked with {.compileTime.} and the macro inside the static block are executed at the "compile time" of the static block (which again is run at compile time, but this doesn't really matter).
I think it is a bit confusing from a terminology standpoint, because compile time can refer to both everything running inside the nimvm, but also to what's running at the "compilation" of what then will run inside the nimvm.
I've made some progress by explicitly declaring the types of the macro arguments, like static[string] and static[set[ValueKind]] respectively.
Now, I'm struggling with unrolling-the-loop, but I think I'll somehow manage to solve it: https://forum.nim-lang.org/t/9504
Do you want something like this, or am I missing something?
import macros
type
Test = enum ValueType1, ValueType2, ValueType3
macro transform(x: static[seq[tuple[name: string, data: set[Test]]]]): untyped =
result = newStmtList()
for y in x:
result.add newLetStmt(("t" & y.name).ident, newLit(y.data))
echo result.repr
transform @[
("name1", {ValueType1, ValueType2}),
("name2",{ValueType3, ValueType1})
]
echo tName1
echo tName2