Add data structure for storing overflow of constant values.
authorMario de Sousa <msousa@fe.up.pt>
Fri, 08 Jun 2012 19:44:32 +0100
changeset 569 0d1ab9e78574
parent 568 5f79478142d7
child 570 cb704eca7e37
Add data structure for storing overflow of constant values.
absyntax/absyntax.cc
absyntax/absyntax.hh
stage3/constant_folding.cc
--- a/absyntax/absyntax.cc	Wed Jun 06 16:39:54 2012 +0100
+++ b/absyntax/absyntax.cc	Fri Jun 08 19:44:32 2012 +0100
@@ -62,9 +62,9 @@
   this->last_column  = last_column;
   this->last_order   = last_order;
   this->datatype     = NULL;
-  this->const_value_real     = NULL;
-  this->const_value_integer  = NULL;
-  this->const_value_uinteger = NULL;
+  this->const_value_real64   = NULL;
+  this->const_value_int64    = NULL;
+  this->const_value_uint64   = NULL;
   this->const_value_bool     = NULL;
 }
 
--- a/absyntax/absyntax.hh	Wed Jun 06 16:39:54 2012 +0100
+++ b/absyntax/absyntax.hh	Fri Jun 08 19:44:32 2012 +0100
@@ -52,7 +52,7 @@
 #include <stdint.h>  // required for uint64_t, etc...
 
 
-
+/* Determine, for the current platform, which data type (float, double or long double) uses 64 bits. */
 /* NOTE: we cant use sizeof() in pre-processor directives, so we do it another way... */
 #include <float.h>
 #if    (LDBL_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */
@@ -79,12 +79,22 @@
 class symbol_c; // forward declaration
 
 
