|
1 /* |
|
2 * (c) 2003 Mario de Sousa |
|
3 * |
|
4 * Offered to the public under the terms of the GNU General Public License |
|
5 * as published by the Free Software Foundation; either version 2 of the |
|
6 * License, or (at your option) any later version. |
|
7 * |
|
8 * This program is distributed in the hope that it will be useful, but |
|
9 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|
11 * Public License for more details. |
|
12 * |
|
13 * This code is made available on the understanding that it will not be |
|
14 * used in safety-critical situations without a full and competent review. |
|
15 */ |
|
16 |
|
17 /* |
|
18 * An IEC 61131-3 IL and ST compiler. |
|
19 * |
|
20 * Based on the |
|
21 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
22 * |
|
23 */ |
|
24 |
|
25 |
|
26 /* Determine the data type of an ST expression. |
|
27 * A reference to the relevant type definition is returned. |
|
28 * |
|
29 * For example: |
|
30 * 2 + 3 -> returns reference to a int_type_name_c object. |
|
31 * 22.2 - 5 -> returns reference to a real_type_name_c object. |
|
32 * etc... |
|
33 */ |
|
34 |
|
35 |
|
36 |
|
37 #include "absyntax_utils.hh" |
|
38 #include <typeinfo> |
|
39 |
|
40 search_expression_type_c::search_expression_type_c(symbol_c *search_scope) { |
|
41 search_varfb_instance_type = new search_varfb_instance_type_c(search_scope); |
|
42 } |
|
43 |
|
44 search_expression_type_c::~search_expression_type_c(void) { |
|
45 delete search_varfb_instance_type; |
|
46 } |
|
47 |
|
48 /* A helper function... */ |
|
49 bool search_expression_type_c::is_bool_type(symbol_c *type_symbol) { |
|
50 bool_type_name_c tt; |
|
51 if (type_symbol == NULL) {return true;} |
|
52 return (typeid(*type_symbol) == typeid(bool_type_name_c)); |
|
53 } |
|
54 |
|
55 /* A helper function... */ |
|
56 bool search_expression_type_c::is_time_type(symbol_c *type_symbol) { |
|
57 if (type_symbol == NULL) {return true;} |
|
58 if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;} |
|
59 if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;} |
|
60 if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;} |
|
61 if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;} |
|
62 return false; |
|
63 } |
|
64 |
|
65 /* A helper function... */ |
|
66 bool search_expression_type_c::is_string_type(symbol_c *type_symbol) { |
|
67 if (type_symbol == NULL) {return true;} |
|
68 if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;} |
|
69 if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;} |
|
70 return false; |
|
71 } |
|
72 |
|
73 /* A helper function... */ |
|
74 bool search_expression_type_c::is_integer_type(symbol_c *type_symbol) { |
|
75 if (type_symbol == NULL) {return true;} |
|
76 if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;} |
|
77 if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;} |
|
78 if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;} |
|
79 if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;} |
|
80 if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;} |
|
81 if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;} |
|
82 if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;} |
|
83 if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;} |
|
84 if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;} |
|
85 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
86 return false; |
|
87 } |
|
88 |
|
89 bool search_expression_type_c::is_real_type(symbol_c *type_symbol) { |
|
90 if (type_symbol == NULL) {return true;} |
|
91 if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;} |
|
92 if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;} |
|
93 if (typeid(*type_symbol) == typeid(constant_real_type_name_c)) {return true;} |
|
94 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
95 return false; |
|
96 } |
|
97 |
|
98 bool search_expression_type_c::is_num_type(symbol_c *type_symbol) { |
|
99 if (type_symbol == NULL) {return true;} |
|
100 return is_real_type(type_symbol) || is_integer_type(type_symbol); |
|
101 } |
|
102 |
|
103 bool search_expression_type_c::is_nbinary_type(symbol_c *type_symbol) { |
|
104 if (type_symbol == NULL) {return true;} |
|
105 if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;} |
|
106 if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;} |
|
107 if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;} |
|
108 if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;} |
|
109 if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;} |
|
110 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
111 return false; |
|
112 } |
|
113 |
|
114 bool search_expression_type_c::is_binary_type(symbol_c *type_symbol) { |
|
115 if (type_symbol == NULL) {return true;} |
|
116 if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} |
|
117 return is_nbinary_type(type_symbol); |
|
118 } |
|
119 |
|
120 bool search_expression_type_c::is_same_type(symbol_c *first_type, symbol_c *second_type) { |
|
121 if (first_type == NULL || second_type == NULL) {return true;} |
|
122 if (typeid(*first_type) == typeid(*second_type)) {return true;} |
|
123 if (is_integer_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;} |
|
124 if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_integer_type(second_type))) {return true;} |
|
125 if (is_binary_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;} |
|
126 if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_binary_type(second_type))) {return true;} |
|
127 if (is_real_type(first_type) && (typeid(*second_type) == typeid(constant_real_type_name_c))) {return true;} |
|
128 if ((typeid(*first_type) == typeid(constant_real_type_name_c) && is_real_type(second_type))) {return true;} |
|
129 if (typeid(*first_type) == typeid(direct_variable_type_name_c)) {return true;} |
|
130 if (typeid(*second_type) == typeid(direct_variable_type_name_c)) {return true;} |
|
131 return false; |
|
132 } |
|
133 |
|
134 symbol_c* search_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) { |
|
135 if (first_type == NULL && second_type == NULL) {return NULL;} |
|
136 if (first_type == NULL) {return second_type;} |
|
137 if (second_type == NULL) {return first_type;} |
|
138 if (typeid(*first_type) == typeid(*second_type)) {return first_type;} |
|
139 if (is_integer_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c))) {return first_type;} |
|
140 if ((typeid(*first_type) == typeid(constant_int_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c)) && is_integer_type(second_type)) {return second_type;} |
|
141 if (is_binary_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c))) {return first_type;} |
|
142 if ((typeid(*first_type) == typeid(constant_int_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c)) && is_binary_type(second_type)) {return second_type;} |
|
143 if (is_real_type(first_type) && (typeid(*second_type) == typeid(constant_real_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c))) {return first_type;} |
|
144 if ((typeid(*first_type) == typeid(constant_real_type_name_c) || typeid(*second_type) == typeid(direct_variable_type_name_c)) && is_real_type(second_type)) {return second_type;} |
|
145 return NULL; |
|
146 } |
|
147 |
|
148 #define compute_standard_function_default search_expression_type_c::compute_standard_function_default |
|
149 #define compute_standard_function_il search_expression_type_c::compute_standard_function_il |
|
150 #include "search_type_code.c" |
|
151 #undef compute_standard_function_default |
|
152 #undef compute_standard_function_il |
|
153 |
|
154 /*static bool_type_name_c bool_type_name;*/ |
|
155 |
|
156 /* A helper function... */ |
|
157 void *search_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type) { |
|
158 if (!is_same_type(left_type, right_type)) |
|
159 ERROR; |
|
160 if (!is_bool_type(left_type) && !is_binary_type(left_type)) |
|
161 ERROR; |
|
162 if (typeid(*left_type) == typeid(constant_int_type_name_c)) {return (void *)right_type;} |
|
163 else {return (void *)left_type;} |
|
164 } |
|
165 |
|
166 /* A helper function... */ |
|
167 void *search_expression_type_c::compute_numeric_expression(symbol_c *left_type, symbol_c *right_type) { |
|
168 if (!is_same_type(left_type, right_type)) |
|
169 ERROR; |
|
170 if (!is_integer_type(left_type) && !is_real_type(left_type)) |
|
171 ERROR; |
|
172 if ((typeid(*left_type) == typeid(constant_int_type_name_c)) || (typeid(*left_type) == typeid(constant_real_type_name_c))) {return (void *)right_type;} |
|
173 else {return (void *)left_type;} |
|
174 return NULL; |
|
175 } |
|
176 |
|
177 /* a helper function... */ |
|
178 symbol_c *search_expression_type_c::base_type(symbol_c *symbol) { |
|
179 return (symbol_c *)symbol->accept(search_base_type); |
|
180 } |
|
181 |
|
182 /*********************/ |
|
183 /* B 1.4 - Variables */ |
|
184 /*********************/ |
|
185 |
|
186 void *search_expression_type_c::visit(symbolic_variable_c *symbol) { |
|
187 symbol_c *res; |
|
188 |
|
189 /* Nope, now we assume it is a variable, and determine its type... */ |
|
190 res = search_varfb_instance_type->get_type(symbol); |
|
191 if (NULL != res) return res; |
|
192 |
|
193 return NULL; |
|
194 } |
|
195 |
|
196 /********************************************/ |
|
197 /* B 1.4.1 - Directly Represented Variables */ |
|
198 /********************************************/ |
|
199 void *search_expression_type_c::visit(direct_variable_c *symbol) { |
|
200 switch (symbol->value[2]) { |
|
201 case 'X': // bit |
|
202 return (void *)&bool_type_name; |
|
203 default: |
|
204 return (void *)&direct_variable_type_name; |
|
205 } |
|
206 } |
|
207 |
|
208 /*************************************/ |
|
209 /* B 1.4.2 - Multi-element variables */ |
|
210 /*************************************/ |
|
211 |
|
212 void *search_expression_type_c::visit(array_variable_c *symbol) { |
|
213 symbol_c *res; |
|
214 |
|
215 /* Nope, now we assume it is a variable, and determine its type... */ |
|
216 res = search_varfb_instance_type->get_type(symbol); |
|
217 if (NULL != res) return res; |
|
218 |
|
219 return NULL; |
|
220 } |
|
221 |
|
222 void *search_expression_type_c::visit(structured_variable_c *symbol) { |
|
223 symbol_c *res; |
|
224 |
|
225 /* Nope, now we assume it is a variable, and determine its type... */ |
|
226 res = search_varfb_instance_type->get_type(symbol); |
|
227 if (NULL != res) return res; |
|
228 |
|
229 return NULL; |
|
230 } |
|
231 |
|
232 /***************************************/ |
|
233 /* B.3 - Language ST (Structured Text) */ |
|
234 /***************************************/ |
|
235 /***********************/ |
|
236 /* B 3.1 - Expressions */ |
|
237 /***********************/ |
|
238 void *search_expression_type_c::visit(or_expression_c *symbol) { |
|
239 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
240 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
241 return compute_boolean_expression(left_type, right_type); |
|
242 } |
|
243 |
|
244 void *search_expression_type_c::visit(xor_expression_c *symbol) { |
|
245 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
246 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
247 return compute_boolean_expression(left_type, right_type); |
|
248 } |
|
249 |
|
250 void *search_expression_type_c::visit(and_expression_c *symbol) { |
|
251 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
252 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
253 return compute_boolean_expression(left_type, right_type); |
|
254 } |
|
255 |
|
256 void *search_expression_type_c::visit(equ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
257 void *search_expression_type_c::visit(notequ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
258 void *search_expression_type_c::visit(lt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
259 void *search_expression_type_c::visit(gt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
260 void *search_expression_type_c::visit(le_expression_c *symbol) {return (void *)&bool_type_name;} |
|
261 void *search_expression_type_c::visit(ge_expression_c *symbol) {return (void *)&bool_type_name;} |
|
262 |
|
263 void *search_expression_type_c::visit(add_expression_c *symbol) { |
|
264 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
265 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
266 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
267 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
268 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
269 return compute_numeric_expression(left_type, right_type); |
|
270 } |
|
271 |
|
272 void *search_expression_type_c::visit(sub_expression_c *symbol) { |
|
273 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
274 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
275 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
276 if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) {return (void *)&time_type_name;} |
|
277 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
278 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) {return (void *)&time_type_name;} |
|
279 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
280 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c)) {return (void *)&time_type_name;} |
|
281 return compute_numeric_expression(left_type, right_type); |
|
282 } |
|
283 |
|
284 void *search_expression_type_c::visit(mul_expression_c *symbol) { |
|
285 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
286 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
287 if (typeid(*left_type) == typeid(time_type_name_c) && is_num_type(right_type)) { |
|
288 return (void *)&time_type_name; |
|
289 } |
|
290 return compute_numeric_expression(left_type, right_type); |
|
291 } |
|
292 |
|
293 void *search_expression_type_c::visit(div_expression_c *symbol) { |
|
294 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
295 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
296 if (typeid(*left_type) == typeid(time_type_name_c) && is_num_type(right_type)){ |
|
297 return (void *)&time_type_name; |
|
298 } |
|
299 return compute_numeric_expression(left_type, right_type); |
|
300 } |
|
301 |
|
302 void *search_expression_type_c::visit(mod_expression_c *symbol) { |
|
303 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
304 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
305 return compute_numeric_expression(left_type, right_type); |
|
306 } |
|
307 |
|
308 void *search_expression_type_c::visit(power_expression_c *symbol) { |
|
309 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
310 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
311 if (is_real_type(left_type) && is_num_type(right_type)) { |
|
312 return (void *)left_type; |
|
313 } |
|
314 ERROR; |
|
315 return NULL; |
|
316 } |
|
317 |
|
318 void *search_expression_type_c::visit(neg_expression_c *symbol) { |
|
319 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
320 if (is_num_type(exp_type) || typeid(*exp_type) == typeid(time_type_name_c)){ |
|
321 return (void *)exp_type; |
|
322 } |
|
323 ERROR; |
|
324 return NULL; |
|
325 } |
|
326 |
|
327 void *search_expression_type_c::visit(not_expression_c *symbol) { |
|
328 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
329 return compute_boolean_expression(exp_type, exp_type); |
|
330 } |
|
331 |
|
332 void *search_expression_type_c::visit(function_invocation_c *symbol) { |
|
333 function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); |
|
334 if (f_decl == function_symtable.end_value()) { |
|
335 void *res = compute_standard_function_default(symbol); |
|
336 if (res == NULL) |
|
337 ERROR; |
|
338 return res; |
|
339 } |
|
340 return base_type(f_decl->type_name); |
|
341 } |
|
342 |
|
343 /*bool_type_name_c search_expression_type_c::bool_type_name;*/ |
|
344 |