|
1 /* |
|
2 * (c) 2007 Mario de Sousa and Laurent Bessard |
|
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 * This is one of the versions available for the 4th stage. |
|
27 * |
|
28 * This 4th stage generates a c++ source program equivalent |
|
29 * to the IL and ST code. |
|
30 */ |
|
31 |
|
32 |
|
33 #define INLINE_RESULT_TEMP_VAR "__res" |
|
34 |
|
35 class generate_c_inlinefcall_c: public generate_c_typedecl_c { |
|
36 |
|
37 public: |
|
38 typedef enum { |
|
39 expression_vg, |
|
40 assignment_vg, |
|
41 complextype_base_vg, |
|
42 complextype_suffix_vg |
|
43 } variablegeneration_t; |
|
44 |
|
45 private: |
|
46 |
|
47 /* The name of the IL default variable... */ |
|
48 #define IL_DEFVAR VAR_LEADER "IL_DEFVAR" |
|
49 /* The name of the variable used to pass the result of a |
|
50 * parenthesised instruction list to the immediately preceding |
|
51 * scope ... |
|
52 */ |
|
53 il_default_variable_c default_variable_name; |
|
54 |
|
55 symbol_c* current_array_type; |
|
56 |
|
57 int fcall_number; |
|
58 symbol_c *fbname; |
|
59 |
|
60 search_expression_type_c *search_expression_type; |
|
61 |
|
62 search_varfb_instance_type_c *search_varfb_instance_type; |
|
63 |
|
64 search_base_type_c search_base_type; |
|
65 |
|
66 variablegeneration_t wanted_variablegeneration; |
|
67 |
|
68 public: |
|
69 generate_c_inlinefcall_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL) |
|
70 : generate_c_typedecl_c(s4o_ptr), |
|
71 default_variable_name(IL_DEFVAR, NULL) |
|
72 { |
|
73 search_expression_type = new search_expression_type_c(scope); |
|
74 search_varfb_instance_type = new search_varfb_instance_type_c(scope); |
|
75 this->set_variable_prefix(variable_prefix); |
|
76 fcall_number = 0; |
|
77 fbname = name; |
|
78 wanted_variablegeneration = expression_vg; |
|
79 } |
|
80 |
|
81 virtual ~generate_c_inlinefcall_c(void) { |
|
82 delete search_expression_type; |
|
83 delete search_varfb_instance_type; |
|
84 } |
|
85 |
|
86 void print(symbol_c* symbol) { |
|
87 function_call_iterator_c fc_iterator(symbol); |
|
88 symbol_c* function_call; |
|
89 while ((function_call = fc_iterator.next()) != NULL) { |
|
90 function_call->accept(*this); |
|
91 } |
|
92 } |
|
93 |
|
94 void generate_inline(symbol_c *function_name, |
|
95 symbol_c *function_type_prefix, |
|
96 symbol_c *function_type_suffix, |
|
97 std::list<FUNCTION_PARAM*> param_list) { |
|
98 std::list<FUNCTION_PARAM*>::iterator pt; |
|
99 |
|
100 fcall_number++; |
|
101 |
|
102 s4o.print(s4o.indent_spaces); |
|
103 s4o.print("inline "); |
|
104 function_type_prefix->accept(*this); |
|
105 s4o.print(" __"); |
|
106 fbname->accept(*this); |
|
107 s4o.print("_"); |
|
108 function_name->accept(*this); |
|
109 if (function_type_suffix) |
|
110 function_type_suffix->accept(*this); |
|
111 s4o.print_integer(fcall_number); |
|
112 s4o.print("("); |
|
113 s4o.indent_right(); |
|
114 |
|
115 PARAM_LIST_ITERATOR() { |
|
116 if (PARAM_DIRECTION == function_param_iterator_c::direction_in) { |
|
117 PARAM_TYPE->accept(*this); |
|
118 s4o.print(" "); |
|
119 PARAM_NAME->accept(*this); |
|
120 s4o.print(",\n" + s4o.indent_spaces); |
|
121 } |
|
122 } |
|
123 fbname->accept(*this); |
|
124 s4o.print(" *"); |
|
125 s4o.print(FB_FUNCTION_PARAM); |
|
126 s4o.indent_left(); |
|
127 s4o.print(")\n" + s4o.indent_spaces); |
|
128 s4o.print("{\n"); |
|
129 s4o.indent_right(); |
|
130 |
|
131 s4o.print(s4o.indent_spaces); |
|
132 function_type_prefix->accept(*this); |
|
133 s4o.print(" "), |
|
134 s4o.print(INLINE_RESULT_TEMP_VAR); |
|
135 s4o.print(";\n"); |
|
136 |
|
137 PARAM_LIST_ITERATOR() { |
|
138 if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || |
|
139 PARAM_DIRECTION == function_param_iterator_c::direction_inout) && |
|
140 PARAM_VALUE != NULL) { |
|
141 s4o.print(s4o.indent_spaces); |
|
142 PARAM_TYPE->accept(*this); |
|
143 s4o.print(" "); |
|
144 s4o.print(TEMP_VAR); |
|
145 PARAM_NAME->accept(*this); |
|
146 s4o.print(" = "); |
|
147 print_check_function(PARAM_TYPE, PARAM_VALUE); |
|
148 s4o.print(";\n"); |
|
149 } |
|
150 } |
|
151 |
|
152 s4o.print(s4o.indent_spaces + INLINE_RESULT_TEMP_VAR), |
|
153 s4o.print(" = "); |
|
154 function_name->accept(*this); |
|
155 if (function_type_suffix) |
|
156 function_type_suffix->accept(*this); |
|
157 s4o.print("("); |
|
158 s4o.indent_right(); |
|
159 |
|
160 PARAM_LIST_ITERATOR() { |
|
161 if (pt != param_list.begin()) |
|
162 s4o.print(",\n" + s4o.indent_spaces); |
|
163 if (PARAM_DIRECTION == function_param_iterator_c::direction_in) |
|
164 PARAM_NAME->accept(*this); |
|
165 else if (PARAM_VALUE != NULL){ |
|
166 s4o.print("&"); |
|
167 s4o.print(TEMP_VAR); |
|
168 PARAM_NAME->accept(*this); |
|
169 } |
|
170 else { |
|
171 s4o.print("NULL"); |
|
172 } |
|
173 } |
|
174 s4o.print(");\n"); |
|
175 s4o.indent_left(); |
|
176 |
|
177 PARAM_LIST_ITERATOR() { |
|
178 if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || |
|
179 PARAM_DIRECTION == function_param_iterator_c::direction_inout) && |
|
180 PARAM_VALUE != NULL) { |
|
181 |
|
182 s4o.print(s4o.indent_spaces); |
|
183 print_setter(PARAM_VALUE, PARAM_TYPE, PARAM_NAME); |
|
184 s4o.print(";\n"); |
|
185 } |
|
186 } |
|
187 s4o.print(s4o.indent_spaces + "return "); |
|
188 s4o.print(INLINE_RESULT_TEMP_VAR); |
|
189 s4o.print(";\n"); |
|
190 |
|
191 s4o.indent_left(); |
|
192 s4o.print(s4o.indent_spaces + "}\n\n"); |
|
193 } |
|
194 |
|
195 private: |
|
196 |
|
197 void *print_getter(symbol_c *symbol) { |
|
198 unsigned int vartype = search_varfb_instance_type->get_vartype(symbol); |
|
199 if (vartype == search_var_instance_decl_c::external_vt) |
|
200 s4o.print(GET_EXTERNAL); |
|
201 else if (vartype == search_var_instance_decl_c::located_vt) |
|
202 s4o.print(GET_LOCATED); |
|
203 else |
|
204 s4o.print(GET_VAR); |
|
205 s4o.print("("); |
|
206 |
|
207 wanted_variablegeneration = complextype_base_vg; |
|
208 symbol->accept(*this); |
|
209 if (search_varfb_instance_type->type_is_complex()) |
|
210 s4o.print(","); |
|
211 wanted_variablegeneration = complextype_suffix_vg; |
|
212 symbol->accept(*this); |
|
213 s4o.print(")"); |
|
214 wanted_variablegeneration = expression_vg; |
|
215 return NULL; |
|
216 } |
|
217 |
|
218 void *print_setter(symbol_c* symbol, |
|
219 symbol_c* type, |
|
220 symbol_c* value) { |
|
221 unsigned int vartype = search_varfb_instance_type->get_vartype(symbol); |
|
222 if (vartype == search_var_instance_decl_c::external_vt) { |
|
223 symbolic_variable_c *variable = dynamic_cast<symbolic_variable_c *>(symbol); |
|
224 /* TODO Find a solution for forcing global complex variables */ |
|
225 if (variable != NULL) { |
|
226 s4o.print(SET_EXTERNAL); |
|
227 s4o.print("("); |
|
228 variable->var_name->accept(*this); |
|
229 s4o.print(","); |
|
230 } |
|
231 else { |
|
232 s4o.print(SET_COMPLEX_EXTERNAL); |
|
233 s4o.print("("); |
|
234 } |
|
235 } |
|
236 else { |
|
237 if (vartype == search_var_instance_decl_c::located_vt) |
|
238 s4o.print(SET_LOCATED); |
|
239 else |
|
240 s4o.print(SET_VAR); |
|
241 s4o.print("("); |
|
242 } |
|
243 |
|
244 wanted_variablegeneration = complextype_base_vg; |
|
245 symbol->accept(*this); |
|
246 s4o.print(","); |
|
247 wanted_variablegeneration = expression_vg; |
|
248 print_check_function(type, value, NULL, true); |
|
249 if (search_varfb_instance_type->type_is_complex()) { |
|
250 s4o.print(","); |
|
251 wanted_variablegeneration = complextype_suffix_vg; |
|
252 symbol->accept(*this); |
|
253 } |
|
254 s4o.print(")"); |
|
255 wanted_variablegeneration = expression_vg; |
|
256 return NULL; |
|
257 } |
|
258 |
|
259 /*********************/ |
|
260 /* B 1.4 - Variables */ |
|
261 /*********************/ |
|
262 void *visit(symbolic_variable_c *symbol) { |
|
263 unsigned int vartype; |
|
264 if (wanted_variablegeneration == complextype_base_vg) |
|
265 generate_c_base_c::visit(symbol); |
|
266 else if (wanted_variablegeneration == complextype_suffix_vg) |
|
267 return NULL; |
|
268 else |
|
269 print_getter(symbol); |
|
270 return NULL; |
|
271 } |
|
272 |
|
273 /********************************************/ |
|
274 /* B.1.4.1 Directly Represented Variables */ |
|
275 /********************************************/ |
|
276 // direct_variable: direct_variable_token {$$ = new direct_variable_c($1);}; |
|
277 void *visit(direct_variable_c *symbol) { |
|
278 TRACE("direct_variable_c"); |
|
279 /* Do not use print_token() as it will change everything into uppercase */ |
|
280 if (strlen(symbol->value) == 0) ERROR; |
|
281 s4o.print(GET_LOCATED); |
|
282 s4o.print("("); |
|
283 this->print_variable_prefix(); |
|
284 s4o.printlocation(symbol->value + 1); |
|
285 s4o.print(")"); |
|
286 return NULL; |
|
287 } |
|
288 |
|
289 /*************************************/ |
|
290 /* B.1.4.2 Multi-element Variables */ |
|
291 /*************************************/ |
|
292 |
|
293 // SYM_REF2(structured_variable_c, record_variable, field_selector) |
|
294 void *visit(structured_variable_c *symbol) { |
|
295 TRACE("structured_variable_c"); |
|
296 switch (wanted_variablegeneration) { |
|
297 case complextype_base_vg: |
|
298 symbol->record_variable->accept(*this); |
|
299 break; |
|
300 case complextype_suffix_vg: |
|
301 symbol->record_variable->accept(*this); |
|
302 s4o.print("."); |
|
303 symbol->field_selector->accept(*this); |
|
304 break; |
|
305 default: |
|
306 print_getter(symbol); |
|
307 break; |
|
308 } |
|
309 return NULL; |
|
310 } |
|
311 |
|
312 /* subscripted_variable '[' subscript_list ']' */ |
|
313 //SYM_REF2(array_variable_c, subscripted_variable, subscript_list) |
|
314 void *visit(array_variable_c *symbol) { |
|
315 switch (wanted_variablegeneration) { |
|
316 case complextype_base_vg: |
|
317 symbol->subscripted_variable->accept(*this); |
|
318 break; |
|
319 case complextype_suffix_vg: |
|
320 symbol->subscripted_variable->accept(*this); |
|
321 |
|
322 current_array_type = search_varfb_instance_type->get_rawtype(symbol->subscripted_variable); |
|
323 if (current_array_type == NULL) ERROR; |
|
324 |
|
325 s4o.print(".table"); |
|
326 symbol->subscript_list->accept(*this); |
|
327 |
|
328 current_array_type = NULL; |
|
329 break; |
|
330 default: |
|
331 print_getter(symbol); |
|
332 break; |
|
333 } |
|
334 return NULL; |
|
335 } |
|
336 |
|
337 /****************************************/ |
|
338 /* B.2 - Language IL (Instruction List) */ |
|
339 /****************************************/ |
|
340 |
|
341 /***********************************/ |
|
342 /* B 2.1 Instructions and Operands */ |
|
343 /***********************************/ |
|
344 |
|
345 void *visit(il_function_call_c *symbol) { |
|
346 symbol_c* function_type_prefix = NULL; |
|
347 symbol_c* function_name = NULL; |
|
348 symbol_c* function_type_suffix = NULL; |
|
349 DECLARE_PARAM_LIST() |
|
350 |
|
351 symbol_c *param_data_type = default_variable_name.current_type; |
|
352 |
|
353 function_call_param_iterator_c function_call_param_iterator(symbol); |
|
354 |
|
355 function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); |
|
356 if (f_decl == function_symtable.end_value()) { |
|
357 function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name); |
|
358 if (current_function_type == function_none) ERROR; |
|
359 |
|
360 function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_il(symbol, param_data_type); |
|
361 |
|
362 symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN")); |
|
363 /* Add the value from EN param */ |
|
364 ADD_PARAM_LIST(en_param_name, |
|
365 (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())), |
|
366 (symbol_c*)(new bool_type_name_c()), |
|
367 function_param_iterator_c::direction_in) |
|
368 |
|
369 symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO")); |
|
370 /* Add the value from ENO param */ |
|
371 ADD_PARAM_LIST(eno_param_name, NULL, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out) |
|
372 |
|
373 int nb_param = 1; |
|
374 if (symbol->il_operand_list != NULL) |
|
375 nb_param += ((list_c *)symbol->il_operand_list)->n; |
|
376 |
|
377 #include "il_code_gen.c" |
|
378 |
|
379 } |
|
380 else { |
|
381 function_name = symbol->function_name; |
|
382 |
|
383 /* determine the base data type returned by the function being called... */ |
|
384 search_base_type_c search_base_type; |
|
385 function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); |
|
386 |
|
387 /* loop through each function parameter, find the value we should pass |
|
388 * to it, and then output the c equivalent... |
|
389 */ |
|
390 |
|
391 function_param_iterator_c fp_iterator(f_decl); |
|
392 identifier_c *param_name; |
|
393 for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) { |
|
394 symbol_c *param_type = fp_iterator.param_type(); |
|
395 if (param_type == NULL) ERROR; |
|
396 |
|
397 function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); |
|
398 |
|
399 symbol_c *param_value = NULL; |
|
400 |
|
401 /* if it is the first parameter, semantics specifies that we should |
|
402 * get the value off the IL default variable! |
|
403 */ |
|
404 if (1 == i) |
|
405 param_value = &this->default_variable_name; |
|
406 |
|
407 /* Get the value from a foo(<param_name> = <param_value>) style call */ |
|
408 /* NOTE: the following line of code is not required in this case, but it doesn't |
|
409 * harm to leave it in, as in the case of a non-formal syntax function call, |
|
410 * it will always return NULL. |
|
411 * We leave it in in case we later decide to merge this part of the code together |
|
412 * with the function calling code in generate_c_st_c, which does require |
|
413 * the following line... |
|
414 */ |
|
415 if (param_value == NULL) |
|
416 param_value = function_call_param_iterator.search_f(param_name); |
|
417 |
|
418 /* Get the value from a foo(<param_value>) style call */ |
|
419 if (param_value == NULL) { |
|
420 param_value = function_call_param_iterator.next_nf(); |
|
421 if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR; |
|
422 } |
|
423 |
|
424 if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) { |
|
425 /* No value given for parameter, so we must use the default... */ |
|
426 /* First check whether default value specified in function declaration...*/ |
|
427 param_value = fp_iterator.default_value(); |
|
428 } |
|
429 |
|
430 ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction()) |
|
431 } /* for(...) */ |
|
432 } |
|
433 |
|
434 if (function_call_param_iterator.next_nf() != NULL) ERROR; |
|
435 if (NULL == function_type_prefix) ERROR; |
|
436 |
|
437 bool has_output_params = false; |
|
438 |
|
439 PARAM_LIST_ITERATOR() { |
|
440 if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || |
|
441 PARAM_DIRECTION == function_param_iterator_c::direction_inout) && |
|
442 PARAM_VALUE != NULL) { |
|
443 has_output_params = true; |
|
444 } |
|
445 } |
|
446 |
|
447 if (has_output_params) |
|
448 generate_inline(function_name, function_type_prefix, function_type_suffix, param_list); |
|
449 |
|
450 CLEAR_PARAM_LIST() |
|
451 |
|
452 return NULL; |
|
453 } |
|
454 |
|
455 /* | function_name '(' eol_list [il_param_list] ')' */ |
|
456 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list) |
|
457 void *visit(il_formal_funct_call_c *symbol) { |
|
458 symbol_c* function_type_prefix = NULL; |
|
459 symbol_c* function_name = NULL; |
|
460 symbol_c* function_type_suffix = NULL; |
|
461 DECLARE_PARAM_LIST() |
|
462 |
|
463 function_call_param_iterator_c function_call_param_iterator(symbol); |
|
464 |
|
465 function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); |
|
466 if (f_decl == function_symtable.end_value()) { |
|
467 function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name); |
|
468 if (current_function_type == function_none) ERROR; |
|
469 |
|
470 function_type_prefix = (symbol_c *)search_expression_type->compute_standard_function_default(NULL, symbol); |
|
471 |
|
472 int nb_param = 0; |
|
473 if (symbol->il_param_list != NULL) |
|
474 nb_param += ((list_c *)symbol->il_param_list)->n; |
|
475 |
|
476 symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN")); |
|
477 /* Get the value from EN param */ |
|
478 symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name); |
|
479 if (EN_param_value == NULL) |
|
480 EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())); |
|
481 else |
|
482 nb_param --; |
|
483 ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in) |
|
484 |
|
485 symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO")); |
|
486 /* Get the value from ENO param */ |
|
487 symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name); |
|
488 if (ENO_param_value != NULL) |
|
489 nb_param --; |
|
490 ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out) |
|
491 |
|
492 #include "st_code_gen.c" |
|
493 |
|
494 } |
|
495 else { |
|
496 function_name = symbol->function_name; |
|
497 |
|
498 /* determine the base data type returned by the function being called... */ |
|
499 search_base_type_c search_base_type; |
|
500 function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); |
|
501 |
|
502 /* loop through each function parameter, find the value we should pass |
|
503 * to it, and then output the c equivalent... |
|
504 */ |
|
505 |
|
506 function_param_iterator_c fp_iterator(f_decl); |
|
507 identifier_c *param_name; |
|
508 for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) { |
|
509 symbol_c *param_type = fp_iterator.param_type(); |
|
510 if (param_type == NULL) ERROR; |
|
511 |
|
512 function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); |
|
513 |
|
514 |
|
515 symbol_c *param_value = NULL; |
|
516 |
|
517 /* Get the value from a foo(<param_name> = <param_value>) style call */ |
|
518 if (param_value == NULL) |
|
519 param_value = function_call_param_iterator.search_f(param_name); |
|
520 |
|
521 /* Get the value from a foo(<param_value>) style call */ |
|
522 /* NOTE: the following line of code is not required in this case, but it doesn't |
|
523 * harm to leave it in, as in the case of a formal syntax function call, |
|
524 * it will always return NULL. |
|
525 * We leave it in in case we later decide to merge this part of the code together |
|
526 * with the function calling code in generate_c_st_c, which does require |
|
527 * the following line... |
|
528 */ |
|
529 if (param_value == NULL) { |
|
530 param_value = function_call_param_iterator.next_nf(); |
|
531 if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR; |
|
532 } |
|
533 |
|
534 if (param_value == NULL) { |
|
535 /* No value given for parameter, so we must use the default... */ |
|
536 /* First check whether default value specified in function declaration...*/ |
|
537 param_value = fp_iterator.default_value(); |
|
538 } |
|
539 |
|
540 ADD_PARAM_LIST(param_name, param_value, param_type, fp_iterator.param_direction()) |
|
541 } |
|
542 } |
|
543 |
|
544 if (function_call_param_iterator.next_nf() != NULL) ERROR; |
|
545 if (NULL == function_type_prefix) ERROR; |
|
546 |
|
547 bool has_output_params = false; |
|
548 |
|
549 PARAM_LIST_ITERATOR() { |
|
550 if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || |
|
551 PARAM_DIRECTION == function_param_iterator_c::direction_inout) && |
|
552 PARAM_VALUE != NULL) { |
|
553 has_output_params = true; |
|
554 } |
|
555 } |
|
556 |
|
557 if (has_output_params) |
|
558 generate_inline(function_name, function_type_prefix, function_type_suffix, param_list); |
|
559 |
|
560 CLEAR_PARAM_LIST() |
|
561 |
|
562 return NULL; |
|
563 } |
|
564 |
|
565 /***************************************/ |
|
566 /* B.3 - Language ST (Structured Text) */ |
|
567 /***************************************/ |
|
568 /***********************/ |
|
569 /* B 3.1 - Expressions */ |
|
570 /***********************/ |
|
571 |
|
572 void *visit(function_invocation_c *symbol) { |
|
573 symbol_c* function_type_prefix = NULL; |
|
574 symbol_c* function_name = NULL; |
|
575 symbol_c* function_type_suffix = NULL; |
|
576 DECLARE_PARAM_LIST() |
|
577 |
|
578 symbol_c *parameter_assignment_list = NULL; |
|
579 if (NULL != symbol-> formal_param_list) parameter_assignment_list = symbol-> formal_param_list; |
|
580 if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list; |
|
581 if (NULL == parameter_assignment_list) ERROR; |
|
582 |
|
583 function_call_param_iterator_c function_call_param_iterator(symbol); |
|
584 |
|
585 function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); |
|
586 if (f_decl == function_symtable.end_value()) { |
|
587 /* The function called is not in the symtable, so we test if it is a |
|
588 * standard function defined in standard */ |
|
589 |
|
590 function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name); |
|
591 if (current_function_type == function_none) ERROR; |
|
592 |
|
593 function_type_prefix = search_expression_type->get_type(symbol); |
|
594 |
|
595 int nb_param = ((list_c *)parameter_assignment_list)->n; |
|
596 |
|
597 symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN")); |
|
598 /* Get the value from EN param */ |
|
599 symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name); |
|
600 if (EN_param_value == NULL) |
|
601 EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())); |
|
602 else |
|
603 nb_param --; |
|
604 ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in) |
|
605 |
|
606 symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO")); |
|
607 /* Get the value from ENO param */ |
|
608 symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name); |
|
609 if (ENO_param_value != NULL) |
|
610 nb_param --; |
|
611 ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out) |
|
612 |
|
613 #include "st_code_gen.c" |
|
614 |
|
615 } |
|
616 else { |
|
617 function_name = symbol->function_name; |
|
618 |
|
619 /* determine the base data type returned by the function being called... */ |
|
620 search_base_type_c search_base_type; |
|
621 function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); |
|
622 |
|
623 /* loop through each function parameter, find the value we should pass |
|
624 * to it, and then output the c equivalent... |
|
625 */ |
|
626 function_param_iterator_c fp_iterator(f_decl); |
|
627 identifier_c *param_name; |
|
628 for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) { |
|
629 symbol_c *param_type = fp_iterator.param_type(); |
|
630 if (param_type == NULL) ERROR; |
|
631 |
|
632 function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); |
|
633 |
|
634 /* Get the value from a foo(<param_name> = <param_value>) style call */ |
|
635 symbol_c *param_value = function_call_param_iterator.search_f(param_name); |
|
636 |
|
637 /* Get the value from a foo(<param_value>) style call */ |
|
638 if (param_value == NULL) { |
|
639 param_value = function_call_param_iterator.next_nf(); |
|
640 if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR; |
|
641 } |
|
642 |
|
643 if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) { |
|
644 /* No value given for parameter, so we must use the default... */ |
|
645 /* First check whether default value specified in function declaration...*/ |
|
646 param_value = fp_iterator.default_value(); |
|
647 } |
|
648 |
|
649 ADD_PARAM_LIST(param_name, param_value, param_type, param_direction) |
|
650 } /* for(...) */ |
|
651 // symbol->parameter_assignment->accept(*this); |
|
652 } |
|
653 |
|
654 if (function_call_param_iterator.next_nf() != NULL) ERROR; |
|
655 if (NULL == function_type_prefix) ERROR; |
|
656 |
|
657 bool has_output_params = false; |
|
658 |
|
659 PARAM_LIST_ITERATOR() { |
|
660 if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || |
|
661 PARAM_DIRECTION == function_param_iterator_c::direction_inout) && |
|
662 PARAM_VALUE != NULL) { |
|
663 has_output_params = true; |
|
664 } |
|
665 } |
|
666 |
|
667 if (has_output_params) |
|
668 generate_inline(function_name, function_type_prefix, function_type_suffix, param_list); |
|
669 |
|
670 CLEAR_PARAM_LIST() |
|
671 |
|
672 return NULL; |
|
673 } |
|
674 |
|
675 }; /* generate_c_inlinefcall_c */ |
|
676 |
|
677 |