Huge change.
authorMario de Sousa <msousa@fe.up.pt>
Wed, 30 Mar 2011 19:53:32 +0100
changeset 257 90782e241346
parent 204 8ffa211b7f9a
child 258 d7d92b2f87e9
Huge change.
.hgignore
.settings/org.eclipse.cdt.core.prefs
Makefile.CYGWIN_NT-5.1
Makefile.CYGWIN_NT-6.0
Makefile.Linux
Makefile.MINGW32_NT-5.1
absyntax/absyntax.def
absyntax_utils/absyntax_utils.cc
absyntax_utils/absyntax_utils.hh
absyntax_utils/add_en_eno_param_decl.cc
absyntax_utils/add_en_eno_param_decl.hh
absyntax_utils/decompose_var_instance_name.hh
absyntax_utils/function_call_iterator.hh
absyntax_utils/function_call_param_iterator.hh
absyntax_utils/function_param_iterator.hh
absyntax_utils/function_type_decl.h
absyntax_utils/get_function_type.cc
absyntax_utils/get_function_type.h
absyntax_utils/get_function_type_decl.c
absyntax_utils/get_sizeof_datatype.cc
absyntax_utils/get_sizeof_datatype.hh
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_expression_type.cc
absyntax_utils/search_expression_type.hh
absyntax_utils/search_fb_instance_decl.hh
absyntax_utils/search_fb_typedecl.cc
absyntax_utils/search_fb_typedecl.hh
absyntax_utils/search_il_operand_type.cc
absyntax_utils/search_il_operand_type.hh
absyntax_utils/search_type_code.c
absyntax_utils/search_var_instance_decl.hh
absyntax_utils/search_varfb_instance_type.hh
absyntax_utils/spec_init_separator.hh
absyntax_utils/type_initial_value.cc
absyntax_utils/type_initial_value.hh
debian/README.Debian
debian/changelog
debian/compat
debian/control
debian/copyright
debian/dirs
debian/docs
debian/postinst
debian/postrm
lib/counter.txt
lib/iec_std_lib.h
lib/iec_std_lib_generated.h
lib/iec_types.h
lib/iec_types_all.h
lib/test_iec_std_lib.c
stage1_2/.cvsignore
stage1_2/Makefile
stage1_2/iec.flex
stage1_2/iec.y
stage1_2/stage1_2.cc
stage1_2/stage1_2.hh
stage1_2/stage1_2_priv.hh
stage1_2/standard_function_names.c
stage3/Makefile
stage3/stage3.cc
stage3/stage3.hh
stage3/visit_expression_type.cc
stage3/visit_expression_type.hh
stage4/generate_c/.cvsignore
stage4/generate_c/generate_c.cc
stage4/generate_c/generate_c_base.cc
stage4/generate_c/generate_c_sfc.cc
stage4/generate_c/generate_c_sfcdecl.cc
stage4/generate_c/generate_c_st.cc
stage4/generate_c/generate_location_list.cc
stage4/generate_c/generate_var_list.cc
stage4/generate_c/il_code_gen.c
stage4/generate_c/st_code_gen.c
stage4/generate_cc/.cvsignore
stage4/generate_iec/.cvsignore
stage4/generate_iec/generate_iec.cc
tests/.cvsignore
tests/LD_TEST.xml
tests/SFC_TEST.xml
tests/STD_TEST.xml
tests/main.c
tests/plc.c
tests/syntax/configuration/configuration.txt
tests/syntax/enumeration/enumerationvalue.txt
tests/syntax/identifier/Makefile
tests/syntax/identifier/basic_code.test
tests/syntax/identifier/identifier.txt
tests/syntax/identifier/identifier_as_configuration.test
tests/syntax/identifier/identifier_as_datatype.test
tests/syntax/identifier/identifier_as_enumerationvalue.test
tests/syntax/identifier/identifier_as_function1.test
tests/syntax/identifier/identifier_as_function2.test
tests/syntax/identifier/identifier_as_functionblock.test
tests/syntax/identifier/identifier_as_label.test
tests/syntax/identifier/identifier_as_program.test
tests/syntax/identifier/identifier_as_variable1.test
tests/syntax/identifier/identifier_as_variable2.test
tests/syntax/identifier/identifier_in_sfc.test
tests/syntax/sfc/sfc.txt
--- a/absyntax/absyntax.def	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax/absyntax.def	Wed Mar 30 19:53:32 2011 +0100
@@ -46,7 +46,7 @@
 /*****************************************************************/
 /*****************************************************************/
 /*                                                               */
-/*             Symbols defined in:                               */
+/*      safe<xxxxxx> Symbols are defined in:                     */
 /*      PLCopen - Technical Committee 5                          */
 /*      Safety Software Technical Specification,                 */
 /*      Part 1: Concepts and Function Blocks,                    */
@@ -60,10 +60,6 @@
 
 
 
-SYM_REF0(safebool_type_name_c)
-
-
-
 
 
 /*****************************************************************/
@@ -129,14 +125,59 @@
 /* Note:
  * We do not have signed_integer_c and signed_real_c classes.
  * These are stored in the parse tree as a integer_c or real_c
- * preceded by a unary minus operator.
+ * preceded by a unary minus operator if they are inside an expression,
+ * or a neg_integer_c and neg_real_c when used outside an ST expression.
  */
 /* Not required:
 SYM_TOKEN(signed_integer_c)
 SYM_TOKEN(signed_real_c)
 */
 
-SYM_REF1(neg_literal_c, exp)
+/* NOTE: literal __values__ are stored directly in classes such as:
+ *          - real_c
+ *          - integer_c
+ *          - binary_integer_c
+ *          - etc...
+ *
+ *       However, for both the real_c and the integer_c, if they are preceded 
+ *       by a '-' negation sign, they are further encapsulated inside 
+ *       a neg_literal_c (i.e. the neg_literal_c will point to the 
+ *       real_c or integer_c with the value being negated.
+ *          neg_literal_c -> integer_literal_c
+ *                OR
+ *          neg_literal_c -> real_literal_c
+ *
+ *      In the semantic verification and code generation stages of the compiler,
+ *      the integer_c is treated as a basic (undefined) data type, since an integer
+ *      constant may be used as a BYTE, BOOLEAN, REAL, etc..., depending on the
+ *      context in which it is used.
+ *      However, an integer_c that is preceded by a '-' may not be used
+ *      as an ANY_BIT data type (BYTE, BOOLEAN, WORD, ...).
+ *      We must therefore be able to determine, holding a simple pointer
+ *      to an integer_c, if that integer_c value is preceded by a '-'.
+ *      However, since the neg_literal_c points to the integer_c, and not
+ *      vice-versa, we can't determine that.
+ *      There are 3 simple ways of working around this:
+ *        - change the order of the pointers: 
+ *              have the integer_c and real_c point to the neg_literal_c
+ *        - maintain the order of the pointers, and
+ *              add redundant info to the integer_c and real_c
+ *        - replace the neg_literal_c with two distinc classes
+ *              (neg_integer_c and neg_real_c), one for each
+ *              lietral type. This means that we can now treat
+ *              each of these classes as an unknown data type
+ *              just as we do with the integer_c and real_c.
+ *
+ *      The second option is simply ugly.
+ *      and the first has a serious drawback: when generating code it is
+ *      easier to encapsulate the real or integer values inside prefix
+ *      and postfix symbols (e.g. NEG(<value>) - with postfix ')' )
+ *      if we keep the pointer order as is.
+ *
+ *      For the above reasoning, we use the third option.
+ */  
+SYM_REF1(neg_real_c, exp)
+SYM_REF1(neg_integer_c, exp)
 
 /* Not required:
 SYM_REF2(numeric_literal_c, type, value)
@@ -144,6 +185,8 @@
 SYM_REF2(integer_literal_c, type, value)
 SYM_REF2(real_literal_c, type, value)
 SYM_REF2(bit_string_literal_c, type, value)
+/* A typed or untyped boolean literal... */
+/* type may be NULL */
 SYM_REF2(boolean_literal_c, type, value)
 
 /* helper class for boolean_literal_c */
@@ -168,7 +211,7 @@
 /* B 1.2.3.1 - Duration */
 /************************/
 SYM_REF0(neg_time_c)
-SYM_REF2(duration_c, neg, interval)
+SYM_REF3(duration_c, type_name, neg, interval)
 SYM_TOKEN(fixed_point_c)
 SYM_REF2(days_c, days, hours)
 SYM_REF2(hours_c, hours, minutes)
@@ -180,11 +223,11 @@
 /************************************/
 /* B 1.2.3.2 - Time of day and Date */
 /************************************/
-SYM_REF1(time_of_day_c, daytime)
+SYM_REF2(time_of_day_c, type_name, daytime)
 SYM_REF3(daytime_c, day_hour, day_minute, day_second)
-SYM_REF1(date_c, date_literal)
+SYM_REF2(date_c, type_name, date_literal)
 SYM_REF3(date_literal_c, year, month, day)
-SYM_REF2(date_and_time_c, date_literal, daytime)
+SYM_REF3(date_and_time_c, type_name, date_literal, daytime)
 
 
 /**********************/
@@ -215,10 +258,31 @@
 SYM_REF0(string_type_name_c)
 SYM_REF0(wstring_type_name_c)
 
-/*
-SYM_REF0(constant_int_type_name_c)
-SYM_REF0(constant_real_type_name_c)
-*/
+  /*****************************************************************/
+  /* Keywords defined in "Safety Software Technical Specification" */
+  /*****************************************************************/
+
+SYM_REF0(safetime_type_name_c)
+SYM_REF0(safebool_type_name_c)
+SYM_REF0(safesint_type_name_c)
+SYM_REF0(safeint_type_name_c)
+SYM_REF0(safedint_type_name_c)
+SYM_REF0(safelint_type_name_c)
+SYM_REF0(safeusint_type_name_c)
+SYM_REF0(safeuint_type_name_c)
+SYM_REF0(safeudint_type_name_c)
+SYM_REF0(safeulint_type_name_c)
+SYM_REF0(safereal_type_name_c)
+SYM_REF0(safelreal_type_name_c)
+SYM_REF0(safedate_type_name_c)
+SYM_REF0(safetod_type_name_c)
+SYM_REF0(safedt_type_name_c)
+SYM_REF0(safebyte_type_name_c)
+SYM_REF0(safeword_type_name_c)
+SYM_REF0(safedword_type_name_c)
+SYM_REF0(safelword_type_name_c)
+SYM_REF0(safestring_type_name_c)
+SYM_REF0(safewstring_type_name_c)
 
 
 /********************************/
--- a/absyntax_utils/get_sizeof_datatype.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/get_sizeof_datatype.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -147,14 +147,19 @@
   * If 'x' were a SINT, then the '30' would have to be a SINT too!
   */
 
-/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+/* 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.
  */
 void *get_sizeof_datatype_c::visit(real_c *symbol) {
   return _encode_int(32);
 }
 
-/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
+void *get_sizeof_datatype_c::visit(neg_real_c *symbol) {
+  return symbol->exp->accept(*this);
+}
+
+
+/* NOTE: all integer_c and real_c literal tokens will always be positive (i.e. no leading '-')
  * due to the way the source code is parsed by iec.flex.
  */
 void *get_sizeof_datatype_c::visit(integer_c *symbol) {
@@ -224,8 +229,13 @@
 }
 
 
-/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
- * due to the way the source code is parsed by iec.flex.
+void *get_sizeof_datatype_c::visit(neg_integer_c *symbol) {
+  return symbol->exp->accept(*this);
+}
+
+
+/* NOTE: all binary_integer_c tokens will always be positive (i.e. no leading '-')
+ * due to the syntax definition of IEC 61131-3.
  */
 void *get_sizeof_datatype_c::visit(binary_integer_c *symbol) {
   const char *sval = symbol->value;
@@ -255,8 +265,8 @@
 }
 
 
-/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
- * due to the way the source code is parsed by iec.flex.
+/* NOTE: all octal_integer_c tokens will always be positive (i.e. no leading '-')
+ * due to the syntax definition of IEC 61131-3.
  */
 void *get_sizeof_datatype_c::visit(octal_integer_c *symbol) {
   const char *sval = symbol->value;
@@ -287,8 +297,8 @@
 }
 
 
