Re-write of stage3 code (done by Manuele and I), re-write of search_varfb_instance_type_c (done by myself), and several other bug fixes.
authorMario de Sousa <msousa@fe.up.pt>
Wed, 01 Feb 2012 19:49:11 +0000
changeset 417 d48f53715f77
parent 416 0c2ef191b22a
child 418 2ac41d2cba91
Re-write of stage3 code (done by Manuele and I), re-write of search_varfb_instance_type_c (done by myself), and several other bug fixes.
absyntax/absyntax.cc
absyntax/absyntax.def
absyntax/absyntax.hh
absyntax/visitor.cc
absyntax_utils/get_sizeof_datatype.cc
absyntax_utils/search_base_type.cc
absyntax_utils/search_base_type.hh
absyntax_utils/search_constant_type.cc
absyntax_utils/search_constant_type.hh
absyntax_utils/search_var_instance_decl.cc
absyntax_utils/search_var_instance_decl.hh
absyntax_utils/search_varfb_instance_type.cc
absyntax_utils/search_varfb_instance_type.hh
stage1_2/iec_bison.yy
stage3/Makefile.am
stage3/Makefile.in
stage3/datatype_functions.cc
stage3/datatype_functions.hh
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
stage3/stage3.cc
stage3/stage3.hh
stage3/visit_expression_type.cc
stage3/visit_expression_type.hh
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_sfc.cc
stage4/generate_c/generate_c_st.cc
--- a/absyntax/absyntax.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -61,6 +61,7 @@
   this->last_line    = last_line;
   this->last_column  = last_column;
   this->last_order   = last_order;
+  this->datatype     = NULL;
 }
 
 
--- a/absyntax/absyntax.def	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.def	Wed Feb 01 19:49:11 2012 +0000
@@ -1047,12 +1047,12 @@
 /* nonformal_param_list -> may be NULL ! */
 /* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
  *       The IEC 61131-3 standard allows for overloaded standard functions. This means that some
- *       function calls are not compeletely defined by the name of the function being called,
+ *       function calls are not completely defined by the name of the function being called,
  *       and need to be disambiguated with using the data types of the parameters being passed.
- *       Stage 3 does this to verify semantic correctnes.
+ *       Stage 3 does this to verify semantic correctness.
  *       Stage 4 also needs to do this in order to determine which function to call.
  *       It does not make sense to determine the exact function being called twice (once in stage 3,
- *       and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration
+ *       and again in stage 4), so stage 3 will store this info in the parameter called_function_declaration
  *       for stage 4 to use it later on.
  */
 SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
--- a/absyntax/absyntax.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -47,6 +47,7 @@
 
 
 #include <stdio.h> // required for NULL
+#include <vector>
 
 /* Forward declaration of the visitor interface
  * dclared in the visitor.hh file
@@ -76,6 +77,9 @@
     int last_column;
     const char *last_file;  /* filename referenced by last line/column */
     long int last_order;    /* relative order in which it is read by lexcial analyser */
+    symbol_c * datatype;    /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */
+    std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
+
 
   public:
     /* default constructor */
--- a/absyntax/visitor.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/visitor.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -73,13 +73,13 @@
 #define SYM_LIST(class_name_c)	\
   void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_TOKEN(class_name_c)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF0(class_name_c)	\
-  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF1(class_name_c, ref1)	\
+#define SYM_TOKEN(class_name_c, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF0(class_name_c, ...)	\
+  void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF1(class_name_c, ref1, ...)	\
   void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
 #define SYM_REF2(class_name_c, ref1, ref2, ...)	\
@@ -136,13 +136,13 @@
 #define SYM_LIST(class_name_c)	\
   void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
 
-#define SYM_TOKEN(class_name_c)	\
+#define SYM_TOKEN(class_name_c, ...)	\
   void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_REF0(class_name_c)	\
+#define SYM_REF0(class_name_c, ...)	\
   void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_REF1(class_name_c, ref1)			\
+#define SYM_REF1(class_name_c, ref1, ...)			\
 void *iterator_visitor_c::visit(class_name_c *symbol) {	\
   if (symbol->ref1!=NULL) symbol->ref1->accept(*this);	\
   return NULL;						\
@@ -238,13 +238,13 @@
 #define SYM_LIST(class_name_c)	\
   void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
 
-#define SYM_TOKEN(class_name_c)	\
+#define SYM_TOKEN(class_name_c, ...)	\
   void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_REF0(class_name_c)	\
+#define SYM_REF0(class_name_c, ...)	\
   void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
 
-#define SYM_REF1(class_name_c, ref1)				\
+#define SYM_REF1(class_name_c, ref1, ...)				\
 void *search_visitor_c::visit(class_name_c *symbol) {		\
   if (symbol->ref1) return symbol->ref1->accept(*this);		\
   return NULL;							\
--- a/absyntax_utils/get_sizeof_datatype.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/get_sizeof_datatype.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -80,6 +80,7 @@
 /* tell stdint.h we want the definition of UINT64_MAX */
 #define __STDC_LIMIT_MACROS
 #include <stdint.h>  // get definition of uint64_t and UINT64_MAX
+#include <errno.h>
 
 
 #define ERROR error_exit(__FILE__,__LINE__)
@@ -158,8 +159,60 @@
 /* NOTE: all integer_c and real_c tokens will always be positive (i.e. no leading '-')
  * due to the way the source code is parsed by iec.flex.
  */
+
+/*
+ * IEC6113-3 and C++ use IEC 60559 to rappresent floating point data types
+ * REAL  => float       => single precision 	32 bit
+ * LREAL => double      => double precision 	64 bit
+ * ????? => long double => quadruple precision 128 bit
+ */
 void *get_sizeof_datatype_c::visit(real_c *symbol) {
-  return _encode_int(32);
+  char *endp;
+  long double ld_test;
+  double d_test;
+  float  f_test;
+
+  /* copy the original string, but leave out any underscores... */
+  char *sval, *oval;
+  const char *pval;
+  oval = sval = (char *)malloc(strlen(symbol->value)+1);
+  if (NULL ==  sval) ERROR;
+  
+  for (pval = symbol->value, sval = oval; *pval != '\0'; pval++) {
+    if ('_' != *pval) {*sval = *pval; sval++;}
+  }  
+  *sval = '\0';  
+  
+  sval = oval;
+  if ('\0' == *sval) ERROR;
+
+  /* now do the conversion using the new string... */
+  f_test = strtof(sval, &endp);
+  if (*endp != '\0') ERROR;
+  if (ERANGE != errno) {
+    /* No overflow/underflow! => It fits in a float! */
+    free(oval);
+    return _encode_int(32);
+  }
+  
+  d_test = strtod(sval, &endp);
+  if (*endp != '\0') ERROR;
+  if (ERANGE != errno) {
+    /* No overflow/underflow! => It fits in a double! */
+    free(oval);
+    return _encode_int(64);
+  }
+  
+  ld_test = strtold(sval, &endp);
+  if (*endp != '\0') ERROR;
+  if (ERANGE != errno) {
+    /* No overflow/underflow! => It fits in a long double! */
+    free(oval);
+    return _encode_int(128);
+  }
+
+  free(oval);
+  return _encode_int(65535); /* a very large number!!! */
 }
 
 void *get_sizeof_datatype_c::visit(neg_real_c *symbol) {
@@ -282,7 +335,7 @@
     if (('0' != *sval) && ('1' != *sval) && ('_' != *sval))
       ERROR;
 
-    if ('_' != *sval) bitsize ++; /* 1 bits per binary digit */
+    if ('_' != *sval) bitsize++; /* 1 bits per binary digit */
   }
 
   /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
--- a/absyntax_utils/search_base_type.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_base_type.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
 /*
  *  matiec - a compiler for the programming languages defined in IEC 61131-3
  *
- *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2003-2012  Mario de Sousa (msousa@fe.up.pt)
  *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -55,16 +55,29 @@
 
 search_base_type_c::search_base_type_c(void) {current_type_name = NULL;}
 
-void *search_base_type_c::visit(identifier_c *type_name) {
-  this->current_type_name = type_name;
-  /* look up the type declaration... */
-  symbol_c *type_decl = type_symtable.find_value(type_name);
-  if (type_decl == type_symtable.end_value())
-    /* Type declaration not found!! */
-    ERROR;
-
-  return type_decl->accept(*this);
-}
+
+
+
+symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) {
+  if (NULL == symbol)
+    return NULL;
+  
+  return (symbol_c *)symbol->accept(*this);
+}
+
+symbol_c *search_base_type_c::get_basetype_id  (symbol_c *symbol) {
+  if (NULL == symbol)
+    return NULL;
+  
+  current_type_name = NULL; /* just to be on the safe side... */
+  symbol->accept(*this);
+  return (symbol_c *)current_type_name;
+}
+
+
+/* Note by MJS: The following two functions definately do not belong in this class!! Maybe create a new utility class?
+ * I will need to clean this up when the opportunity arises!
+ */
 
 bool search_base_type_c::type_is_subrange(symbol_c* type_decl) {
   this->is_subrange = false;
@@ -78,6 +91,35 @@
   return this->is_enumerated;
 }
 
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+void *search_base_type_c::visit(identifier_c *type_name) {
+  symbol_c *type_decl;
+
+  this->current_type_name = type_name;
+  
+  /* look up the type declaration... */
+  type_decl = type_symtable.find_value(type_name);
+  if (type_decl != type_symtable.end_value())
+    return type_decl->accept(*this);
+    
+  type_decl = function_block_type_symtable.find_value(type_name);
+  if (type_decl != function_block_type_symtable.end_value())
+    return type_decl->accept(*this);
+  
+  /* Type declaration not found!! */
+    ERROR;
+    
+  return NULL;
+}
+
+
 /*********************/
 /* B 1.2 - Constants */
 /*********************/
@@ -205,8 +247,7 @@
 /* helper symbol for enumerated_specification->enumerated_spec_init */
 /* enumerated_value_list ',' enumerated_value */
 void *search_base_type_c::visit(enumerated_value_list_c *symbol) {
-  if (NULL == this->current_type_name) ERROR;
-  return (void *)this->current_type_name;
+  return (void *)symbol;
 }
 
 /* enumerated_type_name '#' identifier */
@@ -222,14 +263,16 @@
 /* array_specification [ASSIGN array_initialization} */
 /* array_initialization may be NULL ! */
 void *search_base_type_c::visit(array_spec_init_c *symbol) {
+  /* Note that the 'array_specification' may be either an identifier of a previsously defined array type, 
+   * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c, 
+   * especially if we are looking for the base class!
+   */  
   return symbol->array_specification->accept(*this);
 }
 
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
 void *search_base_type_c::visit(array_specification_c *symbol)	{
-  if (NULL == this->current_type_name)
-	this->current_type_name = symbol->non_generic_type_name;
-  return symbol->non_generic_type_name->accept(*this);
+  return symbol;
 }
 
 /* helper symbol for array_specification */
--- a/absyntax_utils/search_base_type.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_base_type.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
 /*
  *  matiec - a compiler for the programming languages defined in IEC 61131-3
  *
- *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2003-2012  Mario de Sousa (msousa@fe.up.pt)
  *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -60,18 +60,27 @@
     search_base_type_c(void);
 
   public:
-    void *visit(identifier_c *type_name);
+    symbol_c *get_basetype_decl(symbol_c *symbol);
+    symbol_c *get_basetype_id  (symbol_c *symbol);
     bool type_is_subrange(symbol_c* type_decl);
     bool type_is_enumerated(symbol_c* type_decl);
 
   public:
-    /*********************/
-    /* B 1.2 - Constants */
-    /*********************/
-
-    /******************************/
-    /* B 1.2.1 - Numeric Literals */
-    /******************************/
+  /*************************/
+  /* B.1 - Common elements */
+  /*************************/
+  /*******************************************/
+  /* B 1.1 - Letters, digits and identifiers */
+  /*******************************************/
+    void *visit(identifier_c *type_name);
+
+    
+  /*********************/
+  /* B 1.2 - Constants */
+  /*********************/
+  /******************************/
+  /* B 1.2.1 - Numeric Literals */
+  /******************************/
      /* Numeric literals without any explicit type cast have unknown data type, 
       * so we continue considering them as their own basic data types until
       * they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
--- a/absyntax_utils/search_constant_type.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_constant_type.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -155,16 +155,26 @@
 time_type_name_c     search_constant_type_c::time_type_name;
 int_type_name_c      search_constant_type_c::int_type_name;
 
-// safebool_type_name_c    search_constant_type_c::safebool_type_name;
-  /* The following is required because the expression (TOD_var - TOD_var) will result in a data type
-   *  (in this case, TIME) that is neither of the expression elements...
-   */
 safetime_type_name_c     search_constant_type_c::safetime_type_name;
 safetod_type_name_c      search_constant_type_c::safetod_type_name;
 safedt_type_name_c       search_constant_type_c::safedt_type_name;
+safedate_type_name_c     search_constant_type_c::safedate_type_name;
+safereal_type_name_c     search_constant_type_c::safereal_type_name;
+safesint_type_name_c     search_constant_type_c::safesint_type_name;
+safelint_type_name_c     search_constant_type_c::safelint_type_name;
+safedint_type_name_c     search_constant_type_c::safedint_type_name;
+safedword_type_name_c    search_constant_type_c::safedword_type_name;
+safeudint_type_name_c    search_constant_type_c::safeudint_type_name;
+safeword_type_name_c     search_constant_type_c::safeword_type_name;
+safewstring_type_name_c  search_constant_type_c::safewstring_type_name;
+safestring_type_name_c   search_constant_type_c::safestring_type_name;
+safelword_type_name_c    search_constant_type_c::safelword_type_name;
+safeuint_type_name_c     search_constant_type_c::safeuint_type_name;
+safelreal_type_name_c    search_constant_type_c::safelreal_type_name;
+safebyte_type_name_c     search_constant_type_c::safebyte_type_name;
+safeusint_type_name_c    search_constant_type_c::safeusint_type_name;
+safeulint_type_name_c    search_constant_type_c::safeulint_type_name;
+safebool_type_name_c     search_constant_type_c::safebool_type_name;
+safeint_type_name_c      search_constant_type_c::safeint_type_name;
 
 
-
-/* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
-/* It should then move to search_expression_type_c                               */
-integer_c search_constant_type_c::integer("1");
--- a/absyntax_utils/search_constant_type.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_constant_type.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -95,8 +95,24 @@
   static safetime_type_name_c     safetime_type_name;
   static safetod_type_name_c      safetod_type_name;
   static safedt_type_name_c       safedt_type_name;
-
-
+  static safedate_type_name_c     safedate_type_name;
+  static safereal_type_name_c     safereal_type_name;
+  static safesint_type_name_c     safesint_type_name;
+  static safelint_type_name_c     safelint_type_name;
+  static safedint_type_name_c     safedint_type_name;
+  static safedword_type_name_c    safedword_type_name;
+  static safeudint_type_name_c    safeudint_type_name;
+  static safeword_type_name_c     safeword_type_name;
+  static safewstring_type_name_c  safewstring_type_name;
+  static safestring_type_name_c   safestring_type_name;
+  static safelword_type_name_c    safelword_type_name;
+  static safeuint_type_name_c     safeuint_type_name;
+  static safelreal_type_name_c    safelreal_type_name;
+  static safebyte_type_name_c     safebyte_type_name;
+  static safeusint_type_name_c    safeusint_type_name;
+  static safeulint_type_name_c    safeulint_type_name;
+  static safebool_type_name_c     safebool_type_name;
+  static safeint_type_name_c      safeint_type_name;
 
   public:
     symbol_c *get_type(symbol_c *constant);
@@ -163,5 +179,4 @@
 };  // search_constant_type_c
 
 
-
 #endif /* ifndef _SEARCH_CONSTANT_TYPE_HH */
--- a/absyntax_utils/search_var_instance_decl.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_var_instance_decl.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -77,10 +77,14 @@
   return (symbol_c *)search_scope->accept(*this);
 }
 
-unsigned int search_var_instance_decl_c::get_vartype(void) {
+unsigned int search_var_instance_decl_c::get_vartype(symbol_c *variable_instance_name) {
+  this->current_vartype = none_vt;
+  this->search_name = variable_instance_name;
+  search_scope->accept(*this);
   return current_vartype;
 }
 
+
 /***************************/
 /* B 0 - Programming Model */
 /***************************/
--- a/absyntax_utils/search_var_instance_decl.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_var_instance_decl.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -77,7 +77,8 @@
   public:
     search_var_instance_decl_c(symbol_c *search_scope);
     symbol_c *get_decl(symbol_c *variable_instance_name);
-    unsigned int get_vartype(void);
+    
+    unsigned int get_vartype(symbol_c *variable_instance_name);
 
   public:
 
--- a/absyntax_utils/search_varfb_instance_type.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_varfb_instance_type.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
 /*
  *  matiec - a compiler for the programming languages defined in IEC 61131-3
  *
- *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2003-2012  Mario de Sousa (msousa@fe.up.pt)
  *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -75,225 +75,134 @@
  *
  * Member functions:
  * ================
+ *   get_basetype_id()    ---> returns 2A   (implemented, although currently it is not needed! )
  *   get_basetype_decl()  ---> returns 2B 
  *   get_type_id()        ---> returns 1A
  * 
- *   Since we haven't yet needed them, we don't yet implement
- *   get_basetype_id()    ----> would return 2A
- *   get_type_decl()      ----> would return 1B
+ *   Since we haven't yet needed it, we don't yet implement
+ *   get_type_decl()      ---> returns 1B 
  */ 
 
 
-/*
- * TODO: this code has a memory leak...
- *       We call 'new' in several locations, but bever get to 'delete' the object instances...
- */
+
 #include "absyntax_utils.hh"
 
 
+void search_varfb_instance_type_c::init(void) {
+  this->current_type_id        = NULL;
+  this->current_basetype_id    = NULL;
+  this->current_basetype_decl  = NULL;
+  this->current_field_selector = NULL;
+  this->is_complex = false;
+}
+
+
 search_varfb_instance_type_c::search_varfb_instance_type_c(symbol_c *search_scope): search_var_instance_decl(search_scope) {
-  this->decompose_var_instance_name = NULL;
-  this->current_structelement_name = NULL;
-  this->current_typeid = NULL;
-  this->current_basetypeid = NULL;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_decl(symbol_c *variable_name) {
-  this->current_structelement_name = NULL;
-  this->current_typeid = NULL;
-  this->current_basetypeid = NULL;
-  this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
-  if (NULL == decompose_var_instance_name) ERROR;
-
-  /* find the part of the variable name that will appear in the
-   * variable declaration, for e.g., in window.point.x, this would be
-   * window!
-   */
-  symbol_c *var_name_part = decompose_var_instance_name->next_part();
-  if (NULL == var_name_part) ERROR;
-
-  /* Now we try to find the variable instance declaration, to determine its type... */
-  symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
-  if (NULL == var_decl) ERROR;
-
-  /* if it is a struct or function block, we must search the type
-   * of the struct or function block member.
-   * This is done by this class visiting the var_decl.
-   * This class, while visiting, will recursively call
-   * decompose_var_instance_name->get_next() when and if required...
-   */
-  symbol_c *res = (symbol_c *)var_decl->accept(*this);
-  /* NOTE: A Null result is not really an internal compiler error, but rather an error in 
-   * the IEC 61131-3 source code being compiled. This means we cannot just abort the compiler with ERROR.
-   * //   if (NULL == res) ERROR;
-   */
-  if (NULL == res) return NULL;
-
-  /* make sure that we have decomposed all structure elements of the variable name */
-  symbol_c *var_name = decompose_var_instance_name->next_part();
-  /* NOTE: A non-NULL result is not really an internal compiler error, but rather an error in 
-   * the IEC 61131-3 source code being compiled. 
-   *  (for example, 'int_var.struct_elem' in the source code, when 'int_var' is a simple integer,
-   *   and not a structure, will result in this result being non-NULL!)
-   * This means we cannot just abort the compiler with ERROR.
-   * //   if (NULL != var_name) ERROR;
-   */
-  if (NULL != var_name) return NULL;
-
-  return res;
+  this->init();
+}
+
+
+/* We expect to be passed a symbolic_variable_c */
+symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
+  this->init();
+  variable_name->accept(*this);
+  return current_type_id;
+}
+
+
+symbol_c *search_varfb_instance_type_c::get_basetype_id(symbol_c *variable_name) {
+  this->init();
+  variable_name->accept(*this);
+  return current_basetype_id;
 }
 
 
 symbol_c *search_varfb_instance_type_c::get_basetype_decl(symbol_c *variable_name) {
-  symbol_c *res = get_type_decl(variable_name);
-  if (NULL == res) return NULL;
-  return (symbol_c *)base_type(res);
+  this->init();
+  variable_name->accept(*this);
+  return current_basetype_decl;
 }  
 
 
+
+
+
 unsigned int search_varfb_instance_type_c::get_vartype(symbol_c *variable_name) {
-  this->current_structelement_name = NULL;
-  this->current_typeid = NULL;
-  this->current_basetypeid = NULL;
-  this->is_complex = false;
-  this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
-  if (NULL == decompose_var_instance_name) ERROR;
-
-  /* find the part of the variable name that will appear in the
-   * variable declaration, for e.g., in window.point.x, this would be
-   * window!
-   */
-  symbol_c *var_name_part = decompose_var_instance_name->next_part();
-  if (NULL == var_name_part) ERROR;
-
-  /* Now we try to find the variable instance declaration, to determine its type... */
-  symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
-  if (NULL == var_decl) {
-    /* variable instance declaration not found! */
-    return 0;
-  }
-
-  /* if it is a struct or function block, we must search the type
-   * of the struct or function block member.
-   * This is done by this class visiting the var_decl.
-   * This class, while visiting, will recursively call
-   * decompose_var_instance_name->get_next() when and if required...
-   */
-  var_decl->accept(*this);
-  unsigned int res = search_var_instance_decl.get_vartype();
-  
-  /* make sure that we have decomposed all structure elements of the variable name */
-  symbol_c *var_name = decompose_var_instance_name->next_part();
-  if (NULL != var_name) ERROR;
-
-  return res;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
-  this->current_typeid = NULL;
-  symbol_c *vartype = this->get_type_decl(variable_name);
-  if (this->current_typeid != NULL)
-    return this->current_typeid;
-  else
-    return vartype;
-}
+  this->init();
+  return search_var_instance_decl.get_vartype(variable_name);
+}
+
+
 
 bool search_varfb_instance_type_c::type_is_complex(void) {
   return this->is_complex;
 }
 
-/* a helper function... */
-void *search_varfb_instance_type_c::visit_list(list_c *list)	{
-  if (NULL == current_structelement_name) ERROR;
-
-  for(int i = 0; i < list->n; i++) {
-    void *res = list->elements[i]->accept(*this);
-    if (res != NULL)
-      return res;
-  }
-  /* not found! */
-  return NULL;
-}
-
-/* a helper function... */
-void *search_varfb_instance_type_c::base_type(symbol_c *symbol)	{
-    search_base_type_c search_base_type;
-    return symbol->accept(search_base_type);
-}
-
-/* We override the base class' visitor to identifier_c.
- * This is so because the base class does not consider a function block
- * to be a type, unlike this class that allows a variable instance
- * of a function block type...
- */
-void *search_varfb_instance_type_c::visit(identifier_c *type_name) {
-  /* we only store the new type id if none had been found yet.
-   * Since we will recursively carry on looking at the base type 
-   * to determine the base type declaration and id, we must only set this variable
-   * the first time.
-   * e.g. TYPE myint1_t : int    := 1;
-   *           myint2_t : int1_t := 2;
-   *           myint3_t : int2_t := 3;
-   *      END_TYPE;
-   *      VAR
-   *          myint1 : myint1_t;
-   *          myint2 : myint2_t;
-   *          myint3 : myint3_t;
-   *      END_VAR
-   *        
-   *     If we ask for typeid of     myint3, it must return myint3_t
-   *     If we ask for basetypeid of myint3, it must return int
-   *
-   *     When determining the data type of myint3, we will recursively go all the way
-   *     down to int, but we must still only store myint3_t as the base type id.
-   */
-  if (NULL == this->current_typeid)
-    this->current_typeid = type_name;
-  this->current_basetypeid = type_name;
-
-  /* look up the type declaration... */
-  symbol_c *fb_decl = function_block_type_symtable.find_value(type_name);
-  if (fb_decl != function_block_type_symtable.end_value())
-    /* Type declaration found!! */
-    return fb_decl->accept(*this);
-
-  /* No. It is not a function block, so we let
-   * the base class take care of it...
-   */
-  return search_base_type_c::visit(type_name);
-}
+
+
+
+
+
+
+
+
 
 /********************************/
 /* B 1.3.3 - Derived data types */
 /********************************/
-
 /*  identifier ':' array_spec_init */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a 
+ * array_type_declaration_c, but for now, let's leave it in...
+ */
 void *search_varfb_instance_type_c::visit(array_type_declaration_c *symbol) {
-  return symbol->array_spec_init->accept(*this);
+  ERROR;
+  return NULL;
 }
     
 /* array_specification [ASSIGN array_initialization] */
 /* array_initialization may be NULL ! */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a 
