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)
--- 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;
--- 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.
--- 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;
+}
--- 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:
/*************************/
--- 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;
}
--- 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;
--- 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);
}