Move the enumerated_value_symtable to fill_candidate_datatypes_c, since it is only used there!
--- 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<symbol_c *, &null_symbol4> 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<symbol_c *, &null_symbol5> 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) {
--- 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<symbol_c *, &null_symbol4> 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<symbol_c *, &null_symbol5> enumerated_value_symtable;
-
/***********************************************************************/
/***********************************************************************/
--- 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<symbol_c *, &null_globalenumvalue_symbol> 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<symbol_c *, &null_enumvalue_symbol> local_enumerated_value_symtable;
+ symbol_c null_localenumvalue_symbol; /* cannot be static, so it may be used in the template!! */
+ static symtable_c<symbol_c *, &null_localenumvalue_symbol> 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;
}
--- 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 */