LCOV - code coverage report
Current view: top level - data/include/mcrl2/data - data_specification.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 266 275 96.7 %
Date: 2024-04-19 03:43:27 Functions: 45 46 97.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Jeroen Keiren, Jeroen van der Wulp, 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/data_specification.h
      10             : /// \brief The class data_specification.
      11             : 
      12             : #ifndef MCRL2_DATA_DATA_SPECIFICATION_H
      13             : #define MCRL2_DATA_DATA_SPECIFICATION_H
      14             : 
      15             : #include "mcrl2/data/detail/data_functional.h"
      16             : #include "mcrl2/data/sort_specification.h"
      17             : 
      18             : namespace mcrl2
      19             : {
      20             : 
      21             : namespace data
      22             : {
      23             : 
      24             : // template function overloads
      25             : data_expression normalize_sorts(const data_expression& x, const data::sort_specification& sortspec);
      26             : variable_list normalize_sorts(const variable_list& x, const data::sort_specification& sortspec);
      27             : data::data_equation normalize_sorts(const data::data_equation& x, const data::sort_specification& sortspec);
      28             : data_equation_list normalize_sorts(const data_equation_list& x, const data::sort_specification& sortspec);
      29             : void normalize_sorts(data_equation_vector& x, const data::sort_specification& sortspec);
      30             : 
      31             : // prototype
      32             : class data_specification;
      33             : 
      34             : std::string pp(const data::data_specification& x);
      35             : 
      36             : /// \brief Test for a data specification expression
      37             : /// \param x A term
      38             : /// \return True if \a x is a data specification expression
      39             : inline
      40             : bool is_data_specification(const atermpp::aterm_appl& x)
      41             : {
      42             :   return x.function() == core::detail::function_symbols::DataSpec;
      43             : }
      44             : 
      45             : /// \brief data specification.
      46             : 
      47             : class data_specification: public sort_specification
      48             : {
      49             :   public:
      50             :     typedef std::map<function_symbol,std::pair<std::function<data_expression(const data_expression&)>, std::string> > implementation_map;
      51             : 
      52             :   private:
      53             : 
      54             :     /// \cond INTERNAL_DOCS
      55             :     /// \brief Cached constructors by target sort
      56             :     struct target_sort_to_function_map
      57             :     {
      58             :       bool _outdated;
      59             :       std::map<sort_expression, std::vector<function_symbol> > _mapping;
      60             : 
      61       61702 :       target_sort_to_function_map()
      62       61702 :         : _outdated(true)
      63       61702 :       {}
      64             : 
      65             :       /// \brief Groups functions according to their target sorts.
      66             :       /// \param [in,out] c container in which the functions are stored grouped by target sort.
      67             :       /// \param [in] functions a container with function symbols
      68             :       template <typename Container>
      69         781 :       void group_functions_by_target_sort(std::map<sort_expression, std::vector<function_symbol> >& c, const Container& functions)
      70             :       {
      71       12069 :         for (const function_symbol& f: functions)
      72             :         {
      73       11288 :           const sort_expression s=f.sort();
      74       11288 :           const sort_expression& index_sort = s.target_sort();
      75       11288 :           if(c.find(index_sort) == c.end() || std::find(c[index_sort].begin(), c[index_sort].end(), f) == c[index_sort].end())
      76             :           {
      77             :             // Insert the constructors, such that those with the smallest number of elements occur first.
      78             :             // As there are in general only few constructors, this linear insertion should not take too much time. 
      79       11288 :             std::vector<function_symbol>& relevant_rhs = c[index_sort]; // .push_back(f);
      80       11288 :             const std::size_t f_arity=(is_function_sort(s)?atermpp::down_cast<function_sort>(s).size():0);
      81             :             std::vector<function_symbol>::iterator i=
      82       11288 :                    std::find_if(relevant_rhs.begin(),
      83             :                                 relevant_rhs.end(),
      84      192514 :                                 [f_arity](const function_symbol& g)
      85       96257 :                                           { const std::size_t g_arity=(is_function_sort(g.sort())?
      86       91817 :                                                                 atermpp::down_cast<function_sort>(g.sort()).size():0);
      87       96257 :                                             return f_arity<g_arity;
      88             :                                           });
      89       11288 :             relevant_rhs.insert(i,f);
      90             :           }
      91             :         }
      92         781 :       }
      93             : 
      94             :       template <typename FunctionContainer>
      95       26694 :       void reset(const FunctionContainer& c)
      96             :       {
      97       26694 :         if(_outdated)
      98             :         {
      99         781 :           _mapping.clear();
     100         781 :           group_functions_by_target_sort(_mapping, c);
     101         781 :           _outdated = false;
     102             :         }
     103       26694 :       }
     104             : 
     105       20808 :       void expire()
     106             :       {
     107       20808 :         _outdated = true;
     108       20808 :       }
     109             : 
     110       26694 :       std::map<sort_expression, std::vector<function_symbol> >&mapping()
     111             :       {
     112       26694 :         assert(!_outdated);
     113       26694 :         return _mapping;
     114             :       }
     115             :     };
     116             : 
     117             :     ///\brief Builds a specification from aterm
     118             :     void build_from_aterm(const atermpp::aterm_appl& term);
     119             :     /// \endcond
     120             : 
     121             :   protected:
     122             : 
     123             :     /// \brief A mapping of sort expressions to the constructors corresponding to that sort.
     124             :     function_symbol_vector m_user_defined_constructors;
     125             : 
     126             :     /// \brief The mappings of the specification.
     127             :     function_symbol_vector m_user_defined_mappings;
     128             : 
     129             :     /// \brief The equations of the specification.
     130             :     data_equation_vector m_user_defined_equations;
     131             : 
     132             :     /// \brief Set containing all constructors, including the system defined ones.
     133             :     /// The types in these constructors are normalised.
     134             :     mutable function_symbol_vector m_normalised_constructors;
     135             : 
     136             :     /// \brief Cache normalised constructors grouped by target sort.
     137             :     mutable target_sort_to_function_map m_grouped_normalised_constructors;
     138             : 
     139             :     /// \brief Set containing system defined all mappings, including the system defined ones.
     140             :     /// The types in these mappings are normalised.
     141             :     mutable function_symbol_vector m_normalised_mappings;
     142             : 
     143             :     /// \brief Cache normalised mappings grouped by target sort.
     144             :     mutable target_sort_to_function_map m_grouped_normalised_mappings;
     145             :     //
     146             :     /// \brief Table containing all equations, including the system defined ones.
     147             :     ///        The sorts in these equations are normalised.
     148             :     /// \details The normalised equations are a set as the number of equations
     149             :     ///          can become large, in which case removing duplicates while inserting equations can be
     150             :     ///          very time consuming.
     151             :     mutable std::set<data_equation> m_normalised_equations;
     152             : 
     153             :     /// \brief A map that for function symbols gives how it can be implemented.
     154             :     /// \details For each function symbol there is a function : application -> data_expression that
     155             :     ///          when applied to a term in normal form with the function symbol as head symbol
     156             :     ///          returns a function that can be applied to calculate this term. 
     157             :     ///          Furthermore, it provides the name of a function that when applied to the
     158             :     ///          number of arguments that the function expects can be used to rewrite the term.
     159             :     ///          This last string can be used for code generation. 
     160             :     mutable implementation_map m_cpp_implemented_functions;
     161             : 
     162             : 
     163             : 
     164       14856 :     void data_is_not_necessarily_normalised_anymore() const
     165             :     {
     166       14856 :       m_normalised_data_is_up_to_date=false;
     167       14856 :     }
     168             : 
     169             :   protected:
     170             : 
     171             :     /// \brief Adds a constructor to this specification, and marks it as
     172             :     ///        system defined.
     173             :     ///
     174             :     /// \param[in] f A function symbol.
     175             :     /// \pre f does not yet occur in this specification.
     176             :     /// \post is_system_defined(f) == true
     177             :     /// \note this operation does not invalidate iterators of constructors_const_range
     178             :     inline
     179       82123 :     void add_normalised_constructor(const function_symbol& f) const
     180             :     {
     181       82123 :       function_symbol g(normalize_sorts(f, *this));
     182       82123 :       if (std::find(m_normalised_constructors.begin(),m_normalised_constructors.end(),g)==m_normalised_constructors.end()) // not found
     183             :       {
     184       81295 :         m_normalised_constructors.push_back(g);
     185             :       }
     186       82123 :     }
     187             : 
     188             :     /// \brief Adds a mapping to this specification, and marks it as system
     189             :     ///        defined.
     190             :     ///
     191             :     /// \param[in] f A function symbol.
     192             :     /// \pre f does not yet occur in this specification.
     193             :     /// \post is_system_defined(f) == true
     194             :     /// \note this operation does not invalidate iterators of mappings_const_range
     195     1179922 :     void add_normalised_mapping(const function_symbol& f) const
     196             :     {
     197     1179922 :       function_symbol g(normalize_sorts(f, *this));
     198     1179922 :       if (std::find(m_normalised_mappings.begin(),m_normalised_mappings.end(),g)==m_normalised_mappings.end()) // not found
     199             :       {
     200     1145333 :         m_normalised_mappings.push_back(g);
     201             :       }
     202     1179922 :     }
     203             : 
     204             :     /// \brief Adds an equation to this specification, and marks it as system
     205             :     ///        defined.
     206             :     ///
     207             :     /// \param[in] e An equation.
     208             :     /// \pre e does not yet occur in this specification.
     209             :     /// \post is_system_defined(f) == true
     210             :     /// \note this operation does not invalidate iterators of equations_const_range
     211     2726559 :     void add_normalised_equation(const data_equation& e) const
     212             :     {
     213     2726559 :       m_normalised_equations.insert(normalize_sorts(e,*this));
     214     2726559 :     }
     215             : 
     216             :     template < class Iterator >
     217       72131 :     void add_normalised_constructors(Iterator begin, Iterator end) const
     218             :     {
     219      154107 :       for(Iterator i=begin; i!=end; ++i)
     220             :       {
     221       81976 :         data_specification::add_normalised_constructor(*i);
     222             :       }
     223       72131 :     }
     224             : 
     225             :     template < class Iterator >
     226       72131 :     void add_normalised_mappings(Iterator begin, Iterator end) const
     227             :     {
     228     1250054 :       for(Iterator i=begin; i!=end; ++i)
     229             :       {
     230     1177923 :         data_specification::add_normalised_mapping(*i);
     231             :       }
     232       72131 :     }
     233             : 
     234             :     template < class Iterator >
     235       72131 :     void add_normalised_equations(Iterator begin, Iterator end) const
     236             :     {
     237     2795428 :       for(Iterator i=begin; i!=end; ++i)
     238             :       {
     239     2723297 :         data_specification::add_normalised_equation(*i);
     240             :       }
     241       72131 :     }
     242             : 
     243       72131 :     void add_normalised_cpp_implemented_functions(const implementation_map& c) const
     244             :     {
     245             :       typedef std::pair < function_symbol, std::pair<std::function<data_expression(const data_expression&)>, std::string> > map_result_type;
     246       86115 :       for(const map_result_type f: c)
     247             :       {
     248       13984 :         const function_symbol g(normalize_sorts(f.first,*this));
     249       13984 :         m_cpp_implemented_functions[g]=f.second;
     250       13984 :       }
     251       72131 :     }
     252             : 
     253             :     /// \brief Adds constructors, mappings and equations for a structured sort
     254             :     ///        to this specification, and marks them as system defined.
     255             :     ///
     256             :     /// \param[in] sort A sort expression that is representing the structured sort.
     257             :     /// \param[out] constructors To this set the new constructors are added.
     258             :     /// \param[out] mappings     New mappings are added to this set.
     259             :     /// \param[out] equations    New equations for the structured sort are added to this set.
     260             :     /// \param[in]  skip_equations This boolean indicates whether equations are added.
     261             : 
     262        3496 :     void insert_mappings_constructors_for_structured_sort(
     263             :                        const structured_sort& sort,
     264             :                        std::set < function_symbol >& constructors,
     265             :                        std::set < function_symbol >& mappings,
     266             :                        std::set < data_equation >& equations,
     267             :                        const bool skip_equations) const
     268             :     {
     269        3496 :       const structured_sort& s_sort(sort);
     270        3496 :       function_symbol_vector f(s_sort.constructor_functions(sort));
     271        3496 :       constructors.insert(f.begin(),f.end());
     272        3496 :       f = s_sort.projection_functions(sort);
     273        3496 :       mappings.insert(f.begin(),f.end());
     274        3496 :       f = s_sort.recogniser_functions(sort);
     275        3496 :       mappings.insert(f.begin(),f.end());
     276        3496 :       f = s_sort.comparison_functions(sort);
     277        3496 :       mappings.insert(f.begin(),f.end());
     278             : 
     279        3496 :       if (!skip_equations)
     280             :       {
     281        3496 :         data_equation_vector e(s_sort.constructor_equations(sort));
     282        3496 :         equations.insert(e.begin(),e.end());
     283        3496 :         e = s_sort.projection_equations(sort);
     284        3496 :         equations.insert(e.begin(),e.end());
     285        3496 :         e = s_sort.recogniser_equations(sort);
     286        3496 :         equations.insert(e.begin(),e.end());
     287        3496 :         e = s_sort.comparison_equations(sort);
     288        3496 :         equations.insert(e.begin(),e.end());
     289        3496 :       }
     290        3496 :     }
     291             : 
     292       72141 :     void add_standard_mappings_and_equations(
     293             :                        const sort_expression& sort,
     294             :                        std::set < function_symbol >& mappings,
     295             :                        std::set < data_equation >& equations,
     296             :                        const bool skip_equations) const
     297             :     {
     298       72141 :       function_symbol_vector f(standard_generate_functions_code(sort));
     299       72141 :       mappings.insert(f.begin(), f.end());
     300             : 
     301       72141 :       if (!skip_equations)
     302             :       {
     303       72131 :         const data_equation_vector eq(standard_generate_equations_code(sort));
     304       72131 :         equations.insert(eq.begin(), eq.end());
     305       72131 :       }
     306       72141 :     }
     307             : 
     308             :   public:
     309             : 
     310             :     ///\brief Default constructor. Generate a data specification that contains
     311             :     ///       only booleans and positive numbers.
     312       30776 :     data_specification()
     313       30776 :     {
     314       30776 :     }
     315             : 
     316             :     ///\brief Constructor from an aterm.
     317             :     /// \param[in] t a term adhering to the internal format.
     318           3 :     data_specification(const atermpp::aterm_appl& t)
     319           3 :     {
     320           3 :       build_from_aterm(t);
     321           3 :     }
     322             : 
     323             :     ///\brief Constructor from its members.
     324             :     data_specification(const basic_sort_vector& sorts,
     325             :       const alias_vector& aliases,
     326             :       const function_symbol_vector& constructors,
     327             :       const function_symbol_vector& user_defined_mappings,
     328             :       const data_equation_vector& user_defined_equations);
     329             : 
     330             :     /// \brief Gets all constructors including those that are system defined.
     331             :     /// \details The time complexity is the same as for sorts().
     332             :     /// \return All constructors in this specification, including those for
     333             :     /// structured sorts.
     334             :     inline
     335       35548 :     const function_symbol_vector& constructors() const
     336             :     {
     337       35548 :       normalise_data_specification_if_required();
     338       35548 :       return m_normalised_constructors;
     339             :     }
     340             : 
     341             :     /// \brief Gets the constructors defined by the user, excluding those that
     342             :     /// are system defined.
     343             :     /// \details The time complexity for this operation is constant.
     344             :     inline
     345       10381 :     const function_symbol_vector& user_defined_constructors() const
     346             :     {
     347       10381 :       return m_user_defined_constructors;
     348             :     }
     349             : 
     350             :     /// \brief Gets all constructors of a sort including those that are system defined.
     351             :     ///
     352             :     /// \details The time complexity is the same as for sorts().
     353             :     /// \param[in] s A sort expression.
     354             :     /// \return The constructors for sort s in this specification.
     355             :     inline
     356       26624 :     const function_symbol_vector& constructors(const sort_expression& s, const bool do_not_normalize=false) const
     357             :     {
     358       26624 :       normalise_data_specification_if_required();
     359       26624 :       m_grouped_normalised_constructors.reset(constructors());
     360       26624 :       if (do_not_normalize)
     361             :       {
     362        2749 :         assert(normalize_sorts(s,*this)==s);
     363        2749 :         return m_grouped_normalised_constructors.mapping()[s];
     364             :       }
     365       23875 :       return m_grouped_normalised_constructors.mapping()[normalize_sorts(s,*this)];
     366             :     }
     367             : 
     368             :     /// \brief Gets all mappings in this specification including those that are system defined.
     369             :     ///
     370             :     /// \brief The time complexity is the same as for sorts().
     371             :     /// \return All mappings in this specification, including recognisers and
     372             :     /// projection functions from structured sorts.
     373             :     inline
     374        6158 :     const function_symbol_vector& mappings() const
     375             :     {
     376        6158 :       normalise_data_specification_if_required();
     377        6158 :       return m_normalised_mappings;
     378             :     }
     379             : 
     380             :     /// \brief Gets all user defined mappings in this specification.
     381             :     ///
     382             :     /// \brief The time complexity is constant.
     383             :     /// \return All mappings in this specification, including recognisers and
     384             :     /// projection functions from structured sorts.
     385             :     inline
     386       10403 :     const function_symbol_vector& user_defined_mappings() const
     387             :     {
     388       10403 :       return m_user_defined_mappings;
     389             :     }
     390             : 
     391             :     /// \brief Gets all mappings of a sort including those that are system defined
     392             :     ///
     393             :     /// \param[in] s A sort expression.
     394             :     /// \return All mappings in this specification, for which s occurs as a
     395             :     /// right-hand side of the mapping's sort.
     396             :     inline
     397          70 :     const function_symbol_vector& mappings(const sort_expression& s) const
     398             :     {
     399          70 :       normalise_data_specification_if_required();
     400          70 :       m_grouped_normalised_mappings.reset(mappings());
     401          70 :       return m_grouped_normalised_mappings.mapping()[normalize_sorts(s, *this)];
     402             :     }
     403             : 
     404             :     /// \brief Gets all equations in this specification including those that are system defined
     405             :     ///
     406             :     /// \details The time complexity of this operation is the same as that for sort().
     407             :     /// \return All equations in this specification, including those for
     408             :     ///  structured sorts.
     409             :     inline
     410        2898 :     const std::set<data_equation>& equations() const
     411             :     {
     412        2898 :       normalise_data_specification_if_required();
     413        2898 :       return m_normalised_equations;
     414             :     }
     415             : 
     416             :     /// \brief Gets all equations in this specification including those that are system defined
     417             :     ///
     418             :     /// \details The time complexity of this operation is the same as that for sort().
     419             :     /// \return All equations in this specification, including those for
     420             :     ///  structured sorts.
     421             :     inline
     422      278596 :     const implementation_map& cpp_implemented_functions() const
     423             :     {
     424      278596 :       normalise_data_specification_if_required();
     425      278596 :       return m_cpp_implemented_functions;
     426             :     }
     427             : 
     428             :     /// \brief Gets all user defined equations.
     429             :     ///
     430             :     /// \details The time complexity of this operation is constant.
     431             :     /// \return All equations in this specification, including those for
     432             :     ///  structured sorts.
     433             :     inline
     434        1175 :     const data_equation_vector& user_defined_equations() const
     435             :     {
     436        1175 :       return m_user_defined_equations;
     437             :     }
     438             : 
     439             :     // A variant that allows to replace the user defined equations. 
     440             :     inline
     441        9126 :     data_equation_vector& user_defined_equations()
     442             :     {
     443        9126 :       data_is_not_necessarily_normalised_anymore();
     444        9126 :       return m_user_defined_equations;
     445             :     }
     446             : 
     447             :     /// \brief Adds a constructor to this specification
     448             :     ///
     449             :     /// \param[in] f A function symbol.
     450             :     /// \pre a mapping f does not yet occur in this specification.
     451             :     /// \note this operation does not invalidate iterators of constructors_const_range
     452         137 :     void add_constructor(const function_symbol& f)
     453             :     {
     454         137 :       if (std::find(m_user_defined_constructors.begin(),m_user_defined_constructors.end(),f)==m_user_defined_constructors.end())
     455             :       {
     456         134 :         m_user_defined_constructors.push_back(f);
     457         134 :         import_system_defined_sort(f.sort());
     458         134 :         data_is_not_necessarily_normalised_anymore();
     459             :       }
     460         137 :     }
     461             : 
     462             :     /// \brief Adds a mapping to this specification
     463             :     ///
     464             :     /// \param[in] f A function symbol.
     465             :     /// \pre a constructor f does not yet occur in this specification.
     466             :     /// \note this operation does not invalidate iterators of mappings_const_range
     467        1671 :     void add_mapping(const function_symbol& f)
     468             :     {
     469        1671 :       if (std::find(m_user_defined_mappings.begin(),m_user_defined_mappings.end(),f)==m_user_defined_mappings.end())
     470             :       {
     471        1668 :         m_user_defined_mappings.push_back(f);
     472        1668 :         import_system_defined_sort(f.sort());
     473        1668 :         data_is_not_necessarily_normalised_anymore();
     474             :       }
     475        1671 :     }
     476             : 
     477             :     /// \brief Adds an equation to this specification
     478             :     ///
     479             :     /// \param[in] e An equation.
     480             :     /// \pre e does not yet occur in this specification.
     481             :     /// \note this operation does not invalidate iterators of equations_const_range
     482        2224 :     void add_equation(const data_equation& e)
     483             :     {
     484        2224 :       if(std::find(m_user_defined_equations.begin(),m_user_defined_equations.end(),e)==m_user_defined_equations.end())
     485             :       {
     486        2220 :         m_user_defined_equations.push_back(e);
     487        2220 :         import_system_defined_sorts(find_sort_expressions(e));
     488        2220 :         data_is_not_necessarily_normalised_anymore();
     489             :       }
     490        2224 :     }
     491             : 
     492             :     /// \brief Translate user notation within the equations of the data specification.
     493             :     /// \details This function replaces explicit numbers, lists, sets and bags by their counterpart
     494             :     ///          in the data types. This function is to be invoked after type checking. 
     495        1708 :     void translate_user_notation()
     496             :     {
     497        2237 :        for(data_equation& e: m_user_defined_equations)
     498             :        {
     499         529 :          e = data::translate_user_notation(e);
     500             :        }
     501        1708 :        data_is_not_necessarily_normalised_anymore();
     502        1708 :     }
     503             : 
     504             :   private:
     505             : 
     506             :     ///\brief Puts the constructors, functions and equations in normalised form in
     507             :     ///       de data type.
     508             :     ///\details See the function normalise_sorts on arbitrary objects for a more detailed description.
     509             :     /// All sorts in the constructors, mappings and equations are normalised.
     510       10404 :     void add_data_types_for_sorts() const
     511             :     {
     512             :       // Normalise the sorts of the constructors.
     513       10404 :       m_normalised_constructors.clear();
     514       10404 :       m_normalised_mappings.clear();
     515       10404 :       m_normalised_equations.clear();
     516       10404 :       m_cpp_implemented_functions.clear();
     517             : 
     518       78302 :       for (const sort_expression& sort: sorts())
     519             :       {
     520       67898 :         import_data_type_for_system_defined_sort(sort);
     521             :       }
     522             : 
     523       14637 :       for (const alias& a: user_defined_aliases())
     524             :       {
     525        4233 :         import_data_type_for_system_defined_sort(a.reference());
     526             :       }
     527             : 
     528             : 
     529             :       // Normalise the constructors.
     530       10551 :       for (const function_symbol& f: m_user_defined_constructors)
     531             :       {
     532         147 :         add_normalised_constructor(f);
     533             :       }
     534             : 
     535             :       // Normalise the sorts of the mappings.
     536       12403 :       for (const function_symbol& f: m_user_defined_mappings)
     537             :       {
     538        1999 :         add_normalised_mapping(f);
     539             :       }
     540             : 
     541             :       // Normalise the sorts of the expressions and variables in equations.
     542       13666 :       for (const data_equation& eq: m_user_defined_equations)
     543             :       {
     544        3262 :         add_normalised_equation(data::translate_user_notation(eq));     // in due time (after 2025) this translate user notation can be removed. 
     545             :       }
     546       10404 :     }
     547             : 
     548             :     /// \brief
     549             :     /// \details
     550      374051 :     void normalise_data_specification_if_required() const
     551             :     {
     552      374051 :       if (!m_normalised_data_is_up_to_date)
     553             :       {
     554       10404 :         m_normalised_data_is_up_to_date=true;
     555       10404 :         m_grouped_normalised_constructors.expire();
     556       10404 :         m_grouped_normalised_mappings.expire();
     557       10404 :         add_data_types_for_sorts();
     558             :       }
     559      374051 :     }
     560             : 
     561             :     ///\brief Adds the system defined sorts to the sets with constructors, mappings, and equations for
     562             :     //        a given sort. If the boolean skip_equations is true, no equations are added.
     563             :     void find_associated_system_defined_data_types_for_a_sort(
     564             :                        const sort_expression& sort,
     565             :                        std::set < function_symbol >& constructors,
     566             :                        std::set < function_symbol >& mappings,
     567             :                        std::set < data_equation >& equations,
     568             :                        implementation_map& cpp_implemented_functions,
     569             :                        const bool skip_equations=false) const;
     570             : 
     571             :     ///\brief Adds the system defined sorts in a sequence.
     572             :     ///       The second argument is used to check which sorts are added, to prevent
     573             :     ///       useless repetitions of additions of sorts.
     574             :     /// The function normalise_sorts imports for the given sort_expression sort all sorts, constructors,
     575             :     /// mappings and equations that belong to this sort to the `normalised' sets in this
     576             :     /// data type. E.g. for the sort Nat of natural numbers, it is required that Pos
     577             :     /// (positive numbers) are defined.
     578       72131 :     void import_data_type_for_system_defined_sort(const sort_expression& sort) const
     579             :     {
     580       72131 :       std::set < function_symbol > constructors;
     581       72131 :       std::set < function_symbol > mappings;
     582       72131 :       std::set < data_equation > equations;
     583       72131 :       implementation_map cpp_function_symbols;
     584       72131 :       find_associated_system_defined_data_types_for_a_sort(sort, constructors, mappings, equations, cpp_function_symbols);
     585             : 
     586             :       // add normalised constructors, mappings and equations
     587       72131 :       add_normalised_constructors(constructors.begin(), constructors.end());
     588       72131 :       add_normalised_mappings(mappings.begin(), mappings.end());
     589       72131 :       add_normalised_equations(equations.begin(), equations.end());
     590       72131 :       add_normalised_cpp_implemented_functions(cpp_function_symbols);
     591       72131 :     }
     592             : 
     593             :   public:
     594             : 
     595             :     /// \brief This function provides a sample of all system defined sorts, constructors and mappings
     596             :     ///        that contains at least one specimen of each sort and function symbol. Because types
     597             :     ///        can be parameterised not all function symbols for all types are provided.
     598             :     /// \details The sorts, constructors and mappings for the following types are added:
     599             :     ///            Bool, Pos, Int, Nat, Real, List(Pos), FSet(Pos), FBag(Pos), Set(Pos), Bag(Pos).
     600             :     ///       How to deal with struct...
     601             :     void get_system_defined_sorts_constructors_and_mappings(
     602             :                 std::set < sort_expression >& sorts,
     603             :                 std::set < function_symbol >& constructors,
     604             :                 std::set <function_symbol >& mappings) const;
     605             : 
     606             :     /// \brief Removes constructor from specification.
     607             :     ///
     608             :     /// Note that this does not remove equations containing the constructor.
     609             :     /// \param[in] f A constructor.
     610             :     /// \pre f occurs in the specification as constructor.
     611             :     /// \post f does not occur as constructor.
     612             :     /// \note this operation does not invalidate iterators of constructors_const_range,
     613             :     /// only if they point to the element that is removed
     614           3 :     void remove_constructor(const function_symbol& f)
     615             :     {
     616           3 :       detail::remove(m_normalised_constructors, normalize_sorts(f,*this));
     617           3 :       detail::remove(m_user_defined_constructors, f);
     618           3 :     }
     619             : 
     620             :     /// \brief Removes mapping from specification.
     621             :     ///
     622             :     /// Note that this does not remove equations in which the mapping occurs.
     623             :     /// \param[in] f A function.
     624             :     /// \post f does not occur as constructor.
     625             :     /// \note this operation does not invalidate iterators of mappings_const_range,
     626             :     /// only if they point to the element that is removed
     627           2 :     void remove_mapping(const function_symbol& f)
     628             :     {
     629           2 :       detail::remove(m_normalised_mappings, normalize_sorts(f,*this));
     630           2 :       detail::remove(m_user_defined_mappings, f);
     631           2 :     }
     632             : 
     633             :     /// \brief Removes equation from specification.
     634             :     ///
     635             :     /// \param[in] e An equation.
     636             :     /// \post e is removed from this specification.
     637             :     /// \note this operation does not invalidate iterators of equations_const_range,
     638             :     /// only if they point to the element that is removed
     639           2 :     void remove_equation(const data_equation& e)
     640             :     {
     641           2 :       const data_equation e1=data::translate_user_notation(e);              // in due time (after 2025) this translate user notation could possibly be removed.
     642             :                                                                             // as it stands this function is not used. 
     643           2 :       detail::remove(m_normalised_equations, normalize_sorts(e1,*this));
     644           2 :       detail::remove(m_user_defined_equations, e);
     645           2 :     }
     646             : 
     647             :     /// \brief Checks whether two sort expressions represent the same sort
     648             :     ///
     649             :     /// \param[in] s1 A sort expression
     650             :     /// \param[in] s2 A sort expression
     651       24143 :     bool equal_sorts(sort_expression const& s1, sort_expression const& s2) const
     652             :     {
     653       24143 :       normalise_data_specification_if_required();
     654       24143 :       const sort_expression normalised_sort1=normalize_sorts(s1,*this);
     655       24143 :       const sort_expression normalised_sort2=normalize_sorts(s2,*this);
     656       48286 :       return (normalised_sort1 == normalised_sort2);
     657       24143 :     }
     658             : 
     659             :     /// \brief Checks whether a sort is certainly finite.
     660             :     ///
     661             :     /// \param[in] s A sort expression
     662             :     /// \return true if s can be determined to be finite,
     663             :     ///      false otherwise.
     664             :     bool is_certainly_finite(const sort_expression& s) const;
     665             : 
     666             :     /// \brief Checks whether a sort is a constructor sort
     667             :     ///
     668             :     /// \param[in] s A sort expression
     669             :     /// \return true if s is a constructor sort
     670             :     bool is_constructor_sort(const sort_expression& s) const
     671             :     {
     672             :       normalise_data_specification_if_required();
     673             :       const sort_expression normalised_sort=normalize_sorts(s,*this);
     674             :       return !is_function_sort(normalised_sort) && !constructors(normalised_sort).empty();
     675             :     }
     676             : 
     677             :     /// \brief Returns true if
     678             :     /// <ul>
     679             :     /// <li>the domain and range sorts of constructors are contained in the list of sorts</li>
     680             :     /// <li>the domain and range sorts of mappings are contained in the list of sorts</li>
     681             :     /// </ul>
     682             :     /// \return True if the data specification is well typed.
     683             :     bool is_well_typed() const;
     684             : 
     685           7 :     bool operator==(const data_specification& other) const
     686             :     {
     687           7 :       normalise_data_specification_if_required();
     688           7 :       other.normalise_data_specification_if_required();
     689             :       return
     690           7 :         sort_specification::operator==(other) &&
     691           7 :         m_normalised_constructors == other.m_normalised_constructors &&
     692          21 :         m_normalised_mappings == other.m_normalised_mappings &&
     693          14 :         m_normalised_equations == other.m_normalised_equations;
     694             :     }
     695             : 
     696             : }; // class data_specification
     697             : 
     698             : //--- start generated class data_specification ---//
     699             : // prototype declaration
     700             : std::string pp(const data_specification& x);
     701             : 
     702             : /// \\brief Outputs the object to a stream
     703             : /// \\param out An output stream
     704             : /// \\param x Object x
     705             : /// \\return The output stream
     706             : inline
     707           0 : std::ostream& operator<<(std::ostream& out, const data_specification& x)
     708             : {
     709           0 :   return out << data::pp(x);
     710             : }
     711             : //--- end generated class data_specification ---//
     712             : 
     713             : /// \brief Merges two data specifications into one.
     714             : /// \details It is assumed that the two specs can be merged. I.e.
     715             : ///          that the second is a safe extension of the first.
     716             : /// \param[in] spec1 One of the input specifications.
     717             : /// \param[in] spec2 The second input specification.
     718             : /// \return A specification that is merged.
     719          12 : inline data_specification operator +(data_specification spec1, const data_specification& spec2)
     720             : {
     721          12 :   for(const basic_sort& bsort: spec2.user_defined_sorts())
     722             :   {
     723           0 :     spec1.add_sort(bsort);
     724             :   }
     725             : 
     726          80 :   for(const sort_expression& sort: spec2.context_sorts())
     727             :   {
     728          68 :     spec1.add_context_sort(sort);
     729             :   }
     730             : 
     731          16 :   for(const alias& a: spec2.user_defined_aliases())
     732             :   {
     733           4 :     spec1.add_alias(a);
     734             :   }
     735             : 
     736          12 :   for(const function_symbol& f: spec2.user_defined_constructors())
     737             :   {
     738           0 :     spec1.add_constructor(f);
     739             :   }
     740             : 
     741          13 :   for(const function_symbol& f: spec2.user_defined_mappings())
     742             :   {
     743           1 :     spec1.add_mapping(f);
     744             :   }
     745             : 
     746          13 :   for(const data_equation& e: spec2.user_defined_equations())
     747             :   {
     748           1 :     spec1.add_equation(e);
     749             :   }
     750             : 
     751          12 :   return spec1;
     752             : }
     753             : 
     754             : /// \brief Finds a mapping in a data specification.
     755             : /// \param data A data specification
     756             : /// \param s A string
     757             : /// \return The found mapping
     758             : 
     759             : inline
     760          10 : function_symbol find_mapping(data_specification const& data, std::string const& s)
     761             : {
     762          10 :   const function_symbol_vector& r(data.mappings());
     763          10 :   function_symbol_vector::const_iterator i = std::find_if(r.begin(), r.end(), detail::function_symbol_has_name(s));
     764          20 :   return (i == r.end()) ? function_symbol() : *i;
     765             : }
     766             : 
     767             : /// \brief Finds a constructor in a data specification.
     768             : /// \param data A data specification
     769             : /// \param s A string
     770             : /// \return The found constructor
     771             : 
     772             : inline
     773             : function_symbol find_constructor(data_specification const& data, std::string const& s)
     774             : {
     775             :   const function_symbol_vector& r(data.constructors());
     776             :   function_symbol_vector::const_iterator i = std::find_if(r.begin(), r.end(), detail::function_symbol_has_name(s));
     777             :   return (i == r.end()) ? function_symbol() : *i;
     778             : }
     779             : 
     780             : /// \brief Finds a sort in a data specification.
     781             : /// \param data A data specification
     782             : /// \param s A string
     783             : /// \return The found sort
     784             : 
     785             : inline
     786             : sort_expression find_sort(data_specification const& data, std::string const& s)
     787             : {
     788             :   const std::set<sort_expression>& r(data.sorts());
     789             :   const std::set<sort_expression>::const_iterator i = std::find_if(r.begin(), r.end(), detail::sort_has_name(s));
     790             :   return (i == r.end()) ? sort_expression() : *i;
     791             : }
     792             : 
     793             : /// \brief Gets all equations with a data expression as head
     794             : /// on one of its sides.
     795             : ///
     796             : /// \param[in] specification A data specification.
     797             : /// \param[in] d A data expression.
     798             : /// \return All equations with d as head in one of its sides.
     799             : 
     800             : inline
     801           1 : data_equation_vector find_equations(data_specification const& specification, const data_expression& d)
     802             : {
     803           1 :   data_equation_vector result;
     804         130 :   for (const data_equation& eq: specification.equations())
     805             :   {
     806         129 :     if (eq.lhs() == d || eq.rhs() == d)
     807             :     {
     808           1 :       result.push_back(eq);
     809             :     }
     810         128 :     else if (is_application(eq.lhs()))
     811             :     {
     812         128 :       if (atermpp::down_cast<application>(eq.lhs()).head() == d)
     813             :       {
     814           1 :         result.push_back(eq);
     815             :       }
     816             :     }
     817           0 :     else if (is_application(eq.rhs()))
     818             :     {
     819           0 :       if (atermpp::down_cast<application>(eq.rhs()).head() == d)
     820             :       {
     821           0 :         result.push_back(eq);
     822             :       }
     823             :     }
     824             :   }
     825           1 :   return result;
     826           0 : }
     827             : 
     828             : 
     829             : 
     830             : /// \brief Order the variables in a variable list such that enumeration over these variables becomes more efficient.
     831             : //  \detail This routine is experimental, and may benefit from further investigation. The rule of thumb that is
     832             : //          now used is that first variables of enumerated types are put in the variable list. These are sorts with
     833             : //          constructors that have no arguments, typically resulting from declarations such as sort Enum = struct e1 | e2 | e3.
     834             : //          The variables with the largest number of elements are put in front.
     835             : //          Subsequently, the other data types with a finite number of elements are listed, in arbitrary sequence. At the
     836             : //          end all other variables are put in an arbitrary sequence.
     837             : /// \param[in] l A list of variables that are to be sorted.
     838             : /// \param[in] data_spec A data specification containing the constructors that are used to determine efficiency.
     839             : /// \return The same list of variables but ordered in such a way that
     840             : 
     841             : 
     842         576 : inline variable_list order_variables_to_optimise_enumeration(const variable_list& l, const data_specification& data_spec)
     843             : {
     844             :   // Put variables with enumerated types with the largest number of elements in front.
     845             :   // Put variables of finite types as second.
     846             :   // Finally put the other variables in the list.
     847         576 :   std::map < std::size_t,variable_list> vars_of_enumerated_type;
     848         576 :   variable_list vars_of_finite_type;
     849         576 :   variable_list rest_vars;
     850         875 :   for(const variable& v: l)
     851             :   {
     852         299 :     if (data_spec.is_certainly_finite(v.sort()))
     853             :     {
     854         250 :       bool is_enumerated_type=true;
     855         704 :       for(const function_symbol& f: data_spec.constructors(v.sort()))
     856             :       {
     857         466 :         if (is_function_sort(f.sort()) && function_sort(f.sort()).domain().size()>0)
     858             :         {
     859          12 :           is_enumerated_type=false;
     860          12 :           break;
     861             :         }
     862             :       }
     863         250 :       if (is_enumerated_type)
     864             :       {
     865         238 :         vars_of_enumerated_type[data_spec.constructors(v.sort()).size()].push_front(v);
     866             :       }
     867             :       else
     868             :       {
     869          12 :         vars_of_finite_type.push_front(v);
     870             :       }
     871             :     }
     872             :     else
     873             :     {
     874             :       // variable *i has no finite type
     875          49 :       rest_vars.push_front(v);
     876             :     }
     877             :   }
     878             : 
     879             :   // Accumulate the result in rest_vars
     880         576 :   rest_vars=vars_of_finite_type + rest_vars;
     881         809 :   for(std::map <std::size_t,variable_list>::const_reverse_iterator k=vars_of_enumerated_type.rbegin(); k!=vars_of_enumerated_type.rend(); ++k)
     882             :   {
     883         233 :     rest_vars = k->second + rest_vars;
     884             :   }
     885        1152 :   return rest_vars;
     886         576 : }
     887             : 
     888             : /// \brief Returns the names of functions and mappings that occur in a data specification.
     889             : /// \param[in] dataspec A data specification
     890             : inline
     891         528 : std::set<core::identifier_string> function_and_mapping_identifiers(const data_specification& dataspec)
     892             : {
     893         528 :   std::set<core::identifier_string> result;
     894        4816 :   for (const function_symbol& f: dataspec.constructors())
     895             :   {
     896        4288 :     result.insert(f.name());
     897             :   }
     898       65438 :   for (const function_symbol& f: dataspec.mappings())
     899             :   {
     900       64910 :     result.insert(f.name());
     901             :   }
     902         528 :   return result;
     903           0 : }
     904             : 
     905             : } // namespace data
     906             : 
     907             : } // namespace mcrl2
     908             : 
     909             : #endif // MCRL2_DATA_DATA_SPECIFICATION_H

Generated by: LCOV version 1.14