+
+
+
+
+
+
+
+
+
 /* The base class of all symbols */
 class symbol_c {
 
   public:
     /*
-     * Line number for the purposes of error checking
+     * Line number for the purposes of error checking.
+     * Annotated (inserted) by stage1_2
      */
     int first_line;
     int first_column;
@@ -94,6 +104,12 @@
     int last_column;
     const char *last_file;  /* filename referenced by last line/column */
     long int last_order;    /* relative order in which it is read by lexcial analyser */
+
+
+    /*
+     * Annotations produced during stage 3
+     */
+    /*** Data type analysis ***/
     std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
     /* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c 
      * If set to NULL, it means it has not yet been evaluated.
@@ -102,10 +118,44 @@
      */
     symbol_c *datatype;
 
-    real64_t *const_value_real;
-    int64_t  *const_value_integer;
-    uint64_t *const_value_uinteger;
-    bool     *const_value_bool;
+    /*** constant folding ***/
+    /* During stage 3 (semantic analysis/checking) we will be doing constant folding.
+     * That algorithm will anotate the abstract syntax tree with the result of operations
+     * on literals (i.e. 44 + 55 will store the result 99).
+     * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT,
+     * or an ANY_BIT, we need to handle all possibilities, and determine the result of the
+     * operation assuming each type.
+     * For this reason, we have one entry for each possible type, with some expressions
+     * having more than one entry filled in!
+     */
+    typedef enum { cs_undefined,   /* not defined --> const_value is not valid! */
+                   cs_const_value, /* const value is valid */
+                   cs_overflow     /* result produced overflow or underflow --> const_value is not valid! */
+                 } const_status_t;
+ 
+    typedef struct {
+        const_status_t status;
+        real64_t       value; 
+    } const_value_real64_t;
+    const_value_real64_t *const_value_real64; /* when NULL --> UNDEFINED */
+    
+    typedef struct {
+        const_status_t status;
+        int64_t        value; 
+    } const_value_int64_t;
+    const_value_int64_t *const_value_int64; /* when NULL --> UNDEFINED */
+    
+    typedef struct {
+        const_status_t status;
+        uint64_t       value; 
+    } const_value_uint64_t;
+    const_value_uint64_t *const_value_uint64; /* when NULL --> UNDEFINED */
+    
+    typedef struct {
+        const_status_t status;
+        bool           value; 
+    } const_value_bool_t;
+    const_value_bool_t *const_value_bool; /* when NULL --> UNDEFINED */
 
 
   public:
--- a/stage3/constant_folding.cc	Wed Jun 06 16:39:54 2012 +0100
+++ b/stage3/constant_folding.cc	Fri Jun 08 19:44:32 2012 +0100
@@ -31,13 +31,85 @@
  */
 
 
-/* Determine the value of an ST expression.
- * Filling in all symbols the correct value.
+/* Do constant folding...
+ *
+ * I.e., Determine the value of all expressions in which only constant values (i.e. literals) are used.
+ * The (constant) result of each operation is stored (annotated) in the respective operation symbol 
+ * (e.g.: add_expression_c) in the abstract syntax tree,
  *
  * For example:
- *       2 + 3         -> returns constant_value_integer = 5
- *       22.2 - 5.0    -> returns constant_value_real    = 17.2
+ *       2 + 3         -> the constant value '5'    is stored in the add_expression_c symbol.
+ *       22.2 - 5.0    -> the constant value '17.2' is stored in the add_expression_c symbol.
  *       etc...
+ *
+ *
+ * NOTE 1 that some operations and constants can have multiple data types. For example,
+ *        1 AND 0
+ *      may be either a BOOL, BYTE, WORD or LWORD.
+ *
+ *      The same happens with 
+ *        1 + 2
+ *      which may be signed (e.g. INT) or unsigned (UINT)
+ *
+ *      For the above reason, instead of storing a single constant value, we actually store 4:
+ *        - bool
+ *        - uint64
+ *        -  int64
+ *        - real64
+ *
+ *      Additionally, since the result of an operation may result in an overflow, we actually
+ *      store the result inside a struct (defined in absyntax.hh)
+ *
+ *             ** During stage 3 (semantic analysis/checking) we will be doing constant folding.
+ *              * That algorithm will anotate the abstract syntax tree with the result of operations
+ *              * on literals (i.e. 44 + 55 will store the result 99).
+ *              * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT,
+ *              * or an ANY_BIT, we need to handle all possibilities, and determine the result of the
+ *              * operation assuming each type.
+ *              * For this reason, we have one entry for each possible type, with some expressions
+ *              * having more than one entry filled in!
+ *              **
+ *             typedef enum { cs_undefined,   // not defined --> const_value is not valid!
+ *                            cs_const_value, // const value is valid
+ *                            cs_overflow     // result produced overflow or underflow --> const_value is not valid!
+ *                          } const_status_t;
+ *    
+ *             typedef struct {
+ *                 const_status_t status;
+ *                 real64_t       value; 
+ *             } const_value_real64_t;
+ *             const_value_real64_t *const_value_real64; // when NULL --> UNDEFINED
+ *             
+ *             typedef struct {
+ *                 const_status_t status;
+ *                 int64_t        value; 
+ *             } const_value_int64_t;
+ *             const_value_int64_t *const_value_int64; // when NULL --> UNDEFINED
+ *             
+ *             typedef struct {
+ *                 const_status_t status;
+ *                 uint64_t       value; 
+ *             } const_value_uint64_t;
+ *             const_value_uint64_t *const_value_uint64; // when NULL --> UNDEFINED
+ *             
+ *             typedef struct {
+ *                 const_status_t status;
+ *                 bool           value; 
+ *             } const_value_bool_t;
+ *             const_value_bool_t *const_value_bool; // when NULL --> UNDEFINED
+ *
+ *
+ *
+ * NOTE 2 
+ *    This file does not print out any error messages!
+ *    We cannot really print out error messages when we find an overflow. Since each operation
+ *    (symbol in the absract syntax tree for that operation) will have up to 4 constant results,
+ *    it may happen that some of them overflow, while other do not.
+ *    We must wait for data type checking to determine the exact data type of each expression
+ *    before we can decide whether or not we should print out an overflow error message.
+ *
+ *    For this reason, this visitor merely annotates the abstract syntax tree, and leaves the
+ `    actuall printing of errors for the print_datatype_errors_c class!
  */
 
 #include "constant_folding.hh"
@@ -76,26 +148,31 @@
 
 
 
-#define MALLOC(variable, data_type) \
- variable = (data_type *)malloc(sizeof(data_type)); \
- if (variable == NULL) ERROR;
-
-
-#define DO_OPER(dtype)\
-    (NULL != symbol->r_exp->const_value_##dtype ) && \
-    (NULL != symbol->l_exp->const_value_##dtype )
-
-
-#define CHECK_OVERFLOW_SUM(a, b, type)\
-	((((std::numeric_limits< type >::max() - a) < (b)) ? 1 : 0) || \
-	 (((std::numeric_limits< type >::min() + a) > (b)) ? 1 : 0))
-
-#define CHECK_OVERFLOW_SUB(a, b, type)\
-	((((std::numeric_limits< type >::max() - a) < (-b)) ? 1 : 0) || \
-	 (((std::numeric_limits< type >::min() + a) > (-b)) ? 1 : 0))
-
-#define SYMBOL_BOOL_VALUE (symbol->exp->const_value_bool)
-#define SYMBOL_REAL_VALUE (symbol->exp->const_value_real)
+
+
+
+
+
+
+
+
+#define NEW_CVALUE(dtype, symbol) \
+ (symbol->const_value_##dtype) = new(symbol_c::const_value_##dtype##_t); \
+ if ((symbol->const_value_##dtype) == NULL) ERROR; \
+ (symbol->const_value_##dtype)->status = symbol_c::cs_undefined;
+
+#define SET_CVALUE(dtype, symbol, new_value)  ((symbol)->const_value_##dtype->value) = new_value; ((symbol)->const_value_##dtype->status) = symbol_c::cs_const_value;  
+#define GET_CVALUE(dtype, symbol)             ((symbol)->const_value_##dtype->value) 
+#define SET_OVFLOW(dtype, symbol)             ((symbol)->const_value_##dtype->status) = symbol_c::cs_overflow
+    /* The following test is correct in the presence of a NULL pointer, as the logical evaluation will be suspended as soon as the first condition is false! */
+#define VALID_CVALUE(dtype, symbol)           ((NULL != (symbol)->const_value_##dtype) && (symbol_c::cs_const_value == (symbol)->const_value_##dtype->status))
+#define ISZERO_CVALUE(dtype, symbol)          ((VALID_CVALUE(dtype, symbol)) && (GET_CVALUE(dtype, symbol) == 0))
+#define DO_BIN_OPER(dtype, oper)\
+	if (VALID_CVALUE(dtype, symbol->r_exp) && VALID_CVALUE(dtype, symbol->l_exp)) {                                \
+		NEW_CVALUE(dtype, symbol);                                                                             \
+		SET_CVALUE(dtype, symbol, GET_CVALUE(dtype, symbol->l_exp) oper GET_CVALUE(dtype, symbol->r_exp));     \
+	}
+
 
 
 
@@ -110,7 +187,7 @@
     if (! (std::numeric_limits<real64_t>::is_iec559) )
         STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 559 floating point numbers. "
                                                    "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
-                                                   " (i.e. constant folding) may themselves be erroneous, although are most probably correct");
+                                                   " (i.e. constant folding) may themselves be erroneous, although are most probably correct.");
 }
 
 
@@ -130,116 +207,119 @@
 /* B 1.2.1 - Numeric Literals */
 /******************************/
 void *constant_folding_c::visit(real_c *symbol) {
-	MALLOC(symbol->const_value_real, real64_t);
-	*symbol->const_value_real = extract_real_value(symbol);
-
+	NEW_CVALUE(real64, symbol);
+	SET_CVALUE(real64, symbol, extract_real_value(symbol));
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(integer_c *symbol) {
-	int64_t *integer_value;
-
-	integer_value = (int64_t *)malloc(sizeof(int64_t));
-	*integer_value = extract_integer_value(symbol);
-	symbol->const_value_integer = integer_value;
-
+	NEW_CVALUE( int64, symbol);
+	SET_CVALUE( int64, symbol, extract_integer_value(symbol));
+	NEW_CVALUE(uint64, symbol);
+	SET_CVALUE(uint64, symbol, extract_integer_value(symbol));
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(neg_real_c *symbol) {
 	symbol->exp->accept(*this);
-	if (NULL == symbol->exp->const_value_real)
-		ERROR;
-	symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-	*symbol->const_value_real = - *(symbol->exp->const_value_real);
-	return NULL;
-}
-
-
+	if (!VALID_CVALUE(real64, symbol->exp))
+		return NULL;
+	NEW_CVALUE(real64, symbol);
+	SET_CVALUE(real64, symbol, - GET_CVALUE( real64, symbol->exp));
+	return NULL;
+}
+
+/* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
 void *constant_folding_c::visit(neg_integer_c *symbol) {
-	int64_t *integer_value;
-
-	integer_value = (int64_t *)malloc(sizeof(int64_t));
-	*integer_value = extract_integer_value(symbol);
-	symbol->const_value_integer = integer_value;
-
+	symbol->exp->accept(*this);
+	if (VALID_CVALUE(int64, symbol->exp)) {
+		NEW_CVALUE( int64, symbol);
+		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
+	}
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(binary_integer_c *symbol) {
-
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(octal_integer_c *symbol) {
-
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(hex_integer_c *symbol) {
-	symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-	*(symbol->const_value_integer) = extract_hex_value(symbol);
-
-	return NULL;
-}
-
-
+	NEW_CVALUE( int64, symbol);
+	SET_CVALUE( int64, symbol, extract_hex_value(symbol));
+	NEW_CVALUE(uint64, symbol);
+	SET_CVALUE(uint64, symbol, extract_hex_value(symbol));
+	return NULL;
+}
+
+
+/*
+integer_literal:
+  integer_type_name '#' signed_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' binary_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' octal_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' hex_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+*/
+// SYM_REF2(integer_literal_c, type, value)
 void *constant_folding_c::visit(integer_literal_c *symbol) {
 	symbol->value->accept(*this);
-	if (NULL == symbol->value->const_value_integer) ERROR;
-	symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-	*(symbol->const_value_integer) = *(symbol->value->const_value_integer);
-
+	if (VALID_CVALUE( int64, symbol->value)) {
+		NEW_CVALUE( int64, symbol);
+		SET_CVALUE( int64, symbol, GET_CVALUE( int64, symbol->value));
+	}
+	if (VALID_CVALUE(uint64, symbol->value)) {
+		NEW_CVALUE(uint64, symbol);
+		SET_CVALUE(uint64, symbol, GET_CVALUE(uint64, symbol->value));
+	}
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(real_literal_c *symbol) {
 	symbol->value->accept(*this);
-	if (NULL == symbol->value->const_value_real) ERROR;
-	symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-	*symbol->const_value_real =  *(symbol->value->const_value_real);
-
+	if (VALID_CVALUE(real64, symbol->value)) {
+		NEW_CVALUE(real64, symbol);
+		SET_CVALUE(real64, symbol,  GET_CVALUE(real64, symbol->value));
+	}
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(bit_string_literal_c *symbol) {
-
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(boolean_literal_c *symbol) {
 	symbol->value->accept(*this);
-	if (NULL == symbol->value->const_value_bool) ERROR;
-	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
-	*(symbol->const_value_bool) = *(symbol->value->const_value_bool);
-
+	if (VALID_CVALUE(bool, symbol->value)) {
+		NEW_CVALUE(bool, symbol);
+		SET_CVALUE(bool, symbol,  GET_CVALUE(  bool, symbol->value));
+	}
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(boolean_true_c *symbol) {
-	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
-	*(symbol->const_value_bool) = true;
-
+	NEW_CVALUE(bool, symbol);
+	SET_CVALUE(bool, symbol, true);
 	return NULL;
 }
 
 
 void *constant_folding_c::visit(boolean_false_c *symbol) {
-	symbol->const_value_bool = (bool *)malloc(sizeof(bool));
-	*(symbol->const_value_bool) = false;
-
-	return NULL;
-}
-
+	NEW_CVALUE(bool, symbol);
+	SET_CVALUE(bool, symbol, false);
+	return NULL;
+}
 
 
 /***************************************/
@@ -251,15 +331,8 @@
 void *constant_folding_c::visit(or_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(bool)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) || *(symbol->r_exp->const_value_bool);
-	}
-	if (DO_OPER(integer)) {
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) | *(symbol->r_exp->const_value_integer);
-	}
-
+	DO_BIN_OPER(bool,   ||);
+	DO_BIN_OPER(uint64, | );
 	return NULL;
 }
 
@@ -267,11 +340,8 @@
 void *constant_folding_c::visit(xor_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) ^ *(symbol->r_exp->const_value_integer);
-	}
-
+	DO_BIN_OPER(bool,   ^);
+	DO_BIN_OPER(uint64, ^);
 	return NULL;
 }
 
@@ -279,15 +349,8 @@
 void *constant_folding_c::visit(and_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(bool)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) && *(symbol->r_exp->const_value_bool);
-	}
-	if (DO_OPER(integer)) {
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) & *(symbol->r_exp->const_value_integer);
-	}
-
+	DO_BIN_OPER(bool,   &&);
+	DO_BIN_OPER(uint64, & );
 	return NULL;
 }
 
