Add support for REF_TO derived datatypes (along with datatype verification)
authormjsousa
Sun, 13 Jul 2014 12:26:58 +0100
changeset 909 8b2a31dea131
parent 908 9e8e1ba5ca46
child 910 a0518971127d
Add support for REF_TO derived datatypes (along with datatype verification)
absyntax/absyntax.def
absyntax_utils/absyntax_utils.cc
absyntax_utils/get_datatype_info.cc
absyntax_utils/get_datatype_info.hh
absyntax_utils/search_base_type.cc
absyntax_utils/search_base_type.hh
absyntax_utils/spec_init_separator.cc
absyntax_utils/spec_init_separator.hh
lib/C/iec_types_all.h
stage1_2/iec_bison.yy
stage1_2/iec_flex.ll
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
stage4/generate_c/generate_c_st.cc
stage4/generate_c/generate_c_typedecl.cc
stage4/generate_iec/generate_iec.cc
--- a/absyntax/absyntax.def	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax/absyntax.def	Sun Jul 13 12:26:58 2014 +0100
@@ -335,7 +335,7 @@
 /*  identifier ':' array_spec_init */
 SYM_REF2(array_type_declaration_c, identifier, array_spec_init)
 
-/* array_specification [ASSIGN array_initialization} */
+/* array_specification [ASSIGN array_initialization] */
 /* array_initialization may be NULL ! */
 SYM_REF2(array_spec_init_c, array_specification, array_initialization)
 
@@ -481,14 +481,14 @@
  * Ref_Deref      : 'DREF' '(' Ref_Name ')' ;
  */
 
-/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+/* REF_TO (non_generic_type_name | function_block_type_name) */
 SYM_REF1(ref_spec_c, type_name)
 
-/* For the moment, we do not support initialising reference data types */
-/* ref_spec_init: ref_spec; */ 
-/* SYM_REF0(ref_spec_init_c) */
-
-/* ref_type_decl: identifier ':' ref_spec_init */
+/* ref_spec [ ASSIGN ref_initialization ]; */
+/* NOTE: ref_initialization may be NULL!!  */
+SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+
+/* identifier ':' ref_spec_init */
 SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
 
 
--- a/absyntax_utils/absyntax_utils.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/absyntax_utils.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -183,16 +183,10 @@
   /********************************/
 
   /*  subrange_type_name ':' subrange_spec_init */
-  void *visit(subrange_type_declaration_c *symbol) {
-    TRACE("subrange_type_declaration_c");  
-    type_symtable.insert(symbol->subrange_type_name, symbol->subrange_spec_init);
-    return NULL;
-  }
-  
+  void *visit(subrange_type_declaration_c *symbol) {type_symtable.insert(symbol->subrange_type_name, symbol->subrange_spec_init); return NULL;}
 
   /*  enumerated_type_name ':' enumerated_spec_init */
   void *visit(enumerated_type_declaration_c *symbol) {
-    TRACE("enumerated_type_declaration_c");
     type_symtable.insert(symbol->enumerated_type_name, symbol);
     current_enumerated_type = symbol->enumerated_type_name;
     symbol->enumerated_spec_init->accept(*this);
@@ -201,45 +195,17 @@
   }
 
   /* enumerated_specification ASSIGN enumerated_value */
-  void *visit(enumerated_spec_init_c *symbol) {
-    return symbol->enumerated_specification->accept(*this);
-  }
-
-
+  void *visit(enumerated_spec_init_c *symbol) {return symbol->enumerated_specification->accept(*this);}
   /*  identifier ':' array_spec_init */
-  void *visit(array_type_declaration_c *symbol) {
-    TRACE("array_type_declaration_c");
-    type_symtable.insert(symbol->identifier, symbol->array_spec_init);
-    return NULL;
-  }
-
-
+  void *visit(array_type_declaration_c *symbol) {type_symtable.insert(symbol->identifier, symbol->array_spec_init); return NULL;}
   /*  simple_type_name ':' simple_spec_init */
