Continue adding support for semantic verification of JMP and RET.
authorMario de Sousa <msousa@fe.up.pt>
Fri, 02 Mar 2012 12:53:41 +0000
changeset 459 01f6664bf8c5
parent 458 587884880be6
child 460 00f39a4b25fb
Continue adding support for semantic verification of JMP and RET.
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax_utils/Makefile.am
absyntax_utils/Makefile.in
absyntax_utils/absyntax_utils.hh
absyntax_utils/search_constant_type.cc
absyntax_utils/search_constant_type.hh
stage3/datatype_functions.cc
stage3/datatype_functions.hh
stage3/fill_candidate_datatypes.cc
stage3/flow_control_analysis.cc
stage3/flow_control_analysis.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
stage3/print_datatypes_error.cc
stage3/print_datatypes_error.hh
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.def	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax/absyntax.def	Fri Mar 02 12:53:41 2012 +0000
@@ -97,6 +97,12 @@
 SYM_REF0(eno_param_c)
 */
 
+/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */
+/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+SYM_REF0(invalid_type_name_c)
+
+
+
 /********************/
 /* 2.1.6 - Pragmas  */
 /********************/
--- a/absyntax/absyntax.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax/absyntax.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -77,8 +77,13 @@
     int last_column;
     const char *last_file;  /* filename referenced by last line/column */
     long int last_order;    /* relative order in which it is read by lexcial analyser */
-    symbol_c * datatype;    /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */
     std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
+    /* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c 
+     * If set to NULL, it means it has not yet been evaluated.
+     * If it points to an object of type invalid_type_name_c, it means it is invalid.
+     * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...)
+     */
+    symbol_c *datatype;    
 
 
   public:
--- a/absyntax_utils/Makefile.am	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/Makefile.am	Fri Mar 02 12:53:41 2012 +0000
@@ -13,6 +13,7 @@
 	function_param_iterator.cc \
 	get_function_type.cc \
 	get_sizeof_datatype.cc \
+	search_il_label.cc \
 	search_base_type.cc \
 	search_constant_type.cc \
 	search_expression_type.cc \
--- a/absyntax_utils/Makefile.in	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/Makefile.in	Fri Mar 02 12:53:41 2012 +0000
@@ -78,8 +78,8 @@
 	function_call_iterator.$(OBJEXT) \
 	function_call_param_iterator.$(OBJEXT) \
 	function_param_iterator.$(OBJEXT) get_function_type.$(OBJEXT) \
-	get_sizeof_datatype.$(OBJEXT) search_base_type.$(OBJEXT) \
-	search_constant_type.$(OBJEXT) \
+	get_sizeof_datatype.$(OBJEXT) search_il_label.$(OBJEXT) \
+	search_base_type.$(OBJEXT) search_constant_type.$(OBJEXT) \
 	search_expression_type.$(OBJEXT) \
 	search_fb_instance_decl.$(OBJEXT) search_fb_typedecl.$(OBJEXT) \
 	search_varfb_instance_type.$(OBJEXT) \
@@ -213,6 +213,7 @@
 	function_param_iterator.cc \
 	get_function_type.cc \
 	get_sizeof_datatype.cc \
+	search_il_label.cc \
 	search_base_type.cc \
 	search_constant_type.cc \
 	search_expression_type.cc \
@@ -319,6 +320,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_expression_type.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_instance_decl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_fb_typedecl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_il_label.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_var_instance_decl.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search_varfb_instance_type.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spec_init_separator.Po@am__quote@
--- a/absyntax_utils/absyntax_utils.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/absyntax_utils.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -120,7 +120,7 @@
 #include "add_en_eno_param_decl.hh"
 #include "get_sizeof_datatype.hh"
 #include "get_function_type.h"
-
+#include "search_il_label.hh"
 
 /***********************************************************************/
 /***********************************************************************/
--- a/absyntax_utils/search_constant_type.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/search_constant_type.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -133,6 +133,12 @@
   return (void *)value_type;
 }
 
+
+
+
+invalid_type_name_c  search_constant_type_c::invalid_type_name;
+
+
 real_type_name_c     search_constant_type_c::real_type_name;
 sint_type_name_c     search_constant_type_c::sint_type_name;
 lint_type_name_c     search_constant_type_c::lint_type_name;
--- a/absyntax_utils/search_constant_type.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/absyntax_utils/search_constant_type.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -30,6 +30,14 @@
  *
  */
 
+/* NOTE: The use of this visitor class is now deprecated.
+ *       The new version of stage3 data type checking adds an entry to
+ *       every relevant object in the abstract syntax tree defining
+ *       the data type of that object. Please use that instead!
+ */
+
+
+
 /* Determine the data type of a specific constant or variable.
  * A reference to the relevant type definition is returned.
  *
@@ -49,6 +57,10 @@
 class search_constant_type_c: public search_visitor_c {
 
   public:
+  /* object used to identify an entry in the abstract syntax tree with an invalid data type */
+  /* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+  static invalid_type_name_c     invalid_type_name;
+
   /**********************/
   /* B.1.3 - Data types */
   /**********************/
--- a/stage3/datatype_functions.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/datatype_functions.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -228,6 +228,20 @@
 
 
 
