Introduce absyntax class for keyword ANY, and use REF_TO(ANY) as datatype of NULL literal.
authormjsousa
Fri, 08 Aug 2014 10:26:52 +0100
changeset 921 d228aaa4d616
parent 920 4369ce5e687f
child 922 1ba7a814098d
Introduce absyntax class for keyword ANY, and use REF_TO(ANY) as datatype of NULL literal.
absyntax/absyntax.def
absyntax_utils/get_datatype_info.cc
absyntax_utils/get_datatype_info.hh
absyntax_utils/search_base_type.cc
absyntax_utils/search_base_type.hh
stage3/fill_candidate_datatypes.cc
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.def	Wed Aug 06 10:43:15 2014 +0100
+++ b/absyntax/absyntax.def	Fri Aug 08 10:26:52 2014 +0100
@@ -295,6 +295,26 @@
 /* B.1.3.2 - Generic data types */
 /********************************/
 
+/* ANY is currently only allowed when defining REF_TO ANY datatypes
+ * (equivalent to a (void *)). This is a non standard extension to the
+ * standard.
+ * Standard library function that use the generic datatypes (ANY_***) are
+ * currently handed as overloaded functions, and do not therefore require
+ * the use of the generic datatype keywords.
+ */
+SYM_REF0(generic_type_any_c)            // ANY
+/*
+SYM_REF0(generic_type_any_derived_c)    // ANY_DERIVED
+SYM_REF0(generic_type_any_elementary_c) // ANY_ELEMENTARY
+SYM_REF0(generic_type_any_magnitude_c)  // ANY_MAGNITUDE
+SYM_REF0(generic_type_any_num_c)        // ANY_NUM
+SYM_REF0(generic_type_any_real_c)       // ANY_REAL
+SYM_REF0(generic_type_any_int_c)        // ANY_INT
+SYM_REF0(generic_type_any_bit_c)        // ANY_BIT
+SYM_REF0(generic_type_any_string_c)     // ANY_STRING
+SYM_REF0(generic_type_any_date_c)       // ANY_DATE
+*/
+
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
--- a/absyntax_utils/get_datatype_info.cc	Wed Aug 06 10:43:15 2014 +0100
+++ b/absyntax_utils/get_datatype_info.cc	Fri Aug 08 10:26:52 2014 +0100
@@ -238,20 +238,27 @@
 }
 
 
+/* Returns true if both datatypes are identicial.
+ * WARING: When handling REF_TO datatypes, it may return 'true' even though
+ *         the datatypes are not identicial. This occurs when at least one of the
+ *         datatypes if a ref_to_any_c, which os equivalent to a (void *), and the
+ *         other datatype is any REF_TO datatype (including a ref_to_any_c).
+ */
 bool get_datatype_info_c::is_type_equal(symbol_c *first_type, symbol_c *second_type) {
-  if ((NULL == first_type) || (NULL == second_type))                 {return false;}
-  if (typeid(* first_type) == typeid(invalid_type_name_c))           {return false;}
-  if (typeid(*second_type) == typeid(invalid_type_name_c))           {return false;}
-    
+  if (!is_type_valid( first_type))                                   {return false;}
+  if (!is_type_valid(second_type))                                   {return false;}
+
+  /* GENERIC DATATYPES */
+  /* For the moment, we only support the ANY generic datatype! */
+  if ((is_ANY_generic_type( first_type)) ||
+      (is_ANY_generic_type(second_type)))                            {return true;}
+      
   /* ANY_ELEMENTARY */
   if ((is_ANY_ELEMENTARY(first_type)) &&
       (typeid(*first_type) == typeid(*second_type)))                 {return true;}
 
   /* ANY_DERIVED */
   if (is_ref_to(first_type) && is_ref_to(second_type)) {
-    /* if either of them is the constant 'NULL' then we consider them 'equal', as NULL is compatible to a REF_TO any datatype! */
-    if (typeid(* first_type) == typeid(ref_value_null_literal_c))    {return true;}  
-    if (typeid(*second_type) == typeid(ref_value_null_literal_c))    {return true;}
     return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )),
                          search_base_type_c::get_basetype_decl(get_ref_to(second_type)));
   }
@@ -260,7 +267,6 @@
 }
 
 
-
 bool get_datatype_info_c::is_type_valid(symbol_c *type) {
   if (NULL == type)                                                  {return false;}
   if (typeid(*type) == typeid(invalid_type_name_c))                  {return false;}
@@ -299,7 +305,6 @@
   if (typeid(*type_decl) == typeid(ref_type_decl_c))                           {return true;}   /* identifier ':' ref_spec_init */
   if (typeid(*type_decl) == typeid(ref_spec_init_c))                           {return true;}   /* ref_spec [ ASSIGN ref_initialization ]; */
   if (typeid(*type_decl) == typeid(ref_spec_c))                                {return true;}   /* REF_TO (non_generic_type_name | function_block_type_name) */
-  if (typeid(*type_decl) == typeid(ref_value_null_literal_c))                  {return true;}   /* REF_TO (non_generic_type_name | function_block_type_name) */
   return false;
 }
 
