stage3/narrow_candidate_datatypes.cc
changeset 455 933c0dccc82f
parent 454 099aa5d655de
child 456 ca8d98289ff9
--- a/stage3/narrow_candidate_datatypes.cc	Thu Feb 23 13:25:49 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Sat Feb 25 19:16:35 2012 +0000
@@ -175,11 +175,10 @@
 		/* set the desired data type for this parameter */
 		set_datatype(desired_datatype, call_param_value);
 		/* And recursively call that parameter/expression, so it can propagate that info */
-		/* However, when handling an implicit IL FB call, the first parameter is fake (a copy of the prev_il_instruction).
-		 * so the call call_param_value->accept(*this) may actually be calling an object of the base symbol_c .
-		 */
 		call_param_value->accept(*this);
 
+		/* set the extensible_parameter_highest_index, which will be needed in stage 4 */
+		/* This value says how many extensible parameters are being passed to the standard function */
 		if (NULL != param_name) 
 			if (extensible_parameter_highest_index < fp_iterator.extensible_param_index())
 				extensible_parameter_highest_index = fp_iterator.extensible_param_index();
@@ -261,12 +260,15 @@
  * the visit(il_fb_call_c *) method handle it!
  */
 void narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) {
-	if (NULL == called_fb_declaration)
-		/* The fill_candidate_datatypes_c was not able to determine which FB is being called!
-		 * This may be because the il_operand is not the name of a FB instance, or no operand was given. 
-		 * In that case, we just give up!
-		 */
-		return;
+
+	/* set the datatype of the il_operand, this is, the FB being called! */
+	if (NULL != il_operand) {
+		/* only set it if it is in the candidate datatypes list! */  
+		set_datatype(called_fb_declaration, il_operand);
+		il_operand->accept(*this);
+	}
+	symbol_c *fb_decl = il_operand->datatype;
+
 	if (NULL == prev_il_instruction) {
 		/* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction
 		 * (or list of instructions) that will set the IL current/default value.
@@ -275,6 +277,15 @@
 		return;
 	}
 
+	if (NULL == fb_decl) {
+		/* the il_operand is a not FB instance */
+		/* so we simply pass on the required datatype to the prev_il_instruction */
+		/* The invalid FB invocation will be caught by the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
+		prev_il_instruction->datatype = il_instruction->datatype;
+		return;
+	}
+	
+
 	/* The value being passed to the 'param_name' parameter is actually the prev_il_instruction.
 	 * However, we do not place that object directly in the fake il_param_list_c that we will be
 	 * creating, since the visit(il_fb_call_c *) method will recursively call every object in that list.
@@ -285,7 +296,7 @@
 	 * The easiest way to work around this is to simply use a new object, and copy the relevant details to that object!
 	 */
 	symbol_c param_value = *prev_il_instruction;
-	
+        
 	identifier_c variable_name(param_name);
 	// SYM_REF1(il_assign_operator_c, variable_name)
 	il_assign_operator_c il_assign_operator(&variable_name);  
@@ -294,8 +305,9 @@
 	il_param_list_c il_param_list;
 	il_param_list.add_element(&il_param_assignment);
 	// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
-	il_fb_call_c il_fb_call(NULL, il_operand, NULL, &il_param_list);
-	
+	CAL_operator_c CAL_operator;
+	il_fb_call_c il_fb_call(&CAL_operator, il_operand, NULL, &il_param_list);
+	        
 	/* A FB call does not return any datatype, but the IL instructions that come after this
 	 * FB call may require a specific datatype in the il current/default variable, 
 	 * so we must pass this information up to the IL instruction before the FB call, since it will
@@ -304,9 +316,10 @@
 	 * The above will be done by the visit(il_fb_call_c *) method, so we must make sure to
 	 * correctly set up the il_fb_call.datatype variable!
 	 */
-	copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/);
+// 	copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/);
+	il_fb_call.called_fb_declaration = called_fb_declaration;
 	il_fb_call.accept(*this);
-	
+
 	/* set the required datatype of the previous IL instruction! */
 	/* NOTE:
 	 * When handling these implicit IL calls, the parameter_value being passed to the FB parameter
@@ -327,13 +340,11 @@
 	 *     FB call for any datatype. In that case, then the datatype required to pass to the first parameter of the
 	 *     FB call must be left unchanged!
 	 */
-// 	if (NULL != prev_il_instruction) /* already checked above! */
-		if (is_type_equal(param_value.datatype, il_instruction->datatype)) {
-			prev_il_instruction->datatype = param_value.datatype;
-		} else {
-			prev_il_instruction->datatype = NULL;
-		}
-
+	if ((NULL == il_instruction->datatype) || (is_type_equal(param_value.datatype, il_instruction->datatype))) {
+		prev_il_instruction->datatype = param_value.datatype;
+	} else {
+		prev_il_instruction->datatype = NULL;
+	}
 }
 
 
