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 /* |