LCOV - code coverage report
Current view: top level - atermpp/include/mcrl2/atermpp - aterm_appl.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 53 53 100.0 %
Date: 2024-04-17 03:40:49 Functions: 858 2561 33.5 %
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/atermpp/aterm_appl.h
      10             : /// \brief The term_appl class represents function application.
      11             : 
      12             : #ifndef MCRL2_ATERMPP_ATERM_APPL_H
      13             : #define MCRL2_ATERMPP_ATERM_APPL_H
      14             : 
      15             : #include "mcrl2/atermpp/detail/aterm_appl_iterator.h"
      16             : #include "mcrl2/atermpp/detail/aterm_list.h"
      17             : #include "mcrl2/atermpp/detail/global_aterm_pool.h"
      18             : #include "mcrl2/utilities/type_traits.h"
      19             : 
      20             : namespace atermpp
      21             : {
      22             : 
      23             : template <class Term>
      24             : class term_appl: public aterm
      25             : {
      26             : protected:
      27             :   /// \brief Constructor.
      28             :   /// \param t A pointer internal data structure from which the term is constructed.
      29             :   /// \details This function is explicitly protected such that is not used in common code. 
      30             :   explicit term_appl(detail::_term_appl *t)
      31             :    : aterm(reinterpret_cast<detail::_aterm*>(t))
      32             :   {
      33             :     static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
      34             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
      35             :   }
      36             : 
      37             : public:
      38             :   /// The type of object, T stored in the term_appl.
      39             :   typedef Term value_type;
      40             : 
      41             :   /// Pointer to T.
      42             :   typedef Term* pointer;
      43             : 
      44             :   /// Reference to T.
      45             :   typedef Term& reference;
      46             : 
      47             :   /// Const reference to T.
      48             :   typedef const Term const_reference;
      49             : 
      50             :   /// An unsigned integral type.
      51             :   typedef std::size_t size_type;
      52             : 
      53             :   /// A signed integral type.
      54             :   typedef ptrdiff_t difference_type;
      55             : 
      56             :   /// Iterator used to iterate through an term_appl.
      57             :   typedef term_appl_iterator<Term> iterator;
      58             : 
      59             :   /// Const iterator used to iterate through an term_appl.
      60             :   typedef term_appl_iterator<Term> const_iterator;
      61             : 
      62             :   /// \brief Default constructor.
      63      988717 :   term_appl():aterm()
      64      988717 :   {}
      65             : 
      66             :   /// \brief Explicit constructor from an aterm.
      67             :   /// \param t The aterm from which the term is constructed.
      68 10029731636 :   explicit term_appl(const aterm& t) 
      69 10029731636 :    : aterm(t)
      70             :   {
      71 10029731636 :     assert(type_is_appl());
      72             :     static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
      73             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
      74 10029731636 :   } 
      75             : 
      76             :   /// This class has user-declared copy constructor so declare default copy and move operators.
      77   203149628 :   term_appl(const term_appl& other) noexcept = default;
      78     9801948 :   term_appl& operator=(const term_appl& other) noexcept = default;
      79   116170187 :   term_appl(term_appl&& other) noexcept = default;
      80    44718078 :   term_appl& operator=(term_appl&& other) noexcept = default;
      81             : 
      82             :   /// \brief Constructor that provides an aterm_appl based on a function symbol and forward iterator providing the arguments. 
      83             :   /// \details The iterator range is traversed more than once. If only one traversal is required
      84             :   ///          use term_appl with a TermConverter argument. But this function
      85             :   ///          is substantially less efficient.
      86             :   ///          The length of the iterator range must match the arity of the function symbol.
      87             :   /// \param sym A function symbol.
      88             :   /// \param begin The start of a range of elements.
      89             :   /// \param end The end of a range of elements.
      90             :   template <class ForwardIterator,
      91             :             typename std::enable_if<mcrl2::utilities::is_iterator<ForwardIterator>::value>::type* = nullptr,
      92             :             typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr,
      93             :             typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value>::type* = nullptr>
      94      336509 :   term_appl(const function_symbol& sym,
      95             :             ForwardIterator begin,
      96             :             ForwardIterator end)
      97      336509 :   {
      98      336509 :     detail::g_thread_term_pool().create_appl_dynamic(*this, sym, begin, end);
      99             :     static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
     100             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     101             :     static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value,
     102             :                   "A forward iterator has more requirements than an input iterator.");
     103             :     static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value,
     104             :                   "A forward iterator has more requirements than an output iterator.");
     105      336509 :   }
     106             : 
     107             :   /// \brief Constructor that provides an aterm_appl based on a function symbol and an input iterator providing the arguments. 
     108             :   /// \details The given iterator is traversed only once. So it can be used with an input iterator.
     109             :   ///          This means that the TermConverter is applied exactly once to each element.
     110             :   ///          The length of the iterator range must be equal to the arity of the function symbol.
     111             :   /// \param sym A function symbol.
     112             :   /// \param begin The start of a range of elements.
     113             :   /// \param end The end of a range of elements.
     114             :   template <class InputIterator,
     115             :             typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr,
     116             :             typename std::enable_if<std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr>
     117             :   term_appl(const function_symbol& sym,
     118             :             InputIterator begin,
     119             :             InputIterator end)
     120             :     : term_appl(sym, begin, end, [](const Term& term) -> const Term& { return term; } )
     121             :   {
     122             :     static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
     123             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     124             :     static_assert(std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value,
     125             :                   "The InputIterator is missing the input iterator tag.");
     126             :   }
     127             : 
     128             :   /// \details The given iterator is traversed only once. So it can be used with an input iterator.
     129             :   ///          This means that the TermConverter is applied exactly once to each element.
     130             :   ///          The length of the iterator range must be equal to the arity of the function symbol.
     131             :   /// \param sym A function symbol.
     132             :   /// \param begin The start of a range of elements.
     133             :   /// \param end The end of a range of elements.
     134             :   /// \param converter An class or lambda term containing an operator Term operator()(const Term& t) which is
     135             :   ///        applied to each each element in the iterator range before it becomes an argument of this term.
     136             :   template <class InputIterator,
     137             :             class TermConverter,
     138             :             typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr>
     139      792454 :   term_appl(const function_symbol& sym,
     140             :             InputIterator begin,
     141             :             InputIterator end,
     142             :             TermConverter converter)
     143      792454 :   {
     144      792454 :     detail::g_thread_term_pool().create_appl_dynamic(*this, sym, converter, begin, end);
     145             :     static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     146             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     147             :     static_assert(!std::is_same<typename InputIterator::iterator_category, std::output_iterator_tag>::value,
     148             :                   "The InputIterator has the output iterator tag.");
     149      792454 :   }
     150             : 
     151             :   /// \brief Constructor.
     152             :   /// \param sym A function symbol.
     153      894361 :   term_appl(const function_symbol& sym)
     154      894361 :   {
     155      894361 :     detail::g_thread_term_pool().create_term(*this, sym);
     156             :     static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     157             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     158      894361 :   }
     159             : 
     160             :   /// \brief Constructor for n-arity function application.
     161             :   /// \param symbol A function symbol.
     162             :   /// \param arguments The arguments of the function application.
     163             :   template<typename ...Terms>
     164    32213543 :   term_appl(const function_symbol& symbol, const Terms& ...arguments)
     165    32213543 :   {
     166    32213543 :     detail::g_thread_term_pool().create_appl<Term>(*this, symbol, arguments...);
     167             :     static_assert(detail::are_terms<Terms...>::value, "Arguments of function application should be terms.");
     168             :     static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     169             :     static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     170    32213543 :   }
     171             : 
     172             :   /// \brief Returns the function symbol belonging to an aterm_appl.
     173             :   /// \return The function symbol of this term.
     174  7503377051 :   const function_symbol& function() const
     175             :   {
     176  7503377051 :     return m_term->function();
     177             :   }
     178             : 
     179             :   /// \brief Returns the number of arguments of this term.
     180             :   /// \return The number of arguments of this term.
     181 12678165161 :   size_type size() const
     182             :   {
     183 12678165161 :     return m_term->function().arity();
     184             :   }
     185             : 
     186             :   /// \brief Returns true if the term has no arguments.
     187             :   /// \return True if this term has no arguments.
     188        9971 :   bool empty() const
     189             :   {
     190        9971 :     return size()==0;
     191             :   }
     192             : 
     193             :   /// \brief Returns an iterator pointing to the first argument.
     194             :   /// \return An iterator pointing to the first argument.
     195   285789042 :   const_iterator begin() const
     196             :   {
     197   285789042 :     return const_iterator(reinterpret_cast<const Term*>(&(reinterpret_cast<const detail::_term_appl*>(m_term)->arg(0))));
     198             :   }
     199             : 
     200             :   /// \brief Returns a const_iterator pointing past the last argument.
     201             :   /// \return A const_iterator pointing past the last argument.
     202   285815840 :   const_iterator end() const
     203             :   {
     204   285815840 :     return const_iterator(reinterpret_cast<const Term*>(&reinterpret_cast<const detail::_term_appl*>(m_term)->arg(size())));
     205             :   }
     206             : 
     207             :   /// \brief Returns the largest possible number of arguments.
     208             :   /// \return The largest possible number of arguments.
     209             :   constexpr size_type max_size() const
     210             :   {
     211             :     return std::numeric_limits<size_type>::max();
     212             :   }
     213             : 
     214             :   /// \brief Returns the i-th argument.
     215             :   /// \param i A positive integer.
     216             :   /// \return The argument with the given index.
     217  5827225130 :   const Term& operator[](const size_type i) const
     218             :   {
     219  5827225130 :     assert(i < size()); // Check the bounds.
     220  5827225130 :     return reinterpret_cast<const detail::_term_appl*>(m_term)->arg(i);
     221             :   }
     222             : };
     223             : 
     224             : 
     225             : /// \brief Constructor an aterm_appl in a variable based on a function symbol and an forward iterator providing the arguments. 
     226             : /// \details The iterator range is traversed more than once. If only one traversal is required
     227             : ///          use term_appl with a TermConverter argument. But this function
     228             : ///          is substantially less efficient.
     229             : ///          The length of the iterator range must match the arity of the function symbol.
     230             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     231             : /// \param sym A function symbol.
     232             : /// \param begin The start of a range of elements.
     233             : /// \param end The end of a range of elements.
     234             : template <class Term,
     235             :           class ForwardIterator,
     236             :           typename std::enable_if<mcrl2::utilities::is_iterator<ForwardIterator>::value>::type* = nullptr,
     237             :           typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr,
     238             :           typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value>::type* = nullptr>
     239      775668 : void make_term_appl(Term& target,
     240             :                     const function_symbol& sym,
     241             :                     ForwardIterator begin,
     242             :                     ForwardIterator end)
     243             : {
     244      775668 :   detail::g_thread_term_pool().create_appl_dynamic(target, sym, begin, end);
     245             :   
     246             :   static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
     247             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     248             :   static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value,
     249             :                 "A forward iterator has more requirements than an input iterator.");
     250             :   static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value,
     251             :                 "A forward iterator has more requirements than an output iterator.");
     252      775668 : }
     253             : 
     254             : 
     255             : /// \brief Constructor an aterm_appl in a variable based on a function symbol and an input iterator providing the arguments. 
     256             : /// \details The given iterator is traversed only once. So it can be used with an input iterator.
     257             : ///          This means that the TermConverter is applied exactly once to each element.
     258             : ///          The length of the iterator range must be equal to the arity of the function symbol.
     259             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     260             : /// \param sym A function symbol.
     261             : /// \param begin The start of a range of elements.
     262             : /// \param end The end of a range of elements.
     263             : template <class Term,
     264             :           class InputIterator,
     265             :           typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr,
     266             :           typename std::enable_if<std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr>
     267             : void make_term_appl(Term& target,
     268             :                     const function_symbol& sym,
     269             :                     InputIterator begin,
     270             :                     InputIterator end)
     271             : {
     272             :   make_term_appl(target, sym, begin, end, [](const Term& term) -> const Term& { return term; } );
     273             : 
     274             :   static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
     275             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     276             :   static_assert(std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value,
     277             :                 "The InputIterator is missing the input iterator tag.");
     278             : }
     279             : 
     280             : /// \brief Constructor an aterm_appl in a variable based on a function symbol and an forward iterator providing the arguments. 
     281             : /// \details The given iterator is traversed only once. So it can be used with an input iterator.
     282             : ///          This means that the TermConverter is applied exactly once to each element.
     283             : ///          The length of the iterator range must be equal to the arity of the function symbol.
     284             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     285             : /// \param sym A function symbol.
     286             : /// \param begin The start of a range of elements.
     287             : /// \param end The end of a range of elements.
     288             : /// \param converter An class or lambda term containing an operator Term operator()(const Term& t) which is
     289             : ///        applied to each each element in the iterator range before it becomes an argument of this term.
     290             : template <class Term,
     291             :           class InputIterator,
     292             :           class TermConverter,
     293             :           typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr>
     294     9469023 : void make_term_appl(Term& target,
     295             :                     const function_symbol& sym,
     296             :                     InputIterator begin,
     297             :                     InputIterator end,
     298             :                     TermConverter converter)
     299             : {
     300     9469023 :   detail::g_thread_term_pool().create_appl_dynamic(target, sym, converter, begin, end);
     301             : 
     302             :   static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     303             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     304             :   static_assert(!std::is_same<typename InputIterator::iterator_category, std::output_iterator_tag>::value,
     305             :                 "The InputIterator has the output iterator tag.");
     306     9469023 : }
     307             : 
     308             : /// \brief Make an term_appl consisting of a single function symbol. 
     309             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     310             : /// \param sym A function symbol.
     311             : template <class Term>
     312             : void make_term_appl(Term& target,
     313             :                     const function_symbol& sym)
     314             : {
     315             :   detail::g_thread_term_pool().create_term(target, sym);
     316             : 
     317             :   static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     318             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     319             : }
     320             : 
     321             : /// \brief Make an aterm application for n-arity function application.
     322             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     323             : /// \param symbol A function symbol.
     324             : /// \param arguments The arguments of the function application.
     325             : template<class Term,
     326             :          typename ...Terms>
     327    27824178 : void make_term_appl(Term& target, const function_symbol& symbol, const Terms& ...arguments)
     328             : {
     329    27824178 :   detail::g_thread_term_pool().create_appl(target, symbol, arguments...);
     330             : 
     331             :   // TODO: enable the static_assert below. Doesn't seem to work properly now. 
     332             :   // static_assert(detail::are_terms_or_functions<Terms...>::value, "Arguments of function application should be terms.");
     333             :   static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     334             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     335    27824176 : }
     336             : 
     337             : /// \brief Constructor for n-arity function application with an index.
     338             : /// \param target The variable in which the result will be put. This variable may be used for scratch purposes.
     339             : /// \param symbol A function symbol.
     340             : /// \param arguments The arguments of the function application.
     341             : template<class Term, 
     342             :          class INDEX_TYPE,
     343             :          typename ...Terms>
     344    19721037 : void make_term_appl_with_index(aterm& target, const function_symbol& symbol, const Terms& ...arguments)
     345             : {
     346    19721037 :   detail::g_thread_term_pool().create_appl_index<Term, INDEX_TYPE>(target, symbol, arguments...);
     347             :   // TODO: enable the static_assert below. Doesn't seem to work properly now. 
     348             :   // static_assert(detail::are_terms_or_functions<Terms...>::value, "Arguments of function application should be terms.");
     349             :   static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
     350             :   static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
     351    19721037 : }
     352             : 
     353             : typedef term_appl<aterm> aterm_appl;
     354             : 
     355             : } // namespace atermpp
     356             : 
     357             : namespace std
     358             : {
     359             : 
     360             : /// \brief Swaps two term_applss.
     361             : /// \details This operation is more efficient than exchanging terms by an assignment,
     362             : ///          as swapping does not require to change the protection of terms.
     363             : /// \param t1 The first term.
     364             : /// \param t2 The second term.
     365             : template <class T>
     366             : inline void swap(atermpp::term_appl<T>& t1, atermpp::term_appl<T>& t2) noexcept
     367             : {
     368             :   t1.swap(t2);
     369             : }
     370             : 
     371             : /// \brief Standard hash function.
     372             : template<class T>
     373             : struct hash<atermpp::term_appl<T> >
     374             : {
     375          10 :   std::size_t operator()(const atermpp::term_appl<T>& t) const
     376             :   {
     377          10 :     return std::hash<atermpp::aterm>()(t);
     378             :   }
     379             : };
     380             : } // namespace std
     381             : 
     382             : #endif // MCRL2_ATERMPP_ATERM_APPL_H

Generated by: LCOV version 1.14