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/core/builder.h
10 : /// \brief add your file description here.
11 :
12 : #ifndef MCRL2_CORE_BUILDER_H
13 : #define MCRL2_CORE_BUILDER_H
14 :
15 : #include "mcrl2/atermpp/aterm_list.h"
16 :
17 : namespace mcrl2
18 : {
19 :
20 : namespace core
21 : {
22 :
23 : #ifdef MCRL2_DEBUG_EXPRESSION_BUILDER
24 : inline void msg(const std::string& s)
25 : {
26 : std::cout << "--- " << s << " ---" << std::endl;
27 : }
28 : #else
29 2854372 : inline void msg(const std::string&)
30 2854372 : {}
31 : #endif
32 :
33 : /**
34 : * \brief expression builder that visits all sub expressions
35 : *
36 : * Types:
37 : * \arg Derived the type of a derived class, as per CRTP
38 : *
39 : **/
40 : template <typename Derived>
41 : struct builder
42 : {
43 : // Enter object
44 : template <typename T>
45 75565250 : void enter(const T&)
46 75565250 : {}
47 :
48 : // Leave object
49 : template <typename T>
50 75564747 : void leave(const T&)
51 75564747 : {}
52 :
53 : template <typename T>
54 3504 : void update(T& x, typename atermpp::disable_if_container<T>::type* = nullptr)
55 : {
56 3504 : msg("non-container visit");
57 3504 : T result;
58 3504 : static_cast<Derived*>(this)->apply(result, x);
59 3504 : x = result;
60 3504 : }
61 :
62 : // container visit
63 : template <typename T>
64 8469 : void update(T& x, typename atermpp::enable_if_container<T>::type* = nullptr)
65 : {
66 8469 : msg("container visit");
67 23711 : for (auto& v: x)
68 : {
69 15242 : static_cast<Derived*>(this)->update(v);
70 : }
71 8469 : }
72 :
73 : // aterm set visit
74 : template <typename T>
75 1638 : void update(std::set<T>& x)
76 : {
77 1638 : msg("set visit");
78 1638 : std::set<T> result;
79 1793 : for (T v: x)
80 : {
81 155 : static_cast<Derived*>(this)->update(v);
82 155 : result.insert(v);
83 : }
84 1638 : result.swap(x);
85 1638 : }
86 :
87 : // term_list visit copy
88 : template <typename T, typename U>
89 2840761 : void apply(atermpp::term_list<T>& result, const atermpp::term_list<U>& x)
90 : {
91 2840761 : msg("term_list traversal");
92 2840761 : atermpp::make_term_list<T>(static_cast<atermpp::term_list<T>&>(result),
93 : x.begin(),
94 : x.end(),
95 4937508 : [&](T& result, const U& v) { static_cast<Derived*>(this)->apply(result, v); } );
96 2840761 : }
97 : };
98 :
99 :
100 : // apply a builder without additional template arguments
101 : template <template <class> class Builder>
102 : class apply_builder: public Builder<apply_builder<Builder> >
103 : {
104 : typedef Builder<apply_builder<Builder> > super;
105 :
106 : public:
107 :
108 : using super::enter;
109 : using super::leave;
110 : using super::apply;
111 : using super::update;
112 : };
113 :
114 : template <template <class> class Builder>
115 : apply_builder<Builder>
116 24974 : make_apply_builder()
117 : {
118 24974 : return apply_builder<Builder>();
119 : }
120 :
121 : // apply a builder with one additional template argument
122 : template <template <class> class Builder, class Arg1>
123 : class apply_builder_arg1: public Builder<apply_builder_arg1<Builder, Arg1> >
124 : {
125 : typedef Builder<apply_builder_arg1<Builder, Arg1> > super;
126 :
127 : public:
128 : using super::enter;
129 : using super::leave;
130 : using super::apply;
131 : using super::update;
132 :
133 81 : apply_builder_arg1(const Arg1& arg1):
134 81 : super(arg1)
135 81 : {}
136 : };
137 :
138 : template <template <class> class Builder, class Arg1>
139 : apply_builder_arg1<Builder, Arg1>
140 81 : make_apply_builder_arg1(const Arg1& arg1)
141 : {
142 81 : return apply_builder_arg1<Builder, Arg1>(arg1);
143 : }
144 :
145 : // apply a builder with two additional template arguments
146 : template <template <class> class Builder, class Arg1, class Arg2>
147 : class apply_builder_arg2: public Builder<apply_builder_arg2<Builder, Arg1, Arg2> >
148 : {
149 : typedef Builder<apply_builder_arg2<Builder, Arg1, Arg2> > super;
150 :
151 : public:
152 : using super::enter;
153 : using super::leave;
154 : using super::apply;
155 : using super::update;
156 :
157 39 : apply_builder_arg2(const Arg1& arg1, const Arg2& arg2):
158 39 : super(arg1, arg2)
159 39 : {}
160 : };
161 :
162 : template <template <class> class Builder, class Arg1, class Arg2>
163 : apply_builder_arg2<Builder, Arg1, Arg2>
164 39 : make_apply_builder_arg2(const Arg1& arg1, const Arg2& arg2)
165 : {
166 39 : return apply_builder_arg2<Builder, Arg1, Arg2>(arg1, arg2);
167 : }
168 :
169 :
170 : // apply a builder without additional template arguments
171 : template <template <class> class Builder, class Function>
172 : struct update_apply_builder: public Builder<update_apply_builder<Builder, Function> >
173 : {
174 : typedef Builder<update_apply_builder<Builder, Function> > super;
175 :
176 : using super::enter;
177 : using super::leave;
178 : using super::apply;
179 : using super::update;
180 :
181 : using argument_type = typename Function::argument_type; ///< The argument_type is required to restrict the overloads of apply(x) to that type.
182 : using result_type = typename Function::result_type; ///< The argument_type is required to restrict the overloads of apply(x) to that type.
183 : const Function& f_;
184 :
185 : template <class T>
186 29946341 : void apply(T& result, const argument_type& x) // -> decltype(f_(x))
187 : {
188 : // static_cast<result_type&>(result) = f_(x);
189 29946341 : result = static_cast<T>(f_(x));
190 29946341 : }
191 :
192 4786155 : update_apply_builder(const Function& f)
193 4786155 : : f_(f)
194 4786155 : {}
195 : };
196 :
197 : template <template <class> class Builder, class Function>
198 : update_apply_builder<Builder, Function>
199 4786155 : make_update_apply_builder(const Function& f)
200 : {
201 4786155 : return update_apply_builder<Builder, Function>(f);
202 : }
203 :
204 : // apply a builder with one additional template argument
205 : template <template <class> class Builder, class Function, class Arg1>
206 : class update_apply_builder_arg1: public Builder<update_apply_builder_arg1<Builder, Function, Arg1> >
207 : {
208 : typedef Builder<update_apply_builder_arg1<Builder, Function, Arg1> > super;
209 :
210 : using super::enter;
211 : using super::leave;
212 : using super::apply;
213 : using super::update;
214 :
215 : using argument_type = typename Function::argument_type; ///< The argument_type is required to restrict the overloads of apply(x) to that type.
216 : using result_type = typename Function::result_type;
217 : const Function& f_;
218 :
219 : template <class T>
220 : void apply(T& result, const argument_type& x) // -> decltype(f_(x))
221 : {
222 : result = f_(x);
223 : }
224 :
225 : update_apply_builder_arg1(const Function& f, const Arg1& arg1):
226 : super(arg1),
227 : f_(f)
228 : {}
229 : };
230 :
231 : template <template <class> class Builder, class Function, class Arg1>
232 : update_apply_builder_arg1<Builder, Function, Arg1>
233 : make_update_apply_builder_arg1(const Function& f)
234 : {
235 : return update_apply_builder_arg1<Builder, Function, Arg1>(f);
236 : }
237 :
238 : } // namespace core
239 :
240 : } // namespace mcrl2
241 :
242 : #endif // MCRL2_CORE_BUILDER_H
|