Merged Mario's changes
authorEdouard Tisserant
Thu, 04 Apr 2013 09:45:11 +0900
changeset 813 0630cc31569f
parent 804 7898ba56c7cf (current diff)
parent 812 6679b6b21214 (diff)
child 815 4cfca12bf850
Merged Mario's changes
stage3/fill_candidate_datatypes.cc
stage3/fill_candidate_datatypes.hh
stage3/narrow_candidate_datatypes.cc
stage3/narrow_candidate_datatypes.hh
--- a/absyntax/absyntax.def	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax/absyntax.def	Thu Apr 04 09:45:11 2013 +0900
@@ -445,6 +445,29 @@
 					string_type_declaration_init) /* may be == NULL! */
 
 
+/* helper symbol for fb_name_decl_c */
+/* This symbol/leaf does not exist in the IEC standard syntax as an isolated symbol,
+ * as, for some reason, the standard syntax defines FB variable declarations in a slightly 
+ * different style as all other spec_init declarations. I.e., fr FBs variable declarations, 
+ * the standard defines a single leaf/node (fb_name_decl) that references:
+ *   a) the variable name list
+ *   b) the FB datatype
+ *   c) the FB intial value
+ *
+ * All other variable declarations break this out into two nodes:
+ *   1) references b) and c) above (usually named ***_spec_init)
+ *   2) references a), and node 1)
+ *
+ * In order to allow the datatype analyses to proceed without special cases, we will handle
+ * FB variable declarations in the same style. For this reason, we have added the
+ * following node to the Abstract Syntax Tree, even though it does not have a direct equivalent in 
+ * the standard syntax.
+ */
+/*  function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+
+
 /*********************/
 /* B 1.4 - Variables */
 /*********************/
@@ -515,7 +538,8 @@
  */
 SYM_REF0(implicit_definition_c)
 SYM_REF0(explicit_definition_c)
-SYM_REF4(en_param_declaration_c, name, type, value, method)
+/* type_decl is a simple_spec_init_c */
+SYM_REF3(en_param_declaration_c, name, type_decl, method)
 SYM_REF3(eno_param_declaration_c, name, type, method)
 
 /* edge -> The F_EDGE or R_EDGE directive */
@@ -568,8 +592,13 @@
 SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
 
 /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
+/* NOTE: in order to allow datatype handling to proceed using the normal algorithm with no special cases,
+ * we will be storing the 
+ *    function_block_type_name ASSIGN structure_initialization
+ * componentes inside a new node, namely fb_spec_init_c
+ */
 /* structure_initialization -> may be NULL ! */
-SYM_REF3(fb_name_decl_c, fb_name_list, function_block_type_name, structure_initialization)
+SYM_REF2(fb_name_decl_c, fb_name_list, fb_spec_init)
 
 /* fb_name_list ',' fb_name */
 SYM_LIST(fb_name_list_c)
--- a/absyntax_utils/add_en_eno_param_decl.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/add_en_eno_param_decl.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -91,12 +91,11 @@
 
 
 input_declarations_c *add_en_eno_param_decl_c::build_en_param(void) {
-  boolean_literal_c *boolean_literal = 
-    new boolean_literal_c(new bool_type_name_c(), new boolean_true_c());
-  identifier_c *identifier =
-    new identifier_c("EN");
+  boolean_literal_c  *boolean_literal = new boolean_literal_c(new bool_type_name_c(), new boolean_true_c());
+  identifier_c       *identifier      = new identifier_c("EN");
+  simple_spec_init_c *type_spec_init  = new simple_spec_init_c(new bool_type_name_c(), boolean_literal);
   en_param_declaration_c *en_param_declaration = 
-    new en_param_declaration_c(identifier, new bool_type_name_c(), boolean_literal, new implicit_definition_c());
+    new en_param_declaration_c(identifier, type_spec_init, new implicit_definition_c());
     /* the last paramater is to flag that this
      * declaration was inserted automatically, i.e. an implicit declaration 
      */
@@ -109,8 +108,7 @@
 
 
 output_declarations_c *add_en_eno_param_decl_c::build_eno_param(void) {
-  identifier_c *identifier =
-    new identifier_c("ENO");
+  identifier_c *identifier = new identifier_c("ENO");
   eno_param_declaration_c *eno_param_declaration =
     new eno_param_declaration_c(identifier, new bool_type_name_c(), new implicit_definition_c()); 
     /* the last paramater is to flag that this
--- a/absyntax_utils/debug_ast.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/debug_ast.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -95,7 +95,7 @@
 
 
 void print_symbol_c::dump_symbol(symbol_c* symbol) {
-  fprintf(stderr, "(%03d:%03d..%03d:%03d) \t%s\t", symbol->first_line, symbol->first_column, symbol->last_line, symbol->last_column, symbol->absyntax_cname());
+  fprintf(stderr, "(%s->%03d:%03d..%03d:%03d) \t%s\t", symbol->first_file, symbol->first_line, symbol->first_column, symbol->last_line, symbol->last_column, symbol->absyntax_cname());
 
   fprintf(stderr, "  datatype=");
   if (NULL == symbol->datatype)
--- a/absyntax_utils/function_param_iterator.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/function_param_iterator.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -427,9 +427,9 @@
    * variables will get overwritten when we visit the next
    * var1_init_decl_c list!
    */
-  current_param_default_value = symbol->value;
-  current_param_type = symbol->type;
-
+  current_param_default_value = spec_init_sperator_c::get_init(symbol->type_decl);
+  current_param_type = spec_init_sperator_c::get_spec(symbol->type_decl);
+  
   void *res = handle_single_param(symbol->name);
   
     /* If we have found the parameter we will be returning, we set the en_eno_param_implicit to TRUE if implicitly defined */
@@ -467,8 +467,8 @@
 // SYM_REF3(fb_name_decl_c, fb_name_list, function_block_type_name, structure_initialization)
 void *function_param_iterator_c::visit(fb_name_decl_c *symbol) {
   TRACE("structured_var_init_decl_c");
-  current_param_default_value = symbol->structure_initialization ; 
-  current_param_type          = symbol->function_block_type_name ;
+  current_param_default_value = spec_init_sperator_c::get_init(symbol->fb_spec_init); 
+  current_param_type          = spec_init_sperator_c::get_spec(symbol->fb_spec_init);
 
   return symbol->fb_name_list->accept(*this);
 }
--- a/absyntax_utils/search_base_type.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/search_base_type.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -372,7 +372,15 @@
 */
 void *search_base_type_c::visit(string_type_declaration_c *symbol)	                {return (void *)symbol;}
 
-  
+
+/*  function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+// SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+void *search_base_type_c::visit(fb_spec_init_c *symbol)	{
+  return symbol->function_block_type_name->accept(*this);
+}
+
+
 
 /*****************************/
 /* B 1.5.2 - Function Blocks */
--- a/absyntax_utils/search_base_type.hh	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/search_base_type.hh	Thu Apr 04 09:45:11 2013 +0900
@@ -234,6 +234,10 @@
   */
     void *visit(string_type_declaration_c *symbol);
 
+  /* function_block_type_name ASSIGN structure_initialization */
+  /* structure_initialization -> may be NULL ! */
+    void *visit(fb_spec_init_c *symbol);
+    
   /*****************************/
   /* B 1.5.2 - Function Blocks */
   /*****************************/
--- a/absyntax_utils/search_fb_instance_decl.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/search_fb_instance_decl.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -87,7 +87,7 @@
 /* name_list ':' function_block_type_name ASSIGN structure_initialization */
 /* structure_initialization -> may be NULL ! */
 void *search_fb_instance_decl_c::visit(fb_name_decl_c *symbol) {
-  current_fb_type_name = symbol->function_block_type_name;
+  current_fb_type_name = spec_init_sperator_c::get_spec(symbol->fb_spec_init);
   return symbol->fb_name_list->accept(*this);
 }
 
--- a/absyntax_utils/search_var_instance_decl.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/search_var_instance_decl.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -105,6 +105,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) return NULL; // NOTE: This is not an ERROR! declaration_check_c, for e.g., relies on this returning NULL!
   return (symbol_c *)search_scope->accept(*this);
 }
 
