# Multiple macro inherited

**URL:** <https://forum.crystal-lang.org/t/multiple-macro-inherited/6165>\
**Category:** Help & Support\
**Created:** [November 14, 2023, 10:09pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165 "2023-11-14T22:09:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 14, 2023, 10:09pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/1 "2023-11-14T22:09:27Z")

</div>

Hi,

I’m having problems with `inherited` macro, does it runs just once for a type hierarchy?

I want to define an `inherited` macro in 2 classes in the hierarchy and have them run in the third class. To avoid the macro to run in the first 2 I use a annotation.

Example, C inherits B that inherits A, B and A has a `macro inherited`, When C in born to the compiler I was expecting the `inherited` macro defined in `A` and then the `inherited` macro defined in `B` to run, but just the macro from `A` really generates code. Weird is that if I introduce some syntax error in the code generated by the `inherited` macro defined in type `B` the compiler detects it, so it seems the macro is being executed but generating nothing? Is this a compiler bug or am I missing something?

```auto
annotation Skip
end

@[Skip]
class A
  macro inherited
    {% unless @type.annotation(Skip) %}
    def foo
       puts "A"
    end
    {% end %}
  end
end

@[Skip]
class B < A
  macro inherited
    {% unless @type.annotation(Skip) %}
    def foo
      previous_def
      puts "B"
    end
    {% end %}
  end
end

class C < B
end

C.new.foo

```

I was expecting this to print:

```auto
A
B

```

But it just prints

```auto
A

```

Why I want this? I have a type annotation defined in one shard that generated some stuff, but in another shard I want to extend this annotation with more parameters that add more stuff in a series of functions defined with `previous_def` calls. yes, GTK stuff 😁

---

<div class="post-metadata">

**Author:** ![Devonte](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/devonte/32/1927_2.png) [@Devonte](https://forum.crystal-lang.org/u/Devonte)\
**Post date:** [November 14, 2023, 11:08pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/2 "2023-11-14T23:08:27Z")

</div>

In your example, `A`’s `inherited` macro is called for `B` which is skipped, then `B`’s `inherited` macro is called for `C` which defines `B#foo` on `C`, then `A`’s `inherited` macro is called _again_ on `C` which defines `A#foo` on `C`. This final definition overrides the one made by `B` which is why “A” is printed.

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 14, 2023, 11:13pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/3 "2023-11-14T23:13:10Z")

</div>

Thanks, you are right, if I add a `previous_def` call to `foo` definition in `A` `inherited` macro it works…

so the issue is just the ordering with the macros are run in this code. Thanks!

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 14, 2023, 11:21pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/4 "2023-11-14T23:21:40Z")

</div>

But now I have a new problem… I want be able to write

```auto
class D < A
end

D.new.foo

```

and let it print `A`, but if I do this (with the previous code fixed) I get an error because there will be no previous definition of `foo`

---

<div class="post-metadata">

**Author:** ![Devonte](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/devonte/32/1927_2.png) [@Devonte](https://forum.crystal-lang.org/u/Devonte)\
**Post date:** [November 14, 2023, 11:34pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/5 "2023-11-14T23:34:11Z")

</div>

I believe you would need a separate annotation to apply to the subclasses. Out of curiosity, why are you using macros for inheritance control? If `D` defines its own `foo` method it would be separate to `A#foo` unless the signatures are identical, in which case `D#foo` overrides the former.

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 15, 2023, 12:06am UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/6 "2023-11-15T00:06:22Z")

</div>

