Code-clean: Modernize class Value and its implementations.

Mostly to improve code robustness and follow style-guides.

General cleanup:

  * Add a virtual destructor in the base class (otherwise strange things
    might happen)
  * Use 'final' overridden virtuals. This allows compiler errors if
    signature changes in base-class thus robust ways to refactor. Also,
    'final' allows the compiler to optimize away a virtual method look-up
    if it can infer the exact type at compile-time.
  * Use constructor initializer lists instead of assigning in constructor
    body.
  * Type enum: use enum class for more type-safe and enforced scoped use.
    (this required some small changes outside the Value.{h,cpp} files).
  * Use nullptr instead of NULL.

Const cleanness:

  * Getter methods that don't change anything: make const. This way they can be
    used in a const context.
  * operators < and ==: make const member operators and also have their parameters
    be const (otherwise all kinds of algorithms will stumble upon this)
  * Make setter take a const std::string& instead of std::string by value.
  * Copy constructors: take const reference parameter
  * Make parameters whose values are guaranteed to not be modifed const
    e.g. plus()/minus()/.. etc)

Behavior change:

  * Use strtod() instead of atof() to parse double value (avoid
    loss of precision)

Signed-off-by: Henner Zeller <h.zeller@acm.org>
diff --git a/src/Design/DataType.cpp b/src/Design/DataType.cpp
index 326ddb8..74adfd4 100644
--- a/src/Design/DataType.cpp
+++ b/src/Design/DataType.cpp
@@ -114,8 +114,8 @@
   if (m_definition) {
     dtype = m_definition->getType();
   }