-  void *visit(simple_type_declaration_c *symbol) {
-    TRACE("simple_type_declaration_c");
-    type_symtable.insert(symbol->simple_type_name, symbol->simple_spec_init);
-    return NULL;
-  }
-
-
+  void *visit(simple_type_declaration_c *symbol) {type_symtable.insert(symbol->simple_type_name, symbol->simple_spec_init); return NULL;}
   /*  structure_type_name ':' structure_specification */
-  void *visit(structure_type_declaration_c *symbol) {
-    TRACE("structure_type_declaration_c");
-    type_symtable.insert(symbol->structure_type_name, symbol->structure_specification);
-    return NULL;
-  }
-  
-  
+  void *visit(structure_type_declaration_c *symbol) {type_symtable.insert(symbol->structure_type_name, symbol->structure_specification); return NULL;}
   /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
-  // SYM_REF4(string_type_declaration_c,	string_type_name,
-  //    					elementary_string_type_name,
-  //    					string_type_declaration_size,
-  //    					string_type_declaration_init) /* may be == NULL! */
-  void *visit(string_type_declaration_c *symbol)	{
-    TRACE("string_type_declaration_c");
-    type_symtable.insert(symbol->string_type_name, symbol);
-    return NULL;
-}
+  void *visit(string_type_declaration_c *symbol) {type_symtable.insert(symbol->string_type_name, symbol); return NULL;}
+  /* identifier ':' ref_spec_init */
+  void *visit(ref_type_decl_c *symbol) {type_symtable.insert(symbol->ref_type_name, symbol); return NULL;}
 
   /*********************/
   /* B 1.4 - Variables */
--- a/absyntax_utils/get_datatype_info.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/get_datatype_info.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -79,23 +79,25 @@
     /* B 1.3.3 - Derived data types */
     /********************************/
     /*  simple_type_name ':' simple_spec_init */
-    void *visit(simple_type_declaration_c *symbol)      {return symbol->simple_type_name;}
+    void *visit(simple_type_declaration_c     *symbol)  {return symbol->simple_type_name;}
     /*  subrange_type_name ':' subrange_spec_init */
-    void *visit(subrange_type_declaration_c *symbol)    {return symbol->subrange_type_name;}
+    void *visit(subrange_type_declaration_c   *symbol)  {return symbol->subrange_type_name;}
     /*  enumerated_type_name ':' enumerated_spec_init */
     void *visit(enumerated_type_declaration_c *symbol)  {return symbol->enumerated_type_name;}
     /*  identifier ':' array_spec_init */
-    void *visit(array_type_declaration_c *symbol)       {return symbol->identifier;}
+    void *visit(array_type_declaration_c      *symbol)  {return symbol->identifier;}
     /*  structure_type_name ':' structure_specification */
-    void *visit(structure_type_declaration_c *symbol)   {return symbol->structure_type_name;}
+    void *visit(structure_type_declaration_c  *symbol)  {return symbol->structure_type_name;}
     /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
-    void *visit(string_type_declaration_c *symbol)      {return symbol->string_type_name;}
+    void *visit(string_type_declaration_c     *symbol)  {return symbol->string_type_name;}
+    /* ref_type_decl: identifier ':' ref_spec_init */
+    void *visit(ref_type_decl_c               *symbol)  {return symbol->ref_type_name;}
     
     /*****************************/
     /* B 1.5.2 - Function Blocks */
     /*****************************/
     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
-    void *visit(function_block_declaration_c *symbol)      {return symbol->fblock_name;}
+    void *visit(function_block_declaration_c  *symbol)  {return symbol->fblock_name;}
 }; // get_datatype_id_c 
 
 get_datatype_id_c *get_datatype_id_c::singleton = NULL;
@@ -189,23 +191,25 @@
     /* B 1.3.3 - Derived data types */
     /********************************/
     /*  simple_type_name ':' simple_spec_init */
-    void *visit(simple_type_declaration_c *symbol)      {return symbol->simple_type_name->accept(*this);}
+    void *visit(simple_type_declaration_c     *symbol)  {return symbol->simple_type_name->accept(*this);}
     /*  subrange_type_name ':' subrange_spec_init */
