Line data Source code
1 : // Author(s): Wieger Wesselink
2 : // Copyright: see the accompanying file COPYING or copy at
3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4 : //
5 : // Distributed under the Boost Software License, Version 1.0.
6 : // (See accompanying file LICENSE_1_0.txt or copy at
7 : // http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : /// \file mcrl2/data/rewriters/if_rewriter.h
10 : /// \brief add your file description here.
11 :
12 : #ifndef MCRL2_DATA_REWRITERS_IF_REWRITER_H
13 : #define MCRL2_DATA_REWRITERS_IF_REWRITER_H
14 :
15 : #include "mcrl2/data/rewriter.h"
16 : #include "mcrl2/data/builder.h"
17 : #include "mcrl2/data/consistency.h"
18 : #include "mcrl2/data/standard.h"
19 :
20 : namespace mcrl2 {
21 :
22 : namespace data {
23 :
24 : namespace detail {
25 :
26 : // Returns f(x0, ..., x_i-1, y, x_i+1, ..., xn)
27 : inline
28 0 : application replace_argument(const application& x, std::size_t i, const data_expression& y)
29 : {
30 0 : std::size_t j = 0;
31 0 : return application(x.head(), x.begin(), x.end(), [&](const data_expression& x_i) { return (j++ == i+1) ? y : x_i; });
32 : }
33 :
34 : inline
35 0 : data_expression push_if_outside(const application& x)
36 : {
37 0 : for (std::size_t i = 0; i < x.size(); i++)
38 : {
39 0 : if (is_if_application(x[i]))
40 : {
41 0 : const auto& x_i = atermpp::down_cast<application>(x[i]);
42 0 : const data_expression& b = x_i[0];
43 0 : const data_expression& t1 = x_i[1];
44 0 : const data_expression& t2 = x_i[2];
45 0 : return if_(b, push_if_outside(replace_argument(x, i, t1)), push_if_outside(replace_argument(x, i, t2)));
46 : }
47 : }
48 0 : return x;
49 : }
50 :
51 : template <typename Derived>
52 : struct if_rewrite_builder: public data_expression_builder<Derived>
53 : {
54 : typedef data_expression_builder<Derived> super;
55 :
56 : using super::apply;
57 :
58 0 : bool is_simple(const data_expression& x) const
59 : {
60 0 : return !is_and(x) && !is_or(x) && !is_imp(x) && !is_not(x) && !is_true(x) && !is_false(x);
61 : }
62 :
63 0 : data_expression apply_if(const data_expression& b, const data_expression& t1, const data_expression& t2)
64 : {
65 0 : if (is_true(b))
66 : {
67 0 : return t1;
68 : }
69 0 : else if (is_false(b))
70 : {
71 0 : return t2;
72 : }
73 0 : else if (is_and(b))
74 : {
75 0 : const data_expression& b1 = binary_left1(b);
76 0 : const data_expression& b2 = binary_right1(b);
77 0 : return if_(b1, if_(b2, t1, t2), t2);
78 : }
79 0 : else if (is_or(b))
80 : {
81 0 : const data_expression& b1 = binary_left1(b);
82 0 : const data_expression& b2 = binary_right1(b);
83 0 : return if_(b1, t1, if_(b2, t1, t2));
84 : }
85 0 : else if (is_imp(b))
86 : {
87 0 : const data_expression& b1 = binary_left1(b);
88 0 : const data_expression& b2 = binary_right1(b);
89 0 : return if_(b1, if_(b2, t1, t2), t1);
90 : }
91 0 : else if (is_not(b))
92 : {
93 0 : const data_expression& b1 = unary_operand1(b);
94 0 : return if_(b1, t2, t1);
95 : }
96 : else
97 : {
98 0 : assert(is_simple(b));
99 0 : if (t1 == t2)
100 : {
101 0 : return t1;
102 : }
103 0 : else if (is_if_application(t1))
104 : {
105 0 : const application& t1_ = atermpp::down_cast<application>(t1);
106 0 : const data_expression& c = t1_[0];
107 0 : const data_expression& u1 = t1_[1];
108 0 : const data_expression& u2 = t1_[2];
109 0 : if (b == c)
110 : {
111 0 : return apply_if(b, u1, t2);
112 : }
113 0 : else if (b > c) // use the aterm pointer comparison
114 : {
115 0 : assert(is_simple(c));
116 0 : return apply_if(c, apply_if(b, u1, t2), apply_if(b, u2, t2));
117 : }
118 : else
119 : {
120 0 : return if_(b, t1, t2);
121 : }
122 : }
123 0 : else if (is_if_application(t2))
124 : {
125 0 : const application& t2_ = atermpp::down_cast<application>(t2);
126 0 : const data_expression& c = t2_[0];
127 0 : const data_expression& u1 = t2_[1];
128 0 : const data_expression& u2 = t2_[2];
129 0 : if (b == c)
130 : {
131 0 : return apply_if(b, t1, u2);
132 : }
133 0 : else if (b > c) // use the aterm pointer comparison
134 : {
135 0 : assert(is_simple(c));
136 0 : return apply_if(c, apply_if(b, t1, u1), apply_if(b, t1, u2));
137 : }
138 : else
139 : {
140 0 : return if_(b, t1, t2);
141 : }
142 : }
143 : else
144 : {
145 0 : return if_(b, t1, t2);
146 : }
147 : }
148 : }
149 :
150 : template <class T>
151 0 : void apply(T& result, const application& x)
152 : {
153 0 : if (is_if_application(x))
154 : {
155 0 : data_expression b;
156 0 : super::apply(b, x[0]);
157 0 : data_expression t1;
158 0 : super::apply(t1, x[1]);
159 0 : data_expression t2;
160 0 : super::apply(t2, x[2]);
161 0 : result = apply_if(b, t1, t2);
162 0 : }
163 : else
164 : {
165 0 : super::apply(result, x);
166 0 : result = push_if_outside(atermpp::down_cast<application>(result));
167 : }
168 0 : }
169 : };
170 :
171 : struct if_rewrite_with_rewriter_builder: public if_rewrite_builder<if_rewrite_with_rewriter_builder>
172 : {
173 : typedef if_rewrite_builder<if_rewrite_with_rewriter_builder> super;
174 : using super::apply;
175 : using super::apply_if;
176 :
177 : data::rewriter& rewr;
178 :
179 0 : explicit if_rewrite_with_rewriter_builder(data::rewriter& rewr_) : rewr(rewr_)
180 0 : {}
181 :
182 : template <class T>
183 0 : void apply(T& result, const application& x)
184 : {
185 0 : if (is_if_application(x))
186 : {
187 0 : data_expression b;
188 0 : super::apply(b, x[0]);
189 0 : data_expression t1;
190 0 : super::apply(t1, x[1]);
191 0 : data_expression t2;
192 0 : super::apply(t2, x[2]);
193 0 : result = apply_if(b, t1, t2);
194 0 : }
195 : else
196 : {
197 0 : super::apply(result, x);
198 0 : result = push_if_outside(atermpp::down_cast<application>(result));
199 : }
200 0 : result = rewr(result);
201 0 : }
202 : };
203 :
204 : } // namespace detail
205 :
206 : struct if_rewriter
207 : {
208 : using argument_type = data_expression;
209 : using result_type = data_expression;
210 :
211 0 : data_expression operator()(const data_expression& x) const
212 : {
213 0 : data_expression result;
214 0 : core::make_apply_builder<detail::if_rewrite_builder>().apply(result, x);
215 0 : return result;
216 0 : }
217 : };
218 :
219 : template <typename T>
220 : void if_rewrite(T& x, typename std::enable_if< !std::is_base_of< atermpp::aterm, T >::value>::type* = 0)
221 : {
222 : core::make_update_apply_builder<data::data_expression_builder>(if_rewriter()).update(x);
223 : }
224 :
225 : template <typename T>
226 : T if_rewrite(const T& x, typename std::enable_if< std::is_base_of< atermpp::aterm, T >::value>::type* = 0)
227 : {
228 : T result;
229 : core::make_update_apply_builder<data::data_expression_builder>(if_rewriter()).apply(result, x);
230 : return result;
231 : }
232 :
233 : } // namespace data
234 :
235 : } // namespace mcrl2
236 :
237 : #endif // MCRL2_DATA_REWRITERS_IF_REWRITER_H
|