-/* NOTE: all integer and real literal tokens will always be positive (i.e. no leading '-')
- * due to the way the source code is parsed by iec.flex.
+/* NOTE: all hex_integer_c tokens will always be positive (i.e. no leading '-')
+ * due to the syntax definition of IEC 61131-3.
  */
 void *get_sizeof_datatype_c::visit(hex_integer_c *symbol) {
   const char *sval = symbol->value;
@@ -327,27 +337,27 @@
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
-// void *get_sizeof_datatype_c::visit(time_type_name_c *symbol)	{return _encode_int(0); }
-void *get_sizeof_datatype_c::visit(bool_type_name_c *symbol)	{return _encode_int(1); }
-void *get_sizeof_datatype_c::visit(sint_type_name_c *symbol)	{return _encode_int(8); }
-void *get_sizeof_datatype_c::visit(int_type_name_c *symbol)	{return _encode_int(16);}
-void *get_sizeof_datatype_c::visit(dint_type_name_c *symbol)	{return _encode_int(32);}
-void *get_sizeof_datatype_c::visit(lint_type_name_c *symbol)	{return _encode_int(64);}
-void *get_sizeof_datatype_c::visit(usint_type_name_c *symbol)	{return _encode_int(8); }
-void *get_sizeof_datatype_c::visit(uint_type_name_c *symbol)	{return _encode_int(16);}
-void *get_sizeof_datatype_c::visit(udint_type_name_c *symbol)	{return _encode_int(32);}
-void *get_sizeof_datatype_c::visit(ulint_type_name_c *symbol)	{return _encode_int(64);}
-void *get_sizeof_datatype_c::visit(real_type_name_c *symbol)	{return _encode_int(32);}
-void *get_sizeof_datatype_c::visit(lreal_type_name_c *symbol)	{return _encode_int(64);}
-// void *get_sizeof_datatype_c::visit(date_type_name_c *symbol)	{return _encode_int(0); }
-// void *get_sizeof_datatype_c::visit(tod_type_name_c *symbol)	{return _encode_int(0); }
-// void *get_sizeof_datatype_c::visit(dt_type_name_c *symbol)	{return _encode_int(0); }
-void *get_sizeof_datatype_c::visit(byte_type_name_c *symbol)	{return _encode_int(8); }
-void *get_sizeof_datatype_c::visit(word_type_name_c *symbol)	{return _encode_int(16);}
-void *get_sizeof_datatype_c::visit(dword_type_name_c *symbol)	{return _encode_int(32);}
-void *get_sizeof_datatype_c::visit(lword_type_name_c *symbol)	{return _encode_int(64);}
-// void *get_sizeof_datatype_c::visit(string_type_name_c *symbol)	{return _encode_int(0); }
-// void *get_sizeof_datatype_c::visit(wstring_type_name_c *symbol)	{return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(time_type_name_c *symbol) {return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(bool_type_name_c *symbol)    {return _encode_int(1); }
+void *get_sizeof_datatype_c::visit(sint_type_name_c *symbol)    {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(int_type_name_c *symbol)     {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(dint_type_name_c *symbol)    {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lint_type_name_c *symbol)    {return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(usint_type_name_c *symbol)   {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(uint_type_name_c *symbol)    {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(udint_type_name_c *symbol)   {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(ulint_type_name_c *symbol)   {return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(real_type_name_c *symbol)    {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lreal_type_name_c *symbol)   {return _encode_int(64);}
+// void *get_sizeof_datatype_c::visit(date_type_name_c *symbol) {return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(tod_type_name_c *symbol)  {return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(dt_type_name_c *symbol)   {return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(byte_type_name_c *symbol)    {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(word_type_name_c *symbol)    {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(dword_type_name_c *symbol)   {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(lword_type_name_c *symbol)   {return _encode_int(64);}
+// void *get_sizeof_datatype_c::visit(string_type_name_c *symbol)    {return _encode_int(0); }
+// void *get_sizeof_datatype_c::visit(wstring_type_name_c *symbol)   {return _encode_int(0); }
 /******************************************************/
 /* Extensions to the base standard as defined in      */
 /* "Safety Software Technical Specification,          */
@@ -355,7 +365,28 @@
 /*  Version 1.0 – Official Release"                   */
 /* by PLCopen - Technical Committee 5 - 2006-01-31    */
 /******************************************************/
-void *get_sizeof_datatype_c::visit(safebool_type_name_c *symbol)	{return _encode_int(1);}
+//     void *get_sizeof_datatype_c::visit(safetime_type_name_c *symbol); {return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(safebool_type_name_c *symbol)         {return _encode_int(1); }
+void *get_sizeof_datatype_c::visit(safesint_type_name_c *symbol)         {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(safeint_type_name_c *symbol)          {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(safedint_type_name_c *symbol)         {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(safelint_type_name_c *symbol)         {return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(safeusint_type_name_c *symbol)        {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(safeuint_type_name_c *symbol)         {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(safeudint_type_name_c *symbol)        {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(safeulint_type_name_c *symbol)        {return _encode_int(64);}
+void *get_sizeof_datatype_c::visit(safereal_type_name_c *symbol)         {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(safelreal_type_name_c *symbol)        {return _encode_int(64);}
+//     void *get_sizeof_datatype_c::visit(safedate_type_name_c *symbol); {return _encode_int(0); }
+//     void *get_sizeof_datatype_c::visit(safetod_type_name_c *symbol);  {return _encode_int(0); }
+//     void *get_sizeof_datatype_c::visit(safedt_type_name_c *symbol);   {return _encode_int(0); }
+void *get_sizeof_datatype_c::visit(safebyte_type_name_c *symbol)         {return _encode_int(8); }
+void *get_sizeof_datatype_c::visit(safeword_type_name_c *symbol)         {return _encode_int(16);}
+void *get_sizeof_datatype_c::visit(safedword_type_name_c *symbol)        {return _encode_int(32);}
+void *get_sizeof_datatype_c::visit(safelword_type_name_c *symbol)        {return _encode_int(64);}
+//     void *get_sizeof_datatype_c::visit(safestring_type_name_c *symbol);  {return _encode_int(0); }
+//     void *get_sizeof_datatype_c::visit(safewstring_type_name_c *symbol); {return _encode_int(0); }
+
 
 /********************************/
 /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/get_sizeof_datatype.hh	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/get_sizeof_datatype.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -91,7 +91,9 @@
       * If 'x' were a SINT, then the '30' would have to be a SINT too!
       */
     void *visit(real_c *symbol);
+    void *visit(neg_real_c *symbol);
     void *visit(integer_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);
@@ -128,7 +130,27 @@
     /*  Version 1.0 – Official Release"                   */
     /* by PLCopen - Technical Committee 5 - 2006-01-31    */
     /******************************************************/
+//     void *visit(safetime_type_name_c *symbol);
     void *visit(safebool_type_name_c *symbol);
+    void *visit(safesint_type_name_c *symbol);
+    void *visit(safeint_type_name_c *symbol);
+    void *visit(safedint_type_name_c *symbol);
+    void *visit(safelint_type_name_c *symbol);
+    void *visit(safeusint_type_name_c *symbol);
+    void *visit(safeuint_type_name_c *symbol);
+    void *visit(safeudint_type_name_c *symbol);
+    void *visit(safeulint_type_name_c *symbol);
+    void *visit(safereal_type_name_c *symbol);
+    void *visit(safelreal_type_name_c *symbol);
+//     void *visit(safedate_type_name_c *symbol);
+//     void *visit(safetod_type_name_c *symbol);
+//     void *visit(safedt_type_name_c *symbol)	;
+    void *visit(safebyte_type_name_c *symbol);
+    void *visit(safeword_type_name_c *symbol);
+    void *visit(safedword_type_name_c *symbol);
+    void *visit(safelword_type_name_c *symbol);
+//     void *visit(safestring_type_name_c *symbol);
+//     void *visit(safewstring_type_name_c *symbol);
 
   /********************************/
   /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/search_base_type.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/search_base_type.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -85,10 +85,14 @@
   * If 'x' were a SINT, then the '30' would have to be a SINT too!
   */
 void *search_base_type_c::visit(real_c *symbol)          	{return (void *)symbol;}
+void *search_base_type_c::visit(neg_real_c *symbol)          	{return (void *)symbol;}
 void *search_base_type_c::visit(integer_c *symbol)       	{return (void *)symbol;}
+void *search_base_type_c::visit(neg_integer_c *symbol)       	{return (void *)symbol;}
 void *search_base_type_c::visit(binary_integer_c *symbol)	{return (void *)symbol;}
 void *search_base_type_c::visit(octal_integer_c *symbol) 	{return (void *)symbol;}
 void *search_base_type_c::visit(hex_integer_c *symbol)   	{return (void *)symbol;}
+void *search_base_type_c::visit(boolean_true_c *symbol)   	{return (void *)symbol;}
+void *search_base_type_c::visit(boolean_false_c *symbol)   	{return (void *)symbol;}
 
 
 /***********************************/
@@ -115,10 +119,8 @@
 void *search_base_type_c::visit(lword_type_name_c *symbol)	{return (void *)symbol;}
 void *search_base_type_c::visit(string_type_name_c *symbol)	{return (void *)symbol;}
 void *search_base_type_c::visit(wstring_type_name_c *symbol)	{return (void *)symbol;}
-/*
-void *search_base_type_c::visit(constant_int_type_name_c *symbol)	{return (void *)symbol;}
-void *search_base_type_c::visit(constant_real_type_name_c *symbol)	{return (void *)symbol;}
-*/
+
+
 /******************************************************/
 /* Extensions to the base standard as defined in      */
 /* "Safety Software Technical Specification,          */
@@ -126,7 +128,28 @@
 /*  Version 1.0 – Official Release"                   */
 /* by PLCopen - Technical Committee 5 - 2006-01-31    */
 /******************************************************/
-void *search_base_type_c::visit(safebool_type_name_c *symbol)	{return (void *)symbol;}
+
+void *search_base_type_c::visit(safetime_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safebool_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safesint_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safeint_type_name_c *symbol)      {return (void *)symbol;}
+void *search_base_type_c::visit(safedint_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safelint_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safeusint_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safeuint_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safeudint_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safeulint_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safereal_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safelreal_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safedate_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safetod_type_name_c *symbol)      {return (void *)symbol;}
+void *search_base_type_c::visit(safedt_type_name_c *symbol)       {return (void *)symbol;}
+void *search_base_type_c::visit(safebyte_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safeword_type_name_c *symbol)     {return (void *)symbol;}
+void *search_base_type_c::visit(safedword_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safelword_type_name_c *symbol)    {return (void *)symbol;}
+void *search_base_type_c::visit(safestring_type_name_c *symbol)   {return (void *)symbol;}
+void *search_base_type_c::visit(safewstring_type_name_c *symbol)  {return (void *)symbol;}
 
 /********************************/
 /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/search_base_type.hh	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/search_base_type.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -71,10 +71,14 @@
       * If 'x' were a SINT, then the '30' would have to be a SINT too!
       */
     void *visit(real_c *symbol);
+    void *visit(neg_real_c *symbol);
     void *visit(integer_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(boolean_true_c *symbol);
+    void *visit(boolean_false_c *symbol);
 
 
   /***********************************/
@@ -102,11 +106,6 @@
     void *visit(string_type_name_c *symbol);
     void *visit(wstring_type_name_c *symbol);
 
-/*
-    void *visit(constant_int_type_name_c *symbol);
-    void *visit(constant_real_type_name_c *symbol);
-*/
-
     /******************************************************/
     /* Extensions to the base standard as defined in      */
     /* "Safety Software Technical Specification,          */
@@ -114,7 +113,27 @@
     /*  Version 1.0 – Official Release"                   */
     /* by PLCopen - Technical Committee 5 - 2006-01-31    */
     /******************************************************/
+    void *visit(safetime_type_name_c *symbol);
     void *visit(safebool_type_name_c *symbol);
+    void *visit(safesint_type_name_c *symbol);
+    void *visit(safeint_type_name_c *symbol);
+    void *visit(safedint_type_name_c *symbol);
+    void *visit(safelint_type_name_c *symbol);
+    void *visit(safeusint_type_name_c *symbol);
+    void *visit(safeuint_type_name_c *symbol);
+    void *visit(safeudint_type_name_c *symbol);
+    void *visit(safeulint_type_name_c *symbol);
+    void *visit(safereal_type_name_c *symbol);
+    void *visit(safelreal_type_name_c *symbol);
+    void *visit(safedate_type_name_c *symbol);
+    void *visit(safetod_type_name_c *symbol);
+    void *visit(safedt_type_name_c *symbol)	;
+    void *visit(safebyte_type_name_c *symbol);
+    void *visit(safeword_type_name_c *symbol);
+    void *visit(safedword_type_name_c *symbol);
+    void *visit(safelword_type_name_c *symbol);
+    void *visit(safestring_type_name_c *symbol);
+    void *visit(safewstring_type_name_c *symbol);
 
   /********************************/
   /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/search_constant_type.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/search_constant_type.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -59,7 +59,9 @@
   * If 'x' were a SINT, then the '30' would have to be a SINT too!
   */
 void *search_constant_type_c::visit(real_c *symbol)           {return (void *)symbol;}
+void *search_constant_type_c::visit(neg_real_c *symbol)       {return (void *)symbol;}
 void *search_constant_type_c::visit(integer_c *symbol)        {return (void *)symbol;}
+void *search_constant_type_c::visit(neg_integer_c *symbol)    {return (void *)symbol;}
 void *search_constant_type_c::visit(binary_integer_c *symbol) {return (void *)symbol;}
 void *search_constant_type_c::visit(octal_integer_c *symbol)  {return (void *)symbol;}
 void *search_constant_type_c::visit(hex_integer_c *symbol)    {return (void *)symbol;}
@@ -90,7 +92,7 @@
 /* B 1.2.3.1 - Duration */
 /************************/
 void *search_constant_type_c::visit(neg_time_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
-void *search_constant_type_c::visit(duration_c *symbol) {return (void *)&time_type_name;}
+void *search_constant_type_c::visit(duration_c *symbol) {return (void *)(symbol->type_name);}
 void *search_constant_type_c::visit(fixed_point_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
 void *search_constant_type_c::visit(days_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
 void *search_constant_type_c::visit(hours_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
@@ -101,11 +103,12 @@
 /************************************/
 /* B 1.2.3.2 - Time of day and Date */
 /************************************/
-void *search_constant_type_c::visit(time_of_day_c *symbol) {return (void *)&tod_type_name;}
+void *search_constant_type_c::visit(time_of_day_c *symbol) {return (void *)(symbol->type_name);}
 void *search_constant_type_c::visit(daytime_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
-void *search_constant_type_c::visit(date_c *symbol) {return (void *)&date_type_name;}
+void *search_constant_type_c::visit(date_c *symbol) {return (void *)(symbol->type_name);}
 void *search_constant_type_c::visit(date_literal_c *symbol) {ERROR; return NULL;}  /* this member function should never be called. */
-void *search_constant_type_c::visit(date_and_time_c *symbol) {return (void *)&dt_type_name;}
+void *search_constant_type_c::visit(date_and_time_c *symbol) {return (void *)(symbol->type_name);}
+
 
 real_type_name_c     search_constant_type_c::real_type_name;
 sint_type_name_c     search_constant_type_c::sint_type_name;
@@ -129,10 +132,16 @@
 time_type_name_c     search_constant_type_c::time_type_name;
 int_type_name_c      search_constant_type_c::int_type_name;
 
-/*
-constant_real_type_name_c     search_constant_type_c::constant_real_type_name;
-constant_int_type_name_c      search_constant_type_c::constant_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;
+
+
+
 /* 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	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/search_constant_type.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -67,10 +67,6 @@
   static time_type_name_c     time_type_name;
   static int_type_name_c      int_type_name;
 
-/*
-  static constant_real_type_name_c     constant_real_type_name;
-  static constant_int_type_name_c      constant_int_type_name;
-*/
 /* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
   static integer_c      integer;
 
@@ -81,7 +77,15 @@
   /*  Version 1.0 – Official Release"                   */
   /* by PLCopen - Technical Committee 5 - 2006-01-31    */
   /******************************************************/
-  static safebool_type_name_c          safebool_type_name;
+ 
+//  static safebool_type_name_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...
+   */
+  static safetime_type_name_c     safetime_type_name;
+  static safetod_type_name_c      safetod_type_name;
+  static safedt_type_name_c       safedt_type_name;
+
 
 
   public:
@@ -97,7 +101,9 @@
     /* B 1.2.1 - Numeric Literals */
     /******************************/
     void *visit(real_c *symbol);
+    void *visit(neg_real_c *symbol);
     void *visit(integer_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);
--- a/absyntax_utils/search_expression_type.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/search_expression_type.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -49,24 +49,34 @@
 bool search_expression_type_c::is_bool_type(symbol_c *type_symbol) {
   bool_type_name_c tt;
   if (type_symbol == NULL) {return true;}
-  return (typeid(*type_symbol) == typeid(bool_type_name_c));
+  if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(bool_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(boolean_true_c))       {return true;}
+  if (typeid(*type_symbol) == typeid(boolean_false_c))      {return true;}
+  return false;
 }
 
 /* A helper function... */
 bool search_expression_type_c::is_time_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
-  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;}
+  if (typeid(*type_symbol) == typeid(time_type_name_c))     {return true;}
+  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;}
+  if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
+  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 search_expression_type_c::is_string_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(string_type_name_c))  {return true;}
-  if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(string_type_name_c))      {return true;}
+  if (typeid(*type_symbol) == typeid(wstring_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(safestring_type_name_c))  {return true;}
+  if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;}
   return false;
 }
 
@@ -74,6 +84,7 @@
 bool search_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
   if (typeid(*type_symbol) == typeid(integer_c))        {return true;}
+  if (typeid(*type_symbol) == typeid(neg_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;}
@@ -83,29 +94,40 @@
 /* A helper function... */
 bool search_expression_type_c::is_integer_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  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;}
+  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;}
+  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 is_literal_integer_type(type_symbol);
 }
 
 /* A helper function... */
 bool search_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(real_c)) {return true;}
+  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 search_expression_type_c::is_real_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;}
-  if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
+  if (typeid(*type_symbol) == typeid(real_type_name_c))      {return true;}
+  if (typeid(*type_symbol) == typeid(lreal_type_name_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(safereal_type_name_c))  {return true;} 
+  if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;}  
   return is_literal_real_type(type_symbol);
 }
 
@@ -116,28 +138,34 @@
 
 bool search_expression_type_c::is_nbinary_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {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;}
+  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;}
+  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 is_literal_integer_type(type_symbol);
 }
 
 bool search_expression_type_c::is_binary_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;}
-  return is_nbinary_type(type_symbol);
+//   if (typeid(*type_symbol) == typeid(bool_type_name_c))     {return true;}
+//   if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
+  return (is_nbinary_type(type_symbol) || is_bool_type(type_symbol));
 }
 
 bool search_expression_type_c::is_same_type(symbol_c *first_type, symbol_c *second_type) {
   if (first_type == NULL || second_type == NULL) {return true;}
   if (typeid(*first_type) == typeid(*second_type)) {return true;}
-  if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return true;}
-  if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return true;}
-  if (is_binary_type(first_type) && is_literal_integer_type(second_type))  {return true;}
-  if (is_literal_integer_type(first_type) && is_binary_type(second_type))  {return true;}
-  if (is_real_type(first_type) && is_literal_real_type(second_type)) {return true;}
-  if (is_literal_real_type(first_type) && is_real_type(second_type)) {return true;}
+  if (is_bool_type(first_type)            && is_bool_type(second_type))            {return true;}
+  if (is_integer_type(first_type)         && is_literal_integer_type(second_type)) {return true;}
+  if (is_literal_integer_type(first_type) && is_integer_type(second_type))         {return true;}
+  if (is_binary_type(first_type)          && is_literal_integer_type(second_type)) {return true;}
+  if (is_literal_integer_type(first_type) && is_binary_type(second_type))          {return true;}
+  if (is_real_type(first_type)            && is_literal_real_type(second_type))    {return true;}
+  if (is_literal_real_type(first_type)    && is_real_type(second_type))            {return true;}
   return false;
 }
 
@@ -146,12 +174,12 @@
   if (first_type == NULL) {return second_type;}
   if (second_type == NULL) {return first_type;}
   if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
-  if (is_integer_type(first_type) && is_literal_integer_type(second_type)) {return first_type;}
-  if (is_literal_integer_type(first_type) && is_integer_type(second_type)) {return second_type;}
-  if (is_binary_type(first_type) && is_literal_integer_type(second_type))  {return first_type;}
-  if (is_literal_integer_type(first_type) && is_binary_type(second_type))  {return second_type;}
-  if (is_real_type(first_type) && is_literal_real_type(second_type)) {return first_type;}
-  if (is_literal_real_type(first_type) && is_real_type(second_type)) {return second_type;}
+  if (is_integer_type(first_type)         && is_literal_integer_type(second_type)) {return first_type;}
+  if (is_literal_integer_type(first_type) && is_integer_type(second_type))         {return second_type;}
+  if (is_binary_type(first_type)          && is_literal_integer_type(second_type)) {return first_type;}
+  if (is_literal_integer_type(first_type) && is_binary_type(second_type))          {return second_type;}
+  if (is_real_type(first_type)            && is_literal_real_type(second_type))    {return first_type;}
+  if (is_literal_real_type(first_type)    && is_real_type(second_type))            {return second_type;}
   return NULL;
 }
 
--- a/absyntax_utils/type_initial_value.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/type_initial_value.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -76,10 +76,10 @@
     date_literal_0 =  new date_literal_c(integer_1, integer_1, integer_1);
   date_literal_0 =  new date_literal_c(new integer_c("1970"), integer_1, integer_1);
   daytime_literal_0 = new daytime_c(integer_0, integer_0, real_0);
-  time_0 = new duration_c(NULL, new seconds_c(integer_0, NULL));  // T#0S
-  date_0 = new date_c(date_literal_0);  //  D#0001-01-01
-  tod_0 = new time_of_day_c(daytime_literal_0);  //  TOD#00:00:00
-  dt_0 = new date_and_time_c(date_literal_0, daytime_literal_0);  //  DT#0001-01-01-00:00:00
+  time_0 = new duration_c(new time_type_name_c(), NULL, new seconds_c(integer_0, NULL));  // T#0S
+  date_0 = new date_c(new date_type_name_c(), date_literal_0);  //  D#0001-01-01
+  tod_0 = new time_of_day_c(new tod_type_name_c(), daytime_literal_0);  //  TOD#00:00:00
+  dt_0 = new date_and_time_c(new dt_type_name_c(), date_literal_0, daytime_literal_0);  //  DT#0001-01-01-00:00:00
   string_0  = new single_byte_character_string_c("''");
   wstring_0 = new double_byte_character_string_c("\"\"");
 
@@ -128,27 +128,49 @@
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
-void *type_initial_value_c::visit(time_type_name_c *symbol)	{return (void *)time_0;}
-void *type_initial_value_c::visit(bool_type_name_c *symbol)	{return (void *)bool_0;}
-void *type_initial_value_c::visit(sint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(int_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(dint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(lint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(usint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(uint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(udint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(ulint_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(real_type_name_c *symbol)	{return (void *)real_0;}
-void *type_initial_value_c::visit(lreal_type_name_c *symbol)	{return (void *)real_0;}
-void *type_initial_value_c::visit(date_type_name_c *symbol)	{return (void *)date_0;}
-void *type_initial_value_c::visit(tod_type_name_c *symbol)	{return (void *)tod_0;}
-void *type_initial_value_c::visit(dt_type_name_c *symbol)		{return (void *)dt_0;}
-void *type_initial_value_c::visit(byte_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(word_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(dword_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(lword_type_name_c *symbol)	{return (void *)integer_0;}
-void *type_initial_value_c::visit(string_type_name_c *symbol)	{return (void *)string_0;}
-void *type_initial_value_c::visit(wstring_type_name_c *symbol)	{return (void *)wstring_0;}
+void *type_initial_value_c::visit(time_type_name_c *symbol)         {return (void *)time_0;}
+void *type_initial_value_c::visit(bool_type_name_c *symbol)         {return (void *)bool_0;}
+void *type_initial_value_c::visit(sint_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(int_type_name_c *symbol)          {return (void *)integer_0;}
+void *type_initial_value_c::visit(dint_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(lint_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(usint_type_name_c *symbol)        {return (void *)integer_0;}
+void *type_initial_value_c::visit(uint_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(udint_type_name_c *symbol)        {return (void *)integer_0;}
+void *type_initial_value_c::visit(ulint_type_name_c *symbol)        {return (void *)integer_0;}
+void *type_initial_value_c::visit(real_type_name_c *symbol)         {return (void *)real_0;}
+void *type_initial_value_c::visit(lreal_type_name_c *symbol)        {return (void *)real_0;}
+void *type_initial_value_c::visit(date_type_name_c *symbol)         {return (void *)date_0;}
+void *type_initial_value_c::visit(tod_type_name_c *symbol)          {return (void *)tod_0;}
+void *type_initial_value_c::visit(dt_type_name_c *symbol)           {return (void *)dt_0;}
+void *type_initial_value_c::visit(byte_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(word_type_name_c *symbol)         {return (void *)integer_0;}
+void *type_initial_value_c::visit(dword_type_name_c *symbol)        {return (void *)integer_0;}
+void *type_initial_value_c::visit(lword_type_name_c *symbol)        {return (void *)integer_0;}
+void *type_initial_value_c::visit(string_type_name_c *symbol)       {return (void *)string_0;}
+void *type_initial_value_c::visit(wstring_type_name_c *symbol)      {return (void *)wstring_0;}
+
+void *type_initial_value_c::visit(safetime_type_name_c *symbol)     {return (void *)time_0;}
+void *type_initial_value_c::visit(safebool_type_name_c *symbol)     {return (void *)bool_0;}
+void *type_initial_value_c::visit(safesint_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeint_type_name_c *symbol)      {return (void *)integer_0;}
+void *type_initial_value_c::visit(safedint_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safelint_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeusint_type_name_c *symbol)    {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeuint_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeudint_type_name_c *symbol)    {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeulint_type_name_c *symbol)    {return (void *)integer_0;}
+void *type_initial_value_c::visit(safereal_type_name_c *symbol)     {return (void *)real_0;}
+void *type_initial_value_c::visit(safelreal_type_name_c *symbol)    {return (void *)real_0;}
+void *type_initial_value_c::visit(safedate_type_name_c *symbol)     {return (void *)date_0;}
+void *type_initial_value_c::visit(safetod_type_name_c *symbol)      {return (void *)tod_0;}
+void *type_initial_value_c::visit(safedt_type_name_c *symbol)       {return (void *)dt_0;}
+void *type_initial_value_c::visit(safebyte_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safeword_type_name_c *symbol)     {return (void *)integer_0;}
+void *type_initial_value_c::visit(safedword_type_name_c *symbol)    {return (void *)integer_0;}
+void *type_initial_value_c::visit(safelword_type_name_c *symbol)    {return (void *)integer_0;}
+void *type_initial_value_c::visit(safestring_type_name_c *symbol)   {return (void *)string_0;}
+void *type_initial_value_c::visit(safewstring_type_name_c *symbol)  {return (void *)wstring_0;}
 
 /********************************/
 /* B 1.3.3 - Derived data types */
--- a/absyntax_utils/type_initial_value.hh	Thu Aug 27 16:29:23 2009 +0100
+++ b/absyntax_utils/type_initial_value.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -107,6 +107,28 @@
     void *visit(string_type_name_c *symbol);
     void *visit(wstring_type_name_c *symbol);
 
+    void *visit(safetime_type_name_c *symbol);
+    void *visit(safebool_type_name_c *symbol);
+    void *visit(safesint_type_name_c *symbol);
+    void *visit(safeint_type_name_c *symbol);
+    void *visit(safedint_type_name_c *symbol);
+    void *visit(safelint_type_name_c *symbol);
+    void *visit(safeusint_type_name_c *symbol);
+    void *visit(safeuint_type_name_c *symbol);
+    void *visit(safeudint_type_name_c *symbol);
+    void *visit(safeulint_type_name_c *symbol);
+    void *visit(safereal_type_name_c *symbol);
+    void *visit(safelreal_type_name_c *symbol);
+    void *visit(safedate_type_name_c *symbol);
+    void *visit(safetod_type_name_c *symbol);
+    void *visit(safedt_type_name_c *symbol);
+    void *visit(safebyte_type_name_c *symbol);
+    void *visit(safeword_type_name_c *symbol);
+    void *visit(safedword_type_name_c *symbol);
+    void *visit(safelword_type_name_c *symbol);
+    void *visit(safestring_type_name_c *symbol);
+    void *visit(safewstring_type_name_c *symbol);
+
     /********************************/
     /* B 1.3.3 - Derived data types */
     /********************************/
--- a/lib/counter.txt	Thu Aug 27 16:29:23 2009 +0100
+++ b/lib/counter.txt	Wed Mar 30 19:53:32 2011 +0100
@@ -28,6 +28,10 @@
     Q : BOOL;
     CV : INT;
   END_VAR
+ 
+  VAR RRR : REAL; END_VAR
+  RRR := 9.9;
+
   IF R THEN CV := 0 ;
   ELSIF CU AND (CV < PV)
        THEN CV := CV+1;
--- a/stage1_2/Makefile	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage1_2/Makefile	Wed Mar 30 19:53:32 2011 +0100
@@ -3,12 +3,11 @@
 
 
 
-default:	all
+default: all
 
 all: iec.flex.o iec.y.o stage1_2.o
 
 clean:
-	echo > Makefile.depend
 	-rm -f iec.flex.c iec.y.cc iec.y.hh iec.y.output
 	-rm -f iec.noerrorcheck.y
 	-rm -f test_flex
@@ -22,7 +21,7 @@
 iec.flex.c: iec.flex
 	flex -oiec.flex.c iec.flex
 
-stage1_2.cc: iec.y.hh
+stage1_2.o: stage1_2.cc iec.y.hh 
 
 iec.flex.o: iec.y.hh iec.flex.c
 	$(CXX) -c iec.flex.c -D DEFAULT_LIBDIR='"$(IECLIBDIR)"' $(CFLAGS)
@@ -44,10 +43,3 @@
 ../% /%:
 	$(MAKE) -C $(@D) $(@F)
 
-
-Makefile.depend depend:
-	$(CXX) -MM -MG -I. *.cc > Makefile.depend
-	#| perl -pe 's/:/ Makefile.depend:/' > Makefile.depend
-
-include Makefile.depend
-
--- a/stage1_2/iec.flex	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage1_2/iec.flex	Wed Mar 30 19:53:32 2011 +0100
@@ -1034,11 +1034,16 @@
 	/* B 1.2.1 - Numeric Literals */
 	/******************************/
 TRUE		return TRUE;		/* Keyword */
-BOOL#1  	return TRUE;		/* Keyword (Data Type) + Delimiter */
-BOOL#TRUE	return TRUE;		/* Keyword (Data Type) + Delimiter + Keyword */
+BOOL#1  	return boolean_true_literal_token;
+BOOL#TRUE	return boolean_true_literal_token;
+SAFEBOOL#1	{if (get_opt_safe_extensions()) {return safeboolean_true_literal_token;} else{REJECT;}} /* Keyword (Data Type) */ 
+SAFEBOOL#TRUE	{if (get_opt_safe_extensions()) {return safeboolean_true_literal_token;} else{REJECT;}} /* Keyword (Data Type) */
+
 FALSE		return FALSE;		/* Keyword */
-BOOL#0  	return FALSE;		/* Keyword (Data Type) + Delimiter */
-BOOL#FALSE  	return FALSE;		/* Keyword (Data Type) + Delimiter + Keyword */
+BOOL#0  	return boolean_false_literal_token;
+BOOL#FALSE  	return boolean_false_literal_token;
+SAFEBOOL#0	{if (get_opt_safe_extensions()) {return safeboolean_false_literal_token;} else{REJECT;}} /* Keyword (Data Type) */ 
+SAFEBOOL#FALSE	{if (get_opt_safe_extensions()) {return safeboolean_false_literal_token;} else{REJECT;}} /* Keyword (Data Type) */
 
 
 	/************************/
@@ -1064,11 +1069,82 @@
 	/***********************************/
 	/* B 1.3.1 - Elementary Data Types */
 	/***********************************/
+BOOL		return BOOL;		/* Keyword (Data Type) */
+
 BYTE		return BYTE;		/* Keyword (Data Type) */
 WORD		return WORD;		/* Keyword (Data Type) */
 DWORD		return DWORD;		/* Keyword (Data Type) */
 LWORD		return LWORD;		/* Keyword (Data Type) */
 
+SINT		return SINT;		/* Keyword (Data Type) */
+INT		return INT;		/* Keyword (Data Type) */
+DINT		return DINT;		/* Keyword (Data Type) */
+LINT		return LINT;		/* Keyword (Data Type) */
+
+USINT		return USINT;		/* Keyword (Data Type) */
+UINT		return UINT;		/* Keyword (Data Type) */
+UDINT		return UDINT;		/* Keyword (Data Type) */
+ULINT		return ULINT;		/* Keyword (Data Type) */
+
+REAL		return REAL;		/* Keyword (Data Type) */
+LREAL		return LREAL;		/* Keyword (Data Type) */
+
+WSTRING		return WSTRING;		/* Keyword (Data Type) */
+STRING		return STRING;		/* Keyword (Data Type) */
+
+TIME		return TIME;		/* Keyword (Data Type) */
+DATE		return DATE;		/* Keyword (Data Type) */
+DT		return DT;		/* Keyword (Data Type) */
+TOD		return TOD;		/* Keyword (Data Type) */
+DATE_AND_TIME	return DATE_AND_TIME;	/* Keyword (Data Type) */
+TIME_OF_DAY	return TIME_OF_DAY;	/* Keyword (Data Type) */
+
+	/*****************************************************************/
+	/* Keywords defined in "Safety Software Technical Specification" */
+	/*****************************************************************/
+        /* 
+         * NOTE: The following keywords are define in 
+         *       "Safety Software Technical Specification,
+         *        Part 1: Concepts and Function Blocks,  
+         *        Version 1.0 – Official Release"
+         *        written by PLCopen - Technical Committee 5
+         *
+         *        We only support these extensions and keywords
+         *        if the apropriate command line option is given.
+         */
+SAFEBOOL	     {if (get_opt_safe_extensions()) {return SAFEBOOL;}          else {REJECT;}} 
+
+SAFEBYTE	     {if (get_opt_safe_extensions()) {return SAFEBYTE;}          else {REJECT;}} 
+SAFEWORD	     {if (get_opt_safe_extensions()) {return SAFEWORD;}          else {REJECT;}} 
+SAFEDWORD	     {if (get_opt_safe_extensions()) {return SAFEDWORD;}         else{REJECT;}}
+SAFELWORD	     {if (get_opt_safe_extensions()) {return SAFELWORD;}         else{REJECT;}}
+               
+SAFEREAL	     {if (get_opt_safe_extensions()) {return SAFESINT;}          else{REJECT;}}
+SAFELREAL    	     {if (get_opt_safe_extensions()) {return SAFELREAL;}         else{REJECT;}}
+                  
+SAFESINT	     {if (get_opt_safe_extensions()) {return SAFESINT;}          else{REJECT;}}
+SAFEINT	             {if (get_opt_safe_extensions()) {return SAFEINT;}           else{REJECT;}}
+SAFEDINT	     {if (get_opt_safe_extensions()) {return SAFEDINT;}          else{REJECT;}}
+SAFELINT             {if (get_opt_safe_extensions()) {return SAFELINT;}          else{REJECT;}}
+
+SAFEUSINT            {if (get_opt_safe_extensions()) {return SAFEUSINT;}         else{REJECT;}}
+SAFEUINT             {if (get_opt_safe_extensions()) {return SAFEUINT;}          else{REJECT;}}
+SAFEUDINT            {if (get_opt_safe_extensions()) {return SAFEUDINT;}         else{REJECT;}}
+SAFEULINT            {if (get_opt_safe_extensions()) {return SAFEULINT;}         else{REJECT;}}
+
+ /* SAFESTRING and SAFEWSTRING are not yet supported, i.e. checked correctly, in the semantic analyser (stage 3) */
+ /*  so it is best not to support them at all... */
+ /*
+SAFEWSTRING          {if (get_opt_safe_extensions()) {return SAFEWSTRING;}       else{REJECT;}}
+SAFESTRING           {if (get_opt_safe_extensions()) {return SAFESTRING;}        else{REJECT;}}
+ */
+
+SAFETIME             {if (get_opt_safe_extensions()) {return SAFETIME;}          else{REJECT;}}
+SAFEDATE             {if (get_opt_safe_extensions()) {return SAFEDATE;}          else{REJECT;}}
+SAFEDT               {if (get_opt_safe_extensions()) {return SAFEDT;}            else{REJECT;}}
+SAFETOD              {if (get_opt_safe_extensions()) {return SAFETOD;}           else{REJECT;}}
+SAFEDATE_AND_TIME    {if (get_opt_safe_extensions()) {return SAFEDATE_AND_TIME;} else{REJECT;}}
+SAFETIME_OF_DAY      {if (get_opt_safe_extensions()) {return SAFETIME_OF_DAY;}   else{REJECT;}}
 
 	/********************************/
 	/* B 1.3.2 - Generic data types */
@@ -1105,30 +1181,6 @@
 	/*********************/
 	/* B 1.4 - Variables */
 	/*********************/
-REAL		return REAL;		/* Keyword (Data Type) */
-LREAL		return LREAL;		/* Keyword (Data Type) */
-
-SINT		return SINT;		/* Keyword (Data Type) */
-INT		return INT;		/* Keyword (Data Type) */
-DINT		return DINT;		/* Keyword (Data Type) */
-LINT		return LINT;		/* Keyword (Data Type) */
-
-USINT		return USINT;		/* Keyword (Data Type) */
-UINT		return UINT;		/* Keyword (Data Type) */
-UDINT		return UDINT;		/* Keyword (Data Type) */
-ULINT		return ULINT;		/* Keyword (Data Type) */
-
-
-WSTRING		return WSTRING;		/* Keyword (Data Type) */
-STRING		return STRING;		/* Keyword (Data Type) */
-BOOL		return BOOL;		/* Keyword (Data Type) */
-TIME		return TIME;		/* Keyword (Data Type) */
-DATE		return DATE;		/* Keyword (Data Type) */
-DT		return DT;		/* Keyword (Data Type) */
-TOD		return TOD;		/* Keyword (Data Type) */
-DATE_AND_TIME	return DATE_AND_TIME;	/* Keyword (Data Type) */
-TIME_OF_DAY	return TIME_OF_DAY;	/* Keyword (Data Type) */
-
 
 	/******************************************/
 	/* B 1.4.3 - Declaration & Initialisation */
@@ -1388,20 +1440,7 @@
 EXIT		return EXIT;		/* Keyword */
 
 
-	/*****************************************************************/
-	/* Keywords defined in "Safety Software Technical Specification" */
-	/*****************************************************************/
-        /* 
-         * NOTE: The following keywords are define in 
-         *       "Safety Software Technical Specification,
-         *        Part 1: Concepts and Function Blocks,  
-         *        Version 1.0 – Official Release"
-         *        written by PLCopen - Technical Committee 5
-         *
-         *        We only support these extensions and keywords
-         *        if the apropriate command line option is given.
-         */
-SAFEBOOL	{if (get_opt_safe_extensions()) {return SAFEBOOL;} else{REJECT;}}	/* Keyword (Data Type) */ 
+
 
 
 
--- a/stage1_2/iec.y	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage1_2/iec.y	Wed Mar 30 19:53:32 2011 +0100
@@ -326,9 +326,7 @@
 /* B 1.2 - Constants */
 /*********************/
 %type <leaf>	constant
-/* a helper symbol for expression */
-%type  <leaf> non_negative_constant
-
+%type <leaf>	non_negative_constant
 
 /******************************/
 /* B 1.2.1 - Numeric Literals */
@@ -337,12 +335,8 @@
   bit
 */
 %type  <leaf> numeric_literal
-/* helper symbol for non_negative_constant */
-%type  <leaf> non_negative_numeric_literal
 %type  <leaf> integer_literal
 %type  <leaf> signed_integer
-/* a helper symbol for non_negative_constant */
-%type  <leaf> non_negative_signed_integer
 %token <ID>   integer_token
 %type  <leaf> integer
 %token <ID>   binary_integer_token
@@ -354,15 +348,16 @@
 %token <ID>   real_token
 %type  <leaf> real
 %type  <leaf> signed_real
-/* helper symbol for non_negative_real_literal */
-%type  <leaf> non_negative_signed_real
 %type  <leaf> real_literal
-/* helper symbol for non_negative_numeric_literal */
-%type  <leaf> non_negative_real_literal
 // %type  <leaf> exponent
 %type  <leaf> bit_string_literal
 %type  <leaf> boolean_literal
 
+%token safeboolean_true_literal_token
+%token safeboolean_false_literal_token
+%token boolean_true_literal_token
+%token boolean_false_literal_token
+
 %token FALSE
 %token TRUE
 
@@ -419,7 +414,7 @@
 %token <ID>	fixed_point_ms_token
 %token <ID>	integer_ms_token
 
-%token TIME
+// %token TIME
 %token T_SHARP
 
 
@@ -438,10 +433,10 @@
 %type  <leaf>	day
 %type  <leaf>	date_and_time
 
-%token TIME_OF_DAY
-%token DATE
+// %token TIME_OF_DAY
+// %token DATE
 %token D_SHARP
-%token DATE_AND_TIME
+// %token DATE_AND_TIME
 
 
 /**********************/
@@ -522,13 +517,49 @@
 %token STRING
 %token BOOL
 
-// %token TIME
-// %token DATE
-// %token DATE_AND_TIME
+%token TIME
+%token DATE
+%token DATE_AND_TIME
 %token DT
-// %token TIME_OF_DAY
+%token TIME_OF_DAY
 %token TOD
 
+/******************************************************/
+/* Symbols defined in                                 */
+/* "Safety Software Technical Specification,          */
+/*  Part 1: Concepts and Function Blocks,             */
+/*  Version 1.0 – Official Release"                   */
+/* by PLCopen - Technical Committee 5 - 2006-01-31    */
+/******************************************************/
+
+%token SAFEBYTE
+%token SAFEWORD
+%token SAFEDWORD
+%token SAFELWORD
+
+%token SAFELREAL
+%token SAFEREAL
+
+%token SAFESINT
+%token SAFEINT
+%token SAFEDINT
+%token SAFELINT
+
+%token SAFEUSINT
+%token SAFEUINT
+%token SAFEUDINT
+%token SAFEULINT
+
+%token SAFEWSTRING
+%token SAFESTRING
+%token SAFEBOOL
+
+%token SAFETIME
+%token SAFEDATE
+%token SAFEDATE_AND_TIME
+%token SAFEDT
+%token SAFETIME_OF_DAY
+%token SAFETOD
 
 /********************************/
 /* B 1.3.2 - Generic data types */
@@ -1168,6 +1199,7 @@
 %type  <leaf>	unary_expression
 // %type  <leaf>	unary_operator
 %type  <leaf>	primary_expression
+%type  <leaf>	non_negative_primary_expression
 /* intermediate helper symbol for primary_expression */
 %type  <leaf>	function_invocation
 
@@ -1274,15 +1306,6 @@
 %token EXIT
 
 
-/******************************************************/
-/* Symbols defined in                                 */
-/* "Safety Software Technical Specification,          */
-/*  Part 1: Concepts and Function Blocks,             */
-/*  Version 1.0 – Official Release"                   */
-/* by PLCopen - Technical Committee 5 - 2006-01-31    */
-/******************************************************/
-%token SAFEBOOL
-
 %%
 
 
@@ -1597,10 +1620,23 @@
 | bit_string_literal
 | boolean_literal
 /* NOTE: in order to remove reduce/reduce conflicts,
+ * [between -9.5 being parsed as 
+ *     (i)   a signed real, 
+ *     (ii)  or as a real preceded by the '-' operator
+ *  ]
+ *  we need to define a variant of the constant construct
+ *  where any constant is never preceded by the '-' character.
+ * In order to do this, we have borugh the signed_real 
+ * directly into the definition of the constant construct
+ * (so we can define another non_negative_constant
+ * construct that does not include it!)
+ */
+| signed_real
+/* NOTE: in order to remove reduce/reduce conflicts,
  * unsigned_integer, signed_integer, binary_integer, octal_integer
  * and hex_integer have been integrated directly into
  * the constants construct, instead of belonging to
- * either the bit_string_literal or integer_literal
+ * both the bit_string_literal or integer_literal
  * construct.
  */
 /* NOTE: unsigned_integer, although used in some
@@ -1614,24 +1650,58 @@
 | hex_integer
 ;
 
-/* a helper symbol for expression */
-/* A constant without any preceding '-', but may
- * include a preceding '+' !
+
+/* NOTE: in order to remove reduce/reduce conflicts,
+ * [between -9.5 being parsed as 
+ *     (i)   a signed real, 
+ *     (ii)  or as a real preceded by the '-' operator
+ *  ]
+ *  we need to define a variant of the constant construct
+ *  where any constant is never preceded by the '-' character.
+ * In order to do this, we have borugh the signed_real 
+ * directly into the definition of the constant construct
+ * (so we can define another non_negative_constant
+ * construct that does not include it!)
  */
 non_negative_constant:
-  non_negative_numeric_literal
+  numeric_literal
 | character_string
 | time_literal
 | bit_string_literal
 | boolean_literal
-| non_negative_signed_integer
+/* NOTE: in order to remove reduce/reduce conflicts,
+ * [between -9.5 being parsed as 
+ *     (i)   a signed real, 
+ *     (ii)  or as a real preceded by the '-' operator
+ *  ]
+ *  we need to define a variant of the constant construct
+ *  where any constant is never preceded by the '-' character.
+ * In order to do this, we have borugh the signed_real 
+ * directly into the definition of the constant construct
+ * (so we can define another non_negative_constant
+ * construct that does not include it!)
+ */
+/* | signed_real */
+| real /* an unsigned real */
+/* NOTE: in order to remove reduce/reduce conflicts,
+ * unsigned_integer, signed_integer, binary_integer, octal_integer
+ * and hex_integer have been integrated directly into
+ * the constants construct, instead of belonging to
+ * both the bit_string_literal or integer_literal
+ * construct.
+ */
+/* NOTE: unsigned_integer, although used in some
+ * rules, is not defined in the spec!
+ * We therefore replaced unsigned_integer as integer
+ */
+| integer  /* i.e. an unsigned_integer */
+/* | signed_integer */
 | binary_integer
 | octal_integer
 | hex_integer
 ;
 
 
-
 /******************************/
 /* B 1.2.1 - Numeric Literals */
 /******************************/
@@ -1663,7 +1733,7 @@
  *      Flex handles real, while bison handles signed_real
  *      and real_literal.
  *
- *    - According to the spec, intger '.' integer
+ *    - According to the spec, integer '.' integer
  *      may be reduced to either a real or a fixed_point.
  *      It is nevertheless possible to figure out from the
  *      context which of the two rules should be used in
@@ -1720,12 +1790,6 @@
 | real_literal
 ;
 
-/* helper symbol for non_negative_constant */
-non_negative_numeric_literal:
-  integer_literal
-| non_negative_real_literal
-;
-
 
 integer_literal:
   integer_type_name '#' signed_integer
@@ -1761,22 +1825,16 @@
 signed_integer:
   integer
 | '+' integer   {$$ = $2;}
-| '-' integer	{$$ = new neg_literal_c($2, locloc(@$));}
-;
-
-/* a helper symbol for non_negative_constant */
-/* A integer without any preceding '-', but may
- * include a preceding '+' !
- */
-non_negative_signed_integer:
-  integer
-| '+' integer   {$$ = $2;}
+| '-' integer	{$$ = new neg_integer_c($2, locloc(@$));}
 ;
 
 
 real_literal:
-  signed_real
-| real_type_name '#' signed_real
+/* NOTE: see note in the definition of constant for reason
+ * why signed_real is missing here!
+ */
+/*  signed_real */
+  real_type_name '#' signed_real
 	{$$ = new real_literal_c($1, $3, locf(@1), locl(@3));}
 /* ERROR_CHECK_BEGIN */
 | real_type_name signed_real
@@ -1790,24 +1848,13 @@
 /* ERROR_CHECK_END */
 ;
 
-/* helper symbol for non_negative_numeric_literal */
-non_negative_real_literal:
-  non_negative_signed_real
-| real_type_name '#' signed_real
-	{$$ = new real_literal_c($1, $3, locf(@1), locl(@3));}
-;
 
 signed_real:
   real
 | '+' real	{$$ = $2;}
-| '-' real	{$$ = new neg_literal_c($2, locloc(@2));}
-;
-
-/* helper symbol for non_negative_real_literal */
-non_negative_signed_real:
-  real
-| '+' real	{$$ = $2;}
-;
+| '-' real	{$$ = new neg_real_c($2, locloc(@2));}
+;
+
 
 
 bit_string_literal:
@@ -1838,7 +1885,7 @@
 | bit_string_type_name hex_integer
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between bit string type name and value in bit string literal."); yynerrs++;}
 | bit_string_type_name '#' error
-  {$$ = NULL;
+	{$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for bit string literal.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid value for bit string literal."); yyclearin;}
 	 yyerrok;
@@ -1848,12 +1895,36 @@
 
 
 boolean_literal:
-  TRUE	{$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)),
-  				    new boolean_true_c(locloc(@$)),
-				    locloc(@$));}
-| FALSE	{$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)),
+  boolean_true_literal_token
+	{$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)),
+				    new boolean_true_c(locloc(@$)),
+				    locloc(@$));
+	}
+| boolean_false_literal_token
+	{$$ = new boolean_literal_c(new bool_type_name_c(locloc(@$)),
 				    new boolean_false_c(locloc(@$)),
-				    locloc(@$));}
+				    locloc(@$));
+	}
+| safeboolean_true_literal_token
+	{$$ = new boolean_literal_c(new safebool_type_name_c(locloc(@$)),
+				    new boolean_true_c(locloc(@$)),
+				    locloc(@$));
+	}
+| safeboolean_false_literal_token
+	{$$ = new boolean_literal_c(new safebool_type_name_c(locloc(@$)),
+				    new boolean_false_c(locloc(@$)),
+				    locloc(@$));
+	}
+| FALSE
+	{$$ = new boolean_literal_c(NULL,
+				    new boolean_false_c(locloc(@$)),
+				    locloc(@$));
+	}
+| TRUE
+	{$$ = new boolean_literal_c(NULL,
+				    new boolean_true_c(locloc(@$)),
+				    locloc(@$));
+	}
 /*
 |	BOOL '#' '1' {}
 |	BOOL '#' '0' {}
@@ -1935,13 +2006,17 @@
  *       when it comes across 'T#'
  */
   TIME '#' interval
-	{$$ = new duration_c(NULL, $3, locloc(@$));}
+	{$$ = new duration_c(new time_type_name_c(locloc(@1)), NULL, $3, locloc(@$));}
 | TIME '#' '-' interval
-	{$$ = new duration_c(new neg_time_c(locloc(@$)), $4, locloc(@$));}
+	{$$ = new duration_c(new time_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $4, locloc(@$));}
 | T_SHARP interval
-	{$$ = new duration_c(NULL, $2, locloc(@$));}
+	{$$ = new duration_c(new time_type_name_c(locloc(@1)), NULL, $2, locloc(@$));}
 | T_SHARP '-' interval
-	{$$ = new duration_c(new neg_time_c(locloc(@$)), $3, locloc(@$));}
+	{$$ = new duration_c(new time_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $3, locloc(@$));}
+| SAFETIME '#' interval
+	{$$ = new duration_c(new safetime_type_name_c(locloc(@1)), NULL, $3, locloc(@$));}
+| SAFETIME '#' '-' interval
+	{$$ = new duration_c(new safetime_type_name_c(locloc(@1)), new neg_time_c(locloc(@$)), $4, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | TIME interval
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME' and interval in duration."); yynerrs++;}
@@ -2106,7 +2181,9 @@
 /************************************/
 time_of_day:
   TIME_OF_DAY '#' daytime
-	{$$ = new time_of_day_c($3, locloc(@$));}
+	{$$ = new time_of_day_c(new tod_type_name_c(locloc(@1)), $3, locloc(@$));}
+| SAFETIME_OF_DAY '#' daytime
+	{$$ = new time_of_day_c(new safetod_type_name_c(locloc(@1)), $3, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | TIME_OF_DAY daytime
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'TIME_OF_DAY' and daytime in time of day."); yynerrs++;}
@@ -2153,9 +2230,11 @@
 
 date:
   DATE '#' date_literal
-	{$$ = new date_c($3, locloc(@$));}
+	{$$ = new date_c(new date_type_name_c(locloc(@1)), $3, locloc(@$));}
 | D_SHARP date_literal
-	{$$ = new date_c($2, locloc(@$));}
+	{$$ = new date_c(new date_type_name_c(locloc(@1)), $2, locloc(@$));}
+| SAFEDATE '#' date_literal
+	{$$ = new date_c(new safedate_type_name_c(locloc(@1)), $3, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | DATE date_literal
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'DATE' and date literal in date."); yynerrs++;}
@@ -2206,7 +2285,9 @@
 
 date_and_time:
   DATE_AND_TIME '#' date_literal '-' daytime
-	{$$ = new date_and_time_c($3, $5, locloc(@$));}
+	{$$ = new date_and_time_c(new dt_type_name_c(locloc(@1)), $3, $5, locloc(@$));}
+| SAFEDATE_AND_TIME '#' date_literal '-' daytime
+	{$$ = new date_and_time_c(new safedt_type_name_c(locloc(@1)), $3, $5, locloc(@$));}
 /* ERROR_CHECK_BEGIN */
 | DATE_AND_TIME date_literal '-' daytime
 	{$$ = NULL; print_err_msg(locl(@1), locf(@2), "'#' missing between 'DATE_AND_TIME' and date literal in date and time."); yynerrs++;}
@@ -2251,6 +2332,14 @@
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
+    /******************************************************/
+    /* SAFExxxx Symbols defined in                        */
+    /* "Safety Software Technical Specification,          */
+    /*  Part 1: Concepts and Function Blocks,             */
+    /*  Version 1.0 – Official Release"                   */
+    /* by PLCopen - Technical Committee 5 - 2006-01-31    */
+    /******************************************************/
+
 elementary_type_name:
   numeric_type_name
 | date_type_name
@@ -2262,13 +2351,7 @@
  * and grouping type definition for reason why BOOL
  * was added to this definition.
  */
-    /******************************************************/
-    /* Symbols defined in                                 */
-    /* "Safety Software Technical Specification,          */
-    /*  Part 1: Concepts and Function Blocks,             */
-    /*  Version 1.0 – Official Release"                   */
-    /* by PLCopen - Technical Committee 5 - 2006-01-31    */
-    /******************************************************/
+| SAFETIME	{$$ = new safetime_type_name_c(locloc(@$));}
 | SAFEBOOL	{$$ = new safebool_type_name_c(locloc(@$));}
 ;
 
@@ -2283,38 +2366,57 @@
 ;
 
 signed_integer_type_name:
-  SINT	{$$ = new sint_type_name_c(locloc(@$));}
-| INT	{$$ = new int_type_name_c(locloc(@$));}
-| DINT	{$$ = new dint_type_name_c(locloc(@$));}
-| LINT	{$$ = new lint_type_name_c(locloc(@$));}
+  SINT		{$$ = new sint_type_name_c(locloc(@$));}
+| INT		{$$ = new int_type_name_c(locloc(@$));}
+| DINT		{$$ = new dint_type_name_c(locloc(@$));}
+| LINT		{$$ = new lint_type_name_c(locloc(@$));}
+| SAFESINT	{$$ = new safesint_type_name_c(locloc(@$));}
+| SAFEINT	{$$ = new safeint_type_name_c(locloc(@$));}
+| SAFEDINT	{$$ = new safedint_type_name_c(locloc(@$));}
+| SAFELINT	{$$ = new safelint_type_name_c(locloc(@$));}
 ;
 
 unsigned_integer_type_name:
-  USINT	{$$ = new usint_type_name_c(locloc(@$));}
-| UINT	{$$ = new uint_type_name_c(locloc(@$));}
-| UDINT	{$$ = new udint_type_name_c(locloc(@$));}
-| ULINT	{$$ = new ulint_type_name_c(locloc(@$));}
+  USINT		{$$ = new usint_type_name_c(locloc(@$));}
+| UINT		{$$ = new uint_type_name_c(locloc(@$));}
+| UDINT		{$$ = new udint_type_name_c(locloc(@$));}
+| ULINT		{$$ = new ulint_type_name_c(locloc(@$));}
+| SAFEUSINT	{$$ = new safeusint_type_name_c(locloc(@$));}
+| SAFEUINT	{$$ = new safeuint_type_name_c(locloc(@$));}
+| SAFEUDINT	{$$ = new safeudint_type_name_c(locloc(@$));}
+| SAFEULINT	{$$ = new safeulint_type_name_c(locloc(@$));}
 ;
 
 real_type_name:
-  REAL	{$$ = new real_type_name_c(locloc(@$));}
-| LREAL	{$$ = new lreal_type_name_c(locloc(@$));}
+  REAL		{$$ = new real_type_name_c(locloc(@$));}
+| LREAL		{$$ = new lreal_type_name_c(locloc(@$));}
+| SAFEREAL	{$$ = new safereal_type_name_c(locloc(@$));}
+| SAFELREAL	{$$ = new safelreal_type_name_c(locloc(@$));}
 ;
 
 date_type_name:
-  DATE		{$$ = new date_type_name_c(locloc(@$));}
-| TIME_OF_DAY	{$$ = new tod_type_name_c(locloc(@$));}
-| TOD		{$$ = new tod_type_name_c(locloc(@$));}
-| DATE_AND_TIME	{$$ = new dt_type_name_c(locloc(@$));}
-| DT		{$$ = new dt_type_name_c(locloc(@$));}
+  DATE			{$$ = new date_type_name_c(locloc(@$));}
+| TIME_OF_DAY		{$$ = new tod_type_name_c(locloc(@$));}
+| TOD			{$$ = new tod_type_name_c(locloc(@$));}
+| DATE_AND_TIME		{$$ = new dt_type_name_c(locloc(@$));}
+| DT			{$$ = new dt_type_name_c(locloc(@$));}
+| SAFEDATE		{$$ = new safedate_type_name_c(locloc(@$));}
+| SAFETIME_OF_DAY	{$$ = new safetod_type_name_c(locloc(@$));}
+| SAFETOD		{$$ = new safetod_type_name_c(locloc(@$));}
+| SAFEDATE_AND_TIME	{$$ = new safedt_type_name_c(locloc(@$));}
+| SAFEDT		{$$ = new safedt_type_name_c(locloc(@$));}
 ;
 
 
 bit_string_type_name:
-  BYTE	{$$ = new byte_type_name_c(locloc(@$));}
-| WORD	{$$ = new word_type_name_c(locloc(@$));}
-| DWORD	{$$ = new dword_type_name_c(locloc(@$));}
-| LWORD	{$$ = new lword_type_name_c(locloc(@$));}
+  BYTE		{$$ = new byte_type_name_c(locloc(@$));}
+| WORD		{$$ = new word_type_name_c(locloc(@$));}
+| DWORD		{$$ = new dword_type_name_c(locloc(@$));}
+| LWORD		{$$ = new lword_type_name_c(locloc(@$));}
+| SAFEBYTE	{$$ = new safebyte_type_name_c(locloc(@$));}
+| SAFEWORD	{$$ = new safeword_type_name_c(locloc(@$));}
+| SAFEDWORD	{$$ = new safedword_type_name_c(locloc(@$));}
+| SAFELWORD	{$$ = new safelword_type_name_c(locloc(@$));}
 /* NOTE: see note under the B 1.2.1 section of token
  * and grouping type definition for reason why the BOOL
  * was omitted from this definition.
@@ -2333,6 +2435,8 @@
 elementary_string_type_name:
   STRING	{$$ = new string_type_name_c(locloc(@$));}
 | WSTRING	{$$ = new wstring_type_name_c(locloc(@$));}
+| SAFESTRING	{$$ = new safestring_type_name_c(locloc(@$));}
+| SAFEWSTRING	{$$ = new safewstring_type_name_c(locloc(@$));}
 ;
 
 
@@ -6375,7 +6479,7 @@
 
 
 il_param_instruction:
-  il_param_assignment ',' eol_list
+  il_param_assignment ',' eol_list 
 | il_param_out_assignment ',' eol_list
 /* ERROR_CHECK_BEGIN */
 | il_param_assignment ',' error
@@ -6591,13 +6695,61 @@
 /*  any_identifier SENDTO */
   sendto_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));}
+/* The following is not required, as the sendto_identifier_token returned by flex will 
+ * also include the 'ENO' identifier.
+ * The resulting abstract syntax tree is identical with or without this following rule,
+ * as both the eno_identifier and the sendto_identifier are stored as
+ * an identifier_c !!
+ */
+/*
 | eno_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(NULL, $1, locloc(@$));}
+*/
 /*| NOT variable_name SENDTO */
 | NOT sendto_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));}
+/* The following is not required, as the sendto_identifier_token returned by flex will 
+ * also include the 'ENO' identifier.
+ * The resulting abstract syntax tree is identical with or without this following rule,
+ * as both the eno_identifier and the sendto_identifier are stored as
+ * an identifier_c !!
+ *
+ * NOTE: Removing the following rule also removes a shift/reduce conflict from the parser.
+ *       This conflict is not really an error/ambiguity in the syntax, but rather
+ *       due to the fact that more than a single look-ahead token would be required
+ *       to correctly parse the syntax, something that bison does not support.
+ *
+ *       The shift/reduce conflict arises because bison does not know whether
+ *       to parse the 'NOT ENO' in the following code
+ *         LD 1
+ *         funct_name (
+ *                      NOT ENO => bool_var,
+ *                      EN := TRUE
+ *                    )
+ *        as either a il_param_assignment (wrong!) or an il_param_out_assignment.(correct).
+ *        The '=>' delimiter (known as SEND_TO in this iec.y file) is a dead giveaway that 
+ *        it should be parsed as an il_param_out_assignment, but still, bison gets confused!
+ *        Bison considers the possibility of reducing the 'NOT ENO' as an NOT_operator with
+ *        the 'ENO' operand
+ *        (NOT_operator -> il_simple_operator -> il_simple_operation -> il_simple_instruction ->
+ *          -> simple_instr_list -> il_param_assignment)
+ *        instead of reducing it to an il_param_out_operator.
+ *        ( il_param_out_operator -> il_param_out_assignment)
+ *
+ *        Note that the shift/reduce conflict only manifests itself in the il_formal_funct_call,
+ *        where both the il_param_out_assignment and il_param_assignment are used!
+ * 
+ *          il_param_out_assignment --+--> il_param_instruction -> il_param_instruction_list --+
+ *                                    |                                                        |
+ *          il_param_assignment     --+                                                        |
+ *                                                                                             |
+ *                                                     il_formal_funct_call <- il_param_list <-+
+ *
+ */
+/*
 | NOT eno_identifier SENDTO
 	{$$ = new il_assign_out_operator_c(new not_paramassign_c(locloc(@1)), $2, locloc(@$));}
+*/
 /* ERROR_CHECK_BEGIN */
 | error SENDTO
   {$$ = NULL; print_err_msg(locf(@1), locl(@1), "invalid parameter defined in parameter out assignment."); yyerrok;}
@@ -6838,8 +6990,8 @@
 
 
 unary_expression:
-  primary_expression
-| '-' primary_expression
+  non_negative_primary_expression
+| '-' non_negative_primary_expression
 	{$$ = new neg_expression_c($2, locloc(@$));}
 | NOT primary_expression
 	{$$ = new not_expression_c($2, locloc(@$));}
@@ -6874,8 +7026,9 @@
  *       expression<-unary_expression<-constant<-integer
  *       (i.e. the constant 9, preceded by a unary negation)
  *
- *       To remove the conlfict, we only allow constants without
+ *       To remove the conflict, we only allow constants without
  *       a preceding '-' to be used in primary_expression
+ *       (i.e. as a parameter to the unary negation operator)
  */
 /* NOTE: We use enumerated_value_without_identifier instead of enumerated_value
  *       in order to remove a reduce/reduce conflict between reducing an
@@ -6887,8 +7040,7 @@
  *       for a variable and an enumerated value, then the variable shall be
  *       considered.
  */
-primary_expression:
-/* constant */
+non_negative_primary_expression:
   non_negative_constant
 //| enumerated_value_without_identifier
 | enumerated_value
@@ -6903,6 +7055,22 @@
 ;
 
 
+primary_expression:
+  constant
+//| enumerated_value_without_identifier
+  enumerated_value
+| variable
+| '(' expression ')'
+	{$$ = $2;}
+|  function_invocation
+/* ERROR_CHECK_BEGIN */
+| '(' expression error
+  {$$ = NULL; print_err_msg(locl(@2), locf(@3), "')' missing at the end of expression in ST expression."); yyerrok;}
+/* ERROR_CHECK_END */
+;
+
+
+
 /* intermediate helper symbol for primary_expression */
 /* NOTE: function_name includes the standard function name 'NOT' !
  *       This introduces a reduce/reduce conflict, as NOT(var)
@@ -7122,14 +7290,30 @@
 /*| any_identifier SENDTO variable */
 | sendto_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));}
+/* The following is not required, as the sendto_identifier_token returned by flex will 
+ * also include the 'ENO' identifier.
+ * The resulting abstract syntax tree is identical with or without this following rule,
+ * as both the eno_identifier and the sendto_identifier are stored as
+ * an identifier_c !!
+ */
+/*
 | eno_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(NULL, $1, $3, locloc(@$));}
+*/
 /*| NOT variable_name SENDTO variable */
 /*| NOT any_identifier SENDTO variable*/
 | NOT sendto_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));}
+/* The following is not required, as the sendto_identifier_token returned by flex will 
+ * also include the 'ENO' identifier.
+ * The resulting abstract syntax tree is identical with or without this following rule,
+ * as both the eno_identifier and the sendto_identifier are stored as
+ * an identifier_c !!
+ */
+/*
 | NOT eno_identifier SENDTO variable
 	{$$ = new output_variable_param_assignment_c(new not_paramassign_c(locloc(@$)), $2, $4, locloc(@$));}
+*/
 /* ERROR_CHECK_BEGIN */
 | any_identifier ASSIGN error
   {$$ = NULL;
@@ -7149,12 +7333,14 @@
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;}
 	 yyerrok;
 	}
+/*
 | eno_identifier SENDTO error
   {$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no expression defined in ST formal parameter out assignment.");}
 	 else {print_err_msg(locf(@3), locl(@3), "invalid expression in ST formal parameter out assignment."); yyclearin;}
 	 yyerrok;
 	}
+*/
 | NOT SENDTO variable
   {$$ = NULL; print_err_msg(locl(@1), locf(@2), "no parameter name defined in ST formal parameter out negated assignment."); yynerrs++;}
 | NOT error SENDTO variable
@@ -7165,12 +7351,14 @@
 	 else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;}
 	 yyerrok;
 	}
+/*
 | NOT eno_identifier SENDTO error
   {$$ = NULL;
 	 if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no expression defined in ST formal parameter out negated assignment.");}
 	 else {print_err_msg(locf(@4), locl(@4), "invalid expression in ST formal parameter out negated assignment."); yyclearin;}
 	 yyerrok;
 	}
+*/
 /* ERROR_CHECK_END */
 ;
 
@@ -7763,6 +7951,11 @@
   }
 
   /* first parse the standard library file... */
+  /*
+  #if YYDEBUG
+    yydebug = 1;
+  #endif
+  */
   yyin = lib_file;
   allow_function_overloading = true;
   full_token_loc = full_token_loc_;
@@ -7786,11 +7979,11 @@
         library_element_symtable.end_value())
       library_element_symtable.insert(standard_function_block_names[i], standard_function_block_name_token);
 
-#if YYDEBUG
-  yydebug = 1;
-#endif
 
   /* now parse the input file... */
+  #if YYDEBUG
+    yydebug = 1;
+  #endif
   yyin = in_file;
   allow_function_overloading = false;
   full_token_loc = full_token_loc_;
--- a/stage3/stage3.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage3/stage3.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * (c) 20099 Catarina da Costa Boucinha
+ * (c) 2009 Mario de Sousa
  *
  * Offered to the public under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2 of the
--- a/stage3/stage3.hh	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage3/stage3.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * (c) 2009 Catarina da Costa Boucinha
+ * (c) 2009 Mario de Sousa
  *
  * Offered to the public under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2 of the
--- a/stage3/visit_expression_type.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage3/visit_expression_type.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -71,6 +71,7 @@
   symbol->function_block_body->accept(*this);
   il_default_variable_type = NULL;
   delete search_varfb_instance_type;
+  search_varfb_instance_type = NULL;
   return NULL;
 }
 
@@ -84,6 +85,7 @@
   symbol->function_body->accept(*this);
   il_default_variable_type = NULL;
   delete search_varfb_instance_type;
+  search_varfb_instance_type = NULL;
   return NULL;
 }
 
@@ -97,6 +99,7 @@
   symbol->fblock_body->accept(*this);
   il_default_variable_type = NULL;
   delete search_varfb_instance_type;
+  search_varfb_instance_type = NULL;
   return NULL;
 }
 
