1 /* |
|
2 * matiec - a compiler for the programming languages defined in IEC 61131-3 |
|
3 * |
|
4 * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) |
|
5 * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant |
|
6 * |
|
7 * This program is free software: you can redistribute it and/or modify |
|
8 * it under the terms of the GNU General Public License as published by |
|
9 * the Free Software Foundation, either version 3 of the License, or |
|
10 * (at your option) any later version. |
|
11 * |
|
12 * This program is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 * GNU General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License |
|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
19 * |
|
20 * |
|
21 * This code is made available on the understanding that it will not be |
|
22 * used in safety-critical situations without a full and competent review. |
|
23 */ |
|
24 |
|
25 /* |
|
26 * An IEC 61131-3 compiler. |
|
27 * |
|
28 * Based on the |
|
29 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
30 * |
|
31 */ |
|
32 |
|
33 |
|
34 /* Determine the data type of an ST expression. |
|
35 * A reference to the relevant type definition is returned. |
|
36 * |
|
37 * For example: |
|
38 * 2 + 3 -> returns reference to a int_type_name_c object. |
|
39 * 22.2 - 5 -> returns reference to a real_type_name_c object. |
|
40 * etc... |
|
41 */ |
|
42 |
|
43 |
|
44 |
|
45 #include "absyntax_utils.hh" |
|
46 #include <typeinfo> |
|
47 |
|
48 search_expression_type_c::search_expression_type_c(symbol_c *search_scope) { |
|
49 search_varfb_instance_type = new search_varfb_instance_type_c(search_scope); |
|
50 } |
|
51 |
|
52 search_expression_type_c::~search_expression_type_c(void) { |
|
53 delete search_varfb_instance_type; |
|
54 } |
|
55 |
|
56 /* A helper function... */ |
|
57 bool search_expression_type_c::is_bool_type(symbol_c *type_symbol) { |
|
58 bool_type_name_c tt; |
|
59 if (type_symbol == NULL) {return true;} |
|
60 if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} |
|
61 if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} |
|
62 if (typeid(*type_symbol) == typeid(boolean_true_c)) {return true;} |
|
63 if (typeid(*type_symbol) == typeid(boolean_false_c)) {return true;} |
|
64 return false; |
|
65 } |
|
66 |
|
67 /* A helper function... */ |
|
68 bool search_expression_type_c::is_time_type(symbol_c *type_symbol) { |
|
69 if (type_symbol == NULL) {return true;} |
|
70 if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;} |
|
71 if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;} |
|
72 if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;} |
|
73 if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;} |
|
74 if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;} |
|
75 if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;} |
|
76 if (typeid(*type_symbol) == typeid(safetod_type_name_c)) {return true;} |
|
77 if (typeid(*type_symbol) == typeid(safedt_type_name_c)) {return true;} |
|
78 return false; |
|
79 } |
|
80 |
|
81 /* A helper function... */ |
|
82 bool search_expression_type_c::is_string_type(symbol_c *type_symbol) { |
|
83 if (type_symbol == NULL) {return true;} |
|
84 if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;} |
|
85 if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;} |
|
86 if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;} |
|
87 if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;} |
|
88 return false; |
|
89 } |
|
90 |
|
91 /* A helper function... */ |
|
92 bool search_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) { |
|
93 if (type_symbol == NULL) {return true;} |
|
94 if (typeid(*type_symbol) == typeid(integer_c)) {return true;} |
|
95 if (typeid(*type_symbol) == typeid(neg_integer_c)) {return true;} |
|
96 if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;} |
|
97 if (typeid(*type_symbol) == typeid(octal_integer_c)) {return true;} |
|
98 if (typeid(*type_symbol) == typeid(hex_integer_c)) {return true;} |
|
99 return false; |
|
100 } |
|
101 |
|
102 /* A helper function... */ |
|
103 bool search_expression_type_c::is_integer_type(symbol_c *type_symbol) { |
|
104 if (type_symbol == NULL) {return true;} |
|
105 if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;} |
|
106 if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;} |
|
107 if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;} |
|
108 if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;} |
|
109 if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;} |
|
110 if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;} |
|
111 if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;} |
|
112 if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;} |
|
113 if (typeid(*type_symbol) == typeid(safesint_type_name_c)) {return true;} |
|
114 if (typeid(*type_symbol) == typeid(safeint_type_name_c)) {return true;} |
|
115 if (typeid(*type_symbol) == typeid(safedint_type_name_c)) {return true;} |
|
116 if (typeid(*type_symbol) == typeid(safelint_type_name_c)) {return true;} |
|
117 if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;} |
|
118 if (typeid(*type_symbol) == typeid(safeuint_type_name_c)) {return true;} |
|
119 if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;} |
|
120 if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;} |
|
121 return is_literal_integer_type(type_symbol); |
|
122 } |
|
123 |
|
124 /* A helper function... */ |
|
125 bool search_expression_type_c::is_literal_real_type(symbol_c *type_symbol) { |
|
126 if (type_symbol == NULL) {return true;} |
|
127 if (typeid(*type_symbol) == typeid(real_c)) {return true;} |
|
128 if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;} |
|
129 return false; |
|
130 } |
|
131 |
|
132 /* A helper function... */ |
|
133 bool search_expression_type_c::is_real_type(symbol_c *type_symbol) { |
|
134 if (type_symbol == NULL) {return true;} |
|
135 if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;} |
|
136 if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;} |
|
137 if (typeid(*type_symbol) == typeid(safereal_type_name_c)) {return true;} |
|
138 if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;} |
|
139 return is_literal_real_type(type_symbol); |
|
140 } |
|
141 |
|
142 bool search_expression_type_c::is_num_type(symbol_c *type_symbol) { |
|
143 if (type_symbol == NULL) {return true;} |
|
144 return is_real_type(type_symbol) || is_integer_type(type_symbol); |
|
145 } |
|
146 |
|
147 bool search_expression_type_c::is_nbinary_type(symbol_c *type_symbol) { |
|
148 if (type_symbol == NULL) {return true;} |
|
149 if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;} |
|
150 if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;} |
|
151 if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;} |
|
152 if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;} |
|
153 if (typeid(*type_symbol) == typeid(safebyte_type_name_c)) {return true;} |
|
154 if (typeid(*type_symbol) == typeid(safeword_type_name_c)) {return true;} |
|
155 if (typeid(*type_symbol) == typeid(safedword_type_name_c)) {return true;} |
|
156 if (typeid(*type_symbol) == typeid(safelword_type_name_c)) {return true;} |
|
157 return is_literal_integer_type(type_symbol); |
|
158 } |
|
159 |
|
160 bool search_expression_type_c::is_binary_type(symbol_c *type_symbol) { |
|
161 if (type_symbol == NULL) {return true;} |
|
162 // if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} |
|
163 // if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;} |
|
164 return (is_nbinary_type(type_symbol) || is_bool_type(type_symbol)); |
|
165 } |
|
166 |
|
167 bool search_expression_type_c::is_same_type(symbol_c *first_type, symbol_c *second_type) { |
|
168 if (first_type == NULL || second_type == NULL) {return true;} |
|
169 if (typeid(*first_type) == typeid(*second_type)) {return true;} |
|
170 if (is_bool_type(first_type) && is_bool_type(second_type)) {return true;} |
|
171 if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return true;} |
|
172 if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return true;} |
|
173 if (is_binary_type(first_type) && is_literal_integer_type(second_type)) {return true;} |
|
174 if (is_literal_integer_type(first_type) && is_binary_type(second_type)) {return true;} |
|
175 if (is_real_type(first_type) && is_literal_real_type(second_type)) {return true;} |
|
176 if (is_literal_real_type(first_type) && is_real_type(second_type)) {return true;} |
|
177 return false; |
|
178 } |
|
179 |
|
180 symbol_c* search_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) { |
|
181 if (first_type == NULL && second_type == NULL) {return NULL;} |
|
182 if (first_type == NULL) {return second_type;} |
|
183 if (second_type == NULL) {return first_type;} |
|
184 if (typeid(*first_type) == typeid(*second_type)) {return first_type;} |
|
185 if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return first_type;} |
|
186 if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return second_type;} |
|
187 if (is_binary_type(first_type) && is_literal_integer_type(second_type)) {return first_type;} |
|
188 if (is_literal_integer_type(first_type) && is_binary_type(second_type)) {return second_type;} |
|
189 if (is_real_type(first_type) && is_literal_real_type(second_type)) {return first_type;} |
|
190 if (is_literal_real_type(first_type) && is_real_type(second_type)) {return second_type;} |
|
191 return NULL; |
|
192 } |
|
193 |
|
194 symbol_c *search_expression_type_c::default_literal_type(symbol_c* symbol) { |
|
195 if (is_literal_integer_type(symbol)) { |
|
196 return (symbol_c *)&search_constant_type_c::lint_type_name; |
|
197 } |
|
198 else if (is_literal_real_type(symbol)) { |
|
199 return (symbol_c *)&search_constant_type_c::lreal_type_name; |
|
200 } |
|
201 return symbol; |
|
202 } |
|
203 |
|
204 |
|
205 /* A helper function... */ |
|
206 void *search_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type) { |
|
207 if (!is_same_type(left_type, right_type)) |
|
208 ERROR; |
|
209 if (!is_bool_type(left_type) && !is_binary_type(left_type)) |
|
210 ERROR; |
|
211 if (is_literal_integer_type(left_type)) {return (void *)right_type;} |
|
212 else {return (void *)left_type;} |
|
213 } |
|
214 |
|
215 /* A helper function... */ |
|
216 void *search_expression_type_c::compute_numeric_expression(symbol_c *left_type, symbol_c *right_type) { |
|
217 if (!is_same_type(left_type, right_type)) |
|
218 ERROR; |
|
219 if (!is_integer_type(left_type) && !is_real_type(left_type)) |
|
220 ERROR; |
|
221 if (is_literal_integer_type(left_type) || is_literal_real_type(left_type)) {return (void *)right_type;} |
|
222 else {return (void *)left_type;} |
|
223 return NULL; |
|
224 } |
|
225 |
|
226 /* a helper function... */ |
|
227 symbol_c *search_expression_type_c::base_type(symbol_c *symbol) { |
|
228 return (symbol_c *)symbol->accept(search_base_type); |
|
229 } |
|
230 |
|
231 /*********************/ |
|
232 /* B 1.4 - Variables */ |
|
233 /*********************/ |
|
234 |
|
235 void *search_expression_type_c::visit(symbolic_variable_c *symbol) { |
|
236 symbol_c *res; |
|
237 |
|
238 /* Nope, now we assume it is a variable, and determine its type... */ |
|
239 res = search_varfb_instance_type->get_basetype_decl(symbol); |
|
240 if (NULL != res) return res; |
|
241 |
|
242 return NULL; |
|
243 } |
|
244 |
|
245 /********************************************/ |
|
246 /* B 1.4.1 - Directly Represented Variables */ |
|
247 /********************************************/ |
|
248 void *search_expression_type_c::visit(direct_variable_c *symbol) { |
|
249 symbol_c *res; |
|
250 |
|
251 /* Nope, now we assume it is a variable, and determine its type... */ |
|
252 res = search_varfb_instance_type->get_basetype_decl(symbol); |
|
253 if (NULL != res) return res; |
|
254 |
|
255 return NULL; |
|
256 } |
|
257 |
|
258 /*************************************/ |
|
259 /* B 1.4.2 - Multi-element variables */ |
|
260 /*************************************/ |
|
261 |
|
262 void *search_expression_type_c::visit(array_variable_c *symbol) { |
|
263 symbol_c *res; |
|
264 |
|
265 /* Nope, now we assume it is a variable, and determine its type... */ |
|
266 res = search_varfb_instance_type->get_basetype_decl(symbol); |
|
267 if (NULL != res) return res; |
|
268 |
|
269 return NULL; |
|
270 } |
|
271 |
|
272 void *search_expression_type_c::visit(structured_variable_c *symbol) { |
|
273 symbol_c *res; |
|
274 |
|
275 /* Nope, now we assume it is a variable, and determine its type... */ |
|
276 res = search_varfb_instance_type->get_basetype_decl(symbol); |
|
277 if (NULL != res) return res; |
|
278 |
|
279 return NULL; |
|
280 } |
|
281 |
|
282 /***************************************/ |
|
283 /* B.3 - Language ST (Structured Text) */ |
|
284 /***************************************/ |
|
285 /***********************/ |
|
286 /* B 3.1 - Expressions */ |
|
287 /***********************/ |
|
288 void *search_expression_type_c::visit(or_expression_c *symbol) { |
|
289 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
290 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
291 return compute_boolean_expression(left_type, right_type); |
|
292 } |
|
293 |
|
294 void *search_expression_type_c::visit(xor_expression_c *symbol) { |
|
295 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
296 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
297 return compute_boolean_expression(left_type, right_type); |
|
298 } |
|
299 |
|
300 void *search_expression_type_c::visit(and_expression_c *symbol) { |
|
301 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
302 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
303 return compute_boolean_expression(left_type, right_type); |
|
304 } |
|
305 |
|
306 void *search_expression_type_c::visit(equ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
307 void *search_expression_type_c::visit(notequ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
308 void *search_expression_type_c::visit(lt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
309 void *search_expression_type_c::visit(gt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
310 void *search_expression_type_c::visit(le_expression_c *symbol) {return (void *)&bool_type_name;} |
|
311 void *search_expression_type_c::visit(ge_expression_c *symbol) {return (void *)&bool_type_name;} |
|
312 |
|
313 void *search_expression_type_c::visit(add_expression_c *symbol) { |
|
314 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
315 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
316 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
317 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
318 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
319 return compute_numeric_expression(left_type, right_type); |
|
320 } |
|
321 |
|
322 void *search_expression_type_c::visit(sub_expression_c *symbol) { |
|
323 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
324 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
325 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
326 if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) {return (void *)&time_type_name;} |
|
327 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
328 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) {return (void *)&time_type_name;} |
|
329 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
330 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c)) {return (void *)&time_type_name;} |
|
331 return compute_numeric_expression(left_type, right_type); |
|
332 } |
|
333 |
|
334 void *search_expression_type_c::visit(mul_expression_c *symbol) { |
|
335 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
336 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
337 if (typeid(*left_type) == typeid(time_type_name_c) && is_num_type(right_type)) { |
|
338 return (void *)&time_type_name; |
|
339 } |
|
340 return compute_numeric_expression(left_type, right_type); |
|
341 } |
|
342 |
|
343 void *search_expression_type_c::visit(div_expression_c *symbol) { |
|
344 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
345 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
346 if (typeid(*left_type) == typeid(time_type_name_c) && is_num_type(right_type)){ |
|
347 return (void *)&time_type_name; |
|
348 } |
|
349 return compute_numeric_expression(left_type, right_type); |
|
350 } |
|
351 |
|
352 void *search_expression_type_c::visit(mod_expression_c *symbol) { |
|
353 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
354 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
355 return compute_numeric_expression(left_type, right_type); |
|
356 } |
|
357 |
|
358 void *search_expression_type_c::visit(power_expression_c *symbol) { |
|
359 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
360 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
361 if (is_real_type(left_type) && is_num_type(right_type)) { |
|
362 return (void *)left_type; |
|
363 } |
|
364 ERROR; |
|
365 return NULL; |
|
366 } |
|
367 |
|
368 void *search_expression_type_c::visit(neg_expression_c *symbol) { |
|
369 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
370 if (is_num_type(exp_type) || typeid(*exp_type) == typeid(time_type_name_c)){ |
|
371 return (void *)exp_type; |
|
372 } |
|
373 ERROR; |
|
374 return NULL; |
|
375 } |
|
376 |
|
377 void *search_expression_type_c::visit(not_expression_c *symbol) { |
|
378 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
379 return compute_boolean_expression(exp_type, exp_type); |
|
380 } |
|
381 |
|
382 void *search_expression_type_c::visit(function_invocation_c *symbol) { |
|
383 function_declaration_c *f_decl = (function_declaration_c *)symbol->called_function_declaration; |
|
384 if (f_decl == NULL) ERROR; |
|
385 return base_type(f_decl->type_name); |
|
386 } |
|
387 |
|
388 /*bool_type_name_c search_expression_type_c::bool_type_name;*/ |
|
389 |
|