@@ -112,6 +113,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) ERROR;
   search_scope->accept(*this);
   return this->current_vartype;
 }
@@ -120,6 +122,7 @@
   this->current_vartype = none_vt;
   this->current_option  = none_opt;
   this->search_name = get_var_name_c::get_name(variable);
+  if (NULL == search_scope) ERROR;
   search_scope->accept(*this);
   return this->current_option;
 }
@@ -340,7 +343,11 @@
 /* name_list ':' function_block_type_name ASSIGN structure_initialization */
 /* structure_initialization -> may be NULL ! */
 void *search_var_instance_decl_c::visit(fb_name_decl_c *symbol) {
-  current_type_decl = symbol->function_block_type_name;
+  // TODO: The following line is wrong! It should be
+  // current_type_decl = symbol->fb_spec_init;
+  //  However, this change will require a check of all callers, to see if they would handle this correctly.
+  //  For now, just keep what we have had historically, and seems to be working.
+  current_type_decl = spec_init_sperator_c::get_spec(symbol->fb_spec_init);
   return symbol->fb_name_list->accept(*this);
 }
 
--- a/absyntax_utils/spec_init_separator.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/spec_init_separator.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -158,24 +158,23 @@
   return NULL;
 }
 
+/*  function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+//SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+void *spec_init_sperator_c::visit(fb_spec_init_c *symbol) {
+  TRACE("spec_init_sperator_c::fb_spec_init_c");
+  switch (search_what) {
+    case search_spec: return symbol->function_block_type_name;
+    case search_init: return symbol->structure_initialization;
+  }
+  ERROR; /* should never occur */
+  return NULL;
+}
 
 /******************************************/
 /* B 1.4.3 - Declaration & Initialisation */
 /******************************************/
 
-/* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
-/* structure_initialization -> may be NULL ! */
-void *spec_init_sperator_c::visit(fb_name_decl_c *symbol) {
-  TRACE("spec_init_sperator_c::fb_name_decl_c");
-  switch (search_what) {
-    case search_spec: return symbol->function_block_type_name;
-    case search_init: return symbol->structure_initialization;
-  }
-  ERROR; /* should never occur */
-  return NULL;
-}
-
-
 /* STRING '[' integer ']' 
  * STRING ASSIGN single_byte_character_string
  * STRING '[' integer ']' ASSIGN single_byte_character_string
--- a/absyntax_utils/spec_init_separator.hh	Mon Mar 11 12:54:25 2013 +0100
+++ b/absyntax_utils/spec_init_separator.hh	Thu Apr 04 09:45:11 2013 +0900
@@ -93,15 +93,16 @@
   //SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
   void *visit(initialized_structure_c *symbol);
   
-  
+  /*  function_block_type_name ASSIGN structure_initialization */
+  /* structure_initialization -> may be NULL ! */
+  //SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+  void *visit(fb_spec_init_c *symbol);
+
+
   /******************************************/
   /* B 1.4.3 - Declaration & Initialisation */
   /******************************************/
   
-  /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
-  /* structure_initialization -> may be NULL ! */
-  void *visit(fb_name_decl_c *symbol);
-  
   /* STRING '[' integer ']' 
    * STRING ASSIGN single_byte_character_string
    * STRING '[' integer ']' ASSIGN single_byte_character_string
--- a/stage1_2/iec_bison.yy	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage1_2/iec_bison.yy	Thu Apr 04 09:45:11 2013 +0900
@@ -3458,9 +3458,9 @@
  */
 en_param_declaration:
   en_identifier ':' BOOL ASSIGN boolean_literal
-  {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));}
+  {$$ = new en_param_declaration_c($1, new simple_spec_init_c(new bool_type_name_c(locloc(@3)), $5, locf(@3), locl(@5)), new explicit_definition_c(), locloc(@$));}
 | en_identifier ':' BOOL ASSIGN integer
