Add support for FB call semantics of 'S' and 'R' IL operators!
authormjsousa
Tue, 20 Aug 2013 11:15:40 +0100
changeset 834 783ef40344dd
parent 833 27f246b35ac2
child 835 182036ed6475
Add support for FB call semantics of 'S' and 'R' IL operators!
Remove segfaults when analysing buggy IL code (IL operators with no operands).
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
stage3/narrow_candidate_datatypes.cc
stage3/print_datatypes_error.cc
stage4/generate_c/generate_c_il.cc
--- a/stage3/fill_candidate_datatypes.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -555,17 +555,13 @@
  *        CU counter_var
  */
 void *fill_candidate_datatypes_c::handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) {
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(il_operand);
-  	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
-	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl)
-		/* The il_operand is not the name of a FB instance. Most probably it is the name of a variable of some other type.
-		 * this is a semantic error.
-		 */
-		fb_decl = NULL;
-	
+	symbol_c *fb_decl = (NULL == il_operand)? NULL : search_varfb_instance_type->get_basetype_decl(il_operand);
+	if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL;
+
+	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
+	/* However, when calling using the 'S' and 'R' operators, this error is not caught by stage 2, as these operators have two possible semantics */
+	// if (NULL == fb_type_id) ERROR;
+
 	/* The narrow_candidate_datatypes_c does not rely on this called_fb_declaration pointer being == NULL to conclude that
 	 * we have a datatype incompatibility error, so we set it to fb_decl to allow the print_datatype_error_c to print out
 	 * more informative error messages!
@@ -594,10 +590,54 @@
 
 
 
+
+/* handle the S and R IL operators... */
+/* operator_str should be set to either "S" or "R" */
+void *fill_candidate_datatypes_c::handle_S_and_R_operator(symbol_c *symbol, const char *operator_str, symbol_c *&called_fb_declaration) {
+	/* NOTE: this operator has two possible semantic meanings:
+	 *          - Set/Reset the BOOL operand variable to true
+	 *          - call the FB specified by the operand.
+	 *       Which of the two semantics will have to be determined by the datatype of the operand!
+	 */
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
+
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			/* IEC61131-3, Table 52, Note (e) states that the datatype of the operand must be BOOL!
+			 * IEC61131-3, Table 52, line 3 states that this operator should "Set operand to 1 if current result is Boolean 1"
+			 *     which implies that the prev_instruction_type MUST also be BOOL compatible.
+			 */
+			if (get_datatype_info_c::is_BOOL_compatible(prev_instruction_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
+				add_datatype_to_candidate_list(symbol, prev_instruction_type);
+		}
+	}
+
+	/* if the appropriate semantics is not a Set/Reset of a boolean variable, the we try for the FB invocation! */
+	if (symbol->candidate_datatypes.size() == 0) 
+		handle_implicit_il_fb_call(symbol,  operator_str, called_fb_declaration);
+
+	/* If it is also not a valid FB call, make sure the candidate_datatypes is empty (handle_implicit_il_fb_call may leave it non-empty!!) */
+	/* From here on out, all later code will consider the symbol->called_fb_declaration being NULL as an indication that this operator must use the
+	 * Set/Reset semantics, so we must also guarantee that the remainder of the state of this symbol is compatible with that assumption!
+	 */
+	if (NULL == called_fb_declaration)
+		symbol->candidate_datatypes.clear();
+
+	if (debug) std::cout << operator_str << " [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+
 /* handle a binary IL operator, like ADD, SUB, etc... */
 void *fill_candidate_datatypes_c::handle_binary_operator(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr) {
-	if (NULL == l_expr) /* if no prev_il_instruction */
-		return NULL; 
+	if (NULL == l_expr) return NULL; /* if no prev_il_instruction */
+	if (NULL == r_expr) return NULL; /* if no IL operand!! */
 
 	for(unsigned int i = 0; i < l_expr->candidate_datatypes.size(); i++)
 		for(unsigned int j = 0; j < r_expr->candidate_datatypes.size(); j++)
@@ -1553,21 +1593,11 @@
  * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
  * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
  */
-/* 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 */
+/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */
 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
-	/* We do not call
-	 * fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-	 * because we want to make sure it is a FB instance, and not some other data type...
-	 */
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name);
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
- 	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl) 
-		/* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */
-		fb_decl = NULL;
+	symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
+	if (! get_datatype_info_c::is_function_block(fb_decl)) fb_decl = NULL;
 
 	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
 	if (NULL == fb_decl) ERROR;
