LCOV - code coverage report
Current view: top level - data/include/mcrl2/data - replace_capture_avoiding_with_an_identifier_generator.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 45 78 57.7 %
Date: 2024-04-17 03:40:49 Functions: 15 24 62.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Jan Friso Groote
       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_with_an_identifier_generator.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_WITH_AN_IDENTIFIER_GENERATOR_H
      13             : #define MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_WITH_AN_IDENTIFIER_GENERATOR_H
      14             : 
      15             : #include "mcrl2/data/add_binding.h"
      16             : #include "mcrl2/data/builder.h"
      17             : 
      18             : namespace mcrl2 {
      19             : 
      20             : namespace data {
      21             : 
      22             : namespace detail {
      23             : 
      24             : template <typename Substitution, typename IdentifierGenerator>
      25             : class substitution_updater_with_an_identifier_generator
      26             : {
      27             :   protected:
      28             :     Substitution& m_sigma;
      29             :     IdentifierGenerator& m_id_generator;
      30             :     std::vector<data::assignment> m_undo; // why not a stack datatype?
      31             : 
      32             :   public:
      33       55832 :     substitution_updater_with_an_identifier_generator(Substitution& sigma, IdentifierGenerator& id_generator)
      34       55832 :       : m_sigma(sigma), m_id_generator(id_generator)
      35       55832 :     {}
      36             : 
      37       57352 :     Substitution& substitution()
      38             :     {
      39       57352 :       return m_sigma;
      40             :     }
      41             : 
      42         100 :     data::variable bind(const data::variable& v)
      43             :     {
      44         100 :       m_undo.push_back(data::assignment(v, m_sigma(v))); // save the old assignment of m_sigma.
      45         100 :       if (m_sigma.variable_occurs_in_a_rhs(v))                    // v notin FV(m_sigma).
      46             :       {
      47           0 :         m_sigma[v] = v;                                  // Clear sigma[v].
      48           0 :         return v;
      49             :       }
      50             :       else
      51             :       {
      52         200 :         data::variable w(m_id_generator(v.name()), v.sort());
      53         100 :         m_sigma[v] = w;
      54         100 :         return w;
      55         100 :       }
      56             :     }
      57             : 
      58             :     data::variable push(const data::variable& v)
      59             :     {
      60             :       return bind(v);
      61             :     }
      62             : 
      63         100 :     void pop(const data::variable& )
      64             :     {
      65         100 :       const data::assignment& a = m_undo.back();
      66         100 :       m_sigma[a.lhs()] = a.rhs();
      67         100 :       m_undo.pop_back();
      68         100 :     }
      69             : 
      70             :     template <typename VariableContainer>
      71         100 :     VariableContainer push(const VariableContainer& container)
      72             :     {
      73         100 :       std::vector<data::variable> result;
      74         300 :       for (const variable& v: container)
      75             :       {
      76         100 :         result.push_back(bind(v));
      77             :       }
      78         200 :       return VariableContainer(result.begin(), result.end());
      79         100 :     }
      80             : 
      81             :     template <typename VariableContainer>
      82         100 :     void pop(const VariableContainer& container)
      83             :     {
      84         300 :       for (const variable& v: container)
      85             :       {
      86         100 :         pop(v);
      87             :       }
      88         100 :     }
      89             : };
      90             : 
      91             : template <typename Substitution, typename IdentifierGenerator>
      92             : data::variable update_substitution(Substitution& sigma, const data::variable& v, const std::multiset<data::variable>& V, IdentifierGenerator& id_generator)
      93             : {
      94             :   using utilities::detail::contains;
      95             :   if (!contains(V, v) && sigma(v) == v)
      96             :   {
      97             :     return v;
      98             :   }
      99             :   else
     100             :   {
     101             :     id_generator.add_identifier(v.name());
     102             :     data::variable w(id_generator(v.name()), v.sort());
     103             : 
     104             :     while (sigma(w) != w || contains(V, w))
     105             :     {
     106             :       w = data::variable(id_generator(v.name()), v.sort());
     107             :     }
     108             :     sigma[v] = w;
     109             :     return w;
     110             :   }
     111             : }
     112             : 
     113             : template <typename Substitution, typename IdentifierGenerator, typename VariableContainer>
     114             : VariableContainer update_substitution(Substitution& sigma, const VariableContainer& v, const std::multiset<data::variable>& V, IdentifierGenerator& id_generator)
     115             : {
     116             :   std::vector<data::variable> result;
     117             :   for (typename VariableContainer::const_iterator i = v.begin(); i != v.end(); ++i)
     118             :   {
     119             :     result.push_back(update_substitution(sigma, *i, V, id_generator));
     120             :   }
     121             :   return VariableContainer(result.begin(), result.end());
     122             : }
     123             : 
     124             : // Helper code for replace_capture_avoiding_variables_with_an_identifier_generator.
     125             : template<template<class> class Builder,
     126             :   template<template<class> class, class, class, class> class Binder, class Substitution, class IdentifierGenerator>
     127             : struct replace_capture_avoiding_variables_builder_with_an_identifier_generator
     128             :   : public Binder<Builder, replace_capture_avoiding_variables_builder_with_an_identifier_generator<Builder, Binder, Substitution, IdentifierGenerator>, Substitution, IdentifierGenerator>
     129             : {
     130             :   typedef Binder<Builder, replace_capture_avoiding_variables_builder_with_an_identifier_generator<Builder, Binder, Substitution, IdentifierGenerator>, Substitution, IdentifierGenerator> super;
     131             :   using super::enter;
     132             :   using super::leave;
     133             :   using super::apply;
     134             :   using super::update;
     135             : 
     136       55832 :   replace_capture_avoiding_variables_builder_with_an_identifier_generator(Substitution& sigma,
     137             :                                                                           IdentifierGenerator& id_generator)
     138       55832 :     : super(sigma, id_generator)
     139             :   {
     140       55832 :   }
     141             : };
     142             : 
     143             : template<template<class> class Builder,
     144             :   template<template<class> class, class, class, class> class Binder, class Substitution, class IdentifierGenerator>
     145             : replace_capture_avoiding_variables_builder_with_an_identifier_generator<Builder, Binder, Substitution, IdentifierGenerator>
     146       55832 : apply_replace_capture_avoiding_variables_builder_with_an_identifier_generator(Substitution& sigma,
     147             :                                                                               IdentifierGenerator& id_generator)
     148             : {
     149             :   return replace_capture_avoiding_variables_builder_with_an_identifier_generator<Builder, Binder, Substitution, IdentifierGenerator>(
     150       55832 :     sigma, id_generator);
     151             : }
     152             : 
     153             : // In the class below, the IdentifierGenerator is expected to generate fresh identifiers, not
     154             : // occurring anywhere using the operator (). The enumerator_identifier_generator can do this.
     155             : // The substitution has as property that it provides a method "variables_in_rhs" yielding the
     156             : // variables occurring in the right hand side of assignments. The mutable_indexed_substitution has this
     157             : // method.
     158             : template<template<class> class Builder, class Derived, class Substitution, class IdentifierGenerator>
     159             : struct add_capture_avoiding_replacement_with_an_identifier_generator : public Builder<Derived>
     160             : {
     161             :     typedef Builder<Derived> super;
     162             :     using super::enter;
     163             :     using super::leave;
     164             :     using super::apply;
     165             :     using super::update;
     166             : 
     167             :   protected:
     168             :     substitution_updater_with_an_identifier_generator <Substitution, IdentifierGenerator> update_sigma;
     169             : 
     170             :   public:
     171       55832 :     add_capture_avoiding_replacement_with_an_identifier_generator(Substitution& sigma_,
     172             :                                                                   IdentifierGenerator& id_generator_)
     173       55832 :       : update_sigma(sigma_, id_generator_)
     174             :     {
     175       55832 :     }
     176             : 
     177             :     template <class T>
     178       57352 :     void apply(T& result, const variable& v)
     179             :     {
     180       57352 :       result = update_sigma.substitution()(v);
     181       57352 :     }
     182             : 
     183             :     template <class T>
     184           0 :     void apply(T& result, const data::where_clause& x)
     185             :     {
     186           0 :       const auto& assignments = atermpp::container_cast<data::assignment_list>(x.declarations());
     187           0 :       std::vector<data::variable> tmp;
     188           0 :       for (const data::assignment& a: assignments)
     189             :       {
     190           0 :         tmp.push_back(a.lhs());
     191             :       }
     192           0 :       std::vector<data::variable> v = update_sigma.push(tmp);
     193             : 
     194             :       // The updated substitution should be applied to the body.
     195           0 :       data::data_expression new_body;
     196           0 :       apply(new_body, x.body());
     197           0 :       update_sigma.pop(v);
     198             : 
     199             :       // The original substitution should be applied to the right hand sides of the assignments.
     200           0 :       std::vector<data::assignment> a;
     201           0 :       std::vector<data::variable>::const_iterator j = v.begin();
     202           0 :       for (data::assignment_list::const_iterator i = assignments.begin(); i != assignments.end(); ++i, ++j)
     203             :       {
     204           0 :         data::data_expression rhs;
     205           0 :         apply(rhs, i->rhs());
     206           0 :         a.push_back(data::assignment(*j, rhs));
     207             :       }
     208           0 :       data::make_where_clause(result, new_body, assignment_list(a.begin(), a.end()));
     209           0 :     }
     210             : 
     211             :     template <class T>
     212           0 :     void apply(T& result, const data::forall& x)
     213             :     {
     214           0 :       const data::variable_list v = update_sigma.push(x.variables());
     215           0 :       data::data_expression body;
     216           0 :       apply(body, x.body());
     217           0 :       data::make_forall(result, v, body);
     218           0 :       update_sigma.pop(v);
     219           0 :     }
     220             : 
     221             :     template <class T>
     222           0 :     void apply(T& result, const data::exists& x)
     223             :     {
     224           0 :       const data::variable_list v = update_sigma.push(x.variables());
     225           0 :       data::data_expression body;
     226           0 :       apply(body, x.body());
     227           0 :       data::make_exists(result, v, body);
     228           0 :       update_sigma.pop(v);
     229           0 :     }
     230             : 
     231             :     template <class T>
     232          86 :     void apply(T& result, const data::lambda& x)
     233             :     {
     234          86 :       const data::variable_list v = update_sigma.push(x.variables());
     235          86 :       data::data_expression body;
     236          86 :       apply(body, x.body());
     237          86 :       data::make_lambda(result, v, body);
     238          86 :       update_sigma.pop(v);
     239          86 :     }
     240             : 
     241             :     template <class T>
     242             :     void apply(T& /* result */, data_equation& /* x */)
     243             :     {
     244             :       throw mcrl2::runtime_error("not implemented yet");
     245             :     }
     246             : };
     247             : 
     248             : } // namespace detail
     249             : 
     250             : //--- start generated data replace_capture_avoiding_with_identifier_generator code ---//
     251             : /// \\brief Applies sigma as a capture avoiding substitution to x using an identifier generator.
     252             : /// \\details This substitution function is much faster than replace_variables_capture_avoiding, but
     253             : ///          it requires an identifier generator that generates strings for fresh variables. These
     254             : ///          strings must be unique in the sense that they have not been used for other variables.
     255             : /// \\param x The object to which the subsitution is applied.
     256             : /// \\param sigma A mutable substitution of which it can efficiently be checked whether a variable occurs in its
     257             : ///              right hand side. The class maintain_variables_in_rhs is useful for this purpose.
     258             : /// \\param id_generator A generator that generates unique strings, not yet used as variable names.
     259             : 
     260             : template <typename T, typename Substitution, typename IdentifierGenerator>
     261             : void replace_variables_capture_avoiding_with_an_identifier_generator(T& x,
     262             :                        Substitution& sigma,
     263             :                        IdentifierGenerator& id_generator,
     264             :                        typename std::enable_if<!std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     265             :                       )
     266             : {
     267             :   data::detail::apply_replace_capture_avoiding_variables_builder_with_an_identifier_generator<data::data_expression_builder, data::detail::add_capture_avoiding_replacement_with_an_identifier_generator>(sigma, id_generator).update(x);
     268             : }
     269             : 
     270             : /// \\brief Applies sigma as a capture avoiding substitution to x using an identifier generator..
     271             : /// \\details This substitution function is much faster than replace_variables_capture_avoiding, but
     272             : ///          it requires an identifier generator that generates strings for fresh variables. These
     273             : ///          strings must be unique in the sense that they have not been used for other variables.
     274             : /// \\param x The object to which the substiution is applied.
     275             : /// \\param sigma A mutable substitution of which it can efficiently be checked whether a variable occurs in its
     276             : ///              right hand side. The class maintain_variables_in_rhs is useful for this purpose.
     277             : /// \\param id_generator A generator that generates unique strings, not yet used as variable names.
     278             : /// \\return The result is the term x to which sigma has been applied.
     279             : template <typename T, typename Substitution, typename IdentifierGenerator>
     280             : T replace_variables_capture_avoiding_with_an_identifier_generator(const T& x,
     281             :                     Substitution& sigma,
     282             :                     IdentifierGenerator& id_generator,
     283             :                     typename std::enable_if<std::is_base_of<atermpp::aterm, T>::value>::type* = nullptr
     284             :                    )
     285             : {
     286             :   T result;
     287             :   data::detail::apply_replace_capture_avoiding_variables_builder_with_an_identifier_generator<data::data_expression_builder, data::detail::add_capture_avoiding_replacement_with_an_identifier_generator>(sigma, id_generator).apply(result, x);
     288             :   return result;
     289             : }
     290             : //--- end generated data replace_capture_avoiding_with_identifier_generator code ---//
     291             : 
     292             : } // namespace data
     293             : 
     294             : } // namespace mcrl2
     295             : 
     296             : #endif // MCRL2_DATA_REPLACE_CAPTURE_AVOIDING_WITH_AN_IDENTIFIER_GENERATOR_H

Generated by: LCOV version 1.14