Change negation expression (neg_expression_c) to only allow signed data types.
authorMario de Sousa <msousa@fe.up.pt>
Wed, 08 Feb 2012 18:16:13 +0000
changeset 435 82cb6a64a763
parent 434 c1278e52bcbc
child 436 f9fd63f64f5c
Change negation expression (neg_expression_c) to only allow signed data types.
stage3/datatype_functions.cc
stage3/datatype_functions.hh
stage3/fill_candidate_datatypes.cc
--- a/stage3/datatype_functions.cc	Tue Feb 07 17:45:17 2012 +0000
+++ b/stage3/datatype_functions.cc	Wed Feb 08 18:16:13 2012 +0000
@@ -220,6 +220,13 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_MAGNITUDE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
+  return is_ANY_signed_NUM_type(type_symbol);
+}
+
+/* A helper function... */
 bool is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
@@ -227,15 +234,29 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
+  return is_ANY_signed_SAFENUM_type(type_symbol);
+}
+
+/* A helper function... */
 bool is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (is_ANY_MAGNITUDE_type    (type_symbol))              {return true;}
   if (is_ANY_SAFEMAGNITUDE_type(type_symbol))              {return true;}
-
   return is_ANY_NUM_compatible(type_symbol);
 }
 
 /* A helper function... */
+bool is_ANY_signed_MAGNITUDE_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_signed_MAGNITUDE_type    (type_symbol))       {return true;}
+  if (is_ANY_signed_SAFEMAGNITUDE_type(type_symbol))       {return true;}
+  return is_ANY_signed_NUM_compatible(type_symbol);
+}
+
+/* A helper function... */
 bool is_ANY_NUM_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (is_ANY_REAL_type(type_symbol))                       {return true;}
@@ -244,6 +265,14 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_NUM_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_REAL_type(type_symbol))                       {return true;}
+  if (is_ANY_signed_INT_type(type_symbol))                 {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool is_ANY_SAFENUM_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   return is_ANY_SAFEREAL_type(type_symbol)
@@ -251,6 +280,13 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_SAFENUM_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  return is_ANY_SAFEREAL_type(type_symbol)
+      || is_ANY_signed_SAFEINT_type (type_symbol);
+}
+
+/* A helper function... */
 bool is_ANY_NUM_compatible(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (is_ANY_REAL_compatible(type_symbol))                       {return true;}
@@ -259,6 +295,14 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_NUM_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_REAL_compatible(type_symbol))                       {return true;}
+  if (is_ANY_signed_INT_compatible(type_symbol))                 {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool is_ANY_DATE_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
@@ -324,6 +368,26 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_INT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(sint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(int_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(dint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lint_type_name_c))  {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_signed_SAFEINT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safesint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safeint_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(safedint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safelint_type_name_c))  {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool is_ANY_SAFEINT_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (typeid(*type_symbol) == typeid(safesint_type_name_c))  {return true;}
@@ -338,6 +402,15 @@
 }
 
 /* A helper function... */
+bool is_ANY_signed_INT_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_signed_INT_type    (type_symbol))              {return true;}
+  if (is_ANY_signed_SAFEINT_type(type_symbol))              {return true;}
+//   if (is_literal_integer_type(type_symbol))          {return true;}
+  return false;
+}
+
+/* A helper function... */
 bool is_ANY_INT_compatible(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
   if (is_ANY_INT_type    (type_symbol))              {return true;}
--- a/stage3/datatype_functions.hh	Tue Feb 07 17:45:17 2012 +0000
+++ b/stage3/datatype_functions.hh	Wed Feb 08 18:16:13 2012 +0000
@@ -133,6 +133,10 @@
 bool is_ANY_SAFEMAGNITUDE_type      (symbol_c *type_symbol);
 bool is_ANY_MAGNITUDE_compatible    (symbol_c *type_symbol);
 
+bool is_ANY_signed_MAGNITUDE_type          (symbol_c *type_symbol);
+bool is_ANY_signed_SAFEMAGNITUDE_type      (symbol_c *type_symbol);
+bool is_ANY_signed_MAGNITUDE_compatible    (symbol_c *type_symbol);
+
 bool is_ANY_DATE_type               (symbol_c *type_symbol);
 bool is_ANY_SAFEDATE_type           (symbol_c *type_symbol);
 bool is_ANY_DATE_compatible         (symbol_c *type_symbol);
@@ -145,6 +149,10 @@
 bool is_ANY_SAFEINT_type            (symbol_c *type_symbol);
 bool is_ANY_INT_compatible          (symbol_c *type_symbol);
 
+bool is_ANY_signed_INT_type                (symbol_c *type_symbol);
+bool is_ANY_signed_SAFEINT_type            (symbol_c *type_symbol);
+bool is_ANY_signed_INT_compatible          (symbol_c *type_symbol);
+
 bool is_ANY_REAL_type               (symbol_c *type_symbol);
 bool is_ANY_SAFEREAL_type           (symbol_c *type_symbol);
 bool is_ANY_REAL_compatible         (symbol_c *type_symbol);
@@ -153,6 +161,10 @@
 bool is_ANY_SAFENUM_type            (symbol_c *type_symbol);
 bool is_ANY_NUM_compatible          (symbol_c *type_symbol);
 
+bool is_ANY_signed_NUM_type                (symbol_c *type_symbol);
+bool is_ANY_signed_SAFENUM_type            (symbol_c *type_symbol);
+bool is_ANY_signed_NUM_compatible          (symbol_c *type_symbol);
+
 bool is_ANY_BIT_type                (symbol_c *type_symbol);
 bool is_ANY_SAFEBIT_type            (symbol_c *type_symbol);
 bool is_ANY_BIT_compatible          (symbol_c *type_symbol);
--- a/stage3/fill_candidate_datatypes.cc	Tue Feb 07 17:45:17 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Wed Feb 08 18:16:13 2012 +0000
@@ -1666,9 +1666,33 @@
 
 
 void *fill_candidate_datatypes_c::visit(neg_expression_c *symbol) {
+  /* NOTE: The standard defines the syntax for this 'negation' operation, but
+   *       does not define the its semantics.
+   *
+   *       We could be tempted to consider that the semantics of the
+   *       'negation' operation are similar/identical to the semantics of the 
+   *       SUB expression/operation. This would include assuming that the
+   *       possible datatypes for the 'negation' operation is also
+   *       the same as those for the SUB expression/operation, namely ANY_MAGNITUDE.
+   *
+   *       However, this would then mean that the following ST code would be 
+   *       syntactically and semantically correct:
+   *       uint_var := - (uint_var);
+   *
+   *       According to the standard, the above code should result in a 
+   *       runtime error, when we try to apply a negative value to the
+   *       UINT typed variable 'uint_var'.
+   *
+   *       It is much easier for the compiler to detect this at compile time,
+   *       and it is probably safer to the resulting code too.
+   *
+   *       To detect these tyes of errors at compile time, the easisest solution
+   *       is to only allow ANY_NUM datatytpes that are signed.
+   *        So, that is what we do here!
+   */
 	symbol->exp->accept(*this);
 	for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
-		if (is_ANY_MAGNITUDE_compatible(symbol->exp->candidate_datatypes[i]))
+		if (is_ANY_signed_MAGNITUDE_compatible(symbol->exp->candidate_datatypes[i]))
 			symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]);
 	}
 	if (debug) std::cout << "neg [" << symbol->exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";