# HG changeset patch # User Mario de Sousa # Date 1328192282 0 # Node ID 866eb35e4e14360e33bb1dd7256702557e468c98 # Parent 6384168a8e95aa4d0a721a6eadf5a83c5c9b087c Fix search_varfb_instance_decl to be able to find variables and FB when only given an identifier. Fix handling of FB calls in stage3. Start handling of function invocations in stage3. diff -r 6384168a8e95 -r 866eb35e4e14 absyntax/absyntax.def --- a/absyntax/absyntax.def Thu Feb 02 10:00:53 2012 +0000 +++ b/absyntax/absyntax.def Thu Feb 02 14:18:02 2012 +0000 @@ -1045,7 +1045,9 @@ /* 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. +/* NOTES: + * The parameter 'called_function_declaration'... + * ...is 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 completely defined by the name of the function being called, * and need to be disambiguated with using the data types of the parameters being passed. @@ -1054,8 +1056,23 @@ * It does not make sense to determine the exact function being called twice (once in stage 3, * and again in stage 4), so stage 3 will store this info 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;) + * The parameter 'candidate_functions'... + * ...is used to pass data between two passes within stage 3 + * (actually between fill_candidate_datatypes_c and narrow_candidate_datatypes_c). + * It is used to store all the functions that may be legally called with the current parameters + * being used in this function invocation. Note that the standard includes some standard functions + * that have the exact same input parameter types, but return different data types. + * In order to determine which of these functions should be called, we first create a list + * 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 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 + * standard functions may be called with a variable number of paramters. Stage 3 will store + * in extensible_param_count the number of parameters being passed to the extensible parameter. + */ +SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector candidate_functions;) /********************/ diff -r 6384168a8e95 -r 866eb35e4e14 absyntax_utils/search_varfb_instance_type.cc --- a/absyntax_utils/search_varfb_instance_type.cc Thu Feb 02 10:00:53 2012 +0000 +++ b/absyntax_utils/search_varfb_instance_type.cc Thu Feb 02 14:18:02 2012 +0000 @@ -141,7 +141,28 @@ - +/*************************/ +/* B.1 - Common elements */ +/*************************/ +/*******************************************/ +/* B 1.1 - Letters, digits and identifiers */ +/*******************************************/ +// SYM_TOKEN(identifier_c) +void *search_varfb_instance_type_c::visit(identifier_c *variable_name) { + /* symbol should be a variable name!! */ + /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */ + current_type_id = search_var_instance_decl.get_decl (variable_name); + current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); + current_basetype_id = search_base_type.get_basetype_id (current_type_id); + + /* What if the variable has not been declared? Then this should not be a compiler error! + * However, currently stage 2 of the compiler already detects when variables have not been delcared, + * so if the variable's declaration is not found, then that means that we have an internal compiler error! + */ + if (NULL == current_type_id) ERROR; + + return NULL; +} @@ -269,13 +290,7 @@ /*********************/ // SYM_REF1(symbolic_variable_c, var_name) void *search_varfb_instance_type_c::visit(symbolic_variable_c *symbol) { - /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */ - current_type_id = search_var_instance_decl.get_decl (symbol->var_name); - current_basetype_decl = search_base_type.get_basetype_decl(current_type_id); - current_basetype_id = search_base_type.get_basetype_id (current_type_id); - - if (NULL == current_type_id) ERROR; /* why should this be an error? what if the variable has not been declared? */ - + symbol->var_name->accept(*this); return NULL; } diff -r 6384168a8e95 -r 866eb35e4e14 absyntax_utils/search_varfb_instance_type.hh --- a/absyntax_utils/search_varfb_instance_type.hh Thu Feb 02 10:00:53 2012 +0000 +++ b/absyntax_utils/search_varfb_instance_type.hh Thu Feb 02 14:18:02 2012 +0000 @@ -134,13 +134,14 @@ private: - /* We override the base class' visitor to identifier_c. - * This is so because the base class does not consider a function block - * to be a type, unlike this class that allows a variable instance - * of a function block type... - */ -// void *visit(identifier_c *type_name); - + /*************************/ + /* B.1 - Common elements */ + /*************************/ + /*******************************************/ + /* B 1.1 - Letters, digits and identifiers */ + /*******************************************/ + void *visit(identifier_c *variable_name); + /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ diff -r 6384168a8e95 -r 866eb35e4e14 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Thu Feb 02 10:00:53 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Thu Feb 02 14:18:02 2012 +0000 @@ -63,7 +63,8 @@ return NULL; } -void fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) { +/* 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; identifier_c *param_name; function_param_iterator_c fp_iterator(f_decl); @@ -71,37 +72,34 @@ int extensible_parameter_highest_index = -1; unsigned int i; - /* reset error counter */ - if (error_count != NULL) *error_count = 0; /* Iterating through the non-formal parameters of the function call */ while((call_param_value = fcp_iterator.next_nf()) != NULL) { - /* Obtaining the type of the value being passed in the function call */ - std::vector &call_param_types = call_param_value->candidate_datatypes; /* Iterate to the next parameter of the function being called. * Get the name of that parameter, and ignore if EN or ENO. */ do { param_name = fp_iterator.next(); /* If there is no other parameter declared, then we are passing too many parameters... */ - if(param_name == NULL) { - (*error_count)++; - return; - } + if(param_name == NULL) return false; } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0)); /* 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 do not have the same type */ - if(is_type_equal(param_type, call_param_types[i])) { - break; - } - } - if (i >= call_param_types.size()) (*error_count)++; - } -} - -void fill_candidate_datatypes_c::match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) { + + /* 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_value->candidate_datatypes.size(); i++) { + /* If found (correct data type being passed), then stop the search */ + if(is_type_equal(param_type, call_param_value->candidate_datatypes[i])) break; + } + /* if we reached the end of the loop, and no compatible type found, then return false */ + if (i >= call_param_value->candidate_datatypes.size()) return false; + } + /* call is compatible! */ + 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; symbol_c *verify_duplicate_param; identifier_c *param_name; @@ -111,9 +109,6 @@ identifier_c *extensible_parameter_name; unsigned int i; - /* reset error counter */ - if (error_count != NULL) *error_count = 0; - /* Iterating through the formal parameters of the function call */ while((call_param_name = fcp_iterator.next_f()) != NULL) { @@ -125,7 +120,7 @@ /* Checking if there are duplicated parameter values */ verify_duplicate_param = fcp_iterator.search_f(call_param_name); if(verify_duplicate_param != call_param_value) - (*error_count)++; + return false; /* Obtaining the type of the value being passed in the function call */ std::vector &call_param_types = call_param_value->candidate_datatypes; @@ -134,7 +129,7 @@ /* Find the corresponding parameter in function declaration */ param_name = fp_iterator.search(call_param_name); if(param_name == NULL) { - (*error_count)++; + return false; } else { /* Get the parameter type */ param_type = base_type(fp_iterator.param_type()); @@ -143,10 +138,11 @@ if(is_type_equal(param_type, call_param_types[i])) break; } - if (i >= call_param_types.size()) (*error_count)++; - } - } - + if (i >= call_param_types.size()) + return false;; + } + } + return true; } /* a helper function... */ @@ -1667,7 +1663,7 @@ function_declaration_c *f_decl; list_c *parameter_list; list_c *parameter_candidate_datatypes; - symbol_c *parameter_type; + symbol_c *returned_parameter_type; 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 the name of the function being called is not found in the function symbol table, then this is an invalid call */ @@ -1683,21 +1679,25 @@ if (debug) std::cout << "function()\n"; parameter_list->accept(*this); for(; lower != upper; lower++) { - int error_count = 0; + 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) match_nonformal_call(symbol, f_decl, &error_count); - if (NULL != symbol-> formal_param_list) match_formal_call(symbol, f_decl, &error_count); - if (0 == error_count) { - /* Add basetype matching function only if not present */ + if (NULL != symbol->nonformal_param_list) compatible=match_nonformal_call(symbol, f_decl); + if (NULL != symbol-> formal_param_list) compatible= match_formal_call(symbol, f_decl); + if (compatible) { + /* Add the data type returned by the called functions. + * However, only do this if this data type is not already present in the candidate_datatypes list_c + */ unsigned int k; - parameter_type = base_type(f_decl->type_name); + returned_parameter_type = base_type(f_decl->type_name); for(k = 0; k < symbol->candidate_datatypes.size(); k++) { - if (is_type_equal(parameter_type, symbol->candidate_datatypes[k])) + if (is_type_equal(returned_parameter_type, symbol->candidate_datatypes[k])) break; } - if (k >= symbol->candidate_datatypes.size()) - symbol->candidate_datatypes.push_back(parameter_type); + if (k >= symbol->candidate_datatypes.size()) { + symbol->candidate_datatypes.push_back(returned_parameter_type); + symbol->candidate_functions.push_back(f_decl); + } } } if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n"; @@ -1738,11 +1738,18 @@ /* B 3.2.2 Subprogram Control Statements */ /*****************************************/ void *fill_candidate_datatypes_c::visit(fb_invocation_c *symbol) { + bool compatible = false; symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); - + if (NULL == fb_decl) ERROR; - if (symbol-> formal_param_list != NULL) match_formal_call(symbol, fb_decl); - if (symbol->nonformal_param_list != NULL) match_nonformal_call(symbol, fb_decl); + if (symbol-> formal_param_list != NULL) { + symbol->formal_param_list->accept(*this); + compatible = match_formal_call(symbol, fb_decl); + } + if (symbol->nonformal_param_list != NULL) { + symbol->nonformal_param_list->accept(*this); + compatible = match_nonformal_call(symbol, fb_decl); + } if (debug) std::cout << "FB [] ==> " << symbol->candidate_datatypes.size() << " result.\n"; return NULL; } diff -r 6384168a8e95 -r 866eb35e4e14 stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Thu Feb 02 10:00:53 2012 +0000 +++ b/stage3/fill_candidate_datatypes.hh Thu Feb 02 14:18:02 2012 +0000 @@ -85,8 +85,8 @@ virtual ~fill_candidate_datatypes_c(void); /* Match a function declaration with a function call through their parameters.*/ - void match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL); - void match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL); + bool match_nonformal_call(symbol_c *f_call, symbol_c *f_decl); + bool match_formal_call (symbol_c *f_call, symbol_c *f_decl); void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol); void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);