That's what I'm presently doing. I'm using the following pattern (presented 
top-down for easier reading):
    
    
    template dsl*(bodyDsl: untyped) =
      # Structure of the DSL
      block:
        # Inject context variables and do init...
        template action(bodyAction: untyped) =
          # Here in action context.
            actionImpl(bodyAction)
            ...
    
    macro actionImpl(body: untyped): untyped =
      # Delegate syntax processing to procs
      ... extract pieces of syntax
      proc1(var1, code1)
      proc2(var2, code2)
      ...
    
    proc proc1(var1: int; body: NimNode) =
      # Procs can mix different type of arguments and
      # easier to use in proc body.
      ...
      v = op(v1, v2)
    
    template op(v1: Type1; v2: Type2) =
      # Optimize operators at the lowest level
    
    
    Run

Using procs below the macro level means that I don't have to take care of 
`typed/untyped` arguments and automatic macro `untyped` conversions. And I use 
again templates at the lowest level, for small operations or optimizations. I 
hope this pattern will make sense and that the code will be easy to 
understand... 

Reply via email to