@@ -1664,6 +1694,7 @@
 /* B 2.2 Operators */
 /*******************/
 void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+	if (NULL == il_operand)          return NULL;
 	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
 		add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]);
 	}
@@ -1672,6 +1703,7 @@
 }
 
 void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+	if (NULL == il_operand)          return NULL;
 	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
 		if      (get_datatype_info_c::is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
 			add_datatype_to_candidate_list(symbol, il_operand->candidate_datatypes[i]);
@@ -1684,6 +1716,7 @@
 	symbol_c *prev_instruction_type, *operand_type;
 
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
 			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
@@ -1700,6 +1733,7 @@
 	symbol_c *prev_instruction_type, *operand_type;
 
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
 			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
@@ -1720,6 +1754,7 @@
 	 *       We do not need to generate an error message. This error will be caught somewhere else!
 	 */
 	if (NULL == prev_il_instruction) return NULL;
+	if (NULL == il_operand)          return NULL;
 	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
 		if (get_datatype_info_c::is_ANY_BIT_compatible(prev_il_instruction->candidate_datatypes[i]))
 			add_datatype_to_candidate_list(symbol, prev_il_instruction->candidate_datatypes[i]);
@@ -1729,58 +1764,17 @@
 }
 
 
-void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	symbol_c *prev_instruction_type, *operand_type;
-
-	if (NULL == prev_il_instruction) return NULL;
-	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
-			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
-			operand_type = il_operand->candidate_datatypes[j];
-			/* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal.
-			 * the prev_instruction_type MUST be BOOL compatible.
-			 * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check!
-			 */
-			if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
-				add_datatype_to_candidate_list(symbol, prev_instruction_type);
-		}
-	}
-	if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	symbol_c *prev_instruction_type, *operand_type;
-
-	if (NULL == prev_il_instruction) return NULL;
-	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
-			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
-			operand_type = il_operand->candidate_datatypes[j];
-			/* TODO: I believe the following is wrong! The data types of prev_instruction_type and operand_type DO NOT have to be equal.
-			 * the prev_instruction_type MUST be BOOL compatible.
-			 * I am not too sure about operand_type, does it have to be BOOL compatible, or can it be ANY_BIT compatible? Must check!
-			 */
-			if (get_datatype_info_c::is_type_equal(prev_instruction_type,operand_type) && get_datatype_info_c::is_BOOL_compatible(operand_type))
-				add_datatype_to_candidate_list(symbol, prev_instruction_type);
-		}
-	}
-	if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit( S1_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "S1", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( R1_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "R1", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(   S_operator_c *symbol) {return handle_S_and_R_operator   (symbol,   "S", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(   R_operator_c *symbol) {return handle_S_and_R_operator   (symbol,   "R", symbol->called_fb_declaration);}
+
+void *fill_candidate_datatypes_c::visit(  S1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "S1", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  R1_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "R1", symbol->called_fb_declaration);}
 void *fill_candidate_datatypes_c::visit( CLK_operator_c *symbol) {return handle_implicit_il_fb_call(symbol, "CLK", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( CU_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "CU", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( CD_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "CD", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( PV_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "PV", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( IN_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "IN", symbol->called_fb_declaration);}
-void *fill_candidate_datatypes_c::visit( PT_operator_c  *symbol) {return handle_implicit_il_fb_call(symbol,  "PT", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  CU_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "CU", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  CD_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "CD", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  PV_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "PV", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  IN_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "IN", symbol->called_fb_declaration);}
+void *fill_candidate_datatypes_c::visit(  PT_operator_c *symbol) {return handle_implicit_il_fb_call(symbol,  "PT", symbol->called_fb_declaration);}
 
 void *fill_candidate_datatypes_c::visit( AND_operator_c *symbol) {return handle_binary_operator(widen_AND_table, symbol, prev_il_instruction, il_operand);}
 void *fill_candidate_datatypes_c::visit(  OR_operator_c *symbol) {return handle_binary_operator( widen_OR_table, symbol, prev_il_instruction, il_operand);}
@@ -1969,17 +1963,9 @@
 /* B 3.2.2 Subprogram Control Statements */
 /*****************************************/
 void *fill_candidate_datatypes_c::visit(fb_invocation_c *symbol) {
-	symbol_c *fb_type_id = search_varfb_instance_type->get_basetype_id(symbol->fb_name);
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_type_id) ERROR;
-
-	function_block_declaration_c *fb_decl = function_block_type_symtable.find_value(fb_type_id);
-	if (function_block_type_symtable.end_value() == fb_decl) 
-		/* The fb_name not the name of a FB instance. Most probably it is the name of a variable of some other type. */
-		fb_decl = NULL;
-
-	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
-	if (NULL == fb_decl) ERROR;
+	symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
+	if (! get_datatype_info_c::is_function_block(fb_decl )) fb_decl = NULL;
+	if (NULL == fb_decl) ERROR; /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
 	
 	if (symbol->   formal_param_list != NULL) symbol->formal_param_list->accept(*this);
 	if (symbol->nonformal_param_list != NULL) symbol->nonformal_param_list->accept(*this);
--- a/stage3/fill_candidate_datatypes.hh	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Tue Aug 20 11:15:40 2013 +0100
@@ -89,7 +89,8 @@
     bool  match_nonformal_call(symbol_c *f_call, symbol_c *f_decl);
     bool  match_formal_call   (symbol_c *f_call, symbol_c *f_decl, symbol_c **first_param_datatype = NULL);
     void  handle_function_call(symbol_c *fcall, generic_function_call_t fcall_data);
-    void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration);
+    void *handle_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name,   symbol_c *&called_fb_declaration);
+    void *handle_S_and_R_operator   (symbol_c *symbol,         const char *operator_str, symbol_c *&called_fb_declaration);
     void *handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_operator    (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
--- a/stage3/narrow_candidate_datatypes.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -322,11 +322,9 @@
 
 	/* 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);
+		set_datatype(called_fb_declaration, il_operand); /* only set it if it is in the candidate datatypes list! */  
 		il_operand->accept(*this);
 	}
-	symbol_c *fb_decl = il_operand->datatype;
 
 	if (0 == fake_prev_il_instruction->prev_il_instruction.size()) {
 		/* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction
@@ -336,8 +334,10 @@
 		return NULL;
 	}
 
+	symbol_c *fb_decl = (NULL == il_operand)? NULL : il_operand->datatype;
+	
 	if (NULL == fb_decl) {
-		/* the il_operand is a not FB instance */
+		/* the il_operand is a not FB instance, or it simply does not even exist, */
 		/* so we simply pass on the required datatype to the prev_il_instructions */
 		/* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
 		set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction);
@@ -999,7 +999,7 @@
  * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
  * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
  */
-/* 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 */
+/* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 */
 // 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) {
 	symbol_c *fb_decl = symbol->called_fb_declaration;
@@ -1093,7 +1093,9 @@
         if (NULL != deprecated_operation)
 		*deprecated_operation = false;
 
-	/* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
+
+	 /* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
 	 * e.g.  LD 33
 	 *       AND ( 45
 	 *            OR 56
@@ -1136,9 +1138,8 @@
 
 
 void *narrow_candidate_datatypes_c::handle_il_instruction(symbol_c *symbol) {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+  
 	/* NOTE 1: the il_operand __may__ be pointing to a parenthesized list of IL instructions. 
 	 * e.g.  LD 33
 	 *       AND ( 45
@@ -1158,6 +1159,7 @@
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	  
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1167,10 +1169,10 @@
 
 
 void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol)   {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1178,10 +1180,10 @@
 
 
 void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol)  {
-	if (NULL == symbol->datatype)
-		/* next IL instructions were unable to determine the datatype this instruction should produce */
-		return NULL;
+	if (NULL == symbol->datatype) return NULL; /* next IL instructions were unable to determine the datatype this instruction should produce */
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	return NULL;
@@ -1190,28 +1192,39 @@
 void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
 	if (symbol->candidate_datatypes.size() != 1)
 		return NULL;
+
 	symbol->datatype = symbol->candidate_datatypes[0];
-	/* set the datatype for the operand */
-	il_operand->datatype = symbol->datatype;
-	il_operand->accept(*this);
 	/* set the desired datatype of the previous il instruction */
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
 	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
 	 */
 	current_il_instruction->datatype = symbol->datatype;
+	
+	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
 	if (symbol->candidate_datatypes.size() != 1)
 		return NULL;
+	
 	symbol->datatype = symbol->candidate_datatypes[0];
+	/* set the desired datatype of the previous il instruction */
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
+	/* In the case of the ST operator, we must set the datatype of the il_instruction_c object that points to this ST_operator_c ourselves,
+	 * since the following il_instruction_c objects have not done it, as is normal/standard for other instructions!
+	 */
+	current_il_instruction->datatype = symbol->datatype;
+
 	/* set the datatype for the operand */
+	if (NULL == il_operand) return NULL; /* if no IL operand => error in the source code!! */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
-	/* set the desired datatype of the previous il instruction */
-	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -1220,22 +1233,23 @@
 	 *              NOT [<il_operand>]
 	 *       However, it does not define the semantic of the NOT operation when the <il_operand> is specified.
 	 *       We therefore consider it an error if an il_operand is specified!
-	 */
-	/* We do not change the data type, we simply invert the bits in bit types! */
+	 *       This error will be detected in print_datatypes_error_c!!
+	 */
+	/* This operator does not change the data type, it simply inverts the bits in the ANT_BIT data types! */
 	/* So, we set the desired datatype of the previous il instruction */
 	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
 void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol)  {
-  /* TODO: what if this is a FB call? */
-	return handle_il_instruction(symbol);
-}
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return narrow_implicit_il_fb_call(symbol, "S",  symbol->called_fb_declaration); 
+	else                                       /* Reset   semantics */  return handle_il_instruction(symbol);
+}
+
 void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol)  {
-  /* TODO: what if this is a FB call? */
-	return handle_il_instruction(symbol);
-}
-
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return narrow_implicit_il_fb_call(symbol, "R",  symbol->called_fb_declaration); 
+	else                                       /* Reset   semantics */  return handle_il_instruction(symbol);
+}
 
 void *narrow_candidate_datatypes_c::visit(  S1_operator_c *symbol)  {return narrow_implicit_il_fb_call(symbol, "S1",  symbol->called_fb_declaration);}
 void *narrow_candidate_datatypes_c::visit(  R1_operator_c *symbol)  {return narrow_implicit_il_fb_call(symbol, "R1",  symbol->called_fb_declaration);}
--- a/stage3/print_datatypes_error.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage3/print_datatypes_error.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -278,7 +278,7 @@
 		STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name);
 		return NULL;
 	}
