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 ...
#-----------------
from builder import group
group SubWindow:
  Elevate
  Resize
  Move
#-----------------
# More code...
#-----------------
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 ...
#-----------------
No, 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
# 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