181 } |
181 } |
182 if (NULL != fcall_data.nonformal_operand_list) { |
182 if (NULL != fcall_data.nonformal_operand_list) { |
183 fcall_data.nonformal_operand_list->accept(*this); |
183 fcall_data.nonformal_operand_list->accept(*this); |
184 if (f_decl) |
184 if (f_decl) |
185 for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { |
185 for (int i = 1; (param_value = fcp_iterator.next_nf()) != NULL; i++) { |
|
186 /* TODO: verify if it is lvalue when INOUT or OUTPUT parameters! */ |
|
187 |
186 if (NULL == param_value->datatype) { |
188 if (NULL == param_value->datatype) { |
187 function_invocation_error = true; |
189 function_invocation_error = true; |
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); |
190 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); |
189 } |
191 } |
190 } |
192 } |
201 } |
203 } |
202 |
204 |
203 return; |
205 return; |
204 } |
206 } |
205 |
207 |
|
208 |
|
209 |
206 void print_datatypes_error_c::handle_implicit_il_fb_invocation(symbol_c *il_operator, const char *param_name, symbol_c *called_fb_declaration) { |
210 void print_datatypes_error_c::handle_implicit_il_fb_invocation(symbol_c *il_operator, const char *param_name, symbol_c *called_fb_declaration) { |
207 if (NULL == il_operand) { |
211 if (NULL == il_operand) { |
208 STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name); |
212 STAGE3_ERROR(0, il_operator, il_operator, "Missing operand for FB call operator '%s'.", param_name); |
209 return; |
213 return; |
210 } |
214 } |
|
215 il_operand->accept(*this); |
|
216 |
211 if (NULL == called_fb_declaration) { |
217 if (NULL == called_fb_declaration) { |
212 STAGE3_ERROR(0, il_operand, il_operand, "Operand of FB call operator '%s' is not a FB variable.", param_name); |
218 STAGE3_ERROR(0, il_operator, il_operand, "Invalid FB call: operand is not a FB instance."); |
213 return; |
219 return; |
214 } |
220 } |
|
221 |
215 if (NULL == prev_il_instruction) { |
222 if (NULL == prev_il_instruction) { |
216 STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); |
223 STAGE3_ERROR(0, il_operator, il_operand, "FB invocation operator '%s' must be preceded by a 'LD' (or equivalent) operator.", param_name); |
217 return; |
224 return; |
218 } |
225 } |
|
226 |
219 /* Find the corresponding parameter in function declaration */ |
227 /* Find the corresponding parameter in function declaration */ |
220 function_param_iterator_c fp_iterator(called_fb_declaration); |
228 function_param_iterator_c fp_iterator(called_fb_declaration); |
221 if (NULL == fp_iterator.search(param_name)) { |
229 if (NULL == fp_iterator.search(param_name)) { |
222 /* TODO: must also check whther it is an IN parameter!! */ |
230 /* TODO: must also check whther it is an IN parameter!! */ |
|
231 /* NOTE: although all standard FBs have the implicit FB calls defined as input parameters |
|
232 * (i.e., for all standard FBs, CLK, PT, IN, CU, CD, S1, R1, etc... is always an input parameter) |
|
233 * if a non-standard (i.e. a FB not defined in the standard library) FB is being called, then |
|
234 * this (CLK, PT, IN, CU, ...) parameter may just have been defined as OUT or INOUT, |
|
235 * which will not work for an implicit FB call! |
|
236 */ |
223 STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); |
237 STAGE3_ERROR(0, il_operator, il_operand, "FB called by '%s' operator does not have a parameter named '%s'", param_name, param_name); |
224 return; |
238 return; |
225 } |
239 } |
226 if (NULL == prev_il_instruction->datatype) { |
240 if (NULL == prev_il_instruction->datatype) { |
227 STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed, when invoking FB.", param_name); |
241 STAGE3_ERROR(0, il_operator, il_operand, "Data type incompatibility between parameter '%s' and value being passed.", param_name); |
228 return; |
242 return; |
229 } |
243 } |
230 |
244 |
|
245 |
|
246 /* NOTE: The error_level currently being used for errors in variables/constants etc... is rather high. |
|
247 * However, in the case of an implicit FB call, if the datatype of the operand == NULL, this may be |
|
248 * the __only__ indication of an error! So we test it here again, to make sure thtis error will really |
|
249 * be printed out! |
|
250 */ |
|
251 if (NULL == il_operand->datatype) { |
|
252 /* Note: the case of (NULL == fb_declaration) was already caught above! */ |
|
253 // if (NULL != fb_declaration) { |
|
254 STAGE3_ERROR(0, il_operator, il_operator, "Invalid FB call: Datatype incompatibility between the FB's '%s' parameter and value being passed, or paramater '%s' is not a 'VAR_INPUT' parameter.", param_name, param_name); |
|
255 return; |
|
256 // } |
|
257 } |
|
258 // |
231 return; |
259 return; |
232 } |
260 } |
233 |
261 |
234 |
262 |
235 /*********************/ |
263 /*********************/ |
679 /* fcall_param.called_function_declaration = */ symbol->called_fb_declaration, |
705 /* fcall_param.called_function_declaration = */ symbol->called_fb_declaration, |
680 /* fcall_param.extensible_param_count = */ extensible_param_count /* will not be used, but must provide a reference to be able to compile */ |
706 /* fcall_param.extensible_param_count = */ extensible_param_count /* will not be used, but must provide a reference to be able to compile */ |
681 }; |
707 }; |
682 |
708 |
683 handle_function_invocation(symbol, fcall_param); |
709 handle_function_invocation(symbol, fcall_param); |
|
710 /* check the semantics of the CALC, CALCN operators! */ |
|
711 symbol->il_call_operator->accept(*this); |
684 return NULL; |
712 return NULL; |
685 } |
713 } |
686 |
714 |
687 /* | function_name '(' eol_list [il_param_list] ')' */ |
715 /* | function_name '(' eol_list [il_param_list] ')' */ |
688 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
716 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4. */ |
920 |
948 |
921 void *print_datatypes_error_c::visit(CAL_operator_c *symbol) { |
949 void *print_datatypes_error_c::visit(CAL_operator_c *symbol) { |
922 return NULL; |
950 return NULL; |
923 } |
951 } |
924 |
952 |
|
953 |
|
954 void *print_datatypes_error_c::handle_conditional_flow_control_IL_instruction(symbol_c *symbol, const char *oper) { |
|
955 if (NULL == symbol->datatype) |
|
956 STAGE3_ERROR(0, symbol, symbol, "%s operator must be preceded by an IL instruction producing a BOOL value.", oper); |
|
957 return NULL; |
|
958 } |
|
959 |
925 void *print_datatypes_error_c::visit(CALC_operator_c *symbol) { |
960 void *print_datatypes_error_c::visit(CALC_operator_c *symbol) { |
926 return NULL; |
961 return handle_conditional_flow_control_IL_instruction(symbol, "CALC"); |
927 } |
962 } |
928 |
963 |
929 void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) { |
964 void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) { |
930 return NULL; |
965 return handle_conditional_flow_control_IL_instruction(symbol, "CALCN"); |
931 } |
966 } |
932 |
967 |
933 void *print_datatypes_error_c::visit(RET_operator_c *symbol) { |
968 void *print_datatypes_error_c::visit(RET_operator_c *symbol) { |
934 return NULL; |
969 return NULL; |
935 } |
970 } |
936 |
971 |
937 void *print_datatypes_error_c::visit(RETC_operator_c *symbol) { |
972 void *print_datatypes_error_c::visit(RETC_operator_c *symbol) { |
938 return NULL; |
973 return handle_conditional_flow_control_IL_instruction(symbol, "RETC"); |
939 } |
974 } |
940 |
975 |
941 void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) { |
976 void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) { |
942 return NULL; |
977 return handle_conditional_flow_control_IL_instruction(symbol, "RETCN"); |
943 } |
978 } |
944 |
979 |
945 void *print_datatypes_error_c::visit(JMP_operator_c *symbol) { |
980 void *print_datatypes_error_c::visit(JMP_operator_c *symbol) { |
946 return NULL; |
981 return NULL; |
947 } |
982 } |
948 |
983 |
949 void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) { |
984 void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) { |
950 return NULL; |
985 return handle_conditional_flow_control_IL_instruction(symbol, "JMPC"); |
951 } |
986 } |
952 |
987 |
953 void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) { |
988 void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) { |
954 return NULL; |
989 return handle_conditional_flow_control_IL_instruction(symbol, "JMPCN"); |
955 } |
990 } |
956 |
991 |
957 /* Symbol class handled together with function call checks */ |
992 /* Symbol class handled together with function call checks */ |
958 // void *visit(il_assign_operator_c *symbol, variable_name); |
993 // void *visit(il_assign_operator_c *symbol, variable_name); |
959 /* Symbol class handled together with function call checks */ |
994 /* Symbol class handled together with function call checks */ |