+/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */
+void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol) {
+	if (symbol->prev_il_instruction.empty())
+		return;
+	
+	copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/);
+	for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {
+		intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/);
+	}  
+}
+
+
+
+
 /* A helper function... */
 bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return false;}
@@ -544,16 +558,30 @@
 
 
 
-bool is_type_equal(symbol_c *first_type, symbol_c *second_type)
-{
-    if (first_type == NULL || second_type == NULL) {
-        return false;
-    }
-    if (is_ANY_ELEMENTARY_type(first_type)) {
-        if (typeid(*first_type) == typeid(*second_type))
-            return true;
-    } else   /* ANY_DERIVED */
-        return (first_type == second_type);
-
-    return false;
-}
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type) {
+  if ((NULL == first_type) || (NULL == second_type))
+      return false;
+  if (typeid(* first_type) == typeid(invalid_type_name_c))
+      return false;
+  if (typeid(*second_type) == typeid(invalid_type_name_c))
+      return false;
+    
+  if (is_ANY_ELEMENTARY_type(first_type)) {
+      if (typeid(*first_type) == typeid(*second_type))
+          return true;
+  } else   /* ANY_DERIVED */
+      return (first_type == second_type);
+
+  return false;
+}
+
+
+
+bool is_type_valid(symbol_c *type) {
+  if (NULL == type)
+      return false;
+  if (typeid(*type) == typeid(invalid_type_name_c))
+      return false;
+
+  return true;
+}
--- a/stage3/datatype_functions.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/datatype_functions.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -154,6 +154,10 @@
  */
 void intersect_candidate_datatype_list(symbol_c *list1 /*origin, dest.*/, symbol_c *list2 /*with*/);
 
+/* intersect the candidate_datatype lists of all prev_il_intructions, and set the local candidate_datatype list to the result! */
+void intersect_prev_candidate_datatype_lists(il_instruction_c *symbol);
+
+
 
 /* A helper function... */
 bool is_ANY_ELEMENTARY_type         (symbol_c *type_symbol);
@@ -206,8 +210,9 @@
 
 
 bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
-
-// typedef bool (*helper_function_t) (symbol_c *type_symbol);  /* a pointer to a function! */
+bool is_type_valid(symbol_c *type);
+
+
 
 
 #endif /* _HELPER_FUNCTIONS_HH_ */
--- a/stage3/fill_candidate_datatypes.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -565,7 +565,9 @@
 /************************/
 void *fill_candidate_datatypes_c::visit(duration_c *symbol) {
 	/* TODO: check whether the literal follows the rules specified in section '2.2.3.1 Duration' of the standard! */
-	symbol->candidate_datatypes.push_back(symbol->type_name);
+	
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::time_type_name);
+// 	symbol->candidate_datatypes.push_back(symbol->type_name);
 	if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
 	return NULL;
 }
@@ -800,6 +802,7 @@
 // void *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);
@@ -808,16 +811,14 @@
 		/* 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!
 		 */
