stage4/generate_c/generate_c.cc
changeset 870 9c6c588fd708
parent 864 300c27c08753
child 872 3d682f87c870
--- a/stage4/generate_c/generate_c.cc	Wed Feb 19 22:25:10 2014 +0100
+++ b/stage4/generate_c/generate_c.cc	Wed Feb 19 22:27:11 2014 +0100
@@ -340,6 +340,131 @@
 /***********************************************************************/
 /***********************************************************************/
 
+/* A helper class that analyses if the datatype of a variable is 'complex'. */
+/* 'complex' means that it is either a strcuture or an array!               */
+class analyse_variable_c: public search_visitor_c {
+  private:
+    static analyse_variable_c *singleton_;
+
+  public:
+    analyse_variable_c(void) {};
+    
+    static bool is_complex_type(symbol_c *symbol) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid     (symbol->datatype)) ERROR;
+      return (   get_datatype_info_c::is_structure(symbol->datatype) 
+              || get_datatype_info_c::is_array    (symbol->datatype) 
+             );
+    }
+
+    
+  private:
+    symbol_c *last_fb, *first_non_fb_identifier;
+
+  public:  
+    /* returns the first element (from left to right) in a structured variable that is not a FB, i.e. is either a structure or an array! */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns ??????
+     *      fb1.fb2.struct1.real   returns struct1
+     *      struct1.real           returns struct1
+     */
+    static symbol_c *find_first_nonfb(symbol_c *symbol) {
+      if (NULL == singleton_)       singleton_ = new analyse_variable_c();
+      if (NULL == singleton_)       ERROR;
+      if (NULL == symbol)           ERROR;
+      
+      singleton_->last_fb                 = NULL;
+      singleton_->first_non_fb_identifier = NULL;
+      return (symbol_c *)symbol->accept(*singleton_);
+    }
+    
+    /* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns FALSE
+     *      fb1.fb2.struct1.real   returns TRUE
+     *      struct1.real           returns TRUE
+     */
+    static bool contains_complex_type(symbol_c *symbol) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+      
+      symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+      return is_complex_type(first_non_fb->datatype);
+    }
+    
+    
+    /* returns the datatype of the variable returned by find_first_nonfb() */
+    /* eg:
+     *      fb1.fb2.fb3.real       returns ??????
+     *      fb1.fb2.struct1.real   returns datatype of struct1
+     *      struct1.real           returns datatype of struct1
+     */
+    static search_var_instance_decl_c::vt_t first_nonfb_vardecltype(symbol_c *symbol, symbol_c *scope) {
+      if (NULL == symbol) ERROR;
+      if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR;
+      
+      symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol);
+      if (NULL != singleton_->last_fb) {
+        scope = singleton_->last_fb->datatype;
+        symbol = singleton_->first_non_fb_identifier;
+      }
+      
+      search_var_instance_decl_c search_var_instance_decl(scope);
+      
+      return search_var_instance_decl.get_vartype(symbol);
+    }
+    
+    
+    /*********************/
+    /* B 1.4 - Variables */
+    /*********************/
+    void *visit(symbolic_variable_c *symbol) {
+      if (!get_datatype_info_c::is_type_valid    (symbol->datatype)) ERROR;
+      if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+         first_non_fb_identifier = symbol; 
+         return (void *)symbol;
+      }
+      last_fb = symbol;
+      return NULL;
+    }
+    
+    /*************************************/
+    /* B.1.4.2   Multi-element Variables */
+    /*************************************/
+    
+    // SYM_REF2(structured_variable_c, record_variable, field_selector)
+    void *visit(structured_variable_c *symbol) {
+      symbol_c *res = (symbol_c *)symbol->record_variable->accept(*this);
+      if (NULL != res) return res;
+      
+      if (!get_datatype_info_c::is_type_valid    (symbol->datatype)) ERROR;
+      if (!get_datatype_info_c::is_function_block(symbol->datatype)) {
+         first_non_fb_identifier = symbol->field_selector; 
+         return (void *)symbol;
+      }
+
+      last_fb = symbol;      
+      return NULL;      
+    }
+    
+    /*  subscripted_variable '[' subscript_list ']' */
+    //SYM_REF2(array_variable_c, subscripted_variable, subscript_list)
+    void *visit(array_variable_c *symbol) {
+      void *res = symbol->subscripted_variable->accept(*this);
+      if (NULL != res) return res;
+      return (void *)symbol;      
+    }
+
+    
+};
+
+analyse_variable_c *analyse_variable_c::singleton_ = NULL;
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
 
 #include "generate_c_st.cc"
 #include "generate_c_il.cc"
