Hi y'all!
I wrote a macro for conveniently declaring widget types when using traitor, it is used to create a type that conforms to the interface built with traitor with the corresponding member variables. The widget type is generic, where the parameter is the type of the display that is used, and with the display also comes the type of color that is used. In the type definition I use
fgcolor*: typeof(T.color)Here is the reduced code with the macro:
import std/macros
import std/genasts
import traitor
type
    AnyDisplay*[T] = concept display
        display.color is T
    
    TestDisplay = ref object
        color: int
type
    Widgetable* = distinct tuple[
        setPos: proc(a: Atom, x,y: int) {.nimcall.},
        getx: proc(a: Atom): int {.nimcall.},
    ]
implTrait Widgetable
macro implementWidget*(ast: untyped): untyped =
    
    var
        name = ast[0][0][0][1]
        self = newIdentNode("self")
    
    
    result = newNimNode(nnkStmtList)
    result.add(ast)
    
    var
        base = genAst(name, self) do:
            type
                Widget*[T: AnyDisplay] = ref object
                    fgcolor*: typeof(T.color)
                    display*: T
                    x: int
                    y: int
    
    # add variables from base to resulting type
    if result[0][0].kind == nnkTypeSection:
        if result[0][0][0].kind == nnkTypeDef:
            if result[0][0][0][2].kind == nnkRefTy:
                if result[0][0][0][2][0].kind == nnkObjectTy:
                    if result[0][0][0][2][0][2].kind == nnkRecList:
                        for rec in base[0][2][0][2]:
                            result[0][0][0][2][0][2].add(rec)
    
    var
        fg = newIdentNode("fg")
        bg = newIdentNode("bg")
        x = newIdentNode("x")
        y = newIdentNode("y")
    
    # add procs needed for beeing valid "Widgetable" trait
    result.add genAst(name, self, fg, x, y) do:
        proc setfgColor*[T](self: var name[T], fg: auto) =
            self.fgcolor = fg
        
        proc setPos*[T](self: var name[T], x,y: int) =
            self.x = x
            self.y = y
        
        proc getx*[T](self: name[T]): int =
            return self.x
    
    # call macro that generates trait converter
    result.add genAst(name) do:
        emitConverter name, Widgetable
    
    echo result.repr
implementWidget:
    type
        Label*[T] = ref object
            text: string
var
    disp: TestDisplay
    foo: Label[TestDisplay]
And here is the code without the macro, using the code that is printed with echo result.repr at the end of macro:
import std/macros
import std/genasts
import traitor
type
    AnyDisplay*[T] = concept display
        display.color is T
    
    TestDisplay = ref object
        color: int
type
    Widgetable* = distinct tuple[
        setPos: proc(a: Atom, x,y: int) {.nimcall.},
        getx: proc(a: Atom): int {.nimcall.},
    ]
implTrait Widgetable
type
  Label*[T] = ref object
    text: string
    fgcolor*: typeof(T.color)
    display*: T
    x: int
    y: int
proc setfgColor*[T](self: var Label[T]; fg: auto) =
  self.fgcolor = fg
proc setPos*[T](self: var Label[T]; x, y: int) =
  self.x = x
  self.y = y
proc getx*[T](self: Label[T]): int =
  return self.x
emitConverter Label, Widgetable
var
    disp: TestDisplay
    foo: Label[TestDisplay]
I don't understand why the code works when I just copy the output of the macro, but not when macro itself is used ...
Firstly typeof(T.color) is invalid cause T is a typedesc it does not have a color field. typeof(default(T).color) should work but Nim's generics always fight you to the death so this does not work.
If we define template color(T: typedesc): untyped = typeof(default(T).color) to delay resolution a bit, then do fgColor*: color(T) we get the macro to compile.
Hi Beef,
your help is appreciated and valuable as always, and your suggestion solves my problem, thanks a lot!
Interestingly using typeof(T.color) outside the macro does indeed compile and work, maybe a bug in the compiler? But of course using default() does make much more sense :)