@@ -592,32 +603,16 @@
 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */
 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
 void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
-	/* Note: We do not use the symbol->called_fb_declaration value (set in fill_candidate_datatypes_c)
-	 *       because we try to identify any other datatype errors in the expressions used in the 
-	 *       parameters to the FB call. e.g.
-	 *          fb_var( 
-	 *             in1 := var1,
-	 *             in2 := (
-	 *                       LD 56
-	 *                       ADD 43
-	 *                    )
-	 *             )
-	 *       even it the call to the FB is invalid. 
-	 *       This makes sense because it may be errors in those expressions which are
-	 *       making this an invalid call, so it makes sense to point them out to the user!
-	 */
-	symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-
+	symbol_c *fb_decl = symbol->called_fb_declaration;
+	
 	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
 	if (NULL == fb_decl) ERROR;
 	if (NULL != symbol->il_operand_list)  narrow_nonformal_call(symbol, fb_decl);
 	if (NULL != symbol->  il_param_list)     narrow_formal_call(symbol, fb_decl);
 
-	/* An IL FB call does not change the default value in the current/default IL variable, so we pass the
-	 * required datatype up to the previous IL instruction
-	 */
-	if (NULL != prev_il_instruction)
-		prev_il_instruction->datatype = symbol->datatype;
+	/* Let the il_call_operator (CAL, CALC, or CALCN) set the datatype of prev_il_instruction... */
+	symbol->il_call_operator->datatype = symbol->datatype;
+	symbol->il_call_operator->accept(*this);
 	return NULL;
 }
 
@@ -825,40 +820,90 @@
 void *narrow_candidate_datatypes_c::visit(NE_operator_c   *symbol)  {return handle_il_instruction(symbol);}
 
 
+// SYM_REF0(CAL_operator_c)
+/* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */
 void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
-	return NULL;
-}
-
+	/* set the desired datatype of the previous il instruction */
+	/* This FB call does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction */
+	if (NULL != prev_il_instruction)
+		prev_il_instruction->datatype = symbol->datatype;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::narrow_conditional_flow_control_IL_instruction(symbol_c *symbol) {
+	/* if the next IL instructions needs us to provide a datatype other than a bool, 
+	 * then we have an internal compiler error - most likely in fill_candidate_datatypes_c 
+	 */
+	if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR;
+	if (symbol->candidate_datatypes.size() > 1) ERROR;
+
+	/* NOTE: If there is not IL instruction following this CALC, CALCN, JMPC, JMPC, ..., instruction,
+	 *       we must still provide a bool_type_name_c datatype (if possible, i.e. if it exists in the candidate datatype list).
+	 *       If it is not possible, we set it to NULL
+	 */
+	if (symbol->candidate_datatypes.size() == 0)    symbol->datatype = NULL;
+	else    symbol->datatype = symbol->candidate_datatypes[0]; /* i.e. a bool_type_name_c! */
+	if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR;
+
+	/* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */
+	if (NULL != prev_il_instruction)    prev_il_instruction->datatype = symbol->datatype;
+	return NULL;
+}
+
+
+// SYM_REF0(CALC_operator_c)
+/* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */
 void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) {
-	return NULL;
-}
-
+	return narrow_conditional_flow_control_IL_instruction(symbol);
+}
+
+
+// SYM_REF0(CALCN_operator_c)
+/* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */
 void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {
-	return NULL;
-}
+	return narrow_conditional_flow_control_IL_instruction(symbol);
+}
+
 
 void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) {
+	/* set the desired datatype of the previous il instruction */
+	/* This RET instruction does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction.
+	 * Actually this should always be NULL, otherwise we have a bug in the flow_control_analysis_c
+	 * However, since that class has not yet been completely finished, we do not yet check this assertion!
+	 */
+// 	if (NULL != symbol->datatype) ERROR;
+	if (NULL != prev_il_instruction)
+		prev_il_instruction->datatype = symbol->datatype;
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) {
-	return NULL;
+	return narrow_conditional_flow_control_IL_instruction(symbol);
 }
 
 void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {
-	return NULL;
+	return narrow_conditional_flow_control_IL_instruction(symbol);
 }
 
 void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) {
+	/* set the desired datatype of the previous il instruction */
+	/* This JMP instruction does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction.
+	 * Actually this should always be NULL, otherwise we have a bug in the flow_control_analysis_c
+	 * However, since that class has not yet been completely finished, we do not yet check this assertion!
+	 */
+// 	if (NULL != symbol->datatype) ERROR;
+	if (NULL != prev_il_instruction)
+		prev_il_instruction->datatype = symbol->datatype;
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) {
-	return NULL;
+	return narrow_conditional_flow_control_IL_instruction(symbol);
 }
 
 void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {
-	return NULL;
+	return narrow_conditional_flow_control_IL_instruction(symbol);
 }
 
 /* Symbol class handled together with function call checks */