340 /***********************************************************************/ |
340 /***********************************************************************/ |
341 /***********************************************************************/ |
341 /***********************************************************************/ |
342 |
342 |
343 /* A helper class that analyses if the datatype of a variable is 'complex'. */ |
343 /* A helper class that analyses if the datatype of a variable is 'complex'. */ |
344 /* 'complex' means that it is either a strcuture or an array! */ |
344 /* 'complex' means that it is either a strcuture or an array! */ |
345 class analyse_variable_c: public null_visitor_c { |
345 class analyse_variable_c: public search_visitor_c { |
346 private: |
346 private: |
347 static analyse_variable_c *singleton_; |
347 static analyse_variable_c *singleton_; |
348 bool contains_complex_type_res; |
|
349 |
348 |
350 public: |
349 public: |
351 analyse_variable_c(void) {}; |
350 analyse_variable_c(void) {}; |
352 |
351 |
353 static bool is_complex_type(symbol_c *symbol) { |
352 static bool is_complex_type(symbol_c *symbol) { |
354 if (NULL == symbol) ERROR; |
353 if (NULL == symbol) ERROR; |
355 if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; |
354 if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; |
356 return ( get_datatype_info_c::is_structure(symbol->datatype) |
355 return ( get_datatype_info_c::is_structure(symbol->datatype) |
357 || get_datatype_info_c::is_array (symbol->datatype) |
356 || get_datatype_info_c::is_array (symbol->datatype) |
358 ); |
357 ); |
359 } |
358 } |
360 |
359 |
|
360 |
|
361 private: |
|
362 symbol_c *last_fb, *first_non_fb_identifier; |
|
363 |
|
364 public: |
|
365 /* returns the first element (from left to right) in a structured variable that is not a FB, i.e. is either a structure or an array! */ |
|
366 /* eg: |
|
367 * fb1.fb2.fb3.real returns ?????? |
|
368 * fb1.fb2.struct1.real returns struct1 |
|
369 * struct1.real returns struct1 |
|
370 */ |
|
371 static symbol_c *find_first_nonfb(symbol_c *symbol) { |
|
372 if (NULL == singleton_) singleton_ = new analyse_variable_c(); |
|
373 if (NULL == singleton_) ERROR; |
|
374 if (NULL == symbol) ERROR; |
|
375 |
|
376 singleton_->last_fb = NULL; |
|
377 singleton_->first_non_fb_identifier = NULL; |
|
378 return (symbol_c *)symbol->accept(*singleton_); |
|
379 } |
|
380 |
361 /* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */ |
381 /* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */ |
362 /* eg: |
382 /* eg: |
363 * fb1.fb2.fb3.real returns FALSE |
383 * fb1.fb2.fb3.real returns FALSE |
364 * fb1.fb2.struct1.real returns TRUE |
384 * fb1.fb2.struct1.real returns TRUE |
365 * struct1.real returns TRUE |
385 * struct1.real returns TRUE |
366 */ |
386 */ |
367 static bool contains_complex_type(symbol_c *symbol) { |
387 static bool contains_complex_type(symbol_c *symbol) { |
368 if (NULL == singleton_) singleton_ = new analyse_variable_c(); |
388 if (NULL == symbol) ERROR; |
369 if (NULL == singleton_) ERROR; |
389 if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR; |
370 if (NULL == symbol) ERROR; |
390 |
371 if (NULL == symbol->datatype) ERROR; |
391 symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol); |
372 |
392 return is_complex_type(first_non_fb->datatype); |
373 singleton_->contains_complex_type_res = false; |
393 } |
374 symbol->accept(*singleton_); |
394 |
375 return singleton_->contains_complex_type_res; |
395 |
|
396 /* returns the datatype of the variable returned by find_first_nonfb() */ |
|
397 /* eg: |
|
398 * fb1.fb2.fb3.real returns ?????? |
|
399 * fb1.fb2.struct1.real returns datatype of struct1 |
|
400 * struct1.real returns datatype of struct1 |
|
401 */ |
|
402 static search_var_instance_decl_c::vt_t first_nonfb_vardecltype(symbol_c *symbol, symbol_c *scope) { |
|
403 if (NULL == symbol) ERROR; |
|
404 if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR; |
|
405 |
|
406 symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol); |
|
407 if (NULL != singleton_->last_fb) { |
|
408 scope = singleton_->last_fb->datatype; |
|
409 symbol = singleton_->first_non_fb_identifier; |
|
410 } |
|
411 |
|
412 search_var_instance_decl_c search_var_instance_decl(scope); |
|
413 |
|
414 return search_var_instance_decl.get_vartype(symbol); |
376 } |
415 } |
377 |
416 |
378 |
417 |
379 /*********************/ |
418 /*********************/ |
380 /* B 1.4 - Variables */ |
419 /* B 1.4 - Variables */ |
381 /*********************/ |
420 /*********************/ |
382 void *visit(symbolic_variable_c *symbol) { |
421 void *visit(symbolic_variable_c *symbol) { |
383 contains_complex_type_res |= is_complex_type(symbol); |
422 if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; |
|
423 if (!get_datatype_info_c::is_function_block(symbol->datatype)) { |
|
424 first_non_fb_identifier = symbol; |
|
425 return (void *)symbol; |
|
426 } |
|
427 last_fb = symbol; |
384 return NULL; |
428 return NULL; |
385 } |
429 } |
386 |
430 |
387 /*************************************/ |
431 /*************************************/ |
388 /* B.1.4.2 Multi-element Variables */ |
432 /* B.1.4.2 Multi-element Variables */ |
389 /*************************************/ |
433 /*************************************/ |
390 |
434 |
391 // SYM_REF2(structured_variable_c, record_variable, field_selector) |
435 // SYM_REF2(structured_variable_c, record_variable, field_selector) |
392 void *visit(structured_variable_c *symbol) { |
436 void *visit(structured_variable_c *symbol) { |
393 symbol->record_variable->accept(*this); |
437 symbol_c *res = (symbol_c *)symbol->record_variable->accept(*this); |
394 /* do not set the contains_complex_type_res to TRUE if this structured_variable_c is accessing a FB instance! */ |
438 if (NULL != res) return res; |
395 if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR; |
439 |
396 contains_complex_type_res |= get_datatype_info_c::is_structure(symbol->datatype); |
440 if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; |
397 return NULL; |
441 if (!get_datatype_info_c::is_function_block(symbol->datatype)) { |
|
442 first_non_fb_identifier = symbol->field_selector; |
|
443 return (void *)symbol; |
|
444 } |
|
445 |
|
446 last_fb = symbol; |
|
447 return NULL; |
398 } |
448 } |
399 |
449 |
400 /* subscripted_variable '[' subscript_list ']' */ |
450 /* subscripted_variable '[' subscript_list ']' */ |
401 //SYM_REF2(array_variable_c, subscripted_variable, subscript_list) |
451 //SYM_REF2(array_variable_c, subscripted_variable, subscript_list) |
402 void *visit(array_variable_c *symbol) { |
452 void *visit(array_variable_c *symbol) { |
403 contains_complex_type_res |= true; |
453 void *res = symbol->subscripted_variable->accept(*this); |
404 return NULL; |
454 if (NULL != res) return res; |
405 } |
455 return (void *)symbol; |
406 |
456 } |
|
457 |
|
458 |
407 }; |
459 }; |
408 |
460 |
409 analyse_variable_c *analyse_variable_c::singleton_ = NULL; |
461 analyse_variable_c *analyse_variable_c::singleton_ = NULL; |
410 |
462 |
411 /***********************************************************************/ |
463 /***********************************************************************/ |