-    void *visit(subrange_type_declaration_c *symbol)    {return symbol->subrange_type_name->accept(*this);}
+    void *visit(subrange_type_declaration_c   *symbol)  {return symbol->subrange_type_name->accept(*this);}
     /*  enumerated_type_name ':' enumerated_spec_init */
     void *visit(enumerated_type_declaration_c *symbol)  {return symbol->enumerated_type_name->accept(*this);}
     /*  identifier ':' array_spec_init */
-    void *visit(array_type_declaration_c *symbol)       {return symbol->identifier->accept(*this);}
+    void *visit(array_type_declaration_c      *symbol)  {return symbol->identifier->accept(*this);}
     /*  structure_type_name ':' structure_specification */
-    void *visit(structure_type_declaration_c *symbol)   {return symbol->structure_type_name->accept(*this);}
+    void *visit(structure_type_declaration_c  *symbol)  {return symbol->structure_type_name->accept(*this);}
     /*  string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
-    void *visit(string_type_declaration_c *symbol)      {return symbol->string_type_name->accept(*this);}
+    void *visit(string_type_declaration_c     *symbol)  {return symbol->string_type_name->accept(*this);}
+    /* ref_type_decl: identifier ':' ref_spec_init */
+    void *visit(ref_type_decl_c               *symbol)  {return symbol->ref_type_name->accept(*this);}
     
     /*****************************/
     /* B 1.5.2 - Function Blocks */
     /*****************************/
     /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
-    void *visit(function_block_declaration_c *symbol)      {return symbol->fblock_name->accept(*this);}    
+    void *visit(function_block_declaration_c  *symbol)  {return symbol->fblock_name->accept(*this);}    
 };
 
 get_datatype_id_str_c *get_datatype_id_str_c::singleton = NULL;
@@ -239,9 +243,15 @@
   if (typeid(* first_type) == typeid(invalid_type_name_c))           {return false;}
   if (typeid(*second_type) == typeid(invalid_type_name_c))           {return false;}
     
-  if ((get_datatype_info_c::is_ANY_ELEMENTARY(first_type)) &&
+  /* ANY_ELEMENTARY */
+  if ((is_ANY_ELEMENTARY(first_type)) &&
       (typeid(*first_type) == typeid(*second_type)))                 {return true;}
+
   /* ANY_DERIVED */
+  if (is_ref_to(first_type) && is_ref_to(second_type))
+      return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )),
+                           search_base_type_c::get_basetype_decl(get_ref_to(second_type)));
+
   return (first_type == second_type);
 }
 
@@ -258,6 +268,39 @@
 
 
 
