Break constant_folding_c in two classes: constant_folding_c and constant_propagation_c
authormjsousa
Tue, 30 Dec 2014 23:31:36 +0000
changeset 984 634269b0f104
parent 983 ead554e12195
child 985 837c6532a9b8
Break constant_folding_c in two classes: constant_folding_c and constant_propagation_c
stage3/constant_folding.cc
stage3/constant_folding.hh
stage3/stage3.cc
--- a/stage3/constant_folding.cc	Tue Dec 30 22:58:52 2014 +0000
+++ b/stage3/constant_folding.cc	Tue Dec 30 23:31:36 2014 +0000
@@ -591,6 +591,7 @@
 /***********************************************************************/
 /***********************************************************************/
 
+
 /* static void *handle_cmp(symbol_c *symbol, symbol_c *oper1, symbol_c *oper2, OPERATION) */
 #define handle_cmp(symbol, oper1, oper2, operation) {               \
 	if ((NULL == oper1) || (NULL == oper2)) return NULL;        \
@@ -724,9 +725,527 @@
 	return NULL;
 }
 
-static constant_folding_c::map_values_t inner_left_join_values(constant_folding_c::map_values_t m1, constant_folding_c::map_values_t m2) {
-	constant_folding_c::map_values_t::const_iterator itr;
-	constant_folding_c::map_values_t ret;
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***        Helper functions for handling IL instruction lists.      ***/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
+/* If the cvalues of all the prev_il_intructions have the same VALID value, then set the local cvalue to that value, otherwise, set it to NONCONST! */
+#define intersect_prev_CVALUE_(dtype, symbol) {                                                                   \
+	symbol->const_value._##dtype = symbol->prev_il_instruction[0]->const_value._##dtype;                      \
+	for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {                                   \
+		if (!ISEQUAL_CVALUE(dtype, symbol, symbol->prev_il_instruction[i]))                               \
+			{SET_NONCONST(dtype, symbol); break;}                                                     \
+	}                                                                                                         \
+}
+
+static void intersect_prev_cvalues(il_instruction_c *symbol) {
+	if (symbol->prev_il_instruction.empty())
+		return;
+	intersect_prev_CVALUE_(real64, symbol);
+	intersect_prev_CVALUE_(uint64, symbol);
+	intersect_prev_CVALUE_( int64, symbol);
+	intersect_prev_CVALUE_(  bool, symbol);
+}
+
+
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***        The constant_folding_c                                   ***/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
+constant_folding_c::constant_folding_c(symbol_c *symbol) {
+    error_count = 0;
+    warning_found = false;
+    current_display_error_level = 0;
+    il_operand = NULL;
+    prev_il_instruction = NULL;
+    
+    /* check whether the platform on which the compiler is being run implements IEC 559 floating point data types. */
+    symbol_c null_symbol;
+    if (! (std::numeric_limits<real64_t>::is_iec559) )
+        STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 60559 floating point numbers. "
+                                                   "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
+                                                   "(i.e. constant folding) may themselves be erroneous, although are most probably correct."
+                                                   "However, more likely is the possible existance of overflow/underflow errors that are not detected.");
+}
+
+
+constant_folding_c::~constant_folding_c(void) {
+}
+
+
+int constant_folding_c::get_error_count() {
+	return error_count;
+}
+
+
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+void *constant_folding_c::visit(real_c *symbol) {
+	bool overflow;
+	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(real64, symbol);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(integer_c *symbol) {
+	bool overflow;
+	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
+	if (overflow) SET_OVFLOW(int64, symbol);
+	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(uint64, symbol);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(neg_real_c *symbol) {
+	symbol->exp->accept(*this);
+	DO_UNARY_OPER(real64, -, symbol->exp); CHECK_OVERFLOW_real64(symbol);
+	if (IS_OVFLOW(real64, symbol->exp)) SET_OVFLOW(real64, symbol);
+	return NULL;
+}
+
+
+
+/* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
+void *constant_folding_c::visit(neg_integer_c *symbol) {
+	symbol->exp->accept(*this);
+	/* Note that due to syntax restrictions, the value of symbol->exp will always be positive. 
+	 * However, the following code does not depend on that restriction.
+	 */
+	/* The remainder of the code (for example, data type checking) considers the neg_integer_c as a leaf of the
+	 * abstract syntax tree, and therefore simply ignores the values of neg_integer_c->exp.
+	 * For this reason only, and in only this situation, we must guarantee that any 'overflow' situation in 
+	 * the cvalue of neg_integer_c->exp is also reflected back to this neg_integer_c symbol.
+	 * For the rest of the code we do NOT do this, as it would gurantee that a single overflow deep inside
+	 * an expression would imply that the expression itself would also be set to 'overflow' condition.
+	 * This in turn would then have the compiler produce a whole load of error messages where they are not wanted!
+	 */
+	DO_UNARY_OPER(uint64, -, symbol->exp); CHECK_OVERFLOW_uint64_NEG(symbol, symbol->exp);  /* handle the uintv := -0 situation */
+	if (IS_OVFLOW(uint64, symbol->exp)) SET_OVFLOW(uint64, symbol);
+	DO_UNARY_OPER( int64, -, symbol->exp); CHECK_OVERFLOW_int64_NEG (symbol, symbol->exp);
+	if (IS_OVFLOW( int64, symbol->exp)) SET_OVFLOW( int64, symbol);
+	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
+	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
+	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
+	 *
+	 * This same situation is usually considered an overflow (check handle_neg() function). However, here we have a special
+	 * situation. If we do not allow this, then the user would never the able to use the following code:
+	 *  VAR v : LINT; END_VAR
+	 *    v := -9223372036854775809 ; (* - |INT64_MIN| == INT64_MIN *)
+	 */
+	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
+	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) {
+		SET_CVALUE(int64, symbol, INT64_MIN);
+	}
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(binary_integer_c *symbol) {
+	bool overflow;
+	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
+	if (overflow) SET_OVFLOW(int64, symbol);
+	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(uint64, symbol);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(octal_integer_c *symbol) {
+	bool overflow;
+	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
+	if (overflow) SET_OVFLOW(int64, symbol);
+	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(uint64, symbol);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(hex_integer_c *symbol) {
+	bool overflow;
+	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
+	if (overflow) SET_OVFLOW(int64, symbol);
+	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(uint64, symbol);
+	return NULL;
+}
+
+
+/*
+integer_literal:
+  integer_type_name '#' signed_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' binary_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' octal_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+| integer_type_name '#' hex_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
+*/
+// SYM_REF2(integer_literal_c, type, value)
+void *constant_folding_c::visit(integer_literal_c *symbol) {
+	symbol->value->accept(*this);
+	DO_UNARY_OPER( int64, /* none */, symbol->value);
+	DO_UNARY_OPER(uint64, /* none */, symbol->value);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(real_literal_c *symbol) {
+	symbol->value->accept(*this);
+	DO_UNARY_OPER(real64, /* none */, symbol->value);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(bit_string_literal_c *symbol) {
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(boolean_literal_c *symbol) {
+	symbol->value->accept(*this);
+	DO_UNARY_OPER(bool, /* none */, symbol->value);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(boolean_true_c *symbol) {
+	SET_CVALUE(bool, symbol, true);
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(boolean_false_c *symbol) {
+	SET_CVALUE(bool, symbol, false);
+	return NULL;
+}
+
+/************************/
+/* B 1.2.3.1 - Duration */
+/********* **************/
+void *constant_folding_c::visit(fixed_point_c *symbol) {
+	bool overflow;
+	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
+	if (overflow) SET_OVFLOW(real64, symbol);
+	return NULL;
+}
+
+
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+/* Not needed, since we inherit from iterator_visitor_c */
+/*| instruction_list il_instruction */
+// SYM_LIST(instruction_list_c)
+// void *constant_folding_c::visit(instruction_list_c *symbol) {}
+
+/* | label ':' [il_incomplete_instruction] eol_list */
+// SYM_REF2(il_instruction_c, label, il_instruction)
+// void *visit(instruction_list_c *symbol);
+void *constant_folding_c::visit(il_instruction_c *symbol) {
+	if (NULL == symbol->il_instruction) {
+		/* This empty/null il_instruction does not change the value of the current/default IL variable.
+		 * So it inherits the candidate_datatypes from it's previous IL instructions!
+		 */
+		intersect_prev_cvalues(symbol);
+	} else {
+		il_instruction_c fake_prev_il_instruction = *symbol;
+		intersect_prev_cvalues(&fake_prev_il_instruction);
+
+		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
+		else                                          prev_il_instruction = &fake_prev_il_instruction;
+		symbol->il_instruction->accept(*this);
+		prev_il_instruction = NULL;
+
+		/* This object has (inherits) the same cvalues as the il_instruction */
+		symbol->const_value = symbol->il_instruction->const_value;
+	}
+
+	return NULL;
+}
+
+
+void *constant_folding_c::visit(il_simple_operation_c *symbol) {
+	/* determine the cvalue of the operand */
+	if (NULL != symbol->il_operand) {
+		symbol->il_operand->accept(*this);
+	}
+	/* determine the cvalue resulting from executing the il_operator... */
+	il_operand = symbol->il_operand;
+	symbol->il_simple_operator->accept(*this);
+	il_operand = NULL;
+	/* This object has (inherits) the same cvalues as the il_instruction */
+	symbol->const_value = symbol->il_simple_operator->const_value;
+	return NULL;
+}
+
+
+/* TODO: handle function invocations... */
+/* | 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 *constant_folding_c::visit(il_function_call_c *symbol) {}
+
+
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *constant_folding_c::visit(il_expression_c *symbol) {
+  symbol_c *prev_il_instruction_backup = prev_il_instruction;
+  
+  /* Stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list if necessary. We can therefore ignore the 'il_operand' entry! */
+  // if (NULL != symbol->il_operand)
+  //   symbol->il_operand->accept(*this);
+
+  if(symbol->simple_instr_list != NULL)
+    symbol->simple_instr_list->accept(*this);
+
+  /* Now do the operation,  */
+  il_operand = symbol->simple_instr_list;
+  prev_il_instruction = prev_il_instruction_backup;
+  symbol->il_expr_operator->accept(*this);
+  il_operand = NULL;
+  
+  /* This object has (inherits) the same cvalues as the il_instruction */
+  symbol->const_value = symbol->il_expr_operator->const_value;
+  
+  /* Since stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list when an 'il_operand' exists, we know
+   * that if (symbol->il_operand != NULL), then the first IL instruction in the simple_instr_list will be the equivalent and artificial
+   * 'LD <il_operand>' IL instruction.
+   * Just to be cosistent, we will copy the constant info back into the il_operand, even though this should not be necessary!
+   */
+  if ((NULL != symbol->il_operand) && ((NULL == symbol->simple_instr_list) || (0 == ((list_c *)symbol->simple_instr_list)->n))) ERROR; // stage2 is not behaving as we expect it to!
+  if  (NULL != symbol->il_operand)
+    symbol->il_operand->const_value = ((list_c *)symbol->simple_instr_list)->elements[0]->const_value;
+
+  return NULL;
+}
+
+
+
+void *constant_folding_c::visit(il_jump_operation_c *symbol) {
+  /* recursive call to fill const values... */
+  il_operand = NULL;
+  symbol->il_jump_operator->accept(*this);
+  il_operand = NULL;
+  /* This object has (inherits) the same cvalues as the il_jump_operator */
+  symbol->const_value = symbol->il_jump_operator->const_value;
+  return NULL;
+}
+
+
+
+/* FB calls leave the value in the accumulator unchanged */
+/*   il_call_operator prev_declared_fb_name
+ * | il_call_operator prev_declared_fb_name '(' ')'
+ * | il_call_operator prev_declared_fb_name '(' eol_list ')'
+ * | 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 */
+// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
+void *constant_folding_c::visit(il_fb_call_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+
+
+/* TODO: handle function invocations... */
+/* | 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 *constant_folding_c::visit(il_formal_funct_call_c *symbol) {return NULL;}
+
+
+
+/* Not needed, since we inherit from iterator_visitor_c */
+//  void *constant_folding_c::visit(il_operand_list_c *symbol);
+
+
+
+/* | simple_instr_list il_simple_instruction */
+/* This object is referenced by il_expression_c objects */
+void *constant_folding_c::visit(simple_instr_list_c *symbol) {
+  if (symbol->n <= 0)
+    return NULL;  /* List is empty! Nothing to do. */
+    
+  for(int i = 0; i < symbol->n; i++)
+    symbol->elements[i]->accept(*this);
+
+  /* This object has (inherits) the same cvalues as the il_jump_operator */
+  symbol->const_value = symbol->elements[symbol->n-1]->const_value;
+  return NULL;
+}
+
+
+
+// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
+void *constant_folding_c::visit(il_simple_instruction_c *symbol) {
+  if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
+  if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
+  else                                          prev_il_instruction = symbol->prev_il_instruction[0];
+  symbol->il_simple_instruction->accept(*this);
+  prev_il_instruction = NULL;
+
+  /* This object has (inherits) the same cvalues as the il_jump_operator */
+  symbol->const_value = symbol->il_simple_instruction->const_value;
+  return NULL;
+}
+
+
+/*
+    void *visit(il_param_list_c *symbol);
+    void *visit(il_param_assignment_c *symbol);
+    void *visit(il_param_out_assignment_c *symbol);
+*/
+
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *constant_folding_c::visit(   LD_operator_c *symbol) {return handle_move(symbol, il_operand);}
+void *constant_folding_c::visit(  LDN_operator_c *symbol) {return handle_not (symbol, il_operand);}
+
+/* NOTE: we are implementing a constant folding algorithm, not a constant propagation algorithm.
+ *       For the constant propagation algorithm, the correct implementation of ST(N)_operator_c would be...
+ */
+//void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(il_operand, symbol);}
+//void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_not (il_operand, symbol);}
+void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+
+/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
+ *              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! This error will be caught elsewhere!
+ */
+void *constant_folding_c::visit(  NOT_operator_c *symbol) {return handle_not(symbol, prev_il_instruction);}
+
+/* NOTE: Since we are only implementing a constant folding algorithm, and not a constant propagation algorithm,
+ *       the following IL instructions do not change/set the value of the il_operand!
+ */
+void *constant_folding_c::visit(    S_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(    R_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+
+/* FB calls leave the value in the accumulator unchanged */
+void *constant_folding_c::visit(   S1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   R1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(  CLK_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   CU_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   CD_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   PV_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   IN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(   PT_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+
+void *constant_folding_c::visit(  AND_operator_c *symbol) {return handle_and (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(   OR_operator_c *symbol) {return handle_or  (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(  XOR_operator_c *symbol) {return handle_xor (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit( ANDN_operator_c *symbol) {       handle_and (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
+void *constant_folding_c::visit(  ORN_operator_c *symbol) {       handle_or  (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
+void *constant_folding_c::visit( XORN_operator_c *symbol) {       handle_xor (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
+
+void *constant_folding_c::visit(  ADD_operator_c *symbol) {return handle_add (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(  SUB_operator_c *symbol) {return handle_sub (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(  MUL_operator_c *symbol) {return handle_mul (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(  DIV_operator_c *symbol) {return handle_div (symbol, prev_il_instruction, il_operand);}
+void *constant_folding_c::visit(  MOD_operator_c *symbol) {return handle_mod (symbol, prev_il_instruction, il_operand);}
+
+void *constant_folding_c::visit(   GT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, > );}
+void *constant_folding_c::visit(   GE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, >=);}
+void *constant_folding_c::visit(   EQ_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, ==);}
+void *constant_folding_c::visit(   LT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, < );}
+void *constant_folding_c::visit(   LE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, <=);}
+void *constant_folding_c::visit(   NE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, !=);}
+
+void *constant_folding_c::visit(  CAL_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(  RET_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(  JMP_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit( CALC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(CALCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit( RETC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(RETCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit( JMPC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+void *constant_folding_c::visit(JMPCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
+
+
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+void *constant_folding_c::visit(    or_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_or (symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   xor_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_xor(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   and_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_and(symbol, symbol->l_exp, symbol->r_exp);}
+
+void *constant_folding_c::visit(   equ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, ==);}
+void *constant_folding_c::visit(notequ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, !=);}
+void *constant_folding_c::visit(    lt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, < );}
+void *constant_folding_c::visit(    gt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, > );}
+void *constant_folding_c::visit(    le_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, <=);}
+void *constant_folding_c::visit(    ge_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, >=);}
+
+void *constant_folding_c::visit(   add_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_add(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   sub_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_sub(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   mul_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mul(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   div_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_div(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit(   mod_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mod(symbol, symbol->l_exp, symbol->r_exp);}
+void *constant_folding_c::visit( power_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_pow(symbol, symbol->l_exp, symbol->r_exp);}
+
+void *constant_folding_c::visit(   neg_expression_c *symbol) {symbol->  exp->accept(*this); return handle_neg(symbol, symbol->exp);}
+void *constant_folding_c::visit(   not_expression_c *symbol) {symbol->  exp->accept(*this); return handle_not(symbol, symbol->exp);}
+
+
+
+
+
+
+
+
+
+
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***        The constant_propagation_c                               ***/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
+constant_propagation_c::constant_propagation_c(symbol_c *symbol)
+  : constant_folding_c(symbol) {
+    current_resource = NULL;
+    current_configuration = NULL;
+    fixed_init_value_ = false;
+    function_pou_ = false;
+}
+
+
+constant_propagation_c::~constant_propagation_c(void) {}
+
+
+static constant_propagation_c::map_values_t inner_left_join_values(constant_propagation_c::map_values_t m1, constant_propagation_c::map_values_t m2) {
+	constant_propagation_c::map_values_t::const_iterator itr;
+	constant_propagation_c::map_values_t ret;
 
 	itr = m1.begin();
 	for ( ; itr != m1.end(); ++itr) {
@@ -748,92 +1267,6 @@
 	return ret;
 }
 
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***        Helper functions for handling IL instruction lists.      ***/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-
-/* If the cvalues of all the prev_il_intructions have the same VALID value, then set the local cvalue to that value, otherwise, set it to NONCONST! */
-#define intersect_prev_CVALUE_(dtype, symbol) {                                                                   \
-	symbol->const_value._##dtype = symbol->prev_il_instruction[0]->const_value._##dtype;                      \
-	for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {                                   \
-		if (!ISEQUAL_CVALUE(dtype, symbol, symbol->prev_il_instruction[i]))                               \
-			{SET_NONCONST(dtype, symbol); break;}                                                     \
-	}                                                                                                         \
-}
-
-static void intersect_prev_cvalues(il_instruction_c *symbol) {
-	if (symbol->prev_il_instruction.empty())
-		return;
-	intersect_prev_CVALUE_(real64, symbol);
-	intersect_prev_CVALUE_(uint64, symbol);
-	intersect_prev_CVALUE_( int64, symbol);
-	intersect_prev_CVALUE_(  bool, symbol);
-}
-
-
-
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***        The constant_folding_c                                   ***/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-#if 0
-// not currently needed, so comment it out!...
-// returns true if both symbols have the same value in all the cvalues
-bool constant_folding_c::is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2) {
-	if (VALID_CVALUE  (real64, symbol_1) != VALID_CVALUE  (real64, symbol_2)) return false;
-	if (VALID_CVALUE  (uint64, symbol_1) != VALID_CVALUE  (uint64, symbol_2)) return false;
-	if (VALID_CVALUE  ( int64, symbol_1) != VALID_CVALUE  ( int64, symbol_2)) return false;
-	if (VALID_CVALUE  (  bool, symbol_1) != VALID_CVALUE  (  bool, symbol_2)) return false;
-	if (VALID_CVALUE  (real64, symbol_1) && !ISEQUAL_CVALUE(real64, symbol_1, symbol_2)) return false;
-	if (VALID_CVALUE  (uint64, symbol_1) && !ISEQUAL_CVALUE(uint64, symbol_1, symbol_2)) return false;
-	if (VALID_CVALUE  ( int64, symbol_1) && !ISEQUAL_CVALUE( int64, symbol_1, symbol_2)) return false;
-	if (VALID_CVALUE  (  bool, symbol_1) && !ISEQUAL_CVALUE(  bool, symbol_1, symbol_2)) return false;
-	return true;
-}
-#endif
-
-
-
-constant_folding_c::constant_folding_c(symbol_c *symbol) {
-    current_resource = NULL;
-    current_configuration = NULL;
-    fixed_init_value_ = false;
-    function_pou_ = false;
-    error_count = 0;
-    warning_found = false;
-    current_display_error_level = 0;
-    il_operand = NULL;
-    search_varfb_instance_type = NULL;
-    prev_il_instruction = NULL;
-    
-    /* check whether the platform on which the compiler is being run implements IEC 559 floating point data types. */
-    symbol_c null_symbol;
-    if (! (std::numeric_limits<real64_t>::is_iec559) )
-        STAGE3_WARNING(&null_symbol, &null_symbol, "The platform running the compiler does not implement IEC 60559 floating point numbers. "
-                                                   "Any error and/or warning messages related to overflow/underflow of the result of operations on REAL/LREAL literals "
-                                                   "(i.e. constant folding) may themselves be erroneous, although are most probably correct."
-                                                   "However, more likely is the possible existance of overflow/underflow errors that are not detected.");
-}
-
-
-constant_folding_c::~constant_folding_c(void) {
-}
-
-
-int constant_folding_c::get_error_count() {
-	return error_count;
-}
-
-
 /***************************/
 /* B 0 - Programming Model */
 /***************************/
@@ -919,7 +1352,7 @@
    *         any configuration - e.g. functions, and most FBs!).
    *       It is for this reason (3) why we have the two loops on the following code!
    */
-void *constant_folding_c::visit(library_c *symbol) {
+void *constant_propagation_c::visit(library_c *symbol) {
   int i;
   
   for (i = 0; i < symbol->n; i++) {
@@ -941,165 +1374,12 @@
   return NULL;
 }
 
-/*********************/
-/* B 1.2 - Constants */
-/*********************/
-/******************************/
-/* B 1.2.1 - Numeric Literals */
-/******************************/
-void *constant_folding_c::visit(real_c *symbol) {
-	bool overflow;
-	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(real64, symbol);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(integer_c *symbol) {
-	bool overflow;
-	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
-	if (overflow) SET_OVFLOW(int64, symbol);
-	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(uint64, symbol);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(neg_real_c *symbol) {
-	symbol->exp->accept(*this);
-	DO_UNARY_OPER(real64, -, symbol->exp); CHECK_OVERFLOW_real64(symbol);
-	if (IS_OVFLOW(real64, symbol->exp)) SET_OVFLOW(real64, symbol);
-	return NULL;
-}
-
-
-
-/* | '-' integer	{$$ = new neg_integer_c($2, locloc(@$));} */
-void *constant_folding_c::visit(neg_integer_c *symbol) {
-	symbol->exp->accept(*this);
-	/* Note that due to syntax restrictions, the value of symbol->exp will always be positive. 
-	 * However, the following code does not depend on that restriction.
-	 */
-	/* The remainder of the code (for example, data type checking) considers the neg_integer_c as a leaf of the
-	 * abstract syntax tree, and therefore simply ignores the values of neg_integer_c->exp.
-	 * For this reason only, and in only this situation, we must guarantee that any 'overflow' situation in 
-	 * the cvalue of neg_integer_c->exp is also reflected back to this neg_integer_c symbol.
-	 * For the rest of the code we do NOT do this, as it would gurantee that a single overflow deep inside
-	 * an expression would imply that the expression itself would also be set to 'overflow' condition.
-	 * This in turn would then have the compiler produce a whole load of error messages where they are not wanted!
-	 */
-	DO_UNARY_OPER(uint64, -, symbol->exp); CHECK_OVERFLOW_uint64_NEG(symbol, symbol->exp);  /* handle the uintv := -0 situation */
-	if (IS_OVFLOW(uint64, symbol->exp)) SET_OVFLOW(uint64, symbol);
-	DO_UNARY_OPER( int64, -, symbol->exp); CHECK_OVERFLOW_int64_NEG (symbol, symbol->exp);
-	if (IS_OVFLOW( int64, symbol->exp)) SET_OVFLOW( int64, symbol);
-	/* NOTE 1: INT64_MIN = -(INT64_MAX + 1)   ---> assuming two's complement representation!!!
-	 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here.
-	 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue.
-	 *
-	 * This same situation is usually considered an overflow (check handle_neg() function). However, here we have a special
-	 * situation. If we do not allow this, then the user would never the able to use the following code:
-	 *  VAR v : LINT; END_VAR
-	 *    v := -9223372036854775809 ; (* - |INT64_MIN| == INT64_MIN *)
-	 */
-	// if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement
-	if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) {
-		SET_CVALUE(int64, symbol, INT64_MIN);
-	}
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(binary_integer_c *symbol) {
-	bool overflow;
-	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
-	if (overflow) SET_OVFLOW(int64, symbol);
-	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(uint64, symbol);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(octal_integer_c *symbol) {
-	bool overflow;
-	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
-	if (overflow) SET_OVFLOW(int64, symbol);
-	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(uint64, symbol);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(hex_integer_c *symbol) {
-	bool overflow;
-	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
-	if (overflow) SET_OVFLOW(int64, symbol);
-	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(uint64, symbol);
-	return NULL;
-}
-
-
-/*
-integer_literal:
-  integer_type_name '#' signed_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
-| integer_type_name '#' binary_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
-| integer_type_name '#' octal_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
-| integer_type_name '#' hex_integer	{$$ = new integer_literal_c($1, $3, locloc(@$));}
-*/
-// SYM_REF2(integer_literal_c, type, value)
-void *constant_folding_c::visit(integer_literal_c *symbol) {
-	symbol->value->accept(*this);
-	DO_UNARY_OPER( int64, /* none */, symbol->value);
-	DO_UNARY_OPER(uint64, /* none */, symbol->value);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(real_literal_c *symbol) {
-	symbol->value->accept(*this);
-	DO_UNARY_OPER(real64, /* none */, symbol->value);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(bit_string_literal_c *symbol) {
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(boolean_literal_c *symbol) {
-	symbol->value->accept(*this);
-	DO_UNARY_OPER(bool, /* none */, symbol->value);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(boolean_true_c *symbol) {
-	SET_CVALUE(bool, symbol, true);
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(boolean_false_c *symbol) {
-	SET_CVALUE(bool, symbol, false);
-	return NULL;
-}
-
-/************************/
-/* B 1.2.3.1 - Duration */
-/********* **************/
-void *constant_folding_c::visit(fixed_point_c *symbol) {
-	bool overflow;
-	SET_CVALUE(real64, symbol, extract_real_value(symbol, &overflow));
-	if (overflow) SET_OVFLOW(real64, symbol);
-	return NULL;
-}
 
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
 #if DO_CONSTANT_PROPAGATION__
-void *constant_folding_c::visit(symbolic_variable_c *symbol) {
+void *constant_propagation_c::visit(symbolic_variable_c *symbol) {
 	std::string varName = get_var_name_c::get_name(symbol->var_name)->value;
 	if (values.count(varName) > 0) 
 		symbol->const_value = values[varName];
@@ -1107,7 +1387,7 @@
 }
 #endif  // DO_CONSTANT_PROPAGATION__
 
-void *constant_folding_c::visit(symbolic_constant_c *symbol) {
+void *constant_propagation_c::visit(symbolic_constant_c *symbol) {
 	std::string varName = get_var_name_c::get_name(symbol->var_name)->value;
 	if (values.count(varName) > 0) 
 		symbol->const_value = values[varName];
@@ -1119,14 +1399,14 @@
 /* B 1.4.3 - Declaration & Initialisation */
 /******************************************/
   
-void *constant_folding_c::handle_var_decl(symbol_c *var_list, bool fixed_init_value) {
+void *constant_propagation_c::handle_var_decl(symbol_c *var_list, bool fixed_init_value) {
   fixed_init_value_ = fixed_init_value;
   var_list->accept(*this); 
   fixed_init_value_ = false; 
   return NULL;
 }
 
-void *constant_folding_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl) {
+void *constant_propagation_c::handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl) {
   type_decl->accept(*this);  // Do constant folding of the initial value, and literals in subranges! (we will probably be doing this multiple times for the same init value, but this is safe as the cvalue is idem-potent)
   symbol_c *init_value = type_initial_value_c::get(type_decl);  
   if (NULL == init_value)   {return NULL;} // this is probably a FB datatype, for which no initial value exists! Do nothing and return.
@@ -1153,8 +1433,8 @@
 //SYM_REF0(constant_option_c)     // Not needed!
 //SYM_REF0(retain_option_c)       // Not needed!
 //SYM_REF0(non_retain_option_c)   // Not needed!
-bool constant_folding_c::is_constant(symbol_c *option) {return (NULL != dynamic_cast<constant_option_c *>(option));}
-bool constant_folding_c::is_retain  (symbol_c *option) {return (NULL != dynamic_cast<  retain_option_c *>(option));}
+bool constant_propagation_c::is_constant(symbol_c *option) {return (NULL != dynamic_cast<constant_option_c *>(option));}
+bool constant_propagation_c::is_retain  (symbol_c *option) {return (NULL != dynamic_cast<  retain_option_c *>(option));}
 
 /* | var1_list ',' variable_name */
 //SYM_LIST(var1_list_c)           // Not needed!
@@ -1165,7 +1445,7 @@
  *    enumerated_spec_init_c *
  */
 // SYM_REF2(var1_init_decl_c, var1_list, spec_init)
-void *constant_folding_c::visit(var1_init_decl_c *symbol) {return handle_var_list_decl(symbol->var1_list, symbol->spec_init);}
+void *constant_propagation_c::visit(var1_init_decl_c *symbol) {return handle_var_list_decl(symbol->var1_list, symbol->spec_init);}
 
 /* | [var1_list ','] variable_name integer '..' */
 /* NOTE: This is an extension to the standard!!! */
@@ -1188,7 +1468,7 @@
 //SYM_REF3(input_declarations_c, option, input_declaration_list, method) // Not needed since we inherit from iterator_visitor_c!
 // NOTE: Input variables can take any initial value, so we can not set the const_value annotation => we set fixed_init_value to false !!!
 //       We must still visit it iteratively, to set the const_value of all literals in the type declarations.
-void *constant_folding_c::visit(input_declarations_c *symbol) {return handle_var_decl(symbol->input_declaration_list, false);}
+void *constant_propagation_c::visit(input_declarations_c *symbol) {return handle_var_decl(symbol->input_declaration_list, false);}
 
 /* helper symbol for input_declarations */
 //SYM_LIST(input_declaration_list_c)                                     // Not needed!
@@ -1196,13 +1476,13 @@
 /* VAR_OUTPUT [RETAIN | NON_RETAIN] var_init_decl_list END_VAR */
 /* option -> may be NULL ! */
 //SYM_REF3(output_declarations_c, option, var_init_decl_list, method) 
-void *constant_folding_c::visit(output_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, !is_retain(symbol->option) && function_pou_);}
+void *constant_propagation_c::visit(output_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, !is_retain(symbol->option) && function_pou_);}
 
 /*  VAR_IN_OUT var_declaration_list END_VAR */
 //SYM_REF1(input_output_declarations_c, var_declaration_list)
 // NOTE: Input variables can take any initial value, so we can not set the const_value annotation => we set fixed_init_value to false !!!
 //       We must still visit it iteratively, to set the const_value of all literals in the type declarations.
-void *constant_folding_c::visit(input_output_declarations_c *symbol) {return handle_var_decl(symbol->var_declaration_list, false);}
+void *constant_propagation_c::visit(input_output_declarations_c *symbol) {return handle_var_decl(symbol->var_declaration_list, false);}
 
 /* helper symbol for input_output_declarations */
 /* var_declaration_list var_declaration ';' */
@@ -1217,13 +1497,13 @@
 /* VAR [CONSTANT] var_init_decl_list END_VAR */
 /* option -> may be NULL ! */
 //SYM_REF2(var_declarations_c, option, var_init_decl_list)
-void *constant_folding_c::visit(var_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, false);}
+void *constant_propagation_c::visit(var_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, false);}
 
 /*  VAR RETAIN var_init_decl_list END_VAR */
 //SYM_REF1(retentive_var_declarations_c, var_init_decl_list)             // Not needed since we inherit from iterator_visitor_c!
 // NOTE: Retentive variables can take any initial value, so we can not set the const_value annotation => we set fixed_init_value to false !!!
 //       We must still visit it iteratively, to set the const_value of all literals in the type declarations.
-void *constant_folding_c::visit(retentive_var_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, false);}
+void *constant_propagation_c::visit(retentive_var_declarations_c *symbol) {return handle_var_decl(symbol->var_init_decl_list, false);}
 
 #if 0  
 // TODO
@@ -1241,16 +1521,16 @@
 /*| VAR_EXTERNAL [CONSTANT] external_declaration_list END_VAR */
 /* option -> may be NULL ! */
 // SYM_REF2(external_var_declarations_c, option, external_declaration_list)
-void *constant_folding_c::visit(external_var_declarations_c *symbol) {return handle_var_decl(symbol->external_declaration_list, is_constant(symbol->option));}
+void *constant_propagation_c::visit(external_var_declarations_c *symbol) {return handle_var_decl(symbol->external_declaration_list, is_constant(symbol->option));}
 
 /* helper symbol for external_var_declarations */
 /*| external_declaration_list external_declaration';' */
 // SYM_LIST(external_declaration_list_c)
-// void *constant_folding_c::visit(external_declaration_list_c *symbol) {} // Not needed: we inherit from iterator_c
+// void *constant_propagation_c::visit(external_declaration_list_c *symbol) {} // Not needed: we inherit from iterator_c
 
 /*  global_var_name ':' (simple_specification|subrange_specification|enumerated_specification|array_specification|prev_declared_structure_type_name|function_block_type_name */
 //SYM_REF2(external_declaration_c, global_var_name, specification)
-void *constant_folding_c::visit(external_declaration_c *symbol) {
+void *constant_propagation_c::visit(external_declaration_c *symbol) {
   // The syntax does not allow VAR_EXTERN to be initialized. We must get the initial value from the corresponding VAR_GLOBAL declaration
   /* However, we only do this is if the visit() method for the Program/FB in which this VAR_EXTERN is found was called from the visit(configurtion/resource) visitor!
    * When we are called from the visit(library_c) visitor, we do not have the required information to do this!
@@ -1293,7 +1573,7 @@
  * is called from declaration_check_c,
  * This is done like this because we need to know the pairing of external<->global variables to get the cvalue
  * from the global variable. Since the external<->global pairing information is available in the declaration_check_c,
- * we have that class call the constant_folding_c::handle_var_extern_global_pair(), which will actually do the 
+ * we have that class call the constant_propagation_c::handle_var_extern_global_pair(), which will actually do the 
  * constant folding of the global and the external variable declarations!
  */
 /* NOTE: The constant propagation portion of this algorithm must still be done here!!
@@ -1312,18 +1592,18 @@
  * Nevertheless, since constant folding is idem-potent, it is simpler to just call handle_var_decl() instead
  * of writing some code specific for this situation!
  */
-void *constant_folding_c::visit(global_var_declarations_c *symbol) {return handle_var_decl(symbol->global_var_decl_list, is_constant(symbol->option));}
+void *constant_propagation_c::visit(global_var_declarations_c *symbol) {return handle_var_decl(symbol->global_var_decl_list, is_constant(symbol->option));}
 
 
 /* helper symbol for global_var_declarations */
 /*| global_var_decl_list global_var_decl ';' */
 // SYM_LIST(global_var_decl_list_c)
-// void *constant_folding_c::visit(global_var_decl_list_c *symbol) {} // Not needed: we inherit from iterator_c
+// void *constant_propagation_c::visit(global_var_decl_list_c *symbol) {} // Not needed: we inherit from iterator_c
 
 /*| global_var_spec ':' [located_var_spec_init|function_block_type_name] */
 /* type_specification ->may be NULL ! */
 //SYM_REF2(global_var_decl_c, global_var_spec, type_specification)
-void *constant_folding_c::visit(global_var_decl_c *symbol) {
+void *constant_propagation_c::visit(global_var_decl_c *symbol) {
   /* global_var_spec may be either a global_var_spec_c or a global_var_list_c.
    * Since we already have a nice method that handles var lists (handle_var_list_decl() )
    * if it is a global_var_spec_c we will create a temporary list so we can call that method!
@@ -1394,7 +1674,7 @@
 /***********************/
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 //SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;)
-void *constant_folding_c::visit(function_declaration_c *symbol) {
+void *constant_propagation_c::visit(function_declaration_c *symbol) {
 	values.clear(); /* Clear global map */
 	/* Add initial value of all declared variables into Values map. */
 	function_pou_ = true;
@@ -1415,7 +1695,7 @@
 /* option -> storage method, CONSTANT or <null> */
 // SYM_REF2(function_var_decls_c, option, decl_list)
 // NOTE: function_var_decls_c is only used inside Functions, so it is safe to call with fixed_init_value_ = true 
-void *constant_folding_c::visit(function_var_decls_c *symbol) {return handle_var_decl(symbol->decl_list, true);}
+void *constant_propagation_c::visit(function_var_decls_c *symbol) {return handle_var_decl(symbol->decl_list, true);}
 
 /* intermediate helper symbol for function_var_decls */
 // SYM_LIST(var2_init_decl_list_c) // Not needed since we inherit from iterator_c
@@ -1427,7 +1707,7 @@
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 //SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;)
-void *constant_folding_c::visit(function_block_declaration_c *symbol) {
+void *constant_propagation_c::visit(function_block_declaration_c *symbol) {
 	values.clear(); /* Clear global map */
 	/* Add initial value of all declared variables into Values map. */
 	function_pou_ = false;
@@ -1438,7 +1718,7 @@
 
 /*  VAR_TEMP temp_var_decl_list END_VAR */
 // SYM_REF1(temp_var_decls_c, var_decl_list)
-void *constant_folding_c::visit(temp_var_decls_c *symbol) {return handle_var_decl(symbol->var_decl_list, true);}
+void *constant_propagation_c::visit(temp_var_decls_c *symbol) {return handle_var_decl(symbol->var_decl_list, true);}
 
 /* intermediate helper symbol for temp_var_decls */
 // SYM_LIST(temp_var_decls_list_c)
@@ -1446,7 +1726,7 @@
 /*  VAR NON_RETAIN var_init_decl_list END_VAR */
 // SYM_REF1(non_retentive_var_decls_c, var_decl_list)
 // NOTE: non_retentive_var_decls_c is only used inside FBs and Programs, so it is safe to call with fixed_init_value_ = false 
-void *constant_folding_c::visit(non_retentive_var_decls_c *symbol) {return handle_var_decl(symbol->var_decl_list, false);}
+void *constant_propagation_c::visit(non_retentive_var_decls_c *symbol) {return handle_var_decl(symbol->var_decl_list, false);}
 
 
 /**********************/
@@ -1454,7 +1734,7 @@
 /**********************/
 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
 //SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;)
-void *constant_folding_c::visit(program_declaration_c *symbol) {
+void *constant_propagation_c::visit(program_declaration_c *symbol) {
 	values.clear(); /* Clear global map */
 	/* Add initial value of all declared variables into Values map. */
 	function_pou_ = false;
@@ -1479,7 +1759,7 @@
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 // SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, 
 //          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
-void *constant_folding_c::visit(configuration_declaration_c *symbol) {
+void *constant_propagation_c::visit(configuration_declaration_c *symbol) {
 	values.clear(); /* Clear global map */
 
 	/* Add initial value of all declared variables into Values map. */
@@ -1503,7 +1783,7 @@
 /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
 // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, 
 //          enumvalue_symtable_t enumvalue_symtable; localvar_symbmap_t localvar_symbmap; localvar_symbvec_t localvar_symbvec;)
-void *constant_folding_c::visit(resource_declaration_c *symbol) {
+void *constant_propagation_c::visit(resource_declaration_c *symbol) {
 	values.push(); /* Create inner scope */
 
 	/* Add initial value of all declared variables into Values map. */
@@ -1546,7 +1826,7 @@
 /* NOTE: The parameter 'called_prog_declaration'is used to pass data between stage 3 and stage4 */
 // SYM_REF5(program_configuration_c, retain_option, program_name, task_name, program_type_name, prog_conf_elements,
 //          symbol_c *called_prog_declaration;)
-void *constant_folding_c::visit(program_configuration_c *symbol) {
+void *constant_propagation_c::visit(program_configuration_c *symbol) {
 	/* find the declaration (i.e. the datatype) of the program being instantiated */
 	// NOTE: we do not use symbol->datatype so this cost propagation algorithm will not depend on the fill/narrow datatypes algorithm!
 	program_type_symtable_t::iterator itr = program_type_symtable.find(symbol->program_type_name);
@@ -1566,7 +1846,7 @@
 
 /*  fb_name WITH task_name */
 // SYM_REF2(fb_task_c, fb_name, task_name)
-void *constant_folding_c::visit(fb_task_c *symbol) {
+void *constant_propagation_c::visit(fb_task_c *symbol) {
 	/* find the declaration (i.e. the datatype) of the FB being instantiated */
 	// NOTE: we do not use symbol->datatype so this cost propagation algorithm will not depend on the fill/narrow datatypes algorithm!
 	symbol_c *fb_type_name = NULL;
@@ -1610,243 +1890,6 @@
 
 
 
-/****************************************/
-/* B.2 - Language IL (Instruction List) */
-/****************************************/
-/***********************************/
-/* B 2.1 Instructions and Operands */
-/***********************************/
-/* Not needed, since we inherit from iterator_visitor_c */
-/*| instruction_list il_instruction */
-// SYM_LIST(instruction_list_c)
-// void *constant_folding_c::visit(instruction_list_c *symbol) {}
-
-/* | label ':' [il_incomplete_instruction] eol_list */
-// SYM_REF2(il_instruction_c, label, il_instruction)
-// void *visit(instruction_list_c *symbol);
-void *constant_folding_c::visit(il_instruction_c *symbol) {
-	if (NULL == symbol->il_instruction) {
-		/* This empty/null il_instruction does not change the value of the current/default IL variable.
-		 * So it inherits the candidate_datatypes from it's previous IL instructions!
-		 */
-		intersect_prev_cvalues(symbol);
-	} else {
-		il_instruction_c fake_prev_il_instruction = *symbol;
-		intersect_prev_cvalues(&fake_prev_il_instruction);
-
-		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-		else                                          prev_il_instruction = &fake_prev_il_instruction;
-		symbol->il_instruction->accept(*this);
-		prev_il_instruction = NULL;
-
-		/* This object has (inherits) the same cvalues as the il_instruction */
-		symbol->const_value = symbol->il_instruction->const_value;
-	}
-
-	return NULL;
-}
-
-
-void *constant_folding_c::visit(il_simple_operation_c *symbol) {
-	/* determine the cvalue of the operand */
-	if (NULL != symbol->il_operand) {
-		symbol->il_operand->accept(*this);
-	}
-	/* determine the cvalue resulting from executing the il_operator... */
-	il_operand = symbol->il_operand;
-	symbol->il_simple_operator->accept(*this);
-	il_operand = NULL;
-	/* This object has (inherits) the same cvalues as the il_instruction */
-	symbol->const_value = symbol->il_simple_operator->const_value;
-	return NULL;
-}
-
-
-/* TODO: handle function invocations... */
-/* | 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 *constant_folding_c::visit(il_function_call_c *symbol) {}
-
-
-/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
-// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
-void *constant_folding_c::visit(il_expression_c *symbol) {
-  symbol_c *prev_il_instruction_backup = prev_il_instruction;
-  
-  /* Stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list if necessary. We can therefore ignore the 'il_operand' entry! */
-  // if (NULL != symbol->il_operand)
-  //   symbol->il_operand->accept(*this);
-
-  if(symbol->simple_instr_list != NULL)
-    symbol->simple_instr_list->accept(*this);
-
-  /* Now do the operation,  */
-  il_operand = symbol->simple_instr_list;
-  prev_il_instruction = prev_il_instruction_backup;
-  symbol->il_expr_operator->accept(*this);
-  il_operand = NULL;
-  
-  /* This object has (inherits) the same cvalues as the il_instruction */
-  symbol->const_value = symbol->il_expr_operator->const_value;
-  
-  /* Since stage2 will insert an artificial (and equivalent) LD <il_operand> to the simple_instr_list when an 'il_operand' exists, we know
-   * that if (symbol->il_operand != NULL), then the first IL instruction in the simple_instr_list will be the equivalent and artificial
-   * 'LD <il_operand>' IL instruction.
-   * Just to be cosistent, we will copy the constant info back into the il_operand, even though this should not be necessary!
-   */
-  if ((NULL != symbol->il_operand) && ((NULL == symbol->simple_instr_list) || (0 == ((list_c *)symbol->simple_instr_list)->n))) ERROR; // stage2 is not behaving as we expect it to!
-  if  (NULL != symbol->il_operand)
-    symbol->il_operand->const_value = ((list_c *)symbol->simple_instr_list)->elements[0]->const_value;
-
-  return NULL;
-}
-
-
-
-void *constant_folding_c::visit(il_jump_operation_c *symbol) {
-  /* recursive call to fill const values... */
-  il_operand = NULL;
-  symbol->il_jump_operator->accept(*this);
-  il_operand = NULL;
-  /* This object has (inherits) the same cvalues as the il_jump_operator */
-  symbol->const_value = symbol->il_jump_operator->const_value;
-  return NULL;
-}
-
-
-
-/* FB calls leave the value in the accumulator unchanged */
-/*   il_call_operator prev_declared_fb_name
- * | il_call_operator prev_declared_fb_name '(' ')'
- * | il_call_operator prev_declared_fb_name '(' eol_list ')'
- * | 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 */
-// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
-void *constant_folding_c::visit(il_fb_call_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-
-
-/* TODO: handle function invocations... */
-/* | 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 *constant_folding_c::visit(il_formal_funct_call_c *symbol) {return NULL;}
-
-
-
-/* Not needed, since we inherit from iterator_visitor_c */
-//  void *constant_folding_c::visit(il_operand_list_c *symbol);
-
-
-
-/* | simple_instr_list il_simple_instruction */
-/* This object is referenced by il_expression_c objects */
-void *constant_folding_c::visit(simple_instr_list_c *symbol) {
-  if (symbol->n <= 0)
-    return NULL;  /* List is empty! Nothing to do. */
-    
-  for(int i = 0; i < symbol->n; i++)
-    symbol->elements[i]->accept(*this);
-
-  /* This object has (inherits) the same cvalues as the il_jump_operator */
-  symbol->const_value = symbol->elements[symbol->n-1]->const_value;
-  return NULL;
-}
-
-
-
-// SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
-void *constant_folding_c::visit(il_simple_instruction_c *symbol) {
-  if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
-  if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-  else                                          prev_il_instruction = symbol->prev_il_instruction[0];
-  symbol->il_simple_instruction->accept(*this);
-  prev_il_instruction = NULL;
-
-  /* This object has (inherits) the same cvalues as the il_jump_operator */
-  symbol->const_value = symbol->il_simple_instruction->const_value;
-  return NULL;
-}
-
-
-/*
-    void *visit(il_param_list_c *symbol);
-    void *visit(il_param_assignment_c *symbol);
-    void *visit(il_param_out_assignment_c *symbol);
-*/
-
-
-/*******************/
-/* B 2.2 Operators */
-/*******************/
-void *constant_folding_c::visit(   LD_operator_c *symbol) {return handle_move(symbol, il_operand);}
-void *constant_folding_c::visit(  LDN_operator_c *symbol) {return handle_not (symbol, il_operand);}
-
-/* NOTE: we are implementing a constant folding algorithm, not a constant propagation algorithm.
- *       For the constant propagation algorithm, the correct implementation of ST(N)_operator_c would be...
- */
-//void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(il_operand, symbol);}
-//void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_not (il_operand, symbol);}
-void *constant_folding_c::visit(   ST_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(  STN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-
-/* NOTE: the standard allows syntax in which the NOT operator is followed by an optional <il_operand>
- *              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! This error will be caught elsewhere!
- */
-void *constant_folding_c::visit(  NOT_operator_c *symbol) {return handle_not(symbol, prev_il_instruction);}
-
-/* NOTE: Since we are only implementing a constant folding algorithm, and not a constant propagation algorithm,
- *       the following IL instructions do not change/set the value of the il_operand!
- */
-void *constant_folding_c::visit(    S_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(    R_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-
-/* FB calls leave the value in the accumulator unchanged */
-void *constant_folding_c::visit(   S1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   R1_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(  CLK_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   CU_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   CD_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   PV_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   IN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(   PT_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-
-void *constant_folding_c::visit(  AND_operator_c *symbol) {return handle_and (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(   OR_operator_c *symbol) {return handle_or  (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(  XOR_operator_c *symbol) {return handle_xor (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit( ANDN_operator_c *symbol) {       handle_and (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
-void *constant_folding_c::visit(  ORN_operator_c *symbol) {       handle_or  (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
-void *constant_folding_c::visit( XORN_operator_c *symbol) {       handle_xor (symbol, prev_il_instruction, il_operand); return handle_not(symbol, symbol);}
-
-void *constant_folding_c::visit(  ADD_operator_c *symbol) {return handle_add (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(  SUB_operator_c *symbol) {return handle_sub (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(  MUL_operator_c *symbol) {return handle_mul (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(  DIV_operator_c *symbol) {return handle_div (symbol, prev_il_instruction, il_operand);}
-void *constant_folding_c::visit(  MOD_operator_c *symbol) {return handle_mod (symbol, prev_il_instruction, il_operand);}
-
-void *constant_folding_c::visit(   GT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, > );}
-void *constant_folding_c::visit(   GE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, >=);}
-void *constant_folding_c::visit(   EQ_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, ==);}
-void *constant_folding_c::visit(   LT_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, < );}
-void *constant_folding_c::visit(   LE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, <=);}
-void *constant_folding_c::visit(   NE_operator_c *symbol) {       handle_cmp (symbol, prev_il_instruction, il_operand, !=);}
-
-void *constant_folding_c::visit(  CAL_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(  RET_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(  JMP_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit( CALC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(CALCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit( RETC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(RETCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit( JMPC_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-void *constant_folding_c::visit(JMPCN_operator_c *symbol) {return handle_move(symbol, prev_il_instruction);}
-
-
-
 
 /***************************************/
 /* B.3 - Language ST (Structured Text) */
@@ -1854,37 +1897,15 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
-void *constant_folding_c::visit(    or_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_or (symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   xor_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_xor(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   and_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_and(symbol, symbol->l_exp, symbol->r_exp);}
-
-void *constant_folding_c::visit(   equ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, ==);}
-void *constant_folding_c::visit(notequ_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, !=);}
-void *constant_folding_c::visit(    lt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, < );}
-void *constant_folding_c::visit(    gt_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, > );}
-void *constant_folding_c::visit(    le_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, <=);}
-void *constant_folding_c::visit(    ge_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this);        handle_cmp (symbol, symbol->l_exp, symbol->r_exp, >=);}
-
-void *constant_folding_c::visit(   add_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_add(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   sub_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_sub(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   mul_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mul(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   div_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_div(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit(   mod_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_mod(symbol, symbol->l_exp, symbol->r_exp);}
-void *constant_folding_c::visit( power_expression_c *symbol) {symbol->l_exp->accept(*this); symbol->r_exp->accept(*this); return handle_pow(symbol, symbol->l_exp, symbol->r_exp);}
-
-void *constant_folding_c::visit(   neg_expression_c *symbol) {symbol->  exp->accept(*this); return handle_neg(symbol, symbol->exp);}
-void *constant_folding_c::visit(   not_expression_c *symbol) {symbol->  exp->accept(*this); return handle_not(symbol, symbol->exp);}
-
+#if DO_CONSTANT_PROPAGATION__
 /* TODO: handle function invocations... */
 // void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {}
 
 
-
-#if DO_CONSTANT_PROPAGATION__
 /*********************************/
 /* B 3.2.1 Assignment Statements */
 /*********************************/
-void *constant_folding_c::visit(assignment_statement_c *symbol) {
+void *constant_propagation_c::visit(assignment_statement_c *symbol) {
 	std::string varName;
 
 	symbol->r_exp->accept(*this);
@@ -1897,7 +1918,7 @@
 /********************************/
 /* B 3.2.3 Selection Statements */
 /********************************/
-void *constant_folding_c::visit(if_statement_c *symbol) {
+void *constant_propagation_c::visit(if_statement_c *symbol) {
 	map_values_t values_incoming;
 	map_values_t values_statement_result;
 	map_values_t values_elsestatement_result;
@@ -1925,7 +1946,7 @@
 /********************************/
 /* B 3.2.4 Iteration Statements */
 /********************************/
-void *constant_folding_c::visit(for_statement_c *symbol) {
+void *constant_propagation_c::visit(for_statement_c *symbol) {
 	map_values_t values_incoming;
 	map_values_t values_statement_result;
 
@@ -1962,7 +1983,7 @@
 	return NULL;
 }
 
-void *constant_folding_c::visit(while_statement_c *symbol) {
+void *constant_propagation_c::visit(while_statement_c *symbol) {
 	map_values_t values_incoming;
 	map_values_t values_statement_result;
 
@@ -1979,7 +2000,7 @@
 	return NULL;
 }
 
-void *constant_folding_c::visit(repeat_statement_c *symbol) {
+void *constant_propagation_c::visit(repeat_statement_c *symbol) {
 	map_values_t values_incoming;
 	map_values_t values_statement_result;
 
@@ -2003,4 +2024,3 @@
 
 
 
-
--- a/stage3/constant_folding.hh	Tue Dec 30 22:58:52 2014 +0000
+++ b/stage3/constant_folding.hh	Tue Dec 30 23:31:36 2014 +0000
@@ -53,10 +53,11 @@
 
 
 class constant_folding_c : public iterator_visitor_c {
-    search_varfb_instance_type_c *search_varfb_instance_type;
+  protected:
     int error_count;
     bool warning_found;
     int current_display_error_level;
+  private:
     /* Pointer to the previous IL instruction, which contains the current cvalue of the data stored in the IL stack, i.e. the default variable, a.k.a. accumulator */
     symbol_c *prev_il_instruction;
     /* the current IL operand being analyzed */
@@ -68,37 +69,8 @@
     constant_folding_c(symbol_c *symbol = NULL);
     virtual ~constant_folding_c(void);
     int get_error_count();
-    typedef symtable_c<const_value_c> map_values_t;
+ 
   private:
-    symbol_c *current_resource;
-    symbol_c *current_configuration;
-    map_values_t values;
-    map_values_t var_global_values;
-    void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
-    void *handle_var_decl     (symbol_c *var_list, bool fixed_init_value);
-    // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
-    // VAR CONSTANT ... END_VAR will always be true
-    // VAR          ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
-    bool fixed_init_value_; 
-    bool function_pou_;
-    bool is_constant(symbol_c *option);
-    bool is_retain  (symbol_c *option);
-
-
-  public:
-	#if 0
-	// not currently needed, so comment it out!...
-	/* utility functions for other stage3 algorithms to access the contant folded values */
-	/* written as static since we do not need to iteratively visit the symbols! */
-	// returns true if both symbols have the same value in all the cvalues
-	static bool is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2);
-	#endif
-
-  private:
-    /***************************/
-    /* B 0 - Programming Model */
-    /***************************/
-    void *visit(library_c *symbol);
     /*********************/
     /* B 1.2 - Constants */
     /*********************/
@@ -124,58 +96,6 @@
     /********* **************/
     void *visit(fixed_point_c *symbol);
 
-    /*********************/
-    /* B 1.4 - Variables */
-    /*********************/
-    #if DO_CONSTANT_PROPAGATION__
-    void *visit(symbolic_variable_c *symbol);
-    #endif // DO_CONSTANT_PROPAGATION__
-    void *visit(symbolic_constant_c *symbol);
-                             
-    /******************************************/
-    /* B 1.4.3 - Declaration & Initialisation */
-    /******************************************/
-    void *visit(        input_declarations_c *symbol);
-    void *visit(       output_declarations_c *symbol);
-    void *visit( input_output_declarations_c *symbol);
-    void *visit(          var_declarations_c *symbol);
-    void *visit(retentive_var_declarations_c *symbol);
-    void *visit( external_var_declarations_c *symbol);
-    void *visit(   global_var_declarations_c *symbol);
-    void *visit(  external_declaration_c     *symbol);
-    void *visit(global_var_decl_c            *symbol);
-    void *visit( var1_init_decl_c            *symbol);
-
-    /**************************************/
-    /* B.1.5 - Program organization units */
-    /**************************************/
-    /***********************/
-    /* B 1.5.1 - Functions */
-    /***********************/
-    void *visit(function_declaration_c *symbol);
-    void *visit(function_var_decls_c   *symbol);
-
-    /*****************************/
-    /* B 1.5.2 - Function Blocks */
-    /*****************************/
-    void *visit(function_block_declaration_c *symbol);
-    void *visit(            temp_var_decls_c *symbol);
-    void *visit(   non_retentive_var_decls_c *symbol);
-
-    /**********************/
-    /* B 1.5.3 - Programs */
-    /**********************/
-    void *visit(       program_declaration_c *symbol);
-
-    /********************************/
-    /* B 1.7 Configuration elements */
-    /********************************/
-    void *visit( configuration_declaration_c *symbol);
-    void *visit(      resource_declaration_c *symbol);
-    void *visit(     program_configuration_c *symbol);
-    void *visit(                   fb_task_c *symbol);
-
-
     /****************************************/
     /* B.2 - Language IL (Instruction List) */
     /****************************************/
@@ -268,6 +188,127 @@
     void *visit(   neg_expression_c *symbol);
     void *visit(   not_expression_c *symbol);
     //void *visit(function_invocation_c *symbol); /* TODO */
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+class constant_propagation_c : public constant_folding_c {
+  public:
+    constant_propagation_c(symbol_c *symbol = NULL);
+    virtual ~constant_propagation_c(void);
+    typedef symtable_c<const_value_c> map_values_t;
+  private:
+    symbol_c *current_resource;
+    symbol_c *current_configuration;
+    map_values_t values;
+    map_values_t var_global_values;
+    void *handle_var_list_decl(symbol_c *var_list, symbol_c *type_decl);
+    void *handle_var_decl     (symbol_c *var_list, bool fixed_init_value);
+    // Flag to indicate whether the variables in the variable declaration list will always have a fixed value when the POU is executed!
+    // VAR CONSTANT ... END_VAR will always be true
+    // VAR          ... END_VAR will always be true for functions (who initialise local variables every time they are called), but false for FBs and PROGRAMS
+    bool fixed_init_value_; 
+    bool function_pou_;
+    bool is_constant(symbol_c *option);
+    bool is_retain  (symbol_c *option);
+    static map_values_t inner_left_join_values(map_values_t m1, map_values_t m2);
+
+
+  private:
+    /***************************/
+    /* B 0 - Programming Model */
+    /***************************/
+    void *visit(library_c *symbol);
+
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    #if DO_CONSTANT_PROPAGATION__
+    void *visit(symbolic_variable_c *symbol);
+    #endif // DO_CONSTANT_PROPAGATION__
+    void *visit(symbolic_constant_c *symbol);
+                             
+    /******************************************/
+    /* B 1.4.3 - Declaration & Initialisation */
+    /******************************************/
+    void *visit(        input_declarations_c *symbol);
+    void *visit(       output_declarations_c *symbol);
+    void *visit( input_output_declarations_c *symbol);
+    void *visit(          var_declarations_c *symbol);
+    void *visit(retentive_var_declarations_c *symbol);
+    void *visit( external_var_declarations_c *symbol);
+    void *visit(   global_var_declarations_c *symbol);
+    void *visit(  external_declaration_c     *symbol);
+    void *visit(global_var_decl_c            *symbol);
+    void *visit( var1_init_decl_c            *symbol);
+
+    /**************************************/
+    /* B.1.5 - Program organization units */
+    /**************************************/
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    void *visit(function_declaration_c *symbol);
+    void *visit(function_var_decls_c   *symbol);
+
+    /*****************************/
+    /* B 1.5.2 - Function Blocks */
+    /*****************************/
+    void *visit(function_block_declaration_c *symbol);
+    void *visit(            temp_var_decls_c *symbol);
+    void *visit(   non_retentive_var_decls_c *symbol);
+
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    void *visit(       program_declaration_c *symbol);
+
+    /********************************/
+    /* B 1.7 Configuration elements */
+    /********************************/
+    void *visit( configuration_declaration_c *symbol);
+    void *visit(      resource_declaration_c *symbol);
+    void *visit(     program_configuration_c *symbol);
+    void *visit(                   fb_task_c *symbol);
+
+
+    /****************************************/
+    /* B.2 - Language IL (Instruction List) */
+    /****************************************/
+    /***********************************/
+    /* B 2.1 Instructions and Operands */
+    /***********************************/
+    //void *visit(il_function_call_c *symbol);  /* TODO */
+    // void *visit(il_fb_call_c *symbol);       /* TODO: move from constant_folding_c */
+    //void *visit(il_formal_funct_call_c *symbol);   /* TODO */
+    //void *visit(il_operand_list_c *symbol);  /* Not needed, since we inherit from iterator_visitor_c */
+
+
+    /*******************/
+    /* B 2.2 Operators */
+    /*******************/
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, variable_name);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    //void *visit(function_invocation_c *symbol); /* TODO */
 
     #if DO_CONSTANT_PROPAGATION__
     /*********************************/
--- a/stage3/stage3.cc	Tue Dec 30 22:58:52 2014 +0000
+++ b/stage3/stage3.cc	Tue Dec 30 23:31:36 2014 +0000
@@ -71,10 +71,10 @@
 /* Constant folding assumes that flow control analysis has been completed!
  * so be sure to call flow_control_analysis() before calling this function!
  */
-static int constant_folding(symbol_c *tree_root){
-    constant_folding_c constant_folding(tree_root);
-    tree_root->accept(constant_folding);
-    return constant_folding.get_error_count();
+static int constant_propagation(symbol_c *tree_root){
+    constant_propagation_c constant_propagation(tree_root);
+    tree_root->accept(constant_propagation);
+    return constant_propagation.get_error_count();
 }
 
 
@@ -140,7 +140,7 @@
 	error_count += enum_declaration_check(tree_root);
 	error_count += declaration_safety(tree_root);
 	error_count += flow_control_analysis(tree_root);
-	error_count += constant_folding(tree_root);
+	error_count += constant_propagation(tree_root);
 	error_count += type_safety(tree_root);
 	error_count += lvalue_check(tree_root);
 	error_count += array_range_check(tree_root);