|
1 /* |
|
2 * matiec - a compiler for the programming languages defined in IEC 61131-3 |
|
3 * |
|
4 * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt) |
|
5 * Copyright (C) 2011-2012 Manuele Conti (manuele.conti@sirius-es.it) |
|
6 * Copyright (C) 2011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it) |
|
7 * |
|
8 * This program is free software: you can redistribute it and/or modify |
|
9 * it under the terms of the GNU General Public License as published by |
|
10 * the Free Software Foundation, either version 3 of the License, or |
|
11 * (at your option) any later version. |
|
12 * |
|
13 * This program is distributed in the hope that it will be useful, |
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 * GNU General Public License for more details. |
|
17 * |
|
18 * You should have received a copy of the GNU General Public License |
|
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
20 * |
|
21 * |
|
22 * This code is made available on the understanding that it will not be |
|
23 * used in safety-critical situations without a full and competent review. |
|
24 */ |
|
25 |
|
26 /* |
|
27 * An IEC 61131-3 compiler. |
|
28 * |
|
29 * Based on the |
|
30 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
31 * |
|
32 */ |
|
33 |
|
34 /* NOTE: The algorithm implemented here assumes that the symbol_c.candidate_datatype, and the symbol_c.datatype |
|
35 * annotations have already been apropriately filled in! |
|
36 * BEFORE running this visitor, be sure to CALL the fill_candidate_datatypes_c, and the narrow_candidate_datatypes_c visitors! |
|
37 */ |
|
38 |
|
39 |
|
40 /* |
|
41 * By analysing the candidate datatype lists, as well as the chosen datatype for each expression, determine |
|
42 * if an datatype error has been found, and if so, print out an error message. |
|
43 */ |
|
44 |
|
45 |
|
46 #include "print_datatypes_error.hh" |
|
47 #include "datatype_functions.hh" |
|
48 |
|
49 #include <typeinfo> |
|
50 #include <list> |
|
51 #include <string> |
|
52 #include <string.h> |
|
53 #include <strings.h> |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 #define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2)) |
|
61 #define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2)) |
|
62 |
|
63 #define STAGE3_ERROR(error_level, symbol1, symbol2, ...) { \ |
|
64 if (current_display_error_level >= error_level) { \ |
|
65 fprintf(stderr, "%s:%d-%d..%d-%d: error: ", \ |
|
66 FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ |
|
67 LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ |
|
68 fprintf(stderr, __VA_ARGS__); \ |
|
69 fprintf(stderr, "\n"); \ |
|
70 il_error = true; \ |
|
71 error_count++; \ |
|
72 } \ |
|
73 } |
|
74 |
|
75 |
|
76 #define STAGE3_WARNING(symbol1, symbol2, ...) { \ |
|
77 fprintf(stderr, "%s:%d-%d..%d-%d: warning: ", \ |
|
78 FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\ |
|
79 LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\ |
|
80 fprintf(stderr, __VA_ARGS__); \ |
|
81 fprintf(stderr, "\n"); \ |
|
82 warning_found = true; \ |
|
83 } |
|
84 |
|
85 |
|
86 /* set to 1 to see debug info during execution */ |
|
87 static int debug = 0; |
|
88 |
|
89 print_datatypes_error_c::print_datatypes_error_c(symbol_c *ignore) { |
|
90 error_count = 0; |
|
91 warning_found = false; |
|
92 current_display_error_level = error_level_default; |
|
93 } |
|
94 |
|
95 print_datatypes_error_c::~print_datatypes_error_c(void) { |
|
96 } |
|
97 |
|
98 int print_datatypes_error_c::get_error_count() { |
|
99 return error_count; |
|
100 } |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 /* Verify if the datatypes of all prev_il_instructions are valid and equal! */ |
|
107 static bool are_all_datatypes_of_prev_il_instructions_datatypes_equal(il_instruction_c *symbol) { |
|
108 if (NULL == symbol) ERROR; |
|
109 bool res; |
|
110 |
|
111 if (symbol->prev_il_instruction.size() > 0) |
|
112 res = is_type_valid(symbol->prev_il_instruction[0]->datatype); |
|
113 |
|
114 for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) |
|
115 res &= is_type_equal(symbol->prev_il_instruction[i-1]->datatype, symbol->prev_il_instruction[i]->datatype); |
|
116 |
|
117 return res; |
|
118 } |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 /* a helper function... */ |
|
124 symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) { |
|
125 /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used |
|
126 * in the code. |
|
127 */ |
|
128 if (symbol == NULL) return NULL; |
|
129 return (symbol_c *)symbol->accept(search_base_type); |
|
130 } |
|
131 |
|
132 |
|
133 |
|
134 /* |
|
135 typedef struct { |
|
136 symbol_c *function_name, |
|
137 symbol_c *nonformal_operand_list, |
|
138 symbol_c * formal_operand_list, |
|
139 |
|
140 std::vector <symbol_c *> &candidate_functions, |
|
141 symbol_c &*called_function_declaration, |
|
142 int &extensible_param_count |
|
143 } generic_function_call_t; |
|
144 */ |
|
145 void print_datatypes_error_c::handle_function_invocation(symbol_c *fcall, generic_function_call_t fcall_data) { |
|
146 symbol_c *param_value, *param_name; |
|
147 function_call_param_iterator_c fcp_iterator(fcall); |
|
148 bool function_invocation_error = false; |
|
149 const char *POU_str = NULL; |
|
150 |
|
151 if (generic_function_call_t::POU_FB == fcall_data.POU_type) POU_str = "FB"; |
|
152 if (generic_function_call_t::POU_function == fcall_data.POU_type) POU_str = "function"; |
|
153 if (NULL == POU_str) ERROR; |
|
154 |
|
155 if ((NULL != fcall_data.formal_operand_list) && (NULL != fcall_data.nonformal_operand_list)) |
|
156 ERROR; |
|
157 |
|
158 symbol_c *f_decl = fcall_data.called_function_declaration; |
|
159 if ((NULL == f_decl) && (generic_function_call_t::POU_FB ==fcall_data.POU_type)) { |
|
160 /* Due to the way the syntax analysis is buit (i.e. stage 2), this should never occur. */ |
|
161 /* I.e., a FB invocation using an undefined FB variable is not possible in the current implementation of stage 2. */ |
|
162 ERROR; |
|
163 } |
|
164 if (NULL == f_decl) { |
|
165 /* we now try to find any function declaration with the same name, just so we can provide some relevant error messages */ |
|
166 function_symtable_t::iterator lower = function_symtable.lower_bound(fcall_data.function_name); |
|
167 if (lower == function_symtable.end()) ERROR; |
|
168 f_decl = function_symtable.get_value(lower); |
|
169 } |
|
170 |
|
171 if (NULL != fcall_data.formal_operand_list) { |
|
172 fcall_data.formal_operand_list->accept(*this); |
|
173 if (NULL != f_decl) { |
|
174 function_param_iterator_c fp_iterator(f_decl); |
|
175 while ((param_name = fcp_iterator.next_f()) != NULL) { |
|
176 param_value = fcp_iterator.get_current_value(); |
|
177 |
|
178 /* Check if there are duplicate parameter values */ |
|
179 if(fcp_iterator.search_f(param_name) != param_value) { |
|
180 function_invocation_error = true; |
|
181 STAGE3_ERROR(0, param_name, param_name, "Duplicate parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
182 continue; /* jump to next parameter */ |
|
183 } |
|
184 |
|
185 /* Find the corresponding parameter in function declaration */ |
|
186 if (NULL == fp_iterator.search(param_name)) { |
|
187 function_invocation_error = true; |
|
188 STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
189 continue; /* jump to next parameter */ |
|
190 } |
|
191 |
|
192 /* check whether direction (IN, OUT, IN_OUT) and assignment types (:= , =>) are compatible !!! */ |
|
193 /* Obtaining the assignment direction: := (assign_in) or => (assign_out) */ |
|
194 function_call_param_iterator_c::assign_direction_t call_param_dir = fcp_iterator.get_assign_direction(); |
|
195 /* Get the parameter direction: IN, OUT, IN_OUT */ |
|
196 function_param_iterator_c::param_direction_t param_dir = fp_iterator.param_direction(); |
|
197 if (function_call_param_iterator_c::assign_in == call_param_dir) { |
|
198 if ((function_param_iterator_c::direction_in != param_dir) && |
|
199 (function_param_iterator_c::direction_inout != param_dir)) { |
|
200 function_invocation_error = true; |
|
201 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax ':=' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
202 continue; /* jump to next parameter */ |
|
203 } |
|
204 } else if (function_call_param_iterator_c::assign_out == call_param_dir) { |
|
205 if ((function_param_iterator_c::direction_out != param_dir)) { |
|
206 function_invocation_error = true; |
|
207 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax '=>' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
208 continue; /* jump to next parameter */ |
|
209 } |
|
210 } else ERROR; |
|
211 |
|
212 if (NULL == param_value->datatype) { |
|
213 function_invocation_error = true; |
|
214 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
215 continue; /* jump to next parameter */ |
|
216 } |
|
217 } |
|
218 } |
|
219 } |
|
220 if (NULL != fcall_data.nonformal_operand_list) { |
|
221 fcall_data.nonformal_operand_list->accept(*this); |
|
222 if (f_decl) |
|
223 for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { |
|
224 /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */ |
|
225 |
|
226 /* This handle_function_invocation() will be called to handle IL function calls, where the first parameter comes from the previous IL instruction. |
|
227 * In this case, the previous IL instruction will be artifically (and temporarily) added to the begining ot the parameter list |
|
228 * so we (in this function) can handle this situation like all the other function calls. |
|
229 * However, |
|
230 * a) if NO previous IL function exists, then we get a fake previous IL function, with no location data (i.e. not found anywhere in the source code. |
|
231 * b) the function call may actually have several prev IL instructions (if several JMP instructions jump directly to the il function call). |
|
232 * In order to handle these situations gracefully, we first check whether the first parameter is really an IL istruction! |
|
233 */ |
|
234 il_instruction_c *il_instruction_symbol = dynamic_cast<il_instruction_c *>(param_value); |
|
235 if ((NULL != il_instruction_symbol) && (i == 1)) { |
|
236 /* We are in a situation where an IL function call is passed the first parameter, which is actually the previous IL instruction */ |
|
237 /* However, this is really a fake previous il instruction (see visit(il_instruction_c *) ) |
|
238 * We will iterate through all the real previous IL instructions, and analyse each of them one by one */ |
|
239 if (il_instruction_symbol->prev_il_instruction.size() == 0) { |
|
240 function_invocation_error = true; |
|
241 STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((identifier_c *)fcall_data.function_name)->value); |
|
242 } |
|
243 #if 0 |
|
244 /* NOTE: We currently comment out this code... |
|
245 * This does not currently work, since the narrow operation is currently done on the intersection |
|
246 * of all the previous IL instructions, so we currently either accept them all, or none at all. |
|
247 * In order to be able to produce these user freindly error messages, we will need to update the |
|
248 * narrow algorithm. We leave this untill somebody aks for it... |
|
249 * So, for now, we simply comment out this code. |
|
250 */ |
|
251 for (unsigned int p = 0; p < il_instruction_symbol->prev_il_instruction.size(); p++) { |
|
252 symbol_c *value = il_instruction_symbol->prev_il_instruction[p]; |
|
253 if (!is_type_valid(value->datatype)) { |
|
254 function_invocation_error = true; |
|
255 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
|
256 STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
|
257 } |
|
258 } |
|
259 #else |
|
260 if (!is_type_valid(il_instruction_symbol->datatype)) { |
|
261 function_invocation_error = true; |
|
262 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
|
263 } |
|
264 #endif |
|
265 if (function_invocation_error) |
|
266 /* when handling a IL function call, and an error is found in the first parameter, then we bug out and do not print out any more error messages. */ |
|
267 return; |
|
268 } |
|
269 else if (!is_type_valid(param_value->datatype)) { |
|
270 function_invocation_error = true; |
|
271 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
272 } |
|
273 } |
|
274 } |
|
275 |
|
276 if (NULL == fcall_data.called_function_declaration) { |
|
277 function_invocation_error = true; |
|
278 STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
279 } |
|
280 |
|
281 if (function_invocation_error) { |
|
282 /* No compatible function exists */ |
|
283 STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
284 } |
|
285 |
|
286 return; |
|
287 } |
|
288 |
|
289 |
|
290 |
|
291 void *print_datatypes_error_c::handle_implicit_il_fb_invocation(const char *param_name, symbol_c *il_operator, symbol_c *called_fb_declaration) { |
|
292 if (NULL == il_operand) { |
|
293 STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name); |
|
294 return NULL; |
|
295 } |
|
296 il_operand->accept(*this); |
|
297 |
|
298 if (NULL == called_fb_declaration) { |
|
299 STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance."); |
|
300 return NULL; |
|
301 } |
|
302 |
|
303 if (fake_prev_il_instruction->prev_il_instruction.empty()) { |
|
304 STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); |
|
305 return NULL; |
|
306 } |
|
307 |
|
308 /* Find the corresponding parameter in function declaration */ |
|
309 function_param_iterator_c fp_iterator(called_fb_declaration); |
|
310 if (NULL == fp_iterator.search(param_name)) { |
|
311 /* TODO: must also check whther it is an IN parameter!! */ |
|
312 /* NOTE: although all standard FBs have the implicit FB calls defined as input parameters |
|
313 * (i.e., for all standard FBs, CLK, PT, IN, CU, CD, S1, R1, etc... is always an input parameter) |
|
314 * if a non-standard (i.e. a FB not defined in the standard library) FB is being called, then |
|
315 * this (CLK, PT, IN, CU, ...) parameter may just have been defined as OUT or INOUT, |
|
316 * which will not work for an implicit FB call! |
|
317 */ |
|
318 STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); |
|
319 return NULL; |
|
320 } |
|
321 if (!are_all_datatypes_of_prev_il_instructions_datatypes_equal(fake_prev_il_instruction)) { |
|
322 STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name); |
|
323 return NULL; |
|
324 } |
|
325 |
|
326 |
|
327 /* NOTE: The error_level currently being used for errors in variables/constants etc... is rather high. |
|
328 * However, in the case of an implicit FB call, if the datatype of the operand == NULL, this may be |
|
329 * the __only__ indication of an error! So we test it here again, to make sure thtis error will really |
|
330 * be printed out! |
|
331 */ |
|
332 if (NULL == il_operand->datatype) { |
|
333 /* Note: the case of (NULL == fb_declaration) was already caught above! */ |
|
334 // if (NULL != fb_declaration) { |
|
335 STAGE3_ERROR(0, il_operator, il_operator, "Invalid FB call: Datatype incompatibility between the FB's '%s' parameter and value being passed, or paramater '%s' is not a 'VAR_INPUT' parameter.", param_name, param_name); |
|
336 return NULL; |
|
337 // } |
|
338 } |
|
339 |
|
340 return NULL; |
|
341 } |
|
342 |
|
343 |
|
344 /*********************/ |
|
345 /* B 1.2 - Constants */ |
|
346 /*********************/ |
|
347 /******************************/ |
|
348 /* B 1.2.1 - Numeric Literals */ |
|
349 /******************************/ |
|
350 void *print_datatypes_error_c::visit(real_c *symbol) { |
|
351 if (symbol->candidate_datatypes.size() == 0) { |
|
352 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_REAL data type."); |
|
353 } else if (NULL == symbol->datatype) { |
|
354 STAGE3_ERROR(4, symbol, symbol, "ANY_REAL data type not valid in this location."); |
|
355 } |
|
356 return NULL; |
|
357 } |
|
358 |
|
359 void *print_datatypes_error_c::visit(integer_c *symbol) { |
|
360 if (symbol->candidate_datatypes.size() == 0) { |
|
361 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_INT data type."); |
|
362 } else if (NULL == symbol->datatype) { |
|
363 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
364 } |
|
365 return NULL; |
|
366 } |
|
367 |
|
368 void *print_datatypes_error_c::visit(neg_real_c *symbol) { |
|
369 if (symbol->candidate_datatypes.size() == 0) { |
|
370 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_REAL data type."); |
|
371 } else if (NULL == symbol->datatype) { |
|
372 STAGE3_ERROR(4, symbol, symbol, "ANY_REAL data type not valid in this location."); |
|
373 } |
|
374 return NULL; |
|
375 } |
|
376 |
|
377 void *print_datatypes_error_c::visit(neg_integer_c *symbol) { |
|
378 if (symbol->candidate_datatypes.size() == 0) { |
|
379 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_INT data type."); |
|
380 } else if (NULL == symbol->datatype) { |
|
381 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
382 } |
|
383 return NULL; |
|
384 } |
|
385 |
|
386 void *print_datatypes_error_c::visit(binary_integer_c *symbol) { |
|
387 if (symbol->candidate_datatypes.size() == 0) { |
|
388 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_INT data type."); |
|
389 } else if (NULL == symbol->datatype) { |
|
390 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
391 } |
|
392 return NULL; |
|
393 } |
|
394 |
|
395 void *print_datatypes_error_c::visit(octal_integer_c *symbol) { |
|
396 if (symbol->candidate_datatypes.size() == 0) { |
|
397 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_INT data type."); |
|
398 } else if (NULL == symbol->datatype) { |
|
399 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
400 } |
|
401 return NULL; |
|
402 } |
|
403 |
|
404 void *print_datatypes_error_c::visit(hex_integer_c *symbol) { |
|
405 if (symbol->candidate_datatypes.size() == 0) { |
|
406 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for ANY_INT data type."); |
|
407 } else if (NULL == symbol->datatype) { |
|
408 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
409 } |
|
410 return NULL; |
|
411 } |
|
412 |
|
413 void *print_datatypes_error_c::visit(integer_literal_c *symbol) { |
|
414 if (symbol->candidate_datatypes.size() == 0) { |
|
415 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for %s data type.", elementary_type_c::to_string(symbol->type)); |
|
416 } else if (NULL == symbol->datatype) { |
|
417 STAGE3_ERROR(4, symbol, symbol, "ANY_INT data type not valid in this location."); |
|
418 } |
|
419 return NULL; |
|
420 } |
|
421 |
|
422 void *print_datatypes_error_c::visit(real_literal_c *symbol) { |
|
423 if (symbol->candidate_datatypes.size() == 0) { |
|
424 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for %s data type.", elementary_type_c::to_string(symbol->type)); |
|
425 } else if (NULL == symbol->datatype) { |
|
426 STAGE3_ERROR(4, symbol, symbol, "ANY_REAL data type not valid in this location."); |
|
427 } |
|
428 return NULL; |
|
429 } |
|
430 |
|
431 void *print_datatypes_error_c::visit(bit_string_literal_c *symbol) { |
|
432 if (symbol->candidate_datatypes.size() == 0) { |
|
433 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for %s data type.", elementary_type_c::to_string(symbol->type)); |
|
434 } else if (NULL == symbol->datatype) { |
|
435 STAGE3_ERROR(4, symbol, symbol, "ANY_BIT data type not valid in this location."); |
|
436 } |
|
437 return NULL; |
|
438 } |
|
439 |
|
440 void *print_datatypes_error_c::visit(boolean_literal_c *symbol) { |
|
441 if (symbol->candidate_datatypes.size() == 0) { |
|
442 STAGE3_ERROR(0, symbol, symbol, "Value is not valid for %s data type.", elementary_type_c::to_string(symbol->type)); |
|
443 } else if (NULL == symbol->datatype) { |
|
444 STAGE3_ERROR(4, symbol, symbol, "ANY_BOOL data type not valid in this location."); |
|
445 } |
|
446 return NULL; |
|
447 } |
|
448 |
|
449 void *print_datatypes_error_c::visit(boolean_true_c *symbol) { |
|
450 if (symbol->candidate_datatypes.size() == 0) { |
|
451 STAGE3_ERROR(0, symbol, symbol, "Value is not valid for ANY_BOOL data type."); |
|
452 } else if (NULL == symbol->datatype) { |
|
453 STAGE3_ERROR(4, symbol, symbol, "ANY_BOOL data type not valid in this location."); |
|
454 } |
|
455 return NULL; |
|
456 } |
|
457 |
|
458 void *print_datatypes_error_c::visit(boolean_false_c *symbol) { |
|
459 if (symbol->candidate_datatypes.size() == 0) { |
|
460 STAGE3_ERROR(0, symbol, symbol, "Value is not valid for ANY_BOOL data type."); |
|
461 } else if (NULL == symbol->datatype) { |
|
462 STAGE3_ERROR(4, symbol, symbol, "ANY_BOOL data type not valid in this location."); |
|
463 } |
|
464 return NULL; |
|
465 } |
|
466 |
|
467 /*******************************/ |
|
468 /* B.1.2.2 Character Strings */ |
|
469 /*******************************/ |
|
470 void *print_datatypes_error_c::visit(double_byte_character_string_c *symbol) { |
|
471 if (symbol->candidate_datatypes.size() == 0) { |
|
472 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for WSTRING data type."); |
|
473 } else if (NULL == symbol->datatype) { |
|
474 STAGE3_ERROR(4, symbol, symbol, "WSTRING data type not valid in this location."); |
|
475 } |
|
476 return NULL; |
|
477 } |
|
478 |
|
479 void *print_datatypes_error_c::visit(single_byte_character_string_c *symbol) { |
|
480 if (symbol->candidate_datatypes.size() == 0) { |
|
481 STAGE3_ERROR(0, symbol, symbol, "Numerical value exceeds range for STRING data type."); |
|
482 } else if (NULL == symbol->datatype) { |
|
483 STAGE3_ERROR(4, symbol, symbol, "STRING data type not valid in this location."); |
|
484 } |
|
485 return NULL; |
|
486 } |
|
487 |
|
488 /***************************/ |
|
489 /* B 1.2.3 - Time Literals */ |
|
490 /***************************/ |
|
491 /************************/ |
|
492 /* B 1.2.3.1 - Duration */ |
|
493 /************************/ |
|
494 void *print_datatypes_error_c::visit(duration_c *symbol) { |
|
495 if (symbol->candidate_datatypes.size() == 0) { |
|
496 STAGE3_ERROR(0, symbol, symbol, "Invalid syntax for TIME data type."); |
|
497 } else if (NULL == symbol->datatype) { |
|
498 STAGE3_ERROR(4, symbol, symbol, "TIME data type not valid in this location."); |
|
499 } |
|
500 return NULL; |
|
501 } |
|
502 |
|
503 /************************************/ |
|
504 /* B 1.2.3.2 - Time of day and Date */ |
|
505 /************************************/ |
|
506 void *print_datatypes_error_c::visit(time_of_day_c *symbol) { |
|
507 if (symbol->candidate_datatypes.size() == 0) { |
|
508 STAGE3_ERROR(0, symbol, symbol, "Invalid syntax for TOD data type."); |
|
509 } else if (NULL == symbol->datatype) { |
|
510 STAGE3_ERROR(4, symbol, symbol, "TOD data type not valid in this location."); |
|
511 } |
|
512 return NULL; |
|
513 } |
|
514 |
|
515 void *print_datatypes_error_c::visit(date_c *symbol) { |
|
516 if (symbol->candidate_datatypes.size() == 0) { |
|
517 STAGE3_ERROR(0, symbol, symbol, "Invalid syntax for DATE data type."); |
|
518 } else if (NULL == symbol->datatype) { |
|
519 STAGE3_ERROR(4, symbol, symbol, "DATE data type not valid in this location."); |
|
520 } |
|
521 return NULL; |
|
522 } |
|
523 |
|
524 void *print_datatypes_error_c::visit(date_and_time_c *symbol) { |
|
525 if (symbol->candidate_datatypes.size() == 0) { |
|
526 STAGE3_ERROR(0, symbol, symbol, "Invalid syntax for DT data type."); |
|
527 } else if (NULL == symbol->datatype) { |
|
528 STAGE3_ERROR(4, symbol, symbol, "DT data type not valid in this location."); |
|
529 } |
|
530 return NULL; |
|
531 } |
|
532 |
|
533 /**********************/ |
|
534 /* B 1.3 - Data types */ |
|
535 /**********************/ |
|
536 /********************************/ |
|
537 /* B 1.3.3 - Derived data types */ |
|
538 /********************************/ |
|
539 void *print_datatypes_error_c::visit(simple_spec_init_c *symbol) { |
|
540 if (!is_type_valid(symbol->simple_specification->datatype)) { |
|
541 STAGE3_ERROR(0, symbol->simple_specification, symbol->simple_specification, "Invalid data type."); |
|
542 } else if (NULL != symbol->constant) { |
|
543 if (!is_type_valid(symbol->constant->datatype)) |
|
544 STAGE3_ERROR(0, symbol->constant, symbol->constant, "Initial value has incompatible data type."); |
|
545 } else if (!is_type_valid(symbol->datatype)) { |
|
546 ERROR; /* If we have an error here, then we must also have an error in one of |
|
547 * the two previous tests. If we reach this point, some strange error is ocurring! |
|
548 */ |
|
549 } |
|
550 return NULL; |
|
551 } |
|
552 |
|
553 void *print_datatypes_error_c::visit(data_type_declaration_c *symbol) { |
|
554 // TODO !!! |
|
555 /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ |
|
556 return NULL; |
|
557 } |
|
558 |
|
559 void *print_datatypes_error_c::visit(enumerated_value_c *symbol) { |
|
560 if (symbol->candidate_datatypes.size() == 0) |
|
561 STAGE3_ERROR(0, symbol, symbol, "Ambiguous enumerate value or Variable not declared in this scope."); |
|
562 return NULL; |
|
563 } |
|
564 |
|
565 |
|
566 /*********************/ |
|
567 /* B 1.4 - Variables */ |
|
568 /*********************/ |
|
569 void *print_datatypes_error_c::visit(symbolic_variable_c *symbol) { |
|
570 if (symbol->candidate_datatypes.size() == 0) |
|
571 STAGE3_ERROR(0, symbol, symbol, "Variable not declared in this scope."); |
|
572 return NULL; |
|
573 } |
|
574 |
|
575 /********************************************/ |
|
576 /* B 1.4.1 - Directly Represented Variables */ |
|
577 /********************************************/ |
|
578 void *print_datatypes_error_c::visit(direct_variable_c *symbol) { |
|
579 if (symbol->candidate_datatypes.size() == 0) ERROR; |
|
580 if (!is_type_valid(symbol->datatype)) |
|
581 STAGE3_ERROR(4, symbol, symbol, "Direct variable has incompatible data type with expression."); |
|
582 return NULL; |
|
583 } |
|
584 |
|
585 /*************************************/ |
|
586 /* B 1.4.2 - Multi-element variables */ |
|
587 /*************************************/ |
|
588 /* subscripted_variable '[' subscript_list ']' */ |
|
589 // SYM_REF2(array_variable_c, subscripted_variable, subscript_list) |
|
590 void *print_datatypes_error_c::visit(array_variable_c *symbol) { |
|
591 if (symbol->candidate_datatypes.size() == 0) |
|
592 STAGE3_ERROR(0, symbol, symbol, "Array variable not declared in this scope."); |
|
593 |
|
594 /* recursively call the subscript list to print any errors in the expressions used in the subscript...*/ |
|
595 symbol->subscript_list->accept(*this); |
|
596 return NULL; |
|
597 } |
|
598 |
|
599 /* subscript_list ',' subscript */ |
|
600 // SYM_LIST(subscript_list_c) |
|
601 void *print_datatypes_error_c::visit(subscript_list_c *symbol) { |
|
602 for (int i = 0; i < symbol->n; i++) { |
|
603 int start_error_count = error_count; |
|
604 symbol->elements[i]->accept(*this); |
|
605 /* The following error message will only get printed if the current_display_error_level is set higher than 0! */ |
|
606 if ((start_error_count == error_count) && (NULL == symbol->elements[i]->datatype)) |
|
607 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for array subscript field."); |
|
608 } |
|
609 return NULL; |
|
610 } |
|
611 |
|
612 |
|
613 /* record_variable '.' field_selector */ |
|
614 /* WARNING: input and/or output variables of function blocks |
|
615 * may be accessed as fields of a structured variable! |
|
616 * Code handling a structured_variable_c must take |
|
617 * this into account! |
|
618 */ |
|
619 // SYM_REF2(structured_variable_c, record_variable, field_selector) |
|
620 /* NOTE: We do not recursively determine the data types of each field_selector in fill_candidate_datatypes_c, |
|
621 * so it does not make sense to recursively visit all the field_selectors to print out error messages. |
|
622 * Maybe in the future, if we find the need to print out more detailed error messages, we might do it that way. For now, we don't! |
|
623 */ |
|
624 void *print_datatypes_error_c::visit(structured_variable_c *symbol) { |
|
625 if (symbol->candidate_datatypes.size() == 0) |
|
626 STAGE3_ERROR(0, symbol, symbol, "Undeclared structured/FB variable."); |
|
627 return NULL; |
|
628 } |
|
629 |
|
630 |
|
631 |
|
632 /******************************************/ |
|
633 /* B 1.4.3 - Declaration & Initialisation */ |
|
634 /******************************************/ |
|
635 |
|
636 /* AT direct_variable */ |
|
637 // SYM_REF1(location_c, direct_variable) |
|
638 void *print_datatypes_error_c::visit(location_c *symbol) { |
|
639 symbol->direct_variable->accept(*this); |
|
640 return NULL; |
|
641 } |
|
642 |
|
643 |
|
644 /* [variable_name] location ':' located_var_spec_init */ |
|
645 /* variable_name -> may be NULL ! */ |
|
646 // SYM_REF3(located_var_decl_c, variable_name, location, located_var_spec_init) |
|
647 void *print_datatypes_error_c::visit(located_var_decl_c *symbol) { |
|
648 symbol->located_var_spec_init->accept(*this); |
|
649 /* It does not make sense to call symbol->location->accept(*this). The check is done right here if the following if() */ |
|
650 // symbol->location->accept(*this); |
|
651 if ((is_type_valid(symbol->located_var_spec_init->datatype)) && (!is_type_valid(symbol->location->datatype))) |
|
652 STAGE3_ERROR(0, symbol, symbol, "Bit size of data type is incompatible with bit size of location."); |
|
653 return NULL; |
|
654 } |
|
655 |
|
656 |
|
657 /************************************/ |
|
658 /* B 1.5 Program organization units */ |
|
659 /************************************/ |
|
660 /*********************/ |
|
661 /* B 1.5.1 Functions */ |
|
662 /*********************/ |
|
663 void *print_datatypes_error_c::visit(function_declaration_c *symbol) { |
|
664 search_varfb_instance_type = new search_varfb_instance_type_c(symbol); |
|
665 /* We do not check for data type errors in variable declarations, Skip this for now... */ |
|
666 // symbol->var_declarations_list->accept(*this); |
|
667 if (debug) printf("Print error data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); |
|
668 il_parenthesis_level = 0; |
|
669 il_error = false; |
|
670 symbol->function_body->accept(*this); |
|
671 delete search_varfb_instance_type; |
|
672 search_varfb_instance_type = NULL; |
|
673 return NULL; |
|
674 } |
|
675 |
|
676 /***************************/ |
|
677 /* B 1.5.2 Function blocks */ |
|
678 /***************************/ |
|
679 void *print_datatypes_error_c::visit(function_block_declaration_c *symbol) { |
|
680 search_varfb_instance_type = new search_varfb_instance_type_c(symbol); |
|
681 /* We do not check for data type errors in variable declarations, Skip this for now... */ |
|
682 // symbol->var_declarations->accept(*this); |
|
683 if (debug) printf("Print error data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); |
|
684 il_parenthesis_level = 0; |
|
685 il_error = false; |
|
686 symbol->fblock_body->accept(*this); |
|
687 delete search_varfb_instance_type; |
|
688 search_varfb_instance_type = NULL; |
|
689 return NULL; |
|
690 } |
|
691 |
|
692 /**********************/ |
|
693 /* B 1.5.3 - Programs */ |
|
694 /**********************/ |
|
695 void *print_datatypes_error_c::visit(program_declaration_c *symbol) { |
|
696 search_varfb_instance_type = new search_varfb_instance_type_c(symbol); |
|
697 /* We do not check for data type errors in variable declarations, Skip this for now... */ |
|
698 symbol->var_declarations->accept(*this); |
|
699 if (debug) printf("Print error data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); |
|
700 il_parenthesis_level = 0; |
|
701 il_error = false; |
|
702 symbol->function_block_body->accept(*this); |
|
703 delete search_varfb_instance_type; |
|
704 search_varfb_instance_type = NULL; |
|
705 return NULL; |
|
706 } |
|
707 |
|
708 |
|
709 |
|
710 /********************************/ |
|
711 /* B 1.7 Configuration elements */ |
|
712 /********************************/ |
|
713 void *print_datatypes_error_c::visit(configuration_declaration_c *symbol) { |
|
714 // TODO !!! |
|
715 /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */ |
|
716 return NULL; |
|
717 } |
|
718 |
|
719 /****************************************/ |
|
720 /* B.2 - Language IL (Instruction List) */ |
|
721 /****************************************/ |
|
722 /***********************************/ |
|
723 /* B 2.1 Instructions and Operands */ |
|
724 /***********************************/ |
|
725 |
|
726 // void *visit(instruction_list_c *symbol); |
|
727 |
|
728 /* | label ':' [il_incomplete_instruction] eol_list */ |
|
729 // SYM_REF2(il_instruction_c, label, il_instruction) |
|
730 void *print_datatypes_error_c::visit(il_instruction_c *symbol) { |
|
731 if (NULL != symbol->il_instruction) { |
|
732 il_instruction_c tmp_prev_il_instruction(NULL, NULL); |
|
733 #if 0 |
|
734 /* NOTE: The following is currently no longer needed. Since the following code is actually cool, |
|
735 * we don't delete it, but simply comment it out. It might just come in handy later on... |
|
736 */ |
|
737 /* When handling a il function call, this fake_prev_il_instruction may be used as a standard function call parameter, so it is important that |
|
738 * it contain some valid location info so error messages make sense. |
|
739 */ |
|
740 if (symbol->prev_il_instruction.size() > 0) { |
|
741 /* since we don't want to copy all that data one variable at a time, we copy it all at once */ |
|
742 /* This has the advantage that, if we ever add some more data to the base symbol_c later on, we will not need to |
|
743 * change the following line to guarantee that the data is copied correctly! |
|
744 * However, it does have the drawback of copying more data than what we want! |
|
745 * In order to only copy the data in the base class symbol_c, we use the tmp_symbol pointer! |
|
746 * I (mario) have checked with a debugger, and it is working as intended! |
|
747 */ |
|
748 symbol_c *tmp_symbol1 = symbol->prev_il_instruction[0]; |
|
749 symbol_c *tmp_symbol2 = &tmp_prev_il_instruction; |
|
750 *tmp_symbol2 = *tmp_symbol1; |
|
751 /* we do not want to copy the datatype variable, so we reset it to NULL */ |
|
752 tmp_prev_il_instruction.datatype = NULL; |
|
753 /* We don't need to worry about the candidate_datatype list (which we don't want to copy just yet), since that will |
|
754 * be reset to the correct value when we call intersect_prev_candidate_datatype_lists() later on... |
|
755 */ |
|
756 } |
|
757 #endif |
|
758 /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the |
|
759 * list of the prev_il_instructions. |
|
760 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), |
|
761 * and shove that data into this single variable. |
|
762 */ |
|
763 tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; |
|
764 intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction); |
|
765 if (are_all_datatypes_of_prev_il_instructions_datatypes_equal(symbol)) |
|
766 if (symbol->prev_il_instruction.size() > 0) |
|
767 tmp_prev_il_instruction.datatype = (symbol->prev_il_instruction[0])->datatype; |
|
768 |
|
769 /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */ |
|
770 fake_prev_il_instruction = &tmp_prev_il_instruction; |
|
771 symbol->il_instruction->accept(*this); |
|
772 fake_prev_il_instruction = NULL; |
|
773 } |
|
774 |
|
775 return NULL; |
|
776 } |
|
777 |
|
778 |
|
779 |
|
780 void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) { |
|
781 il_operand = symbol->il_operand; |
|
782 if (NULL != symbol->il_operand) { |
|
783 symbol->il_operand->accept(*this); |
|
784 } |
|
785 /* recursive call to see whether data types are compatible */ |
|
786 symbol->il_simple_operator->accept(*this); |
|
787 il_operand = NULL; |
|
788 return NULL; |
|
789 } |
|
790 |
|
791 /* | function_name [il_operand_list] */ |
|
792 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ |
|
793 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
794 void *print_datatypes_error_c::visit(il_function_call_c *symbol) { |
|
795 /* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction) |
|
796 * In order to be able to handle this without coding special cases, we will simply prepend that symbol |
|
797 * to the il_operand_list, and remove it after calling handle_function_call(). |
|
798 * |
|
799 * However, if no further paramters are given, then il_operand_list will be NULL, and we will |
|
800 * need to create a new object to hold the pointer to prev_il_instruction. |
|
801 * This change will also be undone later in print_datatypes_error_c. |
|
802 */ |
|
803 if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; |
|
804 if (NULL == symbol->il_operand_list) ERROR; |
|
805 |
|
806 ((list_c *)symbol->il_operand_list)->insert_element(fake_prev_il_instruction, 0); |
|
807 |
|
808 generic_function_call_t fcall_param = { |
|
809 /* fcall_param.function_name = */ symbol->function_name, |
|
810 /* fcall_param.nonformal_operand_list = */ symbol->il_operand_list, |
|
811 /* fcall_param.formal_operand_list = */ NULL, |
|
812 /* enum {POU_FB, POU_function} POU_type = */ generic_function_call_t::POU_function, |
|
813 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
|
814 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
|
815 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
|
816 }; |
|
817 |
|
818 /* TODO: check what error message (if any) the compiler will give out if this function invocation |
|
819 * is not preceded by a LD operator (or another equivalent operator or list of operators). |
|
820 */ |
|
821 handle_function_invocation(symbol, fcall_param); |
|
822 |
|
823 /* We now undo those changes to the abstract syntax tree made above! */ |
|
824 ((list_c *)symbol->il_operand_list)->remove_element(0); |
|
825 if (((list_c *)symbol->il_operand_list)->n == 0) { |
|
826 /* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */ |
|
827 delete symbol->il_operand_list; |
|
828 symbol->il_operand_list = NULL; |
|
829 } |
|
830 |
|
831 return NULL; |
|
832 } |
|
833 |
|
834 |
|
835 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
|
836 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
|
837 void *print_datatypes_error_c::visit(il_expression_c *symbol) { |
|
838 /* first give the parenthesised IL list a chance to print errors */ |
|
839 il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; |
|
840 symbol->simple_instr_list->accept(*this); |
|
841 fake_prev_il_instruction = save_fake_prev_il_instruction; |
|
842 |
|
843 /* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */ |
|
844 il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */ |
|
845 symbol->il_expr_operator->accept(*this); |
|
846 |
|
847 return NULL; |
|
848 } |
|
849 |
|
850 |
|
851 /* il_call_operator prev_declared_fb_name |
|
852 * | il_call_operator prev_declared_fb_name '(' ')' |
|
853 * | il_call_operator prev_declared_fb_name '(' eol_list ')' |
|
854 * | il_call_operator prev_declared_fb_name '(' il_operand_list ')' |
|
855 * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
|
856 */ |
|
857 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ |
|
858 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
|
859 void *print_datatypes_error_c::visit(il_fb_call_c *symbol) { |
|
860 int extensible_param_count; /* unused vairable! Needed for compilation only! */ |
|
861 std::vector <symbol_c *> candidate_functions; /* unused vairable! Needed for compilation only! */ |
|
862 generic_function_call_t fcall_param = { |
|
863 /* fcall_param.function_name = */ symbol->fb_name, |
|
864 /* fcall_param.nonformal_operand_list = */ symbol->il_operand_list, |
|
865 /* fcall_param.formal_operand_list = */ symbol->il_param_list, |
|
866 /* enum {POU_FB, POU_function} POU_type = */ generic_function_call_t::POU_FB, |
|
867 /* fcall_param.candidate_functions = */ candidate_functions, /* will not be used, but must provide a reference to be able to compile */ |
|
868 /* fcall_param.called_function_declaration = */ symbol->called_fb_declaration, |
|
869 /* fcall_param.extensible_param_count = */ extensible_param_count /* will not be used, but must provide a reference to be able to compile */ |
|
870 }; |
|
871 |
|
872 handle_function_invocation(symbol, fcall_param); |
|
873 /* check the semantics of the CALC, CALCN operators! */ |
|
874 symbol->il_call_operator->accept(*this); |
|
875 return NULL; |
|
876 } |
|
877 |
|
878 /* | function_name '(' eol_list [il_param_list] ')' */ |
|
879 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
|
880 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) |
|
881 void *print_datatypes_error_c::visit(il_formal_funct_call_c *symbol) { |
|
882 generic_function_call_t fcall_param = { |
|
883 /* fcall_param.function_name = */ symbol->function_name, |
|
884 /* fcall_param.nonformal_operand_list = */ NULL, |
|
885 /* fcall_param.formal_operand_list = */ symbol->il_param_list, |
|
886 /* enum {POU_FB, POU_function} POU_type = */ generic_function_call_t::POU_function, |
|
887 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
|
888 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
|
889 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
|
890 }; |
|
891 |
|
892 handle_function_invocation(symbol, fcall_param); |
|
893 return NULL; |
|
894 } |
|
895 |
|
896 |
|
897 // void *visit(il_operand_list_c *symbol); |
|
898 // void *visit(simple_instr_list_c *symbol); |
|
899 |
|
900 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
|
901 void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) { |
|
902 if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ |
|
903 |
|
904 il_instruction_c tmp_prev_il_instruction(NULL, NULL); |
|
905 /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the |
|
906 * list of the prev_il_instructions. |
|
907 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), |
|
908 * and shove that data into this single variable. |
|
909 */ |
|
910 if (symbol->prev_il_instruction.size() > 0) |
|
911 tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes; |
|
912 tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; |
|
913 |
|
914 /* copy the candidate_datatypes list */ |
|
915 fake_prev_il_instruction = &tmp_prev_il_instruction; |
|
916 symbol->il_simple_instruction->accept(*this); |
|
917 fake_prev_il_instruction = NULL; |
|
918 return NULL; |
|
919 |
|
920 |
|
921 // if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
922 // else prev_il_instruction = symbol->prev_il_instruction[0]; |
|
923 |
|
924 // symbol->il_simple_instruction->accept(*this); |
|
925 // prev_il_instruction = NULL; |
|
926 // return NULL; |
|
927 } |
|
928 |
|
929 |
|
930 // void *visit(il_param_list_c *symbol); |
|
931 // void *visit(il_param_assignment_c *symbol); |
|
932 // void *visit(il_param_out_assignment_c *symbol); |
|
933 |
|
934 /*******************/ |
|
935 /* B 2.2 Operators */ |
|
936 /*******************/ |
|
937 void *print_datatypes_error_c::print_binary_operator_errors(const char *il_operator, symbol_c *symbol, bool deprecated_operation) { |
|
938 if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) { |
|
939 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator); |
|
940 } else if (NULL == symbol->datatype) { |
|
941 STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator); |
|
942 } else if (deprecated_operation) |
|
943 STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator); |
|
944 return NULL; |
|
945 } |
|
946 |
|
947 |
|
948 void *print_datatypes_error_c::visit(LD_operator_c *symbol) { |
|
949 return NULL; |
|
950 } |
|
951 |
|
952 void *print_datatypes_error_c::visit(LDN_operator_c *symbol) { |
|
953 if ((symbol->candidate_datatypes.size() == 0) && |
|
954 (il_operand->candidate_datatypes.size() > 0)) |
|
955 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'LDN' operator."); |
|
956 return NULL; |
|
957 } |
|
958 |
|
959 void *print_datatypes_error_c::visit(ST_operator_c *symbol) { |
|
960 /* MANU: |
|
961 * if prev_instruction is NULL we can print a message error or warning error like: |
|
962 * we can't use a ST like first instruction. |
|
963 * What do you think? |
|
964 */ |
|
965 if ((symbol->candidate_datatypes.size() == 0) && |
|
966 (il_operand->candidate_datatypes.size() > 0)) |
|
967 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'ST' operator."); |
|
968 return NULL; |
|
969 } |
|
970 |
|
971 void *print_datatypes_error_c::visit(STN_operator_c *symbol) { |
|
972 /* MANU: |
|
973 * if prev_instruction is NULL we can print a message error or warning error like: |
|
974 * we can't use a ST like first instruction. |
|
975 * What do you think? |
|
976 */ |
|
977 if ((symbol->candidate_datatypes.size() == 0) && |
|
978 (il_operand->candidate_datatypes.size() > 0)) |
|
979 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'STN' operator."); |
|
980 return NULL; |
|
981 } |
|
982 |
|
983 void *print_datatypes_error_c::visit(NOT_operator_c *symbol) { |
|
984 /* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand> |
|
985 * NOT [<il_operand>] |
|
986 * However, it does not define the semantic of the NOT operation when the <il_operand> is specified. |
|
987 * We therefore consider it an error if an il_operand is specified! |
|
988 */ |
|
989 if (il_operand != NULL) |
|
990 STAGE3_ERROR(0, symbol, symbol, "'NOT' operator may not have an operand."); |
|
991 if (symbol->candidate_datatypes.size() == 0) |
|
992 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'NOT' operator."); |
|
993 return NULL; |
|
994 } |
|
995 |
|
996 void *print_datatypes_error_c::visit(S_operator_c *symbol) { |
|
997 /* TODO: what if this is a FB call ?? */ |
|
998 if ((symbol->candidate_datatypes.size() == 0) && |
|
999 (il_operand->candidate_datatypes.size() > 0)) |
|
1000 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'S' operator."); |
|
1001 return NULL; |
|
1002 } |
|
1003 |
|
1004 void *print_datatypes_error_c::visit(R_operator_c *symbol) { |
|
1005 /* TODO: what if this is a FB call ?? */ |
|
1006 if ((symbol->candidate_datatypes.size() == 0) && |
|
1007 (il_operand->candidate_datatypes.size() > 0)) |
|
1008 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'R' operator."); |
|
1009 return NULL; |
|
1010 } |
|
1011 |
|
1012 void *print_datatypes_error_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_invocation( "S1", symbol, symbol->called_fb_declaration);} |
|
1013 void *print_datatypes_error_c::visit( R1_operator_c *symbol) {return handle_implicit_il_fb_invocation( "R1", symbol, symbol->called_fb_declaration);} |
|
1014 void *print_datatypes_error_c::visit(CLK_operator_c *symbol) {return handle_implicit_il_fb_invocation("CLK", symbol, symbol->called_fb_declaration);} |
|
1015 void *print_datatypes_error_c::visit( CU_operator_c *symbol) {return handle_implicit_il_fb_invocation( "CU", symbol, symbol->called_fb_declaration);} |
|
1016 void *print_datatypes_error_c::visit( CD_operator_c *symbol) {return handle_implicit_il_fb_invocation( "CD", symbol, symbol->called_fb_declaration);} |
|
1017 void *print_datatypes_error_c::visit( PV_operator_c *symbol) {return handle_implicit_il_fb_invocation( "PV", symbol, symbol->called_fb_declaration);} |
|
1018 void *print_datatypes_error_c::visit( IN_operator_c *symbol) {return handle_implicit_il_fb_invocation( "IN", symbol, symbol->called_fb_declaration);} |
|
1019 void *print_datatypes_error_c::visit( PT_operator_c *symbol) {return handle_implicit_il_fb_invocation( "PT", symbol, symbol->called_fb_declaration);} |
|
1020 |
|
1021 void *print_datatypes_error_c::visit( AND_operator_c *symbol) {return print_binary_operator_errors("AND" , symbol);} |
|
1022 void *print_datatypes_error_c::visit( OR_operator_c *symbol) {return print_binary_operator_errors( "OR" , symbol);} |
|
1023 void *print_datatypes_error_c::visit( XOR_operator_c *symbol) {return print_binary_operator_errors("XOR" , symbol);} |
|
1024 void *print_datatypes_error_c::visit(ANDN_operator_c *symbol) {return print_binary_operator_errors("ANDN", symbol);} |
|
1025 void *print_datatypes_error_c::visit( ORN_operator_c *symbol) {return print_binary_operator_errors( "ORN", symbol);} |
|
1026 void *print_datatypes_error_c::visit(XORN_operator_c *symbol) {return print_binary_operator_errors("XORN", symbol);} |
|
1027 void *print_datatypes_error_c::visit( ADD_operator_c *symbol) {return print_binary_operator_errors("ADD" , symbol, symbol->deprecated_operation);} |
|
1028 void *print_datatypes_error_c::visit( SUB_operator_c *symbol) {return print_binary_operator_errors("SUB" , symbol, symbol->deprecated_operation);} |
|
1029 void *print_datatypes_error_c::visit( MUL_operator_c *symbol) {return print_binary_operator_errors("MUL" , symbol, symbol->deprecated_operation);} |
|
1030 void *print_datatypes_error_c::visit( DIV_operator_c *symbol) {return print_binary_operator_errors("DIV" , symbol, symbol->deprecated_operation);} |
|
1031 void *print_datatypes_error_c::visit( MOD_operator_c *symbol) {return print_binary_operator_errors("MOD" , symbol);} |
|
1032 |
|
1033 void *print_datatypes_error_c::visit( GT_operator_c *symbol) {return print_binary_operator_errors( "GT" , symbol);} |
|
1034 void *print_datatypes_error_c::visit( GE_operator_c *symbol) {return print_binary_operator_errors( "GE" , symbol);} |
|
1035 void *print_datatypes_error_c::visit( EQ_operator_c *symbol) {return print_binary_operator_errors( "EQ" , symbol);} |
|
1036 void *print_datatypes_error_c::visit( LT_operator_c *symbol) {return print_binary_operator_errors( "LT" , symbol);} |
|
1037 void *print_datatypes_error_c::visit( LE_operator_c *symbol) {return print_binary_operator_errors( "LE" , symbol);} |
|
1038 void *print_datatypes_error_c::visit( NE_operator_c *symbol) {return print_binary_operator_errors( "NE" , symbol);} |
|
1039 |
|
1040 |
|
1041 |
|
1042 |
|
1043 void *print_datatypes_error_c::handle_conditional_flow_control_IL_instruction(symbol_c *symbol, const char *oper) { |
|
1044 if (NULL == symbol->datatype) |
|
1045 STAGE3_ERROR(0, symbol, symbol, "%s operator must be preceded by an IL instruction producing a BOOL value.", oper); |
|
1046 return NULL; |
|
1047 } |
|
1048 |
|
1049 void *print_datatypes_error_c::visit( CAL_operator_c *symbol) {return NULL;} |
|
1050 void *print_datatypes_error_c::visit( CALC_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "CALC" );} |
|
1051 void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "CALCN");} |
|
1052 void *print_datatypes_error_c::visit( RET_operator_c *symbol) {return NULL;} |
|
1053 void *print_datatypes_error_c::visit( RETC_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "RETC" );} |
|
1054 void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "RETCN");} |
|
1055 void *print_datatypes_error_c::visit( JMP_operator_c *symbol) {return NULL;} |
|
1056 void *print_datatypes_error_c::visit( JMPC_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "JMPC" );} |
|
1057 void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) {return handle_conditional_flow_control_IL_instruction(symbol, "JMPCN");} |
|
1058 |
|
1059 |
|
1060 |
|
1061 /* Symbol class handled together with function call checks */ |
|
1062 // void *visit(il_assign_operator_c *symbol, variable_name); |
|
1063 /* Symbol class handled together with function call checks */ |
|
1064 // void *visit(il_assign_operator_c *symbol, option, variable_name); |
|
1065 |
|
1066 /***************************************/ |
|
1067 /* B.3 - Language ST (Structured Text) */ |
|
1068 /***************************************/ |
|
1069 /***********************/ |
|
1070 /* B 3.1 - Expressions */ |
|
1071 /***********************/ |
|
1072 |
|
1073 void *print_datatypes_error_c::print_binary_expression_errors(const char *operation, symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool deprecated_operation) { |
|
1074 l_expr->accept(*this); |
|
1075 r_expr->accept(*this); |
|
1076 if ((symbol->candidate_datatypes.size() == 0) && |
|
1077 (l_expr->candidate_datatypes.size() > 0) && |
|
1078 (r_expr->candidate_datatypes.size() > 0)) |
|
1079 STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' expression.", operation); |
|
1080 if (deprecated_operation) |
|
1081 STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' expression.", operation); |
|
1082 return NULL; |
|
1083 } |
|
1084 |
|
1085 |
|
1086 void *print_datatypes_error_c::visit( or_expression_c *symbol) {return print_binary_expression_errors( "OR", symbol, symbol->l_exp, symbol->r_exp);} |
|
1087 void *print_datatypes_error_c::visit( xor_expression_c *symbol) {return print_binary_expression_errors("XOR", symbol, symbol->l_exp, symbol->r_exp);} |
|
1088 void *print_datatypes_error_c::visit( and_expression_c *symbol) {return print_binary_expression_errors("AND", symbol, symbol->l_exp, symbol->r_exp);} |
|
1089 void *print_datatypes_error_c::visit( equ_expression_c *symbol) {return print_binary_expression_errors( "=" , symbol, symbol->l_exp, symbol->r_exp);} |
|
1090 void *print_datatypes_error_c::visit(notequ_expression_c *symbol) {return print_binary_expression_errors( "<>", symbol, symbol->l_exp, symbol->r_exp);} |
|
1091 void *print_datatypes_error_c::visit( lt_expression_c *symbol) {return print_binary_expression_errors( "<" , symbol, symbol->l_exp, symbol->r_exp);} |
|
1092 void *print_datatypes_error_c::visit( gt_expression_c *symbol) {return print_binary_expression_errors( ">" , symbol, symbol->l_exp, symbol->r_exp);} |
|
1093 void *print_datatypes_error_c::visit( le_expression_c *symbol) {return print_binary_expression_errors( "<=", symbol, symbol->l_exp, symbol->r_exp);} |
|
1094 void *print_datatypes_error_c::visit( ge_expression_c *symbol) {return print_binary_expression_errors( ">=", symbol, symbol->l_exp, symbol->r_exp);} |
|
1095 void *print_datatypes_error_c::visit( add_expression_c *symbol) {return print_binary_expression_errors( "+" , symbol, symbol->l_exp, symbol->r_exp, symbol->deprecated_operation);} |
|
1096 void *print_datatypes_error_c::visit( sub_expression_c *symbol) {return print_binary_expression_errors( "-" , symbol, symbol->l_exp, symbol->r_exp, symbol->deprecated_operation);} |
|
1097 void *print_datatypes_error_c::visit( mul_expression_c *symbol) {return print_binary_expression_errors( "*" , symbol, symbol->l_exp, symbol->r_exp, symbol->deprecated_operation);} |
|
1098 void *print_datatypes_error_c::visit( div_expression_c *symbol) {return print_binary_expression_errors( "/" , symbol, symbol->l_exp, symbol->r_exp, symbol->deprecated_operation);} |
|
1099 void *print_datatypes_error_c::visit( mod_expression_c *symbol) {return print_binary_expression_errors("MOD", symbol, symbol->l_exp, symbol->r_exp);} |
|
1100 void *print_datatypes_error_c::visit( power_expression_c *symbol) {return print_binary_expression_errors( "**", symbol, symbol->l_exp, symbol->r_exp);} |
|
1101 |
|
1102 |
|
1103 void *print_datatypes_error_c::visit(neg_expression_c *symbol) { |
|
1104 symbol->exp->accept(*this); |
|
1105 if ((symbol->candidate_datatypes.size() == 0) && |
|
1106 (symbol->exp->candidate_datatypes.size() > 0)) |
|
1107 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'NEG' expression."); |
|
1108 return NULL; |
|
1109 } |
|
1110 |
|
1111 |
|
1112 void *print_datatypes_error_c::visit(not_expression_c *symbol) { |
|
1113 symbol->exp->accept(*this); |
|
1114 if ((symbol->candidate_datatypes.size() == 0) && |
|
1115 (symbol->exp->candidate_datatypes.size() > 0)) |
|
1116 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'NOT' expression."); |
|
1117 return NULL; |
|
1118 } |
|
1119 |
|
1120 /* NOTE: The parameter 'called_function_declaration', 'extensible_param_count' and 'candidate_functions' are used to pass data between the stage 3 and stage 4. */ |
|
1121 /* formal_param_list -> may be NULL ! */ |
|
1122 /* nonformal_param_list -> may be NULL ! */ |
|
1123 // SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector <symbol_c *> candidate_functions;) |
|
1124 void *print_datatypes_error_c::visit(function_invocation_c *symbol) { |
|
1125 generic_function_call_t fcall_param = { |
|
1126 /* fcall_param.function_name = */ symbol->function_name, |
|
1127 /* fcall_param.nonformal_operand_list = */ symbol->nonformal_param_list, |
|
1128 /* fcall_param.formal_operand_list = */ symbol->formal_param_list, |
|
1129 /* enum {POU_FB, POU_function} POU_type = */ generic_function_call_t::POU_function, |
|
1130 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
|
1131 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
|
1132 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
|
1133 }; |
|
1134 |
|
1135 handle_function_invocation(symbol, fcall_param); |
|
1136 return NULL; |
|
1137 } |
|
1138 |
|
1139 |
|
1140 |
|
1141 /********************/ |
|
1142 /* B 3.2 Statements */ |
|
1143 /********************/ |
|
1144 |
|
1145 /*********************************/ |
|
1146 /* B 3.2.1 Assignment Statements */ |
|
1147 /*********************************/ |
|
1148 void *print_datatypes_error_c::visit(assignment_statement_c *symbol) { |
|
1149 symbol->l_exp->accept(*this); |
|
1150 symbol->r_exp->accept(*this); |
|
1151 if ((NULL == symbol->l_exp->datatype) && |
|
1152 (NULL == symbol->r_exp->datatype) && |
|
1153 (symbol->l_exp->candidate_datatypes.size() > 0) && |
|
1154 (symbol->r_exp->candidate_datatypes.size() > 0)) |
|
1155 STAGE3_ERROR(0, symbol, symbol, "Incompatible data types for ':=' operation."); |
|
1156 return NULL; |
|
1157 } |
|
1158 |
|
1159 |
|
1160 /*****************************************/ |
|
1161 /* B 3.2.2 Subprogram Control Statements */ |
|
1162 /*****************************************/ |
|
1163 /* fb_name '(' [param_assignment_list] ')' */ |
|
1164 /* formal_param_list -> may be NULL ! */ |
|
1165 /* nonformal_param_list -> may be NULL ! */ |
|
1166 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ |
|
1167 // SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list, symbol_c *called_fb_declaration;) |
|
1168 void *print_datatypes_error_c::visit(fb_invocation_c *symbol) { |
|
1169 int extensible_param_count; /* unused vairable! Needed for compilation only! */ |
|
1170 std::vector <symbol_c *> candidate_functions; /* unused vairable! Needed for compilation only! */ |
|
1171 generic_function_call_t fcall_param = { |
|
1172 /* fcall_param.function_name = */ symbol->fb_name, |
|
1173 /* fcall_param.nonformal_operand_list = */ symbol->nonformal_param_list, |
|
1174 /* fcall_param.formal_operand_list = */ symbol->formal_param_list, |
|
1175 /* enum {POU_FB, POU_function} POU_type = */ generic_function_call_t::POU_FB, |
|
1176 /* fcall_param.candidate_functions = */ candidate_functions, /* will not be used, but must provide a reference to be able to compile */ |
|
1177 /* fcall_param.called_function_declaration = */ symbol->called_fb_declaration, |
|
1178 /* fcall_param.extensible_param_count = */ extensible_param_count /* will not be used, but must provide a reference to be able to compile */ |
|
1179 }; |
|
1180 |
|
1181 handle_function_invocation(symbol, fcall_param); |
|
1182 return NULL; |
|
1183 } |
|
1184 |
|
1185 |
|
1186 /********************************/ |
|
1187 /* B 3.2.3 Selection Statements */ |
|
1188 /********************************/ |
|
1189 |
|
1190 void *print_datatypes_error_c::visit(if_statement_c *symbol) { |
|
1191 symbol->expression->accept(*this); |
|
1192 if ((NULL == symbol->expression->datatype) && |
|
1193 (symbol->expression->candidate_datatypes.size() > 0)) { |
|
1194 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'IF' condition."); |
|
1195 } |
|
1196 if (NULL != symbol->statement_list) |
|
1197 symbol->statement_list->accept(*this); |
|
1198 if (NULL != symbol->elseif_statement_list) |
|
1199 symbol->elseif_statement_list->accept(*this); |
|
1200 if (NULL != symbol->else_statement_list) |
|
1201 symbol->else_statement_list->accept(*this); |
|
1202 return NULL; |
|
1203 } |
|
1204 |
|
1205 void *print_datatypes_error_c::visit(elseif_statement_c *symbol) { |
|
1206 symbol->expression->accept(*this); |
|
1207 if ((NULL == symbol->expression->datatype) && |
|
1208 (symbol->expression->candidate_datatypes.size() > 0)) { |
|
1209 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'ELSIF' condition."); |
|
1210 } |
|
1211 if (NULL != symbol->statement_list) |
|
1212 symbol->statement_list->accept(*this); |
|
1213 return NULL; |
|
1214 } |
|
1215 |
|
1216 |
|
1217 void *print_datatypes_error_c::visit(case_statement_c *symbol) { |
|
1218 symbol->expression->accept(*this); |
|
1219 if ((NULL == symbol->expression->datatype) && |
|
1220 (symbol->expression->candidate_datatypes.size() > 0)) { |
|
1221 STAGE3_ERROR(0, symbol, symbol, "'CASE' quantity not an integer or enumerated."); |
|
1222 } |
|
1223 symbol->case_element_list->accept(*this); |
|
1224 if (NULL != symbol->statement_list) |
|
1225 symbol->statement_list->accept(*this); |
|
1226 return NULL; |
|
1227 } |
|
1228 |
|
1229 /********************************/ |
|
1230 /* B 3.2.4 Iteration Statements */ |
|
1231 /********************************/ |
|
1232 |
|
1233 void *print_datatypes_error_c::visit(for_statement_c *symbol) { |
|
1234 symbol->control_variable->accept(*this); |
|
1235 symbol->beg_expression->accept(*this); |
|
1236 symbol->end_expression->accept(*this); |
|
1237 /* Control variable */ |
|
1238 if ((NULL == symbol->control_variable->datatype) && |
|
1239 (symbol->control_variable->candidate_datatypes.size() > 0)) { |
|
1240 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'FOR' control variable."); |
|
1241 } |
|
1242 /* BEG expression */ |
|
1243 if ((NULL == symbol->beg_expression->datatype) && |
|
1244 (symbol->beg_expression->candidate_datatypes.size() > 0)) { |
|
1245 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'FOR' begin expression."); |
|
1246 } |
|
1247 /* END expression */ |
|
1248 if ((NULL == symbol->end_expression->datatype) && |
|
1249 (symbol->end_expression->candidate_datatypes.size() > 0)) { |
|
1250 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'FOR' end expression."); |
|
1251 } |
|
1252 /* BY expression */ |
|
1253 if ((NULL != symbol->by_expression) && |
|
1254 (NULL == symbol->by_expression->datatype) && |
|
1255 (symbol->end_expression->candidate_datatypes.size() > 0)) { |
|
1256 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'FOR' by expression."); |
|
1257 } |
|
1258 /* DO statement */ |
|
1259 if (NULL != symbol->statement_list) |
|
1260 symbol->statement_list->accept(*this); |
|
1261 |
|
1262 return NULL; |
|
1263 } |
|
1264 |
|
1265 void *print_datatypes_error_c::visit(while_statement_c *symbol) { |
|
1266 symbol->expression->accept(*this); |
|
1267 if (!is_type_valid(symbol->expression->datatype)) { |
|
1268 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'WHILE' condition."); |
|
1269 return NULL; |
|
1270 } |
|
1271 if (NULL != symbol->statement_list) |
|
1272 symbol->statement_list->accept(*this); |
|
1273 return NULL; |
|
1274 } |
|
1275 |
|
1276 void *print_datatypes_error_c::visit(repeat_statement_c *symbol) { |
|
1277 if (!is_type_valid(symbol->expression->datatype)) { |
|
1278 STAGE3_ERROR(0, symbol, symbol, "Invalid data type for 'REPEAT' condition."); |
|
1279 return NULL; |
|
1280 } |
|
1281 if (NULL != symbol->statement_list) |
|
1282 symbol->statement_list->accept(*this); |
|
1283 symbol->expression->accept(*this); |
|
1284 return NULL; |
|
1285 } |
|
1286 |
|
1287 |
|
1288 |
|
1289 |
|
1290 |