173 if ((NULL == param_name) && (NULL != desired_datatype)) ERROR; |
173 if ((NULL == param_name) && (NULL != desired_datatype)) ERROR; |
174 |
174 |
175 /* set the desired data type for this parameter */ |
175 /* set the desired data type for this parameter */ |
176 set_datatype(desired_datatype, call_param_value); |
176 set_datatype(desired_datatype, call_param_value); |
177 /* And recursively call that parameter/expression, so it can propagate that info */ |
177 /* And recursively call that parameter/expression, so it can propagate that info */ |
178 /* However, when handling an implicit IL FB call, the first parameter is fake (a copy of the prev_il_instruction). |
|
179 * so the call call_param_value->accept(*this) may actually be calling an object of the base symbol_c . |
|
180 */ |
|
181 call_param_value->accept(*this); |
178 call_param_value->accept(*this); |
182 |
179 |
|
180 /* set the extensible_parameter_highest_index, which will be needed in stage 4 */ |
|
181 /* This value says how many extensible parameters are being passed to the standard function */ |
183 if (NULL != param_name) |
182 if (NULL != param_name) |
184 if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) |
183 if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) |
185 extensible_parameter_highest_index = fp_iterator.extensible_param_index(); |
184 extensible_parameter_highest_index = fp_iterator.extensible_param_index(); |
186 } |
185 } |
187 /* call is compatible! */ |
186 /* call is compatible! */ |
259 * |
258 * |
260 * The algorithm will be to build a fake il_fb_call_c equivalent to the implicit IL FB call, and let |
259 * The algorithm will be to build a fake il_fb_call_c equivalent to the implicit IL FB call, and let |
261 * the visit(il_fb_call_c *) method handle it! |
260 * the visit(il_fb_call_c *) method handle it! |
262 */ |
261 */ |
263 void narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) { |
262 void narrow_candidate_datatypes_c::narrow_implicit_il_fb_call(symbol_c *il_instruction, const char *param_name, symbol_c *&called_fb_declaration) { |
264 if (NULL == called_fb_declaration) |
263 |
265 /* The fill_candidate_datatypes_c was not able to determine which FB is being called! |
264 /* set the datatype of the il_operand, this is, the FB being called! */ |
266 * This may be because the il_operand is not the name of a FB instance, or no operand was given. |
265 if (NULL != il_operand) { |
267 * In that case, we just give up! |
266 /* only set it if it is in the candidate datatypes list! */ |
268 */ |
267 set_datatype(called_fb_declaration, il_operand); |
269 return; |
268 il_operand->accept(*this); |
|
269 } |
|
270 symbol_c *fb_decl = il_operand->datatype; |
|
271 |
270 if (NULL == prev_il_instruction) { |
272 if (NULL == prev_il_instruction) { |
271 /* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction |
273 /* This IL implicit FB call (e.g. CLK ton_var) is not preceded by another IL instruction |
272 * (or list of instructions) that will set the IL current/default value. |
274 * (or list of instructions) that will set the IL current/default value. |
273 * We cannot proceed verifying type compatibility of something that does not exist. |
275 * We cannot proceed verifying type compatibility of something that does not exist. |
274 */ |
276 */ |
275 return; |
277 return; |
276 } |
278 } |
|
279 |
|
280 if (NULL == fb_decl) { |
|
281 /* the il_operand is a not FB instance */ |
|
282 /* so we simply pass on the required datatype to the prev_il_instruction */ |
|
283 /* The invalid FB invocation will be caught by the print_datatypes_error_c by analysing NULL value in il_operand->datatype! */ |
|
284 prev_il_instruction->datatype = il_instruction->datatype; |
|
285 return; |
|
286 } |
|
287 |
277 |
288 |
278 /* The value being passed to the 'param_name' parameter is actually the prev_il_instruction. |
289 /* The value being passed to the 'param_name' parameter is actually the prev_il_instruction. |
279 * However, we do not place that object directly in the fake il_param_list_c that we will be |
290 * However, we do not place that object directly in the fake il_param_list_c that we will be |
280 * creating, since the visit(il_fb_call_c *) method will recursively call every object in that list. |
291 * creating, since the visit(il_fb_call_c *) method will recursively call every object in that list. |
281 * The il_prev_intruction object will be visited once we have handled this implici IL FB call |
292 * The il_prev_intruction object will be visited once we have handled this implici IL FB call |
283 * (Anyway, if we let the visit(il_fb_call_c *) recursively visit the current prev_il_instruction, this pointer |
294 * (Anyway, if we let the visit(il_fb_call_c *) recursively visit the current prev_il_instruction, this pointer |
284 * would be changed to the IL instruction coming before the current prev_il_instruction! => things would get all messed up!) |
295 * would be changed to the IL instruction coming before the current prev_il_instruction! => things would get all messed up!) |
285 * The easiest way to work around this is to simply use a new object, and copy the relevant details to that object! |
296 * The easiest way to work around this is to simply use a new object, and copy the relevant details to that object! |
286 */ |
297 */ |
287 symbol_c param_value = *prev_il_instruction; |
298 symbol_c param_value = *prev_il_instruction; |
288 |
299 |
289 identifier_c variable_name(param_name); |
300 identifier_c variable_name(param_name); |
290 // SYM_REF1(il_assign_operator_c, variable_name) |
301 // SYM_REF1(il_assign_operator_c, variable_name) |
291 il_assign_operator_c il_assign_operator(&variable_name); |
302 il_assign_operator_c il_assign_operator(&variable_name); |
292 // SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list) |
303 // SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list) |
293 il_param_assignment_c il_param_assignment(&il_assign_operator, ¶m_value/*il_operand*/, NULL); |
304 il_param_assignment_c il_param_assignment(&il_assign_operator, ¶m_value/*il_operand*/, NULL); |
294 il_param_list_c il_param_list; |
305 il_param_list_c il_param_list; |
295 il_param_list.add_element(&il_param_assignment); |
306 il_param_list.add_element(&il_param_assignment); |
296 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
307 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
297 il_fb_call_c il_fb_call(NULL, il_operand, NULL, &il_param_list); |
308 CAL_operator_c CAL_operator; |
298 |
309 il_fb_call_c il_fb_call(&CAL_operator, il_operand, NULL, &il_param_list); |
|
310 |
299 /* A FB call does not return any datatype, but the IL instructions that come after this |
311 /* A FB call does not return any datatype, but the IL instructions that come after this |
300 * FB call may require a specific datatype in the il current/default variable, |
312 * FB call may require a specific datatype in the il current/default variable, |
301 * so we must pass this information up to the IL instruction before the FB call, since it will |
313 * so we must pass this information up to the IL instruction before the FB call, since it will |
302 * be that IL instruction that will be required to produce the desired dtataype. |
314 * be that IL instruction that will be required to produce the desired dtataype. |
303 * |
315 * |
304 * The above will be done by the visit(il_fb_call_c *) method, so we must make sure to |
316 * The above will be done by the visit(il_fb_call_c *) method, so we must make sure to |
305 * correctly set up the il_fb_call.datatype variable! |
317 * correctly set up the il_fb_call.datatype variable! |
306 */ |
318 */ |
307 copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/); |
319 // copy_candidate_datatype_list(il_instruction/*from*/, &il_fb_call/*to*/); |
|
320 il_fb_call.called_fb_declaration = called_fb_declaration; |
308 il_fb_call.accept(*this); |
321 il_fb_call.accept(*this); |
309 |
322 |
310 /* set the required datatype of the previous IL instruction! */ |
323 /* set the required datatype of the previous IL instruction! */ |
311 /* NOTE: |
324 /* NOTE: |
312 * When handling these implicit IL calls, the parameter_value being passed to the FB parameter |
325 * When handling these implicit IL calls, the parameter_value being passed to the FB parameter |
313 * is actually the prev_il_instruction. |
326 * is actually the prev_il_instruction. |
314 * |
327 * |
325 * datatype in the current/default vairable, once this IL FB call returns. |
338 * datatype in the current/default vairable, once this IL FB call returns. |
326 * However, sometimes, (for e.g., this FB call is the last in the IL list) the subsequent FB to not aks this |
339 * However, sometimes, (for e.g., this FB call is the last in the IL list) the subsequent FB to not aks this |
327 * FB call for any datatype. In that case, then the datatype required to pass to the first parameter of the |
340 * FB call for any datatype. In that case, then the datatype required to pass to the first parameter of the |
328 * FB call must be left unchanged! |
341 * FB call must be left unchanged! |
329 */ |
342 */ |
330 // if (NULL != prev_il_instruction) /* already checked above! */ |
343 if ((NULL == il_instruction->datatype) || (is_type_equal(param_value.datatype, il_instruction->datatype))) { |
331 if (is_type_equal(param_value.datatype, il_instruction->datatype)) { |
344 prev_il_instruction->datatype = param_value.datatype; |
332 prev_il_instruction->datatype = param_value.datatype; |
345 } else { |
333 } else { |
346 prev_il_instruction->datatype = NULL; |
334 prev_il_instruction->datatype = NULL; |
347 } |
335 } |
|
336 |
|
337 } |
348 } |
338 |
349 |
339 |
350 |
340 /* a helper function... */ |
351 /* a helper function... */ |
341 symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) { |
352 symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) { |
590 * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
601 * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')' |
591 */ |
602 */ |
592 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ |
603 /* NOTE: The parameter 'called_fb_declaration'is used to pass data between stage 3 and stage4 (although currently it is not used in stage 4 */ |
593 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
604 // SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list, symbol_c *called_fb_declaration) |
594 void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) { |
605 void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) { |
595 /* Note: We do not use the symbol->called_fb_declaration value (set in fill_candidate_datatypes_c) |
606 symbol_c *fb_decl = symbol->called_fb_declaration; |
596 * because we try to identify any other datatype errors in the expressions used in the |
607 |
597 * parameters to the FB call. e.g. |
|
598 * fb_var( |
|
599 * in1 := var1, |
|
600 * in2 := ( |
|
601 * LD 56 |
|
602 * ADD 43 |
|
603 * ) |
|
604 * ) |
|
605 * even it the call to the FB is invalid. |
|
606 * This makes sense because it may be errors in those expressions which are |
|
607 * making this an invalid call, so it makes sense to point them out to the user! |
|
608 */ |
|
609 symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name); |
|
610 |
|
611 /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ |
608 /* Although a call to a non-declared FB is a semantic error, this is currently caught by stage 2! */ |
612 if (NULL == fb_decl) ERROR; |
609 if (NULL == fb_decl) ERROR; |
613 if (NULL != symbol->il_operand_list) narrow_nonformal_call(symbol, fb_decl); |
610 if (NULL != symbol->il_operand_list) narrow_nonformal_call(symbol, fb_decl); |
614 if (NULL != symbol-> il_param_list) narrow_formal_call(symbol, fb_decl); |
611 if (NULL != symbol-> il_param_list) narrow_formal_call(symbol, fb_decl); |
615 |
612 |
616 /* An IL FB call does not change the default value in the current/default IL variable, so we pass the |
613 /* Let the il_call_operator (CAL, CALC, or CALCN) set the datatype of prev_il_instruction... */ |
617 * required datatype up to the previous IL instruction |
614 symbol->il_call_operator->datatype = symbol->datatype; |
618 */ |
615 symbol->il_call_operator->accept(*this); |
619 if (NULL != prev_il_instruction) |
|
620 prev_il_instruction->datatype = symbol->datatype; |
|
621 return NULL; |
616 return NULL; |
622 } |
617 } |
623 |
618 |
624 |
619 |
625 /* | function_name '(' eol_list [il_param_list] ')' */ |
620 /* | function_name '(' eol_list [il_param_list] ')' */ |
823 void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) {return handle_il_instruction(symbol);} |
818 void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) {return handle_il_instruction(symbol);} |
824 void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) {return handle_il_instruction(symbol);} |
819 void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) {return handle_il_instruction(symbol);} |
825 void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) {return handle_il_instruction(symbol);} |
820 void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) {return handle_il_instruction(symbol);} |
826 |
821 |
827 |
822 |
|
823 // SYM_REF0(CAL_operator_c) |
|
824 /* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */ |
828 void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) { |
825 void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) { |
829 return NULL; |
826 /* set the desired datatype of the previous il instruction */ |
830 } |
827 /* This FB call does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction */ |
831 |
828 if (NULL != prev_il_instruction) |
|
829 prev_il_instruction->datatype = symbol->datatype; |
|
830 return NULL; |
|
831 } |
|
832 |
|
833 |
|
834 void *narrow_candidate_datatypes_c::narrow_conditional_flow_control_IL_instruction(symbol_c *symbol) { |
|
835 /* if the next IL instructions needs us to provide a datatype other than a bool, |
|
836 * then we have an internal compiler error - most likely in fill_candidate_datatypes_c |
|
837 */ |
|
838 if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR; |
|
839 if (symbol->candidate_datatypes.size() > 1) ERROR; |
|
840 |
|
841 /* NOTE: If there is not IL instruction following this CALC, CALCN, JMPC, JMPC, ..., instruction, |
|
842 * we must still provide a bool_type_name_c datatype (if possible, i.e. if it exists in the candidate datatype list). |
|
843 * If it is not possible, we set it to NULL |
|
844 */ |
|
845 if (symbol->candidate_datatypes.size() == 0) symbol->datatype = NULL; |
|
846 else symbol->datatype = symbol->candidate_datatypes[0]; /* i.e. a bool_type_name_c! */ |
|
847 if ((NULL != symbol->datatype) && (!is_type(symbol->datatype, bool_type_name_c))) ERROR; |
|
848 |
|
849 /* set the required datatype of the previous IL instruction, i.e. a bool_type_name_c! */ |
|
850 if (NULL != prev_il_instruction) prev_il_instruction->datatype = symbol->datatype; |
|
851 return NULL; |
|
852 } |
|
853 |
|
854 |
|
855 // SYM_REF0(CALC_operator_c) |
|
856 /* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */ |
832 void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) { |
857 void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) { |
833 return NULL; |
858 return narrow_conditional_flow_control_IL_instruction(symbol); |
834 } |
859 } |
835 |
860 |
|
861 |
|
862 // SYM_REF0(CALCN_operator_c) |
|
863 /* called from il_fb_call_c (symbol->il_call_operator->accpet(*this) ) */ |
836 void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) { |
864 void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) { |
837 return NULL; |
865 return narrow_conditional_flow_control_IL_instruction(symbol); |
838 } |
866 } |
|
867 |
839 |
868 |
840 void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) { |
869 void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) { |
|
870 /* set the desired datatype of the previous il instruction */ |
|
871 /* This RET instruction does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction. |
|
872 * Actually this should always be NULL, otherwise we have a bug in the flow_control_analysis_c |
|
873 * However, since that class has not yet been completely finished, we do not yet check this assertion! |
|
874 */ |
|
875 // if (NULL != symbol->datatype) ERROR; |
|
876 if (NULL != prev_il_instruction) |
|
877 prev_il_instruction->datatype = symbol->datatype; |
841 return NULL; |
878 return NULL; |
842 } |
879 } |
843 |
880 |
844 void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) { |
881 void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) { |
845 return NULL; |
882 return narrow_conditional_flow_control_IL_instruction(symbol); |
846 } |
883 } |
847 |
884 |
848 void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) { |
885 void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) { |
849 return NULL; |
886 return narrow_conditional_flow_control_IL_instruction(symbol); |
850 } |
887 } |
851 |
888 |
852 void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) { |
889 void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) { |
|
890 /* set the desired datatype of the previous il instruction */ |
|
891 /* This JMP instruction does not change the value in the current/default IL variable, so we pass the required datatype to the previous IL instruction. |
|
892 * Actually this should always be NULL, otherwise we have a bug in the flow_control_analysis_c |
|
893 * However, since that class has not yet been completely finished, we do not yet check this assertion! |
|
894 */ |
|
895 // if (NULL != symbol->datatype) ERROR; |
|
896 if (NULL != prev_il_instruction) |
|
897 prev_il_instruction->datatype = symbol->datatype; |
853 return NULL; |
898 return NULL; |
854 } |
899 } |
855 |
900 |
856 void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) { |
901 void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) { |
857 return NULL; |
902 return narrow_conditional_flow_control_IL_instruction(symbol); |
858 } |
903 } |
859 |
904 |
860 void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) { |
905 void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) { |
861 return NULL; |
906 return narrow_conditional_flow_control_IL_instruction(symbol); |
862 } |
907 } |
863 |
908 |
864 /* Symbol class handled together with function call checks */ |
909 /* Symbol class handled together with function call checks */ |
865 // void *visit(il_assign_operator_c *symbol, variable_name); |
910 // void *visit(il_assign_operator_c *symbol, variable_name); |
866 /* Symbol class handled together with function call checks */ |
911 /* Symbol class handled together with function call checks */ |