stage4/generate_c/generate_c_base.cc
changeset 945 477393b00f95
parent 936 0f7bcc160568
child 947 aca1ab9fcb6d
--- 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 */
+
+
+
+
+
+
+
+
+
+
+
+
+