89 |
89 |
90 /* Get the parameter type */ |
90 /* Get the parameter type */ |
91 param_type = base_type(fp_iterator.param_type()); |
91 param_type = base_type(fp_iterator.param_type()); |
92 |
92 |
93 /* check whether one of the candidate_data_types of the value being passed is the same as the param_type */ |
93 /* check whether one of the candidate_data_types of the value being passed is the same as the param_type */ |
|
94 /* TODO |
|
95 * call int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes); |
|
96 * instead of using for loop! |
|
97 */ |
94 for(i = 0; i < call_param_value->candidate_datatypes.size(); i++) { |
98 for(i = 0; i < call_param_value->candidate_datatypes.size(); i++) { |
95 /* If found (correct data type being passed), then stop the search */ |
99 /* If found (correct data type being passed), then stop the search */ |
96 if(is_type_equal(param_type, call_param_value->candidate_datatypes[i])) break; |
100 if(is_type_equal(param_type, call_param_value->candidate_datatypes[i])) break; |
97 } |
101 } |
98 /* if we reached the end of the loop, and no compatible type found, then return false */ |
102 /* if we reached the end of the loop, and no compatible type found, then return false */ |
136 param_name = fp_iterator.search(call_param_name); |
140 param_name = fp_iterator.search(call_param_name); |
137 if(param_name == NULL) return false; |
141 if(param_name == NULL) return false; |
138 /* Get the parameter type */ |
142 /* Get the parameter type */ |
139 param_type = base_type(fp_iterator.param_type()); |
143 param_type = base_type(fp_iterator.param_type()); |
140 /* check whether one of the candidate_data_types of the value being passed is the same as the param_type */ |
144 /* check whether one of the candidate_data_types of the value being passed is the same as the param_type */ |
|
145 /* TODO |
|
146 * call int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes); |
|
147 * instead of using for loop! |
|
148 */ |
141 for (i = 0; i < call_param_types.size(); i++) { |
149 for (i = 0; i < call_param_types.size(); i++) { |
142 /* If found (correct data type being passed), then stop the search */ |
150 /* If found (correct data type being passed), then stop the search */ |
143 if(is_type_equal(param_type, call_param_types[i])) break; |
151 if(is_type_equal(param_type, call_param_types[i])) break; |
144 } |
152 } |
145 /* if we reached the end of the loop, and no compatible type found, then return false */ |
153 /* if we reached the end of the loop, and no compatible type found, then return false */ |
147 |
155 |
148 } |
156 } |
149 /* call is compatible! */ |
157 /* call is compatible! */ |
150 return true; |
158 return true; |
151 } |
159 } |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 /* Handle a generic function call! |
|
165 * Assumes that the parameter_list containing the values being passed in this function invocation |
|
166 * has already had all the candidate_datatype lists filled in! |
|
167 * |
|
168 * All parameters being passed to the called function MUST be in the parameter list to which f_call points to! |
|
169 * This means that, for non formal function calls in IL, de current (default value) must be artificially added to the |
|
170 * beginning of the parameter list BEFORE calling handle_function_call(). |
|
171 */ |
|
172 /* |
|
173 typedef struct { |
|
174 symbol_c *function_name, |
|
175 symbol_c *nonformal_operand_list, |
|
176 symbol_c * formal_operand_list, |
|
177 |
|
178 std::vector <symbol_c *> &candidate_functions, |
|
179 symbol_c &*called_function_declaration, |
|
180 int &extensible_param_count |
|
181 } generic_function_call_t; |
|
182 */ |
|
183 /* |
|
184 void narrow_candidate_datatypes_c::narrow_function_invocation(symbol_c *fcall, generic_function_call_t fcall_data) { |
|
185 void *fill_candidate_datatypes_c::handle_function_call(symbol_c *f_call, symbol_c *function_name, invocation_type_t invocation_type, |
|
186 std::vector <symbol_c *> *candidate_datatypes, |
|
187 std::vector <symbol_c *> *candidate_functions) { |
|
188 */ |
|
189 void fill_candidate_datatypes_c::handle_function_call(symbol_c *fcall, generic_function_call_t fcall_data) { |
|
190 function_declaration_c *f_decl; |
|
191 list_c *parameter_list; |
|
192 list_c *parameter_candidate_datatypes; |
|
193 symbol_c *returned_parameter_type; |
|
194 |
|
195 if (debug) std::cout << "function()\n"; |
|
196 |
|
197 function_symtable_t::iterator lower = function_symtable.lower_bound(fcall_data.function_name); |
|
198 function_symtable_t::iterator upper = function_symtable.upper_bound(fcall_data.function_name); |
|
199 /* If the name of the function being called is not found in the function symbol table, then this is an invalid call */ |
|
200 /* Since the lexical parser already checks for this, then if this occurs then we have an internal compiler error. */ |
|
201 if (lower == function_symtable.end()) ERROR; |
|
202 |
|
203 /* Look for all compatible function declarations, and add their return datatypes |
|
204 * to the candidate_datatype list of this function invocation. |
|
205 * |
|
206 * If only one function exists, we add its return datatype to the candidate_datatype list, |
|
207 * even if the parameters passed to it are invalid. |
|
208 * This guarantees that the remainder of the expression in which the function call is inserted |
|
209 * is treated as if the function call returns correctly, and therefore does not generate |
|
210 * spurious error messages. |
|
211 * Even if the parameters to the function call are invalid, doing this is still safe, as the |
|
212 * expressions inside the function call will themselves have erros and will guarantee that |
|
213 * compilation is aborted in stage3 (in print_datatypes_error_c). |
|
214 */ |
|
215 if (function_symtable.multiplicity(fcall_data.function_name) == 1) { |
|
216 f_decl = function_symtable.get_value(lower); |
|
217 returned_parameter_type = base_type(f_decl->type_name); |
|
218 fcall_data.candidate_functions.push_back(f_decl); |
|
219 fcall-> candidate_datatypes.push_back(returned_parameter_type); |
|
220 } |
|
221 for(; lower != upper; lower++) { |
|
222 bool compatible = false; |
|
223 |
|
224 f_decl = function_symtable.get_value(lower); |
|
225 /* Check if function declaration in symbol_table is compatible with parameters */ |
|
226 if (NULL != fcall_data.nonformal_operand_list) compatible=match_nonformal_call(fcall, f_decl); |
|
227 if (NULL != fcall_data. formal_operand_list) compatible= match_formal_call(fcall, f_decl); |
|
228 if (compatible) { |
|
229 /* Add the data type returned by the called functions. |
|
230 * However, only do this if this data type is not already present in the candidate_datatypes list_c |
|
231 */ |
|
232 /* TODO |
|
233 * call int search_in_datatype_list(symbol_c *datatype, std::vector <symbol_c *> candidate_datatypes); |
|
234 * instead of using for loop! |
|
235 */ |
|
236 unsigned int k; |
|
237 returned_parameter_type = base_type(f_decl->type_name); |
|
238 for(k = 0; k < fcall->candidate_datatypes.size(); k++) { |
|
239 if (is_type_equal(returned_parameter_type, fcall->candidate_datatypes[k])) |
|
240 break; |
|
241 } |
|
242 if (k >= fcall->candidate_datatypes.size()) { |
|
243 fcall-> candidate_datatypes.push_back(returned_parameter_type); |
|
244 fcall_data.candidate_functions.push_back(f_decl); |
|
245 } |
|
246 } |
|
247 } |
|
248 if (debug) std::cout << "end_function() [" << fcall->candidate_datatypes.size() << "] result.\n"; |
|
249 return; |
|
250 } |
|
251 |
152 |
252 |
153 |
253 |
154 |
254 |
155 |
255 |
156 /* a helper function... */ |
256 /* a helper function... */ |
665 symbol->il_simple_operator->accept(*this); |
765 symbol->il_simple_operator->accept(*this); |
666 il_operand = NULL; |
766 il_operand = NULL; |
667 return NULL; |
767 return NULL; |
668 } |
768 } |
669 |
769 |
|
770 |
|
771 /* | function_name [il_operand_list] */ |
|
772 /* NOTE: The parameters 'called_function_declaration' and 'extensible_param_count' are used to pass data between the stage 3 and stage 4. */ |
|
773 // SYM_REF2(il_function_call_c, function_name, il_operand_list, symbol_c *called_function_declaration; int extensible_param_count;) |
670 void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) { |
774 void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) { |
671 } |
775 /* The first parameter of a non formal function call in IL will be the 'current value' (i.e. the prev_il_instruction) |
672 |
776 * In order to be able to handle this without coding special cases, we will simply prepend that symbol |
673 /* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used |
777 * to the il_operand_list, and remove it later (in the print_datatypes_error_c). |
674 * and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree. |
778 * |
675 * |
779 * However, if no further paramters are given, then il_operand_list will be NULL, and we will |
676 * Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c |
780 * need to create a new object to hold the pointer to prev_il_instruction. |
677 * in the 3 new classes fill/narrow/print candidate datatype |
781 * This change will also be undone later in print_datatypes_error_c. |
678 */ |
782 */ |
|
783 if (NULL == symbol->il_operand_list) symbol->il_operand_list = new il_operand_list_c; |
|
784 if (NULL == symbol->il_operand_list) ERROR; |
|
785 |
|
786 symbol->il_operand_list->accept(*this); |
|
787 |
|
788 if (NULL == prev_il_instruction) return NULL; |
|
789 ((list_c *)symbol->il_operand_list)->insert_element(prev_il_instruction, 0); |
|
790 |
|
791 generic_function_call_t fcall_param = { |
|
792 /* fcall_param.function_name = */ symbol->function_name, |
|
793 /* fcall_param.nonformal_operand_list = */ symbol->il_operand_list, |
|
794 /* fcall_param.formal_operand_list = */ NULL, |
|
795 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
|
796 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
|
797 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
|
798 }; |
|
799 handle_function_call(symbol, fcall_param); |
|
800 |
|
801 if (debug) std::cout << "il_function_call_c [" << symbol->candidate_datatypes.size() << "] result.\n"; |
|
802 return NULL; |
|
803 } |
|
804 |
|
805 |
679 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
806 /* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */ |
680 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
807 // SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list); |
681 void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) { |
808 void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) { |
682 if (NULL != symbol->il_operand) |
809 if (NULL != symbol->il_operand) |
683 symbol->il_operand->accept(*this); |
810 symbol->il_operand->accept(*this); |
715 } |
842 } |
716 |
843 |
717 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) { |
844 void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) { |
718 } |
845 } |
719 |
846 |
|
847 /* | function_name '(' eol_list [il_param_list] ')' */ |
|
848 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
|
849 // SYM_REF2(il_formal_funct_call_c, function_name, il_param_list, symbol_c *called_function_declaration; int extensible_param_count;) |
720 void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) { |
850 void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) { |
721 |
851 symbol->il_param_list->accept(*this); |
|
852 |
|
853 generic_function_call_t fcall_param = { |
|
854 /* fcall_param.function_name = */ symbol->function_name, |
|
855 /* fcall_param.nonformal_operand_list = */ NULL, |
|
856 /* fcall_param.formal_operand_list = */ symbol->il_param_list, |
|
857 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
|
858 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
|
859 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
|
860 }; |
|
861 handle_function_call(symbol, fcall_param); |
|
862 |
|
863 if (debug) std::cout << "il_formal_funct_call_c [" << symbol->candidate_datatypes.size() << "] result.\n"; |
|
864 return NULL; |
722 } |
865 } |
723 |
866 |
724 /* |
867 /* |
725 void *visit(il_operand_list_c *symbol); |
868 void *visit(il_operand_list_c *symbol); |
726 void *visit(simple_instr_list_c *symbol); |
869 void *visit(simple_instr_list_c *symbol); |
1709 return NULL; |
1852 return NULL; |
1710 } |
1853 } |
1711 |
1854 |
1712 |
1855 |
1713 void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) { |
1856 void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) { |
1714 function_declaration_c *f_decl; |
1857 if (NULL != symbol->formal_param_list) symbol-> formal_param_list->accept(*this); |
1715 list_c *parameter_list; |
1858 else if (NULL != symbol->nonformal_param_list) symbol->nonformal_param_list->accept(*this); |
1716 list_c *parameter_candidate_datatypes; |
|
1717 symbol_c *returned_parameter_type; |
|
1718 |
|
1719 if (debug) std::cout << "function()\n"; |
|
1720 |
|
1721 function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name); |
|
1722 function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name); |
|
1723 /* If the name of the function being called is not found in the function symbol table, then this is an invalid call */ |
|
1724 /* Since the lexical parser already checks for this, then if this occurs then we have an internal compiler error. */ |
|
1725 if (lower == function_symtable.end()) ERROR; |
|
1726 |
|
1727 if (NULL != symbol->formal_param_list) |
|
1728 parameter_list = (list_c *)symbol->formal_param_list; |
|
1729 else if (NULL != symbol->nonformal_param_list) |
|
1730 parameter_list = (list_c *)symbol->nonformal_param_list; |
|
1731 else ERROR; |
1859 else ERROR; |
1732 |
1860 |
1733 /* Fill in the candidate_datatypes lists of all the expressions used in the function call parameters */ |
1861 generic_function_call_t fcall_param = { |
1734 parameter_list->accept(*this); |
1862 /* fcall_param.function_name = */ symbol->function_name, |
1735 |
1863 /* fcall_param.nonformal_operand_list = */ symbol->nonformal_param_list, |
1736 /* Look for all compatible function declarations, and add their return datatypes |
1864 /* fcall_param.formal_operand_list = */ symbol->formal_param_list, |
1737 * to the candidate_datatype list of this function invocation. |
1865 /* fcall_param.candidate_functions = */ symbol->candidate_functions, |
1738 * |
1866 /* fcall_param.called_function_declaration = */ symbol->called_function_declaration, |
1739 * If only one function exists, we add its return datatype to the candidate_datatype list, |
1867 /* fcall_param.extensible_param_count = */ symbol->extensible_param_count |
1740 * even if the parameters passed to it are invalid. |
1868 }; |
1741 * This guarantees that the remainder of the expression in which the function call is inserted |
1869 handle_function_call(symbol, fcall_param); |
1742 * is treated as if the function call returns correctly, and therefore does not generate |
1870 |
1743 * spurious error messages. |
1871 if (debug) std::cout << "function_invocation_c [" << symbol->candidate_datatypes.size() << "] result.\n"; |
1744 * Even if the parameters to the function call are invalid, doing this is still safe, as the |
|
1745 * expressions inside the function call will themselves have erros and will guarantee that |
|
1746 * compilation is aborted in stage3 (in print_datatypes_error_c). |
|
1747 */ |
|
1748 if (function_symtable.multiplicity(symbol->function_name) == 1) { |
|
1749 f_decl = function_symtable.get_value(lower); |
|
1750 returned_parameter_type = base_type(f_decl->type_name); |
|
1751 symbol->candidate_functions.push_back(f_decl); |
|
1752 symbol->candidate_datatypes.push_back(returned_parameter_type); |
|
1753 } |
|
1754 for(; lower != upper; lower++) { |
|
1755 bool compatible = false; |
|
1756 |
|
1757 f_decl = function_symtable.get_value(lower); |
|
1758 /* Check if function declaration in symbol_table is compatible with parameters */ |
|
1759 if (NULL != symbol->nonformal_param_list) compatible=match_nonformal_call(symbol, f_decl); |
|
1760 if (NULL != symbol-> formal_param_list) compatible= match_formal_call(symbol, f_decl); |
|
1761 if (compatible) { |
|
1762 /* Add the data type returned by the called functions. |
|
1763 * However, only do this if this data type is not already present in the candidate_datatypes list_c |
|
1764 */ |
|
1765 unsigned int k; |
|
1766 returned_parameter_type = base_type(f_decl->type_name); |
|
1767 for(k = 0; k < symbol->candidate_datatypes.size(); k++) { |
|
1768 if (is_type_equal(returned_parameter_type, symbol->candidate_datatypes[k])) |
|
1769 break; |
|
1770 } |
|
1771 if (k >= symbol->candidate_datatypes.size()) { |
|
1772 symbol->candidate_datatypes.push_back(returned_parameter_type); |
|
1773 symbol->candidate_functions.push_back(f_decl); |
|
1774 } |
|
1775 } |
|
1776 } |
|
1777 if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n"; |
|
1778 return NULL; |
1872 return NULL; |
1779 } |
1873 } |
1780 |
1874 |
1781 |
1875 |
1782 |
1876 |