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