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 #include "function_type_decl.h" |
|
36 #include "get_function_type_decl.c" |
|
37 |
|
38 #if 0 |
|
39 typedef enum {function_add, |
|
40 function_sub, |
|
41 function_and, |
|
42 function_or, |
|
43 function_sqrt, |
|
44 function_none} function_type_t; |
|
45 |
|
46 |
|
47 function_type_t get_function_type(identifier_c *function_name) { |
|
48 if (!strcasecmp(function_name->value, "ADD")) |
|
49 return function_add; |
|
50 else if (!strcasecmp(function_name->value, "SUB")) |
|
51 return function_sub; |
|
52 else if (!strcasecmp(function_name->value, "AND")) |
|
53 return function_and; |
|
54 else if (!strcasecmp(function_name->value, "OR")) |
|
55 return function_or; |
|
56 else if (!strcasecmp(function_name->value, "SQRT")) |
|
57 return function_sqrt; |
|
58 else return function_none; |
|
59 } |
|
60 #endif |
|
61 |
|
62 |
|
63 symbol_c *generate_param_name(const char *name) { |
|
64 symbol_c *param_name = new identifier_c(name); |
|
65 return param_name; |
|
66 } |
|
67 |
|
68 |
|
69 symbol_c *generate_param_name(const char *format, int number) { |
|
70 char name[10]; |
|
71 sprintf(name, format, number); |
|
72 symbol_c *param_name = new identifier_c(name); |
|
73 return param_name; |
|
74 } |
|
75 |
|
76 |
|
77 class search_expression_type_c: public search_constant_type_c { |
|
78 private: |
|
79 search_varfb_instance_type_c *search_varfb_instance_type; |
|
80 search_base_type_c search_base_type; |
|
81 |
|
82 public: |
|
83 search_expression_type_c(symbol_c *search_scope) { |
|
84 search_varfb_instance_type = new search_varfb_instance_type_c(search_scope); |
|
85 } |
|
86 |
|
87 virtual ~search_expression_type_c(void) { |
|
88 delete search_varfb_instance_type; |
|
89 } |
|
90 |
|
91 /* A helper function... */ |
|
92 bool is_bool_type(symbol_c *type_symbol) { |
|
93 if (type_symbol == NULL) {return true;} |
|
94 return (typeid(*type_symbol) == typeid(bool_type_name_c)); |
|
95 } |
|
96 |
|
97 /* A helper function... */ |
|
98 bool is_time_type(symbol_c *type_symbol) { |
|
99 if (type_symbol == NULL) {return true;} |
|
100 if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;} |
|
101 if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;} |
|
102 if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;} |
|
103 if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;} |
|
104 return false; |
|
105 } |
|
106 |
|
107 /* A helper function... */ |
|
108 bool is_string_type(symbol_c *type_symbol) { |
|
109 if (type_symbol == NULL) {return true;} |
|
110 if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;} |
|
111 if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;} |
|
112 return false; |
|
113 } |
|
114 |
|
115 /* A helper function... */ |
|
116 bool is_integer_type(symbol_c *type_symbol) { |
|
117 if (type_symbol == NULL) {return true;} |
|
118 if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;} |
|
119 if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;} |
|
120 if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;} |
|
121 if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;} |
|
122 if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;} |
|
123 if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;} |
|
124 if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;} |
|
125 if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;} |
|
126 if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;} |
|
127 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
128 return false; |
|
129 } |
|
130 |
|
131 bool is_real_type(symbol_c *type_symbol) { |
|
132 if (type_symbol == NULL) {return true;} |
|
133 if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;} |
|
134 if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;} |
|
135 if (typeid(*type_symbol) == typeid(constant_real_type_name_c)) {return true;} |
|
136 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
137 return false; |
|
138 } |
|
139 |
|
140 bool is_num_type(symbol_c *type_symbol) { |
|
141 if (type_symbol == NULL) {return true;} |
|
142 return is_real_type(type_symbol) || is_integer_type(type_symbol); |
|
143 } |
|
144 |
|
145 bool is_nbinary_type(symbol_c *type_symbol) { |
|
146 if (type_symbol == NULL) {return true;} |
|
147 if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;} |
|
148 if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;} |
|
149 if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;} |
|
150 if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;} |
|
151 if (typeid(*type_symbol) == typeid(constant_int_type_name_c)) {return true;} |
|
152 if (typeid(*type_symbol) == typeid(direct_variable_type_name_c)) {return true;} |
|
153 return false; |
|
154 } |
|
155 |
|
156 bool is_binary_type(symbol_c *type_symbol) { |
|
157 if (type_symbol == NULL) {return true;} |
|
158 if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;} |
|
159 return is_nbinary_type(type_symbol); |
|
160 } |
|
161 |
|
162 bool is_same_type(symbol_c *first_type, symbol_c *second_type) { |
|
163 if (first_type == NULL || second_type == NULL) {return true;} |
|
164 if (typeid(*first_type) == typeid(*second_type)) {return true;} |
|
165 if (is_integer_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;} |
|
166 if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_integer_type(second_type))) {return true;} |
|
167 if (is_binary_type(first_type) && (typeid(*second_type) == typeid(constant_int_type_name_c))) {return true;} |
|
168 if ((typeid(*first_type) == typeid(constant_int_type_name_c) && is_binary_type(second_type))) {return true;} |
|
169 if (is_real_type(first_type) && (typeid(*second_type) == typeid(constant_real_type_name_c))) {return true;} |
|
170 if ((typeid(*first_type) == typeid(constant_real_type_name_c) && is_real_type(second_type))) {return true;} |
|
171 if (typeid(*first_type) == typeid(direct_variable_type_name_c)) {return true;} |
|
172 if (typeid(*second_type) == typeid(direct_variable_type_name_c)) {return true;} |
|
173 return false; |
|
174 } |
|
175 |
|
176 symbol_c* common_type(symbol_c *first_type, symbol_c *second_type) { |
|
177 if (first_type == NULL && second_type == NULL) {return NULL;} |
|
178 if (first_type == NULL) {return second_type;} |
|
179 if (second_type == NULL) {return first_type;} |
|
180 if (typeid(*first_type) == typeid(*second_type)) {return first_type;} |
|
181 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;} |
|
182 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;} |
|
183 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;} |
|
184 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;} |
|
185 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;} |
|
186 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;} |
|
187 return NULL; |
|
188 } |
|
189 |
|
190 #include "search_type_code.c" |
|
191 |
|
192 /*static bool_type_name_c bool_type_name;*/ |
|
193 |
|
194 /* A helper function... */ |
|
195 void *compute_boolean_expression(symbol_c *left_type, symbol_c *right_type) { |
|
196 if (!is_same_type(left_type, right_type)) |
|
197 ERROR; |
|
198 if (!is_bool_type(left_type) && !is_binary_type(left_type)) |
|
199 ERROR; |
|
200 if (typeid(*left_type) == typeid(constant_int_type_name_c)) {return (void *)right_type;} |
|
201 else {return (void *)left_type;} |
|
202 } |
|
203 |
|
204 /* A helper function... */ |
|
205 void *compute_numeric_expression(symbol_c *left_type, symbol_c *right_type) { |
|
206 if (!is_same_type(left_type, right_type)) |
|
207 ERROR; |
|
208 if (!is_integer_type(left_type) && !is_real_type(left_type)) |
|
209 ERROR; |
|
210 if ((typeid(*left_type) == typeid(constant_int_type_name_c)) || (typeid(*left_type) == typeid(constant_real_type_name_c))) {return (void *)right_type;} |
|
211 else {return (void *)left_type;} |
|
212 return NULL; |
|
213 } |
|
214 |
|
215 /* a helper function... */ |
|
216 symbol_c *base_type(symbol_c *symbol) { |
|
217 return (symbol_c *)symbol->accept(search_base_type); |
|
218 } |
|
219 |
|
220 /*********************/ |
|
221 /* B 1.4 - Variables */ |
|
222 /*********************/ |
|
223 |
|
224 void *visit(symbolic_variable_c *symbol) { |
|
225 symbol_c *res; |
|
226 |
|
227 /* Nope, now we assume it is a variable, and determine its type... */ |
|
228 res = search_varfb_instance_type->get_type(symbol); |
|
229 if (NULL != res) return res; |
|
230 |
|
231 return NULL; |
|
232 } |
|
233 |
|
234 /********************************************/ |
|
235 /* B 1.4.1 - Directly Represented Variables */ |
|
236 /********************************************/ |
|
237 void *visit(direct_variable_c *symbol) { |
|
238 switch (symbol->value[2]) { |
|
239 case 'X': // bit |
|
240 return (void *)&bool_type_name; |
|
241 default: |
|
242 return (void *)&direct_variable_type_name; |
|
243 } |
|
244 } |
|
245 |
|
246 /*************************************/ |
|
247 /* B 1.4.2 - Multi-element variables */ |
|
248 /*************************************/ |
|
249 |
|
250 void *visit(array_variable_c *symbol) { |
|
251 symbol_c *res; |
|
252 |
|
253 /* Nope, now we assume it is a variable, and determine its type... */ |
|
254 res = search_varfb_instance_type->get_type(symbol); |
|
255 if (NULL != res) return res; |
|
256 |
|
257 return NULL; |
|
258 } |
|
259 |
|
260 void *visit(structured_variable_c *symbol) { |
|
261 symbol_c *res; |
|
262 |
|
263 /* Nope, now we assume it is a variable, and determine its type... */ |
|
264 res = search_varfb_instance_type->get_type(symbol); |
|
265 if (NULL != res) return res; |
|
266 |
|
267 return NULL; |
|
268 } |
|
269 |
|
270 /***************************************/ |
|
271 /* B.3 - Language ST (Structured Text) */ |
|
272 /***************************************/ |
|
273 /***********************/ |
|
274 /* B 3.1 - Expressions */ |
|
275 /***********************/ |
|
276 void *visit(or_expression_c *symbol) { |
|
277 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
278 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
279 return compute_boolean_expression(left_type, right_type); |
|
280 } |
|
281 |
|
282 void *visit(xor_expression_c *symbol) { |
|
283 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
284 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
285 return compute_boolean_expression(left_type, right_type); |
|
286 } |
|
287 |
|
288 void *visit(and_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 *visit(equ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
295 void *visit(notequ_expression_c *symbol) {return (void *)&bool_type_name;} |
|
296 void *visit(lt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
297 void *visit(gt_expression_c *symbol) {return (void *)&bool_type_name;} |
|
298 void *visit(le_expression_c *symbol) {return (void *)&bool_type_name;} |
|
299 void *visit(ge_expression_c *symbol) {return (void *)&bool_type_name;} |
|
300 |
|
301 void *visit(add_expression_c *symbol) { |
|
302 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
303 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
304 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
305 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
306 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
307 return compute_numeric_expression(left_type, right_type); |
|
308 } |
|
309 |
|
310 void *visit(sub_expression_c *symbol) { |
|
311 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
312 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
313 if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;} |
|
314 if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) {return (void *)&time_type_name;} |
|
315 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;} |
|
316 if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) {return (void *)&time_type_name;} |
|
317 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;} |
|
318 if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c)) {return (void *)&time_type_name;} |
|
319 return compute_numeric_expression(left_type, right_type); |
|
320 } |
|
321 |
|
322 void *visit(mul_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) && is_num_type(right_type)) { |
|
326 return (void *)&time_type_name; |
|
327 } |
|
328 return compute_numeric_expression(left_type, right_type); |
|
329 } |
|
330 |
|
331 void *visit(div_expression_c *symbol) { |
|
332 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
333 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
334 if (typeid(*left_type) == typeid(time_type_name_c) && is_num_type(right_type)){ |
|
335 return (void *)&time_type_name; |
|
336 } |
|
337 return compute_numeric_expression(left_type, right_type); |
|
338 } |
|
339 |
|
340 void *visit(mod_expression_c *symbol) { |
|
341 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
342 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
343 return compute_numeric_expression(left_type, right_type); |
|
344 } |
|
345 |
|
346 void *visit(power_expression_c *symbol) { |
|
347 symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this)); |
|
348 symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this)); |
|
349 if (is_real_type(left_type) && is_num_type(right_type)) { |
|
350 return (void *)left_type; |
|
351 } |
|
352 ERROR; |
|
353 return NULL; |
|
354 } |
|
355 |
|
356 void *visit(neg_expression_c *symbol) { |
|
357 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
358 if (is_num_type(exp_type) || typeid(*exp_type) == typeid(time_type_name_c)){ |
|
359 return (void *)exp_type; |
|
360 } |
|
361 ERROR; |
|
362 return NULL; |
|
363 } |
|
364 |
|
365 void *visit(not_expression_c *symbol) { |
|
366 symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this)); |
|
367 return compute_boolean_expression(exp_type, exp_type); |
|
368 } |
|
369 |
|
370 void *visit(function_invocation_c *symbol) { |
|
371 function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); |
|
372 |
|
373 if (f_decl == function_symtable.end_value()) { |
|
374 void *res = compute_standard_function_default(symbol); |
|
375 if (res == NULL) |
|
376 ERROR; |
|
377 return res; |
|
378 } |
|
379 |
|
380 return base_type(f_decl->type_name); |
|
381 } |
|
382 |
|
383 }; |
|
384 |
|
385 /*bool_type_name_c search_expression_type_c::bool_type_name;*/ |
|
386 |
|