mCRL2
Loading...
Searching...
No Matches
is_well_typed.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
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/// \file mcrl2/lps/is_well_typed.h
10/// \brief Well-typedness checks for linear process specifications.
11
12#ifndef MCRL2_LPS_IS_WELL_TYPED_H
13#define MCRL2_LPS_IS_WELL_TYPED_H
14
15#include "mcrl2/data/detail/sequence_algorithm.h"
16#include "mcrl2/lps/detail/action_utility.h"
17#include "mcrl2/lps/stochastic_specification.h"
18#include <boost/iterator/transform_iterator.hpp>
19
20namespace mcrl2::lps::detail
21{
22
23/// \brief Function object for applying a substitution to LPS data types.
25{
26 // The result of the last well typedness check.
27 bool result = false;
28
29 // Error message are written to the output stream error.
31
32 /// \brief Checks if the sort of t has type real
33 bool check_time(const data::data_expression& t, const std::string& type) const
34 {
36 {
37 error << "is_well_typed(" << type << ") failed: time " << t << " doesn't have sort real." << std::endl;
38 return false;
39 }
40 return true;
41 }
42
43 /// \brief Checks if the sort of t has type bool
44 bool check_condition(const data::data_expression& t, const std::string& type) const
45 {
47 {
48 error << "is_well_typed(" << type << ") failed: condition " << t << " doesn't have sort bool." << std::endl;
49 return false;
50 }
51 return true;
52 }
53
54 /// \brief Checks if the assignments are well typed and have unique left hand sides
55 bool check_assignments(const data::assignment_list& l, const std::string& type) const
56 {
57 if (!is_well_typed_container(l))
58 {
59 error << "is_well_typed(" << type << ") failed: the assignments " << l << " are not well typed." << std::endl;
60 return false;
61 }
62 auto lhs = [](const data::assignment& a) { return a.lhs(); };
63 if (data::detail::sequence_contains_duplicates(
64 boost::make_transform_iterator(l.begin(), lhs),
65 boost::make_transform_iterator(l.end() , lhs)
66 )
67 )
68 {
69 error << "is_well_typed(" << type << ") failed: data assignments " << l << " don't have unique left hand sides." << std::endl;
70 return false;
71 }
72 return true;
73 }
74
75 /// \brief Checks well typedness of the elements of a container
76 template <typename Container>
77 bool is_well_typed_container(const Container& c) const
78 {
79 for (auto i = c.begin(); i != c.end(); ++i)
80 {
81 if (!is_well_typed(*i))
82 {
83 return false;
84 }
85 }
86 return true;
87 }
88
89 /// \brief Checks well typedness of a sort expression.
90 /// \param d A sort expression.
91 bool is_well_typed(const data::sort_expression& d) const
92 {
93 (void)d; // Suppress an unused variable warning.
94 return true;
95 }
96
97 /// \brief Checks well typedness of a variable.
98 /// \param d A variable.
99 bool is_well_typed(const data::variable& d) const
100 {
101 (void)d; // Suppress an unused variable warning.
102 return true;
103 }
104
105 /// \brief Checks well typedness of a data expression
106 /// \param d A data expression
107 bool is_well_typed(const data::data_expression& d) const
108 {
109 (void)d; // Suppress an unused variable warning.
110 return true;
111 }
112
113 /// \brief Traverses an assignment
114 /// \param a An assignment
115 bool is_well_typed(const data::assignment& a) const
116 {
118 {
119 std::clog << "is_well_typed(data_assignment) failed: the left and right hand sides "
120 << a.lhs() << " and " << a.rhs() << " have different sorts." << std::endl;
121 return false;
122 }
123 return true;
124 }
125
126 /// \brief Traverses an action label.
127 /// \param d An action label.
128 bool is_well_typed(const process::action_label& d) const
129 {
130 (void)d; // Suppress an unused variable warning.
131 return true;
132 }
133
134 /// \brief Traverses an action.
135 /// \param a An action.
136 bool is_well_typed(const process::action& a) const
137 {
138 (void)a; // Suppress an unused variable warning.
139 return true;
140 }
141
142 /// \brief Checks well typedness of a deadlock
143 /// \param d A deadlock
144 /// \return Returns true if
145 /// <ul>
146 /// <li>the (optional) time has sort Real</li>
147 /// </ul>
148 bool is_well_typed(const deadlock& d) const
149 {
150 if (d.has_time())
151 {
152 check_time(d.time(), "deadlock");
153 }
154 return true;
155 }
156
157 /// \brief Checks well typedness of a multi-action
158 /// \param a A multi-action
159 /// \return Returns true if
160 /// <ul>
161 /// <li>the (optional) time has sort Real</li>
162 /// </ul>
163 bool is_well_typed(const multi_action& a) const
164 {
165 if (a.has_time())
166 {
167 check_time(a.time(), "multi_action");
168 }
169 return true;
170 }
171
172 /// \brief Checks well typedness of a summand
173 /// \param s An action summand
174 bool is_well_typed(const action_summand& s) const
175 {
176 if (!data::detail::unique_names(s.summation_variables()))
177 {
178 error << "is_well_typed(action_summand) failed: summation variables " << core::detail::print_list(s.summation_variables()) << " don't have unique names." << std::endl;
179 return false;
180 }
181 if (!check_condition(s.condition(), "action_summand"))
182 {
183 return false;
184 }
185 if (!is_well_typed(s.multi_action()))
186 {
187 return false;
188 }
189 if (!check_assignments(s.assignments(), "action_summand"))
190 {
191 return false;
192 }
193 return true;
194 }
195
196 /// \brief Checks well typedness of a summand
197 /// \param s A summand
198 bool is_well_typed(const deadlock_summand& s) const
199 {
200 if (!check_condition(s.condition(), "deadlock_summand"))
201 {
202 return false;
203 }
204 if (!is_well_typed(s.deadlock()))
205 {
206 return false;
207 }
208 return true;
209 }
210
211 /// \brief Checks well typedness of a linear process
212 /// \param p A linear_process
213 /// \return True if
214 /// <ul>
215 /// <li>the process parameters have unique names</li>
216 /// <li>process parameters and summation variables have different names</li>
217 /// <li>the left hand sides of the assignments of summands are contained in the process parameters</li>
218 /// <li>the summands are well typed</li>
219 /// </ul>
220 template <typename ActionSummand>
221 bool is_well_typed(const linear_process_base<ActionSummand>& p) const
222 {
223 // check 2)
224 if (!data::detail::unique_names(p.process_parameters()))
225 {
226 error << "is_well_typed(linear_process) failed: process parameters " << core::detail::print_list(p.process_parameters()) << " don't have unique names." << std::endl;
227 return false;
228 }
229
230 // check 4)
231 std::set<core::identifier_string> names;
232 for (auto i = p.process_parameters().begin(); i != p.process_parameters().end(); ++i)
233 {
234 names.insert(i->name());
235 }
236 for (auto i = p.action_summands().begin(); i != p.action_summands().end(); ++i)
237 {
238 if (!data::detail::check_variable_names(i->summation_variables(), names))
239 {
240 error << "is_well_typed(linear_process) failed: some of the names of the summation variables " << core::detail::print_list(i->summation_variables()) << " also appear as process parameters." << std::endl;
241 return false;
242 }
243 }
244
245 // check 5)
246 for (auto i = p.action_summands().begin(); i != p.action_summands().end(); ++i)
247 {
248 if (!data::detail::check_assignment_variables(i->assignments(), p.process_parameters()))
249 {
250 error << "is_well_typed(linear_process) failed: some left hand sides of the assignments " << core::detail::print_list(i->assignments()) << " do not appear as process parameters." << std::endl;
251 return false;
252 }
253 }
254
255 // check 6)
256 if (!is_well_typed_container(p.action_summands()))
257 {
258 return false;
259 }
260 if (!is_well_typed_container(p.deadlock_summands()))
261 {
262 return false;
263 }
264 return true;
265 }
266
267 /// \brief Checks well typedness of a linear process specification.
268 /// \param spec A linear process specification.
269 /// \param free_variables Free variables that can be used.
270 /// \return True if
271 /// <ul>
272 /// <li>the sorts occurring in the summation variables are declared in the data specification</li>
273 /// <li>the sorts occurring in the process parameters are declared in the data specification </li>
274 /// <li>the sorts occurring in the free variables are declared in the data specification </li>
275 /// <li>the sorts occurring in the action labels are declared in the data specification </li>
276 /// <li>the action labels occurring in the process are contained in action_labels() </li>
277 /// <li>the process is well typed </li>
278 /// <li>the data specification is well typed </li>
279 /// <li>the initial process is well typed </li>
280 /// <li>the free variables occurring in the linear process are declared in the global variable specification</li>
281 /// <li>the free variables occurring in the initial process are declared in the global variable specification</li>
282 /// <li>the global variables have unique names</li>
283 /// </ul>
284 template <typename LinearProcess, typename InitialProcessExpression>
285 bool is_well_typed(const specification_base<LinearProcess, InitialProcessExpression>& spec,
286 const std::set<data::variable>& free_variables) const
287 {
288 std::set<data::sort_expression> declared_sorts = data::detail::make_set(spec.data().sorts());
289 std::set<process::action_label> declared_labels = data::detail::make_set(spec.action_labels());
290 auto const& action_summands = spec.process().action_summands();
291
292 // check 1)
293 for (auto i = action_summands.begin(); i != action_summands.end(); ++i)
294 {
295 if (!(data::detail::check_variable_sorts(i->summation_variables(), declared_sorts)))
296 {
297 error << "is_well_typed(specification) failed: some of the sorts of the summation variables " << core::detail::print_list(i->summation_variables()) << " are not declared in the data specification " << core::detail::print_list(spec.data().sorts()) << std::endl;
298 return false;
299 }
300 }
301
302 // check 2)
303 if (!(data::detail::check_variable_sorts(spec.process().process_parameters(), declared_sorts)))
304 {
305 error << "is_well_typed(specification) failed: some of the sorts of the process parameters " << core::detail::print_list(spec.process().process_parameters()) << " are not declared in the data specification " << core::detail::print_list(spec.data().sorts()) << std::endl;
306 return false;
307 }
308
309 // check 3)
310 if (!(data::detail::check_variable_sorts(spec.global_variables(), declared_sorts)))
311 {
312 error << "is_well_typed(specification) failed: some of the sorts of the free variables " << core::detail::print_list(spec.global_variables()) << " are not declared in the data specification " << core::detail::print_list(spec.data().sorts()) << std::endl;
313 return false;
314 }
315
316 // check 4)
317 if (!(detail::check_action_label_sorts(spec.action_labels(), declared_sorts)))
318 {
319 error << "is_well_typed(specification) failed: some of the sorts occurring in the action labels " << core::detail::print_list(spec.action_labels()) << " are not declared in the data specification " << core::detail::print_list(spec.data().sorts()) << std::endl;
320 return false;
321 }
322
323 // check 5)
324 for (const action_summand& s: action_summands)
325 {
326 if (!(detail::check_action_labels(s.multi_action().actions(), declared_labels)))
327 {
328 error << "is_well_typed(specification) failed: some of the labels occurring in the actions " << core::detail::print_list(s.multi_action().actions()) << " are not declared in the action specification " << core::detail::print_list(spec.action_labels()) << std::endl;
329 return false;
330 }
331 }
332 if (!is_well_typed(spec.process()))
333 {
334 return false;
335 }
336 if (!spec.data().is_well_typed())
337 {
338 return false;
339 }
340 if (!free_variables.empty())
341 {
342 error << "is_well_typed(specification) failed: some of the free variables were not declared\n";
343 error << "declared global variables: " << core::detail::print_list(spec.global_variables()) << std::endl;
344 error << "occurring free variables: " << core::detail::print_list(free_variables) << std::endl;
345 return false;
346 }
347
348 // check 3)
349 if (!data::detail::unique_names(spec.global_variables()))
350 {
351 error << "is_well_typed(specification) failed: global variables " << core::detail::print_list(spec.global_variables()) << " don't have unique names." << std::endl;
352 return false;
353 }
354
355 return true;
356 }
357
358 bool is_well_typed(const specification& spec) const
359 {
360 std::set<data::variable> free_variables = lps::find_free_variables(spec);
361 return is_well_typed(spec, free_variables);
362 }
363
365 {
366 std::set<data::variable> free_variables = lps::find_free_variables(spec);
367 return is_well_typed(spec, free_variables);
368 }
369
370 template <typename Term>
371 bool operator()(const Term& t) const
372 {
373 return is_well_typed(t);
374 }
375};
376
377/// \brief Checks well typedness of an LPS object.
378template <typename T>
379bool is_well_typed(const T& x)
380{
382 return checker(x);
383}
384
385/// \brief Checks well typedness of an LPS object, and will print error messages to stderr.
386template <typename T>
387bool check_well_typedness(const T& x)
388{
390 bool result = checker(x);
391 if (!result)
392 {
393 mCRL2log(log::error) << checker.error.str();
394 }
395 return result;
396}
397
398} // namespace mcrl2::lps::detail
399
400#endif // MCRL2_LPS_IS_WELL_TYPED_H
\brief Assignment of a data expression to a variable
Definition assignment.h:88
const data_expression & rhs() const
Definition assignment.h:119
const variable & lhs() const
Definition assignment.h:114
sort_expression sort() const
Returns the sort of the data expression.
Definition data.cpp:107
\brief A sort expression
\brief A data variable
Definition variable.h:25
const sort_expression & sort() const
Definition variable.h:40
Action rename specification.
process::action_label_list & action_labels()
Returns the sequence of action labels.
LPS summand containing a multi-action.
data::data_expression_list next_state(const data::variable_list &process_parameters) const
Returns the next state corresponding to this summand.
Definition lps.cpp:71
LPS summand containing a deadlock.
Represents a deadlock.
Definition deadlock.h:23
bool has_time() const
Returns true if time is available.
Definition deadlock.h:39
\brief A timed multi-action
bool has_time() const
Returns true if time is available.
multi_action & operator=(multi_action &&) noexcept=default
Linear process specification.
\brief An action label
\brief An untyped multi action or data application
D_ParserTables parser_tables_mcrl2
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:392
static data_specification const & default_specification()
Definition parse.h:28
bool check_assignment_variables(assignment_list const &assignments, variable_list const &variables)
Returns true if the left hand sides of assignments are contained in variables.
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
Namespace for system defined sort real_.
bool is_real(const sort_expression &e)
Recogniser for sort expression Real.
Definition real1.h:55
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
bool is_well_typed(const T &x)
Checks well typedness of an LPS object.
multi_action complete_multi_action(process::untyped_multi_action &x, const process::action_label_list &action_decls, const data::data_specification &data_spec=data::detail::default_specification())
Definition lps.cpp:148
bool check_well_typedness(const T &x)
Checks well typedness of an LPS object, and will print error messages to stderr.
void complete_action_rename_specification(action_rename_specification &x, const lps::stochastic_specification &spec)
Definition lps.cpp:166
process::untyped_multi_action parse_multi_action_new(const std::string &text)
Definition lps.cpp:130
multi_action complete_multi_action(process::untyped_multi_action &x, multi_action_type_checker &typechecker, const data::data_specification &data_spec=data::detail::default_specification())
Definition lps.cpp:140
action_rename_specification parse_action_rename_specification_new(const std::string &text)
Definition lps.cpp:156
The main namespace for the LPS library.
Definition constelm.h:18
std::string pp(const lps::stochastic_specification &x, bool arg0)
Definition lps.cpp:40
std::set< data::variable > find_all_variables(const lps::linear_process &x)
Definition lps.cpp:47
std::string pp(const lps::specification &x, bool arg0)
Definition lps.cpp:35
std::set< data::sort_expression > find_sort_expressions(const lps::stochastic_specification &x)
Definition lps.cpp:46
std::string pp_extended(const lps::stochastic_specification &x, const std::string &process_name, bool precedence_aware=true)
Definition lps.cpp:79
std::set< process::action_label > find_action_labels(const lps::stochastic_specification &x)
Definition lps.cpp:68
std::set< data::variable > find_free_variables(const lps::stochastic_specification &x)
Definition lps.cpp:56
std::string pp(const lps::stochastic_distribution &x, bool arg0)
Definition lps.cpp:37
std::string pp_extended(const stochastic_specification &x, const std::string &process_name, bool precedence_aware, bool summand_numbers)
Definition lps.cpp:98
std::set< data::variable > find_all_variables(const lps::multi_action &x)
Returns all variables inside a multi-action.
Definition lps.cpp:52
std::set< data::variable > find_all_variables(const lps::stochastic_specification &x)
Definition lps.cpp:50
bool check_well_typedness(const specification &x)
Definition lps.cpp:118
std::set< data::variable > find_free_variables(const lps::linear_process &x)
Definition lps.cpp:53
bool check_well_typedness(const linear_process &x)
Definition lps.cpp:108
std::set< data::function_symbol > find_function_symbols(const lps::stochastic_specification &x)
Definition lps.cpp:62
std::string pp_extended(const specification &x, const std::string &process_name, bool precedence_aware, bool summand_numbers)
Definition lps.cpp:88
std::set< process::action_label > find_action_labels(const lps::process_initializer &x)
Definition lps.cpp:66
std::set< data::variable > find_free_variables(const lps::specification &x)
Definition lps.cpp:55
multi_action typecheck_multi_action(process::untyped_multi_action &mult_act, const data::data_specification &data_spec, const process::action_label_list &action_decls)
Type check a multi action Throws an exception if something went wrong.
Definition typecheck.h:125
void normalize_sorts(lps::specification &x, const data::sort_specification &)
Definition lps.cpp:42
std::set< data::variable > find_free_variables(const lps::deadlock &x)
Definition lps.cpp:57
std::string pp(const lps::deadlock_summand &x, bool arg0)
Definition lps.cpp:31
std::set< process::action_label > find_action_labels(const lps::linear_process &x)
Definition lps.cpp:65
lps::multi_action normalize_sorts(const lps::multi_action &x, const data::sort_specification &sortspec)
Definition lps.cpp:41
std::set< data::variable > find_free_variables(const lps::stochastic_linear_process &x)
Definition lps.cpp:54
multi_action typecheck_multi_action(process::untyped_multi_action &mult_act, multi_action_type_checker &typechecker)
Type check a multi action Throws an exception if something went wrong.
Definition typecheck.h:141
std::set< data::function_symbol > find_function_symbols(const lps::specification &x)
Definition lps.cpp:61
std::string pp(const lps::stochastic_linear_process &x, bool arg0)
Definition lps.cpp:38
std::set< data::variable > find_free_variables(const lps::stochastic_process_initializer &x)
Definition lps.cpp:60
std::set< data::variable > find_free_variables(const lps::multi_action &x)
Definition lps.cpp:58
std::string pp(const lps::deadlock &x, bool arg0)
Definition lps.cpp:30
void normalize_sorts(lps::stochastic_specification &x, const data::sort_specification &)
Definition lps.cpp:43
std::set< data::variable > find_free_variables(const lps::process_initializer &x)
Definition lps.cpp:59
std::string pp(const lps::stochastic_action_summand &x, bool arg0)
Definition lps.cpp:36
std::string pp(const lps::stochastic_process_initializer &x, bool arg0)
Definition lps.cpp:39
std::string pp(const lps::linear_process &x, bool arg0)
Definition lps.cpp:32
std::string pp(const lps::multi_action &x, bool arg0)
Definition lps.cpp:33
std::set< data::sort_expression > find_sort_expressions(const lps::specification &x)
Definition lps.cpp:45
std::string pp(const lps::action_summand &x, bool arg0)
Definition lps.cpp:29
std::set< data::variable > find_all_variables(const lps::specification &x)
Definition lps.cpp:49
bool check_well_typedness(const stochastic_specification &x)
Definition lps.cpp:123
std::set< data::variable > find_all_variables(const lps::deadlock &x)
Definition lps.cpp:51
action_rename_specification typecheck_action_rename_specification(const action_rename_specification &arspec, const lps::stochastic_specification &lpsspec)
Type checks an action rename specification.
Definition typecheck.h:154
std::set< data::variable > find_all_variables(const lps::stochastic_linear_process &x)
Definition lps.cpp:48
bool check_well_typedness(const stochastic_linear_process &x)
Definition lps.cpp:113
lps::multi_action translate_user_notation(const lps::multi_action &x)
Definition lps.cpp:44
std::set< core::identifier_string > find_identifiers(const lps::stochastic_specification &x)
Definition lps.cpp:64
std::set< core::identifier_string > find_identifiers(const lps::specification &x)
Definition lps.cpp:63
std::set< process::action_label > find_action_labels(const lps::specification &x)
Definition lps.cpp:67
std::string pp(const lps::process_initializer &x, bool arg0)
Definition lps.cpp:34
The main namespace for the Process library.
lps::action_rename_specification parse_ActionRenameSpec(const core::parse_node &node) const
Definition parse_impl.h:119
action_rename_actions(const core::parser &parser_)
Definition parse_impl.h:42
Function object for applying a substitution to LPS data types.
bool is_well_typed(const linear_process_base< ActionSummand > &p) const
Checks well typedness of a linear process.
bool is_well_typed(const process::action &a) const
Traverses an action.
bool is_well_typed(const action_summand &s) const
Checks well typedness of a summand.
bool check_time(const data::data_expression &t, const std::string &type) const
Checks if the sort of t has type real.
bool is_well_typed(const data::assignment &a) const
Traverses an assignment.
bool check_condition(const data::data_expression &t, const std::string &type) const
Checks if the sort of t has type bool.
bool is_well_typed(const stochastic_specification &spec) const
bool is_well_typed(const data::variable &d) const
Checks well typedness of a variable.
bool check_assignments(const data::assignment_list &l, const std::string &type) const
Checks if the assignments are well typed and have unique left hand sides.
bool is_well_typed(const specification &spec) const
bool is_well_typed(const data::sort_expression &d) const
Checks well typedness of a sort expression.
bool is_well_typed_container(const Container &c) const
Checks well typedness of the elements of a container.
bool is_well_typed(const process::action_label &d) const
Traverses an action label.
bool is_well_typed(const specification_base< LinearProcess, InitialProcessExpression > &spec, const std::set< data::variable > &free_variables) const
Checks well typedness of a linear process specification.
bool is_well_typed(const deadlock &d) const
Checks well typedness of a deadlock.
bool is_well_typed(const data::data_expression &d) const
Checks well typedness of a data expression.
bool is_well_typed(const deadlock_summand &s) const
Checks well typedness of a summand.
bool is_well_typed(const multi_action &a) const
Checks well typedness of a multi-action.
process::untyped_multi_action parse_MultAct(const core::parse_node &node) const
Definition parse_impl.h:29
multi_action_actions(const core::parser &parser_)
Definition parse_impl.h:25