stage3/narrow_candidate_datatypes.cc
changeset 450 eb1b28acec2e
parent 448 1bd18fc06911
child 451 a1b87eb155e4
equal deleted inserted replaced
449:3c6225521059 450:eb1b28acec2e
   121 		 *       the call 
   121 		 *       the call 
   122 		 *       call_param_value->accept(*this);
   122 		 *       call_param_value->accept(*this);
   123 		 *       may actually be calling an object of the il_instruction_c class.
   123 		 *       may actually be calling an object of the il_instruction_c class.
   124 		 *       If that is the case, that same il_instruction_c object will be called again inside the for() loop
   124 		 *       If that is the case, that same il_instruction_c object will be called again inside the for() loop
   125 		 *       of void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol);
   125 		 *       of void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol);
   126 		 *       This is actually safe, as the narrow algorithm for all IL instructions is idem-potent.
   126 		 *       Since this is not safe (the prev_il_instruction variable will be overwritten with a wrong value!), 
   127 		 *       (It is easier to just let it be called twice than to hack the code to guarantee that it is 
   127 		 *       we only do the recursive call if this parameter does not point to a il_instruction_c object.
   128 		 *       only called once - this would also make this hacked code ugly an un-elegant, so we leave
   128 		 *       Actually, it is easier to check whether it is not the same as the prev_il_instruction.
   129 		 *       it as it is for now...)
       
   130 		 */
   129 		 */
   131 		set_datatype(desired_datatype, call_param_value);
   130 		set_datatype(desired_datatype, call_param_value);
   132 		call_param_value->accept(*this);
   131 		if (call_param_value != prev_il_instruction)
       
   132 			call_param_value->accept(*this);
   133 
   133 
   134 		if (NULL != param_name) 
   134 		if (NULL != param_name) 
   135 			if (extensible_parameter_highest_index < fp_iterator.extensible_param_index())
   135 			if (extensible_parameter_highest_index < fp_iterator.extensible_param_index())
   136 				extensible_parameter_highest_index = fp_iterator.extensible_param_index();
   136 				extensible_parameter_highest_index = fp_iterator.extensible_param_index();
   137 	}
   137 	}
   177 		 */
   177 		 */
   178 		symbol_c *desired_datatype = base_type(fp_iterator.param_type());
   178 		symbol_c *desired_datatype = base_type(fp_iterator.param_type());
   179 		if ((NULL != param_name) && (NULL == desired_datatype)) ERROR;
   179 		if ((NULL != param_name) && (NULL == desired_datatype)) ERROR;
   180 		if ((NULL == param_name) && (NULL != desired_datatype)) ERROR;
   180 		if ((NULL == param_name) && (NULL != desired_datatype)) ERROR;
   181 
   181 
       
   182 		/* set the desired data type for this parameter */
   182 		set_datatype(desired_datatype, call_param_value);
   183 		set_datatype(desired_datatype, call_param_value);
   183 		call_param_value->accept(*this);
   184 		/* And recursively call that parameter/expression, so it can propagate that info */
       
   185 		/* However, when handling an implicit IL FB call, the first parameter is fake, and points to the prev_il_instruction.
       
   186 		 * In this case, we do not propagate this info down, as that prev_il_instruction will be called later
       
   187 		 * (remember, we iterate backwards through the IL instructions) by the for() loop in the instruction_list_c.
       
   188 		 */
       
   189 		if (call_param_value != prev_il_instruction)
       
   190 			call_param_value->accept(*this);
   184 
   191 
   185 		if (NULL != param_name) 
   192 		if (NULL != param_name) 
   186 			if (extensible_parameter_highest_index < fp_iterator.extensible_param_index())
   193 			if (extensible_parameter_highest_index < fp_iterator.extensible_param_index())
   187 				extensible_parameter_highest_index = fp_iterator.extensible_param_index();
   194 				extensible_parameter_highest_index = fp_iterator.extensible_param_index();
   188 	}
   195 	}
   439 /***********************************/
   446 /***********************************/
   440 
   447 
   441 /*| instruction_list il_instruction */
   448 /*| instruction_list il_instruction */
   442 // SYM_LIST(instruction_list_c)
   449 // SYM_LIST(instruction_list_c)
   443 void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol) {
   450 void *narrow_candidate_datatypes_c::visit(instruction_list_c *symbol) {
   444 	/* We need to go through the instructions backwards, so we can not use the base class' visitor */
   451 	/* In order to execute the narrow algoritm correctly, we need to go through the instructions backwards,
       
   452 	 * so we can not use the base class' visitor 
       
   453 	 */
   445 	for(int i = symbol->n-1; i >= 0; i--) {
   454 	for(int i = symbol->n-1; i >= 0; i--) {
   446 		symbol->elements[i]->accept(*this);
   455 		symbol->elements[i]->accept(*this);
   447 	}
   456 	}
   448 	return NULL;
   457 	return NULL;
   449 }
   458 }
   455 	if (NULL == symbol->il_instruction) {
   464 	if (NULL == symbol->il_instruction) {
   456 		/* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */
   465 		/* this empty/null il_instruction cannot generate the desired datatype. We pass on the request to the previous il instruction. */
   457 		if (NULL != symbol->prev_il_instruction)
   466 		if (NULL != symbol->prev_il_instruction)
   458 			symbol->prev_il_instruction->datatype = symbol->datatype;
   467 			symbol->prev_il_instruction->datatype = symbol->datatype;
   459 	} else {
   468 	} else {
   460 		prev_il_instruction = symbol->prev_il_instruction;
       
   461 		/* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
   469 		/* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */
   462 		symbol->il_instruction->datatype = symbol->datatype;
   470 		symbol->il_instruction->datatype = symbol->datatype;
       
   471 		prev_il_instruction = symbol->prev_il_instruction;
   463 		symbol->il_instruction->accept(*this);
   472 		symbol->il_instruction->accept(*this);
   464 	}
   473 		prev_il_instruction = NULL;
   465 	return NULL;
   474 	}
   466 }
   475 	return NULL;
   467 
   476 }
   468 
       
   469 
       
   470 
       
   471 /*************************************************************************************************/
       
   472 /* Important NOTE:                                                                               */
       
   473 /*                                                                                               */
       
   474 /*   The visit() methods for all the IL instructions must be idem-potent, as they may            */
       
   475 /*   potentially be called twice to narrow the same object. In other words, they may be called   */
       
   476 /*   to narrow an object that has already been previously narrowed.                              */
       
   477 /*   This occurs when that IL instruction imediately precedes an IL non-formal function          */
       
   478 /*   invocation:                                                                                 */
       
   479 /*      LD 45.5                                                                                  */
       
   480 /*      SIN                                                                                      */
       
   481 /*                                                                                               */
       
   482 /*   In the above case, 'LD 45.5' will be narrowed once when the code that handles the           */
       
   483 /*   SIN function call                                                                           */
       
   484 /*                                                                                               */
       
   485 /*   narrow_nonformal_call(...), which is called by narrow_function_invocation(...), which is    */
       
   486 /*   in turn called by visit(il_function_call_c *)                                               */
       
   487 /*                                                                                               */
       
   488 /*   calls the call_param_value->accept(*this), where call_param_value will be a pointer         */
       
   489 /*   to the preceding IL instruction (in the above case, 'LD 45.5').                             */
       
   490 /*                                                                                               */
       
   491 /*   That same IL instruction will be again narrowed when called by the for() loop in            */
       
   492 /*   the visit(instruction_list_c *) visitor method.                                             */
       
   493 /*************************************************************************************************/
       
   494  
       
   495 
   477 
   496 
   478 
   497 
   479 
   498 
   480 
   499 // void *visit(instruction_list_c *symbol);
   481 // void *visit(instruction_list_c *symbol);
   527 	 *
   509 	 *
   528 	 * Since this class is executed after fill_candidate_datatypes_c, and before print_datatypes_error_c,
   510 	 * Since this class is executed after fill_candidate_datatypes_c, and before print_datatypes_error_c,
   529 	 * the following code is actually correct!
   511 	 * the following code is actually correct!
   530 	 */
   512 	 */
   531 	narrow_function_invocation(symbol, fcall_param);
   513 	narrow_function_invocation(symbol, fcall_param);
   532 	/* set the desired datatype of the previous il instruction */
   514 	/* The desired datatype of the previous il instruction was already set by narrow_function_invocation() */
   533 	prev_il_instruction->datatype = symbol->datatype;
       
   534 	return NULL;
   515 	return NULL;
   535 }
   516 }
   536 
   517 
   537 /* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
   518 /* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
   538  *     and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
   519  *     and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
   572 	 * In this case, the prev_il_instruction->datatype will be set by the arrow_[non]formal_call(),
   553 	 * In this case, the prev_il_instruction->datatype will be set by the arrow_[non]formal_call(),
   573 	 * using the prama_value pointer to this same object.
   554 	 * using the prama_value pointer to this same object.
   574 	 * If we were to have the following line of code after calling arrow_[non]formal_call(),
   555 	 * If we were to have the following line of code after calling arrow_[non]formal_call(),
   575 	 * we would then be overwriting the datatype with the wrong value!
   556 	 * we would then be overwriting the datatype with the wrong value!
   576 	 */
   557 	 */
   577 	prev_il_instruction->datatype = symbol->datatype;
   558 	if (NULL != prev_il_instruction)
       
   559 		prev_il_instruction->datatype = symbol->datatype;
   578 
   560 
   579 	/* Note: We do not use the symbol->called_fb_declaration value (set in fill_candidate_datatypes_c)
   561 	/* Note: We do not use the symbol->called_fb_declaration value (set in fill_candidate_datatypes_c)
   580 	 *       because we try to identify any other datatype errors in the expressions used in the 
   562 	 *       because we try to identify any other datatype errors in the expressions used in the 
   581 	 *       parameters to the FB call. e.g.
   563 	 *       parameters to the FB call. e.g.
   582 	 *          fb_var( 
   564 	 *          fb_var( 
   595 	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
   577 	/* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */
   596 	if (NULL == fb_decl) ERROR;
   578 	if (NULL == fb_decl) ERROR;
   597 	if (NULL != symbol->il_operand_list)  narrow_nonformal_call(symbol, fb_decl);
   579 	if (NULL != symbol->il_operand_list)  narrow_nonformal_call(symbol, fb_decl);
   598 	if (NULL != symbol->  il_param_list)     narrow_formal_call(symbol, fb_decl);
   580 	if (NULL != symbol->  il_param_list)     narrow_formal_call(symbol, fb_decl);
   599 
   581 
       
   582 	/* NOTE:
       
   583 	 * When handling these implicit IL calls, the parameter_value being passed to the FB parameter
       
   584 	 * (in the previous example, the 'CU' parameter) is actually the prev_il_instruction.
       
   585 	 * In this case, the prev_il_instruction->datatype will be set by the narrow_[non]formal_call(),
       
   586 	 * using the param_value pointer to this same object.
       
   587 	 * 
       
   588 	 * We must check that the datatype required by the IL instructions following this FB call 
       
   589 	 * is the same as that required for the first parameter. If not, then we have a semantic error,
       
   590 	 * and we set it to NULL.
       
   591 	 *
       
   592 	 * However, we only do that if:
       
   593 	 *  - There really exists an il_prev_instruction 
       
   594 	 *     (if it does not exist, it will be a semantic error. But that will be caught by the print_datatypes_error_c)
       
   595 	 *  - The IL instruction that comes after this IL FB call actually asked this FB call for a specific 
       
   596 	 *     datatype in the current/default vairable, once this IL FB call returns.
       
   597 	 *     However, sometimes, (for e.g., this FB call is the last in the IL list) the subsequent FB to not aks this
       
   598 	 *     FB call for any datatype. In that case, then the datatype required to pass to the first parameter of the
       
   599 	 *     FB call must be left unchanged!
       
   600 	 */
       
   601 	if ((NULL != prev_il_instruction) && (NULL != symbol->datatype))
       
   602 		if (!is_type_equal(prev_il_instruction->datatype, symbol->datatype)) {
       
   603 			prev_il_instruction->datatype = NULL;
       
   604 		}
   600 	return NULL;
   605 	return NULL;
   601 }
   606 }
   602 
   607 
   603 
   608 
   604 /* | function_name '(' eol_list [il_param_list] ')' */
   609 /* | function_name '(' eol_list [il_param_list] ')' */
   614 		/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
   619 		/* fcall_param.called_function_declaration = */ symbol->called_function_declaration,
   615 		/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
   620 		/* fcall_param.extensible_param_count      = */ symbol->extensible_param_count
   616 	};
   621 	};
   617   
   622   
   618 	narrow_function_invocation(symbol, fcall_param);
   623 	narrow_function_invocation(symbol, fcall_param);
   619 	/* set the desired datatype of the previous il instruction */
   624 	/* The desired datatype of the previous il instruction was already set by narrow_function_invocation() */
   620 	prev_il_instruction->datatype = symbol->datatype;
       
   621 	return NULL;
   625 	return NULL;
   622 }
   626 }
   623 
   627 
   624 
   628 
   625 /*
   629 /*