+ * array_spec_init_c, but for now, let's leave it in...
+ */
 void *search_varfb_instance_type_c::visit(array_spec_init_c *symbol) {
-  return symbol->array_specification->accept(*this);
+  /* Note that the 'array_specification' may be either an identifier of a previsously defined array type, 
+   * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c, 
+   * especially if we are looking for the base class!
+   */
+  ERROR;
+  return NULL;
 }
 
 /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+/* NOTE: This method will be reached after being called from the 
+ * search_varfb_instance_type_c::visit(array_variable_c *symbol)
+ * method, so we must return the data type of the data stored in the array, 
+ * and not the data type of the array itself!
+ */
 void *search_varfb_instance_type_c::visit(array_specification_c *symbol) {
-  this->is_complex = true;
-  this->current_typeid = symbol;
-  return symbol->non_generic_type_name->accept(*this);
-}
+  /* found the type of the element we were looking for! */
+  current_type_id       = symbol->non_generic_type_name;
+  current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+  current_basetype_id   = search_base_type.get_basetype_id  (current_type_id);
+    
+  return NULL; 
+}
+
 
 /*  structure_type_name ':' structure_specification */
 /* NOTE: this is only used inside a TYPE ... END_TYPE declaration. 
  * It is never used directly when declaring a new variable! 
  */
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a 
+ * structure_type_declaration_c, but for now, let's leave it in...
+ */
 void *search_varfb_instance_type_c::visit(structure_type_declaration_c *symbol) {
-  this->is_complex = true;
-
-  if (NULL == current_structelement_name) ERROR;
-  return symbol->structure_specification->accept(*this);
+  if (NULL == current_field_selector) ERROR;
+  symbol->structure_specification->accept(*this);
+  return NULL;
   /* NOTE: structure_specification will point to either a
    *       initialized_structure_c
    *       OR A
@@ -304,51 +213,42 @@
 /* structure_type_name ASSIGN structure_initialization */
 /* structure_initialization may be NULL ! */
 // SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
-/* NOTE: only the initialized structure is ever used when declaring a new variable instance */
+/* NOTE: only the initialized structure is never used when declaring a new variable instance */
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a 
+ * initialized_structure_c, but for now, let's leave it in...
+ */
 void *search_varfb_instance_type_c::visit(initialized_structure_c *symbol)	{
-  this->is_complex = true;
-  if (NULL != current_structelement_name) ERROR;
-  
-  /* make sure that we have decomposed all structure elements of the variable name */
-  symbol_c *var_name = decompose_var_instance_name->next_part();
-  if (NULL == var_name) {
-    /* this is it... !
-     * No need to look any further...
-     * Note also that, unlike for the struct types, a function block may
-     * not be defined based on another (i.e. no inheritance is allowed),
-     * so this function block is already the most base type.
-     * We simply return it.
-     */
-    return (void *)symbol;
-  }
-
-  /* reset current_type_id because of new structure element part */
-  this->current_typeid = NULL;
-
-  /* look for the var_name in the structure declaration */
-  current_structelement_name = var_name;
-
-  /* recursively find out the data type of current_structelement_name... */
-  return symbol->structure_type_name->accept(*this);
+  if (NULL != current_field_selector) ERROR;
+  
+  /* recursively find out the data type of current_field_selector... */
+  symbol->structure_type_name->accept(*this);
+  return NULL;
 }
 
 /* helper symbol for structure_declaration */
 /* structure_declaration:  STRUCT structure_element_declaration_list END_STRUCT */
 /* structure_element_declaration_list structure_element_declaration ';' */
 void *search_varfb_instance_type_c::visit(structure_element_declaration_list_c *symbol)	{
-  if (NULL == current_structelement_name) ERROR;
+  if (NULL == current_field_selector) ERROR;
+
   /* now search the structure declaration */
-  return visit_list(symbol);
+  for(int i = 0; i < symbol->n; i++) {
+    symbol->elements[i]->accept(*this);
+  }
+  
+  return NULL;
 }
 
 /*  structure_element_name ':' spec_init */
 void *search_varfb_instance_type_c::visit(structure_element_declaration_c *symbol) {
-  if (NULL == current_structelement_name) ERROR;
-
-  if (compare_identifiers(symbol->structure_element_name, current_structelement_name) == 0) {
-    current_structelement_name = NULL;
+  if (NULL == current_field_selector) ERROR;
+
+  if (compare_identifiers(symbol->structure_element_name, current_field_selector) == 0) {
     /* found the type of the element we were looking for! */
-    return symbol->spec_init->accept(*this);
+    current_type_id       = symbol->spec_init;
+    current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+    current_basetype_id   = search_base_type.get_basetype_id  (current_type_id);
   }  
 
   /* Did not find the type of the element we were looking for! */
@@ -364,6 +264,79 @@
 void *search_varfb_instance_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */
 
 
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+// SYM_REF1(symbolic_variable_c, var_name)
+void *search_varfb_instance_type_c::visit(symbolic_variable_c *symbol) {
+  /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */
+  current_type_id       = search_var_instance_decl.get_decl (symbol->var_name);
+  current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+  current_basetype_id   = search_base_type.get_basetype_id  (current_type_id);
+    
+  if (NULL == current_type_id) ERROR; /* why should this be an error? what if the variable has not been declared? */
+
+  return NULL;
+}
+
+/********************************************/
+/* B.1.4.1   Directly Represented Variables */
+/********************************************/
+// SYM_TOKEN(direct_variable_c)
+/* We do not yet handle this. Will we ever need to handle it, as the data type of the direct variable is
+ * directly obtainable from the syntax of the direct variable itself?
+ */
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/*  subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+/* NOTE: when passed a array_variable_c, which represents some IEC61131-3 code similar to X[42]
+ * we must return the data type of the value _stored_ in the array.
+ * If you want to get the data type of the array itself (i.e. just the X variable, without the [42])
+ * then this class must be called with the identifier_c 'X'.
+ */
+void *search_varfb_instance_type_c::visit(array_variable_c *symbol) {
+  this->is_complex = true;
+
+  /* determine the data type of the subscripted_variable... 
+   * This should be an array_specification_c
+   *    ARRAY [xx..yy] OF Stored_Data_Type
+   */
+  symbol->subscripted_variable->accept(*this);
+  
+  /* Now we determine the 'Stored_Data_Type', i.e. the data type of the variable stored in the array. */
+  if (NULL != current_basetype_decl) {
+    current_basetype_decl->accept(*this);
+  }
+  
+  return NULL;
+}
+
+
+/*  record_variable '.' field_selector */
+/*  WARNING: input and/or output variables of function blocks
+ *           may be accessed as fields of a structured variable!
+ *           Code handling a structured_variable_c must take
+ *           this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+void *search_varfb_instance_type_c::visit(structured_variable_c *symbol) {
+  this->is_complex = true;
+  symbol->record_variable->accept(*this);
+  
+  /* Now we search for the data type of the field... But only if we were able to determine the data type of the variable */
+  if (NULL != current_basetype_decl) {
+    current_field_selector = symbol->field_selector;
+    current_basetype_decl->accept(*this);
+    current_field_selector = NULL;
+  }
+  
+  return NULL;
+}
+
+
 
 /**************************************/
 /* B.1.5 - Program organization units */
@@ -371,46 +344,18 @@
 /*****************************/
 /* B 1.5.2 - Function Blocks */
 /*****************************/
+
 /*  FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
 // SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
 void *search_varfb_instance_type_c::visit(function_block_declaration_c *symbol) {
-  /* make sure that we have decomposed all structure elements of the variable name */
-  symbol_c *var_name = decompose_var_instance_name->next_part();
-  if (NULL == var_name) {
-    /* this is it... !
-     * No need to look any further...
-     * Note also that, unlike for the struct types, a function block may
-     * not be defined based on another (i.e. no inheritance is allowed),
-     * so this function block is already the most base type.
-     * We simply return it.
-     */
-    return (void *)symbol;
-   }
-
-   /* reset current_type_id because of new structure element part */
-   this->current_typeid = NULL;
-
-   /* now search the function block declaration for the variable... */
-   search_var_instance_decl_c search_decl(symbol);
-   symbol_c *var_decl = search_decl.get_decl(var_name);
-   if (NULL == var_decl) {
-     /* variable instance declaration not found! */
-     return NULL;
-   }
-#if 0
-   /* We have found the declaration.
-    * Should we look any further?
-    */
-   var_name = decompose_var_instance_name->next_part();
-   if (NULL == var_name) {
-     /* this is it... ! */
-     return base_type(var_decl);
-   }
-
-  current_structelement_name = var_name;
-  /* recursively find out the data type of var_name... */
-  return symbol->var_declarations->accept(*this);
-#endif
-  /* carry on recursively, in case the variable has more elements to be decomposed... */
-  return var_decl->accept(*this);
-}
+  if (NULL == current_field_selector) ERROR;
+
+  /* now search the function block declaration for the variable... */
+  /* If not found, these pointers will all be set to NULL!! */
+  search_var_instance_decl_c search_decl(symbol);
+  current_type_id       = search_decl.get_decl(current_field_selector);
+  current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+  current_basetype_id   = search_base_type.get_basetype_id  (current_type_id);
+  
+  return NULL;
+}
--- a/absyntax_utils/search_varfb_instance_type.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_varfb_instance_type.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
 /*
  *  matiec - a compiler for the programming languages defined in IEC 61131-3
  *
- *  Copyright (C) 2003-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2003-2012  Mario de Sousa (msousa@fe.up.pt)
  *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -77,28 +77,37 @@
  *
  * Member functions:
  * ================
+ *   get_basetype_id()    ---> returns 2A   (implemented, although currently it is not needed! )
  *   get_basetype_decl()  ---> returns 2B 
  *   get_type_id()        ---> returns 1A
  * 
- *   Since we haven't yet needed them, we don't yet implement
- *   get_basetype_id()    ----> would return 2A
- *   get_type_decl()      ----> would return 1B
+ *   Since we haven't yet needed it, we don't yet implement
+ *   get_type_decl()      ---> returns 1B 
  */ 
 
-class search_varfb_instance_type_c: public search_base_type_c {
+class search_varfb_instance_type_c : null_visitor_c {
 
   private:
     search_var_instance_decl_c search_var_instance_decl;
-    decompose_var_instance_name_c *decompose_var_instance_name;
-    symbol_c *current_structelement_name;
-    symbol_c *current_typeid;
-    symbol_c *current_basetypeid;
+    search_base_type_c         search_base_type;
+
+//  symbol_c *current_type_decl;
+    symbol_c *current_type_id;
+    symbol_c *current_basetype_decl;
+    symbol_c *current_basetype_id;
+    
+    symbol_c *current_field_selector;
+
     bool is_complex;
+    
+    /* sets all the above variables to NULL, or false */
+    void init(void);
 
   public:
     search_varfb_instance_type_c(symbol_c *search_scope);
     symbol_c *get_basetype_decl(symbol_c *variable_name);
-    symbol_c *get_type_decl(symbol_c *variable_name);
+    symbol_c *get_basetype_id  (symbol_c *variable_name);
+//     symbol_c *get_type_decl(symbol_c *variable_name);
     symbol_c *get_type_id(symbol_c *variable_name);
 
     /* NOTE: this function should be remvoed/deleted.
@@ -130,12 +139,11 @@
      * to be a type, unlike this class that allows a variable instance
      * of a function block type...
      */
-    void *visit(identifier_c *type_name);
+//     void *visit(identifier_c *type_name);
 
     /********************************/
     /* B 1.3.3 - Derived data types */
     /********************************/
-    
     /*  identifier ':' array_spec_init */
     void *visit(array_type_declaration_c *symbol);
     
@@ -170,7 +178,20 @@
     void *visit(structure_element_initialization_c *symbol); /* should never get called... */
 
 
-
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol);
+
+    /********************************************/
+    /* B.1.4.1   Directly Represented Variables */
+    /********************************************/
+    /*************************************/
+    /* B 1.4.2 - Multi-element variables */
+    /*************************************/
+    void *visit(array_variable_c *symbol);
+    void *visit(structured_variable_c *symbol);
+    
     /**************************************/
     /* B.1.5 - Program organization units */
     /**************************************/
--- a/stage1_2/iec_bison.yy	Wed Feb 01 13:01:08 2012 +0000
+++ b/stage1_2/iec_bison.yy	Wed Feb 01 19:49:11 2012 +0000
@@ -2791,7 +2791,7 @@
 | signed_integer DOTDOT error
 	{$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for upper bound in subrange definition.");}
-	 else {print_err_msg(locf(@3), locl(@3), "invalid value for upper bound in subrange definition."); yyclearin;}
+	 else {print_err_msg(locf(@3), locl(@3), "invalid value for lower bound in subrange definition."); yyclearin;}
 	 yyerrok;
 	}
 /* ERROR_CHECK_END */
--- a/stage3/Makefile.am	Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/Makefile.am	Wed Feb 01 19:49:11 2012 +0000
@@ -4,5 +4,8 @@
 
 libstage3_a_SOURCES = \
 	stage3.cc \
-	visit_expression_type.cc 
+	fill_candidate_datatypes.cc \
+	narrow_candidate_datatypes.cc \
+	print_datatypes_error.cc \
+	datatype_functions.cc
 
--- a/stage3/Makefile.in	Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/Makefile.in	Wed Feb 01 19:49:11 2012 +0000
@@ -33,7 +33,7 @@
 PRE_UNINSTALL = :
 POST_UNINSTALL = :
 DIST_COMMON = $(srcdir)/../common.mk $(srcdir)/Makefile.am \
-	$(srcdir)/Makefile.in
+	$(srcdir)/Makefile.in TODO
 subdir = stage3
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -71,7 +71,9 @@
 libstage3_a_AR = $(AR) $(ARFLAGS)
 libstage3_a_LIBADD =
 am_libstage3_a_OBJECTS = stage3.$(OBJEXT) \
-	visit_expression_type.$(OBJEXT)
+	fill_candidate_datatypes.$(OBJEXT) \
+	narrow_candidate_datatypes.$(OBJEXT) \
+	print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT)
 libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
 depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -188,7 +190,10 @@
 lib_LIBRARIES = libstage3.a
 libstage3_a_SOURCES = \
 	stage3.cc \
-	visit_expression_type.cc 
+	fill_candidate_datatypes.cc \
+	narrow_candidate_datatypes.cc \
+	print_datatypes_error.cc \
+	datatype_functions.cc
 
 all: all-am
 