@@ -295,19 +358,10 @@
 void *constant_folding_c::visit(equ_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(bool)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) == *(symbol->r_exp->const_value_bool);
-	}
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) == *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) == *(symbol->r_exp->const_value_real);
-	}
-
+	DO_BIN_OPER(bool,   ==);
+	DO_BIN_OPER(uint64, ==);
+	DO_BIN_OPER( int64, ==);
+	DO_BIN_OPER(real64, ==);
 	return NULL;
 }
 
@@ -315,19 +369,10 @@
 void *constant_folding_c::visit(notequ_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(bool)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_bool) != *(symbol->r_exp->const_value_bool);
-	}
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) != *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) != *(symbol->r_exp->const_value_real);
-	}
-
+	DO_BIN_OPER(bool,   !=);
+	DO_BIN_OPER(uint64, !=);
+	DO_BIN_OPER( int64, !=);
+	DO_BIN_OPER(real64, !=);
 	return NULL;
 }
 
@@ -335,15 +380,10 @@
 void *constant_folding_c::visit(lt_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) < *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) < *(symbol->r_exp->const_value_real);
-	}
-
+	DO_BIN_OPER(bool,   <);
+	DO_BIN_OPER(uint64, <);
+	DO_BIN_OPER( int64, <);
+	DO_BIN_OPER(real64, <);
 	return NULL;
 }
 
