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; }