28 * Based on the |
28 * Based on the |
29 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
29 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
30 * |
30 * |
31 */ |
31 */ |
32 |
32 |
33 /* Determine the data type of a specific variable instance, including |
33 /* Search in a VAR* END_VAR declaration for the delcration of the specified variable instance. |
34 * function block instances. |
34 * Will return: |
35 * A reference to the relevant variable declaration is returned. |
35 * - the declaration itself (get_decl() ) |
36 * The variable instance may NOT be a member of a structure of a member |
36 * - the type of declaration in which the variable was declared (get_vartype() ) |
|
37 * |
|
38 * The variable instance may NOT be a member of a structure of a memeber |
37 * of a structure of an element of an array of ... |
39 * of a structure of an element of an array of ... |
38 * |
40 * |
39 * example: |
41 * For example, considering the following 'variables': |
40 * window.points[1].coordinate.x |
42 * window.points[1].coordinate.x |
41 * window.points[1].colour |
43 * window.points[1].colour |
42 * etc... ARE NOT ALLOWED! |
44 * offset[99] |
|
45 * |
|
46 * passing a reference to 'points', 'points[1]', 'points[1].colour', 'colour' |
|
47 * ARE NOT ALLOWED! |
43 * |
48 * |
44 * This class must only be passed the name of the variable that will appear |
49 * This class must only be passed the name of the variable that will appear |
45 * in the variable declaration. In the above examples, this would be |
50 * in the variable declaration. In the above examples, this would be |
46 * 'window' !! |
51 * 'window.points[1].coordinate.x' |
47 * |
52 * 'window.points[1].coordinate' |
48 * |
53 * 'window.points[1]' |
49 * If you need to pass a complete name of a variable instance (such as |
54 * 'window' |
50 * 'window.points[1].coordinate.x') use the search_varfb_instance_type_c instead! |
55 * 'window.points[1].colour' |
|
56 * 'offset' |
|
57 * 'offset[99]' |
|
58 * |
|
59 * |
51 */ |
60 */ |
52 |
61 |
53 /* Note that current_type_decl that this class returns may reference the |
62 /* Note: |
|
63 * Determining the declaration type of a specific variable instance (including |
|
64 * function block instances) really means determining whether the variable was declared in a |
|
65 * VAR_INPUT |
|
66 * VAR_OUTPUT |
|
67 * VAR_IN_OUT |
|
68 * VAR |
|
69 * VAR_TEMP |
|
70 * VAR_EXTERNAL |
|
71 * VAR_GLOBAL |
|
72 * VAR <var_name> AT <location> -> Located variable! |
|
73 * |
|
74 */ |
|
75 |
|
76 /* Note: |
|
77 * The current_type_decl that this class returns may reference the |
54 * name of a type, or the type declaration itself! |
78 * name of a type, or the type declaration itself! |
55 * For an example of the first, consider a variable declared as ... |
79 * For an example of the first, consider a variable declared as ... |
56 * x : AAA; |
80 * x : AAA; |
57 * where the AAA type is previously declared as whatever. |
81 * where the AAA type is previously declared as whatever. |
58 * For an example of the second, consider a variable declared as ... |
82 * For an example of the second, consider a variable declared as ... |
59 * x : array of int [10]; ----> is allowed |
83 * x : array of int [10]; ----> is allowed |
60 * |
84 * |
61 * If it is the first, we will return a reference to the name, if the second |
85 * If it is the first, we will return a reference to the name, if the second |
62 * we return a reference to the declaration!! |
86 * we return a reference to the declaration!! |
63 */ |
87 */ |
|
88 |
|
89 |
64 #include "absyntax_utils.hh" |
90 #include "absyntax_utils.hh" |
|
91 |
|
92 |
|
93 |
65 |
94 |
66 |
95 |
67 search_var_instance_decl_c::search_var_instance_decl_c(symbol_c *search_scope) { |
96 search_var_instance_decl_c::search_var_instance_decl_c(symbol_c *search_scope) { |
68 this->current_vartype = none_vt; |
97 this->current_vartype = none_vt; |
69 this->search_scope = search_scope; |
98 this->search_scope = search_scope; |
70 this->search_name = NULL; |
99 this->search_name = NULL; |
71 this->current_type_decl = NULL; |
100 this->current_type_decl = NULL; |
72 } |
101 this->current_option = none_opt; |
73 |
102 } |
74 symbol_c *search_var_instance_decl_c::get_decl(symbol_c *variable_instance_name) { |
103 |
|
104 symbol_c *search_var_instance_decl_c::get_decl(symbol_c *variable) { |
75 this->current_vartype = none_vt; |
105 this->current_vartype = none_vt; |
76 this->search_name = variable_instance_name; |
106 this->current_option = none_opt; |
|
107 this->search_name = get_var_name_c::get_name(variable); |
77 return (symbol_c *)search_scope->accept(*this); |
108 return (symbol_c *)search_scope->accept(*this); |
78 } |
109 } |
79 |
110 |
80 unsigned int search_var_instance_decl_c::get_vartype(void) { |
111 search_var_instance_decl_c::vt_t search_var_instance_decl_c::get_vartype(symbol_c *variable) { |
81 return current_vartype; |
112 this->current_vartype = none_vt; |
82 } |
113 this->current_option = none_opt; |
|
114 this->search_name = get_var_name_c::get_name(variable); |
|
115 search_scope->accept(*this); |
|
116 return this->current_vartype; |
|
117 } |
|
118 |
|
119 search_var_instance_decl_c::opt_t search_var_instance_decl_c::get_option(symbol_c *variable) { |
|
120 this->current_vartype = none_vt; |
|
121 this->current_option = none_opt; |
|
122 this->search_name = get_var_name_c::get_name(variable); |
|
123 search_scope->accept(*this); |
|
124 return this->current_option; |
|
125 } |
|
126 |
|
127 |
|
128 |
|
129 /* This is a temporary fix. Hopefully, once I clean up stage4 code, and I change the way |
|
130 * we generate C code, this function will no longer be needed! |
|
131 */ |
|
132 #include <typeinfo> /* required for typeid() */ |
|
133 bool search_var_instance_decl_c::type_is_complex(symbol_c *symbol) { |
|
134 symbol_c *decl; |
|
135 search_base_type_c search_base_type; |
|
136 |
|
137 decl = this->get_decl(symbol); |
|
138 if (NULL == decl) ERROR; |
|
139 decl = search_base_type.get_basetype_decl(decl); |
|
140 if (NULL == decl) ERROR; |
|
141 |
|
142 return ((typeid( *(decl) ) == typeid( array_specification_c )) || |
|
143 // (typeid( *(decl) ) == typeid( array_spec_init_c )) || /* does not seem to be necessary */ |
|
144 (typeid( *(decl) ) == typeid( structure_type_declaration_c )) || |
|
145 (typeid( *(decl) ) == typeid( structure_element_declaration_list_c )) || |
|
146 // (typeid( *(decl) ) == typeid( structure_type_declaration_c )) || /* does not seem to be necessary */ |
|
147 (typeid( *(decl) ) == typeid( initialized_structure_c )) |
|
148 |
|
149 ); |
|
150 } |
|
151 |
|
152 |
83 |
153 |
84 /***************************/ |
154 /***************************/ |
85 /* B 0 - Programming Model */ |
155 /* B 0 - Programming Model */ |
86 /***************************/ |
156 /***************************/ |
87 void *search_var_instance_decl_c::visit(library_c *symbol) { |
157 void *search_var_instance_decl_c::visit(library_c *symbol) { |
98 /******************************************/ |
168 /******************************************/ |
99 |
169 |
100 /* edge -> The F_EDGE or R_EDGE directive */ |
170 /* edge -> The F_EDGE or R_EDGE directive */ |
101 // SYM_REF2(edge_declaration_c, edge, var1_list) |
171 // SYM_REF2(edge_declaration_c, edge, var1_list) |
102 // TODO |
172 // TODO |
|
173 void *search_var_instance_decl_c::visit(constant_option_c *symbol) { |
|
174 current_option = constant_opt; |
|
175 return NULL; |
|
176 } |
|
177 |
|
178 void *search_var_instance_decl_c::visit(retain_option_c *symbol) { |
|
179 current_option = retain_opt; |
|
180 return NULL; |
|
181 } |
|
182 |
|
183 void *search_var_instance_decl_c::visit(non_retain_option_c *symbol) { |
|
184 current_option = non_retain_opt; |
|
185 return NULL; |
|
186 } |
103 |
187 |
104 void *search_var_instance_decl_c::visit(input_declarations_c *symbol) { |
188 void *search_var_instance_decl_c::visit(input_declarations_c *symbol) { |
105 current_vartype = input_vt; |
189 current_vartype = input_vt; |
|
190 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
191 if (NULL != symbol->option) |
|
192 symbol->option->accept(*this); |
106 void *res = symbol->input_declaration_list->accept(*this); |
193 void *res = symbol->input_declaration_list->accept(*this); |
107 if (res == NULL) { |
194 if (res == NULL) { |
108 current_vartype = none_vt; |
195 current_vartype = none_vt; |
|
196 current_option = none_opt; |
109 } |
197 } |
110 return res; |
198 return res; |
111 } |
199 } |
112 |
200 |
113 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */ |
201 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */ |
114 /* option -> may be NULL ! */ |
202 /* option -> may be NULL ! */ |
115 void *search_var_instance_decl_c::visit(output_declarations_c *symbol) { |
203 void *search_var_instance_decl_c::visit(output_declarations_c *symbol) { |
116 current_vartype = output_vt; |
204 current_vartype = output_vt; |
|
205 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
206 if (NULL != symbol->option) |
|
207 symbol->option->accept(*this); |
117 void *res = symbol->var_init_decl_list->accept(*this); |
208 void *res = symbol->var_init_decl_list->accept(*this); |
118 if (res == NULL) { |
209 if (res == NULL) { |
119 current_vartype = none_vt; |
210 current_vartype = none_vt; |
|
211 current_option = none_opt; |
120 } |
212 } |
121 return res; |
213 return res; |
122 } |
214 } |
123 |
215 |
124 /* VAR_IN_OUT var_declaration_list END_VAR */ |
216 /* VAR_IN_OUT var_declaration_list END_VAR */ |
125 void *search_var_instance_decl_c::visit(input_output_declarations_c *symbol) { |
217 void *search_var_instance_decl_c::visit(input_output_declarations_c *symbol) { |
126 current_vartype = inoutput_vt; |
218 current_vartype = inoutput_vt; |
|
219 current_option = none_opt; /* not really required. Just to make the code more readable */ |
127 void *res = symbol->var_declaration_list->accept(*this); |
220 void *res = symbol->var_declaration_list->accept(*this); |
128 if (res == NULL) { |
221 if (res == NULL) { |
129 current_vartype = none_vt; |
222 current_vartype = none_vt; |
130 } |
223 } |
131 return res; |
224 return res; |
142 /* VAR [CONSTANT] var_init_decl_list END_VAR */ |
235 /* VAR [CONSTANT] var_init_decl_list END_VAR */ |
143 /* option -> may be NULL ! */ |
236 /* option -> may be NULL ! */ |
144 /* helper symbol for input_declarations */ |
237 /* helper symbol for input_declarations */ |
145 void *search_var_instance_decl_c::visit(var_declarations_c *symbol) { |
238 void *search_var_instance_decl_c::visit(var_declarations_c *symbol) { |
146 current_vartype = private_vt; |
239 current_vartype = private_vt; |
|
240 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
241 if (NULL != symbol->option) |
|
242 symbol->option->accept(*this); |
147 void *res = symbol->var_init_decl_list->accept(*this); |
243 void *res = symbol->var_init_decl_list->accept(*this); |
148 if (res == NULL) { |
244 if (res == NULL) { |
149 current_vartype = none_vt; |
245 current_vartype = none_vt; |
|
246 current_option = none_opt; |
150 } |
247 } |
151 return res; |
248 return res; |
152 } |
249 } |
153 |
250 |
154 /* VAR RETAIN var_init_decl_list END_VAR */ |
251 /* VAR RETAIN var_init_decl_list END_VAR */ |
155 void *search_var_instance_decl_c::visit(retentive_var_declarations_c *symbol) { |
252 void *search_var_instance_decl_c::visit(retentive_var_declarations_c *symbol) { |
156 current_vartype = private_vt; |
253 current_vartype = private_vt; |
|
254 current_option = retain_opt; |
157 void *res = symbol->var_init_decl_list->accept(*this); |
255 void *res = symbol->var_init_decl_list->accept(*this); |
158 if (res == NULL) { |
256 if (res == NULL) { |
159 current_vartype = none_vt; |
257 current_vartype = none_vt; |
|
258 current_option = none_opt; |
160 } |
259 } |
161 return res; |
260 return res; |
162 } |
261 } |
163 |
262 |
164 /* VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */ |
263 /* VAR [CONSTANT|RETAIN|NON_RETAIN] located_var_decl_list END_VAR */ |
165 /* option -> may be NULL ! */ |
264 /* option -> may be NULL ! */ |
166 //SYM_REF2(located_var_declarations_c, option, located_var_decl_list) |
265 //SYM_REF2(located_var_declarations_c, option, located_var_decl_list) |
167 void *search_var_instance_decl_c::visit(located_var_declarations_c *symbol) { |
266 void *search_var_instance_decl_c::visit(located_var_declarations_c *symbol) { |
168 current_vartype = located_vt; |
267 current_vartype = located_vt; |
|
268 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
269 if (NULL != symbol->option) |
|
270 symbol->option->accept(*this); |
169 void *res = symbol->located_var_decl_list->accept(*this); |
271 void *res = symbol->located_var_decl_list->accept(*this); |
170 if (res == NULL) { |
272 if (res == NULL) { |
171 current_vartype = none_vt; |
273 current_vartype = none_vt; |
|
274 current_option = none_opt; |
172 } |
275 } |
173 return res; |
276 return res; |
174 } |
277 } |
175 |
278 |
176 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */ |
279 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */ |
177 /* option -> may be NULL ! */ |
280 /* option -> may be NULL ! */ |
178 //SYM_REF2(external_var_declarations_c, option, external_declaration_list) |
281 //SYM_REF2(external_var_declarations_c, option, external_declaration_list) |
179 void *search_var_instance_decl_c::visit(external_var_declarations_c *symbol) { |
282 void *search_var_instance_decl_c::visit(external_var_declarations_c *symbol) { |
180 current_vartype = external_vt; |
283 current_vartype = external_vt; |
|
284 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
285 if (NULL != symbol->option) |
|
286 symbol->option->accept(*this); |
181 void *res = symbol->external_declaration_list->accept(*this); |
287 void *res = symbol->external_declaration_list->accept(*this); |
182 if (res == NULL) { |
288 if (res == NULL) { |
183 current_vartype = none_vt; |
289 current_vartype = none_vt; |
|
290 current_option = none_opt; |
184 } |
291 } |
185 return res; |
292 return res; |
186 } |
293 } |
187 |
294 |
188 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */ |
295 /*| VAR_GLOBAL [CONSTANT|RETAIN] global_var_decl_list END_VAR */ |
189 /* option -> may be NULL ! */ |
296 /* option -> may be NULL ! */ |
190 //SYM_REF2(global_var_declarations_c, option, global_var_decl_list) |
297 //SYM_REF2(global_var_declarations_c, option, global_var_decl_list) |
191 void *search_var_instance_decl_c::visit(global_var_declarations_c *symbol) { |
298 void *search_var_instance_decl_c::visit(global_var_declarations_c *symbol) { |
192 current_vartype = global_vt; |
299 current_vartype = global_vt; |
|
300 current_option = none_opt; /* not really required. Just to make the code more readable */ |
|
301 if (NULL != symbol->option) |
|
302 symbol->option->accept(*this); |
193 void *res = symbol->global_var_decl_list->accept(*this); |
303 void *res = symbol->global_var_decl_list->accept(*this); |
194 if (res == NULL) { |
304 if (res == NULL) { |
195 current_vartype = none_vt; |
305 current_vartype = none_vt; |
|
306 current_option = none_opt; |
196 } |
307 } |
197 return res; |
308 return res; |
198 } |
309 } |
199 |
310 |
200 /* var1_list is one of the following... |
311 /* var1_list is one of the following... |
398 } |
509 } |
399 |
510 |
400 /*****************************/ |
511 /*****************************/ |
401 /* B 1.5.2 - Function Blocks */ |
512 /* B 1.5.2 - Function Blocks */ |
402 /*****************************/ |
513 /*****************************/ |
|
514 /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ |
|
515 // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body) |
403 void *search_var_instance_decl_c::visit(function_block_declaration_c *symbol) { |
516 void *search_var_instance_decl_c::visit(function_block_declaration_c *symbol) { |
404 /* no need to search through all the body, so we only |
517 /* visit the variable declarations...! */ |
405 * visit the variable declarations...! |
518 void *res = symbol->var_declarations->accept(*this); |
406 */ |
519 if (NULL != res) |
407 return symbol->var_declarations->accept(*this); |
520 return res; |
|
521 |
|
522 /* not yet found, so we look into the body, to see if it is an SFC step! */ |
|
523 return symbol->fblock_body->accept(*this); |
408 } |
524 } |
409 |
525 |
410 /**********************/ |
526 /**********************/ |
411 /* B 1.5.3 - Programs */ |
527 /* B 1.5.3 - Programs */ |
412 /**********************/ |
528 /**********************/ |
|
529 /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ |
|
530 // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body) |
413 void *search_var_instance_decl_c::visit(program_declaration_c *symbol) { |
531 void *search_var_instance_decl_c::visit(program_declaration_c *symbol) { |
414 /* no need to search through all the body, so we only |
532 /* visit the variable declarations...! */ |
415 * visit the variable declarations...! |
533 void *res = symbol->var_declarations->accept(*this); |
416 */ |
534 if (NULL != res) |
417 return symbol->var_declarations->accept(*this); |
535 return res; |
|
536 |
|
537 /* not yet found, so we look into the body, to see if it is an SFC step! */ |
|
538 return symbol->function_block_body->accept(*this); |
|
539 } |
|
540 |
|
541 |
|
542 /*********************************************/ |
|
543 /* B.1.6 Sequential function chart elements */ |
|
544 /*********************************************/ |
|
545 /* | sequential_function_chart sfc_network */ |
|
546 // SYM_LIST(sequential_function_chart_c) |
|
547 /* search_var_instance_decl_c inherits from serach_visitor_c, so no need to implement the following method. */ |
|
548 // void *search_var_instance_decl_c::visit(sequential_function_chart_c *symbol) {...} |
|
549 |
|
550 /* initial_step {step | transition | action} */ |
|
551 // SYM_LIST(sfc_network_c) |
|
552 /* search_var_instance_decl_c inherits from serach_visitor_c, so no need to implement the following method. */ |
|
553 // void *search_var_instance_decl_c::visit(sfc_network_c *symbol) {...} |
|
554 |
|
555 |
|
556 /* INITIAL_STEP step_name ':' action_association_list END_STEP */ |
|
557 // SYM_REF2(initial_step_c, step_name, action_association_list) |
|
558 void *search_var_instance_decl_c::visit(initial_step_c *symbol) { |
|
559 if (compare_identifiers(symbol->step_name, search_name) == 0) |
|
560 return symbol; |
|
561 return NULL; |
|
562 } |
|
563 |
|
564 /* STEP step_name ':' action_association_list END_STEP */ |
|
565 // SYM_REF2(step_c, step_name, action_association_list) |
|
566 void *search_var_instance_decl_c::visit(step_c *symbol) { |
|
567 if (compare_identifiers(symbol->step_name, search_name) == 0) |
|
568 return symbol; |
|
569 return NULL; |
418 } |
570 } |
419 |
571 |
420 |
572 |
421 /********************************/ |
573 /********************************/ |
422 /* B 1.7 Configuration elements */ |
574 /* B 1.7 Configuration elements */ |
467 * and there is no global variable declarations...! |
619 * and there is no global variable declarations...! |
468 */ |
620 */ |
469 return NULL; |
621 return NULL; |
470 } |
622 } |
471 |
623 |
472 #if 0 |
624 |
473 /*********************/ |
625 |
474 /* B 1.4 - Variables */ |
626 /****************************************/ |
475 /*********************/ |
627 /* B.2 - Language IL (Instruction List) */ |
476 SYM_REF2(symbolic_variable_c, var_name, unused) |
628 /****************************************/ |
477 |
629 /***********************************/ |
478 /********************************************/ |
630 /* B 2.1 Instructions and Operands */ |
479 /* B.1.4.1 Directly Represented Variables */ |
631 /***********************************/ |
480 /********************************************/ |
632 /*| instruction_list il_instruction */ |
481 SYM_TOKEN(direct_variable_c) |
633 // SYM_LIST(instruction_list_c) |
482 |
634 void *search_var_instance_decl_c::visit(instruction_list_c *symbol) { |
483 /*************************************/ |
635 /* IL code does not contain any variable declarations! */ |
484 /* B.1.4.2 Multi-element Variables */ |
636 return NULL; |
485 /*************************************/ |
637 } |
486 /* subscripted_variable '[' subscript_list ']' */ |
638 |
487 SYM_REF2(array_variable_c, subscripted_variable, subscript_list) |
639 |
488 |
640 /***************************************/ |
489 /* subscript_list ',' subscript */ |
641 /* B.3 - Language ST (Structured Text) */ |
490 SYM_LIST(subscript_list_c) |
642 /***************************************/ |
491 |
643 /********************/ |
492 /* record_variable '.' field_selector */ |
644 /* B 3.2 Statements */ |
493 /* WARNING: input and/or output variables of function blocks |
645 /********************/ |
494 * may be accessed as fields of a tructured variable! |
646 // SYM_LIST(statement_list_c) |
495 * Code handling a structured_variable_c must take |
647 void *search_var_instance_decl_c::visit(statement_list_c *symbol) { |
496 * this into account! |
648 /* ST code does not contain any variable declarations! */ |
497 */ |
649 return NULL; |
498 SYM_REF2(structured_variable_c, record_variable, field_selector) |
650 } |
499 |
|
500 |
|
501 |
|
502 }; |
|
503 #endif |
|