Re-organizing the code.
authorMario de Sousa <msousa@fe.up.pt>
Tue, 13 Mar 2012 18:29:34 +0000
changeset 479 a174d61f2087
parent 478 b13feab3b918
child 480 8a58d7b8b26c
Re-organizing the code.
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
--- a/stage3/fill_candidate_datatypes.cc	Tue Mar 13 16:38:21 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Tue Mar 13 18:29:34 2012 +0000
@@ -317,6 +317,33 @@
 }
 
 
+
+
+/* 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; 
+
+	for(unsigned int i = 0; i < l_expr->candidate_datatypes.size(); i++)
+		for(unsigned int j = 0; j < r_expr->candidate_datatypes.size(); j++)
+			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
+			add_datatype_to_candidate_list(symbol, widening_conversion(l_expr->candidate_datatypes[i], r_expr->candidate_datatypes[j], widen_table));
+
+	if (debug) std::cout <<  "[" << l_expr->candidate_datatypes.size() << "," << r_expr->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+/* handle a binary ST expression, like '+', '-', etc... */
+void *fill_candidate_datatypes_c::handle_binary_expression(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr) {
+	l_expr->accept(*this);
+	r_expr->accept(*this);
+	return handle_binary_operator(widen_table, symbol, l_expr, r_expr);
+}
+
+
+
+
 /* a helper function... */
 symbol_c *fill_candidate_datatypes_c::base_type(symbol_c *symbol) {
 	/* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
@@ -365,6 +392,8 @@
 		add_2datatypes_to_candidate_list(symbol, &search_constant_type_c::udint_type_name, &search_constant_type_c::safeudint_type_name);
 	if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
 		add_2datatypes_to_candidate_list(symbol, &search_constant_type_c::ulint_type_name, &search_constant_type_c::safeulint_type_name);
+
+	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
 	return NULL;
 }
 
@@ -384,14 +413,6 @@
 }
 
 
-
-void *fill_candidate_datatypes_c::visit(integer_c *symbol) {
-	handle_any_integer(symbol);
-	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
-	return NULL;
-}
-
-
 void *fill_candidate_datatypes_c::visit(neg_real_c *symbol) {
 	int calc_size;
 
@@ -422,27 +443,10 @@
 }
 
 
-void *fill_candidate_datatypes_c::visit(binary_integer_c *symbol) {
-	handle_any_integer(symbol);
-	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
-	return NULL;
-}
-
-
-
-void *fill_candidate_datatypes_c::visit(octal_integer_c *symbol) {
-	handle_any_integer(symbol);
-	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
-	return NULL;
-}
-
-
-
-void *fill_candidate_datatypes_c::visit(hex_integer_c *symbol) {
-	handle_any_integer(symbol);
-	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
-	return NULL;
-}
+void *fill_candidate_datatypes_c::visit(integer_c        *symbol) {return handle_any_integer(symbol);}
+void *fill_candidate_datatypes_c::visit(binary_integer_c *symbol) {return handle_any_integer(symbol);}
+void *fill_candidate_datatypes_c::visit(octal_integer_c  *symbol) {return handle_any_integer(symbol);}
+void *fill_candidate_datatypes_c::visit(hex_integer_c    *symbol) {return handle_any_integer(symbol);}
 
 
 // SYM_REF2(integer_literal_c, type, value)
@@ -531,20 +535,9 @@
 /************************************/
 /* B 1.2.3.2 - Time of day and Date */
 /************************************/
-void *fill_candidate_datatypes_c::visit(time_of_day_c *symbol) {
-	add_datatype_to_candidate_list(symbol, symbol->type_name);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(date_c *symbol) {
-	add_datatype_to_candidate_list(symbol, symbol->type_name);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(date_and_time_c *symbol) {
-	add_datatype_to_candidate_list(symbol, symbol->type_name);
-	return NULL;
-}
+void *fill_candidate_datatypes_c::visit(time_of_day_c   *symbol) {add_datatype_to_candidate_list(symbol, symbol->type_name); return NULL;}
+void *fill_candidate_datatypes_c::visit(date_c          *symbol) {add_datatype_to_candidate_list(symbol, symbol->type_name); return NULL;}
+void *fill_candidate_datatypes_c::visit(date_and_time_c *symbol) {add_datatype_to_candidate_list(symbol, symbol->type_name); return NULL;}
 
 /**********************/
 /* B 1.3 - Data types */
@@ -600,9 +593,7 @@
 /* B 1.4 - Variables */
 /*********************/
 void *fill_candidate_datatypes_c::visit(symbolic_variable_c *symbol) {
-	symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
-	if (NULL != result)
-		add_datatype_to_candidate_list(symbol, result);
+	add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol)); /* will only add if non NULL */
 	if (debug) std::cout << "VAR [" << symbol->candidate_datatypes.size() << "]\n";
 	return NULL;
 }
@@ -620,29 +611,13 @@
 	 * if (symbol->value[1] == '\0') ERROR;
 	 */
 	switch (symbol->value[2]) {
-	case 'X': // bit - 1 bit
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::bool_type_name);
-		break;
-
-	case 'B': // byte - 8 bits
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::byte_type_name);
-		break;
-
-	case 'W': // word - 16 bits
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::word_type_name);
-		break;
-
-	case 'D': // double word - 32 bits
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::dword_type_name);
-		break;
-
-	case 'L': // long word - 64 bits
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::lword_type_name);
-		break;
-
-	default:  // if none of the above, then the empty string was used <=> boolean
-		add_datatype_to_candidate_list(symbol, &search_constant_type_c::bool_type_name);
-		break;
+		case 'X': /* bit   -  1 bit  */ add_datatype_to_candidate_list(symbol, &search_constant_type_c::bool_type_name);  break;
+		case 'B': /* byte  -  8 bits */ add_datatype_to_candidate_list(symbol, &search_constant_type_c::byte_type_name);  break;
+		case 'W': /* word  - 16 bits */ add_datatype_to_candidate_list(symbol, &search_constant_type_c::word_type_name);  break;
+		case 'D': /* dword - 32 bits */	add_datatype_to_candidate_list(symbol, &search_constant_type_c::dword_type_name); break;
+		case 'L': /* lword - 64 bits */	add_datatype_to_candidate_list(symbol, &search_constant_type_c::lword_type_name); break;
+        	          /* if none of the above, then the empty string was used <=> boolean */
+		default:                        add_datatype_to_candidate_list(symbol, &search_constant_type_c::bool_type_name);  break;
 	}
 	return NULL;
 }
