122 /* Due to the way the syntax analysis is buit (i.e. stage 2), this should never occur. */ |
122 /* Due to the way the syntax analysis is buit (i.e. stage 2), this should never occur. */ |
123 /* I.e., a FB invocation using an undefined FB variable is not possible in the current implementation of stage 2. */ |
123 /* I.e., a FB invocation using an undefined FB variable is not possible in the current implementation of stage 2. */ |
124 ERROR; |
124 ERROR; |
125 } |
125 } |
126 if (NULL == f_decl) { |
126 if (NULL == f_decl) { |
127 STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
128 /* we now try to find any function declaration with the same name, just so we can provide some relevant error messages */ |
127 /* we now try to find any function declaration with the same name, just so we can provide some relevant error messages */ |
129 function_symtable_t::iterator lower = function_symtable.lower_bound(fcall_data.function_name); |
128 function_symtable_t::iterator lower = function_symtable.lower_bound(fcall_data.function_name); |
130 if (lower == function_symtable.end()) ERROR; |
129 if (lower == function_symtable.end()) ERROR; |
131 f_decl = function_symtable.get_value(lower); |
130 f_decl = function_symtable.get_value(lower); |
132 } |
131 } |
134 if (NULL != fcall_data.formal_operand_list) { |
133 if (NULL != fcall_data.formal_operand_list) { |
135 fcall_data.formal_operand_list->accept(*this); |
134 fcall_data.formal_operand_list->accept(*this); |
136 if (NULL != f_decl) { |
135 if (NULL != f_decl) { |
137 function_param_iterator_c fp_iterator(f_decl); |
136 function_param_iterator_c fp_iterator(f_decl); |
138 while ((param_name = fcp_iterator.next_f()) != NULL) { |
137 while ((param_name = fcp_iterator.next_f()) != NULL) { |
139 #if 0 |
|
140 /* TODO: check whether direction (IN, OUT, IN_OUT) and assignment types (:= , =>) are compatible !!! */ |
|
141 |
|
142 |
|
143 /* TODO: Check if there are duplicat parameter values */ |
|
144 verify_duplicate_param = fcp_iterator.search_f(call_param_name); |
|
145 if(verify_duplicate_param != call_param_value) |
|
146 return false; |
|
147 #endif |
|
148 param_value = fcp_iterator.get_current_value(); |
138 param_value = fcp_iterator.get_current_value(); |
|
139 |
|
140 /* Check if there are duplicate parameter values */ |
|
141 if(fcp_iterator.search_f(param_name) != param_value) { |
|
142 function_invocation_error = true; |
|
143 STAGE3_ERROR(0, param_name, param_name, "Duplicate parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
144 continue; /* jump to next parameter */ |
|
145 } |
|
146 |
149 /* Find the corresponding parameter in function declaration */ |
147 /* Find the corresponding parameter in function declaration */ |
150 if (NULL == fp_iterator.search(param_name)) { |
148 if (NULL == fp_iterator.search(param_name)) { |
151 STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
149 function_invocation_error = true; |
152 } else if (NULL == param_value->datatype) { |
150 STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
151 continue; /* jump to next parameter */ |
|
152 } |
|
153 |
|
154 /* check whether direction (IN, OUT, IN_OUT) and assignment types (:= , =>) are compatible !!! */ |
|
155 /* Obtaining the assignment direction: := (assign_in) or => (assign_out) */ |
|
156 function_call_param_iterator_c::assign_direction_t call_param_dir = fcp_iterator.get_assign_direction(); |
|
157 /* Get the parameter direction: IN, OUT, IN_OUT */ |
|
158 function_param_iterator_c::param_direction_t param_dir = fp_iterator.param_direction(); |
|
159 if (function_call_param_iterator_c::assign_in == call_param_dir) { |
|
160 if ((function_param_iterator_c::direction_in != param_dir) && |
|
161 (function_param_iterator_c::direction_inout != param_dir)) { |
|
162 function_invocation_error = true; |
|
163 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax ':=' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
164 continue; /* jump to next parameter */ |
|
165 } |
|
166 } else if (function_call_param_iterator_c::assign_out == call_param_dir) { |
|
167 if ((function_param_iterator_c::direction_out != param_dir)) { |
|
168 function_invocation_error = true; |
|
169 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax '=>' used for parameter '%s', when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
170 continue; /* jump to next parameter */ |
|
171 } |
|
172 } else ERROR; |
|
173 |
|
174 if (NULL == param_value->datatype) { |
153 function_invocation_error = true; |
175 function_invocation_error = true; |
154 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
176 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((identifier_c *)param_name)->value, POU_str, ((identifier_c *)fcall_data.function_name)->value); |
|
177 continue; /* jump to next parameter */ |
155 } |
178 } |
156 } |
179 } |
157 } |
180 } |
158 } |
181 } |
159 if (NULL != fcall_data.nonformal_operand_list) { |
182 if (NULL != fcall_data.nonformal_operand_list) { |
163 if (NULL == param_value->datatype) { |
186 if (NULL == param_value->datatype) { |
164 function_invocation_error = true; |
187 function_invocation_error = true; |
165 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); |
188 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); |
166 } |
189 } |
167 } |
190 } |
|
191 } |
|
192 |
|
193 if (NULL == fcall_data.called_function_declaration) { |
|
194 function_invocation_error = true; |
|
195 STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
168 } |
196 } |
169 |
197 |
170 if (function_invocation_error) { |
198 if (function_invocation_error) { |
171 /* No compatible function exists */ |
199 /* No compatible function exists */ |
172 STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
200 STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((identifier_c *)fcall_data.function_name)->value); |