mCRL2
Loading...
Searching...
No Matches
typecheck.cpp
Go to the documentation of this file.
1// Author(s): Yaroslav Usenko, Jan Friso Groote, Wieger Wesselink (2015)
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#include "mcrl2/data/print.h"
11
12using namespace mcrl2::log;
13using namespace mcrl2::core::detail;
14using namespace mcrl2::data;
15using namespace atermpp;
16
17namespace mcrl2
18{
19namespace data
20{
21
22namespace detail
23{
24
25void variable_context::typecheck_variable(const data_type_checker& typechecker, const variable& v) const
26{
27 typechecker(v, *this);
28}
29
30// This function checks whether the set s1 is included in s2. If not the variable culprit
31// is the variable occuring in s1 but not in s2.
32static bool includes(const std::set<variable>& s1, const std::set<variable>& s2, variable& culprit)
33{
34 for(const variable& v: s1)
35 {
36 if (s2.count(v)==0)
37 {
38 culprit=v;
39 return false;
40 }
41 }
42 return true;
43}
44
45static inline bool IsPos(const core::identifier_string& Number)
46{
47 char c=Number.function().name()[0];
48 return isdigit(c) && c>'0';
49}
50static inline bool IsNat(const core::identifier_string& Number)
51{
52 return isdigit(Number.function().name()[0]) != 0;
53}
54
56static bool HasUnknown(const sort_expression& Type);
57static bool IsNumericType(const sort_expression& Type);
58static sort_expression MinType(const sort_expression_list& TypeList);
60
61// Insert an element in the list provided, it did not already occur in the list.
62template<class S>
64{
65 if (std::find(list.begin(),list.end(), el) == list.end())
66 {
67 atermpp::term_list<S> result=list;
68 result.push_front(el);
69 return result;
70 }
71 return list;
72}
73
74} // namespace detail
75} // namespace data
76
77// ------------------------------ Here starts the new class based data expression checker -----------------------
78
79// The function below is used to check whether a term is well typed.
80// It always yields true, but if the dataterm is not properly typed, using the types
81// that are included inside the term it calls an assert. This function is useful to check
82// whether typing was succesful, using assert(strict_type_check(d)).
83
85{
86 if (is_abstraction(d))
87 {
88 const abstraction& abstr=down_cast<const abstraction>(d);
89 assert(abstr.variables().size()>0);
90 const binder_type& BindingOperator = abstr.binding_operator();
91
92 if (is_forall_binder(BindingOperator) || is_exists_binder(BindingOperator))
93 {
94 assert(d.sort()==sort_bool::bool_());
95 strict_type_check(abstr.body());
96 }
97
98 if (is_lambda_binder(BindingOperator))
99 {
100 strict_type_check(abstr.body());
101 }
102 return true;
103 }
104
105 if (is_where_clause(d))
106 {
107 const where_clause& where=down_cast<const where_clause>(d);
108 const assignment_expression_list& where_asss=where.declarations();
109 for (assignment_expression_list::const_iterator i=where_asss.begin(); i!=where_asss.end(); ++i)
110 {
111 const assignment_expression WhereElem= *i;
112 const assignment& t=down_cast<const assignment>(WhereElem);
113 strict_type_check(t.rhs());
114 }
115 strict_type_check(where.body());
116 return true;
117 }
118
119 if (is_application(d))
120 {
121 const application& appl=down_cast<application>(d);
122 const data_expression& head = appl.head();
123
124 if (data::is_function_symbol(head))
125 {
128 {
129 const sort_expression s=d.sort();
130 assert(sort_list::is_list(s));
132
133 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
134 {
135 strict_type_check(*i);
136 assert(i->sort()==s1);
137
138 }
139 return true;
140 }
141 if (name == sort_set::set_enumeration_name())
142 {
143 const sort_expression s=d.sort();
144 assert(sort_fset::is_fset(s));
146
147 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
148 {
149 strict_type_check(*i);
150 assert(i->sort()==s1);
151
152 }
153 return true;
154 }
155 if (name == sort_bag::bag_enumeration_name())
156 {
157 const sort_expression s=d.sort();
158 assert(sort_fbag::is_fbag(s));
160
161 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
162 {
163 strict_type_check(*i);
164 assert(i->sort()==s1);
165 // Every second element in a bag enumeration should be of type Nat.
166 ++i;
167 strict_type_check(*i);
168 assert(i->sort()==sort_nat::nat());
169
170 }
171 return true;
172
173 }
174 }
175 strict_type_check(head);
176 const sort_expression& s=head.sort();
177 assert(is_function_sort(s));
178 assert(d.sort()==function_sort(s).codomain());
179 sort_expression_list argument_sorts=function_sort(s).domain();
180 assert(appl.size()==argument_sorts.size());
182 for(sort_expression_list::const_iterator i=argument_sorts.begin(); i!=argument_sorts.end(); ++i,++j)
183 {
184 assert(UnwindType(j->sort())==UnwindType(*i));
185 strict_type_check(*j);
186 }
187 return true;
188 }
189
191 {
192 return true;
193 }
194
195 assert(0); // Unexpected data_expression.
196 return true;
197}
198
200 sort_expression NeededType,
201 sort_expression Type,
202 data_expression& Par,
203 const detail::variable_context& DeclaredVars,
204 const bool strictly_ambiguous,
205 bool warn_upcasting,
206 const bool print_cast_error) const
207{
208 // Makes upcasting from Type to Needed Type for Par. Returns the resulting type.
209 // Moreover, *Par is extended with the required type transformations.
210
211 if (data::is_untyped_sort(Type))
212 {
213 return Type;
214 }
215 if (data::is_untyped_sort(NeededType))
216 {
217 return Type;
218 }
219
220 // Added to make sure that the types are sufficiently unrolled, because this function is not always called
221 // with unrolled types.
222 NeededType=UnwindType(NeededType);
223 Type=UnwindType(Type);
224
225 if (EqTypesA(NeededType,Type))
226 {
227 return Type;
228 }
229
230 if (data::is_untyped_possible_sorts(NeededType))
231 {
232 untyped_possible_sorts mps(NeededType);
233 const sort_expression_list& l=mps.sorts();
234 for(sort_expression_list::const_iterator i=l.begin(); i!=l.end(); ++i)
235 {
236 bool found_solution=true;
238 try
239 {
240 r=UpCastNumericType(*i,Type,Par,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
241 }
242 catch (mcrl2::runtime_error&)
243 {
244 found_solution=false;
245 }
246 if (found_solution)
247 {
248 return r;
249 }
250 }
251 throw mcrl2::runtime_error("Cannot transform " + data::pp(Type) + " to a number.");
252 }
253
254 if (warn_upcasting && data::is_function_symbol(Par) && utilities::is_numeric_string(down_cast<function_symbol>(Par).name().function().name()))
255 {
256 warn_upcasting=false;
257 }
258
259 // Try Upcasting to Pos
260 sort_expression temp;
261 if (TypeMatchA(NeededType,sort_pos::pos(),temp))
262 {
263 if (TypeMatchA(Type,sort_pos::pos(),temp))
264 {
265 return sort_pos::pos();
266 }
267 }
268
269 // Try Upcasting to Nat
270 if (TypeMatchA(NeededType,sort_nat::nat(),temp))
271 {
272 if (TypeMatchA(Type,sort_pos::pos(),temp))
273 {
274 data_expression OldPar=Par;
275#ifdef MCRL2_ENABLE_MACHINENUMBERS
276 Par=sort_nat::transform_positive_number_to_nat(Par);
277#else
278 Par=application(sort_nat::cnat(),Par);
279#endif
280 if (warn_upcasting)
281 {
282 was_warning_upcasting=true;
283 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Nat by applying Pos2Nat to it." << std::endl;
284 }
285 return sort_nat::nat();
286 }
287 if (TypeMatchA(Type,sort_nat::nat(),temp))
288 {
289 return sort_nat::nat();
290 }
291 }
292
293 // Try Upcasting to Int
294 if (TypeMatchA(NeededType,sort_int::int_(),temp))
295 {
296 if (TypeMatchA(Type,sort_pos::pos(),temp))
297 {
298 data_expression OldPar=Par;
299#ifdef MCRL2_ENABLE_MACHINENUMBERS
300 Par=application(sort_int::cint(),sort_nat::transform_positive_number_to_nat(Par));
301#else
303#endif
304 if (warn_upcasting)
305 {
306 was_warning_upcasting=true;
307 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Int by applying Pos2Int to it." << std::endl;
308 }
309 return sort_int::int_();
310 }
311 if (TypeMatchA(Type,sort_nat::nat(),temp))
312 {
313 data_expression OldPar=Par;
314 Par=application(sort_int::cint(),Par);
315 if (warn_upcasting)
316 {
317 was_warning_upcasting=true;
318 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Int by applying Nat2Int to it." << std::endl;
319 }
320 return sort_int::int_();
321 }
322 if (TypeMatchA(Type,sort_int::int_(),temp))
323 {
324 return sort_int::int_();
325 }
326 }
327
328 // Try Upcasting to Real
329 if (TypeMatchA(NeededType,sort_real::real_(),temp))
330 {
331 if (TypeMatchA(Type,sort_pos::pos(),temp))
332 {
333 data_expression OldPar=Par;
334#ifdef MCRL2_ENABLE_MACHINENUMBERS
336 application(sort_int::cint(), sort_nat::transform_positive_number_to_nat(Par)),
337 sort_pos::pos(1));
338#else
341 sort_pos::c1());
342#endif
343 if (warn_upcasting)
344 {
345 was_warning_upcasting=true;
346 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Real by applying Pos2Real to it." << std::endl;
347 }
348 return sort_real::real_();
349 }
350 if (TypeMatchA(Type,sort_nat::nat(),temp))
351 {
352 data_expression OldPar=Par;
355 sort_pos::c1());
356 if (warn_upcasting)
357 {
358 was_warning_upcasting=true;
359 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Real by applying Nat2Real to it." << std::endl;
360 }
361 return sort_real::real_();
362 }
363 if (TypeMatchA(Type,sort_int::int_(),temp))
364 {
365 data_expression OldPar=Par;
367 if (warn_upcasting)
368 {
369 was_warning_upcasting=true;
370 mCRL2log(warning) << "Upcasting " << OldPar << " to sort Real by applying Int2Real to it." << std::endl;
371 }
372 return sort_real::real_();
373 }
374 if (TypeMatchA(Type,sort_real::real_(),temp))
375 {
376 return sort_real::real_();
377 }
378 }
379
380 // If NeededType and Type are both container types, try to upcast the argument.
381 if (is_container_sort(NeededType) && is_container_sort(Type))
382 {
383 const container_sort needed_container_type(NeededType);
384 const container_sort container_type(Type);
385 sort_expression needed_argument_type=needed_container_type.element_sort();
386 const sort_expression& argument_type=container_type.element_sort();
387 if (is_untyped_sort(needed_argument_type))
388 {
389 needed_argument_type=argument_type;
390 }
391 const sort_expression needed_similar_container_type=container_sort(container_type.container_name(),needed_argument_type);
392 if (needed_similar_container_type==NeededType)
393 {
394 throw mcrl2::runtime_error("Cannot typecast " + data::pp(Type) + " into " + data::pp(NeededType) + " for data expression " + data::pp(Par) + ".");
395 }
396 try
397 {
398 Type=TraverseVarConsTypeD(DeclaredVars,Par,
399 needed_similar_container_type,strictly_ambiguous,warn_upcasting,print_cast_error);
400 assert(UnwindType(Type)==UnwindType(needed_similar_container_type));
401
402 }
403 catch (mcrl2::runtime_error& e)
404 {
405 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while trying to match argument types of " + data::pp(NeededType) + " and " +
406 data::pp(Type) + " in data expression " + data::pp(Par) + ".");
407 }
408 }
409
410
411 // If is is an fset, try upcasting to a set.
412 if (is_container_sort(NeededType) && is_set_container(container_sort(NeededType).container_name()))
413 {
414 if (is_container_sort(Type) && is_fset_container(container_sort(Type).container_name()))
415 {
416 Par=sort_set::constructor(container_sort(NeededType).element_sort(),sort_set::false_function(container_sort(NeededType).element_sort()),Par);
417 // Do this again to lift argument types if needed. TODO.
418 return NeededType;
419 }
420 else if (is_container_sort(Type) && is_set_container(container_sort(Type).container_name()))
421 {
422 if (Type==NeededType)
423 {
424 return Type;
425 }
426 else
427 {
428 throw mcrl2::runtime_error("Upcasting " + data::pp(Type) + " to " + data::pp(NeededType) + " fails (1).");
429 }
430 }
431 }
432
433 // If is is an fbag, try upcasting to a bag.
434 if (is_container_sort(NeededType) && is_bag_container(container_sort(NeededType).container_name()))
435 {
436 if (is_container_sort(Type) && is_fbag_container(container_sort(Type).container_name()))
437 {
438 Par=sort_bag::constructor(container_sort(NeededType).element_sort(),sort_bag::zero_function(container_sort(NeededType).element_sort()),Par);
439 // Do this again to lift argument types if needed. TODO.
440 return NeededType;
441 }
442 else if (is_container_sort(Type) && is_bag_container(container_sort(Type).container_name()))
443 {
444 if (Type==NeededType)
445 {
446 return Type;
447 }
448 else
449 {
450 throw mcrl2::runtime_error("Upcasting " + data::pp(Type) + " to " + data::pp(NeededType) + " fails (1).");
451 }
452 }
453 }
454
455 if (is_function_sort(NeededType))
456 {
457 const function_sort needed_function_type(NeededType);
458 if (is_function_sort(Type))
459 {
460 // we only deal here with @false_ and @zero (false_function and zero_function).
462 {
463 assert(needed_function_type.domain().size()==1);
464 Par=sort_set::false_function(needed_function_type.domain().front());
465 return NeededType;
466 }
468 {
469 assert(needed_function_type.domain().size()==1);
470 Par=sort_bag::zero_function(needed_function_type.domain().front());
471 return NeededType;
472 }
473 }
474 }
475
476 throw mcrl2::runtime_error("Upcasting " + data::pp(Type) + " to " + data::pp(NeededType) + " fails (3).");
477}
478
479
481{
482 //select Set(Type), elements, return their list of arguments.
483 if (is_basic_sort(PosType))
484 {
485 PosType=UnwindType(PosType);
486 }
487 if (sort_fset::is_fset(PosType) || sort_set::is_set(PosType))
488 {
489 result=down_cast<container_sort>(PosType).element_sort();
490 return true;
491 }
492 if (data::is_untyped_sort(PosType))
493 {
494 result=PosType;
495 return true;
496 }
497
498 sort_expression_list NewPosTypes;
499 if (is_untyped_possible_sorts(PosType))
500 {
501 const untyped_possible_sorts& mps=down_cast<untyped_possible_sorts>(PosType);
502 for (sort_expression_list PosTypes=mps.sorts(); !PosTypes.empty(); PosTypes=PosTypes.tail())
503 {
504 sort_expression NewPosType=PosTypes.front();
505 if (is_basic_sort(NewPosType))
506 {
507 NewPosType=UnwindType(NewPosType);
508 }
509 if (sort_fset::is_fset(sort_expression(NewPosType))|| (sort_set::is_set(sort_expression(NewPosType))))
510 {
511 NewPosType=down_cast<const container_sort>(NewPosType).element_sort();
512 }
513 else if (!data::is_untyped_sort(data::sort_expression(NewPosType)))
514 {
515 continue;
516 }
517 NewPosTypes.push_front(NewPosType);
518 }
519 NewPosTypes=reverse(NewPosTypes);
520 result=untyped_possible_sorts(sort_expression_list(NewPosTypes));
521 return true;
522 }
523 return false;
524}
525
527{
528 //select Bag(Type), elements, return their list of arguments.
529 if (is_basic_sort(PosType))
530 {
531 PosType=UnwindType(PosType);
532 }
534 {
535 result=down_cast<const container_sort>(PosType).element_sort();
536 return true;
537 }
539 {
540 result=PosType;
541 return true;
542 }
543
544 sort_expression_list NewPosTypes;
545 if (is_untyped_possible_sorts(PosType))
546 {
547 const untyped_possible_sorts& mps=down_cast<untyped_possible_sorts>(PosType);
548 for (sort_expression_list PosTypes=mps.sorts(); !PosTypes.empty(); PosTypes=PosTypes.tail())
549 {
550 sort_expression NewPosType=PosTypes.front();
551 if (is_basic_sort(NewPosType))
552 {
553 NewPosType=UnwindType(NewPosType);
554 }
556 {
557 NewPosType=down_cast<const container_sort>(NewPosType).element_sort();
558 }
559 else if (!data::is_untyped_sort(data::sort_expression(NewPosType)))
560 {
561 continue;
562 }
563 NewPosTypes.push_front(NewPosType);
564 }
565 NewPosTypes=reverse(NewPosTypes);
566 result=untyped_possible_sorts(sort_expression_list(NewPosTypes));
567 return true;
568 }
569 return false;
570}
571
573{
574 //select List(Type), elements, return their list of arguments.
575 if (is_basic_sort(PosType))
576 {
577 PosType=UnwindType(PosType);
578 }
580 {
581 result=down_cast<const container_sort>(PosType).element_sort();
582 return true;
583 }
585 {
586 result=PosType;
587 return true;
588 }
589
590 sort_expression_list NewPosTypes;
591 if (is_untyped_possible_sorts(PosType))
592 {
593 const untyped_possible_sorts& mps=down_cast<untyped_possible_sorts>(PosType);
594 for (sort_expression_list PosTypes=mps.sorts(); !PosTypes.empty(); PosTypes=PosTypes.tail())
595 {
596 sort_expression NewPosType=PosTypes.front();
597 if (is_basic_sort(NewPosType))
598 {
599 NewPosType=UnwindType(NewPosType);
600 }
601 if (sort_list::is_list(NewPosType))
602 {
603 NewPosType=down_cast<const container_sort>(NewPosType).element_sort();
604 }
605 else if (!data::is_untyped_sort(NewPosType))
606 {
607 continue;
608 }
609 NewPosTypes.push_front(NewPosType);
610 }
611 NewPosTypes=reverse(NewPosTypes);
612 result=untyped_possible_sorts(sort_expression_list(NewPosTypes));
613 return true;
614 }
615 return false;
616}
617
618
620{
621 //Filter PosType to contain only functions ArgTypes -> TypeX
622 //result is TypeX if unique, the set of TypeX as NotInferred if many.
623 //return true if successful, otherwise false.
624
625 if (is_basic_sort(PosType))
626 {
627 PosType=UnwindType(PosType);
628 }
629 if (is_function_sort(PosType))
630 {
631 const function_sort& s=down_cast<const function_sort>(PosType);
632 const sort_expression_list& PosArgTypes=s.domain();
633
634 if (PosArgTypes.size()!=ArgTypes.size())
635 {
636 return false;
637 }
639 if (TypeMatchL(PosArgTypes,ArgTypes,temp))
640 {
641 result=s.codomain();
642 return true;
643 }
644 else
645 {
646 // Lift the argument of PosType.
647 TypeMatchL(ArgTypes,ExpandNumTypesUpL(PosArgTypes),temp);
648 result=s.codomain();
649 return true;
650 }
651 }
653 {
654 result=PosType;
655 return true;
656 }
657
658 sort_expression_list NewPosTypes;
659 if (is_untyped_possible_sorts(PosType))
660 {
661 const untyped_possible_sorts& mps=down_cast<untyped_possible_sorts>(PosType);
662 for (sort_expression_list PosTypes=mps.sorts(); !PosTypes.empty(); PosTypes=PosTypes.tail())
663 {
664 sort_expression NewPosType=PosTypes.front();
665 if (is_basic_sort(NewPosType))
666 {
667 NewPosType=UnwindType(NewPosType);
668 }
669 if (is_function_sort(NewPosType))
670 {
671 const function_sort& s=down_cast<const function_sort>(NewPosType);
672 const sort_expression_list& PosArgTypes=s.domain();
673 if (PosArgTypes.size()!=ArgTypes.size())
674 {
675 continue;
676 }
677 sort_expression_list temp_list;
678 if (TypeMatchL(PosArgTypes,ArgTypes,temp_list))
679 {
680 NewPosType=s.codomain();
681 }
682 }
683 else if (!data::is_untyped_sort(data::sort_expression(NewPosType)))
684 {
685 continue;
686 }
687 NewPosTypes=detail::insert_sort_unique(NewPosTypes,NewPosType);
688 }
689 NewPosTypes=reverse(NewPosTypes);
690 result=untyped_possible_sorts(sort_expression_list(NewPosTypes));
691 return true;
692 }
693 return false;
694}
695
697{
698 //Find the minimal type that Unifies the 2. If not possible, return false.
699 if (!TypeMatchA(Type1,Type2,result))
700 {
701 if (!TypeMatchA(Type1,ExpandNumTypesUp(Type2),result))
702 {
703 if (!TypeMatchA(Type2,ExpandNumTypesUp(Type1),result))
704 {
705 return false;
706 }
707 }
708 }
709
710 if (is_untyped_possible_sorts(result))
711 {
712 result=down_cast<untyped_possible_sorts>(result).sorts().front();
713 }
714 return true;
715}
716
718{
719 //tries to sort out the types for if.
720 //If some of the parameters are Pos,Nat, or Int do upcasting
721
722 sort_expression_list Args=type.domain();
723 sort_expression Res=type.codomain();
724 if (Args.size()!=3)
725 {
726 return false;
727 }
728 Args=Args.tail();
729
730 if (!UnifyMinType(Res,Args.front(),Res))
731 {
732 return false;
733 }
734 Args=Args.tail();
735 if (!UnifyMinType(Res,Args.front(),Res))
736 {
737 return false;
738 }
739
740 result = function_sort({ sort_bool::bool_(), Res, Res }, Res);
741 return true;
742}
743
745{
746 //tries to sort out the types for ==, !=, <, <=, >= and >.
747 //If some of the parameters are Pos,Nat, or Int do upcasting.
748
749 sort_expression_list Args=type.domain();
750 if (Args.size()!=2)
751 {
752 return false;
753 }
754 sort_expression Arg1=Args.front();
755 Args=Args.tail();
756 sort_expression Arg2=Args.front();
757
758 sort_expression Arg;
759 if (!UnifyMinType(Arg1,Arg2,Arg))
760 {
761 return false;
762 }
763
764 result = function_sort({ Arg, Arg },sort_bool::bool_());
765 return true;
766}
767
769{
770 //tries to sort out the types for sqrt. There is only one option: sqrt:Nat->Nat.
771
772 const sort_expression_list& Args=type.domain();
773 if (Args.size()!=1)
774 {
775 return false;
776 }
777 const sort_expression& Arg=Args.front();
778
779 if (Arg==sort_nat::nat())
780 {
781 result=function_sort(Args,sort_nat::nat());
782 return true;
783 }
784 return false;
785}
786
787
788
790{
791 //tries to sort out the types of Cons operations (SxList(S)->List(S))
792 //If some of the parameters are Pos,Nat, or Int do upcasting.
793
794 sort_expression Res=type.codomain();
795 if (is_basic_sort(Res))
796 {
797 Res=UnwindType(Res);
798 }
799 if (!sort_list::is_list(UnwindType(Res)))
800 {
801 return false;
802 }
803 Res=down_cast<container_sort>(Res).element_sort();
804 sort_expression_list Args=type.domain();
805 if (Args.size()!=2)
806 {
807 return false;
808 }
809 sort_expression Arg1=Args.front();
810 Args=Args.tail();
811 sort_expression Arg2=Args.front();
812 if (is_basic_sort(Arg2))
813 {
814 Arg2=UnwindType(Arg2);
815 }
817 {
818 return false;
819 }
820 Arg2=down_cast<container_sort>(Arg2).element_sort();
821
822 sort_expression new_result;
823 if (!UnifyMinType(Res,Arg1,new_result))
824 {
825 return false;
826 }
827
828 if (!UnifyMinType(new_result,Arg2,Res))
829 {
830 return false;
831 }
832
834 return true;
835}
836
838{
839 //tries to sort out the types of Cons operations (SxList(S)->List(S))
840 //If some of the parameters are Pos,Nat, or Int do upcasting.
841
842 sort_expression Res=type.codomain();
843 if (is_basic_sort(Res))
844 {
845 Res=UnwindType(Res);
846 }
848 {
849 return false;
850 }
851 Res=down_cast<container_sort>(Res).element_sort();
852 sort_expression_list Args=type.domain();
853 if (Args.size()!=2)
854 {
855 return false;
856 }
857 sort_expression Arg1=Args.front();
858 if (is_basic_sort(Arg1))
859 {
860 Arg1=UnwindType(Arg1);
861 }
863 {
864 return false;
865 }
866 Arg1=down_cast<container_sort>(Arg1).element_sort();
867
868 Args=Args.tail();
869 sort_expression Arg2=Args.front();
870
871 sort_expression new_result;
872 if (!UnifyMinType(Res,Arg1,new_result))
873 {
874 return false;
875 }
876
877 if (!UnifyMinType(new_result,Arg2,Res))
878 {
879 return false;
880 }
881
883 return true;
884}
885
887{
888 //tries to sort out the types of Concat operations (List(S)xList(S)->List(S))
889 //If some of the parameters are Pos,Nat, or Int do upcasting.
890
891 sort_expression Res=type.codomain();
892 if (is_basic_sort(Res))
893 {
894 Res=UnwindType(Res);
895 }
897 {
898 return false;
899 }
900 Res=down_cast<container_sort>(Res).element_sort();
901 sort_expression_list Args=type.domain();
902 if (Args.size()!=2)
903 {
904 return false;
905 }
906
907 sort_expression Arg1=Args.front();
908 if (is_basic_sort(Arg1))
909 {
910 Arg1=UnwindType(Arg1);
911 }
913 {
914 return false;
915 }
916 Arg1=down_cast<container_sort>(Arg1).element_sort();
917
918 Args=Args.tail();
919
920 sort_expression Arg2=Args.front();
921 if (is_basic_sort(Arg2))
922 {
923 Arg2=UnwindType(Arg2);
924 }
926 {
927 return false;
928 }
929 Arg2=down_cast<container_sort>(Arg2).element_sort();
930
931 sort_expression new_result;
932 if (!UnifyMinType(Res,Arg1,new_result))
933 {
934 return false;
935 }
936
937 if (!UnifyMinType(new_result,Arg2,Res))
938 {
939 return false;
940 }
941
944 return true;
945}
946
948{
949 //tries to sort out the types of EltAt operations (List(S)xNat->S)
950 //If some of the parameters are Pos,Nat, or Int do upcasting.
951
952 sort_expression Res=type.codomain();
953 const sort_expression_list& Args=type.domain();
954 if (Args.size()!=2)
955 {
956 return false;
957 }
958
959 sort_expression Arg1=Args.front();
960 if (is_basic_sort(Arg1))
961 {
962 Arg1=UnwindType(Arg1);
963 }
965 {
966 return false;
967 }
968 Arg1=down_cast<container_sort>(Arg1).element_sort();
969
970 sort_expression new_result;
971 if (!UnifyMinType(Res,Arg1,new_result))
972 {
973 return false;
974 }
975 Res=new_result;
976
978 return true;
979}
980
982{
983 //tries to sort out the types of Cons operations (SxList(S)->List(S))
984 //If some of the parameters are Pos,Nat, or Int do upcasting.
985
986 sort_expression Res=type.codomain();
987 const sort_expression_list& Args=type.domain();
988 if (Args.size()!=1)
989 {
990 return false;
991 }
992 sort_expression Arg=Args.front();
993 if (is_basic_sort(Arg))
994 {
995 Arg=UnwindType(Arg);
996 }
997 if (!sort_list::is_list(Arg))
998 {
999 return false;
1000 }
1001 Arg=down_cast<container_sort>(Arg).element_sort();
1002
1003 sort_expression new_result;
1004 if (!UnifyMinType(Res,Arg,new_result))
1005 {
1006 return false;
1007 }
1008 Res=new_result;
1009
1011 return true;
1012}
1013
1015{
1016 //tries to sort out the types of Cons operations (SxList(S)->List(S))
1017 //If some of the parameters are Pos,Nat, or Int do upcasting.
1018
1019 sort_expression Res=type.codomain();
1020 if (is_basic_sort(Res))
1021 {
1022 Res=UnwindType(Res);
1023 }
1025 {
1026 return false;
1027 }
1028 Res=down_cast<container_sort>(Res).element_sort();
1029 const sort_expression_list& Args=type.domain();
1030 if (Args.size()!=1)
1031 {
1032 return false;
1033 }
1034 sort_expression Arg=Args.front();
1035 if (is_basic_sort(Arg))
1036 {
1037 Arg=UnwindType(Arg);
1038 }
1040 {
1041 return false;
1042 }
1043 Arg=down_cast<container_sort>(Arg).element_sort();
1044
1045 sort_expression new_result;
1046 if (!UnifyMinType(Res,Arg,new_result))
1047 {
1048 return false;
1049 }
1050 Res=new_result;
1051
1054 return true;
1055}
1056
1057//Sets
1059{
1060 //tries to sort out the types of Set2Bag (Set(S)->Bag(s))
1061 //If some of the parameters are Pos,Nat, or Int do upcasting.
1062
1063
1064 sort_expression Res=type.codomain();
1065 if (is_basic_sort(Res))
1066 {
1067 Res=UnwindType(Res);
1068 }
1070 {
1071 return false;
1072 }
1073 Res=down_cast<container_sort>(Res).element_sort();
1074
1075 const sort_expression_list& Args=type.domain();
1076 if (Args.size()!=1)
1077 {
1078 return false;
1079 }
1080
1081 sort_expression Arg=Args.front();
1082 if (is_basic_sort(Arg))
1083 {
1084 Arg=UnwindType(Arg);
1085 }
1087 {
1088 return false;
1089 }
1090 Arg=down_cast<container_sort>(Arg).element_sort();
1091
1092 sort_expression new_result;
1093 if (!UnifyMinType(Arg,Res,new_result))
1094 {
1095 return false;
1096 }
1097 Arg=new_result;
1098
1101 return true;
1102}
1103
1105{
1106 //tries to sort out the types of @set (Set(S)->Bool)->FSet(s))->Set(S)
1107 //If some of the parameters are Pos,Nat, or Int do upcasting.
1108 sort_expression Res=type.codomain();
1109 if (is_basic_sort(Res))
1110 {
1111 Res=UnwindType(Res);
1112 }
1113 if (!sort_set::is_set(Res))
1114 {
1115 return false;
1116 }
1117 Res=down_cast<container_sort>(Res).element_sort();
1118
1119 sort_expression_list Args=type.domain();
1120 if (Args.size()!=2)
1121 {
1122 return false;
1123 }
1124
1125 sort_expression Arg1=Args.front();
1126 if (is_basic_sort(Arg1))
1127 {
1128 Arg1=UnwindType(Arg1);
1129 }
1131 {
1132 return false;
1133 }
1134
1135 const sort_expression Arg12=down_cast<function_sort>(Arg1).codomain();
1136
1137 sort_expression new_result;
1138 if (!UnifyMinType(Arg12,sort_bool::bool_(),new_result))
1139 {
1140 return false;
1141 }
1142
1143 const sort_expression_list Arg11l=down_cast<function_sort>(Arg1).domain();
1144 if (Arg11l.size()!=1)
1145 {
1146 return false;
1147 }
1148 const sort_expression& Arg11=Arg11l.front();
1149
1150 if (!UnifyMinType(Arg11,Res,new_result))
1151 {
1152 return false;
1153 }
1154
1155
1156 Args.pop_front();
1157 sort_expression Arg2=Args.front();
1158 if (is_basic_sort(Arg2))
1159 {
1160 Arg2=UnwindType(Arg2);
1161 }
1162 if (!sort_fset::is_fset(Arg2))
1163 {
1164 return false;
1165 }
1166 sort_expression Arg21=down_cast<container_sort>(Arg2).element_sort();
1167
1168 sort_expression new_result2;
1169 if (!UnifyMinType(Arg21,new_result,new_result2))
1170 {
1171 return false;
1172 }
1173
1174 Arg1=function_sort({ new_result2 }, sort_bool::bool_());
1175 Arg2=sort_fset::fset(new_result2);
1176 result=function_sort({ Arg1, Arg2 }, sort_set::set_(new_result2));
1177 return true;
1178}
1179
1181{
1182 //tries to sort out the types of @false (S->Bool)
1183 //If some of the parameters are Pos,Nat, or Int do upcasting.
1184
1185 result=type;
1186 return true;
1187
1188
1189
1190}
1191
1193{
1194 //tries to sort out the types of @bag (Bag(S)->Bool)->FBag(s))->Bag(S)
1195 //If some of the parameters are Pos,Nat, or Int do upcasting.
1196
1197 sort_expression Res=type.codomain();
1198 if (is_basic_sort(Res))
1199 {
1200 Res=UnwindType(Res);
1201 }
1202 if (!sort_bag::is_bag(Res))
1203 {
1204 return false;
1205 }
1206 Res=down_cast<container_sort>(Res).element_sort();
1207
1208 sort_expression_list Args=type.domain();
1209 if (Args.size()!=2)
1210 {
1211 return false;
1212 }
1213
1214 sort_expression Arg1=Args.front();
1215 if (is_basic_sort(Arg1))
1216 {
1217 Arg1=UnwindType(Arg1);
1218 }
1220 {
1221 return false;
1222 }
1223
1224 const sort_expression Arg12=down_cast<function_sort>(Arg1).codomain();
1225
1226 sort_expression new_result;
1227 if (!UnifyMinType(Arg12,sort_nat::nat(),new_result))
1228 {
1229 return false;
1230 }
1231
1232 const sort_expression_list Arg11l=down_cast<function_sort>(Arg1).domain();
1233 if (Arg11l.size()!=1)
1234 {
1235 return false;
1236 }
1237 const sort_expression& Arg11=Arg11l.front();
1238
1239 if (!UnifyMinType(Arg11,Res,new_result))
1240 {
1241 return false;
1242 }
1243
1244
1245 Args.pop_front();
1246 sort_expression Arg2=Args.front();
1247 if (is_basic_sort(Arg2))
1248 {
1249 Arg2=UnwindType(Arg2);
1250 }
1251 if (!sort_fbag::is_fbag(Arg2))
1252 {
1253 return false;
1254 }
1255 sort_expression Arg21=down_cast<container_sort>(Arg2).element_sort();
1256
1257 sort_expression new_result2;
1258 if (!UnifyMinType(Arg21,new_result,new_result2))
1259 {
1260 return false;
1261 }
1262
1263 Arg1=function_sort(sort_expression_list({ new_result2 }),sort_nat::nat());
1264 Arg2=sort_fbag::fbag(new_result2);
1265 result=function_sort(sort_expression_list({ Arg1, Arg2 }), sort_bag::bag(new_result2));
1266 return true;
1267}
1268
1269
1271{
1272 //tries to sort out the type of EltIn (SxList(S)->Bool or SxSet(S)->Bool or SxBag(S)->Bool)
1273 //If some of the parameters are Pos,Nat, or Int do upcasting.
1274
1275 sort_expression_list Args=type.domain();
1276 if (Args.size()!=2)
1277 {
1278 return false;
1279 }
1280
1281 sort_expression Arg1=Args.front();
1282
1283 Args=Args.tail();
1284 sort_expression Arg2=Args.front();
1285 if (is_basic_sort(Arg2))
1286 {
1287 Arg2=UnwindType(Arg2);
1288 }
1289 if (!is_container_sort(Arg2))
1290 {
1291 return false;
1292 }
1293 sort_expression Arg2s=down_cast<container_sort>(Arg2).element_sort();
1294 sort_expression Arg;
1295 if (!UnifyMinType(Arg1,Arg2s,Arg))
1296 {
1297 return false;
1298 }
1299
1300 result=function_sort({ Arg, container_sort(down_cast<const container_sort>(Arg2).container_name(),Arg)},
1302 return true;
1303}
1304
1306{
1307 sort_expression_list Args=type.domain();
1308 if (Args.size()!=2)
1309 {
1310 return false;
1311 }
1312
1313 sort_expression Arg1=Args.front();
1314
1315 Args=Args.tail();
1316 sort_expression Arg2=Args.front();
1317 if (is_basic_sort(Arg2))
1318 {
1319 Arg2=UnwindType(Arg2);
1320 }
1321 if (!is_container_sort(Arg2))
1322 {
1323 return false;
1324 }
1325 sort_expression Arg2s=down_cast<container_sort>(Arg2).element_sort();
1326 sort_expression Arg;
1327 if (!UnifyMinType(Arg1,Arg2s,Arg))
1328 {
1329 return false;
1330 }
1331
1332 const sort_expression fset_type=container_sort(down_cast<const container_sort>(Arg2).container_name(),Arg);
1333 result=function_sort({ Arg, fset_type },fset_type);
1334 return true;
1335}
1336
1338{
1339 sort_expression_list Args=type.domain();
1340 if (Args.size()!=3)
1341 {
1342 return false;
1343 }
1344
1345 sort_expression Arg1=Args.front();
1346
1347 Args=Args.tail();
1348 sort_expression Arg2=Args.front();
1349 if (is_basic_sort(Arg2))
1350 {
1351 Arg2=UnwindType(Arg2);
1352 }
1353 Args=Args.tail();
1354 sort_expression Arg3=Args.front();
1355 if (is_basic_sort(Arg3))
1356 {
1357 Arg3=UnwindType(Arg3);
1358 }
1359
1360 sort_expression Arg2r;
1361 if (!UnifyMinType(Arg2,sort_nat::nat(),Arg2r))
1362 {
1363 return false;
1364 }
1365
1366 if (!is_container_sort(Arg3))
1367 {
1368 return false;
1369 }
1370
1371 sort_expression Arg3s=down_cast<container_sort>(Arg3).element_sort();
1372 sort_expression Arg3r;
1373 if (!UnifyMinType(Arg1,Arg3s,Arg3r))
1374 {
1375 return false;
1376 }
1377
1378
1379 const sort_expression fbag_type=container_sort(down_cast<const container_sort>(Arg3).container_name(),Arg3r);
1380 result=function_sort({ Arg3r, Arg2r, fbag_type },fbag_type);
1381 return true;
1382}
1383
1385{
1386 return UnifyMinType(container_sort(Arg1).element_sort(), container_sort(Arg2).element_sort(), result);
1387}
1388
1390{
1391 //tries to sort out the types of Set or Bag Union, Diff or Intersect
1392 //operations (Set(S)xSet(S)->Set(S)). It can also be that this operation is
1393 //performed on numbers. In this case we do nothing.
1394 //If some of the parameters are Pos,Nat, or Int do upcasting.
1395 sort_expression Res=type.codomain();
1396 if (is_basic_sort(Res))
1397 {
1398 Res=UnwindType(Res);
1399 }
1401 {
1402 result=type;
1403 return true;
1404 }
1407 {
1408 return false;
1409 }
1410 sort_expression_list Args=type.domain();
1411 if (Args.size()!=2)
1412 {
1413 return false;
1414 }
1415
1416 sort_expression Arg1=Args.front();
1417 if (is_basic_sort(Arg1))
1418 {
1419 Arg1=UnwindType(Arg1);
1420 }
1422 {
1423 result=type;
1424 return true;
1425 }
1428 {
1429 return false;
1430 }
1431
1432 Args=Args.tail();
1433
1434 sort_expression Arg2=Args.front();
1435 if (is_basic_sort(Arg2))
1436 {
1437 Arg2=UnwindType(Arg2);
1438 }
1439 if (detail::IsNumericType(Arg2))
1440 {
1441 result=type;
1442 return true;
1443 }
1446 {
1447 return false;
1448 }
1449
1450 sort_expression temp_result;
1451
1452 // If one argument is a FSet/FBag and the other one a Set/Bag, allow a finite Set/Bag result if:
1453 // - The element types match.
1454 // - The result type is finitely representable.
1455 // Otherwise, lift it to match the Bag/Set.
1457 {
1458 if (sort_set::intersection_name() == data_term_name)
1459 {
1460 if (!UnifyElementSort(Arg1, Arg2, temp_result))
1461 {
1462 return false;
1463 }
1464
1465 Arg1 = sort_set::set_(temp_result);
1466 Arg2 = sort_fset::fset(temp_result);
1467 result = function_sort({ Arg1, Arg2 }, Arg2);
1468 return true;
1469 }
1470 Arg2=sort_set::set_(container_sort(Arg2).element_sort());
1471 }
1472
1474 {
1475 if (sort_set::intersection_name() == data_term_name)
1476 {
1477 if (!UnifyElementSort(Arg1, Arg2, temp_result))
1478 {
1479 return false;
1480 }
1481
1482 Arg1 = sort_bag::bag(temp_result);
1483 Arg2 = sort_fbag::fbag(temp_result);
1484 result = function_sort({ Arg1, Arg2 }, Arg2);
1485 return true;
1486 }
1487 Arg2=sort_bag::bag(container_sort(Arg2).element_sort());
1488 }
1489
1491 {
1492 if (sort_set::union_name() != data_term_name)
1493 {
1494 if (!UnifyElementSort(Arg1, Arg2, temp_result))
1495 {
1496 return false;
1497 }
1498
1499 Arg1 = sort_fset::fset(temp_result);
1500 Arg2 = sort_set::set_(temp_result);
1501 result = function_sort({ Arg1, Arg2 }, Arg1);
1502 return true;
1503 }
1504 Arg1=sort_set::set_(container_sort(Arg1).element_sort());
1505 }
1506
1508 {
1509 if (sort_set::union_name() != data_term_name)
1510 {
1511 if (!UnifyElementSort(Arg1, Arg2, temp_result))
1512 {
1513 return false;
1514 }
1515
1516 Arg1 = sort_fbag::fbag(temp_result);
1517 Arg2 = sort_bag::bag(temp_result);
1518 result = function_sort({ Arg1, Arg2 }, Arg1);
1519 return true;
1520 }
1521 Arg1=sort_bag::bag(container_sort(Arg1).element_sort());
1522 }
1523
1524 if (!UnifyMinType(Res,Arg1,temp_result))
1525 {
1526 return false;
1527 }
1528
1529 if (!UnifyMinType(temp_result,Arg2,Res))
1530 {
1531 return false;
1532 }
1533
1534 result=function_sort({ Res,Res },Res);
1535 return true;
1536}
1537
1539{
1540 //tries to sort out the types of SetCompl operation (Set(S)->Set(S))
1541 //If some of the parameters are Pos,Nat, or Int do upcasting.
1542
1543 sort_expression Res=type.codomain();
1544 if (is_basic_sort(Res))
1545 {
1546 Res=UnwindType(Res);
1547 }
1548 // if (detail::IsNumericType(Res))
1549 if (Res==sort_bool::bool_())
1550 {
1551 result=type;
1552 return true;
1553 }
1554
1555 const sort_expression_list& Args=type.domain();
1556 if (Args.size()!=1)
1557 {
1558 return false;
1559 }
1560
1561 sort_expression Arg=Args.front();
1562 if (is_basic_sort(Arg))
1563 {
1564 Arg=UnwindType(Arg);
1565 }
1566 // if (detail::IsNumericType(Arg))
1567 if (Arg==sort_bool::bool_())
1568 {
1569 result=type;
1570 return true;
1571 }
1573 {
1574 return false;
1575 }
1576 Res=down_cast<container_sort>(Res).element_sort();
1578 {
1579 return false;
1580 }
1581 Arg=down_cast<container_sort>(Arg).element_sort();
1582
1583 sort_expression temp_result;
1584 if (!UnifyMinType(Res,Arg,temp_result))
1585 {
1586 return false;
1587 }
1588 Res=temp_result;
1589
1591 return true;
1592}
1593
1594//Bags
1596{
1597 //tries to sort out the types of Bag2Set (Bag(S)->Set(S))
1598 //If some of the parameters are Pos,Nat, or Int do upcasting.
1599
1600
1601 sort_expression Res=type.codomain();
1602 if (is_basic_sort(Res))
1603 {
1604 Res=UnwindType(Res);
1605 }
1607 {
1608 return false;
1609 }
1610 Res=down_cast<container_sort>(Res).element_sort();
1611
1612 const sort_expression_list& Args=type.domain();
1613 if (Args.size()!=1)
1614 {
1615 return false;
1616 }
1617
1618 sort_expression Arg=Args.front();
1619 if (is_basic_sort(Arg))
1620 {
1621 Arg=UnwindType(Arg);
1622 }
1624 {
1625 return false;
1626 }
1627 Arg=down_cast<container_sort>(Arg).element_sort();
1628
1629 sort_expression temp_result;
1630 if (!UnifyMinType(Arg,Res,temp_result))
1631 {
1632 return false;
1633 }
1634 Arg=temp_result;
1635
1637 return true;
1638}
1639
1641{
1642 //tries to sort out the types of BagCount (SxBag(S)->Nat)
1643 //If some of the parameters are Pos,Nat, or Int do upcasting.
1644
1645 //If the second argument is not a Bag, don't match
1646
1647 if (!is_function_sort(type))
1648 {
1649 result=type;
1650 return true;
1651 }
1652 sort_expression_list Args=type.domain();
1653 if (!(Args.size()==2))
1654 {
1655 result=type;
1656 return true;
1657 }
1658
1659 sort_expression Arg1=Args.front();
1660
1661 Args=Args.tail();
1662 sort_expression Arg2=Args.front();
1663 if (is_basic_sort(Arg2))
1664 {
1665 Arg2=UnwindType(Arg2);
1666 }
1668 {
1669 result=type;
1670 return true;
1671 }
1672 Arg2=down_cast<container_sort>(Arg2).element_sort();
1673
1674 sort_expression Arg;
1675 if (!UnifyMinType(Arg1,Arg2,Arg))
1676 {
1677 return false;
1678 }
1679
1681 return true;
1682}
1683
1684
1686{
1687 //tries to sort out the types of FuncUpdate ((A->B)xAxB->(A->B))
1688 //If some of the parameters are Pos,Nat, or Int do upcasting.
1689
1690 sort_expression_list Args=type.domain();
1691 if (Args.size()!=3)
1692 {
1693 return false;
1694 }
1695 function_sort Arg1=down_cast<function_sort>(Args.front());
1696 Args=Args.tail();
1697 sort_expression Arg2=Args.front();
1698 Args=Args.tail();
1699 sort_expression Arg3=Args.front();
1700 const sort_expression& Res=type.codomain();
1701 if (!is_function_sort(Res))
1702 {
1703 return false;
1704 }
1705
1706 sort_expression temp_result;
1707 if (!UnifyMinType(Arg1,Res,temp_result))
1708 {
1709 return false;
1710 }
1711 Arg1 = atermpp::down_cast<function_sort>(UnwindType(temp_result));
1712
1713 // determine A and B from Arg1:
1714 sort_expression_list LA=Arg1.domain();
1715 if (LA.size()!=1)
1716 {
1717 return false;
1718 }
1719 const sort_expression& A=LA.front();
1720 sort_expression B=Arg1.codomain();
1721
1722 if (!UnifyMinType(A,Arg2,temp_result))
1723 {
1724 return false;
1725 }
1726 if (!UnifyMinType(B,Arg3,temp_result))
1727 {
1728 return false;
1729 }
1730
1731 result=function_sort(sort_expression_list({ Arg1,A,B}) ,Arg1);
1732 return true;
1733}
1734
1735
1736
1738{
1739 // if Type1 is convertible into Type2 or vice versa, the most general
1740 // of these types are returned in result. If no conversion is possible false is returned
1741 // and result is not changed. Conversions only take place between numerical types
1742 if (EqTypesA(Type1,Type2))
1743 {
1744 result=Type1;
1745 return true;
1746 }
1748 {
1749 result=Type2;
1750 return true;
1751 }
1753 {
1754 result=Type1;
1755 return true;
1756 }
1757 if (EqTypesA(Type1,sort_real::real_()))
1758 {
1759 if (EqTypesA(Type2,sort_int::int_()))
1760 {
1761 result=Type1;
1762 return true;
1763 }
1764 if (EqTypesA(Type2,sort_nat::nat()))
1765 {
1766 result=Type1;
1767 return true;
1768 }
1769 if (EqTypesA(Type2,sort_pos::pos()))
1770 {
1771 result=Type1;
1772 return true;
1773 }
1774 return false;
1775 }
1776 if (EqTypesA(Type1,sort_int::int_()))
1777 {
1778 if (EqTypesA(Type2,sort_real::real_()))
1779 {
1780 result=Type2;
1781 return true;
1782 }
1783 if (EqTypesA(Type2,sort_nat::nat()))
1784 {
1785 result=Type1;
1786 return true;
1787 }
1788 if (EqTypesA(Type2,sort_pos::pos()))
1789 {
1790 result=Type1;
1791 return true;
1792 }
1793 return false;
1794 }
1795 if (EqTypesA(Type1,sort_nat::nat()))
1796 {
1797 if (EqTypesA(Type2,sort_real::real_()))
1798 {
1799 result=Type2;
1800 return true;
1801 }
1802 if (EqTypesA(Type2,sort_int::int_()))
1803 {
1804 result=Type2;
1805 return true;
1806 }
1807 if (EqTypesA(Type2,sort_pos::pos()))
1808 {
1809 result=Type1;
1810 return true;
1811 }
1812 return false;
1813 }
1814 if (EqTypesA(Type1,sort_pos::pos()))
1815 {
1816 if (EqTypesA(Type2,sort_real::real_()))
1817 {
1818 result=Type2;
1819 return true;
1820 }
1821 if (EqTypesA(Type2,sort_int::int_()))
1822 {
1823 result=Type2;
1824 return true;
1825 }
1826 if (EqTypesA(Type2,sort_nat::nat()))
1827 {
1828 result=Type2;
1829 return true;
1830 }
1831 return false;
1832 }
1833 return false;
1834}
1835
1837{
1839 for(sort_expression_list::const_iterator i=type_list.begin(); i!=type_list.end(); ++i)
1840 {
1841 result.push_back(ExpandNumTypesUp(*i));
1842 }
1843 return sort_expression_list(result.begin(),result.end());
1844}
1845
1847{
1848 //Expand Type to possible bigger types.
1850 {
1851 return Type;
1852 }
1853 if (EqTypesA(sort_pos::pos(),Type))
1854 {
1856 }
1857 if (EqTypesA(sort_nat::nat(),Type))
1858 {
1860 }
1861 if (EqTypesA(sort_int::int_(),Type))
1862 {
1864 }
1865 if (is_basic_sort(Type))
1866 {
1867 return Type;
1868 }
1869 if (is_container_sort(Type))
1870 {
1871 const container_sort& s=down_cast<container_sort>(Type);
1872 const container_type& ConsType = s.container_name();
1873 if (is_list_container(ConsType))
1874 {
1875 return container_sort(s.container_name(),ExpandNumTypesUp(s.element_sort()));
1876 }
1877
1878 if (is_set_container(ConsType))
1879 {
1880 return container_sort(s.container_name(),ExpandNumTypesUp(s.element_sort()));
1881 }
1882
1883 if (is_bag_container(ConsType))
1884 {
1885 return container_sort(s.container_name(),ExpandNumTypesUp(s.element_sort()));
1886 }
1887
1888 if (is_fset_container(ConsType))
1889 {
1890 const sort_expression expanded_sorts=ExpandNumTypesUp(s.element_sort());
1892 container_sort(s.container_name(),expanded_sorts),
1893 container_sort(set_container(),expanded_sorts) }));
1894 }
1895
1896 if (is_fbag_container(ConsType))
1897 {
1898 const sort_expression expanded_sorts=ExpandNumTypesUp(s.element_sort());
1900 container_sort(s.container_name(),expanded_sorts),
1901 container_sort(bag_container(),expanded_sorts) }));
1902 }
1903 }
1904
1905 if (is_structured_sort(Type))
1906 {
1907 return Type;
1908 }
1909
1910 if (is_function_sort(Type))
1911 {
1912 const function_sort& t=down_cast<const function_sort>(Type);
1913 //the argument types, and if the resulting type is SortArrow -- recursively
1914 sort_expression_list NewTypeList;
1915 for (sort_expression_list TypeList=t.domain(); !TypeList.empty(); TypeList=TypeList.tail())
1916 {
1917 NewTypeList.push_front(ExpandNumTypesUp(UnwindType(TypeList.front())));
1918 }
1919 const sort_expression& ResultType=t.codomain();
1920 if (!is_function_sort(ResultType))
1921 {
1922 return function_sort(reverse(NewTypeList),ResultType);
1923 }
1924 else
1925 {
1926 return function_sort(reverse(NewTypeList),ExpandNumTypesUp(UnwindType(ResultType)));
1927 }
1928 }
1929
1930 return Type;
1931}
1932
1934{
1935 // Expand Numeric types down
1936 if (data::is_untyped_sort(Type))
1937 {
1938 return Type;
1939 }
1940 if (is_basic_sort(Type))
1941 {
1942 Type=UnwindType(Type);
1943 }
1944
1945 bool function=false;
1947 if (is_function_sort(Type))
1948 {
1949 const function_sort& fs=down_cast<const function_sort>(Type);
1950 function=true;
1951 Args=fs.domain();
1952 Type=fs.codomain();
1953 }
1954
1955 if (EqTypesA(sort_real::real_(),Type))
1956 {
1958 }
1959 if (EqTypesA(sort_int::int_(),Type))
1960 {
1962 }
1963 if (EqTypesA(sort_nat::nat(),Type))
1964 {
1966 }
1967 if (is_container_sort(Type))
1968 {
1969 const container_sort& s=down_cast<container_sort>(Type);
1970 const container_type& ConsType = s.container_name();
1971 if (is_list_container(ConsType))
1972 {
1973 Type=container_sort(s.container_name(),ExpandNumTypesDown(s.element_sort()));
1974 }
1975
1976 if (is_fset_container(ConsType))
1977 {
1978 Type=container_sort(s.container_name(),ExpandNumTypesDown(s.element_sort()));
1979 }
1980
1981 if (is_fbag_container(ConsType))
1982 {
1983 Type=container_sort(s.container_name(),ExpandNumTypesDown(s.element_sort()));
1984 }
1985
1986 if (is_set_container(ConsType))
1987 {
1988 const sort_expression shrinked_sorts=ExpandNumTypesDown(s.element_sort());
1990 container_sort(s.container_name(),shrinked_sorts),
1991 container_sort(set_container(),shrinked_sorts) } ));
1992 }
1993
1994 if (is_bag_container(ConsType))
1995 {
1996 const sort_expression shrinked_sorts=ExpandNumTypesDown(s.element_sort());
1998 container_sort(s.container_name(),shrinked_sorts),
1999 container_sort(bag_container(),shrinked_sorts) } ));
2000 }
2001 }
2002
2003 return (function)?function_sort(Args,Type):Type;
2004}
2005
2006
2008{
2009 for (const sort_expression& s: Types)
2010 {
2011 if (EqTypesA(Type,s))
2012 {
2013 return true;
2014 }
2015 }
2016 return false;
2017}
2018
2020{
2021 if (Type1==Type2)
2022 {
2023 return true;
2024 }
2025
2026 return UnwindType(Type1)==UnwindType(Type2);
2027}
2028
2030{
2031 for (const sort_expression_list&l: Types)
2032 {
2033 if (EqTypesL(Type,l))
2034 {
2035 return true;
2036 }
2037 }
2038 return false;
2039}
2040
2042{
2043 if (Type1==Type2)
2044 {
2045 return true;
2046 }
2047 if (Type1.size()!=Type2.size())
2048 {
2049 return false;
2050 }
2052 for (const sort_expression& s: Type2)
2053 {
2054 if (!EqTypesA(*i,s))
2055 {
2056 return false;
2057 }
2058 ++i;
2059 }
2060 return true;
2061}
2062
2064{
2065 if (is_variable(d))
2066 {
2067 variable v(d);
2068 // Set the type to one option in possible sorts, if there are more options.
2069 const sort_expression new_type=detail::replace_possible_sorts(proposed_type);
2070 v=variable(v.name(),new_type);
2071 return new_type;
2072 }
2073
2074 assert(proposed_type.defined());
2075
2076 sort_expression Type=proposed_type;
2077 // If d is not a variable it is an untyped name, or a function symbol.
2079 atermpp::down_cast<const untyped_identifier>(d).name():
2080 (down_cast<const data::function_symbol>(d).name());
2081
2082 if (data::detail::if_symbol::is_symbol(data_term_name))
2083 {
2084 sort_expression NewType;
2085 if (!MatchIf(atermpp::down_cast<function_sort>(Type), NewType))
2086 {
2087 throw mcrl2::runtime_error("The function if has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2088 }
2089 Type=NewType;
2090 }
2091
2092 if (data::detail::equal_symbol::is_symbol(data_term_name)
2093 || data::detail::not_equal_symbol::is_symbol(data_term_name)
2094 || data::detail::less_symbol::is_symbol(data_term_name)
2095 || data::detail::less_equal_symbol::is_symbol(data_term_name)
2096 || data::detail::greater_symbol::is_symbol(data_term_name)
2097 || data::detail::greater_equal_symbol::is_symbol(data_term_name)
2098 )
2099 {
2100 sort_expression NewType;
2101 if (!MatchEqNeqComparison(atermpp::down_cast<function_sort>(Type), NewType))
2102 {
2103 throw mcrl2::runtime_error("The function " + core::pp(data_term_name) + " has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2104 }
2105 Type=NewType;
2106 }
2107
2108 if (sort_nat::sqrt_name()==data_term_name)
2109 {
2110 sort_expression NewType;
2111 if (!MatchSqrt(atermpp::down_cast<function_sort>(Type), NewType))
2112 {
2113 throw mcrl2::runtime_error("The function sqrt has an incorrect argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2114 }
2115 Type=NewType;
2116 }
2117
2118 if (sort_list::cons_name()==data_term_name)
2119 {
2120 sort_expression NewType;
2121 if (!MatchListOpCons(atermpp::down_cast<function_sort>(Type), NewType))
2122 {
2123 throw mcrl2::runtime_error("The function |> has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2124 }
2125 Type=NewType;
2126 }
2127
2128 if (sort_list::snoc_name()==data_term_name)
2129 {
2130 sort_expression NewType;
2131 if (!MatchListOpSnoc(atermpp::down_cast<function_sort>(Type), NewType))
2132 {
2133 throw mcrl2::runtime_error("The function <| has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2134 }
2135 Type=NewType;
2136 }
2137
2138 if (sort_list::concat_name()==data_term_name)
2139 {
2140 sort_expression NewType;
2141 if (!MatchListOpConcat(atermpp::down_cast<function_sort>(Type), NewType))
2142 {
2143 throw mcrl2::runtime_error("The function ++ has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2144 }
2145 Type=NewType;
2146 }
2147
2148 if (sort_list::element_at_name()==data_term_name)
2149 {
2150 sort_expression NewType;
2151 if (!MatchListOpEltAt(atermpp::down_cast<function_sort>(Type), NewType))
2152 {
2153 throw mcrl2::runtime_error("The function @ has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2154 }
2155 Type=NewType;
2156 }
2157
2158 if (sort_list::head_name()==data_term_name||
2159 sort_list::rhead_name()==data_term_name)
2160 {
2161
2162 sort_expression NewType;
2163 if (!MatchListOpHead(atermpp::down_cast<function_sort>(Type), NewType))
2164 {
2165 throw mcrl2::runtime_error("The function {R,L}head has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2166 }
2167 Type=NewType;
2168 }
2169
2170 if (sort_list::tail_name()==data_term_name||
2171 sort_list::rtail_name()==data_term_name)
2172 {
2173 sort_expression NewType;
2174 if (!MatchListOpTail(atermpp::down_cast<function_sort>(Type), NewType))
2175 {
2176 throw mcrl2::runtime_error("The function {R,L}tail has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2177 }
2178 Type=NewType;
2179 }
2180
2181 if (sort_bag::set2bag_name()==data_term_name)
2182 {
2183 sort_expression NewType;
2184 if (!MatchSetOpSet2Bag(atermpp::down_cast<function_sort>(Type), NewType))
2185 {
2186 throw mcrl2::runtime_error("The function Set2Bag has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2187 }
2188 Type=NewType;
2189 }
2190
2191 if (sort_list::in_name()==data_term_name)
2192 {
2193 sort_expression NewType;
2194 if (!MatchListSetBagOpIn(atermpp::down_cast<function_sort>(Type), NewType))
2195 {
2196 throw mcrl2::runtime_error("The function {List,Set,Bag}In has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2197 }
2198 Type=NewType;
2199 }
2200
2201 if (sort_set::union_name()==data_term_name||
2202 sort_set::difference_name()==data_term_name||
2203 sort_set::intersection_name()==data_term_name)
2204 {
2205 sort_expression NewType;
2206 if (!MatchSetBagOpUnionDiffIntersect(data_term_name, atermpp::down_cast<function_sort>(Type), NewType))
2207 {
2208 throw mcrl2::runtime_error("The function {Set,Bag}{Union,Difference,Intersect} has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2209 }
2210 Type=NewType;
2211 }
2212
2213
2214 if (sort_fset::insert_name()==data_term_name)
2215 {
2216 sort_expression NewType;
2217 if (!match_fset_insert(atermpp::down_cast<function_sort>(Type), NewType))
2218 {
2219 throw mcrl2::runtime_error("Set enumeration has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2220 }
2221 Type=NewType;
2222 }
2223
2224 if (sort_fbag::cinsert_name()==data_term_name)
2225 {
2226 sort_expression NewType;
2227 if (!match_fbag_cinsert(atermpp::down_cast<function_sort>(Type), NewType))
2228 {
2229 throw mcrl2::runtime_error("Bag enumeration has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2230 }
2231 Type=NewType;
2232 }
2233
2234
2235
2236 if (sort_set::complement_name()==data_term_name)
2237 {
2238 sort_expression NewType;
2239 if (!MatchSetOpSetCompl(atermpp::down_cast<function_sort>(Type), NewType))
2240 {
2241 throw mcrl2::runtime_error("The function SetCompl has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2242 }
2243 Type=NewType;
2244 }
2245
2246 if (sort_bag::bag2set_name()==data_term_name)
2247 {
2248 sort_expression NewType;
2249 if (!MatchBagOpBag2Set(atermpp::down_cast<function_sort>(Type), NewType))
2250 {
2251 throw mcrl2::runtime_error("The function Bag2Set has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2252 }
2253 Type=NewType;
2254 }
2255
2256 if (sort_bag::count_name()==data_term_name)
2257 {
2258 sort_expression NewType;
2259 if (!MatchBagOpBagCount(atermpp::down_cast<function_sort>(Type), NewType))
2260 {
2261 throw mcrl2::runtime_error("The function BagCount has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2262 }
2263 Type=NewType;
2264 }
2265
2266
2267 if (data::function_update_name()==data_term_name)
2268 {
2269 sort_expression NewType;
2270 if (!MatchFuncUpdate(atermpp::down_cast<function_sort>(Type), NewType))
2271 {
2272 throw mcrl2::runtime_error("Function update has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2273 }
2274 Type=NewType;
2275 }
2276
2277 if (sort_set::constructor_name()==data_term_name)
2278 {
2279 sort_expression NewType;
2280 if (!MatchSetConstructor(atermpp::down_cast<function_sort>(Type), NewType))
2281 {
2282 throw mcrl2::runtime_error("Set constructor has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2283 }
2284 Type=NewType;
2285 }
2286
2287
2288 if (sort_bag::constructor_name()==data_term_name)
2289 {
2290 sort_expression NewType;
2291 if (!MatchBagConstructor(atermpp::down_cast<function_sort>(Type), NewType))
2292 {
2293 throw mcrl2::runtime_error("Bag constructor has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2294 }
2295 Type=NewType;
2296 }
2297
2298 if (sort_set::false_function_name()==data_term_name)
2299 {
2300 sort_expression NewType;
2301 if (!MatchFalseFunction(atermpp::down_cast<function_sort>(Type), NewType))
2302 {
2303 throw mcrl2::runtime_error("Bag constructor has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2304 }
2305 Type=NewType;
2306 }
2307
2308 if (sort_bag::zero_function_name()==data_term_name)
2309 {
2310 sort_expression NewType;
2311 if (!MatchBagConstructor(atermpp::down_cast<function_sort>(Type), NewType))
2312 {
2313 throw mcrl2::runtime_error("Bag constructor has incompatible argument types " + data::pp(Type) + " (while typechecking " + data::pp(d) + ").");
2314 }
2315 Type=NewType;
2316 }
2317
2318 return Type;
2319}
2320
2321
2322
2324 const detail::variable_context& DeclaredVars,
2325 data_expression& DataTerm,
2326 sort_expression PosType,
2327 const bool strictly_ambiguous,
2328 const std::size_t nFactPars,
2329 const bool warn_upcasting,
2330 const bool print_cast_error) const
2331{
2332 // std::string::npos for nFactPars means the number of arguments is not known.
2334 {
2335 core::identifier_string Name=data::is_untyped_identifier(DataTerm)?down_cast<const untyped_identifier>(DataTerm).name():
2336 atermpp::down_cast<const function_symbol>(DataTerm).name();
2337
2338 bool variable_=false;
2339 bool TypeADefined=false;
2340 sort_expression TypeA;
2341 std::map<core::identifier_string,sort_expression>::const_iterator i=DeclaredVars.context().find(Name);
2342
2343 if (i!=DeclaredVars.context().end())
2344 {
2345 TypeA=normalize_sorts(i->second,get_sort_specification());
2346 TypeADefined=true;
2347 const sort_expression Type1(UnwindType(TypeA));
2348 if (is_function_sort(Type1)?(function_sort(Type1).domain().size()==nFactPars):(nFactPars==0))
2349 {
2350 variable_=true;
2351
2352 //Add to free variables list
2353 }
2354 else
2355 {
2356 TypeADefined=false;
2357 }
2358 }
2359
2360 sort_expression_list ParList;
2361 if (nFactPars==0)
2362 {
2363 std::map<core::identifier_string,sort_expression>::const_iterator i=DeclaredVars.context().find(Name);
2364 if (i!=DeclaredVars.context().end())
2365 {
2366 TypeA=normalize_sorts(i->second,get_sort_specification());
2367 TypeADefined=true;
2368 sort_expression temp;
2369 if (!TypeMatchA(TypeA,PosType,temp))
2370 {
2371 throw mcrl2::runtime_error("The type " + data::pp(TypeA) + " of variable " + core::pp(Name)
2372 + " is incompatible with " + data::pp(PosType) + " (typechecking " + data::pp(DataTerm) + ").");
2373 }
2374 DataTerm=variable(Name,TypeA);
2375 return TypeA;
2376 }
2377 else
2378 {
2379 std::map<core::identifier_string,sort_expression>::const_iterator i=user_constants.find(Name);
2380 if (i!=user_constants.end())
2381 {
2382 TypeA=i->second;
2383 TypeADefined=true;
2384 sort_expression temp;
2385 if (!TypeMatchA(TypeA,PosType,temp))
2386 {
2387 throw mcrl2::runtime_error("The type " + data::pp(TypeA) + " of constant " + core::pp(Name)
2388 + " is incompatible with " + data::pp(PosType) + " (typechecking " + data::pp(DataTerm) + ").");
2389 }
2390 DataTerm=data::function_symbol(Name,TypeA);
2391 return TypeA;
2392 }
2393 else
2394 {
2395 std::map<core::identifier_string,sort_expression_list>::const_iterator j=system_constants.find(Name);
2396
2397 if (j!=system_constants.end())
2398 {
2399 ParList=j->second;
2400 if (ParList.size()==1)
2401 {
2402 sort_expression Type1=ParList.front();
2403 DataTerm=function_symbol(Name,Type1);
2404 return Type1;
2405 }
2406 else
2407 {
2409 throw mcrl2::runtime_error("Ambiguous system constant " + core::pp(Name) + ".");
2410 }
2411 }
2412 else
2413 {
2414 throw mcrl2::runtime_error("Unknown constant " + core::pp(Name) + ".");
2415 }
2416 }
2417 }
2418 }
2419
2420 if (TypeADefined)
2421 {
2422 ParList = sort_expression_list({ UnwindType(TypeA) });
2423 }
2424 else
2425 {
2426 const std::map <core::identifier_string,sort_expression_list>::const_iterator j_context=user_functions.find(Name);
2427 const std::map <core::identifier_string,sort_expression_list>::const_iterator j_gssystem=system_functions.find(Name);
2428
2429 if (j_context==user_functions.end())
2430 {
2431 if (j_gssystem!=system_functions.end())
2432 {
2433 ParList=j_gssystem->second; // The function only occurs in the system.
2434 }
2435 else // None are defined.
2436 {
2437 if (nFactPars!=std::string::npos)
2438 {
2439 throw mcrl2::runtime_error("Unknown operation " + core::pp(Name) + " with " + std::to_string(nFactPars) + " parameter" + ((nFactPars != 1)?"s.":"."));
2440 }
2441 else
2442 {
2443 throw mcrl2::runtime_error("Unknown operation " + core::pp(Name) + ".");
2444 }
2445 }
2446 }
2447 else if (j_gssystem==system_functions.end())
2448 {
2449 ParList=j_context->second; // only the context sorts are defined.
2450 }
2451 else // Both are defined.
2452 {
2453 ParList=j_gssystem->second+j_context->second;
2454 }
2455 }
2456
2457 sort_expression_list CandidateParList=ParList;
2458
2459 {
2460 // filter ParList keeping only functions A_0#...#A_nFactPars->A
2461 sort_expression_list NewParList;
2462 if (nFactPars!=std::string::npos)
2463 {
2464 for (; !ParList.empty(); ParList=ParList.tail())
2465 {
2466 const sort_expression& Par=ParList.front();
2467 if (!is_function_sort(Par))
2468 {
2469 continue;
2470 }
2471 if (down_cast<function_sort>(Par).domain().size()!=nFactPars)
2472 {
2473 continue;
2474 }
2475 NewParList.push_front(Par);
2476 }
2477 ParList=reverse(NewParList);
2478 }
2479
2480 if (!ParList.empty())
2481 {
2482 CandidateParList=ParList;
2483 }
2484
2485 // filter ParList keeping only functions of the right type
2486 sort_expression_list BackupParList=ParList;
2487 NewParList=sort_expression_list();
2488 for (; !ParList.empty(); ParList=ParList.tail())
2489 {
2490 const sort_expression& Par=ParList.front();
2491 try
2492 {
2493 PosType=determine_allowed_type(DataTerm, PosType); // XXXXXXXXXX
2494 sort_expression result;
2495 if (TypeMatchA(Par,PosType,result))
2496 {
2497 NewParList=detail::insert_sort_unique(NewParList,result);
2498 }
2499 }
2500 catch (mcrl2::runtime_error&)
2501 {
2502 // Ignore the error. Just do not add the type to NewParList
2503 }
2504 }
2505 NewParList=reverse(NewParList);
2506
2507 if (NewParList.empty())
2508 {
2509 //Ok, this looks like a type error. We are not that strict.
2510 //Pos can be Nat, or even Int...
2511 //So lets make PosType more liberal
2512 //We change every Pos to NotInferred(Pos,Nat,Int)...
2513 //and get the list. Then we take the min of the list.
2514
2515 ParList=BackupParList;
2516 PosType=ExpandNumTypesUp(PosType);
2517 for (; !ParList.empty(); ParList=ParList.tail())
2518 {
2519 const sort_expression& Par=ParList.front();
2520 sort_expression result;
2521 if (TypeMatchA(Par,PosType,result))
2522 {
2523 NewParList=detail::insert_sort_unique(NewParList,result);
2524 }
2525 }
2526 NewParList=reverse(NewParList);
2527 if (NewParList.size()>1)
2528 {
2529 NewParList = sort_expression_list({ detail::MinType(NewParList) });
2530 }
2531 }
2532
2533 if (NewParList.empty())
2534 {
2535 //Ok, casting of the arguments did not help.
2536 //Let's try to be more relaxed about the result, e.g. returning Pos or Nat is not a bad idea for int.
2537
2538 ParList=BackupParList;
2539
2540 PosType=ExpandNumTypesDown(ExpandNumTypesUp(PosType));
2541 for (; !ParList.empty(); ParList=ParList.tail())
2542 {
2543 const sort_expression& Par=ParList.front();
2544 sort_expression result;
2545 if (TypeMatchA(Par,PosType,result))
2546 {
2547 NewParList=detail::insert_sort_unique(NewParList,result);
2548 }
2549 }
2550 NewParList=reverse(NewParList);
2551 if (NewParList.size()>1)
2552 {
2553 NewParList = sort_expression_list({ detail::MinType(NewParList) });
2554 }
2555 }
2556
2557 ParList=NewParList;
2558 }
2559 if (ParList.empty())
2560 {
2561 //provide some information to the upper layer for a better error message
2562 sort_expression Sort;
2563 if (CandidateParList.size()==1)
2564 {
2565 Sort=CandidateParList.front();
2566 }
2567 else
2568 {
2569 Sort=untyped_possible_sorts(sort_expression_list(CandidateParList));
2570 }
2571 DataTerm=data::function_symbol(Name,Sort);
2572 if (nFactPars!=std::string::npos)
2573 {
2574 throw mcrl2::runtime_error("Unknown operation/variable " + core::pp(Name)
2575 + " with " + std::to_string(nFactPars) + " argument" + ((nFactPars != 1)?"s":"")
2576 + " that matches type " + data::pp(PosType) + ".");
2577 }
2578 else
2579 {
2580 throw mcrl2::runtime_error("Unknown operation/variable " + core::pp(Name) + " that matches type " + data::pp(PosType) + ".");
2581 }
2582 }
2583
2584 if (ParList.size()==1)
2585 {
2586 // replace PossibleSorts by a single possibility.
2587 sort_expression Type=ParList.front();
2588
2589 sort_expression OldType=Type;
2590 bool result=true;
2591 assert(Type.defined());
2592 if (detail::HasUnknown(Type))
2593 {
2594 sort_expression new_type;
2595 result=TypeMatchA(Type,PosType,new_type);
2596 Type=new_type;
2597 }
2598
2599 if (detail::HasUnknown(Type) && data::is_function_symbol(DataTerm))
2600 {
2601 sort_expression new_type;
2602 result=TypeMatchA(Type,DataTerm.sort(),new_type);
2603 Type=new_type;
2604 }
2605
2606 if (!result)
2607 {
2608 throw mcrl2::runtime_error("Fail to match sort " + data::pp(OldType) + " with " + data::pp(PosType) + ".");
2609 }
2610
2611 Type=determine_allowed_type(DataTerm,Type);
2612
2613 Type=detail::replace_possible_sorts(Type); // Set the type to one option in possible sorts, if there are more options.
2614
2615 if (variable_)
2616 {
2617 DataTerm=variable(Name,Type);
2618 }
2619 else if (is_untyped_identifier(DataTerm))
2620 {
2621 DataTerm=data::function_symbol(untyped_identifier(DataTerm).name(),Type);
2622 }
2623 else
2624 {
2625 DataTerm=data::function_symbol(function_symbol(DataTerm).name(),Type);
2626 }
2627 assert(Type.defined());
2628 return Type;
2629 }
2630 else
2631 {
2632 if (strictly_ambiguous)
2633 {
2634 if (nFactPars!=std::string::npos)
2635 {
2636 throw mcrl2::runtime_error("Ambiguous operation " + core::pp(Name) + " with " + std::to_string(nFactPars) + " parameter" + ((nFactPars != 1)?"s.":"."));
2637 }
2638 else
2639 {
2640 throw mcrl2::runtime_error("Ambiguous operation " + core::pp(Name) + ".");
2641 }
2642 }
2643 else
2644 {
2645 return data::untyped_sort();
2646 }
2647 }
2648 }
2649 else
2650 {
2651 return TraverseVarConsTypeD(DeclaredVars,DataTerm,PosType,strictly_ambiguous,warn_upcasting,print_cast_error);
2652 }
2653}
2654
2655
2657 const detail::variable_context& DeclaredVars,
2658 data_expression& DataTerm,
2659 const sort_expression& PosType,
2660 const bool strictly_ambiguous,
2661 const bool warn_upcasting,
2662 const bool print_cast_error) const
2663{
2664 //Type checks and transforms DataTerm replacing Unknown datatype with other ones.
2665 //Returns the type of the term which should match the PosType.
2666
2667 if (is_abstraction(DataTerm))
2668 {
2669 const abstraction& abstr=down_cast<const abstraction>(DataTerm);
2670 //The variable declaration of a binder should have at least 1 declaration
2671 if (abstr.variables().size()==0)
2672 {
2673 throw mcrl2::runtime_error("Binder " + data::pp(DataTerm) + " should have at least one declared variable.");
2674 }
2675
2676 const binder_type& BindingOperator = abstr.binding_operator();
2677
2678 if (is_untyped_set_or_bag_comprehension_binder(BindingOperator) ||
2679 is_set_comprehension_binder(BindingOperator) ||
2680 is_bag_comprehension_binder(BindingOperator))
2681 {
2682 const variable_list& comprehension_variables=abstr.variables();
2683 // Type check the comprehension_variables.
2684 try
2685 {
2686 (*this)(comprehension_variables,DeclaredVars);
2687 }
2688 catch (mcrl2::runtime_error& e)
2689 {
2690 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking the bag/set " + data::pp(DataTerm) + ".");
2691 }
2692
2693
2694 //A Set/bag comprehension should have exactly one variable declared
2695 if (comprehension_variables.size()!=1)
2696 {
2697 throw mcrl2::runtime_error("Set/bag comprehension " + data::pp(DataTerm) + " should have exactly one declared variable.");
2698 }
2699
2700 const sort_expression element_sort=comprehension_variables.front().sort();
2701
2702 detail::variable_context CopyDeclaredVars(DeclaredVars);
2703 CopyDeclaredVars.add_context_variables(comprehension_variables);
2704
2705 data_expression Data=abstr.body();
2706
2707 sort_expression ResType;
2708 sort_expression NewType;
2709 try
2710 {
2711 ResType=TraverseVarConsTypeD(CopyDeclaredVars,Data,data::untyped_sort(),strictly_ambiguous,warn_upcasting,print_cast_error);
2712 }
2713 catch (mcrl2::runtime_error& e)
2714 {
2715 throw mcrl2::runtime_error(std::string(e.what()) + "\nThe condition or count of a set/bag comprehension " + data::pp(DataTerm) + " cannot be determined.");
2716 }
2717 sort_expression temp;
2718 if (TypeMatchA(sort_bool::bool_(),ResType,temp))
2719 {
2720 NewType=sort_set::set_(sort_expression(element_sort));
2721 DataTerm = abstraction(set_comprehension_binder(),comprehension_variables,Data);
2722 }
2723 else if (TypeMatchA(sort_nat::nat(),ResType,temp))
2724 {
2725 NewType=sort_bag::bag(sort_expression(element_sort));
2726 DataTerm = abstraction(bag_comprehension_binder(),comprehension_variables,Data);
2727 }
2728 else if (TypeMatchA(sort_pos::pos(),ResType,temp))
2729 {
2730 NewType=sort_bag::bag(sort_expression(element_sort));
2731#ifdef MCRL2_ENABLE_MACHINENUMBERS
2732 Data=sort_nat::transform_positive_number_to_nat(Data);
2733#else
2734 Data=application(sort_nat::cnat(),Data);
2735#endif
2736 DataTerm = abstraction(bag_comprehension_binder(),comprehension_variables,Data);
2737 }
2738 else
2739 {
2740 throw mcrl2::runtime_error("The condition or count of a set/bag comprehension is not of sort Bool, Nat or Pos, but of sort " + data::pp(ResType) + ".");
2741 }
2742
2743 if (!TypeMatchA(NewType,PosType,NewType))
2744 {
2745 throw mcrl2::runtime_error("A set or bag comprehension of type " + data::pp(element_sort) + " does not match possible type " +
2746 data::pp(PosType) + " (while typechecking " + data::pp(DataTerm) + ").");
2747 }
2748
2749 return NewType;
2750 }
2751
2752 if (is_forall_binder(BindingOperator) || is_exists_binder(BindingOperator))
2753 {
2754 const variable_list& bound_variables=abstr.variables();
2755
2756 // Type check the variables.
2757 try
2758 {
2759 (*this)(bound_variables,DeclaredVars);
2760 }
2761 catch (mcrl2::runtime_error& e)
2762 {
2763 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking the quantification " + data::pp(DataTerm) + ".");
2764 }
2765
2766 detail::variable_context CopyDeclaredVars(DeclaredVars);
2767 CopyDeclaredVars.add_context_variables(bound_variables);
2768
2769 data_expression Data=abstr.body();
2770 sort_expression temp;
2771 if (!TypeMatchA(sort_bool::bool_(),PosType,temp))
2772 {
2773 throw mcrl2::runtime_error("The type of an exist/forall for " + data::pp(DataTerm) + " cannot be determined.");
2774 }
2775 sort_expression NewType=TraverseVarConsTypeD(CopyDeclaredVars,Data,sort_bool::bool_(),strictly_ambiguous,warn_upcasting,print_cast_error);
2776
2777 if (!TypeMatchA(sort_bool::bool_(),NewType,temp))
2778 {
2779 throw mcrl2::runtime_error("The type of an exist/forall for " + data::pp(DataTerm) + " cannot be determined.");
2780 }
2781
2782 DataTerm=abstraction(BindingOperator,bound_variables,Data);
2783 return sort_bool::bool_();
2784 }
2785
2786 if (is_lambda_binder(BindingOperator))
2787 {
2788 const variable_list& bound_variables=abstr.variables();
2789 // Typecheck the variables.
2790 try
2791 {
2792 (*this)(bound_variables,DeclaredVars);
2793 }
2794 catch (mcrl2::runtime_error& e)
2795 {
2796 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking the lambda expression " + data::pp(DataTerm) + ".");
2797 }
2798
2799 detail::variable_context CopyDeclaredVars(DeclaredVars);
2800 CopyDeclaredVars.add_context_variables(bound_variables);
2801
2802 sort_expression_list ArgTypes=detail::GetVarTypes(bound_variables);
2803 sort_expression NewType;
2804 if (!UnArrowProd(ArgTypes,PosType,NewType))
2805 {
2806 throw mcrl2::runtime_error("No functions with arguments " + data::pp(ArgTypes) + " among " + data::pp(PosType) + " (while typechecking " + data::pp(DataTerm) + ").");
2807 }
2808 data_expression Data=abstr.body();
2809
2810 try
2811 {
2812 NewType=TraverseVarConsTypeD(CopyDeclaredVars,Data,NewType,strictly_ambiguous,warn_upcasting,print_cast_error);
2813 }
2814 catch (mcrl2::runtime_error& e)
2815 {
2816 throw e;
2817 }
2818
2819 DataTerm=abstraction(BindingOperator,bound_variables,Data);
2820 return function_sort(ArgTypes,NewType);
2821 }
2822 }
2823
2824 if (is_where_clause(DataTerm))
2825 {
2826 const where_clause& where=down_cast<const where_clause>(DataTerm);
2827 variable_list WhereVarList;
2828 assignment_list NewWhereList;
2829 const assignment_expression_list& where_asss=where.declarations();
2830 for (assignment_expression_list::const_iterator i=where_asss.begin(); i!=where_asss.end(); ++i)
2831 {
2832 const assignment_expression WhereElem= *i;
2833 data_expression WhereTerm;
2834 variable NewWhereVar;
2836 {
2837 const data::untyped_identifier_assignment& t=down_cast<const data::untyped_identifier_assignment>(WhereElem);
2838 WhereTerm=t.rhs();
2839 sort_expression WhereType=TraverseVarConsTypeD(DeclaredVars,WhereTerm,data::untyped_sort(),strictly_ambiguous,warn_upcasting,print_cast_error);
2840
2841 // The variable in WhereElem is just a string and needs to be transformed to a DataVarId.
2842 NewWhereVar=variable(t.lhs(),WhereType);
2843 }
2844 else
2845 {
2846 const assignment& t=down_cast<const assignment>(WhereElem);
2847 WhereTerm=t.rhs();
2848 NewWhereVar=t.lhs();
2849 sort_expression WhereType=TraverseVarConsTypeD(DeclaredVars,WhereTerm,NewWhereVar.sort(),strictly_ambiguous,warn_upcasting,print_cast_error);
2850 }
2851 WhereVarList.push_front(NewWhereVar);
2852 NewWhereList.push_front(assignment(NewWhereVar,WhereTerm));
2853 }
2854 NewWhereList=reverse(NewWhereList);
2855
2856 variable_list where_variables=reverse(WhereVarList);
2857 // Typecheck the where_variables
2858 try
2859 {
2860 (*this)(where_variables,DeclaredVars);
2861 }
2862 catch (mcrl2::runtime_error& e)
2863 {
2864 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking the where expression " + data::pp(DataTerm) + ".");
2865 }
2866
2867 detail::variable_context CopyDeclaredVars(DeclaredVars);
2868 CopyDeclaredVars.add_context_variables(where_variables);
2869
2870 data_expression Data=where.body();
2871 sort_expression NewType=TraverseVarConsTypeD(CopyDeclaredVars,Data,PosType,strictly_ambiguous,warn_upcasting,print_cast_error);
2872
2873 DataTerm=where_clause(Data,NewWhereList);
2874 return NewType;
2875 }
2876
2877 if (is_application(DataTerm))
2878 {
2879 //arguments
2880 const application& appl=down_cast<application>(DataTerm);
2881 std::size_t nArguments=appl.size();
2882
2883 //The following is needed to check enumerations
2884 const data_expression& Arg0 = appl.head();
2886 {
2887 core::identifier_string Name = is_function_symbol(Arg0)?down_cast<function_symbol>(Arg0).name():
2888 atermpp::down_cast<untyped_identifier>(Arg0).name();
2890 {
2891 sort_expression Type;
2892 if (!UnList(PosType,Type))
2893 {
2894 throw mcrl2::runtime_error("It is not possible to cast list to " + data::pp(PosType) + " (while typechecking " + data::pp(data_expression_list(appl.begin(),appl.end())) + ").");
2895 }
2896
2897 //First time to determine the common type only!
2898 data_expression_list NewArguments;
2899 bool Type_is_stable=true;
2900 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
2901 {
2902 data_expression Argument= *i;
2903 sort_expression Type0;
2904 try
2905 {
2906 Type0=TraverseVarConsTypeD(DeclaredVars,Argument,Type,strictly_ambiguous,warn_upcasting,false);
2907 }
2908 catch (mcrl2::runtime_error&)
2909 {
2910 // Try again, but now without Type as the suggestion.
2911 // If this does not work, it will be caught in the second pass below.
2912 Type0=TraverseVarConsTypeD(DeclaredVars,Argument,data::untyped_sort(),strictly_ambiguous,warn_upcasting,print_cast_error);
2913 }
2914 NewArguments.push_front(Argument);
2915 Type_is_stable=Type_is_stable && (Type==Type0);
2916 Type=Type0;
2917 }
2918 // Arguments=OldArguments;
2919
2920 //Second time to do the real work, but only if the elements in the list have different types.
2921 if (!Type_is_stable)
2922 {
2923 NewArguments=data_expression_list();
2924 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
2925 {
2926 data_expression Argument= *i;
2927 sort_expression Type0=TraverseVarConsTypeD(DeclaredVars,Argument,Type,strictly_ambiguous,warn_upcasting,print_cast_error);
2928 NewArguments.push_front(Argument);
2929 Type=Type0;
2930 }
2931 }
2932
2933 Type=sort_list::list(sort_expression(Type));
2935 return Type;
2936 }
2937 if (Name == sort_set::set_enumeration_name())
2938 {
2939 sort_expression Type;
2940 if (!UnFSet(PosType,Type))
2941 {
2942 throw mcrl2::runtime_error("It is not possible to cast set to " + data::pp(PosType) + " (while typechecking " + data::pp(data_expression_list(appl.begin(),appl.end())) + ").");
2943 }
2944
2945 //First time to determine the common type only (which will be NewType)!
2946 bool NewTypeDefined=false;
2947 sort_expression NewType;
2948 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
2949 {
2950 data_expression Argument= *i;
2951 sort_expression Type0;
2952 try
2953 {
2954 Type0=TraverseVarConsTypeD(DeclaredVars,Argument,Type,strictly_ambiguous,warn_upcasting,print_cast_error);
2955 }
2956 catch (mcrl2::runtime_error& e)
2957 {
2958 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast element to " + data::pp(Type) + " (while typechecking " + data::pp(Argument) + ").");
2959 }
2960
2961 sort_expression OldNewType=NewType;
2962 if (!NewTypeDefined)
2963 {
2964 NewType=Type0;
2965 NewTypeDefined=true;
2966 }
2967 else
2968 {
2969 sort_expression temp;
2970 if (!MaximumType(NewType,Type0,temp))
2971 {
2972 throw mcrl2::runtime_error("Set contains incompatible elements of sorts " + data::pp(OldNewType) + " and " + data::pp(Type0) + " (while typechecking " + data::pp(Argument) + ".");
2973 }
2974 NewType=temp;
2975 NewTypeDefined=true;
2976 }
2977 }
2978
2979
2980 // Type is now the most generic type to be used.
2981 assert(Type.defined());
2982 assert(NewTypeDefined);
2983 Type=NewType;
2984 // Arguments=OldArguments;
2985
2986 //Second time to do the real work.
2987 data_expression_list NewArguments;
2988 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
2989 {
2990 data_expression Argument= *i;
2991 sort_expression Type0;
2992 try
2993 {
2994 Type0=TraverseVarConsTypeD(DeclaredVars,Argument,Type,strictly_ambiguous,warn_upcasting,print_cast_error);
2995 }
2996 catch (mcrl2::runtime_error& e)
2997 {
2998 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast element to " + data::pp(Type) + " (while typechecking " + data::pp(Argument) + ").");
2999 }
3000 NewArguments.push_front(Argument);
3001 Type=Type0;
3002 }
3004 if (sort_set::is_set(PosType))
3005 {
3006 DataTerm=sort_set::constructor(Type, sort_set::false_function(Type),DataTerm);
3007
3008 return sort_set::set_(Type);
3009 }
3010 return sort_fset::fset(Type);
3011 }
3012 if (Name == sort_bag::bag_enumeration_name())
3013 {
3014 sort_expression Type;
3015 if (!UnFBag(PosType,Type))
3016 {
3017 throw mcrl2::runtime_error("Impossible to cast bag to " + data::pp(PosType) + "(while typechecking " +
3018 data::pp(data_expression_list(appl.begin(),appl.end())) + ").");
3019 }
3020
3021 //First time to determine the common type only!
3022 sort_expression NewType;
3023 bool NewTypeDefined=false;
3024 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
3025 {
3026 data_expression Argument0= *i;
3027 ++i;
3028 data_expression Argument1= *i;
3029 sort_expression Type0;
3030 try
3031 {
3032 Type0=TraverseVarConsTypeD(DeclaredVars,Argument0,Type,strictly_ambiguous,warn_upcasting,print_cast_error);
3033 }
3034 catch (mcrl2::runtime_error& e)
3035 {
3036 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast element to " + data::pp(Type) + " (while typechecking " + data::pp(Argument0) + ").");
3037 }
3038 sort_expression Type1;
3039 try
3040 {
3041 Type1=TraverseVarConsTypeD(DeclaredVars,Argument1,sort_nat::nat(),strictly_ambiguous,warn_upcasting,print_cast_error);
3042 }
3043 catch (mcrl2::runtime_error& e)
3044 {
3045 if (print_cast_error)
3046 {
3047 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast number to " + data::pp(sort_nat::nat()) + " (while typechecking " + data::pp(Argument1) + ").");
3048 }
3049 else
3050 {
3051 throw e;
3052 }
3053 }
3054 sort_expression OldNewType=NewType;
3055 if (!NewTypeDefined)
3056 {
3057 NewType=Type0;
3058 NewTypeDefined=true;
3059 }
3060 else
3061 {
3062 sort_expression temp;
3063 if (!MaximumType(NewType,Type0,temp))
3064 {
3065 throw mcrl2::runtime_error("Bag contains incompatible elements of sorts " + data::pp(OldNewType) + " and " + data::pp(Type0) + " (while typechecking " + data::pp(Argument0) + ").");
3066 }
3067
3068 NewType=temp;
3069 NewTypeDefined=true;
3070 }
3071 }
3072 assert(Type.defined());
3073 assert(NewTypeDefined);
3074 Type=NewType;
3075 // Arguments=OldArguments;
3076
3077 //Second time to do the real work.
3078 data_expression_list NewArguments;
3079 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
3080 {
3081 data_expression Argument0= *i;
3082 ++i;
3083 data_expression Argument1= *i;
3084 sort_expression Type0;
3085 try
3086 {
3087 Type0=TraverseVarConsTypeD(DeclaredVars,Argument0,Type,strictly_ambiguous,warn_upcasting,print_cast_error);
3088 }
3089 catch (mcrl2::runtime_error& e)
3090 {
3091 if (print_cast_error)
3092 {
3093 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast element to " + data::pp(Type) + " (while typechecking " + data::pp(Argument0) + ").");
3094 }
3095 else
3096 {
3097 throw e;
3098 }
3099 }
3100 sort_expression Type1;
3101 try
3102 {
3103 Type1=TraverseVarConsTypeD(DeclaredVars,Argument1,sort_nat::nat(),strictly_ambiguous,warn_upcasting,print_cast_error);
3104 }
3105 catch (mcrl2::runtime_error& e)
3106 {
3107 if (print_cast_error)
3108 {
3109 throw mcrl2::runtime_error(std::string(e.what()) + "\nImpossible to cast number to " + data::pp(sort_nat::nat()) + " (while typechecking " + data::pp(Argument1) + ").");
3110 }
3111 else
3112 {
3113 throw e;
3114 }
3115 }
3116 NewArguments.push_front(Argument0);
3117 NewArguments.push_front(Argument1);
3118 Type=Type0;
3119 }
3120 DataTerm=sort_bag::bag_enumeration(Type, data_expression_list(reverse(NewArguments)));
3121 if (sort_bag::is_bag(PosType))
3122 {
3123 DataTerm=sort_bag::constructor(Type, sort_bag::zero_function(Type),DataTerm);
3124
3125 return sort_bag::bag(Type);
3126 }
3127 return sort_fbag::fbag(Type);
3128 }
3129 }
3130 sort_expression_list NewArgumentTypes;
3131 data_expression_list NewArguments;
3132 sort_expression_list argument_sorts;
3133 for (application::const_iterator i=appl.begin(); i!=appl.end(); ++i)
3134 {
3135 data_expression Arg= *i;
3136 sort_expression Type=TraverseVarConsTypeD(DeclaredVars,Arg,data::untyped_sort(),false,warn_upcasting,print_cast_error);
3137 assert(Type.defined());
3138 NewArguments.push_front(Arg);
3139 NewArgumentTypes.push_front(Type);
3140 }
3141 data_expression_list Arguments=reverse(NewArguments);
3142 sort_expression_list ArgumentTypes=reverse(NewArgumentTypes);
3143 //function
3144 data_expression Data=appl.head();
3145 sort_expression NewType;
3146 try
3147 {
3148 NewType=TraverseVarConsTypeDN(DeclaredVars,
3149 Data,
3150 // data::untyped_sort(), /* function_sort(ArgumentTypes,PosType) */
3151 function_sort(ArgumentTypes,PosType), // XXXXXXXX
3152 false,nArguments,warn_upcasting,print_cast_error);
3153 }
3154 catch (mcrl2::runtime_error& e)
3155 {
3156 throw mcrl2::runtime_error(std::string(e.what()) + "\nType error while trying to cast an application of " +
3157 data::pp(Data) + " to arguments " + data::pp(Arguments) + " to type " + data::pp(PosType) + ".");
3158 }
3159
3160 //it is possible that:
3161 //1) a cast has happened
3162 //2) some parameter Types became sharper.
3163 //we do the arguments again with the types.
3164
3165
3166 if (is_function_sort(UnwindType(NewType)))
3167 {
3168 sort_expression_list NeededArgumentTypes=down_cast<function_sort>(UnwindType(NewType)).domain();
3169
3170 if (NeededArgumentTypes.size()!=Arguments.size())
3171 {
3172 throw mcrl2::runtime_error("Need argumens of sorts " + data::pp(NeededArgumentTypes) +
3173 " which does not match the number of provided arguments "
3174 + data::pp(Arguments) + " (while typechecking "
3175 + data::pp(DataTerm) + ").");
3176 }
3177 //arguments again
3178 sort_expression_list NewArgumentTypes;
3179 data_expression_list NewArguments;
3180 for (; !Arguments.empty(); Arguments=Arguments.tail(),
3181 ArgumentTypes=ArgumentTypes.tail(),NeededArgumentTypes=NeededArgumentTypes.tail())
3182 {
3183 assert(!Arguments.empty());
3184 assert(!NeededArgumentTypes.empty());
3185 data_expression Arg=Arguments.front();
3186 const sort_expression& NeededType=NeededArgumentTypes.front();
3187 sort_expression Type=ArgumentTypes.front();
3188 if (!EqTypesA(NeededType,Type))
3189 {
3190 //upcasting
3191 try
3192 {
3193 Type=UpCastNumericType(NeededType,Type,Arg,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3194 }
3195 catch (mcrl2::runtime_error&)
3196 {
3197 }
3198 }
3199 if (!EqTypesA(NeededType,Type))
3200 {
3201 sort_expression NewArgType;
3202 if (!TypeMatchA(NeededType,Type,NewArgType))
3203 {
3204 if (!TypeMatchA(NeededType,ExpandNumTypesUp(Type),NewArgType))
3205 {
3206 NewArgType=NeededType;
3207 }
3208 }
3209 try
3210 {
3211 NewArgType=TraverseVarConsTypeD(DeclaredVars,Arg,NewArgType,strictly_ambiguous,warn_upcasting,print_cast_error);
3212 }
3213 catch (mcrl2::runtime_error& e)
3214 {
3215 throw mcrl2::runtime_error(std::string(e.what()) + "\nRequired type " + data::pp(NeededType) + " does not match possible type "
3216 + data::pp(Type) + " (while typechecking " + data::pp(Arg) + " in " + data::pp(DataTerm) + ").");
3217 }
3218 Type=NewArgType;
3219 }
3220 NewArguments.push_front(Arg);
3221 NewArgumentTypes.push_front(Type);
3222 }
3223 Arguments=reverse(NewArguments);
3224 ArgumentTypes=reverse(NewArgumentTypes);
3225 }
3226
3227 //the function again
3228 try
3229 {
3230 NewType=TraverseVarConsTypeDN(DeclaredVars,
3231 Data,function_sort(ArgumentTypes,PosType),
3232 strictly_ambiguous,nArguments,warn_upcasting,print_cast_error);
3233 }
3234 catch (mcrl2::runtime_error& e)
3235 {
3236 throw mcrl2::runtime_error(std::string(e.what()) + "\nType error while trying to cast " +
3237 data::pp(application(Data,Arguments)) + " to type " + data::pp(PosType) + ".");
3238 }
3239
3240 //and the arguments once more
3241 if (is_function_sort(UnwindType(NewType)))
3242 {
3243 sort_expression_list NeededArgumentTypes=down_cast<function_sort>(UnwindType(NewType)).domain();
3244 sort_expression_list NewArgumentTypes;
3245 data_expression_list NewArguments;
3246 for (; !Arguments.empty(); Arguments=Arguments.tail(),
3247 ArgumentTypes=ArgumentTypes.tail(),NeededArgumentTypes=NeededArgumentTypes.tail())
3248 {
3249 data_expression Arg=Arguments.front();
3250 const sort_expression& NeededType=NeededArgumentTypes.front();
3251 sort_expression Type=ArgumentTypes.front();
3252
3253 if (!EqTypesA(NeededType,Type))
3254 {
3255 //upcasting
3256 try
3257 {
3258 Type=UpCastNumericType(NeededType,Type,Arg,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3259 }
3260 catch (mcrl2::runtime_error&)
3261 {
3262 }
3263 }
3264 if (!EqTypesA(NeededType,Type))
3265 {
3266 sort_expression NewArgType;
3267 if (!TypeMatchA(NeededType,Type,NewArgType))
3268 {
3269 if (!TypeMatchA(NeededType,ExpandNumTypesUp(Type),NewArgType))
3270 {
3271 NewArgType=NeededType;
3272 }
3273 }
3274 try
3275 {
3276 NewArgType=TraverseVarConsTypeD(DeclaredVars,Arg,NewArgType,strictly_ambiguous,warn_upcasting,print_cast_error);
3277 }
3278 catch (mcrl2::runtime_error& e)
3279 {
3280 throw mcrl2::runtime_error(std::string(e.what()) + "\nNeeded type " + data::pp(NeededType) + " does not match possible type "
3281 + data::pp(Type) + " (while typechecking " + data::pp(Arg) + " in " + data::pp(DataTerm) + ").");
3282 }
3283 Type=NewArgType;
3284 }
3285
3286 NewArguments.push_front(Arg);
3287 NewArgumentTypes.push_front(Type);
3288 }
3289 Arguments=reverse(NewArguments);
3290 ArgumentTypes=reverse(NewArgumentTypes);
3291 }
3292
3293 DataTerm=application(Data,Arguments);
3294
3295 if (is_function_sort(UnwindType(NewType)))
3296 {
3297 // Code below is a hack as sometimes the type of the returned numeral is not equal
3298 // to the PosType that is requested. Hence, a typecast must be added explicitly.
3299 const sort_expression s=DataTerm.sort();
3300 if (PosType !=data::untyped_sort() && s != PosType &&
3301 (s == sort_int::int_() || s == sort_pos::pos() || s == sort_nat::nat() || s == sort_real::real_()))
3302 {
3303 return UpCastNumericType(PosType, atermpp::down_cast<function_sort>(UnwindType(NewType)).codomain(),
3304 DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3305 }
3306 // end of the explicit upcast hack. Continuing with the original code.
3307 return atermpp::down_cast<function_sort>(UnwindType(NewType)).codomain();
3308 }
3309
3310 sort_expression temp_type;
3311 if (!UnArrowProd(ArgumentTypes,NewType,temp_type))
3312 {
3313 throw mcrl2::runtime_error("Fail to properly type " + data::pp(DataTerm) + ".");
3314 }
3315 if (detail::HasUnknown(temp_type))
3316 {
3317 throw mcrl2::runtime_error("Fail to properly type " + data::pp(DataTerm) + ".");
3318 }
3319 return temp_type;
3320 }
3321
3322 if (data::is_untyped_identifier(DataTerm)||data::is_function_symbol(DataTerm)||is_variable(DataTerm))
3323 {
3325 data::is_untyped_identifier(DataTerm)?down_cast<untyped_identifier>(DataTerm).name():
3326 is_function_symbol(DataTerm)?down_cast<function_symbol>(DataTerm).name():
3327 atermpp::down_cast<variable>(DataTerm).name();
3329 {
3331 if (detail::IsPos(Name))
3332 {
3333 Sort=sort_pos::pos();
3334 }
3335 else if (detail::IsNat(Name))
3336 {
3337 Sort=sort_nat::nat();
3338 }
3339 DataTerm=data::function_symbol(Name,Sort);
3340
3341 sort_expression temp;
3342 if (TypeMatchA(Sort,PosType,temp))
3343 {
3344 return Sort;
3345 }
3346
3347 //upcasting
3348 sort_expression CastedNewType;
3349 try
3350 {
3351 CastedNewType=UpCastNumericType(PosType,Sort,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3352 }
3353 catch (mcrl2::runtime_error& e)
3354 {
3355 throw mcrl2::runtime_error(std::string(e.what()) + "\nCannot (up)cast number " + data::pp(DataTerm) + " to type " + data::pp(PosType) + ".");
3356 }
3357 return CastedNewType;
3358 }
3359
3360 const std::map<core::identifier_string,sort_expression>::const_iterator it=DeclaredVars.context().find(Name);
3361 if (it!=DeclaredVars.context().end())
3362 {
3363 sort_expression Type=normalize_sorts(it->second,get_sort_specification());
3364 DataTerm=variable(Name,Type);
3365
3366 sort_expression NewType;
3367 if (TypeMatchA(Type,PosType,NewType))
3368 {
3369 Type=NewType;
3370 }
3371 else
3372 {
3373 //upcasting
3374 sort_expression CastedNewType;
3375 try
3376 {
3377 CastedNewType=UpCastNumericType(PosType,Type,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3378 }
3379 catch (mcrl2::runtime_error& e)
3380 {
3381 if (print_cast_error)
3382 {
3383 throw mcrl2::runtime_error(std::string(e.what()) + "\nCannot (up)cast variable " + data::pp(DataTerm) + " to type " + data::pp(PosType) + ".");
3384 }
3385 else
3386 {
3387 throw e;
3388 }
3389 }
3390
3391 Type=CastedNewType;
3392 }
3393
3394 //Add to free variables list
3395 return Type;
3396 }
3397
3398 std::map<core::identifier_string,sort_expression>::const_iterator i=user_constants.find(Name);
3399 if (i!=user_constants.end())
3400 {
3401 sort_expression Type=i->second;
3402 sort_expression NewType;
3403 if (TypeMatchA(Type,PosType,NewType))
3404 {
3405 Type=NewType;
3406 DataTerm=data::function_symbol(Name,Type);
3407 return Type;
3408 }
3409 else
3410 {
3411 // The type cannot be unified. Try upcasting the type.
3412 DataTerm=data::function_symbol(Name,Type);
3413 try
3414 {
3415 return UpCastNumericType(PosType,Type,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3416 }
3417 catch (mcrl2::runtime_error& e)
3418 {
3419 throw mcrl2::runtime_error(std::string(e.what()) + "\nNo constant " + data::pp(DataTerm) + " with type " + data::pp(PosType) + ".");
3420 }
3421 }
3422 }
3423
3424 std::map<core::identifier_string,sort_expression_list>::const_iterator j=system_constants.find(Name);
3425 if (j!=system_constants.end())
3426 {
3427 sort_expression_list TypeList=j->second;
3428 sort_expression_list NewParList;
3429 for (sort_expression_list::const_iterator i=TypeList.begin(); i!=TypeList.end(); ++i)
3430 {
3431 const sort_expression Type=*i;
3432 sort_expression result;
3433 if (TypeMatchA(Type,PosType,result))
3434 {
3435 DataTerm=data::function_symbol(Name,result);
3436 NewParList.push_front(result);
3437 }
3438 }
3439 sort_expression_list ParList=reverse(NewParList);
3440 if (ParList.empty())
3441 {
3442 // Try to do the matching again with relaxed typing.
3443 for (sort_expression_list::const_iterator i=TypeList.begin(); i!=TypeList.end(); ++i)
3444 {
3445 sort_expression Type=*i;
3446 if (is_untyped_identifier(DataTerm) )
3447 {
3448 DataTerm=data::function_symbol(Name,Type);
3449 }
3450 Type=UpCastNumericType(PosType,Type,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3451 // if (EqTypesA(Type,PosType))
3452 sort_expression result;
3453 if (TypeMatchA(Type,PosType,result))
3454 {
3455 NewParList.push_front(result);
3456 }
3457 }
3458 ParList=reverse(NewParList);
3459 }
3460
3461 if (ParList.empty())
3462 {
3463 throw mcrl2::runtime_error("No system constant " + data::pp(DataTerm) + " with type " + data::pp(PosType) + ".");
3464 }
3465
3466 if (ParList.size()==1)
3467 {
3468 const sort_expression& Type=ParList.front();
3469
3470 if (is_untyped_identifier(DataTerm) )
3471 {
3472 assert(0);
3473 DataTerm=data::function_symbol(Name,Type);
3474 }
3475 try
3476 {
3477 sort_expression r= UpCastNumericType(PosType,Type,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3478 return r;
3479 }
3480 catch (mcrl2::runtime_error& e)
3481 {
3482 throw mcrl2::runtime_error(std::string(e.what()) + "\nNo constant " + data::pp(DataTerm) + " with type " + data::pp(PosType) + ".");
3483 }
3484 }
3485 else
3486 {
3488 return data::untyped_sort();
3489 }
3490 }
3491
3492 const std::map <core::identifier_string,sort_expression_list>::const_iterator j_context=user_functions.find(Name);
3493 const std::map <core::identifier_string,sort_expression_list>::const_iterator j_gssystem=system_functions.find(Name);
3494
3495 sort_expression_list ParList;
3496 if (j_context==user_functions.end())
3497 {
3498 if (j_gssystem!=system_functions.end())
3499 {
3500 ParList=j_gssystem->second; // The function only occurs in the system.
3501 }
3502 else
3503 {
3504 throw mcrl2::runtime_error("Unknown operation " + core::pp(Name) + ".");
3505 }
3506 }
3507 else if (j_gssystem==system_functions.end())
3508 {
3509 ParList=j_context->second; // only the context sorts are defined.
3510 }
3511 else // Both are defined.
3512 {
3513 ParList=j_gssystem->second+j_context->second;
3514 }
3515
3516
3517 if (ParList.size()==1)
3518 {
3519 const sort_expression& Type=ParList.front();
3520 DataTerm=data::function_symbol(Name,Type);
3521 try
3522 {
3523 return UpCastNumericType(PosType,Type,DataTerm,DeclaredVars,strictly_ambiguous,warn_upcasting,print_cast_error);
3524 }
3525 catch (mcrl2::runtime_error& e)
3526 {
3527 throw mcrl2::runtime_error(std::string(e.what()) + "\nNo constant " + data::pp(DataTerm) + " with type " + data::pp(PosType) + ".");
3528 }
3529 }
3530 else
3531 {
3532 return TraverseVarConsTypeDN(DeclaredVars, DataTerm, PosType, strictly_ambiguous, std::string::npos, warn_upcasting,print_cast_error);
3533 }
3534 }
3535
3536#ifdef MCRL2_ENABLE_MACHINENUMBERS
3537 if (is_machine_number(DataTerm))
3538 {
3540 }
3541#endif
3542
3543 throw mcrl2::runtime_error("Internal type checking error: " + data::pp(DataTerm) + " does not match any type checking case." );
3544}
3545
3547{
3548 std::size_t constr_number=constructors.size();
3549 function_symbol_vector functions_and_constructors=constructors;
3550 functions_and_constructors.insert(functions_and_constructors.end(),mappings.begin(),mappings.end());
3551 for (const function_symbol& Func: functions_and_constructors)
3552 {
3553 const core::identifier_string& FuncName=Func.name();
3554 sort_expression FuncType=Func.sort();
3555
3556 check_sort_is_declared(FuncType);
3557
3558 //if FuncType is a defined function sort, unwind it
3559 if (is_basic_sort(FuncType))
3560 {
3561 const sort_expression NewFuncType=UnwindType(FuncType);
3562 if (is_function_sort(NewFuncType))
3563 {
3564 FuncType=NewFuncType;
3565 }
3566 }
3567
3568 if (is_function_sort(FuncType))
3569 {
3570 add_function(data::function_symbol(FuncName,FuncType),"function");
3571 }
3572 else
3573 {
3574 try
3575 {
3576 add_constant(data::function_symbol(FuncName,FuncType),"constant");
3577 }
3578 catch (mcrl2::runtime_error& e)
3579 {
3580 throw mcrl2::runtime_error(std::string(e.what()) + "\nCould not add constant.");
3581 }
3582 }
3583
3584 if (constr_number)
3585 {
3586 constr_number--;
3587
3588 //Here checks for the constructors
3589 sort_expression ConstructorType=FuncType;
3590 if (is_function_sort(ConstructorType))
3591 {
3592 ConstructorType=down_cast<function_sort>(ConstructorType).codomain();
3593 }
3594 ConstructorType=UnwindType(ConstructorType);
3595 if (!is_basic_sort(ConstructorType) ||
3596 sort_bool::is_bool(sort_expression(ConstructorType)) ||
3597 sort_pos::is_pos(sort_expression(ConstructorType)) ||
3598 sort_nat::is_nat(sort_expression(ConstructorType)) ||
3599 sort_int::is_int(sort_expression(ConstructorType)) ||
3600 sort_real::is_real(sort_expression(ConstructorType))
3601 )
3602 {
3603 throw mcrl2::runtime_error("Could not add constructor " + core::pp(FuncName) + " of sort " + data::pp(FuncType) + ". Constructors of built-in sorts are not allowed.");
3604 }
3605 }
3606 }
3607
3608 // Check that the constructors are defined such that they cannot generate an empty sort.
3609 // E.g. in the specification sort D; cons f:D->D; the sort D must be necessarily empty, which is
3610 // forbidden. The function below checks whether such malicious specifications occur.
3611
3612 check_for_empty_constructor_domains(normalized_constructors); // throws exception if not ok.
3613}
3614
3616{
3617 const core::identifier_string& Name = f.name();
3618 const sort_expression& Sort = f.sort();
3619
3620 if (user_constants.count(Name)>0)
3621 {
3622 throw mcrl2::runtime_error("Double declaration of " + msg + " " + core::pp(Name) + ".");
3623 }
3624
3625 if (system_constants.count(Name)>0 || system_functions.count(Name)>0)
3626 {
3627 throw mcrl2::runtime_error("Attempt to declare a constant with the name that is a built-in identifier (" + core::pp(Name) + ").");
3628 }
3629
3630 user_constants[Name]=normalize_sorts(Sort,get_sort_specification());
3631}
3632
3633
3635 const sort_expression_list& TypeList,
3636 const sort_expression_list& PosTypeList,
3637 sort_expression_list& result) const
3638{
3639 if (TypeList.size()!=PosTypeList.size())
3640 {
3641 return false;
3642 }
3643
3644 sort_expression_list Result;
3646 for (sort_expression_list::const_iterator i=TypeList.begin(); i!=TypeList.end(); ++i, ++j)
3647 {
3648 sort_expression Type;
3649 if (!TypeMatchA(*i,*j,Type))
3650 {
3651 return false;
3652 }
3653 Result.push_front(Type);
3654 }
3655 result=reverse(Result);
3656 return true;
3657}
3658
3659
3661{
3662 return normalize_sorts(Type,get_sort_specification());
3663}
3664
3666{
3667 return variable(v.name(),UnwindType(v.sort()));
3668}
3669
3671 const sort_expression& Type_in,
3672 const sort_expression& PosType_in,
3673 sort_expression& result) const
3674{
3675 // Checks if Type and PosType match by instantiating unknown sorts.
3676 // It returns the matching instantiation of Type in result. If matching fails,
3677 // it returns false, otherwise true.
3678
3679 sort_expression Type=Type_in;
3680 sort_expression PosType=PosType_in;
3681
3682 if (data::is_untyped_sort(Type))
3683 {
3684 result=PosType;
3685 return true;
3686 }
3687 if (data::is_untyped_sort(PosType) || EqTypesA(Type,PosType))
3688 {
3689 result=Type;
3690 return true;
3691 }
3693 {
3694 PosType.swap(Type);
3695 }
3696 if (is_untyped_possible_sorts(PosType))
3697 {
3698 sort_expression_list NewTypeList;
3699 const untyped_possible_sorts& mps=down_cast<const untyped_possible_sorts>(PosType);
3700 for (sort_expression_list::const_iterator i=mps.sorts().begin(); i!=mps.sorts().end(); ++i)
3701 {
3702 sort_expression NewPosType= *i;
3703
3704 sort_expression new_type;
3705 if (TypeMatchA(Type,NewPosType,new_type))
3706 {
3707 NewPosType=new_type;
3708 // Avoid double insertions.
3709 if (std::find(NewTypeList.begin(),NewTypeList.end(),NewPosType)==NewTypeList.end())
3710 {
3711 NewTypeList.push_front(NewPosType);
3712 }
3713 }
3714 }
3715 if (NewTypeList.empty())
3716 {
3717 return false;
3718 }
3719 if (NewTypeList.tail().empty())
3720 {
3721 result=NewTypeList.front();
3722 return true;
3723 }
3724
3726 return true;
3727 }
3728
3729 if (is_basic_sort(Type))
3730 {
3731 Type=UnwindType(Type);
3732 }
3733 if (is_basic_sort(PosType))
3734 {
3735 PosType=UnwindType(PosType);
3736 }
3737 if (is_container_sort(Type))
3738 {
3739 const container_sort& s=down_cast<container_sort>(Type);
3740 const container_type& ConsType = s.container_name();
3741 if (is_list_container(ConsType))
3742 {
3743 if (!sort_list::is_list(PosType))
3744 {
3745 return false;
3746 }
3747 sort_expression Res;
3748 if (!TypeMatchA(s.element_sort(),down_cast<container_sort>(PosType).element_sort(),Res))
3749 {
3750 return false;
3751 }
3752 result=sort_list::list(Res);
3753 return true;
3754 }
3755
3756 if (is_set_container(ConsType))
3757 {
3758 if (!sort_set::is_set(PosType))
3759 {
3760 return false;
3761 }
3762 else
3763 {
3764 sort_expression Res;
3765 if (!TypeMatchA(s.element_sort(),down_cast<container_sort>(PosType).element_sort(),Res))
3766 {
3767 return false;
3768 }
3769 result=sort_set::set_(Res);
3770 return true;
3771 }
3772 }
3773
3774 if (is_bag_container(ConsType))
3775 {
3776 if (!sort_bag::is_bag(PosType))
3777 {
3778 return false;
3779 }
3780 else
3781 {
3782 sort_expression Res;
3783 if (!TypeMatchA(s.element_sort(),down_cast<container_sort>(PosType).element_sort(),Res))
3784 {
3785 return false;
3786 }
3787 result=sort_bag::bag(Res);
3788 return true;
3789 }
3790 }
3791
3792 if (is_fset_container(ConsType))
3793 {
3794 if (!sort_fset::is_fset(PosType))
3795 {
3796 return false;
3797 }
3798 else
3799 {
3800 sort_expression Res;
3801 if (!TypeMatchA(s.element_sort(),down_cast<container_sort>(PosType).element_sort(),Res))
3802 {
3803 return false;
3804 }
3805 result=sort_fset::fset(Res);
3806 return true;
3807 }
3808 }
3809
3810 if (is_fbag_container(ConsType))
3811 {
3812 if (!sort_fbag::is_fbag(PosType))
3813 {
3814 return false;
3815 }
3816 else
3817 {
3818 sort_expression Res;
3819 if (!TypeMatchA(s.element_sort(),down_cast<container_sort>(PosType).element_sort(),Res))
3820 {
3821 return false;
3822 }
3823 result=sort_fbag::fbag(Res);
3824 return true;
3825 }
3826 }
3827 }
3828
3829 if (is_function_sort(Type))
3830 {
3831 if (!is_function_sort(PosType))
3832 {
3833 return false;
3834 }
3835 else
3836 {
3837 const function_sort& fs=down_cast<const function_sort>(Type);
3838 const function_sort& posfs=down_cast<const function_sort>(PosType);
3839 sort_expression_list ArgTypes;
3840 if (!TypeMatchL(fs.domain(),posfs.domain(),ArgTypes))
3841 {
3842 return false;
3843 }
3844 sort_expression ResType;
3845 if (!TypeMatchA(fs.codomain(),posfs.codomain(),ResType))
3846 {
3847 return false;
3848 }
3849 result=function_sort(ArgTypes,ResType);
3850 return true;
3851 }
3852 }
3853
3854 return false;
3855}
3856
3857
3859{
3860 // append the Type to the entry of the Name of the OpId in system constants table
3861
3862 const core::identifier_string& OpIdName = f.name();
3863 const sort_expression& Type = f.sort();
3864
3865 std::map<core::identifier_string,sort_expression_list>::const_iterator i=system_constants.find(OpIdName);
3866
3868 if (i!=system_constants.end())
3869 {
3870 Types=i->second;
3871 }
3872 Types=push_back(Types,Type);
3873 system_constants[OpIdName]=Types;
3874}
3875
3877{
3878 //Pre: OpId is an OpId
3879 // append the Type to the entry of the Name of the OpId in gssystem.functions table
3880 const core::identifier_string& OpIdName = f.name();
3881 const sort_expression& Type = f.sort();
3882 assert(is_function_sort(Type));
3883
3884 const std::map <core::identifier_string,sort_expression_list>::const_iterator j=system_functions.find(OpIdName);
3885
3887 if (j!=system_functions.end())
3888 {
3889 Types=j->second;
3890 }
3891 Types=Types + sort_expression_list({ Type }); // TODO: Avoid concatenate but the order is essential.
3892 system_functions[OpIdName]=Types;
3893}
3894
3895void mcrl2::data::data_type_checker::add_system_constants_and_functions(const std::vector<data::function_symbol>& v)
3896{
3897 for(const function_symbol& f: v)
3898 {
3899 if (is_function_sort(f.sort()))
3900 {
3901 add_system_function(f);
3902 }
3903 else
3904 {
3905 add_system_constant(f);
3906 }
3907 }
3908}
3909
3911{
3912 //Creation of operation identifiers for system defined operations.
3913 //Bool
3914 add_system_function(if_(data::untyped_sort()));
3915 add_system_function(less(data::untyped_sort()));
3916 add_system_function(less_equal(data::untyped_sort()));
3917 add_system_function(greater_equal(data::untyped_sort()));
3918 add_system_function(greater(data::untyped_sort()));
3919 add_system_function(equal_to(data::untyped_sort()));
3920 add_system_function(not_equal_to(data::untyped_sort()));
3921
3922 //Bool
3923 add_system_constants_and_functions(sort_bool::bool_mCRL2_usable_constructors());
3924 add_system_constants_and_functions(sort_bool::bool_mCRL2_usable_mappings());
3925 // add_system_constants_and_functions(sort_bool::bool_generate_constructors_and_functions_code());
3926
3927 //Numbers
3928 add_system_constants_and_functions(sort_pos::pos_mCRL2_usable_constructors());
3929 add_system_constants_and_functions(sort_pos::pos_mCRL2_usable_mappings());
3930 assert(system_constants.find(sort_pos::c1().name())!=system_constants.end());
3931 // This function is explicitly required by the typechecker.
3932 // It adds it and then typechecks the terms containing this function.
3933 add_system_constants_and_functions(sort_nat::nat_mCRL2_usable_constructors());
3934 add_system_constants_and_functions(sort_nat::nat_mCRL2_usable_mappings());
3935#ifdef MCRL2_ENABLE_MACHINENUMBERS
3936 assert(system_functions.find(sort_nat::pos2nat().name())!=system_functions.end());
3937#else
3938 assert(system_functions.find(sort_nat::cnat().name())!=system_functions.end());
3939#endif
3940 // This function is explicitly required by the typechecker.
3941 // It adds it and then typechecks the terms containing this function.
3942 add_system_constants_and_functions(sort_int::int_mCRL2_usable_constructors());
3943 add_system_constants_and_functions(sort_int::int_mCRL2_usable_mappings());
3944 assert(system_functions.find(sort_int::cint().name())!=system_functions.end());
3945 // This function is explicitly required by the typechecker.
3946 // It adds it and then typechecks the terms containing this function.
3947 add_system_constants_and_functions(sort_real::real_mCRL2_usable_constructors());
3948 add_system_constants_and_functions(sort_real::real_mCRL2_usable_mappings());
3949 assert(system_functions.find(sort_real::creal().name())!=system_functions.end());
3950 // This function is explicitly required by the typechecker.
3951 // It adds it and then typechecks the terms containing this function.
3952
3953 //Lists
3954 add_system_constants_and_functions(sort_list::list_mCRL2_usable_constructors(data::untyped_sort()));
3955 add_system_constants_and_functions(sort_list::list_mCRL2_usable_mappings(data::untyped_sort()));
3956
3957 //FSets
3958 add_system_constants_and_functions(sort_fset::fset_mCRL2_usable_constructors(data::untyped_sort()));
3959 add_system_constants_and_functions(sort_fset::fset_mCRL2_usable_mappings(data::untyped_sort()));
3960
3961 //Sets
3962 // add_system_constants_and_functions(sort_set::set_mCRL2_usable_constructors(data::untyped_sort()));
3963 // add_system_constants_and_functions(sort_set::set_mCRL2_usable_mappings(data::untyped_sort()));
3964 add_system_function(sort_set::false_function(data::untyped_sort())); // Needed as it is used within the typechecker.
3965 add_system_function(sort_set::constructor(data::untyped_sort())); // Needed as it is used within the typechecker.
3966
3978 // **** add_system_function(sort_bag::set2bag(data::untyped_sort()));
3979 // add_system_constant(sort_set::empty(data::untyped_sort()));
3980 // add_system_function(sort_set::in(data::untyped_sort()));
3981 // add_system_function(sort_set::union_(data::untyped_sort()));
3982 // add_system_function(sort_set::difference(data::untyped_sort()));
3983 // add_system_function(sort_set::intersection(data::untyped_sort()));
3984 add_system_function(sort_set::complement(data::untyped_sort()));
3985
3986 //FBags
3987 add_system_constants_and_functions(sort_fbag::fbag_mCRL2_usable_constructors(data::untyped_sort()));
3988 add_system_constants_and_functions(sort_fbag::fbag_mCRL2_usable_mappings(data::untyped_sort()));
3989 /* add_system_constant(sort_fbag::empty(data::untyped_sort()));
3990 // add_system_function(sort_fbag::count(data::untyped_sort()));
3991 // add_system_function(sort_fbag::in(data::untyped_sort()));
3992 // add_system_function(sort_fbag::union_(data::untyped_sort()));
3993 // add_system_function(sort_fbag::intersection(data::untyped_sort()));
3994 // add_system_function(sort_fbag::difference(data::untyped_sort()));
3995 add_system_function(sort_fbag::count_all(data::untyped_sort()));
3996 add_system_function(sort_fbag::cinsert(data::untyped_sort())); // Needed as it is used within the typechecker. */
3997
3998 //Bags
3999 add_system_function(sort_bag::bag2set(data::untyped_sort()));
4000 add_system_function(sort_bag::set2bag(data::untyped_sort()));
4014 // add_system_constant(sort_bag::empty(data::untyped_sort()));
4015 // add_system_function(sort_bag::in(data::untyped_sort()));
4016 //**** add_system_function(sort_bag::count(data::untyped_sort()));
4017 // add_system_function(sort_bag::count(data::untyped_sort(), data::untyped_sort(), sort_fset::fset(data::untyped_sort())));
4018 //add_system_function(sort_bag::join(data::untyped_sort()));
4019 // add_system_function(sort_bag::difference(data::untyped_sort()));
4020 // add_system_function(sort_bag::intersection(data::untyped_sort()));
4021 add_system_function(sort_bag::zero_function(data::untyped_sort())); // Needed as it is used within the typechecker.
4022 add_system_function(sort_bag::constructor(data::untyped_sort())); // Needed as it is used within the typechecker.
4023
4024 // function update
4025 // add_system_constants_and_functions(data::function_update_mCRL2_usable_constructors());
4027}
4028
4029void mcrl2::data::data_type_checker::add_function(const data::function_symbol& f, const std::string& msg, bool allow_double_decls)
4030{
4031 const sort_expression_list domain=function_sort(f.sort()).domain();
4032 const core::identifier_string& Name = f.name();
4033 const sort_expression& Sort = f.sort();
4034
4035 if (system_constants.count(Name)>0)
4036 {
4037 throw mcrl2::runtime_error("Attempt to redeclare the system constant with a " + msg + " " + data::pp(f) + ".");
4038 }
4039
4040 if (system_functions.count(Name)>0)
4041 {
4042 throw mcrl2::runtime_error("Attempt to redeclare a system function with a " + msg + " " + data::pp(f) + ".");
4043 }
4044
4045 std::map <core::identifier_string,sort_expression_list>::const_iterator j=user_functions.find(Name);
4046
4047 // the table user_functions contains a list of types for each
4048 // function name. We need to check if there is already such a type
4049 // in the list. If so -- error, otherwise -- add
4050 if (j!=user_functions.end())
4051 {
4052 sort_expression_list Types=j->second;
4053 if (InTypesA(Sort, Types))
4054 {
4055 if (!allow_double_decls)
4056 {
4057 throw mcrl2::runtime_error("Double declaration of " + msg + " " + core::pp(Name) + ".");
4058 }
4059 }
4060 Types = Types + sort_expression_list({ UnwindType(Sort) });
4061 user_functions[Name]=Types;
4062 }
4063 else
4064 {
4065 user_functions[Name] = sort_expression_list({ UnwindType(Sort) });
4066 }
4067}
4068
4070{
4071 if (is_basic_sort(sort_expr))
4072 {
4073 check_basic_sort_is_declared(down_cast<basic_sort>(sort_expr));
4074 return;
4075 }
4076
4077 if (is_container_sort(sort_expr))
4078 {
4079 return read_sort(down_cast<container_sort>(sort_expr).element_sort());
4080 }
4081
4082 if (is_function_sort(sort_expr))
4083 {
4084 const function_sort& fs = atermpp::down_cast<function_sort>(sort_expr);
4085 read_sort(fs.codomain());
4086
4087 for (const sort_expression& s: fs.domain())
4088 {
4089 read_sort(s);
4090 }
4091 return;
4092 }
4093
4094 if (is_structured_sort(sort_expr))
4095 {
4096 // The map below is used to warn that there are projections with the same name
4097 // in this structured sort. This hardly ever serves a purpose and gives rise confusion.
4098 std::map<core::identifier_string, sort_expression> duplicate_projections_warner;
4099 const structured_sort& struct_sort = atermpp::down_cast<structured_sort>(sort_expr);
4100 for (const structured_sort_constructor& constr: struct_sort.constructors())
4101 {
4102 // recognizer -- if present -- a function from SortExpr to Bool
4103 core::identifier_string Name=constr.recogniser();
4105 {
4106 add_function(data::function_symbol(Name,function_sort(sort_expression_list({ sort_expr }),sort_bool::bool_())),"recognizer");
4107 }
4108
4109 // constructor type and projections
4110 const structured_sort_constructor_argument_list& Projs=constr.arguments();
4111 Name=constr.name();
4112 if (Projs.empty())
4113 {
4114 add_constant(data::function_symbol(Name,sort_expr),"constructor constant");
4115 continue;
4116 }
4117
4118 sort_expression_list ConstructorType;
4119 for (const structured_sort_constructor_argument& proj: Projs)
4120 {
4121 if (!proj.name().empty() && duplicate_projections_warner.count(proj.name())>0 && duplicate_projections_warner[proj.name()]!=proj.sort())
4122 {
4123 mCRL2log(warning) << "Warning. Projection function " << proj.name() << " occurs multiple times with different sorts in " << struct_sort << ". " << std::endl;
4124 }
4125 else
4126 {
4127 duplicate_projections_warner[proj.name()]=proj.sort();
4128 }
4129 const sort_expression& proj_sort=proj.sort();
4130
4131 // not to forget, recursive call for proj_sort ;-)
4132 read_sort(proj_sort);
4133
4134 const core::identifier_string& proj_name=proj.name();
4135 if (proj_name!=core::empty_identifier_string())
4136 {
4137 add_function(function_symbol(proj_name,function_sort(sort_expression_list({ sort_expr }),proj_sort)),"projection",true);
4138 }
4139 ConstructorType.push_front(proj_sort);
4140 }
4141 add_function(data::function_symbol(Name,function_sort(reverse(ConstructorType),sort_expr)),"constructor");
4142 }
4143 return;
4144 }
4145}
4146
4148{
4149 for (const sort_expression& s: TypeList)
4150 {
4151 if (EqTypesA(s,Type))
4152 {
4153 return TypeList;
4154 }
4155 }
4156 sort_expression_list result=TypeList;
4157 result.push_front(Type);
4158 return result;
4159}
4160
4161
4162
4163
4165{
4166 //Checks if Type is allowed by PosType
4168 {
4169 return true;
4170 }
4171 if (is_untyped_possible_sorts(PosType))
4172 {
4173 return InTypesA(Type,down_cast<const untyped_possible_sorts>(PosType).sorts());
4174 }
4175
4176 //PosType is a normal type
4177 return EqTypesA(Type,PosType);
4178}
4179
4181{
4182 //Checks if TypeList is allowed by PosTypeList (each respective element)
4183 assert(TypeList.size()==PosTypeList.size());
4185 for (sort_expression_list::const_iterator i=TypeList.begin(); i!=TypeList.end(); ++i,++j)
4186 if (!IsTypeAllowedA(*i,*j))
4187 {
4188 return false;
4189 }
4190 return true;
4191}
4192
4194{
4195 for (const sort_expression& Type: TypeList)
4196 {
4197 if (is_untyped_sort(Type) || is_untyped_possible_sorts(Type))
4198 {
4199 return true;
4200 }
4201 }
4202 return false;
4203}
4204
4205
4206
4208 const sort_expression_list& PosTypeList,
4209 const term_list<sort_expression_list>& TypeListList) const
4210{
4211 // PosTypeList -- List of Sortexpressions (possibly NotInferred(List Sortexpr))
4212 // TypeListList -- List of (Lists of Types)
4213 // returns: PosTypeList, adjusted to the elements of TypeListList
4214 // NULL if cannot be ajusted.
4215
4216 //if PosTypeList has only normal types -- check if it is in TypeListList,
4217 //if so return PosTypeList, otherwise return false.
4218 if (!IsNotInferredL(PosTypeList))
4219 {
4220 if (InTypesL(PosTypeList,TypeListList))
4221 {
4222 return std::make_pair(true,PosTypeList);
4223 }
4224 else
4225 {
4226 return std::make_pair(false, sort_expression_list());
4227 }
4228 }
4229
4230 //Filter TypeListList to contain only compatible with TypeList lists of parameters.
4231 term_list<sort_expression_list> NewTypeListList;
4233 i!=TypeListList.end(); ++i)
4234 {
4235 sort_expression_list TypeList= *i;
4236 if (IsTypeAllowedL(TypeList,PosTypeList))
4237 {
4238 NewTypeListList.push_front(TypeList);
4239 }
4240 }
4241 if (NewTypeListList.empty())
4242 {
4243 return std::make_pair(false, sort_expression_list());
4244 }
4245 if (NewTypeListList.size()==1)
4246 {
4247 return std::make_pair(true,NewTypeListList.front());
4248 }
4249
4250 // otherwise return not inferred.
4251 return std::make_pair(true,GetNotInferredList(reverse(NewTypeListList)));
4252}
4253
4254
4256{
4257 //we get: List of Lists of SortExpressions
4258 //Outer list: possible parameter types 0..nPosParsVectors-1
4259 //inner lists: parameter types vectors 0..nFormPars-1
4260
4261 //we constuct 1 vector (list) of sort expressions (NotInferred if ambiguous)
4262 //0..nFormPars-1
4263
4264 sort_expression_list Result;
4265 std::size_t nFormPars=TypeListList.front().size();
4266 std::vector<sort_expression_list> Pars(nFormPars);
4267 for (std::size_t i=0; i<nFormPars; i++)
4268 {
4269 Pars[i]=sort_expression_list();
4270 }
4271
4272 for (term_list<sort_expression_list>::const_iterator j=TypeListList.begin(); j!=TypeListList.end(); ++j)
4273 {
4274 sort_expression_list TypeList=*j;
4275 for (std::size_t i=0; i<nFormPars; TypeList=TypeList.tail(),i++)
4276 {
4277 Pars[i]=InsertType(Pars[i],TypeList.front());
4278 }
4279 }
4280
4281 for (std::size_t i=nFormPars; i>0; i--)
4282 {
4283 sort_expression Sort;
4284 if (Pars[i-1].size()==1)
4285 {
4286 Sort=Pars[i-1].front();
4287 }
4288 else
4289 {
4291 }
4292 Result.push_front(Sort);
4293 }
4294 return Result;
4295}
4296
4298 : sort_type_checker(data_spec),
4299 was_warning_upcasting(false)
4300{
4302
4303 try
4304 {
4306 {
4307 read_sort(a.reference());
4308 }
4310 }
4311 catch (mcrl2::runtime_error& e)
4312 {
4313 throw mcrl2::runtime_error(std::string(e.what()) + "\nType checking of data expression failed.");
4314 }
4315
4316 type_checked_data_spec=data_spec;
4317
4318 // Type check equations and add them to the specification.
4319 try
4320 {
4322 }
4323 catch (mcrl2::runtime_error& e)
4324 {
4325 type_checked_data_spec=data_specification(); // Type checking failed. Data specification is not usable.
4326 throw mcrl2::runtime_error(std::string(e.what()) + "\nFailed to type check data specification.");
4327 }
4328}
4329
4331 const data_expression& data_expr,
4332 const detail::variable_context& context_variables) const
4333{
4334 data_expression data=data_expr;
4335 sort_expression Type;
4336 try
4337 {
4338 Type=TraverseVarConsTypeD(context_variables,data,data::untyped_sort());
4339 }
4340 catch (mcrl2::runtime_error& e)
4341 {
4342 throw mcrl2::runtime_error(std::string(e.what()) + "\nType checking of data expression failed.");
4343 }
4344 if (data::is_untyped_sort(Type))
4345 {
4346 throw mcrl2::runtime_error("Type checking of data expression " + data::pp(data_expr) + " failed. Result is an unknown sort.");
4347 }
4348
4349 assert(strict_type_check(data));
4350 return data;
4351}
4352
4353
4355 const detail::variable_context& context_variables) const
4356{
4357 // First check whether the variable name clashes with a system or user defined function or constant.
4358 const std::map<core::identifier_string,sort_expression_list>::const_iterator i1=system_constants.find(v.name());
4359 if (i1!=system_constants.end())
4360 {
4361 throw mcrl2::runtime_error("The variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) +
4362 " clashes with the system defined constant " + core::pp(i1->first) + ":" + data::pp(i1->second.front()) + ".");
4363 }
4364 const std::map<core::identifier_string,sort_expression_list>::const_iterator i2=system_functions.find(v.name());
4365 if (i2!=system_functions.end())
4366 {
4367 throw mcrl2::runtime_error("The variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) +
4368 " clashes with the system defined function " + core::pp(i2->first) + ":" + data::pp(i2->second.front()) + ".");
4369 }
4370 const std::map<core::identifier_string,sort_expression>::const_iterator i3=user_constants.find(v.name());
4371 if (i3!=user_constants.end())
4372 {
4373 throw mcrl2::runtime_error("The variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) +
4374 " clashes with the user defined constant " + core::pp(i3->first) + ":" + data::pp(i3->second) + ".");
4375 }
4376 const std::map<core::identifier_string,sort_expression_list>::const_iterator i4=user_functions.find(v.name());
4377 if (i4!=user_functions.end())
4378 {
4379 throw mcrl2::runtime_error("The variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) +
4380 " clashes with the user defined function " + core::pp(i4->first) + ":" + data::pp(i4->second.front()) + ".");
4381 }
4382
4383 // Second, check that the variable has a valid sort.
4384 try
4385 {
4387 }
4388 catch (mcrl2::runtime_error& e)
4389 {
4390 throw mcrl2::runtime_error(std::string(e.what()) + "\nType error while typechecking the data variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) + ".");
4391 }
4392
4393 // Third, check that the variable did not occur in the context with a different type.
4394 const std::map<core::identifier_string,sort_expression>::const_iterator i=context_variables.context().find(v.name());
4395 sort_expression temp;
4396 if (i!=context_variables.context().end() && !TypeMatchA(i->second,v.sort(),temp))
4397 {
4398 throw mcrl2::runtime_error("The variable " + core::pp(v.name()) + ":" + data::pp(v.sort()) +
4399 " is used in its surrounding context with a different sort " + core::pp(i->second) + ".");
4400 }
4401}
4402
4403
4404
4406 const detail::variable_context& context_variables) const
4407{
4408 // Type check each variable.
4409 for (const variable& v: l)
4410 {
4411 (*this)(v, context_variables);
4412 }
4413
4414 // Check that all variable names are unique.
4415 std::set<core::identifier_string> variable_names;
4416 for (const variable& v: l)
4417 {
4418 if (!variable_names.insert(v.name()).second) // The variable name is already in the set.
4419 {
4420 throw mcrl2::runtime_error("The variable " + data::pp(v) + " occurs multiple times.");
4421 }
4422 }
4423}
4424
4425// ------------------------------ Here ends the new class based data expression checker -----------------------
4426// ------------------------------ Here starts the new class based data specification checker -----------------------
4427
4429{
4430 data_equation_vector resulting_equations;
4431 for (const data_equation& eqn: eqns)
4432 {
4433 const variable_list& vars=eqn.variables();
4434 try
4435 {
4436 // Typecheck the variables in an equation.
4437 (*this)(vars,detail::variable_context());
4438 }
4439 catch (mcrl2::runtime_error& e)
4440 {
4441 throw mcrl2::runtime_error(std::string(e.what()) + "\nThis error occurred while typechecking equation " + data::pp(eqn) + ".");
4442 }
4443
4444 detail::variable_context DeclaredVars;
4445 DeclaredVars.add_context_variables(vars);
4446
4447 data_expression left=eqn.lhs();
4448
4449 sort_expression leftType;
4450 try
4451 {
4452 leftType=TraverseVarConsTypeD(DeclaredVars,left,data::untyped_sort(),true,true);
4453 }
4454 catch (mcrl2::runtime_error& e)
4455 {
4456 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking " + data::pp(left) + " as left hand side of equation " + data::pp(eqn) + ".");
4457 }
4458
4459 if (was_warning_upcasting)
4460 {
4461 was_warning_upcasting=false;
4462 mCRL2log(warning) << "Warning occurred while typechecking " << left << " as left hand side of equation " << eqn << "." << std::endl;
4463 }
4464
4465 data_expression cond=eqn.condition();
4466 TraverseVarConsTypeD(DeclaredVars,cond,sort_bool::bool_());
4467
4468 data_expression right=eqn.rhs();
4469 sort_expression rightType;
4470 try
4471 {
4472 rightType=TraverseVarConsTypeD(DeclaredVars,right,leftType,false);
4473 }
4474 catch (mcrl2::runtime_error& e)
4475 {
4476 throw mcrl2::runtime_error(std::string(e.what()) + "\nError occurred while typechecking " + data::pp(right) + " as right hand side of equation " + data::pp(eqn) + ".");
4477 }
4478
4479 //If the types are not uniquely the same now: do once more:
4480 if (!EqTypesA(leftType,rightType))
4481 {
4482 sort_expression Type;
4483 if (!TypeMatchA(leftType,rightType,Type))
4484 {
4485 throw mcrl2::runtime_error("Types of the left- (" + data::pp(leftType) + ") and right- (" + data::pp(rightType) + ") hand-sides of the equation " + data::pp(eqn) + " do not match.");
4486 }
4487 left=eqn.lhs();
4488 try
4489 {
4490 leftType=TraverseVarConsTypeD(DeclaredVars,left,Type,true);
4491 }
4492 catch (mcrl2::runtime_error& e)
4493 {
4494 throw mcrl2::runtime_error(std::string(e.what()) + "\nTypes of the left- and right-hand-sides of the equation " + data::pp(eqn) + " do not match.");
4495 }
4496 if (was_warning_upcasting)
4497 {
4498 was_warning_upcasting=false;
4499 mCRL2log(warning) << "Warning occurred while typechecking " << left << " as left hand side of equation " << eqn << "." << std::endl;
4500 }
4501 right=eqn.rhs();
4502 try
4503 {
4504 rightType=TraverseVarConsTypeD(DeclaredVars,right,leftType);
4505 }
4506 catch (mcrl2::runtime_error& e)
4507 {
4508 throw mcrl2::runtime_error(std::string(e.what()) + "\nTypes of the left- and right-hand-sides of the equation " + data::pp(eqn) + " do not match.");
4509 }
4510 if (!TypeMatchA(leftType,rightType,Type))
4511 {
4512 throw mcrl2::runtime_error("Types of the left- (" + data::pp(leftType) + ") and right- (" + data::pp(rightType) + ") hand-sides of the equation " + data::pp(eqn) + " do not match.");
4513 }
4514 if (detail::HasUnknown(Type))
4515 {
4516 throw mcrl2::runtime_error("Types of the left- (" + data::pp(leftType) + ") and right- (" + data::pp(rightType) + ") hand-sides of the equation " + data::pp(eqn) + " cannot be uniquely determined.");
4517 }
4518 // Check that the variable in the condition and the right hand side are a subset of those in the left hand side of the equation.
4519 const std::set<variable> vars_in_lhs=find_free_variables(left);
4520 const std::set<variable> vars_in_rhs=find_free_variables(right);
4521
4522 variable culprit;
4523 if (!detail::includes(vars_in_rhs,vars_in_lhs,culprit))
4524 {
4525 throw mcrl2::runtime_error("The variable " + data::pp(culprit) + " in the right hand side is not included in the left hand side of the equation " + data::pp(eqn) + ".");
4526 }
4527
4528 const std::set<variable> vars_in_condition=find_free_variables(cond);
4529 if (!detail::includes(vars_in_condition,vars_in_lhs,culprit))
4530 {
4531 throw mcrl2::runtime_error("The variable " + data::pp(culprit) + " in the condition is not included in the left hand side of the equation " + data::pp(eqn) + ".");
4532 }
4533 }
4534 resulting_equations.push_back(data_equation(vars,cond,left,right));
4535 }
4536 eqns = resulting_equations;
4537}
4538
4539// Type check and replace user defined equations.
4541{
4542
4543 //Create a new specification; admittedly, this is somewhat clumsy.
4544 data_specification new_specification;
4545 for(const basic_sort& s: data_spec.user_defined_sorts())
4546 {
4547 new_specification.add_sort(s);
4548 }
4549 for(const alias& a: data_spec.user_defined_aliases())
4550 {
4551 new_specification.add_alias(a);
4552 }
4553 for(const function_symbol& f: data_spec.user_defined_constructors())
4554 {
4555 new_specification.add_constructor(f);
4556 }
4557 for(const function_symbol& f: data_spec.user_defined_mappings())
4558 {
4559 new_specification.add_mapping(f);
4560 }
4561
4563 operator ()(eqns); // Type check the equations.
4564 for(const data_equation& eqn: eqns)
4565 {
4566 new_specification.add_equation(eqn);
4567 }
4568
4569 std::map<std::pair<data_expression, data_expression>, data_equation> lhs_map;
4570 for (const data_equation& eqn: new_specification.user_defined_equations())
4571 {
4572 const auto find_result = lhs_map.find(std::make_pair(eqn.condition(), eqn.lhs()));
4573 if(find_result != lhs_map.end())
4574 {
4575 mCRL2log(warning) << "Warning: condition and left-hand side of equations " << find_result->second << " and " << eqn << " completely overlap." << std::endl;
4576 }
4577 else
4578 {
4579 lhs_map[std::make_pair(eqn.condition(), eqn.lhs())] = eqn;
4580 }
4581 }
4582 data_spec=new_specification;
4583}
4584
4586{
4587 return type_checked_data_spec;
4588}
4589
4590// ------------------------------ Here ends the new class based data specification checker -----------------------
4591
4592
4593
4594
4595
4596namespace data
4597{
4598namespace detail
4599{
4600
4602{
4603 sort_expression_list Result;
4604 for (const variable& VarDecl: VarDecls)
4605 {
4606 Result.push_front(VarDecl.sort());
4607 }
4608 return reverse(Result);
4609}
4610
4611// Replace occurrences of untyped_possible_sorts([s1,...,sn]) by selecting
4612// one of the possible sorts from s1,...,sn. Currently, the first is chosen.
4614{
4616 {
4617 return atermpp::down_cast<untyped_possible_sorts>(Type).sorts().front(); // get the first element of the possible sorts.
4618 }
4619 if (data::is_untyped_sort(data::sort_expression(Type)))
4620 {
4621 return data::untyped_sort();
4622 }
4623 if (is_basic_sort(Type))
4624 {
4625 return Type;
4626 }
4627 if (is_container_sort(Type))
4628 {
4629 const container_sort& s=down_cast<container_sort>(Type);
4631 }
4632
4633 if (is_structured_sort(Type))
4634 {
4635 return Type; // I assume that there are no possible sorts in sort constructors. JFG.
4636 }
4637
4638 if (is_function_sort(Type))
4639 {
4640 const function_sort& s=down_cast<function_sort>(Type);
4641 sort_expression_list NewTypeList;
4642 for (sort_expression_list::const_iterator TypeList=s.domain().begin(); TypeList!=s.domain().end(); ++TypeList)
4643 {
4644 NewTypeList.push_front(replace_possible_sorts(*TypeList));
4645 }
4646 const sort_expression& ResultType=s.codomain();
4647 return function_sort(reverse(NewTypeList),replace_possible_sorts(ResultType));
4648 }
4649 assert(0); // All cases are dealt with above.
4650 return Type; // Avoid compiler warnings.
4651}
4652
4653
4654static bool HasUnknown(const sort_expression& Type)
4655{
4656 if (data::is_untyped_sort(data::sort_expression(Type)))
4657 {
4658 return true;
4659 }
4660 if (is_basic_sort(Type))
4661 {
4662 return false;
4663 }
4664 if (is_container_sort(Type))
4665 {
4666 return HasUnknown(down_cast<container_sort>(Type).element_sort());
4667 }
4668 if (is_structured_sort(Type))
4669 {
4670 return false;
4671 }
4672
4673 if (is_function_sort(Type))
4674 {
4675 const function_sort& s=down_cast<function_sort>(Type);
4676 for (sort_expression_list::const_iterator TypeList=s.domain().begin(); TypeList!=s.domain().end(); ++TypeList)
4677 if (HasUnknown(*TypeList))
4678 {
4679 return true;
4680 }
4681 return HasUnknown(s.codomain());
4682 }
4683
4684 return true;
4685}
4686
4687static bool IsNumericType(const sort_expression& Type)
4688{
4689 //returns true if Type is Bool,Pos,Nat,Int or Real
4690 //otherwise return fase
4691 if (data::is_untyped_sort(Type))
4692 {
4693 return false;
4694 }
4695 return (bool)(sort_bool::is_bool(Type)||
4696 sort_pos::is_pos(Type)||
4697 sort_nat::is_nat(Type)||
4698 sort_int::is_int(Type)||
4699 sort_real::is_real(Type));
4700}
4701
4702
4704{
4705 return TypeList.front();
4706}
4707
4708} //namespace detail
4709} //namespace data
4710}
Term containing a string.
const_iterator end() const
Returns a const_iterator pointing past the last argument.
Definition aterm.h:172
const_iterator begin() const
Returns an iterator pointing to the first argument.
Definition aterm.h:165
const function_symbol & function() const
Returns the function symbol belonging to an aterm.
Definition aterm.h:144
const std::string & name() const
Return the name of the function_symbol.
Iterator for term_appl.
Iterator for term_list.
A list of aterm objects.
Definition aterm_list.h:24
size_type size() const
Returns the size of the term_list.
Definition aterm_list.h:256
const_iterator end() const
Returns a const_iterator pointing to the end of the term_list.
Definition aterm_list.h:282
const term_list< Term > & tail() const
Returns the tail of the list.
Definition aterm_list.h:225
const Term & front() const
Returns the first element of the list.
Definition aterm_list.h:239
void pop_front()
Removes the first element of the list.
Definition aterm_list.h:232
const_iterator begin() const
Returns a const_iterator pointing to the beginning of the term_list.
Definition aterm_list.h:275
bool empty() const
Returns true if the list's size is 0.
Definition aterm_list.h:268
void push_front(const Term &el)
Inserts a new element at the beginning of the current list.
void swap(unprotected_aterm_core &t) noexcept
Swaps this term with its argument.
Definition aterm_core.h:152
bool defined() const
Returns true if this term is not equal to the term assigned by the default constructor of aterms,...
Definition aterm_core.h:143
An abstraction expression.
Definition abstraction.h:26
const variable_list & variables() const
Definition abstraction.h:63
const data_expression & body() const
Definition abstraction.h:68
const binder_type & binding_operator() const
Definition abstraction.h:58
\brief A sort alias
Definition alias.h:26
An application of a data expression to a number of arguments.
const_iterator end() const
Returns an iterator pointing past the last argument of the application.
const_iterator begin() const
Returns an iterator pointing to the first argument of the application.
const data_expression & head() const
Get the function at the head of this expression.
std::size_t size() const
\brief Assignment expression
Definition assignment.h:27
\brief Assignment of a data expression to a variable
Definition assignment.h:91
const data_expression & rhs() const
Definition assignment.h:122
const variable & lhs() const
Definition assignment.h:117
\brief Binder for bag comprehension
\brief Container type for bags
\brief A basic sort
Definition basic_sort.h:26
\brief A container sort
const container_type & container_name() const
const sort_expression & element_sort() const
\brief Container type
\brief A data equation
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:108
const function_symbol_vector & user_defined_constructors() const
Gets the constructors defined by the user, excluding those that are system defined.
void add_mapping(const function_symbol &f)
Adds a mapping to this specification.
void add_equation(const data_equation &e)
Adds an equation to this specification.
const function_symbol_vector & user_defined_mappings() const
Gets all user defined mappings in this specification.
const data_equation_vector & user_defined_equations() const
Gets all user defined equations.
void add_constructor(const function_symbol &f)
Adds a constructor to this specification.
const function_symbol_vector & constructors() const
Gets all constructors including those that are system defined.
bool IsNotInferredL(sort_expression_list TypeList) const
bool TypeMatchL(const sort_expression_list &TypeList, const sort_expression_list &PosTypeList, sort_expression_list &result) const
bool UnFBag(sort_expression PosType, sort_expression &result) const
bool MatchIf(const function_sort &type, sort_expression &result) const
sort_expression TraverseVarConsTypeD(const detail::variable_context &DeclaredVars, data_expression &DataTerm, const sort_expression &PosType, const bool strictly_ambiguous=true, const bool warn_upcasting=false, const bool print_cast_error=true) const
bool MatchFalseFunction(const function_sort &type, sort_expression &result) const
bool MatchListOpCons(const function_sort &type, sort_expression &result) const
bool UnifyMinType(const sort_expression &Type1, const sort_expression &Type2, sort_expression &result) const
bool MatchListOpEltAt(const function_sort &type, sort_expression &result) const
const data_specification operator()() const
Yields a type checked data specification, provided typechecking was successful. If not successful an ...
bool EqTypesA(const sort_expression &Type1, const sort_expression &Type2) const
sort_expression UpCastNumericType(sort_expression NeededType, sort_expression Type, data_expression &Par, const detail::variable_context &DeclaredVars, const bool strictly_ambiguous, bool warn_upcasting=false, const bool print_cast_error=false) const
bool UnifyElementSort(sort_expression &Arg1, sort_expression &Arg2, sort_expression &result) const
bool MatchListSetBagOpIn(const function_sort &type, sort_expression &result) const
bool match_fbag_cinsert(const function_sort &type, sort_expression &result) const
bool MatchSqrt(const function_sort &type, sort_expression &result) const
bool MatchBagOpBag2Set(const function_sort &type, sort_expression &result) const
void read_constructors_and_mappings(const function_symbol_vector &constructors, const function_symbol_vector &mappings, const function_symbol_vector &normalized_constructors)
bool MatchEqNeqComparison(const function_sort &type, sort_expression &result) const
bool InTypesL(const sort_expression_list &Type, atermpp::term_list< sort_expression_list > Types) const
sort_expression UnwindType(const sort_expression &Type) const
bool strict_type_check(const data_expression &d) const
Definition typecheck.cpp:84
bool MatchBagConstructor(const function_sort &type, sort_expression &result) const
bool MatchBagOpBagCount(const function_sort &type, sort_expression &result) const
sort_expression ExpandNumTypesUp(sort_expression Type) const
sort_expression ExpandNumTypesDown(sort_expression Type) const
sort_expression_list ExpandNumTypesUpL(const sort_expression_list &type_list) const
void add_constant(const data::function_symbol &f, const std::string &msg)
bool MatchSetBagOpUnionDiffIntersect(const core::identifier_string &data_term_name, const function_sort &type, sort_expression &result) const
bool MatchListOpSnoc(const function_sort &type, sort_expression &result) const
bool UnFSet(sort_expression PosType, sort_expression &result) const
bool MatchListOpConcat(const function_sort &type, sort_expression &result) const
void add_system_function(const data::function_symbol &f)
void TransformVarConsTypeData(data_specification &data_spec)
void add_system_constants_and_functions(const std::vector< data::function_symbol > &v)
bool IsTypeAllowedA(const sort_expression &Type, const sort_expression &PosType) const
bool MatchSetOpSetCompl(const function_sort &type, sort_expression &result) const
void initialise_system_defined_functions(void)
bool InTypesA(const sort_expression &Type, sort_expression_list Types) const
bool MaximumType(const sort_expression &Type1, const sort_expression &Type2, sort_expression &result) const
data_type_checker(const data_specification &data_spec)
make a data type checker. Throws a mcrl2::runtime_error exception if the data_specification is not we...
bool UnList(sort_expression PosType, sort_expression &result) const
bool MatchFuncUpdate(const function_sort &type, sort_expression &result) const
void add_system_constant(const data::function_symbol &f)
bool MatchSetOpSet2Bag(const function_sort &type, sort_expression &result) const
std::pair< bool, sort_expression_list > AdjustNotInferredList(const sort_expression_list &PosTypeList, const atermpp::term_list< sort_expression_list > &TypeListList) const
bool EqTypesL(sort_expression_list Type1, sort_expression_list Type2) const
sort_expression determine_allowed_type(const data_expression &d, const sort_expression &proposed_type) const
void add_function(const data::function_symbol &f, const std::string &msg, bool allow_double_decls=false)
sort_expression_list GetNotInferredList(const atermpp::term_list< sort_expression_list > &TypeListList) const
void read_sort(const sort_expression &SortExpr)
bool MatchListOpHead(const function_sort &type, sort_expression &result) const
bool match_fset_insert(const function_sort &type, sort_expression &result) const
sort_expression TraverseVarConsTypeDN(const detail::variable_context &DeclaredVars, data_expression &DataTerm, sort_expression PosType, const bool strictly_ambiguous=true, const std::size_t nFactPars=std::string::npos, const bool warn_upcasting=false, const bool print_cast_error=true) const
sort_expression_list InsertType(const sort_expression_list &TypeList, const sort_expression &Type) const
bool UnArrowProd(const sort_expression_list &ArgTypes, sort_expression PosType, sort_expression &result) const
bool TypeMatchA(const sort_expression &Type_in, const sort_expression &PosType_in, sort_expression &result) const
bool IsTypeAllowedL(const sort_expression_list &TypeList, const sort_expression_list &PosTypeList) const
bool MatchSetConstructor(const function_sort &type, sort_expression &result) const
data_specification type_checked_data_spec
Definition typecheck.h:35
bool MatchListOpTail(const function_sort &type, sort_expression &result) const
void typecheck_variable(const data_type_checker &typechecker, const variable &v) const
Definition typecheck.cpp:25
void add_context_variables(const VariableContainer &variables)
const std::map< core::identifier_string, sort_expression > & context() const
\brief A function sort
const sort_expression & codomain() const
const sort_expression_list & domain() const
\brief A function symbol
const core::identifier_string & name() const
const sort_expression & sort() const
\brief Binder for set comprehension
\brief Container type for sets
\brief A sort expression
const basic_sort_vector & user_defined_sorts() const
Gets all sorts defined by a user (excluding the system defined sorts).
void add_alias(const alias &a)
Adds an alias (new name for a sort) to this specification.
void add_sort(const basic_sort &s)
Adds a sort to this specification.
const alias_vector & user_defined_aliases() const
Gets the user defined aliases.
const sort_specification & get_sort_specification() const
void check_sort_is_declared(const sort_expression &x) const
\brief An argument of a constructor of a structured sort
\brief A constructor for a structured sort
const structured_sort_constructor_list & constructors() const
\brief Assignment of a data expression to a string
Definition assignment.h:182
const core::identifier_string & lhs() const
Definition assignment.h:213
const data_expression & rhs() const
Definition assignment.h:218
\brief An untyped identifier
const sort_expression_list & sorts() const
\brief Unknown sort expression
\brief A data variable
Definition variable.h:28
const core::identifier_string & name() const
Definition variable.h:38
const sort_expression & sort() const
Definition variable.h:43
\brief A where expression
const data_expression & body() const
const assignment_expression_list & declarations() const
Standard exception class for reporting runtime errors.
Definition exception.h:27
Provides utilities for pretty printing.
add your file description here.
@ variable_
Definition linearise.cpp:80
#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
term_list< Term > reverse(const term_list< Term > &l)
Returns the list with the elements in reversed order.
term_list< Term > push_back(const term_list< Term > &l, const Term &el)
Appends a new element at the end of the list. Note that the complexity of this function is O(n),...
identifier_string empty_identifier_string()
Provides the empty identifier string.
std::string pp(const identifier_string &x)
Definition core.cpp:26
static bool HasUnknown(const sort_expression &Type)
static bool includes(const std::set< variable > &s1, const std::set< variable > &s2, variable &culprit)
Definition typecheck.cpp:32
atermpp::term_list< S > insert_sort_unique(const atermpp::term_list< S > &list, const S &el)
Definition typecheck.cpp:63
static bool IsPos(const core::identifier_string &Number)
Definition typecheck.cpp:45
static sort_expression MinType(const sort_expression_list &TypeList)
static bool IsNat(const core::identifier_string &Number)
Definition typecheck.cpp:50
static bool IsNumericType(const sort_expression &Type)
static sort_expression replace_possible_sorts(const sort_expression &Type)
static sort_expression_list GetVarTypes(variable_list VarDecls)
function_symbol difference(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition bag1.h:612
const core::identifier_string & set2bag_name()
Generate identifier Set2Bag.
Definition bag1.h:759
const core::identifier_string & zero_function_name()
Generate identifier @zero_.
Definition bag1.h:821
function_symbol bag2set(const sort_expression &s)
Constructor for function symbol Bag2Set.
Definition bag1.h:707
function_symbol intersection(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition bag1.h:511
function_symbol count(const sort_expression &, const sort_expression &s0, const sort_expression &s1)
Definition bag1.h:298
function_symbol set2bag(const sort_expression &s)
Constructor for function symbol Set2Bag.
Definition bag1.h:769
const core::identifier_string & bag2set_name()
Generate identifier Bag2Set.
Definition bag1.h:697
core::identifier_string const & bag_enumeration_name()
Generate identifier bag_enumeration.
function_symbol constructor(const sort_expression &s)
Constructor for function symbol @bag.
Definition bag1.h:78
const core::identifier_string & constructor_name()
Generate identifier @bag.
Definition bag1.h:68
function_symbol in(const sort_expression &, const sort_expression &s0, const sort_expression &s1)
Definition bag1.h:362
function_symbol bag_enumeration(const sort_expression &s)
Constructor for function symbol bag_enumeration.
function_symbol union_(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition bag1.h:426
const core::identifier_string & count_name()
Generate identifier count.
Definition bag1.h:290
bool is_bag(const sort_expression &e)
Recogniser for sort expression Bag(s)
Definition bag1.h:55
container_sort bag(const sort_expression &s)
Constructor for sort expression Bag(S)
Definition bag1.h:44
function_symbol zero_function(const sort_expression &s)
Constructor for function symbol @zero_.
Definition bag1.h:831
function_symbol_vector bool_mCRL2_usable_mappings()
Give all system defined mappings that can be used in mCRL2 specs for bool_.
Definition bool.h:442
function_symbol_vector bool_mCRL2_usable_constructors()
Give all defined constructors which can be used in mCRL2 specs for bool_.
Definition bool.h:141
bool is_bool(const sort_expression &e)
Recogniser for sort expression Bool.
Definition bool.h:54
const basic_sort & bool_()
Constructor for sort expression Bool.
Definition bool.h:44
container_sort fbag(const sort_expression &s)
Constructor for sort expression FBag(S)
Definition fbag1.h:43
const core::identifier_string & cinsert_name()
Generate identifier @fbag_cinsert.
Definition fbag1.h:267
bool is_fbag(const sort_expression &e)
Recogniser for sort expression FBag(s)
Definition fbag1.h:54
function_symbol_vector fbag_mCRL2_usable_mappings(const sort_expression &s)
Give all system defined mappings that can be used in mCRL2 specs for fbag.
Definition fbag1.h:810
function_symbol_vector fbag_mCRL2_usable_constructors(const sort_expression &s)
Give all defined constructors which can be used in mCRL2 specs for fbag.
Definition fbag1.h:177
bool is_fset(const sort_expression &e)
Recogniser for sort expression FSet(s)
Definition fset1.h:52
function_symbol_vector fset_mCRL2_usable_mappings(const sort_expression &s)
Give all system defined mappings that can be used in mCRL2 specs for fset.
Definition fset1.h:676
function_symbol_vector fset_mCRL2_usable_constructors(const sort_expression &s)
Give all defined constructors which can be used in mCRL2 specs for fset.
Definition fset1.h:173
const core::identifier_string & insert_name()
Generate identifier @fset_insert.
Definition fset1.h:97
container_sort fset(const sort_expression &s)
Constructor for sort expression FSet(S)
Definition fset1.h:41
function_symbol_vector int_mCRL2_usable_mappings()
Give all system defined mappings that can be used in mCRL2 specs for int_.
Definition int1.h:1444
bool is_int(const sort_expression &e)
Recogniser for sort expression Int.
Definition int1.h:57
function_symbol_vector int_mCRL2_usable_constructors()
Give all defined constructors which can be used in mCRL2 specs for int_.
Definition int1.h:204
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
const core::identifier_string & rtail_name()
Generate identifier rtail.
Definition list1.h:702
const core::identifier_string & snoc_name()
Generate identifier <|.
Definition list1.h:324
function_symbol_vector list_mCRL2_usable_constructors(const sort_expression &s)
Give all defined constructors which can be used in mCRL2 specs for list.
Definition list1.h:174
const core::identifier_string & tail_name()
Generate identifier tail.
Definition list1.h:578
const core::identifier_string & rhead_name()
Generate identifier rhead.
Definition list1.h:640
const core::identifier_string & in_name()
Generate identifier in.
Definition list1.h:198
const core::identifier_string & head_name()
Generate identifier head.
Definition list1.h:516
const core::identifier_string & cons_name()
Generate identifier |>.
Definition list1.h:98
const core::identifier_string & concat_name()
Generate identifier ++.
Definition list1.h:388
function_symbol_vector list_mCRL2_usable_mappings(const sort_expression &s)
Give all system defined mappings that can be used in mCRL2 specs for list.
Definition list1.h:797
const core::identifier_string & element_at_name()
Generate identifier ..
Definition list1.h:452
function_symbol list_enumeration(const sort_expression &s)
Constructor for function symbol list_enumeration.
container_sort list(const sort_expression &s)
Constructor for sort expression List(S)
Definition list1.h:42
core::identifier_string const & list_enumeration_name()
Generate identifier list_enumeration.
bool is_list(const sort_expression &e)
Recogniser for sort expression List(s)
Definition list1.h:53
const basic_sort & machine_word()
Constructor for sort expression @word.
const function_symbol & cnat()
Constructor for function symbol @cNat.
Definition nat1.h:140
function_symbol_vector nat_mCRL2_usable_mappings()
Give all system defined mappings that can be used in mCRL2 specs for nat.
Definition nat1.h:2154
const basic_sort & nat()
Constructor for sort expression Nat.
Definition nat1.h:46
bool is_nat(const sort_expression &e)
Recogniser for sort expression Nat.
Definition nat1.h:56
function_symbol_vector nat_mCRL2_usable_constructors()
Give all defined constructors which can be used in mCRL2 specs for nat.
Definition nat1.h:267
const core::identifier_string & sqrt_name()
Generate identifier sqrt.
Definition nat1.h:1653
const function_symbol & pos2nat()
Constructor for function symbol Pos2Nat.
Definition nat1.h:300
bool is_pos(const sort_expression &e)
Recogniser for sort expression Pos.
Definition pos1.h:55
const function_symbol & c1()
Constructor for function symbol @c1.
Definition pos1.h:78
function_symbol_vector pos_mCRL2_usable_constructors()
Give all defined constructors which can be used in mCRL2 specs for pos.
Definition pos1.h:174
const basic_sort & pos()
Constructor for sort expression Pos.
Definition pos1.h:45
function_symbol_vector pos_mCRL2_usable_mappings()
Give all system defined mappings that can be used in mCRL2 specs for pos.
Definition pos1.h:733
const function_symbol & creal()
Constructor for function symbol @cReal.
Definition real1.h:107
const basic_sort & real_()
Constructor for sort expression Real.
Definition real1.h:48
function_symbol_vector real_mCRL2_usable_constructors()
Give all defined constructors which can be used in mCRL2 specs for real_.
Definition real1.h:78
bool is_real(const sort_expression &e)
Recogniser for sort expression Real.
Definition real1.h:58
function_symbol_vector real_mCRL2_usable_mappings()
Give all system defined mappings that can be used in mCRL2 specs for real_.
Definition real1.h:1891
const core::identifier_string & constructor_name()
Generate identifier @set.
Definition set1.h:66
bool is_set(const sort_expression &e)
Recogniser for sort expression Set(s)
Definition set1.h:53
core::identifier_string const & set_enumeration_name()
Generate identifier set_enumeration.
const core::identifier_string & false_function_name()
Generate identifier @false_.
Definition set1.h:657
function_symbol set_enumeration(const sort_expression &s)
Constructor for function symbol set_enumeration.
const core::identifier_string & complement_name()
Generate identifier !.
Definition set1.h:352
function_symbol intersection(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition set1.h:499
container_sort set_(const sort_expression &s)
Constructor for sort expression Set(S)
Definition set1.h:42
const core::identifier_string & intersection_name()
Generate identifier *.
Definition set1.h:491
function_symbol constructor(const sort_expression &s)
Constructor for function symbol @set.
Definition set1.h:76
function_symbol false_function(const sort_expression &s)
Constructor for function symbol @false_.
Definition set1.h:667
const core::identifier_string & union_name()
Generate identifier +.
Definition set1.h:414
function_symbol in(const sort_expression &, const sort_expression &s0, const sort_expression &s1)
Definition set1.h:296
function_symbol union_(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition set1.h:422
const core::identifier_string & difference_name()
Generate identifier -.
Definition set1.h:576
function_symbol difference(const sort_expression &s, const sort_expression &s0, const sort_expression &s1)
Definition set1.h:584
function_symbol complement(const sort_expression &s)
Constructor for function symbol !.
Definition set1.h:362
Namespace for all data library functionality.
Definition abstraction.h:22
bool is_structured_sort(const atermpp::aterm &x)
Returns true if the term t is a structured sort.
function_symbol_vector function_update_mCRL2_usable_mappings(const sort_expression &s, const sort_expression &t)
Give all system defined mappings that can be used in mCRL2 specs for function_update.
function_symbol less_equal(const sort_expression &s)
Constructor for function symbol <=.
Definition standard.h:277
bool is_set_container(const atermpp::aterm &x)
function_symbol not_equal_to(const sort_expression &s)
Constructor for function symbol !=.
Definition standard.h:163
std::vector< sort_expression > sort_expression_vector
\brief vector of sort_expressions
bool is_list_container(const atermpp::aterm &x)
function_symbol less(const sort_expression &s)
Constructor for function symbol <.
Definition standard.h:240
bool is_where_clause(const atermpp::aterm &x)
Returns true if the term t is a where clause.
const core::identifier_string & function_update_name()
Generate identifier @func_update.
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_abstraction(const atermpp::aterm &x)
Returns true if the term t is an abstraction.
std::vector< data_equation > data_equation_vector
\brief vector of data_equations
bool is_untyped_identifier(const atermpp::aterm &x)
Returns true if the term t is an identifier.
bool is_set_comprehension_bi