@@ -404,6 +409,12 @@
 
 
 
+bool get_datatype_info_c::is_ANY_generic_type(symbol_c *type_symbol) {
+  symbol_c *type_decl = search_base_type_c::get_basetype_decl(type_symbol);
+  if (NULL == type_decl)                                             {return false;}  
+  if (typeid(*type_decl) == typeid(generic_type_any_c))              {return true;}   /*  The ANY keyword! */
+  return false;
+}
 
 
 bool get_datatype_info_c::is_ANY_ELEMENTARY(symbol_c *type_symbol) {
--- a/absyntax_utils/get_datatype_info.hh	Wed Aug 06 10:43:15 2014 +0100
+++ b/absyntax_utils/get_datatype_info.hh	Fri Aug 08 10:26:52 2014 +0100
@@ -62,6 +62,12 @@
 
     static symbol_c *get_ref_to                    (symbol_c *type_symbol);    // Defined in IEC 61131-3 v3 (returns the type that is being referenced/pointed to)        
     
+    /* Returns true if both datatypes are identicial.
+     * WARING: When handling REF_TO datatypes, it may return 'true' even though
+     *         the datatypes are not identicial. This occurs when at least one of the
+     *         datatypes if a ref_to_any_c, which os equivalent to a (void *), and the
+     *         other datatype is any REF_TO datatype (including a ref_to_any_c).
+     */
     static bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
     static bool is_type_valid(symbol_c *type);
 
@@ -77,10 +83,14 @@
     static bool is_ANY_REAL_literal(symbol_c *type_symbol); /* Can't we do away with this?? */
     static bool is_ANY_INT_literal (symbol_c *type_symbol); /* Can't we do away with this?? */
 
+    static bool is_ANY_generic_type                (symbol_c *type_symbol);
+
+    //static bool is_ANY_ELEMENTARY_generic_type   (symbol_c *type_symbol);
     static bool is_ANY_ELEMENTARY                  (symbol_c *type_symbol);
     static bool is_ANY_SAFEELEMENTARY              (symbol_c *type_symbol);
     static bool is_ANY_ELEMENTARY_compatible       (symbol_c *type_symbol);
 
+    //static bool is_ANY_MAGNITUDE_generic_type    (symbol_c *type_symbol);
     static bool is_ANY_MAGNITUDE                   (symbol_c *type_symbol);
     static bool is_ANY_SAFEMAGNITUDE               (symbol_c *type_symbol);
     static bool is_ANY_MAGNITUDE_compatible        (symbol_c *type_symbol);
@@ -89,6 +99,7 @@
     static bool is_ANY_signed_SAFEMAGNITUDE        (symbol_c *type_symbol);
     static bool is_ANY_signed_MAGNITUDE_compatible (symbol_c *type_symbol);
 
+    //static bool is_ANY_NUM_generic_type          (symbol_c *type_symbol);
     static bool is_ANY_NUM                         (symbol_c *type_symbol);
     static bool is_ANY_SAFENUM                     (symbol_c *type_symbol);
     static bool is_ANY_NUM_compatible              (symbol_c *type_symbol);
@@ -97,6 +108,7 @@
     static bool is_ANY_signed_SAFENUM              (symbol_c *type_symbol);
     static bool is_ANY_signed_NUM_compatible       (symbol_c *type_symbol);
 
+    //static bool is_ANY_INT_generic_type          (symbol_c *type_symbol);
     static bool is_ANY_INT                         (symbol_c *type_symbol);
     static bool is_ANY_SAFEINT                     (symbol_c *type_symbol);
     static bool is_ANY_INT_compatible              (symbol_c *type_symbol);
@@ -109,6 +121,7 @@
     static bool is_ANY_unsigned_SAFEINT            (symbol_c *type_symbol);
     static bool is_ANY_unsigned_INT_compatible     (symbol_c *type_symbol);
 
+    //static bool is_ANY_REAL_generic_type         (symbol_c *type_symbol);
     static bool is_ANY_REAL                        (symbol_c *type_symbol);
     static bool is_ANY_SAFEREAL                    (symbol_c *type_symbol);
     static bool is_ANY_REAL_compatible             (symbol_c *type_symbol);
@@ -121,10 +134,12 @@
     static bool is_SAFEBOOL                        (symbol_c *type_symbol);
     static bool is_BOOL_compatible                 (symbol_c *type_symbol);
 
+    //static bool is_ANY_BIT_generic_type          (symbol_c *type_symbol);
     static bool is_ANY_BIT                         (symbol_c *type_symbol);
     static bool is_ANY_SAFEBIT                     (symbol_c *type_symbol);
     static bool is_ANY_BIT_compatible              (symbol_c *type_symbol);
 
+    //static bool is_ANY_DATE_generic_type         (symbol_c *type_symbol);
     static bool is_ANY_DATE                        (symbol_c *type_symbol);
     static bool is_ANY_SAFEDATE                    (symbol_c *type_symbol);
     static bool is_ANY_DATE_compatible             (symbol_c *type_symbol);
@@ -133,6 +148,7 @@
     static bool is_SAFETIME                        (symbol_c *type_symbol);
     static bool is_TIME_compatible                 (symbol_c *type_symbol);
 
+    //static bool is_ANY_STRING_generic_type       (symbol_c *type_symbol);
     static bool is_ANY_STRING                      (symbol_c *type_symbol);
     static bool is_ANY_SAFESTRING                  (symbol_c *type_symbol);
     static bool is_ANY_STRING_compatible           (symbol_c *type_symbol);
--- a/absyntax_utils/search_base_type.cc	Wed Aug 06 10:43:15 2014 +0100
+++ b/absyntax_utils/search_base_type.cc	Fri Aug 08 10:26:52 2014 +0100
@@ -133,12 +133,6 @@
 /*********************/
 /* B 1.2 - Constants */
 /*********************/
-/*********************************/
-/* B 1.2.XX - Reference Literals */
-/*********************************/
-/* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */
-/* See the comment in fill_candidate_datatypes_c::visit(ref_value_null_literal_c) for reason why we use this symbol as a datatype! */
-void *search_base_type_c::visit(ref_value_null_literal_c *symbol) {return (void *)symbol;}
 
 /******************************/
 /* B 1.2.1 - Numeric Literals */
@@ -218,6 +212,11 @@
 void *search_base_type_c::visit(safewstring_type_name_c *symbol)  {return (void *)symbol;}
 
 /********************************/
+/* B.1.3.2 - Generic data types */
+/********************************/
+void *search_base_type_c::visit(generic_type_any_c *symbol)       {return (void *)symbol;}
+
+/********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
 /*  simple_type_name ':' simple_spec_init */
--- a/absyntax_utils/search_base_type.hh	Wed Aug 06 10:43:15 2014 +0100
+++ b/absyntax_utils/search_base_type.hh	Fri Aug 08 10:26:52 2014 +0100
@@ -94,12 +94,6 @@
   /*********************/
   /* B 1.2 - Constants */
   /*********************/
-  /*********************************/
-  /* B 1.2.XX - Reference Literals */
-  /*********************************/
-  /* defined in IEC 61131-3 v3 - Basically the 'NULL' keyword! */
-    void *visit(ref_value_null_literal_c *symbol);
-    
   /******************************/
   /* B 1.2.1 - Numeric Literals */
   /******************************/
@@ -176,6 +170,11 @@
     void *visit(safewstring_type_name_c *symbol);
 
   /********************************/
+  /* B.1.3.2 - Generic data types */
+  /********************************/
+  void *visit(generic_type_any_c *symbol);
+
+  /********************************/
   /* B 1.3.3 - Derived data types */
   /********************************/
   /*  simple_type_name ':' simple_spec_init */
--- a/stage3/fill_candidate_datatypes.cc	Wed Aug 06 10:43:15 2014 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Fri Aug 08 10:26:52 2014 +0100
@@ -720,15 +720,10 @@
 	 * However, doing this for all NULL constants that may show up is probably a little too crazy, just for 
 	 * the 'pleasure' of following the standard fill/narrow algorithm.
 	 *
-	 * I have therefore opted to handle this as a special case: We use the ref_value_null_literal_c symbol itself as the NULL datatype!
-	 * This implies the following changes:
-	 *   - We change the get_datatype_info_c::is_type_equal() to take the NULL datatype into account
-	 *   - We change the get_datatype_info_c::is_ref_to()     to take the NULL datatype into account
-	 *   - We change the fill_candidate_datatypes_c::visit(assignment_statement_c) to make sure it uses the datatype of the lvalue 
-	 *            as the datatype of the assignment statement
-	 *   - We search_base_type_c::get_basetype_decl
+	 * I have therefore opted to handle this as a special case:
+	 *     We use the ref_spec_c, pointing to a generic_type_any_c, as a pointer to ANY (basically, a void *)
 	 */
-	add_datatype_to_candidate_list(symbol, symbol);
+	add_datatype_to_candidate_list(symbol, new ref_spec_c(new generic_type_any_c()));
 	return NULL;
 }
 
--- a/stage4/generate_iec/generate_iec.cc	Wed Aug 06 10:43:15 2014 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Fri Aug 08 10:26:52 2014 +0100
@@ -434,6 +434,10 @@
 void *visit(safestring_type_name_c *symbol)  {s4o.print("SAFESTRING");  return NULL;}
 void *visit(safewstring_type_name_c *symbol) {s4o.print("SAFEWSTRING"); return NULL;}
 
+/********************************/
+/* B.1.3.2 - Generic data types */
+/********************************/
+void *visit(generic_type_any_c      *symbol) {s4o.print("ANY");         return NULL;}
 
 /********************************/
 /* B 1.3.3 - Derived data types */