stage3/print_datatypes_error.cc
changeset 455 933c0dccc82f
parent 454 099aa5d655de
child 457 67d8b07bac22
--- a/stage3/print_datatypes_error.cc	Thu Feb 23 13:25:49 2012 +0000
+++ b/stage3/print_datatypes_error.cc	Sat Feb 25 19:16:35 2012 +0000
@@ -183,6 +183,8 @@
 		fcall_data.nonformal_operand_list->accept(*this);
 		if (f_decl)
 			for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) {
+		  		/* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */
+
 				if (NULL == param_value->datatype) {
 					function_invocation_error = true;
 					STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value);
@@ -203,31 +205,57 @@
 	return;
 }
 
+
+
 void print_datatypes_error_c::handle_implicit_il_fb_invocation(symbol_c *il_operator, const char *param_name, symbol_c *called_fb_declaration) {
 	if (NULL == il_operand) {
 		STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name);
 		return;
 	}
+	il_operand->accept(*this);
+	
 	if (NULL == called_fb_declaration) {
-		STAGE3_ERROR(0, il_operand, il_operand, "Operand of FB call operator '%s' is not a FB variable.", param_name);
+		STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance.");
 		return;
 	}
+
 	if (NULL == prev_il_instruction) {
 		STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name);	
 		return;
 	}
+
 	/* Find the corresponding parameter in function declaration */
 	function_param_iterator_c fp_iterator(called_fb_declaration);
 	if (NULL == fp_iterator.search(param_name)) {
-/* TODO: must also check whther it is an IN parameter!! */
+		/* TODO: must also check whther it is an IN parameter!! */
+		/* NOTE: although all standard FBs have the implicit FB calls defined as input parameters
+		*        (i.e., for all standard FBs, CLK, PT, IN, CU, CD, S1, R1, etc... is always an input parameter)
+		*        if a non-standard (i.e. a FB not defined in the standard library) FB is being called, then
+		*        this (CLK, PT, IN, CU, ...) parameter may just have been defined as OUT or INOUT,
+		*        which will not work for an implicit FB call!
+		*/
 		STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name);	
 		return;
 	}
 	if (NULL == prev_il_instruction->datatype) {
-		STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed, when invoking FB.", param_name);
+		STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name);
 		return;
 	}
-
+	
+
+	/* NOTE: The error_level currently being used for errors in variables/constants etc... is rather high.
+	 *       However, in the case of an implicit FB call, if the datatype of the operand == NULL, this may be
+	 *       the __only__ indication of an error! So we test it here again, to make sure thtis error will really
+	 *       be printed out!
+	 */
+	if (NULL == il_operand->datatype) {
+		/* Note: the case of (NULL == fb_declaration) was already caught above! */
+// 		if (NULL != fb_declaration) {
+			STAGE3_ERROR(0, il_operator, il_operator, "Invalid FB call: Datatype incompatibility between the FB's '%s' parameter and value being passed, or paramater '%s' is not a 'VAR_INPUT' parameter.", param_name, param_name);
+			return;
+// 		}
+	}
+// 
 	return;
 }
 
@@ -552,10 +580,8 @@
 /* B 1.7 Configuration elements */
 /********************************/
 void *print_datatypes_error_c::visit(configuration_declaration_c *symbol) {
-#if 0
 	// TODO !!!
 	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-#endif
 	return NULL;
 }
 
@@ -681,6 +707,8 @@
 	};
   
 	handle_function_invocation(symbol, fcall_param);
+	/* check the semantics of the CALC, CALCN operators! */
+	symbol->il_call_operator->accept(*this);
 	return NULL;
 }
 
@@ -922,12 +950,19 @@
 	return NULL;
 }
 
+
+void *print_datatypes_error_c::handle_conditional_flow_control_IL_instruction(symbol_c *symbol, const char *oper) {
+	if (NULL == symbol->datatype)
+		STAGE3_ERROR(0, symbol, symbol, "%s operator must be preceded by an IL instruction producing a BOOL value.", oper);
+	return NULL;
+}
+
 void *print_datatypes_error_c::visit(CALC_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "CALC");
 }
 
 void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "CALCN");
 }
 
 void *print_datatypes_error_c::visit(RET_operator_c *symbol) {
@@ -935,11 +970,11 @@
 }
 
 void *print_datatypes_error_c::visit(RETC_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "RETC");
 }
 
 void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "RETCN");
 }
 
 void *print_datatypes_error_c::visit(JMP_operator_c *symbol) {
@@ -947,11 +982,11 @@
 }
 
 void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "JMPC");
 }
 
 void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) {
-	return NULL;
+	return handle_conditional_flow_control_IL_instruction(symbol, "JMPCN");
 }
 
 /* Symbol class handled together with function call checks */