Fix bug with functions like LEN and TRUNC that have overloaded return type for same inputs type
authorlaurent
Fri, 03 Feb 2012 00:09:52 +0100
changeset 399 55b074ea7255
parent 398 f1f3facc59e7
child 400 093b72cd2ac3
child 401 7f052bd3508a
child 495 8c6823fee086
Fix bug with functions like LEN and TRUNC that have overloaded return type for same inputs type
absyntax/absyntax.def
absyntax_utils/search_constant_type.cc
absyntax_utils/search_constant_type.hh
stage3/visit_expression_type.cc
stage3/visit_expression_type.hh
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_il.cc
stage4/generate_c/generate_c_inlinefcall.cc
stage4/generate_c/generate_c_st.cc
--- a/absyntax/absyntax.def	Thu Feb 02 00:34:04 2012 +0100
+++ b/absyntax/absyntax.def	Fri Feb 03 00:09:52 2012 +0100
@@ -920,10 +920,11 @@
 SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
 
 /* | function_name [il_operand_list] */
-/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass 
+ *       data between the stage 3 and stage 4.
  *       See the comment above function_invocation_c for more details 
  */
-SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
+SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;)
 
 
 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
@@ -942,10 +943,11 @@
 
 
 /* | function_name '(' eol_list [il_param_list] ')' */
-/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass 
+ *       data between the stage 3 and stage 4.
  *       See the comment above function_invocation_c for more details 
  */
-SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
+SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;)
 
 /* | il_operand_list ',' il_operand */
 SYM_LIST(il_operand_list_c)
@@ -1045,7 +1047,8 @@
 
 /*    formal_param_list -> may be NULL ! */
 /* nonformal_param_list -> may be NULL ! */
-/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
+/* NOTE: The parameters 'called_function_declaration' and 'overloaded_return_type' are used to pass 
+ *        data between the stage 3 and stage 4.
  *       The IEC 61131-3 standard allows for overloaded standard functions. This means that some
  *       function calls are not compeletely defined by the name of the function being called,
  *       and need to be disambiguated with using the data types of the parameters being passed.
@@ -1055,7 +1058,7 @@
  *       and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration
  *       for stage 4 to use it later on.
  */
-SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
+SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; symbol_c *overloaded_return_type; int extensible_param_count;)
 
 
 /********************/
--- a/absyntax_utils/search_constant_type.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/absyntax_utils/search_constant_type.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -168,3 +168,4 @@
 /* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
 /* It should then move to search_expression_type_c                               */
 integer_c search_constant_type_c::integer("1");
+real_c search_constant_type_c::real("1.0");
--- a/absyntax_utils/search_constant_type.hh	Thu Feb 02 00:34:04 2012 +0100
+++ b/absyntax_utils/search_constant_type.hh	Fri Feb 03 00:09:52 2012 +0100
@@ -79,6 +79,7 @@
 
 /* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
   static integer_c      integer;
+  static real_c			real;
 
   /******************************************************/
   /* Extensions to the base standard as defined in      */
--- a/stage3/visit_expression_type.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage3/visit_expression_type.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -566,6 +566,31 @@
   return common_type__(first_type, second_type);
 }
 
