stage3/print_datatypes_error.cc
changeset 492 6ae697b34f2d
parent 491 6f4083fe169e
child 502 a6211f73690b
equal deleted inserted replaced
491:6f4083fe169e 492:6ae697b34f2d
   214 		fcall_data.nonformal_operand_list->accept(*this);
   214 		fcall_data.nonformal_operand_list->accept(*this);
   215 		if (f_decl)
   215 		if (f_decl)
   216 			for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) {
   216 			for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) {
   217 		  		/* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */
   217 		  		/* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */
   218 
   218 
   219 				if (NULL == param_value->datatype) {
   219 				/* This handle_function_invocation() will be called to handle IL function calls, where the first parameter comes from the previous IL instruction.
       
   220 				 * In this case, the previous IL instruction will be artifically (and temporarily) added to the begining ot the parameter list
       
   221 				 * so we (in this function) can handle this situation like all the other function calls.
       
   222 				 * However, 
       
   223 				 *     a) if NO previous IL function exists, then we get a fake previous IL function, with no location data (i.e. not found anywhere in the source code.
       
   224 				 *     b) the function call may actually have several prev IL instructions (if several JMP instructions jump directly to the il function call).
       
   225 				 * In order to handle these situations gracefully, we first check whether the first parameter is really an IL istruction!
       
   226 				 */
       
   227 				il_instruction_c *il_instruction_symbol = dynamic_cast<il_instruction_c *>(param_value);
       
   228 				if ((NULL != il_instruction_symbol) && (i == 1)) {
       
   229 					/* We are in a situation where an IL function call is passed the first parameter, which is actually the previous IL instruction */
       
   230 					/* However, this is really a fake previous il instruction (see visit(il_instruction_c *) )
       
   231 					 * We will iterate through all the real previous IL instructions, and analyse each of them one by one */
       
   232 					if (il_instruction_symbol->prev_il_instruction.size() == 0) {
       
   233 						function_invocation_error = true;
       
   234 						STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((identifier_c *)fcall_data.function_name)->value);
       
   235 					}
       
   236 #if 0
       
   237 					/* NOTE: We currently comment out this code...
       
   238 					 * This does not currently work, since the narrow operation is currently done on the intersection 
       
   239 					 * of all the previous IL instructions, so we currently either accept them all, or none at all.
       
   240 					 * In order to be able to produce these user freindly error messages, we will need to update the 
       
   241 					 * narrow algorithm. We leave this untill somebody aks for it...
       
   242 					 * So, for now, we simply comment out this code.
       
   243 					 */
       
   244 					for (unsigned int p = 0; p < il_instruction_symbol->prev_il_instruction.size(); p++) {
       
   245 						symbol_c *value = il_instruction_symbol->prev_il_instruction[p];  
       
   246 						if (!is_type_valid(value->datatype)) {
       
   247 							function_invocation_error = true;
       
   248 							STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((identifier_c *)fcall_data.function_name)->value);
       
   249 							STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value);
       
   250 						}
       
   251 					}
       
   252 #else
       
   253 					if (!is_type_valid(il_instruction_symbol->datatype)) {
       
   254 						function_invocation_error = true;
       
   255 						STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value);
       
   256 					}
       
   257 #endif
       
   258 					if (function_invocation_error)
       
   259 						/* when handling a IL function call, and an error is found in the first parameter, then we bug out and do not print out any more error messages. */
       
   260 						return;
       
   261 				}
       
   262 				else if (!is_type_valid(param_value->datatype)) {
   220 					function_invocation_error = true;
   263 					function_invocation_error = true;
   221 					STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value);
   264 					STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((identifier_c *)fcall_data.function_name)->value);
   222 				}
   265 				}
   223 			}
   266 			}
   224 	}
   267 	}
   628 /* | label ':' [il_incomplete_instruction] eol_list */
   671 /* | label ':' [il_incomplete_instruction] eol_list */
   629 // SYM_REF2(il_instruction_c, label, il_instruction)
   672 // SYM_REF2(il_instruction_c, label, il_instruction)
   630 void *print_datatypes_error_c::visit(il_instruction_c *symbol) {
   673 void *print_datatypes_error_c::visit(il_instruction_c *symbol) {
   631 	if (NULL != symbol->il_instruction) {
   674 	if (NULL != symbol->il_instruction) {
   632 		il_instruction_c tmp_prev_il_instruction(NULL, NULL);
   675 		il_instruction_c tmp_prev_il_instruction(NULL, NULL);
       
   676 #if 0
       
   677 		/* NOTE: The following is currently no longer needed. Since the following code is actually cool, 
       
   678 		 * we don't delete it, but simply comment it out. It might just come in handy later on...
       
   679 		 */
   633 		/* When handling a il function call, this fake_prev_il_instruction may be used as a standard function call parameter, so it is important that 
   680 		/* When handling a il function call, this fake_prev_il_instruction may be used as a standard function call parameter, so it is important that 
   634 		 * it contain some valid location info so error messages make sense.
   681 		 * it contain some valid location info so error messages make sense.
   635 		 */
   682 		 */
   636 		if (symbol->prev_il_instruction.size() > 0) {
   683 		if (symbol->prev_il_instruction.size() > 0) {
   637 			/* since we don't want to copy all that data one variable at a time, we copy it all at once */
   684 			/* since we don't want to copy all that data one variable at a time, we copy it all at once */
   648 			tmp_prev_il_instruction.datatype = NULL;
   695 			tmp_prev_il_instruction.datatype = NULL;
   649 			/* We don't need to worry about the candidate_datatype list (which we don't want to copy just yet), since that will 
   696 			/* We don't need to worry about the candidate_datatype list (which we don't want to copy just yet), since that will 
   650 			 * be reset to the correct value when we call intersect_prev_candidate_datatype_lists() later on...
   697 			 * be reset to the correct value when we call intersect_prev_candidate_datatype_lists() later on...
   651 			 */
   698 			 */
   652 		}
   699 		}
   653 		/* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
   700 #endif
       
   701 		/* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the 
   654 		 * list of the prev_il_instructions.
   702 		 * list of the prev_il_instructions.
   655 		 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
   703 		 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction),
   656 		 * and shove that data into this single variable.
   704 		 * and shove that data into this single variable.
   657 		 */
   705 		 */
   658 		tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;
   706 		tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction;