--- a/stage3/fill_candidate_datatypes.cc Fri Nov 09 13:08:18 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc Fri Nov 09 14:34:36 2012 +0000
@@ -72,6 +72,32 @@
#define VALID_CVALUE(dtype, symbol) (symbol_c::cs_const_value == (symbol)->const_value._##dtype.status)
#define IS_OVERFLOW(dtype, symbol) (symbol_c::cs_overflow == (symbol)->const_value._##dtype.status)
+
+
+
+#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2))
+#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2))
+
+
+#define STAGE3_ERROR(error_level, symbol1, symbol2, ...) { \
+ fprintf(stderr, "%s:%d-%d..%d-%d: error: ", \
+ FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
+ LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+}
+
+
+#define STAGE3_WARNING(symbol1, symbol2, ...) { \
+ fprintf(stderr, "%s:%d-%d..%d-%d: warning: ", \
+ FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
+ LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+}
+
+
+
/* set to 1 to see debug info during execution */
static int debug = 0;
@@ -86,9 +112,11 @@
/* 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 dsymtable_c<symbol_c *, &null_globalenumvalue_symbol> global_enumerated_value_symtable;
+/* NOTE: we do not store any NULL values in this symbol table, so we can safely use NULL and the null value. */
+
+symbol_c null_enumvalue_symbol; /* cannot be static, so it may be used in the template!! */
+typedef dsymtable_c<symbol_c *, &null_enumvalue_symbol> enumerated_value_symtable_t;
+static enumerated_value_symtable_t global_enumerated_value_symtable;
class populate_globalenumvalue_symtable_c: public iterator_visitor_c {
@@ -128,16 +156,14 @@
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; */
+ enumerated_value_symtable_t::iterator lower = global_enumerated_value_symtable.lower_bound(symbol->value);
+ enumerated_value_symtable_t::iterator upper = global_enumerated_value_symtable.upper_bound(symbol->value);
+ for (; lower != upper; lower++)
+ if (lower->second == current_enumerated_type) {
+ /* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
+ STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
+ return NULL; /* No need to insert it! It is already in the table! */
+ }
global_enumerated_value_symtable.insert(symbol->value, current_enumerated_type);
return NULL;
@@ -200,8 +226,7 @@
* END_FUNCTION_BLOCK
*/
- symbol_c null_localenumvalue_symbol; /* cannot be static, so it may be used in the template!! */
- static dsymtable_c<symbol_c *, &null_localenumvalue_symbol> local_enumerated_value_symtable;
+static enumerated_value_symtable_t local_enumerated_value_symtable;
class populate_enumvalue_symtable_c: public iterator_visitor_c {
@@ -241,7 +266,14 @@
/* 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 *local_value_type = local_enumerated_value_symtable.find_value(symbol->value);
+ enumerated_value_symtable_t::iterator lower = local_enumerated_value_symtable.lower_bound(symbol->value);
+ enumerated_value_symtable_t::iterator upper = local_enumerated_value_symtable.upper_bound(symbol->value);
+ for (; lower != upper; lower++)
+ if (lower->second == current_enumerated_type) {
+ /* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
+ STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
+ return NULL; /* No need to insert it! It is already in the table! */
+ }
/* add it to the local symbol table. */
local_enumerated_value_symtable.insert(symbol->value, current_enumerated_type);
@@ -383,7 +415,6 @@
if(param_name == NULL) return false;
} while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
- /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */
/* Get the parameter type */
param_datatype = base_type(fp_iterator.param_type());
@@ -774,8 +805,6 @@
/* B 1.2.3.1 - Duration */
/************************/
void *fill_candidate_datatypes_c::visit(duration_c *symbol) {
- /* TODO: check whether the literal follows the rules specified in section '2.2.3.1 Duration' of the standard! */
-
add_datatype_to_candidate_list(symbol, symbol->type_name);
if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
return NULL;
@@ -903,8 +932,44 @@
symbol_c *local_enumerated_type;
symbol_c *enumerated_type;
- if (NULL != symbol->type)
- enumerated_type = symbol->type; /* TODO: check whether the value really belongs to that datatype!! */
+ if (NULL != symbol->type) {
+#if 1
+ enumerated_type = symbol->type;
+#else
+ /* NOTE: The following code works but is not complete, that is why it is currently commented out!
+ *
+ * It is not complete because it does not yet consider the following situation:
+ *
+ * TYPE
+ * base_enum_t: (x1, x2, x3);
+ * enum_t1 : base_enum_t := x1;
+ * enum_t2 : base_enum_t := x2;
+ * enum_t12: enum_t1 := x2;
+ * END_TYPE
+ *
+ * considering the above, ALL of the following are correct!
+ * base_enum_t#x1
+ * enum_t1#x1
+ * enum_t2#x1
+ * enum_t12#x1
+ *
+ * However, the following code only considers
+ * base_enum_t#x1
+ * as correct, and all the others as incorrect!
+ */
+ /* check whether the value really belongs to that datatype!! */
+ /* All local enum values are declared inside anonymous enumeration datatypes (i.e. inside a VAR ... END_VAR declaration, with
+ * the enum type having no type name), so thay cannot possibly be referenced using a datatype_t#enumvalue syntax.
+ * Because of this, we only look for the datatype identifier in the global enum value symbol table!
+ */
+ enumerated_type = NULL; // assume error...
+ enumerated_value_symtable_t::iterator lower = global_enumerated_value_symtable.lower_bound(symbol->value);
+ enumerated_value_symtable_t::iterator upper = global_enumerated_value_symtable.upper_bound(symbol->value);
+ for (; lower != upper; lower++)
+ if (compare_identifiers(search_base_type_c::get_basetype_id(lower->second), symbol->type) == 0) // returns 0 if identifiers are equal!!
+ enumerated_type = symbol->type;
+#endif
+ }
else {
symbol_c *global_enumerated_type = global_enumerated_value_symtable.find_value (symbol->value);
symbol_c * local_enumerated_type = local_enumerated_value_symtable.find_value (symbol->value);