Fix bug: Add support for de-referencing pointers to struct (struct_ptr^.elem1) when used inside FB.
authormjsousa
Sun, 19 Oct 2014 08:36:49 +0100
changeset 936 0f7bcc160568
parent 935 be4373d07201
child 937 887e7d90445a
Fix bug: Add support for de-referencing pointers to struct (struct_ptr^.elem1) when used inside FB.
Note that multiple de-referencing of structs (struct_ptr_ptr^^.elem) is not supported inside FB code (this would need BIG changes to the compiler!)
absyntax/absyntax.cc
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax_utils/search_varfb_instance_type.cc
absyntax_utils/search_varfb_instance_type.hh
stage1_2/iec_bison.yy
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
stage3/print_datatypes_error.cc
stage3/print_datatypes_error.hh
stage4/generate_c/generate_c_base.cc
stage4/generate_c/generate_c_st.cc
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/absyntax/absyntax.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -56,6 +56,7 @@
   this->last_line    = last_line;
   this->last_column  = last_column;
   this->last_order   = last_order;
+  this->parent       = NULL;
   this->datatype     = NULL;
   this->scope        = NULL;
   this->const_value._real64.status   = cs_undefined;
@@ -110,6 +111,12 @@
   elements[n++] = elem;
  
   if (NULL == elem) return;
+  /* Sometimes add_element() is called in stage3 or stage4 to temporarily add an AST symbol to the list.
+   * Since this symbol already belongs in some other place in the aST, it will have the 'parent' pointer set, 
+   * and so we must not overwrite it. We only set the 'parent' pointer on new symbols that have the 'parent'
+   * pointer still set to NULL.
+   */
+  if (NULL == elem->parent) elem->parent = this;  
 
   /* adjust the location parameters, taking into account the new element. */
   if (NULL == first_file) {
@@ -199,6 +206,7 @@
                            int ll, int lc, const char *lfile, long int lorder)			\
 			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
   this->ref1 = ref1;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
@@ -211,6 +219,8 @@
 			  :symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {		\
   this->ref1 = ref1;										\
   this->ref2 = ref2;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
+  if  (NULL != ref2)   ref2->parent = this;										\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
@@ -225,6 +235,9 @@
   this->ref1 = ref1;										\
   this->ref2 = ref2;										\
   this->ref3 = ref3;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
+  if  (NULL != ref2)   ref2->parent = this;							\
+  if  (NULL != ref3)   ref3->parent = this;							\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
@@ -241,6 +254,10 @@
   this->ref2 = ref2;										\
   this->ref3 = ref3;										\
   this->ref4 = ref4;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
+  if  (NULL != ref2)   ref2->parent = this;							\
+  if  (NULL != ref3)   ref3->parent = this;							\
+  if  (NULL != ref4)   ref4->parent = this;							\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
@@ -259,6 +276,11 @@
   this->ref3 = ref3;										\
   this->ref4 = ref4;										\
   this->ref5 = ref5;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
+  if  (NULL != ref2)   ref2->parent = this;							\
+  if  (NULL != ref3)   ref3->parent = this;							\
+  if  (NULL != ref4)   ref4->parent = this;							\
+  if  (NULL != ref5)   ref5->parent = this;							\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
@@ -280,6 +302,12 @@
   this->ref4 = ref4;										\
   this->ref5 = ref5;										\
   this->ref6 = ref6;										\
+  if  (NULL != ref1)   ref1->parent = this;							\
+  if  (NULL != ref2)   ref2->parent = this;							\
+  if  (NULL != ref3)   ref3->parent = this;							\
+  if  (NULL != ref4)   ref4->parent = this;							\
+  if  (NULL != ref5)   ref5->parent = this;							\
+  if  (NULL != ref6)   ref6->parent = this;							\
 }												\
 void *class_name_c::accept(visitor_c &visitor) {return visitor.visit(this);}
 
