mCRL2
Loading...
Searching...
No Matches
data_specification.cpp
Go to the documentation of this file.
1// Author(s): Jeroen Keiren, Jeroen van der Wulp, Jan Friso Groote
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
10#include "mcrl2/core/load_aterm.h"
11#include "mcrl2/data/data_specification.h"
12#include "mcrl2/data/detail/data_utility.h"
13#include "mcrl2/data/detail/io.h"
14#include "mcrl2/data/replace.h"
15#include "mcrl2/data/substitutions/sort_expression_assignment.h"
16
17// Predefined datatypes
18#include "mcrl2/data/function_update.h"
19#include "mcrl2/data/list.h"
20
21
22namespace mcrl2::data
23{
24
26{
27 protected:
28
31
33 {
34 const function_symbol_vector& constructors=m_specification.constructors(s);
35 if (constructors.empty())
36 {
37 return false;
38 }
39
40 for(const function_symbol& f: constructors)
41 {
42 if (is_function_sort(f.sort()))
43 {
44 const function_sort& f_sort=atermpp::down_cast<function_sort>(f.sort());
45 const sort_expression_list& l=f_sort.domain();
46
47 for(const sort_expression& e: l)
48 {
49 if (!is_finite(e))
50 {
51 return false;
52 }
53 }
54 }
55 }
56 return true;
57 }
58
59 public:
60
61 finiteness_helper(const data_specification& specification) : m_specification(specification)
62 { }
63
65 {
66 assert(s==normalize_sorts(s,m_specification));
67 if (m_visiting.count(s)>0)
68 {
69 return false;
70 }
71
72 m_visiting.insert(s);
73
74 bool result=false;
75 if (is_basic_sort(s))
76 {
78 }
79 else if (is_container_sort(s))
80 {
82 }
83 else if (is_function_sort(s))
84 {
86 }
87 else if (is_structured_sort(s))
88 {
90 }
91
92 m_visiting.erase(s);
93 return result;
94 }
95
96 bool is_finite(const basic_sort& s)
97 {
98 return is_finite_aux(s);
99 }
100
102 {
103 for(const sort_expression& sort: s.domain())
104 {
105 if (!is_finite(sort))
106 {
107 return false;
108 }
109 }
110
112 }
113
115 {
118 }
119
120 bool is_finite(const alias&)
121 {
122 assert(0);
123 return false;
124 }
125
127 {
128 return is_finite_aux(s);
129 }
130};
131
132/// \brief Checks whether a sort is certainly finite.
133///
134/// \param[in] s A sort expression
135/// \return true if s can be determined to be finite,
136/// false otherwise.
138{
139 const bool result=finiteness_helper(*this).is_finite(s);
140 return result;
141}
142
143
144// The function below checks whether there is an alias loop, e.g. aliases
145// of the form A=B; B=A; or more complex A=B->C; B=Set(D); D=List(A); Loops
146// through structured sorts are allowed. If a loop is detected, an exception
147// is thrown.
148void sort_specification::check_for_alias_loop(
149 const sort_expression& s,
150 std::set<sort_expression> sorts_already_seen,
151 const bool toplevel) const
152{
153 if (is_basic_sort(s))
154 {
155 if (sorts_already_seen.count(s)>0)
156 {
157 throw mcrl2::runtime_error("Sort alias " + pp(s) + " is defined in terms of itself.");
158 }
159 for(const alias& a: m_user_defined_aliases)
160 {
161 if (a.name() == s)
162 {
163 sorts_already_seen.insert(s);
164 check_for_alias_loop(a.reference(), sorts_already_seen, true);
165 sorts_already_seen.erase(s);
166 return;
167 }
168 }
169 return;
170 }
171
173 {
174 check_for_alias_loop(container_sort(s).element_sort(),sorts_already_seen,false);
175 return;
176 }
177
179 {
180 sort_expression_list s_domain(function_sort(s).domain());
181 for(const sort_expression& sort: s_domain)
182 {
183 check_for_alias_loop(sort,sorts_already_seen,false);
184 }
185
186 check_for_alias_loop(function_sort(s).codomain(),sorts_already_seen,false);
187 return;
188 }
189
190 // A sort declaration with a struct on toplevel can be recursive. Otherwise a
191 // check needs to be made.
192 if (is_structured_sort(s) && !toplevel)
193 {
194 const structured_sort ss(s);
195 structured_sort_constructor_list constructors=ss.constructors();
196 for(const structured_sort_constructor& constructor: constructors)
197 {
198 structured_sort_constructor_argument_list ssca=constructor.arguments();
199 for(const structured_sort_constructor_argument& a: ssca)
200 {
201 check_for_alias_loop(a.sort(),sorts_already_seen,false);
202 }
203 }
204 }
205
206}
207
208
209// This function returns the normal form of e, under the the map map1.
210// This normal form is obtained by repeatedly applying map1, until this
211// is not possible anymore. It is assumed that this procedure terminates. There is
212// no check for loops.
214 const sort_expression& e,
215 const std::multimap< sort_expression, sort_expression >& map1,
216 std::set < sort_expression > sorts_already_seen = std::set < sort_expression >())
217{
218 assert(sorts_already_seen.find(e)==sorts_already_seen.end()); // e has not been seen already.
219 assert(!is_untyped_sort(e));
221
223 {
224 const function_sort fs(e);
225 const sort_expression normalised_codomain=
226 find_normal_form(fs.codomain(),map1,sorts_already_seen);
227 const sort_expression_list& domain=fs.domain();
228 sort_expression_list normalised_domain;
229 for(const sort_expression& s: domain)
230 {
231 normalised_domain.push_front(find_normal_form(s,map1,sorts_already_seen));
232 }
233 return function_sort(reverse(normalised_domain),normalised_codomain);
234 }
235
237 {
238 const container_sort cs(e);
239 return container_sort(cs.container_name(),find_normal_form(cs.element_sort(),map1,sorts_already_seen));
240 }
241
242 sort_expression result_sort;
243
245 {
246 const structured_sort ss(e);
247 structured_sort_constructor_list constructors=ss.constructors();
248 structured_sort_constructor_list normalised_constructors;
249 for(const structured_sort_constructor& constructor: constructors)
250 {
251 structured_sort_constructor_argument_list normalised_ssa;
252 for(const structured_sort_constructor_argument& a: constructor.arguments())
253 {
254 normalised_ssa.push_front(structured_sort_constructor_argument(a.name(),
255 find_normal_form(a.sort(),map1,sorts_already_seen)));
256 }
257
258 normalised_constructors.push_front(
259 structured_sort_constructor(
260 constructor.name(),
261 reverse(normalised_ssa),
262 constructor.recogniser()));
263
264 }
265 result_sort=structured_sort(reverse(normalised_constructors));
266 }
267
268 if (is_basic_sort(e))
269 {
270 result_sort=e;
271 }
272
273
274 assert(is_basic_sort(result_sort) || is_structured_sort(result_sort));
275 const std::multimap< sort_expression, sort_expression >::const_iterator i1=map1.find(result_sort);
276 if (i1!=map1.end()) // found
277 {
278#ifndef NDEBUG
279 sorts_already_seen.insert(result_sort);
280#endif
281 return find_normal_form(i1->second,map1,sorts_already_seen);
282 }
283 return result_sort;
284}
285
287{
290}
291
293{
295 {
296 mCRL2log(mcrl2::log::debug) << "Erroneous attempt to insert an untyped sort into the a sort specification\n";
297 return;
298 }
299 // Add an element, and stop if it was already added.
300 if (!m_sorts_in_context.insert(sort).second)
301 {
302 return;
303 }
304
306 // add the sorts on which this sorts depends.
307 if (sort == sort_real::real_())
308 {
309 // Int is required as the rewrite rules of Real rely on it.
311 }
312 else if (sort == sort_int::int_())
313 {
314 // See above, Int requires Nat.
316 }
317 else if (sort == sort_nat::nat())
318 {
319#ifdef MCRL2_ENABLE_MACHINENUMBERS
320 import_system_defined_sort(sort_machine_word::machine_word());
321 import_system_defined_sort(sort_nat::natnatpair());
322#else
323 // Nat requires NatPair.
325#endif
326 }
327 else if (sort == sort_pos::pos())
328 {
329#ifdef MCRL2_ENABLE_MACHINENUMBERS
330 import_system_defined_sort(sort_machine_word::machine_word());
331#endif
332 }
333 else if (is_function_sort(sort))
334 {
335 const function_sort& fsort=atermpp::down_cast<function_sort>(sort);
336 import_system_defined_sorts(fsort.domain());
338 }
339 else if (is_container_sort(sort))
340 {
342 // Import the element sort (which may be a complex sort also).
344 if (sort_list::is_list(sort))
345 {
346 import_system_defined_sort(sort_nat::nat()); // Required for lists.
347 }
348 else if (sort_set::is_set(sort))
349 {
351 // Import the functions from element_sort->Bool.
352 sort_expression_list element_sorts;
353 element_sorts.push_front(element_sort);
354 import_system_defined_sort(function_sort(element_sorts,sort_bool::bool_()));
355 }
356 else if (sort_fset::is_fset(sort))
357 {
359 }
360 else if (sort_bag::is_bag(sort))
361 {
362 // Add the sorts Nat and set_(element_sort) to the specification.
366
367 // Add the function sort element_sort->Nat to the specification
368 sort_expression_list element_sorts ;
369 element_sorts.push_front(element_sort);
370 import_system_defined_sort(function_sort(element_sorts,sort_nat::nat()));
371 }
372 else if (sort_fbag::is_fbag(sort))
373 {
376 }
377 }
378 else if (is_structured_sort(sort))
379 {
380 structured_sort s_sort(sort);
381 function_symbol_vector f(s_sort.constructor_functions(sort));
382 for(const function_symbol& f: s_sort.constructor_functions(sort))
383 {
384 import_system_defined_sort(f.sort());
385 }
386 }
387}
388
389// The function below recalculates m_normalised_aliases, such that
390// it forms a confluent terminating rewriting system using which
391// sorts can be normalised.
392// This algorithm is described in the document: algorithm-for-sort-equivalence.tex in
393// the developers library of the mCRL2 toolset.
395{
396 // First reset the normalised aliases and the mappings and constructors that have been
397 // inherited to basic sort aliases during a previous round of sort normalisation.
398 m_normalised_aliases.clear();
399
400 // This is the first step of the algorithm.
401 // Check for loops in the aliases. The type checker should already have done this,
402 // but we check it again here. If there is a loop m_normalised_aliases will not be
403 // built.
404 for(const alias& a: m_user_defined_aliases)
405 {
406 std::set < sort_expression > sorts_already_seen; // Empty set.
407 try
408 {
409 check_for_alias_loop(a.name(),sorts_already_seen,true);
410 }
411 catch (mcrl2::runtime_error &)
412 {
413 mCRL2log(log::debug) << "Encountered an alias loop in the alias for " << a.name() <<". The normalised aliases are not constructed\n";
414 return;
415 }
416 }
417
418 // This is the second step of the algorithm.
419 // Copy m_normalised_aliases. All aliases are stored from left to right,
420 // except structured sorts, which are stored from right to left. The reason is
421 // that structured sorts can be recursive, and therefore, they cannot be
422 // rewritten from left to right, as this can cause sorts to be infinitely rewritten.
423
424 std::multimap< sort_expression, sort_expression > sort_aliases_to_be_investigated;
425 std::multimap< sort_expression, sort_expression > resulting_normalized_sort_aliases;
426
427 for(const alias& a: m_user_defined_aliases)
428 {
429 if (is_structured_sort(a.reference()))
430 {
431 sort_aliases_to_be_investigated.insert(std::pair<sort_expression,sort_expression>(a.reference(),a.name()));
432 }
433 else
434 {
435 resulting_normalized_sort_aliases.insert(std::pair<sort_expression,sort_expression>(a.name(),a.reference()));
436 }
437 }
438
439 // Apply Knuth-Bendix completion to the rules in m_normalised_aliases.
440 for(; !sort_aliases_to_be_investigated.empty() ;)
441 {
442 const std::multimap< sort_expression, sort_expression >::iterator it=sort_aliases_to_be_investigated.begin();
443 const sort_expression lhs=it->first;
444 const sort_expression rhs=it->second;
445 sort_aliases_to_be_investigated.erase(it);
446
447 for(const std::pair<const sort_expression, sort_expression >& p: resulting_normalized_sort_aliases)
448 {
449 const sort_expression s1=data::replace_sort_expressions(lhs,sort_expression_assignment(p.first,p.second), true);
450
451 if (s1!=lhs)
452 {
453 // There is a conflict between the two sort rewrite rules.
454 assert(is_basic_sort(rhs));
455 // Choose the normal form on the basis of a lexicographical ordering. This guarantees
456 // uniqueness of normal forms over different tools. Ordering on addresses (as used previously)
457 // proved to be unstable over different tools.
458 const bool rhs_to_s1 = is_basic_sort(s1) && pp(basic_sort(s1))<=pp(rhs);
459 const sort_expression left_hand_side=(rhs_to_s1?rhs:s1);
460 const sort_expression pre_normal_form=(rhs_to_s1?s1:rhs);
461 assert(is_basic_sort(pre_normal_form));
462 const sort_expression& e1=pre_normal_form;
463 if (e1!=left_hand_side)
464 {
465 const sort_expression normalised_lhs=find_normal_form(left_hand_side,resulting_normalized_sort_aliases);
466 // Check whether the inserted sort rewrite rule is already in sort_aliases_to_be_investigated.
467 if (std::find_if(sort_aliases_to_be_investigated.lower_bound(normalised_lhs),
468 sort_aliases_to_be_investigated.upper_bound(normalised_lhs),
469 [&rhs](const std::pair<sort_expression,sort_expression>& x){ return x.second==rhs; })
470 == sort_aliases_to_be_investigated.upper_bound(normalised_lhs)) // Not found.
471 {
472 sort_aliases_to_be_investigated.insert(
473 std::pair<sort_expression,sort_expression > (normalised_lhs, e1));
474 }
475 }
476 }
477 else
478 {
479 const sort_expression s2 = data::replace_sort_expressions(p.first,sort_expression_assignment(lhs,rhs), true);
480 if (s2!=p.first)
481 {
482 assert(is_basic_sort(p.second));
483 // Choose the normal form on the basis of a lexicographical ordering. This guarantees
484 // uniqueness of normal forms over different tools.
485 const bool i_second_to_s2 = is_basic_sort(s2) && pp(basic_sort(s2))<=pp(p.second);
486 const sort_expression left_hand_side=(i_second_to_s2?p.second:s2);
487 const sort_expression pre_normal_form=(i_second_to_s2?s2:p.second);
488 assert(is_basic_sort(pre_normal_form));
489 const sort_expression& e2=pre_normal_form;
490 if (e2!=left_hand_side)
491 {
492 const sort_expression normalised_lhs=find_normal_form(left_hand_side,resulting_normalized_sort_aliases);
493 // Check whether the inserted sort rewrite rule is already in sort_aliases_to_be_investigated.
494 if (std::find_if(sort_aliases_to_be_investigated.lower_bound(normalised_lhs),
495 sort_aliases_to_be_investigated.upper_bound(normalised_lhs),
496 [&rhs](const std::pair<sort_expression,sort_expression>& x){ return x.second==rhs; })
497 == sort_aliases_to_be_investigated.upper_bound(normalised_lhs)) // Not found.
498 {
499 sort_aliases_to_be_investigated.insert(
500 std::pair<sort_expression,sort_expression > (normalised_lhs,e2));
501 }
502 }
503 }
504 }
505 }
506 assert(lhs!=rhs);
507 const sort_expression normalised_lhs = find_normal_form(lhs,resulting_normalized_sort_aliases);
508 const sort_expression normalised_rhs = find_normal_form(rhs,resulting_normalized_sort_aliases);
509 if (normalised_lhs!=normalised_rhs)
510 {
511 resulting_normalized_sort_aliases.insert(std::pair<sort_expression,sort_expression >(normalised_lhs,normalised_rhs));
512 }
513 }
514 // Copy resulting_normalized_sort_aliases into m_normalised_aliases, i.e. from multimap to map.
515 // If there are rules with equal left hand side, only one is arbitrarily chosen. Rewrite the
516 // right hand side to normal form.
517
518 for(const std::pair<const sort_expression,sort_expression>& p: resulting_normalized_sort_aliases)
519 {
520 const sort_expression normalised_rhs = find_normal_form(p.second,resulting_normalized_sort_aliases);
521 m_normalised_aliases[p.first]=normalised_rhs;
522
523 assert(p.first!=normalised_rhs);
524 }
525}
526
527///\brief Adds the system defined sorts to the sets with constructors, mappings, and equations for
528// a given sort. If the boolean skip_equations is true, no equations are added.
529void data_specification::find_associated_system_defined_data_types_for_a_sort(
530 const sort_expression& sort,
531 std::set < function_symbol >& constructors,
532 std::set < function_symbol >& mappings,
533 std::set < data_equation >& equations,
534 implementation_map& cpp_implemented_functions,
535 const bool skip_equations) const
536{
537 // add sorts, constructors, mappings and equations
538 if (sort == sort_bool::bool_())
539 {
540 function_symbol_vector f(sort_bool::bool_generate_constructors_code());
541 constructors.insert(f.begin(), f.end());
542 f = sort_bool::bool_generate_functions_code();
543 mappings.insert(f.begin(), f.end());
544 implementation_map f1 = sort_bool::bool_cpp_implementable_mappings();
545 cpp_implemented_functions.insert(f1.begin(), f1.end());
546 f1 = sort_bool::bool_cpp_implementable_constructors();
547 cpp_implemented_functions.insert(f1.begin(), f1.end());
548 if (!skip_equations)
549 {
550 data_equation_vector e(sort_bool::bool_generate_equations_code());
551 equations.insert(e.begin(),e.end());
552 }
553 }
554 else if (sort == sort_real::real_())
555 {
556 function_symbol_vector f(sort_real::real_generate_constructors_code());
557 constructors.insert(f.begin(),f.end());
558 f = sort_real::real_generate_functions_code();
559 mappings.insert(f.begin(),f.end());
560 implementation_map f1 = sort_int::int_cpp_implementable_mappings();
561 cpp_implemented_functions.insert(f1.begin(), f1.end());
562 f1 = sort_int::int_cpp_implementable_constructors();
563 cpp_implemented_functions.insert(f1.begin(), f1.end());
564 if (!skip_equations)
565 {
566 data_equation_vector e(sort_real::real_generate_equations_code());
567 equations.insert(e.begin(),e.end());
568 }
569 }
570 else if (sort == sort_int::int_())
571 {
572 function_symbol_vector f(sort_int::int_generate_constructors_code());
573 constructors.insert(f.begin(),f.end());
574 f = sort_int::int_generate_functions_code();
575 mappings.insert(f.begin(),f.end());
576 implementation_map f1 = sort_int::int_cpp_implementable_mappings();
577 cpp_implemented_functions.insert(f1.begin(), f1.end());
578 f1 = sort_int::int_cpp_implementable_constructors();
579 cpp_implemented_functions.insert(f1.begin(), f1.end());
580 if (!skip_equations)
581 {
582 data_equation_vector e(sort_int::int_generate_equations_code());
583 equations.insert(e.begin(),e.end());
584 }
585 }
586 else if (sort == sort_nat::nat())
587 {
588 function_symbol_vector f(sort_nat::nat_generate_constructors_code());
589 constructors.insert(f.begin(),f.end());
590 f = sort_nat::nat_generate_functions_code();
591 mappings.insert(f.begin(),f.end());
592 implementation_map f1 = sort_nat::nat_cpp_implementable_mappings();
593 cpp_implemented_functions.insert(f1.begin(), f1.end());
594 f1 = sort_nat::nat_cpp_implementable_constructors();
595 cpp_implemented_functions.insert(f1.begin(), f1.end());
596 if (!skip_equations)
597 {
598 data_equation_vector e(sort_nat::nat_generate_equations_code());
599 equations.insert(e.begin(),e.end());
600 }
601 }
602 else if (sort == sort_pos::pos())
603 {
604 function_symbol_vector f(sort_pos::pos_generate_constructors_code());
605 constructors.insert(f.begin(),f.end());
606 f = sort_pos::pos_generate_functions_code();
607 mappings.insert(f.begin(),f.end());
608 implementation_map f1 = sort_pos::pos_cpp_implementable_mappings();
609 cpp_implemented_functions.insert(f1.begin(), f1.end());
610 f1 = sort_pos::pos_cpp_implementable_constructors();
611 cpp_implemented_functions.insert(f1.begin(), f1.end());
612 if (!skip_equations)
613 {
614 data_equation_vector e(sort_pos::pos_generate_equations_code());
615 equations.insert(e.begin(),e.end());
616 }
617 }
618#ifdef MCRL2_ENABLE_MACHINENUMBERS
619 else if (sort == sort_machine_word::machine_word())
620 {
621 function_symbol_vector f(sort_machine_word::machine_word_generate_constructors_code());
622 constructors.insert(f.begin(),f.end());
623 f = sort_machine_word::machine_word_generate_functions_code();
624 mappings.insert(f.begin(),f.end());
625 implementation_map f1 = sort_machine_word::machine_word_cpp_implementable_mappings();
626 cpp_implemented_functions.insert(f1.begin(), f1.end());
627 f1 = sort_machine_word::machine_word_cpp_implementable_constructors();
628 cpp_implemented_functions.insert(f1.begin(), f1.end());
629 if (!skip_equations)
630 {
631 data_equation_vector e(sort_machine_word::machine_word_generate_equations_code());
632 equations.insert(e.begin(),e.end());
633 }
634 }
635#endif
636 else if (is_function_sort(sort))
637 {
638 const sort_expression& t = static_cast<const function_sort&>(sort).codomain();
639 const sort_expression_list& l = static_cast<const function_sort&>(sort).domain();
640 if (l.size()==1)
641 {
642 const function_symbol_vector f = function_update_generate_functions_code(l.front(),t);
643 mappings.insert(f.begin(),f.end());
644 implementation_map f1 = function_update_cpp_implementable_mappings(l.front(),t);
645 cpp_implemented_functions.insert(f1.begin(), f1.end());
646 f1 = function_update_cpp_implementable_constructors();
647 cpp_implemented_functions.insert(f1.begin(), f1.end());
648 if (!skip_equations)
649 {
650 data_equation_vector e(function_update_generate_equations_code(l.front(),t));
651 equations.insert(e.begin(),e.end());
652 }
653 }
654 }
655 else if (is_container_sort(sort))
656 {
658 if (sort_list::is_list(sort))
659 {
660 function_symbol_vector f(sort_list::list_generate_constructors_code(element_sort));
661 constructors.insert(f.begin(),f.end());
662 f = sort_list::list_generate_functions_code(element_sort);
663 mappings.insert(f.begin(),f.end());
664 implementation_map f1 = sort_list::list_cpp_implementable_mappings(element_sort);
665 cpp_implemented_functions.insert(f1.begin(), f1.end());
666 f1 = sort_list::list_cpp_implementable_constructors(element_sort);
667 cpp_implemented_functions.insert(f1.begin(), f1.end());
668 if (!skip_equations)
669 {
670 data_equation_vector e(sort_list::list_generate_equations_code(element_sort));
671 equations.insert(e.begin(),e.end());
672 }
673 }
674 else if (sort_set::is_set(sort))
675 {
676 sort_expression_list element_sorts;
677 element_sorts.push_front(element_sort);
678 function_symbol_vector f(sort_set::set_generate_constructors_code(element_sort));
679 constructors.insert(f.begin(),f.end());
680 f = sort_set::set_generate_functions_code(element_sort);
681 mappings.insert(f.begin(),f.end());
682 implementation_map f1 = sort_set::set_cpp_implementable_mappings(element_sort);
683 cpp_implemented_functions.insert(f1.begin(), f1.end());
684 f1 = sort_set::set_cpp_implementable_constructors(element_sort);
685 cpp_implemented_functions.insert(f1.begin(), f1.end());
686 if (!skip_equations)
687 {
688 data_equation_vector e(sort_set::set_generate_equations_code(element_sort));
689 equations.insert(e.begin(),e.end());
690 }
691 }
692 else if (sort_fset::is_fset(sort))
693 {
694 function_symbol_vector f = sort_fset::fset_generate_constructors_code(element_sort);
695 constructors.insert(f.begin(),f.end());
696 f = sort_fset::fset_generate_functions_code(element_sort);
697 mappings.insert(f.begin(),f.end());
698 implementation_map f1 = sort_fset::fset_cpp_implementable_mappings(element_sort);
699 cpp_implemented_functions.insert(f1.begin(), f1.end());
700 f1 = sort_fset::fset_cpp_implementable_constructors(element_sort);
701 cpp_implemented_functions.insert(f1.begin(), f1.end());
702 if (!skip_equations)
703 {
704 data_equation_vector e = sort_fset::fset_generate_equations_code(element_sort);
705 equations.insert(e.begin(),e.end());
706 }
707 }
708 else if (sort_bag::is_bag(sort))
709 {
710 sort_expression_list element_sorts;
711 element_sorts.push_front(element_sort);
712 function_symbol_vector f(sort_bag::bag_generate_constructors_code(element_sort));
713 constructors.insert(f.begin(),f.end());
714 f = sort_bag::bag_generate_functions_code(element_sort);
715 mappings.insert(f.begin(),f.end());
716 implementation_map f1 = sort_bag::bag_cpp_implementable_mappings(element_sort);
717 cpp_implemented_functions.insert(f1.begin(), f1.end());
718 f1 = sort_bag::bag_cpp_implementable_constructors(element_sort);
719 cpp_implemented_functions.insert(f1.begin(), f1.end());
720 if (!skip_equations)
721 {
722 data_equation_vector e(sort_bag::bag_generate_equations_code(element_sort));
723 equations.insert(e.begin(),e.end());
724 }
725 }
726 else if (sort_fbag::is_fbag(sort))
727 {
728 function_symbol_vector f = sort_fbag::fbag_generate_constructors_code(element_sort);
729 constructors.insert(f.begin(),f.end());
730 f = sort_fbag::fbag_generate_functions_code(element_sort);
731 mappings.insert(f.begin(),f.end());
732 implementation_map f1 = sort_fbag::fbag_cpp_implementable_mappings(element_sort);
733 cpp_implemented_functions.insert(f1.begin(), f1.end());
734 f1 = sort_fbag::fbag_cpp_implementable_constructors(element_sort);
735 cpp_implemented_functions.insert(f1.begin(), f1.end());
736 if (!skip_equations)
737 {
738 data_equation_vector e = sort_fbag::fbag_generate_equations_code(element_sort);
739 equations.insert(e.begin(),e.end());
740 }
741 }
742 }
743 else if (is_structured_sort(sort))
744 {
745 insert_mappings_constructors_for_structured_sort(
746 atermpp::down_cast<structured_sort>(sort),
747 constructors, mappings, equations, skip_equations);
748 }
749 add_standard_mappings_and_equations(sort, mappings, equations, skip_equations);
750}
751
752void data_specification::get_system_defined_sorts_constructors_and_mappings(
755 std::set <function_symbol >& mappings) const
756{
758
760#ifdef MCRL2_ENABLE_MACHINENUMBERS
762#endif
772
774 for(const sort_expression& s: sorts)
775 {
777 }
778 assert(dummy_equations.size()==0);
779}
780
782{
783 // check 1)
784 if (!detail::check_data_spec_sorts(constructors(), sorts()))
785 {
786 std::clog << "data_specification::is_well_typed() failed: not all of the sorts appearing in the constructors "
787 << data::pp(constructors()) << " are declared in " << data::pp(sorts()) << std::endl;
788 return false;
789 }
790
791 // check 2)
792 if (!detail::check_data_spec_sorts(mappings(), sorts()))
793 {
794 std::clog << "data_specification::is_well_typed() failed: not all of the sorts appearing in the mappings "
795 << data::pp(mappings()) << " are declared in " << data::pp(sorts()) << std::endl;
796 return false;
797 }
798
799 return true;
800}
801
802/// There are two types of representations of ATerms:
803/// - the bare specification that does not contain constructor, mappings
804/// and equations for system defined sorts
805/// - specification that includes all system defined information (legacy)
806/// The last type must eventually disappear but is unfortunately still in
807/// use in a substantial amount of source code.
808/// Note, all sorts with name prefix \@legacy_ are eliminated
809void data_specification::build_from_aterm(const atermpp::aterm& term)
810{
811 assert(core::detail::check_rule_DataSpec(term));
812
813 // Note backwards compatibility measure: alias is no longer a sort_expression
814 const atermpp::term_list<atermpp::aterm> term_sorts=
815 atermpp::down_cast<atermpp::term_list<atermpp::aterm> >(term[0][0]);
816 const data::function_symbol_list term_constructors=
817 atermpp::down_cast<data::function_symbol_list>(term[1][0]);
818 const data::function_symbol_list term_mappings=
819 atermpp::down_cast<data::function_symbol_list>(term[2][0]);
820 const data::data_equation_list term_equations=
821 atermpp::down_cast<data::data_equation_list>(term[3][0]);
822
823 // Store the sorts and aliases.
824 for(const atermpp::aterm& t: term_sorts)
825 {
826 if (data::is_alias(t)) // Compatibility with legacy code
827 {
828 add_alias(atermpp::down_cast<data::alias>(t));
829 }
830 else
831 {
832 add_sort(atermpp::down_cast<basic_sort>(t));
833 }
834 }
835
836 // Store the constructors.
837 for(const function_symbol& f: term_constructors)
838 {
839 add_constructor(f);
840 }
841
842 // Store the mappings.
843 for(const function_symbol& f: term_mappings)
844 {
845 add_mapping(f);
846 }
847
848 // Store the equations.
849 for(const data_equation& e: term_equations)
850 {
851 add_equation(e);
852 }
853}
854
855data_specification::data_specification(const basic_sort_vector& sorts,
856 const alias_vector& aliases,
857 const function_symbol_vector& constructors,
858 const function_symbol_vector& user_defined_mappings,
859 const data_equation_vector& user_defined_equations)
861{
862 // Store the constructors.
863 for(const function_symbol& f: constructors)
864 {
865 add_constructor(f);
866 }
867
868 // Store the mappings.
869 for(const function_symbol& f: user_defined_mappings)
870 {
871 add_mapping(f);
872 }
873
874 // Store the equations.
875 for(const data_equation& e: user_defined_equations)
876 {
877 add_equation(e);
878 }
879
880 assert(is_well_typed());
881}
882
883} // namespace mcrl2::data
A list of aterm objects.
Definition aterm_list.h:26
A unordered_map class in which aterms can be stored.
\brief A sort alias
Definition alias.h:23
\brief A basic sort
Definition basic_sort.h:25
basic_sort(const atermpp::aterm &term)
Definition basic_sort.h:34
\brief A container sort
const container_type & container_name() const
const sort_expression & element_sort() const
container_sort(const atermpp::aterm &term)
data_specification(const basic_sort_vector &sorts, const alias_vector &aliases, const function_symbol_vector &constructors, const function_symbol_vector &user_defined_mappings, const data_equation_vector &user_defined_equations)
Constructor from its members.
bool is_well_typed() const
Returns true if.
bool is_certainly_finite(const sort_expression &s) const
Checks whether a sort is certainly finite.
bool is_finite(const container_sort &s)
bool is_finite(const basic_sort &s)
bool is_finite_aux(const sort_expression &s)
bool is_finite(const sort_expression &s)
std::set< sort_expression > m_visiting
bool is_finite(const function_sort &s)
const data_specification & m_specification
finiteness_helper(const data_specification &specification)
bool is_finite(const structured_sort &s)
\brief Container type for finite sets
fset_container()
\brief Default constructor X3.
\brief A function sort
const sort_expression & codomain() const
function_sort(const atermpp::aterm &term)
const sort_expression_list & domain() const
\brief Container type for sets
set_container()
\brief Default constructor X3.
\brief A sort expression
sort_expression & operator=(const sort_expression &) noexcept=default
sort_expression(const sort_expression &) noexcept=default
Move semantics.
void add_system_defined_sort(const sort_expression &s)
Adds a sort to this specification, and marks it as system defined.
void sorts_are_not_necessarily_normalised_anymore() const
void import_system_defined_sort(const sort_expression &sort)
Adds the system defined sorts in a sequence. The second argument is used to check which sorts are add...
structured_sort(const atermpp::aterm &term)
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:393
Namespace for system defined sort bag.
Definition bag1.h:35
bool is_bag(const sort_expression &e)
Recogniser for sort expression Bag(s)
Definition bag1.h:52
Namespace for system defined sort bool_.
Definition bool.h:29
const basic_sort & bool_()
Constructor for sort expression Bool.
Definition bool.h:41
Namespace for system defined sort fbag.
Definition fbag1.h:34
container_sort fbag(const sort_expression &s)
Constructor for sort expression FBag(S)
Definition fbag1.h:40
bool is_fbag(const sort_expression &e)
Recogniser for sort expression FBag(s)
Definition fbag1.h:51
Namespace for system defined sort fset.
Definition fset1.h:32
bool is_fset(const sort_expression &e)
Recogniser for sort expression FSet(s)
Definition fset1.h:49
container_sort fset(const sort_expression &s)
Constructor for sort expression FSet(S)
Definition fset1.h:38
Namespace for system defined sort int_.
const basic_sort & int_()
Constructor for sort expression Int.
Definition int1.h:44
Namespace for system defined sort list.
Definition list1.h:33
bool is_list(const sort_expression &e)
Recogniser for sort expression List(s)
Definition list1.h:50
Namespace for system defined sort nat.
const basic_sort & nat()
Constructor for sort expression Nat.
Definition nat1.h:43
const basic_sort & natpair()
Constructor for sort expression @NatPair.
Definition nat1.h:72
Namespace for system defined sort pos.
const basic_sort & pos()
Constructor for sort expression Pos.
Definition pos1.h:42
Namespace for system defined sort real_.
const basic_sort & real_()
Constructor for sort expression Real.
Definition real1.h:45
Namespace for system defined sort set_.
Definition set1.h:33
bool is_set(const sort_expression &e)
Recogniser for sort expression Set(s)
Definition set1.h:50
container_sort set_(const sort_expression &s)
Constructor for sort expression Set(S)
Definition set1.h:39
bool is_structured_sort(const atermpp::aterm &x)
Returns true if the term t is a structured sort.
static sort_expression find_normal_form(const sort_expression &e, const std::multimap< sort_expression, sort_expression > &map1, std::set< sort_expression > sorts_already_seen=std::set< sort_expression >())
bool is_untyped_possible_sorts(const atermpp::aterm &x)
Returns true if the term t is an expression for multiple possible sorts.
bool is_untyped_sort(const atermpp::aterm &x)
Returns true if the term t is the unknown sort.
bool is_container_sort(const atermpp::aterm &x)
Returns true if the term t is a container sort.
bool is_basic_sort(const atermpp::aterm &x)
Returns true if the term t is a basic sort.
bool is_function_sort(const atermpp::aterm &x)
Returns true if the term t is a function sort.