+
+/* returns the datatype the REF_TO datatype references/points to... */ 
+symbol_c *get_datatype_info_c::get_ref_to(symbol_c *type_symbol) {
+  ref_type_decl_c *type1 = dynamic_cast<ref_type_decl_c *>(type_symbol);
+  if (NULL != type1) type_symbol = type1->ref_spec_init;
+
+  ref_spec_init_c *type2 = dynamic_cast<ref_spec_init_c *>(type_symbol);
+  if (NULL != type2) type_symbol = type2->ref_spec;
+
+  ref_spec_c      *type3 = dynamic_cast<ref_spec_c      *>(type_symbol);
+  if (NULL != type3) return type3->type_name;
+  
+  return NULL; /* this is not a ref datatype!! */
+}
+
+
+
+
+
+
+bool get_datatype_info_c::is_ref_to(symbol_c *type_symbol) {
+  symbol_c *type_decl = search_base_type_c::get_basetype_decl(type_symbol);
+  if (NULL == type_decl)                                                       {return false;}
+  
+  if (typeid(*type_decl) == typeid(ref_type_decl_c))                           {return true;}   /* identifier ':' ref_spec_init */
+  if (typeid(*type_decl) == typeid(ref_spec_init_c))                           {return true;}   /* ref_spec [ ASSIGN ref_initialization ]; */
+  if (typeid(*type_decl) == typeid(ref_spec_c))                                {return true;}   /* REF_TO (non_generic_type_name | function_block_type_name) */
+  return false;
+}
+
+
+
+
 bool get_datatype_info_c::is_sfc_initstep(symbol_c *type_symbol) {
   symbol_c *type_decl = search_base_type_c::get_basetype_decl(type_symbol); 
   if (NULL == type_decl)                                             {return false;}
@@ -267,8 +310,6 @@
 
 
 
-
-
 bool get_datatype_info_c::is_sfc_step(symbol_c *type_symbol) {
   symbol_c *type_decl = search_base_type_c::get_basetype_decl(type_symbol); 
   if (NULL == type_decl)                                             {return false;}
@@ -360,10 +401,6 @@
 
 
 
-
-
-
-
 bool get_datatype_info_c::is_ANY_ELEMENTARY(symbol_c *type_symbol) {
   if (type_symbol == NULL)                                     {return false;}
   if (is_ANY_MAGNITUDE(type_symbol))                           {return true;}
--- a/absyntax_utils/get_datatype_info.hh	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/get_datatype_info.hh	Sun Jul 13 12:26:58 2014 +0100
@@ -59,13 +59,13 @@
   public:
     static symbol_c   *get_id    (symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! Does not work for elementary datatypes!*/
     static const char *get_id_str(symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! */
-      
+
+    static symbol_c *get_ref_to                    (symbol_c *type_symbol);    // Defined in IEC 61131-3 v3 (returns the type that is being referenced/pointed to)        
+    
     static bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
     static bool is_type_valid(symbol_c *type);
-      
-    static bool is_ANY_REAL_literal(symbol_c *type_symbol); /* Can't we do away with this?? */
-    static bool is_ANY_INT_literal (symbol_c *type_symbol); /* Can't we do away with this?? */
-
+
+    static bool is_ref_to                          (symbol_c *type_symbol);    // Defined in IEC 61131-3 v3
     static bool is_sfc_initstep                    (symbol_c *type_symbol);
     static bool is_sfc_step                        (symbol_c *type_symbol);
     static bool is_function_block                  (symbol_c *type_symbol);
@@ -73,8 +73,10 @@
     static bool is_enumerated                      (symbol_c *type_symbol);
     static bool is_array                           (symbol_c *type_symbol);
     static bool is_structure                       (symbol_c *type_symbol);
-
   
+    static bool is_ANY_REAL_literal(symbol_c *type_symbol); /* Can't we do away with this?? */
+    static bool is_ANY_INT_literal (symbol_c *type_symbol); /* Can't we do away with this?? */
+
     static bool is_ANY_ELEMENTARY                  (symbol_c *type_symbol);
     static bool is_ANY_SAFEELEMENTARY              (symbol_c *type_symbol);
     static bool is_ANY_ELEMENTARY_compatible       (symbol_c *type_symbol);
--- a/absyntax_utils/search_base_type.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/search_base_type.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -361,7 +361,7 @@
 					string_type_declaration_size,
 					string_type_declaration_init) // may be == NULL!
 */
-void *search_base_type_c::visit(string_type_declaration_c *symbol)	                {return (void *)symbol;}
+void *search_base_type_c::visit(string_type_declaration_c *symbol)                      {return (void *)symbol;}
 
 
 /*  function_block_type_name ASSIGN structure_initialization */
@@ -373,6 +373,27 @@
 
 
 
+/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *search_base_type_c::visit(ref_spec_c *symbol)                                     {return (void *)symbol;}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ]; */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *search_base_type_c::visit(ref_spec_init_c *symbol) {
+  return symbol->ref_spec->accept(*this);
+}
+
+/* ref_type_decl: identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *search_base_type_c::visit(ref_type_decl_c *symbol)  {
+  this->current_basetype_name = symbol->ref_type_name;
+  return symbol->ref_spec_init->accept(*this);
+}
+
+
+
 /*****************************/
 /* B 1.5.2 - Function Blocks */
 /*****************************/
--- a/absyntax_utils/search_base_type.hh	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/search_base_type.hh	Sun Jul 13 12:26:58 2014 +0100
@@ -249,6 +249,13 @@
   /* structure_initialization -> may be NULL ! */
     void *visit(fb_spec_init_c *symbol);
     
+  /* REF_TO (non_generic_type_name | function_block_type_name) */
+    void *visit(ref_spec_c *symbol);       // Defined in IEC 61131-3 v3
+  /* ref_spec [ ASSIGN ref_initialization ]; *//* NOTE: ref_initialization may be NULL!! */
+    void *visit(ref_spec_init_c *symbol);  // Defined in IEC 61131-3 v3
+  /* identifier ':' ref_spec_init */
+    void *visit(ref_type_decl_c *symbol);  // Defined in IEC 61131-3 v3
+
   /*****************************/
   /* B 1.5.2 - Function Blocks */
   /*****************************/
--- a/absyntax_utils/spec_init_separator.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/spec_init_separator.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -171,6 +171,37 @@
   return NULL;
 }
 
+
+/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *spec_init_sperator_c::visit(ref_spec_c *symbol) {
+  TRACE("spec_init_sperator_c::ref_spec_c");
+  /* This visitor should never really be called, but there is no harm in including it... */
+  switch (search_what) {
+    case search_spec: return symbol;
+    case search_init: return NULL; /* should never occur */
+  }
+  ERROR; /* should never occur */
+  return NULL;
+}
+
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *spec_init_sperator_c::visit(ref_spec_init_c *symbol) {
+  TRACE("spec_init_sperator_c::ref_spec_init_c");
+  switch (search_what) {
+    case search_spec: return symbol->ref_spec;
+    case search_init: return symbol->ref_initialization;
+  }
+  ERROR; /* should never occur */
+  return NULL;
+}
+
+
+
 /******************************************/
 /* B 1.4.3 - Declaration & Initialisation */
 /******************************************/
--- a/absyntax_utils/spec_init_separator.hh	Sun Jul 06 23:31:08 2014 +0100
+++ b/absyntax_utils/spec_init_separator.hh	Sun Jul 13 12:26:58 2014 +0100
@@ -98,7 +98,15 @@
   //SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
   void *visit(fb_spec_init_c *symbol);
 
+  /* REF_TO (non_generic_type_name | function_block_type_name) */
+  // SYM_REF1(ref_spec_c, type_name)
+  void *visit(ref_spec_c *symbol);
 
+  /* ref_spec [ ASSIGN ref_initialization ] */ 
+  /* NOTE: ref_initialization may be NULL!! */
+  // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+  void *visit(ref_spec_init_c *symbol);
+  
   /******************************************/
   /* B 1.4.3 - Declaration & Initialisation */
   /******************************************/
--- a/lib/C/iec_types_all.h	Sun Jul 06 23:31:08 2014 +0100
+++ b/lib/C/iec_types_all.h	Sun Jul 13 12:26:58 2014 +0100
@@ -86,6 +86,8 @@
   IEC_##type fvalue;\
 } __IEC_##type##_p;
 
+
+
 #define __DECLARE_DERIVED_TYPE(type, base)\
 typedef base type;\
 typedef __IEC_##base##_t __IEC_##type##_t;\
@@ -121,6 +123,11 @@
 } type;\
 __DECLARE_COMPLEX_STRUCT(type)
 