-  {$$ = new en_param_declaration_c($1, new bool_type_name_c(locloc(@$)), $5, new explicit_definition_c(), locloc(@$));}
+  {$$ = new en_param_declaration_c($1, new simple_spec_init_c(new bool_type_name_c(locloc(@3)), $5, locf(@3), locl(@5)), new explicit_definition_c(), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | en_identifier BOOL ASSIGN boolean_literal
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and specification in EN declaration."); yynerrs++;}
@@ -3598,10 +3598,10 @@
 fb_name_decl:
 /*  fb_name_list ':' function_block_type_name */
   fb_name_list_with_colon function_block_type_name
-	{$$ = new fb_name_decl_c($1, $2, NULL, locloc(@$));}
+	{$$ = new fb_name_decl_c($1, new fb_spec_init_c($2, NULL,locloc(@2)), locloc(@$));}
 /*| fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
 | fb_name_list_with_colon function_block_type_name ASSIGN structure_initialization
-	{$$ = new fb_name_decl_c($1, $2, $4, locloc(@$));}
+	{$$ = new fb_name_decl_c($1, new fb_spec_init_c($2, $4, locf(@2), locl(@4)), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | fb_name_list_with_colon ASSIGN structure_initialization
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "no function block type name defined in function block declaration with initialization."); yynerrs++;}
@@ -4042,7 +4042,7 @@
 	 variable_name_symtable.insert($1, prev_declared_variable_name_token);
 	}
 | global_var_name ':' function_block_type_name
-	{$$ = new external_declaration_c($1, $3, locloc(@$));
+	{$$ = new external_declaration_c($1, new fb_spec_init_c($3, NULL, locloc(@3)), locloc(@$));
 	 variable_name_symtable.insert($1, prev_declared_fb_name_token);
 	}
 /* ERROR_CHECK_BEGIN */
@@ -4136,7 +4136,7 @@
   global_var_spec ':' located_var_spec_init
 	{$$ = new global_var_decl_c($1, $3, locloc(@$));}
 | global_var_spec ':' function_block_type_name
-	{$$ = new global_var_decl_c($1, $3, locloc(@$));}
+	{$$ = new global_var_decl_c($1, new fb_spec_init_c($3, NULL, locloc(@3)), locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | global_var_list located_var_spec_init
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between global variable list and type specification."); yynerrs++;}
@@ -5692,11 +5692,11 @@
 
 
 resource_declaration:
-  RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name ON resource_type_name
+  RESOURCE {variable_name_symtable.push();direct_variable_symtable.push();} resource_name {variable_name_symtable.insert($3, prev_declared_resource_name_token);} ON resource_type_name
    optional_global_var_declarations
    single_resource_declaration
   END_RESOURCE
-	{$$ = new resource_declaration_c($3, $5, $6, $7, locloc(@$));
+	{$$ = new resource_declaration_c($3, $6, $7, $8, locloc(@$));
 	 variable_name_symtable.pop();
 	 direct_variable_symtable.pop();
 	 variable_name_symtable.insert($3, prev_declared_resource_name_token);
@@ -8246,7 +8246,6 @@
              symbol_c **tree_root_ref,
              bool full_token_loc_        /* error messages specify full token location */
             ) {
-
   char *libfilename = NULL;
 
   if (includedir != NULL) {
@@ -8296,7 +8295,6 @@
         library_element_symtable.end_value())
       library_element_symtable.insert(standard_function_block_names[i], standard_function_block_name_token);
 
-
   /* now parse the input file... */
   #if YYDEBUG
     yydebug = 1;
--- a/stage3/declaration_check.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/declaration_check.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -73,6 +73,7 @@
 declaration_check_c::declaration_check_c(symbol_c *ignore) {
   current_display_error_level = 0;
   current_pou_decl = NULL;
+  current_resource_decl = NULL;
   error_count = 0;
 }
 
@@ -85,36 +86,47 @@
 }
 
 void declaration_check_c::check_global_decl(symbol_c *p_decl) {
-	symbol_c *var_name;
-
-	search_var_instance_decl_c search_var_instance_glo_decl(current_pou_decl);
-	search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
-	function_param_iterator_c fpi(p_decl);
-	while((var_name = fpi.next()) != NULL) {
-      if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
-     	 /* found an external reference parameter. */
-     	symbol_c *glo_decl = search_var_instance_glo_decl.get_decl(var_name);
-        symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
-    	if (glo_decl == NULL) {
-    	  STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error an external doesn't mach with any global var.");
-    	  continue;
-    	}
-        if (search_var_instance_glo_decl.get_option(var_name) != search_var_instance_ext_decl.get_option(var_name))
-          STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error an external redefinition option.");
-
-        /* TODO: Check redefinition data type.
-         *       We need a new class (like search_base_type class) to get type id by variable declaration.
-         *  symbol_c *glo_type = ????;
-         *  symbol_c *ext_type = fpi.param_type();
-	 */
-	/* For the moment, we will just use search_base_type_c instead... */
-        symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
-        symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
-        if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
-          STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error an external redefinition data type.");
+  if (NULL == current_pou_decl) ERROR;
+  
+  search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl);
+  search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl);
+  search_var_instance_decl_c search_var_instance_ext_decl(p_decl);
+  function_param_iterator_c  fpi(p_decl);
+  
+  symbol_c *var_name;
+  while((var_name = fpi.next()) != NULL) {
+    if (fpi.param_direction() == function_param_iterator_c::direction_extref) {
+      /* found an external reference parameter. */
+      symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name);
+      
+      // NOTE: Must check the POU first, and RESOURCE second!
+      symbol_c                                       *glo_decl =  search_var_instance_res_glo_decl.get_decl(var_name);           
+      search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl;
+      if (NULL == glo_decl) {
+        glo_decl                     =  search_var_instance_pou_glo_decl.get_decl(var_name);
+        search_var_instance_glo_decl = &search_var_instance_pou_glo_decl;
       }
-	}
-
+      
+      if (NULL == glo_decl) {
+        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable.");
+        continue;
+      }
+      
+      if (search_var_instance_glo_decl->get_option(var_name) != search_var_instance_ext_decl.get_option(var_name))
+        STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error.  The external variable options do not match with thos of the global variable.");
+
+      /* TODO: Check redefinition data type.
+       *       We need a new class (like search_base_type class) to get type id by variable declaration.
+       *  symbol_c *glo_type = ????;
+       *  symbol_c *ext_type = fpi.param_type();
+       */
+      /* For the moment, we will just use search_base_type_c instead... */
+      symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl);
+      symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl);
+      if (! get_datatype_info_c::is_type_equal(glo_type, ext_type))
+        STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error.  Data type mismatch between external and global variable declarations.");
+    }
+  }
 }
 
 
@@ -125,7 +137,10 @@
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
 // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
 void *declaration_check_c::visit(function_block_declaration_c *symbol) {
-  current_pou_decl = symbol;
+  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs!
+   * current_pou_decl = symbol;  
+   * current_resource_decl = NULL;  
+   */
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->var_declarations)
     symbol->var_declarations->accept(*this);
@@ -138,7 +153,10 @@
 /*  PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
 // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body)
 void *declaration_check_c::visit(program_declaration_c *symbol) {
-  current_pou_decl = symbol;
+  /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs!
+   * current_pou_decl = symbol;  
+   * current_resource_decl = NULL;  
+   */
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->var_declarations)
     symbol->var_declarations->accept(*this);
@@ -162,9 +180,27 @@
   /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
   if (NULL != symbol->resource_declarations)
     symbol->resource_declarations->accept(*this);
