Crystal中的tmp宏变量

问题描述

我如何使用宏中的临时变量在 Crystal Lang 中构建代码。例如,我有

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

我有编译错误

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

我需要存储所有 rules 以便在钩子 finished 中重用它。可以吗?

解决方法

宏表达式中的变量作用域为各自的宏上下文。因此,macro included 中定义的变量在 macro rule 中不可见。

但是您可以为此使用常量:RULES = [] of __ 下划线使数组无类型,它仅在编译期间使用,而不用于实际代码。如果在宏表达式之外引用 RULES,编译器会报错。

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