# HG changeset patch # User laurent # Date 1328224192 -3600 # Node ID 55b074ea72556f331ef22535c4f0b01d15685b4f # Parent f1f3facc59e7405e9812ce8c41b1898f70efffba Fix bug with functions like LEN and TRUNC that have overloaded return type for same inputs type diff -r f1f3facc59e7 -r 55b074ea7255 absyntax/absyntax.def --- a/absyntax/absyntax.def Thu Feb 02 00:34:04 2012 +0100 +++ b/absyntax/absyntax.def Fri Feb 03 00:09:52 2012 +0100 @@ -920,10 +920,11 @@ SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand) /* | function_name [il_operand_list] */ -/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. +/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass + * data between the stage 3 and stage 4. * See the comment above function_invocation_c for more details */ -SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) +SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;) /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ @@ -942,10 +943,11 @@ /* | function_name '(' eol_list [il_param_list] ')' */ -/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. +/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass + * data between the stage 3 and stage 4. * See the comment above function_invocation_c for more details */ -SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) +SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;) /* | il_operand_list ',' il_operand */ SYM_LIST(il_operand_list_c) @@ -1045,7 +1047,8 @@ /* formal_param_list -> may be NULL ! */ /* nonformal_param_list -> may be NULL ! */ -/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. +/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass + * data between the stage 3 and stage 4. * The IEC 61131-3 standard allows for overloaded standard functions. This means that some * function calls are not compeletely defined by the name of the function being called, * and need to be disambiguated with using the data types of the parameters being passed. @@ -1055,7 +1058,7 @@ * and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration * for stage 4 to use it later on. */ -SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;) +SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;) /********************/ diff -r f1f3facc59e7 -r 55b074ea7255 absyntax_utils/search_constant_type.cc --- a/absyntax_utils/search_constant_type.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/absyntax_utils/search_constant_type.cc Fri Feb 03 00:09:52 2012 +0100 @@ -168,3 +168,4 @@ /* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */ /* It should then move to search_expression_type_c */ integer_c search_constant_type_c::integer("1"); +real_c search_constant_type_c::real("1.0"); diff -r f1f3facc59e7 -r 55b074ea7255 absyntax_utils/search_constant_type.hh --- a/absyntax_utils/search_constant_type.hh Thu Feb 02 00:34:04 2012 +0100 +++ b/absyntax_utils/search_constant_type.hh Fri Feb 03 00:09:52 2012 +0100 @@ -79,6 +79,7 @@ /* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */ static integer_c integer; + static real_c real; /******************************************************/ /* Extensions to the base standard as defined in */ diff -r f1f3facc59e7 -r 55b074ea7255 stage3/visit_expression_type.cc --- a/stage3/visit_expression_type.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/stage3/visit_expression_type.cc Fri Feb 03 00:09:52 2012 +0100 @@ -566,6 +566,31 @@ return common_type__(first_type, second_type); } +symbol_c *visit_expression_type_c::common_literal(symbol_c *first_type, symbol_c *second_type) { + printf("common_literal: %d == %d, %d == %d, %d == %d\n", + (int)is_ANY_INT_compatible(first_type), + (int)is_ANY_INT_compatible(second_type), + (int)is_ANY_REAL_compatible(first_type), + (int)is_ANY_REAL_compatible(second_type), + (int)is_ANY_BIT_compatible(first_type), + (int)is_ANY_BIT_compatible(second_type)); + if ((is_ANY_INT_compatible(first_type) && is_ANY_INT_compatible(second_type)) || + (is_ANY_BIT_compatible(first_type) && is_ANY_BIT_compatible(second_type))) + return &search_constant_type_c::integer; + else if (is_ANY_REAL_compatible(first_type) && is_ANY_REAL_compatible(second_type)) + return &search_constant_type_c::real; + return NULL; +} + +symbol_c *visit_expression_type_c::overloaded_return_type(symbol_c *type) { + if (is_ANY_INT_compatible(type)) + return &search_constant_type_c::ulint_type_name; + else if (is_ANY_REAL_compatible(type)) + return &search_constant_type_c::lreal_type_name; + else if (is_ANY_BIT_compatible(type)) + return &search_constant_type_c::lword_type_name; + return NULL; +} /* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type * such as: @@ -1042,6 +1067,8 @@ return NULL; symbol_c *return_data_type = NULL; + symbol_c* fdecl_return_type; + symbol->called_function_declaration = NULL; /* First find the declaration of the function being called! */ function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); @@ -1067,25 +1094,40 @@ * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!) * (ii) we have a call to an overloaded function, with no errors! */ + + fdecl_return_type = base_type(f_decl->type_name); + + if (symbol->called_function_declaration == NULL) { + /* Store the pointer to the declaration of the function being called. + * This data will be used by stage 4 to call the correct function. + * Mostly needed to disambiguate overloaded functions... + * See comments in absyntax.def for more details + */ + symbol->called_function_declaration = f_decl; + symbol->overloaded_return_type = NULL; + + /* determine the base data type returned by the function being called... */ + return_data_type = fdecl_return_type; + } + else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){ + if (symbol->overloaded_return_type == NULL) + symbol->overloaded_return_type = overloaded_return_type(return_data_type); + return_data_type = common_literal(return_data_type, fdecl_return_type); + } - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - /* determine the base data type returned by the function being called... */ - return_data_type = base_type(f_decl->type_name); - /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */ if (NULL == return_data_type) ERROR; - /* set the new data type of the default variable for the following verifications... */ - il_default_variable_type = return_data_type; - return NULL; } } - /* No compatible function was found for this function call */ - STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); + if (NULL == return_data_type) { + /* No compatible function was found for this function call */ + STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); + } + else { + /* set the new data type of the default variable for the following verifications... */ + il_default_variable_type = return_data_type; + } + return NULL; } @@ -1206,6 +1248,9 @@ return NULL; symbol_c *return_data_type = NULL; + symbol_c* fdecl_return_type; + symbol->called_function_declaration = NULL; + function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); @@ -1235,25 +1280,42 @@ * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!) * (ii) we have a call to an overloaded function, with no errors! */ - - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - /* determine the base data type returned by the function being called... */ - return_data_type = base_type(f_decl->type_name); + + fdecl_return_type = base_type(f_decl->type_name); + + if (symbol->called_function_declaration == NULL) { + /* Store the pointer to the declaration of the function being called. + * This data will be used by stage 4 to call the correct function. + * Mostly needed to disambiguate overloaded functions... + * See comments in absyntax.def for more details + */ + symbol->called_function_declaration = f_decl; + symbol->overloaded_return_type = NULL; + + /* determine the base data type returned by the function being called... */ + return_data_type = fdecl_return_type; + } + else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){ + if (symbol->overloaded_return_type == NULL) + symbol->overloaded_return_type = overloaded_return_type(return_data_type); + return_data_type = common_literal(return_data_type, fdecl_return_type); + } + /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */ if (NULL == return_data_type) ERROR; - /* the data type of the data returned by the function, and stored in the il default variable... */ - il_default_variable_type = return_data_type; - return NULL; - } + + } } - /* No compatible function was found for this function call */ - STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); + if (NULL == return_data_type) { + /* No compatible function was found for this function call */ + STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); + } + else { + /* the data type of the data returned by the function, and stored in the il default variable... */ + il_default_variable_type = return_data_type; + } + return NULL; } @@ -2007,6 +2069,10 @@ function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); if (lower == function_symtable.end()) ERROR; + symbol_c* return_data_type; + symbol_c* fdecl_return_type; + symbol->called_function_declaration = NULL; + function_symtable_t::iterator second = lower; second++; if (second == upper) { @@ -2024,6 +2090,7 @@ * See comments in absyntax.def for more details */ symbol->called_function_declaration = f_decl; + symbol->overloaded_return_type = NULL; return base_type(f_decl->type_name); } @@ -2036,16 +2103,34 @@ if (symbol-> formal_param_list != NULL) check_formal_call (symbol, f_decl, &error_count); if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count); if (0 == error_count) { - /* Store the pointer to the declaration of the function being called. - * This data will be used by stage 4 to call the correct function. - * Mostly needed to disambiguate overloaded functions... - * See comments in absyntax.def for more details - */ - symbol->called_function_declaration = f_decl; - return base_type(f_decl->type_name); + + fdecl_return_type = base_type(f_decl->type_name); + + if (symbol->called_function_declaration == NULL) { + /* Store the pointer to the declaration of the function being called. + * This data will be used by stage 4 to call the correct function. + * Mostly needed to disambiguate overloaded functions... + * See comments in absyntax.def for more details + */ + symbol->called_function_declaration = f_decl; + symbol->overloaded_return_type = NULL; + + /* determine the base data type returned by the function being called... */ + return_data_type = fdecl_return_type; + } + else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){ + if (symbol->overloaded_return_type == NULL) + symbol->overloaded_return_type = overloaded_return_type(return_data_type); + return_data_type = common_literal(return_data_type, fdecl_return_type); + } + + if (NULL == return_data_type) ERROR; } } + if (return_data_type != NULL) + return return_data_type; + /* No compatible function was found for this function call */ STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type."); return NULL; diff -r f1f3facc59e7 -r 55b074ea7255 stage3/visit_expression_type.hh --- a/stage3/visit_expression_type.hh Thu Feb 02 00:34:04 2012 +0100 +++ b/stage3/visit_expression_type.hh Fri Feb 03 00:09:52 2012 +0100 @@ -156,6 +156,10 @@ * if no common data type is found. */ symbol_c *common_type(symbol_c *first_type, symbol_c *second_type); + + symbol_c *common_literal(symbol_c *first_type, symbol_c *second_type); + symbol_c *overloaded_return_type(symbol_c *type); + /* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type * such as: * var_type value_type diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/stage4/generate_c/generate_c.cc Fri Feb 03 00:09:52 2012 +0100 @@ -182,6 +182,7 @@ class print_function_parameter_data_types_c: public generate_c_base_c { private: symbol_c *current_type; + symbol_c *return_type; bool_type_name_c tmp_bool; void print_list(symbol_c *var_list, symbol_c *data_type) { @@ -197,9 +198,11 @@ } 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, symbol_c* return_type): + generate_c_base_c(s4o_ptr) { + current_type = NULL; + this->return_type = return_type; + } /**************************************/ /* B.1.5 - Program organization units */ @@ -210,7 +213,11 @@ /* 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) { - symbol->type_name->accept(*this); /* return type */ + /* return type */ + if (this->return_type == NULL) + symbol->type_name->accept(*this); + else + this->return_type->accept(*this); symbol->var_declarations_list->accept(*this); return NULL; } diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_il.cc --- a/stage4/generate_c/generate_c_il.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/stage4/generate_c/generate_c_il.cc Fri Feb 03 00:09:52 2012 +0100 @@ -962,7 +962,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } s4o.print_integer(fcall_number); @@ -973,7 +973,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } } @@ -1370,7 +1370,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } s4o.print_integer(fcall_number); @@ -1381,7 +1381,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } } diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_inlinefcall.cc --- a/stage4/generate_c/generate_c_inlinefcall.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/stage4/generate_c/generate_c_inlinefcall.cc Fri Feb 03 00:09:52 2012 +0100 @@ -169,7 +169,7 @@ if (f_decl != NULL) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, function_type_prefix); f_decl->accept(overloaded_func_suf); } if (function_type_suffix) { @@ -222,7 +222,7 @@ if (f_decl != NULL) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, function_type_prefix); f_decl->accept(overloaded_func_suf); } @@ -492,7 +492,10 @@ /* determine the base data type returned by the function being called... */ search_base_type_c search_base_type; - function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + if (symbol->overloaded_return_type == NULL) + function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + else + function_type_prefix = symbol->overloaded_return_type; function_name = symbol->function_name; @@ -675,7 +678,10 @@ /* determine the base data type returned by the function being called... */ search_base_type_c search_base_type; - function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + if (symbol->overloaded_return_type == NULL) + function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + else + function_type_prefix = symbol->overloaded_return_type; if (NULL == function_type_prefix) ERROR; function_name = symbol->function_name; @@ -1044,7 +1050,10 @@ /* determine the base data type returned by the function being called... */ search_base_type_c search_base_type; - function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + if (symbol->overloaded_return_type == NULL) + function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type); + else + function_type_prefix = symbol->overloaded_return_type; if (NULL == function_type_prefix) ERROR; /* loop through each function parameter, find the value we should pass diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Thu Feb 02 00:34:04 2012 +0100 +++ b/stage4/generate_c/generate_c_st.cc Fri Feb 03 00:09:52 2012 +0100 @@ -777,7 +777,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } s4o.print_integer(fcall_number); @@ -787,7 +787,7 @@ if (fdecl_mutiplicity == 2) { /* function being called is overloaded! */ s4o.print("__"); - print_function_parameter_data_types_c overloaded_func_suf(&s4o); + print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type); f_decl->accept(overloaded_func_suf); } }