--- a/absyntax/absyntax.def	Sun Sep 28 17:48:42 2014 +0100
+++ b/absyntax/absyntax.def	Sun Oct 19 08:36:49 2014 +0100
@@ -1139,8 +1139,9 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
-SYM_REF1(  ref_expression_c, exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
-SYM_REF1(deref_expression_c, exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Dereferences an address!        */
+SYM_REF1(  ref_expression_c, exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard.  REF() -> returns address of the varible! */
+SYM_REF1(deref_expression_c, exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. DREF() -> dereferences an address!        */
+SYM_REF1(deref_operator_c,   exp)  /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard.    ^   -> dereferences an address!        */
 SYM_REF2( or_expression_c, l_exp, r_exp)
 SYM_REF2(xor_expression_c, l_exp, r_exp)
 SYM_REF2(and_expression_c, l_exp, r_exp)
--- a/absyntax/absyntax.hh	Sun Sep 28 17:48:42 2014 +0100
+++ b/absyntax/absyntax.hh	Sun Oct 19 08:36:49 2014 +0100
@@ -109,6 +109,9 @@
     /*
      * Annotations produced during stage 1_2
      */    
+    /* Points to the parent symbol in the AST, i.e. the symbol in the AST that will contain the current symbol */
+    symbol_c *parent; 
+    
     /* Line number for the purposes of error checking.  */
     int first_line;
     int first_column;
--- a/absyntax_utils/search_varfb_instance_type.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/absyntax_utils/search_varfb_instance_type.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -405,3 +405,61 @@
   initial_step_c initial_step(NULL, NULL);
   return initial_step.accept(*this);
 }
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+/* SYM_REF1(deref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *search_varfb_instance_type_c::visit(deref_expression_c  *symbol) {
+  symbol->exp->accept(*this);
+  symbol_c *basetype_decl = current_basetype_decl;
+  this->init(); /* set all current_*** pointers to NULL ! */
+  
+  /* Check whether the expression if a REF_TO datatype, and if so, set the new datatype to the datatype it references! */
+    /* Determine whether the datatype is a ref_spec_c, as this is the class used as the    */
+    /* canonical/base datatype of REF_TO types (see search_base_type_c ...)                */   
+  ref_spec_c * ref_spec = dynamic_cast<ref_spec_c *>(basetype_decl);
+  if (NULL != ref_spec) {
+    current_basetype_decl = search_base_type_c::get_basetype_decl(ref_spec->type_name);
+    current_basetype_id   = search_base_type_c::get_basetype_id  (ref_spec->type_name);
+  }
+  
+/* ########### WARNING ########################################################## */
+/* The following two lines DO NOT belong here. It is just a temporary measure until I get the chance 
+ * to clean this up, and move it to fill/narrow candidate datatypes in stage 3 
+ */
+  symbol->datatype = current_basetype_decl;
+  symbol->exp->datatype = ref_spec;
+  
+  return NULL;
+}
+
+  
+/* SYM_REF1(deref_operator_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *search_varfb_instance_type_c::visit(deref_operator_c  *symbol) {
+  symbol->exp->accept(*this);
+  symbol_c *basetype_decl = current_basetype_decl;
+  this->init(); /* set all current_*** pointers to NULL ! */
+  
+  /* Check whether the expression if a REF_TO datatype, and if so, set the new datatype to the datatype it references! */
+    /* Determine whether the datatype is a ref_spec_c, as this is the class used as the    */
+    /* canonical/base datatype of REF_TO types (see search_base_type_c ...)                */   
+  ref_spec_c * ref_spec = dynamic_cast<ref_spec_c *>(basetype_decl);
+  if (NULL != ref_spec) {
+    current_basetype_decl = search_base_type_c::get_basetype_decl(ref_spec->type_name);
+    current_basetype_id   = search_base_type_c::get_basetype_id  (ref_spec->type_name);
+  }
+  
+/* ########### WARNING ########################################################## */
+/* The following two lines DO NOT belong here. It is just a temporary measure until I get the chance 
+ * to clean this up, and move it to fill/narrow candidate datatypes in stage 3 
+ */
+  symbol->datatype = current_basetype_decl;
+  symbol->exp->datatype = ref_spec;
+  
+  return NULL;
+}
--- a/absyntax_utils/search_varfb_instance_type.hh	Sun Sep 28 17:48:42 2014 +0100
+++ b/absyntax_utils/search_varfb_instance_type.hh	Sun Oct 19 08:36:49 2014 +0100
@@ -197,7 +197,17 @@
     /* STEP step_name ':' action_association_list END_STEP */
     // SYM_REF2(step_c, step_name, action_association_list)
     void *visit(step_c *symbol);
-
+    
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    /* SYM_REF1(deref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+    void *visit(deref_operator_c    *symbol);
+    void *visit(deref_expression_c  *symbol);
+    
 }; // search_varfb_instance_type_c
 
 
--- a/stage1_2/iec_bison.yy	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage1_2/iec_bison.yy	Sun Oct 19 08:36:49 2014 +0100
@@ -3406,7 +3406,7 @@
 */
 | symbolic_variable '^'     
 	/* Dereferencing operator defined in IEC 61131-3 v3. However, implemented here differently then how it is defined in the standard! See following note for explanation! */
-	{$$ = new deref_expression_c($1, locloc(@$));
+	{$$ = new deref_operator_c($1, locloc(@$));
 	 if (!allow_ref_dereferencing) {
 	   print_err_msg(locf(@$), locl(@$), "Derefencing REF_TO datatypes with '^' is not allowed (use -r option to activate support for this IEC 61131-3 v3 feature)."); 
 	   yynerrs++;
--- a/stage3/fill_candidate_datatypes.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -1906,6 +1906,23 @@
 }
 
 
+/* SYM_REF1(deref_operator_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *fill_candidate_datatypes_c::visit(deref_operator_c  *symbol) {
+  symbol->exp->accept(*this);
+
+  for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+    /* Determine whether the datatype is a ref_spec_c, as this is the class used as the    */
+    /* canonical/base datatype of REF_TO types (see search_base_type_c ...)                */ 
+    ref_spec_c *ref_spec = dynamic_cast<ref_spec_c *>(symbol->exp->candidate_datatypes[i]);
+    
+    if (NULL != ref_spec)
+      add_datatype_to_candidate_list(symbol, search_base_type_c::get_basetype_decl(ref_spec->type_name));
+  }
+  
+  return NULL;
+}
+
+
 /* SYM_REF1(ref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
 void *fill_candidate_datatypes_c::visit(  ref_expression_c  *symbol) {
   /* We must first determine the datatype of the expression passed to the REF() operator, with no ambiguities! 
--- a/stage3/fill_candidate_datatypes.hh	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Sun Oct 19 08:36:49 2014 +0100
@@ -337,6 +337,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(   deref_operator_c   *symbol);
     void *visit(   deref_expression_c *symbol);
     void *visit(     ref_expression_c *symbol);
     void *visit(      or_expression_c *symbol);
--- a/stage3/narrow_candidate_datatypes.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -1395,6 +1395,23 @@
 }
 
 
+/* SYM_REF1(deref_operator_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *narrow_candidate_datatypes_c::visit(deref_operator_c  *symbol) {
+  for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+    /* Determine whether the datatype is a ref_spec_c, as this is the class used as the    */
+    /* canonical/base datatype of REF_TO types (see search_base_type_c ...)                */ 
+    ref_spec_c *ref_spec = dynamic_cast<ref_spec_c *>(symbol->exp->candidate_datatypes[i]);
+    
+    if ((NULL != ref_spec) && get_datatype_info_c::is_type_equal(ref_spec->type_name, symbol->datatype))
+      /* if it points to the required datatype for symbol, then that is the required datatype for symbol->exp */
+      symbol->exp->datatype = ref_spec;
+  }
+  
+  symbol->exp->accept(*this);
+  return NULL;
+}
+
+
 /* SYM_REF1(ref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
 void *narrow_candidate_datatypes_c::visit(  ref_expression_c  *symbol) {
   if (symbol->exp->candidate_datatypes.size() > 0) {
--- a/stage3/narrow_candidate_datatypes.hh	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.hh	Sun Oct 19 08:36:49 2014 +0100
@@ -308,6 +308,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(   deref_operator_c   *symbol);
     void *visit(   deref_expression_c *symbol);
     void *visit(     ref_expression_c *symbol);
     void *visit(      or_expression_c *symbol);
--- a/stage3/print_datatypes_error.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/print_datatypes_error.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -1044,6 +1044,15 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+/* SYM_REF1(deref_operator_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *print_datatypes_error_c::visit(deref_operator_c  *symbol) {
+	symbol->exp->accept(*this);
+	/* we should really check whether the expression is merely a variable. For now, leave it for the future! */
+	if ((symbol->candidate_datatypes.size() == 0) && (symbol->exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(0, symbol, symbol, "^ operator must be preceded by a value of type REF_TO.");
+	return NULL;
+}
+
 /* SYM_REF1(deref_expression_c, exp)  --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
 void *print_datatypes_error_c::visit(deref_expression_c  *symbol) {
 	symbol->exp->accept(*this);
--- a/stage3/print_datatypes_error.hh	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage3/print_datatypes_error.hh	Sun Oct 19 08:36:49 2014 +0100
@@ -288,6 +288,7 @@
     /***********************/
     /* B 3.1 - Expressions */
     /***********************/
+    void *visit(   deref_operator_c   *symbol);
     void *visit(   deref_expression_c *symbol);
     void *visit(     ref_expression_c *symbol);
     void *visit(      or_expression_c *symbol);
--- a/stage4/generate_c/generate_c_base.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage4/generate_c/generate_c_base.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -747,9 +747,10 @@
  *           this into account!
  */
 // SYM_REF2(structured_variable_c, record_variable, field_selector)
+// TODO:  It seems to me this code no longer gets to execute, since the function is overloaded in generate_c_st_c and generate_c_il_c
+//        I will have to check this later, and delete this code if the above is really true!
 void *visit(structured_variable_c *symbol) {
   TRACE("structured_variable_c");
-
   symbol->record_variable->accept(*this);
   s4o.print(".");
   symbol->field_selector->accept(*this);
--- a/stage4/generate_c/generate_c_st.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -348,8 +348,10 @@
           || get_datatype_info_c::is_sfc_step      (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("->");
+        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("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
+        else if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)
+          s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
         else  
           s4o.print(".");
         symbol->field_selector->accept(*this);
@@ -360,12 +362,22 @@
       // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:'
       if (!(   get_datatype_info_c::is_function_block(symbol->record_variable->datatype)     // if the record variable is not a FB... 
             || get_datatype_info_c::is_sfc_step      (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure!
-        s4o.print(".");
+        if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)
+          s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */
+        else
+          s4o.print(".");
         symbol->field_selector->accept(*this);
       }
       break;
     default:
       if (this->is_variable_prefix_null()) {
+        /* We are writing code for a FUNCTION. In this case, deref_operator_c are not transformed into the C pointer derefence syntax '->' (e.g. ptr->elem).
+         * We use instead the '*' syntax (e.g. (*ptr).elem)
+         * While in FB the '->' is generated by this structured_variable_c visitor, in Functions the '*' syntax is generated by the deref_operator_c visitor
+         * This is why here we do NOT have --> {if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL)  ..}
+	 *  
+	 * please read the comment in visit(deref_operator_c *) for more information!
+         */
         symbol->record_variable->accept(*this);
         s4o.print(".");
         symbol->field_selector->accept(*this);
@@ -463,6 +475,45 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
+void *visit(deref_operator_c *symbol) {
+  /* When producing C code for FUNCTION_BLOCKS, we use the '*' syntax (e.g. (*ptr).elem)
+   * When producing C code for a FUNCTION_BLOCK, the deref_operator_c are transformed in two ways, depending on where they occur.
+   *    - deref_operator between a struct and its elem (e.g. struct_ref^.elem1) 
+   *        are transformed into C using the C pointer derefence syntax '->' (e.g. struct_ref->elem1).
+   *        (In this case, '->' is generated by this structured_variable_c visitor)
+   *    - deref_operator at the end of a struct variable (e.g. struct.elem_ptr^)
+   *        are transformed using the '*' syntax for C pointer dereferencing (e.g. *(struct.elem_ptr) )
+   * 
+   *   NOTE: Ideally, we should always use the '*' C pointer dereferencing syntax. However, due to the
+   *         was the GET_VAR and SET_VAR are transformed into C, this does not work for '^' between a struct and its 
+   *         element (e.g. struct_ref^.elem), which is whey in this case only we use the '->' syntax.
+   *   NOTE: The use of the -> syntax means that pointers to pointers are not supported betweem a struct and its elem
+   *         (e.g. . struct_ref_ref^^.elem) as this would be transformed into the invalid C code struct_ref_ref->->elem.
+   *         This is why we add a test for this case, and bug out with an error if we encounter it!!
+   */
+  if (this->is_variable_prefix_null()) {  
+    /* For code in FUNCTIONs */
+    s4o.print("(*");  
+    symbol->exp->accept(*this);    
+    s4o.print(")");  
+  } else {
+    /* For code in FBs, and PROGRAMS... */
+    if (NULL == dynamic_cast<structured_variable_c *>(symbol->parent)) {
+      s4o.print("(*");  
+      symbol->exp->accept(*this);    
+      s4o.print(")");  
+    } else {
+      /* We are in a structured variable - the structured_variable_c itself will already have printed out the '->' !! */ 
+      if (NULL != dynamic_cast<deref_operator_c *>(symbol->exp))
+        STAGE4_ERROR(symbol, symbol->exp, "The use of consecutive derefencing operators between a struct and its elem (ex: struct_ref_ref^^.elem) is currently not supported for code inside a Function_Block.");
+      symbol->exp->accept(*this);
+    }
+  }
+
+  return NULL;
+}
+
+
 void *visit(deref_expression_c *symbol) {
   s4o.print("(");  
   if (this->is_variable_prefix_null()) {  
@@ -472,7 +523,6 @@
     s4o.print("");  
   } else {
     /* For code in FBs, and PROGRAMS... */
-    s4o.print("(");  
     unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_);
     if (vartype == search_var_instance_decl_c::external_vt) {
       if (!get_datatype_info_c::is_type_valid    (symbol->exp->datatype)) ERROR;
@@ -496,8 +546,6 @@
     symbol->exp->accept(*this);
     s4o.print(")");
     wanted_variablegeneration = old_wanted_variablegeneration;
-    
-    s4o.print(")");  
   }
   s4o.print(")");  
 
--- a/stage4/generate_iec/generate_iec.cc	Sun Sep 28 17:48:42 2014 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Sun Oct 19 08:36:49 2014 +0100
@@ -1917,8 +1917,9 @@
 /***********************/
 /* B 3.1 - Expressions */
 /***********************/
-void *visit(   ref_expression_c *symbol) {return  s4o.print( "REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
-void *visit( deref_expression_c *symbol) {return  s4o.print("DREF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */
+void *visit( deref_operator_c   *symbol) {return symbol->exp->accept(*this); s4o.print("^");}                      /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. ^      -> dereferences an address into a variable! */
+void *visit( deref_expression_c *symbol) {return  s4o.print("DREF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. DREF() -> dereferences an address into a variable! */
+void *visit(   ref_expression_c *symbol) {return  s4o.print( "REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. REF()  -> returns address of the varible! */
 void *visit(    or_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " OR ");}
 void *visit(   xor_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " XOR ");}
 void *visit(   and_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " AND ");}