# HG changeset patch # User mjsousa # Date 1396964131 -3600 # Node ID 5f380b99e95e1660a6fc8817aa336b1eef25b117 # Parent 4893e6b11b2566c75585a1d0a53daf98326af981 Correctly handle structured variables that include FB and external FBs (example: FB1.FB2.extFB3.FB4.extFB5.extFB6.structvar.field1 := 42;) (this commit fixes only ST code. TODO: IL and SFC) diff -r 4893e6b11b25 -r 5f380b99e95e absyntax/absyntax.cc --- a/absyntax/absyntax.cc Fri Apr 04 16:21:55 2014 +0100 +++ b/absyntax/absyntax.cc Tue Apr 08 14:35:31 2014 +0100 @@ -57,6 +57,7 @@ this->last_column = last_column; this->last_order = last_order; this->datatype = NULL; + this->scope = NULL; this->const_value._real64.status = cs_undefined; this->const_value._int64.status = cs_undefined; this->const_value._uint64.status = cs_undefined; diff -r 4893e6b11b25 -r 5f380b99e95e absyntax/absyntax.hh --- a/absyntax/absyntax.hh Fri Apr 04 16:21:55 2014 +0100 +++ b/absyntax/absyntax.hh Tue Apr 08 14:35:31 2014 +0100 @@ -131,6 +131,10 @@ * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...) */ symbol_c *datatype; + /* The POU in which the symbolic variable (or structured variable, or array variable, or located variable, - any more?) + * was declared. This will point to a Configuration, Resource, Program, FB, or Function. + */ + symbol_c *scope; /*** constant folding ***/ /* During stage 3 (semantic analysis/checking) we will be doing constant folding. diff -r 4893e6b11b25 -r 5f380b99e95e absyntax_utils/get_var_name.cc --- a/absyntax_utils/get_var_name.cc Fri Apr 04 16:21:55 2014 +0100 +++ b/absyntax_utils/get_var_name.cc Tue Apr 08 14:35:31 2014 +0100 @@ -35,26 +35,6 @@ * appear in the variable declaration. */ -/* For ex.: - * VAR - * A : int; - * B : ARRAY [1..9] of int; - * C : some_struct_t; - * END_VAR - * - * A := 56; - * B[8] := 99; - * C.e := 77; - * - * Calling this visitor class with symbolic_variable_c instance referencing 'A' in - * the line 'A := 56', will return the string "A". - * - * Calling this visitor class with array_variable_c instance referencing 'B[8]' in - * the line 'B[8] := 99', will return the string "B". - * - * Calling this visitor class with array_variable_c instance referencing 'C.e' in - * the line 'C.e := 77', will return the string "C". - */ #include "absyntax_utils.hh" @@ -68,6 +48,26 @@ +/* For ex.: + * VAR + * A : int; + * B : ARRAY [1..9] of int; + * C : some_struct_t; + * END_VAR + * + * A := 56; + * B[8] := 99; + * C.e := 77; + * + * Calling this method with symbolic_variable_c instance referencing 'A' in + * the line 'A := 56', will return the string "A". + * + * Calling this method with array_variable_c instance referencing 'B[8]' in + * the line 'B[8] := 99', will return the string "B". + * + * Calling this method with array_variable_c instance referencing 'C.e' in + * the line 'C.e := 77', will return the string "C". + */ token_c *get_var_name_c::get_name(symbol_c *symbol) { if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); @@ -77,6 +77,24 @@ } +/* Return the last field of a structured variable... + * + * A := 56; --> returns A + * B[8] := 99; --> returns B + * C.e := 77; --> returns e !!! + */ +symbol_c *get_var_name_c::get_last_field(symbol_c *symbol) { + if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); + if (NULL == singleton_instance_) ERROR; + + singleton_instance_->last_field = NULL; + symbol_c *res = (symbol_c*)(symbol->accept(*singleton_instance_)); + return (NULL != singleton_instance_->last_field)? singleton_instance_->last_field : res; +} + + + + /*************************/ /* B.1 - Common elements */ /*************************/ @@ -114,7 +132,11 @@ * this into account! */ // SYM_REF2(structured_variable_c, record_variable, field_selector) -void *get_var_name_c::visit(structured_variable_c *symbol) {return symbol->record_variable->accept(*this);} +void *get_var_name_c::visit(structured_variable_c *symbol) { + void *res = symbol->record_variable->accept(*this); + last_field = symbol->field_selector; + return res; +} diff -r 4893e6b11b25 -r 5f380b99e95e absyntax_utils/get_var_name.hh --- a/absyntax_utils/get_var_name.hh Fri Apr 04 16:21:55 2014 +0100 +++ b/absyntax_utils/get_var_name.hh Tue Apr 08 14:35:31 2014 +0100 @@ -63,10 +63,12 @@ public: get_var_name_c(void) {}; ~get_var_name_c(void) {}; - static token_c *get_name(symbol_c *symbol); - + static token_c *get_name(symbol_c *symbol); + static symbol_c *get_last_field(symbol_c *symbol); + private: static get_var_name_c *singleton_instance_; + symbol_c *last_field; private: /*************************/ diff -r 4893e6b11b25 -r 5f380b99e95e stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Fri Apr 04 16:21:55 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Tue Apr 08 14:35:31 2014 +0100 @@ -70,6 +70,7 @@ fake_prev_il_instruction = NULL; current_il_instruction = NULL; il_operand = NULL; + current_scope = NULL; } narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) { @@ -651,6 +652,7 @@ /*********************/ // SYM_REF1(symbolic_variable_c, var_name) void *narrow_candidate_datatypes_c::visit(symbolic_variable_c *symbol) { + symbol->scope = current_scope; // the scope in which this variable was declared! symbol->var_name->datatype = symbol->datatype; return NULL; } @@ -674,6 +676,8 @@ if (symbol->subscripted_variable->candidate_datatypes.size() == 1) symbol->subscripted_variable->datatype = symbol->subscripted_variable->candidate_datatypes[0]; // set the datatype + // the scope in which this variable was declared! It will be the same as the subscripted variable (a symbolic_variable_ !) + symbol->scope = symbol->subscripted_variable->scope; return NULL; } @@ -708,6 +712,7 @@ if (symbol->record_variable->candidate_datatypes.size() == 1) symbol->record_variable->datatype = symbol->record_variable->candidate_datatypes[0]; // set the datatype + symbol->scope = symbol->record_variable->datatype; // the scope in which this variable was declared! return NULL; } @@ -764,12 +769,14 @@ symbol->type_name->datatype = search_base_type_c::get_basetype_decl(symbol->type_name); symbol->datatype = symbol->type_name->datatype; + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations_list->accept(*this); if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); symbol->function_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; + current_scope = NULL; return NULL; } @@ -777,13 +784,15 @@ /* B 1.5.2 Function blocks */ /***************************/ void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) { + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); symbol->fblock_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; - + current_scope = NULL; + // A FB declaration can also be used as a Datatype! We now do the narrow algorithm considering it as such! if (symbol->candidate_datatypes.size() == 1) symbol->datatype = symbol->candidate_datatypes[0]; @@ -794,12 +803,14 @@ /* B 1.5.3 Programs */ /********************/ void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) { + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); symbol->function_block_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; + current_scope = NULL; return NULL; } diff -r 4893e6b11b25 -r 5f380b99e95e stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Fri Apr 04 16:21:55 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Tue Apr 08 14:35:31 2014 +0100 @@ -65,6 +65,7 @@ private: search_varfb_instance_type_c *search_varfb_instance_type; + symbol_c *current_scope; symbol_c *il_operand; il_instruction_c *fake_prev_il_instruction; il_instruction_c *current_il_instruction; diff -r 4893e6b11b25 -r 5f380b99e95e stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Fri Apr 04 16:21:55 2014 +0100 +++ b/stage4/generate_c/generate_c_st.cc Tue Apr 08 14:35:31 2014 +0100 @@ -179,9 +179,11 @@ if (fb_symbol == NULL) { unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol, scope_); + symbol_c *first_nonfb = analyse_variable_c::find_first_nonfb(symbol); + if (first_nonfb == NULL) ERROR; if (vartype == search_var_instance_decl_c::external_vt) { - if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; - if ( get_datatype_info_c::is_function_block(symbol->datatype)) + if (!get_datatype_info_c::is_type_valid (first_nonfb->datatype)) ERROR; + if ( get_datatype_info_c::is_function_block(first_nonfb->datatype)) // handle situation where we are copying a complete fb -> fb1.fb2.fb3 := fb4 (and fb3 is external!) s4o.print(SET_EXTERNAL_FB); else s4o.print(SET_EXTERNAL); @@ -329,18 +331,22 @@ // SYM_REF2(structured_variable_c, record_variable, field_selector) void *visit(structured_variable_c *symbol) { TRACE("structured_variable_c"); - bool type_is_complex = analyse_variable_c::is_complex_type(symbol->record_variable); switch (wanted_variablegeneration) { case complextype_base_vg: symbol->record_variable->accept(*this); - if (!type_is_complex) { - s4o.print("."); + if ( get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) { + if (NULL == symbol->record_variable->scope) ERROR; + search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope); + if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable))) + s4o.print("->"); + else + s4o.print("."); symbol->field_selector->accept(*this); } break; case complextype_suffix_vg: symbol->record_variable->accept(*this); - if (type_is_complex) { + if (!get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) { // if the record variable is not a FB, then it will certainly be a structure! s4o.print("."); symbol->field_selector->accept(*this); }