mCRL2
Loading...
Searching...
No Matches
jittycpreamble.h
Go to the documentation of this file.
1// Author(s): Muck van Weerdenburg
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/detail/rewrite/jittycpreamble.h
10
11#ifndef MCRL2_DATA_DETAIL_REWR_JITTYC_PREAMBLE_H
12#define MCRL2_DATA_DETAIL_REWR_JITTYC_PREAMBLE_H
13
14#include "mcrl2/utilities/toolset_version_const.h"
15#include "mcrl2/utilities/export.h"
16#include "mcrl2/data/detail/rewrite/jitty_jittyc.h"
17#include "mcrl2/data/detail/rewrite/jittyc.h"
18
19using namespace mcrl2::data::detail;
20using namespace mcrl2::data;
21using atermpp::down_cast;
22
23//
24// Declaration of rewriter library interface
25//
26
27extern "C" {
28 MCRL2_EXPORT bool init(rewriter_interface* i, RewriterCompilingJitty* this_rewriter);
29}
30
31// A rewrite_term is a term that may or may not be in normal form. If the method"
32// normal_form is invoked, it will calculate a normal form for itself as efficiently as possible."
33template <class REWRITE_TERM>
34static data_expression& local_rewrite(const REWRITE_TERM& t)
35{
36 return t.normal_form();
37}
38
39template <class REWRITE_TERM>
40static void local_rewrite(data_expression& result, const REWRITE_TERM& t)
41{
42 t.normal_form(result);
43}
44
46{
47 return t;
48}
49
50static void local_rewrite(data_expression& result, const data_expression& t)
51{
52 result=t;
53}
54
55//
56// Forward declarations
57//
58static void set_the_precompiled_rewrite_functions_in_a_lookup_table(RewriterCompilingJitty* this_rewriter);
59
60template <bool ARGUMENTS_IN_NORMAL_FORM>
61static void rewrite_aux(data_expression& result, const data_expression& t, RewriterCompilingJitty* this_rewriter);
62template <bool ARGUMENTS_IN_NORMAL_FORM>
63static void rewrite_abstraction_aux(data_expression& result, const abstraction& a, const data_expression& t, RewriterCompilingJitty* this_rewriter);
64
66 data_expression& result,
67 const data_expression& t,
68 RewriterCompilingJitty* this_rewriter)
69{
70 rewrite_aux<true>(result, t, this_rewriter);
71 return;
72}
73
74static void rewrite(data_expression& result, const data_expression& t, RewriterCompilingJitty* this_rewriter)
75{
76 rewrite_aux<false>(result, t, this_rewriter);
77 return;
78}
79
80//
81// Type definitions
82//
83using rewriter_function = void (*)(data_expression&, const application&, RewriterCompilingJitty*);
84
85// A class that contains terms which are explicitly tagged to be
86// not in normal form. By invoking normal_form the normalform
87// of this term is calculated.
89{
90 protected:
93
94 public:
95 term_not_in_normal_form(const data_expression& term, RewriterCompilingJitty* tr)
96 : m_term(term), this_rewriter(tr)
97 {}
98
100 {
101 data_expression& local_store = this_rewriter->m_rewrite_stack.new_stack_position<data_expression>();
102 rewrite_aux<false>(local_store, m_term, this_rewriter);
103 return local_store;
104 }
105
106 void normal_form(data_expression& result) const
107 {
108 rewrite_aux<false>(result, m_term, this_rewriter);
109 }
110};
111
112// This is an abstraction, of which the arguments are not yet
113// in normal form. This is done when the method "normal_form" is invoked.
114template <class TERM_TO_BE_REWRITTEN>
116{
117 protected:
119 const variable_list& m_variables;
120 const TERM_TO_BE_REWRITTEN& m_body;
122 public:
123 delayed_abstraction(const binder_type& binding_operator,
124 const variable_list& variables,
125 const TERM_TO_BE_REWRITTEN& body,
126 RewriterCompilingJitty* tr)
127 : m_binding_operator(binding_operator), m_variables(variables), m_body(body), this_rewriter(tr)
128 {}
129
131 {
132 data_expression& t = this_rewriter->m_rewrite_stack.new_stack_position<data_expression>();
133 make_abstraction(t, m_binding_operator, m_variables, local_rewrite(m_body));
134 data_expression& result = this_rewriter->m_rewrite_stack.new_stack_position<data_expression>();
135 rewrite_abstraction_aux<false>(result, atermpp::down_cast<abstraction>(t),t,this_rewriter);
136 return result;
137 }
138
139 void normal_form(data_expression& result) const
140 {
141 local_rewrite(result, m_body);
142 make_abstraction(result, m_binding_operator, m_variables, result);
143 rewrite_abstraction_aux<true>(result, atermpp::down_cast<abstraction>(result),result,this_rewriter);
144 }
145};
146
147
149{
151
152 rewrite_functor(RewriterCompilingJitty* tr)
154 {}
155
157 {
158 data_expression result;
159 rewrite_aux<false>(result, arg, this_rewriter);
160 return result;
161 }
162};
163
164
165// Miscellaneous helper functions
166//
167static inline
169{
170 result=t;
171}
172
173static inline
174assignment_expression_list jittyc_local_push_front(assignment_expression_list l, const assignment& e)
175{
176 l.push_front(e);
177 return l;
178}
179
180static inline
182{
183 return atermpp::detail::index_traits<function_symbol, function_symbol_key_type, 2>::index(func);
184}
185
186static inline
188{
189 return *(this_rewriter->global_sigma);
190}
191
192static inline
193uintptr_t uint_address(const atermpp::aterm& t)
194{
195 return reinterpret_cast<uintptr_t>(atermpp::detail::address(t));
196}
197
198//
199// Rewriting functions
200//
201
202template <bool ARGUMENTS_IN_NORMAL_FORM>
203static inline rewriter_function get_precompiled_rewrite_function(
204 const function_symbol& f,
205 const std::size_t arity,
206 RewriterCompilingJitty* this_rewriter)
207{
208 const std::size_t index = get_index(f);
209 if (index>=this_rewriter->index_bound || arity>=this_rewriter->arity_bound)
210 {
211 return nullptr;
212 }
213 if (ARGUMENTS_IN_NORMAL_FORM)
214 {
215 assert(this_rewriter -> arity_bound * index + arity<this_rewriter->functions_when_arguments_are_in_normal_form.size());
216 return this_rewriter->functions_when_arguments_are_in_normal_form[this_rewriter->arity_bound * index + arity];
217 }
218 else
219 {
220 assert(this_rewriter->arity_bound * index + arity<this_rewriter->functions_when_arguments_are_not_in_normal_form.size());
221 return this_rewriter->functions_when_arguments_are_not_in_normal_form[this_rewriter->arity_bound * index + arity];
222 }
223}
224
225template <bool ARGUMENTS_IN_NORMAL_FORM>
226static inline
227void rewrite_abstraction_aux(data_expression& result, const abstraction& head, const data_expression& a, RewriterCompilingJitty* this_rewriter)
228{
229 const binder_type& binder(head.binding_operator());
230 if (is_lambda_binder(binder))
231 {
232 this_rewriter->rewrite_lambda_application(result, a, sigma(this_rewriter), ARGUMENTS_IN_NORMAL_FORM);
233 assert(result.sort()==a.sort());
234 return;
235 }
236 if (is_exists_binder(binder))
237 {
238 this_rewriter->existential_quantifier_enumeration(result, head, sigma(this_rewriter));
239 assert(result.sort()==a.sort());
240 return;
241 }
242 assert(is_forall_binder(binder));
243 this_rewriter->universal_quantifier_enumeration(result, head, sigma(this_rewriter));
244 assert(result.sort()==a.sort());
245 return;
246}
247
248
249// Rewrite t with the arguments in normal form.
250template <bool ARGUMENTS_IN_NORMAL_FORM>
251static inline
252void rewrite_appl_aux(data_expression& result, const application& t, RewriterCompilingJitty* this_rewriter)
253{
254 // Here t has the shape F(u1,...,um) and F is either a lambda term, variable or an application.
256 if (is_function_symbol(thead))
257 {
258 const std::size_t arity=recursive_number_of_args(t);
259 const rewriter_function f = get_precompiled_rewrite_function<ARGUMENTS_IN_NORMAL_FORM>(atermpp::down_cast<function_symbol>(thead),arity,this_rewriter);
260 if (f != nullptr)
261 {
262 f(result, t, this_rewriter);
263 assert(t.sort()==result.sort());
264 return;
265 }
266 make_application(result, t.head(), t.begin(), t.end(), rewrite_functor(this_rewriter));
267 return;
268 }
269 // Here the head symbol of, which can be deeply nested, is not a function_symbol.
270 const data_expression& head0 = get_nested_head(t);
271 data_expression head;
272 if (!ARGUMENTS_IN_NORMAL_FORM && is_variable(head0))
273 {
274 head=sigma(this_rewriter)(down_cast<const variable>(head0));
275 // Rewrite all arguments, but not the head.
276 rewrite_all_arguments(result, t, rewrite_functor(this_rewriter), true);
277 const application t1=atermpp::down_cast<application>(replace_nested_head(result, head));
278 rewrite_appl_aux<true>(result, t1, this_rewriter);
279 return;
280 }
281 else if (!ARGUMENTS_IN_NORMAL_FORM && is_where_clause(head0))
282 {
283 this_rewriter->rewrite_where(head, atermpp::down_cast<where_clause>(head0), sigma(this_rewriter));
284 rewrite_all_arguments(result, t, rewrite_functor(this_rewriter), true);
285 const application t1=atermpp::down_cast<application>(replace_nested_head(result, head));
286 rewrite_appl_aux<true>(result, t1, this_rewriter);
287 return;
288 }
289
291 // Here head1 has the shape
292 // variable, function_symbol, lambda y1,....,ym.u, forall y1,....,ym.u or exists y1,....,ym.u,
293 if (is_variable(head1))
294 {
295 if constexpr (ARGUMENTS_IN_NORMAL_FORM)
296 {
297 result=t;
298 }
299 else
300 {
301 rewrite_all_arguments(result, t, rewrite_functor(this_rewriter),true);
302 }
303 return;
304 }
305
306 assert(is_abstraction(head1));
307 const abstraction& ha=down_cast<abstraction>(head1);
308 rewrite_abstraction_aux<ARGUMENTS_IN_NORMAL_FORM>(result, ha,t,this_rewriter);
309 return;
310}
311
312template <bool ARGUMENTS_IN_NORMAL_FORM>
313static inline
314void rewrite_aux(data_expression& result, const data_expression& t, RewriterCompilingJitty* this_rewriter)
315{
317 {
318 result=t;
319 return;
320 }
321 else
323 {
324 const std::size_t index = get_index(down_cast<function_symbol>(t));
325 if (index<this_rewriter->normal_forms_for_constants.size())
326 {
327 // In this case we can use an unprotected_assign as the normal_forms_for_constants will
328 // not change anymore, while rewriting is going on.
329 result.unprotected_assign<false>(this_rewriter->normal_forms_for_constants[index]);
330
332 {
333 assert(t.sort()==result.sort());
334 return;
335 }
336 }
337 result=t;
338 return;
339 }
340 else
342 {
343 const application& appl = down_cast<application>(t);
344 const data_expression& head = appl.head();
345 if (is_function_symbol(head))
346 {
347 const std::size_t appl_size=appl.size();
348 const rewriter_function f = get_precompiled_rewrite_function<ARGUMENTS_IN_NORMAL_FORM>(down_cast<function_symbol>(head), appl_size, this_rewriter);
349 if (f != nullptr)
350 {
351 f(result, appl,this_rewriter);
352 assert(result.sort()==t.sort());
353 return;
354 }
355 make_application(result, appl.head(), appl.begin(), appl.end(), rewrite_functor(this_rewriter));
356 return;
357 }
358 else
359 {
360 // Here appl has the shape F(u1,...,um) and F is either a lambda term, variable or an application.
361 rewrite_appl_aux<ARGUMENTS_IN_NORMAL_FORM>(result, appl, this_rewriter);
362 assert(result.sort()==appl.sort());
363 return;
364 }
365 }
366 else
367 if (is_variable(t))
368 {
369 sigma(this_rewriter).apply(down_cast<variable>(t),result,
370 *this_rewriter->m_thread_aterm_pool);
371 return;
372 }
373 else
374 if (is_abstraction(t))
375 {
376 const abstraction& abstr=down_cast<abstraction>(t);
377 const binder_type& binder(abstr.binding_operator());
378 if (is_exists_binder(binder))
379 {
380 this_rewriter->existential_quantifier_enumeration(result, abstr, sigma(this_rewriter));
381 assert(result.sort()==t.sort());
382 return;
383 }
384 if (is_forall_binder(binder))
385 {
386 this_rewriter->universal_quantifier_enumeration(result, abstr, sigma(this_rewriter));
387 assert(result.sort()==t.sort());
388 return;
389 }
390 assert(is_lambda_binder(binder));
391 this_rewriter->rewrite_single_lambda(result, abstr.variables(), abstr.body(), sigma(this_rewriter), false);
392 return;
393 }
394 else
395 {
396 assert(is_where_clause(t));
397 this_rewriter->rewrite_where(result,down_cast<where_clause>(t), sigma(this_rewriter));
398 return;
399 }
400}
401
402static
404{
405}
406
407extern "C" {
408 MCRL2_EXPORT bool init(rewriter_interface* i, RewriterCompilingJitty* this_rewriter) // NOLINT
409 {
410 if (mcrl2::utilities::MCRL2_VERSION != i->caller_toolset_version)
411 {
412 i->status = "rewriter version does not match the version of the calling application.";
413 return false;
414 }
415
416 i->rewrite_external = &rewrite;
417 i->rewrite_cleanup = &rewrite_cleanup;
418 set_the_precompiled_rewrite_functions_in_a_lookup_table(this_rewriter);
419 i->status = "rewriter loaded successfully.";
420 return true;
421 }
422}
423
424#endif // MCRL2_DATA_DETAIL_REWR_JITTYC_PREAMBLE_H
A unordered_map class in which aterms can be stored.
const TERM_TO_BE_REWRITTEN & m_body
data_expression & normal_form() const
delayed_abstraction(const binder_type &binding_operator, const variable_list &variables, const TERM_TO_BE_REWRITTEN &body, RewriterCompilingJitty *tr)
RewriterCompilingJitty * this_rewriter
const binder_type & m_binding_operator
void normal_form(data_expression &result) const
const variable_list & m_variables
An abstraction expression.
Definition abstraction.h:23
const binder_type & binding_operator() const
Definition abstraction.h:55
\brief Assignment of a data expression to a variable
Definition assignment.h:88
data_expression & operator=(const data_expression &) noexcept=default
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:107
data_expression(const data_expression &) noexcept=default
Move semantics.
bool is_default_data_expression() const
A function to efficiently determine whether a data expression is made by the default constructor.
\brief A function symbol
const data_expression & m_term
RewriterCompilingJitty * this_rewriter
void normal_form(data_expression &result) const
data_expression & normal_form() const
term_not_in_normal_form(const data_expression &term, RewriterCompilingJitty *tr)
#define MCRL2_EXPORT
Definition export.h:18
static void rewrite_abstraction_aux(data_expression &result, const abstraction &a, const data_expression &t, RewriterCompilingJitty *this_rewriter)
static void rewrite_with_arguments_in_normal_form(data_expression &result, const data_expression &t, RewriterCompilingJitty *this_rewriter)
static const data_expression & local_rewrite(const data_expression &t)
static RewriterCompilingJitty::substitution_type & sigma(RewriterCompilingJitty *this_rewriter)
static void set_the_precompiled_rewrite_functions_in_a_lookup_table(RewriterCompilingJitty *this_rewriter)
static void rewrite_appl_aux(data_expression &result, const application &t, RewriterCompilingJitty *this_rewriter)
static void rewrite_cleanup()
static assignment_expression_list jittyc_local_push_front(assignment_expression_list l, const assignment &e)
static void pass_on(data_expression &result, const data_expression &t)
static void local_rewrite(data_expression &result, const REWRITE_TERM &t)
static uintptr_t uint_address(const atermpp::aterm &t)
static void rewrite(data_expression &result, const data_expression &t, RewriterCompilingJitty *this_rewriter)
static std::size_t get_index(const function_symbol &func)
static rewriter_function get_precompiled_rewrite_function(const function_symbol &f, const std::size_t arity, RewriterCompilingJitty *this_rewriter)
static void local_rewrite(data_expression &result, const data_expression &t)
static data_expression & local_rewrite(const REWRITE_TERM &t)
MCRL2_EXPORT bool init(rewriter_interface *i, RewriterCompilingJitty *this_rewriter)
static void rewrite_aux(data_expression &result, const data_expression &t, RewriterCompilingJitty *this_rewriter)
const data_expression & get_nested_head(const data_expression &t)
bool is_application_no_check(const atermpp::aterm &x)
Returns true if the term t is an application, but it does not check whether an application symbol of ...
bool is_where_clause(const atermpp::aterm &x)
Returns true if the term t is a where clause.
bool is_abstraction(const atermpp::aterm &x)
Returns true if the term t is an abstraction.
bool is_exists_binder(const atermpp::aterm &x)
bool is_lambda_binder(const atermpp::aterm &x)
bool is_function_symbol(const atermpp::aterm &x)
Returns true if the term t is a function symbol.
bool is_machine_number(const atermpp::aterm &x)
Returns true if the term t is a machine_number.
bool is_forall_binder(const atermpp::aterm &x)
bool is_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
data_expression operator()(const data_expression &arg) const
RewriterCompilingJitty * this_rewriter
rewrite_functor(RewriterCompilingJitty *tr)