+#define __DECLARE_REFTO_TYPE(type, name)\
+typedef name * type;\
+__DECLARE_COMPLEX_STRUCT(type)
+
+
 /* Those typdefs clash with windows.h */
 /* i.e. this file cannot be included aside windows.h */
 __ANY(__DECLARE_IEC_TYPE)
--- a/stage1_2/iec_bison.yy	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage1_2/iec_bison.yy	Sun Jul 13 12:26:58 2014 +0100
@@ -3209,7 +3209,12 @@
 
 
 ref_spec_init: /* defined in IEC 61131-3 v3 */
-  ref_spec  /* For the moment, we do not support initialising reference data types */
+  ref_spec
+	{$$ = new ref_spec_init_c($1, NULL, locloc(@$));}
+/*  For the moment, we do not support initialising reference data types...
+| ref_spec ASSIGN ... 
+	{$$ = new ref_spec_init_c($1, $3, locloc(@$));}
+*/
 ;
 
 ref_type_decl:  /* defined in IEC 61131-3 v3 */
--- a/stage1_2/iec_flex.ll	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage1_2/iec_flex.ll	Sun Jul 13 12:26:58 2014 +0100
@@ -1251,8 +1251,8 @@
 	/******************************************************/
 
 
-REF	{if (get_opt_ref_operator()) return REF;    else unput(0);}		/* Keyword in IEC 61131-3 v3 */
-REF_TO	{/*if (get_opt_ref_operator()) return REF_TO; else */unput(0);}		/* Keyword in IEC 61131-3 v3 */
+REF	{if (get_opt_ref_operator()) return REF;    else{REJECT;}}		/* Keyword in IEC 61131-3 v3 */
+REF_TO	{if (get_opt_ref_operator()) return REF_TO; else{REJECT;}}		/* Keyword in IEC 61131-3 v3 */
 
 EN	return EN;			/* Keyword */
 ENO	return ENO;			/* Keyword */
