Catch on nested macros

Dear all, I just had a little surprise (at least to me) that for macro nesting you don’t need to have a macro inside a macro definition, but this is enough already…

{% if true %}

# this also counts as a nested macro and needs escaping!
macro uint64_from_letters(str)
    \{% value = 0_u64 %}
    \{% for c in str.chars %}
        \{% value = (value << 8) | (c.ord) %}
    \{% end %}
    \{{ value }}
end

{% end %}

p uint64_from_letters("12345678")

… and needs escaping. If you don’t - you get misleading error messages like

In x.cr:15:17

 15 | {% for c in str.chars %}
                  ^--
Error: undefined macro variable 'str'

No big deal, just unexpected…

Yes, you can have arbitrary macro expressions outside of macro. Like the {% if true %} for example.
And macro expressions can be escaped which means they’ll get evaluated in the next pass.
As long as the compiler finds any macro expressions in the source code, it keeps resolving them, and pushes escaped ones up for the next iteration.

1 Like