@@ -351,15 +391,10 @@
 void *constant_folding_c::visit(gt_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) > *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) > *(symbol->r_exp->const_value_real);
-	}
-
+	DO_BIN_OPER(bool,   >);
+	DO_BIN_OPER(uint64, >);
+	DO_BIN_OPER( int64, >);
+	DO_BIN_OPER(real64, >);
 	return NULL;
 }
 
@@ -367,15 +402,10 @@
 void *constant_folding_c::visit(le_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) <= *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) <= *(symbol->r_exp->const_value_real);
-	}
-
+	DO_BIN_OPER(bool,   <=);
+	DO_BIN_OPER(uint64, <=);
+	DO_BIN_OPER( int64, <=);
+	DO_BIN_OPER(real64, <=);
 	return NULL;
 }
 
@@ -383,138 +413,99 @@
 void *constant_folding_c::visit(ge_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_integer) >= *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = *(symbol->l_exp->const_value_real) >= *(symbol->r_exp->const_value_real);
-	}
-
-	return NULL;
-}
-
-
+	DO_BIN_OPER(bool,   >=);
+	DO_BIN_OPER(uint64, >=);
+	DO_BIN_OPER( int64, >=);
+	DO_BIN_OPER(real64, >=);
+	return NULL;
+}
+
+
+#define CHECK_OVERFLOW_SUM(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
+		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
+			SET_OVFLOW(dtype, symbol);
+#define CHECK_OVERFLOW_real64  \
+	if (VALID_CVALUE(real64, symbol))                                                                                                            \
+        	/* NaN => underflow, overflow, number is a higher precision format, is a complex number (IEEE standard) */                           \
+		 if (isnan(GET_CVALUE(real64, symbol)))                                                                                              \
+			SET_OVFLOW(real64, symbol);
 void *constant_folding_c::visit(add_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		if (CHECK_OVERFLOW_SUM(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) + *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) + *(symbol->r_exp->const_value_real);
-		/*
-		 * According to the IEEE standard, NaN value is used as:
-		 *   - representation of a number that has underflowed
-		 *   - representation of number that has overflowed
-		 *   - number is a higher precision format
-		 *   - A complex number
-		 */
-		 if (isnan(*(symbol->const_value_real)))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-	}
-
-	return NULL;
-}
-
-
+	DO_BIN_OPER(uint64, +);
+	DO_BIN_OPER( int64, +);
+	DO_BIN_OPER(real64, +);
+	CHECK_OVERFLOW_SUM(uint64);
+	CHECK_OVERFLOW_SUM( int64);
+	CHECK_OVERFLOW_real64;
+	return NULL;
+}
+
+
+#define CHECK_OVERFLOW_SUB(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if ((((std::numeric_limits< dtype##_t >::max() - GET_CVALUE(dtype, symbol->l_exp)) < (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0) || \
+		    (((std::numeric_limits< dtype##_t >::min() + GET_CVALUE(dtype, symbol->l_exp)) > (-GET_CVALUE(dtype, symbol->r_exp))) ? 1 : 0))   \
+			SET_OVFLOW(dtype, symbol);
 void *constant_folding_c::visit(sub_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		if (CHECK_OVERFLOW_SUB(*(symbol->l_exp->const_value_integer), *(symbol->r_exp->const_value_integer), int64_t))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) - *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) - *(symbol->r_exp->const_value_real);
-		/*
-		 * According to the IEEE standard, NaN value is used as:
-		 *   - representation of a number that has underflowed
-		 *   - representation of number that has overflowed
-		 *   - number is a higher precision format
-		 *   - A complex number
-		 */
-		if (isnan(*(symbol->const_value_real)))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-	}
-
-	return NULL;
-}
-
-
+	DO_BIN_OPER(uint64, -);
+	DO_BIN_OPER( int64, -);
+	DO_BIN_OPER(real64, -);
+	CHECK_OVERFLOW_SUB(uint64);
+	CHECK_OVERFLOW_SUB( int64);
+	CHECK_OVERFLOW_real64;
+	return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_MUL(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if (false)                                                                                                                                   \
+			SET_OVFLOW(dtype, symbol);
 void *constant_folding_c::visit(mul_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) * *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) * *(symbol->r_exp->const_value_real);