@@ -115,13 +118,55 @@
 }
 
 
+
+
+/* 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... 
+ */
+
 /* A helper function... */
 bool visit_expression_type_c::is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
   if (type_symbol == NULL) {ERROR;}
   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);
+      || 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) {ERROR;}
+  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) {ERROR;}
+  /* 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);
 }
 
 
@@ -132,32 +177,95 @@
   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) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
-  return is_ANY_REAL_type(type_symbol) || is_ANY_INT_type(type_symbol);
-}
-
+  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) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
   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;}
+  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) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
   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) {ERROR;}
+  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) {ERROR;}
+  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) {
@@ -170,49 +278,130 @@
   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;}
-  if (is_literal_integer_type(type_symbol))              {return true;}
   return false;
 }
 
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_SAFEINT_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
   if (typeid(*type_symbol) == typeid(real_type_name_c))  {return true;}
   if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
-  if (is_literal_real_type(type_symbol))                 {return true;}
   return false;
 }
 
+/* A helper function... */
+bool visit_expression_type_c::is_ANY_SAFEREAL_type(symbol_c *type_symbol) {
+  if (type_symbol == NULL) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
-  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;}
-  if (is_literal_integer_type(type_symbol))              {return true;}
+  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) {ERROR;}
+  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) {ERROR;}
+  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) {ERROR;}
-  if (typeid(*type_symbol) == typeid(bool_type_name_c))  {return true;}
-  if (is_literal_bool_type(type_symbol))                 {return true;}
+  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) {ERROR;}
+  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) {ERROR;}
+  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)  (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 true;}
+  if (type_symbol == NULL) {ERROR;}
+  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) {ERROR;}
   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;}