-  return NULL;
-}
-
+  current_pou_decl = NULL;
+  return NULL;
+}
+
+/*
+RESOURCE resource_name ON resource_type_name
+   optional_global_var_declarations
+   single_resource_declaration
+END_RESOURCE
+*/
+/* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */
+// SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, enumvalue_symtable_t enumvalue_symtable;)
+void *declaration_check_c::visit(resource_declaration_c *symbol) {
+  current_resource_decl = symbol;
+  /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */
+  symbol->resource_declaration->accept(*this);
+  current_resource_decl = NULL;  
+  return NULL;
+}
+
+/*  PROGRAM [RETAIN | NON_RETAIN] program_name [WITH task_name] ':' program_type_name ['(' prog_conf_elements ')'] */
 void *declaration_check_c::visit(program_configuration_c *symbol) {
   symbol_c *p_decl = program_type_symtable.find_value(symbol->program_type_name);
   if (p_decl == program_type_symtable.end_value())
--- a/stage3/declaration_check.hh	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/declaration_check.hh	Thu Apr 04 09:45:11 2013 +0900
@@ -39,6 +39,7 @@
     int error_count;
     int current_display_error_level;
     symbol_c *current_pou_decl;
+    symbol_c *current_resource_decl;
 
 public:
     declaration_check_c(symbol_c *ignore);
@@ -61,5 +62,6 @@
     /* B 1.7 Configuration elements */
     /********************************/
     void *visit(configuration_declaration_c *symbol);
-    void *visit(program_configuration_c *symbol);
+    void *visit(resource_declaration_c      *symbol);
+    void *visit(program_configuration_c     *symbol);
 };
--- a/stage3/fill_candidate_datatypes.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/fill_candidate_datatypes.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -798,6 +798,69 @@
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
+
+void *fill_candidate_datatypes_c::fill_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init) {
+  /* NOTE: Unlike the rest of the 'fill' algorithm that works using a bottom->up approach, when handling 
+   *       data type declarations (section B.1.3.3 - Derived data types) we use a top->bottom approach. 
+   *       This is intentional, and not a bug! Explanation follows...
+   *       Here we are essentially determining the base type of each defined data type. In many cases (especially structs,
+   *       enumerations, arrays, etc...), the datatype is its own base type. However, the derived datatype is stored in
+   *       multiple symbol_c classes (e.g. an enumeration uses enumerated_type_declaration_c, enumerated_spec_init_c,
+   *       enumerated_value_list_c, enumerated_value_c, ...). Several of these could be chosen to work as the canonical base datatype
+   *       symbol. Which symbol is used is really up to the search_base_type_c, and not this fill_candidate_datatypes_c.
+   *       Here we must right the code to handle whatever the search_base_type_c chooses to use as the canonical symbol to represent
+   *       the base datatype.
+   *       Since the base datatype may be (and sometimes/often/always(?) actually is) the top level symbol_c (an enumerated_type_declaration_c
+   *       in the case of the enumerations), it only makes sense to ask search_base_type_c for a basetype when we pass it the 
+   *       symbol in the highest level of the type declaration (the enumerated_type_declaration_c in the case of the enumerations).
+   *       For this reason, we determine the basetype at the top level, and send that info down to the bottom level of the data type 
+   *       declaration. In summary, a top->down algorithm!
+   */ 
+  add_datatype_to_candidate_list(symbol, base_type(symbol));
+  type_name->candidate_datatypes = symbol->candidate_datatypes;  // use top->down algorithm!!
+  spec_init->candidate_datatypes = symbol->candidate_datatypes;  // use top->down algorithm!!
+  spec_init->accept(*this);
+  return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::fill_spec_init(symbol_c *symbol, symbol_c *type_spec, symbol_c *init_value) {
+	/* NOTE: The note in the fill_type_decl() function is also partially valid here, 
+	 *       i.e. here too we work using a top->down algorithm for the type_spec part, but a bottom->up algorithm
+	 *       for the init_value part!!
+	 */
+	/* NOTE: When a variable is declared inside a POU as, for example
+	 *         VAR
+	 *            a : ARRAY[9] OF REAL;
+	 *            e : ENUM (black, white, gray);
+	 *            s : STRUCT x, y: REAL; END_STRUCT
+	 *         END_VAR
+	 *      the anonymous datatype will be defined directly by the ***_spec_init_c, and will not have an
+	 *      ****_type_declaration_c. In these cases, the anonymous data type is its own basetype, and the
+	 *      ***_spec_init_c class will act as the canonical symbol that represents the (anonymous) basetype.
+	 *      
+	 *      This method must handle the above case, as well as the case in which the ***_spec_init_c is called
+	 *      from an ****_type_declaration_c.
+	 */
+	if (symbol->candidate_datatypes.size() == 0) // i.e., if this is an anonymous datatype!
+		add_datatype_to_candidate_list(symbol, base_type(symbol)); 
+	
+	// use top->down algorithm!!
+	type_spec->candidate_datatypes = symbol->candidate_datatypes;   
+	type_spec->accept(*this);
+	
+	// use bottom->up algorithm!!
+	if (NULL != init_value) init_value->accept(*this);  
+	/* NOTE: Even if the constant and the type are of incompatible data types, we let the
+	 *       ***_spec_init_c object inherit the data type of the type declaration (simple_specification)
+	 *       This will let us produce more informative error messages when checking data type compatibility
+	 *       with located variables (AT %QW3.4 : WORD).
+	 */
+	// if (NULL != init_value) intersect_candidate_datatype_list(symbol /*origin, dest.*/, init_value /*with*/);
+	return NULL;
+}
+
+
 /*  TYPE type_declaration_list END_TYPE */
 // SYM_REF1(data_type_declaration_c, type_declaration_list)
 /* NOTE: Not required. already handled by iterator_visitor_c base class */
@@ -808,32 +871,25 @@
 
 /*  simple_type_name ':' simple_spec_init */
 // SYM_REF2(simple_type_declaration_c, simple_type_name, simple_spec_init)
-/* NOTE: Not required. already handled by iterator_visitor_c base class */
+void *fill_candidate_datatypes_c::visit(simple_type_declaration_c *symbol) {return fill_type_decl(symbol, symbol->simple_type_name, symbol->simple_spec_init);}
+  
 
 /* simple_specification ASSIGN constant */
 // SYM_REF2(simple_spec_init_c, simple_specification, constant)
-void *fill_candidate_datatypes_c::visit(simple_spec_init_c *symbol) {
-	if (NULL != symbol->constant) symbol->constant->accept(*this);
-	add_datatype_to_candidate_list(symbol->simple_specification, base_type(symbol->simple_specification));
-	symbol->candidate_datatypes = symbol->simple_specification->candidate_datatypes;
-	/* NOTE: Even if the constant and the type are of incompatible data types, we let the
-	 *       simple_spec_init_c object inherit the data type of the type declaration (simple_specification)
-	 *       This will let us produce more informative error messages when checking data type compatibility
-	 *       with located variables (AT %QW3.4 : WORD).
-	 */
-	// if (NULL != symbol->constant) intersect_candidate_datatype_list(symbol /*origin, dest.*/, symbol->constant /*with*/);
-	return NULL;
-}
+void *fill_candidate_datatypes_c::visit(simple_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->simple_specification, symbol->constant);}
 
 
 /*  subrange_type_name ':' subrange_spec_init */
 // SYM_REF2(subrange_type_declaration_c, subrange_type_name, subrange_spec_init)
