I'm trying to do something like this:
template declareEnum*(enumName: untyped, values: untyped) =
type enumName = enum
values
declareEnum(Foo):
Alpha = 0
Bravo = 1
let val: Foo = Alpha
and the compiler gives me an Illformed AST on the line with "Alpha" in it. I take it the two lines with "Alpha" and "Bravo" are not statements? Is there any way to do this with templates?
To be more specific to what araq stated:
Make your life very easy and use the newEnum proc (which can only be used inside macros) which does exactly what you want to do here - just not in a way that can be called from normal code and needs you to wrap it in a macro.
Thank you both.
For my needs, I must be able to specify the enum values; so I created the sequence of nnkEnumFieldDef to give to newEnum() which involved copying leaves of the Asgn node.
For future me: dumpTree is your friend. For other learners, here is what I came up with. For current talent, I welcome suggestions for improvement.
import std/macros
macro declareEnum(enumName: untyped, enumPairsStmtList: untyped) =
enumPairsStmtList.expectKind(nnkStmtList)
var fields: seq[NimNode]
for asgnNode in enumPairsStmtList:
var node = newNimNode(nnkEnumFieldDef)
node.add(asgnNode[0])
node.add(asgnNode[1])
fields.add(node)
newEnum(enumName, fields, true, true)
declareEnum(Foo):
Alpha = 1
Bravo = 2
Charlie = 3
proc main =
let v: Foo = Alpha
echo v
echo Charlie.int
when isMainModule:
main()