# HG changeset patch
# User laurent
# Date 1328224192 -3600
# Node ID 55b074ea72556f331ef22535c4f0b01d15685b4f
# Parent  f1f3facc59e7405e9812ce8c41b1898f70efffba
Fix bug with functions like LEN and TRUNC that have overloaded return type for same inputs type

diff -r f1f3facc59e7 -r 55b074ea7255 absyntax/absyntax.def
--- 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;)
 
 
 /********************/
diff -r f1f3facc59e7 -r 55b074ea7255 absyntax_utils/search_constant_type.cc
--- 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");
diff -r f1f3facc59e7 -r 55b074ea7255 absyntax_utils/search_constant_type.hh
--- 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      */
diff -r f1f3facc59e7 -r 55b074ea7255 stage3/visit_expression_type.cc
--- 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;
diff -r f1f3facc59e7 -r 55b074ea7255 stage3/visit_expression_type.hh
--- 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
diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c.cc
--- 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;
     }
diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_il.cc
--- 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);
       }
     }  
diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_inlinefcall.cc
--- 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
diff -r f1f3facc59e7 -r 55b074ea7255 stage4/generate_c/generate_c_st.cc
--- 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);
     }
   }