+void *fill_candidate_datatypes_c::visit(subrange_type_declaration_c *symbol) {return fill_type_decl(symbol, symbol->subrange_type_name, symbol->subrange_spec_init);}
 
 /* subrange_specification ASSIGN signed_integer */
 // SYM_REF2(subrange_spec_init_c, subrange_specification, signed_integer)
+void *fill_candidate_datatypes_c::visit(subrange_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->subrange_specification, symbol->signed_integer);}
 
 /*  integer_type_name '(' subrange')' */
 // SYM_REF2(subrange_specification_c, integer_type_name, subrange)
+// NOTE: not needed! Iterator visitor already handles this!
 
 /*  signed_integer DOTDOT signed_integer */
 /* dimension will be filled in during stage 3 (array_range_check_c) with the number of elements in this subrange */
@@ -854,41 +910,25 @@
 
 /*  enumerated_type_name ':' enumerated_spec_init */
 // SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init)
-void *fill_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {
-  current_enumerated_spec_type = base_type(symbol);
-  add_datatype_to_candidate_list(symbol,                       current_enumerated_spec_type);
-  add_datatype_to_candidate_list(symbol->enumerated_type_name, current_enumerated_spec_type);
-  symbol->enumerated_spec_init->accept(*this);
-  current_enumerated_spec_type = NULL;  
-  return NULL;
-}
+void *fill_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {return fill_type_decl(symbol, symbol->enumerated_type_name, symbol->enumerated_spec_init);}
 
 
 /* enumerated_specification ASSIGN enumerated_value */
 // SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
-void *fill_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {
-  /* 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(enumerated_spec_init_c) method!
-   */
-  if (NULL == current_enumerated_spec_type)
-    current_enumerated_spec_type = base_type(symbol);  
-  add_datatype_to_candidate_list(symbol, current_enumerated_spec_type);
-  symbol->enumerated_specification->accept(*this); /* calls enumerated_value_list_c (or identifier_c, which we ignore!) visit method */
-  current_enumerated_spec_type = NULL;  
-  if (NULL != symbol->enumerated_value) symbol->enumerated_value->accept(*this);
-  return NULL;
-}
+// NOTE: enumerated_specification is either an enumerated_value_list_c or identifier_c.
+void *fill_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->enumerated_specification, symbol->enumerated_value);}
+
 
 /* helper symbol for enumerated_specification->enumerated_spec_init */
 /* enumerated_value_list ',' enumerated_value */
 // SYM_LIST(enumerated_value_list_c)
 void *fill_candidate_datatypes_c::visit(enumerated_value_list_c *symbol) {
-  if (NULL == current_enumerated_spec_type) ERROR;  
-  add_datatype_to_candidate_list(symbol, current_enumerated_spec_type);
+  if (symbol->candidate_datatypes.size() != 1) ERROR;
+  symbol_c *current_enumerated_spec_type = symbol->candidate_datatypes[0];
   
   /* We already know the datatype of the enumerated_value(s) in the list, so we set them directly instead of recursively calling the enumerated_value_c visit method! */
   for(int i = 0; i < symbol->n; i++)
-    add_datatype_to_candidate_list(symbol->elements[i], current_enumerated_spec_type);
+    add_datatype_to_candidate_list(symbol->elements[i], current_enumerated_spec_type); // top->down algorithm!!
 
   return NULL;  
 }
@@ -969,10 +1009,12 @@
 
 /*  identifier ':' array_spec_init */
 // SYM_REF2(array_type_declaration_c, identifier, array_spec_init)
+void *fill_candidate_datatypes_c::visit(array_type_declaration_c *symbol) {return fill_type_decl(symbol, symbol->identifier, symbol->array_spec_init);}
 
 /* array_specification [ASSIGN array_initialization} */
 /* array_initialization may be NULL ! */
 // SYM_REF2(array_spec_init_c, array_specification, array_initialization)
+void *fill_candidate_datatypes_c::visit(array_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->array_specification, symbol->array_initialization);}
 
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
 // SYM_REF2(array_specification_c, array_subrange_list, non_generic_type_name)
@@ -992,10 +1034,12 @@
 
 /*  structure_type_name ':' structure_specification */
 // SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+void *fill_candidate_datatypes_c::visit(structure_type_declaration_c *symbol) {return fill_type_decl(symbol, symbol->structure_type_name, symbol->structure_specification);}
 
 /* structure_type_name ASSIGN structure_initialization */
 /* structure_initialization may be NULL ! */
 // SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+void *fill_candidate_datatypes_c::visit(initialized_structure_c *symbol) {return fill_spec_init(symbol, symbol->structure_type_name, symbol->structure_initialization);}
 
 /* helper symbol for structure_declaration */
 /* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
@@ -1017,6 +1061,11 @@
 // SYM_REF4(string_type_declaration_c, string_type_name, elementary_string_type_name, string_type_declaration_size, string_type_declaration_init/* may be == NULL! */) 
 
 
+/*  function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+// SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization)
+void *fill_candidate_datatypes_c::visit(fb_spec_init_c *symbol) {return fill_spec_init(symbol, symbol->function_block_type_name, symbol->structure_initialization);}
+
 
 
 /*********************/
@@ -1211,8 +1260,6 @@
 
 
 
-
-
 /************************************/
 /* B 1.5 Program organization units */
 /************************************/
@@ -1249,6 +1296,12 @@
 	search_varfb_instance_type = NULL;
 
 	local_enumerated_value_symtable.reset();
+	
+	/* The FB declaration itself may be used as a dataype! We now do the fill algorithm considering 
+	 * function_block_declaration_c a data type declaration...
+	 */
+	// The next line is essentially equivalent to doing-->  symbol->candidate_datatypes.push_back(symbol);
+	add_datatype_to_candidate_list(symbol, base_type(symbol));
 	return NULL;
 }
 
--- a/stage3/fill_candidate_datatypes.hh	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/fill_candidate_datatypes.hh	Thu Apr 04 09:45:11 2013 +0900
@@ -94,6 +94,8 @@
     void *handle_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_binary_operator    (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
     void *handle_conditional_il_flow_control_operator(symbol_c *symbol);
+    void *fill_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init);
+    void *fill_spec_init(symbol_c *symbol, symbol_c *type_spec, symbol_c *init_value);
     
     /* a helper function... */
     symbol_c *base_type(symbol_c *symbol);    
