# HG changeset patch # User Mario de Sousa # Date 1328199619 0 # Node ID 840cb1e1e177f6158d1474524adcbd61002b512c # Parent 866eb35e4e14360e33bb1dd7256702557e468c98 Add support in stage 3 for checking function invocations in ST. diff -r 866eb35e4e14 -r 840cb1e1e177 absyntax/absyntax.def --- a/absyntax/absyntax.def Thu Feb 02 14:18:02 2012 +0000 +++ b/absyntax/absyntax.def Thu Feb 02 16:20:19 2012 +0000 @@ -1066,6 +1066,8 @@ * of all possible functions, and then narrow down the list (hopefully down to 1 function) * once we know the data type that the function invocation must return (this will take into * account the expression in which the function invocation is inserted/occurs). + * The 'called_function_declaration' will eventually be set (in stage 3) to one of + * the functions in the 'candidate_functions' list! * The parameter 'extensible_param_count'... * ...is used to pass data between the stage 3 and stage 4. * The IEC 61131-3 standard allows for extensible standard functions. This means that some diff -r 866eb35e4e14 -r 840cb1e1e177 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Thu Feb 02 14:18:02 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Thu Feb 02 16:20:19 2012 +0000 @@ -63,6 +63,9 @@ return NULL; } + + + /* returns true if compatible function/FB invocation, otherwise returns false */ bool fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { symbol_c *call_param_value, *param_type; @@ -98,6 +101,8 @@ return true; } + + /* returns true if compatible function/FB invocation, otherwise returns false */ bool fill_candidate_datatypes_c::match_formal_call(symbol_c *f_call, symbol_c *f_decl) { symbol_c *call_param_value, *call_param_name, *param_type; @@ -128,23 +133,25 @@ /* Find the corresponding parameter in function declaration */ param_name = fp_iterator.search(call_param_name); - if(param_name == NULL) { - return false; - } else { - /* Get the parameter type */ - param_type = base_type(fp_iterator.param_type()); - for (i = 0; i < call_param_types.size(); i++) { - /* If the declared parameter and the parameter from the function call have the same type */ - if(is_type_equal(param_type, call_param_types[i])) - break; - } - if (i >= call_param_types.size()) - return false;; - } - } + if(param_name == NULL) return false; + /* Get the parameter type */ + param_type = base_type(fp_iterator.param_type()); + /* check whether one of the candidate_data_types of the value being passed is the same as the param_type */ + for (i = 0; i < call_param_types.size(); i++) { + /* If found (correct data type being passed), then stop the search */ + if(is_type_equal(param_type, call_param_types[i])) break; + } + /* if we reached the end of the loop, and no compatible type found, then return false */ + if (i >= call_param_types.size()) return false; + + } + /* call is compatible! */ return true; } + + + /* a helper function... */ symbol_c *fill_candidate_datatypes_c::base_type(symbol_c *symbol) { /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used @@ -1680,6 +1687,7 @@ parameter_list->accept(*this); for(; lower != upper; lower++) { bool compatible = false; + f_decl = function_symtable.get_value(lower); /* Check if function declaration in symbol_table is compatible with parameters */ if (NULL != symbol->nonformal_param_list) compatible=match_nonformal_call(symbol, f_decl); @@ -1704,6 +1712,8 @@ return NULL; } + + /********************/ /* B 3.2 Statements */ /********************/ diff -r 866eb35e4e14 -r 840cb1e1e177 stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Thu Feb 02 14:18:02 2012 +0000 +++ b/stage3/fill_candidate_datatypes.hh Thu Feb 02 16:20:19 2012 +0000 @@ -85,6 +85,7 @@ virtual ~fill_candidate_datatypes_c(void); /* Match a function declaration with a function call through their parameters.*/ + /* returns true if compatible function/FB invocation, otherwise returns false */ bool match_nonformal_call(symbol_c *f_call, symbol_c *f_decl); bool match_formal_call (symbol_c *f_call, symbol_c *f_decl); diff -r 866eb35e4e14 -r 840cb1e1e177 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Thu Feb 02 14:18:02 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.cc Thu Feb 02 16:20:19 2012 +0000 @@ -65,15 +65,15 @@ return false; } -void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl) { +void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count) { symbol_c *call_param_value, *param_type; identifier_c *param_name; function_param_iterator_c fp_iterator(f_decl); function_call_param_iterator_c fcp_iterator(f_call); int extensible_parameter_highest_index = -1; - identifier_c *extensible_parameter_name; unsigned int i; + if (NULL != ext_parm_count) *ext_parm_count = -1; /* Iterating through the non-formal parameters of the function call */ while((call_param_value = fcp_iterator.next_nf()) != NULL) { @@ -84,28 +84,33 @@ do { param_name = fp_iterator.next(); /* If there is no other parameter declared, then we are passing too many parameters... */ - if(param_name == NULL) { - return; - } + /* This error should have been caught in fill_candidate_datatypes_c */ + if(param_name == NULL) ERROR; } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); - /* Get the parameter type */ + /* Set the desired datatype for this parameter, and call it recursively. */ call_param_value->datatype = base_type(fp_iterator.param_type()); call_param_value->accept(*this); - if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { + + if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) extensible_parameter_highest_index = fp_iterator.extensible_param_index(); - extensible_parameter_name = param_name; - } - } - int extensible_param_count = -1; - if (extensible_parameter_highest_index >=0) /* if call to extensible function */ - extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); - function_invocation_c *function_invocation = dynamic_cast(f_call); - if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; - -} - -void narrow_candidate_datatypes_c::narrow_formal_call(symbol_c *f_call, symbol_c *f_decl) { + } + /* call is compatible! */ + + /* In the case of a call to an extensible function, we store the highest index + * of the extensible parameters this particular call uses, in the symbol_c object + * of the function call itself! + * In calls to non-extensible functions, this value will be set to -1. + * This information is later used in stage4 to correctly generate the + * output code. + */ + if ((NULL != ext_parm_count) && (extensible_parameter_highest_index >=0) /* if call to extensible function */) + *ext_parm_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); +} + + + +void narrow_candidate_datatypes_c::narrow_formal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count) { symbol_c *call_param_value, *call_param_name, *param_type; symbol_c *verify_duplicate_param; identifier_c *param_name; @@ -115,6 +120,7 @@ identifier_c *extensible_parameter_name; unsigned int i; + if (NULL != ext_parm_count) *ext_parm_count = -1; /* Iterating through the formal parameters of the function call */ while((call_param_name = fcp_iterator.next_f()) != NULL) { @@ -127,28 +133,27 @@ /* Find the corresponding parameter in function declaration */ param_name = fp_iterator.search(call_param_name); - /* Get the parameter type */ + /* Set the desired datatype for this parameter, and call it recursively. */ call_param_name->datatype = base_type(fp_iterator.param_type()); call_param_name->accept(*this); - /* the first parameter (il_def_variable) is correct */ - if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) { - extensible_parameter_highest_index = fp_iterator.extensible_param_index(); - } - } - /* The function call may not have any errors! */ - /* In the case of a call to an extensible function, we store the highest index + + if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) + extensible_parameter_highest_index = fp_iterator.extensible_param_index(); + } + /* call is compatible! */ + + /* In the case of a call to an extensible function, we store the highest index * of the extensible parameters this particular call uses, in the symbol_c object * of the function call itself! * In calls to non-extensible functions, this value will be set to -1. * This information is later used in stage4 to correctly generate the * output code. */ - int extensible_param_count = -1; - if (extensible_parameter_highest_index >=0) /* if call to extensible function */ - extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); - function_invocation_c *function_invocation = dynamic_cast(f_call); - if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count; -} + if ((NULL != ext_parm_count) && (extensible_parameter_highest_index >=0) /* if call to extensible function */) + *ext_parm_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index(); +} + + /* a helper function... */ symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) { @@ -986,33 +991,21 @@ void *narrow_candidate_datatypes_c::visit(function_invocation_c *symbol) { - function_declaration_c *f_decl; - list_c *parameter_list; - list_c *parameter_candidate_datatypes; - function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); - function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); - - if (NULL != symbol->formal_param_list) - parameter_list = (list_c *)symbol->formal_param_list; - else if (NULL != symbol->nonformal_param_list) - parameter_list = (list_c *)symbol->nonformal_param_list; - else ERROR; - for(; lower != upper; lower++) { - f_decl = function_symtable.get_value(lower); - symbol_c * return_type = base_type(f_decl->type_name); - if (return_type && typeid(*symbol->datatype) != typeid(*return_type)) - continue; - /* We set which function declaration it'll use in STAGE4 */ - symbol->called_function_declaration = f_decl; - /* Check if function declaration in symbol_table is compatible with parameters */ - if (NULL != symbol->nonformal_param_list) - /* nonformal parameter function call */ - narrow_nonformal_call(symbol, f_decl); - else - /* formal parameter function call */ - narrow_formal_call (symbol, f_decl); - break; - } + int ext_parm_count; + + /* set the called_function_declaration taking into account the datatype that we need to return */ + symbol->called_function_declaration = NULL; + for(unsigned int i = 0; i < symbol->candidate_datatypes.size(); i++) { + if (is_type_equal(symbol->candidate_datatypes[i], symbol->datatype)) { + symbol->called_function_declaration = symbol->candidate_functions[i]; + break; + } + } + if (NULL == symbol->called_function_declaration) ERROR; + + if (NULL != symbol->nonformal_param_list) narrow_nonformal_call(symbol, symbol->called_function_declaration, &ext_parm_count); + if (NULL != symbol-> formal_param_list) narrow_formal_call(symbol, symbol->called_function_declaration, &ext_parm_count); + symbol->extensible_param_count = ext_parm_count; return NULL; } diff -r 866eb35e4e14 -r 840cb1e1e177 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Thu Feb 02 14:18:02 2012 +0000 +++ b/stage3/narrow_candidate_datatypes.hh Thu Feb 02 16:20:19 2012 +0000 @@ -50,8 +50,8 @@ public: narrow_candidate_datatypes_c(symbol_c *ignore); virtual ~narrow_candidate_datatypes_c(void); - void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl); - void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl); + void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); + void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl, int *ext_parm_count = NULL); symbol_c *base_type(symbol_c *symbol);