--- a/stage3/fill_candidate_datatypes.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -1108,6 +1108,33 @@
 void *fill_candidate_datatypes_c::visit(fb_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->function_block_type_name, symbol->structure_initialization);}
 
 
+/* REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *fill_candidate_datatypes_c::visit(ref_spec_c *symbol) {
+  
+	// when parsing datatype declarations, fill_candidate_datatypes_c follows a top->down algorithm (see the comment in fill_type_decl() for an explanation)
+	add_datatype_to_candidate_list(symbol->type_name, base_type(symbol->type_name)); 
+	symbol->type_name->accept(*this);  /* The referenced/pointed to datatype! */
+
+	if (symbol->candidate_datatypes.size() == 0) // i.e., if this is an anonymous datatype!
+		add_datatype_to_candidate_list(symbol, base_type(symbol)); 
+
+	return NULL;
+}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec [ ASSIGN ref_initialization ] */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *fill_candidate_datatypes_c::visit(ref_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->ref_spec, symbol->ref_initialization);}
+
+/* identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *fill_candidate_datatypes_c::visit(ref_type_decl_c *symbol) {return fill_type_decl(symbol, symbol->ref_type_name, symbol->ref_spec_init);}
+
+
+
+
 
 /*********************/
 /* B 1.4 - Variables */
@@ -1835,7 +1862,7 @@
 /* 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) {
   symbol->exp->accept(*this);
-  /* we should really check whether the expression is merely a variable. For now, leave it for the future! */
+  /* we should really check whether the expression is an lvalue. For now, leave it for the future! */
   /* For now, we handle references (i.e. pointers) as ULINT datatypes! */
   add_datatype_to_candidate_list(symbol, &get_datatype_info_c::ulint_type_name);
   return NULL;
--- a/stage3/fill_candidate_datatypes.hh	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Sun Jul 13 12:26:58 2014 +0100
@@ -172,7 +172,7 @@
     /********************************/
 //  void *visit(data_type_declaration_c *symbol);   /* Not required. already handled by iterator_visitor_c base class */
 //  void *visit(type_declaration_list_c *symbol);   /* Not required. already handled by iterator_visitor_c base class */
-    void *visit(simple_type_declaration_c *symbol); /* Not required. already handled by iterator_visitor_c base class */
+    void *visit(simple_type_declaration_c *symbol);
     void *visit(simple_spec_init_c *symbol);
     void *visit(subrange_type_declaration_c *symbol);
     void *visit(subrange_spec_init_c *symbol);
@@ -196,6 +196,11 @@
 //  void *visit(structure_element_initialization_c *symbol);
 //  void *visit(string_type_declaration_c *symbol);
     void *visit(fb_spec_init_c *symbol);
+      
+    void *visit(ref_spec_c *symbol);      // Defined in IEC 61131-3 v3
+    void *visit(ref_spec_init_c *symbol); // Defined in IEC 61131-3 v3
+    void *visit(ref_type_decl_c *symbol); // Defined in IEC 61131-3 v3
+
 
     
     /*********************/
--- a/stage3/narrow_candidate_datatypes.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -647,6 +647,37 @@
 void *narrow_candidate_datatypes_c::visit(fb_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->function_block_type_name, symbol->structure_initialization);}
 
 