-		if (!symbol->prev_il_instruction.empty()) {
-			copy_candidate_datatype_list(symbol->prev_il_instruction[0] /*from*/, symbol /*to*/);
-			for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) {
-				intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->prev_il_instruction[i] /*with*/);
-			}
-		}
+		intersect_prev_candidate_datatype_lists(symbol);
 	} else {
-		if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+// 		if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+		il_instruction_c fake_prev_il_instruction = *symbol;
+		intersect_prev_candidate_datatype_lists(&fake_prev_il_instruction);
+
 		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-		else                                          prev_il_instruction = symbol->prev_il_instruction[0];
+		else                                          prev_il_instruction = &fake_prev_il_instruction;
 		symbol->il_instruction->accept(*this);
 		prev_il_instruction = NULL;
 
@@ -855,7 +856,6 @@
 	 *
 	 * However, if no further paramters are given, then il_operand_list will be NULL, and we will
 	 * need to create a new object to hold the pointer to prev_il_instruction.
-	 * This change will also be undone later in print_datatypes_error_c.
 	 */
 	if (NULL == symbol->il_operand_list)  symbol->il_operand_list = new il_operand_list_c;
 	if (NULL == symbol->il_operand_list)  ERROR;
@@ -1022,7 +1022,7 @@
 
 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
 void *fill_candidate_datatypes_c::visit(il_simple_instruction_c *symbol) {
-  if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
+  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);
--- a/stage3/flow_control_analysis.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/flow_control_analysis.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -113,6 +113,8 @@
 static int debug = 0;
 
 flow_control_analysis_c::flow_control_analysis_c(symbol_c *ignore) {
+  prev_il_instruction = NULL;
+  curr_il_instruction = NULL;
 }
 
 flow_control_analysis_c::~flow_control_analysis_c(void) {
@@ -127,11 +129,11 @@
 /* B 1.5.1 Functions */
 /*********************/
 void *flow_control_analysis_c::visit(function_declaration_c *symbol) {
-	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	search_il_label = new search_il_label_c(symbol);
 	if (debug) printf("Doing flow control analysis in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
 	symbol->function_body->accept(*this);
-	delete search_varfb_instance_type;
-	search_varfb_instance_type = NULL;
+	delete search_il_label;
+	search_il_label = NULL;
 	return NULL;
 }
 
@@ -139,11 +141,11 @@
 /* B 1.5.2 Function blocks */
 /***************************/
 void *flow_control_analysis_c::visit(function_block_declaration_c *symbol) {
-	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	search_il_label = new search_il_label_c(symbol);
 	if (debug) printf("Doing flow control analysis in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
 	symbol->fblock_body->accept(*this);
-	delete search_varfb_instance_type;
-	search_varfb_instance_type = NULL;
+	delete search_il_label;
+	search_il_label = NULL;
 	return NULL;
 }
 
@@ -151,11 +153,11 @@
 /* B 1.5.3 Programs */
 /********************/
 void *flow_control_analysis_c::visit(program_declaration_c *symbol) {
-	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	search_il_label = new search_il_label_c(symbol);
 	if (debug) printf("Doing flow control analysis in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
 	symbol->function_block_body->accept(*this);
-	delete search_varfb_instance_type;
-	search_varfb_instance_type = NULL;
+	delete search_il_label;
+	search_il_label = NULL;
 	return NULL;
 }
 
@@ -181,7 +183,9 @@
 	for(int i = 0; i < symbol->n; i++) {
 		prev_il_instruction = NULL;
 		if (i > 0) prev_il_instruction = symbol->elements[i-1];
-		symbol->elements[i]->accept(*this);
+		curr_il_instruction = symbol->elements[i];
+		curr_il_instruction->accept(*this);
+		curr_il_instruction = NULL;
 	}
 	return NULL;
 }
@@ -190,34 +194,28 @@
 // SYM_REF2(il_instruction_c, label, il_instruction)
 // void *visit(instruction_list_c *symbol);
 void *flow_control_analysis_c::visit(il_instruction_c *symbol) {
-	symbol->prev_il_instruction.push_back(prev_il_instruction);
-	/* TODO: handle labels correctly!
-	 *
-	 *      Don't forget to handle multiple consecutive lables too!
-	 *        label2:
-	 *        label3:
-	 *        label4:
-	 *                LD I
-	 */
-	/* NOTE: the following recursive call will mess up the value in the
-	 *       this->prev_il_instruction variable, so be sure not to use it
-	 *       after the return of symbol->il_instruction->accept(*this);
-	 */
-	/* check if it is an il_expression_c, and if so, handle it correctly */
+	if (NULL != prev_il_instruction)
+		symbol->prev_il_instruction.push_back(prev_il_instruction);
+
+	/* check if it is an il_expression_c, or a JMP[C[N]] and if so, handle it correctly */
 	if (NULL != symbol->il_instruction)
 		symbol->il_instruction->accept(*this);
 	return NULL;
 }
 
 
-#if 0
+
+/* | il_simple_operator [il_operand] */
+// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
+// void *flow_control_analysis_c::visit(il_simple_operation_c *symbol)
+
+
+
 /* | 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 *flow_control_analysis_c::visit(il_function_call_c *symbol) {
-	return NULL;
-}
-#endif
+// void *flow_control_analysis_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);
@@ -226,13 +224,28 @@
 		/* nothing to do... */
 		return NULL;
   
+	symbol_c *save_prev_il_instruction = prev_il_instruction;
 	prev_il_instruction = symbol->il_operand;
 	symbol->simple_instr_list->accept(*this);
-	return NULL;
-}
-
-
-#if 0
+	prev_il_instruction = save_prev_il_instruction;
+	return NULL;
+}
+
+
+/*  il_jump_operator label */
+// SYM_REF2(il_jump_operation_c, il_jump_operator, label)
+void *flow_control_analysis_c::visit(il_jump_operation_c *symbol) {
+  /* search for the il_instruction_c containing the label */
+  il_instruction_c *destination = search_il_label->find_label(symbol->label);
+
+  /* TODO: for JMP and RET (unconditional) instructions, make sure the next IL instruction does not point back! */
+  /* add, to that il_instruction's list of prev_il_intsructions, the curr_il_instruction */
+  if (NULL != destination)
+    destination->prev_il_instruction.push_back(curr_il_instruction);
+  return NULL;
+}
+
+
 /*   il_call_operator prev_declared_fb_name
  * | il_call_operator prev_declared_fb_name '(' ')'
  * | il_call_operator prev_declared_fb_name '(' eol_list ')'
@@ -241,18 +254,14 @@
  */
 /* 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 *flow_control_analysis_c::visit(il_fb_call_c *symbol) {
-	return NULL;
-}
+// void *flow_control_analysis_c::visit(il_fb_call_c *symbol)
 
 
 /* | 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 *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol) {
-	return NULL;
-}
-#endif
+// void *flow_control_analysis_c::visit(il_formal_funct_call_c *symbol)
+
 
 
 //  void *visit(il_operand_list_c *symbol);
@@ -268,7 +277,8 @@
 
 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
 void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) {
-	symbol->prev_il_instruction.push_back(prev_il_instruction);
+	if (NULL != prev_il_instruction)
+		symbol->prev_il_instruction.push_back(prev_il_instruction);
 	return NULL;
 }
 
@@ -281,3 +291,54 @@
 
 
 
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+// void *visit(   LD_operator_c *symbol);
+// void *visit(  LDN_operator_c *symbol);
+// void *visit(   ST_operator_c *symbol);
+// void *visit(  STN_operator_c *symbol);
+// void *visit(  NOT_operator_c *symbol);
+// void *visit(    S_operator_c *symbol);
+// void *visit(    R_operator_c *symbol);
+// void *visit(   S1_operator_c *symbol);
+// void *visit(   R1_operator_c *symbol);
+// void *visit(  CLK_operator_c *symbol);
+// void *visit(   CU_operator_c *symbol);
+// void *visit(   CD_operator_c *symbol);
+// void *visit(   PV_operator_c *symbol);
+// void *visit(   IN_operator_c *symbol);
+// void *visit(   PT_operator_c *symbol);
+// void *visit(  AND_operator_c *symbol);
+// void *visit(   OR_operator_c *symbol);
+// void *visit(  XOR_operator_c *symbol);
+// void *visit( ANDN_operator_c *symbol);
+// void *visit(  ORN_operator_c *symbol);
+// void *visit( XORN_operator_c *symbol);
+// void *visit(  ADD_operator_c *symbol);
+// void *visit(  SUB_operator_c *symbol);
+// void *visit(  MUL_operator_c *symbol);
+// void *visit(  DIV_operator_c *symbol);
+// void *visit(  MOD_operator_c *symbol);
+// void *visit(   GT_operator_c *symbol);
+// void *visit(   GE_operator_c *symbol);
+// void *visit(   EQ_operator_c *symbol);
+// void *visit(   LT_operator_c *symbol);
+// void *visit(   LE_operator_c *symbol);
+// void *visit(   NE_operator_c *symbol);
+// void *visit(  CAL_operator_c *symbol);
+// void *visit( CALC_operator_c *symbol);
+// void *visit(CALCN_operator_c *symbol);
+// void *visit(  RET_operator_c *symbol);
+// void *visit( RETC_operator_c *symbol);
+// void *visit(RETCN_operator_c *symbol);
+// void *visit(  JMP_operator_c *symbol);
+// void *visit( JMPC_operator_c *symbol);
+// void *visit(JMPCN_operator_c *symbol);
+
+/* 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);
+
--- a/stage3/flow_control_analysis.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/flow_control_analysis.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -48,8 +48,9 @@
 class flow_control_analysis_c: public iterator_visitor_c {
 
   private:
-    search_varfb_instance_type_c *search_varfb_instance_type;
+    search_il_label_c *search_il_label;
     symbol_c *prev_il_instruction;
+    symbol_c *curr_il_instruction;
 
   public:
     flow_control_analysis_c(symbol_c *ignore);
@@ -89,6 +90,7 @@
 //     void *visit(il_simple_operation_c *symbol);
 //     void *visit(il_function_call_c *symbol);
     void *visit(il_expression_c *symbol);
+    void *visit(il_jump_operation_c *symbol);
 //     void *visit(il_fb_call_c *symbol);
 //     void *visit(il_formal_funct_call_c *symbol);
 //     void *visit(il_operand_list_c *symbol);
@@ -101,49 +103,48 @@
     /*******************/
     /* B 2.2 Operators */
     /*******************/
-    /*
-    void *visit(LD_operator_c *symbol);
-    void *visit(LDN_operator_c *symbol);
-    void *visit(ST_operator_c *symbol);
-    void *visit(STN_operator_c *symbol);
-    void *visit(NOT_operator_c *symbol);
-    void *visit(S_operator_c *symbol);
-    void *visit(R_operator_c *symbol);
-    void *visit(S1_operator_c *symbol);
-    void *visit(R1_operator_c *symbol);
-    void *visit(CLK_operator_c *symbol);
-    void *visit(CU_operator_c *symbol);
-    void *visit(CD_operator_c *symbol);
-    void *visit(PV_operator_c *symbol);
-    void *visit(IN_operator_c *symbol);
-    void *visit(PT_operator_c *symbol);
-    void *visit(AND_operator_c *symbol);
-    void *visit(OR_operator_c *symbol);
-    void *visit(XOR_operator_c *symbol);
-    void *visit(ANDN_operator_c *symbol);
-    void *visit(ORN_operator_c *symbol);
-    void *visit(XORN_operator_c *symbol);
-    void *visit(ADD_operator_c *symbol);
-    void *visit(SUB_operator_c *symbol);
-    void *visit(MUL_operator_c *symbol);
-    void *visit(DIV_operator_c *symbol);
-    void *visit(MOD_operator_c *symbol);
-    void *visit(GT_operator_c *symbol);
-    void *visit(GE_operator_c *symbol);
-    void *visit(EQ_operator_c *symbol);
-    void *visit(LT_operator_c *symbol);
-    void *visit(LE_operator_c *symbol);
-    void *visit(NE_operator_c *symbol);
-    void *visit(CAL_operator_c *symbol);
-    void *visit(CALC_operator_c *symbol);
-    void *visit(CALCN_operator_c *symbol);
-    void *visit(RET_operator_c *symbol);
-    void *visit(RETC_operator_c *symbol);
-    void *visit(RETCN_operator_c *symbol);
-    void *visit(JMP_operator_c *symbol);
-    void *visit(JMPC_operator_c *symbol);
-    void *visit(JMPCN_operator_c *symbol);
-    */
+//     void *visit(   LD_operator_c *symbol);
+//     void *visit(  LDN_operator_c *symbol);
+//     void *visit(   ST_operator_c *symbol);
+//     void *visit(  STN_operator_c *symbol);
+//     void *visit(  NOT_operator_c *symbol);
+//     void *visit(    S_operator_c *symbol);
+//     void *visit(    R_operator_c *symbol);
+//     void *visit(   S1_operator_c *symbol);
+//     void *visit(   R1_operator_c *symbol);
+//     void *visit(  CLK_operator_c *symbol);
+//     void *visit(   CU_operator_c *symbol);
+//     void *visit(   CD_operator_c *symbol);
+//     void *visit(   PV_operator_c *symbol);
+//     void *visit(   IN_operator_c *symbol);
+//     void *visit(   PT_operator_c *symbol);
+//     void *visit(  AND_operator_c *symbol);
+//     void *visit(   OR_operator_c *symbol);
+//     void *visit(  XOR_operator_c *symbol);
+//     void *visit( ANDN_operator_c *symbol);
+//     void *visit(  ORN_operator_c *symbol);
+//     void *visit( XORN_operator_c *symbol);
+//     void *visit(  ADD_operator_c *symbol);
+//     void *visit(  SUB_operator_c *symbol);
+//     void *visit(  MUL_operator_c *symbol);
+//     void *visit(  DIV_operator_c *symbol);
+//     void *visit(  MOD_operator_c *symbol);
+//     void *visit(   GT_operator_c *symbol);
+//     void *visit(   GE_operator_c *symbol);
+//     void *visit(   EQ_operator_c *symbol);
+//     void *visit(   LT_operator_c *symbol);
+//     void *visit(   LE_operator_c *symbol);
+//     void *visit(   NE_operator_c *symbol);
+//     void *visit(  CAL_operator_c *symbol);
+//     void *visit( CALC_operator_c *symbol);
+//     void *visit(CALCN_operator_c *symbol);
+//     void *visit(  RET_operator_c *symbol);
+//     void *visit( RETC_operator_c *symbol);
+//     void *visit(RETCN_operator_c *symbol);
+//     void *visit(  JMP_operator_c *symbol);
+//     void *visit( JMPC_operator_c *symbol);
+//     void *visit(JMPCN_operator_c *symbol);
+
     /* 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 */
--- a/stage3/narrow_candidate_datatypes.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -57,15 +57,38 @@
 
 /* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */
 static void set_datatype(symbol_c *datatype, symbol_c *symbol) {
-	symbol->datatype = NULL;   
-	if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) >= 0)
-		symbol->datatype = datatype;  
+  
+	/* If we are trying to set to the undefined type, and the symbol's datatype has already been set to something else, 
+	 * we abort the compoiler as I don't think this should ever occur. 
+	 * However, I (Mario) am not too sure of this, so if the compiler ever aborts here, please analyse the situation
+	 * carefully as it might be perfectly legal and something I have missed!
+	 */
+	if ((NULL == datatype) && (NULL != symbol->datatype)) ERROR;
+	
+	if ((NULL == datatype) && (NULL == symbol->datatype)) return;
+	
+	if (search_in_candidate_datatype_list(datatype, symbol->candidate_datatypes) < 0)
+		symbol->datatype = &(search_constant_type_c::invalid_type_name);   
+	else {
+		if (NULL == symbol->datatype)   
+			/* not yet set to anything, so we set it to the requested data type */
+			symbol->datatype = datatype; 
+		else {
+			/* had already been set previously to some data type. Let's check if they are the same! */
+			if (!is_type_equal(symbol->datatype, datatype))
+				symbol->datatype = &(search_constant_type_c::invalid_type_name);
+// 			else 
+				/* we leave it unchanged, as it is the same as the requested data type! */
+		}
+	}
 }
 
 
 
 /* Only set the symbol's desired datatype to 'datatype' if that datatype is in the candidate_datatype list */