@@ -223,8 +412,9 @@
 
 /* A helper function... */
 bool visit_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
-  if (type_symbol == NULL) {return true;}
-  if (typeid(*type_symbol) == typeid(real_c)) {return true;}
+  if (type_symbol == NULL) {ERROR;}
+  if (typeid(*type_symbol) == typeid(real_c))     {return true;}
+  if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;}
   return false;
 }
 
@@ -233,15 +423,14 @@
 bool visit_expression_type_c::is_literal_bool_type(symbol_c *type_symbol) {
   bool_type_name_c bool_t;
 
-  if (type_symbol == NULL) {return true;}
+  if (type_symbol == NULL) {ERROR;}
   if (typeid(*type_symbol) == typeid(boolean_true_c))    {return true;}
   if (typeid(*type_symbol) == typeid(boolean_false_c))   {return true;}
-  if (is_literal_integer_type(type_symbol))
+  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.
  *
@@ -253,6 +442,7 @@
  *
  * 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) {ERROR;}
   if (first_type == NULL)  {return second_type;}
@@ -267,30 +457,82 @@
   if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
     {return first_type;}
 
-  /* This check can only be made after the is_literal_XXXX checks */
+  /* 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...
+   * we must return the one that occupies more bits... This is done above.
    */
   if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
 