-  Value::ValueType vtype = value->getType();
-  if (vtype == Value::String) {
+  Value::Type vtype = value->getType();
+  if (vtype == Value::Type::String) {
     std::string st = value->getValueS();
     if (st.size() == 3)  // "\"c\""
     {
@@ -124,9 +124,9 @@
     } else if (!isString_type(dtype)) {
       result = false;
     }
-  } else if (vtype == Value::Double) {
+  } else if (vtype == Value::Type::Double) {
     if (isString_type(dtype)) result = false;
-  } else if (vtype == Value::Unsigned) {
+  } else if (vtype == Value::Type::Unsigned) {
     if (value->getValueL(0) == 0) {
       // Null
     } else {
diff --git a/src/DesignCompile/CompileHelper.cpp b/src/DesignCompile/CompileHelper.cpp
index 20d1b51..cf2b94e 100644
--- a/src/DesignCompile/CompileHelper.cpp
+++ b/src/DesignCompile/CompileHelper.cpp
@@ -292,7 +292,7 @@
         value = m_exprBuilder.evalExpr(fC, enumValueId, NULL);
       } else {
         value = m_exprBuilder.getValueFactory().newLValue();
-        value->set(val, Value::Integer, 32);
+        value->set(val, Value::Type::Integer, 32);
       }
       the_enum->addValue(enumName, value);
       enum_name_declaration = fC->Sibling(enum_name_declaration);
diff --git a/src/DesignCompile/TestbenchElaboration.cpp b/src/DesignCompile/TestbenchElaboration.cpp
index ac088b5..4df445f 100644
--- a/src/DesignCompile/TestbenchElaboration.cpp
+++ b/src/DesignCompile/TestbenchElaboration.cpp
@@ -421,9 +421,9 @@
                   symbols->registerSymbol(fileName), line, 0,
                   symbols->registerSymbol(name + " of type " + typeName));
               std::string exp;
-              if (value->getType() == Value::String)
+              if (value->getType() == Value::Type::String)
                 exp = value->getValueS();
-              else if (value->getType() == Value::Double)
+              else if (value->getType() == Value::Type::Double)
                 exp = std::to_string(value->getValueD(0));
               else
                 exp = std::to_string(value->getValueL(0));
diff --git a/src/Expression/ExprBuilder.cpp b/src/Expression/ExprBuilder.cpp
index c230846..6e68a21 100644
--- a/src/Expression/ExprBuilder.cpp
+++ b/src/Expression/ExprBuilder.cpp
@@ -43,7 +43,7 @@
 Value* ExprBuilder::clone(Value* val) {
   Value* clone = NULL;
   bool isLValue = val->isLValue();
-  if (val->getType() == Value::String) {
+  if (val->getType() == Value::Type::String) {
     clone = m_valueFactory.newValue(*(StValue*)val);
   } else if (isLValue) {
     clone = m_valueFactory.newValue(*(LValue*)val);
@@ -335,7 +335,7 @@
           value->set(NAN);
           break;
         }
-        if (sval->getType() == Value::String) {
+        if (sval->getType() == Value::Type::String) {
           m_valueFactory.deleteValue(value);
           value = sval;
         } else {
diff --git a/src/Expression/Value.cpp b/src/Expression/Value.cpp
index ba7e957..b7bbb29 100644
--- a/src/Expression/Value.cpp
+++ b/src/Expression/Value.cpp
@@ -40,27 +40,24 @@
 
 StValue::~StValue() {}
 
-bool LValue::operator<(Value& rhs) {
+bool LValue::operator<(const Value& rhs) const {
   // TODO
   return true;
 }
 
-bool LValue::operator==(Value& rhs) {
+bool LValue::operator==(const Value& rhs) const {
   // TODO
   return true;
 }
 
-ValueFactory::ValueFactory() {
-  m_headFree = NULL;
-  m_headInUse = NULL;
-}
+ValueFactory::ValueFactory() : m_headFree(nullptr), m_headInUse(nullptr) {}
 
 Value* ValueFactory::newSValue() { return new SValue(); }
 
 Value* ValueFactory::newStValue() { return new StValue(); }
 
 Value* ValueFactory::newLValue() {
-  if (m_headFree == NULL) {
+  if (m_headFree == nullptr) {
     return new LValue();
   } else {
     LValue* ret = m_headFree;
@@ -68,13 +65,13 @@
     LValue* prev = m_headFree->m_prev;
     m_headFree = next;
     if (prev == next) {
-      m_headFree = NULL;
+      m_headFree = nullptr;
     } else {
       next->m_prev = prev;
       prev->m_next = next;
     }
-    ret->m_prev = NULL;
-    ret->m_next = NULL;
+    ret->m_prev = nullptr;
+    ret->m_next = nullptr;
     return ret;
   }
 }
@@ -84,7 +81,7 @@
 Value* ValueFactory::newValue(StValue& initVal) { return new StValue(initVal); }
 
 Value* ValueFactory::newValue(LValue& initVal) {
-  if (m_headFree == NULL) {
+  if (m_headFree == nullptr) {
     return new LValue(initVal);
   } else {
     LValue* ret = m_headFree;
@@ -92,13 +89,13 @@
     LValue* prev = m_headFree->m_prev;
     m_headFree = next;
     if (prev == next) {
-      m_headFree = NULL;
+      m_headFree = nullptr;
     } else {
       next->m_prev = prev;
       prev->m_next = next;
     }
-    ret->m_prev = NULL;
-    ret->m_next = NULL;
+    ret->m_prev = nullptr;
+    ret->m_next = nullptr;
     ret->adjust(&initVal);
     for (unsigned int i = 0; i < ret->m_nbWords; i++) {
       ret->m_valueArray[i] = initVal.m_valueArray[i];
@@ -109,14 +106,14 @@
 }
 
 void ValueFactory::deleteValue(Value* value) {
-  if (value->getType() == Value::String) {
+  if (value->getType() == Value::Type::String) {
     // TODO: investigate memory corruption
     // delete (StValue*) value;
     return;
   }
   LValue* val = (LValue*)value;
-  Value* prev = m_headFree;
-  if (prev == NULL) {
+  const Value* prev = m_headFree;
+  if (prev == nullptr) {
     m_headFree = (LValue*)val;
     m_headFree->m_next = m_headFree;
     m_headFree->m_prev = m_headFree;
@@ -143,13 +140,13 @@
   m_value = (uint64_t)val;
   m_size = 64;
 }
-void SValue::set(uint64_t val, ValueType type, unsigned short size) {
+void SValue::set(uint64_t val, Type type, unsigned short size) {
   m_value = val;
   m_size = size;
 }
 
-void SValue::u_plus(Value* a) {
-  SValue* aval = (SValue*)a;
+void SValue::u_plus(const Value* a) {
+  const SValue* aval = (const SValue*)a;
   m_size = aval->m_size;
   m_value = aval->m_value;
 }
@@ -158,151 +155,151 @@
 
 void SValue::decr() { m_value--; }
 
-void SValue::u_minus(Value* a) {
-  SValue* aval = (SValue*)a;
+void SValue::u_minus(const Value* a) {
+  const SValue* aval = (const SValue*)a;
   m_size = aval->m_size;
   m_value = -aval->m_value;
 }
 
-void SValue::u_not(Value* a) {
-  SValue* aval = (SValue*)a;
+void SValue::u_not(const Value* a) {
+  const SValue* aval = (const SValue*)a;
   m_size = aval->m_size;
   m_value = !aval->m_value;
 }
 
-void SValue::u_tilda(Value* a) {
-  SValue* aval = (SValue*)a;
+void SValue::u_tilda(const Value* a) {
+  const SValue* aval = (const SValue*)a;
   m_size = aval->m_size;
   m_value = ~aval->m_value;
 }
 
-void SValue::plus(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::plus(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value + bval->m_value;
 }
 
-void SValue::minus(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::minus(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value - bval->m_value;
 }
 
-void SValue::mult(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::mult(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value * bval->m_value;
 }
 
-void SValue::div(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::div(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value / bval->m_value;
 }
 
-void SValue::mod(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::mod(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value % bval->m_value;
 }
 
-void SValue::greater(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::greater(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value > bval->m_value;
 }
 
-void SValue::greater_equal(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::greater_equal(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value >= bval->m_value;
 }
 
-void SValue::lesser(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::lesser(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value < bval->m_value;
 }
 
-void SValue::lesser_equal(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::lesser_equal(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value <= bval->m_value;
 }
 
-void SValue::equiv(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::equiv(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value == bval->m_value;
 }
 
-void SValue::logAnd(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::logAnd(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value && bval->m_value;
 }
 
-void SValue::logOr(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::logOr(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value || bval->m_value;
 }
 
-void SValue::bitwAnd(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::bitwAnd(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value & bval->m_value;
 }
 
-void SValue::bitwOr(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::bitwOr(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value | bval->m_value;
 }
 
-void SValue::bitwXor(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::bitwXor(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value ^ bval->m_value;
 }
 
-void SValue::notEqual(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::notEqual(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value != bval->m_value;
 }
 
-void SValue::shiftLeft(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::shiftLeft(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value << bval->m_value;
 }
 
-void SValue::shiftRight(Value* a, Value* b) {
-  SValue* aval = (SValue*)a;
-  SValue* bval = (SValue*)b;
+void SValue::shiftRight(const Value* a, const Value* b) {
+  const SValue* aval = (const SValue*)a;
+  const SValue* bval = (const SValue*)b;
   m_size = (aval->m_size > bval->m_size) ? aval->m_size : bval->m_size;
   m_value = aval->m_value >> bval->m_value;
 }
 
-unsigned short LValue::getSize() {
+unsigned short LValue::getSize() const {
   unsigned short size = 0;
   for (int i = 0; i < m_nbWords; i++) {
     size += m_valueArray[i].m_size;
@@ -310,59 +307,45 @@
   return size;
 }
 
-LValue::LValue(LValue& val) {
-  m_type = val.m_type;
-  m_prev = NULL;
-  m_next = NULL;
-  m_nbWords = val.m_nbWords;
-  m_valueArray = new SValue[val.m_nbWords];
+LValue::LValue(const LValue& val)
+  : m_type(val.m_type), m_nbWords(val.m_nbWords),
+    m_valueArray(new SValue[val.m_nbWords]),
+    m_prev(nullptr), m_next(nullptr) {
   for (int i = 0; i < val.m_nbWords; i++) {
     m_valueArray[i] = val.m_valueArray[i];
   }
 }
 
-LValue::LValue(uint64_t val) {
-  m_type = Unsigned;
-  m_nbWords = 1;
-  m_valueArray = new SValue[1];
+LValue::LValue(uint64_t val)
+  : m_type(Type::Unsigned), m_nbWords(1),
+    m_valueArray(new SValue[1]), m_prev(nullptr), m_next(nullptr) {
   m_valueArray[0].m_value = val;
   m_valueArray[0].m_size = 64;
-  m_prev = NULL;
-  m_next = NULL;
 }
 
-LValue::LValue(int64_t val) {
-  m_type = Integer;
-  m_nbWords = 1;
-  m_valueArray = new SValue[1];
+LValue::LValue(int64_t val)
+  : m_type(Type::Integer), m_nbWords(1), m_valueArray(new SValue[1]),
+    m_prev(nullptr), m_next(nullptr) {
   m_valueArray[0].m_value = (uint64_t)val;
   m_valueArray[0].m_size = 64;
-  m_prev = NULL;
-  m_next = NULL;
 }
 
-LValue::LValue(double val) {
-  m_type = Double;
-  m_nbWords = 1;
-  m_valueArray = new SValue[1];
+LValue::LValue(double val)
+  : m_type(Type::Double), m_nbWords(1), m_valueArray(new SValue[1]),
+    m_prev(nullptr), m_next(nullptr) {
   m_valueArray[0].m_value = (uint64_t)val;
   m_valueArray[0].m_size = 64;
-  m_prev = NULL;
-  m_next = NULL;
 }
 
-LValue::LValue(uint64_t val, ValueType type, unsigned short size) {
-  m_type = type;
-  m_nbWords = 1;
-  m_valueArray = new SValue[1];
+LValue::LValue(uint64_t val, Type type, unsigned short size)
+  : m_type(type), m_nbWords(1), m_valueArray(new SValue[1]),
+    m_prev(nullptr), m_next(nullptr) {
   m_valueArray[0].m_value = val;
   m_valueArray[0].m_size = size;
-  m_prev = NULL;
-  m_next = NULL;
 }
 
 void LValue::set(uint64_t val) {
-  m_type = Unsigned;
+  m_type = Type::Unsigned;
   m_nbWords = 1;
   if (!m_valueArray) m_valueArray = new SValue[1];
   m_valueArray[0].m_value = val;
@@ -370,7 +353,7 @@
 }
 
 void LValue::set(int64_t val) {
-  m_type = Integer;
+  m_type = Type::Integer;
   m_nbWords = 1;
   if (!m_valueArray) m_valueArray = new SValue[1];
   m_valueArray[0].m_value = (uint64_t)val;
@@ -378,14 +361,14 @@
 }
 
 void LValue::set(double val) {
-  m_type = Double;
+  m_type = Type::Double;
   m_nbWords = 1;
   if (!m_valueArray) m_valueArray = new SValue[1];
   m_valueArray[0].m_value = (uint64_t)val;
   m_valueArray[0].m_size = 64;
 }
 
-void LValue::set(uint64_t val, ValueType type, unsigned short size) {
+void LValue::set(uint64_t val, Type type, unsigned short size) {
   m_type = type;
   m_nbWords = 1;
   if (!m_valueArray) m_valueArray = new SValue[1];
@@ -393,7 +376,7 @@
   m_valueArray[0].m_size = size;
 }
 
-void LValue::adjust(Value* a) {
+void LValue::adjust(const Value* a) {
   m_type = a->getType();
   if (a->getNbWords() > getNbWords()) {
     if (m_valueArray) delete[] m_valueArray;
@@ -402,7 +385,7 @@
   }
 }
 
-void LValue::u_plus(Value* a) {
+void LValue::u_plus(const Value* a) {
   adjust(a);
   for (unsigned int i = 0; i < m_nbWords; i++) {
     m_valueArray[i].m_value = a->getValueUL(i);
@@ -413,7 +396,7 @@
 
 void LValue::decr() { m_valueArray[0].m_value--; }
 
-void LValue::u_minus(Value* a) {
+void LValue::u_minus(const Value* a) {
   adjust(a);
   for (unsigned short i = 0; i < m_nbWords; i++) {
     m_valueArray[i].m_value = a->getValueUL(i);
@@ -423,7 +406,7 @@
   }
 }
 
-void LValue::u_not(Value* a) {
+void LValue::u_not(const Value* a) {
   adjust(a);
   for (unsigned int i = 0; i < m_nbWords; i++) {
     m_valueArray[0].m_value |= a->getValueUL(i);
@@ -431,32 +414,32 @@
   m_valueArray[0].m_value = !m_valueArray[0].m_value;
 }
 
-void LValue::u_tilda(Value* a) {
+void LValue::u_tilda(const Value* a) {
   adjust(a);
   for (unsigned int i = 0; i < m_nbWords; i++) {
     m_valueArray[i].m_value = ~a->getValueUL(i);
   }
 }
 
-void LValue::plus(Value* a, Value* b) {
+void LValue::plus(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) + b->getValueL(0);
 }
 
-void LValue::minus(Value* a, Value* b) {
+void LValue::minus(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) - b->getValueL(0);
 }
 
-void LValue::mult(Value* a, Value* b) {
+void LValue::mult(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) * b->getValueL(0);
 }
 
-void LValue::div(Value* a, Value* b) {
+void LValue::div(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   if (b->getValueL(0))
@@ -465,37 +448,37 @@
     m_valueArray[0].m_value = 69;
 }
 
-void LValue::mod(Value* a, Value* b) {
+void LValue::mod(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) % b->getValueL(0);
 }
 
-void LValue::greater(Value* a, Value* b) {
+void LValue::greater(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) > b->getValueL(0);
 }
 
-void LValue::greater_equal(Value* a, Value* b) {
+void LValue::greater_equal(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) >= b->getValueL(0);
 }
 
-void LValue::lesser(Value* a, Value* b) {
+void LValue::lesser(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) < b->getValueL(0);
 }
 
-void LValue::lesser_equal(Value* a, Value* b) {
+void LValue::lesser_equal(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueL(0) <= b->getValueL(0);
 }
 
-void LValue::equiv(Value* a, Value* b) {
+void LValue::equiv(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   for (unsigned int i = 0; i < m_nbWords; i++) {
@@ -507,7 +490,7 @@
   m_valueArray[0].m_value = 1;
 }
 
-void LValue::logAnd(Value* a, Value* b) {
+void LValue::logAnd(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   uint64_t tmp1 = 0;
@@ -519,7 +502,7 @@
   m_valueArray[0].m_value = tmp1 && tmp2;
 }
 
-void LValue::logOr(Value* a, Value* b) {
+void LValue::logOr(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   uint64_t tmp1 = 0;
@@ -531,7 +514,7 @@
   m_valueArray[0].m_value = tmp1 || tmp2;
 }
 
-void LValue::bitwAnd(Value* a, Value* b) {
+void LValue::bitwAnd(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   for (unsigned int i = 0; i < m_nbWords; i++) {
@@ -539,7 +522,7 @@
   }
 }
 
-void LValue::bitwOr(Value* a, Value* b) {
+void LValue::bitwOr(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   for (unsigned int i = 0; i < m_nbWords; i++) {
@@ -547,7 +530,7 @@
   }
 }
 
-void LValue::bitwXor(Value* a, Value* b) {
+void LValue::bitwXor(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   for (unsigned int i = 0; i < m_nbWords; i++) {
@@ -555,20 +538,20 @@
   }
 }
 
-void LValue::notEqual(Value* a, Value* b) {
+void LValue::notEqual(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   equiv(a, b);
   m_valueArray[0].m_value = !m_valueArray[0].m_value;
 }
 
-void LValue::shiftLeft(Value* a, Value* b) {
+void LValue::shiftLeft(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueUL(0) << b->getValueUL(0);
 }
 
-void LValue::shiftRight(Value* a, Value* b) {
+void LValue::shiftRight(const Value* a, const Value* b) {
   adjust(a);
   adjust(b);
   m_valueArray[0].m_value = a->getValueUL(0) >> b->getValueUL(0);
diff --git a/src/Expression/Value.h b/src/Expression/Value.h
index 4468713..34dfb33 100644
--- a/src/Expression/Value.h
+++ b/src/Expression/Value.h
@@ -39,7 +39,7 @@
   friend Expr;
   friend ValueFactory;
 
-  typedef enum {
+  enum class Type {
     None,
     Binary,
     Hexadecimal,
@@ -48,52 +48,64 @@
     Integer,
     Double,
     String
-  } ValueType;
+  };
 
-  virtual unsigned short getSize() = 0;  // size in bits
-  virtual unsigned short
-  getNbWords() = 0;  // nb of 64 bits words necessary to encode the size
-  virtual ValueType getType() = 0;
-  virtual bool isLValue() = 0;  // is large value (more than one 64 bit word)
-  virtual uint64_t getValueUL(unsigned short index = 0) = 0;
-  virtual int64_t getValueL(unsigned short index = 0) = 0;
-  virtual double getValueD(unsigned short index = 0) = 0;
-  virtual std::string getValueS() = 0;
+  virtual ~Value() {}
+
+  virtual unsigned short getSize() const = 0;  // size in bits
+
+  // nb of 64 bits words necessary to encode the size
+  virtual unsigned short getNbWords() const = 0;
+
+  virtual Type getType() const = 0;
+
+  // is large value (more than one 64 bit word)
+  virtual bool isLValue() const = 0;
+
+  virtual uint64_t getValueUL(unsigned short index = 0) const = 0;
+  virtual int64_t getValueL(unsigned short index = 0) const = 0;
+  virtual double getValueD(unsigned short index = 0) const = 0;
+  virtual std::string getValueS() const = 0;
+
   virtual void set(uint64_t val) = 0;
   virtual void set(int64_t val) = 0;
   virtual void set(double val) = 0;
-  virtual void set(uint64_t val, ValueType type, unsigned short size) = 0;
-  virtual void set(std::string val) = 0;
-  virtual bool operator<(Value& rhs) = 0;
-  bool operator>(Value& rhs) { return rhs < (*this); }
-  bool operator<=(Value& rhs) { return !(*this > rhs); }
-  bool operator>=(Value& rhs) { return !(*this < rhs); }
-  virtual bool operator==(Value& rhs) = 0;
-  bool operator!=(Value& rhs) { return !((*this) == rhs); }
-  virtual void u_plus(Value* a) = 0;
-  virtual void u_minus(Value* a) = 0;
-  virtual void u_not(Value* a) = 0;
-  virtual void u_tilda(Value* a) = 0;
+  virtual void set(uint64_t val, Type type, unsigned short size) = 0;
+  virtual void set(const std::string& val) = 0;
+
+  virtual bool operator<(const Value& rhs) const = 0;
+  virtual bool operator==(const Value& rhs) const = 0;
+
+  bool operator>(const Value& rhs) const { return rhs < (*this); }
+  bool operator<=(const Value& rhs) const { return !(*this > rhs); }
+  bool operator>=(const Value& rhs) const { return !(*this < rhs); }
+  bool operator!=(const Value& rhs) const { return !((*this) == rhs); }
+
+  virtual void u_plus(const Value* a) = 0;
+  virtual void u_minus(const Value* a) = 0;
+  virtual void u_not(const Value* a) = 0;
+  virtual void u_tilda(const Value* a) = 0;
   virtual void incr() = 0;
   virtual void decr() = 0;
-  virtual void plus(Value* a, Value* b) = 0;
-  virtual void minus(Value* a, Value* b) = 0;
-  virtual void mult(Value* a, Value* b) = 0;
-  virtual void div(Value* a, Value* b) = 0;
-  virtual void mod(Value* a, Value* b) = 0;
-  virtual void greater(Value* a, Value* b) = 0;
-  virtual void greater_equal(Value* a, Value* b) = 0;
-  virtual void lesser(Value* a, Value* b) = 0;
-  virtual void lesser_equal(Value* a, Value* b) = 0;
-  virtual void equiv(Value* a, Value* b) = 0;
-  virtual void logAnd(Value* a, Value* b) = 0;
-  virtual void logOr(Value* a, Value* b) = 0;
-  virtual void bitwAnd(Value* a, Value* b) = 0;
-  virtual void bitwOr(Value* a, Value* b) = 0;
-  virtual void bitwXor(Value* a, Value* b) = 0;
-  virtual void notEqual(Value* a, Value* b) = 0;
-  virtual void shiftLeft(Value* a, Value* b) = 0;
-  virtual void shiftRight(Value* a, Value* b) = 0;
+  virtual void plus(const Value* a, const Value* b) = 0;
+  virtual void minus(const Value* a, const Value* b) = 0;
+  virtual void mult(const Value* a, const Value* b) = 0;
+  virtual void div(const Value* a, const Value* b) = 0;
+  virtual void mod(const Value* a, const Value* b) = 0;
+
+  virtual void greater(const Value* a, const Value* b) = 0;
+  virtual void greater_equal(const Value* a, const Value* b) = 0;
+  virtual void lesser(const Value* a, const Value* b) = 0;
+  virtual void lesser_equal(const Value* a, const Value* b) = 0;
+  virtual void equiv(const Value* a, const Value* b) = 0;
+  virtual void logAnd(const Value* a, const Value* b) = 0;
+  virtual void logOr(const Value* a, const Value* b) = 0;
+  virtual void bitwAnd(const Value* a, const Value* b) = 0;
+  virtual void bitwOr(const Value* a, const Value* b) = 0;
+  virtual void bitwXor(const Value* a, const Value* b) = 0;
+  virtual void notEqual(const Value* a, const Value* b) = 0;
+  virtual void shiftLeft(const Value* a, const Value* b) = 0;
+  virtual void shiftRight(const Value* a, const Value* b) = 0;
 
  protected:
   unsigned int nbWords_(unsigned int size);
@@ -103,74 +115,65 @@
   friend LValue;
 
  public:
-  SValue() {
-    m_value = 0;
-    m_size = 0;
-  }
-  SValue(uint64_t val) {
-    m_value = val;
-    m_size = 64;
-  }
-  SValue(int64_t val) {
-    m_value = val;
-    m_size = 64;
-  }
-  SValue(double val) {
-    m_value = (uint64_t)val;
-    m_size = 64;
-  }
-  SValue(uint64_t val, unsigned short size) {
-    m_value = val;
-    m_size = size;
-  }
-  unsigned short getSize() { return m_size; }
-  unsigned short getNbWords() { return 1; }
-  bool isLValue() { return false; }
-  ValueType getType() { return None; }
-  void set(uint64_t val);
-  void set(int64_t val);
-  void set(double val);
-  void set(uint64_t val, ValueType type, unsigned short size);
-  void set(std::string val) {
+  SValue() : m_value(0), m_size(0) {}
+  SValue(uint64_t val, unsigned short size) : m_value(val), m_size(size) {}
+  SValue(uint64_t val) : SValue(val, 64) {}
+  SValue(int64_t val) : SValue(val, 64) {}
+  SValue(double val) : SValue((uint64_t)val, 64) {}
+  ~SValue() final;
+
+  unsigned short getSize() const final { return m_size; }
+  unsigned short getNbWords() const final { return 1; }
+  bool isLValue() const final { return false; }
+  Type getType() const final { return Type::None; }
+  void set(uint64_t val) final;
+  void set(int64_t val) final;
+  void set(double val) final;
+  void set(uint64_t val, Type type, unsigned short size) final;
+  void set(const std::string& val) final {
     m_value = 6969696969;
     m_size = 6969;
   }
-  bool operator<(Value& rhs) {
-    return m_value < (dynamic_cast<SValue*>(&rhs))->m_value;
-  }
-  bool operator==(Value& rhs) {
-    return m_value == (dynamic_cast<SValue*>(&rhs))->m_value;
-  }
-  uint64_t getValueUL(unsigned short index = 0) { return m_value; }
-  int64_t getValueL(unsigned short index = 0) { return (int64_t)m_value; }
-  double getValueD(unsigned short index = 0) { return (double)m_value; }
-  std::string getValueS() { return "NOT_A_STRING_VALUE"; }
-  virtual ~SValue();
 
-  void u_plus(Value* a);
-  void u_minus(Value* a);
-  void u_not(Value* a);
-  void u_tilda(Value* a);
-  void incr();
-  void decr();
-  void plus(Value* a, Value* b);
-  void minus(Value* a, Value* b);
-  void mult(Value* a, Value* b);
-  void div(Value* a, Value* b);
-  void mod(Value* a, Value* b);
-  void greater(Value* a, Value* b);
-  void greater_equal(Value* a, Value* b);
-  void lesser(Value* a, Value* b);
-  void lesser_equal(Value* a, Value* b);
-  void equiv(Value* a, Value* b);
-  void logAnd(Value* a, Value* b);
-  void logOr(Value* a, Value* b);
-  void bitwAnd(Value* a, Value* b);
-  void bitwOr(Value* a, Value* b);
-  void bitwXor(Value* a, Value* b);
-  void notEqual(Value* a, Value* b);
-  void shiftLeft(Value* a, Value* b);
-  void shiftRight(Value* a, Value* b);
+  bool operator<(const Value& rhs) const final {
+    return m_value < (dynamic_cast<const SValue*>(&rhs))->m_value;
+  }
+  bool operator==(const Value& rhs) const final {
+    return m_value == (dynamic_cast<const SValue*>(&rhs))->m_value;
+  }
+  uint64_t getValueUL(unsigned short index = 0) const final { return m_value; }
+  int64_t getValueL(unsigned short index = 0) const final {
+    return (int64_t)m_value;
+  }
+  double getValueD(unsigned short index = 0) const final {
+    return (double)m_value;
+  }
+  std::string getValueS() const final { return "NOT_A_STRING_VALUE"; }
+
+  void u_plus(const Value* a) final;
+  void u_minus(const Value* a) final;
+  void u_not(const Value* a) final;
+  void u_tilda(const Value* a) final;
+  void incr() final;
+  void decr() final;
+  void plus(const Value* a, const Value* b) final;
+  void minus(const Value* a, const Value* b) final;
+  void mult(const Value* a, const Value* b) final;
+  void div(const Value* a, const Value* b) final;
+  void mod(const Value* a, const Value* b) final;
+  void greater(const Value* a, const Value* b) final;
+  void greater_equal(const Value* a, const Value* b) final;
+  void lesser(const Value* a, const Value* b) final;
+  void lesser_equal(const Value* a, const Value* b) final;
+  void equiv(const Value* a, const Value* b) final;
+  void logAnd(const Value* a, const Value* b) final;
+  void logOr(const Value* a, const Value* b) final;
+  void bitwAnd(const Value* a, const Value* b) final;
+  void bitwOr(const Value* a, const Value* b) final;
+  void bitwXor(const Value* a, const Value* b) final;
+  void notEqual(const Value* a, const Value* b) final;
+  void shiftLeft(const Value* a, const Value* b) final;
+  void shiftRight(const Value* a, const Value* b) final;
 
  private:
   uint64_t m_value;
@@ -197,73 +200,69 @@
   friend ValueFactory;
 
  public:
-  LValue(LValue&);
-  LValue() {
-    m_type = None;
-    m_nbWords = 0;
-    m_valueArray = NULL;
-  }
-  LValue(ValueType type, SValue* values, unsigned short nbWords) {
-    m_type = type, m_valueArray = values;
-    m_nbWords = nbWords;
-  }
+  LValue(const LValue&);
+  LValue() : m_type(Type::None), m_nbWords(0), m_valueArray(nullptr) {}
+  LValue(Type type, SValue* values, unsigned short nbWords)
+    : m_type(type), m_nbWords(nbWords), m_valueArray(values) {}
   LValue(uint64_t val);
   LValue(int64_t val);
   LValue(double val);
-  LValue(uint64_t val, ValueType type, unsigned short size);
-  unsigned short getSize();
-  unsigned short getNbWords() { return m_nbWords; }
-  bool isLValue() { return true; }
-  ValueType getType() { return (ValueType)m_type; }
-  virtual ~LValue();
+  LValue(uint64_t val, Type type, unsigned short size);
+  ~LValue() final;
 
-  void set(uint64_t val);
-  void set(int64_t val);
-  void set(double val);
-  void set(uint64_t val, ValueType type, unsigned short size);
-  void set(std::string val) {}
-  bool operator<(Value& rhs);
-  bool operator==(Value& rhs);
+  unsigned short getSize() const final;
+  unsigned short getNbWords() const final { return m_nbWords; }
+  bool isLValue() const final { return true; }
+  Type getType() const final { return m_type; }
 
-  uint64_t getValueUL(unsigned short index = 0) {
+
+  void set(uint64_t val) final;
+  void set(int64_t val) final;
+  void set(double val) final;
+  void set(uint64_t val, Type type, unsigned short size) final;
+  void set(const std::string& val) final {}
+  bool operator<(const Value& rhs) const final;
+  bool operator==(const Value& rhs) const final;
+
+  uint64_t getValueUL(unsigned short index = 0) const final {
     return ((index < m_nbWords) ? m_valueArray[index].m_value : 0);
   }
-  int64_t getValueL(unsigned short index = 0) {
+  int64_t getValueL(unsigned short index = 0) const final {
     return ((index < m_nbWords) ? (int64_t)m_valueArray[index].m_value : 0);
   }
-  double getValueD(unsigned short index = 0) {
+  double getValueD(unsigned short index = 0) const final {
     return ((index < m_nbWords) ? (double)m_valueArray[index].m_value : 0);
   }
-  std::string getValueS() { return "NOT_A_STRING_VALUE"; }
-  void u_plus(Value* a);
-  void u_minus(Value* a);
-  void u_not(Value* a);
-  void u_tilda(Value* a);
-  void incr();
-  void decr();
-  void plus(Value* a, Value* b);
-  void minus(Value* a, Value* b);
-  void mult(Value* a, Value* b);
-  void div(Value* a, Value* b);
-  void mod(Value* a, Value* b);
-  void greater(Value* a, Value* b);
-  void greater_equal(Value* a, Value* b);
-  void lesser(Value* a, Value* b);
-  void lesser_equal(Value* a, Value* b);
-  void equiv(Value* a, Value* b);
-  void logAnd(Value* a, Value* b);
-  void logOr(Value* a, Value* b);
-  void bitwAnd(Value* a, Value* b);
-  void bitwOr(Value* a, Value* b);
-  void bitwXor(Value* a, Value* b);
-  void notEqual(Value* a, Value* b);
-  void shiftLeft(Value* a, Value* b);
-  void shiftRight(Value* a, Value* b);
+  std::string getValueS() const final { return "NOT_A_STRING_VALUE"; }
+  void u_plus(const Value* a) final;
+  void u_minus(const Value* a) final;
+  void u_not(const Value* a) final;
+  void u_tilda(const Value* a) final;
+  void incr() final;
+  void decr() final;
+  void plus(const Value* a, const Value* b) final;
+  void minus(const Value* a, const Value* b) final;
+  void mult(const Value* a, const Value* b) final;
+  void div(const Value* a, const Value* b) final;
+  void mod(const Value* a, const Value* b) final;
+  void greater(const Value* a, const Value* b) final;
+  void greater_equal(const Value* a, const Value* b) final;
+  void lesser(const Value* a, const Value* b) final;
+  void lesser_equal(const Value* a, const Value* b) final;
+  void equiv(const Value* a, const Value* b) final;
+  void logAnd(const Value* a, const Value* b) final;
+  void logOr(const Value* a, const Value* b) final;
+  void bitwAnd(const Value* a, const Value* b) final;
+  void bitwOr(const Value* a, const Value* b) final;
+  void bitwXor(const Value* a, const Value* b) final;
+  void notEqual(const Value* a, const Value* b) final;
+  void shiftLeft(const Value* a, const Value* b) final;
+  void shiftRight(const Value* a, const Value* b) final;
 
-  void adjust(Value* a);
+  void adjust(const Value* a);
 
  private:
-  unsigned short m_type;
+  Type m_type;
   unsigned short m_nbWords;
   SValue* m_valueArray;
   LValue* m_prev;
@@ -274,70 +273,65 @@
   friend LValue;
 
  public:
-  StValue() {
-    m_value = "";
-    m_size = 0;
-  }
-  StValue(std::string val) {
-    m_value = val;
-    m_size = val.size();
-  }
-  unsigned short getSize() { return m_size; }
-  unsigned short getNbWords() { return 1; }
-  bool isLValue() { return false; }
-  ValueType getType() { return String; }
-  void set(uint64_t val) { m_value = std::to_string(val); }
-  void set(int64_t val) { m_value = std::to_string(val); }
-  void set(double val) { m_value = std::to_string(val); }
-  void set(uint64_t val, ValueType type, unsigned short size) {
+  StValue() : m_value(""), m_size(0) {}
+  StValue(const std::string& val) : m_value(val), m_size(val.size()) {}
+  ~StValue() final;
+
+  unsigned short getSize() const final { return m_size; }
+  unsigned short getNbWords() const final { return 1; }
+  bool isLValue() const final { return false; }
+  Type getType() const final { return Type::String; }
+  void set(uint64_t val) final { m_value = std::to_string(val); }
+  void set(int64_t val) final { m_value = std::to_string(val); }
+  void set(double val) final { m_value = std::to_string(val); }
+  void set(uint64_t val, Type type, unsigned short size) final {
     m_value = std::to_string(val);
   }
-  void set(std::string val) {
+  void set(const std::string& val) final {
     m_value = val;
     m_size = val.size();
   }
-  bool operator<(Value& rhs) {
-    return m_value < (dynamic_cast<StValue*>(&rhs))->m_value;
+  bool operator<(const Value& rhs) const final {
+    return m_value < (dynamic_cast<const StValue*>(&rhs))->m_value;
   }
-  bool operator==(Value& rhs) {
-    return m_value == (dynamic_cast<StValue*>(&rhs))->m_value;
+  bool operator==(const Value& rhs) const final {
+    return m_value == (dynamic_cast<const StValue*>(&rhs))->m_value;
   }
-  uint64_t getValueUL(unsigned short index = 0) {
+  uint64_t getValueUL(unsigned short index = 0) const final {
     return atol(m_value.c_str());
   }
-  int64_t getValueL(unsigned short index = 0) {
+  int64_t getValueL(unsigned short index = 0) const final {
     return (int64_t)atol(m_value.c_str());
   }
-  double getValueD(unsigned short index = 0) {
-    return (double)atof(m_value.c_str());
+  double getValueD(unsigned short index = 0) const final {
+    return strtod(m_value.c_str(), NULL);
   }
-  std::string getValueS() { return m_value; }
-  virtual ~StValue();
+  std::string getValueS() const final { return m_value; }
 
-  void u_plus(Value* a) {}
-  void u_minus(Value* a) {}
-  void u_not(Value* a) {}
-  void u_tilda(Value* a) {}
-  void incr() {}
-  void decr() {}
-  void plus(Value* a, Value* b) {}
-  void minus(Value* a, Value* b) {}
-  void mult(Value* a, Value* b) {}
-  void div(Value* a, Value* b) {}
-  void mod(Value* a, Value* b) {}
-  void greater(Value* a, Value* b) {}
-  void greater_equal(Value* a, Value* b) {}
-  void lesser(Value* a, Value* b) {}
-  void lesser_equal(Value* a, Value* b) {}
-  void equiv(Value* a, Value* b) {}
-  void logAnd(Value* a, Value* b) {}
-  void logOr(Value* a, Value* b) {}
-  void bitwAnd(Value* a, Value* b) {}
-  void bitwOr(Value* a, Value* b) {}
-  void bitwXor(Value* a, Value* b) {}
-  void notEqual(Value* a, Value* b) {}
-  void shiftLeft(Value* a, Value* b) {}
-  void shiftRight(Value* a, Value* b) {}
+  void u_plus(const Value* a) final {}
+  void u_minus(const Value* a) final {}
+  void u_not(const Value* a) final {}
+  void u_tilda(const Value* a) final {}
+  void incr() final {}
+  void decr() final {}
+  void plus(const Value* a, const Value* b) final {}
+  void minus(const Value* a, const Value* b) final {}
+  void mult(const Value* a, const Value* b) final {}
+  void div(const Value* a, const Value* b) final {}
+  void mod(const Value* a, const Value* b) final {}
+  void greater(const Value* a, const Value* b) final {}
+  void greater_equal(const Value* a, const Value* b) final {}
+  void lesser(const Value* a, const Value* b) final {}
+  void lesser_equal(const Value* a, const Value* b) final {}
+  void equiv(const Value* a, const Value* b) final {}
+  void logAnd(const Value* a, const Value* b) final {}
+  void logOr(const Value* a, const Value* b) final {}
+  void bitwAnd(const Value* a, const Value* b) final {}
+  void bitwOr(const Value* a, const Value* b) final {}
+  void bitwXor(const Value* a, const Value* b) final {}
+  void notEqual(const Value* a, const Value* b) final {}
+  void shiftLeft(const Value* a, const Value* b) final {}
+  void shiftRight(const Value* a, const Value* b) final {}
 
  private:
   std::string m_value;