+/* REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *narrow_candidate_datatypes_c::visit(ref_spec_c *symbol) {
+	/* First handle the datatype being referenced (pointed to) */
+	if (symbol->type_name->candidate_datatypes.size() == 1) {
+		symbol->type_name->datatype = symbol->type_name->candidate_datatypes[0];
+		symbol->type_name->accept(*this);
+	}
+
+	/* Now handle the reference datatype itself (i.e. the pointer) */
+	// If we are handling an anonymous datatype (i.e. a datatype implicitly declared inside a VAR ... END_VAR declaration)
+	// then the symbol->datatype has not yet been set by the previous visit(type_decl) method, because it does not exist!
+	// So we set the datatype ourselves!
+	if ((NULL == symbol->datatype) && (symbol->candidate_datatypes.size() == 1))
+		symbol->datatype = symbol->candidate_datatypes[0];
+
+	return NULL;
+}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec [ ASSIGN ref_initialization ] */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *narrow_candidate_datatypes_c::visit(ref_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->ref_spec, symbol->ref_initialization);}
+
+/* identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *narrow_candidate_datatypes_c::visit(ref_type_decl_c *symbol) {return narrow_type_decl(symbol, symbol->ref_type_name, symbol->ref_spec_init);}
+
+
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
--- a/stage3/narrow_candidate_datatypes.hh	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage3/narrow_candidate_datatypes.hh	Sun Jul 13 12:26:58 2014 +0100
@@ -179,6 +179,11 @@
 //  void *visit(structure_element_initialization_c *symbol);
 //  void *visit(string_type_declaration_c *symbol);
     void *visit(fb_spec_init_c *symbol);
+      
+    void *visit(ref_spec_c *symbol);      // Defined in IEC 61131-3 v3
+    void *visit(ref_spec_init_c *symbol); // Defined in IEC 61131-3 v3
+    void *visit(ref_type_decl_c *symbol); // Defined in IEC 61131-3 v3
+
 
     /*********************/
     /* B 1.4 - Variables */
--- a/stage4/generate_c/generate_c_st.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -464,7 +464,8 @@
 /* B 3.1 - Expressions */
 /***********************/
 void *visit(ref_expression_c *symbol) {
-  s4o.print("((IEC_UDINT)");  
+  s4o.print("(");  
+  s4o.print("(IEC_UDINT)");  
   if (this->is_variable_prefix_null()) {  
     /* For code in FUNCTIONs */
     s4o.print("&(");  
--- a/stage4/generate_c/generate_c_typedecl.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage4/generate_c/generate_c_typedecl.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -642,6 +642,48 @@
 					string_type_declaration_init) /* may be == NULL! */
 #endif
 
+
+
+/* ref_spec:  REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *visit(ref_spec_c *symbol) {
+  return symbol->type_name->accept(*this);
+}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *visit(ref_spec_init_c *symbol) {
+  return symbol->ref_spec->accept(*this);
+}
+
+/* ref_type_decl: identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *visit(ref_type_decl_c *symbol) {
+  TRACE("ref_type_decl_c");
+  
+  current_type_name = NULL;
+  current_typedefinition = none_td;
+
+  s4o_incl.print("__DECLARE_REFTO_TYPE(");
+  symbol->ref_type_name->accept(*basedecl);
+  s4o_incl.print(", ");
+  symbol->ref_spec_init->accept(*this);
+  s4o_incl.print(") ");
+
+  current_type_name = NULL;
+  current_typedefinition = none_td;
+
+  return NULL;
+}
+
+
+
+
+
+
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
--- a/stage4/generate_iec/generate_iec.cc	Sun Jul 06 23:31:08 2014 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Sun Jul 13 12:26:58 2014 +0100
@@ -669,10 +669,18 @@
   return NULL;
 }
 
-
 /* For the moment, we do not support initialising reference data types */
-/* ref_spec_init: ref_spec; */ 
-/* SYM_REF0(ref_spec_init_c) */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ]; */ 
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *visit(ref_spec_init_c *symbol) {
+  symbol->ref_spec->accept(*this);
+  if (symbol->ref_initialization != NULL) {
+    s4o.print(" := ");
+    symbol->ref_initialization->accept(*this);
+  }
+  return NULL;
+}
 
 /* ref_type_decl: identifier ':' ref_spec_init */
 // SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)