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)
authormjsousa
Tue, 08 Apr 2014 14:35:31 +0100
changeset 889 5f380b99e95e
parent 888 4893e6b11b25
child 890 499486ece119
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)
absyntax/absyntax.cc
absyntax/absyntax.hh
absyntax_utils/get_var_name.cc
absyntax_utils/get_var_name.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
stage4/generate_c/generate_c_st.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;
--- 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);
       }