Move the enumerated_value_symtable to fill_candidate_datatypes_c, since it is only used there!
authorMario de Sousa <msousa@fe.up.pt>
Thu, 08 Nov 2012 12:49:03 +0000
changeset 719 19595fce59f0
parent 718 a9f8cc778444
child 720 f637ac331a68
Move the enumerated_value_symtable to fill_candidate_datatypes_c, since it is only used there!
absyntax_utils/absyntax_utils.cc
absyntax_utils/absyntax_utils.hh
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
--- 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 */