Fix bug: correctly generate code when accessing external variables declared inside FBs as a structured variable (realvar := fb1.fb2.extvar1.realvar)
--- a/stage4/generate_c/generate_c.cc Sun Dec 22 09:50:02 2013 +0000
+++ b/stage4/generate_c/generate_c.cc Mon Jan 06 12:25:21 2014 +0000
@@ -342,22 +342,42 @@
/* A helper class that analyses if the datatype of a variable is 'complex'. */
/* 'complex' means that it is either a strcuture or an array! */
-class analyse_variable_c: public null_visitor_c {
+class analyse_variable_c: public search_visitor_c {
private:
static analyse_variable_c *singleton_;
- bool contains_complex_type_res;
public:
analyse_variable_c(void) {};
static bool is_complex_type(symbol_c *symbol) {
- if (NULL == symbol) ERROR;
+ if (NULL == symbol) ERROR;
if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR;
return ( get_datatype_info_c::is_structure(symbol->datatype)
|| get_datatype_info_c::is_array (symbol->datatype)
);
}
+
+ private:
+ symbol_c *last_fb, *first_non_fb_identifier;
+
+ public:
+ /* 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! */
+ /* eg:
+ * fb1.fb2.fb3.real returns ??????
+ * fb1.fb2.struct1.real returns struct1
+ * struct1.real returns struct1
+ */
+ static symbol_c *find_first_nonfb(symbol_c *symbol) {
+ if (NULL == singleton_) singleton_ = new analyse_variable_c();
+ if (NULL == singleton_) ERROR;
+ if (NULL == symbol) ERROR;
+
+ singleton_->last_fb = NULL;
+ singleton_->first_non_fb_identifier = NULL;
+ return (symbol_c *)symbol->accept(*singleton_);
+ }
+
/* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */
/* eg:
* fb1.fb2.fb3.real returns FALSE
@@ -365,14 +385,33 @@
* struct1.real returns TRUE
*/
static bool contains_complex_type(symbol_c *symbol) {
- if (NULL == singleton_) singleton_ = new analyse_variable_c();
- if (NULL == singleton_) ERROR;
- if (NULL == symbol) ERROR;
- if (NULL == symbol->datatype) ERROR;
-
- singleton_->contains_complex_type_res = false;
- symbol->accept(*singleton_);
- return singleton_->contains_complex_type_res;
+ if (NULL == symbol) ERROR;
+ if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+
+ symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+ return is_complex_type(first_non_fb->datatype);
+ }
+
+
+ /* returns the datatype of the variable returned by find_first_nonfb() */
+ /* eg:
+ * fb1.fb2.fb3.real returns ??????
+ * fb1.fb2.struct1.real returns datatype of struct1
+ * struct1.real returns datatype of struct1
+ */
+ static search_var_instance_decl_c::vt_t first_nonfb_vardecltype(symbol_c *symbol, symbol_c *scope) {
+ if (NULL == symbol) ERROR;
+ if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+
+ symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+ if (NULL != singleton_->last_fb) {
+ scope = singleton_->last_fb->datatype;
+ symbol = singleton_->first_non_fb_identifier;
+ }
+
+ search_var_instance_decl_c search_var_instance_decl(scope);
+
+ return search_var_instance_decl.get_vartype(symbol);
}
@@ -380,7 +419,12 @@
/* B 1.4 - Variables */
/*********************/
void *visit(symbolic_variable_c *symbol) {
- contains_complex_type_res |= is_complex_type(symbol);
+ if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR;
+ if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+ first_non_fb_identifier = symbol;
+ return (void *)symbol;
+ }
+ last_fb = symbol;
return NULL;
}
@@ -390,20 +434,28 @@
// SYM_REF2(structured_variable_c, record_variable, field_selector)
void *visit(structured_variable_c *symbol) {
- symbol->record_variable->accept(*this);
- /* do not set the contains_complex_type_res to TRUE if this structured_variable_c is accessing a FB instance! */
- if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
- contains_complex_type_res |= get_datatype_info_c::is_structure(symbol->datatype);
- return NULL;
+ symbol_c *res = (symbol_c *)symbol->record_variable->accept(*this);
+ if (NULL != res) return res;
+
+ if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR;
+ if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+ first_non_fb_identifier = symbol->field_selector;
+ return (void *)symbol;
+ }
+
+ last_fb = symbol;
+ return NULL;
}
/* subscripted_variable '[' subscript_list ']' */
//SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
void *visit(array_variable_c *symbol) {
- contains_complex_type_res |= true;
- return NULL;
- }
-
+ void *res = symbol->subscripted_variable->accept(*this);
+ if (NULL != res) return res;
+ return (void *)symbol;
+ }
+
+
};
analyse_variable_c *analyse_variable_c::singleton_ = NULL;
--- a/stage4/generate_c/generate_c_st.cc Sun Dec 22 09:50:02 2013 +0000
+++ b/stage4/generate_c/generate_c_st.cc Mon Jan 06 12:25:21 2014 +0000
@@ -76,10 +76,11 @@
* so we do not create an object instance when handling
* a function declaration.
*/
- search_fb_instance_decl_c *search_fb_instance_decl;
-
+ search_fb_instance_decl_c *search_fb_instance_decl;
search_varfb_instance_type_c *search_varfb_instance_type;
search_var_instance_decl_c *search_var_instance_decl;
+
+ symbol_c *scope_;
symbol_c* current_array_type;
symbol_c* current_param_type;
@@ -98,6 +99,7 @@
search_fb_instance_decl = new search_fb_instance_decl_c (scope);
search_varfb_instance_type = new search_varfb_instance_type_c(scope);
search_var_instance_decl = new search_var_instance_decl_c (scope);
+ scope_ = scope;
this->set_variable_prefix(variable_prefix);
current_array_type = NULL;
@@ -128,7 +130,7 @@
void *print_getter(symbol_c *symbol) {
- unsigned int vartype = search_var_instance_decl->get_vartype(symbol);
+ unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol, scope_);
if (wanted_variablegeneration == fparam_output_vg) {
if (vartype == search_var_instance_decl_c::external_vt) {
if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR;
@@ -178,7 +180,7 @@
bool type_is_complex = false;
if (fb_symbol == NULL) {
- unsigned int vartype = search_var_instance_decl->get_vartype(symbol);
+ unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol, scope_);
type_is_complex = analyse_variable_c::contains_complex_type(symbol);
if (vartype == search_var_instance_decl_c::external_vt) {
if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR;