Hi again, i want to create a final enum after calling a macro that define a group with actions on various modules, something weird is that i need import the module where the enum is generated before other modules are imported, is there a way for create a macro that will be called after the group macro is called on every module?, Here is an example of what I mean:
# Module where is the macro
# Actually is implemented using const by incrementing a compileTime var
from builder import group
# Module A
# Module A imports this module before Module B and Module C is imported
group Window:
Maximize
Minimize
Close
FocusIM
UnfocusIM
# Module B
group SubWindow:
Elevate
Resize
Move
# Module C
group Color: discard
group Layers: discard
# Final Type, generated here, using other macro
type
Groups = enum
gWindow
gSubWindow
gColor
gLayers
GroupsSet = set[Groups]
See example in Synthesis: https://github.com/mratsim/Synthesis/blob/3a443cf3/synthesis/factory.nim#L77
I.e. Gather everything in a compile-time table or sequence and use a final macro generateGroups that read it.
thanks, i do that, but the real problem is that i need import the enum before other groups are generated, i get an undeclared identifier error
Module A
from builder import groupType
#Generate the enum type
groupType(Groups)
type GroupsSet* = set[Groups]
#-----------------
# More code ...
#-----------------
Module B
from builder import group
group SubWindow:
Elevate
Resize
Move
#-----------------
# More code...
#-----------------
Module C
from builder import group
import moduleB
from moduleA import Groups, GroupsSet
group Window:
Maximize
Minimize
Close
FocusIM
UnfocusIM
# undeclared identifier: 'gWindow'
# undeclared identifier: 'gSubWindow'
var a: GroupsSet = {gWindow, gSubWindow}
#-----------------
# More code...
#-----------------
but if i define all groups in Module A, the error is gone
from builder import group, groupType
group SubWindow:
Elevate
Resize
Move
group Window:
Maximize
Minimize
Close
FocusIM
UnfocusIM
# Now gSubWindow and gWindow are defined in the enum
groupType(Groups)
type GroupsSet* = set[Groups]
#-----------------
# More code ...
#-----------------
i dont have a problem define all groups in one module, but define them on various modules could much betterNo, the final enum has the export marker and the group macro adds an entry for the final enum and creates an optional enum with suffix "Msg" for actions (with the export marker too):
import macros
# Groups Enum
var groupEnum {.compileTime.} = newNimNode(nnkEnumTy).add(
newEmptyNode(), newIdentNode("gGeneric")
)
# Group Builder
macro group*(name: untyped, messages: untyped) =
# Expects Ident and StmtList
name.expectKind(nnkIdent)
messages.expectKind(nnkStmtList)
# Add the Group name to Group Enums
groupEnum.add(
newIdentNode("g" & name.strVal)
)
# Create a nameMsg enum if is not discarded
if messages[0].kind != nnkDiscardStmt:
result = nnkStmtList.newTree()
# Create Enum Node
var msgNode = newNimNode(nnkEnumTy)
msgNode.add(newEmptyNode())
for m in messages:
m.expectKind(nnkIdent)
msgNode.add(
newIdentNode("msg" & m.strVal)
)
# Create Type Enum Node
result.add(
newNimNode(nnkTypeSection).add(
newNimNode(nnkTypeDef).add(
newNimNode(nnkPostfix).add(
newIdentNode("*"),
newIdentNode(name.strVal & "Msg")
),
newEmptyNode(),
msgNode
)
)
)
# Generates Group Enum
macro groupType*(name: untyped) =
# Expect name as ident
name.expectKind(nnkIdent)
# Create a new Enum type
result = newNimNode(nnkTypeSection).add(
newNimNode(nnkTypeDef).add(
newNimNode(nnkPostfix).add(
newIdentNode("*"), name
),
newEmptyNode(),
groupEnum
)
)
group Window:
Open
Close
# Generate Groups Type
groupType(Groups)
when isMainModule:
echo sizeof(Groups)
var s = {gWindow}
echo s
i noticed that calling "group" macro after "groupType" macro doesn't add the group to enum too
# Called before groupType
group Window:
Exit
# Generate Groups Type, only has Window
groupType(Groups)
# Called after groupType
group SubWindow:
Move
Resize
when isMainModule:
echo sizeof(Groups)
var s = {gWindow, gSubWindow} # undeclared identifier 'gSubWindow'
echo s
maybe is impossible for now modify the generated enum type at every call of "group" macro. a workaround for this is still use a counter var and use a fixed set size (set[0..63])