+symbol_c *visit_expression_type_c::common_literal(symbol_c *first_type, symbol_c *second_type) {
+  printf("common_literal: %d == %d, %d == %d, %d == %d\n",
+		 (int)is_ANY_INT_compatible(first_type),
+		 (int)is_ANY_INT_compatible(second_type),
+		 (int)is_ANY_REAL_compatible(first_type),
+		 (int)is_ANY_REAL_compatible(second_type),
+		 (int)is_ANY_BIT_compatible(first_type),
+		 (int)is_ANY_BIT_compatible(second_type));
+  if ((is_ANY_INT_compatible(first_type) && is_ANY_INT_compatible(second_type)) ||
+	  (is_ANY_BIT_compatible(first_type) && is_ANY_BIT_compatible(second_type)))
+	 return &search_constant_type_c::integer;
+  else if (is_ANY_REAL_compatible(first_type) && is_ANY_REAL_compatible(second_type))
+	 return &search_constant_type_c::real;
+  return NULL;
+}
+
+symbol_c *visit_expression_type_c::overloaded_return_type(symbol_c *type) {
+  if (is_ANY_INT_compatible(type))
+	return &search_constant_type_c::ulint_type_name;
+  else if (is_ANY_REAL_compatible(type))
+	return &search_constant_type_c::lreal_type_name;
+  else if (is_ANY_BIT_compatible(type))
+  	return &search_constant_type_c::lword_type_name;
+  return NULL;
+}
 
 /* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
  * such as: 
@@ -1042,6 +1067,8 @@
     return NULL;
 
   symbol_c *return_data_type = NULL;
+  symbol_c* fdecl_return_type;
+  symbol->called_function_declaration = NULL;
 
   /* First find the declaration of the function being called! */
   function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
@@ -1067,25 +1094,40 @@
        * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
        * (ii) we have a call to an overloaded function, with no errors!
        */
+
+      fdecl_return_type = base_type(f_decl->type_name);
+
+      if (symbol->called_function_declaration == NULL) {
+      	/* Store the pointer to the declaration of the function being called.
+      	 * This data will be used by stage 4 to call the correct function.
+      	 * Mostly needed to disambiguate overloaded functions...
+      	 * See comments in absyntax.def for more details
+         */
+        symbol->called_function_declaration = f_decl;
+  		symbol->overloaded_return_type = NULL;
+
+  		/* determine the base data type returned by the function being called... */
+  	    return_data_type = fdecl_return_type;
+  	  }
+  	  else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){
+  		if (symbol->overloaded_return_type == NULL)
+  		  symbol->overloaded_return_type = overloaded_return_type(return_data_type);
+  		return_data_type = common_literal(return_data_type, fdecl_return_type);
+  	  }
       
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      /* determine the base data type returned by the function being called... */
-      return_data_type = base_type(f_decl->type_name);
-      /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */
       if (NULL == return_data_type) ERROR;
-      /* set the new data type of the default variable for the following verifications... */
-      il_default_variable_type = return_data_type;
-      return NULL;
     }
   }
 
-  /* No compatible function was found for this function call */
-  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
+  if (NULL == return_data_type) {
+    /* No compatible function was found for this function call */
+    STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
+  }
+  else {
+    /* set the new data type of the default variable for the following verifications... */
+    il_default_variable_type = return_data_type;
+  }
+
   return NULL;
 }
 
@@ -1206,6 +1248,9 @@
     return NULL;
 
   symbol_c *return_data_type = NULL;
+  symbol_c* fdecl_return_type;
+  symbol->called_function_declaration = NULL;
+
   function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
   function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
   
@@ -1235,25 +1280,42 @@
        * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
        * (ii) we have a call to an overloaded function, with no errors!
        */
-      
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      /* determine the base data type returned by the function being called... */
-      return_data_type = base_type(f_decl->type_name);
+
+      fdecl_return_type = base_type(f_decl->type_name);
+
+      if (symbol->called_function_declaration == NULL) {
+    	/* Store the pointer to the declaration of the function being called.
+    	 * This data will be used by stage 4 to call the correct function.
+    	 * Mostly needed to disambiguate overloaded functions...
+    	 * See comments in absyntax.def for more details
+         */
+        symbol->called_function_declaration = f_decl;
+		symbol->overloaded_return_type = NULL;
+
+		/* determine the base data type returned by the function being called... */
+		return_data_type = fdecl_return_type;
+	  }
+	  else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){
+		if (symbol->overloaded_return_type == NULL)
+		  symbol->overloaded_return_type = overloaded_return_type(return_data_type);
+		return_data_type = common_literal(return_data_type, fdecl_return_type);
+	  }
+
       /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */
       if (NULL == return_data_type) ERROR;
