29 #include <list> |
29 #include <list> |
30 #include <map> |
30 #include <map> |
31 #include <sstream> |
31 #include <sstream> |
32 #include <strings.h> |
32 #include <strings.h> |
33 |
33 |
|
34 |
34 #include "../../util/symtable.hh" |
35 #include "../../util/symtable.hh" |
35 #include "../../util/dsymtable.hh" |
36 #include "../../util/dsymtable.hh" |
36 #include "../../absyntax/visitor.hh" |
37 #include "../../absyntax/visitor.hh" |
37 #include "../../absyntax_utils/absyntax_utils.hh" |
38 #include "../../absyntax_utils/absyntax_utils.hh" |
|
39 #include "../../main.hh" // required for ERROR() and ERROR_MSG() macros. |
38 |
40 |
39 #include "../stage4.hh" |
41 #include "../stage4.hh" |
40 |
42 |
41 //#define DEBUG |
43 //#define DEBUG |
42 #ifdef DEBUG |
44 #ifdef DEBUG |
43 #define TRACE(classname) printf("\n____%s____\n",classname); |
45 #define TRACE(classname) printf("\n____%s____\n",classname); |
44 #else |
46 #else |
45 #define TRACE(classname) |
47 #define TRACE(classname) |
46 #endif |
48 #endif |
47 |
49 |
48 #define ERROR error_exit(__FILE__,__LINE__) |
50 |
49 /* function defined in main.cc */ |
51 |
50 extern void error_exit(const char *file_name, int line_no); |
52 #define STAGE4_ERROR(symbol1, symbol2, ...) {stage4err("while generating C code", symbol1, symbol2, __VA_ARGS__); exit(EXIT_FAILURE);} |
|
53 |
|
54 |
|
55 /* Macros to access the constant value of each expression (if it exists) from the annotation introduced to the symbol_c object by constant_folding_c in stage3! */ |
|
56 #define VALID_CVALUE(dtype, symbol) (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status) |
|
57 #define GET_CVALUE(dtype, symbol) ((symbol)->const_value._##dtype.value) |
|
58 |
|
59 |
51 |
60 |
52 /***********************************************************************/ |
61 /***********************************************************************/ |
53 |
62 |
54 /* Unlike Programs and Configurations which get mapped onto C++ classes, |
63 /* Unlike Programs and Configurations which get mapped onto C++ classes, |
55 * Function Blocks are mapped onto a C structure containing the variables, and |
64 * Function Blocks are mapped onto a C structure containing the variables, and |
195 } |
204 } |
196 } |
205 } |
197 } |
206 } |
198 |
207 |
199 public: |
208 public: |
200 print_function_parameter_data_types_c(stage4out_c *s4o_ptr): |
209 print_function_parameter_data_types_c(stage4out_c *s4o_ptr): |
201 generate_c_base_c(s4o_ptr) { |
210 generate_c_base_c(s4o_ptr) |
202 current_type = NULL; |
211 {current_type = NULL;} |
203 } |
|
204 |
212 |
205 /**************************************/ |
213 /**************************************/ |
206 /* B.1.5 - Program organization units */ |
214 /* B.1.5 - Program organization units */ |
207 /**************************************/ |
215 /**************************************/ |
208 /***********************/ |
216 /***********************/ |
209 /* B 1.5.1 - Functions */ |
217 /* B 1.5.1 - Functions */ |
210 /***********************/ |
218 /***********************/ |
211 /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
219 /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
212 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
220 /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ |
213 void *visit(function_declaration_c *symbol) { |
221 void *visit(function_declaration_c *symbol) { |
214 /* return type */ |
222 symbol->type_name->accept(*this); /* return type */ |
215 symbol->type_name->accept(*this); |
|
216 symbol->var_declarations_list->accept(*this); |
223 symbol->var_declarations_list->accept(*this); |
217 return NULL; |
224 return NULL; |
218 } |
225 } |
219 |
226 |
220 /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */ |
227 /* already handled by iterator base class (note that generate_c_base_c inherits from iterator_c) */ |
337 /***********************************************************************/ |
344 /***********************************************************************/ |
338 |
345 |
339 #define MILLISECOND 1000000 |
346 #define MILLISECOND 1000000 |
340 #define SECOND 1000 * MILLISECOND |
347 #define SECOND 1000 * MILLISECOND |
341 |
348 |
342 /* A helper class that knows how to generate code for both the IL and ST languages... */ |
349 unsigned long long calculate_time(symbol_c *symbol) { |
343 class calculate_time_c: public iterator_visitor_c { |
350 if (NULL == symbol) return 0; |
344 private: |
|
345 unsigned long long time; |
|
346 float current_value; |
|
347 |
351 |
348 public: |
352 interval_c *interval = dynamic_cast<interval_c *>(symbol); |
349 calculate_time_c(void){time = 0;}; |
353 duration_c *duration = dynamic_cast<duration_c *>(symbol); |
350 |
|
351 unsigned long long get_time(void) {return time;}; |
|
352 |
|
353 void *get_integer_value(token_c *token) { |
|
354 std::string str = ""; |
|
355 for (unsigned int i = 0; i < strlen(token->value); i++) |
|
356 if (token->value[i] != '_') |
|
357 str += token->value[i]; |
|
358 current_value = atof(str.c_str()); |
|
359 return NULL; |
|
360 } |
|
361 |
|
362 void *get_float_value(token_c *token) { |
|
363 current_value = atof(token->value); |
|
364 return NULL; |
|
365 } |
|
366 |
|
367 /******************************/ |
|
368 /* B 1.2.1 - Numeric Literals */ |
|
369 /******************************/ |
|
370 |
|
371 void *visit(integer_c *symbol) {return get_integer_value(symbol);} |
|
372 |
|
373 /************************/ |
|
374 /* B 1.2.3.1 - Duration */ |
|
375 /************************/ |
|
376 |
354 |
|
355 if ((NULL == interval) && (NULL == duration)) ERROR; |
|
356 |
|
357 if (NULL != duration) { |
377 /* SYM_REF2(duration_c, neg, interval) */ |
358 /* SYM_REF2(duration_c, neg, interval) */ |
378 void *visit(duration_c *symbol) { |
359 if (duration->neg != NULL) |
379 if (symbol->neg != NULL) |
360 {STAGE4_ERROR(duration, duration, "Negative TIME literals are not currently supported"); ERROR;} |
380 ERROR; |
361 return calculate_time(duration->interval); |
381 symbol->interval->accept(*this); |
362 } |
382 return NULL; |
363 |
383 } |
364 if (NULL != interval) { |
384 |
365 /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */ |
385 /* SYM_TOKEN(fixed_point_c) */ |
366 unsigned long long int time_ull = 0; |
386 void *visit(fixed_point_c *symbol) {return get_float_value(symbol);} |
367 long double time_ld = 0; |
387 |
368 /* |
388 /* SYM_REF2(days_c, days, hours) */ |
369 const unsigned long long int MILLISECOND = 1000000; |
389 void *visit(days_c *symbol) { |
370 const unsigned long long int SECOND = 1000 * MILLISECOND |
390 if (symbol->hours) |
371 */ |
391 symbol->hours->accept(*this); |
372 |
392 symbol->days->accept(*this); |
373 if (NULL != interval->milliseconds) { |
393 time += (unsigned long long)(current_value * 24 * 3600 * SECOND); |
374 if (VALID_CVALUE( int64, interval->milliseconds) && GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive! |
394 return NULL; |
375 if (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND; |
395 } |
376 else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND; |
396 |
377 else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND; |
397 /* SYM_REF2(hours_c, hours, minutes) */ |
378 else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value! |
398 void *visit(hours_c *symbol) { |
379 } |
399 if (symbol->minutes) |
380 |
400 symbol->minutes->accept(*this); |
381 if (NULL != interval->seconds ) { |
401 symbol->hours->accept(*this); |
382 if (VALID_CVALUE( int64, interval->seconds ) && GET_CVALUE( int64, interval->seconds ) < 0) ERROR; // interval elements should always be positive! |
402 time += (unsigned long long)(current_value * 3600 * SECOND); |
383 if (VALID_CVALUE( int64, interval->seconds )) time_ull += GET_CVALUE( int64, interval->seconds ) * SECOND; |
403 return NULL; |
384 else if (VALID_CVALUE(uint64, interval->seconds )) time_ull += GET_CVALUE(uint64, interval->seconds ) * SECOND; |
404 } |
385 else if (VALID_CVALUE(real64, interval->seconds )) time_ld += GET_CVALUE(real64, interval->seconds ) * SECOND; |
405 |
386 else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value! |
406 /* SYM_REF2(minutes_c, minutes, seconds) */ |
387 } |
407 void *visit(minutes_c *symbol) { |
388 |
408 if (symbol->seconds) |
389 if (NULL != interval->minutes ) { |
409 symbol->seconds->accept(*this); |
390 if (VALID_CVALUE( int64, interval->minutes ) && GET_CVALUE( int64, interval->minutes ) < 0) ERROR; // interval elements should always be positive! |
410 symbol->minutes->accept(*this); |
391 if (VALID_CVALUE( int64, interval->minutes )) time_ull += GET_CVALUE( int64, interval->minutes ) * SECOND * 60; |
411 time += (unsigned long long)(current_value * 60 * SECOND); |
392 else if (VALID_CVALUE(uint64, interval->minutes )) time_ull += GET_CVALUE(uint64, interval->minutes ) * SECOND * 60; |
412 return NULL; |
393 else if (VALID_CVALUE(real64, interval->minutes )) time_ld += GET_CVALUE(real64, interval->minutes ) * SECOND * 60; |
413 } |
394 else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value! |
414 |
395 } |
415 /* SYM_REF2(seconds_c, seconds, milliseconds) */ |
396 |
416 void *visit(seconds_c *symbol) { |
397 if (NULL != interval->hours ) { |
417 if (symbol->milliseconds) |
398 if (VALID_CVALUE( int64, interval->hours ) && GET_CVALUE( int64, interval->hours ) < 0) ERROR; // interval elements should always be positive! |
418 symbol->milliseconds->accept(*this); |
399 if (VALID_CVALUE( int64, interval->hours )) time_ull += GET_CVALUE( int64, interval->hours ) * SECOND * 60 * 60; |
419 symbol->seconds->accept(*this); |
400 else if (VALID_CVALUE(uint64, interval->hours )) time_ull += GET_CVALUE(uint64, interval->hours ) * SECOND * 60 * 60; |
420 time += (unsigned long long)(current_value * SECOND); |
401 else if (VALID_CVALUE(real64, interval->hours )) time_ld += GET_CVALUE(real64, interval->hours ) * SECOND * 60 * 60; |
421 return NULL; |
402 else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value! |
422 } |
403 } |
423 |
404 |
424 /* SYM_REF2(milliseconds_c, milliseconds, unused) */ |
405 if (NULL != interval->days ) { |
425 void *visit(milliseconds_c *symbol) { |
406 if (VALID_CVALUE( int64, interval->days ) && GET_CVALUE( int64, interval->days ) < 0) ERROR; // interval elements should always be positive! |
426 symbol->milliseconds->accept(*this); |
407 if (VALID_CVALUE( int64, interval->days )) time_ull += GET_CVALUE( int64, interval->days ) * SECOND * 60 * 60 * 24; |
427 time += (unsigned long long)(current_value * MILLISECOND); |
408 else if (VALID_CVALUE(uint64, interval->days )) time_ull += GET_CVALUE(uint64, interval->days ) * SECOND * 60 * 60 * 24; |
428 return NULL; |
409 else if (VALID_CVALUE(real64, interval->days )) time_ld += GET_CVALUE(real64, interval->days ) * SECOND * 60 * 60 * 24; |
429 } |
410 else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value! |
|
411 } |
|
412 |
|
413 time_ull += time_ld; |
|
414 return time_ull; |
|
415 }; |
|
416 ERROR; // should never reach this point! |
|
417 return 0; // humour the compiler! |
430 }; |
418 }; |
431 |
419 |
432 /***********************************************************************/ |
420 /***********************************************************************/ |
433 /***********************************************************************/ |
421 /***********************************************************************/ |
434 /***********************************************************************/ |
422 /***********************************************************************/ |
786 } |
769 } |
787 |
770 |
788 /* signed_integer DOTDOT signed_integer */ |
771 /* signed_integer DOTDOT signed_integer */ |
789 //SYM_REF2(subrange_c, lower_limit, upper_limit) |
772 //SYM_REF2(subrange_c, lower_limit, upper_limit) |
790 void *visit(subrange_c *symbol) { |
773 void *visit(subrange_c *symbol) { |
791 int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1; |
|
792 switch (current_mode) { |
774 switch (current_mode) { |
793 case arrayname_im: |
775 case arrayname_im: |
794 current_array_name += "_"; |
776 current_array_name += "_"; |
795 { |
777 { |
796 std::stringstream ss; |
778 std::stringstream ss; |
797 ss << dimension; |
779 ss << symbol->dimension; |
798 current_array_name += ss.str(); |
780 current_array_name += ss.str(); |
799 } |
781 } |
800 break; |
782 break; |
801 case arraydeclaration_im: |
783 case arraydeclaration_im: |
802 s4o_incl.print("["); |
784 s4o_incl.print("["); |
803 s4o_incl.print_integer(dimension); |
785 s4o_incl.print(symbol->dimension); |
804 s4o_incl.print("]"); |
786 s4o_incl.print("]"); |
805 default: |
787 default: |
806 generate_c_typedecl_c::visit(symbol); |
788 generate_c_typedecl_c::visit(symbol); |
807 break; |
789 break; |
808 } |
790 } |
809 return NULL; |
791 return NULL; |
810 } |
792 } |
811 |
|
812 /* var1_list ':' structure_type_name */ |
|
813 void *visit(structured_var_declaration_c *symbol) { |
|
814 return NULL; |
|
815 } |
|
816 |
793 |
817 /* var1_list ':' initialized_structure */ |
794 /* var1_list ':' initialized_structure */ |
818 // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) |
795 // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) |
819 void *visit(structured_var_init_decl_c *symbol) { |
796 void *visit(structured_var_init_decl_c *symbol) { |
820 return NULL; |
797 return NULL; |