--- a/absyntax/absyntax.def Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax/absyntax.def Sun Nov 16 15:37:12 2014 +0000
@@ -125,6 +125,9 @@
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
SYM_TOKEN(identifier_c)
+/* A special identifier class, used for identifiers that have been previously declared as a derived datatype */
+/* This is currently needed because generate_c stage 4 needs to handle the array datatype identifiers differently to all other identifiers. */
+SYM_TOKEN(derived_datatype_identifier_c)
/*********************/
--- a/absyntax_utils/get_datatype_info.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/get_datatype_info.cc Sun Nov 16 15:37:12 2014 +0000
@@ -43,7 +43,7 @@
*/
#include "absyntax_utils.hh"
-#include "../main.hh" // required for ERROR() and ERROR_MSG() macros.
+#include "../main.hh" // required for ERROR() and ERROR_MSG() macros, as well as the runtime_options global variable
@@ -199,7 +199,8 @@
/*******************************************/
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
- void *visit(identifier_c *symbol) {return (void *)symbol->value;};
+ void *visit( identifier_c *symbol) {return (void *)symbol->value;};
+ void *visit(derived_datatype_identifier_c *symbol) {return (void *)symbol->value;};
/***********************************/
/* B 1.3.1 - Elementary Data Types */
@@ -249,6 +250,11 @@
void *visit(safewstring_type_name_c *symbol) {return (void *)"SAFEWSTRING"; };
/********************************/
+ /* B.1.3.2 - Generic data types */
+ /********************************/
+ void *visit(generic_type_any_c *symbol) {return (void *)"ANY"; };
+
+ /********************************/
/* B 1.3.3 - Derived data types */
/********************************/
/* simple_type_name ':' simple_spec_init */
@@ -417,17 +423,21 @@
return get_struct_info_c::get_field_type_id(struct_datatype, struct_fieldname);
}
+
+
symbol_c *get_datatype_info_c::get_array_storedtype_id(symbol_c *type_symbol) {
// returns the datatype of the variables stored in the array
- symbol_c *basetype = search_base_type_c::get_basetype_decl(type_symbol);
- array_specification_c *symbol = dynamic_cast<array_specification_c *>(basetype);
-
- if (NULL != symbol)
+ array_specification_c *symbol = NULL;
+ if (NULL == symbol) symbol = dynamic_cast<array_specification_c *>(type_symbol);
+ if (NULL == symbol) symbol = dynamic_cast<array_specification_c *>(search_base_type_c::get_basetype_decl(type_symbol));
+ if (NULL != symbol)
return symbol->non_generic_type_name;
return NULL; // this is not an array!
}
+
+
/* Returns true if both datatypes are equivalent (not necessarily equal!).
* WARNING: May return true even though the datatypes are not the same/identicial!!!
* This occurs when at least one of the datatypes is of a generic
@@ -439,7 +449,13 @@
* this function will currently only return true if the dataypes are identicial.
*/
-/* NOTE: Currently the datatype model used by matiec considers any implicitly defined datatype
+/* NOTE: matiec supports a strict and a relaxed data type model. Which datatype model to use is chosen
+ * as a command line option.
+ *
+ *
+ * The Strict Datatype Model
+ * =========================
+ * The strict datatype model used by matiec considers any implicitly defined datatype
* (e.g. an array datatype defined in the variable declaration itself, instead of inside a TYPE ... END_TYPE
* construct) to be different (i.e. not the same datatype, and therefore not compatible) to any other
* datatype, including with datatypes declared identically to the implicit datatype.
@@ -459,6 +475,8 @@
* (this rule is specified in the standard, so we follow it!)
* (2) REF_TO datatypes that reference the same datatype
* (I dont think the standard says anything about this!)
+ * (This rule should actually be part of the relaxed datatype model, but for now we
+ * will leave it in the strict datatype model)
*
* TYPE
* my_array_1_t: ARRAY [1..3] OF INT;
@@ -511,6 +529,29 @@
* This rule was adopted as without it, the datatype of the value returned by the REF()
* operator would be considered distinct to all other datatypes, and therefore the
* REF() operator would be essentially useless.
+ *
+ *
+ * The Relaxed Datatype Model
+ * ==========================
+ * In the relaxed datatype model, the same rules as the strict datatype model are followed, with the
+ * exception of implicitly defined array datatypes, which are now considered equal if they define
+ * identical datatypes.
+ * This means that in the following example
+ * TYPE
+ * array_t: ARRAY [1..3] OF INT;
+ * END_TYPE;
+ * VAR
+ * array_var1: array_t;
+ * array_var2: ARRAY [1..3] OF INT;
+ * array_var3: ARRAY [1..3] OF INT;
+ * END_VAR
+ *
+ * all three variables (array_var1, array_var2, and array_var3) are considered as being of the
+ * same datatype.
+ *
+ * Note that the strict datatype model currently actually uses a relaxed datatype model for
+ * REF_TO datatypes, so in both the relaxed and strict datatype models matiec currently uses a
+ * relaxed datatype equivalince for REF_TO datatypes.
*/
bool get_datatype_info_c::is_type_equal(symbol_c *first_type, symbol_c *second_type) {
if (!is_type_valid( first_type)) {return false;}
@@ -522,16 +563,116 @@
(is_ANY_generic_type(second_type))) {return true;}
/* ANY_ELEMENTARY */
- if ((is_ANY_ELEMENTARY(first_type)) &&
+ if ((is_ANY_ELEMENTARY_compatible(first_type)) &&
(typeid(*first_type) == typeid(*second_type))) {return true;}
-
- /* ANY_DERIVED */
+ if ( is_ANY_ELEMENTARY_compatible(first_type)
+ || is_ANY_ELEMENTARY_compatible(second_type)) {return false;}
+
+ /* ANY_DERIVED */
+ // from now on, we are sure both datatypes are derived...
if (is_ref_to(first_type) && is_ref_to(second_type)) {
return is_type_equal(search_base_type_c::get_basetype_decl(get_ref_to(first_type )),
search_base_type_c::get_basetype_decl(get_ref_to(second_type)));
}
- return (first_type == second_type);
-}
+
+ // check for same datatype
+ if (first_type == second_type) {return true;}
+
+ // remaining type equivalence rules are not applied in the strict datatype model
+ if (false == runtime_options.relaxed_datatype_model) {return false;}
+
+ // check for array equivalence usig the relaxed datatype model
+ if (is_arraytype_equal_relaxed(first_type, second_type)) {return true;}
+
+ return false;
+}
+
+
+
+/* A local helper function that transforms strings conatining signed_integers into a normalized
+ * form, so they can be compared for equality.
+ * examples:
+ * 82 -> 82
+ * 8_2 -> 82
+ * +82 -> 82
+ * 082 -> 82
+ * +082 -> 82
+ * -82 -> -82
+ * -8_2 -> -82
+ * -082 -> -82
+ */
+#include <string.h> /* required for strlen() */
+static std::string normalize_integer(symbol_c *symbol) {
+ integer_c *token = dynamic_cast<integer_c *>(symbol);
+ if (NULL == token) ERROR;
+
+ std::string str = "";
+ bool leading_zero = true;
+ unsigned int offset = 0;
+
+ // handle any possible leading '-' or '+'
+ if (token->value[0] == '-') {
+ // '-' -> retained
+ str += token->value[0];
+ offset++;
+ } else if (token->value[0] == '+')
+ // '+' -> skip, so '+8' and '8' will both result in '8'
+ offset++;
+
+ for (unsigned int i = offset; i < strlen(token->value); i++) {
+ if (leading_zero && (token->value[i] != '0'))
+ leading_zero = false;
+ if (!leading_zero && token->value[i] != '_')
+ str += token->value[i];
+ }
+ return str;
+}
+
+
+/* A helper method to get_datatype_info_c::is_type_equal()
+ * Assuming the relaxed datatype model, determine whether the two array datatypes are equal/equivalent
+ */
+bool get_datatype_info_c::is_arraytype_equal_relaxed(symbol_c *first_type, symbol_c *second_type) {
+ symbol_c *basetype_1 = search_base_type_c::get_basetype_decl( first_type);
+ symbol_c *basetype_2 = search_base_type_c::get_basetype_decl(second_type);
+ array_specification_c *array_1 = dynamic_cast<array_specification_c *>(basetype_1);
+ array_specification_c *array_2 = dynamic_cast<array_specification_c *>(basetype_2);
+
+ // are they both array datatypes?
+ if ((NULL == array_1) || (NULL == array_2))
+ return false;
+
+ // number of subranges
+ array_subrange_list_c *subrange_list_1 = dynamic_cast<array_subrange_list_c *>(array_1->array_subrange_list);
+ array_subrange_list_c *subrange_list_2 = dynamic_cast<array_subrange_list_c *>(array_2->array_subrange_list);
+ if ((NULL == subrange_list_1) || (NULL == subrange_list_2)) ERROR;
+ if (subrange_list_1->n != subrange_list_2->n)
+ return false;
+
+ // comparison of each subrange start and end elements
+ for (int i = 0; i < subrange_list_1->n; i++) {
+ subrange_c *subrange_1 = dynamic_cast<subrange_c *>(subrange_list_1->elements[i]);
+ subrange_c *subrange_2 = dynamic_cast<subrange_c *>(subrange_list_2->elements[i]);
+ if ((NULL == subrange_1) || (NULL == subrange_2)) ERROR;
+ #if 0
+ /* An alternative method of checking whether the subranges have the same values, using the result of the constant folding agorithm.
+ * This method has the drawback that it inserts a dependency on having to run the constant folding algorithm before
+ * the get_datatype_info_c::is_type_equal() method is called.
+ * The probably slower alternative of comparing the strings themselves is therefor used.
+ */
+ if (!constant_folding_c::is_equal_cvalue(subrange_1->lower_limit, subrange_2->lower_limit)) return false;
+ if (!constant_folding_c::is_equal_cvalue(subrange_1->upper_limit, subrange_2->upper_limit)) return false;
+ #endif
+ if (normalize_integer(subrange_1->lower_limit) != normalize_integer(subrange_2->lower_limit)) return false;
+ if (normalize_integer(subrange_1->upper_limit) != normalize_integer(subrange_2->upper_limit)) return false;
+ }
+
+ return is_type_equal(search_base_type_c::get_basetype_decl(array_1->non_generic_type_name),
+ search_base_type_c::get_basetype_decl(array_2->non_generic_type_name));
+}
+
+
+
bool get_datatype_info_c::is_type_valid(symbol_c *type) {
--- a/absyntax_utils/get_datatype_info.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/get_datatype_info.hh Sun Nov 16 15:37:12 2014 +0000
@@ -55,6 +55,9 @@
get_datatype_info_c(void) {};
~get_datatype_info_c(void) {};
+ // A helper method to get_datatype_info_c::is_type_equal()
+ // Assuming the relaxed datatype model, return whether the two array datatypes are equal/equivalent
+ static bool is_arraytype_equal_relaxed(symbol_c *first_type, symbol_c *second_type);
public:
static symbol_c *get_id (symbol_c *datatype); /* get the identifier (name) of the datatype); returns NULL if anonymous datatype! Does not work for elementary datatypes!*/
@@ -65,14 +68,17 @@
static symbol_c *get_ref_to (symbol_c *type_symbol); // Defined in IEC 61131-3 v3 (returns the type that is being referenced/pointed to)
/* Returns true if both datatypes are equivalent (not necessarily equal!).
- * WARNING: May return true even though the datatypes are not the same/identicial!!!
- * This occurs when at least one of the datatypes is of a generic
- * datatype (or a REF_TO a generic datatype).
- * (Generic dataypes: ANY, ANY_INT, ANY_NUM, ...)
+ * Two datatype models are supported: relaxed and strict (chosen from a command line option).
+ * WARNING: May return true even though the datatypes are not the same/identical!!!
+ * In both of the models, this may occur when at least one of the datatypes is of a generic
+ * datatype (Generic dataypes: ANY, ANY_INT, ANY_NUM, ...),
+ * or when two REF_TO datatypes both reference an equivalent datatype.
+ * In only the relaxed datatype, it may also return true if two array datatypes
+ * have the same subrange limits, and contain the same data.
+ *
* NOTE: Currently only the ANY generic datatype is implemented!
* NOTE: Currently stage1_2 only allows the use of the ANY keyword when in conjuntion with
- * the REF_TO keyword (i.e. REF_TO ANY), so when handling non REF_TO datatypes,
- * this function will currently only return true if the dataypes are identicial.
+ * the REF_TO keyword (i.e. REF_TO ANY).
*/
static bool is_type_equal(symbol_c *first_type, symbol_c *second_type);
static bool is_type_valid(symbol_c *type);
--- a/absyntax_utils/search_base_type.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/search_base_type.cc Sun Nov 16 15:37:12 2014 +0000
@@ -105,7 +105,9 @@
/*******************************************/
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
-void *search_base_type_c::visit(identifier_c *type_name) {
+
+
+void *search_base_type_c::handle_datatype_identifier(token_c *type_name) {
symbol_c *type_decl;
this->current_basetype_name = type_name;
@@ -129,6 +131,9 @@
return NULL;
}
+void *search_base_type_c::visit( identifier_c *type_name) {return handle_datatype_identifier(type_name);} // still needed to handle FB and program datatypes!
+void *search_base_type_c::visit(derived_datatype_identifier_c *type_name) {return handle_datatype_identifier(type_name);}
+
/*********************/
/* B 1.2 - Constants */
--- a/absyntax_utils/search_base_type.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/search_base_type.hh Sun Nov 16 15:37:12 2014 +0000
@@ -74,6 +74,7 @@
private:
static void create_singleton(void);
+ void *handle_datatype_identifier(token_c *type_name);
public:
search_base_type_c(void);
@@ -88,8 +89,8 @@
/*******************************************/
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
- void *visit(identifier_c *type_name);
-
+ void *visit( identifier_c *type_name);
+ void *visit(derived_datatype_identifier_c *type_name);
/*********************/
/* B 1.2 - Constants */
--- a/absyntax_utils/spec_init_separator.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/spec_init_separator.cc Sun Nov 16 15:37:12 2014 +0000
@@ -74,7 +74,22 @@
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
// SYM_TOKEN(identifier_c)
-void *spec_init_sperator_c::visit(identifier_c *symbol) {
+/* visitor for identifier_c is necessary because spec_init_sperator_c will be called to analyse PROGRAM identfiers,
+ * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
+ */
+void *spec_init_sperator_c::visit( identifier_c *symbol) {
+ TRACE("spec_init_sperator_c::identifier_c");
+ switch (search_what) {
+ /* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
+ case search_spec: return symbol;
+ case search_init: return NULL;
+ }
+ ERROR; /* should never occur */
+ return NULL;
+ }
+
+
+void *spec_init_sperator_c::visit(derived_datatype_identifier_c *symbol) {
TRACE("spec_init_sperator_c::identifier_c");
switch (search_what) {
/* if we ever get called sith a simple identifier_c, then it must be a previously declared type... */
--- a/absyntax_utils/spec_init_separator.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/spec_init_separator.hh Sun Nov 16 15:37:12 2014 +0000
@@ -65,7 +65,8 @@
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
// SYM_TOKEN(identifier_c)
- void *visit(identifier_c *symbol);
+ void *visit( identifier_c *symbol);
+ void *visit(derived_datatype_identifier_c *symbol);
/********************************/
--- a/absyntax_utils/type_initial_value.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/type_initial_value.cc Sun Nov 16 15:37:12 2014 +0000
@@ -117,8 +117,27 @@
}
-
-void *type_initial_value_c::visit(identifier_c *type_name) {
+/* visitor for identifier_c is necessary because type_initial_value_c will be called to analyse PROGRAM identfiers,
+ * which are still transformed into identfier_c, instead of a derived_datatype_identifier_c
+ */
+void *type_initial_value_c::visit( identifier_c *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!! */
+ /* NOTE: Variables declared out of function block 'data types',
+ * for eg: VAR timer: TON; END_VAR
+ * do not have a default value, so (TON) will never be found in the
+ * type symbol table. This means we cannot simply consider this
+ * an error and abort, but must rather return a NULL.
+ */
+ return NULL;
+
+ return type_decl->accept(*this);
+}
+
+
+void *type_initial_value_c::visit(derived_datatype_identifier_c *type_name) {
/* look up the type declaration... */
symbol_c *type_decl = type_symtable.find_value(type_name);
if (type_decl == type_symtable.end_value())
--- a/absyntax_utils/type_initial_value.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/absyntax_utils/type_initial_value.hh Sun Nov 16 15:37:12 2014 +0000
@@ -86,7 +86,8 @@
void *handle_type_spec(symbol_c *base_type_name, symbol_c *type_spec_init);
private:
- void *visit(identifier_c *type_name);
+ void *visit( identifier_c *type_name);
+ void *visit(derived_datatype_identifier_c *type_name);
/***********************************/
/* B 1.3.1 - Elementary Data Types */
--- a/main.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/main.cc Sun Nov 16 15:37:12 2014 +0000
@@ -113,15 +113,8 @@
printf(" -h : show this help message\n");
printf(" -v : print version number\n");
printf(" -f : display full token location on error messages\n");
- /******************************************************/
- /* whether we are supporting safe extensions */
- /* as defined in PLCopen - Technical Committee 5 */
- /* Safety Software Technical Specification, */
- /* Part 1: Concepts and Function Blocks, */
- /* Version 1.0 is Official Release */
- /******************************************************/
- printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.) (defined in PLCOpen Safety)\n");
- printf(" -n : allow use of nested comments (an IEC 61131-3 v3 feature)\n");
+ printf(" -l : use a relaxed datatype equivalence model (a non-standard extension?)\n");
+ printf(" -s : allow use of safe datatypes (SAFEBOOL, etc.) (defined in PLCOpen Safety)\n"); // PLCopen TC5 "Safety Software Technical Specification - Part 1" v1.0
printf(" -r : allow use of references (REF_TO, REF, ^, NULL) (an IEC 61131-3 v3 feature)\n");
printf(" -R : allow use of REF_TO ANY datatypes (a non-standard extension!)\n");
printf(" as well as REF_TO in ARRAYs and STRUCTs (a non-standard extension!)\n");
@@ -135,27 +128,32 @@
}
+/* declare the global options variable */
+runtime_options_t runtime_options;
+
int main(int argc, char **argv) {
symbol_c *tree_root;
char * builddir = NULL;
- stage1_2_options_t stage1_2_options;
int optres, errflg = 0;
int path_len;
/* Default values for the command line options... */
- stage1_2_options.safe_extensions = false; /* allow use of SAFExxx datatypes */
- stage1_2_options.full_token_loc = false; /* error messages specify full token location */
- stage1_2_options.conversion_functions = false; /* Create a conversion function for derived datatype */
- stage1_2_options.nested_comments = false; /* Allow the use of nested comments. */
- stage1_2_options.ref_standard_extensions = false; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
- stage1_2_options.ref_nonstand_extensions = false; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
- stage1_2_options.includedir = NULL; /* Include directory, where included files will be searched for... */
-
+ runtime_options.safe_extensions = false; /* allow use of SAFExxx datatypes */
+ runtime_options.full_token_loc = false; /* error messages specify full token location */
+ runtime_options.conversion_functions = false; /* Create a conversion function for derived datatype */
+ runtime_options.nested_comments = false; /* Allow the use of nested comments. */
+ runtime_options.ref_standard_extensions = false; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
+ runtime_options.ref_nonstand_extensions = false; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
+ runtime_options.includedir = NULL; /* Include directory, where included files will be searched for... */
+
+ /* Default values for the command line options... */
+ runtime_options.relaxed_datatype_model = false; /* by default use the strict datatype equivalence model */
+
/******************************************/
/* Parse command line options... */
/******************************************/
- while ((optres = getopt(argc, argv, ":nhvfrRscI:T:O:")) != -1) {
+ while ((optres = getopt(argc, argv, ":nhvflsrRcI:T:O:")) != -1) {
switch(optres) {
case 'h':
printusage(argv[0]);
@@ -163,24 +161,28 @@
case 'v':
fprintf(stdout, "%s version %s\n" "changeset id: %s\n", PACKAGE_NAME, PACKAGE_VERSION, HGVERSION);
return 0;
+ case 'l':
+ runtime_options.relaxed_datatype_model = true;
+ break;
+
case 'f':
- stage1_2_options.full_token_loc = true;
+ runtime_options.full_token_loc = true;
break;
case 's':
- stage1_2_options.safe_extensions = true;
+ runtime_options.safe_extensions = true;
break;
case 'R':
- stage1_2_options.ref_standard_extensions = true; /* use of REF_TO ANY implies activating support for REF extensions! */
- stage1_2_options.ref_nonstand_extensions = true;
+ runtime_options.ref_standard_extensions = true; /* use of REF_TO ANY implies activating support for REF extensions! */
+ runtime_options.ref_nonstand_extensions = true;
break;
case 'r':
- stage1_2_options.ref_standard_extensions = true;
+ runtime_options.ref_standard_extensions = true;
break;
case 'c':
- stage1_2_options.conversion_functions = true;
+ runtime_options.conversion_functions = true;
break;
case 'n':
- stage1_2_options.nested_comments = true;
+ runtime_options.nested_comments = true;
break;
case 'I':
/* NOTE: To improve the usability under windows:
@@ -190,7 +192,7 @@
*/
path_len = strlen(optarg) - 1;
if (optarg[path_len] == '\\') optarg[path_len]= '\0';
- stage1_2_options.includedir = optarg;
+ runtime_options.includedir = optarg;
break;
case 'T':
/* NOTE: see note above */
@@ -236,7 +238,7 @@
/* Run the compiler... */
/***************************/
/* 1st Pass */
- if (stage1_2(argv[optind], &tree_root, stage1_2_options) < 0)
+ if (stage1_2(argv[optind], &tree_root) < 0)
return EXIT_FAILURE;
/* 2nd Pass */
@@ -245,7 +247,7 @@
/* moved to bison, although it could perfectly well still be here instead of in bison code. */
//add_en_eno_param_decl_c::add_to(tree_root);
- /* Do semantic verification of code (data type and lvalue checking currently implemented) */
+ /* Do semantic verification of code */
if (stage3(tree_root) < 0)
return EXIT_FAILURE;
--- a/main.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/main.hh Sun Nov 16 15:37:12 2014 +0000
@@ -36,6 +36,29 @@
+/* Compiler options, specified at runtime on the command line */
+
+typedef struct {
+ /* options specific to stage1_2 */
+ bool safe_extensions; /* support SAFE_* datatypes defined in PLCOpen TC5 "Safety Software Technical Specification - Part 1" v1.0 */
+ bool full_token_loc; /* error messages specify full token location */
+ bool conversion_functions; /* Create a conversion function for derived datatype */
+ bool nested_comments; /* Allow the use of nested comments. */
+ bool ref_standard_extensions; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
+ bool ref_nonstand_extensions; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
+ const char *includedir; /* Include directory, where included files will be searched for... */
+
+ /* options specific to stage3 */
+ bool relaxed_datatype_model; /* Use the relaxed datatype equivalence model, instead of the default strict equivalence model */
+} runtime_options_t;
+
+extern runtime_options_t runtime_options;
+
+
+
+
+
+
/* Function used throughout the code --> used to report failed assertions (i.e. internal compiler errors)! */
#include <stddef.h> /* required for NULL */
--- a/stage1_2/iec_bison.yy Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/iec_bison.yy Sun Nov 16 15:37:12 2014 +0000
@@ -1608,13 +1608,13 @@
prev_declared_variable_name : prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));};
prev_declared_fb_name : prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_simple_type_name : prev_declared_simple_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_subrange_type_name : prev_declared_subrange_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_array_type_name : prev_declared_array_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_structure_type_name : prev_declared_structure_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_string_type_name : prev_declared_string_type_name_token {$$ = new identifier_c($1, locloc(@$));};
-prev_declared_ref_type_name : prev_declared_ref_type_name_token {$$ = new identifier_c($1, locloc(@$));}; /* defined in IEC 61131-3 v3 */
+prev_declared_simple_type_name : prev_declared_simple_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_subrange_type_name : prev_declared_subrange_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_array_type_name : prev_declared_array_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_structure_type_name : prev_declared_structure_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_string_type_name : prev_declared_string_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));};
+prev_declared_ref_type_name : prev_declared_ref_type_name_token {$$ = new derived_datatype_identifier_c($1, locloc(@$));}; /* defined in IEC 61131-3 v3 */
prev_declared_derived_function_name : prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));};
prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));};
@@ -8487,13 +8487,12 @@
int stage2__(const char *filename,
- symbol_c **tree_root_ref,
- stage1_2_options_t options
+ symbol_c **tree_root_ref
) {
char *libfilename = NULL;
- if (options.includedir != NULL) {
- INCLUDE_DIRECTORIES[0] = options.includedir;
+ if (runtime_options.includedir != NULL) {
+ INCLUDE_DIRECTORIES[0] = runtime_options.includedir;
}
/* first parse the standard library file... */
@@ -8520,11 +8519,11 @@
allow_function_overloading = true;
allow_extensible_function_parameters = true;
- full_token_loc = options.full_token_loc;
- conversion_functions = options.conversion_functions;
- allow_ref_dereferencing = options.ref_standard_extensions;
- allow_ref_to_any = options.ref_nonstand_extensions;
- allow_ref_to_in_derived_datatypes = options.ref_nonstand_extensions;
+ full_token_loc = runtime_options.full_token_loc;
+ conversion_functions = runtime_options.conversion_functions;
+ allow_ref_dereferencing = runtime_options.ref_standard_extensions;
+ allow_ref_to_any = runtime_options.ref_nonstand_extensions;
+ allow_ref_to_in_derived_datatypes = runtime_options.ref_nonstand_extensions;
if (yyparse() != 0)
ERROR;
fclose(libfile);
@@ -8557,11 +8556,11 @@
allow_function_overloading = false;
allow_extensible_function_parameters = false;
- full_token_loc = options.full_token_loc;
- conversion_functions = options.conversion_functions;
- allow_ref_dereferencing = options.ref_standard_extensions;
- allow_ref_to_any = options.ref_nonstand_extensions;
- allow_ref_to_in_derived_datatypes = options.ref_nonstand_extensions;
+ full_token_loc = runtime_options.full_token_loc;
+ conversion_functions = runtime_options.conversion_functions;
+ allow_ref_dereferencing = runtime_options.ref_standard_extensions;
+ allow_ref_to_any = runtime_options.ref_nonstand_extensions;
+ allow_ref_to_in_derived_datatypes = runtime_options.ref_nonstand_extensions;
//allow_ref_to_any = false; /* we only allow REF_TO ANY in library functions/FBs, no matter what the user asks for in the command line */
if (yyparse() != 0) {
--- a/stage1_2/stage1_2.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/stage1_2.cc Sun Nov 16 15:37:12 2014 +0000
@@ -43,6 +43,7 @@
#include "../absyntax/absyntax.hh"
+#include "../main.hh"
#include "stage1_2.hh"
#include "iec_bison.hh"
#include "stage1_2_priv.hh"
@@ -51,7 +52,6 @@
-static stage1_2_options_t options_;
/******************************************************/
/* whether we are supporting safe extensions */
@@ -60,17 +60,17 @@
/* Part 1: Concepts and Function Blocks, */
/* Version 1.0 – Official Release */
/******************************************************/
-bool get_opt_safe_extensions() {return options_.safe_extensions;}
+bool get_opt_safe_extensions() {return runtime_options.safe_extensions;}
/************************************/
/* whether to allow nested comments */
/************************************/
-bool get_opt_nested_comments() {return options_.nested_comments;}
+bool get_opt_nested_comments() {return runtime_options.nested_comments;}
/**************************************************************************/
/* whether to allow REF(), DREF(), REF_TO, NULL and ^ operators/keywords */
/**************************************************************************/
-bool get_opt_ref_standard_extensions() {return options_.ref_standard_extensions;}
+bool get_opt_ref_standard_extensions() {return runtime_options.ref_standard_extensions;}
@@ -226,12 +226,11 @@
/***********************************************************************/
int stage2__(const char *filename,
- symbol_c **tree_root_ref,
- stage1_2_options_t options
+ symbol_c **tree_root_ref
);
-int stage1_2(const char *filename, symbol_c **tree_root_ref, stage1_2_options_t options) {
+int stage1_2(const char *filename, symbol_c **tree_root_ref) {
/* NOTE: we only call stage2 (bison - syntax analysis) directly, as stage 2 will itself call stage1 (flex - lexical analysis)
* automatically as needed
*/
@@ -242,7 +241,6 @@
* These callback functions will get their data from local (to this file) global variables...
* We now set those variables...
*/
- options_ = options;
- return stage2__(filename, tree_root_ref, options);
-}
-
+ return stage2__(filename, tree_root_ref);
+}
+
--- a/stage1_2/stage1_2.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/stage1_2/stage1_2.hh Sun Nov 16 15:37:12 2014 +0000
@@ -42,31 +42,10 @@
-/*
- * This file includes the interface through which the main function accesses the stage1_2 services
- */
+/* This file includes the interface through which the main function accesses the stage1_2 services */
-
-typedef struct {
- /******************************************************/
- /* whether we are suporting safe extensions */
- /* as defined in PLCopen - Technical Committee 5 */
- /* Safety Software Technical Specification, */
- /* Part 1: Concepts and Function Blocks, */
- /* Version 1.0 – Official Release */
- /******************************************************/
- bool safe_extensions;
- bool full_token_loc; /* error messages specify full token location */
- bool conversion_functions; /* Create a conversion function for derived datatype */
- bool nested_comments; /* Allow the use of nested comments. */
- bool ref_standard_extensions; /* Allow the use of REFerences (keywords REF_TO, REF, DREF, ^, NULL). */
- bool ref_nonstand_extensions; /* Allow the use of non-standard extensions to REF_TO datatypes: REF_TO ANY, and REF_TO in struct elements! */
- const char *includedir; /* Include directory, where included files will be searched for... */
-} stage1_2_options_t;
-
-
-int stage1_2(const char *filename, symbol_c **tree_root, stage1_2_options_t options);
+int stage1_2(const char *filename, symbol_c **tree_root);
--- a/stage3/constant_folding.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/constant_folding.cc Sun Nov 16 15:37:12 2014 +0000
@@ -788,8 +788,21 @@
/***********************************************************************/
/***********************************************************************/
-
-
+#if 0
+// not currently needed, so comment it out!...
+// returns true if both symbols have the same value in all the cvalues
+bool constant_folding_c::is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2) {
+ if (VALID_CVALUE (real64, symbol_1) != VALID_CVALUE (real64, symbol_2)) return false;
+ if (VALID_CVALUE (uint64, symbol_1) != VALID_CVALUE (uint64, symbol_2)) return false;
+ if (VALID_CVALUE ( int64, symbol_1) != VALID_CVALUE ( int64, symbol_2)) return false;
+ if (VALID_CVALUE ( bool, symbol_1) != VALID_CVALUE ( bool, symbol_2)) return false;
+ if (VALID_CVALUE (real64, symbol_1) && !ISEQUAL_CVALUE(real64, symbol_1, symbol_2)) return false;
+ if (VALID_CVALUE (uint64, symbol_1) && !ISEQUAL_CVALUE(uint64, symbol_1, symbol_2)) return false;
+ if (VALID_CVALUE ( int64, symbol_1) && !ISEQUAL_CVALUE( int64, symbol_1, symbol_2)) return false;
+ if (VALID_CVALUE ( bool, symbol_1) && !ISEQUAL_CVALUE( bool, symbol_1, symbol_2)) return false;
+ return true;
+}
+#endif
--- a/stage3/constant_folding.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/constant_folding.hh Sun Nov 16 15:37:12 2014 +0000
@@ -66,6 +66,14 @@
virtual ~constant_folding_c(void);
int get_error_count();
+ #if 0
+ // not currently needed, so comment it out!...
+ /* utility functions for other stage3 algorithms to access the contant folded values */
+ /* written as static since we do not need to iteratively visit the symbols! */
+ // returns true if both symbols have the same value in all the cvalues
+ static bool is_equal_cvalue(symbol_c *symbol_1, symbol_c *symbol_2);
+ #endif
+
private:
/*********************/
/* B 1.2 - Constants */
--- a/stage3/fill_candidate_datatypes.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/fill_candidate_datatypes.cc Sun Nov 16 15:37:12 2014 +0000
@@ -1303,10 +1303,57 @@
/* B 1.4.3 - Declaration & Initialisation */
/******************************************/
+/* When handling the declaration of variables the fill/narrow algorithm will simply visit the objects
+ * in the abstract syntax tree defining the desired datatype for the variables. Tis is to set the
+ * symbol->datatype to the basetype of that datatype.
+ *
+ * Note that we do not currently set the symbol->datatype annotation for the identifier_c objects naming the
+ * variables inside the variable declaration. However, this is liable to change in the future, so do not write
+ * any code that depends on this!
+ *
+ * example:
+ * VAR var1, var2, var3 : my_type; END_VAR
+ * (* ^^^^ ^^^^ ^^^^ -> will NOT have the symbol->datatype set (for now, may change in the future!) *)
+ * (* ^^^^^^^ -> WILL have the symbol->datatype set *)
+ *
+ * (remeber too that the identifier_c objects identifying variables inside ST/IL/SFC code *will* have their
+ * symbol->datatype annotation filled by the fill/narrow algorithm)
+ */
+void *fill_candidate_datatypes_c::fill_var_declaration(symbol_c *var_list, symbol_c *type) {
+ /* The type may be either a datatype object (e.g. array_spec_init_c, ...), or a derived_datatype_identifier_c
+ * naming a previously declared datatype.
+ * If it is a derived_datatype_identifier_c, we will search the list of all declared datatypes to determine
+ * the requested datatype. This is done automatically by the search_base_type_c::get_basetype_decl() method,
+ * so we do not need to do anything special here!
+ */
+ add_datatype_to_candidate_list(type, search_base_type_c::get_basetype_decl(type)); /* will only add if non NULL */
+ type->accept(*this);
+ // handle the extensible_input_parameter_c, etc...
+ /* The extensible_input_parameter_c will be visited since this class inherits from the iterator_visitor_c.
+ * It needs to be visited in order to handle the datatype of the first_index parameter of that class.
+ */
+ var_list->accept(*this);
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(var1_init_decl_c *symbol) {return fill_var_declaration(symbol->var1_list, symbol->spec_init);}
+void *fill_candidate_datatypes_c::visit(array_var_init_decl_c *symbol) {return fill_var_declaration(symbol->var1_list, symbol->array_spec_init);}
+void *fill_candidate_datatypes_c::visit(structured_var_init_decl_c *symbol) {return fill_var_declaration(symbol->var1_list, symbol->initialized_structure);}
+void *fill_candidate_datatypes_c::visit(fb_name_decl_c *symbol) {return fill_var_declaration(symbol->fb_name_list, symbol->fb_spec_init);}
+void *fill_candidate_datatypes_c::visit(array_var_declaration_c *symbol) {return fill_var_declaration(symbol->var1_list, symbol->array_specification);}
+void *fill_candidate_datatypes_c::visit(structured_var_declaration_c *symbol) {return fill_var_declaration(symbol->var1_list, symbol->structure_type_name);}
+void *fill_candidate_datatypes_c::visit(external_declaration_c *symbol) {return fill_var_declaration(symbol->global_var_name, symbol->specification);}
+void *fill_candidate_datatypes_c::visit(global_var_decl_c *symbol) {return fill_var_declaration(symbol->global_var_spec, symbol->type_specification);}
+void *fill_candidate_datatypes_c::visit(incompl_located_var_decl_c *symbol) {return fill_var_declaration(symbol->variable_name, symbol->var_spec);}
+//void *fill_candidate_datatypes_c::visit(single_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->single_byte_string_spec);}
+//void *fill_candidate_datatypes_c::visit(double_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->double_byte_string_spec);}
+
+
+
+// NOTE: this method is not required since fill_candidate_datatypes_c inherits from iterator_visitor_c. TODO: delete this method!
void *fill_candidate_datatypes_c::visit(var1_list_c *symbol) {
- for(int i = 0; i < symbol->n; i++) {
- symbol->elements[i]->accept(*this); // handle the extensible_input_parameter_c, etc...
- }
+ for(int i = 0; i < symbol->n; i++) {symbol->elements[i]->accept(*this);}
return NULL;
}
@@ -1509,10 +1556,56 @@
/* B 1.7 Configuration elements */
/********************************/
void *fill_candidate_datatypes_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;
-}
+ if (debug) printf("Filling candidate data types list in configuration %s\n", ((token_c *)(symbol->configuration_name))->value);
+ current_scope = symbol;
+// local_enumerated_value_symtable.reset(); // TODO
+// symbol->global_var_declarations->accept(populate_enumvalue_symtable); // TODO
+
+ search_var_instance_decl = new search_var_instance_decl_c(symbol);
+ symbol->global_var_declarations ->accept(*this);
+ symbol->resource_declarations ->accept(*this); // points to a single_resource_declaration_c or a resource_declaration_list_c
+// symbol->access_declarations ->accept(*this); // TODO
+// symbol->instance_specific_initializations->accept(*this); // TODO
+
+ delete search_var_instance_decl;
+ search_var_instance_decl = NULL;
+
+ current_scope = NULL;
+// local_enumerated_value_symtable.reset(); // TODO
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(resource_declaration_c *symbol) {
+ if (debug) printf("Filling candidate data types list in resource %s\n", ((token_c *)(symbol->resource_name))->value);
+// local_enumerated_value_symtable.reset(); // TODO-> this must be replaced with local_enumerated_value_symtable.push(), which is not yet implemented for the dsyntable_c!
+ symbol_c *prev_scope = current_scope;
+ current_scope = symbol;
+ /* TODO Enumeration constants may be defined inside a VAR_GLOBAL .. END_VAR variable declaration list.
+ * We currently do not yet consider enumeration values defined in the var declarations inside a resource!
+ */
+// symbol->global_var_declarations->accept(populate_enumvalue_symtable); // TODO!
+
+ search_var_instance_decl_c *prev_search_var_instance_decl = search_var_instance_decl;
+ search_var_instance_decl = new search_var_instance_decl_c(symbol);
+ symbol->global_var_declarations->accept(*this);
+ symbol->resource_declaration ->accept(*this); // points to a single_resource_declaration_c!
+
+ delete search_var_instance_decl;
+ search_var_instance_decl = prev_search_var_instance_decl;
+
+ current_scope = prev_scope;
+// local_enumerated_value_symtable.reset(); // TODO-> this must be replaced with local_enumerated_value_symtable.pop(), which is not yet implemented for the dsyntable_c!
+ return NULL;
+}
+
+
+void *fill_candidate_datatypes_c::visit(single_resource_declaration_c *symbol) {
+// symbol->task_configuration_list ->accept(*this); // TODO
+// symbol->program_configuration_list ->accept(*this); // TODO
+ return NULL;
+}
+
/****************************************/
/* B.2 - Language IL (Instruction List) */
--- a/stage3/fill_candidate_datatypes.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/fill_candidate_datatypes.hh Sun Nov 16 15:37:12 2014 +0000
@@ -96,10 +96,11 @@
void *handle_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
void *handle_binary_expression (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
void *handle_binary_operator (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr);
- void *handle_conditional_il_flow_control_operator(symbol_c *symbol);
- void *fill_type_decl(symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init);
- void *fill_spec_init(symbol_c *symbol, symbol_c *type_spec, symbol_c *init_value);
-
+ void *handle_conditional_il_flow_control_operator (symbol_c *symbol);
+ void *fill_type_decl (symbol_c *symbol, symbol_c *type_name, symbol_c *spec_init);
+ void *fill_spec_init (symbol_c *symbol, symbol_c *type_spec, symbol_c *init_value);
+ void *fill_var_declaration (symbol_c *var_list, symbol_c *type);
+
/* a helper function... */
symbol_c *base_type(symbol_c *symbol);
@@ -230,9 +231,20 @@
/******************************************/
/* B 1.4.3 - Declaration & Initialisation */
/******************************************/
- void *visit(var1_list_c *symbol);
- void *visit(location_c *symbol);
- void *visit(located_var_decl_c *symbol);
+ void *visit(var1_list_c *symbol);
+ void *visit(location_c *symbol);
+ void *visit(located_var_decl_c *symbol);
+ void *visit(var1_init_decl_c *symbol);
+ void *visit(array_var_init_decl_c *symbol);
+ void *visit(structured_var_init_decl_c *symbol);
+ void *visit(fb_name_decl_c *symbol);
+ void *visit(array_var_declaration_c *symbol);
+ void *visit(structured_var_declaration_c *symbol);
+ void *visit(external_declaration_c *symbol);
+ void *visit(global_var_decl_c *symbol);
+ void *visit(incompl_located_var_decl_c *symbol);
+ //void *visit(single_byte_string_var_declaration_c *symbol);
+ //void *visit(double_byte_string_var_declaration_c *symbol);
/**************************************/
/* B 1.5 - Program organization units */
@@ -260,7 +272,9 @@
/********************************/
/* B 1.7 Configuration elements */
/********************************/
- void *visit(configuration_declaration_c *symbol);
+ void *visit(configuration_declaration_c *symbol);
+ void *visit(resource_declaration_c *symbol);
+ void *visit(single_resource_declaration_c *symbol);
/****************************************/
/* B.2 - Language IL (Instruction List) */
--- a/stage3/narrow_candidate_datatypes.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.cc Sun Nov 16 15:37:12 2014 +0000
@@ -747,6 +747,44 @@
/* B 1.4.3 - Declaration & Initialisation */
/******************************************/
+/* When handling the declaration of variables the fill/narrow algorithm will simply visit the objects
+ * in the abstract syntax tree defining the desired datatype for the variables. Tis is to set the
+ * symbol->datatype to the basetype of that datatype.
+ *
+ * Note that we do not currently set the symbol->datatype annotation for the identifier_c objects naming the
+ * variables inside the variable declaration. However, this is liable to change in the future, so do not write
+ * any code that depends on this!
+ *
+ * example:
+ * VAR var1, var2, var3 : my_type; END_VAR
+ * (* ^^^^ ^^^^ ^^^^ -> will NOT have the symbol->datatype set (for now, may change in the future!) *)
+ * (* ^^^^^^^ -> WILL have the symbol->datatype set *)
+ *
+ * (remeber too that the identifier_c objects identifying variables inside ST/IL/SFC code *will* have their
+ * symbol->datatype annotation filled by the fill/narrow algorithm)
+ */
+void *narrow_candidate_datatypes_c::narrow_var_declaration(symbol_c *type) {
+ if (type->candidate_datatypes.size() == 1)
+ type->datatype = type->candidate_datatypes[0];
+ type->accept(*this);
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(var1_init_decl_c *symbol) {return narrow_var_declaration(symbol->spec_init);}
+void *narrow_candidate_datatypes_c::visit(array_var_init_decl_c *symbol) {return narrow_var_declaration(symbol->array_spec_init);}
+void *narrow_candidate_datatypes_c::visit(structured_var_init_decl_c *symbol) {return narrow_var_declaration(symbol->initialized_structure);}
+void *narrow_candidate_datatypes_c::visit(fb_name_decl_c *symbol) {return narrow_var_declaration(symbol->fb_spec_init);}
+void *narrow_candidate_datatypes_c::visit(array_var_declaration_c *symbol) {return narrow_var_declaration(symbol->array_specification);}
+void *narrow_candidate_datatypes_c::visit(structured_var_declaration_c *symbol) {return narrow_var_declaration(symbol->structure_type_name);}
+void *narrow_candidate_datatypes_c::visit(external_declaration_c *symbol) {return narrow_var_declaration(symbol->specification);}
+void *narrow_candidate_datatypes_c::visit(global_var_decl_c *symbol) {return narrow_var_declaration(symbol->type_specification);}
+void *narrow_candidate_datatypes_c::visit(incompl_located_var_decl_c *symbol) {return narrow_var_declaration(symbol->var_spec);}
+//void *narrow_candidate_datatypes_c::visit(single_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->single_byte_string_spec);}
+//void *narrow_candidate_datatypes_c::visit(double_byte_string_var_declaration_c *symbol) {return handle_var_declaration(symbol->double_byte_string_spec);}
+
+
+
void *narrow_candidate_datatypes_c::visit(var1_list_c *symbol) {
#if 0 /* We don't really need to set the datatype of each variable. We just check the declaration itself! */
for(int i = 0; i < symbol->n; i++) {
@@ -856,10 +894,36 @@
/* B 1.7 Configuration elements */
/********************************/
void *narrow_candidate_datatypes_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;
-}
+ if (debug) printf("Narrowing candidate data types list in configuration %s\n", ((token_c *)(symbol->configuration_name))->value);
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ symbol->global_var_declarations->accept(*this);
+ symbol->resource_declarations ->accept(*this); // points to a single_resource_declaration_c or a resource_declaration_list_c
+// symbol->access_declarations ->accept(*this); // TODO
+// symbol->instance_specific_initializations->accept(*this); // TODO
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = NULL;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(resource_declaration_c *symbol) {
+ if (debug) printf("Narrowing candidate data types list in resource %s\n", ((token_c *)(symbol->resource_name))->value);
+ search_varfb_instance_type_c *prev_search_varfb_instance_type = search_varfb_instance_type;
+ search_varfb_instance_type = new search_varfb_instance_type_c(symbol);
+ symbol->global_var_declarations->accept(*this);
+ symbol->resource_declaration ->accept(*this); // points to a single_resource_declaration_c!
+ delete search_varfb_instance_type;
+ search_varfb_instance_type = prev_search_varfb_instance_type;
+ return NULL;
+}
+
+
+void *narrow_candidate_datatypes_c::visit(single_resource_declaration_c *symbol) {
+// symbol->task_configuration_list ->accept(*this); // TODO
+// symbol->program_configuration_list ->accept(*this); // TODO
+ return NULL;
+}
+
/****************************************/
--- a/stage3/narrow_candidate_datatypes.hh Sun Nov 09 22:02:34 2014 +0000
+++ b/stage3/narrow_candidate_datatypes.hh Sun Nov 16 15:37:12 2014 +0000
@@ -80,9 +80,10 @@
void *narrow_S_and_R_operator (symbol_c *symbol, const char *param_name, symbol_c * called_fb_declaration);
void *narrow_store_operator (symbol_c *symbol);
void *narrow_conditional_operator(symbol_c *symbol);
- void *narrow_binary_operator (const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation = NULL);
- void *narrow_binary_expression (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false);
- void *narrow_equality_comparison(const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL);
+ void *narrow_binary_operator (const struct widen_entry widen_table[], symbol_c *symbol, bool *deprecated_operation = NULL);
+ void *narrow_binary_expression (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL, bool allow_enums = false);
+ void *narrow_equality_comparison (const struct widen_entry widen_table[], symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool *deprecated_operation = NULL);
+ void *narrow_var_declaration (symbol_c *type);
void *set_il_operand_datatype (symbol_c *il_operand, symbol_c *datatype);
@@ -201,9 +202,20 @@
/******************************************/
/* B 1.4.3 - Declaration & Initialisation */
/******************************************/
- void *visit(var1_list_c *symbol);
- void *visit(location_c *symbol);
- void *visit(located_var_decl_c *symbol);
+ void *visit(var1_list_c *symbol);
+ void *visit(location_c *symbol);
+ void *visit(located_var_decl_c *symbol);
+ void *visit(var1_init_decl_c *symbol);
+ void *visit(array_var_init_decl_c *symbol);
+ void *visit(structured_var_init_decl_c *symbol);
+ void *visit(fb_name_decl_c *symbol);
+ void *visit(array_var_declaration_c *symbol);
+ void *visit(structured_var_declaration_c *symbol);
+ void *visit(external_declaration_c *symbol);
+ void *visit(global_var_decl_c *symbol);
+ void *visit(incompl_located_var_decl_c *symbol);
+ //void *visit(single_byte_string_var_declaration_c *symbol);
+ //void *visit(double_byte_string_var_declaration_c *symbol);
/**************************************/
/* B 1.5 - Program organization units */
@@ -231,7 +243,10 @@
/********************************/
/* B 1.7 Configuration elements */
/********************************/
- void *visit(configuration_declaration_c *symbol);
+ void *visit(configuration_declaration_c *symbol);
+ void *visit(resource_declaration_c *symbol);
+ void *visit(single_resource_declaration_c *symbol);
+
/****************************************/
/* B.2 - Language IL (Instruction List) */
/****************************************/
--- a/stage4/generate_c/generate_c.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c.cc Sun Nov 16 15:37:12 2014 +0000
@@ -250,7 +250,7 @@
* LEN( STRING) : INT -> prints out -> INT__STRING
* MUL(TIME, INT) : TIME -> prints out -> TIME__TIME__INT
*/
-class print_function_parameter_data_types_c: public generate_c_base_c {
+class print_function_parameter_data_types_c: public generate_c_base_and_typeid_c {
private:
symbol_c *current_type;
bool_type_name_c tmp_bool;
@@ -269,7 +269,7 @@
public:
print_function_parameter_data_types_c(stage4out_c *s4o_ptr):
- generate_c_base_c(s4o_ptr)
+ generate_c_base_and_typeid_c(s4o_ptr)
{current_type = NULL;}
/**************************************/
@@ -752,185 +752,6 @@
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-/***********************************************************************/
-
-
-identifier_c *generate_unique_id(const char *prefix = "", symbol_c *clone = NULL) {
- static int counter = 0;
-
- counter++;
- int len = snprintf(NULL, 0, "%s__UID_%d", prefix, counter); // UID -> Unique IDentifier
- char *str = (char *)malloc(len+1);
- if (snprintf(str, len+1, "%s__UID_%d", prefix, counter) < 0) ERROR;
-
- identifier_c *id = new identifier_c(str);
- if (NULL == id) ERROR;
- if (NULL != clone)
- *(dynamic_cast<symbol_c *>(id)) = *(dynamic_cast<symbol_c *>(clone));
- return id;
-}
-
-
-identifier_c *generate_unique_id(symbol_c *prefix, symbol_c *clone = NULL) {
- token_c *token = dynamic_cast<token_c *>(prefix);
- //if (NULL == token) ERROR;
- if (NULL == token)
- return generate_unique_id("", clone);
- return generate_unique_id(token->value, clone);
-}
-
-
-/* This class will generate a new datatype for each implicitly declared array datatype
- * (i.e. arrays declared in a variable declaration, or a struct datatype declaration...)
- * It will do the same for implicitly declared REF_TO datatypes.
- *
- * The class will be called once for each POU declaration, and once for each derived datatype declaration.
- *
- * e.g.:
- * VAR a: ARRAY [1..3] OF INT; END_VAR <---- ARRAY datatype is implicitly declared inside the variable declaration
- * TYPE STRUCT
- * a: ARRAY [1..3] OF INT; <---- ARRAY datatype is implicitly declared inside the struct type declaration
- * b: INT;
- * END_STRUCT
- * END_TYPE
- */
-class generate_c_datatypes_c: public iterator_visitor_c {
- private:
- generate_c_typedecl_c generate_c_typedecl;
- symbol_c *prefix;
- public:
- generate_c_datatypes_c(stage4out_c *s4o_incl_ptr)
- : generate_c_typedecl(s4o_incl_ptr) {
- prefix = NULL;
- };
- virtual ~generate_c_datatypes_c(void) {
- }
-
- /*************************/
- /* B.1 - Common elements */
- /*************************/
- /**********************/
- /* B.1.3 - Data types */
- /**********************/
- /********************************/
- /* B 1.3.3 - Derived data types */
- /********************************/
- /* identifier ':' array_spec_init */
- void *visit(array_type_declaration_c *symbol) {return NULL;} // This is not an implicitly defined array!
-
- /* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
- void *visit(ref_spec_c *symbol) {
- identifier_c *id = generate_unique_id(prefix, symbol);
- /* Warning: The following is dangerous...
- * We are asking the generate_c_typedecl_c visitor to visit a newly created ref_spec_init_c object
- * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
- * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
- */
- ref_spec_init_c ref_spec(symbol, NULL);
- ref_type_decl_c ref_decl(id, &ref_spec);
- ref_decl.accept(generate_c_typedecl); // Must be done _before_ adding the annotation, due to the way generate_c_typedecl_c works
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
- return NULL;
- }
-
- /* For the moment, we do not support initialising reference data types */
- /* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */
- /* NOTE: ref_initialization may be NULL!! */
- // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
- void *visit(ref_spec_init_c *symbol) {
- symbol->ref_spec->accept(*this);
- int implicit_id_count = symbol->ref_spec->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1)
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->ref_spec->anotations_map["generate_c_annotaton__implicit_type_id"];
- return NULL;
- }
-
- /* ref_type_decl: identifier ':' ref_spec_init */
- void *visit(ref_type_decl_c *symbol) {return NULL;} // This is not an implicitly defined REF_TO!
-
- /******************************************/
- /* B 1.4.3 - Declaration & Initialization */
- /******************************************/
- void *visit(edge_declaration_c *symbol) {return NULL;}
- void *visit(en_param_declaration_c *symbol) {return NULL;}
- void *visit(eno_param_declaration_c *symbol) {return NULL;}
-
- /* array_specification [ASSIGN array_initialization] */
- /* array_initialization may be NULL ! */
- void *visit(array_spec_init_c *symbol) {
- symbol->array_specification->accept(*this);
- int implicit_id_count = symbol->array_specification->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1)
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->array_specification->anotations_map["generate_c_annotaton__implicit_type_id"];
- return NULL;
- }
-
- /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
- void *visit(array_specification_c *symbol) {
- identifier_c *id = generate_unique_id(prefix, symbol);
- /* Warning: The following is dangerous...
- * We are asking the generate_c_typedecl_c visitor to visit a newly created array_type_declaration_c object
- * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
- * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
- */
- array_spec_init_c array_spec(symbol, NULL);
- array_type_declaration_c array_decl(id, &array_spec);
- array_decl.accept(generate_c_typedecl); // Must be done _before_ adding the annotation, due to the way generate_c_typedecl_c works
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
- return NULL;
- }
-
- /* var1_list ':' initialized_structure */
- // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
- void *visit(structured_var_init_decl_c *symbol) {return NULL;}
-
- /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
- /* structure_initialization -> may be NULL ! */
- void *visit(fb_name_decl_c *symbol) {return NULL;}
-
- /* var1_list ':' structure_type_name */
- //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
- void *visit(structured_var_declaration_c *symbol) {return NULL;}
-
-
- /***********************/
- /* B 1.5.1 - Functions */
- /***********************/
- void *visit(function_declaration_c *symbol) {
- prefix = symbol->derived_function_name;
- symbol->var_declarations_list->accept(*this);
- prefix = NULL;
- return NULL;
- }
- /*****************************/
- /* B 1.5.2 - Function Blocks */
- /*****************************/
- void *visit(function_block_declaration_c *symbol) {
- prefix = symbol->fblock_name;
- symbol->var_declarations->accept(*this);
- prefix = NULL;
- return NULL;
- }
- /**********************/
- /* B 1.5.3 - Programs */
- /**********************/
- void *visit(program_declaration_c *symbol) {
- prefix = symbol->program_type_name;
- symbol->var_declarations->accept(*this);
- prefix = NULL;
- return NULL;
- }
-};
-
-
-
-
@@ -986,8 +807,8 @@
/* FUNCTION derived_function_name ':' elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
/* | FUNCTION derived_function_name ':' derived_type_name io_OR_function_var_declarations_list function_body END_FUNCTION */
static void handle_function(function_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
- generate_c_vardecl_c *vardecl = NULL;
- generate_c_base_c print_base(&s4o);
+ generate_c_vardecl_c *vardecl = NULL;
+ generate_c_base_and_typeid_c print_base(&s4o);
TRACE("function_declaration_c");
@@ -1123,9 +944,9 @@
/* 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)
static void handle_function_block(function_block_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
- generate_c_vardecl_c *vardecl;
- generate_c_sfcdecl_c *sfcdecl;
- generate_c_base_c print_base(&s4o);
+ generate_c_vardecl_c *vardecl;
+ generate_c_sfcdecl_c *sfcdecl;
+ generate_c_base_and_typeid_c print_base(&s4o);
TRACE("function_block_declaration_c");
/* (A) Function Block data structure declaration... */
@@ -1325,9 +1146,9 @@
/* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */
//SYM_REF4(program_declaration_c, program_type_name, var_declarations, function_block_body, unused)
static void handle_program(program_declaration_c *symbol, stage4out_c &s4o, bool print_declaration) {
- generate_c_vardecl_c *vardecl;
- generate_c_sfcdecl_c *sfcdecl;
- generate_c_base_c print_base(&s4o);
+ generate_c_vardecl_c *vardecl;
+ generate_c_sfcdecl_c *sfcdecl;
+ generate_c_base_and_typeid_c print_base(&s4o);
TRACE("program_declaration_c");
/* (A) Program data structure declaration... */
@@ -1499,13 +1320,13 @@
/***********************************************************************/
/***********************************************************************/
-class generate_c_config_c: public generate_c_base_c {
+class generate_c_config_c: public generate_c_base_and_typeid_c {
private:
stage4out_c &s4o_incl;
public:
generate_c_config_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
- : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
};
virtual ~generate_c_config_c(void) {}
@@ -1710,7 +1531,7 @@
/***********************************************************************/
-class generate_c_resources_c: public generate_c_typedecl_c {
+class generate_c_resources_c: public generate_c_base_and_typeid_c {
search_var_instance_decl_c *search_config_instance;
search_var_instance_decl_c *search_resource_instance;
@@ -1726,7 +1547,7 @@
public:
generate_c_resources_c(stage4out_c *s4o_ptr, symbol_c *config_scope, symbol_c *resource_scope, unsigned long time)
- : generate_c_typedecl_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
current_configuration = config_scope;
search_config_instance = new search_var_instance_decl_c(config_scope);
search_resource_instance = new search_var_instance_decl_c(resource_scope);
@@ -2237,9 +2058,9 @@
stage4out_c located_variables_s4o;
stage4out_c variables_s4o;
- generate_c_datatypes_c generate_c_datatypes;
- generate_c_typedecl_c generate_c_typedecl;
- generate_c_pous_c generate_c_pous;
+ generate_c_typedecl_c generate_c_typedecl;
+ generate_c_implicit_typedecl_c generate_c_implicit_typedecl;
+ generate_c_pous_c generate_c_pous;
symbol_c *current_configuration;
@@ -2257,8 +2078,8 @@
pous_incl_s4o(builddir, "POUS", "h"),
located_variables_s4o(builddir, "LOCATED_VARIABLES","h"),
variables_s4o(builddir, "VARIABLES","csv"),
- generate_c_datatypes(&pous_incl_s4o),
- generate_c_typedecl (&pous_incl_s4o)
+ generate_c_typedecl (&pous_incl_s4o),
+ generate_c_implicit_typedecl(&pous_incl_s4o, &generate_c_typedecl)
{
current_builddir = builddir;
current_configuration = NULL;
@@ -2337,7 +2158,7 @@
/* helper symbol for data_type_declaration */
void *visit(type_declaration_list_c *symbol) {
for(int i = 0; i < symbol->n; i++) {
- symbol->elements[i]->accept(generate_c_datatypes);
+ symbol->elements[i]->accept(generate_c_implicit_typedecl);
symbol->elements[i]->accept(generate_c_typedecl);
}
return NULL;
@@ -2349,14 +2170,14 @@
#define handle_pou(fname,pname) \
if (!allow_output) return NULL;\
if (generate_pou_filepairs__) {\
- const char *pou_name = get_datatype_info_c::get_id_str(pname);\
+ const char *pou_name = get_datatype_info_c::get_id_str(pname);\
stage4out_c s4o_c(current_builddir, pou_name, "c");\
stage4out_c s4o_h(current_builddir, pou_name, "h");\
s4o_c.print("#include \""); s4o_c.print(pou_name); s4o_c.print(".h\"\n");\
s4o_h.print("#ifndef __"); s4o_h.print(pou_name); s4o_h.print("_H\n");\
s4o_h.print("#define __"); s4o_h.print(pou_name); s4o_h.print("_H\n");\
- generate_c_datatypes_c generate_c_datatypes__(&s4o_h);\
- symbol->accept(generate_c_datatypes__); /* generate implicitly delcared datatypes (arrays and ref_to) */\
+ generate_c_implicit_typedecl_c generate_c_implicit_typedecl__(&s4o_h);\
+ symbol->accept(generate_c_implicit_typedecl__); /* generate implicitly delcared datatypes (arrays and ref_to) */\
generate_c_pous_c::fname(symbol, s4o_h, true); /* generate the <pou_name>.h file */\
generate_c_pous_c::fname(symbol, s4o_c, false);/* generate the <pou_name>.c file */\
s4o_h.print("#endif /* __"); s4o_h.print(pou_name); s4o_h.print("_H */\n");\
@@ -2368,7 +2189,7 @@
pous_incl_s4o.print(".h\"\n");\
pous_s4o. print(".c\"\n");\
} else {\
- symbol->accept(generate_c_datatypes);\
+ symbol->accept(generate_c_implicit_typedecl);\
generate_c_pous_c::fname(symbol, pous_incl_s4o, true);\
generate_c_pous_c::fname(symbol, pous_s4o, false);\
}
@@ -2403,7 +2224,7 @@
/********************************/
void *visit(configuration_declaration_c *symbol) {
if (symbol->global_var_declarations != NULL)
- symbol->global_var_declarations->accept(generate_c_datatypes);
+ symbol->global_var_declarations->accept(generate_c_implicit_typedecl);
static int configuration_count = 0;
if (configuration_count++) {
@@ -2446,7 +2267,7 @@
void *visit(resource_declaration_c *symbol) {
if (symbol->global_var_declarations != NULL)
- symbol->global_var_declarations->accept(generate_c_datatypes);
+ symbol->global_var_declarations->accept(generate_c_implicit_typedecl);
symbol->resource_name->accept(*this);
stage4out_c resources_s4o(current_builddir, current_name, "c");
generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
--- a/stage4/generate_c/generate_c_base.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_base.cc Sun Nov 16 15:37:12 2014 +0000
@@ -26,6 +26,30 @@
+/* This file cotains two main classes:
+ * - generate_c_base_c
+ * - generate_c_base_and_typeid_c
+ *
+ * generate_c_base_c
+ * -----------------
+ * This class generates C code for all literals and varables. In short, all the basic stuff
+ * that will probably be needed in all other code generating classes.
+ * It does not however handle derived datatypes.
+ *
+ * generate_c_base_and_typeid_c
+ * ----------------------------
+ * This is similar to the generate_c_base_c (from which it inherits), but it also handles
+ * all the derived datatypes. Note that it does not generate C code for the declaration of
+ * those datatypes (that is what generate_c_typedecl_c is for), but rather it merely
+ * generates the name/id of a derived datatype.
+ * Note too that not all derived datatypes in the IEC 61131-3 have a name (for example,
+ * VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should
+ * have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c.
+ */
+
+
+
+
typedef struct
{
@@ -61,6 +85,12 @@
param_list.clear();
+/* generate_c_base_c
+ * -----------------
+ * This class generates C code for all literals and varables. In short, all the basic stuff
+ * that will probably be needed in all other code generating classes.
+ * It does not however handle derived datatypes.
+ */
class generate_c_base_c: public iterator_visitor_c {
protected:
@@ -298,6 +328,10 @@
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
void *visit(identifier_c *symbol) {return print_token(symbol);}
+ /* If you need the derived_datatype_identifier_c visitor, then you should probably be
+ * inheriting from generate_c_base_and_typeid_c and not generate_c_base_c !!
+ */
+ void *visit(derived_datatype_identifier_c *symbol) {ERROR; return NULL;}
/*********************/
/* B 1.2 - Constants */
@@ -594,12 +628,11 @@
/* Currently only used in REF_TO ANY, which is mapped onto (void *) */
void *visit(generic_type_any_c *symbol) {s4o.print("void"); return NULL;}
+
/********************************/
/* B 1.3.3 - Derived data types */
/********************************/
- /* leave for derived classes... */
-
-
+
/* enumerated_type_name '#' identifier */
void *visit(enumerated_value_c *symbol) {
if (NULL == symbol->datatype) {
@@ -619,97 +652,6 @@
}
-/* identifier ':' array_spec_init */
-void *visit(array_type_declaration_c *symbol) {ERROR;/* Should never get called! */ return NULL;}
-
-/* array_specification [ASSIGN array_initialization] */
-/* array_initialization may be NULL ! */
-void *visit(array_spec_init_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count != 1) ERROR;
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
-void *visit(array_specification_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count != 1) ERROR;
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-
-/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
-void *visit(ref_spec_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count != 1) ERROR;
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* For the moment, we do not support initialising reference data types */
-/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */
-/* NOTE: ref_initialization may be NULL!! */
-// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
-void *visit(ref_spec_init_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count != 1) ERROR;
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
-}
-
-/* ref_type_decl: identifier ':' ref_spec_init */
-void *visit(ref_type_decl_c *symbol) {ERROR;/* Should never get called! */ return NULL;}
-
-
-
-
-
-/* NOTE: visit(subrange_spec_init_c *)
- * and visit(subrange_specification_c *)
- * together simply print out the integer datatype
- * on which the subrange is based.
- *
- * Future code clean-ups should delete these two
- * visit mehotds, and make sure whoever calls them
- * uses symbol->datatype instead!
- */
-/* subrange_specification ASSIGN signed_integer */
-void *visit(subrange_spec_init_c *symbol) {
- TRACE("subrange_spec_init_c");
- symbol->subrange_specification->accept(*this);
- return NULL;
-}
-
-/* integer_type_name '(' subrange')' */
-void *visit(subrange_specification_c *symbol) {
- TRACE("subrange_specification_c");
- symbol->integer_type_name->accept(*this);
- return NULL;
-}
-
-
-/* NOTE: Why is this here? This visit() method should not be here!!
- * TODO: Figure out who is dependent on this method, and move it to its correct location!
- */
-/* helper symbol for array_specification */
-/* array_subrange_list ',' subrange */
-void *visit(array_subrange_list_c *symbol) {
- TRACE("array_subrange_list_c");
- print_list(symbol);
- return NULL;
-}
-
-
/*********************/
/* B 1.4 - Variables */
/*********************/
@@ -720,6 +662,7 @@
return NULL;
}
+
/********************************************/
/* B.1.4.1 Directly Represented Variables */
/********************************************/
@@ -730,15 +673,12 @@
}
-
/*************************************/
/* B.1.4.2 Multi-element Variables */
/*************************************/
-#if 0
/* subscripted_variable '[' subscript_list ']' */
-SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
-
-#endif
+//SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+
/* record_variable '.' field_selector */
/* WARNING: input and/or output variables of function blocks
@@ -845,10 +785,205 @@
-
-
-
-
-
-
-
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+/************************************************************************************************/
+
+
+
+/* generate_c_base_and_typeid_c
+ * ----------------------------
+ * This is similar to the generate_c_base_c (from which it inherits), but it also handles
+ * all the derived datatypes. Note that it does not generate C code for the declaration of
+ * those datatypes (that is what generate_c_typedecl_c is for), but rather it merely
+ * generates the name/id of a derived datatype.
+ * Note too that not all derived datatypes in the IEC 61131-3 have a name (for example,
+ * VAR a: ARRAY [3..5] of INT END_VAR), in which case an alias for this datatype should
+ * have been previously generated by either generate_c_typedecl_c or generate_implicit_typedecl_c.
+ */
+class generate_c_base_and_typeid_c: public generate_c_base_c {
+
+ public:
+ generate_c_base_and_typeid_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr) {}
+ ~generate_c_base_and_typeid_c(void) {}
+
+
+/*************************/
+/* B.1 - Common elements */
+/*************************/
+/*******************************************/
+/* B 1.1 - Letters, digits and identifiers */
+/*******************************************/
+ void *visit(derived_datatype_identifier_c *symbol) {
+ if (get_datatype_info_c::is_array(symbol->datatype)) {
+ return symbol->datatype->accept(*this);
+ }
+ return print_token(symbol);
+ }
+
+/*********************/
+/* B 1.2 - Constants */
+/*********************/
+/**********************/
+/* B.1.3 - Data types */
+/**********************/
+/***********************************/
+/* B 1.3.1 - Elementary Data Types */
+/***********************************/
+/********************************/
+/* B.1.3.2 - Generic data types */
+/********************************/
+ /* Currently only used in REF_TO ANY, which is mapped onto (void *) */
+ void *visit(generic_type_any_c *symbol) {s4o.print("void"); return NULL;}
+
+/********************************/
+/* B 1.3.3 - Derived data types */
+/********************************/
+
+/* subrange_type_name ':' subrange_spec_init */
+void *visit(subrange_type_declaration_c *symbol) {return symbol->subrange_type_name->accept(*this);}
+
+/* subrange_specification ASSIGN signed_integer */
+void *visit(subrange_spec_init_c *symbol) {return symbol->subrange_specification->accept(*this);}
+
+/* integer_type_name '(' subrange')' */
+void *visit(subrange_specification_c *symbol) {return symbol->integer_type_name->accept(*this);}
+
+/* enumerated_type_name ':' enumerated_spec_init */
+void *visit(enumerated_type_declaration_c *symbol) {return symbol->enumerated_type_name->accept(*this);}
+
+/* enumerated_specification ASSIGN enumerated_value */
+void *visit(enumerated_spec_init_c *symbol) {return symbol->enumerated_specification->accept(*this);}
+
+
+/* enumerated_type_name '#' identifier */
+/* Handled by generate_c_base_c class!!
+void *visit(enumerated_value_c *symbol) {}
+*/
+
+/* identifier ':' array_spec_init */
+void *visit(array_type_declaration_c *symbol) {
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (1 != implicit_id_count) ERROR;
+ return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+}
+
+
+
+/* array_specification [ASSIGN array_initialization] */
+/* array_initialization may be NULL ! */
+void *visit(array_spec_init_c *symbol) {
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (1 == implicit_id_count) return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+ if (0 == implicit_id_count) return symbol->datatype->accept(*this);
+ return NULL;
+}
+
+/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+void *visit(array_specification_c *symbol) {
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (1 != implicit_id_count) ERROR;
+ return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+}
+
+
+
+/* simple_type_name ':' simple_spec_init */
+void *visit(simple_type_declaration_c *symbol) {return symbol->simple_type_name->accept(*this);}
+
+/* simple_specification [ASSIGN constant] */
+//SYM_REF2(simple_spec_init_c, simple_specification, constant)
+// <constant> may be NULL
+void *visit(simple_spec_init_c *symbol) {return symbol->simple_specification->accept(*this);}
+
+/* structure_type_name ':' structure_specification */
+//SYM_REF2(structure_type_declaration_c, structure_type_name, structure_specification)
+void *visit(structure_type_declaration_c *symbol) {return symbol->structure_type_name->accept(*this);}
+
+/* structure_type_name ASSIGN structure_initialization */
+/* structure_initialization may be NULL ! */
+//SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
+void *visit(initialized_structure_c *symbol) {return symbol->structure_type_name->accept(*this);}
+
+
+
+/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
+// SYM_REF1(ref_spec_c, type_name)
+void *visit(ref_spec_c *symbol) {
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (implicit_id_count > 1) ERROR;
+ if (implicit_id_count == 1) {
+ /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
+ * has already been defined. So, we simly print out the id of that C datatpe...
+ */
+ return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+ }
+ /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *),
+ * through the visit(ref_spec_init_c*)), so we need to simply print out the name of the datatype we reference to.
+ */
+ //debug_c::print(symbol); ERROR;
+ symbol->type_name->accept(*this);
+ s4o.print("*");
+ return NULL;
+}
+
+/* For the moment, we do not support initialising reference data types */
+/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */
+/* NOTE: ref_initialization may be NULL!! */
+// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+void *visit(ref_spec_init_c *symbol) {
+ /* NOTE An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+ * and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+ * However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+ * to the same identifier (e.g: __REF_TO_INT).
+ * In order for the C compiler not to find the same datatype being defined two or more times,
+ * we will keep track of the datatypes that have already been declared, and henceforth
+ * only declare the datatypes that have not been previously defined.
+ */
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (1 < implicit_id_count) ERROR;
+ if (1 == implicit_id_count)
+ return symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*this);
+ return symbol->ref_spec->accept(*this); // this is probably pointing to an identifier_c !!
+}
+
+/* ref_type_decl: identifier ':' ref_spec_init */
+// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
+void *visit(ref_type_decl_c *symbol) {
+ TRACE("ref_type_decl_c");
+ /* NOTE An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+ * and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+ * However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+ * to the same identifier (e.g: __REF_TO_INT).
+ * In order for the C compiler not to find the same datatype being defined two or more times,
+ * we will keep track of the datatypes that have already been declared, and henceforth
+ * only declare the datatypes that have not been previously defined.
+ */
+ int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (0 != implicit_id_count) ERROR;
+ //symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(generate_c_base);
+ return symbol->ref_type_name->accept(*this);
+}
+
+
+}; /* class generate_c_base_and_typeid_c */
+
+
+
+
+
+
+
+
+
+
+
+
+
--- a/stage4/generate_c/generate_c_configbody.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_configbody.cc Sun Nov 16 15:37:12 2014 +0000
@@ -22,11 +22,11 @@
* used in safety-critical situations without a full and competent review.
*/
-class generate_c_configbody_c: public generate_c_base_c {
+class generate_c_configbody_c: public generate_c_base_and_typeid_c {
public:
generate_c_configbody_c(stage4out_c *s4o_ptr)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
current_resource_name = NULL;
}
--- a/stage4/generate_c/generate_c_il.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_il.cc Sun Nov 16 15:37:12 2014 +0000
@@ -126,7 +126,7 @@
-class generate_c_il_c: public generate_c_base_c, il_default_variable_visitor_c {
+class generate_c_il_c: public generate_c_base_and_typeid_c, il_default_variable_visitor_c {
public:
typedef enum {
@@ -197,7 +197,7 @@
public:
generate_c_il_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr),
+ : generate_c_base_and_typeid_c(s4o_ptr),
implicit_variable_current (IL_DEFVAR, NULL),
implicit_variable_result (IL_DEFVAR, NULL),
implicit_variable_result_back(IL_DEFVAR_BACK, NULL)
--- a/stage4/generate_c/generate_c_inlinefcall.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_inlinefcall.cc Sun Nov 16 15:37:12 2014 +0000
@@ -26,7 +26,7 @@
#define INLINE_RESULT_TEMP_VAR "__res"
#define INLINE_PARAM_COUNT "__PARAM_COUNT"
-class generate_c_inlinefcall_c: public generate_c_base_c {
+class generate_c_inlinefcall_c: public generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -76,7 +76,7 @@
public:
generate_c_inlinefcall_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr),
+ : generate_c_base_and_typeid_c(s4o_ptr),
implicit_variable_current(IL_DEFVAR, NULL)
{
search_varfb_instance_type = new search_varfb_instance_type_c(scope);
--- a/stage4/generate_c/generate_c_sfc.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_sfc.cc Sun Nov 16 15:37:12 2014 +0000
@@ -34,7 +34,7 @@
/***********************************************************************/
/***********************************************************************/
-class generate_c_sfc_elements_c: public generate_c_base_c {
+class generate_c_sfc_elements_c: public generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -63,7 +63,7 @@
public:
generate_c_sfc_elements_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
generate_c_il = new generate_c_il_c(s4o_ptr, name, scope, variable_prefix);
generate_c_st = new generate_c_st_c(s4o_ptr, name, scope, variable_prefix);
generate_c_code = new generate_c_SFC_IL_ST_c(s4o_ptr, name, scope, variable_prefix);
@@ -655,7 +655,7 @@
/***********************************************************************/
/***********************************************************************/
-class generate_c_sfc_c: public generate_c_base_c {
+class generate_c_sfc_c: public generate_c_base_and_typeid_c {
private:
std::list<VARIABLE> variable_list;
@@ -665,7 +665,7 @@
public:
generate_c_sfc_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
generate_c_sfc_elements = new generate_c_sfc_elements_c(s4o_ptr, name, scope, variable_prefix);
search_var_instance_decl = new search_var_instance_decl_c(scope);
this->set_variable_prefix(variable_prefix);
--- a/stage4/generate_c/generate_c_sfcdecl.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_sfcdecl.cc Sun Nov 16 15:37:12 2014 +0000
@@ -32,7 +32,7 @@
/***********************************************************************/
/***********************************************************************/
-class generate_c_sfcdecl_c: protected generate_c_base_c {
+class generate_c_sfcdecl_c: protected generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -59,7 +59,7 @@
public:
generate_c_sfcdecl_c(stage4out_c *s4o_ptr, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
this->set_variable_prefix(variable_prefix);
search_var_instance_decl = new search_var_instance_decl_c(scope);
}
--- a/stage4/generate_c/generate_c_st.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_st.cc Sun Nov 16 15:37:12 2014 +0000
@@ -44,7 +44,7 @@
/***********************************************************************/
-class generate_c_st_c: public generate_c_base_c {
+class generate_c_st_c: public generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -93,7 +93,7 @@
public:
generate_c_st_c(stage4out_c *s4o_ptr, symbol_c *name, symbol_c *scope, const char *variable_prefix = NULL)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
search_fb_instance_decl = new search_fb_instance_decl_c (scope);
search_varfb_instance_type = new search_varfb_instance_type_c(scope);
search_var_instance_decl = new search_var_instance_decl_c (scope);
--- a/stage4/generate_c/generate_c_typedecl.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_typedecl.cc Sun Nov 16 15:37:12 2014 +0000
@@ -23,6 +23,221 @@
*/
#include <stdlib.h>
+
+/* Ths class contains two main classes:
+ * - generate_c_typedecl_c
+ * - generate_c_implicit_typedecl_c
+ *
+ * and an auxiliary class
+ * - generate_datatypes_aliasid_c
+ *
+ *
+ * Both the generate_c_typedecl_c and the generate_c_implicit_typedecl_c may set a stage4
+ * annotation (in the stage4 annotation map of each symbol_c) named
+ * "generate_c_annotaton__implicit_type_id"
+ * If this annotation is set, the generate_c_base_c will print out this value instead of
+ * the datatype's name!
+ *
+ *
+ *
+ * generate_c_typedecl_c
+ * ---------------------
+ * Given a datatype object (i.e. an object in the AST that is also used to define a datatype,
+ * typically one that may be returned by search_basetype_c), this class will generate the
+ * C code to declare an equivakent datatype in C.
+ * Note that array datatypes are handled in a special way; instead of using the name given
+ * to it in the IEC 61131-3 source code, and new alias is created for the datatype name in C.
+ * Eplanations why we do this may be found further on...
+ *
+ *
+ * generate_c_implicit_typedecl_c
+ * ------------------------------
+ * Given a POU or a derived datatype declaration, it will search for any implicitly defined
+ * datatypes in that POU/datatype declaration. Implicit datatypes are datatypes that are not
+ * explicitly declared and given a name. Example:
+ * VAR a: ARRAY [9..11] of INT; END_VAR
+ * Here, the array is implictly delcared.
+ * For eac implicitly defined datatype, an alias for that datatype is created (by calling
+ * generate_datatypes_aliasid_c), and a C declaration is generated in C source code (by
+ * calling generate_c_typedecl_c).
+ *
+ *
+ * generate_datatypes_aliasid_c
+ * ----------------------------
+ * Given a datatype object (i.e. an object in the AST that defines a datatype), it will create
+ * an alias name for that datatype.
+ * This class is used by both the generate_c_implicit_typedecl_c, and the generate_c_typedecl_c
+ * classes!
+ */
+
+
+
+
+
+
+/* generate an alias/name (identifier) for array and REF_TO datatypes */
+/*
+ * The generated alias is created based on the structure of the datatype itself, in order to
+ * guarantee that any two datatypes that have the same internal format will result in the same
+ * alias.
+ * examples:
+ * ARRAY [9..11] of INT --> __ARRAY_9_11_OF_INT
+ * REF_TO INT --> __REF_TO_INT
+ * ARRAY [9..11] of REF_TO INT --> __ARRAY_9_11_OF___REF_TO_INT
+ */
+class generate_datatypes_aliasid_c: fcall_visitor_c {
+
+ private:
+ //std::map<std::string, int> inline_array_defined;
+ std::string current_array_name;
+ static generate_datatypes_aliasid_c *singleton_;
+
+ public:
+ generate_datatypes_aliasid_c(void) {};
+
+ virtual ~generate_datatypes_aliasid_c(void) {
+ //inline_array_defined.clear(); // Not really necessary...
+ }
+
+ /* implement the virtual member function declared in fcall_visitor_c */
+ // by default generate an ERROR if a visit method is called, unless it is explicitly handled in generate_datatypes_aliasid_c
+ void fcall(symbol_c *symbol) {ERROR;}
+
+ static identifier_c *create_id(symbol_c *symbol) {
+ if (NULL == singleton_) singleton_ = new generate_datatypes_aliasid_c();
+ if (NULL == singleton_) ERROR;
+ singleton_->current_array_name = "";
+ symbol->accept(*singleton_);
+ const char *str1 = singleton_->current_array_name.c_str();
+ char *str2 = (char *)malloc(strlen(str1)+1);
+ if (NULL == str2) ERROR;
+ strcpy(str2, str1);
+ identifier_c *id = new identifier_c(str2);
+ /* Copy all the anotations in the symbol_c object 'symbol' to the newly created 'id' object
+ * This includes the location (in the IEC 61131-3 source file) annotations set in stage1_2,
+ * the symbol->datatype set in stage3, and any other anotaions that may be created in the future!
+ */
+ *(dynamic_cast<symbol_c *>(id)) = *(dynamic_cast<symbol_c *>(symbol));
+ return id;
+ }
+
+ /*************************/
+ /* B.1 - Common elements */
+ /*************************/
+ /**********************/
+ /* B.1.3 - Data types */
+ /**********************/
+ /***********************************/
+ /* B 1.3.1 - Elementary Data Types */
+ /***********************************/
+ /***********************************/
+ /* B 1.3.2 - Generic Data Types */
+ /***********************************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ /* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
+ void *visit(ref_spec_c *symbol) {
+ current_array_name = "__REF_TO_";
+ current_array_name += get_datatype_info_c::get_id_str(symbol->type_name);
+ return NULL;
+ }
+
+ /******************************************/
+ /* B 1.4.3 - Declaration & Initialization */
+ /******************************************/
+ /* array_specification [ASSIGN array_initialization] */
+ /* array_initialization may be NULL ! */
+ void *visit(array_spec_init_c *symbol) {
+ if (NULL == symbol->datatype) ERROR;
+ symbol->datatype->accept(*this); // the base datatype should be an array_specification_c !!
+ return NULL;
+ }
+
+ /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+ void *visit(array_specification_c *symbol) {
+ current_array_name = "__ARRAY_OF_";
+ if ( get_datatype_info_c::is_ref_to(symbol->non_generic_type_name)
+ && (get_datatype_info_c::get_ref_to(symbol->non_generic_type_name) != NULL)) {
+ /* handle situations where we have 2 impliclitly defined datatype, namely a REF_TO inside an ARRAY
+ * e.g. TYPE array_of_ref_to_sint : ARRAY [1..3] OF REF_TO SINT; END_TYPE
+ * The second condition (get_datatype_info_c::get_ref_to(symbol->non_generic_type_name) != NULL)
+ * in the above if() is to make sure we use the standard algorithm if the array is of a previously
+ * defined REF_TO type, in which case symbol->non_generic_type_name will reference an identifier_c!
+ * e.g. TYPE array_of_ref_to_sint : ARRAY [1..3] OF REF_TO SINT; END_TYPE
+ */
+ current_array_name += "__REF_TO_";
+ current_array_name += get_datatype_info_c::get_id_str(get_datatype_info_c::get_ref_to(symbol->non_generic_type_name));
+ } else {
+ current_array_name += get_datatype_info_c::get_id_str(symbol->non_generic_type_name);
+ }
+ symbol->array_subrange_list->accept(*this);
+ return NULL;
+ }
+
+ /* helper symbol for array_specification */
+ /* array_subrange_list ',' subrange */
+ void *visit(array_subrange_list_c *symbol) {
+ for(int i = 0; i < symbol->n; i++) {symbol->elements[i]->accept(*this);}
+ return NULL;
+ }
+
+ /* signed_integer DOTDOT signed_integer */
+ //SYM_REF2(subrange_c, lower_limit, upper_limit)
+ void *visit(subrange_c *symbol) {
+ current_array_name += "_";
+ std::stringstream ss;
+ ss << symbol->dimension;
+ current_array_name += ss.str();
+ return NULL;
+ }
+
+
+};
+
+
+generate_datatypes_aliasid_c *generate_datatypes_aliasid_c::singleton_ = NULL;
+
+
+
+
+
+
+
+/***************************************************************************************/
+/***************************************************************************************/
+/***************************************************************************************/
+/***************************************************************************************/
+
+/* Given an object in the AST that defines a datatype, generate the C source code that declares an
+ * equivalent dataype in C.
+ * WARNING: This class maintains internal state in the datatypes_already_defined map.
+ * Using multiple isntances of this class may result in different C source code
+ * compared to when a single instance of this class is used for all datatype declarations!
+ *
+ * Except for arrays, the C datatype will have the same name as the name of the datatype in the
+ * IEC 61131-3 source code.
+ * For arrays an alias is created for each datatype. This alias has the property of being equal
+ * for arrays with the same internal structure.
+ *
+ * Example:
+ * TYPE
+ * array1: ARRAY [9..11] of INT;
+ * array2: ARRAY [9..11] of INT;
+ * END_TYPE
+ *
+ * will result in both arrays having the same name (__ARRAY_9_11_OF_INT) in the C source code.
+ *
+ * A single C datatype declaration will be generated for both arrays
+ * (the datatypes_already_defined keeps track of which datatypes have already been declared in C)
+ * This method of handling arrays is needed when the relaxed datatype model is used
+ * (see get_datatype_info_c for explanation on the relaxed datatype model).
+ */
+/* Notice that this class inherits from generate_c_base_c, and not from generate_c_base_and_typeid_c.
+ * This is intentional!
+ * Whenever this class needs to print out the id of a datatype, it will explicitly use a private instance
+ * (generate_c_typeid) of generate_c_base_and_typeid_c!
+ */
class generate_c_typedecl_c: public generate_c_base_c {
protected:
@@ -30,18 +245,18 @@
private:
symbol_c* current_type_name;
- bool array_is_derived;
- generate_c_base_c *basedecl;
-
+ generate_c_base_and_typeid_c *generate_c_typeid;
+ std::map<std::string, int> datatypes_already_defined;
+
public:
- generate_c_typedecl_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_ptr) {
+ generate_c_typedecl_c(stage4out_c *s4o_ptr): generate_c_base_c(s4o_ptr), s4o_incl(*s4o_ptr) /*, generate_c_print_typename(s4o_ptr) */{
current_typedefinition = none_td;
current_basetypedeclaration = none_bd;
current_type_name = NULL;
- basedecl = new generate_c_base_c(&s4o_incl);
+ generate_c_typeid = new generate_c_base_and_typeid_c(&s4o_incl);
}
~generate_c_typedecl_c(void) {
- delete basedecl;
+ delete generate_c_typeid;
}
typedef enum {
@@ -71,13 +286,11 @@
if (visitor == NULL) visitor = this;
if (list->n > 0) {
-//std::cout << "generate_c_base_c::print_list(n = " << list->n << ") 000\n";
s4o_incl.print(pre_elem_str);
list->elements[0]->accept(*visitor);
}
for(int i = 1; i < list->n; i++) {
-//std::cout << "generate_c_base_c::print_list " << i << "\n";
s4o_incl.print(inter_elem_str);
list->elements[i]->accept(*visitor);
}
@@ -100,8 +313,6 @@
/*******************************************/
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
- /* done in base class(es) */
-
/*********************/
/* B 1.2 - Constants */
/*********************/
@@ -154,7 +365,7 @@
current_type_name = symbol->subrange_type_name;
s4o_incl.print("__DECLARE_DERIVED_TYPE(");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(",");
current_basetypedeclaration = subrangebasetype_bd;
symbol->subrange_spec_init->accept(*this);
@@ -184,16 +395,16 @@
if (current_typedefinition == subrange_td) {
switch (current_basetypedeclaration) {
case subrangebasetype_bd:
- symbol->integer_type_name->accept(*basedecl);
+ symbol->integer_type_name->accept(*generate_c_typeid);
break;
case subrangetest_bd:
if (symbol->subrange != NULL) {
s4o_incl.print("static inline ");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(" __CHECK_");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print("(");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(" value) {\n");
s4o_incl.indent_right();
@@ -217,9 +428,9 @@
}
else {
s4o_incl.print("#define __CHECK_");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(" __CHECK_");
- symbol->integer_type_name->accept(*basedecl);
+ symbol->integer_type_name->accept(*generate_c_typeid);
s4o_incl.print("\n");
}
break;
@@ -247,19 +458,19 @@
break;
case subrange_td:
s4o_incl.print(s4o_incl.indent_spaces + "if (value < ");
- symbol->lower_limit->accept(*basedecl);
+ symbol->lower_limit->accept(*generate_c_typeid);
s4o_incl.print(")\n");
s4o_incl.indent_right();
s4o_incl.print(s4o_incl.indent_spaces + "return ");
- symbol->lower_limit->accept(*basedecl);
+ symbol->lower_limit->accept(*generate_c_typeid);
s4o_incl.print(";\n");
s4o_incl.indent_left();
s4o_incl.print(s4o_incl.indent_spaces + "else if (value > ");
- symbol->upper_limit->accept(*basedecl);
+ symbol->upper_limit->accept(*generate_c_typeid);
s4o_incl.print(")\n");
s4o_incl.indent_right();
s4o_incl.print(s4o_incl.indent_spaces + "return ");
- symbol->upper_limit->accept(*basedecl);
+ symbol->upper_limit->accept(*generate_c_typeid);
s4o_incl.print(";\n");
s4o_incl.indent_left();
s4o_incl.print(s4o_incl.indent_spaces + "else\n");
@@ -280,7 +491,7 @@
current_type_name = symbol->enumerated_type_name;
s4o_incl.print("__DECLARE_ENUMERATED_TYPE(");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(",\n");
s4o_incl.indent_right();
symbol->enumerated_spec_init->accept(*this);
@@ -299,7 +510,7 @@
if (current_typedefinition == enumerated_td)
symbol->enumerated_specification->accept(*this);
else
- symbol->enumerated_specification->accept(*basedecl);
+ symbol->enumerated_specification->accept(*generate_c_typeid);
return NULL;
}
@@ -319,22 +530,40 @@
/* identifier ':' array_spec_init */
void *visit(array_type_declaration_c *symbol) {
TRACE("array_type_declaration_c");
+
+ // NOTE: remeber that symbol->array_spec_init may point to an identifier_c, which is why we use symbol->array_spec_init->datatype instead!
+ if (NULL == symbol->array_spec_init->datatype) ERROR;
+ identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol->array_spec_init->datatype);
+
+ /* NOTE An array_type_declaration_c will be created in stage4 for each implicitly defined array,
+ * and this generate_c_typedecl_c will be called to define that array in C.
+ * However, every implictly defined array with the exact same parameters will be mapped
+ * to the same identifier (e.g: __ARRAY_OF_INT_33 where 33 is the number of elements in the array).
+ * In order for the C compiler not to find the same datatype being defined two or more times,
+ * we will keep track of the array datatypes that have already been declared, and henceforth
+ * only declare arrays that have not been previously defined.
+ */
+ if (datatypes_already_defined.find(id->value) != datatypes_already_defined.end())
+ goto end; // already defined. No need to define it again!!
+ datatypes_already_defined[id->value] = 1; // insert this datatype into the list of already defined arrays!
+
current_typedefinition = array_td;
- current_type_name = symbol->identifier;
-
- int implicit_id_count = symbol->array_spec_init->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1)
- s4o_incl.print("__DECLARE_DERIVED_TYPE(");
- else
- s4o_incl.print("__DECLARE_ARRAY_TYPE(");
- current_type_name->accept(*basedecl);
+ current_type_name = id;
+
+ s4o_incl.print("__DECLARE_ARRAY_TYPE(");
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(",");
symbol->array_spec_init->accept(*this);
s4o_incl.print(")\n");
current_type_name = NULL;
current_typedefinition = none_td;
+
+end:
+ symbol ->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+ symbol->datatype ->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+ symbol->array_spec_init->anotations_map["generate_c_annotaton__implicit_type_id"] = id; // probably not needed, bu let's play safe.
+
return NULL;
}
@@ -344,16 +573,6 @@
/* array_initialization may be NULL ! */
void *visit(array_spec_init_c *symbol) {
TRACE("array_spec_init_c");
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1) {
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
- return NULL;
- }
-// if (current_typedefinition != array_td) {debug_c::print(symbol); ERROR;}
symbol->array_specification->accept(*this);
return NULL;
}
@@ -361,17 +580,8 @@
/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
void *visit(array_specification_c *symbol) {
TRACE("array_specification_c");
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1) {
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
- return NULL;
- }
// The 2nd and 3rd argument of a call to the __DECLARE_ARRAY_TYPE macro!
- symbol->non_generic_type_name->accept(*this);
+ symbol->non_generic_type_name->accept(/*generate_c_print_typename*/*generate_c_typeid);
s4o_incl.print(",");
current_basetypedeclaration = arraysubrange_bd;
symbol->array_subrange_list->accept(*this);
@@ -399,14 +609,14 @@
TRACE("simple_type_declaration_c");
s4o_incl.print("__DECLARE_DERIVED_TYPE(");
- symbol->simple_type_name->accept(*basedecl);
+ symbol->simple_type_name->accept(*generate_c_typeid);
s4o_incl.print(",");
symbol->simple_spec_init->accept(*this);
s4o_incl.print(")\n");
if (get_datatype_info_c::is_subrange(symbol->simple_type_name)) {
s4o_incl.print("#define __CHECK_");
- current_type_name->accept(*basedecl);
+ current_type_name->accept(*generate_c_typeid);
s4o_incl.print(" __CHECK_");
symbol->simple_spec_init->accept(*this);
s4o_incl.print("\n");
@@ -420,7 +630,7 @@
// <constant> may be NULL
void *visit(simple_spec_init_c *symbol) {
TRACE("simple_spec_init_c");
- symbol->simple_specification->accept(*basedecl);
+ symbol->simple_specification->accept(*generate_c_typeid);
return NULL;
}
@@ -482,7 +692,7 @@
current_typedefinition = struct_td;
s4o_incl.print("__DECLARE_STRUCT_TYPE(");
- symbol->structure_type_name->accept(*basedecl);
+ symbol->structure_type_name->accept(*generate_c_typeid);
s4o_incl.print(",");
symbol->structure_specification->accept(*this);
s4o_incl.print(")\n");
@@ -497,9 +707,7 @@
//SYM_REF2(initialized_structure_c, structure_type_name, structure_initialization)
void *visit(initialized_structure_c *symbol) {
TRACE("initialized_structure_c");
-
- symbol->structure_type_name->accept(*basedecl);
-
+ symbol->structure_type_name->accept(*generate_c_typeid);
return NULL;
}
@@ -525,9 +733,9 @@
void *visit(structure_element_declaration_c *symbol) {
TRACE("structure_element_declaration_c");
- symbol->spec_init->accept(*this);
+ symbol->spec_init->accept(/*generate_c_print_typename*/*generate_c_typeid);
s4o_incl.print(" ");
- symbol->structure_element_name->accept(*basedecl);
+ symbol->structure_element_name->accept(*generate_c_typeid);
s4o_incl.print(";\n");
s4o_incl.print(s4o_incl.indent_spaces);
@@ -628,20 +836,8 @@
/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
// SYM_REF1(ref_spec_c, type_name)
-void *visit(ref_spec_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1) {
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
- return NULL;
- }
- /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *),
- * through the visit(ref_spec_init_c*)), so we need to simply print out the name of the datatype we reference to.
- */
- symbol->type_name->accept(*this);
+void *visit(ref_spec_c *symbol) {
+ symbol->type_name->accept(/*generate_c_print_typename*/*generate_c_typeid);
s4o_incl.print("*");
return NULL;
}
@@ -651,31 +847,31 @@
/* NOTE: ref_initialization may be NULL!! */
// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
void *visit(ref_spec_init_c *symbol) {
- int implicit_id_count = symbol->anotations_map.count("generate_c_annotaton__implicit_type_id");
- if (implicit_id_count > 1) ERROR;
- if (implicit_id_count == 1) {
- /* this is part of an implicitly declared datatype (i.e. inside a variable decaration), for which an equivalent C datatype
- * has already been defined. So, we simly print out the id of that C datatpe...
- */
- symbol->anotations_map["generate_c_annotaton__implicit_type_id"]->accept(*basedecl);
- return NULL;
- }
- /* This is NOT part of an implicitly declared datatype (i.e. we are being called from an visit(ref_type_decl_c *)),
- * so we need to simply print out the name of the datatype we reference to.
- */
- return symbol->ref_spec->accept(*this);
+ return symbol->ref_spec->accept(*generate_c_typeid);
}
/* ref_type_decl: identifier ':' ref_spec_init */
// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
void *visit(ref_type_decl_c *symbol) {
TRACE("ref_type_decl_c");
+
+ /* NOTE An ref_type_decl_c will be created in stage4 for each implicitly defined REF_TO datatype,
+ * and this generate_c_typedecl_c will be called to define that REF_TO datatype in C.
+ * However, every implictly defined REF_TO datatype with the exact same parameters will be mapped
+ * to the same identifier (e.g: __REF_TO_INT).
+ * In order for the C compiler not to find the same datatype being defined two or more times,
+ * we will keep track of the datatypes that have already been declared, and henceforth
+ * only declare the datatypes that have not been previously defined.
+ */
+ if (datatypes_already_defined.find(((identifier_c *)(symbol->ref_type_name))->value) != datatypes_already_defined.end())
+ return NULL; // already defined. No need to define it again!!
+ datatypes_already_defined[((identifier_c *)(symbol->ref_type_name))->value] = 1; // insert this datatype into the list of already defined arrays!
current_type_name = NULL;
current_typedefinition = none_td;
s4o_incl.print("__DECLARE_REFTO_TYPE(");
- symbol->ref_type_name->accept(*basedecl);
+ symbol->ref_type_name->accept(*generate_c_typeid);
s4o_incl.print(", ");
symbol->ref_spec_init->accept(*this);
s4o_incl.print(")\n");
@@ -688,10 +884,6 @@
-
-
-
-
/*********************/
/* B 1.4 - Variables */
/*********************/
@@ -793,10 +985,176 @@
/********************************/
/* leave for derived classes... */
-
-
-
}; /* generate_c_typedecl_c */
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
+
+/* This class will generate a new datatype for each implicitly declared array datatype
+ * (i.e. arrays declared in a variable declaration, or a struct datatype declaration...)
+ * It will do the same for implicitly declared REF_TO datatypes.
+ *
+ * Each new implicitly datatype will be atributed an alias, and a C datatype will be declared for that alias.
+ * The alias itself will be stored (annotated) in the datatype object in the AST, using the annotation
+ * map reserved for stage4 anotations. The alias is stored under the "generate_c_annotaton__implicit_type_id"
+ * entry, and this entry will then be used whenever the name of the datatype is needed (to declare a varable,
+ * for example).
+ *
+ * The class will be called once for each POU declaration, and once for each derived datatype declaration.
+ *
+ * e.g.:
+ * VAR x: ARRAY [1..3] OF INT; END_VAR <---- ARRAY datatype is implicitly declared inside the variable declaration
+ * VAR y: REF_TO INT; END_VAR <---- REF_TO datatype is implicitly declared inside the variable declaration
+ * TYPE STRUCT
+ * a: ARRAY [1..3] OF INT; <---- ARRAY datatype is implicitly declared inside the struct type declaration
+ * b: REF_TO INT; <---- REF_TO datatype is implicitly declared inside the struct type declaration
+ * c: INT;
+ * END_STRUCT
+ * END_TYPE
+ */
+class generate_c_implicit_typedecl_c: public iterator_visitor_c {
+ private:
+ generate_c_typedecl_c *generate_c_typedecl_;
+ generate_c_typedecl_c generate_c_typedecl_local;
+ symbol_c *prefix;
+ public:
+ generate_c_implicit_typedecl_c(stage4out_c *s4o, generate_c_typedecl_c *generate_c_typedecl=NULL)
+ : generate_c_typedecl_local(s4o) {
+ generate_c_typedecl_ = generate_c_typedecl;
+ if (NULL == generate_c_typedecl_)
+ generate_c_typedecl_ = &generate_c_typedecl_local;
+ prefix = NULL;
+ };
+ virtual ~generate_c_implicit_typedecl_c(void) {
+ }
+
+ /*************************/
+ /* B.1 - Common elements */
+ /*************************/
+ /**********************/
+ /* B.1.3 - Data types */
+ /**********************/
+ /********************************/
+ /* B 1.3.3 - Derived data types */
+ /********************************/
+ /* identifier ':' array_spec_init */
+ void *visit(array_type_declaration_c *symbol) {return NULL;} // This is not an implicitly defined array!
+
+ /* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
+ void *visit(ref_spec_c *symbol) {
+ identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol);
+ /* Warning: The following is dangerous...
+ * We are asking the generate_c_typedecl_c visitor to visit a newly created ref_spec_init_c object
+ * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
+ * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
+ */
+ ref_spec_init_c ref_spec(symbol, NULL);
+ ref_type_decl_c ref_decl(id, &ref_spec);
+ ref_decl.accept(*generate_c_typedecl_);
+ symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+ return NULL;
+ }
+
+ /* For the moment, we do not support initialising reference data types */
+ /* ref_spec_init: ref_spec [ ASSIGN ref_initialization ] */
+ /* NOTE: ref_initialization may be NULL!! */
+ // SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
+ void *visit(ref_spec_init_c *symbol) {
+ symbol->ref_spec->accept(*this);
+ int implicit_id_count = symbol->ref_spec->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (implicit_id_count > 1) ERROR;
+ if (implicit_id_count == 1)
+ symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->ref_spec->anotations_map["generate_c_annotaton__implicit_type_id"];
+ return NULL;
+ }
+
+ /* ref_type_decl: identifier ':' ref_spec_init */
+ void *visit(ref_type_decl_c *symbol) {return NULL;} // This is not an implicitly defined REF_TO!
+
+ /******************************************/
+ /* B 1.4.3 - Declaration & Initialization */
+ /******************************************/
+ void *visit(edge_declaration_c *symbol) {return NULL;}
+ void *visit(en_param_declaration_c *symbol) {return NULL;}
+ void *visit(eno_param_declaration_c *symbol) {return NULL;}
+
+ /* array_specification [ASSIGN array_initialization] */
+ /* array_initialization may be NULL ! */
+ void *visit(array_spec_init_c *symbol) {
+ symbol->array_specification->accept(*this);
+ int implicit_id_count = symbol->array_specification->anotations_map.count("generate_c_annotaton__implicit_type_id");
+ if (implicit_id_count > 1) ERROR;
+ if (implicit_id_count == 1)
+ symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = symbol->array_specification->anotations_map["generate_c_annotaton__implicit_type_id"];
+ return NULL;
+ }
+
+ /* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
+ void *visit(array_specification_c *symbol) {
+ identifier_c *id = generate_datatypes_aliasid_c::create_id(symbol);
+ /* Warning: The following is dangerous...
+ * We are asking the generate_c_typedecl_c visitor to visit a newly created array_type_declaration_c object
+ * that has not been through stage 3, and therefore does not have stage 3 annotations filled in.
+ * This will only work if generate_c_typedecl_c does ot depend on the stage 3 annotations!
+ */
+ array_spec_init_c array_spec(symbol, NULL);
+ array_type_declaration_c array_decl(id, &array_spec);
+ array_decl.datatype = symbol->datatype;
+ array_spec.datatype = symbol->datatype;
+ array_decl.accept(*generate_c_typedecl_);
+ symbol->anotations_map["generate_c_annotaton__implicit_type_id"] = id;
+ return NULL;
+ }
+
+ /* var1_list ':' initialized_structure */
+ // SYM_REF2(structured_var_init_decl_c, var1_list, initialized_structure)
+ void *visit(structured_var_init_decl_c *symbol) {return NULL;}
+
+ /* fb_name_list ':' function_block_type_name ASSIGN structure_initialization */
+ /* structure_initialization -> may be NULL ! */
+ void *visit(fb_name_decl_c *symbol) {return NULL;}
+
+ /* var1_list ':' structure_type_name */
+ //SYM_REF2(structured_var_declaration_c, var1_list, structure_type_name)
+ void *visit(structured_var_declaration_c *symbol) {return NULL;}
+
+
+ /***********************/
+ /* B 1.5.1 - Functions */
+ /***********************/
+ void *visit(function_declaration_c *symbol) {
+ prefix = symbol->derived_function_name;
+ symbol->var_declarations_list->accept(*this);
+ prefix = NULL;
+ return NULL;
+ }
+ /*****************************/
+ /* B 1.5.2 - Function Blocks */
+ /*****************************/
+ void *visit(function_block_declaration_c *symbol) {
+ prefix = symbol->fblock_name;
+ symbol->var_declarations->accept(*this);
+ prefix = NULL;
+ return NULL;
+ }
+ /**********************/
+ /* B 1.5.3 - Programs */
+ /**********************/
+ void *visit(program_declaration_c *symbol) {
+ prefix = symbol->program_type_name;
+ symbol->var_declarations->accept(*this);
+ prefix = NULL;
+ return NULL;
+ }
+};
+
+
+
+
+
--- a/stage4/generate_c/generate_c_vardecl.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_c_vardecl.cc Sun Nov 16 15:37:12 2014 +0000
@@ -60,7 +60,7 @@
// Does this class really need to derive from generate_c_typedecl_c ???
-class generate_c_array_initialization_c: public generate_c_typedecl_c {
+class generate_c_array_initialization_c: public generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -83,7 +83,7 @@
unsigned long long int current_initialization_count;
public:
- generate_c_array_initialization_c(stage4out_c *s4o_ptr): generate_c_typedecl_c(s4o_ptr) {}
+ generate_c_array_initialization_c(stage4out_c *s4o_ptr): generate_c_base_and_typeid_c(s4o_ptr) {}
~generate_c_array_initialization_c(void) {}
void init_array_size(symbol_c *array_specification) {
@@ -149,9 +149,7 @@
case arraysize_am:
/* look up the type declaration... */
type_decl = type_symtable.find_value(type_name);
- if (type_decl == type_symtable.end_value())
- /* Type declaration not found!! */
- ERROR;
+ if (type_decl == type_symtable.end_value()) ERROR; // Type declaration not found!!
type_decl->accept(*this);
break;
default:
@@ -495,7 +493,12 @@
}
};
-class generate_c_structure_initialization_c: public generate_c_typedecl_c {
+
+
+
+
+
+class generate_c_structure_initialization_c: public generate_c_base_and_typeid_c {
public:
typedef enum {
@@ -513,7 +516,7 @@
symbol_c* current_element_default_value;
public:
- generate_c_structure_initialization_c(stage4out_c *s4o_ptr): generate_c_typedecl_c(s4o_ptr) {}
+ generate_c_structure_initialization_c(stage4out_c *s4o_ptr): generate_c_base_and_typeid_c(s4o_ptr) {}
~generate_c_structure_initialization_c(void) {}
void init_structure_default(symbol_c *structure_type_name) {
@@ -572,6 +575,24 @@
return NULL;
}
+ void *visit(derived_datatype_identifier_c *type_name) {
+ symbol_c *type_decl;
+ switch (current_mode) {
+ case initdefault_sm:
+ /* look up the type declaration... */
+ type_decl = type_symtable.find_value(type_name);
+ if (type_decl == type_symtable.end_value())
+ /* Type declaration not found!! */
+ ERROR;
+ type_decl->accept(*this);
+ break;
+ default:
+ print_token(type_name);
+ break;
+ }
+ return NULL;
+ }
+
void *visit(var1_list_c *symbol) {
int i, j;
@@ -689,7 +710,7 @@
-class generate_c_vardecl_c: protected generate_c_base_c {
+class generate_c_vardecl_c: protected generate_c_base_and_typeid_c {
/* A Helper class to the main class... */
/* print a string, except the first time it is called */
@@ -890,8 +911,11 @@
void update_type_init(symbol_c *symbol /* a spec_init_c, subrange_spec_init_c, etc... */ ) {
this->current_var_type_symbol = spec_init_sperator_c::get_spec(symbol);
this->current_var_init_symbol = spec_init_sperator_c::get_init(symbol);
- if (NULL == this->current_var_type_symbol)
- ERROR;
+ if (NULL == this->current_var_type_symbol) ERROR;
+ if (NULL == this->current_var_type_symbol->datatype) {debug_c::print(this->current_var_type_symbol); ERROR;}
+ if (get_datatype_info_c::is_array(this->current_var_type_symbol))
+ this->current_var_type_symbol = this->current_var_type_symbol->datatype;
+ if (NULL == this->current_var_type_symbol) ERROR;
if (NULL == this->current_var_init_symbol) {
/* We try to find the data type's default value... */
this->current_var_init_symbol = type_initial_value_c::get(this->current_var_type_symbol);
@@ -1097,7 +1121,7 @@
public:
generate_c_vardecl_c(stage4out_c *s4o_ptr, varformat_t varformat, unsigned int vartype, symbol_c* res_name = NULL)
- : generate_c_base_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
wanted_varformat = varformat;
wanted_vartype = vartype;
current_vartype = none_vt;
@@ -1408,7 +1432,8 @@
/* Start off by setting the current_var_type_symbol and
* current_var_init_symbol private variables...
*/
- update_type_init(symbol->array_spec_init);
+ if (NULL == symbol->array_spec_init->datatype) ERROR;
+ update_type_init(symbol->array_spec_init->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'!
/* now to produce the c equivalent... */
if (wanted_varformat == constructorinit_vf) {
@@ -1550,7 +1575,8 @@
/* Start off by setting the current_var_type_symbol and
* current_var_init_symbol private variables...
*/
- update_type_init(symbol->array_specification);
+ if (symbol->array_specification->datatype == NULL) {debug_c::print(symbol->array_specification); ERROR;}
+ update_type_init(symbol->array_specification->datatype); // we want to print the name of the base datatype, and nt the derived datatype, so we use '->datatype'!
/* now to produce the c equivalent... */
if (wanted_varformat == constructorinit_vf) {
@@ -1839,8 +1865,9 @@
/* Start off by setting the current_var_type_symbol and
* current_var_init_symbol private variables...
*/
- this->current_var_type_symbol = symbol->specification;
- this->current_var_init_symbol = NULL;
+ update_type_init(symbol->specification);
+ this->current_var_init_symbol = NULL; // We do NOt want to initialize external variables.
+
if(!get_datatype_info_c::is_type_valid(this->current_var_type_symbol)) ERROR;
bool is_fb = get_datatype_info_c::is_function_block(this->current_var_type_symbol);
--- a/stage4/generate_c/generate_var_list.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_c/generate_var_list.cc Sun Nov 16 15:37:12 2014 +0000
@@ -184,7 +184,7 @@
/***********************************************************************/
/***********************************************************************/
-class generate_var_list_c: protected generate_c_typedecl_c {
+class generate_var_list_c: protected generate_c_base_and_typeid_c {
public:
typedef struct {
@@ -222,7 +222,7 @@
public:
generate_var_list_c(stage4out_c *s4o_ptr, symbol_c *scope)
- : generate_c_typedecl_c(s4o_ptr) {
+ : generate_c_base_and_typeid_c(s4o_ptr) {
search_type_symbol = new search_type_symbol_c(scope);
current_var_number = 0;
current_var_type_symbol = NULL;
--- a/stage4/generate_iec/generate_iec.cc Sun Nov 09 22:02:34 2014 +0000
+++ b/stage4/generate_iec/generate_iec.cc Sun Nov 16 15:37:12 2014 +0000
@@ -253,7 +253,8 @@
/*******************************************/
/* B 1.1 - Letters, digits and identifiers */
/*******************************************/
-void *visit(identifier_c *symbol) {return print_token(symbol);}
+void *visit( identifier_c *symbol) {return print_token(symbol);}
+void *visit(derived_datatype_identifier_c *symbol) {return print_token(symbol);}
/*********************/
/* B 1.2 - Constants */