mCRL2
Loading...
Searching...
No Matches
unfold_pattern_matching.h
Go to the documentation of this file.
1// Author(s): Ruud Koolen, Thomas Neele
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#ifndef MCRL2_SMT_UNFOLD_PATTERN_MATCHING_H
10#define MCRL2_SMT_UNFOLD_PATTERN_MATCHING_H
11
12#include "mcrl2/data/join.h"
13#include "mcrl2/data/replace.h"
14#include "mcrl2/data/representative_generator.h"
15#include "mcrl2/data/unfold_pattern_matching.h"
16#include "mcrl2/data/substitutions/map_substitution.h"
17#include "mcrl2/data/substitutions/variable_substitution.h"
18#include "mcrl2/smt/utilities.h"
19
20namespace mcrl2
21{
22namespace smt
23{
24
25/**
26 * \brief Contains information on sorts that behave similar to a structured sort in a data specification.
27 * \details That is, there is a number of constructors, and for some constructors we have a recogniser function
28 * and several projection functions.
29 */
31{
35
36 bool is_constructor(const data::function_symbol& f) const
37 {
38 const auto& cons_s = constructors.at(f.sort().target_sort());
39 return cons_s.find(f) != cons_s.end();
40 }
41
43 {
44 return constructors.at(sort);
45 }
46
48 {
49 return data::application(recogniser_func.at(f), expr);
50 }
51
53 {
54 std::set<data::function_symbol> constr = get_constructors(target.sort());
55 auto const_it = constr.begin();
56 auto rhs_it = rhss.begin();
57 data::data_expression result = *rhs_it++;
58 for (const_it++; const_it != constr.end(); ++const_it, ++rhs_it)
59 {
60 data::data_expression term = *rhs_it;
61 data::data_expression condition = create_recogniser_expr(*const_it, target);
62 result = data::lazy::if_(condition, term, result);
63 }
64 return result;
65 }
66
68 {
69 return projection_func.at(f);
70 }
71};
72
73template <typename T>
75{
76 bool operator()(const T&)
77 {
78 return false;
79 }
80};
81
82/// @brief Find sorts that behave like a structured sort and the associated rewrite rules
83/// @tparam Skip Unary Boolean function type.
84/// @param dataspec The data specification to consider
85/// @param skip If skip(f) is true then function symbol f will not be considered
86/// @return A pair containing: (1) recogniser and projection function symbols for each structured sort and
87/// (2) a map that gives a list of equations for each function symbol.
88template <typename Skip = always_false<data::function_symbol>>
91{
93 for(const data::sort_expression& s: dataspec.sorts())
94 {
95 ssf.constructors[s] = std::set<data::function_symbol>(dataspec.constructors(s).begin(), dataspec.constructors(s).end());
96 }
97
98 std::map< data::function_symbol, data::data_equation_vector > rewrite_rules;
99 for (const data::data_equation& eqn: dataspec.equations())
100 {
101 data::data_expression lhs = eqn.lhs();
102 data::function_symbol function = data::detail::get_top_fs(lhs);
103 if (function == data::function_symbol())
104 {
105 continue;
106 }
107 if (skip(function))
108 {
109 continue;
110 }
111 //TODO equations of the shape x < x or x <= x are simply removed, so the remaining equations
112 // form a valid pattern matching. How can this problem be adressed in a proper way?
113 if(eqn.variables().size() == 1 && (core::pp(function.name()) == "<" || core::pp(function.name()) == "<="))
114 {
115 continue;
116 }
117
118 rewrite_rules[function].push_back(eqn);
119 }
120
121 // For each mapping, find out whether it is a recogniser or projection function.
122 for (const auto& [mapping, equations]: rewrite_rules)
123 {
124 if (!data::is_function_sort(mapping.sort()))
125 {
126 continue;
127 }
128 data::function_sort sort(mapping.sort());
129 if (sort.domain().size() != 1)
130 {
131 continue;
132 }
133 data::sort_expression domain = sort.domain().front();
134 if (ssf.constructors[domain].empty())
135 {
136 continue;
137 }
138
139 // TODO implement this using a rewriter, which is a much easier way the find
140 // the same patterns that are implemented manually below.
141 // Check for recognisers.
142 if (data::sort_bool::is_bool(sort.codomain()))
143 {
144 std::set<data::function_symbol> positive_recogniser_equation_seen;
145 std::set<data::function_symbol> negative_recogniser_equation_seen;
146 bool invalid_equations_seen = false;
147 for (const data::data_equation& eqn: equations)
148 {
149 if (eqn.condition() != data::sort_bool::true_() ||
150 !data::is_application(eqn.lhs()))
151 {
152 invalid_equations_seen = true;
153 break;
154 }
155
156 data::application application(eqn.lhs());
157 assert(application.head() == mapping);
158 assert(application.size() == 1);
159 data::data_expression argument(application[0]);
160 data::function_symbol constructor = data::detail::get_top_fs(argument);
161 if (constructor == data::function_symbol())
162 {
163 invalid_equations_seen = true;
164 break;
165 }
166 if (data::is_application(argument))
167 {
168 const data::application& constructor_application = atermpp::down_cast<data::application>(argument);
169 bool all_args_are_vars = std::all_of(constructor_application.begin(), constructor_application.end(), &data::is_variable);
170 bool all_vars_are_unique = data::find_all_variables(constructor_application).size() == constructor_application.size();
171 if(!all_args_are_vars || !all_vars_are_unique)
172 {
173 invalid_equations_seen = true;
174 break;
175 }
176 }
177 // Check if the function symbol we found is really a constructor
178 if (ssf.constructors[domain].count(constructor) == 0)
179 {
180 invalid_equations_seen = true;
181 break;
182 }
183
184 if (eqn.rhs() == data::sort_bool::true_())
185 {
186 positive_recogniser_equation_seen.insert(constructor);
187 if (negative_recogniser_equation_seen.count(constructor) != 0)
188 {
189 invalid_equations_seen = true;
190 break;
191 }
192 }
193 else if (eqn.rhs() == data::sort_bool::false_())
194 {
195 negative_recogniser_equation_seen.insert(constructor);
196 if (positive_recogniser_equation_seen.count(constructor) != 0)
197 {
198 invalid_equations_seen = true;
199 break;
200 }
201 }
202 else
203 {
204 invalid_equations_seen = true;
205 break;
206 }
207 }
208 if (!invalid_equations_seen &&
209 positive_recogniser_equation_seen.size() == 1 &&
210 positive_recogniser_equation_seen.size() + negative_recogniser_equation_seen.size() == ssf.constructors[domain].size())
211 {
212 data::function_symbol constructor = *positive_recogniser_equation_seen.begin();
213 ssf.recogniser_func[constructor] = mapping;
214 }
215 }
216
217 // Check for projections.
218 if (equations.size() == 1)
219 {
220 data::data_equation equation = equations[0];
221 if (equation.condition() == data::sort_bool::true_() &&
222 data::is_variable(equation.rhs()) &&
223 data::is_application(equation.lhs()))
224 {
225 data::application application(equation.lhs());
226 assert(application.head() == mapping);
227 assert(application.size() == 1);
228 data::data_expression argument(application[0]);
229 if (data::is_application(argument) &&
230 data::is_function_symbol(data::application(argument).head()) &&
231 ssf.constructors[domain].count(data::function_symbol(data::application(argument).head())) == 1)
232 {
233 data::application constructor_application(argument);
234 data::function_symbol constructor(constructor_application.head());
235
236 bool all_args_are_vars = std::all_of(constructor_application.begin(), constructor_application.end(), &data::is_variable);
237 bool all_vars_are_unique = data::find_all_variables(constructor_application).size() == constructor_application.size();
238 auto find_result = std::find(constructor_application.begin(), constructor_application.end(), equation.rhs());
239
240 if (find_result != constructor_application.end() && all_args_are_vars && all_vars_are_unique)
241 {
242 data::application::const_iterator::difference_type index = find_result - constructor_application.begin();
243 assert(index >= 0 && index < static_cast<data::application::const_iterator::difference_type>(constructor_application.size()));
244 ssf.projection_func[constructor].resize(constructor_application.size());
245 ssf.projection_func[constructor][index] = mapping;
246 }
247 }
248 }
249 }
250 }
251
252 return std::make_pair(ssf, rewrite_rules);
253}
254
255/**
256 * \brief Complete the containers with recognisers and projections in ssf
257 * \details Also sets native translations and build a set of all recognisers and
258 * projections in dataspec.
259 */
261{
262 std::set<data::function_symbol> recog_and_proj;
263
264 for(const data::function_symbol& cons: dataspec.constructors())
265 {
266 auto find_result = ssf.recogniser_func.find(cons);
267 if(find_result != ssf.recogniser_func.end())
268 {
269 nt.set_native_definition(find_result->second, make_recogniser_name(cons, nt));
270 recog_and_proj.insert(find_result->second);
271 }
272 else
273 {
274 ssf.recogniser_func[cons] = make_recogniser_func(cons, nt);
275 }
276
277 if(data::is_function_sort(cons.sort()))
278 {
279 std::size_t index = 0;
280 const data::sort_expression_list& arg_list = atermpp::down_cast<data::function_sort>(cons.sort()).domain();
281 ssf.projection_func[cons].resize(arg_list.size());
282 for(const data::sort_expression& arg: arg_list)
283 {
284 data::function_symbol& projection = ssf.projection_func[cons][index];
285 if(projection != data::function_symbol())
286 {
287 nt.set_native_definition(projection, make_projection_name(cons, index, nt));
288 recog_and_proj.insert(projection);
289 }
290 else
291 {
292 projection = make_projection_func(cons, arg, index, nt);
293 }
294 index++;
295 }
296 }
297 }
298
299 return recog_and_proj;
300}
301
302inline
304{
305 std::set<core::identifier_string> used_ids = data::find_identifiers(dataspec);
306 auto p = find_structured_sort_functions(dataspec, [&nt](const data::function_symbol& f){ return nt.has_native_definition(f); });
307 structured_sort_functions& ssf = p.first;
308 std::map<data::function_symbol, data::data_equation_vector>& rewrite_rules = p.second;
309
310 std::set<data::function_symbol> recog_and_proj = complete_recognisers_projections(dataspec, nt, ssf);
311
312 data::representative_generator rep_gen(dataspec);
313 for(const auto& [function, rewr_equations]: rewrite_rules)
314 {
315 // Only unfold equations with parameters
316 // Do not unfold recognisers and projection functions
317 // Only unfold equations that satisfy the function 'is_pattern_matching_rule'
318 if (data::is_function_sort(function.sort()) &&
319 recog_and_proj.find(function) == recog_and_proj.end() &&
320 std::all_of(rewr_equations.begin(),
321 rewr_equations.end(),
322 [&ssf](const data::data_equation& eqn){ return data::is_pattern_matching_rule(ssf, eqn); }))
323 {
324 data::set_identifier_generator id_gen;
325 id_gen.add_identifiers(used_ids);
326 data::data_equation unfolded_eqn = data::unfold_pattern_matching(function, rewr_equations, ssf, rep_gen, id_gen);
327 nt.set_native_definition(function, unfolded_eqn);
328 }
329 }
330}
331
332} // namespace smt
333} // namespace mcrl2
334
335#endif
bool operator==(const unprotected_aterm_core &t) const
Comparison operator.
Definition aterm_core.h:83
const variable_list & variables() const
Definition abstraction.h:63
const data_expression & body() const
Definition abstraction.h:68
\brief A sort alias
Definition alias.h:26
\brief A basic sort
Definition basic_sort.h:26
\brief A container sort
const container_type & container_name() const
\brief A data equation
const data_expression & lhs() const
const data_expression & condition() const
const data_expression & rhs() const
const variable_list & variables() const
data_expression & operator=(data_expression &&) noexcept=default
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:108
application operator()(const data_expression &e) const
Apply a data expression to a data expression.
existential quantification.
Definition exists.h:26
universal quantification.
Definition forall.h:26
\brief A function sort
function_sort(const sort_expression_list &domain, const sort_expression &codomain)
\brief Constructor Z14.
\brief A function symbol
const sort_expression & sort() const
Components for generating an arbitrary element of a sort.
representative_generator(const data_specification &specification)
Constructor with data specification as context.
Identifier generator that stores the identifiers of the context in a set. Using the operator()() and ...
\brief A sort expression
const sort_expression & target_sort() const
Returns the target sort of this expression.
\brief A data variable
Definition variable.h:28
const sort_expression & sort() const
Definition variable.h:43
\brief A where expression
const data_expression & body() const
answer solve(const data::variable_list &vars, const data::data_expression &expr, const std::chrono::microseconds &timeout=std::chrono::microseconds::zero())
Definition solver.cpp:54
std::unordered_map< data::data_expression, std::string > m_cache
Definition solver.h:27
native_translations m_native
Definition solver.h:26
answer execute_and_check(const std::string &command, const std::chrono::microseconds &timeout) const
Definition solver.cpp:21
child_process z3
Definition solver.h:28
smt_solver(const data::data_specification &dataspec)
Definition solver.cpp:45
OutStream::pos_type top_size()
Definition utilities.h:180
std::ostringstream buf
Definition utilities.h:157
std::stack< typename OutStream::pos_type > m_stack
Definition utilities.h:156
stack_outstream(OutStream &out)
Definition utilities.h:161
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
The main namespace for the aterm++ library.
Definition algorithm.h:21
atermpp::aterm_string identifier_string
String type of the LPS library. Identifier strings are represented internally as ATerms.
A collection of utilities for lazy expression construction.
data_expression implies(data_expression const &p, data_expression const &q)
Returns an expression equivalent to p implies q.
data_expression and_(data_expression const &p, data_expression const &q)
Returns an expression equivalent to p or q.
Namespace for system defined sort bool_.
Definition bool.h:32
const basic_sort & bool_()
Constructor for sort expression Bool.
Definition bool.h:44
const function_symbol & implies()
Constructor for function symbol =>.
Definition bool.h:363
const function_symbol & and_()
Constructor for function symbol &&.
Definition bool.h:235
const function_symbol & false_()
Constructor for function symbol false.
Definition bool.h:109
const function_symbol & or_()
Constructor for function symbol ||.
Definition bool.h:299
const function_symbol & not_()
Constructor for function symbol !.
Definition bool.h:173
const function_symbol & true_()
Constructor for function symbol true.
Definition bool.h:77
Namespace for system defined sort int_.
const function_symbol & pos2int()
Constructor for function symbol Pos2Int.
Definition int1.h:360
const function_symbol & int2nat()
Constructor for function symbol Int2Nat.
Definition int1.h:298
const function_symbol & nat2int()
Constructor for function symbol Nat2Int.
Definition int1.h:236
const function_symbol & cneg()
Constructor for function symbol @cNeg.
Definition int1.h:142
const function_symbol & int2pos()
Constructor for function symbol Int2Pos.
Definition int1.h:422
const function_symbol & cint()
Constructor for function symbol @cInt.
Definition int1.h:80
const basic_sort & int_()
Constructor for sort expression Int.
Definition int1.h:47
Namespace for system defined sort nat.
const function_symbol & c0()
Constructor for function symbol @c0.
Definition nat1.h:108
const function_symbol & cnat()
Constructor for function symbol @cNat.
Definition nat1.h:140
const basic_sort & nat()
Constructor for sort expression Nat.
Definition nat1.h:46
const function_symbol & nat2pos()
Constructor for function symbol Nat2Pos.
Definition nat1.h:362
const function_symbol & pos2nat()
Constructor for function symbol Pos2Nat.
Definition nat1.h:300
Namespace for system defined sort pos.
const function_symbol & c1()
Constructor for function symbol @c1.
Definition pos1.h:78
const function_symbol & cdub()
Constructor for function symbol @cDub.
Definition pos1.h:110
const basic_sort & pos()
Constructor for sort expression Pos.
Definition pos1.h:45
Namespace for system defined sort real_.
const function_symbol & creal()
Constructor for function symbol @cReal.
Definition real1.h:107
const function_symbol & pos2real()
Constructor for function symbol Pos2Real.
Definition real1.h:171
const function_symbol & real2nat()
Constructor for function symbol Real2Nat.
Definition real1.h:419
const function_symbol & real2int()
Constructor for function symbol Real2Int.
Definition real1.h:481
const basic_sort & real_()
Constructor for sort expression Real.
Definition real1.h:48
const function_symbol & nat2real()
Constructor for function symbol Nat2Real.
Definition real1.h:233
const function_symbol & int2real()
Constructor for function symbol Int2Real.
Definition real1.h:295
const function_symbol & real2pos()
Constructor for function symbol Real2Pos.
Definition real1.h:357
Namespace for all data library functionality.
Definition data.cpp:22
bool is_application(const data_expression &t)
Returns true if the term t is an application.
atermpp::term_list< sort_expression > sort_expression_list
\brief list of sort_expressions
std::vector< data_expression > data_expression_vector
\brief vector of data_expressions
bool is_function_symbol(const atermpp::aterm &x)
Returns true if the term t is a function symbol.
atermpp::term_list< variable > variable_list
\brief list of variables
application greater_equal(const data_expression &arg0, const data_expression &arg1)
Application of function symbol >=.
Definition standard.h:369
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.
function_symbol equal_to(const sort_expression &s)
Constructor for function symbol ==.
Definition standard.h:126
application equal_to(const data_expression &arg0, const data_expression &arg1)
Application of function symbol ==.
Definition standard.h:144
std::vector< function_symbol > function_symbol_vector
\brief vector of function_symbols
void translate_sort_definitions(const data::data_specification &dataspec, OutputStream &out, const native_translations &nt, data::set_identifier_generator &id_gen, std::map< data::structured_sort, std::string > &struct_name_map)
void translate_sort_definition(const std::string &sort_name, const data::sort_expression &s, const data::data_specification &dataspec, OutputStream &out, const native_translations &nt, std::map< data::structured_sort, std::string > &struct_name_map)
static const std::map< data::structured_sort, std::string > & empty_name_map()
void translate_mapping(const data::function_symbol &f, OutputStream &out, const native_translations &nt, const std::map< data::structured_sort, std::string > &snm, bool check_native=true)
static const native_translation_t pp_real_translation
Definition solver.cpp:91
void translate_equation(const data::data_equation &eq, OutputStream &out, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt)
std::string translate_symbol_disambiguate(const data::function_symbol &f, const native_translations &nt)
data::data_expression declare_variables_binder(const data::variable_list &vars, OutputStream &out, const native_translations &nt)
Declare variables to be used in binder such as exists or forall and print the declaration to out.
static const native_translation_t pp_translation
Definition solver.cpp:85
bool is_higher_order(const data::application &a)
bool is_higher_order(const data::function_symbol &f)
translate_sort_expression_traverser< Traverser, OutputStream > make_translate_sort_expression_traverser(OutputStream &out, const native_translations &nt, const std::map< data::structured_sort, std::string > &snm)
std::map< data::sort_expression, std::set< data::sort_expression > > find_sorts_and_dependencies(const data::data_specification &dataspec, std::map< data::structured_sort, std::string > &struct_name_map)
void translate_alias(const data::alias &s, OutputStream &out, const native_translations &nt, const std::map< data::structured_sort, std::string > &struct_name_map)
void translate_sort_definition(const data::basic_sort &s, const data::data_specification &dataspec, OutputStream &out, const native_translations &nt, std::map< data::structured_sort, std::string > &struct_name_map)
static const native_translation_t reconstruct_divmod
Definition solver.cpp:99
static std::set< data::sort_expression > find_dependencies(const data::data_specification &dataspec, const data::sort_expression &sort)
bool is_higher_order(const data::data_equation &eq)
void translate_native_mappings(OutputStream &out, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt, const std::map< data::structured_sort, std::string > &snm)
void translate_sort_expression(const T &x, OutputStream &o, const native_translations &nt, const std::map< data::structured_sort, std::string > &snm=detail::empty_name_map())
std::string make_projection_name(const data::function_symbol &cons, std::size_t i, const native_translations &nt)
Definition utilities.h:50
void translate_assertion(const T &x, OutputStream &o, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt)
native_translations initialise_native_translation(const data::data_specification &dataspec)
Definition solver.cpp:126
data::function_symbol make_recogniser_func(const data::function_symbol &cons, const native_translations &nt)
Definition utilities.h:85
std::set< data::function_symbol > complete_recognisers_projections(const data::data_specification &dataspec, native_translations &nt, structured_sort_functions &ssf)
Complete the containers with recognisers and projections in ssf.
std::pair< structured_sort_functions, std::map< data::function_symbol, data::data_equation_vector > > find_structured_sort_functions(const data::data_specification &dataspec, Skip skip=Skip())
Find sorts that behave like a structured sort and the associated rewrite rules.
data::function_symbol make_projection_func(const data::function_symbol &cons, const data::sort_expression &arg_sort, std::size_t i, const native_translations &nt)
Definition utilities.h:66
std::string make_recogniser_name(const data::function_symbol &cons, const native_translations &nt)
Definition utilities.h:73
void translate_data_specification(const data::data_specification &dataspec, OutputStream &o, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt)
void unfold_pattern_matching(const data::data_specification &dataspec, native_translations &nt)
void translate_variable_declaration(const Container &vars, OutputStream &o, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt)
void translate_data_expression(const T &x, OutputStream &o, std::unordered_map< data::data_expression, std::string > &c, const native_translations &nt)
std::string translate_symbol(const data::function_symbol &f, const native_translations &nt)
Definition utilities.h:43
std::vector< T > topological_sort(std::map< T, std::set< T > > dependencies)
Definition utilities.h:92
std::string translate_identifier(const core::identifier_string &id)
Definition utilities.h:37
std::function< void(data::data_expression, std::function< void(std::string)>, std::function< void(data::data_expression)>)> native_translation_t
@ UNKNOWN
Definition answer.h:24
fixed_string_translation(const std::string &s)
Definition solver.cpp:73
void operator()(const data::data_expression &, const std::function< void(std::string)> &output_func, const std::function< void(data::data_expression)> &) const
Definition solver.cpp:77
Traverser< translate_data_expression_traverser< Traverser, OutputStream > > super
translate_data_expression_traverser(OutputStream &out_, std::unordered_map< data::data_expression, std::string > &cache, const native_translations &nt)
std::unordered_map< data::data_expression, std::string > & m_cache
const std::map< data::structured_sort, std::string > & m_struct_names
translate_sort_expression_traverser(OutputStream &out_, const native_translations &nt, const std::map< data::structured_sort, std::string > &snm)
Traverser< translate_sort_expression_traverser< Traverser, OutputStream > > super
std::map< data::function_symbol, std::string > symbols
std::set< data::function_symbol > ambiguous_symbols
bool is_ambiguous(const data::function_symbol &f) const
std::set< data::function_symbol > do_not_define
void set_native_definition(const data::function_symbol &f)
Record that the mapping and equations for f should not be translated.
std::map< data::function_symbol, native_translation_t > expressions
std::map< data::function_symbol, std::string > special_recogniser
void set_native_definition(const data::function_symbol &f, const data::data_equation &eq)
bool has_native_definition(const data::function_symbol &f) const
bool has_native_definition(const data::data_equation &eq) const
bool has_native_definition(const data::application &a) const
std::map< data::function_symbol, data::data_equation > mappings
std::map< data::sort_expression, std::string > sorts
std::map< data::function_symbol, native_translation_t >::const_iterator find_native_translation(const data::application &a) const
void set_ambiguous(const data::function_symbol &f)
Contains information on sorts that behave similar to a structured sort in a data specification.
data::data_expression create_recogniser_expr(const data::function_symbol &f, const data::data_expression &expr) const
const std::set< data::function_symbol > & get_constructors(const data::sort_expression &sort) const
const data::function_symbol_vector & get_projection_funcs(const data::function_symbol &f) const
data::data_expression create_cases(const data::data_expression &target, const data::data_expression_vector &rhss)
std::map< data::function_symbol, data::function_symbol > recogniser_func
std::map< data::sort_expression, std::set< data::function_symbol > > constructors
bool is_constructor(const data::function_symbol &f) const
std::map< data::function_symbol, data::function_symbol_vector > projection_func
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const