@@ -267,8 +272,11 @@
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/narrow_candidate_datatypes.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_datatypes_error.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stage3.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visit_expression_type.Po@am__quote@
 
 .cc.o:
 @am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/datatype_functions.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,620 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti  (conti.ma@alice.it)
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+#include "datatype_functions.hh"
+#include "../absyntax_utils/absyntax_utils.hh"
+
+/*
+ * 2.5.1.5.6 Functions of time data types
+ * Table 30 - page 64
+ */
+
+const struct widen_entry widen_ADD_table[] = {
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::time_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::tod_type_name,             &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::dt_type_name,              &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::safetod_type_name,         &search_constant_type_c::safetod_type_name  },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::safedt_type_name,          &search_constant_type_c::safedt_type_name   },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::time_type_name,            &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::time_type_name,            &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::safetime_type_name,        &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safetod_type_name  },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::time_type_name,            &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::time_type_name,            &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::safetime_type_name,        &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safedt_type_name   },
+    { NULL, NULL, NULL },
+};
+
+
+const struct widen_entry widen_SUB_table[] = {
+	{ &search_constant_type_c::time_type_name,          &search_constant_type_c::time_type_name,            &search_constant_type_c::time_type_name     },
+	{ &search_constant_type_c::tod_type_name,           &search_constant_type_c::tod_type_name,             &search_constant_type_c::tod_type_name      },
+	{ &search_constant_type_c::dt_type_name,            &search_constant_type_c::dt_type_name,              &search_constant_type_c::dt_type_name       },
+	{ &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safetime_type_name },
+	{ &search_constant_type_c::safetod_type_name,       &search_constant_type_c::safetod_type_name,         &search_constant_type_c::safetod_type_name  },
+	{ &search_constant_type_c::safedt_type_name,        &search_constant_type_c::safedt_type_name,          &search_constant_type_c::safedt_type_name   },
+
+	{ &search_constant_type_c::tod_type_name,           &search_constant_type_c::time_type_name,            &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::time_type_name,            &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::safetime_type_name,        &search_constant_type_c::tod_type_name      },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safetod_type_name  },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::time_type_name,            &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::time_type_name,            &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::safetime_type_name,        &search_constant_type_c::dt_type_name       },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::safetime_type_name,        &search_constant_type_c::safedt_type_name   },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::tod_type_name,             &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::tod_type_name,             &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::tod_type_name,           &search_constant_type_c::safetod_type_name,         &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safetod_type_name,       &search_constant_type_c::safetod_type_name,         &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::date_type_name,          &search_constant_type_c::date_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safedate_type_name,      &search_constant_type_c::date_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::date_type_name,          &search_constant_type_c::safedate_type_name,        &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safedate_type_name,      &search_constant_type_c::safedate_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::dt_type_name,              &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::dt_type_name,              &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::dt_type_name,            &search_constant_type_c::safedt_type_name,          &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::safedt_type_name,        &search_constant_type_c::safedt_type_name,          &search_constant_type_c::safetime_type_name },
+    { NULL, NULL, NULL },
+};
+
+const struct widen_entry widen_MUL_table[] = {
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::lreal_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::real_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::dint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::int_type_name,             &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::sint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::ulint_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::udint_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::uint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::usint_type_name,           &search_constant_type_c::time_type_name     },
+
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::lreal_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::real_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::dint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::int_type_name,             &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::sint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::ulint_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::udint_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::uint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::usint_type_name,           &search_constant_type_c::safetime_type_name },
+
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safelreal_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safereal_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safedint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeint_type_name,         &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safesint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeulint_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeudint_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeuint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeusint_type_name,       &search_constant_type_c::safetime_type_name },
+
+    { NULL, NULL, NULL },
+};
+
+const struct widen_entry widen_DIV_table[] = {
+	{ &search_constant_type_c::time_type_name,          &search_constant_type_c::lreal_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::real_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::dint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::int_type_name,             &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::sint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::ulint_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::udint_type_name,           &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::uint_type_name,            &search_constant_type_c::time_type_name     },
+    { &search_constant_type_c::time_type_name,          &search_constant_type_c::usint_type_name,           &search_constant_type_c::time_type_name     },
+
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::lreal_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::real_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::dint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::int_type_name,             &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::sint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::ulint_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::udint_type_name,           &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::uint_type_name,            &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::usint_type_name,           &search_constant_type_c::safetime_type_name },
+
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safelreal_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safereal_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safedint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeint_type_name,         &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safesint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeulint_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeudint_type_name,       &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeuint_type_name,        &search_constant_type_c::safetime_type_name },
+    { &search_constant_type_c::safetime_type_name,      &search_constant_type_c::safeusint_type_name,       &search_constant_type_c::safetime_type_name },
+
+    { NULL, NULL, NULL },
+};
+
+/* NOTE on data type handling and literals...
+ * ==========================================
+ *
+ * Literals that are explicitly type cast
+ *   e.g.:   BYTE#42
+ *           INT#65
+ *           TIME#45h23m
+ *               etc...
+ *  are NOT considered literals in the following code.
+ *  Since they are type cast, and their data type is fixed and well known,
+ *  they are treated as a variable of that data type (except when determining lvalues)
+ *  In other words, when calling search_constant_type_c on these constants, it returns
+ *  a xxxxx_type_name_c, and not one of the xxxx_literal_c !
+ *
+ *  When the following code handles a literal, it is really a literal of unknown data type.
+ *    e.g.   42, may be considered an int, a byte, a word, etc...
+ *
+ * NOTE: type_symbol == NULL is valid!
+ *       This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program.
+ *       This will not be of any type, so we always return false.
+ */
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  return is_ANY_MAGNITUDE_type(type_symbol)
+      || is_ANY_BIT_type      (type_symbol)
+      || is_ANY_STRING_type   (type_symbol)
+      || is_ANY_DATE_type     (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  return is_ANY_SAFEMAGNITUDE_type(type_symbol)
+      || is_ANY_SAFEBIT_type      (type_symbol)
+      || is_ANY_SAFESTRING_type   (type_symbol)
+      || is_ANY_SAFEDATE_type     (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  /* NOTE: doing
+   *          return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type()
+   *       is incorrect, as the literals would never be considered compatible...
+   */
+  return is_ANY_MAGNITUDE_compatible(type_symbol)
+      || is_ANY_BIT_compatible      (type_symbol)
+      || is_ANY_STRING_compatible   (type_symbol)
+      || is_ANY_DATE_compatible     (type_symbol);
+}
+
+
+/* A helper function... */
+bool is_ANY_MAGNITUDE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
+  return is_ANY_NUM_type(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
+  return is_ANY_SAFENUM_type(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_MAGNITUDE_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFEMAGNITUDE_type(type_symbol))              {return true;}
+
+  return is_ANY_NUM_compatible(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_NUM_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_REAL_type(type_symbol))                       {return true;}
+  if (is_ANY_INT_type(type_symbol))                        {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFENUM_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  return is_ANY_SAFEREAL_type(type_symbol)
+      || is_ANY_SAFEINT_type (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_NUM_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_REAL_compatible(type_symbol))                       {return true;}
+  if (is_ANY_INT_compatible(type_symbol))                        {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_DATE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(tod_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(dt_type_name_c))   {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEDATE_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(safetod_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safedt_type_name_c))   {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_DATE_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_DATE_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFEDATE_type(type_symbol))              {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_STRING_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
+// TODO literal_string ???
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFESTRING_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_STRING_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_STRING_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFESTRING_type(type_symbol))              {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_INT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(sint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(int_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(dint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(uint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEINT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safesint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safeint_type_name_c))   {return true;}
+  if (typeid(*type_symbol) == typeid(safedint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safelint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(safeuint_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_INT_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_INT_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFEINT_type(type_symbol))              {return true;}
+  if (is_literal_integer_type(type_symbol))          {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_REAL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(real_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEREAL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safereal_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_REAL_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_REAL_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFEREAL_type(type_symbol))              {return true;}
+  if (is_literal_real_type(type_symbol))              {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_BIT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(bool_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(byte_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(word_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(dword_type_name_c))    {return true;}
+  if (typeid(*type_symbol) == typeid(lword_type_name_c))    {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEBIT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safebool_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(safebyte_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(safeword_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(safedword_type_name_c))    {return true;}
+  if (typeid(*type_symbol) == typeid(safelword_type_name_c))    {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_BIT_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_ANY_BIT_type    (type_symbol))              {return true;}
+  if (is_ANY_SAFEBIT_type(type_symbol))              {return true;}
+  if (is_nonneg_literal_integer_type(type_symbol))   {return true;}
+  if (is_literal_bool_type(type_symbol))             {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_BOOL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(bool_type_name_c))      {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_SAFEBOOL_type(symbol_c *type_symbol){
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(safebool_type_name_c))  {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_ANY_BOOL_compatible(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (is_BOOL_type    (type_symbol))              {return true;}
+  if (is_SAFEBOOL_type(type_symbol))              {return true;}
+  if (is_literal_bool_type(type_symbol))              {return true;}
+  return false;
+}
+
+/* A helper function... */
+bool is_literal_integer_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(neg_integer_c))        {return true;}
+  return is_nonneg_literal_integer_type(type_symbol);
+}
+
+
+/* A helper function... */
+bool is_nonneg_literal_integer_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(integer_c))        {return true;}
+  if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(octal_integer_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(hex_integer_c))    {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool is_literal_real_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(real_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;}
+  return false;
+}
+
+
+/* A helper function... */
+bool is_literal_bool_type(symbol_c *type_symbol) {
+  bool_type_name_c bool_t;
+
+  if (type_symbol == NULL) {return false;}
+  if (typeid(*type_symbol) == typeid(boolean_true_c))    {return true;}
+  if (typeid(*type_symbol) == typeid(boolean_false_c))   {return true;}
+  if (is_nonneg_literal_integer_type(type_symbol))
+    if (sizeoftype(&bool_t) >= sizeoftype(type_symbol))  {return true;}
+  return false;
+}
+
+/* Determine the common data type between two data types.
+ * If no common data type found, return NULL.
+ *
+ * If data types are identical, return the first (actually any would do...).
+ * If any of the data types is a literal, we confirm that
+ *   the literal uses less bits than the fixed size data type.
+ *   e.g. BYTE and 1024 returns NULL
+ *        BYTE and 255  returns BYTE
+ *
+ * If two literals, then return the literal that requires more bits...
+ */
+
+symbol_c *common_type(symbol_c *first_type, symbol_c *second_type) {
+  if (first_type == NULL && second_type == NULL) {return NULL;}
+  if (first_type == NULL)  {return second_type;}
+  if (second_type == NULL) {return first_type;}
+
+  if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+  if (is_literal_real_type(first_type) && is_literal_real_type(second_type))
+    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+  if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
+    {return first_type;}
+
+  /* The following check can only be made after the is_literal_XXXX checks */
+  /* When two literals of the same type, with identical typeid's are checked,
+   * we must return the one that occupies more bits... This is done above.
+   */
+  if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
+
+  /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some
+   *       literal bool values are not literal integers...
+   */
+  if (is_BOOL_type(first_type)        && is_literal_bool_type(second_type))    {return first_type;}
+  if (is_BOOL_type(second_type)       && is_literal_bool_type(first_type))     {return second_type;}
+
+  if (is_SAFEBOOL_type(first_type)    && is_literal_bool_type(second_type))    {return first_type;}
+  if (is_SAFEBOOL_type(second_type)   && is_literal_bool_type(first_type))     {return second_type;}
+
+  if (is_SAFEBOOL_type(first_type)    && is_BOOL_type(second_type))            {return second_type;}
+  if (is_SAFEBOOL_type(second_type)   && is_BOOL_type(first_type))             {return first_type;}
+
+  if (is_ANY_BIT_type(first_type)     && is_nonneg_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_BIT_type(second_type)    && is_nonneg_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if (is_ANY_SAFEBIT_type(first_type)     && is_nonneg_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_SAFEBIT_type(second_type)    && is_nonneg_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if  (is_ANY_SAFEBIT_type(first_type)    && is_ANY_BIT_type(second_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+  if  (is_ANY_SAFEBIT_type(second_type)   && is_ANY_BIT_type(first_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+  if (is_ANY_INT_type(first_type)     && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_INT_type(second_type)    && is_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if (is_ANY_SAFEINT_type(first_type)     && is_literal_integer_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_SAFEINT_type(second_type)    && is_literal_integer_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if  (is_ANY_SAFEINT_type(first_type)    && is_ANY_INT_type(second_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+  if  (is_ANY_SAFEINT_type(second_type)   && is_ANY_INT_type(first_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+  if (is_ANY_REAL_type(first_type)    && is_literal_real_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_REAL_type(second_type)   && is_literal_real_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if (is_ANY_SAFEREAL_type(first_type)    && is_literal_real_type(second_type))
+    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
+  if (is_ANY_SAFEREAL_type(second_type)   && is_literal_real_type(first_type))
+    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+  if  (is_ANY_SAFEREAL_type(first_type)    && is_ANY_REAL_type(second_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+  if  (is_ANY_SAFEREAL_type(second_type)   && is_ANY_REAL_type(first_type))
+    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+  /* the Time and Date types... */
+  if (is_type(first_type,  safetime_type_name_c) && is_type(second_type, time_type_name_c))  {return second_type;}
+  if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c))  {return  first_type;}
+
+  if (is_type(first_type,  safedate_type_name_c) && is_type(second_type, date_type_name_c))  {return second_type;}
+  if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c))  {return  first_type;}
+
+  if (is_type(first_type,  safedt_type_name_c)   && is_type(second_type, dt_type_name_c))    {return second_type;}
+  if (is_type(second_type, safedt_type_name_c)   && is_type( first_type, dt_type_name_c))    {return  first_type;}
+
+  if (is_type(first_type,  safetod_type_name_c)  && is_type(second_type, tod_type_name_c))   {return second_type;}
+  if (is_type(second_type, safetod_type_name_c)  && is_type( first_type, tod_type_name_c))   {return  first_type;}
+
+  /* no common type */
+  return NULL;
+}
+
+/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
+ * such as:
+ *     var_type     value_type
+ *    BOOL           BYTE#7     -> returns false
+ *    INT            INT#7      -> returns true
+ *    INT            7          -> returns true
+ *    REAL           7.89       -> returns true
+ *    REAL           7          -> returns true
+ *    INT            7.89       -> returns false
+ *    SAFEBOOL       BOOL#1     -> returns false   !!!
+ *   etc...
+ *
+ * NOTE: It is assumed that the var_type is the data type of an lvalue
+ */
+bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type) {
+  if (var_type == NULL)   {/* STAGE3_ERROR(value_type, value_type, "Var_type   == NULL"); */ return false;}
+  if (value_type == NULL) {/* STAGE3_ERROR(var_type,   var_type,   "Value_type == NULL"); */ return false;}
+
+  symbol_c *common_type_symbol = common_type(var_type, value_type);
+  if (NULL == common_type_symbol)
+    return false;
+  return (typeid(*var_type) == typeid(*common_type_symbol));
+}
+
+
+/* Return TRUE if there is a common data type, otherwise return FALSE
+ * i.e., return TRUE if both data types may be used simultaneously in an expression
+ * such as:
+ *    BOOL#0     AND BYTE#7  -> returns false
+ *    0          AND BYTE#7  -> returns true
+ *    INT#10     AND INT#7   -> returns true
+ *    INT#10     AND 7       -> returns true
+ *    REAL#34.3  AND 7.89    -> returns true
+ *    REAL#34.3  AND 7       -> returns true
+ *    INT#10     AND 7.89    -> returns false
+ *    SAFEBOOL#0 AND BOOL#1  -> returns true   !!!
+ *   etc...
+ */
+bool is_compatible_type(symbol_c *first_type, symbol_c *second_type) {
+  if (first_type == NULL || second_type == NULL) {return false;}
+  return (NULL != common_type(first_type, second_type));
+}
+
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type)
+{
+    if (first_type == NULL || second_type == NULL) {
+        return false;
+    }
+    if (is_ANY_ELEMENTARY_type(first_type)) {
+        if (typeid(*first_type) == typeid(*second_type))
+            return true;
+    } else   /* ANY_DERIVED */
+        return (first_type == second_type);
+
+    return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/datatype_functions.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,111 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti  (conti.ma@alice.it)
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+#ifndef _HELPER_FUNCTIONS_HH_
+#define _HELPER_FUNCTIONS_HH_
+
+#include "../absyntax/visitor.hh"
+#include <typeinfo>
+
+#define is_type(type_name_symbol, type_name_class)  ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class)))
+#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol)
+
+/* Widening Primitive Conversion */
+struct widen_entry {
+	symbol_c *left;
+	symbol_c *right;
+	symbol_c *result;
+};
+/*
+ * 2.5.1.5.6 Functions of time data types
+ * Table 30 - page 64
+ */
+extern const struct widen_entry widen_ADD_table[];
+extern const struct widen_entry widen_SUB_table[];
+extern const struct widen_entry widen_MUL_table[];
+extern const struct widen_entry widen_DIV_table[];
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_type         (symbol_c *type_symbol);
+bool is_ANY_SAFEELEMENTARY_type     (symbol_c *type_symbol);
+bool is_ANY_ELEMENTARY_compatible   (symbol_c *type_symbol);
+
+bool is_ANY_MAGNITUDE_type          (symbol_c *type_symbol);
+bool is_ANY_SAFEMAGNITUDE_type      (symbol_c *type_symbol);
+bool is_ANY_MAGNITUDE_compatible    (symbol_c *type_symbol);
+
+bool is_ANY_DATE_type               (symbol_c *type_symbol);
+bool is_ANY_SAFEDATE_type           (symbol_c *type_symbol);
+bool is_ANY_DATE_compatible         (symbol_c *type_symbol);
+
+bool is_ANY_STRING_type             (symbol_c *type_symbol);
+bool is_ANY_SAFESTRING_type         (symbol_c *type_symbol);
+bool is_ANY_STRING_compatible       (symbol_c *type_symbol);
+
+bool is_ANY_INT_type                (symbol_c *type_symbol);
+bool is_ANY_SAFEINT_type            (symbol_c *type_symbol);
+bool is_ANY_INT_compatible          (symbol_c *type_symbol);
+
+bool is_ANY_REAL_type               (symbol_c *type_symbol);
+bool is_ANY_SAFEREAL_type           (symbol_c *type_symbol);
+bool is_ANY_REAL_compatible         (symbol_c *type_symbol);
+
+bool is_ANY_NUM_type                (symbol_c *type_symbol);
+bool is_ANY_SAFENUM_type            (symbol_c *type_symbol);
+bool is_ANY_NUM_compatible          (symbol_c *type_symbol);
+
+bool is_ANY_BIT_type                (symbol_c *type_symbol);
+bool is_ANY_SAFEBIT_type            (symbol_c *type_symbol);
+bool is_ANY_BIT_compatible          (symbol_c *type_symbol);
+
+bool is_BOOL_type                   (symbol_c *type_symbol);
+bool is_SAFEBOOL_type               (symbol_c *type_symbol);
+bool is_ANY_BOOL_compatible         (symbol_c *type_symbol);
+
+bool is_nonneg_literal_integer_type (symbol_c *type_symbol);
+bool is_literal_integer_type        (symbol_c *type_symbol);
+bool is_literal_real_type           (symbol_c *type_symbol);
+bool is_literal_bool_type           (symbol_c *type_symbol);
+
+/* Determine the common data type between two data types.
+ * If no common data type found, return NULL.
+ *
+ * If data types are identical, return the first (any would do...).
+ * If any of the data types is a literal, we confirm that
+ *   the literal uses less bits than the fixed size data type.
+ *   e.g. BYTE and 1024 returns NULL
+ *        BYTE and 255  returns BYTE
+ *
+ * If two literals, then return the literal that requires more bits...
+ */
+symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
+bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type);
+bool is_compatible_type(symbol_c *first_type, symbol_c *second_type);
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
+
+typedef bool (*helper_function_t) (symbol_c *type_symbol);  /* a pointer to a function! */
+
+
+
+#endif /* _HELPER_FUNCTIONS_HH_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/fill_candidate_datatypes.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1830 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2012       Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ *  Fill candidate list of data types for all symbols
+ */
+
+#include "fill_candidate_datatypes.hh"
+#include "datatype_functions.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+fill_candidate_datatypes_c::fill_candidate_datatypes_c(symbol_c *ignore) {
+
+}
+
+fill_candidate_datatypes_c::~fill_candidate_datatypes_c(void) {
+}
+
+symbol_c *fill_candidate_datatypes_c::widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]) {
+	int k;
+	/* find a widening table entry compatible */
+	for (k = 0; NULL != widen_table[k].left;  k++)
+		if ((typeid(*left_type) == typeid(*widen_table[k].left)) && (typeid(*right_type) == typeid(*widen_table[k].right)))
+			return widen_table[k].result;
+	return NULL;
+}
+
+void fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
+	symbol_c *call_param_value,  *param_type;
+	identifier_c *param_name;
+	function_param_iterator_c       fp_iterator(f_decl);
+	function_call_param_iterator_c fcp_iterator(f_call);
+	int extensible_parameter_highest_index = -1;
+	unsigned int i;
+
+	/* reset error counter */
+	if (error_count != NULL) *error_count = 0;
+	/* Iterating through the non-formal parameters of the function call */
+	while((call_param_value = fcp_iterator.next_nf()) != NULL) {
+		/* Obtaining the type of the value being passed in the function call */
+		std::vector <symbol_c *>&call_param_types = call_param_value->candidate_datatypes;
+		/* Iterate to the next parameter of the function being called.
+		 * Get the name of that parameter, and ignore if EN or ENO.
+		 */
+		do {
+			param_name = fp_iterator.next();
+			/* If there is no other parameter declared, then we are passing too many parameters... */
+			if(param_name == NULL) {
+				(*error_count)++;
+				return;
+			}
+		} while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
+
+		/* Get the parameter type */
+		param_type = base_type(fp_iterator.param_type());
+		for(i = 0; i < call_param_types.size(); i++) {
+			/* If the declared parameter and the parameter from the function call do not have the same type */
+			if(is_type_equal(param_type, call_param_types[i])) {
+				break;
+			}
+		}
+		if (i >= call_param_types.size()) (*error_count)++;
+	}
+}
+
+void fill_candidate_datatypes_c::match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
+	symbol_c *call_param_value, *call_param_name, *param_type;
+	symbol_c *verify_duplicate_param;
+	identifier_c *param_name;
+	function_param_iterator_c       fp_iterator(f_decl);
+	function_call_param_iterator_c fcp_iterator(f_call);
+	int extensible_parameter_highest_index = -1;
+	identifier_c *extensible_parameter_name;
+	unsigned int i;
+
+	/* reset error counter */
+	if (error_count != NULL) *error_count = 0;
+
+	/* Iterating through the formal parameters of the function call */
+	while((call_param_name = fcp_iterator.next_f()) != NULL) {
+
+		/* Obtaining the value being passed in the function call */
+		call_param_value = fcp_iterator.get_current_value();
+		/* the following should never occur. If it does, then we have a bug in our code... */
+		if (NULL == call_param_value) ERROR;
+
+		/* Checking if there are duplicated parameter values */
+		verify_duplicate_param = fcp_iterator.search_f(call_param_name);
+		if(verify_duplicate_param != call_param_value)
+			(*error_count)++;
+
+		/* Obtaining the type of the value being passed in the function call */
+		std::vector <symbol_c *>&call_param_types = call_param_value->candidate_datatypes;
+
+
+		/* Find the corresponding parameter in function declaration */
+		param_name = fp_iterator.search(call_param_name);
+		if(param_name == NULL) {
+			(*error_count)++;
+		} else {
+			/* Get the parameter type */
+			param_type = base_type(fp_iterator.param_type());
+			for (i = 0; i < call_param_types.size(); i++) {
+				/* If the declared parameter and the parameter from the function call have the same type */
+				if(is_type_equal(param_type, call_param_types[i]))
+					break;
+			}
+			if (i >= call_param_types.size()) (*error_count)++;
+		}
+	}
+
+}
+
+/* a helper function... */
+symbol_c *fill_candidate_datatypes_c::base_type(symbol_c *symbol) {
+	/* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+	 *       in the code.
+	 */
+	if (symbol == NULL) return NULL;
+	return (symbol_c *)symbol->accept(search_base_type);
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+void *fill_candidate_datatypes_c::visit(real_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name);
+	if (debug) std::cout << "ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(integer_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+	        symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+	if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(neg_real_c *symbol) {
+	if (sizeoftype(symbol) <= sizeoftype(&search_constant_type_c::real_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name);
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name);
+	if (debug) std::cout << "neg ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(neg_integer_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::int_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::sint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::dint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::lint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+	if (debug) std::cout << "neg ANY_INT [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(binary_integer_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+	        symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+	
+	if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(octal_integer_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+	        symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+	if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(hex_integer_c *symbol) {
+	int calc_size;
+
+	calc_size = sizeoftype(symbol);
+	if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+	        symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+	if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+	if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+	if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+	if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(integer_literal_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type);
+	if (debug) std::cout << "INT_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(real_literal_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type);
+	if (debug) std::cout << "REAL_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(bit_string_literal_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_literal_c *symbol) {
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_true_c *symbol) {
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_false_c *symbol) {
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+/*******************************/
+/* B.1.2.2   Character Strings */
+/*******************************/
+void *fill_candidate_datatypes_c::visit(double_byte_character_string_c *symbol) {
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::wstring_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(single_byte_character_string_c *symbol) {
+	symbol->candidate_datatypes.push_back(&search_constant_type_c::string_type_name);
+	return NULL;
+}
+
+/***************************/
+/* B 1.2.3 - Time Literals */
+/***************************/
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+void *fill_candidate_datatypes_c::visit(duration_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type_name);
+	if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+	return NULL;
+}
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+void *fill_candidate_datatypes_c::visit(time_of_day_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(date_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(date_and_time_c *symbol) {
+	symbol->candidate_datatypes.push_back(symbol->type_name);
+	return NULL;
+}
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+/*  signed_integer DOTDOT signed_integer */
+// SYM_REF2(subrange_c, lower_limit, upper_limit)
+void *fill_candidate_datatypes_c::visit(subrange_c *symbol) {
+	symbol->lower_limit->accept(*this);
+	symbol->upper_limit->accept(*this);
+	
+	for (unsigned int u = 0; u < symbol->upper_limit->candidate_datatypes.size(); u++) {
+		for(unsigned int l = 0; l < symbol->lower_limit->candidate_datatypes.size(); l++) {
+			if (is_type_equal(symbol->upper_limit->candidate_datatypes[u], symbol->lower_limit->candidate_datatypes[l]))
+				symbol->candidate_datatypes.push_back(symbol->lower_limit->candidate_datatypes[l]);
+		}
+	}
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(data_type_declaration_c *symbol) {
+	// TODO !!!
+	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) {
+	symbol_c *enumerated_type;
+
+	if (NULL != symbol->type)
+		enumerated_type = symbol->type;
+	else {
+		enumerated_type = enumerated_value_symtable.find_value(symbol->value);
+		if (enumerated_type == enumerated_value_symtable.end_value())
+			enumerated_type = NULL;
+	}
+	enumerated_type = base_type(enumerated_type);
+	if (NULL != enumerated_type)
+		symbol->candidate_datatypes.push_back(enumerated_type);
+
+	if (debug) std::cout << "ENUMERATE [" << symbol->candidate_datatypes.size() << "]\n";
+	return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *fill_candidate_datatypes_c::visit(symbolic_variable_c *symbol) {
+	symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+	if (NULL != result)
+		symbol->candidate_datatypes.push_back(result);
+	if (debug) std::cout << "VAR [" << symbol->candidate_datatypes.size() << "]\n";
+	return NULL;
+}
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+void *fill_candidate_datatypes_c::visit(direct_variable_c *symbol) {
+	/* Comment added by mario:
+	 * The following code is safe, actually, as the lexical parser guarantees the correct IEC61131-3 syntax was used.
+	 */
+	/* However, we should probably add an assertion in case we later change the lexical parser! */
+	/* if (symbol->value == NULL) ERROR;
+	 * if (symbol->value[0] == '\0') ERROR;
+	 * if (symbol->value[1] == '\0') ERROR;
+	 */
+	switch (symbol->value[2]) {
+	case 'X': // bit - 1 bit
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+		break;
+
+	case 'B': // byte - 8 bits
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+		break;
+
+	case 'W': // word - 16 bits
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+		break;
+
+	case 'D': // double word - 32 bits
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+		break;
+
+	case 'L': // long word - 64 bits
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+		break;
+
+	default:  // if none of the above, then the empty string was used <=> boolean
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+		break;
+	}
+	return NULL;
+}
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/*  subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *fill_candidate_datatypes_c::visit(array_variable_c *symbol) {
+	/* get the declaration of the data type __stored__ in the array... */
+	/* if we were to want the data type of the array itself, then we should call_param_name
+	 * search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable)
+	 */
+	symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+	if (NULL != result) symbol->candidate_datatypes.push_back(result);
+	
+	/* recursively call the subscript list, so we can check the data types of the expressions used for the subscripts */
+if (debug) std::cout << "ARRAY_VAR XXX\n";		
+	symbol->subscript_list->accept(*this);
+if (debug) std::cout << "ARRAY_VAR YYY\n";		
+
+	if (debug) std::cout << "ARRAY_VAR [" << symbol->candidate_datatypes.size() << "]\n";	
+	return NULL;
+}
+
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */
+#if 0
+void *fill_candidate_datatypes_c::visit(subscript_list_c *symbol) {
+}
+#endif
+
+
+/*  record_variable '.' field_selector */
+/*  WARNING: input and/or output variables of function blocks
+ *           may be accessed as fields of a structured variable!
+ *           Code handling a structured_variable_c must take
+ *           this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+/* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type
+ * will do that for us. So we determine the candidate datatypes only for the full structured_variable.
+ */
+void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) {
+	symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+	if (NULL != result) symbol->candidate_datatypes.push_back(result);
+	return NULL;
+}
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *fill_candidate_datatypes_c::visit(function_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	symbol->var_declarations_list->accept(*this);
+	if (debug) printf("Filling candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+	il_parenthesis_level = 0;
+	prev_il_instruction = NULL;
+	symbol->function_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *fill_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	symbol->var_declarations->accept(*this);
+	if (debug) printf("Filling candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+	il_parenthesis_level = 0;
+	prev_il_instruction = NULL;
+	symbol->fblock_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *fill_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	symbol->var_declarations->accept(*this);
+	if (debug) printf("Filling candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+	il_parenthesis_level = 0;
+	prev_il_instruction = NULL;
+	symbol->function_block_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *fill_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
+#if 0
+	// TODO !!!
+	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+	return NULL;
+}
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *fill_candidate_datatypes_c::visit(il_simple_operation_c *symbol) {
+	/* determine the data type of the operand */
+	if (NULL != symbol->il_operand) {
+		symbol->il_operand->accept(*this);
+	}
+	/* recursive call to fill the candidate data types list */
+	il_operand = symbol->il_operand;
+	symbol->il_simple_operator->accept(*this);
+	il_operand = NULL;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) {
+}
+
+/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
+ *     and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
+ *
+ *       Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c
+ *       in the 3 new classes fill/narrow/print candidate datatype 
+ */
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) {
+  if (NULL != symbol->il_operand)
+    symbol->il_operand->accept(*this);
+  
+  il_parenthesis_level++;
+
+  /* Note that prev_il_instruction will actually be used to get the current value store in the il_default_variable */
+  /* If a symbol->il_operand is provided, then that will be the result before executing the simple_instr_list.
+   * If this symbol is NULL, then the current result is also NULL, which is correct for what we want to do!
+   */
+  symbol_c *prev_il_instruction_backup = prev_il_instruction;
+  prev_il_instruction = symbol->il_operand;
+  
+  if(symbol->simple_instr_list != NULL) {
+    symbol->simple_instr_list->accept(*this);
+  }
+
+  il_parenthesis_level--;
+  if (il_parenthesis_level < 0) ERROR;
+
+  /* Now check the if the data type semantics of operation are correct,  */
+  il_operand = prev_il_instruction;
+  prev_il_instruction = prev_il_instruction_backup;
+  symbol->il_expr_operator->accept(*this);
+  il_operand = NULL;
+  return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_jump_operation_c *symbol) {
+  /* recursive call to fill the candidate data types list */
+  il_operand = NULL;
+  symbol->il_jump_operator->accept(*this);
+  il_operand = NULL;
+  return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
+}
+
+void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
+
+}
+
+/*
+    void *visit(il_operand_list_c *symbol);
+    void *visit(simple_instr_list_c *symbol);
+    void *visit(il_param_list_c *symbol);
+    void *visit(il_param_assignment_c *symbol);
+    void *visit(il_param_out_assignment_c *symbol);
+*/
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
+		symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]);
+	}
+	if (debug) std::cout << "LD [" <<  il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+	for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
+		if      (is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
+			symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]);
+	}
+	if (debug) std::cout << "LDN [" << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ST_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "ST [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(STN_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "STN [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(S1_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "S1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(R1_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout << "R1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CLK_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CU_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CD_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(PV_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(IN_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(PT_operator_c *symbol) {
+	/* MANU:
+	 * How it works? I(MANU) don't know this function
+	 */
+
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(AND_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(OR_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(XOR_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ANDN_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ORN_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(XORN_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_BIT_compatible(operand_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ADD_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_NUM_compatible(prev_instruction_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+			else {
+				symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_ADD_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+
+			}
+		}
+	}
+	if (debug) std::cout <<  "ADD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(SUB_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_NUM_compatible(prev_instruction_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+			else {
+				symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_SUB_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+		}
+	}
+	if (debug) std::cout <<  "SUB [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(MUL_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_NUM_compatible(prev_instruction_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+			else {
+				symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_MUL_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+		}
+	}
+	if (debug) std::cout <<  "MUL [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(DIV_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_NUM_compatible(prev_instruction_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+			else {
+				symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_DIV_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+		}
+	}
+	if (debug) std::cout <<  "DIV [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(MOD_operator_c *symbol) {
+	symbol_c *prev_instruction_type, *operand_type;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+			operand_type = il_operand->candidate_datatypes[j];
+			if (is_type_equal(prev_instruction_type, operand_type) &&
+					is_ANY_INT_compatible(prev_instruction_type))
+				symbol->candidate_datatypes.push_back(prev_instruction_type);
+		}
+	}
+	if (debug) std::cout <<  "MOD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(GT_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(GE_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(EQ_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LT_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LE_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(NE_operator_c *symbol) {
+	bool found = false;
+
+	if (NULL == prev_il_instruction) return NULL;
+	for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+			if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+	        /* does not need to be bool type !! */
+		symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "CAL [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CALC_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "CALC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "CALCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RET_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+	        /* does not need to be bool type !! */
+		symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "RET [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RETC_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "RETC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "RETCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMP_operator_c *symbol) {
+	if (NULL == prev_il_instruction) return NULL;
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+	        /* does not need to be bool type !! */
+		symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "JMP [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMPC_operator_c *symbol) {
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "JMPC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {
+	for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+		if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+			symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+	}
+	if (debug) std::cout <<  "JMPCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	prev_il_instruction = symbol;
+	return NULL;
+}
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *fill_candidate_datatypes_c::visit(or_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for (unsigned  int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned  int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+		}
+	}
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(xor_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+
+	for (unsigned  int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned  int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+		}
+	}
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(and_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+
+	for (unsigned  int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+				symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+		}
+	}
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(equ_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(notequ_expression_c *symbol)  {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found)
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(lt_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found)
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(gt_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found)
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(le_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found)
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ge_expression_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	bool found = false;
+
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+				found = true;
+				break;
+			}
+		}
+	}
+	if (found)
+		symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(add_expression_c *symbol) {
+	/* The following code is correct when handling the addition of 2 symbolic_variables
+	 * In this case, adding two variables (e.g. USINT_var1 + USINT_var2) will always yield
+	 * the same data type, even if the result of the adition could not fit inside the same
+	 * data type (due to overflowing)
+	 *
+	 * However, when adding two literals (e.g. USINT#42 + USINT#3)
+	 * we should be able to detect overflows of the result, and therefore not consider
+	 * that the result may be of type USINT.
+	 * Currently we do not yet detect these overflows, and allow handling the sum of two USINTs
+	 * as always resulting in an USINT, even in the following expression
+	 * (USINT#65535 + USINT#2).
+	 *
+	 * In the future we can add some code to reduce
+	 * all the expressions that are based on literals into the resulting literal
+	 * value (maybe some visitor class that will run before or after data type
+	 * checking). Since this class will have to be very careful to make sure it implements the same mathematical
+	 * details (e.g. how to round and truncate numbers) as defined in IEC 61131-3, we will leave this to the future.
+	 * Also, the question will arise if we should also replace calls to standard
+	 * functions if the input parameters are all literals (e.g. ADD(42, 42)). This
+	 * means this class will be more difficult than it appears at first.
+	 */
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+				symbol->candidate_datatypes.push_back(left_type);
+			else {
+				symbol_c *result = widening_conversion(left_type, right_type, widen_ADD_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+		}
+	}
+	if (debug) std::cout <<  "+ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(sub_expression_c *symbol) {
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+				symbol->candidate_datatypes.push_back(left_type);
+			else {
+				symbol_c *result = widening_conversion(left_type, right_type, widen_SUB_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+		}
+	}
+	if (debug) std::cout <<  "- [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(mul_expression_c *symbol) {
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if      (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+				symbol->candidate_datatypes.push_back(left_type);
+			else {
+				symbol_c *result = widening_conversion(left_type, right_type, widen_MUL_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+
+		}
+	}
+	if (debug) std::cout << "* [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+
+	return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(div_expression_c *symbol) {
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if      (is_type_equal(left_type, right_type) && is_ANY_NUM_type(left_type))
+				symbol->candidate_datatypes.push_back(left_type);
+			else {
+				symbol_c *result = widening_conversion(left_type, right_type, widen_DIV_table);
+				if (result)
+					symbol->candidate_datatypes.push_back(result);
+			}
+
+		}
+	}
+	if (debug) std::cout << "/ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(mod_expression_c *symbol) {
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if (is_type_equal(left_type, right_type) && is_ANY_INT_compatible(left_type))
+				symbol->candidate_datatypes.push_back(left_type);
+		}
+	}
+	if (debug) std::cout << "mod [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(power_expression_c *symbol) {
+	symbol_c *left_type, *right_type;
+	bool check_ok;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	check_ok = false;
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		left_type = symbol->l_exp->candidate_datatypes[i];
+		if (is_ANY_REAL_compatible(left_type)) {
+			check_ok = true;
+			break;
+		}
+	}
+	if (! check_ok) return NULL;
+	check_ok = false;
+	for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+		right_type = symbol->r_exp->candidate_datatypes[j];
+		if (is_ANY_NUM_compatible(right_type)) {
+			check_ok = true;
+			break;
+		}
+	}
+	if (! check_ok) return NULL;
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+	}
+	if (debug) std::cout << "** [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(neg_expression_c *symbol) {
+	symbol->exp->accept(*this);
+	for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+		if (is_ANY_MAGNITUDE_compatible(symbol->exp->candidate_datatypes[i]))
+			symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]);
+	}
+	if (debug) std::cout << "neg [" << symbol->exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(not_expression_c *symbol) {
+	symbol->exp->accept(*this);
+	for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+		if      (is_ANY_BIT_compatible(symbol->exp->candidate_datatypes[i]))
+			symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]);
+	}
+	if (debug) std::cout << "not [" << symbol->exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {
+	function_declaration_c *f_decl;
+	list_c *parameter_list;
+	list_c *parameter_candidate_datatypes;
+	symbol_c *parameter_type;
+	int error_count;
+	function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+	function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+
+	if (NULL != symbol->formal_param_list)
+		parameter_list = (list_c *)symbol->formal_param_list;
+	else if (NULL != symbol->nonformal_param_list)
+		parameter_list = (list_c *)symbol->nonformal_param_list;
+	else ERROR;
+	if (debug) std::cout << "function()\n";
+	parameter_list->accept(*this);
+	for(; lower != upper; lower++) {
+		f_decl = function_symtable.get_value(lower);
+		error_count = 0;
+		/* Check if function declaration in symbol_table is compatible with parameters */
+		if (NULL != symbol->nonformal_param_list)
+			/* nonformal parameter function call */
+			match_nonformal_call(symbol, f_decl, &error_count);
+		else
+			/* formal parameter function call */
+			match_formal_call (symbol, f_decl, &error_count);
+		if (0 == error_count) {
+			/* Add basetype matching function only if not present */
+			unsigned int k;
+			parameter_type = base_type(f_decl->type_name);
+			for(k = 0; k < symbol->candidate_datatypes.size(); k++) {
+				if (is_type_equal(parameter_type, symbol->candidate_datatypes[k]))
+					break;
+			}
+			if (k >= symbol->candidate_datatypes.size())
+				symbol->candidate_datatypes.push_back(parameter_type);
+		}
+	}
+	if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n";
+	return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+// SYM_LIST(statement_list_c)
+/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
+ * We do not need to do anything here...
+ */
+// void *fill_candidate_datatypes_c::visit(statement_list_c *symbol)
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *fill_candidate_datatypes_c::visit(assignment_statement_c *symbol) {
+	symbol_c *left_type, *right_type;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			left_type = symbol->l_exp->candidate_datatypes[i];
+			right_type = symbol->r_exp->candidate_datatypes[j];
+			if (is_type_equal(left_type, right_type))
+				symbol->candidate_datatypes.push_back(left_type);
+		}
+	}
+	if (debug) std::cout << ":= [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> "  << symbol->candidate_datatypes.size() << " result.\n";
+	return NULL;
+}
+
+
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+void *fill_candidate_datatypes_c::visit(if_statement_c *symbol) {
+	/* MANU:
+	 * IF statement accept only BOOL type. We intersect with BOOL type to validate current if condition
+	 * Example:
+	 * IF 1 THEN 		---> 	 ok
+	 * IF 5 THEN 		---> not ok
+	 * IF 1 OR 1 THEN	--->     ok
+	 * IF 1 OR 5 THEN   ---> not ok
+	 * IF SHL() THEN	---> 	 ok if shl return BOOL
+	 * IF INT_TO_REAL() ---> not ok
+	 */
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	if (NULL != symbol->elseif_statement_list)
+		symbol->elseif_statement_list->accept(*this);
+	if (NULL != symbol->else_statement_list)
+		symbol->else_statement_list->accept(*this);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(elseif_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
+void *fill_candidate_datatypes_c::visit(case_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if (NULL != symbol->case_element_list)
+		symbol->case_element_list->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+/* helper symbol for case_statement */
+// SYM_LIST(case_element_list_c)
+/* NOTE: visitor method for case_element_list_c is not required since we inherit from iterator_visitor_c */
+
+/*  case_list ':' statement_list */
+// SYM_REF2(case_element_c, case_list, statement_list)
+/* NOTE: visitor method for case_element_c is not required since we inherit from iterator_visitor_c */
+
+// SYM_LIST(case_list_c)
+/* NOTE: visitor method for case_list_c is not required since we inherit from iterator_visitor_c */
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+void *fill_candidate_datatypes_c::visit(for_statement_c *symbol) {
+	symbol->control_variable->accept(*this);
+	symbol->beg_expression->accept(*this);
+	symbol->end_expression->accept(*this);
+	if (NULL != symbol->by_expression)
+		symbol->by_expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(while_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(repeat_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/fill_candidate_datatypes.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,320 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2012       Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class fill_candidate_datatypes_c: public iterator_visitor_c {
+
+  private:
+    search_varfb_instance_type_c *search_varfb_instance_type;
+    search_base_type_c search_base_type;
+    /* When calling a function block, we must first find it's type,
+     * by searching through the declarations of the variables currently
+     * in scope.
+     * This class does just that...
+     * A new object instance is instantiated whenever we start checking semantics
+     * for a function block type declaration, or a program declaration.
+     * This object instance will then later be called while the
+     * function block's or the program's body is being handled.
+     *
+     * Note that functions cannot contain calls to function blocks,
+     * so we do not create an object instance when handling
+     * a function declaration.
+     */
+    //     search_var_instance_decl_c *search_var_instance_decl;
+
+    /* This variable was created to pass information from
+     * fill_candidate_datatypes_c::visit(case_statement_c *symbol) function to
+     * fill_candidate_datatypes_c::visit(case_list_c *symbol) function.
+     */
+    symbol_c *case_expression_type;
+
+    /* In IL code, once we find a type mismatch error, it is best to
+     * ignore any further errors until the end of the logical operation,
+     * i.e. until the next LD.
+     * However, we cannot clear the il_error flag on all LD operations,
+     * as these may also be used within parenthesis. LD operations
+     * within parenthesis may not clear the error flag.
+     * We therefore need a counter to know how deep inside a parenthesis
+     * structure we are.
+     */
+    int  il_parenthesis_level;
+    bool error_found;
+
+    /* the current data type of the data stored in the IL stack, i.e. the default variable */
+    symbol_c *prev_il_instruction;
+    /* the current IL operand being analyzed - its symbol and its data type */
+    symbol_c *il_operand_type;
+    symbol_c *il_operand;
+    symbol_c *widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]);
+
+  public:
+    fill_candidate_datatypes_c(symbol_c *ignore);
+    virtual ~fill_candidate_datatypes_c(void);
+
+    /* Match a function declaration with a function call through their parameters.*/
+    void match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
+    void match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
+
+    void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
+    void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);
+
+    /* a helper function... */
+    symbol_c *base_type(symbol_c *symbol);
+
+    /*********************/
+    /* B 1.2 - Constants */
+    /*********************/
+    /******************************/
+    /* B 1.2.1 - Numeric Literals */
+    /******************************/
+    void *visit(real_c *symbol);
+    void *visit(integer_c *symbol);
+    void *visit(neg_real_c *symbol);
+    void *visit(neg_integer_c *symbol);
+    void *visit(binary_integer_c *symbol);
+    void *visit(octal_integer_c *symbol);
+    void *visit(hex_integer_c *symbol);
+    void *visit(integer_literal_c *symbol);
+    void *visit(real_literal_c *symbol);
+    void *visit(bit_string_literal_c *symbol);
+    void *visit(boolean_literal_c *symbol);
+    void *visit(boolean_true_c *symbol);
+    void *visit(boolean_false_c *symbol);
+
+    /*******************************/
+    /* B.1.2.2   Character Strings */
+    /*******************************/
+    void *visit(double_byte_character_string_c *symbol);
+    void *visit(single_byte_character_string_c *symbol);
+
+    /***************************/
+    /* B 1.2.3 - Time Literals */
+    /***************************/
+    /************************/
+    /* B 1.2.3.1 - Duration */
+    /************************/
+    void *visit(duration_c *symbol);
+
+    /************************************/
+    /* B 1.2.3.2 - Time of day and Date */
+    /************************************/
+    void *visit(time_of_day_c *symbol);
+    void *visit(date_c *symbol);
+    void *visit(date_and_time_c *symbol);
+
+
+    /**********************/
+    /* B 1.3 - Data types */
+    /**********************/
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    void *visit(subrange_c *symbol);
+    void *visit(data_type_declaration_c *symbol);
+    void *visit(enumerated_value_c *symbol);
+
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol);
+
+    /********************************************/
+    /* B 1.4.1 - Directly Represented Variables */
+    /********************************************/
+    void *visit(direct_variable_c *symbol);
+
+    /*************************************/
+    /* B 1.4.2 - Multi-element variables */
+    /*************************************/
+    void *visit(array_variable_c *symbol);
+    void *visit(structured_variable_c *symbol);
+
+    /**************************************/
+    /* B 1.5 - Program organization units */
+    /**************************************/
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    void *visit(function_declaration_c *symbol);
+
+    /*****************************/
+    /* B 1.5.2 - Function blocks */
+    /*****************************/
+    void *visit(function_block_declaration_c *symbol);
+
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    void *visit(program_declaration_c *symbol);
+
+    /********************************/
+    /* B 1.7 Configuration elements */
+    /********************************/
+    void *visit(configuration_declaration_c *symbol);
+
+    /****************************************/
+    /* B.2 - Language IL (Instruction List) */
+    /****************************************/
+    /***********************************/
+    /* B 2.1 Instructions and Operands */
+    /***********************************/
+    // void *visit(instruction_list_c *symbol);
+    void *visit(il_simple_operation_c *symbol);
+    void *visit(il_function_call_c *symbol);
+    void *visit(il_expression_c *symbol);
+    void *visit(il_jump_operation_c *symbol);
+    void *visit(il_fb_call_c *symbol);
+    void *visit(il_formal_funct_call_c *symbol);
+    /*
+        void *visit(il_operand_list_c *symbol);
+        void *visit(simple_instr_list_c *symbol);
+        void *visit(il_param_list_c *symbol);
+        void *visit(il_param_assignment_c *symbol);
+        void *visit(il_param_out_assignment_c *symbol);
+     */
+
+    /*******************/
+    /* B 2.2 Operators */
+    /*******************/
+    void *visit(LD_operator_c *symbol);
+    void *visit(LDN_operator_c *symbol);
+    void *visit(ST_operator_c *symbol);
+    void *visit(STN_operator_c *symbol);
+    void *visit(NOT_operator_c *symbol);
+    void *visit(S_operator_c *symbol);
+    void *visit(R_operator_c *symbol);
+    void *visit(S1_operator_c *symbol);
+    void *visit(R1_operator_c *symbol);
+    void *visit(CLK_operator_c *symbol);
+    void *visit(CU_operator_c *symbol);
+    void *visit(CD_operator_c *symbol);
+    void *visit(PV_operator_c *symbol);
+    void *visit(IN_operator_c *symbol);
+    void *visit(PT_operator_c *symbol);
+    void *visit(AND_operator_c *symbol);
+    void *visit(OR_operator_c *symbol);
+    void *visit(XOR_operator_c *symbol);
+    void *visit(ANDN_operator_c *symbol);
+    void *visit(ORN_operator_c *symbol);
+    void *visit(XORN_operator_c *symbol);
+    void *visit(ADD_operator_c *symbol);
+    void *visit(SUB_operator_c *symbol);
+    void *visit(MUL_operator_c *symbol);
+    void *visit(DIV_operator_c *symbol);
+    void *visit(MOD_operator_c *symbol);
+    void *visit(GT_operator_c *symbol);
+    void *visit(GE_operator_c *symbol);
+    void *visit(EQ_operator_c *symbol);
+    void *visit(LT_operator_c *symbol);
+    void *visit(LE_operator_c *symbol);
+    void *visit(NE_operator_c *symbol);
+    void *visit(CAL_operator_c *symbol);
+    void *visit(CALC_operator_c *symbol);
+    void *visit(CALCN_operator_c *symbol);
+    void *visit(RET_operator_c *symbol);
+    void *visit(RETC_operator_c *symbol);
+    void *visit(RETCN_operator_c *symbol);
+    void *visit(JMP_operator_c *symbol);
+    void *visit(JMPC_operator_c *symbol);
+    void *visit(JMPCN_operator_c *symbol);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, variable_name);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    void *visit(or_expression_c *symbol);
+    void *visit(xor_expression_c *symbol);
+    void *visit(and_expression_c *symbol);
+    void *visit(equ_expression_c *symbol);
+    void *visit(notequ_expression_c *symbol);
+    void *visit(lt_expression_c *symbol);
+    void *visit(gt_expression_c *symbol);
+    void *visit(le_expression_c *symbol);
+    void *visit(ge_expression_c *symbol);
+    void *visit(add_expression_c *symbol);
+    void *visit(sub_expression_c *symbol);
+    void *visit(mul_expression_c *symbol);
+    void *visit(div_expression_c *symbol);
+    void *visit(mod_expression_c *symbol);
+    void *visit(power_expression_c *symbol);
+    void *visit(neg_expression_c *symbol);
+    void *visit(not_expression_c *symbol);
+    void *visit(function_invocation_c *symbol);
+
+    /*********************************/
+    /* B 3.2.1 Assignment Statements */
+    /*********************************/
+    void *visit(assignment_statement_c *symbol);
+
+    /*****************************************/
+    /* B 3.2.2 Subprogram Control Statements */
+    /*****************************************/
+    //void *visit(fb_invocation_c *symbol);
+
+    /********************************/
+    /* B 3.2.3 Selection Statements */
+    /********************************/
+    void *visit(if_statement_c *symbol);
+    //     void *visit(elseif_statement_list_c *symbol);
+    void *visit(elseif_statement_c *symbol);
+    void *visit(case_statement_c *symbol);
+
+    /********************************/
+    /* B 3.2.4 Iteration Statements */
+    /********************************/
+    void *visit(for_statement_c *symbol);
+    void *visit(while_statement_c *symbol);
+    void *visit(repeat_statement_c *symbol);
+
+}; // fill_candidate_datatypes_c
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/narrow_candidate_datatypes.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1194 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2012       Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ *  Narrow class select and store a data type from candidate data types list for all symbols
+ */
+
+#include "narrow_candidate_datatypes.hh"
+#include "datatype_functions.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+narrow_candidate_datatypes_c::narrow_candidate_datatypes_c(symbol_c *ignore) {
+}
+
+narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) {
+}
+
+bool narrow_candidate_datatypes_c::is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]) {
+	for (int k = 0; NULL != widen_table[k].left;  k++) {
+		if        ((typeid(*left_type)   == typeid(*widen_table[k].left))
+		        && (typeid(*right_type)  == typeid(*widen_table[k].right))
+				&& (typeid(*result_type) == typeid(*widen_table[k].result))) {
+			return true;
+		}
+	}
+	return false;
+}
+
+void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl) {
+	symbol_c *call_param_value,  *param_type;
+	identifier_c *param_name;
+	function_param_iterator_c       fp_iterator(f_decl);
+	function_call_param_iterator_c fcp_iterator(f_call);
+	int extensible_parameter_highest_index = -1;
+	identifier_c *extensible_parameter_name;
+	unsigned int i;
+
+
+	/* Iterating through the non-formal parameters of the function call */
+	while((call_param_value = fcp_iterator.next_nf()) != NULL) {
+		/* Obtaining the type of the value being passed in the function call */
+		/* Iterate to the next parameter of the function being called.
+		 * Get the name of that parameter, and ignore if EN or ENO.
+		 */
+		do {
+			param_name = fp_iterator.next();
+			/* If there is no other parameter declared, then we are passing too many parameters... */
+			if(param_name == NULL) {
+				return;
+			}
+		} while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
+
+		/* Get the parameter type */
+		call_param_value->datatype = base_type(fp_iterator.param_type());
+		call_param_value->accept(*this);
+		if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+			extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+			extensible_parameter_name = param_name;
+		}
+	}
+    int extensible_param_count = -1;
+    if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+      extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+    function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
+    if (function_invocation  != NULL) function_invocation->extensible_param_count = extensible_param_count;
+
+}
+
+void narrow_candidate_datatypes_c::narrow_formal_call(symbol_c *f_call, symbol_c *f_decl) {
+	symbol_c *call_param_value, *call_param_name, *param_type;
+	symbol_c *verify_duplicate_param;
+	identifier_c *param_name;
+	function_param_iterator_c       fp_iterator(f_decl);
+	function_call_param_iterator_c fcp_iterator(f_call);
+	int extensible_parameter_highest_index = -1;
+	identifier_c *extensible_parameter_name;
+	unsigned int i;
+
+
+	/* Iterating through the formal parameters of the function call */
+	while((call_param_name = fcp_iterator.next_f()) != NULL) {
+
+		/* Obtaining the value being passed in the function call */
+		call_param_value = fcp_iterator.get_current_value();
+		/* the following should never occur. If it does, then we have a bug in our code... */
+		if (NULL == call_param_value) ERROR;
+
+		/* Find the corresponding parameter in function declaration */
+		param_name = fp_iterator.search(call_param_name);
+
+		/* Get the parameter type */
+		call_param_name->datatype = base_type(fp_iterator.param_type());
+		call_param_name->accept(*this);
+	    /* the first parameter (il_def_variable) is correct */
+	    if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+	      extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+	    }
+	}
+	/* The function call may not have any errors! */
+	/* In the case of a call to an extensible function, we store the highest index
+	 * of the extensible parameters this particular call uses, in the symbol_c object
+	 * of the function call itself!
+	 * In calls to non-extensible functions, this value will be set to -1.
+	 * This information is later used in stage4 to correctly generate the
+	 * output code.
+	 */
+	int extensible_param_count = -1;
+	if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+		extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+	function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
+	if (function_invocation  != NULL) function_invocation->extensible_param_count = extensible_param_count;
+}
+
+/* a helper function... */
+symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) {
+	/* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+	 *       in the code.
+	 */
+	return NULL;
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+/*  signed_integer DOTDOT signed_integer */
+// SYM_REF2(subrange_c, lower_limit, upper_limit)
+void *narrow_candidate_datatypes_c::visit(subrange_c *symbol) {
+	symbol->lower_limit->datatype = symbol->datatype;
+	symbol->lower_limit->accept(*this);
+	symbol->upper_limit->datatype = symbol->datatype;
+	symbol->upper_limit->accept(*this);
+	return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/*  subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *narrow_candidate_datatypes_c::visit(array_variable_c *symbol) {
+	/* we need to check the data types of the expressions used for the subscripts... */
+	symbol->subscript_list->accept(*this);
+	return NULL;
+}
+
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+void *narrow_candidate_datatypes_c::visit(subscript_list_c *symbol) {
+	for (int i = 0; i < symbol->n; i++) {
+		for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) {
+			if (is_ANY_INT_type(symbol->elements[i]->candidate_datatypes[k]))
+				symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k];
+		}
+		symbol->elements[i]->accept(*this);
+	}
+	return NULL;  
+}
+
+
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *narrow_candidate_datatypes_c::visit(function_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+	prev_il_instruction = NULL;
+	symbol->function_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+	prev_il_instruction = NULL;
+	symbol->fblock_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/********************/
+/* B 1.5.3 Programs */
+/********************/
+void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+	prev_il_instruction = NULL;
+	symbol->function_block_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *narrow_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
+#if 0
+	// TODO !!!
+	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+	return NULL;
+}
+
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *narrow_candidate_datatypes_c::visit(il_simple_operation_c *symbol) {
+	il_operand = symbol->il_operand;
+	if (NULL != symbol->il_operand) {
+		symbol->il_operand->accept(*this);
+	}
+	/* recursive call to see whether data types are compatible */
+	symbol->il_simple_operator->accept(*this);
+	il_operand = NULL;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_function_call_c *symbol) {
+	return NULL;
+}
+
+/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
+ *     and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
+ *
+ *       Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c
+ *       in the 3 new classes fill/narrow/print candidate datatype 
+ */
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *narrow_candidate_datatypes_c::visit(il_expression_c *symbol) {
+/* MJS: TODO... */
+return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
+	return NULL;
+}
+
+
+/*
+    void *visit(il_operand_list_c *symbol);
+    void *visit(simple_instr_list_c *symbol);
+    void *visit(il_param_list_c *symbol);
+    void *visit(il_param_assignment_c *symbol);
+    void *visit(il_param_out_assignment_c *symbol);
+ */
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(S1_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(R1_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CLK_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CU_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(PV_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(IN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(PT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(AND_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(OR_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(XOR_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ANDN_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ORN_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(XORN_operator_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	il_operand->datatype = symbol->datatype;
+	il_operand->accept(*this);
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ADD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(SUB_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(MUL_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(DIV_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(MOD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(GT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(GE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(EQ_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *narrow_candidate_datatypes_c::visit(or_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(xor_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(and_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(equ_expression_c *symbol) {
+	/* Here symbol->datatype has already assigned to BOOL
+	 * In conditional symbols like =, <>, =<, <, >, >= we have to set
+	 * l_exp and r_exp expression matched with compatible type.
+	 * Example:
+	 * 		INT#14 = INT#81
+	 * 		equ_expression_c symbol->datatype = BOOL from top visit
+	 * 		symbol->l_exp->datatype => INT
+	 * 		symbol->r_exp->datatype => INT
+	 */
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+				/*
+				 * We do not need to check whether the type is an ANY_ELEMENTARY here.
+				 * That was already done in fill_candidate_datatypes_c.
+				 */
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(notequ_expression_c *symbol)  {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(lt_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(gt_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(le_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(ge_expression_c *symbol) {
+	symbol_c * selected_type = NULL;
+	for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+		for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+			if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+					&& is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+				selected_type = symbol->l_exp->candidate_datatypes[i];
+				break;
+			}
+		}
+	}
+
+	if (NULL != selected_type) {
+		symbol->l_exp->datatype = selected_type;
+		symbol->l_exp->accept(*this);
+		symbol->r_exp->datatype = selected_type;
+		symbol->r_exp->accept(*this);
+	}
+	else
+		ERROR;
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(add_expression_c *symbol) {
+	int count = 0;
+
+	if (is_ANY_NUM_compatible(symbol->datatype)) {
+		symbol->l_exp->datatype = symbol->datatype;
+		symbol->r_exp->datatype = symbol->datatype;
+		count++;
+	} else {
+		/* TIME data type */
+		for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+			for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+				/* test widening compatibility */
+				if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+						symbol->r_exp->candidate_datatypes[j],
+						symbol->datatype, widen_ADD_table)) {
+					symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+					symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+					count ++;
+				}
+			}
+		}
+	}
+	if (count > 1)
+		ERROR;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+
+
+void *narrow_candidate_datatypes_c::visit(sub_expression_c *symbol) {
+	int count = 0;
+
+	if (is_ANY_NUM_compatible(symbol->datatype)) {
+		symbol->l_exp->datatype = symbol->datatype;
+		symbol->r_exp->datatype = symbol->datatype;
+		count++;
+	} else {
+		/* TIME data type */
+		for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+			for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+				/* test widening compatibility */
+				if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+						symbol->r_exp->candidate_datatypes[j],
+						symbol->datatype, widen_SUB_table)) {
+					symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+					symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+					count ++;
+				}
+			}
+		}
+	}
+	if (count > 1)
+		ERROR;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(mul_expression_c *symbol) {
+	int count = 0;
+
+	if (is_ANY_NUM_compatible(symbol->datatype)) {
+		symbol->l_exp->datatype = symbol->datatype;
+		symbol->r_exp->datatype = symbol->datatype;
+		count++;
+	} else {
+		/* TIME data type */
+		for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+			for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+				/* test widening compatibility */
+				if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+						symbol->r_exp->candidate_datatypes[j],
+						symbol->datatype, widen_MUL_table)) {
+					symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+					symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+					count ++;
+				}
+			}
+		}
+	}
+	if (count > 1)
+		ERROR;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(div_expression_c *symbol) {
+	int count = 0;
+
+	if (is_ANY_NUM_compatible(symbol->datatype)) {
+		symbol->l_exp->datatype = symbol->datatype;
+		symbol->r_exp->datatype = symbol->datatype;
+		count++;
+	} else {
+		/* TIME data type */
+		for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+			for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+				/* test widening compatibility */
+				if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+						symbol->r_exp->candidate_datatypes[j],
+						symbol->datatype, widen_DIV_table)) {
+					symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+					symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+					count ++;
+				}
+			}
+		}
+	}
+	if (count > 1)
+		ERROR;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(mod_expression_c *symbol) {
+	symbol->l_exp->datatype = symbol->datatype;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->datatype = symbol->datatype;
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(power_expression_c *symbol) {
+	symbol->l_exp->datatype = symbol->datatype;
+	symbol->l_exp->accept(*this);
+	if (! symbol->r_exp->candidate_datatypes.size()){
+		symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[0];
+		symbol->r_exp->accept(*this);
+	}
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(neg_expression_c *symbol) {
+	symbol->exp->datatype = symbol->datatype;
+	symbol->exp->accept(*this);
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(not_expression_c *symbol) {
+	symbol->exp->datatype = symbol->datatype;
+	symbol->exp->accept(*this);
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(function_invocation_c *symbol) {
+	function_declaration_c *f_decl;
+	list_c *parameter_list;
+	list_c *parameter_candidate_datatypes;
+	function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+	function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+
+	if (NULL != symbol->formal_param_list)
+		parameter_list = (list_c *)symbol->formal_param_list;
+	else if (NULL != symbol->nonformal_param_list)
+		parameter_list = (list_c *)symbol->nonformal_param_list;
+	else ERROR;
+	for(; lower != upper; lower++) {
+		f_decl = function_symtable.get_value(lower);
+		symbol_c * return_type = base_type(f_decl->type_name);
+		if (return_type && typeid(*symbol->datatype) != typeid(*return_type))
+			continue;
+		/* We set which function declaration it'll use in STAGE4 */
+		symbol->called_function_declaration = f_decl;
+		/* Check if function declaration in symbol_table is compatible with parameters */
+		if (NULL != symbol->nonformal_param_list)
+			/* nonformal parameter function call */
+			narrow_nonformal_call(symbol, f_decl);
+		else
+			/* formal parameter function call */
+			narrow_formal_call (symbol, f_decl);
+		break;
+	}
+
+	return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+
+void *narrow_candidate_datatypes_c::visit(assignment_statement_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1)
+		return NULL;
+	symbol->datatype = symbol->candidate_datatypes[0];
+	symbol->l_exp->datatype = symbol->datatype;
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->datatype = symbol->datatype;
+	symbol->r_exp->accept(*this);
+	return NULL;
+}
+
+
+/*****************************************/
+/* B 3.2.2 Subprogram Control Statements */
+/*****************************************/
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+
+void *narrow_candidate_datatypes_c::visit(if_statement_c *symbol) {
+	for(unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+		if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c))
+			symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+	}
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	if (NULL != symbol->elseif_statement_list)
+		symbol->elseif_statement_list->accept(*this);
+	if (NULL != symbol->else_statement_list)
+		symbol->else_statement_list->accept(*this);
+	return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(elseif_statement_c *symbol) {
+	for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+		if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c))
+			symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+	}
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
+void *narrow_candidate_datatypes_c::visit(case_statement_c *symbol) {
+	for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+		if ((is_ANY_INT_type(symbol->expression->candidate_datatypes[i]))
+				 || (search_base_type.type_is_enumerated(symbol->expression->candidate_datatypes[i])))
+			symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+	}
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	if (NULL != symbol->case_element_list) {
+		symbol->case_element_list->datatype = symbol->expression->datatype;
+		symbol->case_element_list->accept(*this);
+	}
+	return NULL;
+}
+
+/* helper symbol for case_statement */
+// SYM_LIST(case_element_list_c)
+void *narrow_candidate_datatypes_c::visit(case_element_list_c *symbol) {
+	for (int i = 0; i < symbol->n; i++) {
+		symbol->elements[i]->datatype = symbol->datatype;
+		symbol->elements[i]->accept(*this);
+	}
+	return NULL;
+}
+
+/*  case_list ':' statement_list */
+// SYM_REF2(case_element_c, case_list, statement_list)
+void *narrow_candidate_datatypes_c::visit(case_element_c *symbol) {
+	symbol->case_list->datatype = symbol->datatype;
+	symbol->case_list->accept(*this);
+	symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+// SYM_LIST(case_list_c)
+void *narrow_candidate_datatypes_c::visit(case_list_c *symbol) {
+	for (int i = 0; i < symbol->n; i++) {
+		for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) {
+			if (is_type_equal(symbol->datatype, symbol->elements[i]->candidate_datatypes[k]))
+				symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k];
+		}
+		/* NOTE: this may be an integer, a subrange_c, or a enumerated value! */
+		symbol->elements[i]->accept(*this);
+	}
+	return NULL;
+}
+
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+void *narrow_candidate_datatypes_c::visit(for_statement_c *symbol) {
+	/* Control variable */
+	for(unsigned int i = 0; i < symbol->control_variable->candidate_datatypes.size(); i++) {
+		if (is_ANY_INT_type(symbol->control_variable->candidate_datatypes[i])) {
+			symbol->control_variable->datatype = symbol->control_variable->candidate_datatypes[i];
+		}
+	}
+	symbol->control_variable->accept(*this);
+	/* BEG expression */
+	for(unsigned int i = 0; i < symbol->beg_expression->candidate_datatypes.size(); i++) {
+		if (is_type_equal(symbol->control_variable->datatype,symbol->beg_expression->candidate_datatypes[i]) &&
+				is_ANY_INT_type(symbol->beg_expression->candidate_datatypes[i])) {
+			symbol->beg_expression->datatype = symbol->beg_expression->candidate_datatypes[i];
+		}
+	}
+	symbol->beg_expression->accept(*this);
+	/* END expression */
+	for(unsigned int i = 0; i < symbol->end_expression->candidate_datatypes.size(); i++) {
+		if (is_type_equal(symbol->control_variable->datatype,symbol->end_expression->candidate_datatypes[i]) &&
+				is_ANY_INT_type(symbol->end_expression->candidate_datatypes[i])) {
+			symbol->end_expression->datatype = symbol->end_expression->candidate_datatypes[i];
+		}
+	}
+	symbol->end_expression->accept(*this);
+	/* BY expression */
+	if (NULL != symbol->by_expression) {
+		for(unsigned int i = 0; i < symbol->by_expression->candidate_datatypes.size(); i++) {
+			if (is_type_equal(symbol->control_variable->datatype,symbol->by_expression->candidate_datatypes[i]) &&
+					is_ANY_INT_type(symbol->by_expression->candidate_datatypes[i])) {
+				symbol->by_expression->datatype = symbol->by_expression->candidate_datatypes[i];
+			}
+		}
+		symbol->by_expression->accept(*this);
+	}
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(while_statement_c *symbol) {
+	for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+		if(is_BOOL_type(symbol->expression->candidate_datatypes[i]))
+			symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+	}
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(repeat_statement_c *symbol) {
+	for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+		if(is_BOOL_type(symbol->expression->candidate_datatypes[i]))
+			symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+	}
+	symbol->expression->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/narrow_candidate_datatypes.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,224 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2012       Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2012       Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class narrow_candidate_datatypes_c: public iterator_visitor_c {
+
+  private:
+    symbol_c * selected_datatype;
+    search_varfb_instance_type_c *search_varfb_instance_type;
+    search_base_type_c search_base_type;
+    symbol_c *case_expression_type;
+    symbol_c *il_operand;
+    symbol_c *prev_il_instruction;
+
+    bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]);
+
+  public:
+    narrow_candidate_datatypes_c(symbol_c *ignore);
+    virtual ~narrow_candidate_datatypes_c(void);
+    void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl);
+    void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl);
+
+    symbol_c *base_type(symbol_c *symbol);
+
+    /**********************/
+    /* B 1.3 - Data types */
+    /**********************/
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    void *visit(subrange_c *symbol);
+
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    /********************************************/
+    /* B 1.4.1 - Directly Represented Variables */
+    /********************************************/
+    /*************************************/
+    /* B 1.4.2 - Multi-element variables */
+    /*************************************/
+    void *visit(array_variable_c *symbol);
+    void *visit(subscript_list_c *symbol);
+
+    /**************************************/
+    /* B 1.5 - Program organization units */
+    /**************************************/
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    void *visit(function_declaration_c *symbol);
+
+    /*****************************/
+    /* B 1.5.2 - Function blocks */
+    /*****************************/
+    void *visit(function_block_declaration_c *symbol);
+
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    void *visit(program_declaration_c *symbol);
+
+    /********************************/
+    /* B 1.7 Configuration elements */
+    /********************************/
+    void *visit(configuration_declaration_c *symbol);
+    /****************************************/
+    /* B.2 - Language IL (Instruction List) */
+    /****************************************/
+    /***********************************/
+    /* B 2.1 Instructions and Operands */
+    /***********************************/
+    // void *visit(instruction_list_c *symbol);
+    void *visit(il_simple_operation_c *symbol);
+    void *visit(il_function_call_c *symbol);
+    void *visit(il_expression_c *symbol);
+    void *visit(il_fb_call_c *symbol);
+    void *visit(il_formal_funct_call_c *symbol);
+    /*
+        void *visit(il_operand_list_c *symbol);
+        void *visit(simple_instr_list_c *symbol);
+        void *visit(il_param_list_c *symbol);
+        void *visit(il_param_assignment_c *symbol);
+        void *visit(il_param_out_assignment_c *symbol);
+     */
+
+    /*******************/
+    /* B 2.2 Operators */
+    /*******************/
+    void *visit(LD_operator_c *symbol);
+    void *visit(LDN_operator_c *symbol);
+    void *visit(ST_operator_c *symbol);
+    void *visit(STN_operator_c *symbol);
+    void *visit(NOT_operator_c *symbol);
+    void *visit(S_operator_c *symbol);
+    void *visit(R_operator_c *symbol);
+    void *visit(S1_operator_c *symbol);
+    void *visit(R1_operator_c *symbol);
+    void *visit(CLK_operator_c *symbol);
+    void *visit(CU_operator_c *symbol);
+    void *visit(CD_operator_c *symbol);
+    void *visit(PV_operator_c *symbol);
+    void *visit(IN_operator_c *symbol);
+    void *visit(PT_operator_c *symbol);
+    void *visit(AND_operator_c *symbol);
+    void *visit(OR_operator_c *symbol);
+    void *visit(XOR_operator_c *symbol);
+    void *visit(ANDN_operator_c *symbol);
+    void *visit(ORN_operator_c *symbol);
+    void *visit(XORN_operator_c *symbol);
+    void *visit(ADD_operator_c *symbol);
+    void *visit(SUB_operator_c *symbol);
+    void *visit(MUL_operator_c *symbol);
+    void *visit(DIV_operator_c *symbol);
+    void *visit(MOD_operator_c *symbol);
+    void *visit(GT_operator_c *symbol);
+    void *visit(GE_operator_c *symbol);
+    void *visit(EQ_operator_c *symbol);
+    void *visit(LT_operator_c *symbol);
+    void *visit(LE_operator_c *symbol);
+    void *visit(NE_operator_c *symbol);
+    void *visit(CAL_operator_c *symbol);
+    void *visit(CALC_operator_c *symbol);
+    void *visit(CALCN_operator_c *symbol);
+    void *visit(RET_operator_c *symbol);
+    void *visit(RETC_operator_c *symbol);
+    void *visit(RETCN_operator_c *symbol);
+    void *visit(JMP_operator_c *symbol);
+    void *visit(JMPC_operator_c *symbol);
+    void *visit(JMPCN_operator_c *symbol);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, variable_name);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, option, variable_name);
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    void *visit(or_expression_c *symbol);
+    void *visit(xor_expression_c *symbol);
+    void *visit(and_expression_c *symbol);
+    void *visit(equ_expression_c *symbol);
+    void *visit(notequ_expression_c *symbol);
+    void *visit(lt_expression_c *symbol);
+    void *visit(gt_expression_c *symbol);
+    void *visit(le_expression_c *symbol);
+    void *visit(ge_expression_c *symbol);
+    void *visit(add_expression_c *symbol);
+    void *visit(sub_expression_c *symbol);
+    void *visit(mul_expression_c *symbol);
+    void *visit(div_expression_c *symbol);
+    void *visit(mod_expression_c *symbol);
+    void *visit(power_expression_c *symbol);
+    void *visit(neg_expression_c *symbol);
+    void *visit(not_expression_c *symbol);
+
+    void *visit(function_invocation_c *symbol);
+
+    /*********************************/
+    /* B 3.2.1 Assignment Statements */
+    /*********************************/
+    void *visit(assignment_statement_c *symbol);
+
+    /********************************/
+    /* B 3.2.3 Selection Statements */
+    /********************************/
+    void *visit(if_statement_c *symbol);
+    void *visit(elseif_statement_c *symbol);
+    void *visit(case_statement_c *symbol);
+    void *visit(case_element_list_c *symbol);
+    void *visit(case_element_c *symbol);
+    void *visit(case_list_c *symbol);
+
+    /********************************/
+    /* B 3.2.4 Iteration Statements */
+    /********************************/
+    void *visit(for_statement_c *symbol);
+    void *visit(while_statement_c *symbol);
+    void *visit(repeat_statement_c *symbol);
+
+}; // narrow_candidate_datatypes_c
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/print_datatypes_error.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1162 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 20011-2012 Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 20011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ *  Fill candidate list of data types for all symbols
+ */
+
+#include "print_datatypes_error.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+
+#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
+#define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
+
+#define STAGE3_ERROR(symbol1, symbol2, ...) {                                          \
+    fprintf(stderr, "%s:%d-%d..%d-%d: error : ",                                       \
+           FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \
+                                                LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column); \
+    fprintf(stderr, __VA_ARGS__);                                                      \
+    fprintf(stderr, "\n");                                                             \
+    il_error = true;                                                                   \
+    error_found = true;\
+  }
+
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+print_datatypes_error_c::print_datatypes_error_c(symbol_c *ignore) {
+	error_found = false;
+}
+
+print_datatypes_error_c::~print_datatypes_error_c(void) {
+	error_found = false;
+}
+
+int print_datatypes_error_c::get_error_found() {
+	return error_found;
+}
+
+/* a helper function... */
+symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) {
+	/* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+	 *       in the code.
+	 */
+	if (symbol == NULL) return NULL;
+	return (symbol_c *)symbol->accept(search_base_type);
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+void *print_datatypes_error_c::visit(real_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(integer_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(neg_real_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(neg_integer_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(binary_integer_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(octal_integer_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(hex_integer_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(integer_literal_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(real_literal_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(bit_string_literal_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BIT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_BIT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_literal_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_true_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_false_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+	}
+	return NULL;
+}
+
+/*******************************/
+/* B.1.2.2   Character Strings */
+/*******************************/
+void *print_datatypes_error_c::visit(double_byte_character_string_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for WSTRING data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "WSTRING data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(single_byte_character_string_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for STRING data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "STRING data type not valid in this location.");
+	}
+	return NULL;
+}
+
+/***************************/
+/* B 1.2.3 - Time Literals */
+/***************************/
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+void *print_datatypes_error_c::visit(duration_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Invalid syntax for TIME data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "TIME data type not valid in this location.");
+	}
+	return NULL;
+}
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+void *print_datatypes_error_c::visit(time_of_day_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Invalid syntax for TOD data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "TOD data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(date_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Invalid syntax for DATE data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "DATE data type not valid in this location.");
+	}
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(date_and_time_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0) {
+		STAGE3_ERROR(symbol, symbol, "Invalid syntax for DT data type.");
+	} else if (NULL == symbol->datatype) {
+		STAGE3_ERROR(symbol, symbol, "DT data type not valid in this location.");
+	}
+	return NULL;
+}
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+void *print_datatypes_error_c::visit(data_type_declaration_c *symbol) {
+	// TODO !!!
+	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(enumerated_value_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0)
+		STAGE3_ERROR(symbol, symbol, "Ambiguous enumerate value or Variable not declared in this scope.");
+	return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *print_datatypes_error_c::visit(symbolic_variable_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0)
+		STAGE3_ERROR(symbol, symbol, "Variable not declared in this scope.");
+	return NULL;
+}
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+void *print_datatypes_error_c::visit(direct_variable_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0)
+		STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for located variable data type.");
+	return NULL;
+}
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/*  subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *print_datatypes_error_c::visit(array_variable_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0)
+		STAGE3_ERROR(symbol, symbol, "Array variable not declared in this scope.");
+	
+	/* recursively call the subscript list to print any errors in the expressions used in the subscript...*/
+	symbol->subscript_list->accept(*this);
+	return NULL;
+}
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */
+#if 0
+void *print_datatypes_error_c::visit(subscript_list_c *symbol) {
+}
+#endif
+
+
+/*  record_variable '.' field_selector */
+/*  WARNING: input and/or output variables of function blocks
+ *           may be accessed as fields of a structured variable!
+ *           Code handling a structured_variable_c must take
+ *           this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+/* NOTE: We do not recursively determine the data types of each field_selector in fill_candidate_datatypes_c,
+ * so it does not make sense to recursively visit all the field_selectors to print out error messages. 
+ * Maybe in the future, if we find the need to print out more detailed error messages, we might do it that way. For now, we don't!
+ */
+void *print_datatypes_error_c::visit(structured_variable_c *symbol) {
+	if (symbol->candidate_datatypes.size() == 0)
+		STAGE3_ERROR(symbol, symbol, "Structure variable not declared in this scope.");
+	return NULL;
+}
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *print_datatypes_error_c::visit(function_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	/* We do not check for data type errors in variable declarations, Skip this for now... */
+// 	symbol->var_declarations_list->accept(*this);
+	if (debug) printf("Print error data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+	il_parenthesis_level = 0;
+	il_error = false;
+	prev_il_instruction = NULL;
+	symbol->function_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *print_datatypes_error_c::visit(function_block_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	/* We do not check for data type errors in variable declarations, Skip this for now... */
+// 	symbol->var_declarations->accept(*this);
+	if (debug) printf("Print error data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+	il_parenthesis_level = 0;
+	il_error = false;
+	prev_il_instruction = NULL;
+	symbol->fblock_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *print_datatypes_error_c::visit(program_declaration_c *symbol) {
+	search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+	/* We do not check for data type errors in variable declarations, Skip this for now... */
+// 	symbol->var_declarations->accept(*this);
+	if (debug) printf("Print error data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+	il_parenthesis_level = 0;
+	il_error = false;
+	prev_il_instruction = NULL;
+	symbol->function_block_body->accept(*this);
+	prev_il_instruction = NULL;
+	delete search_varfb_instance_type;
+	search_varfb_instance_type = NULL;
+	return NULL;
+}
+
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *print_datatypes_error_c::visit(configuration_declaration_c *symbol) {
+#if 0
+	// TODO !!!
+	/* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+	return NULL;
+}
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) {
+	il_operand = symbol->il_operand;
+	if (NULL != symbol->il_operand) {
+		symbol->il_operand->accept(*this);
+	}
+	/* recursive call to see whether data types are compatible */
+	symbol->il_simple_operator->accept(*this);
+	il_operand = NULL;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_function_call_c *symbol) {
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_expression_c *symbol) {
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_fb_call_c *symbol) {
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_formal_funct_call_c *symbol) {
+	return NULL;
+}
+
+
+/*
+    void *visit(il_operand_list_c *symbol);
+    void *visit(simple_instr_list_c *symbol);
+    void *visit(il_param_list_c *symbol);
+    void *visit(il_param_assignment_c *symbol);
+    void *visit(il_param_out_assignment_c *symbol);
+ */
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *print_datatypes_error_c::visit(LD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(LDN_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'LDN' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(ST_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+	/* MANU:
+	 * if prev_instruction is NULL we can print a message error or warning error like:
+	 * we can't use a ST like first instruction.
+	 * What do you think?
+	 */
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ST' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(STN_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+	/* MANU:
+	 * if prev_instruction is NULL we can print a message error or warning error like:
+	 * we can't use a ST like first instruction.
+	 * What do you think?
+	 */
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'STN' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(NOT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(S_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(R_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(S1_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S1' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(R1_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R1' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CLK_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CU_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CD_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(PV_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(IN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(PT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(AND_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(OR_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(XOR_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(ANDN_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ANDN' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(ORN_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(XORN_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(ADD_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ADD' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(SUB_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'SUB' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(MUL_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MUL' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(DIV_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'DIV' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(MOD_operator_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	il_operand->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(il_operand->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MOD' operator.");
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(GT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(GE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(EQ_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(LT_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(LE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(NE_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CAL_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CALC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(RET_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(RETC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMP_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) {
+	prev_il_instruction = symbol;
+	return NULL;
+}
+
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *print_datatypes_error_c::visit(or_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(xor_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(and_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(equ_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '=' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(notequ_expression_c *symbol)  {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<>' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(lt_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(gt_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(le_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<=' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(ge_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>=' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(add_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Current '+' result and operand not of same data type.");
+
+	return NULL;
+}
+
+
+
+void *print_datatypes_error_c::visit(sub_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+			STAGE3_ERROR(symbol, symbol, "Current '-' result and operand not of same data type.");
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(mul_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Current '*' result and operand not of same data type.");
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(div_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Current '/' result and operand not of same data type.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(mod_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Current 'MOD' result and operand not of same data type.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(power_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0) 		&&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Data type mismatch for '**' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(neg_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0)      &&
+		(symbol->exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NEG' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(not_expression_c *symbol) {
+	if (NULL != symbol->datatype) return NULL;
+
+	symbol->exp->accept(*this);
+	if ((symbol->candidate_datatypes.size() == 0)      &&
+		(symbol->exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NOT' expression.");
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(function_invocation_c *symbol) {
+	list_c *parameter_list;
+	function_declaration_c * f_decl;
+
+	if (NULL != symbol->datatype) return NULL;
+	if (NULL != symbol->formal_param_list)
+		parameter_list = (list_c *)symbol->formal_param_list;
+	else if (NULL != symbol->nonformal_param_list)
+		parameter_list = (list_c *)symbol->nonformal_param_list;
+	else ERROR;
+	parameter_list->accept(*this);
+	if (symbol->candidate_datatypes.size() == 0) {
+		identifier_c *fname = (identifier_c *)symbol->function_name;
+		f_decl = (function_declaration_c *)symbol->called_function_declaration;
+		/*
+		 * Manuele: In the future we have to test parameter number
+		 * and show a specific message.
+		 */
+		STAGE3_ERROR(symbol, symbol, "No matching overloaded '%s' function call.", fname->value);
+	}
+	return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *print_datatypes_error_c::visit(assignment_statement_c *symbol) {
+	symbol->l_exp->accept(*this);
+	symbol->r_exp->accept(*this);
+	if ((NULL == symbol->l_exp->datatype) &&
+	    (NULL == symbol->r_exp->datatype) &&
+		(symbol->l_exp->candidate_datatypes.size() > 0)	&&
+		(symbol->r_exp->candidate_datatypes.size() > 0))
+		STAGE3_ERROR(symbol, symbol, "Invalid data types for ':=' operation.");
+	return NULL;
+}
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+
+void *print_datatypes_error_c::visit(if_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if ((NULL == symbol->expression->datatype) &&
+		(symbol->expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'IF' condition.");
+	}
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	if (NULL != symbol->elseif_statement_list)
+		symbol->elseif_statement_list->accept(*this);
+	if (NULL != symbol->else_statement_list)
+		symbol->else_statement_list->accept(*this);
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(elseif_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if ((NULL == symbol->expression->datatype) &&
+		(symbol->expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'ELSIF' condition.");
+	}
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(case_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if ((NULL == symbol->expression->datatype) &&
+		(symbol->expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "'CASE' quantity not an integer or enumerated.");
+	}
+	symbol->case_element_list->accept(*this);
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+void *print_datatypes_error_c::visit(for_statement_c *symbol) {
+	symbol->control_variable->accept(*this);
+	symbol->beg_expression->accept(*this);
+	symbol->end_expression->accept(*this);
+	/* Control variable */
+	if ((NULL == symbol->control_variable->datatype) &&
+		(symbol->control_variable->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' control variable.");
+	}
+	/* BEG expression */
+	if ((NULL == symbol->beg_expression->datatype) &&
+		(symbol->beg_expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' begin expression.");
+	}
+	/* END expression */
+	if ((NULL == symbol->end_expression->datatype) &&
+		(symbol->end_expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' end expression.");
+	}
+	/* BY expression */
+	if ((NULL != symbol->by_expression) &&
+		(NULL == symbol->by_expression->datatype) &&
+		(symbol->end_expression->candidate_datatypes.size() > 0)) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' by expression.");
+	}
+	/* DO statement */
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(while_statement_c *symbol) {
+	symbol->expression->accept(*this);
+	if (symbol->candidate_datatypes.size() != 1) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'WHILE' condition.");
+		return NULL;
+	}
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	return NULL;
+}
+
+void *print_datatypes_error_c::visit(repeat_statement_c *symbol) {
+	if (symbol->candidate_datatypes.size() != 1) {
+		STAGE3_ERROR(symbol, symbol, "Invalid data type for 'REPEAT' condition.");
+		return NULL;
+	}
+	if (NULL != symbol->statement_list)
+		symbol->statement_list->accept(*this);
+	symbol->expression->accept(*this);
+	return NULL;
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/print_datatypes_error.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,303 @@
+/*
+ *  matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ *  Copyright (C) 2009-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2011-2012  Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2011-2012  Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class print_datatypes_error_c: public iterator_visitor_c {
+
+  private:
+    search_varfb_instance_type_c *search_varfb_instance_type;
+    search_base_type_c search_base_type;
+    /* When calling a function block, we must first find it's type,
+     * by searching through the declarations of the variables currently
+     * in scope.
+     * This class does just that...
+     * A new object instance is instantiated whenever we start checking semantics
+     * for a function block type declaration, or a program declaration.
+     * This object instance will then later be called while the
+     * function block's or the program's body is being handled.
+     *
+     * Note that functions cannot contain calls to function blocks,
+     * so we do not create an object instance when handling
+     * a function declaration.
+     */
+
+    /* In IL code, once we find a type mismatch error, it is best to
+     * ignore any further errors until the end of the logical operation,
+     * i.e. until the next LD.
+     * However, we cannot clear the il_error flag on all LD operations,
+     * as these may also be used within parenthesis. LD operations
+     * within parenthesis may not clear the error flag.
+     * We therefore need a counter to know how deep inside a parenthesis
+     * structure we are.
+     */
+    int  il_parenthesis_level;
+    bool il_error;
+    bool error_found;
+
+    /* the current data type of the data stored in the IL stack, i.e. the default variable */
+    symbol_c *prev_il_instruction;
+    /* the current IL operand being analyzed - its symbol and its data type */
+    symbol_c *il_operand_type;
+    symbol_c *il_operand;
+
+
+  public:
+    print_datatypes_error_c(symbol_c *ignore);
+    virtual ~print_datatypes_error_c(void);
+    int get_error_found();
+
+    /* a helper function... */
+    symbol_c *base_type(symbol_c *symbol);
+
+    /*********************/
+    /* B 1.2 - Constants */
+    /*********************/
+    /******************************/
+    /* B 1.2.1 - Numeric Literals */
+    /******************************/
+    void *visit(real_c *symbol);
+    void *visit(integer_c *symbol);
+    void *visit(neg_real_c *symbol);
+    void *visit(neg_integer_c *symbol);
+    void *visit(binary_integer_c *symbol);
+    void *visit(octal_integer_c *symbol);
+    void *visit(hex_integer_c *symbol);
+    void *visit(integer_literal_c *symbol);
+    void *visit(real_literal_c *symbol);
+    void *visit(bit_string_literal_c *symbol);
+    void *visit(boolean_literal_c *symbol);
+    void *visit(boolean_true_c *symbol);
+    void *visit(boolean_false_c *symbol);
+
+    /*******************************/
+    /* B.1.2.2   Character Strings */
+    /*******************************/
+    void *visit(double_byte_character_string_c *symbol);
+    void *visit(single_byte_character_string_c *symbol);
+
+    /***************************/
+    /* B 1.2.3 - Time Literals */
+    /***************************/
+    /************************/
+    /* B 1.2.3.1 - Duration */
+    /************************/
+    void *visit(duration_c *symbol);
+
+    /************************************/
+    /* B 1.2.3.2 - Time of day and Date */
+    /************************************/
+    void *visit(time_of_day_c *symbol);
+    void *visit(date_c *symbol);
+    void *visit(date_and_time_c *symbol);
+
+    /**********************/
+    /* B 1.3 - Data types */
+    /**********************/
+    /********************************/
+    /* B 1.3.3 - Derived data types */
+    /********************************/
+    void *visit(data_type_declaration_c *symbol);
+    void *visit(enumerated_value_c *symbol);
+
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol);
+
+    /********************************************/
+    /* B 1.4.1 - Directly Represented Variables */
+    /********************************************/
+    void *visit(direct_variable_c *symbol);
+
+    /*************************************/
+    /* B 1.4.2 - Multi-element variables */
+    /*************************************/
+    void *visit(array_variable_c *symbol);
+    void *visit(structured_variable_c *symbol);
+
+    /**************************************/
+    /* B 1.5 - Program organization units */
+    /**************************************/
+    /***********************/
+    /* B 1.5.1 - Functions */
+    /***********************/
+    void *visit(function_declaration_c *symbol);
+
+    /*****************************/
+    /* B 1.5.2 - Function blocks */
+    /*****************************/
+    void *visit(function_block_declaration_c *symbol);
+
+    /**********************/
+    /* B 1.5.3 - Programs */
+    /**********************/
+    void *visit(program_declaration_c *symbol);
+
+    /********************************/
+    /* B 1.7 Configuration elements */
+    /********************************/
+    void *visit(configuration_declaration_c *symbol);
+
+    /****************************************/
+    /* B.2 - Language IL (Instruction List) */
+    /****************************************/
+    /***********************************/
+    /* B 2.1 Instructions and Operands */
+    /***********************************/
+    // void *visit(instruction_list_c *symbol);
+    void *visit(il_simple_operation_c *symbol);
+    void *visit(il_function_call_c *symbol);
+    void *visit(il_expression_c *symbol);
+    void *visit(il_fb_call_c *symbol);
+    void *visit(il_formal_funct_call_c *symbol);
+    /*
+        void *visit(il_operand_list_c *symbol);
+        void *visit(simple_instr_list_c *symbol);
+        void *visit(il_param_list_c *symbol);
+        void *visit(il_param_assignment_c *symbol);
+        void *visit(il_param_out_assignment_c *symbol);
+     */
+
+    /*******************/
+    /* B 2.2 Operators */
+    /*******************/
+    void *visit(LD_operator_c *symbol);
+    void *visit(LDN_operator_c *symbol);
+    void *visit(ST_operator_c *symbol);
+    void *visit(STN_operator_c *symbol);
+    void *visit(NOT_operator_c *symbol);
+    void *visit(S_operator_c *symbol);
+    void *visit(R_operator_c *symbol);
+    void *visit(S1_operator_c *symbol);
+    void *visit(R1_operator_c *symbol);
+    void *visit(CLK_operator_c *symbol);
+    void *visit(CU_operator_c *symbol);
+    void *visit(CD_operator_c *symbol);
+    void *visit(PV_operator_c *symbol);
+    void *visit(IN_operator_c *symbol);
+    void *visit(PT_operator_c *symbol);
+    void *visit(AND_operator_c *symbol);
+    void *visit(OR_operator_c *symbol);
+    void *visit(XOR_operator_c *symbol);
+    void *visit(ANDN_operator_c *symbol);
+    void *visit(ORN_operator_c *symbol);
+    void *visit(XORN_operator_c *symbol);
+    void *visit(ADD_operator_c *symbol);
+    void *visit(SUB_operator_c *symbol);
+    void *visit(MUL_operator_c *symbol);
+    void *visit(DIV_operator_c *symbol);
+    void *visit(MOD_operator_c *symbol);
+    void *visit(GT_operator_c *symbol);
+    void *visit(GE_operator_c *symbol);
+    void *visit(EQ_operator_c *symbol);
+    void *visit(LT_operator_c *symbol);
+    void *visit(LE_operator_c *symbol);
+    void *visit(NE_operator_c *symbol);
+    void *visit(CAL_operator_c *symbol);
+    void *visit(CALC_operator_c *symbol);
+    void *visit(CALCN_operator_c *symbol);
+    void *visit(RET_operator_c *symbol);
+    void *visit(RETC_operator_c *symbol);
+    void *visit(RETCN_operator_c *symbol);
+    void *visit(JMP_operator_c *symbol);
+    void *visit(JMPC_operator_c *symbol);
+    void *visit(JMPCN_operator_c *symbol);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, variable_name);
+    /* Symbol class handled together with function call checks */
+    // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+    /***************************************/
+    /* B.3 - Language ST (Structured Text) */
+    /***************************************/
+    /***********************/
+    /* B 3.1 - Expressions */
+    /***********************/
+    void *visit(or_expression_c *symbol);
+    void *visit(xor_expression_c *symbol);
+    void *visit(and_expression_c *symbol);
+    void *visit(equ_expression_c *symbol);
+    void *visit(notequ_expression_c *symbol);
+    void *visit(lt_expression_c *symbol);
+    void *visit(gt_expression_c *symbol);
+    void *visit(le_expression_c *symbol);
+    void *visit(ge_expression_c *symbol);
+    void *visit(add_expression_c *symbol);
+    void *visit(sub_expression_c *symbol);
+    void *visit(mul_expression_c *symbol);
+    void *visit(div_expression_c *symbol);
+    void *visit(mod_expression_c *symbol);
+    void *visit(power_expression_c *symbol);
+    void *visit(neg_expression_c *symbol);
+    void *visit(not_expression_c *symbol);
+    void *visit(function_invocation_c *symbol);
+
+    /*********************************/
+    /* B 3.2.1 Assignment Statements */
+    /*********************************/
+    void *visit(assignment_statement_c *symbol);
+
+    /*****************************************/
+    /* B 3.2.2 Subprogram Control Statements */
+    /*****************************************/
+    //void *visit(fb_invocation_c *symbol);
+
+    /********************************/
+    /* B 3.2.3 Selection Statements */
+    /********************************/
+    void *visit(if_statement_c *symbol);
+    //     void *visit(elseif_statement_list_c *symbol);
+    void *visit(elseif_statement_c *symbol);
+    void *visit(case_statement_c *symbol);
+    //     void *visit(case_element_list_c *symbol);
+    //     void *visit(case_element_c *symbol);
+    // void *visit(case_list_c *symbol);
+
+    /********************************/
+    /* B 3.2.4 Iteration Statements */
+    /********************************/
+    void *visit(for_statement_c *symbol);
+    void *visit(while_statement_c *symbol);
+    void *visit(repeat_statement_c *symbol);
+
+}; // print_datatypes_error_c
+
+
+
+
+
+
+
--- a/stage3/stage3.cc	Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/stage3.cc	Wed Feb 01 19:49:11 2012 +0000
@@ -1,8 +1,10 @@
 /*
  *  matiec - a compiler for the programming languages defined in IEC 61131-3
  *
- *  Copyright (C) 2009-2011  Mario de Sousa (msousa@fe.up.pt)
+ *  Copyright (C) 2009-2012  Mario de Sousa (msousa@fe.up.pt)
  *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
+ *  Copyright (C) 2012       Manuele Conti (manuele.conti@sirius-es.it)
+ *  Copyright (C) 2012       Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -32,14 +34,20 @@
 
 #include "stage3.hh"
 
+#include "fill_candidate_datatypes.hh"
+#include "narrow_candidate_datatypes.hh"
+#include "print_datatypes_error.hh"
+
+
 int type_safety(symbol_c *tree_root){
-	visit_expression_type_c visit_expression_type(tree_root);
-
-	(*tree_root).accept(visit_expression_type);
-
-	if (visit_expression_type.get_error_found())
-	  return -1;
-	
+	fill_candidate_datatypes_c fill_candidate_datatypes(tree_root);
+	tree_root->accept(fill_candidate_datatypes);
+	narrow_candidate_datatypes_c narrow_candidate_datatypes(tree_root);
+	tree_root->accept(narrow_candidate_datatypes);
+	print_datatypes_error_c print_datatypes_error(tree_root);
+	tree_root->accept(print_datatypes_error);
+	if (print_datatypes_error.get_error_found())
+		return -1;
 	return 0;
 }
 
--- a/stage3/stage3.hh	Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/stage3.hh	Wed Feb 01 19:49:11 2012 +0000
@@ -31,19 +31,7 @@
  */
 
 
-// #include <stdio.h>  /* required for NULL */
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <typeinfo>
-#include <list>
-#include <strings.h>
-
 #include "../util/symtable.hh"
-#include "../util/dsymtable.hh"
-#include "../absyntax/visitor.hh"
-
-#include "visit_expression_type.hh"
 
 
 int stage3(symbol_c *tree_root);
--- a/stage3/visit_expression_type.cc	Wed Feb 01 13:01:08 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2291 +0,0 @@
-/*
- *  matiec - a compiler for the programming languages defined in IEC 61131-3
- *
- *  Copyright (C) 2009-2011  Mario de Sousa (msousa@fe.up.pt)
- *  Copyright (C) 2007-2011  Laurent Bessard and Edouard Tisserant
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- *
- * This code is made available on the understanding that it will not be
- * used in safety-critical situations without a full and competent review.
- */
-
-/*
- * An IEC 61131-3 compiler.
- *
- * Based on the
- * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
- *
- */
-
-
-/* Verify whether the semantic rules of data type compatibility are being followed.
- *
- * For example:
- */
-
-#include "visit_expression_type.hh"
-#include <typeinfo>
-#include <list>
-#include <string>
-#include <string.h>
-#include <strings.h>
-
-
-#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order)   ? (symbol1) : (symbol2))
-#define  LAST_(symbol1, symbol2) (((symbol1)->last_order  > (symbol2)->last_order)    ? (symbol1) : (symbol2))
-
-#define STAGE3_ERROR(symbol1, symbol2, ...) {                                          \
-    fprintf(stderr, "%s:%d-%d..%d-%d: error : ",                                       \
-           FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \
-                                                LAST_(symbol1,symbol2) ->last_line,  LAST_(symbol1,symbol2) ->last_column); \
-    fprintf(stderr, __VA_ARGS__);                                                      \
-    fprintf(stderr, "\n");                                                             \
-    il_error = true;                                                                   \
-    error_found = true;                                                                \
-  }
-
-
-/* set to 1 to see debug info during execution */
-static int debug = 0;
-
-
-void *visit_expression_type_c::visit(program_declaration_c *symbol) {
-  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-  symbol->var_declarations->accept(*this);
-  if (debug) printf("checking semantics in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
-  il_parenthesis_level = 0;
-  il_error = false;
-  il_default_variable_type = NULL;
-  symbol->function_block_body->accept(*this);
-  il_default_variable_type = NULL;
-  delete search_varfb_instance_type;
-  search_varfb_instance_type = NULL;
-  return NULL;
-}
-
-void *visit_expression_type_c::visit(function_declaration_c *symbol) {
-  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-  symbol->var_declarations_list->accept(*this);
-  if (debug) printf("checking semantics in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
-  il_parenthesis_level = 0;
-  il_error = false;
-  il_default_variable_type = NULL;
-  symbol->function_body->accept(*this);
-  il_default_variable_type = NULL;
-  delete search_varfb_instance_type;
-  search_varfb_instance_type = NULL;
-  return NULL;
-}
-
-void *visit_expression_type_c::visit(function_block_declaration_c *symbol) {
-  search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
-  symbol->var_declarations->accept(*this);
-  if (debug) printf("checking semantics in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
-  il_parenthesis_level = 0;
-  il_error = false;
-  il_default_variable_type = NULL;
-  symbol->fblock_body->accept(*this);
-  il_default_variable_type = NULL;
-  delete search_varfb_instance_type;
-  search_varfb_instance_type = NULL;
-  return NULL;
-}
-
-
-
-
-
-
-
-
-
-visit_expression_type_c::visit_expression_type_c(symbol_c *ignore) {
-  error_found = false;
-}
-
-visit_expression_type_c::~visit_expression_type_c(void) {
-}
-
-bool visit_expression_type_c::get_error_found(void) {
-  return error_found;
-}
-
-
-
-/* NOTE on data type handling and literals...
- * ==========================================
- *
- * Literals that are explicitly type cast 
- *   e.g.:   BYTE#42
- *           INT#65
- *           TIME#45h23m
- *               etc...
- *  are NOT considered literals in the following code.
- *  Since they are type cast, and their data type is fixed and well known,
- *  they are treated as a variable of that data type (except when determining lvalues)
- *  In other words, when calling search_constant_type_c on these constants, it returns
- *  a xxxxx_type_name_c, and not one of the xxxx_literal_c ! 
- *
- *  When the following code handles a literal, it is really a literal of unknown data type.
- *    e.g.   42, may be considered an int, a byte, a word, etc... 
- *
- * NOTE: type_symbol == NULL is valid!
- *       This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program.
- *       This will not be of any type, so we always return false.
- */
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  return is_ANY_MAGNITUDE_type(type_symbol)
-      || is_ANY_BIT_type      (type_symbol)
-      || is_ANY_STRING_type   (type_symbol)
-      || is_ANY_DATE_type     (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  return is_ANY_SAFEMAGNITUDE_type(type_symbol)
-      || is_ANY_SAFEBIT_type      (type_symbol)
-      || is_ANY_SAFESTRING_type   (type_symbol)
-      || is_ANY_SAFEDATE_type     (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  /* NOTE: doing 
-   *          return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type()
-   *       is incorrect, as the literals would never be considered compatible...
-   */
-  return is_ANY_MAGNITUDE_compatible(type_symbol)
-      || is_ANY_BIT_compatible      (type_symbol)
-      || is_ANY_STRING_compatible   (type_symbol)
-      || is_ANY_DATE_compatible     (type_symbol);
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_MAGNITUDE_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
-  return is_ANY_NUM_type(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
-  return is_ANY_SAFENUM_type(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_MAGNITUDE_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFEMAGNITUDE_type(type_symbol))              {return true;}
-
-  return is_ANY_NUM_compatible(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_NUM_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_REAL_type(type_symbol))                       {return true;}
-  if (is_ANY_INT_type(type_symbol))                        {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFENUM_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  return is_ANY_SAFEREAL_type(type_symbol) 
-      || is_ANY_SAFEINT_type (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_NUM_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_REAL_compatible(type_symbol))                       {return true;}
-  if (is_ANY_INT_compatible(type_symbol))                        {return true;}
-  return false;  
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_DATE_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(tod_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(dt_type_name_c))   {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEDATE_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(safetod_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safedt_type_name_c))   {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_DATE_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_DATE_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFEDATE_type(type_symbol))              {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_STRING_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
-// TODO literal_string ???
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFESTRING_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_STRING_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_STRING_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFESTRING_type(type_symbol))              {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_INT_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(sint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(int_type_name_c))   {return true;}
-  if (typeid(*type_symbol) == typeid(dint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(lint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(uint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEINT_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safesint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safeint_type_name_c))   {return true;}
-  if (typeid(*type_symbol) == typeid(safedint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safelint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(safeuint_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_INT_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_INT_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFEINT_type(type_symbol))              {return true;}
-  if (is_literal_integer_type(type_symbol))          {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_REAL_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(real_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEREAL_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safereal_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_REAL_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_REAL_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFEREAL_type(type_symbol))              {return true;}
-  if (is_literal_real_type(type_symbol))              {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BIT_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(bool_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(byte_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(word_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(dword_type_name_c))    {return true;}
-  if (typeid(*type_symbol) == typeid(lword_type_name_c))    {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEBIT_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safebool_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(safebyte_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(safeword_type_name_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(safedword_type_name_c))    {return true;}
-  if (typeid(*type_symbol) == typeid(safelword_type_name_c))    {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BIT_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_ANY_BIT_type    (type_symbol))              {return true;}
-  if (is_ANY_SAFEBIT_type(type_symbol))              {return true;}
-  if (is_nonneg_literal_integer_type(type_symbol))   {return true;}
-  if (is_literal_bool_type(type_symbol))             {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_BOOL_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(bool_type_name_c))      {return true;}
-  return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_SAFEBOOL_type(symbol_c *type_symbol){
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(safebool_type_name_c))  {return true;}
-  return false;  
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BOOL_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (is_BOOL_type    (type_symbol))              {return true;}
-  if (is_SAFEBOOL_type(type_symbol))              {return true;}
-  if (is_literal_bool_type(type_symbol))              {return true;}
-  return false;
-}
-
-
-#define is_type(type_name_symbol, type_name_class)  ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class)))
-
-
-#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol)
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(neg_integer_c))        {return true;}
-  return is_nonneg_literal_integer_type(type_symbol);
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_nonneg_literal_integer_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(integer_c))        {return true;}
-  if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(octal_integer_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(hex_integer_c))    {return true;}
-  return false;
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(real_c))     {return true;}
-  if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;}
-  return false;
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_bool_type(symbol_c *type_symbol) {
-  bool_type_name_c bool_t;
-
-  if (type_symbol == NULL) {return false;}
-  if (typeid(*type_symbol) == typeid(boolean_true_c))    {return true;}
-  if (typeid(*type_symbol) == typeid(boolean_false_c))   {return true;}
-  if (is_nonneg_literal_integer_type(type_symbol))
-    if (sizeoftype(&bool_t) >= sizeoftype(type_symbol))  {return true;}
-  return false;
-}
-
-bool visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return false;}
-  if (search_base_type.type_is_enumerated(type_symbol)) {return true;}
-  return is_ANY_ELEMENTARY_compatible(type_symbol);
-}
-
-
-/* Determine the common data type between two data types.
- * If no common data type found, return NULL.
- *
- * If data types are identical, return the first (actually any would do...).
- * If any of the data types is a literal, we confirm that 
- *   the literal uses less bits than the fixed size data type.
- *   e.g. BYTE and 1024 returns NULL
- *        BYTE and 255  returns BYTE
- *
- * If two literals, then return the literal that requires more bits...
- */
-
-symbol_c *visit_expression_type_c::common_type__(symbol_c *first_type, symbol_c *second_type) {
-  if (first_type == NULL && second_type == NULL) {return NULL;}
-  if (first_type == NULL)  {return second_type;}
-  if (second_type == NULL) {return first_type;}
-
-  if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type))
-    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
-
-  if (is_literal_real_type(first_type) && is_literal_real_type(second_type))
-    {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
-
-  if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
-    {return first_type;}
-
-  /* The following check can only be made after the is_literal_XXXX checks */
-  /* When two literals of the same type, with identical typeid's are checked,
-   * we must return the one that occupies more bits... This is done above.
-   */
-  if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
-
-  /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some
-   *       literal bool values are not literal integers...
-   */ 
-  if (is_BOOL_type(first_type)        && is_literal_bool_type(second_type))    {return first_type;}
-  if (is_BOOL_type(second_type)       && is_literal_bool_type(first_type))     {return second_type;}
-
-  if (is_SAFEBOOL_type(first_type)    && is_literal_bool_type(second_type))    {return first_type;}
-  if (is_SAFEBOOL_type(second_type)   && is_literal_bool_type(first_type))     {return second_type;}
-
-  if (is_SAFEBOOL_type(first_type)    && is_BOOL_type(second_type))            {return second_type;}
-  if (is_SAFEBOOL_type(second_type)   && is_BOOL_type(first_type))             {return first_type;}
-
-  if (is_ANY_BIT_type(first_type)     && is_nonneg_literal_integer_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_BIT_type(second_type)    && is_nonneg_literal_integer_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if (is_ANY_SAFEBIT_type(first_type)     && is_nonneg_literal_integer_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_SAFEBIT_type(second_type)    && is_nonneg_literal_integer_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if  (is_ANY_SAFEBIT_type(first_type)    && is_ANY_BIT_type(second_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
-  if  (is_ANY_SAFEBIT_type(second_type)   && is_ANY_BIT_type(first_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
-  if (is_ANY_INT_type(first_type)     && is_literal_integer_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_INT_type(second_type)    && is_literal_integer_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if (is_ANY_SAFEINT_type(first_type)     && is_literal_integer_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_SAFEINT_type(second_type)    && is_literal_integer_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if  (is_ANY_SAFEINT_type(first_type)    && is_ANY_INT_type(second_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
-  if  (is_ANY_SAFEINT_type(second_type)   && is_ANY_INT_type(first_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
-  if (is_ANY_REAL_type(first_type)    && is_literal_real_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_REAL_type(second_type)   && is_literal_real_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if (is_ANY_SAFEREAL_type(first_type)    && is_literal_real_type(second_type))
-    {return ((sizeoftype(first_type)  >= sizeoftype(second_type))? first_type :NULL);}
-  if (is_ANY_SAFEREAL_type(second_type)   && is_literal_real_type(first_type))
-    {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
-  if  (is_ANY_SAFEREAL_type(first_type)    && is_ANY_REAL_type(second_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
-  if  (is_ANY_SAFEREAL_type(second_type)   && is_ANY_REAL_type(first_type))
-    {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
-  /* the Time and Date types... */
-  if (is_type(first_type,  safetime_type_name_c) && is_type(second_type, time_type_name_c))  {return second_type;}
-  if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c))  {return  first_type;}
-
-  if (is_type(first_type,  safedate_type_name_c) && is_type(second_type, date_type_name_c))  {return second_type;}
-  if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c))  {return  first_type;}
-
-  if (is_type(first_type,  safedt_type_name_c)   && is_type(second_type, dt_type_name_c))    {return second_type;}
-  if (is_type(second_type, safedt_type_name_c)   && is_type( first_type, dt_type_name_c))    {return  first_type;}
-
-  if (is_type(first_type,  safetod_type_name_c)  && is_type(second_type, tod_type_name_c))   {return second_type;}
-  if (is_type(second_type, safetod_type_name_c)  && is_type( first_type, tod_type_name_c))   {return  first_type;}
-
-  /* no common type */
-  return NULL;
-}
-
-/* Determine the common data type between two data types.
- * Unlike the common_type__() function, we stop the compiler with an ERROR
- *  if no common data type is found.
- */
-symbol_c *visit_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) {
-/*  
-  symbol_c *res = common_type__(first_type, second_type);
-  if (NULL == res) ERROR;
-  return res;
-*/
-  return common_type__(first_type, second_type);
-}
-
-
-/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
- * such as: 
- *     var_type     value_type
- *    BOOL           BYTE#7     -> returns false
- *    INT            INT#7      -> returns true
- *    INT            7          -> returns true
- *    REAL           7.89       -> returns true
- *    REAL           7          -> returns true
- *    INT            7.89       -> returns false
- *    SAFEBOOL       BOOL#1     -> returns false   !!!
- *   etc...
- *
- * NOTE: It is assumed that the var_type is the data type of an lvalue
- */
-bool visit_expression_type_c::is_valid_assignment(symbol_c *var_type, symbol_c *value_type) {
-  if (var_type == NULL)   {/* STAGE3_ERROR(value_type, value_type, "Var_type   == NULL"); */ return false;}
-  if (value_type == NULL) {/* STAGE3_ERROR(var_type,   var_type,   "Value_type == NULL"); */ return false;}
-
-  symbol_c *common_type = common_type__(var_type, value_type);
-  if (NULL == common_type)
-    return false;
-  return (typeid(*var_type) == typeid(*common_type));
-}
-
-
-/* Return TRUE if there is a common data type, otherwise return FALSE
- * i.e., return TRUE if both data types may be used simultaneously in an expression
- * such as:
- *    BOOL#0     AND BYTE#7  -> returns false
- *    0          AND BYTE#7  -> returns true
- *    INT#10     AND INT#7   -> returns true
- *    INT#10     AND 7       -> returns true
- *    REAL#34.3  AND 7.89    -> returns true
- *    REAL#34.3  AND 7       -> returns true
- *    INT#10     AND 7.89    -> returns false
- *    SAFEBOOL#0 AND BOOL#1  -> returns true   !!!
- *   etc...
- */
-bool visit_expression_type_c::is_compatible_type(symbol_c *first_type, symbol_c *second_type) {
-  if (first_type == NULL || second_type == NULL) {return false;}
-  return (NULL != common_type__(first_type, second_type));
-}
-
-
-
-
-/* A helper function... */
-/*
-symbol_c *visit_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type,
-                                                              is_data_type_t is_data_type) {
-*/
-symbol_c *visit_expression_type_c::compute_expression(symbol_c *left_type,      symbol_c *right_type,     is_data_type_t is_data_type,
-						      symbol_c *left_expr, symbol_c *right_expr) {
-  bool error = false;
-
-  if (!(this->*is_data_type)(left_type)) {
-    if (debug) printf("visit_expression_type_c::compute_expression(): invalid left_type\n");
-    if (left_expr != NULL)
-      STAGE3_ERROR(left_expr, left_expr, "Invalid data type of operand, or of data resulting from previous IL instructions.");
-    error = true;
-  }
-  if (!(this->*is_data_type)(right_type)) {
-    if (debug) printf("visit_expression_type_c::compute_expression(): invalid right_type\n");
-    if (right_expr != NULL)
-      STAGE3_ERROR(right_expr, right_expr, "Invalid data type of operand.");
-    error = true;
-  }
-  if (!is_compatible_type(left_type, right_type)) {
-    if (debug) printf("visit_expression_type_c::compute_expression(): left_type & right_type are incompatible\n");
-    if ((left_expr != NULL) && (right_expr != NULL))
-      STAGE3_ERROR(left_expr, right_expr, "Type mismatch between operands.");
-    error = true;
-  }
-
-  if (error)
-    return NULL;
-  else
-    return common_type(left_type, right_type);
-}
-
-
-
-
-/* A helper function... */
-/* check the semantics of a FB or Function non-formal call */
-/* e.g. foo(1, 2, 3, 4);  */
-/* If error_count pointer is != NULL, we do not really print out the errors,
- * but rather only count how many errors were found.
- * This is used to support overloaded functions, where we have to check each possible
- * function, one at a time, untill we find a function call without any errors.
- */
-void visit_expression_type_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar, int *error_count) {
-  symbol_c *call_param_value, *call_param_type, *param_type;
-  identifier_c *param_name;
-  function_param_iterator_c       fp_iterator(f_decl);
-  function_call_param_iterator_c fcp_iterator(f_call);
-  int extensible_parameter_highest_index = -1;
-  
-  /* reset error counter */
-  if (error_count != NULL) *error_count = 0;
-  /* if use_il_defvar, then the first parameter for the call comes from the il_default_variable */
-  if (use_il_defvar) {
-    /* The first parameter of the function corresponds to the il_default_variable_type of the function call */
-    do {
-      param_name = fp_iterator.next();
-      if(param_name == NULL) break;
-      /*  The EN and ENO parameters are default parameters.
-       *  In the non-formal invocation of a function there can be no assignment of
-       * values to these parameters. Therefore, we ignore the parameters declared
-       * in the function.
-       */
-    } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
-    /* If the function does not have any parameters (param_name == NULL)
-     * then we cannot compare its type with the il_default_variable_type.
-     *
-     * However, I (Mario) think this is invalid syntax, as it seems to me all functions must
-     * have at least one parameter.
-     * However, we will make this semantic verification consider it possible, as later
-     * versions of the standard may change that syntax.
-     * So, instead of generating a syntax error message, we simply check whether the call
-     * is passing any more parameters besides the default variable (the il default variable may be ignored
-     * in this case, and not consider it as being a parameter being passed to the function).
-     * If it does, then we have found a semantic error, otherwise the function call is 
-     * correct, and we simply return.
-     */
-    if(param_name == NULL) {
-      if (fcp_iterator.next_nf() != NULL)
-        STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call.");
-      return;
-    } else { 
-      /* param_name != NULL */
-      param_type = fp_iterator.param_type();
-      if(!is_valid_assignment(param_type, il_default_variable_type)) {
-        if (error_count != NULL) (*error_count)++;
-        else STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
-      }
-    }
-    
-    /* the fisrt parameter (il_def_variable) is correct */
-    if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
-      extensible_parameter_highest_index = fp_iterator.extensible_param_index();
-    }
-  } // if (use_il_defvar)
-  
-  
-
-  /* Iterating through the non-formal parameters of the function call */
-  while((call_param_value = fcp_iterator.next_nf()) != NULL) {
-    /* Obtaining the type of the value being passed in the function call */
-    call_param_type = base_type((symbol_c*)call_param_value->accept(*this));
-    if (call_param_type == NULL) {
-      if (error_count != NULL) (*error_count)++;
-      /* the following error will usually occur when ST code uses an identifier, that could refer to an enumerated constant,
-       * but was not actually used as a constant in any definitions of an enumerated data type
-       */
-      else STAGE3_ERROR(call_param_value, call_param_value, "Could not determine data type of value being passed in function/FB call.");
-      continue;
-    }  
-    
-    /* Iterate to the next parameter of the function being called.
-     * Get the name of that parameter, and ignore if EN or ENO.
-     */
-    do {
-      param_name = fp_iterator.next();
-      /* If there is no other parameter declared, then we are passing too many parameters... */
-      if(param_name == NULL) {
-        if (error_count != NULL) (*error_count)++;
-        /* Note: We don't want to print out the follwoing error message multiple times, so we return instead of continuing with 'break' */
-        else STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); return;
-      }
-    } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
-
-    /* Get the parameter type */
-    param_type = base_type(fp_iterator.param_type());
-    /* If the declared parameter and the parameter from the function call do not have the same type */
-    if(!is_valid_assignment(param_type, call_param_type)) {
-      if (error_count != NULL) (*error_count)++;
-      else STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
-    }
-
-    if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
-      extensible_parameter_highest_index = fp_iterator.extensible_param_index();
-    }
-  }
-  
-  /* The function call may not have any errors! */
-  /* In the case of a call to an extensible function, we store the highest index 
-   * of the extensible parameters this particular call uses, in the symbol_c object
-   * of the function call itself!
-   * In calls to non-extensible functions, this value will be set to -1.
-   * This information is later used in stage4 to correctly generate the
-   * output code.
-   */
-  int extensible_param_count = -1;
-  if (extensible_parameter_highest_index >=0) /* if call to extensible function */
-    extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
-  il_function_call_c     *il_function_call = dynamic_cast<il_function_call_c *>(f_call);
-  function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
-  if      (il_function_call     != NULL) il_function_call   ->extensible_param_count = extensible_param_count;
-  else if (function_invocation  != NULL) function_invocation->extensible_param_count = extensible_param_count;
-  //   else ERROR;  /* this function is also called by Function Blocks, so this is not an error! */
-}
-
-
-/* check semantics of FB call in the IL language using input operators */
-/* e.g. CU, CLK, IN, PT, SR, ...                                       */
-void visit_expression_type_c::check_il_fbcall(symbol_c *il_operator, const char *il_operator_str) {
-  symbol_c *call_param_type = il_default_variable_type;
-  symbol_c *fb_decl = il_operand_type;
-    /* The following should never occur. The function block must be defined, 
-     * and the FB type being called MUST be in the symtable... 
-     * This was all already checked at stage 2!
-     */
-  if (NULL == fb_decl) ERROR;
-  if (call_param_type == NULL) ERROR;
-
-  /* We also create an identifier_c object, so we can later use it to find the equivalent FB parameter */
-  /* Note however that this symbol does not have the correct location (file name and line numbers) 
-   * so any error messages must use the il_operator symbol to generate the error location
-   */
-  identifier_c call_param_name(il_operator_str);
-
-  /* Obtaining the type of the value being passed in the function call */
-  call_param_type = base_type(call_param_type);
-  if (call_param_type == NULL) STAGE3_ERROR(il_operator, il_operator, "Could not determine data type of value being passed in FB call.");
-
-  /* Find the corresponding parameter of the function being called */
-  function_param_iterator_c fp_iterator(fb_decl);
-  if(fp_iterator.search(&call_param_name) == NULL) {
-    STAGE3_ERROR(il_operand, il_operand, "Called FB does not have an input parameter named %s.", il_operator_str);
-  } else {
-    /* Get the parameter type */
-    symbol_c *param_type = base_type(fp_iterator.param_type());
-    /* If the declared parameter and the parameter from the function call have the same type */
-    if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(il_operator, il_operator, "Type mismatch in FB call parameter.");
-  }
-}
-
-
-/* A helper function... */
-/* check the semantics of a FB or Function formal call */
-/* e.g. foo(IN1 := 1, OUT1 =>x, EN := true);  */
-/* If error_count pointer is != NULL, we do not really print out the errors,
- * but rather only count how many errors were found.
- * This is used to support overloaded functions, where we have to check each possible
- * function, one at a time, untill we find a function call without any errors.
- */
-void visit_expression_type_c::check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
-  symbol_c *call_param_value, *call_param_type, *call_param_name, *param_type;
-  symbol_c *verify_duplicate_param;
-  identifier_c *param_name;
-  function_param_iterator_c       fp_iterator(f_decl);
-  function_call_param_iterator_c fcp_iterator(f_call);
-  int extensible_parameter_highest_index = -1;
-  identifier_c *extensible_parameter_name;
-
-  /* reset error counter */
-  if (error_count != NULL) *error_count = 0;
-
-  /* Iterating through the formal parameters of the function call */
-  while((call_param_name = fcp_iterator.next_f()) != NULL) {
-        
-    /* Obtaining the value being passed in the function call */
-    call_param_value = fcp_iterator.get_current_value();
-    /* the following should never occur. If it does, then we have a bug in our code... */
-    if (NULL == call_param_value) ERROR;
-
-    /* Checking if there are duplicated parameter values */
-    verify_duplicate_param = fcp_iterator.search_f(call_param_name);
-    if(verify_duplicate_param != call_param_value){
-      if (error_count != NULL) (*error_count)++;
-      else STAGE3_ERROR(call_param_name, verify_duplicate_param, "Duplicated parameter values.");
-    }   
-
-    /* Obtaining the type of the value being passed in the function call */
-    call_param_type = (symbol_c*)call_param_value->accept(*this);
-    if (call_param_type == NULL) {
-      if (error_count != NULL) (*error_count)++;
-      else STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
-      /* The data value being passed is possibly any enumerated type value.
-       * We do not yet handle semantic verification of enumerated types.
-       */
-      ERROR;
-    }
-    call_param_type = base_type(call_param_type);
-    if (call_param_type == NULL) STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
-
-    /* Find the corresponding parameter of the function being called */
-    param_name = fp_iterator.search(call_param_name);
-    if(param_name == NULL) {
-      if (error_count != NULL) (*error_count)++;
-      else STAGE3_ERROR(call_param_name, call_param_name, "Invalid parameter in function/FB call.");
-    } else {
-      /* Get the parameter type */
-      param_type = base_type(fp_iterator.param_type());
-      /* If the declared parameter and the parameter from the function call have the same type */
-      if(!is_valid_assignment(param_type, call_param_type)) {
-        if (error_count != NULL) (*error_count)++;
-        else STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
-      }
-      if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
-        extensible_parameter_highest_index = fp_iterator.extensible_param_index();
-        extensible_parameter_name = param_name;
-      }
-    }
-  }
-  
-  /* In the case of a call to an extensible function, we store the highest index 
-   * of the extensible parameters this particular call uses, in the symbol_c object
-   * of the function call itself!
-   * In calls to non-extensible functions, this value will be set to -1.
-   * This information is later used in stage4 to correctly generate the
-   * output code.
-   */
-  int extensible_param_count = -1;
-  if (extensible_parameter_highest_index >=0) /* if call to extensible function */
-    extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
-  il_formal_funct_call_c *il_formal_funct_call = dynamic_cast<il_formal_funct_call_c *>(f_call);
-  function_invocation_c  *function_invocation  = dynamic_cast<function_invocation_c  *>(f_call);
-  if      (il_formal_funct_call != NULL) il_formal_funct_call->extensible_param_count = extensible_param_count;
-  else if (function_invocation  != NULL) function_invocation->extensible_param_count  = extensible_param_count;
-//   else ERROR;  /* this function is also called by Function Blocks, so this is not an error! */
-
-  /* We have iterated through all the formal parameters of the function call,
-   * and everything seems fine. 
-   * If the function being called in an extensible function, we now check
-   * whether the extensible paramters in the formal invocation do not skip
-   * any indexes...
-   *
-   * f(in1:=0, in2:=0, in4:=0) --> ERROR!!
-   */
-  if (extensible_parameter_highest_index >=0) { /* if call to extensible function */
-    for (int i=fp_iterator.first_extensible_param_index(); i < extensible_parameter_highest_index; i++) {
-      char tmp[256];
-      if (snprintf(tmp, 256, "%s%d", extensible_parameter_name->value, i) >= 256) ERROR;
-      if (fcp_iterator.search_f(tmp) == NULL) {
-        /* error in invocation of extensible function */
-        if (error_count != NULL) (*error_count)++;
-        else STAGE3_ERROR(f_call, f_call, "Missing extensible parameters in call to extensible function.");
-      }  
-    }    
-  }  
-}
-
-
-
-
-/* a helper function... */
-symbol_c *visit_expression_type_c::base_type(symbol_c *symbol) {
-  /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
-   *       in the code.
-   */
-  if (symbol == NULL) return NULL;
-  return (symbol_c *)symbol->accept(search_base_type);
-}
-
-
-/* a helper function... */
-void *visit_expression_type_c::verify_null(symbol_c *symbol){
-  if(il_default_variable_type == NULL){
-    STAGE3_ERROR(symbol, symbol, "Missing LD instruction (or equivalent) before this instruction.");
-  }
-  if(il_operand_type == NULL){
-    STAGE3_ERROR(symbol, symbol, "This instruction requires an operand.");
-  }
-  return NULL;
-}
-
-
-/********************************/
-/* B 1.3.3 - Derived data types */
-/********************************/
-void *visit_expression_type_c::visit(data_type_declaration_c *symbol) {
-  // TODO !!!
-  /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-  return NULL;
-}
-
-
-/*********************/
-/* B 1.4 - Variables */
-/*********************/
-
-void *visit_expression_type_c::visit(symbolic_variable_c *symbol) {
-  return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-/********************************************/
-/* B 1.4.1 - Directly Represented Variables */
-/********************************************/
-void *visit_expression_type_c::visit(direct_variable_c *symbol) {
-  switch (symbol->value[2]) {
-    case 'X': // bit - 1 bit
-      return (void *)&bool_type_name;
-    case 'B': // byte - 8 bits
-      return (void *)&byte_type_name;
-    case 'W': // word - 16 bits
-      return (void *)&word_type_name;
-    case 'D': // double word - 32 bits
-      return (void *)&dword_type_name;
-    case 'L': // long word - 64 bits
-      return (void *)&lword_type_name;
-    default:  // if none of the above, then the empty string was used <=> boolean 
-      return (void *)&bool_type_name;
-   }
-}
-
-/*************************************/
-/* B 1.4.2 - Multi-element variables */
-/*************************************/
-void *visit_expression_type_c::visit(array_variable_c *symbol) {
-  return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-void *visit_expression_type_c::visit(structured_variable_c *symbol) {
-  return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-
-
-/********************************/
-/* B 1.7 Configuration elements */
-/********************************/
-void *visit_expression_type_c::visit(configuration_declaration_c *symbol) {
-  // TODO !!!
-  /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
-  return NULL;
-}
-
-
-/****************************************/
-/* B.2 - Language IL (Instruction List) */
-/****************************************/
-/***********************************/
-/* B 2.1 Instructions and Operands */
-/***********************************/
-/*| instruction_list il_instruction */
-/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
- * We do not need to do anything here...
- */
-// void *visit_expression_type_c::visit(instruction_list_c *symbol)
-
-/* | label ':' [il_incomplete_instruction] eol_list */
-//SYM_REF2(il_instruction_c, label, il_instruction)
-// void *visit_expression_type_c::visit(il_instruction_c *symbol);
-
-
-/* | il_simple_operator [il_operand] */
-// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
-void *visit_expression_type_c::visit(il_simple_operation_c *symbol) {
-  if (il_error)
-    return NULL;
-
-  /* determine the data type of the operand */
-  il_operand = symbol->il_operand;
-  if (symbol->il_operand != NULL){
-    il_operand_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
-  } else {
-    il_operand_type = NULL;
-  }
-  /* recursive call to see whether data types are compatible */
-  symbol->il_simple_operator->accept(*this);
-
-  il_operand_type = NULL;
-  il_operand = NULL;
-  return NULL;
-}
-
-// | function_name [il_operand_list] */
-//SYM_REF2(il_function_call_c, function_name, il_operand_list)
-void *visit_expression_type_c::visit(il_function_call_c *symbol) {
-  if (il_error)
-    return NULL;
-
-  symbol_c *return_data_type = NULL;
-
-  /* First find the declaration of the function being called! */
-  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
-  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
-  if (lower == function_symtable.end()) ERROR;
-
-  int error_count = 0; 
-  int *error_count_ptr = NULL;
-
-  function_symtable_t::iterator second = lower;
-  second++;
-  if (second != upper) 
-    /* This is a call to an overloaded function... */  
-    error_count_ptr = &error_count;
-
-  for(; lower != upper; lower++) {
-    function_declaration_c *f_decl = function_symtable.get_value(lower);
-    
-    check_nonformal_call(symbol, f_decl, true, error_count_ptr);
-    
-    if (0 == error_count) {
-      /* Either: 
-       * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
-       * (ii) we have a call to an overloaded function, with no errors!
-       */
-      
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      /* determine the base data type returned by the function being called... */
-      return_data_type = base_type(f_decl->type_name);
-      /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */
-      if (NULL == return_data_type) ERROR;
-      /* set the new data type of the default variable for the following verifications... */
-      il_default_variable_type = return_data_type;
-      return NULL;
-    }
-  }
-
-  /* No compatible function was found for this function call */
-  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
-  return NULL;
-}
-
-
-/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
-// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
-void *visit_expression_type_c::visit(il_expression_c *symbol) {
-  if (il_error)
-    return NULL;
-
-  symbol_c *il_default_variable_type_back = il_default_variable_type;
-
-  il_parenthesis_level++;
-
-  if(symbol->il_operand != NULL) {
-     il_default_variable_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
-  } else {
-     il_default_variable_type = NULL;
-  }
-
-  if(symbol->simple_instr_list != NULL) {
-    symbol->simple_instr_list->accept(*this);
-  }
-
-  il_parenthesis_level--;
-  if (il_parenthesis_level < 0) ERROR;
-
-  il_operand = symbol->simple_instr_list;
-  il_operand_type = il_default_variable_type;
-  il_default_variable_type = il_default_variable_type_back;
-
-  /* Now check the if the data type semantics of operation are correct,
-   * but only if no previous error has been found...
-   */
-  if (!il_error)
-    symbol->il_expr_operator->accept(*this);
-
-  il_operand_type = NULL;
-  il_operand = NULL;
-  return NULL;
-}
-
-
-#if 0
-/*  il_jump_operator label */
-SYM_REF2(il_jump_operation_c, il_jump_operator, label)
-void *visit_expression_type_c::visit(il_jump_operation_c *symbol);
-#endif
-
-
-/*   il_call_operator prev_declared_fb_name
- * | il_call_operator prev_declared_fb_name '(' ')'
- * | il_call_operator prev_declared_fb_name '(' eol_list ')'
- * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
- * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
- */
-/* SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list) */
-void *visit_expression_type_c::visit(il_fb_call_c *symbol) {
-  if (il_error)
-    return NULL;
-
-  /* first check whether the il_default_variable is of the correct type
-   * for the CAL / CALC / CALCN operator being used...
-   */
-  symbol->il_call_operator->accept(*this);
-
-  /* Now check the FB call itself... */
-
-  /* First we find the declaration of the FB type of the FB instance being called... */
-  /* e.g.  Function_block foo_fb_type
-   *         ...
-   *       End_Function_Block
-   *
-   *       Program test
-   *         var fb1 : foo_fb_type; end_var
-   *         fb1(...)
-   *       End_Program
-   *
-   *    search_varfb_instance_type->get_basetype_decl( identifier_c("fb1") )
-   *    in the scope of Program 'test'
-   *    will return the fb declaration of foo_fb_type !!
-   */
-#if 0
-  symbol_c *fb_decl_symbol = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-    /* The following should never occur. The function block must be defined, 
-     * and the FB type being called MUST be in the symtable... 
-     * This was all already checked at stage 2!
-     */
-  if (NULL == fb_decl_symbol) ERROR;
-
-  function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(fb_decl_symbol);
-    /* should never occur. ... */
-  if (NULL == fb_decl) ERROR;
-#endif
-  symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-    /* The following should never occur. The function block must be defined, 
-     * and the FB type being called MUST be in the symtable... 
-     * This was all already checked at stage 2!
-     */
-  if (NULL == fb_decl) ERROR;
-
-  /* now check the semantics of the fb call... */
-  /* If the syntax parser is working correctly, exactly one of the 
-   * following two symbols will be NULL, while the other is != NULL.
-   */
-  if (NULL != symbol->il_operand_list)  check_nonformal_call(symbol, fb_decl);
-  if (NULL != symbol->il_param_list)    check_formal_call   (symbol, fb_decl);
-
-  return NULL;
-}
-
-
-
-/* | function_name '(' eol_list [il_param_list] ')' */
-/* SYM_REF2(il_formal_funct_call_c, function_name, il_param_list) */
-void *visit_expression_type_c::visit(il_formal_funct_call_c *symbol) {
-  if (il_error)
-    return NULL;
-
-  symbol_c *return_data_type = NULL;
-  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
-  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
-  
-  if (lower == function_symtable.end()) {
-    function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
-    if (current_function_type == function_none) ERROR;
-    return NULL;
-  }
-
-  int error_count = 0; 
-  int *error_count_ptr = NULL;
-
-  function_symtable_t::iterator second = lower;
-  second++;
-  if (second != upper) 
-    /* This is a call to an overloaded function... */  
-    error_count_ptr = &error_count;
-
-  for(; lower != upper; lower++) {
-    function_declaration_c *f_decl = function_symtable.get_value(lower);
-  
-    /* check semantics of data passed in the function call... */
-    check_formal_call(symbol, f_decl, error_count_ptr);
-
-    if (0 == error_count) {
-      /* Either: 
-       * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)  
-       * (ii) we have a call to an overloaded function, with no errors!
-       */
-      
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      /* determine the base data type returned by the function being called... */
-      return_data_type = base_type(f_decl->type_name);
-      /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */
-      if (NULL == return_data_type) ERROR;
-      /* the data type of the data returned by the function, and stored in the il default variable... */
-      il_default_variable_type = return_data_type;
-      return NULL;
-    }  
-  }
-  
-  /* No compatible function was found for this function call */
-  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
-  return NULL;
-}
-
-
-#if 0
-/* | il_operand_list ',' il_operand */
-SYM_LIST(il_operand_list_c)
-void *visit_expression_type_c::visit(il_operand_list_c *symbol);
-
-/* | simple_instr_list il_simple_instruction */
-SYM_LIST(simple_instr_list_c)
-void *visit_expression_type_c::visit(simple_instr_list_c *symbol);
-
-/* | il_initial_param_list il_param_instruction */
-SYM_LIST(il_param_list_c)
-void *visit_expression_type_c::visit(il_param_list_c *symbol);
-
-/*  il_assign_operator il_operand
- * | il_assign_operator '(' eol_list simple_instr_list ')'
- */
-SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list)
-void *visit_expression_type_c::visit(il_param_assignment_c *symbol);
-/*  il_assign_out_operator variable */
-SYM_REF2(il_param_out_assignment_c, il_assign_out_operator, variable)
-void *visit_expression_type_c::visit(il_param_out_assignment_c *symbol);
-
-#endif
-
-
-/*******************/
-/* B 2.2 Operators */
-/*******************/
-
-//SYM_REF0(LD_operator_c)
-void *visit_expression_type_c::visit(LD_operator_c *symbol) {
-  if (0 == il_parenthesis_level)
-    il_error = false;
-
-  if(il_operand_type == NULL)
-      STAGE3_ERROR(symbol, symbol, "LD operator requires an operand.");
-  il_default_variable_type = il_operand_type;
-  return NULL;
-}
-
-// SYM_REF0(LDN_operator_c)
-void *visit_expression_type_c::visit(LDN_operator_c *symbol) {
-  if(il_operand_type == NULL)
-      STAGE3_ERROR(symbol, symbol, "LDN operator requires an operand.");
-  if(!is_ANY_BIT_compatible(il_operand_type))
-      STAGE3_ERROR(symbol, il_operand, "invalid data type of LDN operand, should be of type ANY_BIT.");
-  il_default_variable_type = il_operand_type;
-  return NULL;
-}
-
-// SYM_REF0(ST_operator_c)
-void *visit_expression_type_c::visit(ST_operator_c *symbol) {
-  verify_null(symbol);
-
-  if(!is_valid_assignment(il_operand_type, il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
-  /* TODO: check whether il_operand_type is an LVALUE !! */
-  /* data type of il_default_variable_type is unchanged... */
-  // il_default_variable_type = il_default_variable_type;
-  return NULL;
-}
-
-// SYM_REF0(STN_operator_c)
- void *visit_expression_type_c::visit(STN_operator_c *symbol) {
-  verify_null(symbol);
-  if(!is_valid_assignment(il_operand_type, il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
-  /* TODO: check whether il_operand_type is an LVALUE !! */
-  if(!is_ANY_BIT_compatible(il_default_variable_type))
-      STAGE3_ERROR(symbol, symbol, "invalid data type of il_default_variable for STN operand, should be of type ANY_BIT.");
-  if(!is_ANY_BIT_compatible(il_operand_type))
-      STAGE3_ERROR(symbol, il_operand, "invalid data type of STN operand, should be of type ANY_BIT.");
-  /* data type of il_default_variable_type is unchanged... */
-  // il_default_variable_type = il_default_variable_type;
-  return NULL;
-}
-
-//SYM_REF0(NOT_operator_c)
-void *visit_expression_type_c::visit(NOT_operator_c *symbol) {
-  if(il_operand_type != NULL){
-    STAGE3_ERROR(symbol, il_operand, "NOT operator may not have an operand.");
-    return NULL;
-  }
-  if(il_default_variable_type == NULL) {
-    STAGE3_ERROR(symbol, symbol, "Il default variable should not be NULL.");
-    return NULL;
-  }
-  if(!is_ANY_BIT_compatible(il_default_variable_type)) {
-    STAGE3_ERROR(symbol, symbol, "Il default variable should be of type ANY_BIT.");
-    return NULL;
-  }
-  /* data type of il_default_variable_type is unchanged... */
-  // il_default_variable_type = il_default_variable_type;
-  return NULL;
-}
-
-// SYM_REF0(S_operator_c)
-void *visit_expression_type_c::visit(S_operator_c *symbol) {
-  verify_null(symbol);
-  if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
-  if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator S requires operand of type BOOL.");}
-  /* TODO: check whether il_operand_type is an LVALUE !! */
-  /* data type of il_default_variable_type is unchanged... */
-  // il_default_variable_type = il_default_variable_type;
-  return NULL;
-}
-
-// SYM_REF0(R_operator_c)
-void *visit_expression_type_c::visit(R_operator_c *symbol) {
-  verify_null(symbol);
-  if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
-  if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator R requires operand of type BOOL.");}
-  /* TODO: check whether il_operand_type is an LVALUE !! */
-  /* data type of il_default_variable_type is unchanged... */
-  // il_default_variable_type = il_default_variable_type;
-  return NULL;
-}
-
-
-// SYM_REF0(S1_operator_c)
-void *visit_expression_type_c::visit(S1_operator_c *symbol){
-  check_il_fbcall(symbol, "S1");
-  return NULL;
-}
-
-// SYM_REF0(R1_operator_c)
-void *visit_expression_type_c::visit(R1_operator_c *symbol) {
-  check_il_fbcall(symbol, "R1");
-  return NULL;
-}
-
-// SYM_REF0(CLK_operator_c)
-void *visit_expression_type_c::visit(CLK_operator_c *symbol) {
-  check_il_fbcall(symbol, "CLK");
-  return NULL;
-}
-
-// SYM_REF0(CU_operator_c)
-void *visit_expression_type_c::visit(CU_operator_c *symbol) {
-  check_il_fbcall(symbol, "CU");
-  return NULL;
-}
-
-// SYM_REF0(CD_operator_c)
-void *visit_expression_type_c::visit(CD_operator_c *symbol) {
-  check_il_fbcall(symbol, "CD");
-  return NULL;
-}
-
-// SYM_REF0(PV_operator_c)
-void *visit_expression_type_c::visit(PV_operator_c *symbol) {
-  check_il_fbcall(symbol, "PV");
-  return NULL;
-}
-
-// SYM_REF0(IN_operator_c)
-void *visit_expression_type_c::visit(IN_operator_c *symbol) {
-  check_il_fbcall(symbol, "IN");
-  return NULL;
-}
-
-// SYM_REF0(PT_operator_c)
-void *visit_expression_type_c::visit(PT_operator_c *symbol) {
-  check_il_fbcall(symbol, "PT");
-  return NULL;
-}
-
-//SYM_REF0(AND_operator_c)
-void *visit_expression_type_c::visit(AND_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-//SYM_REF0(OR_operator_c)
-void *visit_expression_type_c::visit(OR_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-//SYM_REF0(XOR_operator_c)
-void *visit_expression_type_c::visit(XOR_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(ANDN_operator_c)
-void *visit_expression_type_c::visit(ANDN_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(ORN_operator_c)
-void *visit_expression_type_c::visit(ORN_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(XORN_operator_c)
-void *visit_expression_type_c::visit(XORN_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(ADD_operator_c)
-void *visit_expression_type_c::visit(ADD_operator_c *symbol) {
-  verify_null(symbol);
-  symbol_c *left_type  = il_default_variable_type;
-  symbol_c *right_type = il_operand_type;
-
-/* The following is not required, it is already handled by compute_expression() ... */
-/*
-  if      (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &time_type_name;
-*/
-
-  if      (is_type(left_type, tod_type_name_c)      && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, tod_type_name_c)      && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &safetod_type_name;
-
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &safedt_type_name;
-
-  else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible,
-                                                     symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(SUB_operator_c)
-void *visit_expression_type_c::visit(SUB_operator_c *symbol) {
-  verify_null(symbol);
-  symbol_c *left_type = il_default_variable_type;
-  symbol_c *right_type = il_operand_type;;
-
-/* The following is not required, it is already handled by compute_expression() ... */
-/*
-  if      (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c))
-    il_default_variable_type = &time_type_name;
-*/
-
-  if      (is_type(left_type, tod_type_name_c)       && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, safetod_type_name_c)   && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, tod_type_name_c)       && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (is_type(left_type, safetod_type_name_c)   && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &safetod_type_name;
-
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, time_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, safetime_type_name_c))
-    il_default_variable_type = &safedt_type_name;
-
-  else if (is_type(left_type, date_type_name_c)     && is_type(right_type, date_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, date_type_name_c)     && is_type(right_type, safedate_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c))
-    il_default_variable_type = &safetime_type_name;
-
-  else if (is_type(left_type, tod_type_name_c)      && is_type(right_type, tod_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, tod_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, tod_type_name_c)      && is_type(right_type, safetod_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, safetod_type_name_c))
-    il_default_variable_type = &safetime_type_name;
-
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, dt_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, dt_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, dt_type_name_c)       && is_type(right_type, safedt_type_name_c))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, safedt_type_name_c))
-    il_default_variable_type = &safetime_type_name;
-
-  else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible,
-                                                     symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(MUL_operator_c)
-void *visit_expression_type_c::visit(MUL_operator_c *symbol) {
-  verify_null(symbol);
-  symbol_c *left_type = il_default_variable_type;
-  symbol_c *right_type = il_operand_type;
-
-  if      (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
-    il_default_variable_type = &safetime_type_name;
-  /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
-   * this next line is really only to check for integers/reals of undefined type on 'right_type'... 
-   */
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
-    il_default_variable_type = &safetime_type_name;
-
-  else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible,
-                                                     symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(DIV_operator_c)
-void *visit_expression_type_c::visit(DIV_operator_c *symbol) {
-  verify_null(symbol);
-  symbol_c *left_type = il_default_variable_type;
-  symbol_c *right_type = il_operand_type;
-
-  if      (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
-    il_default_variable_type = &time_type_name;
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
-    il_default_variable_type = &safetime_type_name;
-  /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
-   * this next line is really only to check for integers/reals of undefined type on 'right_type'... 
-   */
-  else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
-    il_default_variable_type = &safetime_type_name;
-
-  else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible,
-                                                     symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(MOD_operator_c)
-void *visit_expression_type_c::visit(MOD_operator_c *symbol) {
-  verify_null(symbol);
-  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_compatible,
-                                                symbol                  , il_operand);
-  return NULL;
-}
-
-// SYM_REF0(GT_operator_c)
-void *visit_expression_type_c::visit(GT_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-//SYM_REF0(GE_operator_c)
-void *visit_expression_type_c::visit(GE_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-//SYM_REF0(EQ_operator_c)
-void *visit_expression_type_c::visit(EQ_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-//SYM_REF0(LT_operator_c)
-void *visit_expression_type_c::visit(LT_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-//SYM_REF0(LE_operator_c)
-void *visit_expression_type_c::visit(LE_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-//SYM_REF0(NE_operator_c)
-void *visit_expression_type_c::visit(NE_operator_c *symbol) {
-  verify_null(symbol);
-  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
-                     symbol                  , il_operand);
-  il_default_variable_type = &search_expression_type_c::bool_type_name;
-  return NULL;
-}
-
-// SYM_REF0(CAL_operator_c)
-void *visit_expression_type_c::visit(CAL_operator_c *symbol) {
-  return NULL;
-}
-
-// SYM_REF0(CALC_operator_c)
-void *visit_expression_type_c::visit(CALC_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "CALC: il default variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "CALC operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-// SYM_REF0(CALCN_operator_c)
-void *visit_expression_type_c::visit(CALCN_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "CALCN: il_default_variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "CALCN operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-// SYM_REF0(RET_operator_c)
-void *visit_expression_type_c::visit(RET_operator_c *symbol) {
-  return NULL;
-}
-
-// SYM_REF0(RETC_operator_c)
-void *visit_expression_type_c::visit(RETC_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "RETC: il default variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "RETC operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-// SYM_REF0(RETCN_operator_c)
-void *visit_expression_type_c::visit(RETCN_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "RETCN: il_default_variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "RETCN operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-// SYM_REF0(JMP_operator_c)
-void *visit_expression_type_c::visit(JMP_operator_c *symbol){
-  return NULL;
-}
-
-// SYM_REF0(JMPC_operator_c)
-void *visit_expression_type_c::visit(JMPC_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "JMPC: il default variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "JMPC operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-// SYM_REF0(JMPCN_operator_c)
-void *visit_expression_type_c::visit(JMPCN_operator_c *symbol) {
-  if(il_default_variable_type == NULL)
-    STAGE3_ERROR(symbol, symbol, "JMPCN: il_default_variable should not be NULL.");
-  if (!is_BOOL_type(il_default_variable_type))
-    STAGE3_ERROR(symbol, symbol, "JMPCN operator requires il_default_variable to be of type BOOL.");
-  return NULL;
-}
-
-/* Symbol class handled together with function call checks */
-/*  any_identifier ASSIGN */
-// SYM_REF1(il_assign_operator_c, variable_name)
-// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, variable_name);
-
-/* Symbol class handled together with function call checks */
-/*| [NOT] any_identifier SENDTO */
-// SYM_REF2(il_assign_out_operator_c, option, variable_name)
-// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, option, variable_name);
-
-
-
-
-
-/***************************************/
-/* B.3 - Language ST (Structured Text) */
-/***************************************/
-/***********************/
-/* B 3.1 - Expressions */
-/***********************/
-
-void *visit_expression_type_c::visit(or_expression_c *symbol) {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(xor_expression_c *symbol) {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(and_expression_c *symbol) {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(equ_expression_c *symbol) {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(notequ_expression_c *symbol)  {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(lt_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(gt_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(le_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(ge_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
-  return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(add_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-/* The following is already checked in compute_expression */
-/*
-  if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c)) 
-    return (void *)&time_type_name;
-*/
-
-  if (is_type(left_type, tod_type_name_c)      && is_type(right_type, time_type_name_c)) 
-    return (void *)&tod_type_name;
-  if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, time_type_name_c)) 
-    return (void *)&tod_type_name;
-  if (is_type(left_type, tod_type_name_c)      && is_type(right_type, safetime_type_name_c)) 
-    return (void *)&tod_type_name;
-  if (is_type(left_type, safetod_type_name_c)  && is_type(right_type, safetime_type_name_c)) 
-    return (void *)&safetod_type_name;
-
-  if (is_type(left_type, dt_type_name_c)       && is_type(right_type, time_type_name_c)) 
-    return (void *)&dt_type_name;
-  if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, time_type_name_c)) 
-    return (void *)&dt_type_name;
-  if (is_type(left_type, dt_type_name_c)       && is_type(right_type, safetime_type_name_c)) 
-    return (void *)&dt_type_name;
-  if (is_type(left_type, safedt_type_name_c)   && is_type(right_type, safetime_type_name_c)) 
-    return (void *)&safedt_type_name;
-
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(sub_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-/* The following is already checked in compute_expression */
-/*
-  if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c))
-    return (void *)&time_type_name;
-*/
-
-  if (is_type(left_type, tod_type_name_c)     && is_type(right_type, time_type_name_c))
-    return (void *)&tod_type_name;
-  if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c))
-    return (void *)&tod_type_name;
-  if (is_type(left_type, tod_type_name_c)     && is_type(right_type, safetime_type_name_c))
-    return (void *)&tod_type_name;
-  if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c))
-    return (void *)&safetod_type_name;
-
-  if (is_type(left_type, dt_type_name_c)     && is_type(right_type, time_type_name_c))
-    return (void *)&dt_type_name;
-  if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c))
-    return (void *)&dt_type_name;
-  if (is_type(left_type, dt_type_name_c)     && is_type(right_type, safetime_type_name_c))
-    return (void *)&dt_type_name;
-  if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c))
-    return (void *)&safedt_type_name;
-
-  if (is_type(left_type, tod_type_name_c)     && is_type(right_type, tod_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetod_type_name_c) && is_type(right_type, tod_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, tod_type_name_c)     && is_type(right_type, safetod_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetod_type_name_c))
-    return (void *)&safetime_type_name;
-
-  if (is_type(left_type, date_type_name_c)     && is_type(right_type, date_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, date_type_name_c)     && is_type(right_type, safedate_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c))
-    return (void *)&safetime_type_name;
-
-  if (is_type(left_type, dt_type_name_c)     && is_type(right_type, dt_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safedt_type_name_c) && is_type(right_type, dt_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, dt_type_name_c)     && is_type(right_type, safedt_type_name_c))
-    return (void *)&time_type_name;
-  if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safedt_type_name_c))
-    return (void *)&safetime_type_name;
-
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(mul_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-  if (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type)) 
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) 
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) 
-    return (void *)&safetime_type_name;
-  /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
-   * this next line is really only to check for integers/reals of undefined type on 'right_type'... 
-   */
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) 
-    return (void *)&safetime_type_name;
-
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(div_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-  if (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type)) 
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type)) 
-    return (void *)&time_type_name;
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type)) 
-    return (void *)&safetime_type_name;
-  /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
-   * this next line is really only to check for integers/reals of undefined type on 'right_type'... 
-   */
-  if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type)) 
-    return (void *)&safetime_type_name;
-
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(mod_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(power_expression_c *symbol) {
-  symbol_c *left_type  = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-  if (!is_ANY_REAL_compatible(left_type))
-    STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "first operand of ** operator has invalid data type, should be of type ANY_REAL.");
-  if (!is_ANY_NUM_compatible(right_type))
-    STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "second operand of ** operator has invalid data type, should be of type ANY_NUM.");
-
-  return (void *)left_type;
-}
-
-
-void *visit_expression_type_c::visit(neg_expression_c *symbol) {
-  symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this));
-  if (!is_ANY_MAGNITUDE_compatible(exp_type))
-    STAGE3_ERROR(symbol, symbol, "operand of negate expression '-' has invalid data type, should be of type ANY_MAGNITUDE.");
-
-  return exp_type;
-}
-
-
-void *visit_expression_type_c::visit(not_expression_c *symbol) {
-  symbol_c *type = base_type((symbol_c *)symbol->exp->accept(*this));
-  return compute_expression(type, type, &visit_expression_type_c::is_ANY_BIT_compatible, NULL, symbol->exp);
-}
-
-
-void *visit_expression_type_c::visit(function_invocation_c *symbol) {
-  function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
-  function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
-  if (lower == function_symtable.end()) ERROR;
-
-  function_symtable_t::iterator second = lower;
-  second++;
-  if (second == upper) {
-    /* call to a function that is not overloaded. */	  
-    /* now check the semantics of the function call... */
-    /* If the syntax parser is working correctly, exactly one of the 
-     * following two symbols will be NULL, while the other is != NULL.
-     */
-    function_declaration_c *f_decl = function_symtable.get_value(lower);
-    if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl);
-    if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl);
-    /* Store the pointer to the declaration of the function being called.
-     * This data will be used by stage 4 to call the correct function.
-     * Mostly needed to disambiguate overloaded functions...
-     * See comments in absyntax.def for more details
-     */
-    symbol->called_function_declaration = f_decl;
-    return base_type(f_decl->type_name);
-  }  
-
-  /* This is a call to an overloaded function... */
-  if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!!\n");
-  for(; lower != upper; lower++) {
-    if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!! iterating...\n");
-    int error_count = 0; 
-    function_declaration_c *f_decl = function_symtable.get_value(lower);
-    if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, f_decl, &error_count);
-    if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count);
-    if (0 == error_count) {
-      /* Store the pointer to the declaration of the function being called.
-       * This data will be used by stage 4 to call the correct function.
-       * Mostly needed to disambiguate overloaded functions...
-       * See comments in absyntax.def for more details
-       */
-      symbol->called_function_declaration = f_decl;
-      return base_type(f_decl->type_name);
-    }
-  }
-
-  /* No compatible function was found for this function call */
-  STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
-  return NULL;
-}
-
-/********************/
-/* B 3.2 Statements */
-/********************/
-// SYM_LIST(statement_list_c)
-/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
- * We do not need to do anything here...
- */
-// void *visit_expression_type_c::visit(statement_list_c *symbol)
-
-
-/*********************************/
-/* B 3.2.1 Assignment Statements */
-/*********************************/
-
-void *visit_expression_type_c::visit(assignment_statement_c *symbol) {
-  symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
-  symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-  if (debug) {
-    printf("visit_expression_type_c::visit(assignment_statement_c) called. Checking --->");  
-    symbolic_variable_c *hi = dynamic_cast<symbolic_variable_c *>(symbol->l_exp);  
-    if (hi != NULL) {
-      identifier_c *hi1 = dynamic_cast<identifier_c *>(hi->var_name);  
-      if (hi1 != NULL) printf("%s", hi1->value);
-    }
-    printf(" := ");
-    hex_integer_c *hi2 = dynamic_cast<hex_integer_c *>(symbol->r_exp);  
-    if (hi2 != NULL) printf("%s", hi2->value);
-    printf("\n");
-  } // if (debug)
-
-  if        (NULL == left_type) {
-    STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n");
-  } else if (NULL == right_type) {
-    STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n");
-  } else if (!is_valid_assignment(left_type, right_type))
-    STAGE3_ERROR(symbol, symbol, "data type mismatch in assignment statement!\n");
-
-  return NULL;
-}
-
-
-
-/*****************************************/
-/* B 3.2.2 Subprogram Control Statements */
-/*****************************************/
-
-/*  RETURN */
-// SYM_REF0(return_statement_c)
-
-
-/* fb_name '(' [param_assignment_list] ')' */
-/* param_assignment_list -> may be NULL ! */
-// SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list)
-void *visit_expression_type_c::visit(fb_invocation_c *symbol) {
-  symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
-    /* The following should never occur. The function block must be defined, 
-     * and the FB type being called MUST be in the symtable... 
-     * This was all already checked at stage 2!
-     */
-  if (NULL == fb_decl) ERROR;
-
-  /* now check the semantics of the fb call... */
-  /* If the syntax parser is working correctly, exactly one of the 
-   * following two symbols will be NULL, while the other is != NULL.
-   */
-  if (symbol->   formal_param_list != NULL) check_formal_call   (symbol, fb_decl);
-  if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, fb_decl);
-
-  return NULL;
-}
-
-
-#if 0
-/* helper symbol for fb_invocation */
-/* param_assignment_list ',' param_assignment */
-SYM_LIST(param_assignment_list_c)
-
-/*  variable_name ASSIGN expression */
-SYM_REF2(input_variable_param_assignment_c, variable_name, expression)
-
-/* [NOT] variable_name '=>' variable */
-SYM_REF3(output_variable_param_assignment_c, not_param, variable_name, variable)
-
-/* helper CLASS for output_variable_param_assignment */
-SYM_REF0(not_paramassign_c)
-#