Tmp macro variable in the Crystal

Viewed 99

How i can use temporary variables in macros for building code in the Crystal Lang. For examle, i have:

module Rule
  macro included
    {% rules = [] of TypeDeclaration %}
    
    macro rule(declaration)
        raise("Should be TypeDeclaration") unless \{{declaration.is_a?(TypeDeclaration)}}

        \{% {{rules}} << declaration %}
    end

    macro finished
        \{% for declaration in rules %}
            puts \{{declaration}}
        \{% end %}
    end

  end
end



class StringRule
    include Rule

    rule min : Int32 = 0
    rule max : Int32 = 255
end

And i have compile error

 > 6 |      {% [] << declaration %}
               ^
Error: for empty arrays use '[] of ElementType'

I need store all rules for reusing it in a hook finished. Is it posible?

1 Answers

Variables in macro expressions are scoped to the respective macro context. So a variable defined in macro included is not visible in macro rule.

But you can use constants for this: RULES = [] of _. The _ underscore makes the array untyped, it is only to be used during compilation and not for actual code. If you refer to RULES outside a macro expression, the compiler will complain.

module Rule
  macro included
    RULES = [] of _
    
    macro rule(declaration)
      \{% raise("Should be TypeDeclaration") unless declaration.is_a?(TypeDeclaration) %}

      \{% RULES << declaration %}
    end

    macro finished
      \{% for declaration in RULES %}
      puts \{{ declaration.stringify }}
      \{% end %}
    end
  end
end

class StringRule
    include Rule

    rule min : Int32 = 0
    rule max : Int32 = 255
end
Related