# HG changeset patch # User Mario de Sousa # Date 1352378943 0 # Node ID 19595fce59f0d9a1dd8fc646eabad2ccb1ee566c # Parent a9f8cc778444f5c44374d2441021431b4ca72ffb Move the enumerated_value_symtable to fill_candidate_datatypes_c, since it is only used there! diff -r a9f8cc778444 -r 19595fce59f0 absyntax_utils/absyntax_utils.cc --- a/absyntax_utils/absyntax_utils.cc Wed Nov 07 20:07:11 2012 +0000 +++ b/absyntax_utils/absyntax_utils.cc Thu Nov 08 12:49:03 2012 +0000 @@ -124,21 +124,6 @@ symbol_c null_symbol4; symtable_c type_symtable; -/* A symbol table with all values declared for enumerated type... */ -/* Notes: - * - if the value is defined multiple times the value - * is the null pointer. - * - * - The stored symbol_c * associated to the value points to the enumerated_type_name - * (i.e. the name of the enumerated data type) in which the the value/identifier - * is used/declared. - * - * - We could re-use the null_symbol4 object, but it is safer to use a distinct object - * (i.e. it might make it easier to find strange bugs). - */ -symbol_c null_symbol5; -symtable_c enumerated_value_symtable; - /***********************************************************************/ /***********************************************************************/ @@ -220,35 +205,6 @@ return symbol->enumerated_specification->accept(*this); } - /* [enumerated_type_name '#'] identifier */ - void *visit(enumerated_value_c *symbol) { - if (current_enumerated_type != NULL) { - if (symbol->type != NULL) ERROR; - - symbol_c *value_type = enumerated_value_symtable.find_value(symbol->value); - /* NOTE: The following condition checks whether the same identifier is used more than once - * when defining the enumerated values of the type declaration of the new enumerated type. - * If this occurs, then the program beeing compiled contains a semantic error, which - * must be caught and reported by the semantic analyser. However, since - * this code is run before the semantic analyser, we must not yet raise the ERROR (internal - * compiler error message). - * For this reason, the follosing check is commented out. - */ - /* if (value_type == current_enumerated_type) ERROR; */ - - if (value_type == enumerated_value_symtable.end_value()) - /* This identifier has not yet been used in any previous declaration of an enumeration data type. - * so we add it to the symbol table. - */ - enumerated_value_symtable.insert(symbol->value, current_enumerated_type); - else if (value_type != NULL) - /* This identifier has already been used in a previous declaration of an enumeration data type. - * so we set the symbol in symbol table pointing to NULL. - */ - enumerated_value_symtable.set(symbol->value, NULL); - } - return NULL; - } /* identifier ':' array_spec_init */ void *visit(array_type_declaration_c *symbol) { diff -r a9f8cc778444 -r 19595fce59f0 absyntax_utils/absyntax_utils.hh --- a/absyntax_utils/absyntax_utils.hh Wed Nov 07 20:07:11 2012 +0000 +++ b/absyntax_utils/absyntax_utils.hh Thu Nov 08 12:49:03 2012 +0000 @@ -77,26 +77,6 @@ extern symbol_c null_symbol4; extern symtable_c type_symtable; -/* A symbol table with all values declared for enumerated types declared in global scope - * (i.e. declared inside a TYPE ... END_TYPE declaration. - */ -/* Notes: - * (A) - Some enumerations are implicitly declared inside a VAR ... END_VAR declaration - * (e.g. VAR enum_var : (enumvalue1, enumvalue2); END_VAR) - * These enumvalueX will only be valid (in scope) inside the POU in which the enum_var is declared. - * Because of this, they are not stored in this symbol table - * - * (B) - if the value is defined multiple times the value is the null pointer. - * - * (C) - The stored symbol_c * associated to the value points to the enumerated_type_name - * (i.e. the name of the enumerated data type) in which the the value/identifier is used/declared. - * - * (D) - We could re-use the null_symbol4 object, but it is safer to use a distinct object - * (i.e. it might make it easier to find strange bugs). - */ -extern symbol_c null_symbol5; -extern symtable_c enumerated_value_symtable; - /***********************************************************************/ /***********************************************************************/ diff -r a9f8cc778444 -r 19595fce59f0 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Wed Nov 07 20:07:11 2012 +0000 +++ b/stage3/fill_candidate_datatypes.cc Thu Nov 08 12:49:03 2012 +0000 @@ -53,6 +53,10 @@ * The candidate datatype list will be filled with a list of all the data types that expression may legally take. * For example, the very simple literal '0' (as in foo := 0), may represent a: * BOOL, BYTE, WORD, DWORD, LWORD, USINT, SINT, UINT, INT, UDINT, DINT, ULINT, LINT (as well as the SAFE versions of these data tyes too!) + * + * WARNING: This visitor class starts off by building a map of all enumeration constants that are defined in the source code (i.e. a library_c symbol), + * and this map is later used to determine the datatpe of each use of an enumeration constant. By implication, the fill_candidate_datatypes_c + * visitor class will only work corretly if it is asked to visit a symbol of class library_c!! */ #include <../main.hh> /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */ @@ -73,17 +77,104 @@ - /*****************************************************/ /* */ /* A small helper class... */ /* */ /*****************************************************/ +/* Add to the global_enumerated_value_symtable the global enum value constants, i.e. the enum constants used in the enumerated + * datatypes that are defined inside a TYPE ... END_TYPE declaration. + */ + + symbol_c null_globalenumvalue_symbol; /* cannot be static, so it may be used in the template!! */ + static symtable_c global_enumerated_value_symtable; + + +class populate_globalenumvalue_symtable_c: public iterator_visitor_c { + private: + symbol_c *current_enumerated_type; + + public: + populate_globalenumvalue_symtable_c(void) {current_enumerated_type = NULL;}; + ~populate_globalenumvalue_symtable_c(void) {} + + public: + /*************************/ + /* B.1 - Common elements */ + /*************************/ + /**********************/ + /* B.1.3 - Data types */ + /**********************/ + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + /* enumerated_type_name ':' enumerated_spec_init */ + void *visit(enumerated_type_declaration_c *symbol) { + //current_enumerated_type = symbol->enumerated_type_name; + current_enumerated_type = symbol; + symbol->enumerated_spec_init->accept(*this); + current_enumerated_type = NULL; + return NULL; + } + + /* enumerated_specification ASSIGN enumerated_value */ + void *visit(enumerated_spec_init_c *symbol) { + return symbol->enumerated_specification->accept(*this); + } + + /* [enumerated_type_name '#'] identifier */ + void *visit(enumerated_value_c *symbol) { + if (current_enumerated_type == NULL) ERROR; + if (symbol->type != NULL) ERROR; + + symbol_c *value_type = global_enumerated_value_symtable.find_value(symbol->value); + /* NOTE: The following condition checks whether the same identifier is used more than once + * when defining the enumerated values of the type declaration of the new enumerated type. + * If this occurs, then the program beeing compiled contains a semantic error, which + * must be caught and reported by the semantic analyser. However, since + * this code is run before the semantic analyser, we must not yet raise the ERROR (internal + * compiler error message). + * For this reason, the follosing check is commented out. + */ + /* if (value_type == current_enumerated_type) ERROR; */ + + if (value_type == global_enumerated_value_symtable.end_value()) + /* This identifier has not yet been used in any previous declaration of an enumeration data type. + * so we add it to the symbol table. + */ + global_enumerated_value_symtable.insert(symbol->value, current_enumerated_type); + else if (value_type != NULL) + /* This identifier has already been used in a previous declaration of an enumeration data type. + * so we set the symbol in symbol table pointing to NULL. + */ + global_enumerated_value_symtable.set(symbol->value, NULL); + + return NULL; + } + + /**************************************/ + /* B.1.5 - Program organization units */ + /**************************************/ + /* B 1.5.1 - Functions */ + void *visit(function_declaration_c *symbol) {return NULL;} + /* B 1.5.2 - Function Blocks */ + void *visit(function_block_declaration_c *symbol) {return NULL;} + /* B 1.5.3 - Programs */ + void *visit(program_declaration_c *symbol) {return NULL;} + +}; /* populate_globalenumvalue_symtable_c */ + +static populate_globalenumvalue_symtable_c populate_globalenumvalue_symtable; + + +/*****************************************************/ +/* */ +/* A small helper class... */ +/* */ +/*****************************************************/ + /* Add to the local_enumerated_value_symtable the local enum value constants */ -/* WARNING: This visitor expects to visit a POU (function, FB, program, ...) - * It should not be called to visit any symbol that may include a TYPE .., END_TYPE declaration! - */ /* Notes: * Some enumerations are * (A) declared anonymously inside a VAR ... END_VAR declaration @@ -119,8 +210,8 @@ * END_FUNCTION_BLOCK */ - symbol_c null_enumvalue_symbol; /* cannot be static, so it may be used in the template!! */ - static symtable_c local_enumerated_value_symtable; + symbol_c null_localenumvalue_symbol; /* cannot be static, so it may be used in the template!! */ + static symtable_c local_enumerated_value_symtable; class populate_enumvalue_symtable_c: public iterator_visitor_c { @@ -141,6 +232,9 @@ /********************************/ /* B 1.3.3 - Derived data types */ /********************************/ + /* TYPE type_declaration_list END_TYPE */ + void *visit(data_type_declaration_c *symbol) {return NULL;} // do not visit the type declarations!! + /* enumerated_specification ASSIGN enumerated_value */ void *visit(enumerated_spec_init_c *symbol) { current_enumerated_type = symbol; @@ -157,7 +251,7 @@ /* this is really an ERROR! The initial value may use the syntax NUM_TYPE#enum_value, but in that case we should have return'd in the above statement !! */ if (symbol->type != NULL) ERROR; - // symbol_c *global_value_type = enumerated_value_symtable.find_value(symbol->value); + // symbol_c *global_value_type = global_enumerated_value_symtable.find_value(symbol->value); symbol_c *local_value_type = local_enumerated_value_symtable.find_value(symbol->value); if (local_value_type == local_enumerated_value_symtable.end_value()) /* This identifier has not yet been used in any previous local declaration of an enumeration data type, so we add it to the local symbol table. */ @@ -181,7 +275,6 @@ /*****************************************************/ - fill_candidate_datatypes_c::fill_candidate_datatypes_c(symbol_c *ignore) { il_operand = NULL; prev_il_instruction = NULL; @@ -192,6 +285,12 @@ fill_candidate_datatypes_c::~fill_candidate_datatypes_c(void) { } + + + + + + symbol_c *fill_candidate_datatypes_c::widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]) { int k; /* find a widening table entry compatible */ @@ -551,6 +650,18 @@ return search_base_type_c::get_basetype_decl(symbol); } + +/***************************/ +/* B 0 - Programming Model */ +/***************************/ +/* main entry function! */ +void *fill_candidate_datatypes_c::visit(library_c *symbol) { + symbol->accept(populate_globalenumvalue_symtable); + /* Now let the base class iterator_visitor_c iterate through all the library elements */ + return iterator_visitor_c::visit(symbol); +} + + /*********************/ /* B 1.2 - Constants */ /*********************/ @@ -809,17 +920,17 @@ if (NULL != symbol->type) enumerated_type = symbol->type; /* TODO: check whether the value really belongs to that datatype!! */ else { - global_enumerated_type = enumerated_value_symtable.find_value(symbol->value); - local_enumerated_type = local_enumerated_value_symtable.find_value(symbol->value); - if ((local_enumerated_type == local_enumerated_value_symtable.end_value()) && (global_enumerated_type == enumerated_value_symtable.end_value())) + global_enumerated_type = global_enumerated_value_symtable.find_value(symbol->value); + local_enumerated_type = local_enumerated_value_symtable.find_value(symbol->value); + if (( local_enumerated_type == local_enumerated_value_symtable.end_value()) && (global_enumerated_type == global_enumerated_value_symtable.end_value())) enumerated_type = NULL; // not found! - else if ((local_enumerated_type != local_enumerated_value_symtable.end_value()) && (local_enumerated_type == NULL)) + else if (( local_enumerated_type != local_enumerated_value_symtable.end_value()) && (local_enumerated_type == NULL)) enumerated_type = NULL; // Duplicate, so it is ambiguous! - else if ((local_enumerated_type != local_enumerated_value_symtable.end_value())) + else if (( local_enumerated_type != local_enumerated_value_symtable.end_value())) enumerated_type = local_enumerated_type; - else if ((global_enumerated_type != enumerated_value_symtable.end_value()) && (global_enumerated_type == NULL)) + else if ((global_enumerated_type != global_enumerated_value_symtable.end_value()) && (global_enumerated_type == NULL)) enumerated_type = NULL; // Duplicate, so it is ambiguous! - else if ((global_enumerated_type != enumerated_value_symtable.end_value())) + else if ((global_enumerated_type != global_enumerated_value_symtable.end_value())) enumerated_type = global_enumerated_type; else ERROR; } diff -r a9f8cc778444 -r 19595fce59f0 stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Wed Nov 07 20:07:11 2012 +0000 +++ b/stage3/fill_candidate_datatypes.hh Thu Nov 08 12:49:03 2012 +0000 @@ -43,6 +43,10 @@ * The candidate datatype list will be filled with a list of all the data types that expression may legally take. * For example, the very simple literal '0' (as in foo := 0), may represent a: * BOOL, BYTE, WORD, DWORD, LWORD, USINT, SINT, UINT, INT, UDINT, DINT, ULINT, LINT (as well as the SAFE versions of these data tyes too!) + * + * WARNING: This visitor class starts off by building a map of all enumeration constants that are defined in the source code (i.e. a library_c symbol), + * and this map is later used to determine the datatpe of each use of an enumeration constant. By implication, the fill_candidate_datatypes_c + * visitor class will only work corretly if it is asked to visit a symbol of class library_c!! */ @@ -69,24 +73,6 @@ // search_var_instance_decl_c *search_var_instance_decl; /* This variable was created to pass information from - * fill_candidate_datatypes_c::visit(case_statement_c *symbol) function to - * fill_candidate_datatypes_c::visit(case_list_c *symbol) function. - */ -// symbol_c *case_expression_type; - - /* In IL code, once we find a type mismatch error, it is best to - * ignore any further errors until the end of the logical operation, - * i.e. until the next LD. - * However, we cannot clear the il_error flag on all LD operations, - * as these may also be used within parenthesis. LD operations - * within parenthesis may not clear the error flag. - * We therefore need a counter to know how deep inside a parenthesis - * structure we are. - */ -// int il_parenthesis_level; -// bool error_found; - - /* This variable was created to pass information from * fill_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) function to * fill_candidate_datatypes_c::visit(enumerated_value_list_c *symbol) function. */ @@ -123,6 +109,11 @@ fill_candidate_datatypes_c(symbol_c *ignore); virtual ~fill_candidate_datatypes_c(void); + + /***************************/ + /* B 0 - Programming Model */ + /***************************/ + void *visit(library_c *symbol); /*********************/ /* B 1.2 - Constants */