-	il_operand->accept(*this);
+	// il_operand->accept(*this);  // NOT required. The il_simple_operation_c already visits it!!
 	
 	if (NULL == called_fb_declaration) {
 		STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance.");
@@ -760,10 +760,8 @@
 
 void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) {
 	il_operand = symbol->il_operand;
-	if (NULL != symbol->il_operand) {
-		symbol->il_operand->accept(*this);
-	}
-	/* recursive call to see whether data types are compatible */
+	if (NULL != il_operand)     symbol->il_operand->accept(*this); /* recursive call to see whether data types are compatible */
+
 	symbol->il_simple_operator->accept(*this);
 	il_operand = NULL;
 	return NULL;
@@ -932,50 +930,22 @@
 /* B 2.2 Operators */
 /*******************/
 void *print_datatypes_error_c::print_binary_operator_errors(const char *il_operator, symbol_c *symbol, bool deprecated_operation) {
-	if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) {
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator);
-	} else if (NULL == symbol->datatype) {
-		STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator);
+	if (NULL == il_operand) {
+		STAGE3_ERROR(0, symbol, symbol, "Missing operand for %s operator.", il_operator);		// message (a)
+	} else if ((symbol->candidate_datatypes.size() == 0) && (il_operand->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for '%s' operator.", il_operator);		// message (b)
+	} else if (NULL == symbol->datatype) {
+		STAGE3_WARNING(symbol, symbol, "Result of '%s' operation is never used.", il_operator);		// message (c)
 	} else if (deprecated_operation)
-		STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator);
-	return NULL;
-}
-
-
-void *print_datatypes_error_c::visit(LD_operator_c *symbol) {
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(LDN_operator_c *symbol) {
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'LDN' operator.");
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(ST_operator_c *symbol) {
-	/* MANU:
-	 * if prev_instruction is NULL we can print a message error or warning error like:
-	 * we can't use a ST like first instruction.
-	 * What do you think?
-	 */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'ST' operator.");
-	return NULL;
-}
-
-void *print_datatypes_error_c::visit(STN_operator_c *symbol) {
-	/* MANU:
-	 * if prev_instruction is NULL we can print a message error or warning error like:
-	 * we can't use a ST like first instruction.
-	 * What do you think?
-	 */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'STN' operator.");
-	return NULL;
-}
+		STAGE3_WARNING(symbol, symbol, "Deprecated operation for '%s' operator.", il_operator);		// message (d)
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(  LD_operator_c *symbol) {return print_binary_operator_errors("LD"  , symbol);}  // I believe it will never emit messages (b) and (c)!!
+void *print_datatypes_error_c::visit( LDN_operator_c *symbol) {return print_binary_operator_errors("LDN" , symbol);}  // I believe it will never emit message (c)
+void *print_datatypes_error_c::visit(  ST_operator_c *symbol) {return print_binary_operator_errors("ST"  , symbol);}  // I believe it will never emit message (c)
+void *print_datatypes_error_c::visit( STN_operator_c *symbol) {return print_binary_operator_errors("STN" , symbol);}  // I believe it will never emit message (c)
 
 void *print_datatypes_error_c::visit(NOT_operator_c *symbol) {
 	/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
@@ -983,27 +953,21 @@
 	 *       However, it does not define the semantic of the NOT operation when the <il_operand> is specified.
 	 *       We therefore consider it an error if an il_operand is specified!
 	 */
-	if (il_operand != NULL)
+	if (il_operand != NULL) {
 		STAGE3_ERROR(0, symbol, symbol, "'NOT' operator may not have an operand.");
-	if (symbol->candidate_datatypes.size() == 0)
+	} else if (symbol->candidate_datatypes.size() == 0)
 		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'NOT' operator.");
 	return NULL;
 }
 
 void *print_datatypes_error_c::visit(S_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'S' operator.");
-	return NULL;
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return handle_implicit_il_fb_invocation("S", symbol, symbol->called_fb_declaration);
+	else                                       /* Reset   semantics */  return print_binary_operator_errors    ("S", symbol);
 }
 
 void *print_datatypes_error_c::visit(R_operator_c *symbol) {
-  /* TODO: what if this is a FB call ?? */
-	if ((symbol->candidate_datatypes.size() == 0) 		&&
-		(il_operand->candidate_datatypes.size() > 0))
-		STAGE3_ERROR(0, symbol, symbol, "Data type mismatch for 'R' operator.");
-	return NULL;
+	if (NULL != symbol->called_fb_declaration) /* FB call semantics */  return handle_implicit_il_fb_invocation("R", symbol, symbol->called_fb_declaration);
+	else                                       /* Reset   semantics */  return print_binary_operator_errors    ("R", symbol);
 }
 
 void *print_datatypes_error_c::visit( S1_operator_c *symbol) {return handle_implicit_il_fb_invocation( "S1", symbol, symbol->called_fb_declaration);}
--- a/stage4/generate_c/generate_c_il.cc	Tue Aug 20 11:11:09 2013 +0100
+++ b/stage4/generate_c/generate_c_il.cc	Tue Aug 20 11:15:40 2013 +0100
@@ -1530,6 +1530,16 @@
 
 
 void *visit(S_operator_c *symbol) {
+  /* This operator must implement one of two possible semantics: 
+   *     - FB call
+   *     - Set all the bits of an ANY_BIT type variable to 1
+   */
+  
+  /* Check whether we must implement the FB call semantics... */
+  if (NULL != symbol->called_fb_declaration)
+    return XXX_CAL_operator( "S", this->current_operand);
+  
+  /* Implement the bit setting semantics... */
   if (wanted_variablegeneration != expression_vg) {
     s4o.print("LD");
     return NULL;
@@ -1552,6 +1562,16 @@
 
 
 void *visit(R_operator_c *symbol) {
+  /* This operator must implement one of two possible semantics: 
+   *     - FB call
+   *     - Set all the bits of an ANY_BIT type variable to 0
+   */
+  
+  /* Check whether we must implement the FB call semantics... */
+  if (NULL != symbol->called_fb_declaration)
+    return XXX_CAL_operator( "R", this->current_operand);
+  
+  /* Implement the bit setting semantics... */
   if (wanted_variablegeneration != expression_vg) {
     s4o.print("LD");
     return NULL;