--- a/stage4/generate_c/generate_c_base.cc Sat Oct 25 13:20:10 2014 +0100
+++ b/stage4/generate_c/generate_c_base.cc Sun Nov 16 12:54:10 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 */
+
+
+
+
+
+
+
+
+
+
+
+
+