Issue with compiling and compiler recursion

Solved the issue!
This rubbish looking code was causing the issue:

  # provide introspection into available functions
  @@functions : String?
  def self.functions : String
    functions = @@functions
    return functions if functions

      list = %({
      {% for method in methods %}
        {% index = 0 %}
        {% args = [] of Crystal::Macros::Arg %}
        {% for arg in method.args %}
          {% if !method.splat_index || index < method.splat_index %}
            {% args << arg %}
          {% end %}
          {% index = index + 1 %}
        {% end %}

        {{method.name.stringify}}: {
          {% for arg in args %}
            {% if !arg.restriction.is_a?(Union) && arg.restriction.resolve < ::Enum %}
              {% if arg.default_value.is_a?(Nop) %}
                {{arg.name.stringify}}: ["String"],
              {% else %}
                {{arg.name.stringify}}: ["String", "#{{{arg.default_value}}.to_s.to_json}"],
              {% end %}
            {% else %}
              {% if arg.default_value.is_a?(Nop) %}
                {{arg.name.stringify}}: [{{arg.restriction.stringify}}],
              {% else %}
                {{arg.name.stringify}}: [{{arg.restriction.stringify}}, "#{{{arg.default_value}}.to_json}"],
              {% end %}
            {% end %}
          {% end %}
        },
      {% end %}})

    # Remove whitespace, remove all ',' followed by a '}'
    @@functions = list.gsub(/\s/, "").gsub(",}", "}")
  end

replaced it with a string builder and everything works wonderfully now!

  # provide introspection into available functions
  @@functions : String?
  def self.functions : String
    functions = @@functions
    return functions if functions

    list = String.build do |str|
      str << "{"
      {% for method in methods %}
        {% index = 0 %}
        {% args = [] of Crystal::Macros::Arg %}
        {% for arg in method.args %}
          {% if !method.splat_index || index < method.splat_index %}
            {% args << arg %}
          {% end %}
          {% index = index + 1 %}
        {% end %}

        str << '"'
        str << {{method.name.stringify}}
        str << %(": {)
          {% for arg in args %}
            str << '"'
            str << {{arg.name.stringify}}

            {% if !arg.restriction.is_a?(Union) && arg.restriction.resolve < ::Enum %}
              {% if arg.default_value.is_a?(Nop) %}
                str << %(": ["String"],)
              {% else %}
                str << %(": ["String", ")
                str << {{arg.default_value}}.to_s.to_json
                str << %("],)
              {% end %}
            {% else %}
              str << %(": [")
              str << {{arg.restriction.stringify}}
              {% if !arg.default_value.is_a?(Nop) %}
                str << %(", ")
                str << {{arg.default_value}}.to_json
              {% end %}
              str << %("],)
            {% end %}
          {% end %}
        str << "},"
      {% end %}
      str << "}"
    end

    # Remove whitespace, remove all ',' followed by a '}'
    @@functions = funcs = list.gsub(/\s/, "").gsub(",}", "}")
    funcs
  end

Thanks for the advice @asterite I made a whole lot of other improvements too however this was the only thing that actually prevented the compilation.

2 Likes