-      /* the data type of the data returned by the function, and stored in the il default variable... */
-      il_default_variable_type = return_data_type;
-      return NULL;
-    }  
+
+    }
   }
   
-  /* No compatible function was found for this function call */
-  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
+  if (NULL == return_data_type) {
+	/* No compatible function was found for this function call */
+	STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
+  }
+  else {
+    /* the data type of the data returned by the function, and stored in the il default variable... */
+    il_default_variable_type = return_data_type;
+  }
+
   return NULL;
 }
 
@@ -2007,6 +2069,10 @@
   function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
   if (lower == function_symtable.end()) ERROR;
 
+  symbol_c* return_data_type;
+  symbol_c* fdecl_return_type;
+  symbol->called_function_declaration = NULL;
+
   function_symtable_t::iterator second = lower;
   second++;
   if (second == upper) {
@@ -2024,6 +2090,7 @@
      * See comments in absyntax.def for more details
      */
     symbol->called_function_declaration = f_decl;
+    symbol->overloaded_return_type = NULL;
     return base_type(f_decl->type_name);
   }  
 
@@ -2036,16 +2103,34 @@
     if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl, &error_count);
     if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count);
     if (0 == error_count) {
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      return base_type(f_decl->type_name);
+
+      fdecl_return_type = base_type(f_decl->type_name);
+
+      if (symbol->called_function_declaration == NULL) {
+        /* Store the pointer to the declaration of the function being called.
+         * This data will be used by stage 4 to call the correct function.
+         * Mostly needed to disambiguate overloaded functions...
+         * See comments in absyntax.def for more details
+         */
+        symbol->called_function_declaration = f_decl;
+        symbol->overloaded_return_type = NULL;
+
+        /* determine the base data type returned by the function being called... */
+        return_data_type = fdecl_return_type;
+      }
+      else if (typeid(*return_data_type) != typeid(*fdecl_return_type)){
+      	if (symbol->overloaded_return_type == NULL)
+      	  symbol->overloaded_return_type = overloaded_return_type(return_data_type);
+      	return_data_type = common_literal(return_data_type, fdecl_return_type);
+      }
+
+      if (NULL == return_data_type) ERROR;
     }
   }
 
+  if (return_data_type != NULL)
+	return return_data_type;
+
   /* No compatible function was found for this function call */
   STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
   return NULL;
--- a/stage3/visit_expression_type.hh	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage3/visit_expression_type.hh	Fri Feb 03 00:09:52 2012 +0100
@@ -156,6 +156,10 @@
      *  if no common data type is found.
      */
     symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
+
+    symbol_c *common_literal(symbol_c *first_type, symbol_c *second_type);
+    symbol_c *overloaded_return_type(symbol_c *type);
+
 /* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
  * such as: 
  *     var_type     value_type
--- a/stage4/generate_c/generate_c.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage4/generate_c/generate_c.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -182,6 +182,7 @@
 class print_function_parameter_data_types_c: public generate_c_base_c {
   private:
     symbol_c *current_type;
+    symbol_c *return_type;
     bool_type_name_c tmp_bool;
 
     void print_list(symbol_c *var_list, symbol_c *data_type) { 
@@ -197,9 +198,11 @@
     }
     
   public:
-    print_function_parameter_data_types_c(stage4out_c *s4o_ptr): 
-      generate_c_base_c(s4o_ptr)
-      {current_type = NULL;}
+    print_function_parameter_data_types_c(stage4out_c *s4o_ptr, symbol_c* return_type):
+      generate_c_base_c(s4o_ptr) {
+    	current_type = NULL;
+    	this->return_type = return_type;
+      }
 
     /**************************************/
     /* B.1.5 - Program organization units */