-  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_ANY_BIT_type(first_type)     && is_literal_integer_type(second_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_literal_integer_type(first_type))
+  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_INT_type(first_type)   && is_literal_integer_type(second_type))
+  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_INT_type(second_type)  && is_literal_integer_type(first_type))
+  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_REAL_type(first_type)  && is_literal_real_type(second_type))
+  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_REAL_type(second_type) && is_literal_real_type(first_type))
+  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;
 }
@@ -306,7 +548,44 @@
 }
 
 
+/* 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"); */ ERROR;}
+  if (value_type == NULL) {/* STAGE3_ERROR(var_type,   var_type,   "Value_type == NULL"); */ ERROR;}
+  if (var_type == NULL || value_type == NULL) {ERROR;}
+
+  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) {ERROR;}
@@ -315,12 +594,12 @@
 
 
 
-#define is_num_type      is_ANY_NUM_type
-#define is_integer_type  is_ANY_INT_type
-#define is_real_type     is_ANY_REAL_type
-#define is_binary_type   is_ANY_BIT_type
+#define is_num_type      is_ANY_NUM_compatible
+#define is_integer_type  is_ANY_INT_compatible
+#define is_real_type     is_ANY_REAL_compatible
+#define is_binary_type   is_ANY_BIT_compatible
  /* actually the ROR, ROL, SHL, and SHR function also accept boolean type! */