@@ -588,15 +713,13 @@
     } inlinearray_mode_t;
 
   private:
-    stage4out_c *s4o_ptr;
     std::map<std::string, int> inline_array_defined;
     std::string current_array_name;
     inlinearray_mode_t current_mode;
 
   public:
     generate_c_datatypes_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_datatypes_c::s4o_ptr = s4o_ptr;
+      : generate_c_typedecl_c(s4o_incl_ptr) {
       current_mode = none_im;
     };
     virtual ~generate_c_datatypes_c(void) {
@@ -782,11 +905,20 @@
     void *visit(array_spec_init_c *symbol) {
       switch (current_mode) {
         case arraydeclaration_im:
+          {
+            array_specification_c *specification = dynamic_cast<array_specification_c*>(symbol->array_specification);
+            if (specification != NULL)
+              symbol->array_specification->accept(*this);
+          }
+          break;
         case arrayname_im:
           {
             array_specification_c *specification = dynamic_cast<array_specification_c*>(symbol->array_specification);
             if (specification != NULL)
               symbol->array_specification->accept(*this);
+            identifier_c *name = dynamic_cast<identifier_c*>(symbol->array_specification);
+            if (name != NULL)
+              s4o_incl.print(name->value);
           }
           break;
         default:
@@ -1013,14 +1145,13 @@
 /***********************************************************************/
 
 
-class generate_c_pous_c: public generate_c_typedecl_c {
+class generate_c_pous_c: public generate_c_base_c {
   private:
-    stage4out_c *s4o_ptr;
+    stage4out_c &s4o_incl;
     
   public:
     generate_c_pous_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_pous_c::s4o_ptr = s4o_ptr;
+      : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
     };
     virtual ~generate_c_pous_c(void) {}
 
@@ -1054,8 +1185,8 @@
 /********************/
 /* 2.1.6 - Pragmas  */
 /********************/
-void *visit(enable_code_generation_pragma_c * symbol)   {s4o_ptr->enable_output();  return NULL;}
-void *visit(disable_code_generation_pragma_c * symbol)  {s4o_ptr->disable_output(); return NULL;} 
+void *visit(enable_code_generation_pragma_c * symbol)   {s4o.enable_output();  return NULL;}
+void *visit(disable_code_generation_pragma_c * symbol)  {s4o.disable_output(); return NULL;} 
 
 /*************************/
 /* B.1 - Common elements */
@@ -1617,16 +1748,13 @@
 /***********************************************************************/
 /***********************************************************************/
 
-class generate_c_config_c: public generate_c_typedecl_c {
+class generate_c_config_c: public generate_c_base_c {
     private:
-    stage4out_c *s4o_ptr;
-    stage4out_c *s4o_incl_ptr;
+    stage4out_c &s4o_incl;
     
     public:
     generate_c_config_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr)
-      : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) {
-      generate_c_config_c::s4o_ptr = s4o_ptr;
-      generate_c_config_c::s4o_incl_ptr = s4o_incl_ptr;
+      : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) {
     };
 
     virtual ~generate_c_config_c(void) {}
@@ -1646,14 +1774,14 @@
 /* 2.1.6 - Pragmas  */
 /********************/
 void *visit(enable_code_generation_pragma_c * symbol)   {
-    s4o_ptr->enable_output();
-    s4o_incl_ptr->enable_output();
+    s4o.enable_output();
+    s4o_incl.enable_output();
     return NULL;
 }
 
 void *visit(disable_code_generation_pragma_c * symbol)  {
-    s4o_ptr->disable_output();
-    s4o_incl_ptr->disable_output();    
+    s4o.disable_output();
+    s4o_incl.disable_output();    
     return NULL;
 }