162 param_value = fcp_iterator.get_current_value(); |
162 param_value = fcp_iterator.get_current_value(); |
163 |
163 |
164 /* Check if there are duplicate parameter values */ |
164 /* Check if there are duplicate parameter values */ |
165 if(fcp_iterator.search_f(param_name) != param_value) { |
165 if(fcp_iterator.search_f(param_name) != param_value) { |
166 function_invocation_error = true; |
166 function_invocation_error = true; |
167 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); |
167 STAGE3_ERROR(0, param_name, param_name, "Duplicate parameter '%s' when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value); |
168 continue; /* jump to next parameter */ |
168 continue; /* jump to next parameter */ |
169 } |
169 } |
170 |
170 |
171 /* Find the corresponding parameter in function declaration */ |
171 /* Find the corresponding parameter in function declaration */ |
172 if (NULL == fp_iterator.search(param_name)) { |
172 if (NULL == fp_iterator.search(param_name)) { |
173 function_invocation_error = true; |
173 function_invocation_error = true; |
174 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); |
174 STAGE3_ERROR(0, param_name, param_name, "Invalid parameter '%s' when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value); |
175 continue; /* jump to next parameter */ |
175 continue; /* jump to next parameter */ |
176 } |
176 } |
177 |
177 |
178 /* check whether direction (IN, OUT, IN_OUT) and assignment types (:= , =>) are compatible !!! */ |
178 /* check whether direction (IN, OUT, IN_OUT) and assignment types (:= , =>) are compatible !!! */ |
179 /* Obtaining the assignment direction: := (assign_in) or => (assign_out) */ |
179 /* Obtaining the assignment direction: := (assign_in) or => (assign_out) */ |
182 function_param_iterator_c::param_direction_t param_dir = fp_iterator.param_direction(); |
182 function_param_iterator_c::param_direction_t param_dir = fp_iterator.param_direction(); |
183 if (function_call_param_iterator_c::assign_in == call_param_dir) { |
183 if (function_call_param_iterator_c::assign_in == call_param_dir) { |
184 if ((function_param_iterator_c::direction_in != param_dir) && |
184 if ((function_param_iterator_c::direction_in != param_dir) && |
185 (function_param_iterator_c::direction_inout != param_dir)) { |
185 (function_param_iterator_c::direction_inout != param_dir)) { |
186 function_invocation_error = true; |
186 function_invocation_error = true; |
187 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); |
187 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax ':=' used for parameter '%s', when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value); |
188 continue; /* jump to next parameter */ |
188 continue; /* jump to next parameter */ |
189 } |
189 } |
190 } else if (function_call_param_iterator_c::assign_out == call_param_dir) { |
190 } else if (function_call_param_iterator_c::assign_out == call_param_dir) { |
191 if ((function_param_iterator_c::direction_out != param_dir)) { |
191 if ((function_param_iterator_c::direction_out != param_dir)) { |
192 function_invocation_error = true; |
192 function_invocation_error = true; |
193 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); |
193 STAGE3_ERROR(0, param_name, param_name, "Invalid assignment syntax '=>' used for parameter '%s', when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value); |
194 continue; /* jump to next parameter */ |
194 continue; /* jump to next parameter */ |
195 } |
195 } |
196 } else ERROR; |
196 } else ERROR; |
197 |
197 |
198 if (!get_datatype_info_c::is_type_valid(param_value->datatype)) { |
198 if (!get_datatype_info_c::is_type_valid(param_value->datatype)) { |
199 function_invocation_error = true; |
199 function_invocation_error = true; |
200 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); |
200 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility between parameter '%s' and value being passed, when invoking %s '%s'", ((token_c *)param_name)->value, POU_str, ((token_c *)fcall_data.function_name)->value); |
201 continue; /* jump to next parameter */ |
201 continue; /* jump to next parameter */ |
202 } |
202 } |
203 } |
203 } |
204 } |
204 } |
205 } |
205 } |
221 /* We are in a situation where an IL function call is passed the first parameter, which is actually the previous IL instruction */ |
221 /* We are in a situation where an IL function call is passed the first parameter, which is actually the previous IL instruction */ |
222 /* However, this is really a fake previous il instruction (see visit(il_instruction_c *) ) |
222 /* However, this is really a fake previous il instruction (see visit(il_instruction_c *) ) |
223 * We will iterate through all the real previous IL instructions, and analyse each of them one by one */ |
223 * We will iterate through all the real previous IL instructions, and analyse each of them one by one */ |
224 if (il_instruction_symbol->prev_il_instruction.size() == 0) { |
224 if (il_instruction_symbol->prev_il_instruction.size() == 0) { |
225 function_invocation_error = true; |
225 function_invocation_error = true; |
226 STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((identifier_c *)fcall_data.function_name)->value); |
226 STAGE3_ERROR(0, fcall, fcall, "No available data to pass to first parameter of IL function %s. Missing a previous LD instruction?", ((token_c *)fcall_data.function_name)->value); |
227 } |
227 } |
228 #if 0 |
228 #if 0 |
229 /* NOTE: We currently comment out this code... |
229 /* NOTE: We currently comment out this code... |
230 * This does not currently work, since the narrow operation is currently done on the intersection |
230 * This does not currently work, since the narrow operation is currently done on the intersection |
231 * of all the previous IL instructions, so we currently either accept them all, or none at all. |
231 * of all the previous IL instructions, so we currently either accept them all, or none at all. |
235 */ |
235 */ |
236 for (unsigned int p = 0; p < il_instruction_symbol->prev_il_instruction.size(); p++) { |
236 for (unsigned int p = 0; p < il_instruction_symbol->prev_il_instruction.size(); p++) { |
237 symbol_c *value = il_instruction_symbol->prev_il_instruction[p]; |
237 symbol_c *value = il_instruction_symbol->prev_il_instruction[p]; |
238 if (!get_datatype_info_c::is_type_valid(value->datatype)) { |
238 if (!get_datatype_info_c::is_type_valid(value->datatype)) { |
239 function_invocation_error = true; |
239 function_invocation_error = true; |
240 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
240 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility for value passed to first parameter when invoking function '%s'", ((token_c *)fcall_data.function_name)->value); |
241 STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
241 STAGE3_ERROR(0, value, value, "This is the IL instruction producing the incompatible data type to first parameter of function '%s'", ((token_c *)fcall_data.function_name)->value); |
242 } |
242 } |
243 } |
243 } |
244 #else |
244 #else |
245 if (!get_datatype_info_c::is_type_valid(il_instruction_symbol->datatype)) { |
245 if (!get_datatype_info_c::is_type_valid(il_instruction_symbol->datatype)) { |
246 function_invocation_error = true; |
246 function_invocation_error = true; |
247 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((identifier_c *)fcall_data.function_name)->value); |
247 STAGE3_ERROR(0, fcall, fcall, "Data type incompatibility between value in IL 'accumulator' and first parameter of function '%s'", ((token_c *)fcall_data.function_name)->value); |
248 } |
248 } |
249 #endif |
249 #endif |
250 if (function_invocation_error) |
250 if (function_invocation_error) |
251 /* when handling a IL function call, and an error is found in the first parameter, then we bug out and do not print out any more error messages. */ |
251 /* when handling a IL function call, and an error is found in the first parameter, then we bug out and do not print out any more error messages. */ |
252 return; |
252 return; |
253 } else { |
253 } else { |
254 if (!get_datatype_info_c::is_type_valid(param_value->datatype)) { |
254 if (!get_datatype_info_c::is_type_valid(param_value->datatype)) { |
255 function_invocation_error = true; |
255 function_invocation_error = true; |
256 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); |
256 STAGE3_ERROR(0, param_value, param_value, "Data type incompatibility for value passed in position %d when invoking %s '%s'", i, POU_str, ((token_c *)fcall_data.function_name)->value); |
257 } |
257 } |
258 param_value->accept(*this); |
258 param_value->accept(*this); |
259 } |
259 } |
260 } |
260 } |
261 } |
261 } |
262 |
262 |
263 if (NULL == fcall_data.called_function_declaration) { |
263 if (NULL == fcall_data.called_function_declaration) { |
264 function_invocation_error = true; |
264 function_invocation_error = true; |
265 STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
265 STAGE3_ERROR(0, fcall, fcall, "Unable to resolve which overloaded %s '%s' is being invoked.", POU_str, ((token_c *)fcall_data.function_name)->value); |
266 } |
266 } |
267 |
267 |
268 if (function_invocation_error) { |
268 if (function_invocation_error) { |
269 /* No compatible function exists */ |
269 /* No compatible function exists */ |
270 STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((identifier_c *)fcall_data.function_name)->value); |
270 STAGE3_ERROR(2, fcall, fcall, "Invalid parameters when invoking %s '%s'", POU_str, ((token_c *)fcall_data.function_name)->value); |
271 } |
271 } |
272 |
272 |
273 return; |
273 return; |
274 } |
274 } |
275 |
275 |