-		/*
-		 * According to the IEEE standard, NaN value is used as:
-		 *   - representation of a number that has underflowed
-		 *   - representation of number that has overflowed
-		 *   - number is a higher precision format
-		 *   - A complex number
-		 */
-		if (isnan(*(symbol->const_value_real)))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-	}
-
-	return NULL;
-}
-
-
+	DO_BIN_OPER(uint64, *);
+	DO_BIN_OPER( int64, *);
+	DO_BIN_OPER(real64, *);
+	CHECK_OVERFLOW_MUL(uint64);
+	CHECK_OVERFLOW_MUL( int64);
+	CHECK_OVERFLOW_real64;
+	return NULL;
+}
+
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_DIV(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if (false)                                                                                                                                   \
+			SET_OVFLOW(dtype, symbol);
 void *constant_folding_c::visit(div_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		if (*(symbol->r_exp->const_value_integer) == 0)
-			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) / *(symbol->r_exp->const_value_integer);
-	}
-	if (DO_OPER(real)) {
-		if (*(symbol->r_exp->const_value_real) == 0)
-			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = *(symbol->l_exp->const_value_real) / *(symbol->r_exp->const_value_real);
-		/*
-		 * According to the IEEE standard, NaN value is used as:
-		 *   - representation of a number that has underflowed
-		 *   - representation of number that has overflowed
-		 *   - number is a higher precision format
-		 *   - A complex number
-		 */
-		if (isnan(*(symbol->const_value_real)))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-	}
-
-	return NULL;
-}
-
-
+	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, /); CHECK_OVERFLOW_DIV(uint64)};
+	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, /); CHECK_OVERFLOW_DIV( int64)};
+	if (ISZERO_CVALUE(real64, symbol->r_exp))  {NEW_CVALUE(real64, symbol); SET_OVFLOW(real64, symbol);} else {DO_BIN_OPER(real64, /); CHECK_OVERFLOW_real64;};
+	return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_MOD(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if (false)                                                                                                                                   \
+			SET_OVFLOW(dtype, symbol);
 void *constant_folding_c::visit(mod_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if (DO_OPER(integer)) {
-		if (*(symbol->r_exp->const_value_integer) == 0)
-			STAGE3_ERROR(0, symbol, symbol, "Division by zero in constant expression.");
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = *(symbol->l_exp->const_value_integer) % *(symbol->r_exp->const_value_integer);
-
-	}
-
+	if (ISZERO_CVALUE(uint64, symbol->r_exp))  {NEW_CVALUE(uint64, symbol); SET_OVFLOW(uint64, symbol);} else {DO_BIN_OPER(uint64, %); CHECK_OVERFLOW_MOD(uint64)};
+	if (ISZERO_CVALUE( int64, symbol->r_exp))  {NEW_CVALUE( int64, symbol); SET_OVFLOW( int64, symbol);} else {DO_BIN_OPER( int64, %); CHECK_OVERFLOW_MOD( int64)};
 	return NULL;
 }
 
@@ -522,34 +513,40 @@
 void *constant_folding_c::visit(power_expression_c *symbol) {
 	symbol->l_exp->accept(*this);
 	symbol->r_exp->accept(*this);
-	if ((NULL != symbol->l_exp->const_value_real) && (NULL != symbol->r_exp->const_value_integer)) {
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = pow(*(symbol->l_exp->const_value_real), *(symbol->r_exp->const_value_integer));
-		/*
-		 * According to the IEEE standard, NaN value is used as:
-		 *   - representation of a number that has underflowed
-		 *   - representation of number that has overflowed
-		 *   - number is a higher precision format
-		 *   - A complex number
-		 */
-		if (isnan(*(symbol->const_value_real)))
-			STAGE3_ERROR(0, symbol, symbol, "Overflow in constant expression.");
-	}
-
-	return NULL;
-}
-
-
+	/* NOTE: If the const_value in symbol->r_exp is within the limits of both int64 and uint64, then we do both operations.
+	 *       That is OK, as the result should be identicial (we do create an unnecessary CVALUE variable, but who cares?).
+	 *       If only one is valid, then that is the oper we will do!
+	 */
+	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE( int64, symbol->r_exp)) {
+		NEW_CVALUE(real64, symbol);
+		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE( int64, symbol->r_exp)));
+	}
+	if (VALID_CVALUE(real64, symbol->l_exp) && VALID_CVALUE(uint64, symbol->r_exp)) {
+		NEW_CVALUE(real64, symbol);
+		SET_CVALUE(real64, symbol, pow(GET_CVALUE(real64, symbol->l_exp), GET_CVALUE(uint64, symbol->r_exp)));
+	}
+	CHECK_OVERFLOW_real64;
+	return NULL;
+}
+
+
+/* TODO!!! */
+#define CHECK_OVERFLOW_NEG(dtype)\
+	if (VALID_CVALUE(dtype, symbol))                                                                                                             \
+		if (false)                                                                                                                                   \
+			SET_OVFLOW(dtype, symbol);
 void *constant_folding_c::visit(neg_expression_c *symbol) {
 	symbol->exp->accept(*this);
-	if (NULL != symbol->exp->const_value_integer) {
-		symbol->const_value_integer = (int64_t*) malloc(sizeof(int64_t));
-		*(symbol->const_value_integer) = - *(symbol->exp->const_value_integer);
-	}
-	if (NULL != symbol->exp->const_value_real) {
-		symbol->const_value_real = (real64_t*) malloc(sizeof(real64_t));
-		*(symbol->const_value_real) = - *(symbol->exp->const_value_real);
-	}
+	if (VALID_CVALUE( int64, symbol->exp)) {
+		NEW_CVALUE( int64, symbol);
+		SET_CVALUE( int64, symbol, - GET_CVALUE( int64, symbol->exp));
+	}
+	if (VALID_CVALUE(real64, symbol->exp)) {
+		NEW_CVALUE(real64, symbol);
+		SET_CVALUE(real64, symbol, - GET_CVALUE(real64, symbol->exp));
+	}
+	CHECK_OVERFLOW_NEG( int64);
+	CHECK_OVERFLOW_real64;
 	return NULL;
 }
 
@@ -557,13 +554,15 @@
 
 void *constant_folding_c::visit(not_expression_c *symbol) {
 	symbol->exp->accept(*this);
-	if (NULL != symbol->exp->const_value_bool) {
-		symbol->const_value_bool = (bool*) malloc(sizeof(bool));
-		*(symbol->const_value_bool) = !*(symbol->exp->const_value_bool);
-	}
-
-	return NULL;
-}
-
-
-
+	if (VALID_CVALUE(  bool, symbol->exp)) {
+		NEW_CVALUE(  bool, symbol);
+		SET_CVALUE(  bool, symbol,  ! GET_CVALUE(  bool, symbol->exp));
+	}
+	if (VALID_CVALUE(uint64, symbol->exp)) {
+		NEW_CVALUE(uint64, symbol);
+		SET_CVALUE(uint64, symbol,  ~ GET_CVALUE(uint64, symbol->exp));
+	}
+	return NULL;
+}
+
+