LCOV - code coverage report
Current view: top level - modal_formula/include/mcrl2/modal_formula - resolve_name_clashes.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 44 150 29.3 %
Date: 2024-04-21 03:44:01 Functions: 10 36 27.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Wieger Wesselink
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file mcrl2/modal_formula/detail/state_formula_name_clash_resolver.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_MODAL_FORMULA_RESOLVE_NAME_CLASHES_H
      13             : #define MCRL2_MODAL_FORMULA_RESOLVE_NAME_CLASHES_H
      14             : 
      15             : #include "mcrl2/modal_formula/builder.h"
      16             : #include "mcrl2/utilities/detail/container_utility.h"
      17             : 
      18             : namespace mcrl2::state_formulas {
      19             : 
      20             : namespace detail
      21             : {
      22             : 
      23             : template <typename Derived>
      24             : class state_variable_name_clash_resolver: public state_formulas::state_formula_builder<Derived>
      25             : {
      26             :   public:
      27             :     typedef state_formulas::state_formula_builder<Derived> super;
      28             : 
      29             :     using super::enter;
      30             :     using super::leave;
      31             :     using super::apply;
      32             : 
      33             :     typedef std::map<core::identifier_string, std::vector<core::identifier_string> > name_map;
      34             : 
      35             :     /// \brief The stack of names.
      36             :     name_map m_names;
      37             : 
      38             :     /// \brief Generator for fresh variable names.
      39             :     utilities::number_postfix_generator m_generator;
      40             : 
      41             :     /// \brief Pops the name of the stack
      42          16 :     void pop(const core::identifier_string& name)
      43             :     {
      44          16 :       m_names[name].pop_back();
      45          16 :     }
      46             : 
      47             :     /// \brief Pushes name on the stack.
      48          16 :     void push(const core::identifier_string& name)
      49             :     {
      50          16 :       std::vector<core::identifier_string>& names = m_names[name];
      51          16 :       if (names.empty())
      52             :       {
      53           8 :         names.push_back(name);
      54             :       }
      55             :       else
      56             :       {
      57           8 :         names.push_back(m_generator(std::string(name) + "_"));
      58             :       }
      59          16 :     }
      60             : 
      61          14 :     void enter(const mu& x)
      62             :     {
      63          14 :       push(x.name());
      64          14 :     }
      65             : 
      66          14 :     void leave(const mu& x)
      67             :     {
      68          14 :       pop(x.name());
      69          14 :     }
      70             : 
      71           2 :     void enter(const nu& x)
      72             :     {
      73           2 :       push(x.name());
      74           2 :     }
      75             : 
      76           2 :     void leave(const nu& x)
      77             :     {
      78           2 :       pop(x.name());
      79           2 :     }
      80             : 
      81             :     // Rename variable
      82             :     template <class T>
      83          14 :     void apply(T& result, const mu& x)
      84             :     {
      85          14 :       enter(x);
      86             :       // N.B. If the two lines below are replace by
      87             :       //   state_formula result = mu(m_names[x.name()].back(), x.assignments(), (*this)(x.operand()));
      88             :       // a memory error occurs with the clang and intel compilers!
      89          14 :       core::identifier_string name = m_names[x.name()].back();
      90          14 :       state_formula f;
      91          14 :       apply(f, x.operand());
      92          14 :       result = mu(name, x.assignments(), f);
      93          14 :       leave(x);
      94          14 :     }
      95             : 
      96             :     // Rename variable
      97             :     template <class T>
      98           2 :     void apply(T& result, const nu& x)
      99             :     {
     100           2 :       enter(x);
     101             :       // N.B. If the two lines below are replace by
     102             :       //   state_formula result = nu(m_names[x.name()].back(), x.assignments(), (*this)(x.operand()));
     103             :       // a memory error occurs with the clang and intel compilers!
     104           2 :       core::identifier_string name = m_names[x.name()].back();
     105           2 :       state_formula f;
     106           2 :       apply(f, x.operand());
     107           2 :       result = nu(name, x.assignments(), f);
     108           2 :       leave(x);
     109           2 :     }
     110             : 
     111             :     // Rename variable
     112             :     template <class T>
     113          13 :     void apply(T& result, const variable& x)
     114             :     {
     115          13 :       result = variable(m_names[x.name()].back(), x.arguments());
     116          13 :     }
     117             : };
     118             : 
     119             : class state_formula_data_variable_name_clash_resolver: public state_formulas::data_expression_builder<state_formula_data_variable_name_clash_resolver>
     120             : {
     121             :   public:
     122             :     typedef state_formulas::data_expression_builder<state_formula_data_variable_name_clash_resolver> super;
     123             : 
     124             :     using super::enter;
     125             :     using super::leave;
     126             :     using super::apply;
     127             : 
     128             :     data::set_identifier_generator& generator;
     129             :     std::multiset<data::variable> bound_variables;
     130             :     std::map<data::variable, std::vector<data::variable>> substitutions;
     131             : 
     132           0 :     explicit state_formula_data_variable_name_clash_resolver(data::set_identifier_generator& generator_)
     133           0 :      : generator(generator_)
     134           0 :     {}
     135             : 
     136           0 :     void insert(const data::variable& v)
     137             :     {
     138           0 :       if (utilities::detail::contains(bound_variables, v))
     139             :       {
     140           0 :         substitutions[v].push_back(data::variable(generator(v.name()), v.sort()));
     141             :       }
     142           0 :       bound_variables.insert(v);
     143           0 :     }
     144             : 
     145           0 :     void erase(const data::variable& v)
     146             :     {
     147             :       // Remove one variable, which must exist. Do not use bound_variables.erase(v) as it removes all variables v. 
     148           0 :       std::multiset<data::variable>::const_iterator var_iter=bound_variables.find(v);
     149           0 :       assert(var_iter!=bound_variables.end()); 
     150           0 :       bound_variables.erase(var_iter); 
     151             : 
     152           0 :       auto i = substitutions.find(v);
     153           0 :       if (i != substitutions.end())
     154             :       {
     155           0 :         i->second.pop_back();
     156           0 :         if (i->second.empty())
     157             :         {
     158           0 :           substitutions.erase(i);
     159             :         }
     160             :       }
     161           0 :     }
     162             : 
     163           0 :     data::assignment_list apply_assignments(const data::assignment_list& x)
     164             :     {
     165           0 :       auto sigma = [&](const data::variable& v) -> data::data_expression
     166             :       {
     167           0 :         auto i = substitutions.find(v);
     168           0 :         if (i == substitutions.end())
     169             :         {
     170           0 :           return v;
     171             :         }
     172           0 :         return i->second.back();
     173           0 :       };
     174             : 
     175           0 :       return data::assignment_list(x.begin(), x.end(), [&](const data::assignment& a)
     176             :         {
     177           0 :           return data::assignment(atermpp::down_cast<data::variable>(sigma(a.lhs())), data::replace_free_variables(a.rhs(), sigma));
     178             :         }
     179           0 :       );
     180             :     }
     181             : 
     182           0 :     data::variable_list apply_variables(const data::variable_list& x)
     183             :     {
     184           0 :       auto sigma = [&](const data::variable& v) -> data::data_expression
     185             :       {
     186           0 :         auto i = substitutions.find(v);
     187           0 :         if (i == substitutions.end())
     188             :         {
     189           0 :           return v;
     190             :         }
     191           0 :         return i->second.back();
     192           0 :       };
     193             : 
     194           0 :       return data::variable_list(x.begin(), x.end(), [&](const data::variable& v)
     195             :                                    {
     196           0 :                                      return atermpp::down_cast<data::variable>(sigma(v));
     197             :                                    }
     198           0 :       );
     199             :     }
     200             : 
     201             :     template <class T>
     202           0 :     void apply(T& result, const mu& x)
     203             :     {
     204           0 :       for (const data::assignment& a: x.assignments())
     205             :       {
     206           0 :         insert(a.lhs());
     207             :       }
     208           0 :       apply(result, x.operand());
     209           0 :       result = mu(x.name(), apply_assignments(x.assignments()), result);
     210           0 :       for (const data::assignment& a: x.assignments())
     211             :       {
     212           0 :         erase(a.lhs());
     213             :       }
     214           0 :     }
     215             : 
     216             :     template <class T>
     217           0 :     void apply(T& result, const nu& x)
     218             :     {
     219           0 :       for (const data::assignment& a: x.assignments())
     220             :       {
     221           0 :         insert(a.lhs());
     222             :       }
     223           0 :       apply(result, x.operand());
     224           0 :       result = nu(x.name(), apply_assignments(x.assignments()), result);
     225           0 :       for (const data::assignment& a: x.assignments())
     226             :       {
     227           0 :         erase(a.lhs());
     228             :       }
     229           0 :     }
     230             : 
     231             :     template <class T>
     232           0 :     void apply(T& result, const forall& x)
     233             :     {
     234           0 :       for (const data::variable& v: x.variables())
     235             :       {
     236           0 :         insert(v);
     237             :       }
     238           0 :       apply(result,x.body());
     239           0 :       result = forall(apply_variables(x.variables()), result);
     240           0 :       for (const data::variable& v: x.variables())
     241             :       {
     242           0 :         erase(v);
     243             :       }
     244           0 :     }
     245             : 
     246             :     template <class T>
     247           0 :     void apply(T& result, const exists& x)
     248             :     {
     249           0 :       for (const data::variable& v: x.variables())
     250             :       {
     251           0 :         insert(v);
     252             :       }
     253           0 :       apply(result, x.body());
     254           0 :       result = exists(apply_variables(x.variables()), result);
     255           0 :       for (const data::variable& v: x.variables())
     256             :       {
     257           0 :         erase(v);
     258             :       }
     259           0 :     }
     260             : 
     261             :     template <class T>
     262           0 :     void apply(T& result, const action_formulas::forall& x)
     263             :     {
     264           0 :       for (const data::variable& v: x.variables())
     265             :       {
     266           0 :         insert(v);
     267             :       }
     268           0 :       action_formulas::action_formula body;
     269           0 :       apply(body, x.body());
     270           0 :       result = action_formulas::forall(apply_variables(x.variables()), body);
     271           0 :       for (const data::variable& v: x.variables())
     272             :       {
     273           0 :         erase(v);
     274             :       }
     275           0 :     }
     276             : 
     277             :     template <class T>
     278           0 :     void apply(T& result, const action_formulas::exists& x)
     279             :     {
     280           0 :       for (const data::variable& v: x.variables())
     281             :       {
     282           0 :         insert(v);
     283             :       }
     284           0 :       action_formulas::action_formula body;
     285           0 :       apply(body, x.body());
     286           0 :       result = action_formulas::exists(apply_variables(x.variables()), body);
     287           0 :       for (const data::variable& v: x.variables())
     288             :       {
     289           0 :         erase(v);
     290             :       }
     291           0 :     }
     292             : 
     293             :     template <class T>
     294           0 :     void apply(T& result, const data::data_expression& x)
     295             :     {
     296           0 :       auto sigma = [&](const data::variable& v) -> data::data_expression
     297             :       {
     298           0 :         auto i = substitutions.find(v);
     299           0 :         if (i == substitutions.end())
     300             :         {
     301           0 :           return v;
     302             :         }
     303           0 :         return i->second.back();
     304             :       };
     305             : 
     306           0 :       result=data::replace_free_variables(x, sigma);
     307           0 :     }
     308             : };
     309             : 
     310             : } // namespace detail
     311             : 
     312             : /// \brief Resolves name clashes in state variables of formula x
     313             : inline
     314           8 : state_formula resolve_state_variable_name_clashes(const state_formula& x)
     315             : {
     316           8 :   state_formula result;
     317           8 :   core::make_apply_builder<detail::state_variable_name_clash_resolver>().apply(result, x);
     318           8 :   return result;
     319           0 : }
     320             : 
     321             : /// \brief Resolves name clashes in data variables of formula x
     322             : inline
     323           0 : state_formula resolve_state_formula_data_variable_name_clashes(const state_formula& x, const std::set<core::identifier_string>& context_ids = std::set<core::identifier_string>())
     324             : {
     325           0 :   data::set_identifier_generator generator;
     326           0 :   generator.add_identifiers(state_formulas::find_identifiers(x));
     327           0 :   generator.add_identifiers(context_ids);
     328           0 :   detail::state_formula_data_variable_name_clash_resolver f(generator);
     329           0 :   state_formula result;
     330           0 :   f.apply(result, x);
     331           0 :   return result;
     332           0 : }
     333             : 
     334             : } // namespace mcrl2::state_formulas
     335             : 
     336             : #endif // MCRL2_MODAL_FORMULA_RESOLVE_NAME_CLASHES_H

Generated by: LCOV version 1.14