# HG changeset patch # User mjsousa # Date 1413750658 -3600 # Node ID 31e3b3f2eff162ccbb21a91619a3486cf16e224b # Parent 887e7d90445a2e834018e8111a0cac5d7f343705 Do the full fill_candidate/narrow_datatype algorithm for all fields of a structured variable in the fill_candidate_datatypes_c Allows us to remove temporary code from the search_varfb_decl_c diff -r 887e7d90445a -r 31e3b3f2eff1 absyntax/absyntax.hh --- a/absyntax/absyntax.hh Sun Oct 19 11:53:36 2014 +0100 +++ b/absyntax/absyntax.hh Sun Oct 19 21:30:58 2014 +0100 @@ -136,6 +136,8 @@ symbol_c *datatype; /* The POU in which the symbolic variable (or structured variable, or array variable, or located variable, - any more?) * was declared. This will point to a Configuration, Resource, Program, FB, or Function. + * This is set in stage 3 by the datatype analyser algorithm (fill/narrow) for the symbols: + * symbolic_variable_c, array_variable_c, structured_variable_c */ symbol_c *scope; diff -r 887e7d90445a -r 31e3b3f2eff1 absyntax_utils/get_datatype_info.cc --- a/absyntax_utils/get_datatype_info.cc Sun Oct 19 11:53:36 2014 +0100 +++ b/absyntax_utils/get_datatype_info.cc Sun Oct 19 21:30:58 2014 +0100 @@ -62,7 +62,12 @@ /**********************************************************/ /**********************************************************/ + +/****************************************************************************************************/ +/****************************************************************************************************/ /* Return the identifier (name) of a datatype, typically declared in a TYPE .. END_TYPE declaration */ +/****************************************************************************************************/ +/****************************************************************************************************/ class get_datatype_id_c: null_visitor_c { private: static get_datatype_id_c *singleton; @@ -157,9 +162,13 @@ -/***********************************************************************/ -/***********************************************************************/ - + + +/**************************************************/ +/**************************************************/ +/* transform elementary data type class to string */ +/**************************************************/ +/**************************************************/ /* A small helper class, to transform elementary data type to string. * this allows us to generate more relevant error messages... @@ -273,6 +282,115 @@ +/*********************************************************/ +/*********************************************************/ +/* get the datatype of a field inside a struct data type */ +/*********************************************************/ +/*********************************************************/ + +class get_struct_info_c : null_visitor_c { + private: + symbol_c *current_field; + /* singleton class! */ + static get_struct_info_c *singleton; + + public: + get_struct_info_c(void) {current_field = NULL;} + + static symbol_c *get_field_type_id(symbol_c *struct_type, symbol_c *field_name) { + if (NULL == singleton) singleton = new get_struct_info_c; + if (NULL == singleton) ERROR; + singleton->current_field = field_name; + return (symbol_c *)struct_type->accept(*singleton); + } + + + private: + /*************************/ + /* B.1 - Common elements */ + /*************************/ + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + /* structure_type_name ':' structure_specification */ + /* NOTE: this is only used inside a TYPE ... END_TYPE declaration. It is never used directly when declaring a new variable! */ + /* NOTE: structure_specification will point to either initialized_structure_c OR structure_element_declaration_list_c */ + void *visit(structure_type_declaration_c *symbol) {return symbol->structure_specification->accept(*this);} + + /* structure_type_name ASSIGN structure_initialization */ + /* structure_initialization may be NULL ! */ + // SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization) + /* NOTE: only the initialized structure is never used when declaring a new variable instance */ + void *visit(initialized_structure_c *symbol) {return symbol->structure_type_name->accept(*this);} + + /* helper symbol for structure_declaration */ + /* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */ + /* structure_element_declaration_list structure_element_declaration ';' */ + void *visit(structure_element_declaration_list_c *symbol) { + /* now search the structure declaration */ + for(int i = 0; i < symbol->n; i++) { + void *tmp = symbol->elements[i]->accept(*this); + if (NULL != tmp) return tmp; + } + return NULL; // not found!! + } + + /* structure_element_name ':' spec_init */ + void *visit(structure_element_declaration_c *symbol) { + if (compare_identifiers(symbol->structure_element_name, current_field) == 0) + return symbol->spec_init; /* found the type of the element we were looking for! */ + return NULL; /* not the element we are looking for! */ + } + + + /* helper symbol for structure_initialization */ + /* structure_initialization: '(' structure_element_initialization_list ')' */ + /* structure_element_initialization_list ',' structure_element_initialization */ + void *visit(structure_element_initialization_list_c *symbol) {ERROR; return NULL;} /* should never get called... */ + /* structure_element_name ASSIGN value */ + void *visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */ + + + /**************************************/ + /* B.1.5 - Program organization units */ + /**************************************/ + /*****************************/ + /* B 1.5.2 - Function Blocks */ + /*****************************/ + /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ + // SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused) + void *visit(function_block_declaration_c *symbol) { + /* now search the function block declaration for the variable... */ + search_var_instance_decl_c search_decl(symbol); + return search_decl.get_decl(current_field); + } + + /*********************************************/ + /* B.1.6 Sequential function chart elements */ + /*********************************************/ + /* INITIAL_STEP step_name ':' action_association_list END_STEP */ + // SYM_REF2(initial_step_c, step_name, action_association_list) + void *visit(initial_step_c *symbol) { + identifier_c T("T"); identifier_c X("X"); + /* Hard code the datatypes of the implicit variables Stepname.X and Stepname.T */ + if (compare_identifiers(&T, current_field) == 0) return &get_datatype_info_c::time_type_name; + if (compare_identifiers(&X, current_field) == 0) return &get_datatype_info_c::bool_type_name; + return NULL; + } + + /* STEP step_name ':' action_association_list END_STEP */ + // SYM_REF2(step_c, step_name, action_association_list) + /* The code here should be identicial to the code in the visit(initial_step_c *) visitor! So we simply call the other visitor! */ + void *visit(step_c *symbol) {initial_step_c initial_step(NULL, NULL); return initial_step.accept(*this);} + +}; // get_struct_info_c + +get_struct_info_c *get_struct_info_c::singleton = NULL; + + + + + /**********************************************************/ /**********************************************************/ /**********************************************************/ @@ -295,6 +413,10 @@ } +symbol_c *get_datatype_info_c::get_struct_field_type_id(symbol_c *struct_datatype, symbol_c *struct_fieldname) { + return get_struct_info_c::get_field_type_id(struct_datatype, struct_fieldname); +} + /* Returns true if both datatypes are equivalent (not necessarily equal!). * WARNING: May return true even though the datatypes are not the same/identicial!!! * This occurs when at least one of the datatypes is of a generic diff -r 887e7d90445a -r 31e3b3f2eff1 absyntax_utils/get_datatype_info.hh --- a/absyntax_utils/get_datatype_info.hh Sun Oct 19 11:53:36 2014 +0100 +++ b/absyntax_utils/get_datatype_info.hh Sun Oct 19 21:30:58 2014 +0100 @@ -60,6 +60,7 @@ static symbol_c *get_id (symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! Does not work for elementary datatypes!*/ static const char *get_id_str(symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! */ + static symbol_c *get_struct_field_type_id (symbol_c *struct_datatype, symbol_c *struct_fieldname); static symbol_c *get_ref_to (symbol_c *type_symbol); // Defined in IEC 61131-3 v3 (returns the type that is being referenced/pointed to) /* Returns true if both datatypes are equivalent (not necessarily equal!). diff -r 887e7d90445a -r 31e3b3f2eff1 absyntax_utils/search_varfb_instance_type.cc --- a/absyntax_utils/search_varfb_instance_type.cc Sun Oct 19 11:53:36 2014 +0100 +++ b/absyntax_utils/search_varfb_instance_type.cc Sun Oct 19 21:30:58 2014 +0100 @@ -428,13 +428,6 @@ current_basetype_id = search_base_type_c::get_basetype_id (ref_spec->type_name); } -/* ########### WARNING ########################################################## */ -/* The following two lines DO NOT belong here. It is just a temporary measure until I get the chance - * to clean this up, and move it to fill/narrow candidate datatypes in stage 3 - */ - symbol->datatype = current_basetype_decl; - symbol->exp->datatype = ref_spec; - return NULL; } @@ -454,12 +447,5 @@ current_basetype_id = search_base_type_c::get_basetype_id (ref_spec->type_name); } -/* ########### WARNING ########################################################## */ -/* The following two lines DO NOT belong here. It is just a temporary measure until I get the chance - * to clean this up, and move it to fill/narrow candidate datatypes in stage 3 - */ - symbol->datatype = current_basetype_decl; - symbol->exp->datatype = ref_spec; - - return NULL; -} + return NULL; +} diff -r 887e7d90445a -r 31e3b3f2eff1 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Sun Oct 19 11:53:36 2014 +0100 +++ b/stage3/fill_candidate_datatypes.cc Sun Oct 19 21:30:58 2014 +0100 @@ -1170,7 +1170,14 @@ /* B 1.4 - Variables */ /*********************/ void *fill_candidate_datatypes_c::visit(symbolic_variable_c *symbol) { - add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */ + /* NOTE: We need to fully determine the datatype of each element in the structured_variable inside this fill_candidate_datatypes class! + * Basically, for variables (be they symbolic_variable, structured_variable, array_variable), we do the narrow algorithm + * in this fill_candidate_datatypes_c itself! + * This is needed because we need to know in which scope (i.e. the datatype of the recor_variable in a structtured_variable_c) + * we will search for the field_variable of the structured_variable_c + */ + symbol->datatype = search_varfb_instance_type->get_basetype_decl(symbol); // Do the narrow algorithm in this fill_candidate_datatypes_c!! + add_datatype_to_candidate_list(symbol, symbol->datatype); /* will only add if non NULL */ if (debug) std::cout << "VAR [" << symbol->candidate_datatypes.size() << "]\n"; return NULL; } @@ -1211,7 +1218,17 @@ * search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable) */ add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */ - + + /* NOTE: We need to fully determine the datatype of each element in the structured_variable inside this fill_candidate_datatypes class! + * Basically, for variables (be they symbolic_variable, structured_variable, array_variable), we do the narrow algorithm + * in this fill_candidate_datatypes_c itself! + * This is needed because we need to know in which scope (i.e. the datatype of the recor_variable in a structtured_variable_c) + * we will search for the field_variable of the structured_variable_c + */ + if (symbol->candidate_datatypes.size() == 1) + // narrow the symbol->datatype for this strcutured_variable as explained above! + symbol->datatype = symbol->candidate_datatypes[0]; + /* recursively call the subscript list, so we can check the data types of the expressions used for the subscripts */ symbol->subscript_list->accept(*this); @@ -1252,17 +1269,25 @@ */ // SYM_REF2(structured_variable_c, record_variable, field_selector) void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) { - /* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type - * will do that for us. So we determine the candidate datatypes only for the full structured_variable. - */ - add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */ - /* However, we do need to visit each record type recursively! - * Remember that a structured variable may be stored inside an array (e.g. arrayvar[33].elem1) + /* Remember that a structured variable may be stored inside an array (e.g. arrayvar[33].elem1) * The array subscripts may contain a complex expression (e.g. arrayvar[ varx + 33].elem1) whose datatype must be correctly determined! * The expression, may even contain a function call to an overloaded function! * (e.g. arrayvar[ varx + TRUNC(realvar)].elem1) */ symbol->record_variable->accept(*this); + + /* NOTE: We need to fully determine the datatype of each element in the structured_variable inside this fill_candidate_datatypes class! + * Basically, for variables (be they symbolic_variable, structured_variable, array_variable), we do the narrow algorithm + * in this fill_candidate_datatypes_c itself! + * This is needed because we need to know in which scope (i.e. the datatype of the recor_variable in a structtured_variable_c) + * we will search for the field_variable of the structured_variable_c + */ + if (NULL != symbol->record_variable->datatype) + // We relly on the fact that we have already narrowed the symbol->datatype for the record variable, and use it as the scope in which the filed_variable is declared! + add_datatype_to_candidate_list(symbol, search_base_type_c::get_basetype_decl(get_datatype_info_c::get_struct_field_type_id(symbol->record_variable->datatype, symbol->field_selector))); /* will only add if non NULL */ + if (symbol->candidate_datatypes.size() == 1) + // narrow the symbol->datatype for this strcutured_variable as explained above! + symbol->datatype = symbol->candidate_datatypes[0]; return NULL; } @@ -1917,7 +1942,20 @@ if (NULL != ref_spec) add_datatype_to_candidate_list(symbol, search_base_type_c::get_basetype_decl(ref_spec->type_name)); + } + + /* NOTE: We need to fully determine the datatype of each element in the structured_variable inside this fill_candidate_datatypes class! + * Basically, for variables (be they symbolic_variable, structured_variable, array_variable), we do the narrow algorithm + * in this fill_candidate_datatypes_c itself! + * This is needed because we need to know in which scope (i.e. the datatype of the recor_variable in a structtured_variable_c) + * we will search for the field_variable of the structured_variable_c + * + * Since the deref_operator_c may be used inside structures, we must narrow it here, if possible! + */ + if (symbol->candidate_datatypes.size() == 1) + // narrow the symbol->datatype for this symbol as explained above! + symbol->datatype = symbol->candidate_datatypes[0]; return NULL; }