10#define NAME std::string("rewr_jitty")
12#include "mcrl2/data/detail/rewrite/jitty.h"
13#include "mcrl2/data/detail/rewrite/jitty_jittyc.h"
15#include <boost/config.hpp>
17#include "mcrl2/data/substitutions/mutable_map_substitution.h"
18#include "mcrl2/data/replace.h"
20#ifdef MCRL2_DISPLAY_REWRITE_STATISTICS
21#include "mcrl2/data/detail/rewrite_statistics.h"
24using namespace mcrl2::log;
25using namespace mcrl2::
core;
56 const application& ta=atermpp::down_cast<application>(t);
69 const where_clause& t1=atermpp::down_cast<where_clause>(t);
73 assignment_vector new_assignments;
74 for(
const assignment_expression& ae: assignments)
76 const assignment& assignment_expr = atermpp::down_cast<assignment>(ae);
77 new_assignments.emplace_back(assignment_expr.lhs(), remove_normal_form_function(assignment_expr.rhs()));
79 return where_clause(remove_normal_form_function(body),assignment_list(new_assignments.begin(),new_assignments.end()));
84 const abstraction& t1=atermpp::down_cast<abstraction>(t);
109 m_r.rewrite_aux(result, t, m_sigma);
126 return m_dependencies;
139void RewriterJitty::make_jitty_strat_sufficiently_larger(
const std::size_t i)
141 if (i>=jitty_strat.size())
143 jitty_strat.resize(i+1);
150 function_symbol_vector function_symbols=data_spec.constructors();
151 function_symbols.insert(function_symbols.end(), data_spec.mappings().begin(), data_spec.mappings().end());
152 for(
const function_symbol& f: function_symbols)
154 if (equation_selector(f))
156 const std::size_t i=atermpp::detail::index_traits<data::function_symbol, function_symbol_key_type, 2>::index(f);
157 make_jitty_strat_sufficiently_larger(i);
158 std::map< function_symbol, data_equation_list >::const_iterator j=jitty_eqns.find(f);
161 ?create_strategy(f,data_equation_list(), data_spec)
162 :create_strategy(f,reverse(j->second), data_spec));
178 for (
const data_equation& eq: data_spec.equations())
180 if (equation_selector(eq))
184 CheckRewriteRule(eq);
186 catch (std::runtime_error& e)
188 mCRL2log(warning) << e.what() << std::endl;
192 const function_symbol& lhs_head_index=atermpp::down_cast<function_symbol>(get_nested_head(eq.lhs()));
194 data_equation_list n;
195 std::map< function_symbol, data_equation_list >::iterator it = jitty_eqns.find(lhs_head_index);
196 if (it != jitty_eqns.end())
201 jitty_eqns[lhs_head_index] = n;
214 std::set<variable> variables_in_substitution;
215 for(std::size_t i=0; i<assignments.size; ++i)
217 std::set<variable> s=find_free_variables(assignments.assignment[i].term);
218 variables_in_substitution.insert(s.begin(),s.end());
219 variables_in_substitution.insert(assignments.assignment[i].var);
221 return variables_in_substitution;
243 for (std::size_t i=0; i<assignments.size; i++)
245 if (t==assignments.assignment[i].var)
247 result.assign(assignments.assignment[i].term, *m_thread_aterm_pool);
248 if (assignments.assignment[i].variable_is_a_normal_form)
251 add_normal_form_function(result);
262 const abstraction& t1=atermpp::down_cast<abstraction>(t);
266 std::set<variable> variables_in_substitution=bound_variables_in_substitution(assignments);
268 variable_vector new_variables;
269 mutable_map_substitution<> sigma;
270 bool sigma_trivial=
true;
271 for(
const variable& v: bound_variables)
273 if (variables_in_substitution.count(v)>0)
276 const variable fresh_variable(generator(),v.sort());
277 new_variables.push_back(fresh_variable);
278 sigma[v]=fresh_variable;
283 new_variables.push_back(v);
288 (sigma_trivial?t1.body():replace_variables(t1.body(),sigma)),
290 result=abstraction(binder,
291 variable_list(new_variables.begin(),new_variables.end()),
297 const where_clause& t1=atermpp::down_cast<where_clause>(t);
301 std::set<variable> variables_in_substitution=bound_variables_in_substitution(assignments);
303 assignment_vector new_assignments;
305 mutable_map_substitution<> sigma;
306 bool sigma_trivial=
true;
308 for(
const assignment_expression& a: local_assignments)
310 const assignment& assignment_expr = atermpp::down_cast<assignment>(a);
311 const variable& v=assignment_expr.lhs();
312 subst_values(result,assignments,assignment_expr.rhs(),generator);
313 if (variables_in_substitution.count(v)>0)
316 const variable fresh_variable(generator(),v.sort());
317 new_assignments.emplace_back(fresh_variable, result);
318 sigma[v]=fresh_variable;
323 new_assignments.emplace_back(v, result);
328 (sigma_trivial?body:replace_variables(body,sigma)),
330 result=where_clause(result, assignment_list(new_assignments.begin(),new_assignments.end()));
335 const application& t1 = atermpp::down_cast<application>(t);
336 make_application(result,
350 const bool term_context_guarantees_normal_form)
363 for (std::size_t i=0; i<assignments.size; i++)
365 if (p==assignments.assignment[i].var)
367 return t==assignments.assignment[i].term;
371 new (&assignments.assignment[assignments.size])
372 jitty_variable_assignment_for_a_rewrite_rule(
373 atermpp::down_cast<variable>(p),
375 term_context_guarantees_normal_form);
386 assert(term_context_guarantees_normal_form);
388 const application& pa=atermpp::down_cast<application>(p);
389 const application& ta=atermpp::down_cast<application>(t);
390 if (pa.size()!=ta.size())
396 pa.head()
,assignments
,true))
401 for (std::size_t i=0; i<pa.size(); i++)
403 if (!match_jitty(ta[i], pa[i],assignments,
true))
416template <
class ITERATOR>
419 const application& t,
420 const std::function<
void(data_expression&,
const data_expression&)> rewrite_cpp_code,
423 substitution_type& sigma)
428 make_application(intermediate, t.head(), begin, end);
429 rewrite_cpp_code(result, intermediate);
433 const application& ta=atermpp::down_cast<application>(t.head());
434 std::size_t n_args=recursive_number_of_args(ta);
435 apply_cpp_code_to_higher_order_term(result,ta,rewrite_cpp_code,begin,begin+n_args,sigma);
437 rewrite_aux(result,application(rewrite_result,
440 [&](
const data_expression& t){
return application(this_term_is_in_normal_form(),t); } ),
449 substitution_type& sigma)
454 rewrite_aux_const_function_symbol(result,atermpp::down_cast<
const function_symbol>(term),sigma);
459 sigma.apply(atermpp::down_cast<variable>(term),result, *m_thread_aterm_pool);
470 const where_clause& w = atermpp::down_cast<where_clause>(term);
471 rewrite_where(result,w,sigma);
477 const abstraction& ta=atermpp::down_cast<abstraction>(term);
480 existential_quantifier_enumeration(result,ta,sigma);
485 universal_quantifier_enumeration(result,ta,sigma);
489 rewrite_single_lambda(result,ta.variables(),ta.body(), sigma,
false);
496 const application& terma=atermpp::down_cast<application>(term);
499 assert(terma.size()==1);
516 rewrite_aux_function_symbol(result, atermpp::down_cast<function_symbol>(head),terma,sigma);
520 const application& tapp=atermpp::down_cast<application>(term);
522 m_rewrite_stack.increase(2);
524 const std::size_t t = 0;
525 rewrite_aux(m_rewrite_stack.element(t,2),tapp.head(),sigma);
531 const std::size_t head1 = 1;
532 m_rewrite_stack.set_element(head1,2,get_nested_head(m_rewrite_stack.get_element(t,2)));
533 if (is_function_symbol(m_rewrite_stack.get_element(head1,2)))
537 make_application(result, m_rewrite_stack.get_element(t,2), tapp.begin(), tapp.end());
538 const std::size_t do_not_rewrite_first_arguments=recursive_number_of_args( m_rewrite_stack.get_element(t,2));
539 assert(remove_normal_form_function(m_rewrite_stack.get_element(t,2))==m_rewrite_stack.get_element(t,2));
540 rewrite_aux_function_symbol(m_rewrite_stack.element(t,2),
541 atermpp::down_cast<function_symbol>(m_rewrite_stack.get_element(head1,2)),
542 atermpp::down_cast<application>(result),
544 do_not_rewrite_first_arguments);
545 result=m_rewrite_stack.element(t,2);
546 m_rewrite_stack.decrease(2);
549 else if (is_variable(m_rewrite_stack.element(head1,2)))
553 const bool do_not_rewrite_head=
false;
554 make_application(result, m_rewrite_stack.element(t,2) , tapp.begin(), tapp.end(), r, do_not_rewrite_head);
555 m_rewrite_stack.decrease(2);
558 assert(is_abstraction(m_rewrite_stack.top()));
559 const abstraction& ta=atermpp::down_cast<abstraction>(m_rewrite_stack.element(t,2) );
563 rewrite_lambda_application(result,ta,tapp,sigma);
564 m_rewrite_stack.decrease(2);
569 assert(term.size()==1);
570 existential_quantifier_enumeration(result,ta,sigma);
571 m_rewrite_stack.decrease(2);
575 assert(term.size()==1);
576 universal_quantifier_enumeration(result,ta,sigma);
577 m_rewrite_stack.decrease(2);
586 const application& term,
587 substitution_type& sigma,
588 const std::size_t do_not_rewrite_first_arguments )
592 const std::size_t arity=detail::recursive_number_of_args(term);
594 m_rewrite_stack.increase(arity+1);
595 bool* rewritten_defined = MCRL2_SPECIFIC_STACK_ALLOCATOR(
bool, arity);
597 for(std::size_t i=0; i<arity; ++i)
599 rewritten_defined[i]=
false;
602 const std::size_t op_value=atermpp::detail::index_traits<data::function_symbol,function_symbol_key_type, 2>::index(op);
603 make_jitty_strat_sufficiently_larger(op_value);
604 const strategy& strat=jitty_strat[op_value];
606 if (!strat.rules().empty())
611 for (
const strategy_rule& rule : strat.rules())
613 if (rule.is_rewrite_index())
615 const std::size_t i = rule.rewrite_index();
618 assert(!rewritten_defined[i]||i==0);
619 if (!rewritten_defined[i])
621 if (i<do_not_rewrite_first_arguments)
623 m_rewrite_stack.set_element(i,arity+1,detail::get_argument_of_higher_order_term(term,i));
627 rewrite_aux(m_rewrite_stack.element(i,arity+1),detail::get_argument_of_higher_order_term(term,i),sigma);
629 rewritten_defined[i]=
true;
631 assert(m_rewrite_stack.element(i,arity+1).defined());
638 else if (rule.is_cpp_code())
645 assert(m_rewrite_stack.stack_size()>=arity+1);
646 application rewriteable_term(op, m_rewrite_stack.stack_iterator(0,arity+1),
647 m_rewrite_stack.stack_iterator(arity,arity+1));
648 rule.rewrite_cpp_code()(result, rewriteable_term);
649 m_rewrite_stack.decrease(arity+1);
656 for(std::size_t i=0; i<recursive_number_of_args(term); i++)
658 if (!rewritten_defined[i])
660 rewrite_aux(m_rewrite_stack.element(i,arity+1),detail::get_argument_of_higher_order_term(term,i),sigma);
661 rewritten_defined[i]=
true;
664 apply_cpp_code_to_higher_order_term(
667 rule.rewrite_cpp_code(),
668 m_rewrite_stack.stack_iterator(0,arity+1),
669 m_rewrite_stack.stack_iterator(arity,arity+1), sigma);
670 m_rewrite_stack.decrease(arity+1);
676 const data_equation& rule1=rule.equation();
677 const data_expression& lhs=rule1.lhs();
678 std::size_t rule_arity = (is_function_symbol(lhs)?0:detail::recursive_number_of_args(lhs));
680 if (rule_arity > arity)
685 assert(assignments.size==0);
688 for (std::size_t i=0; i<rule_arity; i++)
691 if (!match_jitty(rewritten_defined[i]?
692 m_rewrite_stack.get_element(i,arity+1):
693 detail::get_argument_of_higher_order_term(term,i),
694 detail::get_argument_of_higher_order_term(atermpp::down_cast<application>(lhs),i),
695 assignments,rewritten_defined[i]))
703 bool condition_of_this_rule=
false;
704 if (rule1.condition()==sort_bool::true_())
706 condition_of_this_rule=
true;
710 subst_values(m_rewrite_stack.top(),assignments,rule1.condition(),m_generator);
711 rewrite_aux(result, m_rewrite_stack.top(), sigma);
712 condition_of_this_rule = (result==sort_bool::true_());
714 if (condition_of_this_rule)
716 const data_expression& rhs=rule1.rhs();
718 if (arity == rule_arity)
720 subst_values(m_rewrite_stack.top(),assignments,rhs,m_generator);
721 rewrite_aux(result, m_rewrite_stack.top(),sigma);
722 m_rewrite_stack.decrease(arity+1);
727 assert(arity>rule_arity);
731 for(std::size_t i=rule_arity; i<arity; ++i)
733 m_rewrite_stack.set_element(i,arity+1,detail::get_argument_of_higher_order_term(term,i));
734 rewritten_defined[i]=
true;
737 subst_values(m_rewrite_stack.top(),assignments,rhs,m_generator);
738 std::size_t i = rule_arity;
739 sort_expression sort = detail::residual_sort(op.sort(),i);
740 while (is_function_sort(sort) && (i < arity))
742 const function_sort& fsort = atermpp::down_cast<function_sort>(sort);
743 const std::size_t end=i+fsort.domain().size();
745 assert(m_rewrite_stack.stack_size()+i>=arity+1);
749 make_application(m_rewrite_stack.top(),m_rewrite_stack.top(),
750 m_rewrite_stack.stack_iterator(i,arity+1),
751 m_rewrite_stack.stack_iterator(end,arity+1));
753 sort = fsort.codomain();
756 rewrite_aux(result,m_rewrite_stack.top(),sigma);
757 m_rewrite_stack.decrease(arity+1);
771 for (std::size_t i=0; i<arity; i++)
773 if (!rewritten_defined[i])
775 rewrite_aux(m_rewrite_stack.element(i,arity+1),detail::get_argument_of_higher_order_term(term,i),sigma);
781 const function_sort& fsort=atermpp::down_cast<function_sort>(op.sort());
782 const std::size_t end=fsort.domain().size();
784 make_application(result,op,m_rewrite_stack.stack_iterator(0,arity+1), m_rewrite_stack.stack_iterator(end,arity+1));
787 while (i<arity && is_function_sort(*sort))
789 const function_sort& fsort=atermpp::down_cast<function_sort>(*sort);
790 const std::size_t end=i+fsort.domain().size();
791 assert(m_rewrite_stack.stack_size()+i>=arity+1);
794 make_application(result,result,m_rewrite_stack.stack_iterator(i,arity+1), m_rewrite_stack.stack_iterator(end,arity+1));
796 sort = &fsort.codomain();
799 m_rewrite_stack.decrease(arity+1);
806 substitution_type& sigma)
811 const std::size_t op_value=atermpp::detail::index_traits<data::function_symbol,function_symbol_key_type, 2>::index(op);
812 make_jitty_strat_sufficiently_larger(op_value);
815 if (rhs_for_constants_cache.size()<=op_value)
817 rhs_for_constants_cache.resize(op_value+1);
823
824
825
830 const strategy& strat=jitty_strat[op_value];
832 for (
const strategy_rule& rule : strat.rules())
834 if (rule.is_rewrite_index())
840 else if (rule.is_cpp_code())
842 rule.rewrite_cpp_code()(result, op);
843 rhs_for_constants_cache[op_value]=result;
848 const data_equation& rule1=rule.equation();
849 const data_expression& lhs=rule1.lhs();
850 std::size_t rule_arity = (is_function_symbol(lhs)?0:detail::recursive_number_of_args(lhs));
857 if (rule1.condition()==sort_bool::true_())
859 rewrite_aux(result,rule1.rhs(),sigma);
860 rhs_for_constants_cache[op_value]=result;
863 rewrite_aux(result,rule1.condition(),sigma);
864 if (result==sort_bool::true_())
866 rewrite_aux(result,rule1.rhs(),sigma);
867 rhs_for_constants_cache[op_value]=result;
873 rhs_for_constants_cache[op_value]=op;
881 substitution_type& sigma)
883#ifdef MCRL2_DISPLAY_REWRITE_STATISTICS
884 data::detail::increment_rewrite_count();
888 rewrite_aux(result, term, sigma);
892 assert(m_rewrite_stack.stack_size()==0);
896 rewrite_aux(result, term, sigma);
903 m_rewrite_stack.reserve_more_space();
904 rewrite(result,term,sigma);
908 assert(m_rewrite_stack.stack_size()==0);
917 substitution_type& sigma)
920 rewrite(result, term, sigma);
An abstraction expression.
const variable_list & variables() const
abstraction(const binder_type &binding_operator, const variable_list &variables, const data_expression &body)
Constructor.
const data_expression & body() const
const binder_type & binding_operator() const
data_expression & operator=(const data_expression &) noexcept=default
bool is_default_data_expression() const
A function to efficiently determine whether a data expression is made by the default constructor.
void rewrite_aux_const_function_symbol(data_expression &result, const function_symbol &op, substitution_type &sigma)
void thread_initialise() override
rewrite_strategy getStrategy() override
Get rewriter strategy that is used.
RewriterJitty(const data_specification &data_spec, const used_data_equation_selector &)
void rewrite_aux(data_expression &result, const data_expression &term, substitution_type &sigma)
Rewrite a term with a given substitution and put the rewritten term in result.
void add_normal_form_function(data_expression &t)
data_expression rewrite(const data_expression &term, substitution_type &sigma) override
Rewrite an mCRL2 data term.
void apply_cpp_code_to_higher_order_term(data_expression &result, const application &t, const std::function< void(data_expression &, const data_expression &)> rewrite_cpp_code, ITERATOR begin, ITERATOR end, substitution_type &sigma)
const function_symbol & this_term_is_in_normal_form()
void subst_values(data_expression &result, const jitty_assignments_for_a_rewrite_rule &assignments, const data_expression &t, data::enumerator_identifier_generator &generator)
data_expression remove_normal_form_function(const data_expression &t)
atermpp::detail::thread_aterm_pool * m_thread_aterm_pool
void rebuild_strategy(const data_specification &data_spec, const mcrl2::data::used_data_equation_selector &equation_selector)
void rewrite(data_expression &result, const data_expression &term, substitution_type &sigma) override
Rewrite an mCRL2 data term.
bool rewriting_in_progress
~RewriterJitty() override
Rewriter interface class.
Rewriter(const data_specification &data_spec, const used_data_equation_selector &eq_selector)
Constructor. Do not use directly; use createRewriter() function instead.
std::set< std::size_t > m_dependencies
const std::set< std::size_t > & dependencies() const
dependencies_rewrite_rule_pair(std::set< std::size_t > &dependencies, const data_equation &eq)
data_equation equation() const
mutable_indexed_substitution & m_sigma
jitty_argument_rewriter(mutable_indexed_substitution<> &sigma, RewriterJitty &r)
void operator()(data_expression &result, const data_expression &t)
A strategy is a list of rules and the number of variables that occur in it.
const sort_expression & codomain() const
const sort_expression & sort() const
Component for selecting a subset of equations that are actually used in an encompassing specification...
\brief A where expression
const data_expression & body() const
const assignment_expression_list & declarations() const
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
static bool match_jitty(const data_expression &t, const data_expression &p, jitty_assignments_for_a_rewrite_rule &assignments, const bool term_context_guarantees_normal_form)
std::set< variable > bound_variables_in_substitution(const jitty_assignments_for_a_rewrite_rule &assignments)
const data_expression & get_nested_head(const data_expression &t)
bool is_application(const data_expression &t)
Returns true if the term t is an application.
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_forall(const atermpp::aterm &x)
Returns true if the term t is a universal quantification.
bool is_function_symbol(const atermpp::aterm &x)
Returns true if the term t is a function symbol.
bool is_exists(const atermpp::aterm &x)
Returns true if the term t is an existential quantification.
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
bool is_machine_number(const atermpp::aterm &x)
Returns true if the term t is a machine_number.
bool is_lambda(const atermpp::aterm &x)
Returns true if the term t is a lambda abstraction.
bool is_forall_binder(const atermpp::aterm &x)
bool is_variable(const atermpp::aterm &x)
Returns true if the term t is a variable.
jitty_assignments_for_a_rewrite_rule(jitty_variable_assignment_for_a_rewrite_rule *a)