> [@Devonte](#):
>
> Out of curiosity, why are you using macros for inheritance control?

Maybe it’s a a lot of detail if you aren’t used to GObject type system, but here it goes anyway:

I’m writing a binding generator for GObject based libraries and for GTK4 itself, GObject has properties, nowadays you can create a Crystal object that inherits a GObject and use an annotation to let it register this property on GObject.

```auto
class Foo < GObject::Object
  @[GObject::Property]
  property my_prop : Int32 = 0
end

```

You can pass the object above to a C function call and it will recognize the `my_prop` property.

**How it works**

In GObject C world this is done at type registration time (`class_init` functions), in the bindings when a type is registered in the GObject type system a class method named `_class_init` is called and scan the object instance variables with the `Property` annotation to do the right C function calls to register the properties in the object.

So far so good, but in GTK there’s a function named `gtk_widget_class_add_binding_action`, this function adds a [gtk\_widget\_class\_install\_property\_action](https://docs.gtk.org/gtk4/class_method.Widget.install_property_action.html) that creates a GTK action for a GObject property, so when the action is triggered in the application the property value changes.

The problem is that this C function also needs to be called in the `_class_init` function, it’s in another shard and the worst… I would like to implement this as a parameter anotation in the same `Property` annotation, but this extra parameter would be handled by the GTK4 shard, not by the gi-crystal shard that has the GLib and GObject bindings.

I wanted this code:

```auto
# GObject::Object is part of Gtk::Widget hierarchy
class Foo < Gtk::Widget
  @[GObject::Property(action: "my_action")
  property bar : Int32 = 0
end

```

to generate

```Crystal
class Foo
    # generated by an inherited macro on GObject::Object
  def _class_init(...)
    # register the property, code created by a macro in GObject
  end

  # generated by an inherited macro on Gtk::Widget
  def _class_init(...)
    LibGtk.gtk_widget_class_install_property_action(...)
    previous_def
  end
end

```

GObject::Object uses a lot the `previous_def` to create a chain of `_class_init` function calls, because different features of GObject library need to call functions at class initialization time (a.k.a. class\_init).

For example, when people do:

```Crystal
class Bar < Gtk::Widget
  include Gtk::Editable
end

```

this also creates a `_class_init` implementation telling GObject type system that this types implements this module, such implementation have a `previous_def` call, so all `_class_init` are called in the case of a type implement multiple interface or simple has multiple properties. The same for GObject virtual functions implementation in the bindings.

If everything gets implemented in GObject::Object all works, but I’ll be messing up hard with shard boundaries and this isn’t an option.

Anyway, seems a nice problem to solve.

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 15, 2023, 12:08am UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/7 "2023-11-15T00:08:02Z")

</div>

Ah, the classes generated by the generator, i.e. `GObject::Object` and `Gtk::Widget` have an annotation, the equivalent of the `Skip` annotation in the code snippet, so I can do all this machinery only for user types, not for types generated by the binding generator.

---

<div class="post-metadata">

**Author:** ![hugopl](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hugopl/32/970_2.png) [@hugopl](https://forum.crystal-lang.org/u/hugopl)\
**Post date:** [November 16, 2023, 2:48pm UTC](https://forum.crystal-lang.org/t/multiple-macro-inherited/6165/8 "2023-11-16T14:48:44Z")

</div>

A `previous_def?` macro would solve the problem

Since it doesn’t exist I solved the issue with a bit of runtime code, creating a simple linked list with the Procs that must be called.

```Crystal
annotation Skip
end

annotation Property
end

class ClassInitChain
  property class_init : Proc(Nil)?
  property next : ClassInitChain?

  def initialize(@class_init = nil, @next = nil)
  end

  def prepend(class_init : Proc(Nil))
    if @class_init.nil?
      @class_init = class_init
    else
      new_next = ClassInitChain.new(@class_init, @next)
      @class_init = class_init
      @next = new_next
    end
  end

  def call
    @class_init.try(&.call)
    next_init = @next
    while next_init
      next_init.class_init.try(&.call)
      next_init = next_init.next
    end
  end
end

@[Skip]
class Obj
  macro property(var)
    @[Property]
    @{{ var }}
  end

  def self.prepend_class_init(init : Proc(Nil))
    @@class_init_chain.try(&.prepend(init))
  end

  macro inherited
    {% unless @type.annotation(Skip) %}
    puts "Obj#inherited macro on #{{{ @type.name }}}"

    def self.%obj_init
      {% verbatim do %}
      puts {{ "Obj#inherited: " + (@type.name + ".class_init").stringify }}
      print "properties: "
      puts {{ @type.instance_vars.select(&.annotation(Property)).stringify }}
      {% end %}

    end

    @@class_init_chain : ClassInitChain? = ClassInitChain.new
    prepend_class_init(->%obj_init)

    def self.class_init
      @@class_init_chain.try(&.call)
      @@class_init_chain = nil # free some bytes
    end
    {% end %}
  end
end

@[Skip]
class Widget < Obj
  macro inherited
    {% unless @type.annotation(Skip) %}
    puts "Widget#inherited macro on #{{{ @type.name }}}"

    def self.%widget_init
      puts {{ "Widget#inherited: " + (@type.name + ".class_init").stringify }}
    end
    prepend_class_init(->self.%widget_init)

    {% end %}
  end
end

class UserWidget < Widget
  property foo : Int32 = 0
end

class UserObj < Obj
  property bar : Int32 = 0
end

puts "\n --- RUN -- \n\n"

puts "--- UserObj.class_init"
UserObj.class_init
puts "--- UserWidget.class_init"
UserWidget.class_init

```

With prints:

```auto
Widget#inherited macro on UserWidget
Obj#inherited macro on UserWidget
Obj#inherited macro on UserObj

 --- RUN -- 

--- UserObj.class_init
Obj#inherited: UserObj.class_init
properties: [bar]
--- UserWidget.class_init
Obj#inherited: UserWidget.class_init
properties: [foo]
Widget#inherited: UserWidget.class_init

```

The extra price is just few memory allocations that can be freed after the type is initialized.

Thanks everyone.