@@ -685,8 +660,7 @@
  * will do that for us. So we determine the candidate datatypes only for the full structured_variable.
  */
 void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) {
-	symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
-	if (NULL != result) add_datatype_to_candidate_list(symbol, result);
+	add_datatype_to_candidate_list(symbol, search_varfb_instance_type->get_basetype_decl(symbol));  /* will only add if non NULL */
 	return NULL;
 }
 
@@ -697,10 +671,9 @@
 /* B 1.5.1 Functions */
 /*********************/
 void *fill_candidate_datatypes_c::visit(function_declaration_c *symbol) {
+	if (debug) printf("Filling candidate data types list of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations_list->accept(*this);
-	if (debug) printf("Filling candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
-// 	il_parenthesis_level = 0;
 	symbol->function_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
@@ -711,10 +684,9 @@
 /* B 1.5.2 Function blocks */
 /***************************/
 void *fill_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+	if (debug) printf("Filling candidate data types list of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations->accept(*this);
-	if (debug) printf("Filling candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
-// 	il_parenthesis_level = 0;
 	symbol->fblock_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
@@ -725,10 +697,9 @@
 /* B 1.5.3 - Programs */
 /**********************/
 void *fill_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+	if (debug) printf("Filling candidate data types list in program %s\n", ((token_c *)(symbol->program_type_name))->value);
 	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
 	symbol->var_declarations->accept(*this);
-	if (debug) printf("Filling candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
-// 	il_parenthesis_level = 0;
 	symbol->function_block_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = NULL;
@@ -871,7 +842,6 @@
 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
 void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) {
   symbol_c *prev_il_instruction_backup = prev_il_instruction;
-//   il_parenthesis_level++;
   
   if (NULL != symbol->il_operand)
     symbol->il_operand->accept(*this);
@@ -879,9 +849,6 @@
   if(symbol->simple_instr_list != NULL)
     symbol->simple_instr_list->accept(*this);
 
-//   il_parenthesis_level--;
-//   if (il_parenthesis_level < 0) ERROR;
-  
   /* Now check the if the data type semantics of operation are correct,  */
   il_operand = symbol->simple_instr_list;
   prev_il_instruction = prev_il_instruction_backup;
@@ -1130,45 +1097,14 @@
 }
 
 
-void *fill_candidate_datatypes_c::visit(S1_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "S1", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(R1_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "R1", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(CLK_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "CLK", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(CU_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "CU", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(CD_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "CD", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(PV_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "PV", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(IN_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "IN", symbol->called_fb_declaration);
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(PT_operator_c *symbol) {
-	handle_implicit_il_fb_call(symbol, "PT", symbol->called_fb_declaration);
-	return NULL;
-}
+void *fill_candidate_datatypes_c::visit(S1_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "S1", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(R1_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "R1", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(CLK_operator_c *symbol) {handle_implicit_il_fb_call(symbol, "CLK", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(CU_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "CU", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(CD_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "CD", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(PV_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "PV", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(IN_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "IN", symbol->called_fb_declaration); return NULL;}
+void *fill_candidate_datatypes_c::visit(PT_operator_c  *symbol) {handle_implicit_il_fb_call(symbol,  "PT", symbol->called_fb_declaration); return NULL;}
 
 
 void *fill_candidate_datatypes_c::visit(AND_operator_c *symbol) {
@@ -1273,73 +1209,11 @@
 	return NULL;
 }
 
-void *fill_candidate_datatypes_c::visit(ADD_operator_c *symbol) {
-	symbol_c *prev_instruction_type, *operand_type;
-        
-        symbol->deprecated_operation = false;
-	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];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(prev_instruction_type, operand_type, widen_ADD_table));
-		}
-	}
-	if (debug) std::cout <<  "ADD [" << 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(SUB_operator_c *symbol) {
-	symbol_c *prev_instruction_type, *operand_type;
-
-        symbol->deprecated_operation = false;
-	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];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(prev_instruction_type, operand_type, widen_SUB_table));
-		}
-	}
-	if (debug) std::cout <<  "SUB [" << 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(MUL_operator_c *symbol) {
-	symbol_c *prev_instruction_type, *operand_type;
-
-        symbol->deprecated_operation = false;
-	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];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(prev_instruction_type, operand_type, widen_MUL_table));
-		}
-	}
-	if (debug) std::cout <<  "MUL [" << 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(DIV_operator_c *symbol) {
-	symbol_c *prev_instruction_type, *operand_type;
-
-        symbol->deprecated_operation = false;
-	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];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(prev_instruction_type, operand_type, widen_DIV_table));
-		}
-	}
-	if (debug) std::cout <<  "DIV [" << 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(ADD_operator_c *symbol) {return handle_binary_operator(widen_ADD_table, symbol, prev_il_instruction, il_operand);}
+void *fill_candidate_datatypes_c::visit(SUB_operator_c *symbol) {return handle_binary_operator(widen_SUB_table, symbol, prev_il_instruction, il_operand);}
+void *fill_candidate_datatypes_c::visit(MUL_operator_c *symbol) {return handle_binary_operator(widen_MUL_table, symbol, prev_il_instruction, il_operand);}
+void *fill_candidate_datatypes_c::visit(DIV_operator_c *symbol) {return handle_binary_operator(widen_DIV_table, symbol, prev_il_instruction, il_operand);}
+
 
 void *fill_candidate_datatypes_c::visit(MOD_operator_c *symbol) {
 	symbol_c *prev_instruction_type, *operand_type;
@@ -1719,101 +1593,32 @@
 	return NULL;
 }
 
-void *fill_candidate_datatypes_c::visit(add_expression_c *symbol) {
-	/* The following code is correct when handling the addition of 2 symbolic_variables
-	 * In this case, adding two variables (e.g. USINT_var1 + USINT_var2) will always yield
-	 * the same data type, even if the result of the adition could not fit inside the same
-	 * data type (due to overflowing)
-	 *
-	 * However, when adding two literals (e.g. USINT#42 + USINT#3)
-	 * we should be able to detect overflows of the result, and therefore not consider
-	 * that the result may be of type USINT.
-	 * Currently we do not yet detect these overflows, and allow handling the sum of two USINTs
-	 * as always resulting in an USINT, even in the following expression
-	 * (USINT#65535 + USINT#2).
-	 *
-	 * In the future we can add some code to reduce
-	 * all the expressions that are based on literals into the resulting literal
-	 * value (maybe some visitor class that will run before or after data type
-	 * checking). Since this class will have to be very careful to make sure it implements the same mathematical
-	 * details (e.g. how to round and truncate numbers) as defined in IEC 61131-3, we will leave this to the future.
-	 * Also, the question will arise if we should also replace calls to standard
-	 * functions if the input parameters are all literals (e.g. ADD(42, 42)). This
-	 * means this class will be more difficult than it appears at first.
-	 */
-	symbol_c *left_type, *right_type;
-
-        symbol->deprecated_operation = false;
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
-			left_type = symbol->l_exp->candidate_datatypes[i];
-			right_type = symbol->r_exp->candidate_datatypes[j];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(left_type, right_type, widen_ADD_table));
-		}
-	}
-	if (debug) std::cout <<  "+ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit(sub_expression_c *symbol) {
-	symbol_c *left_type, *right_type;
-
-        symbol->deprecated_operation = false;
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
-			left_type = symbol->l_exp->candidate_datatypes[i];
-			right_type = symbol->r_exp->candidate_datatypes[j];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(left_type, right_type, widen_SUB_table));
-		}
-	}
-	if (debug) std::cout <<  "- [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
-
-
-void *fill_candidate_datatypes_c::visit(mul_expression_c *symbol) {
-	symbol_c *left_type, *right_type;
-
-        symbol->deprecated_operation = false;
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
-			left_type = symbol->l_exp->candidate_datatypes[i];
-			right_type = symbol->r_exp->candidate_datatypes[j];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(left_type, right_type, widen_MUL_table));
-		}
-	}
-	if (debug) std::cout << "* [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-
-	return NULL;
-}
-
-void *fill_candidate_datatypes_c::visit(div_expression_c *symbol) {
-	symbol_c *left_type, *right_type;
-
-        symbol->deprecated_operation = false;
-	symbol->l_exp->accept(*this);
-	symbol->r_exp->accept(*this);
-	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
-		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
-			left_type = symbol->l_exp->candidate_datatypes[i];
-			right_type = symbol->r_exp->candidate_datatypes[j];
-			/* NOTE: add_datatype_to_candidate_list() will only really add the datatype if it is != NULL !!! */
-			add_datatype_to_candidate_list(symbol, widening_conversion(left_type, right_type, widen_DIV_table));
-		}
-	}
-	if (debug) std::cout << "/ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
-	return NULL;
-}
+
+/* The following code is correct when handling the addition of 2 symbolic_variables
+ * In this case, adding two variables (e.g. USINT_var1 + USINT_var2) will always yield
+ * the same data type, even if the result of the adition could not fit inside the same
+ * data type (due to overflowing)
+ *
+ * However, when adding two literals (e.g. USINT#42 + USINT#3)
+ * we should be able to detect overflows of the result, and therefore not consider
+ * that the result may be of type USINT.
+ * Currently we do not yet detect these overflows, and allow handling the sum of two USINTs
+ * as always resulting in an USINT, even in the following expression
+ * (USINT#65535 + USINT#2).
+ *
+ * In the future we can add some code to reduce
+ * all the expressions that are based on literals into the resulting literal
+ * value (maybe some visitor class that will run before or after data type
+ * checking). Since this class will have to be very careful to make sure it implements the same mathematical
+ * details (e.g. how to round and truncate numbers) as defined in IEC 61131-3, we will leave this to the future.
+ * Also, the question will arise if we should also replace calls to standard
+ * functions if the input parameters are all literals (e.g. ADD(42, 42)). This
+ * means this class will be more difficult than it appears at first.
+ */
+void *fill_candidate_datatypes_c::visit(add_expression_c *symbol) {return handle_binary_expression(widen_ADD_table, symbol, symbol->l_exp, symbol->r_exp);}
+void *fill_candidate_datatypes_c::visit(sub_expression_c *symbol) {return handle_binary_expression(widen_SUB_table, symbol, symbol->l_exp, symbol->r_exp);}
+void *fill_candidate_datatypes_c::visit(mul_expression_c *symbol) {return handle_binary_expression(widen_MUL_table, symbol, symbol->l_exp, symbol->r_exp);}
+void *fill_candidate_datatypes_c::visit(div_expression_c *symbol) {return handle_binary_expression(widen_DIV_table, symbol, symbol->l_exp, symbol->r_exp);}
 
 
 void *fill_candidate_datatypes_c::visit(mod_expression_c *symbol) {
--- a/stage3/fill_candidate_datatypes.hh	Tue Mar 13 16:38:21 2012 +0000
+++ b/stage3/fill_candidate_datatypes.hh	Tue Mar 13 18:29:34 2012 +0000
@@ -83,10 +83,12 @@
 
     /* Match a function declaration with a function call through their parameters.*/
     /* returns true if compatible function/FB invocation, otherwise returns false */
-    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);
+    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_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 helper function... */
     symbol_c *base_type(symbol_c *symbol);