@@ -169,29 +171,30 @@
     /********************************/
 //  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); /* Not required. already handled by iterator_visitor_c base class */
     void *visit(simple_spec_init_c *symbol);
-//  void *visit(subrange_type_declaration_c *symbol);
-//  void *visit(subrange_spec_init_c *symbol);
+    void *visit(subrange_type_declaration_c *symbol);
+    void *visit(subrange_spec_init_c *symbol);
 //  void *visit(subrange_specification_c *symbol);
     void *visit(subrange_c *symbol);
     void *visit(enumerated_type_declaration_c *symbol);
     void *visit(enumerated_spec_init_c *symbol);
     void *visit(enumerated_value_list_c *symbol);
     void *visit(enumerated_value_c *symbol);
-//  void *visit(array_type_declaration_c *symbol);
-//  void *visit(array_spec_init_c *symbol);
+    void *visit(array_type_declaration_c *symbol);
+    void *visit(array_spec_init_c *symbol);
 //  void *visit(array_specification_c *symbol);
 //  void *visit(array_subrange_list_c *symbol);
 //  void *visit(array_initial_elements_list_c *symbol);
 //  void *visit(array_initial_elements_c *symbol);
-//  void *visit(structure_type_declaration_c *symbol);
-//  void *visit(initialized_structure_c *symbol);
+    void *visit(structure_type_declaration_c *symbol);
+    void *visit(initialized_structure_c *symbol);
 //  void *visit(structure_element_declaration_list_c *symbol);
 //  void *visit(structure_element_declaration_c *symbol);
 //  void *visit(structure_element_initialization_list_c *symbol);
 //  void *visit(structure_element_initialization_c *symbol);
 //  void *visit(string_type_declaration_c *symbol);
+    void *visit(fb_spec_init_c *symbol);
 
     
     /*********************/
@@ -217,7 +220,6 @@
     void *visit(location_c *symbol);
     void *visit(located_var_decl_c *symbol);
 
-
     /**************************************/
     /* B 1.5 - Program organization units */
     /**************************************/
--- a/stage3/narrow_candidate_datatypes.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/narrow_candidate_datatypes.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -477,6 +477,36 @@
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
+void *narrow_candidate_datatypes_c::narrow_spec_init(symbol_c *symbol, symbol_c *type_decl, symbol_c *init_value) {
+	// 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];
+  
+	set_datatype(symbol->datatype, type_decl);
+	type_decl->accept(*this);
+
+	if (NULL != init_value) {
+		set_datatype(symbol->datatype, init_value);
+		init_value->accept(*this);
+	}
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::narrow_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init) {
+	if (symbol->candidate_datatypes.size() == 1) {
+		symbol->datatype = symbol->candidate_datatypes[0];
+  
+		set_datatype(symbol->datatype, type_name);
+		set_datatype(symbol->datatype, spec_init);
+		spec_init->accept(*this);
+	}
+	return NULL;
+}
+
+
 /*  TYPE type_declaration_list END_TYPE */
 // SYM_REF1(data_type_declaration_c, type_declaration_list)
 /* NOTE: Not required. already handled by iterator_visitor_c base class */
@@ -487,41 +517,37 @@
 
 /*  simple_type_name ':' simple_spec_init */
 // SYM_REF2(simple_type_declaration_c, simple_type_name, simple_spec_init)
-/* NOTE: Not required. already handled by iterator_visitor_c base class */
+void *narrow_candidate_datatypes_c::visit(simple_type_declaration_c *symbol) {return narrow_type_decl(symbol, symbol->simple_type_name, symbol->simple_spec_init);}
 
 /* simple_specification ASSIGN constant */
 // SYM_REF2(simple_spec_init_c, simple_specification, constant)
-void *narrow_candidate_datatypes_c::visit(simple_spec_init_c *symbol) {
-	if (symbol->candidate_datatypes.size() == 1)
-	  symbol->datatype = symbol->candidate_datatypes[0];
-	  
-	if (symbol->simple_specification->candidate_datatypes.size() == 1)
-	  symbol->simple_specification->datatype = symbol->simple_specification->candidate_datatypes[0];
-
-	if (NULL != symbol->constant) {
-		set_datatype(symbol->datatype, symbol->constant);
-		symbol->constant->accept(*this);
-	}
-	return NULL;
-}
-
+void *narrow_candidate_datatypes_c::visit(simple_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->simple_specification, symbol->constant);}
 
 /*  subrange_type_name ':' subrange_spec_init */
 // SYM_REF2(subrange_type_declaration_c, subrange_type_name, subrange_spec_init)
+void *narrow_candidate_datatypes_c::visit(subrange_type_declaration_c *symbol) {return narrow_type_decl(symbol, symbol->subrange_type_name, symbol->subrange_spec_init);}
 
 /* subrange_specification ASSIGN signed_integer */
 // SYM_REF2(subrange_spec_init_c, subrange_specification, signed_integer)
+void *narrow_candidate_datatypes_c::visit(subrange_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->subrange_specification, symbol->signed_integer);}
 
 /*  integer_type_name '(' subrange')' */
 // SYM_REF2(subrange_specification_c, integer_type_name, subrange)
+void *narrow_candidate_datatypes_c::visit(subrange_specification_c *symbol) {
+	set_datatype(symbol->datatype, symbol->integer_type_name);
+	symbol->integer_type_name->accept(*this);
+	set_datatype(symbol->datatype, symbol->integer_type_name);
+	symbol->integer_type_name->accept(*this);
+	return NULL;
+}
 
 /*  signed_integer DOTDOT signed_integer */
 /* dimension will be filled in during stage 3 (array_range_check_c) with the number of elements in this subrange */
 // SYM_REF2(subrange_c, lower_limit, upper_limit, unsigned long long int dimension;)
 void *narrow_candidate_datatypes_c::visit(subrange_c *symbol) {
-	symbol->lower_limit->datatype = symbol->datatype;
+	set_datatype(symbol->datatype, symbol->lower_limit);
 	symbol->lower_limit->accept(*this);
-	symbol->upper_limit->datatype = symbol->datatype;
+	set_datatype(symbol->datatype, symbol->upper_limit);
 	symbol->upper_limit->accept(*this);
 	return NULL;
 }
@@ -529,49 +555,20 @@
 
 /*  enumerated_type_name ':' enumerated_spec_init */
 // SYM_REF2(enumerated_type_declaration_c, enumerated_type_name, enumerated_spec_init)