-static void set_datatype_in_prev_il_instruction(symbol_c *datatype, il_instruction_c *symbol) {
+// static void set_datatype_in_prev_il_instructions(symbol_c *datatype, std::vector <symbol_c *> prev_il_instructions) {
+static void set_datatype_in_prev_il_instructions(symbol_c *datatype, il_instruction_c *symbol) {
+	if (NULL == symbol) ERROR;
 	for (unsigned int i = 0; i < symbol->prev_il_instruction.size(); i++)
 		set_datatype(datatype, symbol->prev_il_instruction[i]);
 }
@@ -276,7 +299,7 @@
 	}
 	symbol_c *fb_decl = il_operand->datatype;
 
-	if (NULL == prev_il_instruction) {
+	if (0 == fake_prev_il_instruction->prev_il_instruction.size()) {
 		/* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction
 		 * (or list of instructions) that will set the IL current/default value.
 		 * We cannot proceed verifying type compatibility of something that does not exist.
@@ -286,9 +309,9 @@
 
 	if (NULL == fb_decl) {
 		/* the il_operand is a not FB instance */
-		/* so we simply pass on the required datatype to the prev_il_instruction */
-		/* The invalid FB invocation will be caught by the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
-		prev_il_instruction->datatype = il_instruction->datatype;
+		/* so we simply pass on the required datatype to the prev_il_instructions */
+		/* The invalid FB invocation will be caught in the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */
+		set_datatype_in_prev_il_instructions(il_instruction->datatype, fake_prev_il_instruction);
 		return NULL;
 	}
 	
@@ -302,8 +325,15 @@
 	 * would be changed to the IL instruction coming before the current prev_il_instruction! => things would get all messed up!)
 	 * The easiest way to work around this is to simply use a new object, and copy the relevant details to that object!
 	 */
