LCOV - code coverage report
Current view: top level - data/include/mcrl2/data - replace_capture_avoiding.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 81 96 84.4 %
Date: 2024-04-17 03:40:49 Functions: 74 190 38.9 %
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/data/replace_capture_avoiding.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_H
      13             : #define MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_H
      14             : 
      15             : #include "mcrl2/core/detail/print_utility.h"
      16             : #include "mcrl2/data/builder.h"
      17             : #include "mcrl2/data/find.h"
      18             : 
      19             : namespace mcrl2 {
      20             : 
      21             : namespace data {
      22             : 
      23             : namespace detail {
      24             : 
      25             : // Wraps a substitution, such that assignments to variables can be added and removed.
      26             : template <typename Substitution>
      27             : struct capture_avoiding_substitution_updater
      28             : {
      29             :   Substitution& sigma;
      30             :   data::set_identifier_generator& id_generator;
      31             :   std::map<variable, std::list<variable>> updates;
      32             : 
      33       12853 :   capture_avoiding_substitution_updater(Substitution& sigma_, data::set_identifier_generator& id_generator_)
      34       12853 :     : sigma(sigma_), id_generator(id_generator_)
      35       12853 :   {}
      36             : 
      37             :   // adds the assignment [v := v'] to sigma, and returns v'
      38         234 :   variable add_fresh_variable_assignment(const variable& v)
      39             :   {
      40         468 :     variable v1(id_generator(v.name()), v.sort());
      41         234 :     updates[v].push_back(v1);
      42         234 :     return v1;
      43           0 :   }
      44             : 
      45             :   // removes the assignment [v := v'] from sigma
      46         234 :   void remove_fresh_variable_assignment(const variable& v)
      47             :   {
      48         234 :     auto i = updates.find(v);
      49         234 :     id_generator.remove_identifier(i->second.back().name());
      50         234 :     i->second.pop_back();
      51         234 :     if (i->second.empty())
      52             :     {
      53         231 :       updates.erase(i);
      54             :     }
      55         234 :   }
      56             : 
      57             :   // adds the assignments [variables := variables'] to sigma, and returns variables'
      58             :   template <typename VariableContainer>
      59        3135 :   variable_list add_fresh_variable_assignments(const VariableContainer& variables)
      60             :   {
      61             :     return variable_list(
      62             :       variables.begin(),
      63             :       variables.end(),
      64         230 :       [&](const variable& v)
      65             :       {
      66         230 :         return add_fresh_variable_assignment(v);
      67             :       }
      68        3135 :     );
      69             :   }
      70             : 
      71             :   // removes the assignments [variables := variables'] from sigma
      72             :   template <typename VariableContainer>
      73        3135 :   void remove_fresh_variable_assignments(const VariableContainer& variables)
      74             :   {
      75        6500 :     for (const variable& v: variables)
      76             :     {
      77         230 :       remove_fresh_variable_assignment(v);
      78             :     }
      79        3135 :   }
      80             : 
      81       76307 :   data_expression operator()(const variable& x)
      82             :   {
      83       76307 :     auto i = updates.find(x);
      84       76307 :     if (i != updates.end())
      85             :     {
      86         345 :       return i->second.back();
      87             :     }
      88             :     else
      89             :     {
      90       75962 :       return sigma(x);
      91             :     }
      92             :   }
      93             : };
      94             : 
      95             : template <typename Substitution>
      96             : std::ostream& operator<<(std::ostream& out, const capture_avoiding_substitution_updater<Substitution>& sigma)
      97             : {
      98             :   std::vector<std::string> updates;
      99             :   for (const auto& p: sigma.updates)
     100             :   {
     101             :     updates.push_back(data::pp(p.first) + " := " + core::detail::print_list(p.second));
     102             :   }
     103             :   return out << sigma.sigma << " with updates " << core::detail::print_list(updates);
     104             : }
     105             : 
     106             : template <template <class> class Builder, template <template <class> class, class, class> class Binder, class Substitution>
     107             : struct replace_capture_avoiding_variables_builder: public Binder<Builder, replace_capture_avoiding_variables_builder<Builder, Binder, Substitution>, Substitution>
     108             : {
     109             :   typedef Binder<Builder, replace_capture_avoiding_variables_builder<Builder, Binder, Substitution>, Substitution> super;
     110             :   using super::enter;
     111             :   using super::leave;
     112             :   using super::apply;
     113             :   using super::update;
     114             : 
     115       12853 :   explicit replace_capture_avoiding_variables_builder(capture_avoiding_substitution_updater<Substitution>& sigma)
     116       12853 :     : super(sigma)
     117       12853 :   { }
     118             : };
     119             : 
     120             : template <template <class> class Builder, template <template <class> class, class, class> class Binder, class Substitution>
     121             : replace_capture_avoiding_variables_builder<Builder, Binder, Substitution>
     122       12853 : apply_replace_capture_avoiding_variables_builder(capture_avoiding_substitution_updater<Substitution>& sigma)
     123             : {
     124       12853 :   return replace_capture_avoiding_variables_builder<Builder, Binder, Substitution>(sigma);
     125             : }
     126             : 
     127             : template <template <class> class Builder, class Derived, class Substitution>
     128             : struct add_capture_avoiding_replacement: public Builder<Derived>
     129             : {
     130             :   typedef Builder<Derived> super;
     131             :   using super::enter;
     132             :   using super::leave;
     133             :   using super::apply;
     134             :   using super::update;
     135             : 
     136             :   capture_avoiding_substitution_updater<Substitution>& sigma;
     137             : 
     138       12853 :   explicit add_capture_avoiding_replacement(capture_avoiding_substitution_updater<Substitution>& sigma_)
     139       12853 :     : sigma(sigma_)
     140       12853 :   { }
     141             : 
     142             :   // applies the substitution to the right hand sides of the assignments
     143             :   template <class T>
     144        3119 :   void apply(atermpp::term_list<T>& result, const assignment_list& x)
     145             :   {
     146        3119 :     result = assignment_list(
     147             :       x.begin(),
     148             :       x.end(),
     149       48304 :       [&](data::assignment&r, const data::assignment& a)
     150             :       {
     151       48304 :         data::make_assignment(r, a.lhs(), [&](data_expression& r){ apply(r, a.rhs() ); } );
     152             :       }
     153             :     );
     154        3119 :   }
     155             : 
     156             :   template <class T>
     157       76307 :   void apply(T& result, const variable& v)
     158             :   {
     159       76307 :     result = sigma(v);
     160       76307 :   }
     161             : 
     162             :   template <class T>
     163           3 :   void apply(T& result, const data::where_clause& x)
     164             :   {
     165           3 :     const auto& declarations = atermpp::container_cast<data::assignment_list>(x.declarations());
     166             : 
     167           3 :     auto declarations1 = data::assignment_list(
     168             :       declarations.begin(),
     169             :       declarations.end(),
     170          12 :       [&](const assignment& a)
     171             :       {
     172           4 :         const data::variable& v = a.lhs();
     173           4 :         const data_expression& x1 = a.rhs();
     174             :         // add the assignment [v := v'] to sigma
     175           4 :         data::variable v1 = sigma.add_fresh_variable_assignment(v);
     176           4 :         data::data_expression rhs;
     177           4 :         apply(rhs, x1);
     178           8 :         return assignment(v1, rhs);
     179           4 :       }
     180             :     );
     181           3 :     data::data_expression body;
     182           3 :     apply(body, x.body());
     183           3 :     make_where_clause(result, body, declarations1);
     184             : 
     185             :     // remove the assignments [v := v'] from sigma
     186          10 :     for (const assignment& a: declarations)
     187             :     {
     188           4 :       const variable& v = a.lhs();
     189           4 :       sigma.remove_fresh_variable_assignment(v);
     190             :     }
     191           3 :   }
     192             : 
     193             :   template <class T>
     194         100 :   void apply(T& result, const data::forall& x)
     195             :   {
     196         100 :     variable_list v1 = sigma.add_fresh_variable_assignments(x.variables());
     197         100 :     data::data_expression body;
     198         100 :     apply(body, x.body());
     199         100 :     data::make_forall(result, v1, body);
     200         100 :     sigma.remove_fresh_variable_assignments(x.variables());
     201         100 :   }
     202             : 
     203             :   template <class T>
     204           0 :   void apply(T& result, const data::exists& x)
     205             :   {
     206           0 :     variable_list v1 = sigma.add_fresh_variable_assignments(x.variables());
     207           0 :     data::data_expression body;
     208           0 :     apply(body, x.body());
     209           0 :     data::make_exists(result, v1, body);
     210           0 :     sigma.remove_fresh_variable_assignments(x.variables());
     211           0 :   }
     212             : 
     213             :   template <class T>
     214           0 :   void apply(T& result, const data::lambda& x)
     215             :   {
     216           0 :     variable_list v1 = sigma.add_fresh_variable_assignments(x.variables());
     217           0 :     data::data_expression body;
     218           0 :     apply(body, x.body());
     219           0 :     data::make_lambda(result, v1, body);
     220           0 :     sigma.remove_fresh_variable_assignments(x.variables());
     221           0 :   }
     222             : 
     223             :   template <class T>
     224             :   void apply(T& /* result */, data_equation& /* x */)
     225             :   {
     226             :     throw mcrl2::runtime_error("not implemented yet");
     227             :   }
     228             : };
     229             : 
     230             : } // namespace detail
     231             : 
     232             : //--- start generated data replace_capture_avoiding code ---//
     233             : /// \\brief Applies sigma as a capture avoiding substitution to x.
     234             : /// \\param x The object to which the subsitution is applied.
     235             : /// \\param sigma A substitution.
     236             : /// \\param id_generator An identifier generator that generates names that do not appear in x and sigma
     237             : template <typename T, typename Substitution>
     238             : void replace_variables_capture_avoiding(T& x,
     239             :                                         Substitution& sigma,
     240             :                                         data::set_identifier_generator& id_generator,
     241             :                                         typename std::enable_if<!std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     242             : )
     243             : {
     244             :   data::detail::capture_avoiding_substitution_updater<Substitution> sigma1(sigma, id_generator);
     245             :   data::detail::apply_replace_capture_avoiding_variables_builder<data::data_expression_builder, data::detail::add_capture_avoiding_replacement>(sigma1).update(x);
     246             : }
     247             : 
     248             : /// \\brief Applies sigma as a capture avoiding substitution to x.
     249             : /// \\param x The object to which the substiution is applied.
     250             : /// \\param sigma A substitution.
     251             : /// \\param id_generator An identifier generator that generates names that do not appear in x and sigma
     252             : template <typename T, typename Substitution>
     253       10197 : T replace_variables_capture_avoiding(const T& x,
     254             :                                      Substitution& sigma,
     255             :                                      data::set_identifier_generator& id_generator,
     256             :                                      typename std::enable_if<std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     257             : )
     258             : {
     259       10197 :   data::detail::capture_avoiding_substitution_updater<Substitution> sigma1(sigma, id_generator);
     260       10197 :   T result;
     261       10197 :   data::detail::apply_replace_capture_avoiding_variables_builder<data::data_expression_builder, data::detail::add_capture_avoiding_replacement>(sigma1).apply(result, x);
     262       20394 :   return result;
     263       10197 : }
     264             : 
     265             : /// \\brief Applies sigma as a capture avoiding substitution to x.
     266             : /// \\param x The object to which the subsitution is applied.
     267             : /// \\param sigma A substitution.
     268             : template <typename T, typename Substitution>
     269             : void replace_variables_capture_avoiding(T& x,
     270             :                                         Substitution& sigma,
     271             :                                         typename std::enable_if<!std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     272             : )
     273             : {
     274             :   data::set_identifier_generator id_generator;
     275             :   id_generator.add_identifiers(data::find_identifiers(x));
     276             :   for (const data::variable& v: substitution_variables(sigma))
     277             :   {
     278             :     id_generator.add_identifier(v.name());
     279             :   }
     280             :   data::replace_variables_capture_avoiding(x, sigma, id_generator);
     281             : }
     282             : 
     283             : /// \\brief Applies sigma as a capture avoiding substitution to x.
     284             : /// \\param x The object to which the substiution is applied.
     285             : /// \\param sigma A substitution.
     286             : template <typename T, typename Substitution>
     287        6405 : T replace_variables_capture_avoiding(const T& x,
     288             :                                      Substitution& sigma,
     289             :                                      typename std::enable_if<std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     290             : )
     291             : {
     292        6405 :   data::set_identifier_generator id_generator;
     293        6405 :   id_generator.add_identifiers(data::find_identifiers(x));
     294       12433 :   for (const data::variable& v: substitution_variables(sigma))
     295             :   {
     296        6028 :     id_generator.add_identifier(v.name());
     297             :   }
     298       12810 :   return data::replace_variables_capture_avoiding(x, sigma, id_generator);
     299        6405 : }
     300             : //--- end generated data replace_capture_avoiding code ---//
     301             : 
     302             : } // namespace data
     303             : 
     304             : } // namespace mcrl2
     305             : 
     306             : #endif // MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_H

Generated by: LCOV version 1.14