-#define is_nbinary_type  is_ANY_BIT_type  
+#define is_nbinary_type  is_ANY_BIT_compatible
 #define compute_standard_function_default visit_expression_type_c::compute_standard_function_default
 #define compute_standard_function_il visit_expression_type_c::compute_standard_function_il
 #define search_expression_type_c visit_expression_type_c
@@ -350,20 +629,24 @@
 
 
 /* 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) {
   bool error = false;
 
   if (!(this->*is_data_type)(left_type)) {
-    STAGE3_ERROR(left_type, left_type, "invalid data type of first operand.");
+    STAGE3_ERROR(left_type, left_type, "Invalid data type of left operand.");
     error = true;
   }
   if (!(this->*is_data_type)(right_type)) {
-    STAGE3_ERROR(right_type, right_type, "invalid data type of second operand.");
+    STAGE3_ERROR(right_type, right_type, "Invalid data type of right operand.");
     error = true;
   }
   if (!is_compatible_type(left_type, right_type)) {
-    STAGE3_ERROR(left_type, right_type, "type mismatch between operands.");
+    STAGE3_ERROR(left_type, right_type, "Type mismatch between operands.");
     error = true;
   }
 
@@ -374,26 +657,44 @@
 }
 
 
+# if 0
 /* A helper function... */
 symbol_c *visit_expression_type_c::compute_numeric_expression(symbol_c *left_type, symbol_c *right_type,
                                                               is_data_type_t is_data_type) {
-  if (!(this->*is_data_type)(left_type))
-    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
-  if (!(this->*is_data_type)(right_type))
-    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
-  if (!is_compatible_type(left_type, right_type))
-    STAGE3_ERROR(left_type, right_type, "Both parts of the equation must be the same type.");
-
+  bool error = false;
+
+  if (!(this->*is_data_type)(left_type)) {
+    STAGE3_ERROR(left_type, right_type, "Invalid data type of left operand.");
+    error = true;
+  }
+  if (!(this->*is_data_type)(right_type)) {
+    STAGE3_ERROR(left_type, right_type, "Invalid data type of right operand.");
+    error = true;
+  }
+  if (!is_compatible_type(left_type, right_type)) {
+    STAGE3_ERROR(left_type, right_type, "Type mismatch between operands.");
+    error = true;
+  }
+
+/*
   if (is_literal_integer_type(left_type) || is_literal_real_type(left_type)) {
     return right_type;
   } else {
     return left_type;
   }
+*/
+
+  if (error)
+    return NULL;
+  else
+    return common_type(left_type, right_type);
 
   /* humour the compiler... */
-  return NULL;
-}
-
+/*
+  return NULL;
+*/
+}
+#endif
 
 
 
@@ -425,7 +726,7 @@
      */
     if(param_name != NULL) {
       param_type = fp_iterator.param_type();
-      if(!is_compatible_type(il_default_variable_type,param_type)) 
+      if(!is_valid_assignment(param_type, il_default_variable_type)) 
         STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
     }
   } // if (use_il_defvar)
@@ -449,7 +750,7 @@
       /* Get the parameter type */
       param_type = fp_iterator.param_type();
       /* If the declared parameter and the parameter from the function call do no have the same type */
-      if(!is_compatible_type(call_param_type,param_type)) STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
+      if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
     }
   }
 }
@@ -499,8 +800,7 @@
     /* Get the parameter type */
     param_type = fp_iterator.param_type();
     /* If the declared parameter and the parameter from the function call have the same type */
-//     if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
-    if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_name, "Type mismatch function/FB call parameter.");
+    if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(call_param_name, call_param_name, "Type mismatch function/FB call parameter.");
   }
 }
 