-	symbol_c param_value = *prev_il_instruction;
-        
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  fake_prev_il_instruction->candidate_datatypes.size() = %d\n",fake_prev_il_instruction->candidate_datatypes.size());
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  fake_prev_il_instruction->candidate_datatypes[0] = %p\n",fake_prev_il_instruction->candidate_datatypes[0]);
+	symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list ! */
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.candidate_datatypes.size() = %d\n",param_value.candidate_datatypes.size());
+printf("XX::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.candidate_datatypes[0] = %p\n",param_value.candidate_datatypes[0]);
+printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  search_constant_type::time_type_name = %p\n", &search_constant_type_c::time_type_name);
+printf("00::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  search_constant_type::invalid_type_name = %p\n", &search_constant_type_c::invalid_type_name);
+
+printf("11::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.datatype = %p\n", param_value.datatype);
 	identifier_c variable_name(param_name);
 	// SYM_REF1(il_assign_operator_c, variable_name)
 	il_assign_operator_c il_assign_operator(&variable_name);  
@@ -314,6 +344,7 @@
 	// SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration)
 	CAL_operator_c CAL_operator;
 	il_fb_call_c il_fb_call(&CAL_operator, il_operand, NULL, &il_param_list);
+printf("22::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.datatype = %p\n", param_value.datatype);
 	        
 	/* A FB call does not return any datatype, but the IL instructions that come after this
 	 * FB call may require a specific datatype in the il current/default variable, 
@@ -326,6 +357,7 @@
 // 	copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/);
 	il_fb_call.called_fb_declaration = called_fb_declaration;
 	il_fb_call.accept(*this);
+printf("33::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.datatype = %p\n", param_value.datatype);
 
 	/* set the required datatype of the previous IL instruction! */
 	/* NOTE:
@@ -338,7 +370,7 @@
 	 * This means that we have two consumers/users for the same value. 
 	 * We must therefore check whether the datatype required by the IL instructions following this FB call 
 	 * is the same as that required for the first parameter. If not, then we have a semantic error,
-	 * and we set it to NULL.
+	 * and we set it to invalid_type_name.
 	 *
 	 * However, we only do that if:
 	 *  - The IL instruction that comes after this IL FB call actually asked this FB call for a specific 
@@ -348,9 +380,11 @@
 	 *     FB call must be left unchanged!
 	 */
 	if ((NULL == il_instruction->datatype) || (is_type_equal(param_value.datatype, il_instruction->datatype))) {
-		prev_il_instruction->datatype = param_value.datatype;
+printf("44::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.datatype = %p\n", param_value.datatype);
+		set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction);
 	} else {
-		prev_il_instruction->datatype = NULL;
+printf("55::narrow_candidate_datatypes_c::narrow_implicit_il_fb_call():  param_value.datatype = %p\n", param_value.datatype);
+		set_datatype_in_prev_il_instructions(&search_constant_type_c::invalid_type_name, fake_prev_il_instruction);
 	}
 	return NULL;
 }
