slang_solidity 1.3.5

A modular set of compiler APIs empowering the next generation of Solidity code analysis and developer tooling. Written in Rust and distributed in multiple languages.
Documentation
{% macro render_rewriter(language) -%}
  {%- set target = model.ir_languages[language].target -%}
  #![allow(clippy::too_many_lines)]

  use std::rc::Rc;
  #[allow(clippy::wildcard_imports)]
  use super::nodes::*;

  pub trait Rewriter {
    //
    // Sequences:
    //
    {% for parent_type, sequence in target.sequences %}
      fn rewrite_{{ parent_type | snake_case }}(&mut self, source: &{{ parent_type }}) -> {{ parent_type }} {
        {% for field in sequence.fields %}
          let {{ field.label }} =
          {%- if field.is_optional -%}
            {%- if field.type.kind == "Terminal" -%}
              source.{{ field.label }}.as_ref().map(Rc::clone);
            {%- elif field.type.kind == "UniqueTerminal" -%}
              source.{{ field.label }};
            {%- else -%}
              source.{{ field.label }}.as_ref().map(
                |value| self.rewrite_{{ field.type.name | snake_case }}(value)
              );
            {%- endif -%}
          {%- else -%}
            {%- if field.type.is_terminal -%}
              Rc::clone(&source.{{ field.label }});
            {%- else -%}
              self.rewrite_{{ field.type.name | snake_case }}(&source.{{ field.label }});
            {%- endif -%}
          {%- endif -%}
        {%- endfor %}

        Rc::new({{ parent_type }}Struct {
          node_id: source.node_id,
          {%- for field in sequence.fields -%}
            {{ field.label }},
          {%- endfor %}
        })
      }
    {% endfor %}

    //
    // Choices:
    //
    {% for parent_type, choice in target.choices %}
      fn default_rewrite_{{ parent_type | snake_case }}(&mut self, source: &{{ parent_type }}) -> {{ parent_type }} {
        match source {
          {% for nonterminal in choice.variants | filter(attribute="kind", value="Nonterminal") -%}
            {{ parent_type }}::{{ nonterminal.name }}(ref {{ nonterminal.name | snake_case }}) => {
              {{ parent_type }}::{{ nonterminal.name }}(self.rewrite_{{ nonterminal.name | snake_case }}({{ nonterminal.name | snake_case }}))
            }
          {%- endfor %}
          {% for terminal in choice.variants | filter(attribute="kind", value="Terminal") -%}
            {{ parent_type }}::{{ terminal.name }}(node) => {{ parent_type }}::{{ terminal.name }}(Rc::clone(node)),
          {%- endfor -%}
          {% for terminal in choice.variants | filter(attribute="kind", value="UniqueTerminal") -%}
            {{ parent_type }}::{{ terminal.name }} => {{ parent_type }}::{{ terminal.name }},
          {%- endfor -%}
        }
      }
      fn rewrite_{{ parent_type | snake_case }}(&mut self, source: &{{ parent_type }}) -> {{ parent_type }} {
        self.default_rewrite_{{ parent_type | snake_case }}(source)
      }
    {% endfor %}

    //
    // Repeated & Separated
    //
    {% for parent_type, collection in target.collections %}
      fn rewrite_{{ parent_type | snake_case }}(&mut self, source: &{{ parent_type }}) -> {{ parent_type }} {
        source.iter().map(
          {%- if collection.item_type.is_terminal -%}
            Rc::clone
          {%- else -%}
            |item| self.rewrite_{{ collection.item_type.name | snake_case }}(item)
          {%- endif -%}
        ).collect()
      }
    {% endfor %}
  }

{% endmacro render_rewriter %}