90 |
90 |
91 int print_datatypes_error_c::get_error_found() { |
91 int print_datatypes_error_c::get_error_found() { |
92 return error_found; |
92 return error_found; |
93 } |
93 } |
94 |
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 /* Verify if the datatypes of all prev_il_instructions are valid and equal! */ |
|
100 static bool are_all_datatypes_of_prev_il_instructions_datatypes_equal(il_instruction_c *symbol) { |
|
101 if (NULL == symbol) ERROR; |
|
102 bool res; |
|
103 |
|
104 if (symbol->prev_il_instruction.size() > 0) |
|
105 res = is_type_valid(symbol->prev_il_instruction[0]->datatype); |
|
106 |
|
107 for (unsigned int i = 1; i < symbol->prev_il_instruction.size(); i++) |
|
108 res &= is_type_equal(symbol->prev_il_instruction[i-1]->datatype, symbol->prev_il_instruction[i]->datatype); |
|
109 |
|
110 return res; |
|
111 } |
|
112 |
|
113 |
|
114 |
|
115 |
95 /* a helper function... */ |
116 /* a helper function... */ |
96 symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) { |
117 symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) { |
97 /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used |
118 /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used |
98 * in the code. |
119 * in the code. |
99 */ |
120 */ |
237 if (NULL == called_fb_declaration) { |
258 if (NULL == called_fb_declaration) { |
238 STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance."); |
259 STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance."); |
239 return; |
260 return; |
240 } |
261 } |
241 |
262 |
242 if (NULL == prev_il_instruction) { |
263 if (fake_prev_il_instruction->prev_il_instruction.empty()) { |
243 STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); |
264 STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); |
244 return; |
265 return; |
245 } |
266 } |
246 |
267 |
247 /* Find the corresponding parameter in function declaration */ |
268 /* Find the corresponding parameter in function declaration */ |
255 * which will not work for an implicit FB call! |
276 * which will not work for an implicit FB call! |
256 */ |
277 */ |
257 STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); |
278 STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); |
258 return; |
279 return; |
259 } |
280 } |
260 if (NULL == prev_il_instruction->datatype) { |
281 if (!are_all_datatypes_of_prev_il_instructions_datatypes_equal(fake_prev_il_instruction)) { |
261 STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name); |
282 STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name); |
262 return; |
283 return; |
263 } |
284 } |
264 |
285 |
265 |
286 |
616 |
637 |
617 /* | label ':' [il_incomplete_instruction] eol_list */ |
638 /* | label ':' [il_incomplete_instruction] eol_list */ |
618 // SYM_REF2(il_instruction_c, label, il_instruction) |
639 // SYM_REF2(il_instruction_c, label, il_instruction) |
619 void *print_datatypes_error_c::visit(il_instruction_c *symbol) { |
640 void *print_datatypes_error_c::visit(il_instruction_c *symbol) { |
620 if (NULL != symbol->il_instruction) { |
641 if (NULL != symbol->il_instruction) { |
621 if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ |
642 // #if 0 |
622 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
643 il_instruction_c tmp_prev_il_instruction(NULL, NULL); |
623 else prev_il_instruction = symbol->prev_il_instruction[0]; |
644 /* the narrow algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the |
624 |
645 * list of the prev_il_instructions. |
|
646 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), |
|
647 * and shove that data into this single variable. |
|
648 */ |
|
649 tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; |
|
650 intersect_prev_candidate_datatype_lists(&tmp_prev_il_instruction); |
|
651 if (are_all_datatypes_of_prev_il_instructions_datatypes_equal(symbol)) |
|
652 if (symbol->prev_il_instruction.size() > 0) |
|
653 tmp_prev_il_instruction.datatype = (symbol->prev_il_instruction[0])->datatype; |
|
654 /* Tell the il_instruction the datatype that it must generate - this was chosen by the next il_instruction (remember: we are iterating backwards!) */ |
|
655 fake_prev_il_instruction = &tmp_prev_il_instruction; |
625 symbol->il_instruction->accept(*this); |
656 symbol->il_instruction->accept(*this); |
626 prev_il_instruction = NULL; |
657 fake_prev_il_instruction = NULL; |
|
658 // #endif |
|
659 // if (symbol->prev_il_instruction.size() > 1) ERROR; /* only valid for now! */ |
|
660 // if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
661 // else prev_il_instruction = symbol->prev_il_instruction[0]; |
|
662 |
|
663 // symbol->il_instruction->accept(*this); |
|
664 // prev_il_instruction = NULL; |
627 } |
665 } |
628 |
666 |
629 return NULL; |
667 return NULL; |
630 } |
668 } |
631 |
669 |
655 * This change will also be undone later in print_datatypes_error_c. |
693 * This change will also be undone later in print_datatypes_error_c. |
656 */ |
694 */ |
657 if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; |
695 if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; |
658 if (NULL == symbol->il_operand_list) ERROR; |
696 if (NULL == symbol->il_operand_list) ERROR; |
659 |
697 |
660 ((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0); |
698 ((list_c *)symbol->il_operand_list)->insert_element(fake_prev_il_instruction, 0); |
661 |
699 |
662 generic_function_call_t fcall_param = { |
700 generic_function_call_t fcall_param = { |
663 /* fcall_param.function_name = */ symbol->function_name, |
701 /* fcall_param.function_name = */ symbol->function_name, |
664 /* fcall_param.nonformal_operand_list = */ symbol->il_operand_list, |
702 /* fcall_param.nonformal_operand_list = */ symbol->il_operand_list, |
665 /* fcall_param.formal_operand_list = */ NULL, |
703 /* fcall_param.formal_operand_list = */ NULL, |
669 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
707 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
670 }; |
708 }; |
671 |
709 |
672 /* TODO: check what error message (if any) the compiler will give out if this function invocation |
710 /* TODO: check what error message (if any) the compiler will give out if this function invocation |
673 * is not preceded by a LD operator (or another equivalent operator or list of operators). |
711 * is not preceded by a LD operator (or another equivalent operator or list of operators). |
674 * I.e. if it is preceded by an operator or operator list that will set the 'current value'. |
|
675 * I.e. if the prev_il_operand == NULL; |
|
676 */ |
712 */ |
677 handle_function_invocation(symbol, fcall_param); |
713 handle_function_invocation(symbol, fcall_param); |
678 |
714 |
679 /* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction) |
715 /* We now undo those changes to the abstract syntax tree made above! */ |
680 * In order to be able to handle this without coding special cases, we simply prepend that symbol |
|
681 * to the il_operand_list. This was done in fill_candidate_datatypes_c. |
|
682 * We now undo those changes! |
|
683 */ |
|
684 ((list_c *)symbol->il_operand_list)->remove_element(0); |
716 ((list_c *)symbol->il_operand_list)->remove_element(0); |
685 if (((list_c *)symbol->il_operand_list)->n == 0) { |
717 if (((list_c *)symbol->il_operand_list)->n == 0) { |
686 /* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */ |
718 /* if the list becomes empty, then that means that it did not exist before we made these changes, so we delete it! */ |
687 delete symbol->il_operand_list; |
719 delete symbol->il_operand_list; |
688 symbol->il_operand_list = NULL; |
720 symbol->il_operand_list = NULL; |
694 |
726 |
695 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
727 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
696 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
728 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
697 void *print_datatypes_error_c::visit(il_expression_c *symbol) { |
729 void *print_datatypes_error_c::visit(il_expression_c *symbol) { |
698 /* first give the parenthesised IL list a chance to print errors */ |
730 /* first give the parenthesised IL list a chance to print errors */ |
699 symbol_c *save_prev_il_instruction = prev_il_instruction; |
731 il_instruction_c *save_fake_prev_il_instruction = fake_prev_il_instruction; |
700 symbol->simple_instr_list->accept(*this); |
732 symbol->simple_instr_list->accept(*this); |
701 prev_il_instruction = save_prev_il_instruction; |
733 fake_prev_il_instruction = save_fake_prev_il_instruction; |
702 |
734 |
703 /* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */ |
735 /* Now handle the operation (il_expr_operator) that will use the result coming from the parenthesised IL list (i.e. simple_instr_list) */ |
704 il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */ |
736 il_operand = symbol->simple_instr_list; /* This is not a bug! The parenthesised expression will be used as the operator! */ |
705 symbol->il_expr_operator->accept(*this); |
737 symbol->il_expr_operator->accept(*this); |
706 |
738 |
757 // void *visit(il_operand_list_c *symbol); |
789 // void *visit(il_operand_list_c *symbol); |
758 // void *visit(simple_instr_list_c *symbol); |
790 // void *visit(simple_instr_list_c *symbol); |
759 |
791 |
760 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
792 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
761 void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) { |
793 void *print_datatypes_error_c::visit(il_simple_instruction_c *symbol) { |
762 if (symbol->prev_il_instruction.size() > 1) ERROR; /* This assertion is only valid for now. Remove it once flow_control_analysis_c is complete */ |
794 if (symbol->prev_il_instruction.size() > 1) ERROR; /* There should be no labeled insructions inside an IL expression! */ |
763 if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
795 |
764 else prev_il_instruction = symbol->prev_il_instruction[0]; |
796 il_instruction_c tmp_prev_il_instruction(NULL, NULL); |
765 |
797 /* the print error algorithm will need access to the intersected candidate_datatype lists of all prev_il_instructions, as well as the |
|
798 * list of the prev_il_instructions. |
|
799 * Instead of creating two 'global' (within the class) variables, we create a single il_instruction_c variable (fake_prev_il_instruction), |
|
800 * and shove that data into this single variable. |
|
801 */ |
|
802 if (symbol->prev_il_instruction.size() > 0) |
|
803 tmp_prev_il_instruction.candidate_datatypes = symbol->prev_il_instruction[0]->candidate_datatypes; |
|
804 tmp_prev_il_instruction.prev_il_instruction = symbol->prev_il_instruction; |
|
805 |
|
806 /* copy the candidate_datatypes list */ |
|
807 fake_prev_il_instruction = &tmp_prev_il_instruction; |
766 symbol->il_simple_instruction->accept(*this); |
808 symbol->il_simple_instruction->accept(*this); |
767 prev_il_instruction = NULL; |
809 fake_prev_il_instruction = NULL; |
768 return NULL; |
810 return NULL; |
|
811 |
|
812 |
|
813 // if (symbol->prev_il_instruction.size() == 0) prev_il_instruction = NULL; |
|
814 // else prev_il_instruction = symbol->prev_il_instruction[0]; |
|
815 |
|
816 // symbol->il_simple_instruction->accept(*this); |
|
817 // prev_il_instruction = NULL; |
|
818 // return NULL; |
769 } |
819 } |
770 |
820 |
771 |
821 |
772 // void *visit(il_param_list_c *symbol); |
822 // void *visit(il_param_list_c *symbol); |
773 // void *visit(il_param_assignment_c *symbol); |
823 // void *visit(il_param_assignment_c *symbol); |