@@ -510,14 +544,21 @@
 void *narrow_candidate_datatypes_c::visit(il_instruction_c *symbol) {
 	if (NULL == symbol->il_instruction) {
 		/* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */
-		set_datatype_in_prev_il_instruction(symbol->datatype, symbol);
+		set_datatype_in_prev_il_instructions(symbol->datatype, symbol);
 	} else {
+		il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+		/* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
+		 * list of the prev_il_instructions.
+		 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+		 * and shove that data into this single variable.
+		 */
+		tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+		intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction);
 		/* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
-		if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
-		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-		else                                          prev_il_instruction = symbol->prev_il_instruction[0];
+		fake_prev_il_instruction = &tmp_prev_il_instruction;
+		symbol->il_instruction->datatype = symbol->datatype;
 		symbol->il_instruction->accept(*this);
-		prev_il_instruction = NULL;
+		fake_prev_il_instruction = NULL;
 	}
 	return NULL;
 }
@@ -552,12 +593,10 @@
 	 * need to create a new object to hold the pointer to prev_il_instruction.
 	 * This change will also be undone later in print_datatypes_error_c.
 	 */
-	symbol_c param_value;
+	symbol_c param_value = *fake_prev_il_instruction; /* copy the candidate_datatypes list */
 	if (NULL == symbol->il_operand_list)  symbol->il_operand_list = new il_operand_list_c;
 	if (NULL == symbol->il_operand_list)  ERROR;
 
-	if (NULL != prev_il_instruction)
-		param_value = *prev_il_instruction;
 	((list_c *)symbol->il_operand_list)->insert_element(&param_value, 0);
 
 	generic_function_call_t fcall_param = {
@@ -571,8 +610,7 @@
 	};
 
 	narrow_function_invocation(symbol, fcall_param);
-	if (NULL != prev_il_instruction)
-		prev_il_instruction->datatype = param_value.datatype;
+	set_datatype_in_prev_il_instructions(param_value.datatype, fake_prev_il_instruction);
 
 	/* Undo the changes to the abstract syntax tree we made above... */
 	((list_c *)symbol->il_operand_list)->remove_element(0);
@@ -596,10 +634,10 @@
 
   /* now give the parenthesised IL list a chance to narrow the datatypes */
   /* The datatype that is must return was set by the call symbol->il_expr_operator->accept(*this) */
-  symbol_c *save_prev_il_instruction = prev_il_instruction; /*this is not really necessary, but lets play it safe */
+  il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; /*this is not really necessary, but lets play it safe */
   symbol->simple_instr_list->accept(*this);
-  prev_il_instruction = save_prev_il_instruction;
-return NULL;
+  fake_prev_il_instruction = save_fake_prev_il_instruction;
+  return NULL;
 }
 
 
