diff -r aad38592bdde -r c0bda77b37a0 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Tue Aug 14 19:40:01 2012 +0200 +++ b/stage4/generate_c/generate_c.cc Wed Aug 22 16:46:17 2012 +0200 @@ -31,10 +31,12 @@ #include #include + #include "../../util/symtable.hh" #include "../../util/dsymtable.hh" #include "../../absyntax/visitor.hh" #include "../../absyntax_utils/absyntax_utils.hh" +#include "../../main.hh" // required for ERROR() and ERROR_MSG() macros. #include "../stage4.hh" @@ -45,9 +47,16 @@ #define TRACE(classname) #endif -#define ERROR error_exit(__FILE__,__LINE__) -/* function defined in main.cc */ -extern void error_exit(const char *file_name, int line_no); + + +#define STAGE4_ERROR(symbol1, symbol2, ...) {stage4err("while generating C code", symbol1, symbol2, __VA_ARGS__); exit(EXIT_FAILURE);} + + +/* 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! */ +#define VALID_CVALUE(dtype, symbol) (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status) +#define GET_CVALUE(dtype, symbol) ((symbol)->const_value._##dtype.value) + + /***********************************************************************/ @@ -197,10 +206,9 @@ } public: - print_function_parameter_data_types_c(stage4out_c *s4o_ptr): - generate_c_base_c(s4o_ptr) { - current_type = NULL; - } + print_function_parameter_data_types_c(stage4out_c *s4o_ptr): + generate_c_base_c(s4o_ptr) + {current_type = NULL;} /**************************************/ /* B.1.5 - Program organization units */ @@ -211,8 +219,7 @@ /* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */ void *visit(function_declaration_c *symbol) { - /* return type */ - symbol->type_name->accept(*this); + symbol->type_name->accept(*this); /* return type */ symbol->var_declarations_list->accept(*this); return NULL; } @@ -339,94 +346,75 @@ #define MILLISECOND 1000000 #define SECOND 1000 * MILLISECOND -/* A helper class that knows how to generate code for both the IL and ST languages... */ -class calculate_time_c: public iterator_visitor_c { - private: - unsigned long long time; - float current_value; +unsigned long long calculate_time(symbol_c *symbol) { + if (NULL == symbol) return 0; - public: - calculate_time_c(void){time = 0;}; - - unsigned long long get_time(void) {return time;}; - - void *get_integer_value(token_c *token) { - std::string str = ""; - for (unsigned int i = 0; i < strlen(token->value); i++) - if (token->value[i] != '_') - str += token->value[i]; - current_value = atof(str.c_str()); - return NULL; - } - - void *get_float_value(token_c *token) { - current_value = atof(token->value); - return NULL; - } - -/******************************/ -/* B 1.2.1 - Numeric Literals */ -/******************************/ - - void *visit(integer_c *symbol) {return get_integer_value(symbol);} - -/************************/ -/* B 1.2.3.1 - Duration */ -/************************/ + interval_c *interval = dynamic_cast(symbol); + duration_c *duration = dynamic_cast(symbol); + if ((NULL == interval) && (NULL == duration)) ERROR; + + if (NULL != duration) { /* SYM_REF2(duration_c, neg, interval) */ - void *visit(duration_c *symbol) { - if (symbol->neg != NULL) - ERROR; - symbol->interval->accept(*this); - return NULL; - } - - /* SYM_TOKEN(fixed_point_c) */ - void *visit(fixed_point_c *symbol) {return get_float_value(symbol);} - - /* SYM_REF2(days_c, days, hours) */ - void *visit(days_c *symbol) { - if (symbol->hours) - symbol->hours->accept(*this); - symbol->days->accept(*this); - time += (unsigned long long)(current_value * 24 * 3600 * SECOND); - return NULL; - } - - /* SYM_REF2(hours_c, hours, minutes) */ - void *visit(hours_c *symbol) { - if (symbol->minutes) - symbol->minutes->accept(*this); - symbol->hours->accept(*this); - time += (unsigned long long)(current_value * 3600 * SECOND); - return NULL; - } - - /* SYM_REF2(minutes_c, minutes, seconds) */ - void *visit(minutes_c *symbol) { - if (symbol->seconds) - symbol->seconds->accept(*this); - symbol->minutes->accept(*this); - time += (unsigned long long)(current_value * 60 * SECOND); - return NULL; - } - - /* SYM_REF2(seconds_c, seconds, milliseconds) */ - void *visit(seconds_c *symbol) { - if (symbol->milliseconds) - symbol->milliseconds->accept(*this); - symbol->seconds->accept(*this); - time += (unsigned long long)(current_value * SECOND); - return NULL; - } - - /* SYM_REF2(milliseconds_c, milliseconds, unused) */ - void *visit(milliseconds_c *symbol) { - symbol->milliseconds->accept(*this); - time += (unsigned long long)(current_value * MILLISECOND); - return NULL; - } + if (duration->neg != NULL) + {STAGE4_ERROR(duration, duration, "Negative TIME literals are not currently supported"); ERROR;} + return calculate_time(duration->interval); + } + + if (NULL != interval) { + /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */ + unsigned long long int time_ull = 0; + long double time_ld = 0; + /* + const unsigned long long int MILLISECOND = 1000000; + const unsigned long long int SECOND = 1000 * MILLISECOND + */ + + if (NULL != interval->milliseconds) { + if (VALID_CVALUE( int64, interval->milliseconds) && GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive! + if (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND; + else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND; + else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND; + else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value! + } + + if (NULL != interval->seconds ) { + if (VALID_CVALUE( int64, interval->seconds ) && GET_CVALUE( int64, interval->seconds ) < 0) ERROR; // interval elements should always be positive! + if (VALID_CVALUE( int64, interval->seconds )) time_ull += GET_CVALUE( int64, interval->seconds ) * SECOND; + else if (VALID_CVALUE(uint64, interval->seconds )) time_ull += GET_CVALUE(uint64, interval->seconds ) * SECOND; + else if (VALID_CVALUE(real64, interval->seconds )) time_ld += GET_CVALUE(real64, interval->seconds ) * SECOND; + else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value! + } + + if (NULL != interval->minutes ) { + if (VALID_CVALUE( int64, interval->minutes ) && GET_CVALUE( int64, interval->minutes ) < 0) ERROR; // interval elements should always be positive! + if (VALID_CVALUE( int64, interval->minutes )) time_ull += GET_CVALUE( int64, interval->minutes ) * SECOND * 60; + else if (VALID_CVALUE(uint64, interval->minutes )) time_ull += GET_CVALUE(uint64, interval->minutes ) * SECOND * 60; + else if (VALID_CVALUE(real64, interval->minutes )) time_ld += GET_CVALUE(real64, interval->minutes ) * SECOND * 60; + else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value! + } + + if (NULL != interval->hours ) { + if (VALID_CVALUE( int64, interval->hours ) && GET_CVALUE( int64, interval->hours ) < 0) ERROR; // interval elements should always be positive! + if (VALID_CVALUE( int64, interval->hours )) time_ull += GET_CVALUE( int64, interval->hours ) * SECOND * 60 * 60; + else if (VALID_CVALUE(uint64, interval->hours )) time_ull += GET_CVALUE(uint64, interval->hours ) * SECOND * 60 * 60; + else if (VALID_CVALUE(real64, interval->hours )) time_ld += GET_CVALUE(real64, interval->hours ) * SECOND * 60 * 60; + else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value! + } + + if (NULL != interval->days ) { + if (VALID_CVALUE( int64, interval->days ) && GET_CVALUE( int64, interval->days ) < 0) ERROR; // interval elements should always be positive! + if (VALID_CVALUE( int64, interval->days )) time_ull += GET_CVALUE( int64, interval->days ) * SECOND * 60 * 60 * 24; + else if (VALID_CVALUE(uint64, interval->days )) time_ull += GET_CVALUE(uint64, interval->days ) * SECOND * 60 * 60 * 24; + else if (VALID_CVALUE(real64, interval->days )) time_ld += GET_CVALUE(real64, interval->days ) * SECOND * 60 * 60 * 24; + else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value! + } + + time_ull += time_ld; + return time_ull; + }; + ERROR; // should never reach this point! + return 0; // humour the compiler! }; /***********************************************************************/ @@ -480,14 +468,9 @@ /* TASK task_name task_initialization */ //SYM_REF2(task_configuration_c, task_name, task_initialization) void *visit(task_initialization_c *symbol) { - calculate_time_c calculate_time; - unsigned long long time = 0; - if (symbol->interval_data_source != NULL) { - symbol->interval_data_source->accept(calculate_time); - time = calculate_time.get_time(); - } - if (time > 0) - update_ticktime(time); + unsigned long long time = calculate_time(symbol->interval_data_source); + if (time < 0) ERROR; + else update_ticktime(time); return NULL; } }; @@ -788,19 +771,18 @@ /* signed_integer DOTDOT signed_integer */ //SYM_REF2(subrange_c, lower_limit, upper_limit) void *visit(subrange_c *symbol) { - int dimension = extract_integer(symbol->upper_limit) - extract_integer(symbol->lower_limit) + 1; switch (current_mode) { case arrayname_im: current_array_name += "_"; { std::stringstream ss; - ss << dimension; + ss << symbol->dimension; current_array_name += ss.str(); } break; case arraydeclaration_im: s4o_incl.print("["); - s4o_incl.print_integer(dimension); + s4o_incl.print(symbol->dimension); s4o_incl.print("]"); default: generate_c_typedecl_c::visit(symbol); @@ -809,11 +791,6 @@ return NULL; } - /* var1_list ':' structure_type_name */ - void *visit(structured_var_declaration_c *symbol) { - return NULL; - } - /* var1_list ':' initialized_structure */ // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure) void *visit(structured_var_init_decl_c *symbol) { @@ -851,6 +828,12 @@ return NULL; } + /* var1_list ':' structure_type_name */ + //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name) + void *visit(structured_var_declaration_c *symbol) { + return NULL; + } + /* VAR [CONSTANT] var_init_decl_list END_VAR */ /* option -> may be NULL ! */ /* helper symbol for input_declarations */ @@ -1676,7 +1659,8 @@ s4o.print(s4o.indent_spaces); vardecl = new generate_c_vardecl_c(&s4o, generate_c_vardecl_c::constructorinit_vf, - generate_c_vardecl_c::global_vt); + generate_c_vardecl_c::global_vt, + symbol->configuration_name); vardecl->print(symbol); delete vardecl; s4o.print("\n"); @@ -1819,7 +1803,7 @@ declaretype_t wanted_declaretype; - unsigned long common_ticktime; + unsigned long long common_ticktime; const char *current_program_name; @@ -2196,12 +2180,10 @@ current_task_name->accept(*this); s4o.print(" = "); if (symbol->interval_data_source != NULL) { - calculate_time_c calculate_time; - symbol->interval_data_source->accept(calculate_time); - unsigned long time = calculate_time.get_time(); + unsigned long long int time = calculate_time(symbol->interval_data_source); if (time != 0) { s4o.print("!(tick % "); - s4o.print_integer((int)(time / common_ticktime)); + s4o.print(time / common_ticktime); s4o.print(")"); } else @@ -2231,10 +2213,10 @@ if (var_decl == NULL) ERROR; else - vartype = search_config_instance->get_vartype(); + vartype = search_config_instance->get_vartype(current_var_reference); } else - vartype = search_resource_instance->get_vartype(); + vartype = search_resource_instance->get_vartype(current_var_reference); s4o.print(s4o.indent_spaces + "{extern "); var_decl->accept(*this); @@ -2245,7 +2227,7 @@ s4o.print("."); symbol->symbolic_variable->accept(*this); s4o.print(" = "); - if (vartype || search_var_instance_decl_c::global_vt) + if (vartype == search_var_instance_decl_c::global_vt) s4o.print("*"); symbol->prog_data_source->accept(*this); s4o.print(";}\n"); @@ -2266,17 +2248,17 @@ if (var_decl == NULL) ERROR; else - vartype = search_config_instance->get_vartype(); + vartype = search_config_instance->get_vartype(current_var_reference); } else - vartype = search_resource_instance->get_vartype(); + vartype = search_resource_instance->get_vartype(current_var_reference); s4o.print(s4o.indent_spaces + "{extern "); var_decl->accept(*this); s4o.print(" *"); symbol->data_sink->accept(*this); s4o.print("; "); - if (vartype || search_var_instance_decl_c::global_vt) + if (vartype == search_var_instance_decl_c::global_vt) s4o.print("*"); symbol->data_sink->accept(*this); s4o.print(" = "); @@ -2491,6 +2473,7 @@ if (configuration_count++) { /* the first configuration is the one we will use!! */ + STAGE4_ERROR(symbol, symbol, "A previous CONFIGURATION has already been declared (C code generation currently only allows a single configuration)."); ERROR; } @@ -2501,7 +2484,7 @@ symbol->accept(calculate_common_ticktime); common_ticktime = calculate_common_ticktime.get_common_ticktime(); if (common_ticktime == 0) { - fprintf(stderr, "\nYou must at least define a periodic task to set cycle period!"); + STAGE4_ERROR(symbol, symbol, "You must define at least one periodic task (to set cycle period)!"); ERROR; }