stage3/narrow_candidate_datatypes.cc
changeset 438 744b125d911e
parent 428 42d02558ebd9
child 439 cf7d6862033d
--- a/stage3/narrow_candidate_datatypes.cc	Wed Feb 08 18:33:01 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Fri Feb 10 19:04:31 2012 +0000
@@ -182,6 +182,59 @@
 }
 
 
+/*
+typedef struct {
+  symbol_c *function_name,
+  symbol_c *nonformal_operand_list,
+  symbol_c *   formal_operand_list,
+
+  std::vector <symbol_c *> &candidate_functions,  
+  symbol_c &*called_function_declaration,
+  int      &extensible_param_count
+} generic_function_call_t;
+*/
+void narrow_candidate_datatypes_c::narrow_function_invocation(symbol_c *fcall, generic_function_call_t fcall_data) {
+	/* set the called_function_declaration. */
+	fcall_data.called_function_declaration = NULL;
+
+	/* set the called_function_declaration taking into account the datatype that we need to return */
+	for(unsigned int i = 0; i < fcall->candidate_datatypes.size(); i++) {
+		if (is_type_equal(fcall->candidate_datatypes[i], fcall->datatype)) {
+			fcall_data.called_function_declaration = fcall_data.candidate_functions[i];
+			break;
+		}
+	}
+
+	/* NOTE: If we can't figure out the declaration of the function being called, this is not 
+	 *       necessarily an internal compiler error. It could be because the symbol->datatype is NULL
+	 *       (because the ST code being analysed has an error _before_ this function invocation).
+	 *       However, we don't just give, up, we carry on recursivly analysing the code, so as to be
+	 *       able to print out any error messages related to the parameters being passed in this function 
+	 *       invocation.
+	 */
+	/* if (NULL == symbol->called_function_declaration) ERROR; */
+	if (fcall->candidate_datatypes.size() == 1) {
+		/* If only one function declaration, then we use that (even if symbol->datatypes == NULL)
+		 * so we can check for errors in the expressions used to pass parameters in this
+		 * function invocation.
+		 */
+		fcall_data.called_function_declaration = fcall_data.candidate_functions[0];
+	}
+
+	/* If an overloaded function is being invoked, and we cannot determine which version to use,
+	 * then we can not meaningfully verify the expressions used inside that function invocation.
+	 * We simply give up!
+	 */
+	if (NULL == fcall_data.called_function_declaration)
+		return;
+
+	if (NULL != fcall_data.nonformal_operand_list)  narrow_nonformal_call(fcall, fcall_data.called_function_declaration, &(fcall_data.extensible_param_count));
+	if (NULL != fcall_data.   formal_operand_list)     narrow_formal_call(fcall, fcall_data.called_function_declaration, &(fcall_data.extensible_param_count));
+
+	return;
+}
+
+
 
 /* a helper function... */
 symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) {
@@ -324,7 +377,27 @@
 	return NULL;
 }
 
+/* | function_name [il_operand_list] */
+/* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */
+// SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;)
 void *narrow_candidate_datatypes_c::visit(il_function_call_c *symbol) {
+	generic_function_call_t fcall_param = {
+	/* fcall_param.function_name               = */ symbol->function_name,
+	/* fcall_param.nonformal_operand_list      = */ symbol->il_operand_list,
+	/* fcall_param.formal_operand_list         = */ NULL,
+	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
+	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
+	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
+	};
+
+	/* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction)
+	 * In order to be able to handle this without coding special cases, we simply prepend that symbol
+	 * to the il_operand_list (done in fill_candidate_datatypes_c), and remove it later (in the print_datatypes_error_c).
+	 *
+	 * Since this class is executed after fill_candidate_datatypes_c, and before print_datatypes_error_c,
+	 * the following code is actually correct!
+	 */
+	narrow_function_invocation(symbol, fcall_param);
 	return NULL;
 }
 
@@ -345,7 +418,20 @@
 	return NULL;
 }
 
+/* | 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. */
+// SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
 void *narrow_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
+	generic_function_call_t fcall_param = {
+	/* fcall_param.function_name               = */ symbol->function_name,
+	/* fcall_param.nonformal_operand_list      = */ NULL,
+	/* fcall_param.formal_operand_list         = */ symbol->il_param_list,
+	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
+	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
+	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
+	};
+  
+	narrow_function_invocation(symbol, fcall_param);
 	return NULL;
 }
 
@@ -1020,47 +1106,22 @@
 }
 
 
+
+/* NOTE: The parameter 'called_function_declaration', 'extensible_param_count' and 'candidate_functions' are used to pass data between the stage 3 and stage 4. */
+/*    formal_param_list -> may be NULL ! */
+/* nonformal_param_list -> may be NULL ! */
+// SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count; std::vector <symbol_c *> candidate_functions;)
 void *narrow_candidate_datatypes_c::visit(function_invocation_c *symbol) {
-	int  ext_parm_count;
-
-	/* set the called_function_declaration. */
-	symbol->called_function_declaration = NULL;
-
-	/* set the called_function_declaration taking into account the datatype that we need to return */
-	for(unsigned int i = 0; i < symbol->candidate_datatypes.size(); i++) {
-		if (is_type_equal(symbol->candidate_datatypes[i], symbol->datatype)) {
-			symbol->called_function_declaration = symbol->candidate_functions[i];
-			break;
-		}
-	}
-
-	/* NOTE: If we can't figure out the declaration of the function being called, this is not 
-	 *       necessarily an internal compiler error. It could be because the symbol->datatype is NULL
-	 *       (because the ST code being analysed has an error _before_ this function invocation).
-	 *       However, we don't just give, up, we carry on recursivly analysing the code, so as to be
-	 *       able to print out any error messages related to the parameters being passed in this function 
-	 *       invocation.
-	 */
-	/* if (NULL == symbol->called_function_declaration) ERROR; */
-	if (symbol->candidate_datatypes.size() == 1) {
-		/* If only one function declaration, then we use that (even if symbol->datatypes == NULL)
-		 * so we can check for errors in the expressions used to pass parameters in this
-		 * function invocation.
-		 */
-		symbol->called_function_declaration = symbol->candidate_functions[0];
-	}
-
-	/* If an overloaded function is being invoked, and we cannot determine which version to use,
-	 * then we can not meaningfully verify the expressions used inside that function invocation.
-	 * We simply give up!
-	 */
-	if (NULL == symbol->called_function_declaration)
-		return NULL;
-
-	if (NULL != symbol->nonformal_param_list)  narrow_nonformal_call(symbol, symbol->called_function_declaration, &ext_parm_count);
-	if (NULL != symbol->   formal_param_list)     narrow_formal_call(symbol, symbol->called_function_declaration, &ext_parm_count);
-	symbol->extensible_param_count = ext_parm_count;
-
+	generic_function_call_t fcall_param = {
+	/* fcall_param.function_name               = */ symbol->function_name,
+	/* fcall_param.nonformal_operand_list      = */ symbol->nonformal_param_list,
+	/* fcall_param.formal_operand_list         = */ symbol->formal_param_list,
+	/* fcall_param.candidate_functions         = */ symbol->candidate_functions,
+	/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
+	/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
+	};
+  
+	narrow_function_invocation(symbol, fcall_param);
 	return NULL;
 }