@@ -210,7 +213,11 @@
     /*   FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
     /* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
     void *visit(function_declaration_c *symbol) {
-      symbol->type_name->accept(*this); /* return type */
+      /* return type */
+      if (this->return_type == NULL)
+    	symbol->type_name->accept(*this);
+      else
+    	this->return_type->accept(*this);
       symbol->var_declarations_list->accept(*this);
       return NULL;
     }
--- a/stage4/generate_c/generate_c_il.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -962,7 +962,7 @@
     if (fdecl_mutiplicity == 2) {
       /* function being called is overloaded! */
       s4o.print("__");
-      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
       f_decl->accept(overloaded_func_suf);
     }
     s4o.print_integer(fcall_number);
@@ -973,7 +973,7 @@
           if (fdecl_mutiplicity == 2) {
             /* function being called is overloaded! */
             s4o.print("__");
-            print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+            print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
             f_decl->accept(overloaded_func_suf);
           }
     }	  
@@ -1370,7 +1370,7 @@
     if (fdecl_mutiplicity == 2) {
       /* function being called is overloaded! */
       s4o.print("__");
-      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
       f_decl->accept(overloaded_func_suf);
     }
     s4o.print_integer(fcall_number);
@@ -1381,7 +1381,7 @@
       if (fdecl_mutiplicity == 2) {
         /* function being called is overloaded! */
         s4o.print("__");
-        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
         f_decl->accept(overloaded_func_suf);
       }
     }  
--- a/stage4/generate_c/generate_c_inlinefcall.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage4/generate_c/generate_c_inlinefcall.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -169,7 +169,7 @@
       if (f_decl != NULL) {
         /* function being called is overloaded! */
         s4o.print("__");
-        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o, function_type_prefix);
         f_decl->accept(overloaded_func_suf);
       }	
       if (function_type_suffix) {
@@ -222,7 +222,7 @@
       if (f_decl != NULL) {
     	/* function being called is overloaded! */
     	s4o.print("__");
-        print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+        print_function_parameter_data_types_c overloaded_func_suf(&s4o, function_type_prefix);
         f_decl->accept(overloaded_func_suf);
       }
 
@@ -492,7 +492,10 @@
       
       /* determine the base data type returned by the function being called... */
       search_base_type_c search_base_type;
-      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      if (symbol->overloaded_return_type == NULL)
+        function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      else
+    	function_type_prefix = symbol->overloaded_return_type;
       
       function_name = symbol->function_name;      
       
@@ -675,7 +678,10 @@
 
       /* determine the base data type returned by the function being called... */
       search_base_type_c search_base_type;
-      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      if (symbol->overloaded_return_type == NULL)
+		function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      else
+		function_type_prefix = symbol->overloaded_return_type;
       if (NULL == function_type_prefix) ERROR;
       
       function_name = symbol->function_name;
@@ -1044,7 +1050,10 @@
 
       /* determine the base data type returned by the function being called... */
       search_base_type_c search_base_type;
-      function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      if (symbol->overloaded_return_type == NULL)
+        function_type_prefix = (symbol_c *)f_decl->type_name->accept(search_base_type);
+      else
+        function_type_prefix = symbol->overloaded_return_type;
       if (NULL == function_type_prefix) ERROR;
 
       /* loop through each function parameter, find the value we should pass
--- a/stage4/generate_c/generate_c_st.cc	Thu Feb 02 00:34:04 2012 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Fri Feb 03 00:09:52 2012 +0100
@@ -777,7 +777,7 @@
     if (fdecl_mutiplicity == 2) {
       /* function being called is overloaded! */
       s4o.print("__");
-      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
       f_decl->accept(overloaded_func_suf);
     }
     s4o.print_integer(fcall_number);
@@ -787,7 +787,7 @@
     if (fdecl_mutiplicity == 2) {
       /* function being called is overloaded! */
       s4o.print("__");
-      print_function_parameter_data_types_c overloaded_func_suf(&s4o);
+      print_function_parameter_data_types_c overloaded_func_suf(&s4o, symbol->overloaded_return_type);
       f_decl->accept(overloaded_func_suf);
     }
   }