diff -r 90782e241346 -r d7d92b2f87e9 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Wed Mar 30 19:53:32 2011 +0100 +++ b/stage4/generate_c/generate_c_st.cc Thu Mar 31 10:45:34 2011 +0100 @@ -40,6 +40,15 @@ class generate_c_st_c: public generate_c_typedecl_c { + public: + typedef enum { + expression_vg, + assignment_vg, + complextype_base_vg, + complextype_suffix_vg, + fparam_output_vg + } variablegeneration_t; + private: /* When calling a function block, we must first find it's type, * by searching through the declarations of the variables currently @@ -71,18 +80,25 @@ search_base_type_c search_base_type; symbol_c* current_array_type; - - bool current_param_is_pointer; + symbol_c* current_param_type; + + int fcall_number; + symbol_c *fbname; + + variablegeneration_t wanted_variablegeneration; public: - generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL) + generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL) : generate_c_typedecl_c(s4o_ptr) { search_fb_instance_decl = new search_fb_instance_decl_c(scope); search_expression_type = new search_expression_type_c(scope); search_varfb_instance_type = new search_varfb_instance_type_c(scope); this->set_variable_prefix(variable_prefix); current_array_type = NULL; - current_param_is_pointer = false; + current_param_type = NULL; + fcall_number = 0; + fbname = name; + wanted_variablegeneration = expression_vg; } virtual ~generate_c_st_c(void) { @@ -99,25 +115,109 @@ private: +void *print_getter(symbol_c *symbol) { + unsigned int vartype = search_varfb_instance_type->get_vartype(symbol); + if (wanted_variablegeneration == fparam_output_vg) { + if (vartype == search_var_instance_decl_c::external_vt) + s4o.print(GET_EXTERNAL_BY_REF); + else if (vartype == search_var_instance_decl_c::located_vt) + s4o.print(GET_LOCATED_BY_REF); + else + s4o.print(GET_VAR_BY_REF); + } + else { + if (vartype == search_var_instance_decl_c::external_vt) + s4o.print(GET_EXTERNAL); + else if (vartype == search_var_instance_decl_c::located_vt) + s4o.print(GET_LOCATED); + else + s4o.print(GET_VAR); + } + s4o.print("("); + + variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; + wanted_variablegeneration = complextype_base_vg; + symbol->accept(*this); + if (search_varfb_instance_type->type_is_complex()) + s4o.print(","); + wanted_variablegeneration = complextype_suffix_vg; + symbol->accept(*this); + s4o.print(")"); + wanted_variablegeneration = old_wanted_variablegeneration; + return NULL; +} + +void *print_setter(symbol_c* symbol, + symbol_c* type, + symbol_c* value, + symbol_c* fb_symbol = NULL, + symbol_c* fb_value = NULL) { + unsigned int vartype = search_varfb_instance_type->get_vartype(symbol); + if (vartype == search_var_instance_decl_c::external_vt) { + symbolic_variable_c *variable = dynamic_cast(symbol); + /* TODO Find a solution for forcing global complex variables */ + if (variable != NULL) { + s4o.print(SET_EXTERNAL); + s4o.print("("); + variable->var_name->accept(*this); + s4o.print(","); + } + else { + s4o.print(SET_COMPLEX_EXTERNAL); + s4o.print("("); + } + } + else { + if (vartype == search_var_instance_decl_c::located_vt) + s4o.print(SET_LOCATED); + else + s4o.print(SET_VAR); + s4o.print("("); + } + + if (fb_symbol != NULL) { + print_variable_prefix(); + fb_symbol->accept(*this); + s4o.print("."); + } + else + wanted_variablegeneration = complextype_base_vg; + symbol->accept(*this); + s4o.print(","); + wanted_variablegeneration = expression_vg; + print_check_function(type, value, fb_value); + if (search_varfb_instance_type->type_is_complex()) { + s4o.print(","); + wanted_variablegeneration = complextype_suffix_vg; + symbol->accept(*this); + } + s4o.print(")"); + wanted_variablegeneration = expression_vg; + return NULL; +} /*********************/ /* B 1.4 - Variables */ /*********************/ void *visit(symbolic_variable_c *symbol) { - unsigned int vartype = search_varfb_instance_type->get_vartype(symbol); - if (!current_param_is_pointer && (vartype == search_var_instance_decl_c::external_vt || vartype == search_var_instance_decl_c::located_vt)) { - s4o.print("*("); - generate_c_base_c::visit(symbol); - s4o.print(")"); - } - else if (current_param_is_pointer && vartype != search_var_instance_decl_c::external_vt && vartype != search_var_instance_decl_c::located_vt) { - s4o.print("&("); - generate_c_base_c::visit(symbol); - s4o.print(")"); - } - else { - generate_c_base_c::visit(symbol); - } + unsigned int vartype; + if (wanted_variablegeneration == complextype_base_vg) + generate_c_base_c::visit(symbol); + else if (wanted_variablegeneration == complextype_suffix_vg) + return NULL; + else if (this->is_variable_prefix_null()) { + vartype = search_varfb_instance_type->get_vartype(symbol); + if (wanted_variablegeneration == fparam_output_vg) { + s4o.print("&("); + generate_c_base_c::visit(symbol); + s4o.print(")"); + } + else { + generate_c_base_c::visit(symbol); + } + } + else + print_getter(symbol); return NULL; } @@ -129,14 +229,29 @@ TRACE("direct_variable_c"); /* Do not use print_token() as it will change everything into uppercase */ if (strlen(symbol->value) == 0) ERROR; - if (!current_param_is_pointer) { - s4o.print("*("); + if (this->is_variable_prefix_null()) { + if (wanted_variablegeneration != fparam_output_vg) + s4o.print("*("); + } + else { + switch (wanted_variablegeneration) { + case expression_vg: + s4o.print(GET_LOCATED); + s4o.print("("); + break; + case fparam_output_vg: + s4o.print(GET_LOCATED_BY_REF); + s4o.print("("); + break; + default: + break; + } } this->print_variable_prefix(); s4o.printlocation(symbol->value + 1); - if (!current_param_is_pointer) { + if ((this->is_variable_prefix_null() && wanted_variablegeneration != fparam_output_vg) || + wanted_variablegeneration != assignment_vg) s4o.print(")"); - } return NULL; } @@ -144,14 +259,64 @@ /* B.1.4.2 Multi-element Variables */ /*************************************/ +// SYM_REF2(structured_variable_c, record_variable, field_selector) +void *visit(structured_variable_c *symbol) { + TRACE("structured_variable_c"); + switch (wanted_variablegeneration) { + case complextype_base_vg: + symbol->record_variable->accept(*this); + break; + case complextype_suffix_vg: + symbol->record_variable->accept(*this); + s4o.print("."); + symbol->field_selector->accept(*this); + break; + default: + if (this->is_variable_prefix_null()) { + symbol->record_variable->accept(*this); + s4o.print("."); + symbol->field_selector->accept(*this); + } + else + print_getter(symbol); + break; + } + return NULL; +} + /* subscripted_variable '[' subscript_list ']' */ //SYM_REF2(array_variable_c, subscripted_variable, subscript_list) void *visit(array_variable_c *symbol) { - current_array_type = search_varfb_instance_type->get_type(symbol->subscripted_variable, false); - symbol->subscripted_variable->accept(*this); - if (current_array_type != NULL) { - symbol->subscript_list->accept(*this); - current_array_type = NULL; + switch (wanted_variablegeneration) { + case complextype_base_vg: + symbol->subscripted_variable->accept(*this); + break; + case complextype_suffix_vg: + symbol->subscripted_variable->accept(*this); + + current_array_type = search_varfb_instance_type->get_rawtype(symbol->subscripted_variable); + if (current_array_type == NULL) ERROR; + + s4o.print(".table"); + symbol->subscript_list->accept(*this); + + current_array_type = NULL; + break; + default: + if (this->is_variable_prefix_null()) { + symbol->subscripted_variable->accept(*this); + + current_array_type = search_varfb_instance_type->get_rawtype(symbol->subscripted_variable); + if (current_array_type == NULL) ERROR; + + s4o.print(".table"); + symbol->subscript_list->accept(*this); + + current_array_type = NULL; + } + else + print_getter(symbol); + break; } return NULL; } @@ -170,6 +335,29 @@ return NULL; } +/******************************************/ +/* B 1.4.3 - Declaration & Initialisation */ +/******************************************/ + +/* helper symbol for structure_initialization */ +/* structure_element_initialization_list ',' structure_element_initialization */ +void *visit(structure_element_initialization_list_c *symbol) { + generate_c_structure_initialization_c *structure_initialization = new generate_c_structure_initialization_c(&s4o); + structure_initialization->init_structure_default(this->current_param_type); + structure_initialization->init_structure_values(symbol); + delete structure_initialization; + return NULL; +} + +/* helper symbol for array_initialization */ +/* array_initial_elements_list ',' array_initial_elements */ +void *visit(array_initial_elements_list_c *symbol) { + generate_c_array_initialization_c *array_initialization = new generate_c_array_initialization_c(&s4o); + array_initialization->init_array_size(this->current_param_type); + array_initialization->init_array_values(symbol); + delete array_initialization; + return NULL; +} /***************************************/ /* B.3 - Language ST (Structured Text) */ @@ -404,14 +592,15 @@ symbol_c* function_type_prefix = NULL; symbol_c* function_name = NULL; symbol_c* function_type_suffix = NULL; - std::list param_list; - FUNCTION_PARAM *param; + DECLARE_PARAM_LIST() symbol_c *parameter_assignment_list = NULL; if (NULL != symbol-> formal_param_list) parameter_assignment_list = symbol-> formal_param_list; if (NULL != symbol->nonformal_param_list) parameter_assignment_list = symbol->nonformal_param_list; if (NULL == parameter_assignment_list) ERROR; + function_call_param_iterator_c function_call_param_iterator(symbol); + function_declaration_c *f_decl = function_symtable.find_value(symbol->function_name); if (f_decl == function_symtable.end_value()) { /* The function called is not in the symtable, so we test if it is a @@ -422,57 +611,50 @@ symbol_c *function_return_type = search_expression_type->get_type(symbol); - function_call_param_iterator_c function_call_param_iterator(symbol); - int nb_param = ((list_c *)parameter_assignment_list)->n; - identifier_c en_param_name("EN"); + symbol_c *en_param_name = (symbol_c *)(new identifier_c("EN")); /* Get the value from EN param */ - symbol_c *EN_param_value = function_call_param_iterator.search_f(&en_param_name); + symbol_c *EN_param_value = function_call_param_iterator.search_f(en_param_name); if (EN_param_value == NULL) EN_param_value = (symbol_c*)(new boolean_literal_c((symbol_c*)(new bool_type_name_c()), new boolean_true_c())); else nb_param --; - ADD_PARAM_LIST(EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in) - - identifier_c eno_param_name("ENO"); + ADD_PARAM_LIST(en_param_name, EN_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_in) + + symbol_c *eno_param_name = (symbol_c *)(new identifier_c("ENO")); /* Get the value from ENO param */ - symbol_c *ENO_param_value = function_call_param_iterator.search_f(&eno_param_name); + symbol_c *ENO_param_value = function_call_param_iterator.search_f(eno_param_name); if (ENO_param_value != NULL) nb_param --; - ADD_PARAM_LIST(ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out) - - #define search(x) search_f(x) - #define next() next_nf() -// #define search_constant_type_c::constant_int_type_name search_expression_type_c::integer - #define constant_int_type_name integer + ADD_PARAM_LIST(eno_param_name, ENO_param_value, (symbol_c*)(new bool_type_name_c()), function_param_iterator_c::direction_out) + #include "st_code_gen.c" - #undef constant_int_type_name -// #undef search_constant_type_c::constant_int_type_name - #undef next - #undef search } else { - /* loop through each function parameter, find the value we should pass + function_name = symbol->function_name; + + /* loop through each function parameter, find the value we should pass * to it, and then output the c equivalent... */ function_param_iterator_c fp_iterator(f_decl); - - function_name = symbol->function_name; - identifier_c *param_name; - function_call_param_iterator_c function_call_param_iterator(symbol); for(int i = 1; (param_name = fp_iterator.next()) != NULL; i++) { + symbol_c *param_type = fp_iterator.param_type(); + if (param_type == NULL) ERROR; + function_param_iterator_c::param_direction_t param_direction = fp_iterator.param_direction(); /* Get the value from a foo( = ) style call */ symbol_c *param_value = function_call_param_iterator.search_f(param_name); /* Get the value from a foo() style call */ - if (param_value == NULL) + if (param_value == NULL) { param_value = function_call_param_iterator.next_nf(); + if (param_value != NULL && fp_iterator.is_en_eno_param_implicit()) ERROR; + } if (param_value == NULL && param_direction == function_param_iterator_c::direction_in) { /* No value given for parameter, so we must use the default... */ @@ -480,69 +662,106 @@ param_value = fp_iterator.default_value(); } - symbol_c *param_type = fp_iterator.param_type(); - if (param_type == NULL) ERROR; - - ADD_PARAM_LIST(param_value, param_type, param_direction) + ADD_PARAM_LIST(param_name, param_value, param_type, param_direction) } /* for(...) */ // symbol->parameter_assignment->accept(*this); } + if (function_call_param_iterator.next_nf() != NULL) ERROR; + + bool has_output_params = false; + + if (!this->is_variable_prefix_null()) { + PARAM_LIST_ITERATOR() { + if ((PARAM_DIRECTION == function_param_iterator_c::direction_out || + PARAM_DIRECTION == function_param_iterator_c::direction_inout) && + PARAM_VALUE != NULL) { + if (!has_output_params) { + has_output_params = true; + } + } + } + } + if (function_type_prefix != NULL) { s4o.print("("); function_type_prefix->accept(*this); s4o.print(")"); } - if (function_name != NULL) + if (has_output_params) { + fcall_number++; + s4o.print("__"); + fbname->accept(*this); + s4o.print("_"); function_name->accept(*this); - if (function_type_suffix != NULL) - function_type_suffix->accept(*this); + if (function_type_suffix != NULL) + function_type_suffix->accept(*this); + s4o.print_integer(fcall_number); + } + else { + function_name->accept(*this); + if (function_type_suffix != NULL) + function_type_suffix->accept(*this); + } s4o.print("("); s4o.indent_right(); - std::list::iterator pt; - for(pt = param_list.begin(); pt != param_list.end(); pt++) { - if (pt != param_list.begin()) - s4o.print(",\n"+s4o.indent_spaces); - symbol_c *param_value = pt->param_value; - symbol_c *param_type = pt->param_type; + int nb_param = 0; + PARAM_LIST_ITERATOR() { + symbol_c *param_value = PARAM_VALUE; + current_param_type = PARAM_TYPE; - switch (pt->param_direction) { + switch (PARAM_DIRECTION) { case function_param_iterator_c::direction_in: - if (param_value == NULL) { + if (nb_param > 0) + s4o.print(",\n"+s4o.indent_spaces); + if (param_value == NULL) { /* If not, get the default value of this variable's type */ - param_value = (symbol_c *)param_type->accept(*type_initial_value_c::instance()); + param_value = (symbol_c *)current_param_type->accept(*type_initial_value_c::instance()); } if (param_value == NULL) ERROR; - if (search_base_type.type_is_subrange(param_type)) { - s4o.print("__CHECK_"); - param_type->accept(*this); - s4o.print("("); - } - param_value->accept(*this); - if (search_base_type.type_is_subrange(param_type)) - s4o.print(")"); + s4o.print("("); + if (search_expression_type->is_literal_integer_type(current_param_type)) + search_expression_type->lint_type_name.accept(*this); + else if (search_expression_type->is_literal_real_type(current_param_type)) + search_expression_type->lreal_type_name.accept(*this); + else + current_param_type->accept(*this); + s4o.print(")"); + print_check_function(current_param_type, param_value); + nb_param++; break; case function_param_iterator_c::direction_out: case function_param_iterator_c::direction_inout: - current_param_is_pointer = true; - if (param_value == NULL) { - s4o.print("NULL"); - } else { - param_value->accept(*this); - } - current_param_is_pointer = false; + if (!has_output_params) { + if (nb_param > 0) + s4o.print(",\n"+s4o.indent_spaces); + if (param_value == NULL) + s4o.print("NULL"); + else { + wanted_variablegeneration = fparam_output_vg; + param_value->accept(*this); + wanted_variablegeneration = expression_vg; + } + nb_param++; + } break; case function_param_iterator_c::direction_extref: /* TODO! */ ERROR; break; } /* switch */ - } - + } + if (has_output_params) { + if (nb_param > 0) + s4o.print(",\n"+s4o.indent_spaces); + s4o.print(FB_FUNCTION_PARAM); + } s4o.print(")"); s4o.indent_left(); + CLEAR_PARAM_LIST() + return NULL; } @@ -557,18 +776,16 @@ /* B 3.2.1 Assignment Statements */ /*********************************/ void *visit(assignment_statement_c *symbol) { - symbol_c *left_type = search_varfb_instance_type->get_type(symbol->l_exp, false); + symbol_c *left_type = search_varfb_instance_type->get_rawtype(symbol->l_exp); - symbol->l_exp->accept(*this); - s4o.print(" = "); - if (search_base_type.type_is_subrange(left_type)) { - s4o.print("__CHECK_"); - left_type->accept(*this); - s4o.print("("); - } - symbol->r_exp->accept(*this); - if (search_base_type.type_is_subrange(left_type)) - s4o.print(")"); + if (this->is_variable_prefix_null()) { + symbol->l_exp->accept(*this); + s4o.print(" = "); + print_check_function(left_type, symbol->r_exp); + } + else { + print_setter(symbol->l_exp, left_type, symbol->r_exp); + } return NULL; } @@ -616,19 +833,16 @@ if (param_value != NULL) if ((param_direction == function_param_iterator_c::direction_in) || (param_direction == function_param_iterator_c::direction_inout)) { - print_variable_prefix(); - symbol->fb_name->accept(*this); - s4o.print("."); - param_name->accept(*this); - s4o.print(" = "); - if (search_base_type.type_is_subrange(param_type)) { - s4o.print("__CHECK_"); - param_type->accept(*this); - s4o.print("("); + if (this->is_variable_prefix_null()) { + symbol->fb_name->accept(*this); + s4o.print("."); + param_name->accept(*this); + s4o.print(" = "); + print_check_function(param_type, param_value); } - param_value->accept(*this); - if (search_base_type.type_is_subrange(param_type)) - s4o.print(")"); + else { + print_setter(param_name, param_type, param_value, symbol->fb_name); + } s4o.print(";\n" + s4o.indent_spaces); } } /* for(...) */ @@ -660,22 +874,16 @@ if (param_value != NULL) if ((param_direction == function_param_iterator_c::direction_out) || (param_direction == function_param_iterator_c::direction_inout)) { - symbol_c *param_type = search_varfb_instance_type->get_type(param_value, false); - - s4o.print(";\n"+ s4o.indent_spaces); - param_value->accept(*this); - s4o.print(" = "); - if (search_base_type.type_is_subrange(param_type)) { - s4o.print("__CHECK_"); - param_type->accept(*this); - s4o.print("("); + symbol_c *param_type = search_varfb_instance_type->get_rawtype(param_value); + s4o.print(";\n" + s4o.indent_spaces); + if (this->is_variable_prefix_null()) { + param_value->accept(*this); + s4o.print(" = "); + print_check_function(param_type, param_name, symbol->fb_name); } - print_variable_prefix(); - symbol->fb_name->accept(*this); - s4o.print("."); - param_name->accept(*this); - if (search_base_type.type_is_subrange(param_type)) - s4o.print(")"); + else { + print_setter(param_value, param_type, param_name, NULL, symbol->fb_name); + } } } /* for(...) */