Add support in stage 3 for checking function invocations in ST.
--- 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
--- 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 */
/********************/
--- 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);
--- 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<function_invocation_c *>(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<function_invocation_c *>(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;
}
--- 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);