-void *narrow_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {
-  if (symbol->candidate_datatypes.size() != 1) ERROR;
-  
-  symbol->datatype = symbol->candidate_datatypes[0];
-  set_datatype(symbol->datatype, symbol->enumerated_type_name);
-  set_datatype(symbol->datatype, symbol->enumerated_spec_init);
-  
-  symbol->enumerated_spec_init->accept(*this);
-  return NULL;
-}
+void *narrow_candidate_datatypes_c::visit(enumerated_type_declaration_c *symbol) {return narrow_type_decl(symbol, symbol->enumerated_type_name, symbol->enumerated_spec_init);}
 
 
 /* enumerated_specification ASSIGN enumerated_value */
 // SYM_REF2(enumerated_spec_init_c, enumerated_specification, enumerated_value)
-void *narrow_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {
-  /* 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(enumerated_spec_init_c) method!
-   */
-  if (NULL == symbol->datatype) {
-    if (symbol->candidate_datatypes.size() != 1) ERROR;
-    symbol->datatype = symbol->candidate_datatypes[0];
-  }
-  set_datatype(symbol->datatype, symbol->enumerated_specification);
-  if (NULL != symbol->enumerated_value) 
-    set_datatype(symbol->datatype, symbol->enumerated_value);
-
-  symbol->enumerated_specification->accept(*this); /* calls enumerated_value_list_c (or identifier_c, which we ignore!) visit method */
-  return NULL;
-}
+void *narrow_candidate_datatypes_c::visit(enumerated_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->enumerated_specification, symbol->enumerated_value);}
 
 /* helper symbol for enumerated_specification->enumerated_spec_init */
 /* enumerated_value_list ',' enumerated_value */
 // SYM_LIST(enumerated_value_list_c)
 void *narrow_candidate_datatypes_c::visit(enumerated_value_list_c *symbol) {
-  if (NULL == symbol->datatype) ERROR;
-  
-  for(int i = 0; i < symbol->n; i++) {
-    /* the enumerated_value_c objects to which this list points to has both the datatype and the candidate_datatype_list filled in, so we 
-     * call set_datatype() instead of setting the datatype directly!
-     */
-    set_datatype(symbol->datatype, symbol->elements[i]);
-    if (NULL == symbol->elements[i]->datatype) ERROR;
-  }
+//if (NULL == symbol->datatype) ERROR;  // Comented out-> Reserve this check for the print_datatypes_error_c ???  
+  for(int i = 0; i < symbol->n; i++) set_datatype(symbol->datatype, symbol->elements[i]);
+//for(int i = 0; i < symbol->n; i++) if (NULL == symbol->elements[i]->datatype) ERROR; // Comented out-> Reserve this check for the print_datatypes_error_c ???  
   return NULL;  
 }
 
@@ -583,54 +580,70 @@
 
 /*  identifier ':' array_spec_init */
 // SYM_REF2(array_type_declaration_c, identifier, array_spec_init)
+void *narrow_candidate_datatypes_c::visit(array_type_declaration_c *symbol) {return narrow_type_decl(symbol, symbol->identifier, symbol->array_spec_init);}
 
 /* array_specification [ASSIGN array_initialization} */
 /* array_initialization may be NULL ! */
 // SYM_REF2(array_spec_init_c, array_specification, array_initialization)
+void *narrow_candidate_datatypes_c::visit(array_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->array_specification, symbol->array_initialization);}
 
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
 // SYM_REF2(array_specification_c, array_subrange_list, non_generic_type_name)
+// Not needed!!
 
 /* helper symbol for array_specification */
 /* array_subrange_list ',' subrange */
 // SYM_LIST(array_subrange_list_c)
+// Not needed ??
 
 /* array_initialization:  '[' array_initial_elements_list ']' */
 /* helper symbol for array_initialization */
 /* array_initial_elements_list ',' array_initial_elements */
 // SYM_LIST(array_initial_elements_list_c)
+// Not needed ???
 
 /* integer '(' [array_initial_element] ')' */
 /* array_initial_element may be NULL ! */
 // SYM_REF2(array_initial_elements_c, integer, array_initial_element)
+// Not needed ???
 
 /*  structure_type_name ':' structure_specification */
 // SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+void *narrow_candidate_datatypes_c::visit(structure_type_declaration_c *symbol) {return narrow_type_decl(symbol, symbol->structure_type_name, symbol->structure_specification);}
 
 /* structure_type_name ASSIGN structure_initialization */
 /* structure_initialization may be NULL ! */
 // SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+void *narrow_candidate_datatypes_c::visit(initialized_structure_c *symbol) {return narrow_spec_init(symbol, symbol->structure_type_name, symbol->structure_initialization);}
 
 /* helper symbol for structure_declaration */
 /* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
 /* structure_element_declaration_list structure_element_declaration ';' */
 // SYM_LIST(structure_element_declaration_list_c)
+// Not needed ???
 
 /*  structure_element_name ':' *_spec_init */
 // SYM_REF2(structure_element_declaration_c, structure_element_name, spec_init)
+// Not needed ???
 
 /* helper symbol for structure_initialization */
 /* structure_initialization: '(' structure_element_initialization_list ')' */
 /* structure_element_initialization_list ',' structure_element_initialization */
 // SYM_LIST(structure_element_initialization_list_c)
+// Not needed ???
 
 /*  structure_element_name ASSIGN value */
 // SYM_REF2(structure_element_initialization_c, structure_element_name, value)
+// Not needed ???
 
 /*  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! */) 
 
 
+/* structure_type_name ASSIGN structure_initialization */
+/* structure_initialization may be NULL ! */
+// SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+void *narrow_candidate_datatypes_c::visit(fb_spec_init_c *symbol) {return narrow_spec_init(symbol, symbol->function_block_type_name, symbol->structure_initialization);}
 
 
 /*********************/
@@ -709,6 +722,7 @@
 }
 
 
+
 /************************************/
 /* B 1.5 Program organization units */
 /************************************/
@@ -739,6 +753,10 @@
 	symbol->fblock_body->accept(*this);
 	delete search_varfb_instance_type;
 	search_varfb_instance_type = 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];
 	return NULL;
 }
 
--- a/stage3/narrow_candidate_datatypes.hh	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage3/narrow_candidate_datatypes.hh	Thu Apr 04 09:45:11 2013 +0900
@@ -81,6 +81,9 @@
     void *narrow_binary_expression  (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false);
     void *narrow_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL);
 
+    void *narrow_spec_init(symbol_c *symbol, symbol_c *type_decl, symbol_c *init_value);
+    void *narrow_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init);
+
     void *narrow_conditional_flow_control_IL_instruction(symbol_c *symbol);
 
 
@@ -150,29 +153,30 @@
     /********************************/
 //  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); /* Not required. already handled by iterator_visitor_c base class */
     void *visit(simple_spec_init_c *symbol);