@@ -549,7 +849,7 @@
       /* Get the parameter type */
       param_type = fp_iterator.param_type();
       /* If the declared parameter and the parameter from the function call have the same type */
-      if(!is_compatible_type(call_param_type, param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
+      if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
     }
   }
 }
@@ -929,7 +1229,7 @@
 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_type(il_operand_type))
+  if(!is_ANY_BIT_compatible(il_operand_type))
       STAGE3_ERROR(symbol, symbol, "invalid data type of LDN operand, should be of type ANY_BIT.");
   il_default_variable_type = il_operand_type;
   return NULL;
@@ -938,7 +1238,8 @@
 // SYM_REF0(ST_operator_c)
 void *visit_expression_type_c::visit(ST_operator_c *symbol) {
   verify_null(symbol);
-  if(!is_compatible_type(il_default_variable_type, il_operand_type))
+
+  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... */
@@ -949,12 +1250,12 @@
 // SYM_REF0(STN_operator_c)
  void *visit_expression_type_c::visit(STN_operator_c *symbol) {
   verify_null(symbol);
-  if(!is_compatible_type(il_default_variable_type, il_operand_type))
+  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_type(il_default_variable_type))
+  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_type(il_operand_type))
+  if(!is_ANY_BIT_compatible(il_operand_type))
       STAGE3_ERROR(symbol, symbol, "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;
@@ -971,7 +1272,7 @@
     STAGE3_ERROR(symbol, symbol, "Il default variable should not be NULL.");
     return NULL;
   }
-  if(!is_ANY_BIT_type(il_default_variable_type)) {
+  if(!is_ANY_BIT_compatible(il_default_variable_type)) {
     STAGE3_ERROR(symbol, symbol, "Il default variable should be of type ANY_BIT.");
     return NULL;
   }
@@ -1054,42 +1355,42 @@
 //SYM_REF0(AND_operator_c)
 void *visit_expression_type_c::visit(AND_operator_c *symbol) {
   verify_null(symbol);
-  il_default_variable_type = compute_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   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_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   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_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   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_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   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_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   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_boolean_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_type);
+  il_default_variable_type = compute_expression(il_default_variable_type,  il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible);
   return NULL;
 }
 
@@ -1098,13 +1399,32 @@
   verify_null(symbol);
   symbol_c *left_type  = il_default_variable_type;
   symbol_c *right_type = il_operand_type;
-  if      (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) 
+
+/* 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;
-  else if (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(time_type_name_c)) 
+*/
+
+  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 (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(time_type_name_c)) 
+  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 il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+  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);
   return NULL;
 }
 
@@ -1113,19 +1433,59 @@
   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;
-  else if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c))
+*/
+
+  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 (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(time_type_name_c))
-    il_default_variable_type = &tod_type_name;
-  else if (typeid(*left_type) == typeid(tod_type_name_c)  && typeid(*right_type) == typeid(tod_type_name_c))
+  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 (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(time_type_name_c))
-    il_default_variable_type = &dt_type_name;
-  else if (typeid(*left_type) == typeid(dt_type_name_c)   && typeid(*right_type) == typeid(dt_type_name_c))
+  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 il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+  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);
   return NULL;
 }
 
@@ -1134,9 +1494,20 @@
   verify_null(symbol);
   symbol_c *left_type = il_default_variable_type;
   symbol_c *right_type = il_operand_type;
-  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type))
+
+  if      (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type))
     il_default_variable_type = &time_type_name;
-  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_type);
+  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);
   return NULL;
 }
 
@@ -1145,23 +1516,34 @@
   verify_null(symbol);
   symbol_c *left_type = il_default_variable_type;
   symbol_c *right_type = il_operand_type;
-  if (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type))
+
+  if      (is_type(left_type, time_type_name_c)     && is_ANY_NUM_compatible(right_type))
     il_default_variable_type = &time_type_name;
-  else il_default_variable_type = compute_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_type);
+  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);
   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_numeric_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_type); 
+  il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_compatible); 
   return NULL;
 }
 
 // SYM_REF0(GT_operator_c)
 void *visit_expression_type_c::visit(GT_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1169,7 +1551,7 @@
 //SYM_REF0(GE_operator_c)
 void *visit_expression_type_c::visit(GE_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1177,7 +1559,7 @@
 //SYM_REF0(EQ_operator_c)
 void *visit_expression_type_c::visit(EQ_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1185,7 +1567,7 @@
 //SYM_REF0(LT_operator_c)
 void *visit_expression_type_c::visit(LT_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1193,7 +1575,7 @@
 //SYM_REF0(LE_operator_c)
 void *visit_expression_type_c::visit(LE_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1201,7 +1583,7 @@
 //SYM_REF0(NE_operator_c)
 void *visit_expression_type_c::visit(NE_operator_c *symbol) {
   verify_null(symbol);
-  compute_boolean_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   il_default_variable_type = &search_expression_type_c::bool_type_name;
   return NULL;
 }
@@ -1299,28 +1681,28 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible);
 }
 
 
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible);
 }
 
 
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_type);
+  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible);
 }
 
 
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1328,7 +1710,7 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1336,7 +1718,7 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1344,7 +1726,7 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1352,7 +1734,7 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1360,7 +1742,7 @@
 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_boolean_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_type);
+  compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible);
   return &search_expression_type_c::bool_type_name;
 }
 
@@ -1368,55 +1750,147 @@
 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));
-  if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;}
-  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;}
-  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;}
-  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+
+/* 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);
 }
 
 
 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));
-  if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&time_type_name;}
-  if (typeid(*left_type) == typeid(date_type_name_c) && typeid(*right_type) == typeid(date_type_name_c)) {return (void *)&time_type_name;}
-  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&tod_type_name;}
-  if (typeid(*left_type) == typeid(tod_type_name_c) && typeid(*right_type) == typeid(tod_type_name_c)) {return (void *)&time_type_name;}
-  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(time_type_name_c)) {return (void *)&dt_type_name;}
-  if (typeid(*left_type) == typeid(dt_type_name_c) && typeid(*right_type) == typeid(dt_type_name_c)) {return (void *)&time_type_name;}
-  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_type);
+
+/* 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);
 }
 
 
 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 (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type)) {return (void *)&time_type_name;}
-  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_type);
+
+  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);
 }
 
 
 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 (typeid(*left_type) == typeid(time_type_name_c) && is_ANY_NUM_type(right_type)){return (void *)&time_type_name;}
-  return compute_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_type);
+
+  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);
 }
 
 
 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_numeric_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_type);
+  return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_compatible);
 }
 
 
 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_type(left_type))
+  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_type(right_type))
+  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;
@@ -1425,7 +1899,7 @@
 
 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_type(exp_type))
+  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;
@@ -1434,7 +1908,7 @@
 
 void *visit_expression_type_c::visit(not_expression_c *symbol) {
   symbol_c *type = base_type((symbol_c *)symbol->exp->accept(*this));
-  return compute_boolean_expression(type, type, &visit_expression_type_c::is_ANY_BIT_type);
+  return compute_expression(type, type, &visit_expression_type_c::is_ANY_BIT_compatible);
 }
 
 
@@ -1475,7 +1949,7 @@
   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_compatible_type(left_type, right_type))  {
+  if (!is_valid_assignment(left_type, right_type))  {
      STAGE3_ERROR(symbol, symbol, "data type mismatch in assignment statement!\n");
   }
   return NULL;
@@ -1595,6 +2069,7 @@
     } else {
       element_type = base_type(element_type);
       if (NULL != element_type){
+        /* The CASE value is only used for comparison (and not assingment), so we only check for compatibility! */ 
         if (!is_compatible_type(case_expression_type, element_type))
           STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Invalid data type of case list element.");
       }
@@ -1616,21 +2091,24 @@
   if (NULL == var_type) ERROR;
   // ASSIGN
   symbol_c *beg_expr_type = base_type((symbol_c*)symbol->beg_expression->accept(*this));
-  if (NULL != beg_expr_type) { 
-    if(!is_compatible_type(var_type,beg_expr_type)) 
+  if (NULL != beg_expr_type) {
+    /* The BEG value is assigned to the variable, so we check for assignment validity! */ 
+    if(!is_valid_assignment(var_type, beg_expr_type)) 
       STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and initial value.");
   }
   // TO
   symbol_c *end_expr_type = base_type((symbol_c*)symbol->end_expression->accept(*this));
   if (NULL != end_expr_type) { 
-    if(!is_compatible_type(var_type,end_expr_type)) 
+    /* The TO value is only used for comparison, so we only check for compatibility! */ 
+    if(!is_compatible_type(var_type, end_expr_type)) 
       STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and final value.");
   }
   // BY
   if(symbol->by_expression != NULL) {
     symbol_c *by_expr_type = base_type((symbol_c*)symbol->by_expression->accept(*this));
     if (NULL != end_expr_type) {   
-      if(!is_compatible_type(var_type,by_expr_type)) 
+      /* The BY value is used in an expression (add, sub, ...), so we only check for compatibility! */ 
+      if(!is_compatible_type(var_type, by_expr_type)) 
         STAGE3_ERROR(symbol, symbol, "Data type mismatch between control variable and BY value.");
     }
   }
--- a/stage3/visit_expression_type.hh	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage3/visit_expression_type.hh	Wed Mar 30 19:53:32 2011 +0100
@@ -76,20 +76,53 @@
     visit_expression_type_c(symbol_c *search_scope);
     virtual ~visit_expression_type_c(void);
 
+
+    typedef struct {
+      symbol_c *value;
+      symbol_c *type;
+    } value_and_type_t; 
+
     /* A helper function... */
-    bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol);
-    bool is_ANY_MAGNITUDE_type(symbol_c *type_symbol);
-    bool is_ANY_DATE_type(symbol_c *type_symbol);
-    bool is_ANY_STRING_type(symbol_c *type_symbol);
-    bool is_ANY_INT_type(symbol_c *type_symbol);
-    bool is_ANY_REAL_type(symbol_c *type_symbol);
-    bool is_ANY_NUM_type(symbol_c *type_symbol);
-    bool is_ANY_BIT_type(symbol_c *type_symbol);
-    bool is_BOOL_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);
+    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.
@@ -108,7 +141,35 @@
      *  if no common data type is found.
      */
     symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
-    /* Return TRUE if there is a common data type, otherwise return FALSE */
+/* 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);
+
+/* 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);
 
     void compute_input_operatores(symbol_c *symbol, const char *input_operator);
@@ -128,8 +189,9 @@
 
     /* A helper function... */
     typedef bool (visit_expression_type_c::*is_data_type_t)(symbol_c *type_symbol);  /* a pointer to a function! */
-    symbol_c *compute_boolean_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
-    symbol_c *compute_numeric_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
+//    symbol_c *compute_boolean_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
+//    symbol_c *compute_numeric_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
+    symbol_c *compute_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
 
     /* a helper function... */
     symbol_c *base_type(symbol_c *symbol);
--- a/stage4/generate_c/generate_c.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage4/generate_c/generate_c.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -960,6 +960,7 @@
   s4o.print("/* Editing this file is not recommended... */\n");
   s4o.print("/*******************************************/\n\n");
   s4o.print("#include \"iec_std_lib.h\"\n\n");
+  s4o.print("#include \"accessor.h\"\n\n"); 
   
   /* (A) configuration declaration... */
   /* (A.1) configuration name in comment */
--- a/stage4/generate_c/generate_c_base.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage4/generate_c/generate_c_base.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -255,21 +255,34 @@
     void *visit(octal_integer_c *symbol) {s4o.print("0"); return print_striped_token(symbol, 2);}
     void *visit(hex_integer_c *symbol) {s4o.print("0x"); return print_striped_token(symbol, 3);}
 
