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_transformer(language) -%}
  {%- set transformer = model.ir_languages[language].transformer -%}
  {%- set target = model.ir_languages[language].target -%}
  // Transformer from previous language implementation
  #![allow(clippy::too_many_lines)]

  use std::rc::Rc;
  use super::{input, nodes as output};
  #[allow(unused)]
  use crate::cst::TerminalNode;

  pub trait Transformer {
    //
    // Sequences:
    //
    {% for parent_type, sequence in transformer.sequences %}
      fn transform_{{ parent_type | snake_case }}(&mut self, source: &input::{{ parent_type }}) -> output::{{ parent_type }}
      {% if not sequence.has_added_fields %}
        {
          {% for field in sequence.fields %}
            {%- if not field.is_removed -%}
              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.transform_{{ field.type.name | snake_case }}(value)
                  );
                {%- endif -%}
              {%- else -%}
                {%- if field.type.is_terminal -%}
                  Rc::clone(&source.{{ field.label }});
                {%- else -%}
                  self.transform_{{ field.type.name | snake_case }}(&source.{{ field.label }});
                {%- endif -%}
              {%- endif -%}
            {%- endif -%}
          {%- endfor %}

          Rc::new(output::{{ parent_type }}Struct {
            node_id: source.node_id,
            {%- for field in sequence.fields -%}
              {%- if not field.is_removed -%}
                {{ field.label }},
              {%- endif -%}
            {%- endfor %}
          })
        }
      {% else %}
        ;
      {% endif %}
    {% endfor %}

    //
    // Collapsed sequences:
    //
    {% for parent_type, collapsed in transformer.collapsed_sequences %}
      fn transform_{{ parent_type | snake_case }}(&mut self, source: &input::{{ parent_type }}) ->
      {%- if collapsed.target_type.is_terminal -%}
        Rc<TerminalNode>
      {%- else -%}
        output::{{ collapsed.target_type.name }}
      {%- endif -%}
      {
        {%- if collapsed.target_type.is_terminal -%}
          Rc::clone(&source.{{ collapsed.label }})
        {%- else -%}
          self.transform_{{ collapsed.type.name | snake_case }}(&source.{{ collapsed.label }})
        {%- endif -%}
      }
    {% endfor %}

    //
    // Choices:
    //
    {% for parent_type, choice in transformer.choices %}
      {% if not choice.is_new -%}
        fn default_transform_{{ parent_type | snake_case }}(&mut self, source: &input::{{ parent_type }}) -> output::{{ parent_type }} {
          #[allow(clippy::match_wildcard_for_single_variants)]
          #[allow(clippy::match_single_binding)]
          match source {
            {% for nonterminal in choice.variants | filter(attribute="kind", value="Nonterminal") -%}
              input::{{ parent_type }}::{{ nonterminal.name }}(ref {{ nonterminal.name | snake_case }}) => {
                output::{{ parent_type }}::{{ nonterminal.name }}(self.transform_{{ nonterminal.name | snake_case }}({{ nonterminal.name | snake_case }}))
              }
            {%- endfor -%}
            {% for terminal in choice.variants | filter(attribute="kind", value="Terminal") -%}
              input::{{ parent_type }}::{{ terminal.name }}(node) => output::{{ parent_type }}::{{ terminal.name }}(Rc::clone(node)),
            {%- endfor -%}
            {% for terminal in choice.variants | filter(attribute="kind", value="UniqueTerminal") -%}
              input::{{ parent_type }}::{{ terminal.name }} => output::{{ parent_type }}::{{ terminal.name }},
            {%- endfor -%}
            {% if choice.has_removed_variants %}
              _ => panic!("Unexpected variant {source:?}"),
            {% endif %}
          }
        }
        fn transform_{{ parent_type | snake_case }}(&mut self, source: &input::{{ parent_type }}) -> output::{{ parent_type }} {
          self.default_transform_{{ parent_type | snake_case }}(source)
        }
      {%- endif %}
    {% endfor %}

    //
    // Repeated & Separated
    //

    {% for parent_type, collection in transformer.collections %}
      {% if not collection.is_new -%}
        fn transform_{{ parent_type | snake_case }}(&mut self, source: &input::{{ parent_type }}) -> output::{{ parent_type }} {
          source.iter().map(
            {%- if collection.item_type.is_terminal -%}
              Rc::clone
            {%- else -%}
              |item| self.transform_{{ collection.item_type.name | snake_case }}(item)
            {%- endif -%}
          ).collect()
        }
      {%- endif %}
    {% endfor %}
  }

{% endmacro render_transformer %}