# Need help debugging a macro please

**URL:** <https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325>\
**Category:** Help & Support\
**Created:** [July 12, 2020, 7:05am UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325 "2020-07-12T07:05:52Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 7:05am UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/1 "2020-07-12T07:05:52Z")

</div>

Hello Group! Newbie here. I was playing around trying to create a MVC like framework but I’m having difficulties trying to get this work. Can someone explain what’s wrong here?

```auto
annotation Route
end

macro setup_handlers
    {% for m in @type.methods %}
        {% if a = m.annotation(Route) %}
            if path == {{a.args[0]}}
                puts "executing {{m.name}} on {{@type.name}}"
                {{m.name}}()
                return
            end
        {% end %}
    {% end %}
    {% debug %}
end

abstract class Controller
  def call(path)
    setup_handlers
  end
end

class Foo < Controller
  @[Route("/info")]
  def info
    puts "in B::info"
  end
end

class Bar < Foo
  @[Route("/info")]
  def info
    puts "in C::info"
  end
end

Bar.new.call("/info")

```

This works as expected but if I remove the info() from Bar I’d expect it to find “/info” in the parent class, Foo but it doesn’t! Any idea what I’m doing wrong here?

Also, how do I ensure that the most derived methods show up first in the search (in `setup_handlers`) I see the `@type.methods` don’t take any arguments!

Thanks!

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [July 12, 2020, 11:36am UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/2 "2020-07-12T11:36:29Z")

</div>

Hi! [#methods](https://crystal-lang.org/api/0.35.1/Crystal/Macros/TypeNode.html#methods:ArrayLiteral(Def)-instance-method) doesn’t include methods from parent types.

You can do this:

```crystal
macro setup_handlers
  {% for type in [@type] + @type.ancestors %}
    {% for m in type.methods %}
      {% if a = m.annotation(Route) %}
        if path == {{a.args[0]}}
          puts "executing {{m.name}} on {{type.name}}"
          {{m.name}}()
          return
        end
      {% end %}
    {% end %}
  {% end %}
  {% debug %}
end

```

It would probably be nice to have a simpler way to list all methods, including those from ancestors. Maybe in the future? :-)

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2020, 2:00pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/3 "2020-07-12T14:00:47Z")

</div>

> <https://github.com/crystal-lang/crystal/issues/8586>
>
> Currently the TypeNode#methods method only returns methods defined on that given type. I propose to add an optional named argument to...

I made an issue for that 🙂.

Interesting to see someone else go the annotation route. I’m curious to see how it turns out.

---

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 2:04pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/4 "2020-07-12T14:04:47Z")

</div>

Works like a charm! Thanks a bunch @asterite! On a different note, is there any reason why a macro would work when embedded inline but not work when defined as a macro by itself?

---

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 2:07pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/5 "2020-07-12T14:07:26Z")

</div>

That’s neat! Thanks @blacksmoke16! Well, I hope I can positively contribute something to the Crystal community! You guys are awesome!

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [July 12, 2020, 3:07pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/6 "2020-07-12T15:07:37Z")

</div>

> [@u89012](#):
>
> is there any reason why a macro would work when embedded inline but not work when defined as a macro by itself?

Could you show some code? I don’t understand what this means

---

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 3:24pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/7 "2020-07-12T15:24:50Z")

</div>

Sure, here it is. This as is, refuses to work, ie, no handlers are attached for some reason (won’t print any “found x…” as well), debug comes up empty.

```auto
macro setup_handlers
  {% for type in [@type] + @type.ancestors %}
      {% for m in type.methods %}
        {% if a = m.annotation(Route) %}
          if path == {{a.args[0]}}
            {{puts "found #{m.name} on #{type.name}"}}
            {{m.name}}(env)
            return
          end
        {% end %}
      {% end %}
    {% end %}
  {% debug %}
end

abstract class Controller
  include HTTP::Handler

  def call(env)
    setup_handlers
    call_next(env)
  end
end

```

but if I paste the whole macro body inline like so, it seems to work!

```auto
abstract class Controller
  include HTTP::Handler

  def call(env)
    {% for type in [@type] + @type.ancestors %}
      {% for m in type.methods %}
        {% if a = m.annotation(Route) %}
          if path == {{a.args[0]}}
            {{puts "executing #{m.name} on #{type.name}"}}
            puts "executing {{m.name}} on {{type.name}}"
            {{m.name}}(env)
            return
          end
        {% end %}
      {% end %}
    {% end %}
    call_next(env)
  end
end

```

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [July 12, 2020, 3:40pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/8 "2020-07-12T15:40:28Z")

</div>

Try doing:

```auto
macro setup_handlers
  {% verbatim do %}
    {% for type in [@type] + @type.ancestors %}
        {% for m in type.methods %}
          {% if a = m.annotation(Route) %}
            if path == {{a.args[0]}}
              {{puts "found #{m.name} on #{type.name}"}}
              {{m.name}}(env)
              return
            end
          {% end %}
        {% end %}
      {% end %}
    {% debug %}
  {% end %}
end

```

`verbatim do` escapes the macro code so that i’ll evaluate in the scope that the macro is used, i.e. in your `call` method. Currently its being evaluated within the macro itself, which doesn’t have any methods/parent types.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [July 12, 2020, 3:52pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/9 "2020-07-12T15:52:04Z")

</div>

Right, when you call `setup_handlers` manually, the `@type` is just the top-level type, not the type where the macro is called.

There’s a discussion about whether that’s okay or not, but we can’t change it right now because it’s a breaking change. There should be a way to get the type in the scope and the type where the macro is declared.

---

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 4:58pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/10 "2020-07-12T16:58:15Z")

</div>

Ah that’s good to know, I’ll give it a try! Thank you!

---

<div class="post-metadata">

**Author:** ![u89012](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/u89012/32/1021_2.png) [@u89012](https://forum.crystal-lang.org/u/u89012)\
**Post date:** [July 12, 2020, 5:06pm UTC](https://forum.crystal-lang.org/t/need-help-debugging-a-macro-please/2325/11 "2020-07-12T17:06:46Z")

</div>

Thanks for the background – I think it feels more natural to have the macro expand in the lexical scope as is, I think that’s what LISP does if I’m not mistaken – it’s nice to know there’s on-going discussion about this!
