|
1 /* |
|
2 * (c) 2003 Mario de Sousa |
|
3 * |
|
4 * Offered to the public under the terms of the GNU General Public License |
|
5 * as published by the Free Software Foundation; either version 2 of the |
|
6 * License, or (at your option) any later version. |
|
7 * |
|
8 * This program is distributed in the hope that it will be useful, but |
|
9 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|
11 * Public License for more details. |
|
12 * |
|
13 * This code is made available on the understanding that it will not be |
|
14 * used in safety-critical situations without a full and competent review. |
|
15 */ |
|
16 |
|
17 /* |
|
18 * An IEC 61131-3 IL and ST compiler. |
|
19 * |
|
20 * Based on the |
|
21 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
|
22 * |
|
23 */ |
|
24 |
|
25 |
|
26 /* |
|
27 * This is one of the versions available for the 4th stage. |
|
28 * |
|
29 * This 4th stage generates a c++ source program equivalent |
|
30 * to the IL and ST code. |
|
31 */ |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 // #include <stdio.h> /* required for NULL */ |
|
39 #include <string> |
|
40 #include <iostream> |
|
41 |
|
42 #include "../../util/symtable.hh" |
|
43 #include "../../util/dsymtable.hh" |
|
44 #include "../../absyntax/visitor.hh" |
|
45 |
|
46 #include "../stage4.hh" |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 //#define DEBUG |
|
56 #ifdef DEBUG |
|
57 #define TRACE(classname) printf("\n____%s____\n",classname); |
|
58 #else |
|
59 #define TRACE(classname) |
|
60 #endif |
|
61 |
|
62 |
|
63 |
|
64 #define ERROR error_exit(__FILE__,__LINE__) |
|
65 /* function defined in main.cc */ |
|
66 extern void error_exit(const char *file_name, int line_no); |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 /* A symbol table with all globally declared functions... */ |
|
75 function_declaration_c null_symbol1(NULL,NULL,NULL,NULL); |
|
76 dsymtable_c<function_declaration_c *, &null_symbol1> function_symtable; |
|
77 |
|
78 /* A symbol table with all globally declared functions block types... */ |
|
79 function_block_declaration_c null_symbol2(NULL,NULL,NULL,NULL); |
|
80 symtable_c<function_block_declaration_c *, &null_symbol2> function_block_type_symtable; |
|
81 |
|
82 /* A symbol table with all globally declared program types... */ |
|
83 program_declaration_c null_symbol3(NULL,NULL,NULL,NULL); |
|
84 symtable_c<program_declaration_c *, &null_symbol3> program_type_symtable; |
|
85 |
|
86 /* A symbol table with all user declared type definitions... */ |
|
87 /* Note that function block types and program types have their |
|
88 * own symbol tables, so do not get placed in this symbol table! |
|
89 */ |
|
90 symbol_c null_symbol4; |
|
91 symtable_c<symbol_c *, &null_symbol4> type_symtable; |
|
92 |
|
93 |
|
94 |
|
95 /***********************************************************************/ |
|
96 /***********************************************************************/ |
|
97 /***********************************************************************/ |
|
98 /***********************************************************************/ |
|
99 |
|
100 |
|
101 /* returns 0 if the names are equal!! */ |
|
102 /* NOTE: it must ignore case!! */ |
|
103 static int compare_identifiers(symbol_c *ident1, symbol_c *ident2) { |
|
104 |
|
105 identifier_c *name1 = dynamic_cast<identifier_c *>(ident1); |
|
106 identifier_c *name2 = dynamic_cast<identifier_c *>(ident2); |
|
107 |
|
108 if ((name1 == NULL) || (name2 == NULL)) |
|
109 /* invalid identifiers... */ |
|
110 return -1; |
|
111 |
|
112 if (strcasecmp(name1->value, name2->value) == 0) |
|
113 return 0; |
|
114 |
|
115 /* identifiers do not match! */ |
|
116 return 1; |
|
117 } |
|
118 |
|
119 |
|
120 /***********************************************************************/ |
|
121 /***********************************************************************/ |
|
122 /***********************************************************************/ |
|
123 /***********************************************************************/ |
|
124 |
|
125 /* Unlike Programs and Configurations which get mapped onto C++ classes, |
|
126 * Function Blocks are mapped onto a C structure containing the variables, and |
|
127 * a C function containing the code in the FB's body. This is to allow direct allocation |
|
128 * of a FB variable (which is really an instance of the C data structure) to |
|
129 * a member of a union variable (note that classes with constructors cannot |
|
130 * be mebers of a union), which is done in IL when loading a FB onto IL's |
|
131 * default variable. |
|
132 * |
|
133 * So as not to clash the names of the C data structure and the C function, |
|
134 * the C structure is given a name identical to that of the FB name, whereas |
|
135 * the name of the function is the FB name with a constant string appended. |
|
136 * The value of that constant string which is appended is defined in the following |
|
137 * constant. |
|
138 * In order not to clash with any variable in the IL and ST source codem the |
|
139 * following constant should contain a double underscore, which is not allowed |
|
140 * in IL and ST. |
|
141 * |
|
142 * e.g.: FUNTION_BLOCK TEST |
|
143 * is mapped onto a TEST data structure, and a TEST_body__ function. |
|
144 */ |
|
145 |
|
146 #define FB_FUNCTION_SUFFIX "_body__" |
|
147 |
|
148 /* The FB body function is passed as the only parameter a pointer to the FB data |
|
149 * structure instance. The name of this parameter is given by the following cosntant. |
|
150 * In order not to clash with any variable in the IL and ST source codem the |
|
151 * following constant should contain a double underscore, which is not allowed |
|
152 * in IL and ST. |
|
153 * |
|
154 * e.g.: the body of FUNTION_BLOCK TEST |
|
155 * is mapped onto the C function |
|
156 * TEST_body__(TEST *data__) |
|
157 */ |
|
158 |
|
159 #define FB_FUNCTION_PARAM "data__" |
|
160 |
|
161 |
|
162 /***********************************************************************/ |
|
163 /***********************************************************************/ |
|
164 /***********************************************************************/ |
|
165 /***********************************************************************/ |
|
166 |
|
167 |
|
168 #include "spec_init_separator.cc" |
|
169 #include "function_param_iterator.cc" |
|
170 #include "function_call_iterator.cc" |
|
171 #include "function_call_param_iterator.cc" |
|
172 #include "type_initial_value.cc" |
|
173 #include "search_fb_instance_decl.cc" |
|
174 #include "search_base_type.cc" |
|
175 #include "search_var_instance_decl.cc" |
|
176 #include "decompose_var_instance_name.cc" |
|
177 #include "search_varfb_instance_type.cc" |
|
178 #include "search_constant_type.cc" |
|
179 |
|
180 #include "generate_cc_base.cc" |
|
181 #include "generate_cc_typedecl.cc" |
|
182 #include "generate_cc_vardecl.cc" |
|
183 #include "generate_cc_configbody.cc" |
|
184 |
|
185 /***********************************************************************/ |
|
186 /***********************************************************************/ |
|
187 /***********************************************************************/ |
|
188 /***********************************************************************/ |
|
189 |
|
190 /* Generate a name for a temporary variable. |
|
191 * Each new name generated is appended a different number, |
|
192 * starting off from 0. |
|
193 * After calling reset(), the names will start off again from 0. |
|
194 */ |
|
195 #define VAR_LEADER "__" |
|
196 #define TEMP_VAR VAR_LEADER "TMP_" |
|
197 #define SOURCE_VAR VAR_LEADER "SRC_" |
|
198 |
|
199 #include "generate_cc_tempvardecl.cc" |
|
200 |
|
201 #include "generate_cc_st.cc" |
|
202 #include "generate_cc_il.cc" |
|
203 |
|
204 #include "generate_cc.hh" |
|
205 |
|
206 |
|
207 |
|
208 /***********************************************************************/ |
|
209 /***********************************************************************/ |
|
210 /***********************************************************************/ |
|
211 /***********************************************************************/ |
|
212 |
|
213 /* A helper class that knows how to generate code for both the IL and ST languages... */ |
|
214 class generate_cc_IL_and_ST_c: public null_visitor_c { |
|
215 private: |
|
216 stage4out_c *s4o_ptr; |
|
217 symbol_c *scope; |
|
218 const char *variable_prefix; |
|
219 |
|
220 public: |
|
221 generate_cc_IL_and_ST_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL) { |
|
222 if (NULL == scope) ERROR; |
|
223 this->s4o_ptr = s4o_ptr; |
|
224 this->scope = scope; |
|
225 this->variable_prefix = variable_prefix; |
|
226 } |
|
227 |
|
228 |
|
229 public: |
|
230 /****************************************/ |
|
231 /* B.2 - Language IL (Instruction List) */ |
|
232 /****************************************/ |
|
233 |
|
234 /***********************************/ |
|
235 /* B 2.1 Instructions and Operands */ |
|
236 /***********************************/ |
|
237 /*| instruction_list il_instruction */ |
|
238 void *visit(instruction_list_c *symbol) { |
|
239 generate_cc_il_c generate_cc_il(s4o_ptr, scope, variable_prefix); |
|
240 generate_cc_il.generate(symbol); |
|
241 return NULL; |
|
242 } |
|
243 |
|
244 /* Remainder implemented in generate_cc_il_c... */ |
|
245 |
|
246 /***************************************/ |
|
247 /* B.3 - Language ST (Structured Text) */ |
|
248 /***************************************/ |
|
249 /***********************/ |
|
250 /* B 3.1 - Expressions */ |
|
251 /***********************/ |
|
252 /* Implemented in generate_cc_st_c */ |
|
253 |
|
254 /********************/ |
|
255 /* B 3.2 Statements */ |
|
256 /********************/ |
|
257 void *visit(statement_list_c *symbol) { |
|
258 generate_cc_st_c generate_cc_st(s4o_ptr, scope, variable_prefix); |
|
259 generate_cc_st.generate(symbol); |
|
260 return NULL; |
|
261 } |
|
262 |
|
263 /* Remainder implemented in generate_cc_st_c... */ |
|
264 }; |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 /***********************************************************************/ |
|
271 /***********************************************************************/ |
|
272 /***********************************************************************/ |
|
273 /***********************************************************************/ |
|
274 /***********************************************************************/ |
|
275 |
|
276 |
|
277 class generate_cc_c: public generate_cc_typedecl_c { |
|
278 |
|
279 public: |
|
280 generate_cc_c(stage4out_c *s4o_ptr) |
|
281 : generate_cc_typedecl_c(s4o_ptr) {}; |
|
282 virtual ~generate_cc_c(void) {} |
|
283 |
|
284 |
|
285 public: |
|
286 /***************************/ |
|
287 /* B 0 - Programming Model */ |
|
288 /***************************/ |
|
289 void *visit(library_c *symbol) { |
|
290 TRACE("library_c"); |
|
291 |
|
292 /* Insert the header... */ |
|
293 s4o.print("/*******************************************/\n"); |
|
294 s4o.print("/* FILE GENERATED BY iec2cc */\n"); |
|
295 s4o.print("/* Editing this file is not recommended... */\n"); |
|
296 s4o.print("/*******************************************/\n"); |
|
297 s4o.print("\n\n\n\n\n"); |
|
298 s4o.print("#include \"plciec.h\"\n"); |
|
299 s4o.print("\n\n\n\n\n"); |
|
300 |
|
301 /* now do the actual code... */ |
|
302 print_list(symbol); |
|
303 s4o.print("\n\n"); |
|
304 |
|
305 /* Finish off with the main() */ |
|
306 s4o.print("#include \"plciec.cc\"\n"); |
|
307 s4o.print("\n\n"); |
|
308 |
|
309 // function_symtable.print(); |
|
310 return NULL; |
|
311 } |
|
312 |
|
313 /*************************/ |
|
314 /* B.1 - Common elements */ |
|
315 /*************************/ |
|
316 /*******************************************/ |
|
317 /* B 1.1 - Letters, digits and identifiers */ |
|
318 /*******************************************/ |
|
319 /* done in base class(es) */ |
|
320 |
|
321 /*********************/ |
|
322 /* B 1.2 - Constants */ |
|
323 /*********************/ |
|
324 /* originally empty... */ |
|
325 |
|
326 /******************************/ |
|
327 /* B 1.2.1 - Numeric Literals */ |
|
328 /******************************/ |
|
329 /* done in base class(es) */ |
|
330 |
|
331 /*******************************/ |
|
332 /* B.1.2.2 Character Strings */ |
|
333 /*******************************/ |
|
334 /* done in base class(es) */ |
|
335 |
|
336 /***************************/ |
|
337 /* B 1.2.3 - Time Literals */ |
|
338 /***************************/ |
|
339 /************************/ |
|
340 /* B 1.2.3.1 - Duration */ |
|
341 /************************/ |
|
342 /* done in base class(es) */ |
|
343 |
|
344 /************************************/ |
|
345 /* B 1.2.3.2 - Time of day and Date */ |
|
346 /************************************/ |
|
347 /* done in base class(es) */ |
|
348 |
|
349 /**********************/ |
|
350 /* B.1.3 - Data types */ |
|
351 /**********************/ |
|
352 /***********************************/ |
|
353 /* B 1.3.1 - Elementary Data Types */ |
|
354 /***********************************/ |
|
355 /* done in base class(es) */ |
|
356 |
|
357 /********************************/ |
|
358 /* B.1.3.2 - Generic data types */ |
|
359 /********************************/ |
|
360 /* originally empty... */ |
|
361 |
|
362 /********************************/ |
|
363 /* B 1.3.3 - Derived data types */ |
|
364 /********************************/ |
|
365 /* done in base class(es) */ |
|
366 |
|
367 /*********************/ |
|
368 /* B 1.4 - Variables */ |
|
369 /*********************/ |
|
370 /* done in base class(es) */ |
|
371 |
|
372 /********************************************/ |
|
373 /* B.1.4.1 Directly Represented Variables */ |
|
374 /********************************************/ |
|
375 /* done in base class(es) */ |
|
376 |
|
377 /*************************************/ |
|
378 /* B.1.4.2 Multi-element Variables */ |
|
379 /*************************************/ |
|
380 /* done in base class(es) */ |
|
381 |
|
382 /******************************************/ |
|
383 /* B 1.4.3 - Declaration & Initialisation */ |
|
384 /******************************************/ |
|
385 /* done in base class(es) */ |
|
386 |
|
387 /**************************************/ |
|
388 /* B.1.5 - Program organization units */ |
|
389 /**************************************/ |
|
390 /***********************/ |
|
391 /* B 1.5.1 - Functions */ |
|
392 /***********************/ |
|
393 |
|
394 public: |
|
395 /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
|
396 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
|
397 void *visit(function_declaration_c *symbol) { |
|
398 generate_cc_vardecl_c *vardecl; |
|
399 TRACE("function_declaration_c"); |
|
400 |
|
401 /* start off by adding this declaration to the global |
|
402 * function declaration symbol table... |
|
403 */ |
|
404 function_symtable.insert(symbol->derived_function_name, symbol); |
|
405 |
|
406 /* (A) Function declaration... */ |
|
407 /* (A.1) Function return type */ |
|
408 s4o.print("// FUNCTION\n"); |
|
409 symbol->type_name->accept(*this); /* return type */ |
|
410 s4o.print(" "); |
|
411 /* (A.2) Function name */ |
|
412 symbol->derived_function_name->accept(*this); |
|
413 s4o.print("("); |
|
414 |
|
415 /* (A.3) Function parameters */ |
|
416 s4o.indent_right(); |
|
417 vardecl = new generate_cc_vardecl_c(&s4o, |
|
418 generate_cc_vardecl_c::finterface_vf, |
|
419 generate_cc_vardecl_c::input_vt | |
|
420 generate_cc_vardecl_c::output_vt | |
|
421 generate_cc_vardecl_c::inoutput_vt); |
|
422 vardecl->print(symbol->var_declarations_list); |
|
423 delete vardecl; |
|
424 s4o.indent_left(); |
|
425 |
|
426 s4o.print(")\n" + s4o.indent_spaces + "{\n"); |
|
427 |
|
428 /* (B) Function local variable declaration */ |
|
429 /* (B.1) Variables declared in ST source code */ |
|
430 s4o.indent_right(); |
|
431 vardecl = new generate_cc_vardecl_c(&s4o, generate_cc_vardecl_c::localinit_vf, generate_cc_vardecl_c::private_vt); |
|
432 vardecl->print(symbol->var_declarations_list); |
|
433 delete vardecl; |
|
434 |
|
435 /* (B.2) Temporary variable for function's return value */ |
|
436 /* It will have the same name as the function itself! */ |
|
437 s4o.print(s4o.indent_spaces); |
|
438 symbol->type_name->accept(*this); /* return type */ |
|
439 s4o.print(" "); |
|
440 symbol->derived_function_name->accept(*this); |
|
441 s4o.print(" = "); |
|
442 { |
|
443 /* get the default value of this variable's type */ |
|
444 symbol_c *default_value = (symbol_c *)symbol->type_name->accept(*type_initial_value_c::instance()); |
|
445 if (default_value == NULL) ERROR; |
|
446 default_value->accept(*this); |
|
447 } |
|
448 s4o.print(";\n\n"); |
|
449 |
|
450 /* (C) Function body */ |
|
451 generate_cc_IL_and_ST_c generate_cc_code(&s4o, symbol); |
|
452 symbol->function_body->accept(generate_cc_code); |
|
453 s4o.print(s4o.indent_spaces + "return "); |
|
454 symbol->derived_function_name->accept(*this); |
|
455 s4o.print(";\n"); |
|
456 s4o.indent_left(); |
|
457 s4o.print(s4o.indent_spaces + "}\n\n\n"); |
|
458 |
|
459 return NULL; |
|
460 } |
|
461 |
|
462 |
|
463 /* The remaining var_declarations_list_c, function_var_decls_c |
|
464 * and var2_init_decl_list_c are handled in the generate_cc_vardecl_c class |
|
465 */ |
|
466 |
|
467 |
|
468 /*****************************/ |
|
469 /* B 1.5.2 - Function Blocks */ |
|
470 /*****************************/ |
|
471 public: |
|
472 /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ |
|
473 //SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused) |
|
474 void *visit(function_block_declaration_c *symbol) { |
|
475 generate_cc_vardecl_c *vardecl; |
|
476 TRACE("function_block_declaration_c"); |
|
477 |
|
478 /* start off by adding this declaration to the global |
|
479 * function block declaration symbol table... |
|
480 */ |
|
481 function_block_type_symtable.insert(symbol->fblock_name, symbol); |
|
482 |
|
483 /* (A) Function Block data structure declaration... */ |
|
484 /* (A.1) Data structure declaration */ |
|
485 s4o.print("// FUNCTION_BLOCK "); |
|
486 symbol->fblock_name->accept(*this); |
|
487 s4o.print("\n// Data part\n"); |
|
488 s4o.print("typedef struct {\n"); |
|
489 s4o.indent_right(); |
|
490 /* (A.2) Public variables: i.e. the function parameters... */ |
|
491 s4o.print(s4o.indent_spaces + "// FB Interface - IN, OUT, IN_OUT variables\n"); |
|
492 vardecl = new generate_cc_vardecl_c(&s4o, |
|
493 generate_cc_vardecl_c::local_vf, |
|
494 generate_cc_vardecl_c::input_vt | |
|
495 generate_cc_vardecl_c::output_vt | |
|
496 generate_cc_vardecl_c::inoutput_vt); |
|
497 vardecl->print(symbol->var_declarations); |
|
498 delete vardecl; |
|
499 s4o.print("\n"); |
|
500 /* (A.3) Private internal variables */ |
|
501 s4o.print(s4o.indent_spaces + "// FB private variables - TEMP, private and located variables\n"); |
|
502 vardecl = new generate_cc_vardecl_c(&s4o, |
|
503 generate_cc_vardecl_c::local_vf, |
|
504 generate_cc_vardecl_c::temp_vt | |
|
505 generate_cc_vardecl_c::private_vt | |
|
506 generate_cc_vardecl_c::located_vt); |
|
507 vardecl->print(symbol->var_declarations); |
|
508 delete vardecl; |
|
509 s4o.print("\n"); |
|
510 |
|
511 /* (A.4) Function Block data structure type name. */ |
|
512 s4o.indent_left(); |
|
513 s4o.print("} "); |
|
514 symbol->fblock_name->accept(*this); |
|
515 s4o.print(";\n\n"); |
|
516 |
|
517 |
|
518 /* (B) Function with FB body */ |
|
519 /* (B.1) Function declaration */ |
|
520 s4o.print("// Code part\n"); |
|
521 /* function interface */ |
|
522 s4o.print("void "); |
|
523 symbol->fblock_name->accept(*this); |
|
524 s4o.print(FB_FUNCTION_SUFFIX); |
|
525 s4o.print("("); |
|
526 /* first and only parameter is a pointer to the data */ |
|
527 symbol->fblock_name->accept(*this); |
|
528 s4o.print(" *"); |
|
529 s4o.print(FB_FUNCTION_PARAM); |
|
530 s4o.print(") {\n"); |
|
531 s4o.indent_right(); |
|
532 |
|
533 /* (B.2) Initialize TEMP variables */ |
|
534 /* function body */ |
|
535 s4o.print(s4o.indent_spaces + "// Initialise TEMP variables\n"); |
|
536 vardecl = new generate_cc_vardecl_c(&s4o, |
|
537 generate_cc_vardecl_c::init_vf, |
|
538 generate_cc_vardecl_c::temp_vt); |
|
539 vardecl->print(symbol->var_declarations, NULL, FB_FUNCTION_PARAM"->"); |
|
540 delete vardecl; |
|
541 s4o.print("\n"); |
|
542 |
|
543 /* (B.3) Function code */ |
|
544 generate_cc_IL_and_ST_c generate_cc_code(&s4o, symbol, FB_FUNCTION_PARAM"->"); |
|
545 symbol->fblock_body->accept(generate_cc_code); |
|
546 s4o.indent_left(); |
|
547 s4o.print(s4o.indent_spaces + "} // "); |
|
548 symbol->fblock_name->accept(*this); |
|
549 s4o.print(FB_FUNCTION_SUFFIX); |
|
550 s4o.print(s4o.indent_spaces + "() \n\n"); |
|
551 |
|
552 |
|
553 |
|
554 |
|
555 |
|
556 |
|
557 |
|
558 #if 0 |
|
559 |
|
560 +++++++++++++++++++++++++++++++++++++ |
|
561 s4o.print(s4o.indent_spaces + "class "); |
|
562 symbol->fblock_name->accept(*this); |
|
563 s4o.print(" {\n"); |
|
564 s4o.indent_right(); |
|
565 |
|
566 /* (A.2) Public variables: i.e. the function parameters... */ |
|
567 s4o.print(s4o.indent_spaces + "public:\n"); |
|
568 s4o.indent_right(); |
|
569 vardecl = new generate_cc_vardecl_c(&s4o, |
|
570 generate_cc_vardecl_c::local_vf, |
|
571 generate_cc_vardecl_c::input_vt | |
|
572 generate_cc_vardecl_c::output_vt | |
|
573 generate_cc_vardecl_c::inoutput_vt); |
|
574 vardecl->print(symbol->var_declarations); |
|
575 delete vardecl; |
|
576 s4o.indent_left(); |
|
577 s4o.print("\n"); |
|
578 |
|
579 /* (A.3) Private internal variables */ |
|
580 s4o.print(s4o.indent_spaces + "private:\n"); |
|
581 s4o.indent_right(); |
|
582 vardecl = new generate_cc_vardecl_c(&s4o, |
|
583 generate_cc_vardecl_c::local_vf, |
|
584 generate_cc_vardecl_c::private_vt | |
|
585 generate_cc_vardecl_c::located_vt); |
|
586 vardecl->print(symbol->var_declarations); |
|
587 delete vardecl; |
|
588 s4o.indent_left(); |
|
589 s4o.print("\n"); |
|
590 |
|
591 --------------------------------- |
|
592 /* (B) Constructor */ |
|
593 s4o.print(s4o.indent_spaces + "public:\n"); |
|
594 s4o.indent_right(); |
|
595 s4o.print(s4o.indent_spaces); |
|
596 symbol->fblock_name->accept(*this); |
|
597 s4o.print("(void)\n"); |
|
598 s4o.indent_right(); |
|
599 s4o.print(s4o.indent_spaces); |
|
600 vardecl = new generate_cc_vardecl_c(&s4o, |
|
601 generate_cc_vardecl_c::constructorinit_vf, |
|
602 generate_cc_vardecl_c::input_vt | |
|
603 generate_cc_vardecl_c::output_vt | |
|
604 generate_cc_vardecl_c::inoutput_vt | |
|
605 generate_cc_vardecl_c::private_vt); |
|
606 vardecl->print(symbol->var_declarations); |
|
607 delete vardecl; |
|
608 s4o.print("\n" + s4o.indent_spaces + "{}\n\n"); |
|
609 s4o.indent_left(); |
|
610 s4o.indent_left(); |
|
611 --------------------------------- |
|
612 |
|
613 |
|
614 /* (C) Public Function*/ |
|
615 /* (C.1) Public Function declaration */ |
|
616 s4o.print(s4o.indent_spaces + "public:\n"); |
|
617 s4o.indent_right(); |
|
618 s4o.print(s4o.indent_spaces + "void f(void) {\n"); |
|
619 |
|
620 /* (C.2) Temporary variables */ |
|
621 s4o.indent_right(); |
|
622 vardecl = new generate_cc_vardecl_c(&s4o, generate_cc_vardecl_c::localinit_vf, generate_cc_vardecl_c::temp_vt); |
|
623 vardecl->print(symbol->var_declarations); |
|
624 delete vardecl; |
|
625 s4o.indent_left(); |
|
626 s4o.print("\n"); |
|
627 |
|
628 /* (C.3) Public Function body */ |
|
629 s4o.indent_right(); |
|
630 this->current_scope = symbol; |
|
631 symbol->fblock_body->accept(*this); |
|
632 this->current_scope = NULL; |
|
633 s4o.indent_left(); |
|
634 s4o.print(s4o.indent_spaces + "} /* f() */\n\n"); |
|
635 s4o.indent_left(); |
|
636 |
|
637 /* (D) Close the class declaration... */ |
|
638 s4o.indent_left(); |
|
639 s4o.print(s4o.indent_spaces + "}; /* class "); |
|
640 symbol->fblock_name->accept(*this); |
|
641 s4o.print(" */\n"); |
|
642 |
|
643 --------------------------------- |
|
644 /* (E) Initialise the static member variables... */ |
|
645 vardecl = new generate_cc_vardecl_c(&s4o, |
|
646 generate_cc_vardecl_c::globalinit_vf, |
|
647 generate_cc_vardecl_c::located_vt); |
|
648 vardecl->print(symbol->var_declarations, symbol->fblock_name); |
|
649 delete vardecl; |
|
650 |
|
651 #endif |
|
652 |
|
653 s4o.indent_left(); |
|
654 s4o.print("\n\n\n\n"); |
|
655 |
|
656 return NULL; |
|
657 } |
|
658 |
|
659 |
|
660 /* The remaining temp_var_decls_c, temp_var_decls_list_c |
|
661 * and non_retentive_var_decls_c are handled in the generate_cc_vardecl_c class |
|
662 */ |
|
663 |
|
664 |
|
665 /**********************/ |
|
666 /* B 1.5.3 - Programs */ |
|
667 /**********************/ |
|
668 |
|
669 |
|
670 |
|
671 public: |
|
672 /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ |
|
673 //SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused) |
|
674 void *visit(program_declaration_c *symbol) { |
|
675 generate_cc_vardecl_c *vardecl; |
|
676 TRACE("program_declaration_c"); |
|
677 |
|
678 /* start off by adding this declaration to the global |
|
679 * program declaration symbol table... |
|
680 */ |
|
681 program_type_symtable.insert(symbol->program_type_name, symbol); |
|
682 |
|
683 /* (A) Class (Function Block) declaration... */ |
|
684 /* (A.1) Class (Function Block) name */ |
|
685 s4o.print("// PROGRAM\n"); |
|
686 s4o.print(s4o.indent_spaces + "class "); |
|
687 symbol->program_type_name->accept(*this); |
|
688 s4o.print(" {\n"); |
|
689 s4o.indent_right(); |
|
690 |
|
691 /* (A.2) Public variables: i.e. the program parameters... */ |
|
692 s4o.print(s4o.indent_spaces + "public:\n"); |
|
693 s4o.indent_right(); |
|
694 vardecl = new generate_cc_vardecl_c(&s4o, |
|
695 generate_cc_vardecl_c::local_vf, |
|
696 generate_cc_vardecl_c::input_vt | |
|
697 generate_cc_vardecl_c::output_vt | |
|
698 generate_cc_vardecl_c::inoutput_vt); |
|
699 vardecl->print(symbol->var_declarations); |
|
700 delete vardecl; |
|
701 s4o.indent_left(); |
|
702 s4o.print("\n"); |
|
703 |
|
704 /* (A.3) Private internal variables */ |
|
705 s4o.print(s4o.indent_spaces + "private:\n"); |
|
706 s4o.indent_right(); |
|
707 vardecl = new generate_cc_vardecl_c(&s4o, |
|
708 generate_cc_vardecl_c::local_vf, |
|
709 generate_cc_vardecl_c::private_vt | |
|
710 generate_cc_vardecl_c::located_vt | |
|
711 generate_cc_vardecl_c::external_vt); |
|
712 vardecl->print(symbol->var_declarations); |
|
713 delete vardecl; |
|
714 s4o.indent_left(); |
|
715 s4o.print("\n"); |
|
716 |
|
717 /* (B) Constructor */ |
|
718 /* (B.1) Constructor name... */ |
|
719 s4o.print(s4o.indent_spaces + "public:\n"); |
|
720 s4o.indent_right(); |
|
721 s4o.print(s4o.indent_spaces); |
|
722 symbol->program_type_name->accept(*this); |
|
723 |
|
724 /* (B.2) Constructor parameters (i.e. the external variables)... */ |
|
725 s4o.print("("); |
|
726 s4o.indent_right(); |
|
727 vardecl = new generate_cc_vardecl_c(&s4o, |
|
728 generate_cc_vardecl_c::finterface_vf, |
|
729 generate_cc_vardecl_c::external_vt); |
|
730 vardecl->print(symbol->var_declarations); |
|
731 delete vardecl; |
|
732 s4o.print(")\n"); |
|
733 s4o.indent_left(); |
|
734 |
|
735 /* (B.2) Member initializations... */ |
|
736 s4o.indent_right(); |
|
737 s4o.print(s4o.indent_spaces); |
|
738 vardecl = new generate_cc_vardecl_c(&s4o, |
|
739 generate_cc_vardecl_c::constructorinit_vf, |
|
740 generate_cc_vardecl_c::input_vt | |
|
741 generate_cc_vardecl_c::output_vt | |
|
742 generate_cc_vardecl_c::inoutput_vt | |
|
743 generate_cc_vardecl_c::private_vt | |
|
744 generate_cc_vardecl_c::external_vt); |
|
745 vardecl->print(symbol->var_declarations); |
|
746 delete vardecl; |
|
747 s4o.print("\n" + s4o.indent_spaces + "{}\n\n"); |
|
748 s4o.indent_left(); |
|
749 s4o.indent_left(); |
|
750 |
|
751 /* (C) Public Function*/ |
|
752 /* (C.1) Public Function declaration */ |
|
753 s4o.print(s4o.indent_spaces + "public:\n"); |
|
754 s4o.indent_right(); |
|
755 s4o.print(s4o.indent_spaces + "void f(void) {\n"); |
|
756 |
|
757 /* (C.2) Temporary variables */ |
|
758 s4o.indent_right(); |
|
759 vardecl = new generate_cc_vardecl_c(&s4o, generate_cc_vardecl_c::localinit_vf, generate_cc_vardecl_c::temp_vt); |
|
760 vardecl->print(symbol->var_declarations); |
|
761 delete vardecl; |
|
762 s4o.indent_left(); |
|
763 s4o.print("\n"); |
|
764 |
|
765 /* (C.3) Public Function body */ |
|
766 s4o.indent_right(); |
|
767 generate_cc_IL_and_ST_c generate_cc_code(&s4o, symbol); |
|
768 symbol->function_block_body->accept(generate_cc_code); |
|
769 s4o.indent_left(); |
|
770 s4o.print(s4o.indent_spaces + "} /* f() */\n\n"); |
|
771 s4o.indent_left(); |
|
772 |
|
773 /* (D) Close the class declaration... */ |
|
774 s4o.indent_left(); |
|
775 s4o.print(s4o.indent_spaces + "}; /* class "); |
|
776 symbol->program_type_name->accept(*this); |
|
777 s4o.print(" */\n\n\n"); |
|
778 |
|
779 /* (E) Initialise the static member variables... */ |
|
780 vardecl = new generate_cc_vardecl_c(&s4o, |
|
781 generate_cc_vardecl_c::globalinit_vf, |
|
782 generate_cc_vardecl_c::located_vt); |
|
783 vardecl->print(symbol->var_declarations, symbol->program_type_name); |
|
784 delete vardecl; |
|
785 s4o.print("\n\n\n\n"); |
|
786 |
|
787 return NULL; |
|
788 } |
|
789 |
|
790 |
|
791 /* intermediate helper symbol for program_declaration_c */ |
|
792 /* { io_var_declarations | other_var_declarations } */ |
|
793 /* |
|
794 * NOTE: we re-use the var_declarations_list_c |
|
795 */ |
|
796 |
|
797 /*********************************************/ |
|
798 /* B.1.6 Sequential function chart elements */ |
|
799 /*********************************************/ |
|
800 |
|
801 /********************************/ |
|
802 /* B 1.7 Configuration elements */ |
|
803 /********************************/ |
|
804 |
|
805 |
|
806 public: |
|
807 /* |
|
808 CONFIGURATION configuration_name |
|
809 optional_global_var_declarations |
|
810 (resource_declaration_list | single_resource_declaration) |
|
811 optional_access_declarations |
|
812 optional_instance_specific_initializations |
|
813 END_CONFIGURATION |
|
814 */ |
|
815 /* |
|
816 SYM_REF6(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, unused) |
|
817 */ |
|
818 void *visit(configuration_declaration_c *symbol) { |
|
819 static int configuration_count = 0; |
|
820 generate_cc_vardecl_c *vardecl; |
|
821 TRACE("configuration_declaration_c"); |
|
822 |
|
823 configuration_count++; |
|
824 if (configuration_count == 1) { |
|
825 /* the first configuration is the one we will use!! */ |
|
826 s4o.print("#define __configuration_c "); |
|
827 symbol->configuration_name->accept(*this); |
|
828 s4o.print("\n" + s4o.indent_spaces); |
|
829 } |
|
830 |
|
831 /* (A) Class (__configuration) declaration... */ |
|
832 /* (A.1) configuration name in comment */ |
|
833 s4o.print("// CONFIGURATION\n" + s4o.indent_spaces); |
|
834 s4o.print("class "); |
|
835 symbol->configuration_name->accept(*this); |
|
836 s4o.print(" {\n"); |
|
837 s4o.indent_right(); |
|
838 |
|
839 /* (A.2) Global variables |
|
840 * AND |
|
841 * (A.3) Programs in the Configuration |
|
842 */ |
|
843 /* Programs types are mapped onto classes, |
|
844 * and programs are then instantiated inside the configuration |
|
845 * as objects of the appropriate class! |
|
846 */ |
|
847 s4o.print(s4o.indent_spaces + "private:\n"); |
|
848 s4o.indent_right(); |
|
849 vardecl = new generate_cc_vardecl_c(&s4o, |
|
850 generate_cc_vardecl_c::local_vf, |
|
851 generate_cc_vardecl_c::global_vt | |
|
852 generate_cc_vardecl_c::program_vt | |
|
853 generate_cc_vardecl_c::resource_vt); |
|
854 vardecl->print(symbol); |
|
855 delete vardecl; |
|
856 s4o.indent_left(); |
|
857 s4o.print("\n"); |
|
858 |
|
859 |
|
860 |
|
861 /* (B) Constructor */ |
|
862 /* (B.1) Constructor name... */ |
|
863 s4o.print(s4o.indent_spaces + "public:\n"); |
|
864 s4o.indent_right(); |
|
865 s4o.print(s4o.indent_spaces); |
|
866 symbol->configuration_name->accept(*this); |
|
867 s4o.print("(void)\n"); |
|
868 |
|
869 /* (B.2) Member initializations... */ |
|
870 s4o.indent_right(); |
|
871 s4o.print(s4o.indent_spaces); |
|
872 vardecl = new generate_cc_vardecl_c(&s4o, |
|
873 generate_cc_vardecl_c::constructorinit_vf, |
|
874 generate_cc_vardecl_c::program_vt | |
|
875 generate_cc_vardecl_c::global_vt | |
|
876 generate_cc_vardecl_c::resource_vt); |
|
877 vardecl->print(symbol); |
|
878 delete vardecl; |
|
879 |
|
880 /* (B.3) Constructor Body... */ |
|
881 s4o.print("\n" + s4o.indent_spaces + "{}\n\n"); |
|
882 s4o.indent_left(); |
|
883 s4o.indent_left(); |
|
884 |
|
885 /* (C) Public Function*/ |
|
886 /* (C.1) Public Function declaration */ |
|
887 s4o.print(s4o.indent_spaces + "public:\n"); |
|
888 s4o.indent_right(); |
|
889 s4o.print(s4o.indent_spaces + "void run(void) {\n"); |
|
890 |
|
891 /* (C.2) Public Function body */ |
|
892 /* Invoke each program in the configuration */ |
|
893 s4o.indent_right(); |
|
894 generate_cc_configbody_c *configbody = new generate_cc_configbody_c(&s4o); |
|
895 symbol->accept(*configbody); |
|
896 delete configbody; |
|
897 s4o.indent_left(); |
|
898 |
|
899 /* (C.3) Close Public Function body */ |
|
900 s4o.print(s4o.indent_spaces + "} /* f() */\n\n"); |
|
901 s4o.indent_left(); |
|
902 |
|
903 /* (D) Close the class declaration... */ |
|
904 s4o.indent_left(); |
|
905 s4o.print(s4o.indent_spaces + "}; /* class "); |
|
906 symbol->configuration_name->accept(*this); |
|
907 s4o.print(" */\n\n\n"); |
|
908 |
|
909 return NULL; |
|
910 } |
|
911 |
|
912 |
|
913 |
|
914 |
|
915 |
|
916 |
|
917 |
|
918 #if 0 |
|
919 |
|
920 /* helper symbol for configuration_declaration */ |
|
921 SYM_LIST(resource_declaration_list_c) |
|
922 |
|
923 /* |
|
924 RESOURCE resource_name ON resource_type_name |
|
925 optional_global_var_declarations |
|
926 single_resource_declaration |
|
927 END_RESOURCE |
|
928 */ |
|
929 SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration) |
|
930 |
|
931 /* task_configuration_list program_configuration_list */ |
|
932 SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list) |
|
933 |
|
934 /* helper symbol for single_resource_declaration */ |
|
935 SYM_LIST(task_configuration_list_c) |
|
936 |
|
937 /* helper symbol for single_resource_declaration */ |
|
938 SYM_LIST(program_configuration_list_c) |
|
939 |
|
940 /* helper symbol for |
|
941 * - access_path |
|
942 * - instance_specific_init |
|
943 */ |
|
944 SYM_LIST(any_fb_name_list_c) |
|
945 |
|
946 /* [resource_name '.'] global_var_name ['.' structure_element_name] */ |
|
947 SYM_REF4(global_var_reference_c, resource_name, global_var_name, structure_element_name, unused) |
|
948 |
|
949 /* prev_declared_program_name '.' symbolic_variable */ |
|
950 SYM_REF2(program_output_reference_c, program_name, symbolic_variable) |
|
951 |
|
952 /* TASK task_name task_initialization */ |
|
953 SYM_REF2(task_configuration_c, task_name, task_initialization) |
|
954 |
|
955 /* '(' [SINGLE ASSIGN data_source ','] [INTERVAL ASSIGN data_source ','] PRIORITY ASSIGN integer ')' */ |
|
956 SYM_REF4(task_initialization_c, single_data_source, interval_data_source, priority_data_source, unused) |
|
957 |
|
958 /* PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */ |
|
959 SYM_REF6(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements, unused) |
|
960 |
|
961 /* prog_conf_elements ',' prog_conf_element */ |
|
962 SYM_LIST(prog_conf_elements_c) |
|
963 |
|
964 /* fb_name WITH task_name */ |
|
965 SYM_REF2(fb_task_c, fb_name, task_name) |
|
966 |
|
967 /* any_symbolic_variable ASSIGN prog_data_source */ |
|
968 SYM_REF2(prog_cnxn_assign_c, symbolic_variable, prog_data_source) |
|
969 |
|
970 /* any_symbolic_variable SENDTO data_sink */ |
|
971 SYM_REF2(prog_cnxn_sendto_c, symbolic_variable, prog_data_source) |
|
972 |
|
973 /* VAR_CONFIG instance_specific_init_list END_VAR_BOGUS */ |
|
974 SYM_REF2(instance_specific_initializations_c, instance_specific_init_list, unused) |
|
975 |
|
976 /* helper symbol for instance_specific_initializations */ |
|
977 SYM_LIST(instance_specific_init_list_c) |
|
978 |
|
979 /* resource_name '.' program_name '.' {fb_name '.'} |
|
980 ((variable_name [location] ':' located_var_spec_init) | (fb_name ':' fb_initialization)) |
|
981 */ |
|
982 SYM_REF6(instance_specific_init_c, resource_name, program_name, any_fb_name_list, variable_name, location, initialization) |
|
983 |
|
984 /* helper symbol for instance_specific_init */ |
|
985 /* function_block_type_name ':=' structure_initialization */ |
|
986 SYM_REF2(fb_initialization_c, function_block_type_name, structure_initialization) |
|
987 |
|
988 #endif |
|
989 |
|
990 |
|
991 }; /* generate_cc_c */ |
|
992 |
|
993 |
|
994 |
|
995 /***********************************************************************/ |
|
996 /***********************************************************************/ |
|
997 /***********************************************************************/ |
|
998 /***********************************************************************/ |
|
999 /***********************************************************************/ |
|
1000 /***********************************************************************/ |
|
1001 /***********************************************************************/ |
|
1002 /***********************************************************************/ |
|
1003 |
|
1004 |
|
1005 |
|
1006 |
|
1007 visitor_c *new_code_generator(stage4out_c *s4o) {return new generate_cc_c(s4o);} |
|
1008 void delete_code_generator(visitor_c *code_generator) {delete code_generator;} |
|
1009 |
|
1010 |