-//  void *visit(subrange_type_declaration_c *symbol);
-//  void *visit(subrange_spec_init_c *symbol);
-//  void *visit(subrange_specification_c *symbol);
+    void *visit(subrange_type_declaration_c *symbol);
+    void *visit(subrange_spec_init_c *symbol);
+    void *visit(subrange_specification_c *symbol);
     void *visit(subrange_c *symbol);
     void *visit(enumerated_type_declaration_c *symbol);
     void *visit(enumerated_spec_init_c *symbol);
     void *visit(enumerated_value_list_c *symbol);
 //  void *visit(enumerated_value_c *symbol);        /* Not required */
-//  void *visit(array_type_declaration_c *symbol);
-//  void *visit(array_spec_init_c *symbol);
+    void *visit(array_type_declaration_c *symbol);
+    void *visit(array_spec_init_c *symbol);
 //  void *visit(array_specification_c *symbol);
 //  void *visit(array_subrange_list_c *symbol);
 //  void *visit(array_initial_elements_list_c *symbol);
 //  void *visit(array_initial_elements_c *symbol);
-//  void *visit(structure_type_declaration_c *symbol);
-//  void *visit(initialized_structure_c *symbol);
+    void *visit(structure_type_declaration_c *symbol);
+    void *visit(initialized_structure_c *symbol);
 //  void *visit(structure_element_declaration_list_c *symbol);
 //  void *visit(structure_element_declaration_c *symbol);
 //  void *visit(structure_element_initialization_list_c *symbol);
 //  void *visit(structure_element_initialization_c *symbol);
 //  void *visit(string_type_declaration_c *symbol);
+    void *visit(fb_spec_init_c *symbol);
 
     /*********************/
     /* B 1.4 - Variables */
--- a/stage4/generate_c/generate_c.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage4/generate_c/generate_c.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -299,7 +299,7 @@
     //void *visit(var_declaration_list_c *symbol) {iterate through list}
 
     void *visit(fb_name_decl_c *symbol) {
-      print_list(symbol->fb_name_list, symbol->function_block_type_name); 
+      print_list(symbol->fb_name_list, spec_init_sperator_c::get_spec(symbol->fb_spec_init)); 
       return NULL;
     }
 
--- a/stage4/generate_c/generate_c_vardecl.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage4/generate_c/generate_c_vardecl.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -1258,8 +1258,10 @@
   return NULL;
 }
 
+
 void *visit(en_param_declaration_c *symbol) {
   TRACE("en_declaration_c");
+  update_type_init(symbol->type_decl);
   if (wanted_varformat == finterface_vf) {
     finterface_var_count++;
   }  
@@ -1267,7 +1269,7 @@
     if (wanted_varformat == finterface_vf) {
       s4o.print(nv->get());
       s4o.print("\n" + s4o.indent_spaces);
-      symbol->type->accept(*this);
+      this->current_var_type_symbol->accept(*this);
       s4o.print(" ");
       symbol->name->accept(*this);
     }
@@ -1279,11 +1281,11 @@
       if (wanted_varformat == local_vf) {
         s4o.print(DECLARE_VAR);
         s4o.print("(");
-        symbol->type->accept(*this);
+        this->current_var_type_symbol->accept(*this);
         s4o.print(",");
       }
       else if (wanted_varformat == localinit_vf) {
-        symbol->type->accept(*this);
+        this->current_var_type_symbol->accept(*this);
         s4o.print(" ");
       }
       print_variable_prefix();
@@ -1292,7 +1294,7 @@
         s4o.print(")\n");
       else {
         s4o.print(" = ");
-        symbol->value->accept(*this);
+        this->current_var_init_symbol->accept(*this);
         s4o.print(";\n");
       }
     }
@@ -1306,11 +1308,12 @@
       // s4o.print("EN = __BOOL_LITERAL(TRUE);");
       symbol->name->accept(*this);
       s4o.print(",");
-      symbol->value->accept(*this);
+      this->current_var_init_symbol->accept(*this);
       print_retain();
       s4o.print(")");
     }
   }
+  void_type_init();
   return NULL;
 }
 
@@ -1480,7 +1483,7 @@
   /* Start off by setting the current_var_type_symbol and
    * current_var_init_symbol private variables...
    */
-  update_type_init(symbol);
+  update_type_init(symbol->fb_spec_init);
 
   /* now to produce the c equivalent... */
   symbol->fb_name_list->accept(*this);
--- a/stage4/generate_c/generate_var_list.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage4/generate_c/generate_var_list.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -603,7 +603,7 @@
       /* Start off by setting the current_var_type_symbol and
        * current_var_init_symbol private variables...
        */
-      update_var_type_symbol(symbol);
+      update_var_type_symbol(symbol->fb_spec_init);
     
       /* now to produce the c equivalent... */
       declare_variables(symbol->fb_name_list);
@@ -731,7 +731,7 @@
       /* Start off by setting the current_var_type_symbol and
        * current_var_init_symbol private variables...
        */
-      update_var_type_symbol(symbol->type);
+      update_var_type_symbol(symbol->type_decl);
 
       /* now to produce the c equivalent... */
       declare_variable(symbol->name);
--- a/stage4/generate_iec/generate_iec.cc	Mon Mar 11 12:54:25 2013 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Thu Apr 04 09:45:11 2013 +0900
@@ -633,7 +633,16 @@
   return NULL;
 }
 
-
+/*  function_block_type_name ASSIGN structure_initialization */
+/* structure_initialization -> may be NULL ! */
+void *visit(fb_spec_init_c *symbol) {
+  symbol->function_block_type_name->accept(*this);
+  if (symbol->structure_initialization != NULL) {
+    s4o.print(" := ");
+    symbol->structure_initialization->accept(*this);
+  }
+  return NULL;
+}
 
 
 
@@ -722,9 +731,7 @@
   if (typeid(*(symbol->method)) == typeid(explicit_definition_c)) {
     symbol->name->accept(*this);
     s4o.print(" : ");
-    symbol->type->accept(*this);
-    s4o.print(" := ");
-    symbol->value->accept(*this);
+    symbol->type_decl->accept(*this);
   }
   return NULL;
 }
@@ -814,11 +821,7 @@
 void *visit(fb_name_decl_c *symbol) {
   symbol->fb_name_list->accept(*this);
   s4o.print(" : ");
-  symbol->function_block_type_name->accept(*this);
-  if (symbol->structure_initialization != NULL) {
-    s4o.print(" := ");
-    symbol->structure_initialization->accept(*this);
-  }
+  symbol->fb_spec_init->accept(*this);
   return NULL;
 }