+    void *visit(neg_real_c *symbol) {
+      s4o.print("-");
+      symbol->exp->accept(*this);
+      return NULL;
+    }
+
+    void *visit(neg_integer_c *symbol) {
+      s4o.print("-");
+      symbol->exp->accept(*this);
+      return NULL;
+    }
+
     void *visit(integer_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
     void *visit(real_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
     void *visit(bit_string_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
-    void *visit(boolean_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
+    void *visit(boolean_literal_c *symbol) {
+      if (NULL != symbol->type)
+        return print_literal(symbol->type, symbol->value);
+      else {
+	bool_type_name_c bool_type;
+	return print_literal(&bool_type, symbol->value);
+      }
+    }
 
     /* helper class for boolean_literal_c */
     void *visit(boolean_true_c *symbol) {s4o.print("TRUE"); return NULL;}
     void *visit(boolean_false_c *symbol) {s4o.print("FALSE"); return NULL;}
 
-    void *visit(neg_literal_c *symbol) {
-      s4o.print("-");
-      symbol->exp->accept(*this);
-      return NULL;
-    }
-
     void *visit(neg_expression_c *symbol) {
       s4o.print("-");
       symbol->exp->accept(*this);
@@ -514,35 +527,49 @@
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
-    void *visit(time_type_name_c *symbol) {s4o.print("TIME"); return NULL;}
-    void *visit(bool_type_name_c *symbol) {s4o.print("BOOL"); return NULL;}
-    void *visit(sint_type_name_c *symbol) {s4o.print("SINT"); return NULL;}
-    void *visit(int_type_name_c *symbol) {s4o.print("INT"); return NULL;}
-    void *visit(dint_type_name_c *symbol) {s4o.print("DINT"); return NULL;}
-    void *visit(lint_type_name_c *symbol) {s4o.print("LINT"); return NULL;}
-    void *visit(usint_type_name_c *symbol) {s4o.print("USINT"); return NULL;}
-    void *visit(uint_type_name_c *symbol) {s4o.print("UINT"); return NULL;}
-    void *visit(udint_type_name_c *symbol) {s4o.print("UDINT"); return NULL;}
-    void *visit(ulint_type_name_c *symbol) {s4o.print("ULINT"); return NULL;}
-    void *visit(real_type_name_c *symbol) {s4o.print("REAL"); return NULL;}
-    void *visit(lreal_type_name_c *symbol) {s4o.print("LREAL"); return NULL;}
-    void *visit(date_type_name_c *symbol) {s4o.print("DATE"); return NULL;}
-    void *visit(tod_type_name_c *symbol) {s4o.print("TOD"); return NULL;}
-    void *visit(dt_type_name_c *symbol) {s4o.print("DT"); return NULL;}
-    void *visit(byte_type_name_c *symbol) {s4o.print("BYTE"); return NULL;}
-    void *visit(word_type_name_c *symbol) {s4o.print("WORD"); return NULL;}
-    void *visit(lword_type_name_c *symbol) {s4o.print("LWORD"); return NULL;}
-    void *visit(dword_type_name_c *symbol) {s4o.print("DWORD"); return NULL;}
-    void *visit(string_type_name_c *symbol) {s4o.print("STRING"); return NULL;}
-    void *visit(wstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;}
-    /******************************************************/
-    /* Extensions to the base standard as defined in      */
-    /* "Safety Software Technical Specification,          */
-    /*  Part 1: Concepts and Function Blocks,             */
-    /*  Version 1.0 – Official Release"                   */
-    /* by PLCopen - Technical Committee 5 - 2006-01-31    */
-    /******************************************************/
-    void *visit(safebool_type_name_c *symbol) {s4o.print("SAFEBOOL"); return NULL;}
+    void *visit(time_type_name_c *symbol)        {s4o.print("TIME");        return NULL;}
+    void *visit(bool_type_name_c *symbol)        {s4o.print("BOOL");        return NULL;}
+    void *visit(sint_type_name_c *symbol)        {s4o.print("SINT");        return NULL;}
+    void *visit(int_type_name_c *symbol)         {s4o.print("INT");         return NULL;}
+    void *visit(dint_type_name_c *symbol)        {s4o.print("DINT");        return NULL;}
+    void *visit(lint_type_name_c *symbol)        {s4o.print("LINT");        return NULL;}
+    void *visit(usint_type_name_c *symbol)       {s4o.print("USINT");       return NULL;}
+    void *visit(uint_type_name_c *symbol)        {s4o.print("UINT");        return NULL;}
+    void *visit(udint_type_name_c *symbol)       {s4o.print("UDINT");       return NULL;}
+    void *visit(ulint_type_name_c *symbol)       {s4o.print("ULINT");       return NULL;}
+    void *visit(real_type_name_c *symbol)        {s4o.print("REAL");        return NULL;}
+    void *visit(lreal_type_name_c *symbol)       {s4o.print("LREAL");       return NULL;}
+    void *visit(date_type_name_c *symbol)        {s4o.print("DATE");        return NULL;}
+    void *visit(tod_type_name_c *symbol)         {s4o.print("TOD");         return NULL;}
+    void *visit(dt_type_name_c *symbol)          {s4o.print("DT");          return NULL;}
+    void *visit(byte_type_name_c *symbol)        {s4o.print("BYTE");        return NULL;}
+    void *visit(word_type_name_c *symbol)        {s4o.print("WORD");        return NULL;}
+    void *visit(lword_type_name_c *symbol)       {s4o.print("LWORD");       return NULL;}
+    void *visit(dword_type_name_c *symbol)       {s4o.print("DWORD");       return NULL;}
+    void *visit(string_type_name_c *symbol)      {s4o.print("STRING");      return NULL;}
+    void *visit(wstring_type_name_c *symbol)     {s4o.print("WSTRING");     return NULL;}
+
+    void *visit(safetime_type_name_c *symbol)    {s4o.print("TIME");    return NULL;}
+    void *visit(safebool_type_name_c *symbol)    {s4o.print("BOOL");    return NULL;}
+    void *visit(safesint_type_name_c *symbol)    {s4o.print("SINT");    return NULL;}
+    void *visit(safeint_type_name_c *symbol)     {s4o.print("INT");     return NULL;}
+    void *visit(safedint_type_name_c *symbol)    {s4o.print("DINT");    return NULL;}
+    void *visit(safelint_type_name_c *symbol)    {s4o.print("LINT");    return NULL;}
+    void *visit(safeusint_type_name_c *symbol)   {s4o.print("USINT");   return NULL;}
+    void *visit(safeuint_type_name_c *symbol)    {s4o.print("UINT");    return NULL;}
+    void *visit(safeudint_type_name_c *symbol)   {s4o.print("UDINT");   return NULL;}
+    void *visit(safeulint_type_name_c *symbol)   {s4o.print("ULINT");   return NULL;}
+    void *visit(safereal_type_name_c *symbol)    {s4o.print("REAL");    return NULL;}
+    void *visit(safelreal_type_name_c *symbol)   {s4o.print("LREAL");   return NULL;}
+    void *visit(safedate_type_name_c *symbol)    {s4o.print("DATE");    return NULL;}
+    void *visit(safetod_type_name_c *symbol)     {s4o.print("TOD");     return NULL;}
+    void *visit(safedt_type_name_c *symbol)      {s4o.print("DT");      return NULL;}
+    void *visit(safebyte_type_name_c *symbol)    {s4o.print("BYTE");    return NULL;}
+    void *visit(safeword_type_name_c *symbol)    {s4o.print("WORD");    return NULL;}
+    void *visit(safelword_type_name_c *symbol)   {s4o.print("LWORD");   return NULL;}
+    void *visit(safedword_type_name_c *symbol)   {s4o.print("DWORD");   return NULL;}
+    void *visit(safestring_type_name_c *symbol)  {s4o.print("STRING");  return NULL;}
+    void *visit(safewstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;}
 
 /********************************/
 /* B.1.3.2 - Generic data types */
--- a/stage4/generate_c/generate_c_st.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage4/generate_c/generate_c_st.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -383,13 +383,13 @@
 }
 
 /* TODO: power expression... */
-void *visit(power_expression_c *symbol) {ERROR; return print_binary_expression(symbol->l_exp, symbol->r_exp, " ** ");}
+void *visit(power_expression_c *symbol) {
+  ERROR; 
+  return print_binary_expression(symbol->l_exp, symbol->r_exp, " ** ");
+}
+
 void *visit(neg_expression_c *symbol) {
-  symbol_c *exp_type = search_expression_type->get_type(symbol->exp);
-  if (search_expression_type->is_integer_type(exp_type) || search_expression_type->is_real_type(exp_type))
-    return print_unary_expression(symbol->exp, " -");
-  ERROR;
-  return NULL;
+  return print_unary_expression(symbol->exp, " -");
 }
 
 void *visit(not_expression_c *symbol) {
--- a/stage4/generate_iec/generate_iec.cc	Thu Aug 27 16:29:23 2009 +0100
+++ b/stage4/generate_iec/generate_iec.cc	Wed Mar 30 19:53:32 2011 +0100
@@ -71,8 +71,10 @@
 }
 
 void *print_literal(symbol_c *type, symbol_c *value) {
-  type->accept(*this);
-  s4o.print("#");
+  if (NULL != type) {
+    type->accept(*this);
+    s4o.print("#");
+  }
   value->accept(*this);
   return NULL;
 }
@@ -168,22 +170,22 @@
 /******************************/
 /* B 1.2.1 - Numeric Literals */
 /******************************/
-void *visit(real_c *symbol) {return print_token(symbol);}
-void *visit(integer_c *symbol) {return print_token(symbol);}
-void *visit(binary_integer_c *symbol) {return print_token(symbol);}
-void *visit(octal_integer_c *symbol) {return print_token(symbol);}
-void *visit(hex_integer_c *symbol) {return print_token(symbol);}
-
-void *visit(integer_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
-void *visit(real_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
+void *visit(real_c *symbol)               {return print_token(symbol);}
+void *visit(neg_real_c *symbol)           {return print_unary_expression(symbol->exp, "-");}
+void *visit(integer_c *symbol)            {return print_token(symbol);}
+void *visit(neg_integer_c *symbol)        {return print_unary_expression(symbol->exp, "-");}
+void *visit(binary_integer_c *symbol)     {return print_token(symbol);}
+void *visit(octal_integer_c *symbol)      {return print_token(symbol);}
+void *visit(hex_integer_c *symbol)        {return print_token(symbol);}
+
+void *visit(integer_literal_c *symbol)    {return print_literal(symbol->type, symbol->value);}
+void *visit(real_literal_c *symbol)       {return print_literal(symbol->type, symbol->value);}
 void *visit(bit_string_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
-void *visit(boolean_literal_c *symbol) {return print_literal(symbol->type, symbol->value);}
-void *visit(neg_literal_c *symbol) {return print_unary_expression(symbol->exp, "-");}
-
+void *visit(boolean_literal_c *symbol)    {return print_literal(symbol->type, symbol->value);}
 
 /* helper class for boolean_literal_c */
-void *visit(boolean_true_c *symbol) {s4o.print(/*"TRUE"*/"1"); return NULL;}
-void *visit(boolean_false_c *symbol) {s4o.print(/*"FALSE"*/"0"); return NULL;}
+void *visit(boolean_true_c *symbol)       {s4o.print(/*"TRUE"*/"1"); return NULL;}
+void *visit(boolean_false_c *symbol)      {s4o.print(/*"FALSE"*/"0"); return NULL;}
 
 /*******************************/
 /* B.1.2.2   Character Strings */
@@ -297,39 +299,50 @@
 /***********************************/
 /* B 1.3.1 - Elementary Data Types */
 /***********************************/
-void *visit(time_type_name_c *symbol) {s4o.print("TIME"); return NULL;}
-void *visit(bool_type_name_c *symbol) {s4o.print("BOOL"); return NULL;}
-/******************************************************/
-/* whether we are suporting safe extensions           */
-/* as defined in PLCopen - Technical Committee 5      */
-/* Safety Software Technical Specification,           */
-/* Part 1: Concepts and Function Blocks,              */
-/* Version 1.0 – Official Release                     */
-/******************************************************/
-void *visit(safebool_type_name_c *symbol) {s4o.print("SAFEBOOL"); return NULL;}
-void *visit(sint_type_name_c *symbol) {s4o.print("SINT"); return NULL;}
-void *visit(int_type_name_c *symbol) {s4o.print("INT"); return NULL;}
-void *visit(dint_type_name_c *symbol) {s4o.print("DINT"); return NULL;}
-void *visit(lint_type_name_c *symbol) {s4o.print("LINT"); return NULL;}
-void *visit(usint_type_name_c *symbol) {s4o.print("USINT"); return NULL;}
-void *visit(uint_type_name_c *symbol) {s4o.print("UINT"); return NULL;}
-void *visit(udint_type_name_c *symbol) {s4o.print("UDINT"); return NULL;}
-void *visit(ulint_type_name_c *symbol) {s4o.print("ULINT"); return NULL;}
-void *visit(real_type_name_c *symbol) {s4o.print("REAL"); return NULL;}
-void *visit(lreal_type_name_c *symbol) {s4o.print("LREAL"); return NULL;}
-void *visit(date_type_name_c *symbol) {s4o.print("DATE"); return NULL;}
-void *visit(tod_type_name_c *symbol) {s4o.print("TOD"); return NULL;}
-void *visit(dt_type_name_c *symbol) {s4o.print("DT"); return NULL;}
-void *visit(byte_type_name_c *symbol) {s4o.print("BYTE"); return NULL;}
-void *visit(word_type_name_c *symbol) {s4o.print("WORD"); return NULL;}
-void *visit(lword_type_name_c *symbol) {s4o.print("LWORD"); return NULL;}
-void *visit(dword_type_name_c *symbol) {s4o.print("DWORD"); return NULL;}
-void *visit(string_type_name_c *symbol) {s4o.print("STRING"); return NULL;}
-void *visit(wstring_type_name_c *symbol) {s4o.print("WSTRING"); return NULL;}
-/*
-void *visit(constant_int_type_name_c *symbol) {return NULL;}
-void *visit(constant_real_type_name_c *symbol) {return NULL;}
-*/
+void *visit(time_type_name_c *symbol)        {s4o.print("TIME");        return NULL;}
+void *visit(bool_type_name_c *symbol)        {s4o.print("BOOL");        return NULL;}
+void *visit(sint_type_name_c *symbol)        {s4o.print("SINT");        return NULL;}
+void *visit(int_type_name_c *symbol)         {s4o.print("INT");         return NULL;}
+void *visit(dint_type_name_c *symbol)        {s4o.print("DINT");        return NULL;}
+void *visit(lint_type_name_c *symbol)        {s4o.print("LINT");        return NULL;}
+void *visit(usint_type_name_c *symbol)       {s4o.print("USINT");       return NULL;}
+void *visit(uint_type_name_c *symbol)        {s4o.print("UINT");        return NULL;}
+void *visit(udint_type_name_c *symbol)       {s4o.print("UDINT");       return NULL;}
+void *visit(ulint_type_name_c *symbol)       {s4o.print("ULINT");       return NULL;}
+void *visit(real_type_name_c *symbol)        {s4o.print("REAL");        return NULL;}
+void *visit(lreal_type_name_c *symbol)       {s4o.print("LREAL");       return NULL;}
+void *visit(date_type_name_c *symbol)        {s4o.print("DATE");        return NULL;}
+void *visit(tod_type_name_c *symbol)         {s4o.print("TOD");         return NULL;}
+void *visit(dt_type_name_c *symbol)          {s4o.print("DT");          return NULL;}
+void *visit(byte_type_name_c *symbol)        {s4o.print("BYTE");        return NULL;}
+void *visit(word_type_name_c *symbol)        {s4o.print("WORD");        return NULL;}
+void *visit(lword_type_name_c *symbol)       {s4o.print("LWORD");       return NULL;}
+void *visit(dword_type_name_c *symbol)       {s4o.print("DWORD");       return NULL;}
+void *visit(string_type_name_c *symbol)      {s4o.print("STRING");      return NULL;}
+void *visit(wstring_type_name_c *symbol)     {s4o.print("WSTRING");     return NULL;}
+
+void *visit(safetime_type_name_c *symbol)    {s4o.print("SAFETIME");    return NULL;}
+void *visit(safebool_type_name_c *symbol)    {s4o.print("SAFEBOOL");    return NULL;}
+void *visit(safesint_type_name_c *symbol)    {s4o.print("SAFESINT");    return NULL;}
+void *visit(safeint_type_name_c *symbol)     {s4o.print("SAFEINT");     return NULL;}
+void *visit(safedint_type_name_c *symbol)    {s4o.print("SAFEDINT");    return NULL;}
+void *visit(safelint_type_name_c *symbol)    {s4o.print("SAFELINT");    return NULL;}
+void *visit(safeusint_type_name_c *symbol)   {s4o.print("SAFEUSINT");   return NULL;}
+void *visit(safeuint_type_name_c *symbol)    {s4o.print("SAFEUINT");    return NULL;}
+void *visit(safeudint_type_name_c *symbol)   {s4o.print("SAFEUDINT");   return NULL;}
+void *visit(safeulint_type_name_c *symbol)   {s4o.print("SAFEULINT");   return NULL;}
+void *visit(safereal_type_name_c *symbol)    {s4o.print("SAFEREAL");    return NULL;}
+void *visit(safelreal_type_name_c *symbol)   {s4o.print("SAFELREAL");   return NULL;}
+void *visit(safedate_type_name_c *symbol)    {s4o.print("SAFEDATE");    return NULL;}
+void *visit(safetod_type_name_c *symbol)     {s4o.print("SAFETOD");     return NULL;}
+void *visit(safedt_type_name_c *symbol)      {s4o.print("SAFEDT");      return NULL;}
+void *visit(safebyte_type_name_c *symbol)    {s4o.print("SAFEBYTE");    return NULL;}
+void *visit(safeword_type_name_c *symbol)    {s4o.print("SAFEWORD");    return NULL;}
+void *visit(safelword_type_name_c *symbol)   {s4o.print("SAFELWORD");   return NULL;}
+void *visit(safedword_type_name_c *symbol)   {s4o.print("SAFEDWORD");   return NULL;}
+void *visit(safestring_type_name_c *symbol)  {s4o.print("SAFESTRING");  return NULL;}
+void *visit(safewstring_type_name_c *symbol) {s4o.print("SAFEWSTRING"); return NULL;}
+
 
 /********************************/
 /* B 1.3.3 - Derived data types */