@@ -664,12 +702,23 @@
 
 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
 void *narrow_candidate_datatypes_c::visit(il_simple_instruction_c *symbol)	{
-  if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
-  if (symbol->prev_il_instruction.size() == 0)   prev_il_instruction = NULL;
-  else                                           prev_il_instruction = symbol->prev_il_instruction[0];
+  if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
+    
+  il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+  /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
+   * list of the prev_il_instructions.
+   * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+   * and shove that data into this single variable.
+   */
+  if (symbol->prev_il_instruction.size() > 0)
+    tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes;
+  tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+  
+   /* copy the candidate_datatypes list */
+  fake_prev_il_instruction = &tmp_prev_il_instruction;
   symbol->il_simple_instruction->datatype = symbol->datatype;
   symbol->il_simple_instruction->accept(*this);
-  prev_il_instruction = NULL;
+  fake_prev_il_instruction = NULL;
   return NULL;
 }
 
@@ -702,7 +751,8 @@
 	 *         (or simple_instr_list_c), which iterates backwards.
 	 */
 	/* set the desired datatype of the previous il instruction */
-	prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
+	  
 	/* set the datatype for the operand */
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
@@ -739,8 +789,7 @@
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	/* set the desired datatype of the previous il instruction */
-	prev_il_instruction->datatype = symbol->datatype;
-	if (debug) printf("narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) returning. previous_il_instruction->datatype = %p\n", prev_il_instruction->datatype);
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -752,7 +801,7 @@
 	il_operand->datatype = symbol->datatype;
 	il_operand->accept(*this);
 	/* set the desired datatype of the previous il instruction */
-	prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -805,8 +854,7 @@
 void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
 	/* set the desired datatype of the previous il instruction */
 	/* This FB call does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction */
-	if (NULL != prev_il_instruction)
-		prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -827,7 +875,7 @@
 	if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR;
 
 	/* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */
-	if (NULL != prev_il_instruction)    prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -846,8 +894,7 @@
 	 * However, since that class has not yet been completely finished, we do not yet check this assertion!
 	 */
 // 	if (NULL != symbol->datatype) ERROR;
-	if (NULL != prev_il_instruction)
-		prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
@@ -861,8 +908,7 @@
 	 * However, since that class has not yet been completely finished, we do not yet check this assertion!
 	 */
 // 	if (NULL != symbol->datatype) ERROR;
-	if (NULL != prev_il_instruction)
-		prev_il_instruction->datatype = symbol->datatype;
+	set_datatype_in_prev_il_instructions(symbol->datatype, fake_prev_il_instruction);
 	return NULL;
 }
 
--- a/stage3/narrow_candidate_datatypes.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/narrow_candidate_datatypes.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -42,7 +42,9 @@
     search_varfb_instance_type_c *search_varfb_instance_type;
     search_base_type_c search_base_type;
     symbol_c *il_operand;
-    symbol_c *prev_il_instruction;
+    il_instruction_c *fake_prev_il_instruction;
+    std::vector <symbol_c *> *prev_il_instructions;
+    std::vector <symbol_c *> *prev_il_instructions_intersected_datatypes;
 
     bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]);
 
--- a/stage3/print_datatypes_error.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/print_datatypes_error.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -92,6 +92,27 @@
 	return error_found;
 }
 
+
+
+
+
+/* Verify if the datatypes of all prev_il_instructions are valid and equal!  */
+static bool are_all_datatypes_of_prev_il_instructions_datatypes_equal(il_instruction_c *symbol) {
+	if (NULL == symbol) ERROR;
+	bool res;
+	
+	if (symbol->prev_il_instruction.size() > 0)
+		res = is_type_valid(symbol->prev_il_instruction[0]->datatype);
+
+	for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++)
+		res &= is_type_equal(symbol->prev_il_instruction[i-1]->datatype, symbol->prev_il_instruction[i]->datatype);
+	
+	return res;
+}
+
+
+
+
 /* a helper function... */
 symbol_c *print_datatypes_error_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
@@ -239,7 +260,7 @@
 		return;
 	}
 
-	if (NULL == prev_il_instruction) {
+	if (fake_prev_il_instruction->prev_il_instruction.empty()) {
 		STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name);	
 		return;
 	}
@@ -257,7 +278,7 @@
 		STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name);	
 		return;
 	}
-	if (NULL == prev_il_instruction->datatype) {
+	if (!are_all_datatypes_of_prev_il_instructions_datatypes_equal(fake_prev_il_instruction)) {
 		STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name);
 		return;
 	}
