The goal of this macro

[https://github.com/StefanSalewski/gintro/blob/master/gintro/gimpl.nim#L30](https://github.com/StefanSalewski/gintro/blob/master/gintro/gimpl.nim#L30)

was to enable us to connect callbacks to widgets with type checking at compile 
time.

For most signals this works fine, see test in 
[https://github.com/StefanSalewski/gintro/blob/master/examples/connect_args.nim](https://github.com/StefanSalewski/gintro/blob/master/examples/connect_args.nim)

Problem is, that GTK uses not only plain object types, but sometimes define so 
called interfaces. Data types can provide such interfaces, and then can be 
regarded equivalent to the interfaces. (We discussed that on GTk mailing list 
in this thread: 
[https://mail.gnome.org/archives/gtk-list/2017-July/msg00018.html](https://mail.gnome.org/archives/gtk-list/2017-July/msg00018.html))

The above macro generates code like this when Interfaces are involved:
    
    
    import gintro/[gtk, gobject, glib]
    
    var r: CellRenderer
    proc handler2(renderer: CellRenderer, editable: CellEditable, path: string) 
= discard
    
    proc connect_for_signal_cdecl_editing_started2(self: ptr CellRenderer00; 
editable: ptr CellEditable00; path: cstring; data: pointer) {.cdecl.} =
      let h: pointer = g_object_get_qdata(self, Quark)
      var editable1: CellEditable
      new editable1
      editable1.impl = editable
      handler2(cast[CellRenderer](h), editable1, $(path))
    
    
    proc connect_for_signal_editing_started2(self: CellRenderer;  p: proc 
(self: CellRenderer; editable: CellEditable | SpinButton | ComboBox | 
SearchEntry | ComboBoxText | AppChooserButton | Entry; path: string)): culong 
{.discardable.} =
      scediting_started(self, connect_for_signal_cdecl_editing_started2, nil)
    
    
    connect_for_signal_editing_started2(r, handler2)
    

The OR type class results from the fact that CellEditable is the Interface and 
all the other listed widgets provide this interface and are regarded compatible 
in this way. The handler can have one of these widgets type as argument, then 
it should compile. For other incompatible widgets it should of course not 
compile.

The above code does not compile at all currently, as that Or notation is not 
supported.

It seem that I can break down the proc with OR parameters into multiple procs 
like
    
    
    proc connect_for_signal_editing_started2(self: CellRenderer;  p: proc 
(self: CellRenderer; editable: SpinButton; path: string)): culong 
{.discardable.} =
      scediting_started(self, connect_for_signal_cdecl_editing_started2, nil)
    
    proc connect_for_signal_editing_started2(self: CellRenderer;  p: proc 
(self: CellRenderer; editable: CellEditable; path: string)): culong 
{.discardable.} =
      scediting_started(self, connect_for_signal_cdecl_editing_started2, nil)
    

Then the compiler selects the right one. But that is a lot of code generation 
in the macro.

Another approch may be to investigate the actual parameters of the provided 
proc (handler2 here) to check if parameters are compatible. That works, when 
the proc is passed as typed parameter to the macro -- then investigation starts 
with something like p.symbol.getImpl().

Unfortunately currently the proc is passed untyped to the macro. As typed 
parameter it does not compile.

Can I pass the same parameter to a macro as typed and untyped version? 

Reply via email to