stage3/narrow_candidate_datatypes.cc
changeset 459 01f6664bf8c5
parent 457 67d8b07bac22
child 461 fcbc0927fc96
--- 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;
 }