Re-write of stage3 code (done by Manuele and I), re-write of search_varfb_instance_type_c (done by myself), and several other bug fixes.
--- a/absyntax/absyntax.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.cc Wed Feb 01 19:49:11 2012 +0000
@@ -61,6 +61,7 @@
this->last_line = last_line;
this->last_column = last_column;
this->last_order = last_order;
+ this->datatype = NULL;
}
--- a/absyntax/absyntax.def Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.def Wed Feb 01 19:49:11 2012 +0000
@@ -1047,12 +1047,12 @@
/* nonformal_param_list -> may be NULL ! */
/* NOTE: The parameter 'called_function_declaration' is used to pass data between the stage 3 and stage 4.
* The IEC 61131-3 standard allows for overloaded standard functions. This means that some
- * function calls are not compeletely defined by the name of the function being called,
+ * function calls are not completely defined by the name of the function being called,
* and need to be disambiguated with using the data types of the parameters being passed.
- * Stage 3 does this to verify semantic correctnes.
+ * Stage 3 does this to verify semantic correctness.
* Stage 4 also needs to do this in order to determine which function to call.
* It does not make sense to determine the exact function being called twice (once in stage 3,
- * and again in stage 4), so stage 3 will store this infor in the parameter called_function_declaration
+ * and again in stage 4), so stage 3 will store this info in the parameter called_function_declaration
* for stage 4 to use it later on.
*/
SYM_REF3(function_invocation_c, function_name, formal_param_list, nonformal_param_list, symbol_c *called_function_declaration; int extensible_param_count;)
--- a/absyntax/absyntax.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/absyntax.hh Wed Feb 01 19:49:11 2012 +0000
@@ -47,6 +47,7 @@
#include <stdio.h> // required for NULL
+#include <vector>
/* Forward declaration of the visitor interface
* dclared in the visitor.hh file
@@ -76,6 +77,9 @@
int last_column;
const char *last_file; /* filename referenced by last line/column */
long int last_order; /* relative order in which it is read by lexcial analyser */
+ symbol_c * datatype; /* data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c */
+ std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
+
public:
/* default constructor */
--- a/absyntax/visitor.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax/visitor.cc Wed Feb 01 19:49:11 2012 +0000
@@ -73,13 +73,13 @@
#define SYM_LIST(class_name_c) \
void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-#define SYM_TOKEN(class_name_c) \
- void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF0(class_name_c) \
- void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
-
-#define SYM_REF1(class_name_c, ref1) \
+#define SYM_TOKEN(class_name_c, ...) \
+ void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF0(class_name_c, ...) \
+ void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
+
+#define SYM_REF1(class_name_c, ref1, ...) \
void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
#define SYM_REF2(class_name_c, ref1, ref2, ...) \
@@ -136,13 +136,13 @@
#define SYM_LIST(class_name_c) \
void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
-#define SYM_TOKEN(class_name_c) \
+#define SYM_TOKEN(class_name_c, ...) \
void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
-#define SYM_REF0(class_name_c) \
+#define SYM_REF0(class_name_c, ...) \
void *iterator_visitor_c::visit(class_name_c *symbol) {return NULL;}
-#define SYM_REF1(class_name_c, ref1) \
+#define SYM_REF1(class_name_c, ref1, ...) \
void *iterator_visitor_c::visit(class_name_c *symbol) { \
if (symbol->ref1!=NULL) symbol->ref1->accept(*this); \
return NULL; \
@@ -238,13 +238,13 @@
#define SYM_LIST(class_name_c) \
void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
-#define SYM_TOKEN(class_name_c) \
+#define SYM_TOKEN(class_name_c, ...) \
void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
-#define SYM_REF0(class_name_c) \
+#define SYM_REF0(class_name_c, ...) \
void *search_visitor_c::visit(class_name_c *symbol) {return NULL;}
-#define SYM_REF1(class_name_c, ref1) \
+#define SYM_REF1(class_name_c, ref1, ...) \
void *search_visitor_c::visit(class_name_c *symbol) { \
if (symbol->ref1) return symbol->ref1->accept(*this); \
return NULL; \
--- a/absyntax_utils/get_sizeof_datatype.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/get_sizeof_datatype.cc Wed Feb 01 19:49:11 2012 +0000
@@ -80,6 +80,7 @@
/* tell stdint.h we want the definition of UINT64_MAX */
#define __STDC_LIMIT_MACROS
#include <stdint.h> // get definition of uint64_t and UINT64_MAX
+#include <errno.h>
#define ERROR error_exit(__FILE__,__LINE__)
@@ -158,8 +159,60 @@
/* NOTE: all integer_c and real_c tokens will always be positive (i.e. no leading '-')
* due to the way the source code is parsed by iec.flex.
*/
+
+/*
+ * IEC6113-3 and C++ use IEC 60559 to rappresent floating point data types
+ * REAL => float => single precision 32 bit
+ * LREAL => double => double precision 64 bit
+ * ????? => long double => quadruple precision 128 bit
+ */
void *get_sizeof_datatype_c::visit(real_c *symbol) {
- return _encode_int(32);
+ char *endp;
+ long double ld_test;
+ double d_test;
+ float f_test;
+
+ /* copy the original string, but leave out any underscores... */
+ char *sval, *oval;
+ const char *pval;
+ oval = sval = (char *)malloc(strlen(symbol->value)+1);
+ if (NULL == sval) ERROR;
+
+ for (pval = symbol->value, sval = oval; *pval != '\0'; pval++) {
+ if ('_' != *pval) {*sval = *pval; sval++;}
+ }
+ *sval = '\0';
+
+ sval = oval;
+ if ('\0' == *sval) ERROR;
+
+ /* now do the conversion using the new string... */
+ f_test = strtof(sval, &endp);
+ if (*endp != '\0') ERROR;
+ if (ERANGE != errno) {
+ /* No overflow/underflow! => It fits in a float! */
+ free(oval);
+ return _encode_int(32);
+ }
+
+ d_test = strtod(sval, &endp);
+ if (*endp != '\0') ERROR;
+ if (ERANGE != errno) {
+ /* No overflow/underflow! => It fits in a double! */
+ free(oval);
+ return _encode_int(64);
+ }
+
+ ld_test = strtold(sval, &endp);
+ if (*endp != '\0') ERROR;
+ if (ERANGE != errno) {
+ /* No overflow/underflow! => It fits in a long double! */
+ free(oval);
+ return _encode_int(128);
+ }
+
+ free(oval);
+ return _encode_int(65535); /* a very large number!!! */
}
void *get_sizeof_datatype_c::visit(neg_real_c *symbol) {
@@ -282,7 +335,7 @@
if (('0' != *sval) && ('1' != *sval) && ('_' != *sval))
ERROR;
- if ('_' != *sval) bitsize ++; /* 1 bits per binary digit */
+ if ('_' != *sval) bitsize++; /* 1 bits per binary digit */
}
/* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
--- a/absyntax_utils/search_base_type.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_base_type.cc Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
*
* This program is free software: you can redistribute it and/or modify
@@ -55,16 +55,29 @@
search_base_type_c::search_base_type_c(void) {current_type_name = NULL;}
-void *search_base_type_c::visit(identifier_c *type_name) {
- this->current_type_name = type_name;
- /* look up the type declaration... */
- symbol_c *type_decl = type_symtable.find_value(type_name);
- if (type_decl == type_symtable.end_value())
- /* Type declaration not found!! */
- ERROR;
-
- return type_decl->accept(*this);
-}
+
+
+
+symbol_c *search_base_type_c::get_basetype_decl(symbol_c *symbol) {
+ if (NULL == symbol)
+ return NULL;
+
+ return (symbol_c *)symbol->accept(*this);
+}
+
+symbol_c *search_base_type_c::get_basetype_id (symbol_c *symbol) {
+ if (NULL == symbol)
+ return NULL;
+
+ current_type_name = NULL; /* just to be on the safe side... */
+ symbol->accept(*this);
+ return (symbol_c *)current_type_name;
+}
+
+
+/* Note by MJS: The following two functions definately do not belong in this class!! Maybe create a new utility class?
+ * I will need to clean this up when the opportunity arises!
+ */
bool search_base_type_c::type_is_subrange(symbol_c* type_decl) {
this->is_subrange = false;
@@ -78,6 +91,35 @@
return this->is_enumerated;
}
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+void *search_base_type_c::visit(identifier_c *type_name) {
+ symbol_c *type_decl;
+
+ this->current_type_name = type_name;
+
+ /* look up the type declaration... */
+ type_decl = type_symtable.find_value(type_name);
+ if (type_decl != type_symtable.end_value())
+ return type_decl->accept(*this);
+
+ type_decl = function_block_type_symtable.find_value(type_name);
+ if (type_decl != function_block_type_symtable.end_value())
+ return type_decl->accept(*this);
+
+ /* Type declaration not found!! */
+ ERROR;
+
+ return NULL;
+}
+
+
/*********************/
/* B 1.2 - Constants */
/*********************/
@@ -205,8 +247,7 @@
/* helper symbol for enumerated_specification->enumerated_spec_init */
/* enumerated_value_list ',' enumerated_value */
void *search_base_type_c::visit(enumerated_value_list_c *symbol) {
- if (NULL == this->current_type_name) ERROR;
- return (void *)this->current_type_name;
+ return (void *)symbol;
}
/* enumerated_type_name '#' identifier */
@@ -222,14 +263,16 @@
/* array_specification [ASSIGN array_initialization} */
/* array_initialization may be NULL ! */
void *search_base_type_c::visit(array_spec_init_c *symbol) {
+ /* Note that the 'array_specification' may be either an identifier of a previsously defined array type,
+ * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c,
+ * especially if we are looking for the base class!
+ */
return symbol->array_specification->accept(*this);
}
/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
void *search_base_type_c::visit(array_specification_c *symbol) {
- if (NULL == this->current_type_name)
- this->current_type_name = symbol->non_generic_type_name;
- return symbol->non_generic_type_name->accept(*this);
+ return symbol;
}
/* helper symbol for array_specification */
--- a/absyntax_utils/search_base_type.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_base_type.hh Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
*
* This program is free software: you can redistribute it and/or modify
@@ -60,18 +60,27 @@
search_base_type_c(void);
public:
- void *visit(identifier_c *type_name);
+ symbol_c *get_basetype_decl(symbol_c *symbol);
+ symbol_c *get_basetype_id (symbol_c *symbol);
bool type_is_subrange(symbol_c* type_decl);
bool type_is_enumerated(symbol_c* type_decl);
public:
- /*********************/
- /* B 1.2 - Constants */
- /*********************/
-
- /******************************/
- /* B 1.2.1 - Numeric Literals */
- /******************************/
+ /*************************/
+ /* B.1 - Common elements */
+ /*************************/
+ /*******************************************/
+ /* B 1.1 - Letters, digits and identifiers */
+ /*******************************************/
+ void *visit(identifier_c *type_name);
+
+
+ /*********************/
+ /* B 1.2 - Constants */
+ /*********************/
+ /******************************/
+ /* B 1.2.1 - Numeric Literals */
+ /******************************/
/* Numeric literals without any explicit type cast have unknown data type,
* so we continue considering them as their own basic data types until
* they can be resolved (for example, when using '30+x' where 'x' is a LINT variable, the
--- a/absyntax_utils/search_constant_type.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_constant_type.cc Wed Feb 01 19:49:11 2012 +0000
@@ -155,16 +155,26 @@
time_type_name_c search_constant_type_c::time_type_name;
int_type_name_c search_constant_type_c::int_type_name;
-// safebool_type_name_c search_constant_type_c::safebool_type_name;
- /* The following is required because the expression (TOD_var - TOD_var) will result in a data type
- * (in this case, TIME) that is neither of the expression elements...
- */
safetime_type_name_c search_constant_type_c::safetime_type_name;
safetod_type_name_c search_constant_type_c::safetod_type_name;
safedt_type_name_c search_constant_type_c::safedt_type_name;
+safedate_type_name_c search_constant_type_c::safedate_type_name;
+safereal_type_name_c search_constant_type_c::safereal_type_name;
+safesint_type_name_c search_constant_type_c::safesint_type_name;
+safelint_type_name_c search_constant_type_c::safelint_type_name;
+safedint_type_name_c search_constant_type_c::safedint_type_name;
+safedword_type_name_c search_constant_type_c::safedword_type_name;
+safeudint_type_name_c search_constant_type_c::safeudint_type_name;
+safeword_type_name_c search_constant_type_c::safeword_type_name;
+safewstring_type_name_c search_constant_type_c::safewstring_type_name;
+safestring_type_name_c search_constant_type_c::safestring_type_name;
+safelword_type_name_c search_constant_type_c::safelword_type_name;
+safeuint_type_name_c search_constant_type_c::safeuint_type_name;
+safelreal_type_name_c search_constant_type_c::safelreal_type_name;
+safebyte_type_name_c search_constant_type_c::safebyte_type_name;
+safeusint_type_name_c search_constant_type_c::safeusint_type_name;
+safeulint_type_name_c search_constant_type_c::safeulint_type_name;
+safebool_type_name_c search_constant_type_c::safebool_type_name;
+safeint_type_name_c search_constant_type_c::safeint_type_name;
-
-/* temporarily here until we remove the st_code_gen.c and il_code_gen.c files... */
-/* It should then move to search_expression_type_c */
-integer_c search_constant_type_c::integer("1");
--- a/absyntax_utils/search_constant_type.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_constant_type.hh Wed Feb 01 19:49:11 2012 +0000
@@ -95,8 +95,24 @@
static safetime_type_name_c safetime_type_name;
static safetod_type_name_c safetod_type_name;
static safedt_type_name_c safedt_type_name;
-
-
+ static safedate_type_name_c safedate_type_name;
+ static safereal_type_name_c safereal_type_name;
+ static safesint_type_name_c safesint_type_name;
+ static safelint_type_name_c safelint_type_name;
+ static safedint_type_name_c safedint_type_name;
+ static safedword_type_name_c safedword_type_name;
+ static safeudint_type_name_c safeudint_type_name;
+ static safeword_type_name_c safeword_type_name;
+ static safewstring_type_name_c safewstring_type_name;
+ static safestring_type_name_c safestring_type_name;
+ static safelword_type_name_c safelword_type_name;
+ static safeuint_type_name_c safeuint_type_name;
+ static safelreal_type_name_c safelreal_type_name;
+ static safebyte_type_name_c safebyte_type_name;
+ static safeusint_type_name_c safeusint_type_name;
+ static safeulint_type_name_c safeulint_type_name;
+ static safebool_type_name_c safebool_type_name;
+ static safeint_type_name_c safeint_type_name;
public:
symbol_c *get_type(symbol_c *constant);
@@ -163,5 +179,4 @@
}; // search_constant_type_c
-
#endif /* ifndef _SEARCH_CONSTANT_TYPE_HH */
--- a/absyntax_utils/search_var_instance_decl.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_var_instance_decl.cc Wed Feb 01 19:49:11 2012 +0000
@@ -77,10 +77,14 @@
return (symbol_c *)search_scope->accept(*this);
}
-unsigned int search_var_instance_decl_c::get_vartype(void) {
+unsigned int search_var_instance_decl_c::get_vartype(symbol_c *variable_instance_name) {
+ this->current_vartype = none_vt;
+ this->search_name = variable_instance_name;
+ search_scope->accept(*this);
return current_vartype;
}
+
/***************************/
/* B 0 - Programming Model */
/***************************/
--- a/absyntax_utils/search_var_instance_decl.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_var_instance_decl.hh Wed Feb 01 19:49:11 2012 +0000
@@ -77,7 +77,8 @@
public:
search_var_instance_decl_c(symbol_c *search_scope);
symbol_c *get_decl(symbol_c *variable_instance_name);
- unsigned int get_vartype(void);
+
+ unsigned int get_vartype(symbol_c *variable_instance_name);
public:
--- a/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_varfb_instance_type.cc Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
*
* This program is free software: you can redistribute it and/or modify
@@ -75,225 +75,134 @@
*
* Member functions:
* ================
+ * get_basetype_id() ---> returns 2A (implemented, although currently it is not needed! )
* get_basetype_decl() ---> returns 2B
* get_type_id() ---> returns 1A
*
- * Since we haven't yet needed them, we don't yet implement
- * get_basetype_id() ----> would return 2A
- * get_type_decl() ----> would return 1B
+ * Since we haven't yet needed it, we don't yet implement
+ * get_type_decl() ---> returns 1B
*/
-/*
- * TODO: this code has a memory leak...
- * We call 'new' in several locations, but bever get to 'delete' the object instances...
- */
+
#include "absyntax_utils.hh"
+void search_varfb_instance_type_c::init(void) {
+ this->current_type_id = NULL;
+ this->current_basetype_id = NULL;
+ this->current_basetype_decl = NULL;
+ this->current_field_selector = NULL;
+ this->is_complex = false;
+}
+
+
search_varfb_instance_type_c::search_varfb_instance_type_c(symbol_c *search_scope): search_var_instance_decl(search_scope) {
- this->decompose_var_instance_name = NULL;
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_decl(symbol_c *variable_name) {
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
- this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
- if (NULL == decompose_var_instance_name) ERROR;
-
- /* find the part of the variable name that will appear in the
- * variable declaration, for e.g., in window.point.x, this would be
- * window!
- */
- symbol_c *var_name_part = decompose_var_instance_name->next_part();
- if (NULL == var_name_part) ERROR;
-
- /* Now we try to find the variable instance declaration, to determine its type... */
- symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
- if (NULL == var_decl) ERROR;
-
- /* if it is a struct or function block, we must search the type
- * of the struct or function block member.
- * This is done by this class visiting the var_decl.
- * This class, while visiting, will recursively call
- * decompose_var_instance_name->get_next() when and if required...
- */
- symbol_c *res = (symbol_c *)var_decl->accept(*this);
- /* NOTE: A Null result is not really an internal compiler error, but rather an error in
- * the IEC 61131-3 source code being compiled. This means we cannot just abort the compiler with ERROR.
- * // if (NULL == res) ERROR;
- */
- if (NULL == res) return NULL;
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- /* NOTE: A non-NULL result is not really an internal compiler error, but rather an error in
- * the IEC 61131-3 source code being compiled.
- * (for example, 'int_var.struct_elem' in the source code, when 'int_var' is a simple integer,
- * and not a structure, will result in this result being non-NULL!)
- * This means we cannot just abort the compiler with ERROR.
- * // if (NULL != var_name) ERROR;
- */
- if (NULL != var_name) return NULL;
-
- return res;
+ this->init();
+}
+
+
+/* We expect to be passed a symbolic_variable_c */
+symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
+ this->init();
+ variable_name->accept(*this);
+ return current_type_id;
+}
+
+
+symbol_c *search_varfb_instance_type_c::get_basetype_id(symbol_c *variable_name) {
+ this->init();
+ variable_name->accept(*this);
+ return current_basetype_id;
}
symbol_c *search_varfb_instance_type_c::get_basetype_decl(symbol_c *variable_name) {
- symbol_c *res = get_type_decl(variable_name);
- if (NULL == res) return NULL;
- return (symbol_c *)base_type(res);
+ this->init();
+ variable_name->accept(*this);
+ return current_basetype_decl;
}
+
+
+
unsigned int search_varfb_instance_type_c::get_vartype(symbol_c *variable_name) {
- this->current_structelement_name = NULL;
- this->current_typeid = NULL;
- this->current_basetypeid = NULL;
- this->is_complex = false;
- this->decompose_var_instance_name = new decompose_var_instance_name_c(variable_name);
- if (NULL == decompose_var_instance_name) ERROR;
-
- /* find the part of the variable name that will appear in the
- * variable declaration, for e.g., in window.point.x, this would be
- * window!
- */
- symbol_c *var_name_part = decompose_var_instance_name->next_part();
- if (NULL == var_name_part) ERROR;
-
- /* Now we try to find the variable instance declaration, to determine its type... */
- symbol_c *var_decl = search_var_instance_decl.get_decl(var_name_part);
- if (NULL == var_decl) {
- /* variable instance declaration not found! */
- return 0;
- }
-
- /* if it is a struct or function block, we must search the type
- * of the struct or function block member.
- * This is done by this class visiting the var_decl.
- * This class, while visiting, will recursively call
- * decompose_var_instance_name->get_next() when and if required...
- */
- var_decl->accept(*this);
- unsigned int res = search_var_instance_decl.get_vartype();
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL != var_name) ERROR;
-
- return res;
-}
-
-symbol_c *search_varfb_instance_type_c::get_type_id(symbol_c *variable_name) {
- this->current_typeid = NULL;
- symbol_c *vartype = this->get_type_decl(variable_name);
- if (this->current_typeid != NULL)
- return this->current_typeid;
- else
- return vartype;
-}
+ this->init();
+ return search_var_instance_decl.get_vartype(variable_name);
+}
+
+
bool search_varfb_instance_type_c::type_is_complex(void) {
return this->is_complex;
}
-/* a helper function... */
-void *search_varfb_instance_type_c::visit_list(list_c *list) {
- if (NULL == current_structelement_name) ERROR;
-
- for(int i = 0; i < list->n; i++) {
- void *res = list->elements[i]->accept(*this);
- if (res != NULL)
- return res;
- }
- /* not found! */
- return NULL;
-}
-
-/* a helper function... */
-void *search_varfb_instance_type_c::base_type(symbol_c *symbol) {
- search_base_type_c search_base_type;
- return symbol->accept(search_base_type);
-}
-
-/* We override the base class' visitor to identifier_c.
- * This is so because the base class does not consider a function block
- * to be a type, unlike this class that allows a variable instance
- * of a function block type...
- */
-void *search_varfb_instance_type_c::visit(identifier_c *type_name) {
- /* we only store the new type id if none had been found yet.
- * Since we will recursively carry on looking at the base type
- * to determine the base type declaration and id, we must only set this variable
- * the first time.
- * e.g. TYPE myint1_t : int := 1;
- * myint2_t : int1_t := 2;
- * myint3_t : int2_t := 3;
- * END_TYPE;
- * VAR
- * myint1 : myint1_t;
- * myint2 : myint2_t;
- * myint3 : myint3_t;
- * END_VAR
- *
- * If we ask for typeid of myint3, it must return myint3_t
- * If we ask for basetypeid of myint3, it must return int
- *
- * When determining the data type of myint3, we will recursively go all the way
- * down to int, but we must still only store myint3_t as the base type id.
- */
- if (NULL == this->current_typeid)
- this->current_typeid = type_name;
- this->current_basetypeid = type_name;
-
- /* look up the type declaration... */
- symbol_c *fb_decl = function_block_type_symtable.find_value(type_name);
- if (fb_decl != function_block_type_symtable.end_value())
- /* Type declaration found!! */
- return fb_decl->accept(*this);
-
- /* No. It is not a function block, so we let
- * the base class take care of it...
- */
- return search_base_type_c::visit(type_name);
-}
+
+
+
+
+
+
+
+
/********************************/
/* B 1.3.3 - Derived data types */
/********************************/
-
/* identifier ':' array_spec_init */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * array_type_declaration_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(array_type_declaration_c *symbol) {
- return symbol->array_spec_init->accept(*this);
+ ERROR;
+ return NULL;
}
/* array_specification [ASSIGN array_initialization] */
/* array_initialization may be NULL ! */
+/* NOTE: I don't think this will ever get called, since in the visit method for array_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * array_spec_init_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(array_spec_init_c *symbol) {
- return symbol->array_specification->accept(*this);
+ /* Note that the 'array_specification' may be either an identifier of a previsously defined array type,
+ * or an array_specification_c, so we can not stop here and simply return a array_spec_init_c,
+ * especially if we are looking for the base class!
+ */
+ ERROR;
+ return NULL;
}
/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+/* NOTE: This method will be reached after being called from the
+ * search_varfb_instance_type_c::visit(array_variable_c *symbol)
+ * method, so we must return the data type of the data stored in the array,
+ * and not the data type of the array itself!
+ */
void *search_varfb_instance_type_c::visit(array_specification_c *symbol) {
- this->is_complex = true;
- this->current_typeid = symbol;
- return symbol->non_generic_type_name->accept(*this);
-}
+ /* found the type of the element we were looking for! */
+ current_type_id = symbol->non_generic_type_name;
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ return NULL;
+}
+
/* structure_type_name ':' structure_specification */
/* NOTE: this is only used inside a TYPE ... END_TYPE declaration.
* It is never used directly when declaring a new variable!
*/
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * structure_type_declaration_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(structure_type_declaration_c *symbol) {
- this->is_complex = true;
-
- if (NULL == current_structelement_name) ERROR;
- return symbol->structure_specification->accept(*this);
+ if (NULL == current_field_selector) ERROR;
+ symbol->structure_specification->accept(*this);
+ return NULL;
/* NOTE: structure_specification will point to either a
* initialized_structure_c
* OR A
@@ -304,51 +213,42 @@
/* structure_type_name ASSIGN structure_initialization */
/* structure_initialization may be NULL ! */
// SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
-/* NOTE: only the initialized structure is ever used when declaring a new variable instance */
+/* NOTE: only the initialized structure is never used when declaring a new variable instance */
+/* NOTE: I don't think this will ever get called, since in the visit method for structured_variable_c
+ * we use the basetype_decl for recursively calling this class, and the base type should never be a
+ * initialized_structure_c, but for now, let's leave it in...
+ */
void *search_varfb_instance_type_c::visit(initialized_structure_c *symbol) {
- this->is_complex = true;
- if (NULL != current_structelement_name) ERROR;
-
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... !
- * No need to look any further...
- * Note also that, unlike for the struct types, a function block may
- * not be defined based on another (i.e. no inheritance is allowed),
- * so this function block is already the most base type.
- * We simply return it.
- */
- return (void *)symbol;
- }
-
- /* reset current_type_id because of new structure element part */
- this->current_typeid = NULL;
-
- /* look for the var_name in the structure declaration */
- current_structelement_name = var_name;
-
- /* recursively find out the data type of current_structelement_name... */
- return symbol->structure_type_name->accept(*this);
+ if (NULL != current_field_selector) ERROR;
+
+ /* recursively find out the data type of current_field_selector... */
+ symbol->structure_type_name->accept(*this);
+ return NULL;
}
/* helper symbol for structure_declaration */
/* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */
/* structure_element_declaration_list structure_element_declaration ';' */
void *search_varfb_instance_type_c::visit(structure_element_declaration_list_c *symbol) {
- if (NULL == current_structelement_name) ERROR;
+ if (NULL == current_field_selector) ERROR;
+
/* now search the structure declaration */
- return visit_list(symbol);
+ for(int i = 0; i < symbol->n; i++) {
+ symbol->elements[i]->accept(*this);
+ }
+
+ return NULL;
}
/* structure_element_name ':' spec_init */
void *search_varfb_instance_type_c::visit(structure_element_declaration_c *symbol) {
- if (NULL == current_structelement_name) ERROR;
-
- if (compare_identifiers(symbol->structure_element_name, current_structelement_name) == 0) {
- current_structelement_name = NULL;
+ if (NULL == current_field_selector) ERROR;
+
+ if (compare_identifiers(symbol->structure_element_name, current_field_selector) == 0) {
/* found the type of the element we were looking for! */
- return symbol->spec_init->accept(*this);
+ current_type_id = symbol->spec_init;
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
}
/* Did not find the type of the element we were looking for! */
@@ -364,6 +264,79 @@
void *search_varfb_instance_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+// SYM_REF1(symbolic_variable_c, var_name)
+void *search_varfb_instance_type_c::visit(symbolic_variable_c *symbol) {
+ /* Note: although the method is called get_decl(), it is getting the declaration of the variable, which for us is the type_id of that variable! */
+ current_type_id = search_var_instance_decl.get_decl (symbol->var_name);
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ if (NULL == current_type_id) ERROR; /* why should this be an error? what if the variable has not been declared? */
+
+ return NULL;
+}
+
+/********************************************/
+/* B.1.4.1 Directly Represented Variables */
+/********************************************/
+// SYM_TOKEN(direct_variable_c)
+/* We do not yet handle this. Will we ever need to handle it, as the data type of the direct variable is
+ * directly obtainable from the syntax of the direct variable itself?
+ */
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/* subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+/* NOTE: when passed a array_variable_c, which represents some IEC61131-3 code similar to X[42]
+ * we must return the data type of the value _stored_ in the array.
+ * If you want to get the data type of the array itself (i.e. just the X variable, without the [42])
+ * then this class must be called with the identifier_c 'X'.
+ */
+void *search_varfb_instance_type_c::visit(array_variable_c *symbol) {
+ this->is_complex = true;
+
+ /* determine the data type of the subscripted_variable...
+ * This should be an array_specification_c
+ * ARRAY [xx..yy] OF Stored_Data_Type
+ */
+ symbol->subscripted_variable->accept(*this);
+
+ /* Now we determine the 'Stored_Data_Type', i.e. the data type of the variable stored in the array. */
+ if (NULL != current_basetype_decl) {
+ current_basetype_decl->accept(*this);
+ }
+
+ return NULL;
+}
+
+
+/* record_variable '.' field_selector */
+/* WARNING: input and/or output variables of function blocks
+ * may be accessed as fields of a structured variable!
+ * Code handling a structured_variable_c must take
+ * this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+void *search_varfb_instance_type_c::visit(structured_variable_c *symbol) {
+ this->is_complex = true;
+ symbol->record_variable->accept(*this);
+
+ /* Now we search for the data type of the field... But only if we were able to determine the data type of the variable */
+ if (NULL != current_basetype_decl) {
+ current_field_selector = symbol->field_selector;
+ current_basetype_decl->accept(*this);
+ current_field_selector = NULL;
+ }
+
+ return NULL;
+}
+
+
/**************************************/
/* B.1.5 - Program organization units */
@@ -371,46 +344,18 @@
/*****************************/
/* B 1.5.2 - Function Blocks */
/*****************************/
+
/* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
// SYM_REF4(function_block_declaration_c, fblock_name, var_declarations, fblock_body, unused)
void *search_varfb_instance_type_c::visit(function_block_declaration_c *symbol) {
- /* make sure that we have decomposed all structure elements of the variable name */
- symbol_c *var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... !
- * No need to look any further...
- * Note also that, unlike for the struct types, a function block may
- * not be defined based on another (i.e. no inheritance is allowed),
- * so this function block is already the most base type.
- * We simply return it.
- */
- return (void *)symbol;
- }
-
- /* reset current_type_id because of new structure element part */
- this->current_typeid = NULL;
-
- /* now search the function block declaration for the variable... */
- search_var_instance_decl_c search_decl(symbol);
- symbol_c *var_decl = search_decl.get_decl(var_name);
- if (NULL == var_decl) {
- /* variable instance declaration not found! */
- return NULL;
- }
-#if 0
- /* We have found the declaration.
- * Should we look any further?
- */
- var_name = decompose_var_instance_name->next_part();
- if (NULL == var_name) {
- /* this is it... ! */
- return base_type(var_decl);
- }
-
- current_structelement_name = var_name;
- /* recursively find out the data type of var_name... */
- return symbol->var_declarations->accept(*this);
-#endif
- /* carry on recursively, in case the variable has more elements to be decomposed... */
- return var_decl->accept(*this);
-}
+ if (NULL == current_field_selector) ERROR;
+
+ /* now search the function block declaration for the variable... */
+ /* If not found, these pointers will all be set to NULL!! */
+ search_var_instance_decl_c search_decl(symbol);
+ current_type_id = search_decl.get_decl(current_field_selector);
+ current_basetype_decl = search_base_type.get_basetype_decl(current_type_id);
+ current_basetype_id = search_base_type.get_basetype_id (current_type_id);
+
+ return NULL;
+}
--- a/absyntax_utils/search_varfb_instance_type.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/absyntax_utils/search_varfb_instance_type.hh Wed Feb 01 19:49:11 2012 +0000
@@ -1,7 +1,7 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2003-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
*
* This program is free software: you can redistribute it and/or modify
@@ -77,28 +77,37 @@
*
* Member functions:
* ================
+ * get_basetype_id() ---> returns 2A (implemented, although currently it is not needed! )
* get_basetype_decl() ---> returns 2B
* get_type_id() ---> returns 1A
*
- * Since we haven't yet needed them, we don't yet implement
- * get_basetype_id() ----> would return 2A
- * get_type_decl() ----> would return 1B
+ * Since we haven't yet needed it, we don't yet implement
+ * get_type_decl() ---> returns 1B
*/
-class search_varfb_instance_type_c: public search_base_type_c {
+class search_varfb_instance_type_c : null_visitor_c {
private:
search_var_instance_decl_c search_var_instance_decl;
- decompose_var_instance_name_c *decompose_var_instance_name;
- symbol_c *current_structelement_name;
- symbol_c *current_typeid;
- symbol_c *current_basetypeid;
+ search_base_type_c search_base_type;
+
+// symbol_c *current_type_decl;
+ symbol_c *current_type_id;
+ symbol_c *current_basetype_decl;
+ symbol_c *current_basetype_id;
+
+ symbol_c *current_field_selector;
+
bool is_complex;
+
+ /* sets all the above variables to NULL, or false */
+ void init(void);
public:
search_varfb_instance_type_c(symbol_c *search_scope);
symbol_c *get_basetype_decl(symbol_c *variable_name);
- symbol_c *get_type_decl(symbol_c *variable_name);
+ symbol_c *get_basetype_id (symbol_c *variable_name);
+// symbol_c *get_type_decl(symbol_c *variable_name);
symbol_c *get_type_id(symbol_c *variable_name);
/* NOTE: this function should be remvoed/deleted.
@@ -130,12 +139,11 @@
* to be a type, unlike this class that allows a variable instance
* of a function block type...
*/
- void *visit(identifier_c *type_name);
+// void *visit(identifier_c *type_name);
/********************************/
/* B 1.3.3 - Derived data types */
/********************************/
-
/* identifier ':' array_spec_init */
void *visit(array_type_declaration_c *symbol);
@@ -170,7 +178,20 @@
void *visit(structure_element_initialization_c *symbol); /* should never get called... */
-
+ /*********************/
+ /* B 1.4 - Variables */
+ /*********************/
+ void *visit(symbolic_variable_c *symbol);
+
+ /********************************************/
+ /* B.1.4.1 Directly Represented Variables */
+ /********************************************/
+ /*************************************/
+ /* B 1.4.2 - Multi-element variables */
+ /*************************************/
+ void *visit(array_variable_c *symbol);
+ void *visit(structured_variable_c *symbol);
+
/**************************************/
/* B.1.5 - Program organization units */
/**************************************/
--- a/stage1_2/iec_bison.yy Wed Feb 01 13:01:08 2012 +0000
+++ b/stage1_2/iec_bison.yy Wed Feb 01 19:49:11 2012 +0000
@@ -2791,7 +2791,7 @@
| signed_integer DOTDOT error
{$$ = NULL;
if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no value defined for upper bound in subrange definition.");}
- else {print_err_msg(locf(@3), locl(@3), "invalid value for upper bound in subrange definition."); yyclearin;}
+ else {print_err_msg(locf(@3), locl(@3), "invalid value for lower bound in subrange definition."); yyclearin;}
yyerrok;
}
/* ERROR_CHECK_END */
--- a/stage3/Makefile.am Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/Makefile.am Wed Feb 01 19:49:11 2012 +0000
@@ -4,5 +4,8 @@
libstage3_a_SOURCES = \
stage3.cc \
- visit_expression_type.cc
+ fill_candidate_datatypes.cc \
+ narrow_candidate_datatypes.cc \
+ print_datatypes_error.cc \
+ datatype_functions.cc
--- a/stage3/Makefile.in Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/Makefile.in Wed Feb 01 19:49:11 2012 +0000
@@ -33,7 +33,7 @@
PRE_UNINSTALL = :
POST_UNINSTALL = :
DIST_COMMON = $(srcdir)/../common.mk $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in
+ $(srcdir)/Makefile.in TODO
subdir = stage3
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -71,7 +71,9 @@
libstage3_a_AR = $(AR) $(ARFLAGS)
libstage3_a_LIBADD =
am_libstage3_a_OBJECTS = stage3.$(OBJEXT) \
- visit_expression_type.$(OBJEXT)
+ fill_candidate_datatypes.$(OBJEXT) \
+ narrow_candidate_datatypes.$(OBJEXT) \
+ print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT)
libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -188,7 +190,10 @@
lib_LIBRARIES = libstage3.a
libstage3_a_SOURCES = \
stage3.cc \
- visit_expression_type.cc
+ fill_candidate_datatypes.cc \
+ narrow_candidate_datatypes.cc \
+ print_datatypes_error.cc \
+ datatype_functions.cc
all: all-am
@@ -267,8 +272,11 @@
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/narrow_candidate_datatypes.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print_datatypes_error.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stage3.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visit_expression_type.Po@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/datatype_functions.cc Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,620 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+#include "datatype_functions.hh"
+#include "../absyntax_utils/absyntax_utils.hh"
+
+/*
+ * 2.5.1.5.6 Functions of time data types
+ * Table 30 - page 64
+ */
+
+const struct widen_entry widen_ADD_table[] = {
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetod_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedt_type_name },
+ { NULL, NULL, NULL },
+};
+
+
+const struct widen_entry widen_SUB_table[] = {
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name },
+
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::tod_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safetod_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::dt_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedt_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::tod_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::tod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetod_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::date_type_name, &search_constant_type_c::date_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safedate_type_name, &search_constant_type_c::date_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::date_type_name, &search_constant_type_c::safedate_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safedate_type_name, &search_constant_type_c::safedate_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::dt_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::dt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::safedt_type_name, &search_constant_type_c::safedt_type_name, &search_constant_type_c::safetime_type_name },
+ { NULL, NULL, NULL },
+};
+
+const struct widen_entry widen_MUL_table[] = {
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::time_type_name },
+
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::safetime_type_name },
+
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safelreal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safereal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safesint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeulint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeudint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeuint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeusint_type_name, &search_constant_type_c::safetime_type_name },
+
+ { NULL, NULL, NULL },
+};
+
+const struct widen_entry widen_DIV_table[] = {
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::time_type_name },
+ { &search_constant_type_c::time_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::time_type_name },
+
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::lreal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::real_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::dint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::int_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::sint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::ulint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::udint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::uint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::usint_type_name, &search_constant_type_c::safetime_type_name },
+
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safelreal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safereal_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safedint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safesint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeulint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeudint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeuint_type_name, &search_constant_type_c::safetime_type_name },
+ { &search_constant_type_c::safetime_type_name, &search_constant_type_c::safeusint_type_name, &search_constant_type_c::safetime_type_name },
+
+ { NULL, NULL, NULL },
+};
+
+/* NOTE on data type handling and literals...
+ * ==========================================
+ *
+ * Literals that are explicitly type cast
+ * e.g.: BYTE#42
+ * INT#65
+ * TIME#45h23m
+ * etc...
+ * are NOT considered literals in the following code.
+ * Since they are type cast, and their data type is fixed and well known,
+ * they are treated as a variable of that data type (except when determining lvalues)
+ * In other words, when calling search_constant_type_c on these constants, it returns
+ * a xxxxx_type_name_c, and not one of the xxxx_literal_c !
+ *
+ * When the following code handles a literal, it is really a literal of unknown data type.
+ * e.g. 42, may be considered an int, a byte, a word, etc...
+ *
+ * NOTE: type_symbol == NULL is valid!
+ * This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program.
+ * This will not be of any type, so we always return false.
+ */
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ return is_ANY_MAGNITUDE_type(type_symbol)
+ || is_ANY_BIT_type (type_symbol)
+ || is_ANY_STRING_type (type_symbol)
+ || is_ANY_DATE_type (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ return is_ANY_SAFEMAGNITUDE_type(type_symbol)
+ || is_ANY_SAFEBIT_type (type_symbol)
+ || is_ANY_SAFESTRING_type (type_symbol)
+ || is_ANY_SAFEDATE_type (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ /* NOTE: doing
+ * return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type()
+ * is incorrect, as the literals would never be considered compatible...
+ */
+ return is_ANY_MAGNITUDE_compatible(type_symbol)
+ || is_ANY_BIT_compatible (type_symbol)
+ || is_ANY_STRING_compatible (type_symbol)
+ || is_ANY_DATE_compatible (type_symbol);
+}
+
+
+/* A helper function... */
+bool is_ANY_MAGNITUDE_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
+ return is_ANY_NUM_type(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
+ return is_ANY_SAFENUM_type(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_MAGNITUDE_type (type_symbol)) {return true;}
+ if (is_ANY_SAFEMAGNITUDE_type(type_symbol)) {return true;}
+
+ return is_ANY_NUM_compatible(type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_NUM_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_REAL_type(type_symbol)) {return true;}
+ if (is_ANY_INT_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFENUM_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ return is_ANY_SAFEREAL_type(type_symbol)
+ || is_ANY_SAFEINT_type (type_symbol);
+}
+
+/* A helper function... */
+bool is_ANY_NUM_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_REAL_compatible(type_symbol)) {return true;}
+ if (is_ANY_INT_compatible(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_DATE_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEDATE_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safetod_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safedt_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_DATE_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_DATE_type (type_symbol)) {return true;}
+ if (is_ANY_SAFEDATE_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_STRING_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
+// TODO literal_string ???
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFESTRING_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_STRING_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_STRING_type (type_symbol)) {return true;}
+ if (is_ANY_SAFESTRING_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_INT_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEINT_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safesint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safedint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safelint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeuint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_INT_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_INT_type (type_symbol)) {return true;}
+ if (is_ANY_SAFEINT_type(type_symbol)) {return true;}
+ if (is_literal_integer_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_REAL_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEREAL_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safereal_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_REAL_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_REAL_type (type_symbol)) {return true;}
+ if (is_ANY_SAFEREAL_type(type_symbol)) {return true;}
+ if (is_literal_real_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_BIT_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_SAFEBIT_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safebyte_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safeword_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safedword_type_name_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(safelword_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_BIT_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_ANY_BIT_type (type_symbol)) {return true;}
+ if (is_ANY_SAFEBIT_type(type_symbol)) {return true;}
+ if (is_nonneg_literal_integer_type(type_symbol)) {return true;}
+ if (is_literal_bool_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_BOOL_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_SAFEBOOL_type(symbol_c *type_symbol){
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_ANY_BOOL_compatible(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (is_BOOL_type (type_symbol)) {return true;}
+ if (is_SAFEBOOL_type(type_symbol)) {return true;}
+ if (is_literal_bool_type(type_symbol)) {return true;}
+ return false;
+}
+
+/* A helper function... */
+bool is_literal_integer_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(neg_integer_c)) {return true;}
+ return is_nonneg_literal_integer_type(type_symbol);
+}
+
+
+/* A helper function... */
+bool is_nonneg_literal_integer_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(integer_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(octal_integer_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(hex_integer_c)) {return true;}
+ return false;
+}
+
+
+/* A helper function... */
+bool is_literal_real_type(symbol_c *type_symbol) {
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(real_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;}
+ return false;
+}
+
+
+/* A helper function... */
+bool is_literal_bool_type(symbol_c *type_symbol) {
+ bool_type_name_c bool_t;
+
+ if (type_symbol == NULL) {return false;}
+ if (typeid(*type_symbol) == typeid(boolean_true_c)) {return true;}
+ if (typeid(*type_symbol) == typeid(boolean_false_c)) {return true;}
+ if (is_nonneg_literal_integer_type(type_symbol))
+ if (sizeoftype(&bool_t) >= sizeoftype(type_symbol)) {return true;}
+ return false;
+}
+
+/* Determine the common data type between two data types.
+ * If no common data type found, return NULL.
+ *
+ * If data types are identical, return the first (actually any would do...).
+ * If any of the data types is a literal, we confirm that
+ * the literal uses less bits than the fixed size data type.
+ * e.g. BYTE and 1024 returns NULL
+ * BYTE and 255 returns BYTE
+ *
+ * If two literals, then return the literal that requires more bits...
+ */
+
+symbol_c *common_type(symbol_c *first_type, symbol_c *second_type) {
+ if (first_type == NULL && second_type == NULL) {return NULL;}
+ if (first_type == NULL) {return second_type;}
+ if (second_type == NULL) {return first_type;}
+
+ if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type))
+ {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+ if (is_literal_real_type(first_type) && is_literal_real_type(second_type))
+ {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
+
+ if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
+ {return first_type;}
+
+ /* The following check can only be made after the is_literal_XXXX checks */
+ /* When two literals of the same type, with identical typeid's are checked,
+ * we must return the one that occupies more bits... This is done above.
+ */
+ if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
+
+ /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some
+ * literal bool values are not literal integers...
+ */
+ if (is_BOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;}
+ if (is_BOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;}
+
+ if (is_SAFEBOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;}
+ if (is_SAFEBOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;}
+
+ if (is_SAFEBOOL_type(first_type) && is_BOOL_type(second_type)) {return second_type;}
+ if (is_SAFEBOOL_type(second_type) && is_BOOL_type(first_type)) {return first_type;}
+
+ if (is_ANY_BIT_type(first_type) && is_nonneg_literal_integer_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_BIT_type(second_type) && is_nonneg_literal_integer_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEBIT_type(first_type) && is_nonneg_literal_integer_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_SAFEBIT_type(second_type) && is_nonneg_literal_integer_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEBIT_type(first_type) && is_ANY_BIT_type(second_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+ if (is_ANY_SAFEBIT_type(second_type) && is_ANY_BIT_type(first_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+ if (is_ANY_INT_type(first_type) && is_literal_integer_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_INT_type(second_type) && is_literal_integer_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEINT_type(first_type) && is_literal_integer_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_SAFEINT_type(second_type) && is_literal_integer_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEINT_type(first_type) && is_ANY_INT_type(second_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+ if (is_ANY_SAFEINT_type(second_type) && is_ANY_INT_type(first_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+ if (is_ANY_REAL_type(first_type) && is_literal_real_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_REAL_type(second_type) && is_literal_real_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEREAL_type(first_type) && is_literal_real_type(second_type))
+ {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
+ if (is_ANY_SAFEREAL_type(second_type) && is_literal_real_type(first_type))
+ {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
+
+ if (is_ANY_SAFEREAL_type(first_type) && is_ANY_REAL_type(second_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
+ if (is_ANY_SAFEREAL_type(second_type) && is_ANY_REAL_type(first_type))
+ {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
+
+ /* the Time and Date types... */
+ if (is_type(first_type, safetime_type_name_c) && is_type(second_type, time_type_name_c)) {return second_type;}
+ if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c)) {return first_type;}
+
+ if (is_type(first_type, safedate_type_name_c) && is_type(second_type, date_type_name_c)) {return second_type;}
+ if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c)) {return first_type;}
+
+ if (is_type(first_type, safedt_type_name_c) && is_type(second_type, dt_type_name_c)) {return second_type;}
+ if (is_type(second_type, safedt_type_name_c) && is_type( first_type, dt_type_name_c)) {return first_type;}
+
+ if (is_type(first_type, safetod_type_name_c) && is_type(second_type, tod_type_name_c)) {return second_type;}
+ if (is_type(second_type, safetod_type_name_c) && is_type( first_type, tod_type_name_c)) {return first_type;}
+
+ /* no common type */
+ return NULL;
+}
+
+/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
+ * such as:
+ * var_type value_type
+ * BOOL BYTE#7 -> returns false
+ * INT INT#7 -> returns true
+ * INT 7 -> returns true
+ * REAL 7.89 -> returns true
+ * REAL 7 -> returns true
+ * INT 7.89 -> returns false
+ * SAFEBOOL BOOL#1 -> returns false !!!
+ * etc...
+ *
+ * NOTE: It is assumed that the var_type is the data type of an lvalue
+ */
+bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type) {
+ if (var_type == NULL) {/* STAGE3_ERROR(value_type, value_type, "Var_type == NULL"); */ return false;}
+ if (value_type == NULL) {/* STAGE3_ERROR(var_type, var_type, "Value_type == NULL"); */ return false;}
+
+ symbol_c *common_type_symbol = common_type(var_type, value_type);
+ if (NULL == common_type_symbol)
+ return false;
+ return (typeid(*var_type) == typeid(*common_type_symbol));
+}
+
+
+/* Return TRUE if there is a common data type, otherwise return FALSE
+ * i.e., return TRUE if both data types may be used simultaneously in an expression
+ * such as:
+ * BOOL#0 AND BYTE#7 -> returns false
+ * 0 AND BYTE#7 -> returns true
+ * INT#10 AND INT#7 -> returns true
+ * INT#10 AND 7 -> returns true
+ * REAL#34.3 AND 7.89 -> returns true
+ * REAL#34.3 AND 7 -> returns true
+ * INT#10 AND 7.89 -> returns false
+ * SAFEBOOL#0 AND BOOL#1 -> returns true !!!
+ * etc...
+ */
+bool is_compatible_type(symbol_c *first_type, symbol_c *second_type) {
+ if (first_type == NULL || second_type == NULL) {return false;}
+ return (NULL != common_type(first_type, second_type));
+}
+
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type)
+{
+ if (first_type == NULL || second_type == NULL) {
+ return false;
+ }
+ if (is_ANY_ELEMENTARY_type(first_type)) {
+ if (typeid(*first_type) == typeid(*second_type))
+ return true;
+ } else /* ANY_DERIVED */
+ return (first_type == second_type);
+
+ return false;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/datatype_functions.hh Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,111 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (conti.ma@alice.it)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+#ifndef _HELPER_FUNCTIONS_HH_
+#define _HELPER_FUNCTIONS_HH_
+
+#include "../absyntax/visitor.hh"
+#include <typeinfo>
+
+#define is_type(type_name_symbol, type_name_class) ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class)))
+#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol)
+
+/* Widening Primitive Conversion */
+struct widen_entry {
+ symbol_c *left;
+ symbol_c *right;
+ symbol_c *result;
+};
+/*
+ * 2.5.1.5.6 Functions of time data types
+ * Table 30 - page 64
+ */
+extern const struct widen_entry widen_ADD_table[];
+extern const struct widen_entry widen_SUB_table[];
+extern const struct widen_entry widen_MUL_table[];
+extern const struct widen_entry widen_DIV_table[];
+
+/* A helper function... */
+bool is_ANY_ELEMENTARY_type (symbol_c *type_symbol);
+bool is_ANY_SAFEELEMENTARY_type (symbol_c *type_symbol);
+bool is_ANY_ELEMENTARY_compatible (symbol_c *type_symbol);
+
+bool is_ANY_MAGNITUDE_type (symbol_c *type_symbol);
+bool is_ANY_SAFEMAGNITUDE_type (symbol_c *type_symbol);
+bool is_ANY_MAGNITUDE_compatible (symbol_c *type_symbol);
+
+bool is_ANY_DATE_type (symbol_c *type_symbol);
+bool is_ANY_SAFEDATE_type (symbol_c *type_symbol);
+bool is_ANY_DATE_compatible (symbol_c *type_symbol);
+
+bool is_ANY_STRING_type (symbol_c *type_symbol);
+bool is_ANY_SAFESTRING_type (symbol_c *type_symbol);
+bool is_ANY_STRING_compatible (symbol_c *type_symbol);
+
+bool is_ANY_INT_type (symbol_c *type_symbol);
+bool is_ANY_SAFEINT_type (symbol_c *type_symbol);
+bool is_ANY_INT_compatible (symbol_c *type_symbol);
+
+bool is_ANY_REAL_type (symbol_c *type_symbol);
+bool is_ANY_SAFEREAL_type (symbol_c *type_symbol);
+bool is_ANY_REAL_compatible (symbol_c *type_symbol);
+
+bool is_ANY_NUM_type (symbol_c *type_symbol);
+bool is_ANY_SAFENUM_type (symbol_c *type_symbol);
+bool is_ANY_NUM_compatible (symbol_c *type_symbol);
+
+bool is_ANY_BIT_type (symbol_c *type_symbol);
+bool is_ANY_SAFEBIT_type (symbol_c *type_symbol);
+bool is_ANY_BIT_compatible (symbol_c *type_symbol);
+
+bool is_BOOL_type (symbol_c *type_symbol);
+bool is_SAFEBOOL_type (symbol_c *type_symbol);
+bool is_ANY_BOOL_compatible (symbol_c *type_symbol);
+
+bool is_nonneg_literal_integer_type (symbol_c *type_symbol);
+bool is_literal_integer_type (symbol_c *type_symbol);
+bool is_literal_real_type (symbol_c *type_symbol);
+bool is_literal_bool_type (symbol_c *type_symbol);
+
+/* Determine the common data type between two data types.
+ * If no common data type found, return NULL.
+ *
+ * If data types are identical, return the first (any would do...).
+ * If any of the data types is a literal, we confirm that
+ * the literal uses less bits than the fixed size data type.
+ * e.g. BYTE and 1024 returns NULL
+ * BYTE and 255 returns BYTE
+ *
+ * If two literals, then return the literal that requires more bits...
+ */
+symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
+bool is_valid_assignment(symbol_c *var_type, symbol_c *value_type);
+bool is_compatible_type(symbol_c *first_type, symbol_c *second_type);
+bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
+
+typedef bool (*helper_function_t) (symbol_c *type_symbol); /* a pointer to a function! */
+
+
+
+#endif /* _HELPER_FUNCTIONS_HH_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/fill_candidate_datatypes.cc Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1830 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * Fill candidate list of data types for all symbols
+ */
+
+#include "fill_candidate_datatypes.hh"
+#include "datatype_functions.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+fill_candidate_datatypes_c::fill_candidate_datatypes_c(symbol_c *ignore) {
+
+}
+
+fill_candidate_datatypes_c::~fill_candidate_datatypes_c(void) {
+}
+
+symbol_c *fill_candidate_datatypes_c::widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]) {
+ int k;
+ /* find a widening table entry compatible */
+ for (k = 0; NULL != widen_table[k].left; k++)
+ if ((typeid(*left_type) == typeid(*widen_table[k].left)) && (typeid(*right_type) == typeid(*widen_table[k].right)))
+ return widen_table[k].result;
+ return NULL;
+}
+
+void fill_candidate_datatypes_c::match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
+ symbol_c *call_param_value, *param_type;
+ identifier_c *param_name;
+ function_param_iterator_c fp_iterator(f_decl);
+ function_call_param_iterator_c fcp_iterator(f_call);
+ int extensible_parameter_highest_index = -1;
+ unsigned int i;
+
+ /* reset error counter */
+ if (error_count != NULL) *error_count = 0;
+ /* Iterating through the non-formal parameters of the function call */
+ while((call_param_value = fcp_iterator.next_nf()) != NULL) {
+ /* Obtaining the type of the value being passed in the function call */
+ std::vector <symbol_c *>&call_param_types = call_param_value->candidate_datatypes;
+ /* Iterate to the next parameter of the function being called.
+ * Get the name of that parameter, and ignore if EN or ENO.
+ */
+ do {
+ param_name = fp_iterator.next();
+ /* If there is no other parameter declared, then we are passing too many parameters... */
+ if(param_name == NULL) {
+ (*error_count)++;
+ return;
+ }
+ } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
+
+ /* Get the parameter type */
+ param_type = base_type(fp_iterator.param_type());
+ for(i = 0; i < call_param_types.size(); i++) {
+ /* If the declared parameter and the parameter from the function call do not have the same type */
+ if(is_type_equal(param_type, call_param_types[i])) {
+ break;
+ }
+ }
+ if (i >= call_param_types.size()) (*error_count)++;
+ }
+}
+
+void fill_candidate_datatypes_c::match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
+ symbol_c *call_param_value, *call_param_name, *param_type;
+ symbol_c *verify_duplicate_param;
+ identifier_c *param_name;
+ function_param_iterator_c fp_iterator(f_decl);
+ function_call_param_iterator_c fcp_iterator(f_call);
+ int extensible_parameter_highest_index = -1;
+ identifier_c *extensible_parameter_name;
+ unsigned int i;
+
+ /* reset error counter */
+ if (error_count != NULL) *error_count = 0;
+
+ /* Iterating through the formal parameters of the function call */
+ while((call_param_name = fcp_iterator.next_f()) != NULL) {
+
+ /* Obtaining the value being passed in the function call */
+ call_param_value = fcp_iterator.get_current_value();
+ /* the following should never occur. If it does, then we have a bug in our code... */
+ if (NULL == call_param_value) ERROR;
+
+ /* Checking if there are duplicated parameter values */
+ verify_duplicate_param = fcp_iterator.search_f(call_param_name);
+ if(verify_duplicate_param != call_param_value)
+ (*error_count)++;
+
+ /* Obtaining the type of the value being passed in the function call */
+ std::vector <symbol_c *>&call_param_types = call_param_value->candidate_datatypes;
+
+
+ /* Find the corresponding parameter in function declaration */
+ param_name = fp_iterator.search(call_param_name);
+ if(param_name == NULL) {
+ (*error_count)++;
+ } else {
+ /* Get the parameter type */
+ param_type = base_type(fp_iterator.param_type());
+ for (i = 0; i < call_param_types.size(); i++) {
+ /* If the declared parameter and the parameter from the function call have the same type */
+ if(is_type_equal(param_type, call_param_types[i]))
+ break;
+ }
+ if (i >= call_param_types.size()) (*error_count)++;
+ }
+ }
+
+}
+
+/* a helper function... */
+symbol_c *fill_candidate_datatypes_c::base_type(symbol_c *symbol) {
+ /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+ * in the code.
+ */
+ if (symbol == NULL) return NULL;
+ return (symbol_c *)symbol->accept(search_base_type);
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+void *fill_candidate_datatypes_c::visit(real_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::real_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name);
+ if (debug) std::cout << "ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(integer_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+ if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+ if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(neg_real_c *symbol) {
+ if (sizeoftype(symbol) <= sizeoftype(&search_constant_type_c::real_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::real_type_name);
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lreal_type_name);
+ if (debug) std::cout << "neg ANY_REAL [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(neg_integer_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::int_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::sint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::dint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::lint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+ if (debug) std::cout << "neg ANY_INT [" << symbol->candidate_datatypes.size() << "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(binary_integer_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+ if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+ if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(octal_integer_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+ if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+ if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(hex_integer_c *symbol) {
+ int calc_size;
+
+ calc_size = sizeoftype(symbol);
+ if (calc_size <= sizeoftype(&search_constant_type_c::bool_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::byte_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::word_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::dword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::lword_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+
+ if (calc_size < sizeoftype(&search_constant_type_c::sint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::sint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::int_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::int_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::dint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dint_type_name);
+ if (calc_size < sizeoftype(&search_constant_type_c::lint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::usint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::usint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::uint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::uint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::udint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::udint_type_name);
+ if (calc_size <= sizeoftype(&search_constant_type_c::ulint_type_name))
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::ulint_type_name);
+ if (debug) std::cout << "ANY_INT [" << symbol->candidate_datatypes.size()<< "]" << std::endl;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(integer_literal_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type);
+ if (debug) std::cout << "INT_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(real_literal_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type);
+ if (debug) std::cout << "REAL_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(bit_string_literal_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_literal_c *symbol) {
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_true_c *symbol) {
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(boolean_false_c *symbol) {
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+/*******************************/
+/* B.1.2.2 Character Strings */
+/*******************************/
+void *fill_candidate_datatypes_c::visit(double_byte_character_string_c *symbol) {
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::wstring_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(single_byte_character_string_c *symbol) {
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::string_type_name);
+ return NULL;
+}
+
+/***************************/
+/* B 1.2.3 - Time Literals */
+/***************************/
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+void *fill_candidate_datatypes_c::visit(duration_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type_name);
+ if (debug) std::cout << "TIME_LITERAL [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+void *fill_candidate_datatypes_c::visit(time_of_day_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(date_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(date_and_time_c *symbol) {
+ symbol->candidate_datatypes.push_back(symbol->type_name);
+ return NULL;
+}
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+/* signed_integer DOTDOT signed_integer */
+// SYM_REF2(subrange_c, lower_limit, upper_limit)
+void *fill_candidate_datatypes_c::visit(subrange_c *symbol) {
+ symbol->lower_limit->accept(*this);
+ symbol->upper_limit->accept(*this);
+
+ for (unsigned int u = 0; u < symbol->upper_limit->candidate_datatypes.size(); u++) {
+ for(unsigned int l = 0; l < symbol->lower_limit->candidate_datatypes.size(); l++) {
+ if (is_type_equal(symbol->upper_limit->candidate_datatypes[u], symbol->lower_limit->candidate_datatypes[l]))
+ symbol->candidate_datatypes.push_back(symbol->lower_limit->candidate_datatypes[l]);
+ }
+ }
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(data_type_declaration_c *symbol) {
+ // TODO !!!
+ /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) {
+ symbol_c *enumerated_type;
+
+ if (NULL != symbol->type)
+ enumerated_type = symbol->type;
+ else {
+ enumerated_type = enumerated_value_symtable.find_value(symbol->value);
+ if (enumerated_type == enumerated_value_symtable.end_value())
+ enumerated_type = NULL;
+ }
+ enumerated_type = base_type(enumerated_type);
+ if (NULL != enumerated_type)
+ symbol->candidate_datatypes.push_back(enumerated_type);
+
+ if (debug) std::cout << "ENUMERATE [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *fill_candidate_datatypes_c::visit(symbolic_variable_c *symbol) {
+ symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+ if (NULL != result)
+ symbol->candidate_datatypes.push_back(result);
+ if (debug) std::cout << "VAR [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+void *fill_candidate_datatypes_c::visit(direct_variable_c *symbol) {
+ /* Comment added by mario:
+ * The following code is safe, actually, as the lexical parser guarantees the correct IEC61131-3 syntax was used.
+ */
+ /* However, we should probably add an assertion in case we later change the lexical parser! */
+ /* if (symbol->value == NULL) ERROR;
+ * if (symbol->value[0] == '\0') ERROR;
+ * if (symbol->value[1] == '\0') ERROR;
+ */
+ switch (symbol->value[2]) {
+ case 'X': // bit - 1 bit
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ break;
+
+ case 'B': // byte - 8 bits
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::byte_type_name);
+ break;
+
+ case 'W': // word - 16 bits
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::word_type_name);
+ break;
+
+ case 'D': // double word - 32 bits
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::dword_type_name);
+ break;
+
+ case 'L': // long word - 64 bits
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::lword_type_name);
+ break;
+
+ default: // if none of the above, then the empty string was used <=> boolean
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ break;
+ }
+ return NULL;
+}
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/* subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *fill_candidate_datatypes_c::visit(array_variable_c *symbol) {
+ /* get the declaration of the data type __stored__ in the array... */
+ /* if we were to want the data type of the array itself, then we should call_param_name
+ * search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable)
+ */
+ symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+ if (NULL != result) symbol->candidate_datatypes.push_back(result);
+
+ /* recursively call the subscript list, so we can check the data types of the expressions used for the subscripts */
+if (debug) std::cout << "ARRAY_VAR XXX\n";
+ symbol->subscript_list->accept(*this);
+if (debug) std::cout << "ARRAY_VAR YYY\n";
+
+ if (debug) std::cout << "ARRAY_VAR [" << symbol->candidate_datatypes.size() << "]\n";
+ return NULL;
+}
+
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */
+#if 0
+void *fill_candidate_datatypes_c::visit(subscript_list_c *symbol) {
+}
+#endif
+
+
+/* record_variable '.' field_selector */
+/* WARNING: input and/or output variables of function blocks
+ * may be accessed as fields of a structured variable!
+ * Code handling a structured_variable_c must take
+ * this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+/* NOTE: We do not need to recursively determine the data types of each field_selector, as the search_varfb_instance_type
+ * will do that for us. So we determine the candidate datatypes only for the full structured_variable.
+ */
+void *fill_candidate_datatypes_c::visit(structured_variable_c *symbol) {
+ symbol_c *result = search_varfb_instance_type->get_basetype_decl(symbol);
+ if (NULL != result) symbol->candidate_datatypes.push_back(result);
+ return NULL;
+}
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *fill_candidate_datatypes_c::visit(function_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ symbol->var_declarations_list->accept(*this);
+ if (debug) printf("Filling candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+ il_parenthesis_level = 0;
+ prev_il_instruction = NULL;
+ symbol->function_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *fill_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ symbol->var_declarations->accept(*this);
+ if (debug) printf("Filling candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+ il_parenthesis_level = 0;
+ prev_il_instruction = NULL;
+ symbol->fblock_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *fill_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ symbol->var_declarations->accept(*this);
+ if (debug) printf("Filling candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+ il_parenthesis_level = 0;
+ prev_il_instruction = NULL;
+ symbol->function_block_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *fill_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
+#if 0
+ // TODO !!!
+ /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+ return NULL;
+}
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *fill_candidate_datatypes_c::visit(il_simple_operation_c *symbol) {
+ /* determine the data type of the operand */
+ if (NULL != symbol->il_operand) {
+ symbol->il_operand->accept(*this);
+ }
+ /* recursive call to fill the candidate data types list */
+ il_operand = symbol->il_operand;
+ symbol->il_simple_operator->accept(*this);
+ il_operand = NULL;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_function_call_c *symbol) {
+}
+
+/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
+ * and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
+ *
+ * Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c
+ * in the 3 new classes fill/narrow/print candidate datatype
+ */
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *fill_candidate_datatypes_c::visit(il_expression_c *symbol) {
+ if (NULL != symbol->il_operand)
+ symbol->il_operand->accept(*this);
+
+ il_parenthesis_level++;
+
+ /* Note that prev_il_instruction will actually be used to get the current value store in the il_default_variable */
+ /* If a symbol->il_operand is provided, then that will be the result before executing the simple_instr_list.
+ * If this symbol is NULL, then the current result is also NULL, which is correct for what we want to do!
+ */
+ symbol_c *prev_il_instruction_backup = prev_il_instruction;
+ prev_il_instruction = symbol->il_operand;
+
+ if(symbol->simple_instr_list != NULL) {
+ symbol->simple_instr_list->accept(*this);
+ }
+
+ il_parenthesis_level--;
+ if (il_parenthesis_level < 0) ERROR;
+
+ /* Now check the if the data type semantics of operation are correct, */
+ il_operand = prev_il_instruction;
+ prev_il_instruction = prev_il_instruction_backup;
+ symbol->il_expr_operator->accept(*this);
+ il_operand = NULL;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_jump_operation_c *symbol) {
+ /* recursive call to fill the candidate data types list */
+ il_operand = NULL;
+ symbol->il_jump_operator->accept(*this);
+ il_operand = NULL;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
+}
+
+void *fill_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
+
+}
+
+/*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+*/
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *fill_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+ for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
+ symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "LD [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+ for(unsigned int i = 0; i < il_operand->candidate_datatypes.size(); i++) {
+ if (is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(il_operand->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "LDN [" << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ST_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "ST [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(STN_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BIT_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "STN [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(S_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "S [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(R_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "R [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(S1_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "S1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(R1_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type,operand_type) && is_ANY_BOOL_compatible(il_operand->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "R1 [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CLK_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CU_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CD_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(PV_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(IN_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(PT_operator_c *symbol) {
+ /* MANU:
+ * How it works? I(MANU) don't know this function
+ */
+
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(AND_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(OR_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(XOR_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ANDN_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ORN_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(XORN_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_BIT_compatible(operand_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ADD_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_NUM_compatible(prev_instruction_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ else {
+ symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_ADD_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+
+ }
+ }
+ }
+ if (debug) std::cout << "ADD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(SUB_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_NUM_compatible(prev_instruction_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ else {
+ symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_SUB_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+ }
+ }
+ if (debug) std::cout << "SUB [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(MUL_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_NUM_compatible(prev_instruction_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ else {
+ symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_MUL_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+ }
+ }
+ if (debug) std::cout << "MUL [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(DIV_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_NUM_compatible(prev_instruction_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ else {
+ symbol_c *result = widening_conversion(prev_instruction_type, operand_type, widen_DIV_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+ }
+ }
+ if (debug) std::cout << "DIV [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(MOD_operator_c *symbol) {
+ symbol_c *prev_instruction_type, *operand_type;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ prev_instruction_type = prev_il_instruction->candidate_datatypes[i];
+ operand_type = il_operand->candidate_datatypes[j];
+ if (is_type_equal(prev_instruction_type, operand_type) &&
+ is_ANY_INT_compatible(prev_instruction_type))
+ symbol->candidate_datatypes.push_back(prev_instruction_type);
+ }
+ }
+ if (debug) std::cout << "MOD [" << prev_il_instruction->candidate_datatypes.size() << "," << il_operand->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(GT_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(GE_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(EQ_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LT_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(LE_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(NE_operator_c *symbol) {
+ bool found = false;
+
+ if (NULL == prev_il_instruction) return NULL;
+ for(unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < il_operand->candidate_datatypes.size(); j++) {
+ if (is_type_equal(prev_il_instruction->candidate_datatypes[i], il_operand->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(prev_il_instruction->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ /* does not need to be bool type !! */
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "CAL [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CALC_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "CALC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "CALCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RET_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ /* does not need to be bool type !! */
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "RET [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RETC_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "RETC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "RETCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMP_operator_c *symbol) {
+ if (NULL == prev_il_instruction) return NULL;
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ /* does not need to be bool type !! */
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "JMP [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMPC_operator_c *symbol) {
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "JMPC [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {
+ for (unsigned int i = 0; i < prev_il_instruction->candidate_datatypes.size(); i++) {
+ if (is_type(prev_il_instruction->candidate_datatypes[i], bool_type_name_c))
+ symbol->candidate_datatypes.push_back(prev_il_instruction->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "JMPCN [" << prev_il_instruction->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ prev_il_instruction = symbol;
+ return NULL;
+}
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *fill_candidate_datatypes_c::visit(or_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+ }
+ }
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(xor_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+ }
+ }
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(and_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_BIT_compatible(symbol->l_exp->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+ }
+ }
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(equ_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found) symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(notequ_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(lt_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(gt_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(le_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(ge_expression_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ bool found = false;
+
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for (unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_compatible(symbol->l_exp->candidate_datatypes[i])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (found)
+ symbol->candidate_datatypes.push_back(&search_constant_type_c::bool_type_name);
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(add_expression_c *symbol) {
+ /* The following code is correct when handling the addition of 2 symbolic_variables
+ * In this case, adding two variables (e.g. USINT_var1 + USINT_var2) will always yield
+ * the same data type, even if the result of the adition could not fit inside the same
+ * data type (due to overflowing)
+ *
+ * However, when adding two literals (e.g. USINT#42 + USINT#3)
+ * we should be able to detect overflows of the result, and therefore not consider
+ * that the result may be of type USINT.
+ * Currently we do not yet detect these overflows, and allow handling the sum of two USINTs
+ * as always resulting in an USINT, even in the following expression
+ * (USINT#65535 + USINT#2).
+ *
+ * In the future we can add some code to reduce
+ * all the expressions that are based on literals into the resulting literal
+ * value (maybe some visitor class that will run before or after data type
+ * checking). Since this class will have to be very careful to make sure it implements the same mathematical
+ * details (e.g. how to round and truncate numbers) as defined in IEC 61131-3, we will leave this to the future.
+ * Also, the question will arise if we should also replace calls to standard
+ * functions if the input parameters are all literals (e.g. ADD(42, 42)). This
+ * means this class will be more difficult than it appears at first.
+ */
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ else {
+ symbol_c *result = widening_conversion(left_type, right_type, widen_ADD_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+ }
+ }
+ if (debug) std::cout << "+ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(sub_expression_c *symbol) {
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ else {
+ symbol_c *result = widening_conversion(left_type, right_type, widen_SUB_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+ }
+ }
+ if (debug) std::cout << "- [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(mul_expression_c *symbol) {
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type) && is_ANY_NUM_compatible(left_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ else {
+ symbol_c *result = widening_conversion(left_type, right_type, widen_MUL_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+
+ }
+ }
+ if (debug) std::cout << "* [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+
+ return NULL;
+}
+
+void *fill_candidate_datatypes_c::visit(div_expression_c *symbol) {
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type) && is_ANY_NUM_type(left_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ else {
+ symbol_c *result = widening_conversion(left_type, right_type, widen_DIV_table);
+ if (result)
+ symbol->candidate_datatypes.push_back(result);
+ }
+
+ }
+ }
+ if (debug) std::cout << "/ [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(mod_expression_c *symbol) {
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type) && is_ANY_INT_compatible(left_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ }
+ }
+ if (debug) std::cout << "mod [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(power_expression_c *symbol) {
+ symbol_c *left_type, *right_type;
+ bool check_ok;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ check_ok = false;
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ if (is_ANY_REAL_compatible(left_type)) {
+ check_ok = true;
+ break;
+ }
+ }
+ if (! check_ok) return NULL;
+ check_ok = false;
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_ANY_NUM_compatible(right_type)) {
+ check_ok = true;
+ break;
+ }
+ }
+ if (! check_ok) return NULL;
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ symbol->candidate_datatypes.push_back(symbol->l_exp->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "** [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(neg_expression_c *symbol) {
+ symbol->exp->accept(*this);
+ for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+ if (is_ANY_MAGNITUDE_compatible(symbol->exp->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "neg [" << symbol->exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(not_expression_c *symbol) {
+ symbol->exp->accept(*this);
+ for (unsigned int i = 0; i < symbol->exp->candidate_datatypes.size(); i++) {
+ if (is_ANY_BIT_compatible(symbol->exp->candidate_datatypes[i]))
+ symbol->candidate_datatypes.push_back(symbol->exp->candidate_datatypes[i]);
+ }
+ if (debug) std::cout << "not [" << symbol->exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(function_invocation_c *symbol) {
+ function_declaration_c *f_decl;
+ list_c *parameter_list;
+ list_c *parameter_candidate_datatypes;
+ symbol_c *parameter_type;
+ int error_count;
+ function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+ function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+
+ if (NULL != symbol->formal_param_list)
+ parameter_list = (list_c *)symbol->formal_param_list;
+ else if (NULL != symbol->nonformal_param_list)
+ parameter_list = (list_c *)symbol->nonformal_param_list;
+ else ERROR;
+ if (debug) std::cout << "function()\n";
+ parameter_list->accept(*this);
+ for(; lower != upper; lower++) {
+ f_decl = function_symtable.get_value(lower);
+ error_count = 0;
+ /* Check if function declaration in symbol_table is compatible with parameters */
+ if (NULL != symbol->nonformal_param_list)
+ /* nonformal parameter function call */
+ match_nonformal_call(symbol, f_decl, &error_count);
+ else
+ /* formal parameter function call */
+ match_formal_call (symbol, f_decl, &error_count);
+ if (0 == error_count) {
+ /* Add basetype matching function only if not present */
+ unsigned int k;
+ parameter_type = base_type(f_decl->type_name);
+ for(k = 0; k < symbol->candidate_datatypes.size(); k++) {
+ if (is_type_equal(parameter_type, symbol->candidate_datatypes[k]))
+ break;
+ }
+ if (k >= symbol->candidate_datatypes.size())
+ symbol->candidate_datatypes.push_back(parameter_type);
+ }
+ }
+ if (debug) std::cout << "end_function() [" << symbol->candidate_datatypes.size() << "] result.\n";
+ return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+// SYM_LIST(statement_list_c)
+/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
+ * We do not need to do anything here...
+ */
+// void *fill_candidate_datatypes_c::visit(statement_list_c *symbol)
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *fill_candidate_datatypes_c::visit(assignment_statement_c *symbol) {
+ symbol_c *left_type, *right_type;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ for (unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ left_type = symbol->l_exp->candidate_datatypes[i];
+ right_type = symbol->r_exp->candidate_datatypes[j];
+ if (is_type_equal(left_type, right_type))
+ symbol->candidate_datatypes.push_back(left_type);
+ }
+ }
+ if (debug) std::cout << ":= [" << symbol->l_exp->candidate_datatypes.size() << "," << symbol->r_exp->candidate_datatypes.size() << "] ==> " << symbol->candidate_datatypes.size() << " result.\n";
+ return NULL;
+}
+
+
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+void *fill_candidate_datatypes_c::visit(if_statement_c *symbol) {
+ /* MANU:
+ * IF statement accept only BOOL type. We intersect with BOOL type to validate current if condition
+ * Example:
+ * IF 1 THEN ---> ok
+ * IF 5 THEN ---> not ok
+ * IF 1 OR 1 THEN ---> ok
+ * IF 1 OR 5 THEN ---> not ok
+ * IF SHL() THEN ---> ok if shl return BOOL
+ * IF INT_TO_REAL() ---> not ok
+ */
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ if (NULL != symbol->elseif_statement_list)
+ symbol->elseif_statement_list->accept(*this);
+ if (NULL != symbol->else_statement_list)
+ symbol->else_statement_list->accept(*this);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(elseif_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
+void *fill_candidate_datatypes_c::visit(case_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if (NULL != symbol->case_element_list)
+ symbol->case_element_list->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+/* helper symbol for case_statement */
+// SYM_LIST(case_element_list_c)
+/* NOTE: visitor method for case_element_list_c is not required since we inherit from iterator_visitor_c */
+
+/* case_list ':' statement_list */
+// SYM_REF2(case_element_c, case_list, statement_list)
+/* NOTE: visitor method for case_element_c is not required since we inherit from iterator_visitor_c */
+
+// SYM_LIST(case_list_c)
+/* NOTE: visitor method for case_list_c is not required since we inherit from iterator_visitor_c */
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+void *fill_candidate_datatypes_c::visit(for_statement_c *symbol) {
+ symbol->control_variable->accept(*this);
+ symbol->beg_expression->accept(*this);
+ symbol->end_expression->accept(*this);
+ if (NULL != symbol->by_expression)
+ symbol->by_expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(while_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(repeat_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/fill_candidate_datatypes.hh Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,320 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class fill_candidate_datatypes_c: public iterator_visitor_c {
+
+ private:
+ search_varfb_instance_type_c *search_varfb_instance_type;
+ search_base_type_c search_base_type;
+ /* When calling a function block, we must first find it's type,
+ * by searching through the declarations of the variables currently
+ * in scope.
+ * This class does just that...
+ * A new object instance is instantiated whenever we start checking semantics
+ * for a function block type declaration, or a program declaration.
+ * This object instance will then later be called while the
+ * function block's or the program's body is being handled.
+ *
+ * Note that functions cannot contain calls to function blocks,
+ * so we do not create an object instance when handling
+ * a function declaration.
+ */
+ // search_var_instance_decl_c *search_var_instance_decl;
+
+ /* This variable was created to pass information from
+ * fill_candidate_datatypes_c::visit(case_statement_c *symbol) function to
+ * fill_candidate_datatypes_c::visit(case_list_c *symbol) function.
+ */
+ symbol_c *case_expression_type;
+
+ /* In IL code, once we find a type mismatch error, it is best to
+ * ignore any further errors until the end of the logical operation,
+ * i.e. until the next LD.
+ * However, we cannot clear the il_error flag on all LD operations,
+ * as these may also be used within parenthesis. LD operations
+ * within parenthesis may not clear the error flag.
+ * We therefore need a counter to know how deep inside a parenthesis
+ * structure we are.
+ */
+ int il_parenthesis_level;
+ bool error_found;
+
+ /* the current data type of the data stored in the IL stack, i.e. the default variable */
+ symbol_c *prev_il_instruction;
+ /* the current IL operand being analyzed - its symbol and its data type */
+ symbol_c *il_operand_type;
+ symbol_c *il_operand;
+ symbol_c *widening_conversion(symbol_c *left_type, symbol_c *right_type, const struct widen_entry widen_table[]);
+
+ public:
+ fill_candidate_datatypes_c(symbol_c *ignore);
+ virtual ~fill_candidate_datatypes_c(void);
+
+ /* Match a function declaration with a function call through their parameters.*/
+ void match_nonformal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
+ void match_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
+
+ void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
+ void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);
+
+ /* a helper function... */
+ symbol_c *base_type(symbol_c *symbol);
+
+ /*********************/
+ /* B 1.2 - Constants */
+ /*********************/
+ /******************************/
+ /* B 1.2.1 - Numeric Literals */
+ /******************************/
+ void *visit(real_c *symbol);
+ void *visit(integer_c *symbol);
+ void *visit(neg_real_c *symbol);
+ void *visit(neg_integer_c *symbol);
+ void *visit(binary_integer_c *symbol);
+ void *visit(octal_integer_c *symbol);
+ void *visit(hex_integer_c *symbol);
+ void *visit(integer_literal_c *symbol);
+ void *visit(real_literal_c *symbol);
+ void *visit(bit_string_literal_c *symbol);
+ void *visit(boolean_literal_c *symbol);
+ void *visit(boolean_true_c *symbol);
+ void *visit(boolean_false_c *symbol);
+
+ /*******************************/
+ /* B.1.2.2 Character Strings */
+ /*******************************/
+ void *visit(double_byte_character_string_c *symbol);
+ void *visit(single_byte_character_string_c *symbol);
+
+ /***************************/
+ /* B 1.2.3 - Time Literals */
+ /***************************/
+ /************************/
+ /* B 1.2.3.1 - Duration */
+ /************************/
+ void *visit(duration_c *symbol);
+
+ /************************************/
+ /* B 1.2.3.2 - Time of day and Date */
+ /************************************/
+ void *visit(time_of_day_c *symbol);
+ void *visit(date_c *symbol);
+ void *visit(date_and_time_c *symbol);
+
+
+ /**********************/
+ /* B 1.3 - Data types */
+ /**********************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ void *visit(subrange_c *symbol);
+ void *visit(data_type_declaration_c *symbol);
+ void *visit(enumerated_value_c *symbol);
+
+ /*********************/
+ /* B 1.4 - Variables */
+ /*********************/
+ void *visit(symbolic_variable_c *symbol);
+
+ /********************************************/
+ /* B 1.4.1 - Directly Represented Variables */
+ /********************************************/
+ void *visit(direct_variable_c *symbol);
+
+ /*************************************/
+ /* B 1.4.2 - Multi-element variables */
+ /*************************************/
+ void *visit(array_variable_c *symbol);
+ void *visit(structured_variable_c *symbol);
+
+ /**************************************/
+ /* B 1.5 - Program organization units */
+ /**************************************/
+ /***********************/
+ /* B 1.5.1 - Functions */
+ /***********************/
+ void *visit(function_declaration_c *symbol);
+
+ /*****************************/
+ /* B 1.5.2 - Function blocks */
+ /*****************************/
+ void *visit(function_block_declaration_c *symbol);
+
+ /**********************/
+ /* B 1.5.3 - Programs */
+ /**********************/
+ void *visit(program_declaration_c *symbol);
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ void *visit(configuration_declaration_c *symbol);
+
+ /****************************************/
+ /* B.2 - Language IL (Instruction List) */
+ /****************************************/
+ /***********************************/
+ /* B 2.1 Instructions and Operands */
+ /***********************************/
+ // void *visit(instruction_list_c *symbol);
+ void *visit(il_simple_operation_c *symbol);
+ void *visit(il_function_call_c *symbol);
+ void *visit(il_expression_c *symbol);
+ void *visit(il_jump_operation_c *symbol);
+ void *visit(il_fb_call_c *symbol);
+ void *visit(il_formal_funct_call_c *symbol);
+ /*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+ */
+
+ /*******************/
+ /* B 2.2 Operators */
+ /*******************/
+ void *visit(LD_operator_c *symbol);
+ void *visit(LDN_operator_c *symbol);
+ void *visit(ST_operator_c *symbol);
+ void *visit(STN_operator_c *symbol);
+ void *visit(NOT_operator_c *symbol);
+ void *visit(S_operator_c *symbol);
+ void *visit(R_operator_c *symbol);
+ void *visit(S1_operator_c *symbol);
+ void *visit(R1_operator_c *symbol);
+ void *visit(CLK_operator_c *symbol);
+ void *visit(CU_operator_c *symbol);
+ void *visit(CD_operator_c *symbol);
+ void *visit(PV_operator_c *symbol);
+ void *visit(IN_operator_c *symbol);
+ void *visit(PT_operator_c *symbol);
+ void *visit(AND_operator_c *symbol);
+ void *visit(OR_operator_c *symbol);
+ void *visit(XOR_operator_c *symbol);
+ void *visit(ANDN_operator_c *symbol);
+ void *visit(ORN_operator_c *symbol);
+ void *visit(XORN_operator_c *symbol);
+ void *visit(ADD_operator_c *symbol);
+ void *visit(SUB_operator_c *symbol);
+ void *visit(MUL_operator_c *symbol);
+ void *visit(DIV_operator_c *symbol);
+ void *visit(MOD_operator_c *symbol);
+ void *visit(GT_operator_c *symbol);
+ void *visit(GE_operator_c *symbol);
+ void *visit(EQ_operator_c *symbol);
+ void *visit(LT_operator_c *symbol);
+ void *visit(LE_operator_c *symbol);
+ void *visit(NE_operator_c *symbol);
+ void *visit(CAL_operator_c *symbol);
+ void *visit(CALC_operator_c *symbol);
+ void *visit(CALCN_operator_c *symbol);
+ void *visit(RET_operator_c *symbol);
+ void *visit(RETC_operator_c *symbol);
+ void *visit(RETCN_operator_c *symbol);
+ void *visit(JMP_operator_c *symbol);
+ void *visit(JMPC_operator_c *symbol);
+ void *visit(JMPCN_operator_c *symbol);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, variable_name);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+ /***************************************/
+ /* B.3 - Language ST (Structured Text) */
+ /***************************************/
+ /***********************/
+ /* B 3.1 - Expressions */
+ /***********************/
+ void *visit(or_expression_c *symbol);
+ void *visit(xor_expression_c *symbol);
+ void *visit(and_expression_c *symbol);
+ void *visit(equ_expression_c *symbol);
+ void *visit(notequ_expression_c *symbol);
+ void *visit(lt_expression_c *symbol);
+ void *visit(gt_expression_c *symbol);
+ void *visit(le_expression_c *symbol);
+ void *visit(ge_expression_c *symbol);
+ void *visit(add_expression_c *symbol);
+ void *visit(sub_expression_c *symbol);
+ void *visit(mul_expression_c *symbol);
+ void *visit(div_expression_c *symbol);
+ void *visit(mod_expression_c *symbol);
+ void *visit(power_expression_c *symbol);
+ void *visit(neg_expression_c *symbol);
+ void *visit(not_expression_c *symbol);
+ void *visit(function_invocation_c *symbol);
+
+ /*********************************/
+ /* B 3.2.1 Assignment Statements */
+ /*********************************/
+ void *visit(assignment_statement_c *symbol);
+
+ /*****************************************/
+ /* B 3.2.2 Subprogram Control Statements */
+ /*****************************************/
+ //void *visit(fb_invocation_c *symbol);
+
+ /********************************/
+ /* B 3.2.3 Selection Statements */
+ /********************************/
+ void *visit(if_statement_c *symbol);
+ // void *visit(elseif_statement_list_c *symbol);
+ void *visit(elseif_statement_c *symbol);
+ void *visit(case_statement_c *symbol);
+
+ /********************************/
+ /* B 3.2.4 Iteration Statements */
+ /********************************/
+ void *visit(for_statement_c *symbol);
+ void *visit(while_statement_c *symbol);
+ void *visit(repeat_statement_c *symbol);
+
+}; // fill_candidate_datatypes_c
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/narrow_candidate_datatypes.cc Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1194 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * Narrow class select and store a data type from candidate data types list for all symbols
+ */
+
+#include "narrow_candidate_datatypes.hh"
+#include "datatype_functions.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+narrow_candidate_datatypes_c::narrow_candidate_datatypes_c(symbol_c *ignore) {
+}
+
+narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) {
+}
+
+bool narrow_candidate_datatypes_c::is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]) {
+ for (int k = 0; NULL != widen_table[k].left; k++) {
+ if ((typeid(*left_type) == typeid(*widen_table[k].left))
+ && (typeid(*right_type) == typeid(*widen_table[k].right))
+ && (typeid(*result_type) == typeid(*widen_table[k].result))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void narrow_candidate_datatypes_c::narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl) {
+ symbol_c *call_param_value, *param_type;
+ identifier_c *param_name;
+ function_param_iterator_c fp_iterator(f_decl);
+ function_call_param_iterator_c fcp_iterator(f_call);
+ int extensible_parameter_highest_index = -1;
+ identifier_c *extensible_parameter_name;
+ unsigned int i;
+
+
+ /* Iterating through the non-formal parameters of the function call */
+ while((call_param_value = fcp_iterator.next_nf()) != NULL) {
+ /* Obtaining the type of the value being passed in the function call */
+ /* Iterate to the next parameter of the function being called.
+ * Get the name of that parameter, and ignore if EN or ENO.
+ */
+ do {
+ param_name = fp_iterator.next();
+ /* If there is no other parameter declared, then we are passing too many parameters... */
+ if(param_name == NULL) {
+ return;
+ }
+ } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
+
+ /* Get the parameter type */
+ call_param_value->datatype = base_type(fp_iterator.param_type());
+ call_param_value->accept(*this);
+ if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+ extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+ extensible_parameter_name = param_name;
+ }
+ }
+ int extensible_param_count = -1;
+ if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+ extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+ function_invocation_c *function_invocation = dynamic_cast<function_invocation_c *>(f_call);
+ if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count;
+
+}
+
+void narrow_candidate_datatypes_c::narrow_formal_call(symbol_c *f_call, symbol_c *f_decl) {
+ symbol_c *call_param_value, *call_param_name, *param_type;
+ symbol_c *verify_duplicate_param;
+ identifier_c *param_name;
+ function_param_iterator_c fp_iterator(f_decl);
+ function_call_param_iterator_c fcp_iterator(f_call);
+ int extensible_parameter_highest_index = -1;
+ identifier_c *extensible_parameter_name;
+ unsigned int i;
+
+
+ /* Iterating through the formal parameters of the function call */
+ while((call_param_name = fcp_iterator.next_f()) != NULL) {
+
+ /* Obtaining the value being passed in the function call */
+ call_param_value = fcp_iterator.get_current_value();
+ /* the following should never occur. If it does, then we have a bug in our code... */
+ if (NULL == call_param_value) ERROR;
+
+ /* Find the corresponding parameter in function declaration */
+ param_name = fp_iterator.search(call_param_name);
+
+ /* Get the parameter type */
+ call_param_name->datatype = base_type(fp_iterator.param_type());
+ call_param_name->accept(*this);
+ /* the first parameter (il_def_variable) is correct */
+ if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
+ extensible_parameter_highest_index = fp_iterator.extensible_param_index();
+ }
+ }
+ /* The function call may not have any errors! */
+ /* In the case of a call to an extensible function, we store the highest index
+ * of the extensible parameters this particular call uses, in the symbol_c object
+ * of the function call itself!
+ * In calls to non-extensible functions, this value will be set to -1.
+ * This information is later used in stage4 to correctly generate the
+ * output code.
+ */
+ int extensible_param_count = -1;
+ if (extensible_parameter_highest_index >=0) /* if call to extensible function */
+ extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
+ function_invocation_c *function_invocation = dynamic_cast<function_invocation_c *>(f_call);
+ if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count;
+}
+
+/* a helper function... */
+symbol_c *narrow_candidate_datatypes_c::base_type(symbol_c *symbol) {
+ /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+ * in the code.
+ */
+ return NULL;
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+/* signed_integer DOTDOT signed_integer */
+// SYM_REF2(subrange_c, lower_limit, upper_limit)
+void *narrow_candidate_datatypes_c::visit(subrange_c *symbol) {
+ symbol->lower_limit->datatype = symbol->datatype;
+ symbol->lower_limit->accept(*this);
+ symbol->upper_limit->datatype = symbol->datatype;
+ symbol->upper_limit->accept(*this);
+ return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/* subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *narrow_candidate_datatypes_c::visit(array_variable_c *symbol) {
+ /* we need to check the data types of the expressions used for the subscripts... */
+ symbol->subscript_list->accept(*this);
+ return NULL;
+}
+
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+void *narrow_candidate_datatypes_c::visit(subscript_list_c *symbol) {
+ for (int i = 0; i < symbol->n; i++) {
+ for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) {
+ if (is_ANY_INT_type(symbol->elements[i]->candidate_datatypes[k]))
+ symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k];
+ }
+ symbol->elements[i]->accept(*this);
+ }
+ return NULL;
+}
+
+
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *narrow_candidate_datatypes_c::visit(function_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+ prev_il_instruction = NULL;
+ symbol->function_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+ prev_il_instruction = NULL;
+ symbol->fblock_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/********************/
+/* B 1.5.3 Programs */
+/********************/
+void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+ prev_il_instruction = NULL;
+ symbol->function_block_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *narrow_candidate_datatypes_c::visit(configuration_declaration_c *symbol) {
+#if 0
+ // TODO !!!
+ /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+ return NULL;
+}
+
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *narrow_candidate_datatypes_c::visit(il_simple_operation_c *symbol) {
+ il_operand = symbol->il_operand;
+ if (NULL != symbol->il_operand) {
+ symbol->il_operand->accept(*this);
+ }
+ /* recursive call to see whether data types are compatible */
+ symbol->il_simple_operator->accept(*this);
+ il_operand = NULL;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_function_call_c *symbol) {
+ return NULL;
+}
+
+/* MJS: Manuele, could you please not delete the following 2 lines of comments. They help me understand where this class is used
+ * and when it is created by bison - syntax parse, and how it can show up in the abstract syntax tree.
+ *
+ * Actually, it could be helpful if we could have all the similar comments already present in visit_expression_type_c
+ * in the 3 new classes fill/narrow/print candidate datatype
+ */
+/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
+// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
+void *narrow_candidate_datatypes_c::visit(il_expression_c *symbol) {
+/* MJS: TODO... */
+return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_fb_call_c *symbol) {
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(il_formal_funct_call_c *symbol) {
+ return NULL;
+}
+
+
+/*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+ */
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *narrow_candidate_datatypes_c::visit(LD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LDN_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ST_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(STN_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(NOT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(S_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(R_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(S1_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(R1_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CLK_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CU_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(PV_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(IN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(PT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(AND_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(OR_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(XOR_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ANDN_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ORN_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(XORN_operator_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ il_operand->datatype = symbol->datatype;
+ il_operand->accept(*this);
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(ADD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(SUB_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(MUL_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(DIV_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(MOD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(GT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(GE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(EQ_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(LE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(NE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CAL_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CALC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(CALCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RET_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RETC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(RETCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMP_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMPC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(JMPCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *narrow_candidate_datatypes_c::visit(or_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(xor_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (is_type_equal(symbol->l_exp->candidate_datatypes[i], symbol->r_exp->candidate_datatypes[j])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(and_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(equ_expression_c *symbol) {
+ /* Here symbol->datatype has already assigned to BOOL
+ * In conditional symbols like =, <>, =<, <, >, >= we have to set
+ * l_exp and r_exp expression matched with compatible type.
+ * Example:
+ * INT#14 = INT#81
+ * equ_expression_c symbol->datatype = BOOL from top visit
+ * symbol->l_exp->datatype => INT
+ * symbol->r_exp->datatype => INT
+ */
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+ /*
+ * We do not need to check whether the type is an ANY_ELEMENTARY here.
+ * That was already done in fill_candidate_datatypes_c.
+ */
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(notequ_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(lt_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(gt_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(le_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(ge_expression_c *symbol) {
+ symbol_c * selected_type = NULL;
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ if (typeid(*symbol->l_exp->candidate_datatypes[i]) == typeid(*symbol->r_exp->candidate_datatypes[j])
+ && is_ANY_ELEMENTARY_type(symbol->l_exp->candidate_datatypes[i])) {
+ selected_type = symbol->l_exp->candidate_datatypes[i];
+ break;
+ }
+ }
+ }
+
+ if (NULL != selected_type) {
+ symbol->l_exp->datatype = selected_type;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = selected_type;
+ symbol->r_exp->accept(*this);
+ }
+ else
+ ERROR;
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(add_expression_c *symbol) {
+ int count = 0;
+
+ if (is_ANY_NUM_compatible(symbol->datatype)) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->r_exp->datatype = symbol->datatype;
+ count++;
+ } else {
+ /* TIME data type */
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ /* test widening compatibility */
+ if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+ symbol->r_exp->candidate_datatypes[j],
+ symbol->datatype, widen_ADD_table)) {
+ symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+ symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+ count ++;
+ }
+ }
+ }
+ }
+ if (count > 1)
+ ERROR;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+
+
+void *narrow_candidate_datatypes_c::visit(sub_expression_c *symbol) {
+ int count = 0;
+
+ if (is_ANY_NUM_compatible(symbol->datatype)) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->r_exp->datatype = symbol->datatype;
+ count++;
+ } else {
+ /* TIME data type */
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ /* test widening compatibility */
+ if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+ symbol->r_exp->candidate_datatypes[j],
+ symbol->datatype, widen_SUB_table)) {
+ symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+ symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+ count ++;
+ }
+ }
+ }
+ }
+ if (count > 1)
+ ERROR;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(mul_expression_c *symbol) {
+ int count = 0;
+
+ if (is_ANY_NUM_compatible(symbol->datatype)) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->r_exp->datatype = symbol->datatype;
+ count++;
+ } else {
+ /* TIME data type */
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ /* test widening compatibility */
+ if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+ symbol->r_exp->candidate_datatypes[j],
+ symbol->datatype, widen_MUL_table)) {
+ symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+ symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+ count ++;
+ }
+ }
+ }
+ }
+ if (count > 1)
+ ERROR;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(div_expression_c *symbol) {
+ int count = 0;
+
+ if (is_ANY_NUM_compatible(symbol->datatype)) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->r_exp->datatype = symbol->datatype;
+ count++;
+ } else {
+ /* TIME data type */
+ for(unsigned int i = 0; i < symbol->l_exp->candidate_datatypes.size(); i++) {
+ for(unsigned int j = 0; j < symbol->r_exp->candidate_datatypes.size(); j++) {
+ /* test widening compatibility */
+ if (is_widening_compatible(symbol->l_exp->candidate_datatypes[i],
+ symbol->r_exp->candidate_datatypes[j],
+ symbol->datatype, widen_DIV_table)) {
+ symbol->l_exp->datatype = symbol->l_exp->candidate_datatypes[i];
+ symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[j];
+ count ++;
+ }
+ }
+ }
+ }
+ if (count > 1)
+ ERROR;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(mod_expression_c *symbol) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = symbol->datatype;
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(power_expression_c *symbol) {
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->l_exp->accept(*this);
+ if (! symbol->r_exp->candidate_datatypes.size()){
+ symbol->r_exp->datatype = symbol->r_exp->candidate_datatypes[0];
+ symbol->r_exp->accept(*this);
+ }
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(neg_expression_c *symbol) {
+ symbol->exp->datatype = symbol->datatype;
+ symbol->exp->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(not_expression_c *symbol) {
+ symbol->exp->datatype = symbol->datatype;
+ symbol->exp->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(function_invocation_c *symbol) {
+ function_declaration_c *f_decl;
+ list_c *parameter_list;
+ list_c *parameter_candidate_datatypes;
+ function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
+ function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
+
+ if (NULL != symbol->formal_param_list)
+ parameter_list = (list_c *)symbol->formal_param_list;
+ else if (NULL != symbol->nonformal_param_list)
+ parameter_list = (list_c *)symbol->nonformal_param_list;
+ else ERROR;
+ for(; lower != upper; lower++) {
+ f_decl = function_symtable.get_value(lower);
+ symbol_c * return_type = base_type(f_decl->type_name);
+ if (return_type && typeid(*symbol->datatype) != typeid(*return_type))
+ continue;
+ /* We set which function declaration it'll use in STAGE4 */
+ symbol->called_function_declaration = f_decl;
+ /* Check if function declaration in symbol_table is compatible with parameters */
+ if (NULL != symbol->nonformal_param_list)
+ /* nonformal parameter function call */
+ narrow_nonformal_call(symbol, f_decl);
+ else
+ /* formal parameter function call */
+ narrow_formal_call (symbol, f_decl);
+ break;
+ }
+
+ return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+
+void *narrow_candidate_datatypes_c::visit(assignment_statement_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1)
+ return NULL;
+ symbol->datatype = symbol->candidate_datatypes[0];
+ symbol->l_exp->datatype = symbol->datatype;
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->datatype = symbol->datatype;
+ symbol->r_exp->accept(*this);
+ return NULL;
+}
+
+
+/*****************************************/
+/* B 3.2.2 Subprogram Control Statements */
+/*****************************************/
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+
+void *narrow_candidate_datatypes_c::visit(if_statement_c *symbol) {
+ for(unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+ if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c))
+ symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+ }
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ if (NULL != symbol->elseif_statement_list)
+ symbol->elseif_statement_list->accept(*this);
+ if (NULL != symbol->else_statement_list)
+ symbol->else_statement_list->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(elseif_statement_c *symbol) {
+ for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+ if (is_type(symbol->expression->candidate_datatypes[i], bool_type_name_c))
+ symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+ }
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+/* CASE expression OF case_element_list ELSE statement_list END_CASE */
+// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
+void *narrow_candidate_datatypes_c::visit(case_statement_c *symbol) {
+ for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+ if ((is_ANY_INT_type(symbol->expression->candidate_datatypes[i]))
+ || (search_base_type.type_is_enumerated(symbol->expression->candidate_datatypes[i])))
+ symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+ }
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ if (NULL != symbol->case_element_list) {
+ symbol->case_element_list->datatype = symbol->expression->datatype;
+ symbol->case_element_list->accept(*this);
+ }
+ return NULL;
+}
+
+/* helper symbol for case_statement */
+// SYM_LIST(case_element_list_c)
+void *narrow_candidate_datatypes_c::visit(case_element_list_c *symbol) {
+ for (int i = 0; i < symbol->n; i++) {
+ symbol->elements[i]->datatype = symbol->datatype;
+ symbol->elements[i]->accept(*this);
+ }
+ return NULL;
+}
+
+/* case_list ':' statement_list */
+// SYM_REF2(case_element_c, case_list, statement_list)
+void *narrow_candidate_datatypes_c::visit(case_element_c *symbol) {
+ symbol->case_list->datatype = symbol->datatype;
+ symbol->case_list->accept(*this);
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+// SYM_LIST(case_list_c)
+void *narrow_candidate_datatypes_c::visit(case_list_c *symbol) {
+ for (int i = 0; i < symbol->n; i++) {
+ for (unsigned int k = 0; k < symbol->elements[i]->candidate_datatypes.size(); k++) {
+ if (is_type_equal(symbol->datatype, symbol->elements[i]->candidate_datatypes[k]))
+ symbol->elements[i]->datatype = symbol->elements[i]->candidate_datatypes[k];
+ }
+ /* NOTE: this may be an integer, a subrange_c, or a enumerated value! */
+ symbol->elements[i]->accept(*this);
+ }
+ return NULL;
+}
+
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+void *narrow_candidate_datatypes_c::visit(for_statement_c *symbol) {
+ /* Control variable */
+ for(unsigned int i = 0; i < symbol->control_variable->candidate_datatypes.size(); i++) {
+ if (is_ANY_INT_type(symbol->control_variable->candidate_datatypes[i])) {
+ symbol->control_variable->datatype = symbol->control_variable->candidate_datatypes[i];
+ }
+ }
+ symbol->control_variable->accept(*this);
+ /* BEG expression */
+ for(unsigned int i = 0; i < symbol->beg_expression->candidate_datatypes.size(); i++) {
+ if (is_type_equal(symbol->control_variable->datatype,symbol->beg_expression->candidate_datatypes[i]) &&
+ is_ANY_INT_type(symbol->beg_expression->candidate_datatypes[i])) {
+ symbol->beg_expression->datatype = symbol->beg_expression->candidate_datatypes[i];
+ }
+ }
+ symbol->beg_expression->accept(*this);
+ /* END expression */
+ for(unsigned int i = 0; i < symbol->end_expression->candidate_datatypes.size(); i++) {
+ if (is_type_equal(symbol->control_variable->datatype,symbol->end_expression->candidate_datatypes[i]) &&
+ is_ANY_INT_type(symbol->end_expression->candidate_datatypes[i])) {
+ symbol->end_expression->datatype = symbol->end_expression->candidate_datatypes[i];
+ }
+ }
+ symbol->end_expression->accept(*this);
+ /* BY expression */
+ if (NULL != symbol->by_expression) {
+ for(unsigned int i = 0; i < symbol->by_expression->candidate_datatypes.size(); i++) {
+ if (is_type_equal(symbol->control_variable->datatype,symbol->by_expression->candidate_datatypes[i]) &&
+ is_ANY_INT_type(symbol->by_expression->candidate_datatypes[i])) {
+ symbol->by_expression->datatype = symbol->by_expression->candidate_datatypes[i];
+ }
+ }
+ symbol->by_expression->accept(*this);
+ }
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(while_statement_c *symbol) {
+ for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+ if(is_BOOL_type(symbol->expression->candidate_datatypes[i]))
+ symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+ }
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+void *narrow_candidate_datatypes_c::visit(repeat_statement_c *symbol) {
+ for (unsigned int i = 0; i < symbol->expression->candidate_datatypes.size(); i++) {
+ if(is_BOOL_type(symbol->expression->candidate_datatypes[i]))
+ symbol->expression->datatype = symbol->expression->candidate_datatypes[i];
+ }
+ symbol->expression->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/narrow_candidate_datatypes.hh Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,224 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class narrow_candidate_datatypes_c: public iterator_visitor_c {
+
+ private:
+ symbol_c * selected_datatype;
+ search_varfb_instance_type_c *search_varfb_instance_type;
+ search_base_type_c search_base_type;
+ symbol_c *case_expression_type;
+ symbol_c *il_operand;
+ symbol_c *prev_il_instruction;
+
+ bool is_widening_compatible(symbol_c *left_type, symbol_c *right_type, symbol_c *result_type, const struct widen_entry widen_table[]);
+
+ public:
+ narrow_candidate_datatypes_c(symbol_c *ignore);
+ virtual ~narrow_candidate_datatypes_c(void);
+ void narrow_nonformal_call(symbol_c *f_call, symbol_c *f_decl);
+ void narrow_formal_call(symbol_c *f_call, symbol_c *f_decl);
+
+ symbol_c *base_type(symbol_c *symbol);
+
+ /**********************/
+ /* B 1.3 - Data types */
+ /**********************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ void *visit(subrange_c *symbol);
+
+ /*********************/
+ /* B 1.4 - Variables */
+ /*********************/
+ /********************************************/
+ /* B 1.4.1 - Directly Represented Variables */
+ /********************************************/
+ /*************************************/
+ /* B 1.4.2 - Multi-element variables */
+ /*************************************/
+ void *visit(array_variable_c *symbol);
+ void *visit(subscript_list_c *symbol);
+
+ /**************************************/
+ /* B 1.5 - Program organization units */
+ /**************************************/
+ /***********************/
+ /* B 1.5.1 - Functions */
+ /***********************/
+ void *visit(function_declaration_c *symbol);
+
+ /*****************************/
+ /* B 1.5.2 - Function blocks */
+ /*****************************/
+ void *visit(function_block_declaration_c *symbol);
+
+ /**********************/
+ /* B 1.5.3 - Programs */
+ /**********************/
+ void *visit(program_declaration_c *symbol);
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ void *visit(configuration_declaration_c *symbol);
+ /****************************************/
+ /* B.2 - Language IL (Instruction List) */
+ /****************************************/
+ /***********************************/
+ /* B 2.1 Instructions and Operands */
+ /***********************************/
+ // void *visit(instruction_list_c *symbol);
+ void *visit(il_simple_operation_c *symbol);
+ void *visit(il_function_call_c *symbol);
+ void *visit(il_expression_c *symbol);
+ void *visit(il_fb_call_c *symbol);
+ void *visit(il_formal_funct_call_c *symbol);
+ /*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+ */
+
+ /*******************/
+ /* B 2.2 Operators */
+ /*******************/
+ void *visit(LD_operator_c *symbol);
+ void *visit(LDN_operator_c *symbol);
+ void *visit(ST_operator_c *symbol);
+ void *visit(STN_operator_c *symbol);
+ void *visit(NOT_operator_c *symbol);
+ void *visit(S_operator_c *symbol);
+ void *visit(R_operator_c *symbol);
+ void *visit(S1_operator_c *symbol);
+ void *visit(R1_operator_c *symbol);
+ void *visit(CLK_operator_c *symbol);
+ void *visit(CU_operator_c *symbol);
+ void *visit(CD_operator_c *symbol);
+ void *visit(PV_operator_c *symbol);
+ void *visit(IN_operator_c *symbol);
+ void *visit(PT_operator_c *symbol);
+ void *visit(AND_operator_c *symbol);
+ void *visit(OR_operator_c *symbol);
+ void *visit(XOR_operator_c *symbol);
+ void *visit(ANDN_operator_c *symbol);
+ void *visit(ORN_operator_c *symbol);
+ void *visit(XORN_operator_c *symbol);
+ void *visit(ADD_operator_c *symbol);
+ void *visit(SUB_operator_c *symbol);
+ void *visit(MUL_operator_c *symbol);
+ void *visit(DIV_operator_c *symbol);
+ void *visit(MOD_operator_c *symbol);
+ void *visit(GT_operator_c *symbol);
+ void *visit(GE_operator_c *symbol);
+ void *visit(EQ_operator_c *symbol);
+ void *visit(LT_operator_c *symbol);
+ void *visit(LE_operator_c *symbol);
+ void *visit(NE_operator_c *symbol);
+ void *visit(CAL_operator_c *symbol);
+ void *visit(CALC_operator_c *symbol);
+ void *visit(CALCN_operator_c *symbol);
+ void *visit(RET_operator_c *symbol);
+ void *visit(RETC_operator_c *symbol);
+ void *visit(RETCN_operator_c *symbol);
+ void *visit(JMP_operator_c *symbol);
+ void *visit(JMPC_operator_c *symbol);
+ void *visit(JMPCN_operator_c *symbol);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, variable_name);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, option, variable_name);
+ /***************************************/
+ /* B.3 - Language ST (Structured Text) */
+ /***************************************/
+ /***********************/
+ /* B 3.1 - Expressions */
+ /***********************/
+ void *visit(or_expression_c *symbol);
+ void *visit(xor_expression_c *symbol);
+ void *visit(and_expression_c *symbol);
+ void *visit(equ_expression_c *symbol);
+ void *visit(notequ_expression_c *symbol);
+ void *visit(lt_expression_c *symbol);
+ void *visit(gt_expression_c *symbol);
+ void *visit(le_expression_c *symbol);
+ void *visit(ge_expression_c *symbol);
+ void *visit(add_expression_c *symbol);
+ void *visit(sub_expression_c *symbol);
+ void *visit(mul_expression_c *symbol);
+ void *visit(div_expression_c *symbol);
+ void *visit(mod_expression_c *symbol);
+ void *visit(power_expression_c *symbol);
+ void *visit(neg_expression_c *symbol);
+ void *visit(not_expression_c *symbol);
+
+ void *visit(function_invocation_c *symbol);
+
+ /*********************************/
+ /* B 3.2.1 Assignment Statements */
+ /*********************************/
+ void *visit(assignment_statement_c *symbol);
+
+ /********************************/
+ /* B 3.2.3 Selection Statements */
+ /********************************/
+ void *visit(if_statement_c *symbol);
+ void *visit(elseif_statement_c *symbol);
+ void *visit(case_statement_c *symbol);
+ void *visit(case_element_list_c *symbol);
+ void *visit(case_element_c *symbol);
+ void *visit(case_list_c *symbol);
+
+ /********************************/
+ /* B 3.2.4 Iteration Statements */
+ /********************************/
+ void *visit(for_statement_c *symbol);
+ void *visit(while_statement_c *symbol);
+ void *visit(repeat_statement_c *symbol);
+
+}; // narrow_candidate_datatypes_c
+
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/print_datatypes_error.cc Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,1162 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 20011-2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 20011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+/*
+ * Fill candidate list of data types for all symbols
+ */
+
+#include "print_datatypes_error.hh"
+#include <typeinfo>
+#include <list>
+#include <string>
+#include <string.h>
+#include <strings.h>
+
+
+#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2))
+#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2))
+
+#define STAGE3_ERROR(symbol1, symbol2, ...) { \
+ fprintf(stderr, "%s:%d-%d..%d-%d: error : ", \
+ FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \
+ LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ il_error = true; \
+ error_found = true;\
+ }
+
+
+/* set to 1 to see debug info during execution */
+static int debug = 0;
+
+print_datatypes_error_c::print_datatypes_error_c(symbol_c *ignore) {
+ error_found = false;
+}
+
+print_datatypes_error_c::~print_datatypes_error_c(void) {
+ error_found = false;
+}
+
+int print_datatypes_error_c::get_error_found() {
+ return error_found;
+}
+
+/* a helper function... */
+symbol_c *print_datatypes_error_c::base_type(symbol_c *symbol) {
+ /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
+ * in the code.
+ */
+ if (symbol == NULL) return NULL;
+ return (symbol_c *)symbol->accept(search_base_type);
+}
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/******************************/
+/* B 1.2.1 - Numeric Literals */
+/******************************/
+void *print_datatypes_error_c::visit(real_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(integer_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(neg_real_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(neg_integer_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(binary_integer_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(octal_integer_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(hex_integer_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(integer_literal_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_INT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_INT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(real_literal_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_REAL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_REAL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(bit_string_literal_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BIT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_BIT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_literal_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_true_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(boolean_false_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for ANY_BOOL data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "ANY_BOOL data type not valid in this location.");
+ }
+ return NULL;
+}
+
+/*******************************/
+/* B.1.2.2 Character Strings */
+/*******************************/
+void *print_datatypes_error_c::visit(double_byte_character_string_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for WSTRING data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "WSTRING data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(single_byte_character_string_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for STRING data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "STRING data type not valid in this location.");
+ }
+ return NULL;
+}
+
+/***************************/
+/* B 1.2.3 - Time Literals */
+/***************************/
+/************************/
+/* B 1.2.3.1 - Duration */
+/************************/
+void *print_datatypes_error_c::visit(duration_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Invalid syntax for TIME data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "TIME data type not valid in this location.");
+ }
+ return NULL;
+}
+
+/************************************/
+/* B 1.2.3.2 - Time of day and Date */
+/************************************/
+void *print_datatypes_error_c::visit(time_of_day_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Invalid syntax for TOD data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "TOD data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(date_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Invalid syntax for DATE data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "DATE data type not valid in this location.");
+ }
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(date_and_time_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0) {
+ STAGE3_ERROR(symbol, symbol, "Invalid syntax for DT data type.");
+ } else if (NULL == symbol->datatype) {
+ STAGE3_ERROR(symbol, symbol, "DT data type not valid in this location.");
+ }
+ return NULL;
+}
+
+/**********************/
+/* B 1.3 - Data types */
+/**********************/
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+void *print_datatypes_error_c::visit(data_type_declaration_c *symbol) {
+ // TODO !!!
+ /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(enumerated_value_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0)
+ STAGE3_ERROR(symbol, symbol, "Ambiguous enumerate value or Variable not declared in this scope.");
+ return NULL;
+}
+
+
+/*********************/
+/* B 1.4 - Variables */
+/*********************/
+void *print_datatypes_error_c::visit(symbolic_variable_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0)
+ STAGE3_ERROR(symbol, symbol, "Variable not declared in this scope.");
+ return NULL;
+}
+
+/********************************************/
+/* B 1.4.1 - Directly Represented Variables */
+/********************************************/
+void *print_datatypes_error_c::visit(direct_variable_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0)
+ STAGE3_ERROR(symbol, symbol, "Numerical result exceeds range for located variable data type.");
+ return NULL;
+}
+
+/*************************************/
+/* B 1.4.2 - Multi-element variables */
+/*************************************/
+/* subscripted_variable '[' subscript_list ']' */
+// SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+void *print_datatypes_error_c::visit(array_variable_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0)
+ STAGE3_ERROR(symbol, symbol, "Array variable not declared in this scope.");
+
+ /* recursively call the subscript list to print any errors in the expressions used in the subscript...*/
+ symbol->subscript_list->accept(*this);
+ return NULL;
+}
+
+/* subscript_list ',' subscript */
+// SYM_LIST(subscript_list_c)
+/* NOTE: we inherit from iterator visitor, so we do not need to implement this method... */
+#if 0
+void *print_datatypes_error_c::visit(subscript_list_c *symbol) {
+}
+#endif
+
+
+/* record_variable '.' field_selector */
+/* WARNING: input and/or output variables of function blocks
+ * may be accessed as fields of a structured variable!
+ * Code handling a structured_variable_c must take
+ * this into account!
+ */
+// SYM_REF2(structured_variable_c, record_variable, field_selector)
+/* NOTE: We do not recursively determine the data types of each field_selector in fill_candidate_datatypes_c,
+ * so it does not make sense to recursively visit all the field_selectors to print out error messages.
+ * Maybe in the future, if we find the need to print out more detailed error messages, we might do it that way. For now, we don't!
+ */
+void *print_datatypes_error_c::visit(structured_variable_c *symbol) {
+ if (symbol->candidate_datatypes.size() == 0)
+ STAGE3_ERROR(symbol, symbol, "Structure variable not declared in this scope.");
+ return NULL;
+}
+
+/************************************/
+/* B 1.5 Program organization units */
+/************************************/
+/*********************/
+/* B 1.5.1 Functions */
+/*********************/
+void *print_datatypes_error_c::visit(function_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ /* We do not check for data type errors in variable declarations, Skip this for now... */
+// symbol->var_declarations_list->accept(*this);
+ if (debug) printf("Print error data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
+ il_parenthesis_level = 0;
+ il_error = false;
+ prev_il_instruction = NULL;
+ symbol->function_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/***************************/
+/* B 1.5.2 Function blocks */
+/***************************/
+void *print_datatypes_error_c::visit(function_block_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ /* We do not check for data type errors in variable declarations, Skip this for now... */
+// symbol->var_declarations->accept(*this);
+ if (debug) printf("Print error data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
+ il_parenthesis_level = 0;
+ il_error = false;
+ prev_il_instruction = NULL;
+ symbol->fblock_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+/**********************/
+/* B 1.5.3 - Programs */
+/**********************/
+void *print_datatypes_error_c::visit(program_declaration_c *symbol) {
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ /* We do not check for data type errors in variable declarations, Skip this for now... */
+// symbol->var_declarations->accept(*this);
+ if (debug) printf("Print error data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
+ il_parenthesis_level = 0;
+ il_error = false;
+ prev_il_instruction = NULL;
+ symbol->function_block_body->accept(*this);
+ prev_il_instruction = NULL;
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+
+
+/********************************/
+/* B 1.7 Configuration elements */
+/********************************/
+void *print_datatypes_error_c::visit(configuration_declaration_c *symbol) {
+#if 0
+ // TODO !!!
+ /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
+#endif
+ return NULL;
+}
+
+/****************************************/
+/* B.2 - Language IL (Instruction List) */
+/****************************************/
+/***********************************/
+/* B 2.1 Instructions and Operands */
+/***********************************/
+// void *visit(instruction_list_c *symbol);
+void *print_datatypes_error_c::visit(il_simple_operation_c *symbol) {
+ il_operand = symbol->il_operand;
+ if (NULL != symbol->il_operand) {
+ symbol->il_operand->accept(*this);
+ }
+ /* recursive call to see whether data types are compatible */
+ symbol->il_simple_operator->accept(*this);
+ il_operand = NULL;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_function_call_c *symbol) {
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_expression_c *symbol) {
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_fb_call_c *symbol) {
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(il_formal_funct_call_c *symbol) {
+ return NULL;
+}
+
+
+/*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+ */
+
+/*******************/
+/* B 2.2 Operators */
+/*******************/
+void *print_datatypes_error_c::visit(LD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(LDN_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'LDN' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(ST_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+ /* MANU:
+ * if prev_instruction is NULL we can print a message error or warning error like:
+ * we can't use a ST like first instruction.
+ * What do you think?
+ */
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ST' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(STN_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+ /* MANU:
+ * if prev_instruction is NULL we can print a message error or warning error like:
+ * we can't use a ST like first instruction.
+ * What do you think?
+ */
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'STN' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(NOT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(S_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(R_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(S1_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'S1' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(R1_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'R1' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CLK_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CU_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CD_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(PV_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(IN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(PT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(AND_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(OR_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(XOR_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(ANDN_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ANDN' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(ORN_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(XORN_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ORN' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(ADD_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'ADD' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(SUB_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'SUB' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(MUL_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MUL' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(DIV_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'DIV' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(MOD_operator_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ il_operand->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (il_operand->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'MOD' operator.");
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(GT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(GE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(EQ_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(LT_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(LE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(NE_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CAL_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CALC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(CALCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(RET_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(RETC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(RETCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMP_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMPC_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(JMPCN_operator_c *symbol) {
+ prev_il_instruction = symbol;
+ return NULL;
+}
+
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, variable_name);
+/* Symbol class handled together with function call checks */
+// void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+/***************************************/
+/* B.3 - Language ST (Structured Text) */
+/***************************************/
+/***********************/
+/* B 3.1 - Expressions */
+/***********************/
+
+void *print_datatypes_error_c::visit(or_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'OR' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(xor_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'XOR' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(and_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for 'AND' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(equ_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '=' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(notequ_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<>' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(lt_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(gt_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(le_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '<=' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(ge_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '>=' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(add_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Current '+' result and operand not of same data type.");
+
+ return NULL;
+}
+
+
+
+void *print_datatypes_error_c::visit(sub_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Current '-' result and operand not of same data type.");
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(mul_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Current '*' result and operand not of same data type.");
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(div_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Current '/' result and operand not of same data type.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(mod_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Current 'MOD' result and operand not of same data type.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(power_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Data type mismatch for '**' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(neg_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NEG' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(not_expression_c *symbol) {
+ if (NULL != symbol->datatype) return NULL;
+
+ symbol->exp->accept(*this);
+ if ((symbol->candidate_datatypes.size() == 0) &&
+ (symbol->exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'NOT' expression.");
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(function_invocation_c *symbol) {
+ list_c *parameter_list;
+ function_declaration_c * f_decl;
+
+ if (NULL != symbol->datatype) return NULL;
+ if (NULL != symbol->formal_param_list)
+ parameter_list = (list_c *)symbol->formal_param_list;
+ else if (NULL != symbol->nonformal_param_list)
+ parameter_list = (list_c *)symbol->nonformal_param_list;
+ else ERROR;
+ parameter_list->accept(*this);
+ if (symbol->candidate_datatypes.size() == 0) {
+ identifier_c *fname = (identifier_c *)symbol->function_name;
+ f_decl = (function_declaration_c *)symbol->called_function_declaration;
+ /*
+ * Manuele: In the future we have to test parameter number
+ * and show a specific message.
+ */
+ STAGE3_ERROR(symbol, symbol, "No matching overloaded '%s' function call.", fname->value);
+ }
+ return NULL;
+}
+
+/********************/
+/* B 3.2 Statements */
+/********************/
+
+/*********************************/
+/* B 3.2.1 Assignment Statements */
+/*********************************/
+void *print_datatypes_error_c::visit(assignment_statement_c *symbol) {
+ symbol->l_exp->accept(*this);
+ symbol->r_exp->accept(*this);
+ if ((NULL == symbol->l_exp->datatype) &&
+ (NULL == symbol->r_exp->datatype) &&
+ (symbol->l_exp->candidate_datatypes.size() > 0) &&
+ (symbol->r_exp->candidate_datatypes.size() > 0))
+ STAGE3_ERROR(symbol, symbol, "Invalid data types for ':=' operation.");
+ return NULL;
+}
+
+/********************************/
+/* B 3.2.3 Selection Statements */
+/********************************/
+
+void *print_datatypes_error_c::visit(if_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if ((NULL == symbol->expression->datatype) &&
+ (symbol->expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'IF' condition.");
+ }
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ if (NULL != symbol->elseif_statement_list)
+ symbol->elseif_statement_list->accept(*this);
+ if (NULL != symbol->else_statement_list)
+ symbol->else_statement_list->accept(*this);
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(elseif_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if ((NULL == symbol->expression->datatype) &&
+ (symbol->expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'ELSIF' condition.");
+ }
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+
+void *print_datatypes_error_c::visit(case_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if ((NULL == symbol->expression->datatype) &&
+ (symbol->expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "'CASE' quantity not an integer or enumerated.");
+ }
+ symbol->case_element_list->accept(*this);
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+/********************************/
+/* B 3.2.4 Iteration Statements */
+/********************************/
+
+void *print_datatypes_error_c::visit(for_statement_c *symbol) {
+ symbol->control_variable->accept(*this);
+ symbol->beg_expression->accept(*this);
+ symbol->end_expression->accept(*this);
+ /* Control variable */
+ if ((NULL == symbol->control_variable->datatype) &&
+ (symbol->control_variable->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' control variable.");
+ }
+ /* BEG expression */
+ if ((NULL == symbol->beg_expression->datatype) &&
+ (symbol->beg_expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' begin expression.");
+ }
+ /* END expression */
+ if ((NULL == symbol->end_expression->datatype) &&
+ (symbol->end_expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' end expression.");
+ }
+ /* BY expression */
+ if ((NULL != symbol->by_expression) &&
+ (NULL == symbol->by_expression->datatype) &&
+ (symbol->end_expression->candidate_datatypes.size() > 0)) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'FOR' by expression.");
+ }
+ /* DO statement */
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(while_statement_c *symbol) {
+ symbol->expression->accept(*this);
+ if (symbol->candidate_datatypes.size() != 1) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'WHILE' condition.");
+ return NULL;
+ }
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ return NULL;
+}
+
+void *print_datatypes_error_c::visit(repeat_statement_c *symbol) {
+ if (symbol->candidate_datatypes.size() != 1) {
+ STAGE3_ERROR(symbol, symbol, "Invalid data type for 'REPEAT' condition.");
+ return NULL;
+ }
+ if (NULL != symbol->statement_list)
+ symbol->statement_list->accept(*this);
+ symbol->expression->accept(*this);
+ return NULL;
+}
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stage3/print_datatypes_error.hh Wed Feb 01 19:49:11 2012 +0000
@@ -0,0 +1,303 @@
+/*
+ * matiec - a compiler for the programming languages defined in IEC 61131-3
+ *
+ * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2011-2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2011-2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This code is made available on the understanding that it will not be
+ * used in safety-critical situations without a full and competent review.
+ */
+
+/*
+ * An IEC 61131-3 compiler.
+ *
+ * Based on the
+ * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
+ *
+ */
+
+
+#include "../absyntax_utils/absyntax_utils.hh"
+
+class print_datatypes_error_c: public iterator_visitor_c {
+
+ private:
+ search_varfb_instance_type_c *search_varfb_instance_type;
+ search_base_type_c search_base_type;
+ /* When calling a function block, we must first find it's type,
+ * by searching through the declarations of the variables currently
+ * in scope.
+ * This class does just that...
+ * A new object instance is instantiated whenever we start checking semantics
+ * for a function block type declaration, or a program declaration.
+ * This object instance will then later be called while the
+ * function block's or the program's body is being handled.
+ *
+ * Note that functions cannot contain calls to function blocks,
+ * so we do not create an object instance when handling
+ * a function declaration.
+ */
+
+ /* In IL code, once we find a type mismatch error, it is best to
+ * ignore any further errors until the end of the logical operation,
+ * i.e. until the next LD.
+ * However, we cannot clear the il_error flag on all LD operations,
+ * as these may also be used within parenthesis. LD operations
+ * within parenthesis may not clear the error flag.
+ * We therefore need a counter to know how deep inside a parenthesis
+ * structure we are.
+ */
+ int il_parenthesis_level;
+ bool il_error;
+ bool error_found;
+
+ /* the current data type of the data stored in the IL stack, i.e. the default variable */
+ symbol_c *prev_il_instruction;
+ /* the current IL operand being analyzed - its symbol and its data type */
+ symbol_c *il_operand_type;
+ symbol_c *il_operand;
+
+
+ public:
+ print_datatypes_error_c(symbol_c *ignore);
+ virtual ~print_datatypes_error_c(void);
+ int get_error_found();
+
+ /* a helper function... */
+ symbol_c *base_type(symbol_c *symbol);
+
+ /*********************/
+ /* B 1.2 - Constants */
+ /*********************/
+ /******************************/
+ /* B 1.2.1 - Numeric Literals */
+ /******************************/
+ void *visit(real_c *symbol);
+ void *visit(integer_c *symbol);
+ void *visit(neg_real_c *symbol);
+ void *visit(neg_integer_c *symbol);
+ void *visit(binary_integer_c *symbol);
+ void *visit(octal_integer_c *symbol);
+ void *visit(hex_integer_c *symbol);
+ void *visit(integer_literal_c *symbol);
+ void *visit(real_literal_c *symbol);
+ void *visit(bit_string_literal_c *symbol);
+ void *visit(boolean_literal_c *symbol);
+ void *visit(boolean_true_c *symbol);
+ void *visit(boolean_false_c *symbol);
+
+ /*******************************/
+ /* B.1.2.2 Character Strings */
+ /*******************************/
+ void *visit(double_byte_character_string_c *symbol);
+ void *visit(single_byte_character_string_c *symbol);
+
+ /***************************/
+ /* B 1.2.3 - Time Literals */
+ /***************************/
+ /************************/
+ /* B 1.2.3.1 - Duration */
+ /************************/
+ void *visit(duration_c *symbol);
+
+ /************************************/
+ /* B 1.2.3.2 - Time of day and Date */
+ /************************************/
+ void *visit(time_of_day_c *symbol);
+ void *visit(date_c *symbol);
+ void *visit(date_and_time_c *symbol);
+
+ /**********************/
+ /* B 1.3 - Data types */
+ /**********************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ void *visit(data_type_declaration_c *symbol);
+ void *visit(enumerated_value_c *symbol);
+
+ /*********************/
+ /* B 1.4 - Variables */
+ /*********************/
+ void *visit(symbolic_variable_c *symbol);
+
+ /********************************************/
+ /* B 1.4.1 - Directly Represented Variables */
+ /********************************************/
+ void *visit(direct_variable_c *symbol);
+
+ /*************************************/
+ /* B 1.4.2 - Multi-element variables */
+ /*************************************/
+ void *visit(array_variable_c *symbol);
+ void *visit(structured_variable_c *symbol);
+
+ /**************************************/
+ /* B 1.5 - Program organization units */
+ /**************************************/
+ /***********************/
+ /* B 1.5.1 - Functions */
+ /***********************/
+ void *visit(function_declaration_c *symbol);
+
+ /*****************************/
+ /* B 1.5.2 - Function blocks */
+ /*****************************/
+ void *visit(function_block_declaration_c *symbol);
+
+ /**********************/
+ /* B 1.5.3 - Programs */
+ /**********************/
+ void *visit(program_declaration_c *symbol);
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ void *visit(configuration_declaration_c *symbol);
+
+ /****************************************/
+ /* B.2 - Language IL (Instruction List) */
+ /****************************************/
+ /***********************************/
+ /* B 2.1 Instructions and Operands */
+ /***********************************/
+ // void *visit(instruction_list_c *symbol);
+ void *visit(il_simple_operation_c *symbol);
+ void *visit(il_function_call_c *symbol);
+ void *visit(il_expression_c *symbol);
+ void *visit(il_fb_call_c *symbol);
+ void *visit(il_formal_funct_call_c *symbol);
+ /*
+ void *visit(il_operand_list_c *symbol);
+ void *visit(simple_instr_list_c *symbol);
+ void *visit(il_param_list_c *symbol);
+ void *visit(il_param_assignment_c *symbol);
+ void *visit(il_param_out_assignment_c *symbol);
+ */
+
+ /*******************/
+ /* B 2.2 Operators */
+ /*******************/
+ void *visit(LD_operator_c *symbol);
+ void *visit(LDN_operator_c *symbol);
+ void *visit(ST_operator_c *symbol);
+ void *visit(STN_operator_c *symbol);
+ void *visit(NOT_operator_c *symbol);
+ void *visit(S_operator_c *symbol);
+ void *visit(R_operator_c *symbol);
+ void *visit(S1_operator_c *symbol);
+ void *visit(R1_operator_c *symbol);
+ void *visit(CLK_operator_c *symbol);
+ void *visit(CU_operator_c *symbol);
+ void *visit(CD_operator_c *symbol);
+ void *visit(PV_operator_c *symbol);
+ void *visit(IN_operator_c *symbol);
+ void *visit(PT_operator_c *symbol);
+ void *visit(AND_operator_c *symbol);
+ void *visit(OR_operator_c *symbol);
+ void *visit(XOR_operator_c *symbol);
+ void *visit(ANDN_operator_c *symbol);
+ void *visit(ORN_operator_c *symbol);
+ void *visit(XORN_operator_c *symbol);
+ void *visit(ADD_operator_c *symbol);
+ void *visit(SUB_operator_c *symbol);
+ void *visit(MUL_operator_c *symbol);
+ void *visit(DIV_operator_c *symbol);
+ void *visit(MOD_operator_c *symbol);
+ void *visit(GT_operator_c *symbol);
+ void *visit(GE_operator_c *symbol);
+ void *visit(EQ_operator_c *symbol);
+ void *visit(LT_operator_c *symbol);
+ void *visit(LE_operator_c *symbol);
+ void *visit(NE_operator_c *symbol);
+ void *visit(CAL_operator_c *symbol);
+ void *visit(CALC_operator_c *symbol);
+ void *visit(CALCN_operator_c *symbol);
+ void *visit(RET_operator_c *symbol);
+ void *visit(RETC_operator_c *symbol);
+ void *visit(RETCN_operator_c *symbol);
+ void *visit(JMP_operator_c *symbol);
+ void *visit(JMPC_operator_c *symbol);
+ void *visit(JMPCN_operator_c *symbol);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, variable_name);
+ /* Symbol class handled together with function call checks */
+ // void *visit(il_assign_operator_c *symbol, option, variable_name);
+
+ /***************************************/
+ /* B.3 - Language ST (Structured Text) */
+ /***************************************/
+ /***********************/
+ /* B 3.1 - Expressions */
+ /***********************/
+ void *visit(or_expression_c *symbol);
+ void *visit(xor_expression_c *symbol);
+ void *visit(and_expression_c *symbol);
+ void *visit(equ_expression_c *symbol);
+ void *visit(notequ_expression_c *symbol);
+ void *visit(lt_expression_c *symbol);
+ void *visit(gt_expression_c *symbol);
+ void *visit(le_expression_c *symbol);
+ void *visit(ge_expression_c *symbol);
+ void *visit(add_expression_c *symbol);
+ void *visit(sub_expression_c *symbol);
+ void *visit(mul_expression_c *symbol);
+ void *visit(div_expression_c *symbol);
+ void *visit(mod_expression_c *symbol);
+ void *visit(power_expression_c *symbol);
+ void *visit(neg_expression_c *symbol);
+ void *visit(not_expression_c *symbol);
+ void *visit(function_invocation_c *symbol);
+
+ /*********************************/
+ /* B 3.2.1 Assignment Statements */
+ /*********************************/
+ void *visit(assignment_statement_c *symbol);
+
+ /*****************************************/
+ /* B 3.2.2 Subprogram Control Statements */
+ /*****************************************/
+ //void *visit(fb_invocation_c *symbol);
+
+ /********************************/
+ /* B 3.2.3 Selection Statements */
+ /********************************/
+ void *visit(if_statement_c *symbol);
+ // void *visit(elseif_statement_list_c *symbol);
+ void *visit(elseif_statement_c *symbol);
+ void *visit(case_statement_c *symbol);
+ // void *visit(case_element_list_c *symbol);
+ // void *visit(case_element_c *symbol);
+ // void *visit(case_list_c *symbol);
+
+ /********************************/
+ /* B 3.2.4 Iteration Statements */
+ /********************************/
+ void *visit(for_statement_c *symbol);
+ void *visit(while_statement_c *symbol);
+ void *visit(repeat_statement_c *symbol);
+
+}; // print_datatypes_error_c
+
+
+
+
+
+
+
--- a/stage3/stage3.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/stage3.cc Wed Feb 01 19:49:11 2012 +0000
@@ -1,8 +1,10 @@
/*
* matiec - a compiler for the programming languages defined in IEC 61131-3
*
- * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt)
+ * Copyright (C) 2009-2012 Mario de Sousa (msousa@fe.up.pt)
* Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
+ * Copyright (C) 2012 Manuele Conti (manuele.conti@sirius-es.it)
+ * Copyright (C) 2012 Matteo Facchinetti (matteo.facchinetti@sirius-es.it)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,14 +34,20 @@
#include "stage3.hh"
+#include "fill_candidate_datatypes.hh"
+#include "narrow_candidate_datatypes.hh"
+#include "print_datatypes_error.hh"
+
+
int type_safety(symbol_c *tree_root){
- visit_expression_type_c visit_expression_type(tree_root);
-
- (*tree_root).accept(visit_expression_type);
-
- if (visit_expression_type.get_error_found())
- return -1;
-
+ fill_candidate_datatypes_c fill_candidate_datatypes(tree_root);
+ tree_root->accept(fill_candidate_datatypes);
+ narrow_candidate_datatypes_c narrow_candidate_datatypes(tree_root);
+ tree_root->accept(narrow_candidate_datatypes);
+ print_datatypes_error_c print_datatypes_error(tree_root);
+ tree_root->accept(print_datatypes_error);
+ if (print_datatypes_error.get_error_found())
+ return -1;
return 0;
}
--- a/stage3/stage3.hh Wed Feb 01 13:01:08 2012 +0000
+++ b/stage3/stage3.hh Wed Feb 01 19:49:11 2012 +0000
@@ -31,19 +31,7 @@
*/
-// #include <stdio.h> /* required for NULL */
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <typeinfo>
-#include <list>
-#include <strings.h>
-
#include "../util/symtable.hh"
-#include "../util/dsymtable.hh"
-#include "../absyntax/visitor.hh"
-
-#include "visit_expression_type.hh"
int stage3(symbol_c *tree_root);
--- a/stage3/visit_expression_type.cc Wed Feb 01 13:01:08 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2291 +0,0 @@
-/*
- * matiec - a compiler for the programming languages defined in IEC 61131-3
- *
- * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt)
- * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- * This code is made available on the understanding that it will not be
- * used in safety-critical situations without a full and competent review.
- */
-
-/*
- * An IEC 61131-3 compiler.
- *
- * Based on the
- * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
- *
- */
-
-
-/* Verify whether the semantic rules of data type compatibility are being followed.
- *
- * For example:
- */
-
-#include "visit_expression_type.hh"
-#include <typeinfo>
-#include <list>
-#include <string>
-#include <string.h>
-#include <strings.h>
-
-
-#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2))
-#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2))
-
-#define STAGE3_ERROR(symbol1, symbol2, ...) { \
- fprintf(stderr, "%s:%d-%d..%d-%d: error : ", \
- FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column, \
- LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
- il_error = true; \
- error_found = true; \
- }
-
-
-/* set to 1 to see debug info during execution */
-static int debug = 0;
-
-
-void *visit_expression_type_c::visit(program_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
- symbol->var_declarations->accept(*this);
- if (debug) printf("checking semantics in body of program %s\n", ((token_c *)(symbol->program_type_name))->value);
- il_parenthesis_level = 0;
- il_error = false;
- il_default_variable_type = NULL;
- symbol->function_block_body->accept(*this);
- il_default_variable_type = NULL;
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
- return NULL;
-}
-
-void *visit_expression_type_c::visit(function_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
- symbol->var_declarations_list->accept(*this);
- if (debug) printf("checking semantics in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value);
- il_parenthesis_level = 0;
- il_error = false;
- il_default_variable_type = NULL;
- symbol->function_body->accept(*this);
- il_default_variable_type = NULL;
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
- return NULL;
-}
-
-void *visit_expression_type_c::visit(function_block_declaration_c *symbol) {
- search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
- symbol->var_declarations->accept(*this);
- if (debug) printf("checking semantics in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value);
- il_parenthesis_level = 0;
- il_error = false;
- il_default_variable_type = NULL;
- symbol->fblock_body->accept(*this);
- il_default_variable_type = NULL;
- delete search_varfb_instance_type;
- search_varfb_instance_type = NULL;
- return NULL;
-}
-
-
-
-
-
-
-
-
-
-visit_expression_type_c::visit_expression_type_c(symbol_c *ignore) {
- error_found = false;
-}
-
-visit_expression_type_c::~visit_expression_type_c(void) {
-}
-
-bool visit_expression_type_c::get_error_found(void) {
- return error_found;
-}
-
-
-
-/* NOTE on data type handling and literals...
- * ==========================================
- *
- * Literals that are explicitly type cast
- * e.g.: BYTE#42
- * INT#65
- * TIME#45h23m
- * etc...
- * are NOT considered literals in the following code.
- * Since they are type cast, and their data type is fixed and well known,
- * they are treated as a variable of that data type (except when determining lvalues)
- * In other words, when calling search_constant_type_c on these constants, it returns
- * a xxxxx_type_name_c, and not one of the xxxx_literal_c !
- *
- * When the following code handles a literal, it is really a literal of unknown data type.
- * e.g. 42, may be considered an int, a byte, a word, etc...
- *
- * NOTE: type_symbol == NULL is valid!
- * This will occur, for example, when and undefined/undeclared symbolic_variable is used in the program.
- * This will not be of any type, so we always return false.
- */
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_ELEMENTARY_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- return is_ANY_MAGNITUDE_type(type_symbol)
- || is_ANY_BIT_type (type_symbol)
- || is_ANY_STRING_type (type_symbol)
- || is_ANY_DATE_type (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEELEMENTARY_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- return is_ANY_SAFEMAGNITUDE_type(type_symbol)
- || is_ANY_SAFEBIT_type (type_symbol)
- || is_ANY_SAFESTRING_type (type_symbol)
- || is_ANY_SAFEDATE_type (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_ELEMENTARY_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- /* NOTE: doing
- * return is_ANY_SAFEELEMENTARY_type() || is_ANY_ELEMENTARY_type()
- * is incorrect, as the literals would never be considered compatible...
- */
- return is_ANY_MAGNITUDE_compatible(type_symbol)
- || is_ANY_BIT_compatible (type_symbol)
- || is_ANY_STRING_compatible (type_symbol)
- || is_ANY_DATE_compatible (type_symbol);
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_MAGNITUDE_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(time_type_name_c)) {return true;}
- return is_ANY_NUM_type(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEMAGNITUDE_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safetime_type_name_c)) {return true;}
- return is_ANY_SAFENUM_type(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_MAGNITUDE_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_MAGNITUDE_type (type_symbol)) {return true;}
- if (is_ANY_SAFEMAGNITUDE_type(type_symbol)) {return true;}
-
- return is_ANY_NUM_compatible(type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_NUM_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_REAL_type(type_symbol)) {return true;}
- if (is_ANY_INT_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFENUM_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- return is_ANY_SAFEREAL_type(type_symbol)
- || is_ANY_SAFEINT_type (type_symbol);
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_NUM_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_REAL_compatible(type_symbol)) {return true;}
- if (is_ANY_INT_compatible(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_DATE_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(date_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(tod_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(dt_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEDATE_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safedate_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safetod_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safedt_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_DATE_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_DATE_type (type_symbol)) {return true;}
- if (is_ANY_SAFEDATE_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_STRING_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(string_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(wstring_type_name_c)) {return true;}
-// TODO literal_string ???
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFESTRING_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safestring_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safewstring_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_STRING_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_STRING_type (type_symbol)) {return true;}
- if (is_ANY_SAFESTRING_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_INT_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(sint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(int_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(dint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(lint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(usint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(uint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(udint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(ulint_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEINT_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safesint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safedint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safelint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeusint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeuint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeudint_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeulint_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_INT_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_INT_type (type_symbol)) {return true;}
- if (is_ANY_SAFEINT_type(type_symbol)) {return true;}
- if (is_literal_integer_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_REAL_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(real_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(lreal_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEREAL_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safereal_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safelreal_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_REAL_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_REAL_type (type_symbol)) {return true;}
- if (is_ANY_SAFEREAL_type(type_symbol)) {return true;}
- if (is_literal_real_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BIT_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(byte_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(word_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(dword_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(lword_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_SAFEBIT_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safebyte_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safeword_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safedword_type_name_c)) {return true;}
- if (typeid(*type_symbol) == typeid(safelword_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BIT_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_ANY_BIT_type (type_symbol)) {return true;}
- if (is_ANY_SAFEBIT_type(type_symbol)) {return true;}
- if (is_nonneg_literal_integer_type(type_symbol)) {return true;}
- if (is_literal_bool_type(type_symbol)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_BOOL_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(bool_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_SAFEBOOL_type(symbol_c *type_symbol){
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(safebool_type_name_c)) {return true;}
- return false;
-}
-
-/* A helper function... */
-bool visit_expression_type_c::is_ANY_BOOL_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (is_BOOL_type (type_symbol)) {return true;}
- if (is_SAFEBOOL_type(type_symbol)) {return true;}
- if (is_literal_bool_type(type_symbol)) {return true;}
- return false;
-}
-
-
-#define is_type(type_name_symbol, type_name_class) ((type_name_symbol == NULL) ? false : (typeid(*type_name_symbol) == typeid(type_name_class)))
-
-
-#define sizeoftype(symbol) get_sizeof_datatype_c::getsize(symbol)
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_integer_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(neg_integer_c)) {return true;}
- return is_nonneg_literal_integer_type(type_symbol);
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_nonneg_literal_integer_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(integer_c)) {return true;}
- if (typeid(*type_symbol) == typeid(binary_integer_c)) {return true;}
- if (typeid(*type_symbol) == typeid(octal_integer_c)) {return true;}
- if (typeid(*type_symbol) == typeid(hex_integer_c)) {return true;}
- return false;
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_real_type(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(real_c)) {return true;}
- if (typeid(*type_symbol) == typeid(neg_real_c)) {return true;}
- return false;
-}
-
-
-/* A helper function... */
-bool visit_expression_type_c::is_literal_bool_type(symbol_c *type_symbol) {
- bool_type_name_c bool_t;
-
- if (type_symbol == NULL) {return false;}
- if (typeid(*type_symbol) == typeid(boolean_true_c)) {return true;}
- if (typeid(*type_symbol) == typeid(boolean_false_c)) {return true;}
- if (is_nonneg_literal_integer_type(type_symbol))
- if (sizeoftype(&bool_t) >= sizeoftype(type_symbol)) {return true;}
- return false;
-}
-
-bool visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible(symbol_c *type_symbol) {
- if (type_symbol == NULL) {return false;}
- if (search_base_type.type_is_enumerated(type_symbol)) {return true;}
- return is_ANY_ELEMENTARY_compatible(type_symbol);
-}
-
-
-/* Determine the common data type between two data types.
- * If no common data type found, return NULL.
- *
- * If data types are identical, return the first (actually any would do...).
- * If any of the data types is a literal, we confirm that
- * the literal uses less bits than the fixed size data type.
- * e.g. BYTE and 1024 returns NULL
- * BYTE and 255 returns BYTE
- *
- * If two literals, then return the literal that requires more bits...
- */
-
-symbol_c *visit_expression_type_c::common_type__(symbol_c *first_type, symbol_c *second_type) {
- if (first_type == NULL && second_type == NULL) {return NULL;}
- if (first_type == NULL) {return second_type;}
- if (second_type == NULL) {return first_type;}
-
- if (is_literal_integer_type(first_type) && is_literal_integer_type(second_type))
- {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
-
- if (is_literal_real_type(first_type) && is_literal_real_type(second_type))
- {return ((sizeoftype(first_type) > sizeoftype(second_type))? first_type:second_type);}
-
- if (is_literal_bool_type(first_type) && is_literal_bool_type(second_type))
- {return first_type;}
-
- /* The following check can only be made after the is_literal_XXXX checks */
- /* When two literals of the same type, with identical typeid's are checked,
- * we must return the one that occupies more bits... This is done above.
- */
- if (typeid(*first_type) == typeid(*second_type)) {return first_type;}
-
- /* NOTE Although a BOOL is also an ANY_BIT, we must check it explicitly since some
- * literal bool values are not literal integers...
- */
- if (is_BOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;}
- if (is_BOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;}
-
- if (is_SAFEBOOL_type(first_type) && is_literal_bool_type(second_type)) {return first_type;}
- if (is_SAFEBOOL_type(second_type) && is_literal_bool_type(first_type)) {return second_type;}
-
- if (is_SAFEBOOL_type(first_type) && is_BOOL_type(second_type)) {return second_type;}
- if (is_SAFEBOOL_type(second_type) && is_BOOL_type(first_type)) {return first_type;}
-
- if (is_ANY_BIT_type(first_type) && is_nonneg_literal_integer_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_BIT_type(second_type) && is_nonneg_literal_integer_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEBIT_type(first_type) && is_nonneg_literal_integer_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_SAFEBIT_type(second_type) && is_nonneg_literal_integer_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEBIT_type(first_type) && is_ANY_BIT_type(second_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
- if (is_ANY_SAFEBIT_type(second_type) && is_ANY_BIT_type(first_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
- if (is_ANY_INT_type(first_type) && is_literal_integer_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_INT_type(second_type) && is_literal_integer_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEINT_type(first_type) && is_literal_integer_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_SAFEINT_type(second_type) && is_literal_integer_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEINT_type(first_type) && is_ANY_INT_type(second_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
- if (is_ANY_SAFEINT_type(second_type) && is_ANY_INT_type(first_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
- if (is_ANY_REAL_type(first_type) && is_literal_real_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_REAL_type(second_type) && is_literal_real_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEREAL_type(first_type) && is_literal_real_type(second_type))
- {return ((sizeoftype(first_type) >= sizeoftype(second_type))? first_type :NULL);}
- if (is_ANY_SAFEREAL_type(second_type) && is_literal_real_type(first_type))
- {return ((sizeoftype(second_type) >= sizeoftype(first_type)) ? second_type:NULL);}
-
- if (is_ANY_SAFEREAL_type(first_type) && is_ANY_REAL_type(second_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? second_type:NULL);}
- if (is_ANY_SAFEREAL_type(second_type) && is_ANY_REAL_type(first_type))
- {return ((sizeoftype(first_type) == sizeoftype(second_type))? first_type :NULL);}
-
- /* the Time and Date types... */
- if (is_type(first_type, safetime_type_name_c) && is_type(second_type, time_type_name_c)) {return second_type;}
- if (is_type(second_type, safetime_type_name_c) && is_type( first_type, time_type_name_c)) {return first_type;}
-
- if (is_type(first_type, safedate_type_name_c) && is_type(second_type, date_type_name_c)) {return second_type;}
- if (is_type(second_type, safedate_type_name_c) && is_type( first_type, date_type_name_c)) {return first_type;}
-
- if (is_type(first_type, safedt_type_name_c) && is_type(second_type, dt_type_name_c)) {return second_type;}
- if (is_type(second_type, safedt_type_name_c) && is_type( first_type, dt_type_name_c)) {return first_type;}
-
- if (is_type(first_type, safetod_type_name_c) && is_type(second_type, tod_type_name_c)) {return second_type;}
- if (is_type(second_type, safetod_type_name_c) && is_type( first_type, tod_type_name_c)) {return first_type;}
-
- /* no common type */
- return NULL;
-}
-
-/* Determine the common data type between two data types.
- * Unlike the common_type__() function, we stop the compiler with an ERROR
- * if no common data type is found.
- */
-symbol_c *visit_expression_type_c::common_type(symbol_c *first_type, symbol_c *second_type) {
-/*
- symbol_c *res = common_type__(first_type, second_type);
- if (NULL == res) ERROR;
- return res;
-*/
- return common_type__(first_type, second_type);
-}
-
-
-/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
- * such as:
- * var_type value_type
- * BOOL BYTE#7 -> returns false
- * INT INT#7 -> returns true
- * INT 7 -> returns true
- * REAL 7.89 -> returns true
- * REAL 7 -> returns true
- * INT 7.89 -> returns false
- * SAFEBOOL BOOL#1 -> returns false !!!
- * etc...
- *
- * NOTE: It is assumed that the var_type is the data type of an lvalue
- */
-bool visit_expression_type_c::is_valid_assignment(symbol_c *var_type, symbol_c *value_type) {
- if (var_type == NULL) {/* STAGE3_ERROR(value_type, value_type, "Var_type == NULL"); */ return false;}
- if (value_type == NULL) {/* STAGE3_ERROR(var_type, var_type, "Value_type == NULL"); */ return false;}
-
- symbol_c *common_type = common_type__(var_type, value_type);
- if (NULL == common_type)
- return false;
- return (typeid(*var_type) == typeid(*common_type));
-}
-
-
-/* Return TRUE if there is a common data type, otherwise return FALSE
- * i.e., return TRUE if both data types may be used simultaneously in an expression
- * such as:
- * BOOL#0 AND BYTE#7 -> returns false
- * 0 AND BYTE#7 -> returns true
- * INT#10 AND INT#7 -> returns true
- * INT#10 AND 7 -> returns true
- * REAL#34.3 AND 7.89 -> returns true
- * REAL#34.3 AND 7 -> returns true
- * INT#10 AND 7.89 -> returns false
- * SAFEBOOL#0 AND BOOL#1 -> returns true !!!
- * etc...
- */
-bool visit_expression_type_c::is_compatible_type(symbol_c *first_type, symbol_c *second_type) {
- if (first_type == NULL || second_type == NULL) {return false;}
- return (NULL != common_type__(first_type, second_type));
-}
-
-
-
-
-/* A helper function... */
-/*
-symbol_c *visit_expression_type_c::compute_boolean_expression(symbol_c *left_type, symbol_c *right_type,
- is_data_type_t is_data_type) {
-*/
-symbol_c *visit_expression_type_c::compute_expression(symbol_c *left_type, symbol_c *right_type, is_data_type_t is_data_type,
- symbol_c *left_expr, symbol_c *right_expr) {
- bool error = false;
-
- if (!(this->*is_data_type)(left_type)) {
- if (debug) printf("visit_expression_type_c::compute_expression(): invalid left_type\n");
- if (left_expr != NULL)
- STAGE3_ERROR(left_expr, left_expr, "Invalid data type of operand, or of data resulting from previous IL instructions.");
- error = true;
- }
- if (!(this->*is_data_type)(right_type)) {
- if (debug) printf("visit_expression_type_c::compute_expression(): invalid right_type\n");
- if (right_expr != NULL)
- STAGE3_ERROR(right_expr, right_expr, "Invalid data type of operand.");
- error = true;
- }
- if (!is_compatible_type(left_type, right_type)) {
- if (debug) printf("visit_expression_type_c::compute_expression(): left_type & right_type are incompatible\n");
- if ((left_expr != NULL) && (right_expr != NULL))
- STAGE3_ERROR(left_expr, right_expr, "Type mismatch between operands.");
- error = true;
- }
-
- if (error)
- return NULL;
- else
- return common_type(left_type, right_type);
-}
-
-
-
-
-/* A helper function... */
-/* check the semantics of a FB or Function non-formal call */
-/* e.g. foo(1, 2, 3, 4); */
-/* If error_count pointer is != NULL, we do not really print out the errors,
- * but rather only count how many errors were found.
- * This is used to support overloaded functions, where we have to check each possible
- * function, one at a time, untill we find a function call without any errors.
- */
-void visit_expression_type_c::check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar, int *error_count) {
- symbol_c *call_param_value, *call_param_type, *param_type;
- identifier_c *param_name;
- function_param_iterator_c fp_iterator(f_decl);
- function_call_param_iterator_c fcp_iterator(f_call);
- int extensible_parameter_highest_index = -1;
-
- /* reset error counter */
- if (error_count != NULL) *error_count = 0;
- /* if use_il_defvar, then the first parameter for the call comes from the il_default_variable */
- if (use_il_defvar) {
- /* The first parameter of the function corresponds to the il_default_variable_type of the function call */
- do {
- param_name = fp_iterator.next();
- if(param_name == NULL) break;
- /* The EN and ENO parameters are default parameters.
- * In the non-formal invocation of a function there can be no assignment of
- * values to these parameters. Therefore, we ignore the parameters declared
- * in the function.
- */
- } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
- /* If the function does not have any parameters (param_name == NULL)
- * then we cannot compare its type with the il_default_variable_type.
- *
- * However, I (Mario) think this is invalid syntax, as it seems to me all functions must
- * have at least one parameter.
- * However, we will make this semantic verification consider it possible, as later
- * versions of the standard may change that syntax.
- * So, instead of generating a syntax error message, we simply check whether the call
- * is passing any more parameters besides the default variable (the il default variable may be ignored
- * in this case, and not consider it as being a parameter being passed to the function).
- * If it does, then we have found a semantic error, otherwise the function call is
- * correct, and we simply return.
- */
- if(param_name == NULL) {
- if (fcp_iterator.next_nf() != NULL)
- STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call.");
- return;
- } else {
- /* param_name != NULL */
- param_type = fp_iterator.param_type();
- if(!is_valid_assignment(param_type, il_default_variable_type)) {
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(f_call, f_call, "In function/FB call, first parameter has invalid data type.");
- }
- }
-
- /* the fisrt parameter (il_def_variable) is correct */
- if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
- extensible_parameter_highest_index = fp_iterator.extensible_param_index();
- }
- } // if (use_il_defvar)
-
-
-
- /* Iterating through the non-formal parameters of the function call */
- while((call_param_value = fcp_iterator.next_nf()) != NULL) {
- /* Obtaining the type of the value being passed in the function call */
- call_param_type = base_type((symbol_c*)call_param_value->accept(*this));
- if (call_param_type == NULL) {
- if (error_count != NULL) (*error_count)++;
- /* the following error will usually occur when ST code uses an identifier, that could refer to an enumerated constant,
- * but was not actually used as a constant in any definitions of an enumerated data type
- */
- else STAGE3_ERROR(call_param_value, call_param_value, "Could not determine data type of value being passed in function/FB call.");
- continue;
- }
-
- /* Iterate to the next parameter of the function being called.
- * Get the name of that parameter, and ignore if EN or ENO.
- */
- do {
- param_name = fp_iterator.next();
- /* If there is no other parameter declared, then we are passing too many parameters... */
- if(param_name == NULL) {
- if (error_count != NULL) (*error_count)++;
- /* Note: We don't want to print out the follwoing error message multiple times, so we return instead of continuing with 'break' */
- else STAGE3_ERROR(f_call, f_call, "Too many parameters in function/FB call."); return;
- }
- } while ((strcmp(param_name->value, "EN") == 0) || (strcmp(param_name->value, "ENO") == 0));
-
- /* Get the parameter type */
- param_type = base_type(fp_iterator.param_type());
- /* If the declared parameter and the parameter from the function call do not have the same type */
- if(!is_valid_assignment(param_type, call_param_type)) {
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(call_param_value, call_param_value, "Type mismatch in function/FB call parameter.");
- }
-
- if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
- extensible_parameter_highest_index = fp_iterator.extensible_param_index();
- }
- }
-
- /* The function call may not have any errors! */
- /* In the case of a call to an extensible function, we store the highest index
- * of the extensible parameters this particular call uses, in the symbol_c object
- * of the function call itself!
- * In calls to non-extensible functions, this value will be set to -1.
- * This information is later used in stage4 to correctly generate the
- * output code.
- */
- int extensible_param_count = -1;
- if (extensible_parameter_highest_index >=0) /* if call to extensible function */
- extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
- il_function_call_c *il_function_call = dynamic_cast<il_function_call_c *>(f_call);
- function_invocation_c *function_invocation = dynamic_cast<function_invocation_c *>(f_call);
- if (il_function_call != NULL) il_function_call ->extensible_param_count = extensible_param_count;
- else if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count;
- // else ERROR; /* this function is also called by Function Blocks, so this is not an error! */
-}
-
-
-/* check semantics of FB call in the IL language using input operators */
-/* e.g. CU, CLK, IN, PT, SR, ... */
-void visit_expression_type_c::check_il_fbcall(symbol_c *il_operator, const char *il_operator_str) {
- symbol_c *call_param_type = il_default_variable_type;
- symbol_c *fb_decl = il_operand_type;
- /* The following should never occur. The function block must be defined,
- * and the FB type being called MUST be in the symtable...
- * This was all already checked at stage 2!
- */
- if (NULL == fb_decl) ERROR;
- if (call_param_type == NULL) ERROR;
-
- /* We also create an identifier_c object, so we can later use it to find the equivalent FB parameter */
- /* Note however that this symbol does not have the correct location (file name and line numbers)
- * so any error messages must use the il_operator symbol to generate the error location
- */
- identifier_c call_param_name(il_operator_str);
-
- /* Obtaining the type of the value being passed in the function call */
- call_param_type = base_type(call_param_type);
- if (call_param_type == NULL) STAGE3_ERROR(il_operator, il_operator, "Could not determine data type of value being passed in FB call.");
-
- /* Find the corresponding parameter of the function being called */
- function_param_iterator_c fp_iterator(fb_decl);
- if(fp_iterator.search(&call_param_name) == NULL) {
- STAGE3_ERROR(il_operand, il_operand, "Called FB does not have an input parameter named %s.", il_operator_str);
- } else {
- /* Get the parameter type */
- symbol_c *param_type = base_type(fp_iterator.param_type());
- /* If the declared parameter and the parameter from the function call have the same type */
- if(!is_valid_assignment(param_type, call_param_type)) STAGE3_ERROR(il_operator, il_operator, "Type mismatch in FB call parameter.");
- }
-}
-
-
-/* A helper function... */
-/* check the semantics of a FB or Function formal call */
-/* e.g. foo(IN1 := 1, OUT1 =>x, EN := true); */
-/* If error_count pointer is != NULL, we do not really print out the errors,
- * but rather only count how many errors were found.
- * This is used to support overloaded functions, where we have to check each possible
- * function, one at a time, untill we find a function call without any errors.
- */
-void visit_expression_type_c::check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count) {
- symbol_c *call_param_value, *call_param_type, *call_param_name, *param_type;
- symbol_c *verify_duplicate_param;
- identifier_c *param_name;
- function_param_iterator_c fp_iterator(f_decl);
- function_call_param_iterator_c fcp_iterator(f_call);
- int extensible_parameter_highest_index = -1;
- identifier_c *extensible_parameter_name;
-
- /* reset error counter */
- if (error_count != NULL) *error_count = 0;
-
- /* Iterating through the formal parameters of the function call */
- while((call_param_name = fcp_iterator.next_f()) != NULL) {
-
- /* Obtaining the value being passed in the function call */
- call_param_value = fcp_iterator.get_current_value();
- /* the following should never occur. If it does, then we have a bug in our code... */
- if (NULL == call_param_value) ERROR;
-
- /* Checking if there are duplicated parameter values */
- verify_duplicate_param = fcp_iterator.search_f(call_param_name);
- if(verify_duplicate_param != call_param_value){
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(call_param_name, verify_duplicate_param, "Duplicated parameter values.");
- }
-
- /* Obtaining the type of the value being passed in the function call */
- call_param_type = (symbol_c*)call_param_value->accept(*this);
- if (call_param_type == NULL) {
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
- /* The data value being passed is possibly any enumerated type value.
- * We do not yet handle semantic verification of enumerated types.
- */
- ERROR;
- }
- call_param_type = base_type(call_param_type);
- if (call_param_type == NULL) STAGE3_ERROR(call_param_name, call_param_value, "Could not determine data type of value being passed in function/FB call.");
-
- /* Find the corresponding parameter of the function being called */
- param_name = fp_iterator.search(call_param_name);
- if(param_name == NULL) {
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(call_param_name, call_param_name, "Invalid parameter in function/FB call.");
- } else {
- /* Get the parameter type */
- param_type = base_type(fp_iterator.param_type());
- /* If the declared parameter and the parameter from the function call have the same type */
- if(!is_valid_assignment(param_type, call_param_type)) {
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(call_param_name, call_param_value, "Type mismatch function/FB call parameter.");
- }
- if (extensible_parameter_highest_index < fp_iterator.extensible_param_index()) {
- extensible_parameter_highest_index = fp_iterator.extensible_param_index();
- extensible_parameter_name = param_name;
- }
- }
- }
-
- /* In the case of a call to an extensible function, we store the highest index
- * of the extensible parameters this particular call uses, in the symbol_c object
- * of the function call itself!
- * In calls to non-extensible functions, this value will be set to -1.
- * This information is later used in stage4 to correctly generate the
- * output code.
- */
- int extensible_param_count = -1;
- if (extensible_parameter_highest_index >=0) /* if call to extensible function */
- extensible_param_count = 1 + extensible_parameter_highest_index - fp_iterator.first_extensible_param_index();
- il_formal_funct_call_c *il_formal_funct_call = dynamic_cast<il_formal_funct_call_c *>(f_call);
- function_invocation_c *function_invocation = dynamic_cast<function_invocation_c *>(f_call);
- if (il_formal_funct_call != NULL) il_formal_funct_call->extensible_param_count = extensible_param_count;
- else if (function_invocation != NULL) function_invocation->extensible_param_count = extensible_param_count;
-// else ERROR; /* this function is also called by Function Blocks, so this is not an error! */
-
- /* We have iterated through all the formal parameters of the function call,
- * and everything seems fine.
- * If the function being called in an extensible function, we now check
- * whether the extensible paramters in the formal invocation do not skip
- * any indexes...
- *
- * f(in1:=0, in2:=0, in4:=0) --> ERROR!!
- */
- if (extensible_parameter_highest_index >=0) { /* if call to extensible function */
- for (int i=fp_iterator.first_extensible_param_index(); i < extensible_parameter_highest_index; i++) {
- char tmp[256];
- if (snprintf(tmp, 256, "%s%d", extensible_parameter_name->value, i) >= 256) ERROR;
- if (fcp_iterator.search_f(tmp) == NULL) {
- /* error in invocation of extensible function */
- if (error_count != NULL) (*error_count)++;
- else STAGE3_ERROR(f_call, f_call, "Missing extensible parameters in call to extensible function.");
- }
- }
- }
-}
-
-
-
-
-/* a helper function... */
-symbol_c *visit_expression_type_c::base_type(symbol_c *symbol) {
- /* NOTE: symbol == NULL is valid. It will occur when, for e.g., an undefined/undeclared symbolic_variable is used
- * in the code.
- */
- if (symbol == NULL) return NULL;
- return (symbol_c *)symbol->accept(search_base_type);
-}
-
-
-/* a helper function... */
-void *visit_expression_type_c::verify_null(symbol_c *symbol){
- if(il_default_variable_type == NULL){
- STAGE3_ERROR(symbol, symbol, "Missing LD instruction (or equivalent) before this instruction.");
- }
- if(il_operand_type == NULL){
- STAGE3_ERROR(symbol, symbol, "This instruction requires an operand.");
- }
- return NULL;
-}
-
-
-/********************************/
-/* B 1.3.3 - Derived data types */
-/********************************/
-void *visit_expression_type_c::visit(data_type_declaration_c *symbol) {
- // TODO !!!
- /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
- return NULL;
-}
-
-
-/*********************/
-/* B 1.4 - Variables */
-/*********************/
-
-void *visit_expression_type_c::visit(symbolic_variable_c *symbol) {
- return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-/********************************************/
-/* B 1.4.1 - Directly Represented Variables */
-/********************************************/
-void *visit_expression_type_c::visit(direct_variable_c *symbol) {
- switch (symbol->value[2]) {
- case 'X': // bit - 1 bit
- return (void *)&bool_type_name;
- case 'B': // byte - 8 bits
- return (void *)&byte_type_name;
- case 'W': // word - 16 bits
- return (void *)&word_type_name;
- case 'D': // double word - 32 bits
- return (void *)&dword_type_name;
- case 'L': // long word - 64 bits
- return (void *)&lword_type_name;
- default: // if none of the above, then the empty string was used <=> boolean
- return (void *)&bool_type_name;
- }
-}
-
-/*************************************/
-/* B 1.4.2 - Multi-element variables */
-/*************************************/
-void *visit_expression_type_c::visit(array_variable_c *symbol) {
- return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-void *visit_expression_type_c::visit(structured_variable_c *symbol) {
- return search_varfb_instance_type->get_basetype_decl(symbol);
-}
-
-
-
-/********************************/
-/* B 1.7 Configuration elements */
-/********************************/
-void *visit_expression_type_c::visit(configuration_declaration_c *symbol) {
- // TODO !!!
- /* for the moment we must return NULL so semantic analysis of remaining code is not interrupted! */
- return NULL;
-}
-
-
-/****************************************/
-/* B.2 - Language IL (Instruction List) */
-/****************************************/
-/***********************************/
-/* B 2.1 Instructions and Operands */
-/***********************************/
-/*| instruction_list il_instruction */
-/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
- * We do not need to do anything here...
- */
-// void *visit_expression_type_c::visit(instruction_list_c *symbol)
-
-/* | label ':' [il_incomplete_instruction] eol_list */
-//SYM_REF2(il_instruction_c, label, il_instruction)
-// void *visit_expression_type_c::visit(il_instruction_c *symbol);
-
-
-/* | il_simple_operator [il_operand] */
-// SYM_REF2(il_simple_operation_c, il_simple_operator, il_operand)
-void *visit_expression_type_c::visit(il_simple_operation_c *symbol) {
- if (il_error)
- return NULL;
-
- /* determine the data type of the operand */
- il_operand = symbol->il_operand;
- if (symbol->il_operand != NULL){
- il_operand_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
- } else {
- il_operand_type = NULL;
- }
- /* recursive call to see whether data types are compatible */
- symbol->il_simple_operator->accept(*this);
-
- il_operand_type = NULL;
- il_operand = NULL;
- return NULL;
-}
-
-// | function_name [il_operand_list] */
-//SYM_REF2(il_function_call_c, function_name, il_operand_list)
-void *visit_expression_type_c::visit(il_function_call_c *symbol) {
- if (il_error)
- return NULL;
-
- symbol_c *return_data_type = NULL;
-
- /* First find the declaration of the function being called! */
- function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
- function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
- if (lower == function_symtable.end()) ERROR;
-
- int error_count = 0;
- int *error_count_ptr = NULL;
-
- function_symtable_t::iterator second = lower;
- second++;
- if (second != upper)
- /* This is a call to an overloaded function... */
- error_count_ptr = &error_count;
-
- for(; lower != upper; lower++) {
- function_declaration_c *f_decl = function_symtable.get_value(lower);
-
- check_nonformal_call(symbol, f_decl, true, error_count_ptr);
-
- if (0 == error_count) {
- /* Either:
- * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)
- * (ii) we have a call to an overloaded function, with no errors!
- */
-
- /* Store the pointer to the declaration of the function being called.
- * This data will be used by stage 4 to call the correct function.
- * Mostly needed to disambiguate overloaded functions...
- * See comments in absyntax.def for more details
- */
- symbol->called_function_declaration = f_decl;
- /* determine the base data type returned by the function being called... */
- return_data_type = base_type(f_decl->type_name);
- /* If the following occurs, then we must have some big bug in the syntax parser (stage 2)... */
- if (NULL == return_data_type) ERROR;
- /* set the new data type of the default variable for the following verifications... */
- il_default_variable_type = return_data_type;
- return NULL;
- }
- }
-
- /* No compatible function was found for this function call */
- STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
- return NULL;
-}
-
-
-/* | il_expr_operator '(' [il_operand] eol_list [simple_instr_list] ')' */
-// SYM_REF3(il_expression_c, il_expr_operator, il_operand, simple_instr_list);
-void *visit_expression_type_c::visit(il_expression_c *symbol) {
- if (il_error)
- return NULL;
-
- symbol_c *il_default_variable_type_back = il_default_variable_type;
-
- il_parenthesis_level++;
-
- if(symbol->il_operand != NULL) {
- il_default_variable_type = base_type((symbol_c *)symbol->il_operand->accept(*this));
- } else {
- il_default_variable_type = NULL;
- }
-
- if(symbol->simple_instr_list != NULL) {
- symbol->simple_instr_list->accept(*this);
- }
-
- il_parenthesis_level--;
- if (il_parenthesis_level < 0) ERROR;
-
- il_operand = symbol->simple_instr_list;
- il_operand_type = il_default_variable_type;
- il_default_variable_type = il_default_variable_type_back;
-
- /* Now check the if the data type semantics of operation are correct,
- * but only if no previous error has been found...
- */
- if (!il_error)
- symbol->il_expr_operator->accept(*this);
-
- il_operand_type = NULL;
- il_operand = NULL;
- return NULL;
-}
-
-
-#if 0
-/* il_jump_operator label */
-SYM_REF2(il_jump_operation_c, il_jump_operator, label)
-void *visit_expression_type_c::visit(il_jump_operation_c *symbol);
-#endif
-
-
-/* il_call_operator prev_declared_fb_name
- * | il_call_operator prev_declared_fb_name '(' ')'
- * | il_call_operator prev_declared_fb_name '(' eol_list ')'
- * | il_call_operator prev_declared_fb_name '(' il_operand_list ')'
- * | il_call_operator prev_declared_fb_name '(' eol_list il_param_list ')'
- */
-/* SYM_REF4(il_fb_call_c, il_call_operator, fb_name, il_operand_list, il_param_list) */
-void *visit_expression_type_c::visit(il_fb_call_c *symbol) {
- if (il_error)
- return NULL;
-
- /* first check whether the il_default_variable is of the correct type
- * for the CAL / CALC / CALCN operator being used...
- */
- symbol->il_call_operator->accept(*this);
-
- /* Now check the FB call itself... */
-
- /* First we find the declaration of the FB type of the FB instance being called... */
- /* e.g. Function_block foo_fb_type
- * ...
- * End_Function_Block
- *
- * Program test
- * var fb1 : foo_fb_type; end_var
- * fb1(...)
- * End_Program
- *
- * search_varfb_instance_type->get_basetype_decl( identifier_c("fb1") )
- * in the scope of Program 'test'
- * will return the fb declaration of foo_fb_type !!
- */
-#if 0
- symbol_c *fb_decl_symbol = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
- /* The following should never occur. The function block must be defined,
- * and the FB type being called MUST be in the symtable...
- * This was all already checked at stage 2!
- */
- if (NULL == fb_decl_symbol) ERROR;
-
- function_block_declaration_c *fb_decl = dynamic_cast<function_block_declaration_c *>(fb_decl_symbol);
- /* should never occur. ... */
- if (NULL == fb_decl) ERROR;
-#endif
- symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
- /* The following should never occur. The function block must be defined,
- * and the FB type being called MUST be in the symtable...
- * This was all already checked at stage 2!
- */
- if (NULL == fb_decl) ERROR;
-
- /* now check the semantics of the fb call... */
- /* If the syntax parser is working correctly, exactly one of the
- * following two symbols will be NULL, while the other is != NULL.
- */
- if (NULL != symbol->il_operand_list) check_nonformal_call(symbol, fb_decl);
- if (NULL != symbol->il_param_list) check_formal_call (symbol, fb_decl);
-
- return NULL;
-}
-
-
-
-/* | function_name '(' eol_list [il_param_list] ')' */
-/* SYM_REF2(il_formal_funct_call_c, function_name, il_param_list) */
-void *visit_expression_type_c::visit(il_formal_funct_call_c *symbol) {
- if (il_error)
- return NULL;
-
- symbol_c *return_data_type = NULL;
- function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
- function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
-
- if (lower == function_symtable.end()) {
- function_type_t current_function_type = get_function_type((identifier_c *)symbol->function_name);
- if (current_function_type == function_none) ERROR;
- return NULL;
- }
-
- int error_count = 0;
- int *error_count_ptr = NULL;
-
- function_symtable_t::iterator second = lower;
- second++;
- if (second != upper)
- /* This is a call to an overloaded function... */
- error_count_ptr = &error_count;
-
- for(; lower != upper; lower++) {
- function_declaration_c *f_decl = function_symtable.get_value(lower);
-
- /* check semantics of data passed in the function call... */
- check_formal_call(symbol, f_decl, error_count_ptr);
-
- if (0 == error_count) {
- /* Either:
- * (i) we have a call to a non-overloaded function (error_cnt_ptr is NULL!, so error_count won't change!)
- * (ii) we have a call to an overloaded function, with no errors!
- */
-
- /* Store the pointer to the declaration of the function being called.
- * This data will be used by stage 4 to call the correct function.
- * Mostly needed to disambiguate overloaded functions...
- * See comments in absyntax.def for more details
- */
- symbol->called_function_declaration = f_decl;
- /* determine the base data type returned by the function being called... */
- return_data_type = base_type(f_decl->type_name);
- /* the following should never occur. If it does, then we have a bug in the syntax parser (stage 2)... */
- if (NULL == return_data_type) ERROR;
- /* the data type of the data returned by the function, and stored in the il default variable... */
- il_default_variable_type = return_data_type;
- return NULL;
- }
- }
-
- /* No compatible function was found for this function call */
- STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
- return NULL;
-}
-
-
-#if 0
-/* | il_operand_list ',' il_operand */
-SYM_LIST(il_operand_list_c)
-void *visit_expression_type_c::visit(il_operand_list_c *symbol);
-
-/* | simple_instr_list il_simple_instruction */
-SYM_LIST(simple_instr_list_c)
-void *visit_expression_type_c::visit(simple_instr_list_c *symbol);
-
-/* | il_initial_param_list il_param_instruction */
-SYM_LIST(il_param_list_c)
-void *visit_expression_type_c::visit(il_param_list_c *symbol);
-
-/* il_assign_operator il_operand
- * | il_assign_operator '(' eol_list simple_instr_list ')'
- */
-SYM_REF3(il_param_assignment_c, il_assign_operator, il_operand, simple_instr_list)
-void *visit_expression_type_c::visit(il_param_assignment_c *symbol);
-/* il_assign_out_operator variable */
-SYM_REF2(il_param_out_assignment_c, il_assign_out_operator, variable)
-void *visit_expression_type_c::visit(il_param_out_assignment_c *symbol);
-
-#endif
-
-
-/*******************/
-/* B 2.2 Operators */
-/*******************/
-
-//SYM_REF0(LD_operator_c)
-void *visit_expression_type_c::visit(LD_operator_c *symbol) {
- if (0 == il_parenthesis_level)
- il_error = false;
-
- if(il_operand_type == NULL)
- STAGE3_ERROR(symbol, symbol, "LD operator requires an operand.");
- il_default_variable_type = il_operand_type;
- return NULL;
-}
-
-// SYM_REF0(LDN_operator_c)
-void *visit_expression_type_c::visit(LDN_operator_c *symbol) {
- if(il_operand_type == NULL)
- STAGE3_ERROR(symbol, symbol, "LDN operator requires an operand.");
- if(!is_ANY_BIT_compatible(il_operand_type))
- STAGE3_ERROR(symbol, il_operand, "invalid data type of LDN operand, should be of type ANY_BIT.");
- il_default_variable_type = il_operand_type;
- return NULL;
-}
-
-// SYM_REF0(ST_operator_c)
-void *visit_expression_type_c::visit(ST_operator_c *symbol) {
- verify_null(symbol);
-
- if(!is_valid_assignment(il_operand_type, il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
- /* TODO: check whether il_operand_type is an LVALUE !! */
- /* data type of il_default_variable_type is unchanged... */
- // il_default_variable_type = il_default_variable_type;
- return NULL;
-}
-
-// SYM_REF0(STN_operator_c)
- void *visit_expression_type_c::visit(STN_operator_c *symbol) {
- verify_null(symbol);
- if(!is_valid_assignment(il_operand_type, il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "Type mismatch in ST operation.");
- /* TODO: check whether il_operand_type is an LVALUE !! */
- if(!is_ANY_BIT_compatible(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "invalid data type of il_default_variable for STN operand, should be of type ANY_BIT.");
- if(!is_ANY_BIT_compatible(il_operand_type))
- STAGE3_ERROR(symbol, il_operand, "invalid data type of STN operand, should be of type ANY_BIT.");
- /* data type of il_default_variable_type is unchanged... */
- // il_default_variable_type = il_default_variable_type;
- return NULL;
-}
-
-//SYM_REF0(NOT_operator_c)
-void *visit_expression_type_c::visit(NOT_operator_c *symbol) {
- if(il_operand_type != NULL){
- STAGE3_ERROR(symbol, il_operand, "NOT operator may not have an operand.");
- return NULL;
- }
- if(il_default_variable_type == NULL) {
- STAGE3_ERROR(symbol, symbol, "Il default variable should not be NULL.");
- return NULL;
- }
- if(!is_ANY_BIT_compatible(il_default_variable_type)) {
- STAGE3_ERROR(symbol, symbol, "Il default variable should be of type ANY_BIT.");
- return NULL;
- }
- /* data type of il_default_variable_type is unchanged... */
- // il_default_variable_type = il_default_variable_type;
- return NULL;
-}
-
-// SYM_REF0(S_operator_c)
-void *visit_expression_type_c::visit(S_operator_c *symbol) {
- verify_null(symbol);
- if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
- if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator S requires operand of type BOOL.");}
- /* TODO: check whether il_operand_type is an LVALUE !! */
- /* data type of il_default_variable_type is unchanged... */
- // il_default_variable_type = il_default_variable_type;
- return NULL;
-}
-
-// SYM_REF0(R_operator_c)
-void *visit_expression_type_c::visit(R_operator_c *symbol) {
- verify_null(symbol);
- if (!is_BOOL_type(il_default_variable_type)) {STAGE3_ERROR(symbol, symbol, "IL default variable should be BOOL type.");}
- if (!is_BOOL_type(il_operand_type)) {STAGE3_ERROR(symbol, il_operand, "operator R requires operand of type BOOL.");}
- /* TODO: check whether il_operand_type is an LVALUE !! */
- /* data type of il_default_variable_type is unchanged... */
- // il_default_variable_type = il_default_variable_type;
- return NULL;
-}
-
-
-// SYM_REF0(S1_operator_c)
-void *visit_expression_type_c::visit(S1_operator_c *symbol){
- check_il_fbcall(symbol, "S1");
- return NULL;
-}
-
-// SYM_REF0(R1_operator_c)
-void *visit_expression_type_c::visit(R1_operator_c *symbol) {
- check_il_fbcall(symbol, "R1");
- return NULL;
-}
-
-// SYM_REF0(CLK_operator_c)
-void *visit_expression_type_c::visit(CLK_operator_c *symbol) {
- check_il_fbcall(symbol, "CLK");
- return NULL;
-}
-
-// SYM_REF0(CU_operator_c)
-void *visit_expression_type_c::visit(CU_operator_c *symbol) {
- check_il_fbcall(symbol, "CU");
- return NULL;
-}
-
-// SYM_REF0(CD_operator_c)
-void *visit_expression_type_c::visit(CD_operator_c *symbol) {
- check_il_fbcall(symbol, "CD");
- return NULL;
-}
-
-// SYM_REF0(PV_operator_c)
-void *visit_expression_type_c::visit(PV_operator_c *symbol) {
- check_il_fbcall(symbol, "PV");
- return NULL;
-}
-
-// SYM_REF0(IN_operator_c)
-void *visit_expression_type_c::visit(IN_operator_c *symbol) {
- check_il_fbcall(symbol, "IN");
- return NULL;
-}
-
-// SYM_REF0(PT_operator_c)
-void *visit_expression_type_c::visit(PT_operator_c *symbol) {
- check_il_fbcall(symbol, "PT");
- return NULL;
-}
-
-//SYM_REF0(AND_operator_c)
-void *visit_expression_type_c::visit(AND_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-//SYM_REF0(OR_operator_c)
-void *visit_expression_type_c::visit(OR_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-//SYM_REF0(XOR_operator_c)
-void *visit_expression_type_c::visit(XOR_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(ANDN_operator_c)
-void *visit_expression_type_c::visit(ANDN_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(ORN_operator_c)
-void *visit_expression_type_c::visit(ORN_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(XORN_operator_c)
-void *visit_expression_type_c::visit(XORN_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_BIT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(ADD_operator_c)
-void *visit_expression_type_c::visit(ADD_operator_c *symbol) {
- verify_null(symbol);
- symbol_c *left_type = il_default_variable_type;
- symbol_c *right_type = il_operand_type;
-
-/* The following is not required, it is already handled by compute_expression() ... */
-/*
- if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &time_type_name;
-*/
-
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &safetod_type_name;
-
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &safedt_type_name;
-
- else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(SUB_operator_c)
-void *visit_expression_type_c::visit(SUB_operator_c *symbol) {
- verify_null(symbol);
- symbol_c *left_type = il_default_variable_type;
- symbol_c *right_type = il_operand_type;;
-
-/* The following is not required, it is already handled by compute_expression() ... */
-/*
- if (typeid(*left_type) == typeid(time_type_name_c) && typeid(*right_type) == typeid(time_type_name_c))
- il_default_variable_type = &time_type_name;
-*/
-
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &tod_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &safetod_type_name;
-
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &dt_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c))
- il_default_variable_type = &safedt_type_name;
-
- else if (is_type(left_type, date_type_name_c) && is_type(right_type, date_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, date_type_name_c) && is_type(right_type, safedate_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c))
- il_default_variable_type = &safetime_type_name;
-
- else if (is_type(left_type, tod_type_name_c) && is_type(right_type, tod_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, tod_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetod_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetod_type_name_c))
- il_default_variable_type = &safetime_type_name;
-
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, dt_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, dt_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, dt_type_name_c) && is_type(right_type, safedt_type_name_c))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safedt_type_name_c))
- il_default_variable_type = &safetime_type_name;
-
- else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(MUL_operator_c)
-void *visit_expression_type_c::visit(MUL_operator_c *symbol) {
- verify_null(symbol);
- symbol_c *left_type = il_default_variable_type;
- symbol_c *right_type = il_operand_type;
-
- if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
- il_default_variable_type = &safetime_type_name;
- /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
- * this next line is really only to check for integers/reals of undefined type on 'right_type'...
- */
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
- il_default_variable_type = &safetime_type_name;
-
- else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(DIV_operator_c)
-void *visit_expression_type_c::visit(DIV_operator_c *symbol) {
- verify_null(symbol);
- symbol_c *left_type = il_default_variable_type;
- symbol_c *right_type = il_operand_type;
-
- if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
- il_default_variable_type = &time_type_name;
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
- il_default_variable_type = &safetime_type_name;
- /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
- * this next line is really only to check for integers/reals of undefined type on 'right_type'...
- */
- else if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
- il_default_variable_type = &safetime_type_name;
-
- else il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_NUM_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(MOD_operator_c)
-void *visit_expression_type_c::visit(MOD_operator_c *symbol) {
- verify_null(symbol);
- il_default_variable_type = compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_INT_compatible,
- symbol , il_operand);
- return NULL;
-}
-
-// SYM_REF0(GT_operator_c)
-void *visit_expression_type_c::visit(GT_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-//SYM_REF0(GE_operator_c)
-void *visit_expression_type_c::visit(GE_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-//SYM_REF0(EQ_operator_c)
-void *visit_expression_type_c::visit(EQ_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-//SYM_REF0(LT_operator_c)
-void *visit_expression_type_c::visit(LT_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-//SYM_REF0(LE_operator_c)
-void *visit_expression_type_c::visit(LE_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-//SYM_REF0(NE_operator_c)
-void *visit_expression_type_c::visit(NE_operator_c *symbol) {
- verify_null(symbol);
- compute_expression(il_default_variable_type, il_operand_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible,
- symbol , il_operand);
- il_default_variable_type = &search_expression_type_c::bool_type_name;
- return NULL;
-}
-
-// SYM_REF0(CAL_operator_c)
-void *visit_expression_type_c::visit(CAL_operator_c *symbol) {
- return NULL;
-}
-
-// SYM_REF0(CALC_operator_c)
-void *visit_expression_type_c::visit(CALC_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "CALC: il default variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "CALC operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-// SYM_REF0(CALCN_operator_c)
-void *visit_expression_type_c::visit(CALCN_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "CALCN: il_default_variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "CALCN operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-// SYM_REF0(RET_operator_c)
-void *visit_expression_type_c::visit(RET_operator_c *symbol) {
- return NULL;
-}
-
-// SYM_REF0(RETC_operator_c)
-void *visit_expression_type_c::visit(RETC_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "RETC: il default variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "RETC operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-// SYM_REF0(RETCN_operator_c)
-void *visit_expression_type_c::visit(RETCN_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "RETCN: il_default_variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "RETCN operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-// SYM_REF0(JMP_operator_c)
-void *visit_expression_type_c::visit(JMP_operator_c *symbol){
- return NULL;
-}
-
-// SYM_REF0(JMPC_operator_c)
-void *visit_expression_type_c::visit(JMPC_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "JMPC: il default variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "JMPC operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-// SYM_REF0(JMPCN_operator_c)
-void *visit_expression_type_c::visit(JMPCN_operator_c *symbol) {
- if(il_default_variable_type == NULL)
- STAGE3_ERROR(symbol, symbol, "JMPCN: il_default_variable should not be NULL.");
- if (!is_BOOL_type(il_default_variable_type))
- STAGE3_ERROR(symbol, symbol, "JMPCN operator requires il_default_variable to be of type BOOL.");
- return NULL;
-}
-
-/* Symbol class handled together with function call checks */
-/* any_identifier ASSIGN */
-// SYM_REF1(il_assign_operator_c, variable_name)
-// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, variable_name);
-
-/* Symbol class handled together with function call checks */
-/*| [NOT] any_identifier SENDTO */
-// SYM_REF2(il_assign_out_operator_c, option, variable_name)
-// void *visit_expression_type_c::visit(il_assign_operator_c *symbol, option, variable_name);
-
-
-
-
-
-/***************************************/
-/* B.3 - Language ST (Structured Text) */
-/***************************************/
-/***********************/
-/* B 3.1 - Expressions */
-/***********************/
-
-void *visit_expression_type_c::visit(or_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(xor_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(and_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_BIT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(equ_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(notequ_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_OR_ENUMERATED_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(lt_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(gt_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(le_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(ge_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_ELEMENTARY_compatible, symbol->l_exp, symbol->r_exp);
- return &search_expression_type_c::bool_type_name;
-}
-
-
-void *visit_expression_type_c::visit(add_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-/* The following is already checked in compute_expression */
-/*
- if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&time_type_name;
-*/
-
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&safetod_type_name;
-
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&safedt_type_name;
-
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(sub_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
-/* The following is already checked in compute_expression */
-/*
- if (is_type(left_type, time_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&time_type_name;
-*/
-
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&tod_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&safetod_type_name;
-
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, time_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&dt_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safetime_type_name_c))
- return (void *)&safedt_type_name;
-
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, tod_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, tod_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, tod_type_name_c) && is_type(right_type, safetod_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safetod_type_name_c) && is_type(right_type, safetod_type_name_c))
- return (void *)&safetime_type_name;
-
- if (is_type(left_type, date_type_name_c) && is_type(right_type, date_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safedate_type_name_c) && is_type(right_type, date_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, date_type_name_c) && is_type(right_type, safedate_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safedate_type_name_c) && is_type(right_type, safedate_type_name_c))
- return (void *)&safetime_type_name;
-
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, dt_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, dt_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, dt_type_name_c) && is_type(right_type, safedt_type_name_c))
- return (void *)&time_type_name;
- if (is_type(left_type, safedt_type_name_c) && is_type(right_type, safedt_type_name_c))
- return (void *)&safetime_type_name;
-
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_MAGNITUDE_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(mul_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
- if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type))
- return (void *)&time_type_name;
- if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
- return (void *)&time_type_name;
- if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
- return (void *)&safetime_type_name;
- /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
- * this next line is really only to check for integers/reals of undefined type on 'right_type'...
- */
- if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
- return (void *)&safetime_type_name;
-
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(div_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
- if (is_type(left_type, time_type_name_c) && is_ANY_NUM_compatible(right_type))
- return (void *)&time_type_name;
- if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_type(right_type))
- return (void *)&time_type_name;
- if (is_type(left_type, safetime_type_name_c) && is_ANY_SAFENUM_type(right_type))
- return (void *)&safetime_type_name;
- /* Since we have already checked for ANY_NUM_type and ANY_SAFENUM_type in the previous lines,
- * this next line is really only to check for integers/reals of undefined type on 'right_type'...
- */
- if (is_type(left_type, safetime_type_name_c) && is_ANY_NUM_compatible(right_type))
- return (void *)&safetime_type_name;
-
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_NUM_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(mod_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- return compute_expression(left_type, right_type, &visit_expression_type_c::is_ANY_INT_compatible, symbol->l_exp, symbol->r_exp);
-}
-
-
-void *visit_expression_type_c::visit(power_expression_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
- if (!is_ANY_REAL_compatible(left_type))
- STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "first operand of ** operator has invalid data type, should be of type ANY_REAL.");
- if (!is_ANY_NUM_compatible(right_type))
- STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "second operand of ** operator has invalid data type, should be of type ANY_NUM.");
-
- return (void *)left_type;
-}
-
-
-void *visit_expression_type_c::visit(neg_expression_c *symbol) {
- symbol_c *exp_type = base_type((symbol_c *)symbol->exp->accept(*this));
- if (!is_ANY_MAGNITUDE_compatible(exp_type))
- STAGE3_ERROR(symbol, symbol, "operand of negate expression '-' has invalid data type, should be of type ANY_MAGNITUDE.");
-
- return exp_type;
-}
-
-
-void *visit_expression_type_c::visit(not_expression_c *symbol) {
- symbol_c *type = base_type((symbol_c *)symbol->exp->accept(*this));
- return compute_expression(type, type, &visit_expression_type_c::is_ANY_BIT_compatible, NULL, symbol->exp);
-}
-
-
-void *visit_expression_type_c::visit(function_invocation_c *symbol) {
- function_symtable_t::iterator lower = function_symtable.lower_bound(symbol->function_name);
- function_symtable_t::iterator upper = function_symtable.upper_bound(symbol->function_name);
- if (lower == function_symtable.end()) ERROR;
-
- function_symtable_t::iterator second = lower;
- second++;
- if (second == upper) {
- /* call to a function that is not overloaded. */
- /* now check the semantics of the function call... */
- /* If the syntax parser is working correctly, exactly one of the
- * following two symbols will be NULL, while the other is != NULL.
- */
- function_declaration_c *f_decl = function_symtable.get_value(lower);
- if (symbol-> formal_param_list != NULL) check_formal_call (symbol, f_decl);
- if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl);
- /* Store the pointer to the declaration of the function being called.
- * This data will be used by stage 4 to call the correct function.
- * Mostly needed to disambiguate overloaded functions...
- * See comments in absyntax.def for more details
- */
- symbol->called_function_declaration = f_decl;
- return base_type(f_decl->type_name);
- }
-
- /* This is a call to an overloaded function... */
- if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!!\n");
- for(; lower != upper; lower++) {
- if (debug) printf("visit_expression_type_c::visit(function_invocation_c *symbol): FOUND CALL TO OVERLOADED FUNCTION!! iterating...\n");
- int error_count = 0;
- function_declaration_c *f_decl = function_symtable.get_value(lower);
- if (symbol-> formal_param_list != NULL) check_formal_call (symbol, f_decl, &error_count);
- if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, f_decl, false, &error_count);
- if (0 == error_count) {
- /* Store the pointer to the declaration of the function being called.
- * This data will be used by stage 4 to call the correct function.
- * Mostly needed to disambiguate overloaded functions...
- * See comments in absyntax.def for more details
- */
- symbol->called_function_declaration = f_decl;
- return base_type(f_decl->type_name);
- }
- }
-
- /* No compatible function was found for this function call */
- STAGE3_ERROR(symbol, symbol, "Call to an overloaded function with invalid parameter type.");
- return NULL;
-}
-
-/********************/
-/* B 3.2 Statements */
-/********************/
-// SYM_LIST(statement_list_c)
-/* The visitor of the base class search_visitor_c will handle calling each instruction in the list.
- * We do not need to do anything here...
- */
-// void *visit_expression_type_c::visit(statement_list_c *symbol)
-
-
-/*********************************/
-/* B 3.2.1 Assignment Statements */
-/*********************************/
-
-void *visit_expression_type_c::visit(assignment_statement_c *symbol) {
- symbol_c *left_type = base_type((symbol_c *)symbol->l_exp->accept(*this));
- symbol_c *right_type = base_type((symbol_c *)symbol->r_exp->accept(*this));
-
- if (debug) {
- printf("visit_expression_type_c::visit(assignment_statement_c) called. Checking --->");
- symbolic_variable_c *hi = dynamic_cast<symbolic_variable_c *>(symbol->l_exp);
- if (hi != NULL) {
- identifier_c *hi1 = dynamic_cast<identifier_c *>(hi->var_name);
- if (hi1 != NULL) printf("%s", hi1->value);
- }
- printf(" := ");
- hex_integer_c *hi2 = dynamic_cast<hex_integer_c *>(symbol->r_exp);
- if (hi2 != NULL) printf("%s", hi2->value);
- printf("\n");
- } // if (debug)
-
- if (NULL == left_type) {
- STAGE3_ERROR(symbol->l_exp, symbol->l_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n");
- } else if (NULL == right_type) {
- STAGE3_ERROR(symbol->r_exp, symbol->r_exp, "Could not determine data type of expression (undefined variable, constant, or structure element?).\n");
- } else if (!is_valid_assignment(left_type, right_type))
- STAGE3_ERROR(symbol, symbol, "data type mismatch in assignment statement!\n");
-
- return NULL;
-}
-
-
-
-/*****************************************/
-/* B 3.2.2 Subprogram Control Statements */
-/*****************************************/
-
-/* RETURN */
-// SYM_REF0(return_statement_c)
-
-
-/* fb_name '(' [param_assignment_list] ')' */
-/* param_assignment_list -> may be NULL ! */
-// SYM_REF3(fb_invocation_c, fb_name, formal_param_list, nonformal_param_list)
-void *visit_expression_type_c::visit(fb_invocation_c *symbol) {
- symbol_c *fb_decl = search_varfb_instance_type->get_basetype_decl(symbol->fb_name);
- /* The following should never occur. The function block must be defined,
- * and the FB type being called MUST be in the symtable...
- * This was all already checked at stage 2!
- */
- if (NULL == fb_decl) ERROR;
-
- /* now check the semantics of the fb call... */
- /* If the syntax parser is working correctly, exactly one of the
- * following two symbols will be NULL, while the other is != NULL.
- */
- if (symbol-> formal_param_list != NULL) check_formal_call (symbol, fb_decl);
- if (symbol->nonformal_param_list != NULL) check_nonformal_call(symbol, fb_decl);
-
- return NULL;
-}
-
-
-#if 0
-/* helper symbol for fb_invocation */
-/* param_assignment_list ',' param_assignment */
-SYM_LIST(param_assignment_list_c)
-
-/* variable_name ASSIGN expression */
-SYM_REF2(input_variable_param_assignment_c, variable_name, expression)
-
-/* [NOT] variable_name '=>' variable */
-SYM_REF3(output_variable_param_assignment_c, not_param, variable_name, variable)
-
-/* helper CLASS for output_variable_param_assignment */
-SYM_REF0(not_paramassign_c)
-#endif
-
-/********************************/
-/* B 3.2.3 Selection Statements */
-/********************************/
-
-/* IF expression THEN statement_list elseif_statement_list ELSE statement_list END_IF */
-// SYM_REF4(if_statement_c, expression, statement_list, elseif_statement_list, else_statement_list)
-void *visit_expression_type_c::visit(if_statement_c *symbol) {
- symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
- if (!is_BOOL_type(expr_type)) STAGE3_ERROR(symbol->expression,symbol->expression,"IF conditional expression is not of boolean type.");
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
- if (NULL != symbol->elseif_statement_list)
- symbol->elseif_statement_list->accept(*this);
- if (NULL != symbol->else_statement_list)
- symbol->else_statement_list->accept(*this);
- return NULL;
-}
-
-/* helper symbol for if_statement */
-// SYM_LIST(elseif_statement_list_c)
-// void *visit_expression_type_c::visit(elseif_statement_list_c *symbol) { }
-
-/* helper symbol for elseif_statement_list */
-/* ELSIF expression THEN statement_list */
-// SYM_REF2(elseif_statement_c, expression, statement_list)
-void *visit_expression_type_c::visit(elseif_statement_c *symbol) {
- symbol_c *elseif_expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
- if(!is_BOOL_type(elseif_expr_type)) STAGE3_ERROR(symbol->expression,symbol->expression,"ELSIF conditional expression is not of boolean type.");
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
- return NULL;
-}
-
-
-/* CASE expression OF case_element_list ELSE statement_list END_CASE */
-// SYM_REF3(case_statement_c, expression, case_element_list, statement_list)
-void *visit_expression_type_c::visit(case_statement_c *symbol) {
- case_expression_type = base_type((symbol_c*)symbol->expression->accept(*this));
- if (NULL != case_expression_type) {
- if (NULL != symbol->case_element_list)
- symbol->case_element_list->accept(*this);
- }
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
- return NULL;
-}
-
-#if 0
-/* helper symbol for case_statement */
-// SYM_LIST(case_element_list_c)
-// void *visit_expression_type_c::visit(case_element_list_c *symbol);
-
-/* case_list ':' statement_list */
-// SYM_REF2(case_element_c, case_list, statement_list)
-void *visit_expression_type_c::visit(case_element_c *symbol);
-#endif
-
-// SYM_LIST(case_list_c)
-void *visit_expression_type_c::visit(case_list_c *symbol) {
- symbol_c *element_type;
- for(int i = 0; i < symbol->n; i++) {
- element_type = (symbol_c *)symbol->elements[i]->accept(*this);
- if (NULL == element_type) {
- STAGE3_ERROR(symbol->elements[i], symbol->elements[i], "Case list element has undefined data type.");
- } 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.");
- }
- }
- }
- return NULL;
-}
-
-/********************************/
-/* B 3.2.4 Iteration Statements */
-/********************************/
-
-/* FOR control_variable ASSIGN expression TO expression [BY expression] DO statement_list END_FOR */
-// SYM_REF5(for_statement_c, control_variable, beg_expression, end_expression, by_expression, statement_list)
-void *visit_expression_type_c::visit(for_statement_c *symbol) {
- symbol_c *var_type = (symbol_c*)symbol->control_variable->accept(*this);
- if (NULL == var_type) ERROR;
- var_type = base_type(var_type);
- 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) {
- /* 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->beg_expression, symbol->beg_expression, "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) {
- /* 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->end_expression, symbol->end_expression, "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) {
- /* 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->by_expression, symbol->by_expression, "Data type mismatch between control variable and BY value.");
- }
- }
- // DO
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
- return NULL;
-}
-
-
-/* WHILE expression DO statement_list END_WHILE */
-// SYM_REF2(while_statement_c, expression, statement_list)
-void *visit_expression_type_c::visit(while_statement_c *symbol) {
- symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
- if (NULL != expr_type) {
- if(!is_BOOL_type(expr_type))
- STAGE3_ERROR(symbol->expression,symbol->expression,"WHILE conditional expression is not of boolean type.");
- }
-
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
- return NULL;
-}
-
-/* REPEAT statement_list UNTIL expression END_REPEAT */
-// SYM_REF2(repeat_statement_c, statement_list, expression)
-void *visit_expression_type_c::visit(repeat_statement_c *symbol) {
- if (NULL != symbol->statement_list)
- symbol->statement_list->accept(*this);
-
- symbol_c *expr_type = base_type((symbol_c*)symbol->expression->accept(*this));
- if (NULL != expr_type) {
- if(!is_BOOL_type(expr_type))
- STAGE3_ERROR(symbol->expression,symbol->expression,"REPEAT conditional expression is not of boolean type.");
- }
- return NULL;
-}
-
-/* EXIT */
-// SYM_REF0(exit_statement_c)
-
-
-
--- a/stage3/visit_expression_type.hh Wed Feb 01 13:01:08 2012 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,389 +0,0 @@
-/*
- * matiec - a compiler for the programming languages defined in IEC 61131-3
- *
- * Copyright (C) 2009-2011 Mario de Sousa (msousa@fe.up.pt)
- * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- * This code is made available on the understanding that it will not be
- * used in safety-critical situations without a full and competent review.
- */
-
-/*
- * An IEC 61131-3 compiler.
- *
- * Based on the
- * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10)
- *
- */
-
-/* Verify whether the semantic rules of data type compatibility are being followed.
- *
- * For example:
- */
-
-#include "../absyntax_utils/absyntax_utils.hh"
-
-class visit_expression_type_c: public search_constant_type_c {
-
- private:
- search_varfb_instance_type_c *search_varfb_instance_type;
- search_base_type_c search_base_type;
-
- /* When calling a function block, we must first find it's type,
- * by searching through the declarations of the variables currently
- * in scope.
- * This class does just that...
- * A new bject instance is instantiated whenever we start checking semantics
- * for a function block type declaration, or a program declaration.
- * This object instance will then later be called while the
- * function block's or the program's body is being handled.
- *
- * Note that functions cannot contain calls to function blocks,
- * so we do not create an object instance when handling
- * a function declaration.
- */
-// search_var_instance_decl_c *search_var_instance_decl;
-
- /* This variable was created to pass information from
- * visit_expression_type_c::visit(case_statement_c *symbol) function to
- * visit_expression_type_c::visit(case_list_c *symbol) function.
- */
- symbol_c *case_expression_type;
-
- /* In IL code, once we find a type mismatch error, it is best to
- * ignore any further errors until the end of the logicl operation,
- * i.e. until the next LD.
- * However, we cannot clear the il_error flag on all LD operations,
- * as these may also be used within parenthesis. LD operations
- * within parenthesis may not clear the error flag.
- * We therefore need a counter to know how deep inside a parenthesis
- * structure we are.
- */
- int il_parenthesis_level;
- bool il_error;
- bool error_found;
-
- /* the current data type of the data stored in the IL stack, i.e. the default variable */
- symbol_c *il_default_variable_type;
- /* the current IL operand being analysed - its symbol and its data type */
- symbol_c *il_operand_type;
- symbol_c *il_operand;
-
-
- public:
- visit_expression_type_c(symbol_c *ignore);
- virtual ~visit_expression_type_c(void);
-
- bool get_error_found(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_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);
-
- bool is_ANY_ELEMENTARY_OR_ENUMERATED_compatible (symbol_c *type_symbol);
-
- /* Determine the common data type between two data types.
- * If no common data type found, return NULL.
- *
- * If data types are identical, return the first (any would do...).
- * If any of the datat types is a literal, we confirm that
- * the literal uses less bits than the fixed size data type.
- * e.g. BYTE and 1024 returns NULL
- * BYTE and 255 returns BYTE
- *
- * If two literals, then return the literal that requires more bits...
- */
- symbol_c *common_type__(symbol_c *first_type, symbol_c *second_type);
- /* Determine the common data type between two data types.
- * Unlike the common_type__() function, we stop the compiler with an ERROR
- * if no common data type is found.
- */
- symbol_c *common_type(symbol_c *first_type, symbol_c *second_type);
-/* Return TRUE if the second (value) data type may be assigned to a variable of the first (variable) data type
- * such as:
- * var_type value_type
- * BOOL BYTE#7 -> returns false
- * INT INT#7 -> returns true
- * INT 7 -> returns true
- * REAL 7.89 -> returns true
- * REAL 7 -> returns true
- * INT 7.89 -> returns false
- * SAFEBOOL BOOL#1 -> returns false !!!
- * etc...
- *
- * NOTE: It is assumed that the var_type is the data type of an lvalue
- */
- bool 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);
-
- /* check semantics of FB call in the IL language using input operators */
- /* e.g. CU, CLK, IN, PT, SR, ... */
- void check_il_fbcall(symbol_c *symbol, const char *input_operator);
- /* check the semantics of a FB or Function non-formal call */
- /* e.g. foo(1, 2, 3, 4); */
- /* If error_count pointer is NULL, print out error messages.
- * If error_count pointer is != NULL, do not print out error messages, but tally up
- * how many errors were found.
- */
- void check_nonformal_call(symbol_c *f_call, symbol_c *f_decl, bool use_il_defvar = false, int *error_count = NULL);
- /* check the semantics of a FB or Function formal call */
- /* e.g. foo(IN1 := 1, OUT1 =>x, EN := true); */
- /* If error_count pointer is NULL, print out error messages.
- * If error_count pointer is != NULL, do not print out error messages, but tally up
- * how many errors were found.
- */
- void check_formal_call(symbol_c *f_call, symbol_c *f_decl, int *error_count = NULL);
-
-
- void *compute_standard_function_default(function_invocation_c *st_symbol, il_formal_funct_call_c *il_symbol);
- void *compute_standard_function_il(il_function_call_c *symbol, symbol_c *param_data_type);
-
-
- /* A helper function... */
- 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_expression(symbol_c *left_exp, symbol_c *right_exp, is_data_type_t is_data_type);
- symbol_c *compute_expression(symbol_c *left_type, symbol_c *right_type, is_data_type_t is_data_type,
- symbol_c *left_expr, symbol_c *right_expr);
-
-
- /* a helper function... */
- symbol_c *base_type(symbol_c *symbol);
-
- /* a helper function... */
- void *verify_null(symbol_c *symbol);
-
- /********************************/
- /* B 1.3.3 - Derived data types */
- /********************************/
- void *visit(data_type_declaration_c *symbol);
-
- /*********************/
- /* B 1.4 - Variables */
- /*********************/
- void *visit(symbolic_variable_c *symbol);
-
- /********************************************/
- /* B 1.4.1 - Directly Represented Variables */
- /********************************************/
- void *visit(direct_variable_c *symbol);
-
- /*************************************/
- /* B 1.4.2 - Multi-element variables */
- /*************************************/
-
- void *visit(array_variable_c *symbol);
- void *visit(structured_variable_c *symbol);
-
- /********************************/
- /* B 1.7 Configuration elements */
- /********************************/
- void *visit(configuration_declaration_c *symbol);
-
-/****************************************/
- /* B.2 - Language IL (Instruction List) */
- /****************************************/
- /***********************************/
- /* B 2.1 Instructions and Operands */
- /***********************************/
- // void *visit(instruction_list_c *symbol);
- void *visit(il_simple_operation_c *symbol);
- void *visit(il_function_call_c *symbol);
- void *visit(il_expression_c *symbol);
-// void *visit(il_jump_operation_c *symbol);
- void *visit(il_fb_call_c *symbol);
- void *visit(il_formal_funct_call_c *symbol);
- /*
- void *visit(il_operand_list_c *symbol);
- void *visit(simple_instr_list_c *symbol);
- void *visit(il_param_list_c *symbol);
- void *visit(il_param_assignment_c *symbol);
- void *visit(il_param_out_assignment_c *symbol);
- */
-
- /*******************/
- /* B 2.2 Operators */
- /*******************/
- void *visit(LD_operator_c *symbol);
- void *visit(LDN_operator_c *symbol);
- void *visit(ST_operator_c *symbol);
- void *visit(STN_operator_c *symbol);
- void *visit(NOT_operator_c *symbol);
- void *visit(S_operator_c *symbol);
- void *visit(R_operator_c *symbol);
- void *visit(S1_operator_c *symbol);
- void *visit(R1_operator_c *symbol);
- void *visit(CLK_operator_c *symbol);
- void *visit(CU_operator_c *symbol);
- void *visit(CD_operator_c *symbol);
- void *visit(PV_operator_c *symbol);
- void *visit(IN_operator_c *symbol);
- void *visit(PT_operator_c *symbol);
- void *visit(AND_operator_c *symbol);
- void *visit(OR_operator_c *symbol);
- void *visit(XOR_operator_c *symbol);
- void *visit(ANDN_operator_c *symbol);
- void *visit(ORN_operator_c *symbol);
- void *visit(XORN_operator_c *symbol);
- void *visit(ADD_operator_c *symbol);
- void *visit(SUB_operator_c *symbol);
- void *visit(MUL_operator_c *symbol);
- void *visit(DIV_operator_c *symbol);
- void *visit(MOD_operator_c *symbol);
- void *visit(GT_operator_c *symbol);
- void *visit(GE_operator_c *symbol);
- void *visit(EQ_operator_c *symbol);
- void *visit(LT_operator_c *symbol);
- void *visit(LE_operator_c *symbol);
- void *visit(NE_operator_c *symbol);
- void *visit(CAL_operator_c *symbol);
- void *visit(CALC_operator_c *symbol);
- void *visit(CALCN_operator_c *symbol);
- void *visit(RET_operator_c *symbol);
- void *visit(RETC_operator_c *symbol);
- void *visit(RETCN_operator_c *symbol);
- void *visit(JMP_operator_c *symbol);
- void *visit(JMPC_operator_c *symbol);
- void *visit(JMPCN_operator_c *symbol);
- /* Symbol class handled together with function call checks */
- // void *visit(il_assign_operator_c *symbol, variable_name);
- /* Symbol class handled together with function call checks */
- // void *visit(il_assign_operator_c *symbol, option, variable_name);
-
-
-
- /***************************************/
- /* B.3 - Language ST (Structured Text) */
- /***************************************/
- /***********************/
- /* B 3.1 - Expressions */
- /***********************/
- void *visit(or_expression_c *symbol);
- void *visit(xor_expression_c *symbol);
- void *visit(and_expression_c *symbol);
- void *visit(equ_expression_c *symbol);
- void *visit(notequ_expression_c *symbol);
- void *visit(lt_expression_c *symbol);
- void *visit(gt_expression_c *symbol);
- void *visit(le_expression_c *symbol);
- void *visit(ge_expression_c *symbol);
- void *visit(add_expression_c *symbol);
- void *visit(sub_expression_c *symbol);
- void *visit(mul_expression_c *symbol);
- void *visit(div_expression_c *symbol);
- void *visit(mod_expression_c *symbol);
- void *visit(power_expression_c *symbol);
- void *visit(neg_expression_c *symbol);
- void *visit(not_expression_c *symbol);
- void *visit(function_invocation_c *symbol);
-
- /*********************************/
- /* B 3.2.1 Assignment Statements */
- /*********************************/
- void *visit(assignment_statement_c *symbol);
-
- /*****************************************/
- /* B 3.2.2 Subprogram Control Statements */
- /*****************************************/
- void *visit(fb_invocation_c *symbol);
-
- /********************************/
- /* B 3.2.3 Selection Statements */
- /********************************/
-
- void *visit(if_statement_c *symbol);
-// void *visit(elseif_statement_list_c *symbol);
- void *visit(elseif_statement_c *symbol);
- void *visit(case_statement_c *symbol);
-// void *visit(case_element_list_c *symbol);
-// void *visit(case_element_c *symbol);
- void *visit(case_list_c *symbol);
-
- /********************************/
- /* B 3.2.4 Iteration Statements */
- /********************************/
-
- void *visit(for_statement_c *symbol);
- void *visit(while_statement_c *symbol);
- void *visit(repeat_statement_c *symbol);
-
-
-//TODO: delete this functions. Why are they needed?
-void *visit(program_declaration_c *symbol);
-void *visit(function_declaration_c *symbol);
-void *visit(function_block_declaration_c *symbol);
-
-}; // visit_expression_type_c
-
--- a/stage4/generate_c/generate_c.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/stage4/generate_c/generate_c.cc Wed Feb 01 19:49:11 2012 +0000
@@ -2224,10 +2224,10 @@
if (var_decl == NULL)
ERROR;
else
- vartype = search_config_instance->get_vartype();
+ vartype = search_config_instance->get_vartype(current_var_reference);
}
else
- vartype = search_resource_instance->get_vartype();
+ vartype = search_resource_instance->get_vartype(current_var_reference);
s4o.print(s4o.indent_spaces + "{extern ");
var_decl->accept(*this);
@@ -2259,10 +2259,10 @@
if (var_decl == NULL)
ERROR;
else
- vartype = search_config_instance->get_vartype();
+ vartype = search_config_instance->get_vartype(current_var_reference);
}
else
- vartype = search_resource_instance->get_vartype();
+ vartype = search_resource_instance->get_vartype(current_var_reference);
s4o.print(s4o.indent_spaces + "{extern ");
var_decl->accept(*this);
--- a/stage4/generate_c/generate_c_sfc.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/stage4/generate_c/generate_c_sfc.cc Wed Feb 01 19:49:11 2012 +0000
@@ -844,7 +844,7 @@
for(pt = variable_list.begin(); pt != variable_list.end(); pt++) {
symbol_c *var_decl = search_var_instance_decl->get_decl(pt->symbol);
if (var_decl != NULL) {
- unsigned int vartype = search_var_instance_decl->get_vartype();
+ unsigned int vartype = search_var_instance_decl->get_vartype(pt->symbol);
s4o.print(s4o.indent_spaces);
if (vartype == search_var_instance_decl_c::external_vt)
--- a/stage4/generate_c/generate_c_st.cc Wed Feb 01 13:01:08 2012 +0000
+++ b/stage4/generate_c/generate_c_st.cc Wed Feb 01 19:49:11 2012 +0000
@@ -342,7 +342,7 @@
case complextype_suffix_vg:
symbol->subscripted_variable->accept(*this);
- current_array_type = search_varfb_instance_type->get_type_id(symbol->subscripted_variable);
+ current_array_type = search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable);
if (current_array_type == NULL) ERROR;
s4o.print(".table");
@@ -356,7 +356,7 @@
if (this->is_variable_prefix_null()) {
symbol->subscripted_variable->accept(*this);
- current_array_type = search_varfb_instance_type->get_type_id(symbol->subscripted_variable);
+ current_array_type = search_varfb_instance_type->get_basetype_decl(symbol->subscripted_variable);
if (current_array_type == NULL) ERROR;
s4o.print(".table");