@@ -618,12 +639,29 @@
 // SYM_REF2(il_instruction_c, label, il_instruction)
 void *print_datatypes_error_c::visit(il_instruction_c *symbol) {
 	if (NULL != symbol->il_instruction) {
-		if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
-		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-		else                                          prev_il_instruction = symbol->prev_il_instruction[0];
-
+// #if 0
+		il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+		/* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
+		 * list of the prev_il_instructions.
+		 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+		 * and shove that data into this single variable.
+		 */
+		tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+		intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction);
+		if (are_all_datatypes_of_prev_il_instructions_datatypes_equal(symbol))
+			if (symbol->prev_il_instruction.size() > 0)
+				tmp_prev_il_instruction.datatype = (symbol->prev_il_instruction[0])->datatype;
+		/* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
+		fake_prev_il_instruction = &tmp_prev_il_instruction;
 		symbol->il_instruction->accept(*this);
-		prev_il_instruction = NULL;
+		fake_prev_il_instruction = NULL;
+// #endif
+// 		if (symbol->prev_il_instruction.size() > 1) ERROR; /* only valid for now! */
+// 		if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
+// 		else                                          prev_il_instruction = symbol->prev_il_instruction[0];
+
+// 		symbol->il_instruction->accept(*this);
+// 		prev_il_instruction = NULL;
 	}
 
 	return NULL;
@@ -657,7 +695,7 @@
 	if (NULL == symbol->il_operand_list)  symbol->il_operand_list = new il_operand_list_c;
 	if (NULL == symbol->il_operand_list)  ERROR;
 
-	((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0);
+	((list_c *)symbol->il_operand_list)->insert_element(fake_prev_il_instruction, 0);
 
 	generic_function_call_t fcall_param = {
 		/* fcall_param.function_name               = */ symbol->function_name,
@@ -671,16 +709,10 @@
 
 /* TODO: check what error message (if any) the compiler will give out if this function invocation
  * is not preceded by a LD operator (or another equivalent operator or list of operators).
- * I.e. if it is preceded by an operator or operator list that will set the 'current value'.
- * I.e. if the prev_il_operand == NULL;
  */
 	handle_function_invocation(symbol, fcall_param);
 	
-	/* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction)
-	 * In order to be able to handle this without coding special cases, we simply prepend that symbol
-	 * to the il_operand_list. This was done in fill_candidate_datatypes_c.
-	 * We now undo those changes!
-	 */  
+	/* We now undo those changes to the abstract syntax tree made above! */
 	((list_c *)symbol->il_operand_list)->remove_element(0);
 	if (((list_c *)symbol->il_operand_list)->n == 0) {
 		/* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */
@@ -696,9 +728,9 @@
 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
 void *print_datatypes_error_c::visit(il_expression_c *symbol) {
   /* first give the parenthesised IL list a chance to print errors */
-  symbol_c *save_prev_il_instruction = prev_il_instruction;
+  il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction;
   symbol->simple_instr_list->accept(*this);
-  prev_il_instruction = save_prev_il_instruction;
+  fake_prev_il_instruction = save_fake_prev_il_instruction;
 
   /* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */
   il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */
@@ -759,13 +791,31 @@
 
 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;)
 void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol)	{
-  if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */
-  if (symbol->prev_il_instruction.size() == 0)  prev_il_instruction = NULL;
-  else                                          prev_il_instruction = symbol->prev_il_instruction[0];
-
+  if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */
+    
+  il_instruction_c tmp_prev_il_instruction(NULL, NULL);
+  /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
+   * list of the prev_il_instructions.
+   * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+   * and shove that data into this single variable.
+   */
+  if (symbol->prev_il_instruction.size() > 0)
+    tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes;
+  tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
+  
+   /* copy the candidate_datatypes list */
+  fake_prev_il_instruction = &tmp_prev_il_instruction;
   symbol->il_simple_instruction->accept(*this);
-  prev_il_instruction = NULL;
+  fake_prev_il_instruction = NULL;
   return NULL;
+  
+  
+//   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;
+//   return NULL;
 }
 
 
--- a/stage3/print_datatypes_error.hh	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage3/print_datatypes_error.hh	Fri Mar 02 12:53:41 2012 +0000
@@ -77,8 +77,12 @@
     bool warning_found;
 
     /* the current data type of the data stored in the IL stack, i.e. the default variable */
-    symbol_c *prev_il_instruction;
-    /* the current IL operand being analyzed - its symbol and its data type */
+    il_instruction_c *fake_prev_il_instruction;
+    /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
+     * list of the prev_il_instructions.
+     * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
+     * and shove that data into this single variable.
+     */
     symbol_c *il_operand_type;
     symbol_c *il_operand;
 
--- a/stage4/generate_iec/generate_iec.cc	Thu Mar 01 10:28:27 2012 +0000
+++ b/stage4/generate_iec/generate_iec.cc	Fri Mar 02 12:53:41 2012 +0000
@@ -58,6 +58,10 @@
 
 
 
+#define ERROR error_exit(__FILE__,__LINE__)
+/* function defined in main.cc */
+extern void error_exit(const char *file_name, int line_no);
+
 
 
 
@@ -153,6 +157,13 @@
 #endif
 
 
+/* A class used to identify an entry (literal, variable, etc...) in the abstract syntax tree with an invalid data type */
+/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
+// SYM_REF0(invalid_type_name_c)
+void *visit(invalid_type_name_c *symbol) {
+  ERROR;
+  return NULL;
+}
 
 
 /******************/